@nitrostack/cli 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +39 -96
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +4 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +24 -52
- package/dist/commands/generate-types.d.ts +0 -1
- package/dist/commands/generate-types.d.ts.map +1 -1
- package/dist/commands/generate-types.js +18 -39
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +12 -4
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +6 -5
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +3 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +4 -4
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +92 -77
- package/dist/ui/branding.d.ts +21 -4
- package/dist/ui/branding.d.ts.map +1 -1
- package/dist/ui/branding.js +121 -52
- package/package.json +5 -6
- package/templates/typescript-oauth/.env.example +27 -0
- package/templates/typescript-oauth/README.md +36 -231
- package/templates/typescript-pizzaz/.env.example +8 -0
- package/templates/typescript-pizzaz/README.md +42 -217
- package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.module.ts +2 -1
- package/templates/typescript-pizzaz/src/modules/pizzaz/pizzaz.tasks.ts +294 -0
- package/templates/typescript-starter/.env.example +7 -0
- package/templates/typescript-starter/README.md +51 -284
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {
|
|
4
|
-
import { dirname } from 'path';
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = dirname(__filename);
|
|
3
|
+
import { createHeader, createSuccessBox, NitroSpinner, spacer } from '../ui/branding.js';
|
|
7
4
|
/**
|
|
8
5
|
* Generates TypeScript types from tool definitions
|
|
9
|
-
* Scans all *.tools.ts files and extracts types from Zod schemas and examples
|
|
10
6
|
*/
|
|
11
7
|
export async function generateTypes(options = {}) {
|
|
12
8
|
const projectRoot = process.cwd();
|
|
13
9
|
const outputPath = options.output || path.join(projectRoot, 'src', 'types', 'generated-tools.ts');
|
|
14
|
-
console.log('
|
|
10
|
+
console.log(createHeader('Types', 'Generate TypeScript definitions'));
|
|
11
|
+
const spinner = new NitroSpinner('Scanning for tool definitions...').start();
|
|
15
12
|
// Find all *.tools.ts files
|
|
16
13
|
const toolFiles = await findToolFiles(path.join(projectRoot, 'src'));
|
|
17
14
|
if (toolFiles.length === 0) {
|
|
18
|
-
|
|
15
|
+
spinner.fail('No tool files found');
|
|
19
16
|
return;
|
|
20
17
|
}
|
|
21
|
-
|
|
18
|
+
spinner.update(`Found ${toolFiles.length} tool file(s)`);
|
|
22
19
|
// Parse tools and generate types
|
|
23
20
|
const types = await generateTypesFromFiles(toolFiles);
|
|
24
21
|
// Write output file
|
|
@@ -27,7 +24,12 @@ export async function generateTypes(options = {}) {
|
|
|
27
24
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
28
25
|
}
|
|
29
26
|
fs.writeFileSync(outputPath, types);
|
|
30
|
-
|
|
27
|
+
spinner.succeed('Type generation complete');
|
|
28
|
+
spacer();
|
|
29
|
+
console.log(createSuccessBox('Types Generated', [
|
|
30
|
+
`Location: ${path.relative(projectRoot, outputPath)}`,
|
|
31
|
+
`Count: ${toolFiles.length} tools processed`
|
|
32
|
+
]));
|
|
31
33
|
}
|
|
32
34
|
async function findToolFiles(dir) {
|
|
33
35
|
const files = [];
|
|
@@ -135,9 +137,7 @@ function toPascalCase(str) {
|
|
|
135
137
|
}
|
|
136
138
|
function generateTypeFromZodSchema(zodContent) {
|
|
137
139
|
// Simple parser for basic Zod schemas
|
|
138
|
-
// This is a simplified version - in production, you might want to use actual Zod parsing
|
|
139
140
|
const fields = [];
|
|
140
|
-
// Match field definitions like: field_name: z.string().describe('...')
|
|
141
141
|
const fieldRegex = /(\w+):\s*z\.(\w+)\(\)(?:\.optional\(\))?(?:\.describe\([^)]*\))?/g;
|
|
142
142
|
let match;
|
|
143
143
|
while ((match = fieldRegex.exec(zodContent)) !== null) {
|
|
@@ -156,14 +156,7 @@ function generateTypeFromZodSchema(zodContent) {
|
|
|
156
156
|
tsType = 'boolean';
|
|
157
157
|
break;
|
|
158
158
|
case 'enum':
|
|
159
|
-
|
|
160
|
-
const enumMatch = zodContent.match(new RegExp(`${fieldName}:\\s*z\\.enum\\(\\[([^\\]]+)\\]\\)`));
|
|
161
|
-
if (enumMatch) {
|
|
162
|
-
tsType = enumMatch[1].replace(/'/g, '"');
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
tsType = 'string';
|
|
166
|
-
}
|
|
159
|
+
tsType = 'string';
|
|
167
160
|
break;
|
|
168
161
|
case 'array':
|
|
169
162
|
tsType = 'unknown[]';
|
|
@@ -178,11 +171,7 @@ function generateTypeFromZodSchema(zodContent) {
|
|
|
178
171
|
}
|
|
179
172
|
function generateTypeFromExample(exampleJson) {
|
|
180
173
|
try {
|
|
181
|
-
|
|
182
|
-
// This is a simplified version
|
|
183
|
-
const cleaned = exampleJson
|
|
184
|
-
.replace(/\/\/.*/g, '') // Remove comments
|
|
185
|
-
.trim();
|
|
174
|
+
const cleaned = exampleJson.replace(/\/\/.*/g, '').trim();
|
|
186
175
|
const obj = eval('(' + cleaned + ')');
|
|
187
176
|
return generateTypeFromObject(obj);
|
|
188
177
|
}
|
|
@@ -191,29 +180,19 @@ function generateTypeFromExample(exampleJson) {
|
|
|
191
180
|
}
|
|
192
181
|
}
|
|
193
182
|
function generateTypeFromObject(obj, indent = ' ') {
|
|
194
|
-
if (obj === null || obj === undefined)
|
|
183
|
+
if (obj === null || obj === undefined)
|
|
195
184
|
return 'unknown';
|
|
196
|
-
}
|
|
197
185
|
if (Array.isArray(obj)) {
|
|
198
|
-
if (obj.length === 0)
|
|
186
|
+
if (obj.length === 0)
|
|
199
187
|
return 'unknown[]';
|
|
200
|
-
}
|
|
201
|
-
const itemType = generateTypeFromObject(obj[0], indent + ' ');
|
|
202
|
-
return `Array<${itemType}>`;
|
|
188
|
+
return `Array<${generateTypeFromObject(obj[0], indent + ' ')}>`;
|
|
203
189
|
}
|
|
204
190
|
if (typeof obj === 'object') {
|
|
205
191
|
const fields = [];
|
|
206
192
|
for (const [key, value] of Object.entries(obj)) {
|
|
207
|
-
|
|
208
|
-
fields.push(`${key}: ${type}`);
|
|
193
|
+
fields.push(`${key}: ${generateTypeFromObject(value, indent + ' ')}`);
|
|
209
194
|
}
|
|
210
195
|
return `{\n${indent}${fields.join(`;\n${indent}`)};\n${indent.slice(2)}}`;
|
|
211
196
|
}
|
|
212
|
-
|
|
213
|
-
return 'string';
|
|
214
|
-
if (typeof obj === 'number')
|
|
215
|
-
return 'number';
|
|
216
|
-
if (typeof obj === 'boolean')
|
|
217
|
-
return 'boolean';
|
|
218
|
-
return 'unknown';
|
|
197
|
+
return typeof obj;
|
|
219
198
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAgUA,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsGvG"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
-
import { createHeader, createSuccessBox, createErrorBox, log, spacer, nextSteps } from '../ui/branding.js';
|
|
4
|
+
import { createHeader, createSuccessBox, createErrorBox, log, spacer, nextSteps, NITRO_BANNER_FULL, showFooter } from '../ui/branding.js';
|
|
5
5
|
/**
|
|
6
6
|
* Generator templates
|
|
7
7
|
*/
|
|
@@ -295,6 +295,7 @@ function getFilePath(type, name, module) {
|
|
|
295
295
|
* Generate command
|
|
296
296
|
*/
|
|
297
297
|
export async function generate(type, name, options = {}) {
|
|
298
|
+
console.log(NITRO_BANNER_FULL);
|
|
298
299
|
// Special case for types generation
|
|
299
300
|
if (type === 'types') {
|
|
300
301
|
const { generateTypes } = await import('./generate-types.js');
|
|
@@ -305,6 +306,7 @@ export async function generate(type, name, options = {}) {
|
|
|
305
306
|
// Validate type
|
|
306
307
|
const validTypes = Object.keys(TEMPLATES);
|
|
307
308
|
if (!validTypes.includes(type)) {
|
|
309
|
+
spacer();
|
|
308
310
|
console.log(createErrorBox('Invalid Type', `Valid types: ${validTypes.join(', ')}, types`));
|
|
309
311
|
process.exit(1);
|
|
310
312
|
}
|
|
@@ -332,9 +334,9 @@ export async function generate(type, name, options = {}) {
|
|
|
332
334
|
}
|
|
333
335
|
// Check if file already exists
|
|
334
336
|
if (fs.existsSync(filePath) && !options.force) {
|
|
335
|
-
console.log(createErrorBox('File Exists', 'Use --force to overwrite'));
|
|
336
337
|
spacer();
|
|
337
|
-
log(
|
|
338
|
+
console.log(createErrorBox('File Exists', 'Use --force to overwrite if you want to replace the existing file.'));
|
|
339
|
+
log(`Path: ${path.relative(process.cwd(), filePath)}`, 'dim');
|
|
338
340
|
process.exit(1);
|
|
339
341
|
}
|
|
340
342
|
// Write file
|
|
@@ -366,10 +368,16 @@ export async function generate(type, name, options = {}) {
|
|
|
366
368
|
}
|
|
367
369
|
// Summary
|
|
368
370
|
spacer();
|
|
369
|
-
console.log(createSuccessBox('Generation Complete',
|
|
371
|
+
console.log(createSuccessBox('Generation Complete', [
|
|
372
|
+
...generatedFiles,
|
|
373
|
+
'',
|
|
374
|
+
chalk.dim(`Type: ${type}`),
|
|
375
|
+
chalk.dim(`Name: ${name}`)
|
|
376
|
+
]));
|
|
370
377
|
nextSteps([
|
|
371
378
|
'Open the generated file and implement the TODOs',
|
|
372
379
|
'Register the component in your module',
|
|
373
380
|
'Build and test your changes',
|
|
374
381
|
]);
|
|
382
|
+
showFooter();
|
|
375
383
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAoDA,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,WAAW,iBAgNtF"}
|
package/dist/commands/init.js
CHANGED
|
@@ -5,7 +5,7 @@ import { dirname } from 'path';
|
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import inquirer from 'inquirer';
|
|
7
7
|
import { execSync } from 'child_process';
|
|
8
|
-
import { NITRO_BANNER_FULL, createSuccessBox, NitroSpinner, log, spacer, nextSteps, brand } from '../ui/branding.js';
|
|
8
|
+
import { NITRO_BANNER_FULL, createSuccessBox, NitroSpinner, log, spacer, nextSteps, brand, showFooter } from '../ui/branding.js';
|
|
9
9
|
// ES module equivalent of __dirname
|
|
10
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
11
|
const __dirname = dirname(__filename);
|
|
@@ -40,7 +40,7 @@ export async function initCommand(projectName, options) {
|
|
|
40
40
|
try {
|
|
41
41
|
// Show banner
|
|
42
42
|
console.log(NITRO_BANNER_FULL);
|
|
43
|
-
|
|
43
|
+
spacer();
|
|
44
44
|
// Prompt for project name if not provided
|
|
45
45
|
if (!projectName) {
|
|
46
46
|
const answers = await inquirer.prompt([
|
|
@@ -85,15 +85,15 @@ export async function initCommand(projectName, options) {
|
|
|
85
85
|
message: chalk.white('Choose a template:'),
|
|
86
86
|
choices: [
|
|
87
87
|
{
|
|
88
|
-
name: `${brand.
|
|
88
|
+
name: `${brand.signal('Starter')} ${chalk.dim('Simple calculator for learning basics')}`,
|
|
89
89
|
value: 'typescript-starter',
|
|
90
90
|
},
|
|
91
91
|
{
|
|
92
|
-
name: `${brand.
|
|
92
|
+
name: `${brand.signal('Advanced')} ${chalk.dim('Pizza shop finder with maps & widgets')}`,
|
|
93
93
|
value: 'typescript-pizzaz',
|
|
94
94
|
},
|
|
95
95
|
{
|
|
96
|
-
name: `${brand.
|
|
96
|
+
name: `${brand.signal('OAuth')} ${chalk.dim('Flight booking with OAuth 2.1 auth')}`,
|
|
97
97
|
value: 'typescript-oauth',
|
|
98
98
|
},
|
|
99
99
|
],
|
|
@@ -215,6 +215,7 @@ export async function initCommand(projectName, options) {
|
|
|
215
215
|
console.log(chalk.dim(' Mapbox (optional): Get free key from mapbox.com\n'));
|
|
216
216
|
}
|
|
217
217
|
console.log(chalk.dim(' Happy coding! 🎉\n'));
|
|
218
|
+
showFooter();
|
|
218
219
|
}
|
|
219
220
|
catch (error) {
|
|
220
221
|
if (spinner) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAiBA,UAAU,cAAc;IACtB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAoBD;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAkE3E"}
|
package/dist/commands/install.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
|
-
import { createHeader, createSuccessBox, createErrorBox, NitroSpinner, log, spacer, nextSteps } from '../ui/branding.js';
|
|
4
|
+
import { createHeader, createSuccessBox, createErrorBox, NitroSpinner, log, spacer, nextSteps, NITRO_BANNER_FULL, showFooter } from '../ui/branding.js';
|
|
5
5
|
/**
|
|
6
6
|
* Run npm install silently
|
|
7
7
|
*/
|
|
@@ -22,6 +22,7 @@ function hasPackageJson(directory) {
|
|
|
22
22
|
* Main install command handler
|
|
23
23
|
*/
|
|
24
24
|
export async function installCommand(options) {
|
|
25
|
+
console.log(NITRO_BANNER_FULL);
|
|
25
26
|
console.log(createHeader('Install', 'Install project dependencies'));
|
|
26
27
|
const projectRoot = process.cwd();
|
|
27
28
|
const rootPackageJsonPath = path.join(projectRoot, 'package.json');
|
|
@@ -77,4 +78,5 @@ export async function installCommand(options) {
|
|
|
77
78
|
'npm run build - Build for production',
|
|
78
79
|
'npm run upgrade - Upgrade nitrostack',
|
|
79
80
|
]);
|
|
81
|
+
showFooter();
|
|
80
82
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAgBA,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,YAAY,iBA6EvD"}
|
package/dist/commands/start.js
CHANGED
|
@@ -2,8 +2,9 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import fs from 'fs';
|
|
5
|
-
import { createHeader, createInfoBox, createErrorBox, log, spacer,
|
|
5
|
+
import { createHeader, createBox, createInfoBox, createErrorBox, log, spacer, NITRO_BANNER_FULL, showFooter } from '../ui/branding.js';
|
|
6
6
|
export async function startCommand(options) {
|
|
7
|
+
console.log(NITRO_BANNER_FULL);
|
|
7
8
|
console.log(createHeader('Start', 'Production mode'));
|
|
8
9
|
const port = options.port || '3000';
|
|
9
10
|
// Check if dist/index.js exists
|
|
@@ -53,9 +54,7 @@ export async function startCommand(options) {
|
|
|
53
54
|
// Handle graceful shutdown
|
|
54
55
|
const shutdown = () => {
|
|
55
56
|
spacer();
|
|
56
|
-
console.log(
|
|
57
|
-
console.log(brand.accentBold('│') + chalk.yellow.bold(' Shutting down... ') + brand.accentBold('│'));
|
|
58
|
-
console.log(brand.accentBold('└──────────────────────────────────────────────────────────────────┘'));
|
|
57
|
+
console.log(createBox([chalk.yellow.bold('Shutting down...')]));
|
|
59
58
|
serverProcess.kill('SIGTERM');
|
|
60
59
|
setTimeout(() => {
|
|
61
60
|
serverProcess.kill('SIGKILL');
|
|
@@ -65,6 +64,7 @@ export async function startCommand(options) {
|
|
|
65
64
|
};
|
|
66
65
|
process.on('SIGINT', shutdown);
|
|
67
66
|
process.on('SIGTERM', shutdown);
|
|
67
|
+
showFooter();
|
|
68
68
|
// Keep process alive
|
|
69
69
|
await new Promise(() => { });
|
|
70
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"AAyBA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAwHD;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAqI3E"}
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -2,33 +2,33 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { execSync } from 'child_process';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import fs from 'fs-extra';
|
|
5
|
-
import { createHeader, createSuccessBox, createErrorBox, NitroSpinner, log, spacer, nextSteps,
|
|
5
|
+
import { createHeader, createBox, createSuccessBox, createErrorBox, NitroSpinner, log, spacer, nextSteps, NITRO_BANNER_FULL, showFooter } from '../ui/branding.js';
|
|
6
6
|
/**
|
|
7
|
-
* Get the latest version of
|
|
7
|
+
* Get the latest version of a package from npm registry
|
|
8
8
|
*/
|
|
9
|
-
function getLatestVersion() {
|
|
9
|
+
function getLatestVersion(packageName = '@nitrostack/core') {
|
|
10
10
|
try {
|
|
11
|
-
const result = execSync(
|
|
11
|
+
const result = execSync(`npm view ${packageName} version`, {
|
|
12
12
|
encoding: 'utf-8',
|
|
13
13
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
14
14
|
}).trim();
|
|
15
15
|
return result;
|
|
16
16
|
}
|
|
17
17
|
catch {
|
|
18
|
-
throw new Error(
|
|
18
|
+
throw new Error(`Failed to fetch latest version for ${packageName} from npm`);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* Get the current installed version of nitrostack from package.json
|
|
22
|
+
* Get the current installed version of @nitrostack/core from package.json
|
|
23
23
|
*/
|
|
24
|
-
function
|
|
24
|
+
function getCoreVersion(packageJsonPath) {
|
|
25
25
|
if (!fs.existsSync(packageJsonPath)) {
|
|
26
26
|
return null;
|
|
27
27
|
}
|
|
28
28
|
const packageJson = fs.readJSONSync(packageJsonPath);
|
|
29
|
-
|
|
30
|
-
packageJson.devDependencies?.nitrostack
|
|
31
|
-
|
|
29
|
+
return packageJson.dependencies?.['@nitrostack/core'] ||
|
|
30
|
+
packageJson.devDependencies?.['@nitrostack/core'] ||
|
|
31
|
+
null;
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Parse version string to extract the actual version number
|
|
@@ -53,26 +53,41 @@ function compareVersions(v1, v2) {
|
|
|
53
53
|
return 0;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
* Update nitrostack
|
|
56
|
+
* Update all @nitrostack/* versions in package.json
|
|
57
57
|
*/
|
|
58
58
|
function updatePackageJson(packageJsonPath, newVersion, dryRun) {
|
|
59
59
|
if (!fs.existsSync(packageJsonPath)) {
|
|
60
|
-
return
|
|
60
|
+
return [];
|
|
61
61
|
}
|
|
62
62
|
const packageJson = fs.readJSONSync(packageJsonPath);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
const results = [];
|
|
64
|
+
let hasChanges = false;
|
|
65
|
+
const updateDeps = (deps) => {
|
|
66
|
+
if (!deps)
|
|
67
|
+
return;
|
|
68
|
+
for (const pkg of Object.keys(deps)) {
|
|
69
|
+
if (pkg.startsWith('@nitrostack/')) {
|
|
70
|
+
const currentVersion = deps[pkg];
|
|
71
|
+
if (compareVersions(currentVersion, newVersion) < 0) {
|
|
72
|
+
results.push({
|
|
73
|
+
location: path.basename(path.dirname(packageJsonPath)),
|
|
74
|
+
packageName: pkg,
|
|
75
|
+
previousVersion: currentVersion,
|
|
76
|
+
newVersion: `^${newVersion}`,
|
|
77
|
+
upgraded: true,
|
|
78
|
+
});
|
|
79
|
+
deps[pkg] = `^${newVersion}`;
|
|
80
|
+
hasChanges = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
updateDeps(packageJson.dependencies);
|
|
86
|
+
updateDeps(packageJson.devDependencies);
|
|
87
|
+
if (hasChanges && !dryRun) {
|
|
73
88
|
fs.writeJSONSync(packageJsonPath, packageJson, { spaces: 2 });
|
|
74
89
|
}
|
|
75
|
-
return
|
|
90
|
+
return results;
|
|
76
91
|
}
|
|
77
92
|
/**
|
|
78
93
|
* Run npm install silently
|
|
@@ -87,7 +102,8 @@ function runNpmInstall(directory) {
|
|
|
87
102
|
* Main upgrade command handler
|
|
88
103
|
*/
|
|
89
104
|
export async function upgradeCommand(options) {
|
|
90
|
-
console.log(
|
|
105
|
+
console.log(NITRO_BANNER_FULL);
|
|
106
|
+
console.log(createHeader('Upgrade', 'Update @nitrostack packages to latest'));
|
|
91
107
|
const projectRoot = process.cwd();
|
|
92
108
|
const rootPackageJsonPath = path.join(projectRoot, 'package.json');
|
|
93
109
|
const widgetsPath = path.join(projectRoot, 'src', 'widgets');
|
|
@@ -97,16 +113,16 @@ export async function upgradeCommand(options) {
|
|
|
97
113
|
console.log(createErrorBox('Not a NitroStack Project', 'package.json not found'));
|
|
98
114
|
process.exit(1);
|
|
99
115
|
}
|
|
100
|
-
const
|
|
101
|
-
if (!
|
|
102
|
-
console.log(createErrorBox('Not a NitroStack Project', 'nitrostack is not a dependency'));
|
|
116
|
+
const coreVersion = getCoreVersion(rootPackageJsonPath);
|
|
117
|
+
if (!coreVersion) {
|
|
118
|
+
console.log(createErrorBox('Not a NitroStack Project', '@nitrostack/core is not a dependency'));
|
|
103
119
|
process.exit(1);
|
|
104
120
|
}
|
|
105
121
|
// Fetch latest version
|
|
106
122
|
const spinner = new NitroSpinner('Checking for updates...').start();
|
|
107
123
|
let latestVersion;
|
|
108
124
|
try {
|
|
109
|
-
latestVersion = getLatestVersion();
|
|
125
|
+
latestVersion = getLatestVersion('@nitrostack/core');
|
|
110
126
|
spinner.succeed(`Latest version: ${chalk.cyan(latestVersion)}`);
|
|
111
127
|
}
|
|
112
128
|
catch (error) {
|
|
@@ -114,16 +130,16 @@ export async function upgradeCommand(options) {
|
|
|
114
130
|
process.exit(1);
|
|
115
131
|
}
|
|
116
132
|
// Check if already on latest
|
|
117
|
-
const
|
|
118
|
-
if (compareVersions(
|
|
133
|
+
const currentParsedVersion = parseVersion(coreVersion);
|
|
134
|
+
if (compareVersions(currentParsedVersion, latestVersion) >= 0) {
|
|
119
135
|
spacer();
|
|
120
136
|
console.log(createSuccessBox('Already Up to Date', [
|
|
121
|
-
`Current version: ${
|
|
137
|
+
`Current version: ${currentParsedVersion}`,
|
|
122
138
|
`Latest version: ${latestVersion}`,
|
|
123
139
|
]));
|
|
124
140
|
return;
|
|
125
141
|
}
|
|
126
|
-
const
|
|
142
|
+
const allResults = [];
|
|
127
143
|
const dryRun = options.dryRun ?? false;
|
|
128
144
|
if (dryRun) {
|
|
129
145
|
spacer();
|
|
@@ -135,15 +151,10 @@ export async function upgradeCommand(options) {
|
|
|
135
151
|
// Upgrade root
|
|
136
152
|
const rootSpinner = new NitroSpinner('Updating root package.json...').start();
|
|
137
153
|
try {
|
|
138
|
-
const
|
|
139
|
-
if (
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
previousVersion: rootCurrentVersion,
|
|
143
|
-
newVersion: `^${latestVersion}`,
|
|
144
|
-
upgraded: true,
|
|
145
|
-
});
|
|
146
|
-
rootSpinner.succeed(`Root: ${chalk.dim(rootCurrentVersion)} → ${chalk.cyan(`^${latestVersion}`)}`);
|
|
154
|
+
const results = updatePackageJson(rootPackageJsonPath, latestVersion, dryRun);
|
|
155
|
+
if (results.length > 0) {
|
|
156
|
+
allResults.push(...results);
|
|
157
|
+
rootSpinner.succeed(`Root: Updated ${results.length} @nitrostack packages`);
|
|
147
158
|
if (!dryRun) {
|
|
148
159
|
const installSpinner = new NitroSpinner('Installing dependencies...').start();
|
|
149
160
|
runNpmInstall(projectRoot);
|
|
@@ -151,64 +162,68 @@ export async function upgradeCommand(options) {
|
|
|
151
162
|
}
|
|
152
163
|
}
|
|
153
164
|
else {
|
|
154
|
-
rootSpinner.info('Root:
|
|
165
|
+
rootSpinner.info('Root: All @nitrostack packages are up to date');
|
|
155
166
|
}
|
|
156
167
|
}
|
|
157
168
|
catch (error) {
|
|
158
169
|
rootSpinner.fail('Failed to upgrade root');
|
|
159
|
-
|
|
170
|
+
console.error(error);
|
|
160
171
|
}
|
|
161
172
|
// Upgrade widgets if they exist
|
|
162
173
|
if (fs.existsSync(widgetsPackageJsonPath)) {
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
upgraded: true,
|
|
174
|
-
});
|
|
175
|
-
widgetsSpinner.succeed(`Widgets: ${chalk.dim(widgetsCurrentVersion)} → ${chalk.cyan(`^${latestVersion}`)}`);
|
|
176
|
-
if (!dryRun) {
|
|
177
|
-
const installSpinner = new NitroSpinner('Installing widget dependencies...').start();
|
|
178
|
-
runNpmInstall(widgetsPath);
|
|
179
|
-
installSpinner.succeed('Widget dependencies installed');
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
else {
|
|
183
|
-
widgetsSpinner.info('Widgets: No changes needed');
|
|
174
|
+
const widgetsSpinner = new NitroSpinner('Updating widgets package.json...').start();
|
|
175
|
+
try {
|
|
176
|
+
const results = updatePackageJson(widgetsPackageJsonPath, latestVersion, dryRun);
|
|
177
|
+
if (results.length > 0) {
|
|
178
|
+
allResults.push(...results);
|
|
179
|
+
widgetsSpinner.succeed(`Widgets: Updated ${results.length} @nitrostack packages`);
|
|
180
|
+
if (!dryRun) {
|
|
181
|
+
const installSpinner = new NitroSpinner('Installing widget dependencies...').start();
|
|
182
|
+
runNpmInstall(widgetsPath);
|
|
183
|
+
installSpinner.succeed('Widget dependencies installed');
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
|
-
|
|
187
|
-
widgetsSpinner.
|
|
186
|
+
else {
|
|
187
|
+
widgetsSpinner.info('Widgets: All @nitrostack packages are up to date');
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
catch (error) {
|
|
191
|
+
widgetsSpinner.fail('Failed to upgrade widgets');
|
|
192
|
+
}
|
|
193
193
|
}
|
|
194
194
|
// Summary
|
|
195
195
|
spacer();
|
|
196
|
-
if (
|
|
196
|
+
if (allResults.length === 0) {
|
|
197
197
|
log('No packages were upgraded', 'warning');
|
|
198
198
|
}
|
|
199
199
|
else {
|
|
200
|
-
|
|
200
|
+
// Unique packages upgraded
|
|
201
|
+
const uniquePackages = Array.from(new Set(allResults.map(r => r.packageName)));
|
|
202
|
+
const summaryItems = uniquePackages.map(pkg => {
|
|
203
|
+
const result = allResults.find(r => r.packageName === pkg);
|
|
204
|
+
return `${pkg}: ${parseVersion(result.previousVersion)} → ${parseVersion(result.newVersion)}`;
|
|
205
|
+
});
|
|
201
206
|
if (dryRun) {
|
|
202
|
-
|
|
203
|
-
log(
|
|
207
|
+
spacer();
|
|
208
|
+
console.log(createBox([
|
|
209
|
+
chalk.yellow.bold('Dry run complete'),
|
|
210
|
+
'',
|
|
211
|
+
chalk.dim('No changes were made to your project.'),
|
|
212
|
+
chalk.dim('Run without --dry-run to apply the upgrade.'),
|
|
213
|
+
], 'warning'));
|
|
204
214
|
}
|
|
205
215
|
else {
|
|
206
|
-
console.log(createSuccessBox('Upgrade Complete',
|
|
216
|
+
console.log(createSuccessBox('Upgrade Complete', [
|
|
217
|
+
...summaryItems,
|
|
218
|
+
'',
|
|
219
|
+
chalk.dim(`Total updates across all packages: ${allResults.length}`)
|
|
220
|
+
]));
|
|
207
221
|
nextSteps([
|
|
208
|
-
'Review the changes',
|
|
209
|
-
'
|
|
210
|
-
'Check
|
|
222
|
+
'Review the changes in package.json',
|
|
223
|
+
'Restart your development server',
|
|
224
|
+
'Check docs.nitrostack.ai for migration guides',
|
|
211
225
|
]);
|
|
212
226
|
}
|
|
227
|
+
showFooter();
|
|
213
228
|
}
|
|
214
229
|
}
|
package/dist/ui/branding.d.ts
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
|
+
export declare const LINKS: {
|
|
2
|
+
website: string;
|
|
3
|
+
docs: string;
|
|
4
|
+
studio: string;
|
|
5
|
+
};
|
|
1
6
|
export declare const brand: {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
signal: import("chalk").ChalkInstance;
|
|
8
|
+
signalBold: import("chalk").ChalkInstance;
|
|
9
|
+
sky: import("chalk").ChalkInstance;
|
|
10
|
+
skyBold: import("chalk").ChalkInstance;
|
|
11
|
+
mint: import("chalk").ChalkInstance;
|
|
12
|
+
mintBold: import("chalk").ChalkInstance;
|
|
13
|
+
error: import("chalk").ChalkInstance;
|
|
14
|
+
warning: import("chalk").ChalkInstance;
|
|
6
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Creates a clickable terminal link using OSC 8 escape sequence
|
|
18
|
+
*/
|
|
19
|
+
export declare function terminalLink(text: string, url: string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Redesigned Banner with Restored ASCII NITRO
|
|
22
|
+
*/
|
|
7
23
|
export declare const NITRO_BANNER_FULL: string;
|
|
8
24
|
export declare function createHeader(title: string, subtitle?: string): string;
|
|
9
25
|
export declare function createBox(lines: string[], type?: 'success' | 'error' | 'info' | 'warning'): string;
|
|
@@ -28,4 +44,5 @@ export declare function log(message: string, type?: 'success' | 'error' | 'info'
|
|
|
28
44
|
export declare function divider(): void;
|
|
29
45
|
export declare function spacer(): void;
|
|
30
46
|
export declare function nextSteps(steps: string[]): void;
|
|
47
|
+
export declare function showFooter(): void;
|
|
31
48
|
//# sourceMappingURL=branding.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branding.d.ts","sourceRoot":"","sources":["../../src/ui/branding.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"branding.d.ts","sourceRoot":"","sources":["../../src/ui/branding.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,KAAK;;;;CAIjB,CAAC;AAEF,eAAO,MAAM,KAAK;;;;;;;;;CASjB,CAAC;AASF;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG9D;AAaD;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAa7B,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAqBrE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAkB,GAAG,MAAM,CA4B1G;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAQvE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAQrE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,MAAM,CAK/E;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAM;gBAET,IAAI,EAAE,MAAM;IAQxB,KAAK,IAAI,IAAI;IAKb,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK1B,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAK5B,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAKzB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAKzB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAKzB,IAAI,IAAI,IAAI;CAIb;AAED,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,KAAc,GAAG,IAAI,CAU1G;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAED,wBAAgB,MAAM,IAAI,IAAI,CAE7B;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAc/C;AAED,wBAAgB,UAAU,IAAI,IAAI,CAYjC"}
|