Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/gold-places-yawn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"webtools-cli": minor
---

feat: add license key setup to the cli
45 changes: 40 additions & 5 deletions packages/cli/src/commands/install.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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();

Expand Down Expand Up @@ -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,
})),
Expand All @@ -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);
}
Expand Down
13 changes: 13 additions & 0 deletions packages/cli/src/constants/addons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
},
];
6 changes: 5 additions & 1 deletion packages/cli/src/utils/addons.ts
Original file line number Diff line number Diff line change
@@ -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;
}
86 changes: 86 additions & 0 deletions packages/cli/src/utils/license.ts
Original file line number Diff line number Diff line change
@@ -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<boolean> {
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;
}
}