@chemx/create-chemx 26.9.25-747 → 26.9.25-789
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/cli/commands/cmd-router.js +15 -1
- package/cli/commands-schema.js +36 -0
- package/cli/help.d.ts +2 -0
- package/cli/help.js +64 -0
- package/cli/help.spec.js +54 -1
- package/cli/reader-shorthand.spec.js +2 -2
- package/cli/scaffold.js +35 -4
- package/cli/ui-handlers.js +1 -1
- package/package.json +1 -1
|
@@ -94,12 +94,26 @@ export const dispatchCommand = async (firstArg, rawArgs, runAudit, getPackageVer
|
|
|
94
94
|
break;
|
|
95
95
|
}
|
|
96
96
|
case 'init': {
|
|
97
|
+
const isHelpRequested = rawArgs.includes('--help') || rawArgs.includes('-h') || rawArgs[1] === 'help';
|
|
98
|
+
if (isHelpRequested) {
|
|
99
|
+
const { printInitHelp } = await import('../help.js');
|
|
100
|
+
printInitHelp();
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
const nonFlagArgs = rawArgs.slice(1).filter((arg) => !arg.startsWith('-'));
|
|
104
|
+
const targetSubDir = nonFlagArgs[0] || 'src/chemical-x';
|
|
97
105
|
const { runInit } = await import('../scaffold.js');
|
|
98
|
-
await runInit(
|
|
106
|
+
await runInit(targetSubDir, rawArgs, runAudit);
|
|
99
107
|
break;
|
|
100
108
|
}
|
|
101
109
|
case 'create':
|
|
102
110
|
case 'scaffold': {
|
|
111
|
+
const isHelpRequested = rawArgs.includes('--help') || rawArgs.includes('-h') || rawArgs[1] === 'help';
|
|
112
|
+
if (isHelpRequested) {
|
|
113
|
+
const { printScaffoldHelp } = await import('../help.js');
|
|
114
|
+
printScaffoldHelp();
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
103
117
|
const { runScaffold } = await import('../scaffold.js');
|
|
104
118
|
const nonFlagArgs = rawArgs.slice(1).filter((arg) => !arg.startsWith('-'));
|
|
105
119
|
await runScaffold(nonFlagArgs[0], rawArgs, runAudit);
|
package/cli/commands-schema.js
CHANGED
|
@@ -222,5 +222,41 @@ export const COMMANDS_SCHEMA = [
|
|
|
222
222
|
'npx chemx tesseract',
|
|
223
223
|
'npx chemx tesseract --json'
|
|
224
224
|
]
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
name: 'init',
|
|
228
|
+
aliases: [],
|
|
229
|
+
usage: 'npx chemx init [directory] [options]',
|
|
230
|
+
summary: 'Unpack blueprints and molecular architecture drop-in files into an existing codebase.',
|
|
231
|
+
description: 'Installs blueprints, domain hooks, and foundation capsules into target directory (default: src/chemical-x).',
|
|
232
|
+
flags: [
|
|
233
|
+
{ flag: '-h, --help', desc: 'Show this help message' },
|
|
234
|
+
{ flag: '--license=<key>', desc: 'Provide commercial license key for enterprise starter kit assets' }
|
|
235
|
+
],
|
|
236
|
+
examples: [
|
|
237
|
+
'npx chemx init',
|
|
238
|
+
'npx chemx init src/chemical-x',
|
|
239
|
+
'npx chemx init packages/ui/src/modules'
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: 'create',
|
|
244
|
+
aliases: ['scaffold'],
|
|
245
|
+
usage: 'npm create chemx [directory] [options]',
|
|
246
|
+
summary: 'Scaffold a complete new Chemical X Molecular Architecture application.',
|
|
247
|
+
description: 'Generates a full starter project configured with Chemical X molecular architecture, framework presets, and agent steering directives.',
|
|
248
|
+
flags: [
|
|
249
|
+
{ flag: '--framework=<id>', desc: 'Framework flavor: react (default), vue, svelte' },
|
|
250
|
+
{ flag: '--yes, -y', desc: 'Skip interactive prompts and scaffold Community Edition immediately' },
|
|
251
|
+
{ flag: '--install', desc: 'Auto-install dependencies after scaffolding' },
|
|
252
|
+
{ flag: '--headless', desc: 'Run in headless mode for CI/CD and AI agent automation' },
|
|
253
|
+
{ flag: '-h, --help', desc: 'Show this help message' },
|
|
254
|
+
{ flag: '-v, --version', desc: 'Show version number' }
|
|
255
|
+
],
|
|
256
|
+
examples: [
|
|
257
|
+
'npm create chemx my-molecular-app --framework=react',
|
|
258
|
+
'npx create-chemx my-vue-app --framework=vue --yes',
|
|
259
|
+
'npx chemx create my-app --framework=svelte --install'
|
|
260
|
+
]
|
|
225
261
|
}
|
|
226
262
|
];
|
package/cli/help.d.ts
CHANGED
package/cli/help.js
CHANGED
|
@@ -54,3 +54,67 @@ export const printHelp = () => {
|
|
|
54
54
|
|
|
55
55
|
process.stdout.write(lines.join('\n'));
|
|
56
56
|
};
|
|
57
|
+
|
|
58
|
+
export const printInitHelp = () => {
|
|
59
|
+
renderBanner('Chemical X: In-Repo Capsule Drop-in (chemx init)');
|
|
60
|
+
|
|
61
|
+
const BOLD = '\x1b[1m';
|
|
62
|
+
const CYAN = '\x1b[36m';
|
|
63
|
+
const RESET = '\x1b[0m';
|
|
64
|
+
|
|
65
|
+
const lines = [
|
|
66
|
+
`${BOLD}USAGE${RESET}`,
|
|
67
|
+
` ${CYAN}npx chemx init${RESET} [directory] [options]`,
|
|
68
|
+
'',
|
|
69
|
+
`${BOLD}DESCRIPTION${RESET}`,
|
|
70
|
+
' Unpack Chemical X blueprints and molecular architecture drop-in files',
|
|
71
|
+
' into an existing codebase (defaults to src/chemical-x).',
|
|
72
|
+
'',
|
|
73
|
+
`${BOLD}OPTIONS${RESET}`,
|
|
74
|
+
` ${CYAN}-h, --help${RESET} Show this help message`,
|
|
75
|
+
` ${CYAN}--license=<key>${RESET} Provide commercial license key for enterprise starter kit assets`,
|
|
76
|
+
'',
|
|
77
|
+
`${BOLD}EXAMPLES${RESET}`,
|
|
78
|
+
` ${CYAN}npx chemx init${RESET}`,
|
|
79
|
+
` ${CYAN}npx chemx init src/chemical-x${RESET}`,
|
|
80
|
+
` ${CYAN}npx chemx init packages/ui/src/modules${RESET}`,
|
|
81
|
+
''
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
process.stdout.write(lines.join('\n'));
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const printScaffoldHelp = () => {
|
|
88
|
+
renderBanner('Chemical X: Project Scaffolder (npm create chemx)');
|
|
89
|
+
|
|
90
|
+
const BOLD = '\x1b[1m';
|
|
91
|
+
const CYAN = '\x1b[36m';
|
|
92
|
+
const RESET = '\x1b[0m';
|
|
93
|
+
|
|
94
|
+
const lines = [
|
|
95
|
+
`${BOLD}USAGE${RESET}`,
|
|
96
|
+
` ${CYAN}npm create chemx${RESET} [directory] [options]`,
|
|
97
|
+
` ${CYAN}npx create-chemx${RESET} [directory] [options]`,
|
|
98
|
+
` ${CYAN}npx chemx create${RESET} [directory] [options]`,
|
|
99
|
+
'',
|
|
100
|
+
`${BOLD}DESCRIPTION${RESET}`,
|
|
101
|
+
' Scaffold a complete new Chemical X Molecular Architecture application.',
|
|
102
|
+
'',
|
|
103
|
+
`${BOLD}OPTIONS${RESET}`,
|
|
104
|
+
` ${CYAN}--framework=<id>${RESET} Framework flavor: react (default), vue, svelte`,
|
|
105
|
+
` ${CYAN}--install${RESET} Auto-install dependencies after scaffolding`,
|
|
106
|
+
` ${CYAN}--skip-install${RESET} Skip installing dependencies`,
|
|
107
|
+
` ${CYAN}--yes, -y${RESET} Skip interactive prompts and scaffold Community Edition immediately`,
|
|
108
|
+
` ${CYAN}--headless${RESET} Run in headless mode for CI/CD and AI agent automation`,
|
|
109
|
+
` ${CYAN}-h, --help${RESET} Show this help message`,
|
|
110
|
+
` ${CYAN}-v, --version${RESET} Show version number`,
|
|
111
|
+
'',
|
|
112
|
+
`${BOLD}EXAMPLES${RESET}`,
|
|
113
|
+
` ${CYAN}npm create chemx my-molecular-app --framework=react${RESET}`,
|
|
114
|
+
` ${CYAN}npx create-chemx my-vue-app --framework=vue --yes${RESET}`,
|
|
115
|
+
` ${CYAN}npx chemx create my-app --framework=svelte --install${RESET}`,
|
|
116
|
+
''
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
process.stdout.write(lines.join('\n'));
|
|
120
|
+
};
|
package/cli/help.spec.js
CHANGED
|
@@ -4,7 +4,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { COMMANDS_SCHEMA } from './commands-schema.js';
|
|
7
|
-
import { printHelp } from './help.js';
|
|
7
|
+
import { printHelp, printInitHelp, printScaffoldHelp } from './help.js';
|
|
8
8
|
|
|
9
9
|
test('commands-schema: contains all 9 core chemical-x CLI commands', () => {
|
|
10
10
|
const expected = ['search', 'read', 'patch', 'mcp', 'build', 'audit', 'generate', 'team', 'verify'];
|
|
@@ -54,3 +54,56 @@ test('cli: unknown command exits immediately with code 1 and error message', ()
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
|
+
|
|
58
|
+
test('help: printInitHelp and printScaffoldHelp render without throwing', () => {
|
|
59
|
+
assert.doesNotThrow(() => {
|
|
60
|
+
printInitHelp();
|
|
61
|
+
});
|
|
62
|
+
assert.doesNotThrow(() => {
|
|
63
|
+
printScaffoldHelp();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('cli: chemx init --help and -h display usage and do not scaffold /--help/ on disk', () => {
|
|
68
|
+
const cliPath = path.resolve('cli/index.js');
|
|
69
|
+
const helpFlags = ['--help', '-h', 'help'];
|
|
70
|
+
|
|
71
|
+
for (const flag of helpFlags) {
|
|
72
|
+
const res = spawnSync(process.execPath, [cliPath, 'init', flag], {
|
|
73
|
+
encoding: 'utf8',
|
|
74
|
+
timeout: 5000
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
assert.strictEqual(res.status, 0, `chemx init ${flag} should exit with code 0`);
|
|
78
|
+
assert.ok(
|
|
79
|
+
res.stdout.includes('chemx init') && res.stdout.includes('USAGE'),
|
|
80
|
+
`chemx init ${flag} output should include usage instructions`
|
|
81
|
+
);
|
|
82
|
+
assert.strictEqual(
|
|
83
|
+
fs.existsSync(path.resolve(flag)),
|
|
84
|
+
false,
|
|
85
|
+
`chemx init ${flag} must not create directory "${flag}" on disk`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('cli: chemx create --help and scaffold -h display usage', () => {
|
|
91
|
+
const cliPath = path.resolve('cli/index.js');
|
|
92
|
+
const commands = [
|
|
93
|
+
['create', '--help'],
|
|
94
|
+
['scaffold', '-h']
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
for (const [cmd, flag] of commands) {
|
|
98
|
+
const res = spawnSync(process.execPath, [cliPath, cmd, flag], {
|
|
99
|
+
encoding: 'utf8',
|
|
100
|
+
timeout: 5000
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
assert.strictEqual(res.status, 0, `chemx ${cmd} ${flag} should exit with code 0`);
|
|
104
|
+
assert.ok(
|
|
105
|
+
res.stdout.includes('USAGE') && (res.stdout.includes('create chemx') || res.stdout.includes('chemx create')),
|
|
106
|
+
`chemx ${cmd} ${flag} output should include scaffolder usage instructions`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
@@ -49,12 +49,12 @@ describe('Reader Shorthand Syntax', () => {
|
|
|
49
49
|
it('supports MCP chemx({ action: "r" })', async () => {
|
|
50
50
|
const output = await handleChemx({ action: 'r', params: { path: 'package.json:1-3' } });
|
|
51
51
|
assert.ok(output.includes('package.json'));
|
|
52
|
-
assert.ok(output.includes('"name":
|
|
52
|
+
assert.ok(output.includes('"name":'));
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
it('supports MCP chemx({ command: "r path:1-3" })', async () => {
|
|
56
56
|
const output = await handleChemx({ command: 'r package.json:1-3' });
|
|
57
57
|
assert.ok(output.includes('package.json'));
|
|
58
|
-
assert.ok(output.includes('"name":
|
|
58
|
+
assert.ok(output.includes('"name":'));
|
|
59
59
|
});
|
|
60
60
|
});
|
package/cli/scaffold.js
CHANGED
|
@@ -7,6 +7,7 @@ import { runPillarsWizard } from './pillars-wizard.js';
|
|
|
7
7
|
import { resolvePackageManager } from './build/detector.js';
|
|
8
8
|
import { resolveFramework } from './project-detector.js';
|
|
9
9
|
import { getFrameworkConfig, buildScaffoldPackageJson } from './scaffold-frameworks.js';
|
|
10
|
+
import { printInitHelp, printScaffoldHelp } from './help.js';
|
|
10
11
|
|
|
11
12
|
const extractTargetName = (projectName, rawArgs) => {
|
|
12
13
|
if (projectName && !projectName.startsWith('-')) return projectName;
|
|
@@ -25,6 +26,19 @@ const extractTargetName = (projectName, rawArgs) => {
|
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
export const runScaffold = async (projectName, rawArgs = [], onRunAudit = null) => {
|
|
29
|
+
const isHelpRequested =
|
|
30
|
+
rawArgs.includes('--help') ||
|
|
31
|
+
rawArgs.includes('-h') ||
|
|
32
|
+
rawArgs.includes('help') ||
|
|
33
|
+
projectName === '--help' ||
|
|
34
|
+
projectName === '-h' ||
|
|
35
|
+
projectName === 'help';
|
|
36
|
+
|
|
37
|
+
if (isHelpRequested) {
|
|
38
|
+
printScaffoldHelp();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
28
42
|
renderBanner('Chemical X: Molecular Architecture Scaffolder (npm create chemx)');
|
|
29
43
|
|
|
30
44
|
const fwArg = (rawArgs.find((a) => a.startsWith('--framework=')) || '').split('=')[1]
|
|
@@ -125,9 +139,26 @@ export const runScaffold = async (projectName, rawArgs = [], onRunAudit = null)
|
|
|
125
139
|
};
|
|
126
140
|
|
|
127
141
|
export const runInit = async (targetSubDir = 'src/chemical-x', rawArgs = [], onRunAudit = null) => {
|
|
142
|
+
const isHelpRequested =
|
|
143
|
+
rawArgs.includes('--help') ||
|
|
144
|
+
rawArgs.includes('-h') ||
|
|
145
|
+
rawArgs.includes('help') ||
|
|
146
|
+
targetSubDir === '--help' ||
|
|
147
|
+
targetSubDir === '-h' ||
|
|
148
|
+
targetSubDir === 'help';
|
|
149
|
+
|
|
150
|
+
if (isHelpRequested) {
|
|
151
|
+
printInitHelp();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const safeTargetSubDir = (targetSubDir && !targetSubDir.startsWith('-'))
|
|
156
|
+
? targetSubDir
|
|
157
|
+
: (rawArgs.slice(1).find((arg) => !arg.startsWith('-')) || 'src/chemical-x');
|
|
158
|
+
|
|
128
159
|
renderBanner('Chemical X: In-Repo Capsule Drop-in');
|
|
129
160
|
|
|
130
|
-
const targetDir = path.resolve(process.cwd(),
|
|
161
|
+
const targetDir = path.resolve(process.cwd(), safeTargetSubDir);
|
|
131
162
|
const licenseKey = await obtainLicenseKey(rawArgs, onRunAudit);
|
|
132
163
|
let files = {};
|
|
133
164
|
|
|
@@ -141,7 +172,7 @@ export const runInit = async (targetSubDir = 'src/chemical-x', rawArgs = [], onR
|
|
|
141
172
|
files = await fetchStarterKitFiles(licenseKey);
|
|
142
173
|
}
|
|
143
174
|
|
|
144
|
-
process.stdout.write(`Unpacking blueprints and hooks into: \x1b[36m${
|
|
175
|
+
process.stdout.write(`Unpacking blueprints and hooks into: \x1b[36m${safeTargetSubDir}/\x1b[0m\n`);
|
|
145
176
|
|
|
146
177
|
let count = 0;
|
|
147
178
|
for (const [relPath, content] of Object.entries(files)) {
|
|
@@ -160,9 +191,9 @@ export const runInit = async (targetSubDir = 'src/chemical-x', rawArgs = [], onR
|
|
|
160
191
|
}
|
|
161
192
|
|
|
162
193
|
process.stdout.write(
|
|
163
|
-
`\n\x1b[1m\x1b[32m✔ Successfully installed ${count} Chemical X assets into ${
|
|
194
|
+
`\n\x1b[1m\x1b[32m✔ Successfully installed ${count} Chemical X assets into ${safeTargetSubDir}!\x1b[0m\n\n`
|
|
164
195
|
);
|
|
165
196
|
};
|
|
166
197
|
|
|
167
198
|
export { runGenerateCapsule, runGenerateWizard } from './generator.js';
|
|
168
|
-
export { printHelp } from './help.js';
|
|
199
|
+
export { printHelp, printInitHelp, printScaffoldHelp } from './help.js';
|
package/cli/ui-handlers.js
CHANGED
|
@@ -61,7 +61,7 @@ export const handleSwarmStatus = (db, cwd = process.cwd()) => {
|
|
|
61
61
|
parentId: t.parent_id,
|
|
62
62
|
subtaskCount,
|
|
63
63
|
assignedAgentId: t.assigned_agent_id,
|
|
64
|
-
tokenStamp: `[P: ${p} | C: ${c} | Cost:
|
|
64
|
+
tokenStamp: `[P: ${p} | C: ${c} | Cost: $${cost.toFixed(4)}]`
|
|
65
65
|
};
|
|
66
66
|
});
|
|
67
67
|
|