@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.
Files changed (79) hide show
  1. package/README.md +52 -2
  2. package/bin/vmz.js +4 -0
  3. package/dist/application-cmd.d.ts +21 -0
  4. package/dist/application-cmd.js +347 -0
  5. package/dist/bundler-adapter.d.ts +63 -0
  6. package/dist/bundler-adapter.js +110 -0
  7. package/dist/cli.d.ts +23 -0
  8. package/dist/cli.js +474 -0
  9. package/dist/dev-session.d.ts +35 -0
  10. package/dist/dev-session.js +290 -0
  11. package/dist/document-build.d.ts +99 -0
  12. package/dist/document-build.js +273 -0
  13. package/dist/document-check.d.ts +44 -0
  14. package/dist/document-check.js +246 -0
  15. package/dist/document-cmd.d.ts +8 -0
  16. package/dist/document-cmd.js +146 -0
  17. package/dist/document-designs.d.ts +9 -0
  18. package/dist/document-designs.js +126 -0
  19. package/dist/document-enrich.d.ts +23 -0
  20. package/dist/document-enrich.js +233 -0
  21. package/dist/document-evidence.d.ts +49 -0
  22. package/dist/document-evidence.js +509 -0
  23. package/dist/document-integrate.d.ts +34 -0
  24. package/dist/document-integrate.js +88 -0
  25. package/dist/document-interactive.d.ts +69 -0
  26. package/dist/document-interactive.js +254 -0
  27. package/dist/document-locale.d.ts +31 -0
  28. package/dist/document-locale.js +59 -0
  29. package/dist/document-markdown.d.ts +12 -0
  30. package/dist/document-markdown.js +45 -0
  31. package/dist/document-scan.d.ts +21 -0
  32. package/dist/document-scan.js +151 -0
  33. package/dist/document-schema.d.ts +86 -0
  34. package/dist/document-schema.js +87 -0
  35. package/dist/explain-cmd.d.ts +5 -0
  36. package/dist/explain-cmd.js +123 -0
  37. package/dist/index.d.ts +359 -0
  38. package/dist/index.js +580 -0
  39. package/dist/invocation.d.ts +91 -0
  40. package/dist/invocation.js +190 -0
  41. package/dist/locale-check.d.ts +106 -0
  42. package/dist/locale-check.js +736 -0
  43. package/dist/locale-cmd.d.ts +5 -0
  44. package/dist/locale-cmd.js +442 -0
  45. package/dist/locale-delivery.d.ts +298 -0
  46. package/dist/locale-delivery.js +443 -0
  47. package/dist/locale-router.d.ts +206 -0
  48. package/dist/locale-router.js +507 -0
  49. package/dist/locale-runtime.d.ts +406 -0
  50. package/dist/locale-runtime.js +541 -0
  51. package/dist/locale-schema.d.ts +8 -0
  52. package/dist/locale-schema.js +9 -0
  53. package/dist/locale-tooling.d.ts +118 -0
  54. package/dist/locale-tooling.js +357 -0
  55. package/dist/log.d.ts +19 -0
  56. package/dist/log.js +42 -0
  57. package/dist/packages.d.ts +26 -0
  58. package/dist/packages.js +146 -0
  59. package/dist/plugin-host.d.ts +29 -0
  60. package/dist/plugin-host.js +369 -0
  61. package/dist/refactor-cmd.d.ts +8 -0
  62. package/dist/refactor-cmd.js +156 -0
  63. package/dist/resolve-native-cli.d.ts +14 -0
  64. package/dist/resolve-native-cli.js +84 -0
  65. package/dist/resolve.d.ts +24 -0
  66. package/dist/resolve.js +55 -0
  67. package/dist/test-cmd.d.ts +9 -0
  68. package/dist/test-cmd.js +363 -0
  69. package/dist/test-compile.d.ts +2 -0
  70. package/dist/test-compile.js +3 -0
  71. package/dist/test-discover.d.ts +2 -0
  72. package/dist/test-discover.js +3 -0
  73. package/dist/test-logic.d.ts +2 -0
  74. package/dist/test-logic.js +3 -0
  75. package/dist/test-protocol.d.ts +2 -0
  76. package/dist/test-protocol.js +3 -0
  77. package/dist/watch-diff.d.ts +17 -0
  78. package/dist/watch-diff.js +56 -0
  79. package/package.json +96 -3
