Skip to content

Commit f7e080c

Browse files
committed
feat: extended CLI for licensing
1 parent c0a73ae commit f7e080c

File tree

4 files changed

+140
-24
lines changed

4 files changed

+140
-24
lines changed

packages/cli/src/commands/enable.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export async function enable() {
3030

3131
// Enable Webtools for selected content types
3232
if (selectedContentTypes.length > 0) {
33-
console.log(chalk.blue('\nEnabling Webtools for selected content types...'));
33+
console.log(`\n${chalk.cyan('●')} Enabling Webtools for selected content types...`);
3434

35-
const results = selectedContentTypes.map((contentType) => {
35+
selectedContentTypes.map((contentType) => {
3636
const success = enableWebtoolsForContentType(contentType);
3737
if (success) {
3838
console.log(chalk.green(`✓ Enabled Webtools for ${contentType}`));
@@ -42,9 +42,6 @@ export async function enable() {
4242
console.log(chalk.red(`✗ Failed to enable Webtools for ${contentType}`));
4343
return false;
4444
});
45-
46-
const successCount = results.filter(Boolean).length;
47-
console.log(chalk.blue(`\nEnabled Webtools for ${successCount} of ${selectedContentTypes.length} content types.`));
4845
} else {
4946
console.log(chalk.yellow('No content types selected. Nothing to do.'));
5047
}

packages/cli/src/commands/install.ts

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import chalk from 'chalk';
2-
import { checkbox, confirm, input } from '@inquirer/prompts';
2+
import { checkbox, input, select } from '@inquirer/prompts';
33
import { checkStrapiProject } from '../utils/strapi';
44
import { getContentTypes, enableWebtoolsForContentType } from '../utils/content-types';
55
import { getAvailableAddons, getPremiumAddons } from '../utils/addons';
66
import { installPackage } from '../utils/package-manager';
77
import { createLicenseFiles } from '../utils/license';
8+
import { logger } from '../utils/logger';
89

910
export async function install() {
1011
// Check if we're in a Strapi project
@@ -14,14 +15,30 @@ export async function install() {
1415
return;
1516
}
1617

17-
// Ask about license key
18-
const hasLicense = await confirm({
19-
message: 'Do you have a license key for Webtools?',
20-
default: false,
18+
logger.title(
19+
'Webtools',
20+
`${chalk.bold('🚀 Let\'s build your new website with Strapi')}\n`,
21+
);
22+
23+
console.log('🚀 Get more out of Webtools with premium add-ons!\n');
24+
25+
console.log('Start your free trial and get:');
26+
console.log('✨ 30 days of access to the Essential plan, which includes:');
27+
console.log('✅ Automated Redirects');
28+
console.log('✅ Internal Links\n');
29+
30+
const selectedPlan = await select({
31+
message: 'Do you have a license?',
32+
choices: [
33+
{ name: 'Yes, use my license', value: 'license' },
34+
{ name: 'Get me a trial', value: 'trial' },
35+
{ name: 'Skip', value: 'skip' },
36+
],
2137
});
2238

2339
let licenseKey: string | null = null;
24-
if (hasLicense) {
40+
41+
if (selectedPlan === 'license') {
2542
licenseKey = await input({
2643
message: 'Please enter your license key:',
2744
validate: (value) => {
@@ -33,14 +50,53 @@ export async function install() {
3350
});
3451

3552
// Create license files
36-
console.log(chalk.blue('\nSetting up license configuration...'));
53+
console.log(`\n${chalk.cyan('●')} Setting up license configuration...`);
3754
const success = await createLicenseFiles(licenseKey);
3855
if (!success) {
39-
console.log(chalk.red('Failed to setup license configuration. Continuing without the license.'));
56+
console.log(chalk.red('\nFailed to setup license configuration. Continuing without a license.'));
4057
licenseKey = null;
4158
}
4259
}
4360

61+
if (selectedPlan === 'trial') {
62+
logger.title(
63+
'Trial',
64+
`${chalk.bold('🚀 Get your free trial license!')}\n`,
65+
);
66+
console.log('You can start your free trial by visiting the following link:');
67+
console.log(chalk.underline('https://polar.sh/checkout/polar_c_4NUnsZ24PTLPhbSux9STPqeLL7ptZlcz003Yy15MArc'));
68+
console.log('\n✨ Enjoy 30 days of access to the Essential plan completely free!');
69+
console.log('💡 Remember: You can cancel within the 30 days to ensure your trial remains free.\n');
70+
71+
const trialPlan = await select({
72+
message: 'Got your license key?',
73+
choices: [
74+
{ name: 'Yes', value: 'yes' },
75+
{ name: 'Skip', value: 'skip' },
76+
],
77+
});
78+
79+
if (trialPlan === 'yes') {
80+
licenseKey = await input({
81+
message: 'Please enter your license key:',
82+
validate: (value) => {
83+
if (!value || value.trim().length === 0) {
84+
return 'License key cannot be empty';
85+
}
86+
return true;
87+
},
88+
});
89+
90+
// Create license files
91+
console.log(`\n${chalk.cyan('●')} Setting up license configuration...`);
92+
const success = await createLicenseFiles(licenseKey);
93+
if (!success) {
94+
console.log(chalk.red('\nFailed to setup license configuration. Continuing without a license.'));
95+
licenseKey = null;
96+
}
97+
}
98+
}
99+
44100
// Get available content types
45101
const contentTypes = getContentTypes();
46102

@@ -58,9 +114,9 @@ export async function install() {
58114

59115
// Enable Webtools for selected content types
60116
if (selectedContentTypes.length > 0) {
61-
console.log(chalk.blue('\nEnabling Webtools for selected content types...'));
117+
console.log(`\n${chalk.cyan('●')} Enabling Webtools for selected content types...`);
62118

63-
const results = selectedContentTypes.map((contentType) => {
119+
selectedContentTypes.map((contentType) => {
64120
const success = enableWebtoolsForContentType(contentType);
65121
if (success) {
66122
console.log(chalk.green(`✓ Enabled Webtools for ${contentType}`));
@@ -70,9 +126,6 @@ export async function install() {
70126
console.log(chalk.red(`✗ Failed to enable Webtools for ${contentType}`));
71127
return false;
72128
});
73-
74-
const successCount = results.filter(Boolean).length;
75-
console.log(chalk.blue(`\nEnabled Webtools for ${successCount} of ${selectedContentTypes.length} content types.`));
76129
}
77130
}
78131

@@ -86,6 +139,9 @@ export async function install() {
86139
allAddons = [...availableAddons, ...premiumAddons];
87140
}
88141

142+
// New line
143+
console.log('');
144+
89145
// Let user select addons
90146
const selectedAddons = await checkbox({
91147
message: 'Select addons to install:',
@@ -109,13 +165,13 @@ export async function install() {
109165

110166
// Install all packages at once
111167
if (packagesToInstall.length > 0) {
112-
console.log(chalk.blue('\nInstalling packages...'));
168+
console.log(`\n${chalk.cyan('●')} Installing packages...\n`);
113169

114170
const success = installPackage(packagesToInstall.join(' '));
115171
if (success) {
116-
console.log(chalk.green(`✓ Installed ${packagesToInstall.length} packages successfully`));
172+
console.log(chalk.green(`\n✓ Installed ${packagesToInstall.length} packages successfully`));
117173
} else {
118-
console.log(chalk.red('✗ Failed to install packages. Aborting installation.'));
174+
console.log(chalk.red('\n✗ Failed to install packages. Aborting installation.'));
119175
return;
120176
}
121177
}

packages/cli/src/utils/license.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export async function createLicenseFiles(licenseKey: string): Promise<boolean> {
6565
`;
6666

6767
await fs.writeFile(yarnrcPath, yarnrcContent);
68-
console.log(chalk.green('✓ Created .yarnrc.yml file with registry configuration'));
68+
console.log(chalk.green('✓ Created .yarnrc.yml file with registry configuration \n'));
6969
} else {
7070
// Create .npmrc file for npm/pnpm/yarn v1
7171
const npmrcPath = path.join(currentDir, '.npmrc');
@@ -75,12 +75,12 @@ always-auth=true
7575
`;
7676

7777
await fs.writeFile(npmrcPath, npmrcContent);
78-
console.log(chalk.green('✓ Created .npmrc file with registry configuration'));
78+
console.log(chalk.green('✓ Created .npmrc file with registry configuration \n'));
7979
}
8080

8181
return true;
8282
} catch (error) {
83-
console.error(chalk.red('Error creating license files:'), error);
83+
console.error(chalk.red('Error creating license files:'), error, '\n');
8484
return false;
8585
}
8686
}

packages/cli/src/utils/logger.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import chalk from 'chalk';
2+
import type { ChalkFunction } from 'chalk';
3+
4+
const MAX_PREFIX_LENGTH = 8;
5+
6+
const badge = (text: string, bgColor: ChalkFunction, textColor: ChalkFunction = chalk.black) => {
7+
const wrappedText = ` ${text} `;
8+
9+
const repeat = Math.max(0, MAX_PREFIX_LENGTH - wrappedText.length);
10+
11+
return ' '.repeat(repeat) + bgColor(textColor(wrappedText));
12+
};
13+
14+
const textIndent = (
15+
text: string | string[],
16+
indentFirst = true,
17+
indent: number = MAX_PREFIX_LENGTH + 2
18+
) => {
19+
const parts = Array.isArray(text) ? text : [text];
20+
21+
return parts
22+
.map((part, i) => {
23+
if (i === 0 && !indentFirst) {
24+
return part;
25+
}
26+
27+
return ' '.repeat(indent) + part;
28+
})
29+
.join('\n');
30+
};
31+
32+
export const logger = {
33+
log(message: string | string[]): void {
34+
console.log(textIndent(message));
35+
},
36+
title(title: string, message: string): void {
37+
const prefix = badge(title, chalk.bgBlueBright);
38+
console.log(`\n${prefix} ${message}`);
39+
},
40+
info(message: string): void {
41+
console.log(`${' '.repeat(7)}${chalk.cyan('●')} ${message}`);
42+
},
43+
success(message: string): void {
44+
console.log(`\n${' '.repeat(7)}${chalk.green('✓')} ${chalk.green(message)}`);
45+
},
46+
fatal(message?: string | string[]): never {
47+
const prefix = badge('Error', chalk.bgRed);
48+
49+
if (message) {
50+
console.error(`\n${prefix} ${textIndent(message, false)}\n`);
51+
}
52+
53+
process.exit(1);
54+
},
55+
error(message: string | string[]): void {
56+
const prefix = badge('Error', chalk.bgRed);
57+
console.error(`\n${prefix} ${textIndent(message, false)}\n`);
58+
},
59+
warn(message: string | string[]): void {
60+
const prefix = badge('Warn', chalk.bgYellow);
61+
console.warn(`\n${prefix} ${textIndent(message, false)}\n`);
62+
},
63+
};

0 commit comments

Comments
 (0)