@vmz/vmz 0.0.1 → 0.0.3
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/README.md +52 -2
- package/bin/vmz.js +4 -0
- package/dist/application-cmd.d.ts +21 -0
- package/dist/application-cmd.js +347 -0
- package/dist/bundler-adapter.d.ts +63 -0
- package/dist/bundler-adapter.js +110 -0
- package/dist/cli.d.ts +23 -0
- package/dist/cli.js +474 -0
- package/dist/dev-session.d.ts +35 -0
- package/dist/dev-session.js +290 -0
- package/dist/document-build.d.ts +99 -0
- package/dist/document-build.js +273 -0
- package/dist/document-check.d.ts +44 -0
- package/dist/document-check.js +246 -0
- package/dist/document-cmd.d.ts +8 -0
- package/dist/document-cmd.js +146 -0
- package/dist/document-designs.d.ts +9 -0
- package/dist/document-designs.js +126 -0
- package/dist/document-enrich.d.ts +23 -0
- package/dist/document-enrich.js +233 -0
- package/dist/document-evidence.d.ts +49 -0
- package/dist/document-evidence.js +509 -0
- package/dist/document-integrate.d.ts +34 -0
- package/dist/document-integrate.js +88 -0
- package/dist/document-interactive.d.ts +69 -0
- package/dist/document-interactive.js +254 -0
- package/dist/document-locale.d.ts +31 -0
- package/dist/document-locale.js +59 -0
- package/dist/document-markdown.d.ts +12 -0
- package/dist/document-markdown.js +45 -0
- package/dist/document-scan.d.ts +21 -0
- package/dist/document-scan.js +151 -0
- package/dist/document-schema.d.ts +86 -0
- package/dist/document-schema.js +87 -0
- package/dist/explain-cmd.d.ts +5 -0
- package/dist/explain-cmd.js +123 -0
- package/dist/index.d.ts +359 -0
- package/dist/index.js +580 -0
- package/dist/invocation.d.ts +91 -0
- package/dist/invocation.js +190 -0
- package/dist/locale-check.d.ts +106 -0
- package/dist/locale-check.js +736 -0
- package/dist/locale-cmd.d.ts +5 -0
- package/dist/locale-cmd.js +442 -0
- package/dist/locale-delivery.d.ts +298 -0
- package/dist/locale-delivery.js +443 -0
- package/dist/locale-router.d.ts +206 -0
- package/dist/locale-router.js +507 -0
- package/dist/locale-runtime.d.ts +406 -0
- package/dist/locale-runtime.js +541 -0
- package/dist/locale-schema.d.ts +8 -0
- package/dist/locale-schema.js +9 -0
- package/dist/locale-tooling.d.ts +118 -0
- package/dist/locale-tooling.js +357 -0
- package/dist/log.d.ts +19 -0
- package/dist/log.js +42 -0
- package/dist/packages.d.ts +26 -0
- package/dist/packages.js +146 -0
- package/dist/plugin-host.d.ts +29 -0
- package/dist/plugin-host.js +369 -0
- package/dist/refactor-cmd.d.ts +8 -0
- package/dist/refactor-cmd.js +156 -0
- package/dist/resolve-native-cli.d.ts +14 -0
- package/dist/resolve-native-cli.js +84 -0
- package/dist/resolve.d.ts +24 -0
- package/dist/resolve.js +55 -0
- package/dist/test-cmd.d.ts +9 -0
- package/dist/test-cmd.js +363 -0
- package/dist/test-compile.d.ts +2 -0
- package/dist/test-compile.js +3 -0
- package/dist/test-discover.d.ts +2 -0
- package/dist/test-discover.js +3 -0
- package/dist/test-logic.d.ts +2 -0
- package/dist/test-logic.js +3 -0
- package/dist/test-protocol.d.ts +2 -0
- package/dist/test-protocol.js +3 -0
- package/dist/watch-diff.d.ts +17 -0
- package/dist/watch-diff.js +56 -0
- package/package.json +96 -3
package/dist/cli.js
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Node CLI command implementations .
|
|
4
|
+
*/
|
|
5
|
+
import { spawn } from 'node:child_process';
|
|
6
|
+
import { copyFileSync, existsSync } from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { HOST_PROTOCOL, createWorkspace, getProtocolVersions, resolveCoreRuntimeDist } from './index.js';
|
|
9
|
+
import { createDevSession } from './dev-session.js';
|
|
10
|
+
import { gateGlobalProjectCommand, getInvocationContext, isGlobalAllowedCommand } from './invocation.js';
|
|
11
|
+
import { log } from './log.js';
|
|
12
|
+
import { readPackageMeta, resolveWorkspaceDirs } from './resolve.js';
|
|
13
|
+
import { cmdTest } from './test-cmd.js';
|
|
14
|
+
import { cmdDocument } from './document-cmd.js';
|
|
15
|
+
import { buildIntegratedDocuments, projectHasDocuments } from './document-integrate.js';
|
|
16
|
+
import { cmdLocale } from './locale-cmd.js';
|
|
17
|
+
import { cmdApplication } from './application-cmd.js';
|
|
18
|
+
import { cmdRefactor } from './refactor-cmd.js';
|
|
19
|
+
import { cmdExplain } from './explain-cmd.js';
|
|
20
|
+
import { resolveNativeVmzCli } from './resolve-native-cli.js';
|
|
21
|
+
/**
|
|
22
|
+
* @param {string[]} argv
|
|
23
|
+
*/
|
|
24
|
+
export function parseArgs(argv) {
|
|
25
|
+
/** @type {Record<string, string | boolean> & { _: string[] }} */
|
|
26
|
+
const out = { _: [] };
|
|
27
|
+
for (let i = 0; i < argv.length; i++) {
|
|
28
|
+
const a = argv[i];
|
|
29
|
+
if (a === '--') {
|
|
30
|
+
out._.push(...argv.slice(i + 1));
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
if (a.startsWith('--')) {
|
|
34
|
+
const eq = a.indexOf('=');
|
|
35
|
+
if (eq !== -1) {
|
|
36
|
+
out[a.slice(2, eq)] = a.slice(eq + 1);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const key = a.slice(2);
|
|
40
|
+
const next = argv[i + 1];
|
|
41
|
+
if (next && !next.startsWith('-')) {
|
|
42
|
+
out[key] = next;
|
|
43
|
+
i += 1;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
out[key] = true;
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (a.startsWith('-') && a.length === 2) {
|
|
51
|
+
const key = a === '-o' ? 'out-dir' : a.slice(1);
|
|
52
|
+
const next = argv[i + 1];
|
|
53
|
+
if (next && !next.startsWith('-')) {
|
|
54
|
+
out[key] = next;
|
|
55
|
+
i += 1;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
out[key] = true;
|
|
59
|
+
}
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
out._.push(a);
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
export function printGlobalHelp() {
|
|
67
|
+
console.log(`vmz — global mode (scaffold only)
|
|
68
|
+
|
|
69
|
+
developer monorepo source (packages/runtimes/vmz) — full CLI
|
|
70
|
+
project app node_modules/@vmz/vmz (or vmz) — full CLI
|
|
71
|
+
global npm/pnpm -g — only new/init/help/version
|
|
72
|
+
|
|
73
|
+
You are in global mode. Pin \`@vmz/vmz\` in the app so check/build/lsp
|
|
74
|
+
use a traceable project install.
|
|
75
|
+
|
|
76
|
+
Usage:
|
|
77
|
+
vmz new|init <dir> Scaffold (native CLI; Node only gates + forwards)
|
|
78
|
+
vmz version Show host + native protocol versions
|
|
79
|
+
vmz help Show this help
|
|
80
|
+
|
|
81
|
+
Project commands:
|
|
82
|
+
pnpm add -D @vmz/vmz
|
|
83
|
+
pnpm exec vmz check
|
|
84
|
+
# or: vmz new my-app && cd my-app && pnpm install
|
|
85
|
+
|
|
86
|
+
If a project \`node_modules/@vmz/vmz\` (or \`vmz\`) exists, a global
|
|
87
|
+
\`vmz <cmd>\` re-execs that bin.
|
|
88
|
+
`);
|
|
89
|
+
}
|
|
90
|
+
export function printProjectHelp() {
|
|
91
|
+
console.log(`vmz — Node toolchain host (project / developer mode)
|
|
92
|
+
|
|
93
|
+
Usage:
|
|
94
|
+
vmz new|init <dir> Scaffold a minimal app (native CLI)
|
|
95
|
+
vmz check [path] Check project via Workspace
|
|
96
|
+
vmz build [path] [options] Build project via Workspace
|
|
97
|
+
vmz serve [path] [options] Serve dist (optional --build)
|
|
98
|
+
vmz dev [path] [options] Long-lived rebuild session (no CLI spawn)
|
|
99
|
+
vmz format [path] [--check] Format .vmz via N-API (oxc codegen)
|
|
100
|
+
vmz lint [path] [--deny-warnings] Lint (= check) via N-API
|
|
101
|
+
vmz test [path] [options] Native test discover / report
|
|
102
|
+
vmz document|docs <cmd> Project /documents domain
|
|
103
|
+
vmz application <cmd> Application Collection / Mount
|
|
104
|
+
vmz refactor <cmd> DX rename plans / apply
|
|
105
|
+
vmz explain [style] <target> DX causal explain (style Theme chain)
|
|
106
|
+
vmz lsp [root] [--out-dir] Language server (stdio; native CLI)
|
|
107
|
+
vmz mcp [root] [--out-dir] MCP server (stdio; native CLI)
|
|
108
|
+
vmz version Show host + native protocol versions
|
|
109
|
+
vmz help Show this help
|
|
110
|
+
|
|
111
|
+
Options:
|
|
112
|
+
--out-dir, -o <dir> Output directory (default: dist)
|
|
113
|
+
--release Release build (build only)
|
|
114
|
+
--host <host> Listen host (default: 127.0.0.1)
|
|
115
|
+
--port <port> Listen port (default: 5173)
|
|
116
|
+
--poll-ms <ms> Dev watch poll interval (default: 300)
|
|
117
|
+
--build Build before serve
|
|
118
|
+
--check Format check-only (format)
|
|
119
|
+
--deny-warnings Treat warnings as errors (lint)
|
|
120
|
+
--list List discovered tests (test)
|
|
121
|
+
--json [file] Emit TestReport / DocumentManifest / ApplicationCheckReport JSON
|
|
122
|
+
--mode <modes> compile|logic|browser|ssr|resume|deployment|all (test)
|
|
123
|
+
--filter <pattern> Filter by test id or file (test)
|
|
124
|
+
--application <id> Run only tests for ApplicationId (standalone scope)
|
|
125
|
+
--mounted <id> Run relocation + host-boundary tests for ApplicationId
|
|
126
|
+
--affected Select tests from dirty VPG units (test; DX)
|
|
127
|
+
--root <dir> Project root (document check)
|
|
128
|
+
--strict Strict document locale/PageKey coverage (document check)
|
|
129
|
+
`);
|
|
130
|
+
}
|
|
131
|
+
/** @deprecated use printProjectHelp / printGlobalHelp */
|
|
132
|
+
export function printHelp() {
|
|
133
|
+
printProjectHelp();
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* @param {string[]} argv
|
|
137
|
+
* @param {{
|
|
138
|
+
* cwd?: string,
|
|
139
|
+
* thisPackageRoot?: string,
|
|
140
|
+
* reexec?: (bin: string, argv: string[]) => Promise<number>,
|
|
141
|
+
* }} [opts]
|
|
142
|
+
* @returns {Promise<number>}
|
|
143
|
+
*/
|
|
144
|
+
export async function runCli(argv, opts = {}) {
|
|
145
|
+
const [cmd, ...rest] = argv;
|
|
146
|
+
const inv = getInvocationContext({
|
|
147
|
+
cwd: opts.cwd,
|
|
148
|
+
thisPackageRoot: opts.thisPackageRoot,
|
|
149
|
+
});
|
|
150
|
+
if (!cmd || cmd === 'help' || cmd === '-h' || cmd === '--help') {
|
|
151
|
+
if (inv.mode === 'global')
|
|
152
|
+
printGlobalHelp();
|
|
153
|
+
else
|
|
154
|
+
printProjectHelp();
|
|
155
|
+
return 0;
|
|
156
|
+
}
|
|
157
|
+
if (cmd === 'version' || cmd === '-V' || cmd === '--version') {
|
|
158
|
+
return cmdVersion();
|
|
159
|
+
}
|
|
160
|
+
if (!isGlobalAllowedCommand(cmd)) {
|
|
161
|
+
const gated = await gateGlobalProjectCommand({
|
|
162
|
+
argv,
|
|
163
|
+
cwd: opts.cwd,
|
|
164
|
+
thisPackageRoot: opts.thisPackageRoot,
|
|
165
|
+
reexec: opts.reexec,
|
|
166
|
+
logError: (msg) => log.error(msg),
|
|
167
|
+
});
|
|
168
|
+
if (gated.action === 'exit')
|
|
169
|
+
return gated.code;
|
|
170
|
+
}
|
|
171
|
+
const args = parseArgs(rest);
|
|
172
|
+
switch (cmd) {
|
|
173
|
+
case 'new':
|
|
174
|
+
case 'init':
|
|
175
|
+
return cmdNativeForward(cmd, rest);
|
|
176
|
+
case 'check':
|
|
177
|
+
return cmdCheck(args);
|
|
178
|
+
case 'build':
|
|
179
|
+
return cmdBuild(args);
|
|
180
|
+
case 'serve':
|
|
181
|
+
return cmdServe(args);
|
|
182
|
+
case 'dev':
|
|
183
|
+
return cmdDev(args);
|
|
184
|
+
case 'format':
|
|
185
|
+
return cmdFormat(args);
|
|
186
|
+
case 'lint':
|
|
187
|
+
return cmdLint(args);
|
|
188
|
+
case 'test':
|
|
189
|
+
return cmdTest(args);
|
|
190
|
+
case 'document':
|
|
191
|
+
case 'docs':
|
|
192
|
+
return cmdDocument(rest);
|
|
193
|
+
case 'locale':
|
|
194
|
+
case 'locales':
|
|
195
|
+
return cmdLocale(rest);
|
|
196
|
+
case 'application':
|
|
197
|
+
case 'applications':
|
|
198
|
+
case 'app':
|
|
199
|
+
return cmdApplication(rest);
|
|
200
|
+
case 'refactor':
|
|
201
|
+
return cmdRefactor(rest);
|
|
202
|
+
case 'explain':
|
|
203
|
+
return cmdExplain(rest);
|
|
204
|
+
case 'lsp':
|
|
205
|
+
return cmdNativeForward('lsp', rest);
|
|
206
|
+
case 'mcp':
|
|
207
|
+
return cmdNativeForward('mcp', rest);
|
|
208
|
+
default:
|
|
209
|
+
log.error(`unknown command \`${cmd}\``);
|
|
210
|
+
if (inv.mode === 'global')
|
|
211
|
+
printGlobalHelp();
|
|
212
|
+
else
|
|
213
|
+
printProjectHelp();
|
|
214
|
+
return 1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Forward to the single native `vmz` binary (vmz-tools).
|
|
219
|
+
* Scaffold / stdio servers live in Rust — Node only gates + re-execs.
|
|
220
|
+
*
|
|
221
|
+
* @param {'new' | 'init' | 'lsp' | 'mcp'} sub
|
|
222
|
+
* @param {string[]} argv
|
|
223
|
+
* @returns {Promise<number>}
|
|
224
|
+
*/
|
|
225
|
+
function cmdNativeForward(sub, argv) {
|
|
226
|
+
const bin = resolveNativeVmzCli();
|
|
227
|
+
if (!bin) {
|
|
228
|
+
log.error('native `vmz` CLI not found (vmz-tools).');
|
|
229
|
+
log.error('Build: cargo build -p vmz-tools');
|
|
230
|
+
log.error('Or set VMZ_NATIVE to the absolute path of that binary.');
|
|
231
|
+
return Promise.resolve(1);
|
|
232
|
+
}
|
|
233
|
+
return new Promise((resolve) => {
|
|
234
|
+
const child = spawn(bin, [sub, ...argv], { stdio: 'inherit' });
|
|
235
|
+
child.on('error', (err) => {
|
|
236
|
+
log.error(`failed to spawn ${bin}: ${err.message}`);
|
|
237
|
+
resolve(1);
|
|
238
|
+
});
|
|
239
|
+
child.on('exit', (code, signal) => {
|
|
240
|
+
if (signal)
|
|
241
|
+
resolve(1);
|
|
242
|
+
else
|
|
243
|
+
resolve(code ?? 1);
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
function cmdVersion() {
|
|
248
|
+
const native = getProtocolVersions();
|
|
249
|
+
console.log(`vmz host ${HOST_PROTOCOL}`);
|
|
250
|
+
console.log(`native host=${native.hostProtocol} compiler=${native.compilerProtocol} program_ir=${native.programIrSchema} plugin=${native.pluginProtocol}`);
|
|
251
|
+
return 0;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* @param {Record<string, string | boolean> & { _: string[] }} args
|
|
255
|
+
*/
|
|
256
|
+
function cmdCheck(args) {
|
|
257
|
+
const pathArg = args._[0] ?? '.';
|
|
258
|
+
const { project, outDir } = resolveWorkspaceDirs({
|
|
259
|
+
path: pathArg,
|
|
260
|
+
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
261
|
+
});
|
|
262
|
+
const meta = readPackageMeta(project);
|
|
263
|
+
log.info(`check ${project}${meta?.name ? ` (${meta.name})` : ''}`);
|
|
264
|
+
const ws = createWorkspace({ root: project, outDir });
|
|
265
|
+
try {
|
|
266
|
+
return runWithPlugins(ws, project, outDir, async () => {
|
|
267
|
+
const report = ws.check();
|
|
268
|
+
const errors = log.diagnostics(report.diagnostics ?? []);
|
|
269
|
+
log.info(`checked ${report.filesChecked} file(s)`);
|
|
270
|
+
return errors ? 1 : 0;
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
finally {
|
|
274
|
+
ws.dispose();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* @param {import('./index.js').Workspace} ws
|
|
279
|
+
* @param {string} project
|
|
280
|
+
* @param {string} outDir
|
|
281
|
+
* @param { => Promise<number> | number} fn
|
|
282
|
+
*/
|
|
283
|
+
async function runWithPlugins(ws, project, outDir, fn) {
|
|
284
|
+
const { loadVmzConfig, applyPlugins } = await import('./plugin-host.js');
|
|
285
|
+
const { plugins, engines } = await loadVmzConfig(project);
|
|
286
|
+
if (plugins.length) {
|
|
287
|
+
await applyPlugins(ws, plugins, { project, outDir, engines });
|
|
288
|
+
}
|
|
289
|
+
return await fn();
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* @param {Record<string, string | boolean> & { _: string[] }} args
|
|
293
|
+
*/
|
|
294
|
+
async function cmdBuild(args) {
|
|
295
|
+
const pathArg = args._[0] ?? '.';
|
|
296
|
+
const { project, outDir } = resolveWorkspaceDirs({
|
|
297
|
+
path: pathArg,
|
|
298
|
+
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
299
|
+
});
|
|
300
|
+
log.info(`build ${project} → ${outDir}`);
|
|
301
|
+
const ws = createWorkspace({ root: project, outDir });
|
|
302
|
+
try {
|
|
303
|
+
const code = await runWithPlugins(ws, project, outDir, () => {
|
|
304
|
+
const report = ws.build(Boolean(args.release));
|
|
305
|
+
const errors = log.diagnostics(report.diagnostics ?? []);
|
|
306
|
+
if (errors)
|
|
307
|
+
return 1;
|
|
308
|
+
for (const p of report.emitted ?? []) {
|
|
309
|
+
console.log(`emitted ${p}`);
|
|
310
|
+
}
|
|
311
|
+
log.info(`build ok (${(report.emitted ?? []).length} file(s))`);
|
|
312
|
+
return 0;
|
|
313
|
+
});
|
|
314
|
+
if (code !== 0)
|
|
315
|
+
return code;
|
|
316
|
+
if (projectHasDocuments(project)) {
|
|
317
|
+
const docs = await buildIntegratedDocuments({ projectRoot: project, outDir });
|
|
318
|
+
if (!docs.ok)
|
|
319
|
+
return 1;
|
|
320
|
+
}
|
|
321
|
+
return 0;
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
ws.dispose();
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* @param {Record<string, string | boolean> & { _: string[] }} args
|
|
329
|
+
*/
|
|
330
|
+
async function cmdServe(args) {
|
|
331
|
+
const pathArg = args._[0] ?? '.';
|
|
332
|
+
if (args.build) {
|
|
333
|
+
const code = await cmdBuild(args);
|
|
334
|
+
if (code !== 0)
|
|
335
|
+
return code;
|
|
336
|
+
}
|
|
337
|
+
const { project, outDir } = resolveWorkspaceDirs({
|
|
338
|
+
path: pathArg,
|
|
339
|
+
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
340
|
+
});
|
|
341
|
+
const hostJs = path.join(outDir, 'vmz-serve-host.mjs');
|
|
342
|
+
if (!existsSync(hostJs)) {
|
|
343
|
+
const coreDist = resolveCoreRuntimeDist();
|
|
344
|
+
const src = coreDist ? path.join(coreDist, 'serve-host.mjs') : null;
|
|
345
|
+
if (src && existsSync(src)) {
|
|
346
|
+
copyFileSync(src, hostJs);
|
|
347
|
+
log.info(`materialized ${hostJs} from @vmz/core (release builds omit it)`);
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
log.error(`missing ${hostJs} — run \`vmz build\` (without --release) or ensure @vmz/core is installed`);
|
|
351
|
+
return 1;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const host = typeof args.host === 'string' ? args.host : '127.0.0.1';
|
|
355
|
+
const port = Number(args.port ?? 5173);
|
|
356
|
+
log.info(`serve http://${host}:${port}`);
|
|
357
|
+
const node = process.env.VMZ_NODE || process.execPath;
|
|
358
|
+
const child = spawn(node, [hostJs], {
|
|
359
|
+
cwd: project,
|
|
360
|
+
env: {
|
|
361
|
+
...process.env,
|
|
362
|
+
VMZ_DIST: outDir,
|
|
363
|
+
VMZ_PORT: String(port),
|
|
364
|
+
VMZ_HOST: host,
|
|
365
|
+
},
|
|
366
|
+
stdio: 'inherit',
|
|
367
|
+
});
|
|
368
|
+
return await new Promise((resolve) => {
|
|
369
|
+
const shutdown = () => {
|
|
370
|
+
child.kill();
|
|
371
|
+
};
|
|
372
|
+
process.once('SIGINT', shutdown);
|
|
373
|
+
process.once('SIGTERM', shutdown);
|
|
374
|
+
child.on('exit', (code, signal) => {
|
|
375
|
+
process.off('SIGINT', shutdown);
|
|
376
|
+
process.off('SIGTERM', shutdown);
|
|
377
|
+
if (signal)
|
|
378
|
+
resolve(0);
|
|
379
|
+
else
|
|
380
|
+
resolve(code ?? 1);
|
|
381
|
+
});
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* @param {Record<string, string | boolean> & { _: string[] }} args
|
|
386
|
+
*/
|
|
387
|
+
async function cmdDev(args) {
|
|
388
|
+
const pathArg = args._[0] ?? '.';
|
|
389
|
+
const { project, outDir } = resolveWorkspaceDirs({
|
|
390
|
+
path: pathArg,
|
|
391
|
+
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
392
|
+
});
|
|
393
|
+
const host = typeof args.host === 'string' ? args.host : '127.0.0.1';
|
|
394
|
+
const port = Number(args.port ?? 5173);
|
|
395
|
+
const pollMs = Number(args['poll-ms'] ?? 300);
|
|
396
|
+
const ac = new AbortController();
|
|
397
|
+
const onSig = () => {
|
|
398
|
+
log.info('shutting down…');
|
|
399
|
+
ac.abort();
|
|
400
|
+
};
|
|
401
|
+
process.on('SIGINT', onSig);
|
|
402
|
+
process.on('SIGTERM', onSig);
|
|
403
|
+
const session = createDevSession({
|
|
404
|
+
project,
|
|
405
|
+
outDir,
|
|
406
|
+
host,
|
|
407
|
+
port,
|
|
408
|
+
pollMs,
|
|
409
|
+
signal: ac.signal,
|
|
410
|
+
});
|
|
411
|
+
try {
|
|
412
|
+
await session.start();
|
|
413
|
+
return 0;
|
|
414
|
+
}
|
|
415
|
+
catch (err) {
|
|
416
|
+
if (ac.signal.aborted)
|
|
417
|
+
return 0;
|
|
418
|
+
log.error(String(err));
|
|
419
|
+
return 1;
|
|
420
|
+
}
|
|
421
|
+
finally {
|
|
422
|
+
process.off('SIGINT', onSig);
|
|
423
|
+
process.off('SIGTERM', onSig);
|
|
424
|
+
await session.stop();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* @param {Record<string, string | boolean> & { _: string[] }} args
|
|
429
|
+
*/
|
|
430
|
+
function cmdFormat(args) {
|
|
431
|
+
const pathArg = args._[0] ?? '.';
|
|
432
|
+
const { project, outDir } = resolveWorkspaceDirs({
|
|
433
|
+
path: pathArg,
|
|
434
|
+
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
435
|
+
});
|
|
436
|
+
const checkOnly = Boolean(args.check);
|
|
437
|
+
log.info(`format ${project}${checkOnly ? ' --check' : ''}`);
|
|
438
|
+
const ws = createWorkspace({ root: project, outDir });
|
|
439
|
+
try {
|
|
440
|
+
const report = ws.format(checkOnly);
|
|
441
|
+
const errors = log.diagnostics(report.diagnostics ?? []);
|
|
442
|
+
if (checkOnly) {
|
|
443
|
+
log.info(`checked ${report.filesChecked} file(s); ${report.filesNeedWrite} need write`);
|
|
444
|
+
return errors || report.filesNeedWrite > 0 ? 1 : 0;
|
|
445
|
+
}
|
|
446
|
+
log.info(`formatted ${report.filesWritten}/${report.filesChecked} file(s)`);
|
|
447
|
+
return errors ? 1 : 0;
|
|
448
|
+
}
|
|
449
|
+
finally {
|
|
450
|
+
ws.dispose();
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* @param {Record<string, string | boolean> & { _: string[] }} args
|
|
455
|
+
*/
|
|
456
|
+
function cmdLint(args) {
|
|
457
|
+
const pathArg = args._[0] ?? '.';
|
|
458
|
+
const { project, outDir } = resolveWorkspaceDirs({
|
|
459
|
+
path: pathArg,
|
|
460
|
+
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
461
|
+
});
|
|
462
|
+
const denyWarnings = Boolean(args['deny-warnings']);
|
|
463
|
+
log.info(`lint ${project}`);
|
|
464
|
+
const ws = createWorkspace({ root: project, outDir });
|
|
465
|
+
try {
|
|
466
|
+
const report = ws.lint(denyWarnings);
|
|
467
|
+
const errors = log.diagnostics(report.diagnostics ?? [], { denyWarnings });
|
|
468
|
+
log.info(`linted ${report.filesChecked} file(s)`);
|
|
469
|
+
return errors ? 1 : 0;
|
|
470
|
+
}
|
|
471
|
+
finally {
|
|
472
|
+
ws.dispose();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Long-lived Node dev session (/session).
|
|
3
|
+
*
|
|
4
|
+
* Rebuilds go through the N-API `Workspace` — never spawn `cargo` / `vmz-tools`.
|
|
5
|
+
* session: only dirty leaves are marked; Workspace emits affected deployment units.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {object} DevSessionOptions
|
|
9
|
+
* @property {string} project
|
|
10
|
+
* @property {string} outDir
|
|
11
|
+
* @property {string} [host]
|
|
12
|
+
* @property {number} [port]
|
|
13
|
+
* @property {number} [pollMs]
|
|
14
|
+
* @property {AbortSignal} [signal]
|
|
15
|
+
* @property {typeof createWorkspace} [createWorkspaceFn]
|
|
16
|
+
* @property {(opts: { project: string, outDir: string, host: string, port: number }) => import('node:child_process').ChildProcess} [spawnHostFn]
|
|
17
|
+
* @property {(host: string, port: number, payload?: object) => Promise<void>} [softReloadFn]
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* @param {DevSessionOptions} options
|
|
21
|
+
*/
|
|
22
|
+
export declare function createDevSession(options: any): {
|
|
23
|
+
ws: any;
|
|
24
|
+
rebuild: (changes: any) => any;
|
|
25
|
+
start: () => Promise<void>;
|
|
26
|
+
stop: () => Promise<void>;
|
|
27
|
+
project: any;
|
|
28
|
+
outDir: any;
|
|
29
|
+
host: any;
|
|
30
|
+
port: any;
|
|
31
|
+
};
|
|
32
|
+
/** @deprecated use fileFingerprintMap */
|
|
33
|
+
export declare function srcFingerprint(srcDir: any): number;
|
|
34
|
+
/** @deprecated */
|
|
35
|
+
export declare function listWatchedFiles(srcDir: any): any[];
|