@@ -0,0 +1,55 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * Shared project path resolution for the Node CLI host .
4
+ */
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import path from 'node:path';
7
+ /**
8
+ * @param {string} startDir
9
+ * @returns {string | null}
10
+ */
11
+ export function findPackageJson(startDir) {
12
+ let dir = path.resolve(startDir);
13
+ for (;;) {
14
+ const candidate = path.join(dir, 'package.json');
15
+ if (existsSync(candidate))
16
+ return candidate;
17
+ const parent = path.dirname(dir);
18
+ if (parent === dir)
19
+ return null;
20
+ dir = parent;
21
+ }
22
+ }
23
+ /**
24
+ * Resolve project root + out dir from CLI args / cwd.
25
+ * Prefers an explicit path; otherwise walks up for package.json with `src/`.
26
+ *
27
+ * @param {{ cwd?: string, path?: string, outDir?: string }} opts
28
+ */
29
+ export function resolveWorkspaceDirs(opts = {}) {
30
+ const cwd = opts.cwd ?? process.cwd();
31
+ const input = path.resolve(cwd, opts.path ?? '.');
32
+ let project = input;
33
+ if (!existsSync(path.join(project, 'src')) && !existsSync(path.join(project, 'package.json'))) {
34
+ const pkg = findPackageJson(cwd);
35
+ if (pkg)
36
+ project = path.dirname(pkg);
37
+ }
38
+ const outDir = opts.outDir ? (path.isAbsolute(opts.outDir) ? opts.outDir : path.join(project, opts.outDir)) : path.join(project, 'dist');
39
+ return { project, outDir, cwd };
40
+ }
41
+ /**
42
+ * @param {string} projectRoot
43
+ * @returns {{ name?: string, private?: boolean } | null}
44
+ */
45
+ export function readPackageMeta(projectRoot) {
46
+ const pkgPath = path.join(projectRoot, 'package.json');
47
+ if (!existsSync(pkgPath))
48
+ return null;
49
+ try {
50
+ return JSON.parse(readFileSync(pkgPath, 'utf8'));
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `vmz test` command — discovery / build / filter / TestReport orchestration.
3
+ * Semantics live in `@vmz/test` (optional peer — not installed with bare `@vmz/vmz`).
4
+ */
5
+ /**
6
+ * @param {Record<string, string | boolean> & { _: string[] }} args
7
+ * @returns {Promise<number>}
8
+ */
9
+ export declare function cmdTest(args: any): Promise<0 | 1 | 2>;
@@ -0,0 +1,363 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * `vmz test` command — discovery / build / filter / TestReport orchestration.
4
+ * Semantics live in `@vmz/test` (optional peer — not installed with bare `@vmz/vmz`).
5
+ */
6
+ import path from 'node:path';
7
+ import { createWorkspace } from './index.js';
8
+ import { log } from './log.js';
9
+ /**
10
+ * @returns {Promise<typeof import('@vmz/test')>}
11
+ */
12
+ async function loadTestPackage() {
13
+ try {
14
+ return await import('@vmz/test');
15
+ }
16
+ catch (e) {
17
+ const detail = e instanceof Error ? e.message : String(e);
18
+ throw new Error('`vmz test` needs `@vmz/test` (optional peer of `@vmz/vmz`).\n' + ' Install: pnpm add -D @vmz/test\n' + ` Detail: ${detail}`);
19
+ }
20
+ }
21
+ /**
22
+ * @param {Record<string, string | boolean> & { _: string[] }} args
23
+ * @returns {Promise<number>}
24
+ */
25
+ export async function cmdTest(args) {
26
+ let test;
27
+ try {
28
+ test = await loadTestPackage();
29
+ }
30
+ catch (e) {
31
+ log.error(e instanceof Error ? e.message : String(e));
32
+ return 1;
33
+ }
34
+ const { discoverTestManifests, buildTestReport, parseModes, buildForCompile, runCompileManifest, runLogicManifest, runSsrManifest, runResumeManifest, runBrowserManifest, runDeploymentManifest, } = test;
35
+ const project = path.resolve(String(args._[0] || '.'));
36
+ let modes;
37
+ try {
38
+ modes = parseModes(/** @type {string|boolean|undefined} */ (args.mode));
39
+ }
40
+ catch (e) {
41
+ log.error(e instanceof Error ? e.message : String(e));
42
+ return 1;
43
+ }
44
+ const wantList = args.list === true;
45
+ const wantJson = args.json === true || typeof args.json === 'string';
46
+ const filter = typeof args.filter === 'string' && args.filter ? String(args.filter) : null;
47
+ const outDirArg = typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined;
48
+ const wantAffected = args.affected === true || args.target === 'changed' || args.target === 'affected';
49
+ const applicationId = typeof args.application === 'string' && args.application ? String(args.application) : null;
50
+ const mountedId = typeof args.mounted === 'string' && args.mounted ? String(args.mounted) : null;
51
+ if (applicationId && mountedId) {
52
+ log.error('use either --application <id> or --mounted <id>, not both');
53
+ return 1;
54
+ }
55
+ const { manifests, errors } = discoverTestManifests(project);
56
+ for (const err of errors) {
57
+ log.error(err);
58
+ }
59
+ let selected = manifests;
60
+ if (filter) {
61
+ const re = (() => {
62
+ try {
63
+ return new RegExp(filter);
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ })();
69
+ selected = manifests.filter((m) => {
70
+ const id = String(m.id || '');
71
+ const file = String(m.file || '');
72
+ if (re)
73
+ return re.test(id) || re.test(file);
74
+ return id.includes(filter) || file.includes(filter);
75
+ });
76
+ }
77
+ const scopeId = applicationId || mountedId;
78
+ if (scopeId) {
79
+ const mode = applicationId ? 'application' : 'mounted';
80
+ log.info(`test ${mode} scope: ApplicationId=${scopeId}` + (mountedId ? ' contracts=relocation,host_boundary' : ' scope=standalone'));
81
+ selected = selected.filter((m) => {
82
+ const app = (m.applicationId && String(m.applicationId)) || (m.application && String(m.application)) || '';
83
+ const file = String(m.file || '');
84
+ const id = String(m.id || '');
85
+ if (app)
86
+ return app === scopeId;
87
+ return file.includes(scopeId) || id.includes(scopeId);
88
+ });
89
+ }
90
+ /** @type {null | { schema: string, reason: string, testIds: string[], affectedChunkIds: string[], status: string }} */
91
+ let testSelection = null;
92
+ if (wantAffected) {
93
+ const outDir = outDirArg ? path.resolve(outDirArg) : path.join(project, 'dist');
94
+ const ws = createWorkspace({ root: project, outDir });
95
+ try {
96
+ if (typeof ws.selectTestsAffected !== 'function') {
97
+ log.error('selectTestsAffected missing on Workspace — rebuild native (`pnpm napi:build`)');
98
+ return 1;
99
+ }
100
+ const raw = ws.selectTestsAffected();
101
+ try {
102
+ testSelection = JSON.parse(raw);
103
+ }
104
+ catch (e) {
105
+ log.error(`test selection not JSON: ${e}`);
106
+ return 1;
107
+ }
108
+ log.info(`affected selection: ${testSelection.status} — ${testSelection.reason} (chunks=${(testSelection.affectedChunkIds || []).length})`);
109
+ const ids = new Set((testSelection.testIds || []).map(String));
110
+ const chunks = new Set((testSelection.affectedChunkIds || []).map(String));
111
+ if (ids.size > 0) {
112
+ selected = selected.filter((m) => ids.has(String(m.id || '')));
113
+ }
114
+ else if (chunks.size > 0) {
115
+ // Scaffold fallback: match manifest program.chunkId until graph->test edges exist.
116
+ selected = selected.filter((m) => {
117
+ const program = m.program && typeof m.program === 'object' ? m.program : {};
118
+ const chunk = program.chunkId ? String(program.chunkId) : '';
119
+ return chunk && chunks.has(chunk);
120
+ });
121
+ }
122
+ else {
123
+ selected = [];
124
+ }
125
+ }
126
+ finally {
127
+ ws.dispose();
128
+ }
129
+ }
130
+ if (modes.length === 1 && modes[0] !== 'all') {
131
+ const mode = modes[0];
132
+ selected = selected.filter((m) => Array.isArray(m.modes) && m.modes.includes(mode));
133
+ }
134
+ else if (!modes.includes('all')) {
135
+ selected = selected.filter((m) => Array.isArray(m.modes) && m.modes.some((x) => modes.includes(x)));
136
+ }
137
+ /** @type {Array<{
138
+ * testId: string,
139
+ * file: string,
140
+ * modes: string[],
141
+ * programId: string|null,
142
+ * planId: string|null,
143
+ * status: string,
144
+ * diagnostics: unknown[],
145
+ * }>} */
146
+ let tests;
147
+ if (wantList) {
148
+ tests = selected.map((m) => {
149
+ const program = m.program && typeof m.program === 'object' ? m.program : {};
150
+ const plan = m.plan && typeof m.plan === 'object' ? m.plan : {};
151
+ return {
152
+ testId: String(m.id),
153
+ file: String(m.file),
154
+ modes: Array.isArray(m.modes) ? m.modes.map(String) : [],
155
+ programId: program.chunkId ? String(program.chunkId) : null,
156
+ planId: plan.ref ? String(plan.ref) : plan.schema ? String(plan.schema) : null,
157
+ status: 'listed',
158
+ diagnostics: [],
159
+ };
160
+ });
161
+ }
162
+ else {
163
+ const modeActive = (name) => modes.includes('all') || modes.includes(name);
164
+ const needsBuild = selected.length > 0 &&
165
+ selected.some((m) => {
166
+ const mm = Array.isArray(m.modes) ? m.modes : [];
167
+ return ((mm.includes('compile') && modeActive('compile')) ||
168
+ (mm.includes('logic') && modeActive('logic')) ||
169
+ (mm.includes('ssr') && modeActive('ssr')) ||
170
+ (mm.includes('resume') && modeActive('resume')) ||
171
+ (mm.includes('browser') && modeActive('browser')) ||
172
+ (mm.includes('deployment') && modeActive('deployment')));
173
+ });
174
+ /** @type {string|null} */
175
+ let buildOut = null;
176
+ /** @type {unknown[]} */
177
+ let buildDiags = [];
178
+ /** @type {string|null} */
179
+ let buildError = null;
180
+ if (needsBuild) {
181
+ const built = buildForCompile(project, outDirArg ? path.resolve(outDirArg) : undefined, {
182
+ createWorkspace,
183
+ });
184
+ buildOut = built.outDir;
185
+ buildDiags = built.diagnostics || [];
186
+ if (!built.ok) {
187
+ buildError = built.error || 'build failed';
188
+ log.error(buildError);
189
+ }
190
+ }
191
+ tests = [];
192
+ for (const m of selected) {
193
+ const program = m.program && typeof m.program === 'object' ? m.program : {};
194
+ const plan = m.plan && typeof m.plan === 'object' ? m.plan : {};
195
+ const mModes = Array.isArray(m.modes) ? m.modes.map(String) : [];
196
+ const base = {
197
+ testId: String(m.id),
198
+ file: String(m.file),
199
+ modes: mModes,
200
+ programId: program.chunkId ? String(program.chunkId) : null,
201
+ planId: plan.ref ? String(plan.ref) : plan.schema ? String(plan.schema) : null,
202
+ status: 'skipped',
203
+ diagnostics: /** @type {unknown[]} */ ([]),
204
+ };
205
+ const doCompile = mModes.includes('compile') && modeActive('compile');
206
+ const doLogic = mModes.includes('logic') && modeActive('logic');
207
+ const doSsr = mModes.includes('ssr') && modeActive('ssr');
208
+ const doResume = mModes.includes('resume') && modeActive('resume');
209
+ const doBrowser = mModes.includes('browser') && modeActive('browser');
210
+ const doDeployment = mModes.includes('deployment') && modeActive('deployment');
211
+ if (!doCompile && !doLogic && !doSsr && !doResume && !doBrowser && !doDeployment) {
212
+ base.status = 'skipped';
213
+ base.diagnostics = [
214
+ {
215
+ severity: 'info',
216
+ message: `modes [${mModes.join(',')}] not executed in this vmz test slice`,
217
+ },
218
+ ];
219
+ tests.push(base);
220
+ continue;
221
+ }
222
+ if (buildError || !buildOut) {
223
+ base.status = 'error';
224
+ base.diagnostics = [...buildDiags, { severity: 'error', message: buildError || 'build unavailable' }];
225
+ tests.push(base);
226
+ continue;
227
+ }
228
+ /** @type {unknown[]} */
229
+ const diags = [];
230
+ /** @type {string[]} */
231
+ const statuses = [];
232
+ if (doCompile) {
233
+ const result = runCompileManifest(m, { outDir: buildOut });
234
+ statuses.push(result.status);
235
+ diags.push(...result.diagnostics);
236
+ base.programId = result.programId ?? base.programId;
237
+ base.planId = result.planId ?? base.planId;
238
+ }
239
+ if (doLogic) {
240
+ const result = await runLogicManifest(m, { outDir: buildOut });
241
+ statuses.push(result.status);
242
+ diags.push(...result.diagnostics);
243
+ base.programId = result.programId ?? base.programId;
244
+ base.planId = result.planId ?? base.planId;
245
+ }
246
+ if (doSsr) {
247
+ const result = await runSsrManifest(m, { outDir: buildOut });
248
+ statuses.push(result.status);
249
+ diags.push(...result.diagnostics);
250
+ base.programId = result.programId ?? base.programId;
251
+ base.planId = result.planId ?? base.planId;
252
+ }
253
+ if (doResume) {
254
+ const result = await runResumeManifest(m, { outDir: buildOut });
255
+ statuses.push(result.status);
256
+ diags.push(...result.diagnostics);
257
+ base.programId = result.programId ?? base.programId;
258
+ base.planId = result.planId ?? base.planId;
259
+ }
260
+ if (doDeployment) {
261
+ const result = runDeploymentManifest(m, { outDir: buildOut });
262
+ statuses.push(result.status);
263
+ diags.push(...result.diagnostics);
264
+ base.programId = result.programId ?? base.programId;
265
+ base.planId = result.planId ?? base.planId;
266
+ }
267
+ if (doBrowser) {
268
+ const result = await runBrowserManifest(m, { outDir: buildOut });
269
+ statuses.push(result.status);
270
+ diags.push(...result.diagnostics);
271
+ base.programId = result.programId ?? base.programId;
272
+ base.planId = result.planId ?? base.planId;
273
+ }
274
+ base.diagnostics = diags;
275
+ if (statuses.includes('error'))
276
+ base.status = 'error';
277
+ else if (statuses.includes('failed'))
278
+ base.status = 'failed';
279
+ else if (statuses.every((s) => s === 'passed'))
280
+ base.status = 'passed';
281
+ else
282
+ base.status = statuses[0] || 'skipped';
283
+ tests.push(base);
284
+ }
285
+ }
286
+ const failed = tests.some((t) => t.status === 'failed' || t.status === 'error');
287
+ const reportStatus = errors.length
288
+ ? 'error'
289
+ : wantList
290
+ ? tests.length
291
+ ? 'listed'
292
+ : 'empty'
293
+ : failed
294
+ ? 'failed'
295
+ : tests.length === 0
296
+ ? 'empty'
297
+ : 'passed';
298
+ const report = buildTestReport({
299
+ project: path.relative(process.cwd(), project) || '.',
300
+ modes,
301
+ tests,
302
+ status: reportStatus,
303
+ });
304
+ if (wantList && !wantJson) {
305
+ if (tests.length === 0) {
306
+ console.log(`vmz test: no manifests under ${project}`);
307
+ }
308
+ else {
309
+ console.log(`vmz test: ${tests.length} test(s) under ${project}`);
310
+ for (const t of tests) {
311
+ console.log(` ${t.testId}\t${t.file}\t[${t.modes.join(',')}]`);
312
+ }
313
+ }
314
+ if (errors.length) {
315
+ console.log(`vmz test: ${errors.length} manifest error(s)`);
316
+ }
317
+ return errors.length ? 2 : 0;
318
+ }
319
+ if (wantJson) {
320
+ const text = `${JSON.stringify(report, null, 2)}\n`;
321
+ if (typeof args.json === 'string' && args.json !== 'true') {
322
+ const { writeFileSync } = await import('node:fs');
323
+ writeFileSync(path.resolve(String(args.json)), text);
324
+ if (!wantList) {
325
+ console.log(`vmz test: wrote ${args.json}`);
326
+ }
327
+ }
328
+ else {
329
+ process.stdout.write(text);
330
+ }
331
+ if (errors.length)
332
+ return 2;
333
+ if (!wantList && failed)
334
+ return 1;
335
+ return 0;
336
+ }
337
+ console.log(`vmz test: ${tests.length} test(s) — ${reportStatus}`);
338
+ for (const t of tests) {
339
+ console.log(` ${t.status}\t${t.testId}\t${t.file}`);
340
+ for (const d of t.diagnostics || []) {
341
+ if (d && typeof d === 'object' && d.severity === 'error') {
342
+ console.log(` ! ${d.message}`);
343
+ if (process.env.GITHUB_ACTIONS === 'true') {
344
+ const msg = String(d.message || 'error').replace(/[\r\n]+/g, ' ');
345
+ console.log(`::error title=vmz test ${t.testId}::${msg}`);
346
+ }
347
+ }
348
+ }
349
+ if (process.env.GITHUB_ACTIONS === 'true' &&
350
+ (t.status === 'failed' || t.status === 'error') &&
351
+ !(t.diagnostics || []).some((d) => d && typeof d === 'object' && d.severity === 'error')) {
352
+ console.log(`::error title=vmz test ${t.testId}::status=${t.status}`);
353
+ }
354
+ }
355
+ if (tests.length === 0) {
356
+ console.log(' (add *.vmz.test.json manifests)');
357
+ }
358
+ if (errors.length)
359
+ return 2;
360
+ if (failed)
361
+ return 1;
362
+ return 0;
363
+ }
@@ -0,0 +1,2 @@
1
+ /** @deprecated Import from `@vmz/test` — transitional re-export. */
2
+ export { buildForCompile, resolveChunkArtifacts, runCompileManifest, } from '@vmz/test';
@@ -0,0 +1,3 @@
1
+ // @ts-nocheck
2
+ /** @deprecated Import from `@vmz/test` — transitional re-export. */
3
+ export { buildForCompile, resolveChunkArtifacts, runCompileManifest, } from '@vmz/test';
@@ -0,0 +1,2 @@
1
+ /** @deprecated Import from `@vmz/test` — transitional re-export. */
2
+ export * from '@vmz/test/discover';
@@ -0,0 +1,3 @@
1
+ // @ts-nocheck
2
+ /** @deprecated Import from `@vmz/test` — transitional re-export. */
3
+ export * from '@vmz/test/discover';
@@ -0,0 +1,2 @@
1
+ /** @deprecated Import from `@vmz/test` — transitional re-export. */
2
+ export { createLogicHost, runLogicManifest, installHeadlessDocument } from '@vmz/test';
@@ -0,0 +1,3 @@
1
+ // @ts-nocheck
2
+ /** @deprecated Import from `@vmz/test` — transitional re-export. */
3
+ export { createLogicHost, runLogicManifest, installHeadlessDocument } from '@vmz/test';
@@ -0,0 +1,2 @@
1
+ /** @deprecated Import from `@vmz/test` — transitional re-export. */
2
+ export * from '@vmz/test/protocol';
@@ -0,0 +1,3 @@
1
+ // @ts-nocheck
2
+ /** @deprecated Import from `@vmz/test` — transitional re-export. */
3
+ export * from '@vmz/test/protocol';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Track per-file fingerprints so dev rebuilds only dirty leaves (session).
3
+ */
4
+ /**
5
+ * @param {string} srcDir
6
+ * @returns {Map<string, string>}
7
+ */
8
+ export declare function fileFingerprintMap(srcDir: any): Map<any, any>;
9
+ /**
10
+ * @param {Map<string, string>} prev
11
+ * @param {Map<string, string>} next
12
+ * @returns {{ changed: string[], deleted: string[] }}
13
+ */
14
+ export declare function diffFingerprints(prev: any, next: any): {
15
+ changed: any[];
16
+ deleted: any[];
17
+ };
@@ -0,0 +1,56 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * Track per-file fingerprints so dev rebuilds only dirty leaves (session).
4
+ */
5
+ import { existsSync, readdirSync, statSync } from 'node:fs';
6
+ import path from 'node:path';
7
+ const WATCH_EXT = new Set(['.vmz', '.ts', '.tsx', '.js', '.mjs', '.css', '.json']);
8
+ /**
9
+ * @param {string} srcDir
10
+ * @returns {Map<string, string>}
11
+ */
12
+ export function fileFingerprintMap(srcDir) {
13
+ /** @type {Map<string, string>} */
14
+ const map = new Map();
15
+ walk(srcDir, (file) => {
16
+ const st = statSync(file);
17
+ map.set(file, `${st.mtimeMs}|${st.size}`);
18
+ });
19
+ return map;
20
+ }
21
+ /**
22
+ * @param {Map<string, string>} prev
23
+ * @param {Map<string, string>} next
24
+ * @returns {{ changed: string[], deleted: string[] }}
25
+ */
26
+ export function diffFingerprints(prev, next) {
27
+ /** @type {string[]} */
28
+ const changed = [];
29
+ /** @type {string[]} */
30
+ const deleted = [];
31
+ for (const [file, fp] of next) {
32
+ if (prev.get(file) !== fp)
33
+ changed.push(file);
34
+ }
35
+ for (const file of prev.keys()) {
36
+ if (!next.has(file))
37
+ deleted.push(file);
38
+ }
39
+ return { changed, deleted };
40
+ }
41
+ /**
42
+ * @param {string} dir
43
+ * @param {(file: string) => void} fn
44
+ */
45
+ function walk(dir, fn) {
46
+ if (!existsSync(dir))
47
+ return;
48
+ for (const name of readdirSync(dir)) {
49
+ const full = path.join(dir, name);
50
+ const st = statSync(full);
51
+ if (st.isDirectory())
52
+ walk(full, fn);
53
+ else if (WATCH_EXT.has(path.extname(name)))
54
+ fn(full);
55
+ }
56
+ }
package/package.json CHANGED
@@ -1,12 +1,105 @@
1
1
  {
2
2
  "name": "@vmz/vmz",
3
- "version": "0.0.1",
4
- "description": "VMZ placeholder 鈥?not for production use.",
3
+ "version": "0.0.3",
4
+ "type": "module",
5
+ "description": "VMZ Node toolchain — N-API workspace session + CLI",
5
6
  "license": "MIT",
6
- "private": false,
7
+ "bin": {
8
+ "vmz": "./bin/vmz.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "default": "./dist/index.js"
16
+ },
17
+ "./cli": {
18
+ "types": "./dist/cli.d.ts",
19
+ "default": "./dist/cli.js"
20
+ },
21
+ "./dev-session": {
22
+ "types": "./dist/dev-session.d.ts",
23
+ "default": "./dist/dev-session.js"
24
+ },
25
+ "./plugin-host": {
26
+ "types": "./dist/plugin-host.d.ts",
27
+ "default": "./dist/plugin-host.js"
28
+ },
29
+ "./bundler-adapter": {
30
+ "types": "./dist/bundler-adapter.d.ts",
31
+ "default": "./dist/bundler-adapter.js"
32
+ },
33
+ "./test-protocol": {
34
+ "types": "./dist/test-protocol.d.ts",
35
+ "default": "./dist/test-protocol.js"
36
+ },
37
+ "./test-discover": {
38
+ "types": "./dist/test-discover.d.ts",
39
+ "default": "./dist/test-discover.js"
40
+ },
41
+ "./document-check": {
42
+ "types": "./dist/document-check.d.ts",
43
+ "default": "./dist/document-check.js"
44
+ },
45
+ "./document-schema": {
46
+ "types": "./dist/document-schema.d.ts",
47
+ "default": "./dist/document-schema.js"
48
+ }
49
+ },
50
+ "dependencies": {
51
+ "@vmz/core": "0.0.3",
52
+ "@vmz/plugin": "0.0.3",
53
+ "@vmz/protocol": "0.0.3",
54
+ "jiti": "^2.6.1",
55
+ "json5": "^2.2.3"
56
+ },
57
+ "peerDependencies": {
58
+ "@vmz/plugin-markdown-it": "0.0.3",
59
+ "@vmz/test": "0.0.3",
60
+ "typescript": "^5.8.3"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "@vmz/plugin-markdown-it": {
64
+ "optional": true
65
+ },
66
+ "@vmz/test": {
67
+ "optional": true
68
+ },
69
+ "typescript": {
70
+ "optional": true
71
+ }
72
+ },
7
73
  "files": [
74
+ "bin",
75
+ "dist",
8
76
  "README.md"
9
77
  ],
78
+ "scripts": {
79
+ "build:native": "node ../../../scripts/build/napi.mjs",
80
+ "build": "pnpm run build:native && pnpm run build:js",
81
+ "test": "node --experimental-strip-types ./tests/run-node-tests.ts",
82
+ "verify": "node --import ../../../scripts/test/resolve-ts-from-js.mjs --experimental-strip-types ./tests/conformance/run.ts",
83
+ "verify:list": "node --import ../../../scripts/test/resolve-ts-from-js.mjs --experimental-strip-types ./tests/conformance/run.ts --list",
84
+ "build:js": "tsc -p tsconfig.json && node ../../../scripts/build/copy-vmz-public-api.mjs"
85
+ },
86
+ "keywords": [
87
+ "vmz",
88
+ "napi",
89
+ "compiler",
90
+ "cli"
91
+ ],
92
+ "optionalDependencies": {
93
+ "@vmz/vmz-win32-x64": "0.0.3",
94
+ "@vmz/vmz-win32-arm64": "0.0.3",
95
+ "@vmz/vmz-darwin-x64": "0.0.3",
96
+ "@vmz/vmz-darwin-arm64": "0.0.3",
97
+ "@vmz/vmz-linux-x64": "0.0.3",
98
+ "@vmz/vmz-linux-arm64": "0.0.3"
99
+ },
100
+ "publishConfig": {
101
+ "access": "public"
102
+ },
10
103
  "repository": {
11
104
  "type": "git",
12
105
  "url": "git+https://github.com/doki-land/vmz-framework.git"