Skip to content

Commit c0a73ae

Browse files
authored
Merge pull request #317 from pluginpal/feature/cli-license-setup
feat: add license key setup to the cli
2 parents b3850e0 + e913598 commit c0a73ae

File tree

5 files changed

+149
-6
lines changed

5 files changed

+149
-6
lines changed

.changeset/gold-places-yawn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"webtools-cli": minor
3+
---
4+
5+
feat: add license key setup to the cli

packages/cli/src/commands/install.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import chalk from 'chalk';
2-
import { checkbox } from '@inquirer/prompts';
2+
import { checkbox, confirm, input } from '@inquirer/prompts';
33
import { checkStrapiProject } from '../utils/strapi';
44
import { getContentTypes, enableWebtoolsForContentType } from '../utils/content-types';
5-
import { getAvailableAddons } from '../utils/addons';
5+
import { getAvailableAddons, getPremiumAddons } from '../utils/addons';
66
import { installPackage } from '../utils/package-manager';
7+
import { createLicenseFiles } from '../utils/license';
78

89
export async function install() {
910
// Check if we're in a Strapi project
@@ -13,6 +14,33 @@ export async function install() {
1314
return;
1415
}
1516

17+
// Ask about license key
18+
const hasLicense = await confirm({
19+
message: 'Do you have a license key for Webtools?',
20+
default: false,
21+
});
22+
23+
let licenseKey: string | null = null;
24+
if (hasLicense) {
25+
licenseKey = await input({
26+
message: 'Please enter your license key:',
27+
validate: (value) => {
28+
if (!value || value.trim().length === 0) {
29+
return 'License key cannot be empty';
30+
}
31+
return true;
32+
},
33+
});
34+
35+
// Create license files
36+
console.log(chalk.blue('\nSetting up license configuration...'));
37+
const success = await createLicenseFiles(licenseKey);
38+
if (!success) {
39+
console.log(chalk.red('Failed to setup license configuration. Continuing without the license.'));
40+
licenseKey = null;
41+
}
42+
}
43+
1644
// Get available content types
1745
const contentTypes = getContentTypes();
1846

@@ -50,12 +78,19 @@ export async function install() {
5078

5179
// Get available addons
5280
const availableAddons = getAvailableAddons();
81+
let allAddons = [...availableAddons];
82+
83+
// Add premium addons if user has license
84+
if (licenseKey) {
85+
const premiumAddons = getPremiumAddons();
86+
allAddons = [...availableAddons, ...premiumAddons];
87+
}
5388

5489
// Let user select addons
5590
const selectedAddons = await checkbox({
5691
message: 'Select addons to install:',
57-
choices: availableAddons.map((addon) => ({
58-
name: addon.name,
92+
choices: allAddons.map((addon) => ({
93+
name: `${addon.name}${licenseKey && getPremiumAddons().some((p) => p.name === addon.name) ? ' (premium)' : ''}`,
5994
value: addon.name,
6095
description: addon.description,
6196
})),
@@ -66,7 +101,7 @@ export async function install() {
66101

67102
// Add selected addons to the installation list
68103
selectedAddons.forEach((addonName) => {
69-
const addon = availableAddons.find((a) => a.name === addonName);
104+
const addon = allAddons.find((a) => a.name === addonName);
70105
if (addon) {
71106
packagesToInstall.push(addon.packageName);
72107
}

packages/cli/src/constants/addons.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,16 @@ export const AVAILABLE_ADDONS: Addon[] = [
1111
packageName: 'webtools-addon-sitemap',
1212
},
1313
];
14+
15+
export const PREMIUM_ADDONS: Addon[] = [
16+
{
17+
name: 'redirects',
18+
description: 'Manage redirects for your Strapi content',
19+
packageName: '@pluginpal/webtools-addon-redirects',
20+
},
21+
{
22+
name: 'links',
23+
description: 'Advanced link management for your Strapi content',
24+
packageName: '@pluginpal/webtools-addon-links',
25+
},
26+
];

packages/cli/src/utils/addons.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { Addon, AVAILABLE_ADDONS } from '../constants/addons';
1+
import { Addon, AVAILABLE_ADDONS, PREMIUM_ADDONS } from '../constants/addons';
22

33
export function getAvailableAddons(): Addon[] {
44
return AVAILABLE_ADDONS;
55
}
6+
7+
export function getPremiumAddons(): Addon[] {
8+
return PREMIUM_ADDONS;
9+
}

packages/cli/src/utils/license.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import fs from 'fs-extra';
2+
import path from 'path';
3+
import chalk from 'chalk';
4+
import { execSync } from 'child_process';
5+
import { detectPackageManager } from './package-manager';
6+
7+
function getYarnVersion(): string | null {
8+
try {
9+
const version = execSync('yarn --version', { encoding: 'utf8', stdio: 'pipe' }).trim();
10+
return version;
11+
} catch (error) {
12+
return null;
13+
}
14+
}
15+
16+
function isYarnV2OrHigher(): boolean {
17+
const version = getYarnVersion();
18+
if (!version) return false;
19+
20+
const majorVersion = parseInt(version.split('.')[0], 10);
21+
return majorVersion >= 2;
22+
}
23+
24+
export async function createLicenseFiles(licenseKey: string): Promise<boolean> {
25+
try {
26+
const currentDir = process.cwd();
27+
28+
// Create .env file with license key
29+
const envPath = path.join(currentDir, '.env');
30+
let envContent = '';
31+
32+
// Check if .env already exists and read its content
33+
if (await fs.pathExists(envPath)) {
34+
envContent = await fs.readFile(envPath, 'utf8');
35+
36+
// Check if WEBTOOLS_LICENSE_KEY already exists
37+
if (envContent.includes('WEBTOOLS_LICENSE_KEY=')) {
38+
// Replace existing license key
39+
envContent = envContent.replace(/WEBTOOLS_LICENSE_KEY=.*/g, `WEBTOOLS_LICENSE_KEY=${licenseKey}`);
40+
} else {
41+
// Add license key to existing content
42+
envContent += `\nWEBTOOLS_LICENSE_KEY=${licenseKey}\n`;
43+
}
44+
} else {
45+
// Create new .env file
46+
envContent = `WEBTOOLS_LICENSE_KEY=${licenseKey}\n`;
47+
}
48+
49+
await fs.writeFile(envPath, envContent);
50+
console.log(chalk.green('✓ Added license key to .env file'));
51+
52+
// Detect package manager and create appropriate config file
53+
const packageManager = detectPackageManager();
54+
55+
if (packageManager === 'yarn' && isYarnV2OrHigher()) {
56+
// Create .yarnrc.yml file for Yarn v2+
57+
const yarnrcPath = path.join(currentDir, '.yarnrc.yml');
58+
const yarnrcContent = `npmScopes:
59+
pluginpal:
60+
npmPublishRegistry: https://npm.pluginpal.io
61+
npmRegistryServer: https://npm.pluginpal.io
62+
npmAlwaysAuth: true
63+
npmAuthIdent: "token"
64+
npmAuthToken: "${licenseKey}"
65+
`;
66+
67+
await fs.writeFile(yarnrcPath, yarnrcContent);
68+
console.log(chalk.green('✓ Created .yarnrc.yml file with registry configuration'));
69+
} else {
70+
// Create .npmrc file for npm/pnpm/yarn v1
71+
const npmrcPath = path.join(currentDir, '.npmrc');
72+
const npmrcContent = `@pluginpal:registry=https://npm.pluginpal.io
73+
//npm.pluginpal.io/:_authToken=${licenseKey}
74+
always-auth=true
75+
`;
76+
77+
await fs.writeFile(npmrcPath, npmrcContent);
78+
console.log(chalk.green('✓ Created .npmrc file with registry configuration'));
79+
}
80+
81+
return true;
82+
} catch (error) {
83+
console.error(chalk.red('Error creating license files:'), error);
84+
return false;
85+
}
86+
}

0 commit comments

Comments
 (0)