diff --git a/.changeset/gold-places-yawn.md b/.changeset/gold-places-yawn.md new file mode 100644 index 00000000..23a974a6 --- /dev/null +++ b/.changeset/gold-places-yawn.md @@ -0,0 +1,5 @@ +--- +"webtools-cli": minor +--- + +feat: add license key setup to the cli diff --git a/packages/cli/src/commands/install.ts b/packages/cli/src/commands/install.ts index 6c2accab..a82c6e3c 100644 --- a/packages/cli/src/commands/install.ts +++ b/packages/cli/src/commands/install.ts @@ -1,9 +1,10 @@ import chalk from 'chalk'; -import { checkbox } from '@inquirer/prompts'; +import { checkbox, confirm, input } from '@inquirer/prompts'; import { checkStrapiProject } from '../utils/strapi'; import { getContentTypes, enableWebtoolsForContentType } from '../utils/content-types'; -import { getAvailableAddons } from '../utils/addons'; +import { getAvailableAddons, getPremiumAddons } from '../utils/addons'; import { installPackage } from '../utils/package-manager'; +import { createLicenseFiles } from '../utils/license'; export async function install() { // Check if we're in a Strapi project @@ -13,6 +14,33 @@ export async function install() { return; } + // Ask about license key + const hasLicense = await confirm({ + message: 'Do you have a license key for Webtools?', + default: false, + }); + + let licenseKey: string | null = null; + if (hasLicense) { + licenseKey = await input({ + message: 'Please enter your license key:', + validate: (value) => { + if (!value || value.trim().length === 0) { + return 'License key cannot be empty'; + } + return true; + }, + }); + + // Create license files + console.log(chalk.blue('\nSetting up license configuration...')); + const success = await createLicenseFiles(licenseKey); + if (!success) { + console.log(chalk.red('Failed to setup license configuration. Continuing without the license.')); + licenseKey = null; + } + } + // Get available content types const contentTypes = getContentTypes(); @@ -50,12 +78,19 @@ export async function install() { // Get available addons const availableAddons = getAvailableAddons(); + let allAddons = [...availableAddons]; + + // Add premium addons if user has license + if (licenseKey) { + const premiumAddons = getPremiumAddons(); + allAddons = [...availableAddons, ...premiumAddons]; + } // Let user select addons const selectedAddons = await checkbox({ message: 'Select addons to install:', - choices: availableAddons.map((addon) => ({ - name: addon.name, + choices: allAddons.map((addon) => ({ + name: `${addon.name}${licenseKey && getPremiumAddons().some((p) => p.name === addon.name) ? ' (premium)' : ''}`, value: addon.name, description: addon.description, })), @@ -66,7 +101,7 @@ export async function install() { // Add selected addons to the installation list selectedAddons.forEach((addonName) => { - const addon = availableAddons.find((a) => a.name === addonName); + const addon = allAddons.find((a) => a.name === addonName); if (addon) { packagesToInstall.push(addon.packageName); } diff --git a/packages/cli/src/constants/addons.ts b/packages/cli/src/constants/addons.ts index a484210d..5181800f 100644 --- a/packages/cli/src/constants/addons.ts +++ b/packages/cli/src/constants/addons.ts @@ -11,3 +11,16 @@ export const AVAILABLE_ADDONS: Addon[] = [ packageName: 'webtools-addon-sitemap', }, ]; + +export const PREMIUM_ADDONS: Addon[] = [ + { + name: 'redirects', + description: 'Manage redirects for your Strapi content', + packageName: '@pluginpal/webtools-addon-redirects', + }, + { + name: 'links', + description: 'Advanced link management for your Strapi content', + packageName: '@pluginpal/webtools-addon-links', + }, +]; diff --git a/packages/cli/src/utils/addons.ts b/packages/cli/src/utils/addons.ts index 52b0e894..762b9a3a 100644 --- a/packages/cli/src/utils/addons.ts +++ b/packages/cli/src/utils/addons.ts @@ -1,5 +1,9 @@ -import { Addon, AVAILABLE_ADDONS } from '../constants/addons'; +import { Addon, AVAILABLE_ADDONS, PREMIUM_ADDONS } from '../constants/addons'; export function getAvailableAddons(): Addon[] { return AVAILABLE_ADDONS; } + +export function getPremiumAddons(): Addon[] { + return PREMIUM_ADDONS; +} diff --git a/packages/cli/src/utils/license.ts b/packages/cli/src/utils/license.ts new file mode 100644 index 00000000..4d8e16fe --- /dev/null +++ b/packages/cli/src/utils/license.ts @@ -0,0 +1,86 @@ +import fs from 'fs-extra'; +import path from 'path'; +import chalk from 'chalk'; +import { execSync } from 'child_process'; +import { detectPackageManager } from './package-manager'; + +function getYarnVersion(): string | null { + try { + const version = execSync('yarn --version', { encoding: 'utf8', stdio: 'pipe' }).trim(); + return version; + } catch (error) { + return null; + } +} + +function isYarnV2OrHigher(): boolean { + const version = getYarnVersion(); + if (!version) return false; + + const majorVersion = parseInt(version.split('.')[0], 10); + return majorVersion >= 2; +} + +export async function createLicenseFiles(licenseKey: string): Promise { + try { + const currentDir = process.cwd(); + + // Create .env file with license key + const envPath = path.join(currentDir, '.env'); + let envContent = ''; + + // Check if .env already exists and read its content + if (await fs.pathExists(envPath)) { + envContent = await fs.readFile(envPath, 'utf8'); + + // Check if WEBTOOLS_LICENSE_KEY already exists + if (envContent.includes('WEBTOOLS_LICENSE_KEY=')) { + // Replace existing license key + envContent = envContent.replace(/WEBTOOLS_LICENSE_KEY=.*/g, `WEBTOOLS_LICENSE_KEY=${licenseKey}`); + } else { + // Add license key to existing content + envContent += `\nWEBTOOLS_LICENSE_KEY=${licenseKey}\n`; + } + } else { + // Create new .env file + envContent = `WEBTOOLS_LICENSE_KEY=${licenseKey}\n`; + } + + await fs.writeFile(envPath, envContent); + console.log(chalk.green('✓ Added license key to .env file')); + + // Detect package manager and create appropriate config file + const packageManager = detectPackageManager(); + + if (packageManager === 'yarn' && isYarnV2OrHigher()) { + // Create .yarnrc.yml file for Yarn v2+ + const yarnrcPath = path.join(currentDir, '.yarnrc.yml'); + const yarnrcContent = `npmScopes: + pluginpal: + npmPublishRegistry: https://npm.pluginpal.io + npmRegistryServer: https://npm.pluginpal.io + npmAlwaysAuth: true + npmAuthIdent: "token" + npmAuthToken: "${licenseKey}" +`; + + await fs.writeFile(yarnrcPath, yarnrcContent); + console.log(chalk.green('✓ Created .yarnrc.yml file with registry configuration')); + } else { + // Create .npmrc file for npm/pnpm/yarn v1 + const npmrcPath = path.join(currentDir, '.npmrc'); + const npmrcContent = `@pluginpal:registry=https://npm.pluginpal.io +//npm.pluginpal.io/:_authToken=${licenseKey} +always-auth=true +`; + + await fs.writeFile(npmrcPath, npmrcContent); + console.log(chalk.green('✓ Created .npmrc file with registry configuration')); + } + + return true; + } catch (error) { + console.error(chalk.red('Error creating license files:'), error); + return false; + } +}