@nitrostack/cli 1.0.12 → 1.0.14
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/dist/commands/cursor.d.ts +11 -0
- package/dist/commands/cursor.d.ts.map +1 -0
- package/dist/commands/cursor.js +238 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +82 -9
- package/dist/commands/upgrade.d.ts +12 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +210 -106
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/skills/clone.d.ts +28 -0
- package/dist/skills/clone.d.ts.map +1 -0
- package/dist/skills/clone.js +60 -0
- package/dist/skills/detect-agents.d.ts +8 -0
- package/dist/skills/detect-agents.d.ts.map +1 -0
- package/dist/skills/detect-agents.js +129 -0
- package/dist/skills/discover.d.ts +12 -0
- package/dist/skills/discover.d.ts.map +1 -0
- package/dist/skills/discover.js +45 -0
- package/dist/skills/index.d.ts +21 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +97 -0
- package/dist/skills/installer.d.ts +21 -0
- package/dist/skills/installer.d.ts.map +1 -0
- package/dist/skills/installer.js +48 -0
- package/dist/skills/types.d.ts +39 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +1 -0
- package/dist/skills/ui.d.ts +55 -0
- package/dist/skills/ui.d.ts.map +1 -0
- package/dist/skills/ui.js +102 -0
- package/package.json +3 -3
- package/templates/typescript-oauth/.env.example +71 -14
- package/templates/typescript-oauth/src/app.module.ts +7 -0
- package/templates/typescript-oauth/src/guards/oauth.guard.ts +19 -0
- package/templates/typescript-oauth/src/index.ts +9 -11
- package/templates/typescript-oauth/src/modules/flights/flights.prompts.ts +19 -1
- package/templates/typescript-oauth/src/services/duffel.service.ts +4 -2
- package/templates/typescript-pizzaz/.env.example +10 -0
- package/templates/typescript-starter/.env.example +10 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface CursorOptions {
|
|
2
|
+
global?: boolean;
|
|
3
|
+
local?: boolean;
|
|
4
|
+
type?: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
port?: string;
|
|
7
|
+
force?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function cursorCommand(options: CursorOptions): Promise<void>;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/commands/cursor.ts"],"names":[],"mappings":"AAqBA,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAuBD,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAoOzE"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fs from 'fs-extra';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { createHeader, createSuccessBox, createErrorBox, NitroSpinner, log, spacer, nextSteps, showFooter, NITRO_BANNER_FULL } from '../ui/branding.js';
|
|
7
|
+
import { trackEvent, shutdownAnalytics } from '../analytics/posthog.js';
|
|
8
|
+
/** Normalize CLI --type values, including the deprecated `sse` alias. */
|
|
9
|
+
function normalizeConnectionType(raw) {
|
|
10
|
+
if (!raw)
|
|
11
|
+
return undefined;
|
|
12
|
+
if (raw === 'sse')
|
|
13
|
+
return 'legacy-sse';
|
|
14
|
+
if (raw === 'command' || raw === 'legacy-sse' || raw === 'streamable-http') {
|
|
15
|
+
return raw;
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
function defaultHttpUrl(type, port) {
|
|
20
|
+
if (type === 'streamable-http') {
|
|
21
|
+
return `http://localhost:${port}/mcp`;
|
|
22
|
+
}
|
|
23
|
+
return `http://localhost:${port}/sse`;
|
|
24
|
+
}
|
|
25
|
+
function isHttpConnectionType(type) {
|
|
26
|
+
return type === 'legacy-sse' || type === 'streamable-http';
|
|
27
|
+
}
|
|
28
|
+
export async function cursorCommand(options) {
|
|
29
|
+
console.log(NITRO_BANNER_FULL);
|
|
30
|
+
console.log(createHeader('Cursor Integration', 'Configure MCP server in Cursor'));
|
|
31
|
+
const startTime = Date.now();
|
|
32
|
+
trackEvent('cli_command_invoked', {
|
|
33
|
+
command: 'cursor',
|
|
34
|
+
options: Object.keys(options).filter(k => options[k] !== undefined),
|
|
35
|
+
});
|
|
36
|
+
const projectRoot = process.cwd();
|
|
37
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
38
|
+
// Validate project
|
|
39
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
40
|
+
console.log(createErrorBox('Not a Valid Project', 'package.json not found in the current directory.'));
|
|
41
|
+
trackEvent('cli_cursor_failed', {
|
|
42
|
+
error: 'Not a valid project: package.json missing',
|
|
43
|
+
});
|
|
44
|
+
await shutdownAnalytics();
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
let packageJson;
|
|
48
|
+
try {
|
|
49
|
+
packageJson = await fs.readJson(packageJsonPath);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.log(createErrorBox('Invalid package.json', 'Could not parse project package.json.'));
|
|
53
|
+
trackEvent('cli_cursor_failed', {
|
|
54
|
+
error: 'Invalid package.json parsing error',
|
|
55
|
+
});
|
|
56
|
+
await shutdownAnalytics();
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
const rawName = packageJson.name || path.basename(projectRoot);
|
|
60
|
+
const serverName = rawName.includes('/') ? rawName.split('/').pop() : rawName;
|
|
61
|
+
let target;
|
|
62
|
+
if (options.global) {
|
|
63
|
+
target = 'global';
|
|
64
|
+
}
|
|
65
|
+
else if (options.local) {
|
|
66
|
+
target = 'local';
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const answers = await inquirer.prompt([
|
|
70
|
+
{
|
|
71
|
+
type: 'list',
|
|
72
|
+
name: 'target',
|
|
73
|
+
message: chalk.white('Where would you like to install the Cursor MCP configuration?'),
|
|
74
|
+
choices: [
|
|
75
|
+
{ name: `Project-level ${chalk.dim('(.cursor/mcp.json)')}`, value: 'local' },
|
|
76
|
+
{ name: `Global ${chalk.dim('(~/.cursor/mcp.json)')}`, value: 'global' },
|
|
77
|
+
],
|
|
78
|
+
default: 'local',
|
|
79
|
+
}
|
|
80
|
+
]);
|
|
81
|
+
target = answers.target;
|
|
82
|
+
}
|
|
83
|
+
let type = normalizeConnectionType(options.type);
|
|
84
|
+
if (options.type && !type) {
|
|
85
|
+
console.log(createErrorBox('Invalid connection type', `Unknown --type "${options.type}". Use: command, legacy-sse, or streamable-http.`));
|
|
86
|
+
await shutdownAnalytics();
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
if (!type) {
|
|
90
|
+
const answers = await inquirer.prompt([
|
|
91
|
+
{
|
|
92
|
+
type: 'list',
|
|
93
|
+
name: 'type',
|
|
94
|
+
message: chalk.white('Choose the connection type for Cursor:'),
|
|
95
|
+
choices: [
|
|
96
|
+
{ name: `Command (Stdio) ${chalk.dim('─ Starts subprocess (recommended for local dev)')}`, value: 'command' },
|
|
97
|
+
{ name: `Legacy SSE (/sse) ${chalk.dim('─ Cursor and older HTTP clients (recommended for Cursor)')}`, value: 'legacy-sse' },
|
|
98
|
+
{ name: `Streamable HTTP (/mcp) ${chalk.dim('─ MCP Inspector and modern Streamable HTTP clients')}`, value: 'streamable-http' },
|
|
99
|
+
],
|
|
100
|
+
default: 'command',
|
|
101
|
+
}
|
|
102
|
+
]);
|
|
103
|
+
type = answers.type;
|
|
104
|
+
}
|
|
105
|
+
if (!type) {
|
|
106
|
+
console.log(createErrorBox('Invalid connection type', 'No connection type selected.'));
|
|
107
|
+
await shutdownAnalytics();
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
const port = options.port || '3000';
|
|
111
|
+
let httpUrl = options.url;
|
|
112
|
+
if (isHttpConnectionType(type) && !httpUrl) {
|
|
113
|
+
const defaultUrl = defaultHttpUrl(type, port);
|
|
114
|
+
const urlHint = type === 'legacy-sse'
|
|
115
|
+
? chalk.dim('Default /sse; /mcp also works for Cursor (legacy SSE fallback on GET).')
|
|
116
|
+
: chalk.dim('For MCP Inspector and clients that use POST initialize + mcp-session-id.');
|
|
117
|
+
const answers = await inquirer.prompt([
|
|
118
|
+
{
|
|
119
|
+
type: 'input',
|
|
120
|
+
name: 'url',
|
|
121
|
+
message: chalk.white('HTTP connection URL:'),
|
|
122
|
+
default: defaultUrl,
|
|
123
|
+
}
|
|
124
|
+
]);
|
|
125
|
+
httpUrl = answers.url;
|
|
126
|
+
if (urlHint) {
|
|
127
|
+
console.log(urlHint);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let configFilePath;
|
|
131
|
+
if (target === 'global') {
|
|
132
|
+
configFilePath = path.join(os.homedir(), '.cursor', 'mcp.json');
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
configFilePath = path.join(projectRoot, '.cursor', 'mcp.json');
|
|
136
|
+
}
|
|
137
|
+
let entry;
|
|
138
|
+
if (type === 'command') {
|
|
139
|
+
const absIndexPath = path.join(projectRoot, 'dist', 'index.js');
|
|
140
|
+
entry = {
|
|
141
|
+
command: 'node',
|
|
142
|
+
args: [absIndexPath],
|
|
143
|
+
env: {}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
entry = {
|
|
148
|
+
url: httpUrl
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const spinner = new NitroSpinner(`Configuring Cursor MCP server...`).start();
|
|
152
|
+
try {
|
|
153
|
+
await fs.ensureDir(path.dirname(configFilePath));
|
|
154
|
+
let mcpConfig = { mcpServers: {} };
|
|
155
|
+
if (await fs.pathExists(configFilePath)) {
|
|
156
|
+
try {
|
|
157
|
+
mcpConfig = await fs.readJson(configFilePath);
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
// Corrupted or empty file, initialize it
|
|
161
|
+
mcpConfig = { mcpServers: {} };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (!mcpConfig.mcpServers) {
|
|
165
|
+
mcpConfig.mcpServers = {};
|
|
166
|
+
}
|
|
167
|
+
// Check if it already exists
|
|
168
|
+
if (mcpConfig.mcpServers[serverName] && !options.force) {
|
|
169
|
+
spinner.stop();
|
|
170
|
+
const { overwrite } = await inquirer.prompt([
|
|
171
|
+
{
|
|
172
|
+
type: 'confirm',
|
|
173
|
+
name: 'overwrite',
|
|
174
|
+
message: chalk.yellow(`MCP Server "${serverName}" is already registered in Cursor config. Overwrite?`),
|
|
175
|
+
default: true,
|
|
176
|
+
}
|
|
177
|
+
]);
|
|
178
|
+
if (!overwrite) {
|
|
179
|
+
log('Cancelled integration', 'warning');
|
|
180
|
+
trackEvent('cli_cursor_cancelled', {
|
|
181
|
+
server_name: serverName,
|
|
182
|
+
target,
|
|
183
|
+
type,
|
|
184
|
+
});
|
|
185
|
+
await shutdownAnalytics();
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
spinner.start();
|
|
189
|
+
}
|
|
190
|
+
mcpConfig.mcpServers[serverName] = entry;
|
|
191
|
+
await fs.writeJson(configFilePath, mcpConfig, { spaces: 2 });
|
|
192
|
+
spinner.succeed(`Registered "${serverName}" in Cursor config`);
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
spinner.fail('Failed to update Cursor configuration');
|
|
196
|
+
console.log(createErrorBox('Integration Failed', err instanceof Error ? err.message : String(err)));
|
|
197
|
+
trackEvent('cli_cursor_failed', {
|
|
198
|
+
error: err instanceof Error ? err.message : String(err),
|
|
199
|
+
target,
|
|
200
|
+
type,
|
|
201
|
+
});
|
|
202
|
+
await shutdownAnalytics();
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
// Summary
|
|
206
|
+
spacer();
|
|
207
|
+
console.log(createSuccessBox('Cursor Integration Successful', [
|
|
208
|
+
`Configured target: ${chalk.cyan(configFilePath)}`,
|
|
209
|
+
`Server registered: ${chalk.cyan(serverName)}`,
|
|
210
|
+
`Connection type: ${chalk.cyan(type)}`,
|
|
211
|
+
type === 'command'
|
|
212
|
+
? `Command path: ${chalk.dim(path.join(projectRoot, 'dist', 'index.js'))}`
|
|
213
|
+
: `HTTP URL: ${chalk.cyan(httpUrl)}`
|
|
214
|
+
]));
|
|
215
|
+
if (type === 'command') {
|
|
216
|
+
// Check if dist/index.js exists
|
|
217
|
+
const distIndexPath = path.join(projectRoot, 'dist', 'index.js');
|
|
218
|
+
if (!fs.existsSync(distIndexPath)) {
|
|
219
|
+
log('Warning: dist/index.js not found. Remember to run "npm run build" first!', 'warning');
|
|
220
|
+
spacer();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (type === 'legacy-sse') {
|
|
224
|
+
log('Tip: ensure the server is running in dual or http mode before connecting from Cursor.', 'info');
|
|
225
|
+
}
|
|
226
|
+
nextSteps([
|
|
227
|
+
'Restart/Reload your Cursor window to load the new MCP server',
|
|
228
|
+
'Check active MCP servers in Cursor under Settings > Tools > MCP',
|
|
229
|
+
]);
|
|
230
|
+
showFooter();
|
|
231
|
+
trackEvent('cli_cursor_completed', {
|
|
232
|
+
target,
|
|
233
|
+
type,
|
|
234
|
+
server_name: serverName,
|
|
235
|
+
duration_ms: Date.now() - startTime,
|
|
236
|
+
});
|
|
237
|
+
await shutdownAnalytics();
|
|
238
|
+
}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -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":"AA4IA,UAAU,WAAW;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,WAAW,iBAmPtF"}
|
package/dist/commands/init.js
CHANGED
|
@@ -7,6 +7,80 @@ import inquirer from 'inquirer';
|
|
|
7
7
|
import { execSync } from 'child_process';
|
|
8
8
|
import { NITRO_BANNER_FULL, createSuccessBox, NitroSpinner, log, spacer, nextSteps, brand, showFooter } from '../ui/branding.js';
|
|
9
9
|
import { trackEvent, shutdownAnalytics } from '../analytics/posthog.js';
|
|
10
|
+
import { runSkillsFlow } from '../skills/index.js';
|
|
11
|
+
import readline from 'readline';
|
|
12
|
+
/**
|
|
13
|
+
* Prompts the user with a horizontal YES/NO choice using left/right arrow keys.
|
|
14
|
+
*/
|
|
15
|
+
async function promptYesNoHorizontal(message, defaultValue = false) {
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
let value = defaultValue;
|
|
18
|
+
const stdin = process.stdin;
|
|
19
|
+
const stdout = process.stdout;
|
|
20
|
+
// Save TTY and raw mode state
|
|
21
|
+
const isRaw = stdin.isRaw;
|
|
22
|
+
if (stdin.isTTY) {
|
|
23
|
+
stdin.setRawMode(true);
|
|
24
|
+
}
|
|
25
|
+
readline.emitKeypressEvents(stdin);
|
|
26
|
+
stdin.resume();
|
|
27
|
+
// Hide cursor
|
|
28
|
+
stdout.write('\u001B[?25l');
|
|
29
|
+
const render = () => {
|
|
30
|
+
readline.clearLine(stdout, 0);
|
|
31
|
+
readline.cursorTo(stdout, 0);
|
|
32
|
+
const qMark = chalk.cyan('?');
|
|
33
|
+
const msg = chalk.bold(message);
|
|
34
|
+
const pointer = chalk.dim('›');
|
|
35
|
+
const separator = chalk.dim(' / ');
|
|
36
|
+
const noPart = !value
|
|
37
|
+
? chalk.cyan.underline('No')
|
|
38
|
+
: chalk.dim('No');
|
|
39
|
+
const yesPart = value
|
|
40
|
+
? chalk.cyan.underline('Yes')
|
|
41
|
+
: chalk.dim('Yes');
|
|
42
|
+
stdout.write(`${qMark} ${msg} ${pointer} ${noPart}${separator}${yesPart}`);
|
|
43
|
+
};
|
|
44
|
+
render();
|
|
45
|
+
const onKeypress = (str, key) => {
|
|
46
|
+
if (!key)
|
|
47
|
+
return;
|
|
48
|
+
if (key.name === 'left' || key.name === 'right') {
|
|
49
|
+
value = !value;
|
|
50
|
+
render();
|
|
51
|
+
}
|
|
52
|
+
else if (key.name === 'return' || key.name === 'enter') {
|
|
53
|
+
cleanup();
|
|
54
|
+
// Clear prompt line and print final answer
|
|
55
|
+
readline.clearLine(stdout, 0);
|
|
56
|
+
readline.cursorTo(stdout, 0);
|
|
57
|
+
const checkMark = chalk.green('✔');
|
|
58
|
+
const finalAns = value ? chalk.cyan('Yes') : chalk.cyan('No');
|
|
59
|
+
stdout.write(`${checkMark} ${chalk.white(message)} ${finalAns}\n`);
|
|
60
|
+
// Resolve after a small delay to prevent keypress bleeding into the next prompt
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
resolve(value);
|
|
63
|
+
}, 100);
|
|
64
|
+
}
|
|
65
|
+
else if (key.ctrl && key.name === 'c') {
|
|
66
|
+
cleanup();
|
|
67
|
+
process.exit(130); // SIGINT exit code
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
const cleanup = () => {
|
|
71
|
+
// Show cursor
|
|
72
|
+
stdout.write('\u001B[?25h');
|
|
73
|
+
stdin.removeListener('keypress', onKeypress);
|
|
74
|
+
// Consume any data currently sitting in the stream buffer
|
|
75
|
+
stdin.read();
|
|
76
|
+
if (stdin.isTTY) {
|
|
77
|
+
stdin.setRawMode(isRaw);
|
|
78
|
+
}
|
|
79
|
+
stdin.pause();
|
|
80
|
+
};
|
|
81
|
+
stdin.on('keypress', onKeypress);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
10
84
|
// ES module equivalent of __dirname
|
|
11
85
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
86
|
const __dirname = dirname(__filename);
|
|
@@ -69,14 +143,7 @@ export async function initCommand(projectName, options) {
|
|
|
69
143
|
const targetDir = path.join(process.cwd(), finalProjectName);
|
|
70
144
|
// Check if directory exists
|
|
71
145
|
if (fs.existsSync(targetDir)) {
|
|
72
|
-
const
|
|
73
|
-
{
|
|
74
|
-
type: 'confirm',
|
|
75
|
-
name: 'overwrite',
|
|
76
|
-
message: chalk.yellow(`Directory ${finalProjectName} already exists. Overwrite?`),
|
|
77
|
-
default: false,
|
|
78
|
-
},
|
|
79
|
-
]);
|
|
146
|
+
const overwrite = await promptYesNoHorizontal(chalk.yellow(`Directory ${finalProjectName} already exists. Overwrite?`), false);
|
|
80
147
|
if (!overwrite) {
|
|
81
148
|
log('Cancelled', 'warning');
|
|
82
149
|
process.exit(0);
|
|
@@ -99,7 +166,7 @@ export async function initCommand(projectName, options) {
|
|
|
99
166
|
value: 'typescript-pizzaz',
|
|
100
167
|
},
|
|
101
168
|
{
|
|
102
|
-
name: `${brand.signal('
|
|
169
|
+
name: `${brand.signal('Flight booking')} ${chalk.dim('Flight booking with OAuth 2.1 auth')}`,
|
|
103
170
|
value: 'typescript-oauth',
|
|
104
171
|
},
|
|
105
172
|
],
|
|
@@ -152,6 +219,12 @@ export async function initCommand(projectName, options) {
|
|
|
152
219
|
fs.writeJSONSync(packageJsonPath, packageJson, { spaces: 2 });
|
|
153
220
|
}
|
|
154
221
|
spinner.succeed('Project created');
|
|
222
|
+
// Agent skills prompt bypassed - installing project-level skills by default
|
|
223
|
+
// const addAgentSkills = await promptYesNoHorizontal('Add agent skills?', true);
|
|
224
|
+
// if (addAgentSkills) {
|
|
225
|
+
// await runSkillsFlow(options.force ?? false, targetDir);
|
|
226
|
+
// }
|
|
227
|
+
await runSkillsFlow(options.force ?? false, targetDir);
|
|
155
228
|
// Install dependencies
|
|
156
229
|
if (!options.skipInstall) {
|
|
157
230
|
spinner = new NitroSpinner('Installing dependencies...').start();
|
|
@@ -2,6 +2,18 @@ interface UpgradeOptions {
|
|
|
2
2
|
latest?: boolean;
|
|
3
3
|
dryRun?: boolean;
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Fetch a package's latest published version from NPM using standard https module.
|
|
7
|
+
*/
|
|
8
|
+
export declare function fetchLatestNpmVersion(packageName: string): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Compare two version strings
|
|
11
|
+
*/
|
|
12
|
+
export declare function compareVersions(v1: string, v2: string): number;
|
|
13
|
+
/**
|
|
14
|
+
* Determine if a dependency refers to a local file or workspace link.
|
|
15
|
+
*/
|
|
16
|
+
export declare function isLocalDependency(version: string): boolean;
|
|
5
17
|
/**
|
|
6
18
|
* Main upgrade command handler
|
|
7
19
|
*/
|
|
@@ -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":"AAmCA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAUD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgD1E;AA2BD;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAa9D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAM1D;AAqED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmM3E"}
|