@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/README.md
CHANGED
|
@@ -1,3 +1,53 @@
|
|
|
1
|
-
#
|
|
1
|
+
# VMZ CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
When a project reaches the point where it has a browser surface, SSR, server work, documents, tests, and several
|
|
4
|
+
deployment concerns, the usual workflow becomes a chain of tools that each see a different version of the application. A
|
|
5
|
+
build may pass while a route boundary is wrong; a browser test may pass while SSR work is replayed; a plugin may
|
|
6
|
+
transform code without anyone being able to explain the delivery result.
|
|
7
|
+
|
|
8
|
+
`vmz` is the command-line home for a different workflow. Development, checking, building, serving, testing, document
|
|
9
|
+
generation, and deployment output all begin from VMZ's understanding of the same application. The useful unit is not
|
|
10
|
+
only a module graph. It is a program with state reads and writes, control regions, routes, server capabilities,
|
|
11
|
+
ownership, and delivery boundaries.
|
|
12
|
+
|
|
13
|
+
That means the CLI can grow into something more useful than a collection of commands: it can say why a change affects a
|
|
14
|
+
region, why code was placed on the client, why a conservative boundary was used, or why a route and its server work
|
|
15
|
+
belong together. ⚡
|
|
16
|
+
|
|
17
|
+
With VMZ, a normal workflow is expected to answer all of these from the same source program:
|
|
18
|
+
|
|
19
|
+
- **Develop:** which application regions are affected by a change?
|
|
20
|
+
- **Check:** which state, route, server, or lifecycle boundary is unsafe?
|
|
21
|
+
- **Build:** what belongs in browser, SSR, resume, and server output?
|
|
22
|
+
- **Test:** what did a user interaction actually cause?
|
|
23
|
+
- **Explain:** why did the compiler make that decision?
|
|
24
|
+
|
|
25
|
+
Use it when you are adopting VMZ as the application model. It is intentionally not a compatibility compiler for
|
|
26
|
+
arbitrary Vue components, React hooks, or legacy VDOM applications; those ecosystems are better served by their native
|
|
27
|
+
toolchains.
|
|
28
|
+
|
|
29
|
+
## One tool, several views of the same program
|
|
30
|
+
|
|
31
|
+
| Workflow | The question it should answer |
|
|
32
|
+
|-------------|--------------------------------------------------------------------|
|
|
33
|
+
| Development | What changed, and which application regions are affected? |
|
|
34
|
+
| Checking | Which state, route, server, or lifetime boundary cannot be proven? |
|
|
35
|
+
| Building | What belongs in browser, SSR, resume, and server output? |
|
|
36
|
+
| Testing | Did the application behave correctly and avoid unrelated work? |
|
|
37
|
+
| Documents | Are project documents connected, localized, and deployable? |
|
|
38
|
+
|
|
39
|
+
### Designed for the npm world
|
|
40
|
+
|
|
41
|
+
VMZ does not ask users to abandon JavaScript packaging. Node remains the npm, plugin, development-server, and
|
|
42
|
+
orchestration host. A long-lived N-API bridge connects that ecosystem to Rust and oxc without reducing semantic analysis
|
|
43
|
+
to a sequence of tiny file transforms.
|
|
44
|
+
|
|
45
|
+
### More than pass or fail
|
|
46
|
+
|
|
47
|
+
The interesting future of the CLI is explanation. A useful compiler should expose the source span, graph edge, owner,
|
|
48
|
+
deployment boundary, and fallback reason behind a decision. That is a better developer experience than adding more
|
|
49
|
+
colored output to an opaque build. 🧭
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT
|
package/bin/vmz.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vmz application` — Application Collection / Mount .
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* @param {string[]} argv
|
|
6
|
+
* @returns {Promise<number>}
|
|
7
|
+
*/
|
|
8
|
+
export declare function cmdApplication(argv: any): Promise<number>;
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} pathArg
|
|
11
|
+
*/
|
|
12
|
+
export declare function runCheck(pathArg: any): {
|
|
13
|
+
project: string;
|
|
14
|
+
json: any;
|
|
15
|
+
data: any;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} hostRoot
|
|
19
|
+
* @returns {boolean}
|
|
20
|
+
*/
|
|
21
|
+
export declare function hasApplicationsConfig(hostRoot: any): boolean;
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* `vmz application` — Application Collection / Mount .
|
|
4
|
+
*/
|
|
5
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { loadNative } from './index.js';
|
|
8
|
+
import { log } from './log.js';
|
|
9
|
+
import { resolveWorkspacePackages } from './packages.js';
|
|
10
|
+
import { resolveWorkspaceDirs } from './resolve.js';
|
|
11
|
+
/**
|
|
12
|
+
* @param {string[]} argv
|
|
13
|
+
* @returns {Promise<number>}
|
|
14
|
+
*/
|
|
15
|
+
export async function cmdApplication(argv) {
|
|
16
|
+
const [sub, ...rest] = argv;
|
|
17
|
+
if (!sub || sub === 'help' || sub === '-h' || sub === '--help') {
|
|
18
|
+
printHelp();
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
21
|
+
if (sub === 'check')
|
|
22
|
+
return cmdCheck(rest);
|
|
23
|
+
if (sub === 'list')
|
|
24
|
+
return cmdList(rest);
|
|
25
|
+
if (sub === 'schemas' || sub === 'protocol')
|
|
26
|
+
return cmdSchemas();
|
|
27
|
+
if (sub === 'relocatable')
|
|
28
|
+
return cmdRelocatable(rest);
|
|
29
|
+
if (sub === 'relocate')
|
|
30
|
+
return cmdRelocate(rest);
|
|
31
|
+
if (sub === 'artifacts')
|
|
32
|
+
return cmdArtifacts(rest);
|
|
33
|
+
if (sub === 'isolation')
|
|
34
|
+
return cmdIsolation(rest);
|
|
35
|
+
if (sub === 'composition' || sub === 'compose' || sub === 'host')
|
|
36
|
+
return cmdComposition(rest);
|
|
37
|
+
if (sub === 'dev' || sub === 'sessions' || sub === 'm5')
|
|
38
|
+
return cmdDev(rest);
|
|
39
|
+
log.error(`unknown application subcommand \`${sub}\``);
|
|
40
|
+
printHelp();
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
function printHelp() {
|
|
44
|
+
console.log(`vmz application — Application Collection / Mount
|
|
45
|
+
|
|
46
|
+
Usage:
|
|
47
|
+
vmz application check [host] Validate descriptors + applications.config.json5
|
|
48
|
+
vmz application list [host] List resolved ApplicationIds / collections / mounts
|
|
49
|
+
vmz application schemas Print frozen protocol catalog JSON
|
|
50
|
+
vmz application relocatable [pkg] ApplicationBase / non_relocatable_url proof
|
|
51
|
+
vmz application relocate <manifest.json> apply ApplicationBase to relocation manifest
|
|
52
|
+
vmz application artifacts [host] ApplicationArtifact + MountTable boundary
|
|
53
|
+
vmz application isolation [host] isolation namespaces + failure containment
|
|
54
|
+
vmz application composition [host] catalog consumption + cross-app Link hrefs
|
|
55
|
+
vmz application dev [host] sessions / affected / proxy / mounted tests / deploy
|
|
56
|
+
|
|
57
|
+
Options:
|
|
58
|
+
--json [file] Emit report JSON to stdout or file
|
|
59
|
+
--base <path> ApplicationBase for relocatable / relocate (e.g. /examples/counter)
|
|
60
|
+
--dirty <path> Dirty file path for affected planning (repeatable)
|
|
61
|
+
`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* @param {string[]} argv
|
|
65
|
+
*/
|
|
66
|
+
function parseRest(argv) {
|
|
67
|
+
/** @type {Record<string, string | boolean | string[]> & { _: string[] }} */
|
|
68
|
+
const out = { _: [] };
|
|
69
|
+
for (let i = 0; i < argv.length; i++) {
|
|
70
|
+
const a = argv[i];
|
|
71
|
+
if (a.startsWith('--')) {
|
|
72
|
+
const key = a.slice(2);
|
|
73
|
+
const next = argv[i + 1];
|
|
74
|
+
if (key === 'json') {
|
|
75
|
+
if (next && !next.startsWith('-')) {
|
|
76
|
+
out.json = next;
|
|
77
|
+
i += 1;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
out.json = true;
|
|
81
|
+
}
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (key === 'dirty') {
|
|
85
|
+
if (!Array.isArray(out.dirty))
|
|
86
|
+
out.dirty = [];
|
|
87
|
+
if (next && !next.startsWith('-')) {
|
|
88
|
+
out.dirty.push(next);
|
|
89
|
+
i += 1;
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (next && !next.startsWith('-')) {
|
|
94
|
+
out[key] = next;
|
|
95
|
+
i += 1;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
out[key] = true;
|
|
99
|
+
}
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
out._.push(a);
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* @param {{ json?: string | boolean }} args
|
|
108
|
+
* @param {string} json
|
|
109
|
+
* @param {(data: any) => void} [printHuman]
|
|
110
|
+
*/
|
|
111
|
+
function emitJson(args, json, printHuman) {
|
|
112
|
+
if (typeof args.json === 'string') {
|
|
113
|
+
writeFileSync(args.json, `${json}\n`, 'utf8');
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (args.json === true) {
|
|
117
|
+
console.log(json);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (printHuman)
|
|
121
|
+
printHuman(JSON.parse(json));
|
|
122
|
+
else
|
|
123
|
+
console.log(json);
|
|
124
|
+
}
|
|
125
|
+
function cmdSchemas() {
|
|
126
|
+
const native = loadNative();
|
|
127
|
+
console.log(native.queryApplicationProtocolCatalog);
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* @param {string[]} argv
|
|
132
|
+
*/
|
|
133
|
+
function cmdCheck(argv) {
|
|
134
|
+
const args = parseRest(argv);
|
|
135
|
+
const report = runCheck(args._[0] ?? '.');
|
|
136
|
+
emitJson(args, report.json, (data) => {
|
|
137
|
+
const errors = data.diagnostics.filter((d) => d.severity === 'error');
|
|
138
|
+
log.info(`application check: descriptors=${data.descriptors.length} collections=${data.collections.length} mounts=${data.mounts.length} errors=${errors.length}`);
|
|
139
|
+
for (const d of data.diagnostics) {
|
|
140
|
+
const fn = d.severity === 'error' ? log.error : log.warn;
|
|
141
|
+
fn(`${d.code}: ${d.path}: ${d.message}`);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
return report.data.diagnostics.some((d) => d.severity === 'error') ? 1 : 0;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* @param {string[]} argv
|
|
148
|
+
*/
|
|
149
|
+
function cmdList(argv) {
|
|
150
|
+
const args = parseRest(argv);
|
|
151
|
+
const report = runCheck(args._[0] ?? '.');
|
|
152
|
+
emitJson(args, report.json, (data) => {
|
|
153
|
+
for (const d of data.descriptors) {
|
|
154
|
+
console.log(`application ${d.id}\t${d.entryRoute}\t${d.packageRoot ?? ''}`);
|
|
155
|
+
}
|
|
156
|
+
for (const m of data.mounts) {
|
|
157
|
+
console.log(`mount ${m.application}\t${m.routeBase}`);
|
|
158
|
+
}
|
|
159
|
+
for (const c of data.collections) {
|
|
160
|
+
const apps = c.groups.flatMap((g) => g.applications).join(',');
|
|
161
|
+
console.log(`collection ${c.id}\t${apps}`);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
return report.data.diagnostics.some((d) => d.severity === 'error') ? 1 : 0;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* @param {string[]} argv
|
|
168
|
+
*/
|
|
169
|
+
function cmdRelocatable(argv) {
|
|
170
|
+
const args = parseRest(argv);
|
|
171
|
+
const { project } = resolveWorkspaceDirs({ path: args._[0] ?? '.' });
|
|
172
|
+
const native = loadNative();
|
|
173
|
+
if (typeof native.checkApplicationRelocatableJson !== 'function') {
|
|
174
|
+
throw new Error('checkApplicationRelocatableJson missing — rebuild native (pnpm napi:build)');
|
|
175
|
+
}
|
|
176
|
+
const base = typeof args.base === 'string' ? args.base : null;
|
|
177
|
+
const json = native.checkApplicationRelocatableJson(project, base);
|
|
178
|
+
const data = JSON.parse(json);
|
|
179
|
+
emitJson(args, json, () => {
|
|
180
|
+
const errors = data.diagnostics.filter((d) => d.severity === 'error');
|
|
181
|
+
log.info(`application relocatable: entries=${data.manifest?.entries?.length ?? 0} errors=${errors.length}`);
|
|
182
|
+
for (const d of data.diagnostics) {
|
|
183
|
+
const fn = d.severity === 'error' ? log.error : log.warn;
|
|
184
|
+
fn(`${d.code}: ${d.path}: ${d.message}`);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
return data.diagnostics.some((d) => d.severity === 'error') ? 1 : 0;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* @param {string[]} argv
|
|
191
|
+
*/
|
|
192
|
+
function cmdRelocate(argv) {
|
|
193
|
+
const args = parseRest(argv);
|
|
194
|
+
const manifestPath = args._[0];
|
|
195
|
+
if (!manifestPath) {
|
|
196
|
+
log.error('relocate requires a relocation manifest JSON path');
|
|
197
|
+
return 1;
|
|
198
|
+
}
|
|
199
|
+
if (typeof args.base !== 'string' || !args.base) {
|
|
200
|
+
log.error('relocate requires --base <ApplicationBase>');
|
|
201
|
+
return 1;
|
|
202
|
+
}
|
|
203
|
+
const native = loadNative();
|
|
204
|
+
if (typeof native.relocateApplicationManifestJson !== 'function') {
|
|
205
|
+
throw new Error('relocateApplicationManifestJson missing — rebuild native (pnpm napi:build)');
|
|
206
|
+
}
|
|
207
|
+
const manifestJson = readFileSync(path.resolve(manifestPath), 'utf8');
|
|
208
|
+
const json = native.relocateApplicationManifestJson(manifestJson, args.base);
|
|
209
|
+
emitJson(args, json);
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* @param {string[]} argv
|
|
214
|
+
*/
|
|
215
|
+
function cmdArtifacts(argv) {
|
|
216
|
+
const args = parseRest(argv);
|
|
217
|
+
const report = runHostPackageReport(args._[0] ?? '.', 'checkApplicationArtifactBoundaryJson');
|
|
218
|
+
emitJson(args, report.json, (data) => {
|
|
219
|
+
const errors = data.diagnostics.filter((d) => d.severity === 'error');
|
|
220
|
+
log.info(`application artifacts: artifacts=${data.artifacts?.length ?? 0} mounts=${data.mountTable?.mounts?.length ?? 0} errors=${errors.length}`);
|
|
221
|
+
for (const d of data.diagnostics) {
|
|
222
|
+
const fn = d.severity === 'error' ? log.error : log.warn;
|
|
223
|
+
fn(`${d.code}: ${d.path}: ${d.message}`);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
return report.data.diagnostics.some((d) => d.severity === 'error') ? 1 : 0;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* @param {string[]} argv
|
|
230
|
+
*/
|
|
231
|
+
function cmdIsolation(argv) {
|
|
232
|
+
const args = parseRest(argv);
|
|
233
|
+
const report = runHostPackageReport(args._[0] ?? '.', 'checkApplicationIsolationJson');
|
|
234
|
+
emitJson(args, report.json, (data) => {
|
|
235
|
+
const errors = data.diagnostics.filter((d) => d.severity === 'error');
|
|
236
|
+
log.info(`application isolation: namespaces=${data.namespaces?.length ?? 0} containment=${data.failureContainment?.length ?? 0} errors=${errors.length}`);
|
|
237
|
+
for (const d of data.diagnostics) {
|
|
238
|
+
const fn = d.severity === 'error' ? log.error : log.warn;
|
|
239
|
+
fn(`${d.code}: ${d.path}: ${d.message}`);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
return report.data.diagnostics.some((d) => d.severity === 'error') ? 1 : 0;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* @param {string[]} argv
|
|
246
|
+
*/
|
|
247
|
+
function cmdComposition(argv) {
|
|
248
|
+
const args = parseRest(argv);
|
|
249
|
+
const report = runHostPackageReport(args._[0] ?? '.', 'checkApplicationHostCompositionJson');
|
|
250
|
+
emitJson(args, report.json, (data) => {
|
|
251
|
+
const errors = data.diagnostics.filter((d) => d.severity === 'error');
|
|
252
|
+
log.info(`application composition: catalog=${data.catalog?.applications?.length ?? 0} links=${data.crossApplicationLinks?.length ?? 0} errors=${errors.length}`);
|
|
253
|
+
for (const link of data.crossApplicationLinks ?? []) {
|
|
254
|
+
console.log(`link ${link.applicationId}\t${link.routeId}\t${link.href ?? '(unresolved)'}\tdocumentNavigation=${link.documentNavigation}`);
|
|
255
|
+
}
|
|
256
|
+
for (const d of data.diagnostics) {
|
|
257
|
+
const fn = d.severity === 'error' ? log.error : log.warn;
|
|
258
|
+
fn(`${d.code}: ${d.path}: ${d.message}`);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
return report.data.diagnostics.some((d) => d.severity === 'error') ? 1 : 0;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* @param {string[]} argv
|
|
265
|
+
*/
|
|
266
|
+
function cmdDev(argv) {
|
|
267
|
+
const args = parseRest(argv);
|
|
268
|
+
const pathArg = args._[0] ?? '.';
|
|
269
|
+
const { project } = resolveWorkspaceDirs({ path: pathArg });
|
|
270
|
+
const packages = resolveWorkspacePackages(project);
|
|
271
|
+
const roots = packages.map((p) => p.root);
|
|
272
|
+
if (!roots.includes(project))
|
|
273
|
+
roots.unshift(project);
|
|
274
|
+
const dirty = Array.isArray(args.dirty) ? args.dirty.map((d) => path.resolve(project, String(d))) : [];
|
|
275
|
+
const native = loadNative();
|
|
276
|
+
if (typeof native.checkApplicationDevTestDeployJson !== 'function') {
|
|
277
|
+
log.error('checkApplicationDevTestDeployJson missing — rebuild native (`pnpm napi:build`)');
|
|
278
|
+
return 1;
|
|
279
|
+
}
|
|
280
|
+
const json = native.checkApplicationDevTestDeployJson(project, roots, dirty);
|
|
281
|
+
let data;
|
|
282
|
+
try {
|
|
283
|
+
data = JSON.parse(json);
|
|
284
|
+
}
|
|
285
|
+
catch (e) {
|
|
286
|
+
log.error(`dev report not JSON: ${e}`);
|
|
287
|
+
return 1;
|
|
288
|
+
}
|
|
289
|
+
emitJson(args, json, (report) => {
|
|
290
|
+
const errors = (report.diagnostics || []).filter((d) => d.severity === 'error');
|
|
291
|
+
log.info(`application dev: sessions=${report.sessions?.sessions?.length ?? 0} affected=${report.affected?.units?.length ?? 0} proxy=${report.proxy?.cases?.length ?? 0} errors=${errors.length}`);
|
|
292
|
+
for (const u of report.affected?.units ?? []) {
|
|
293
|
+
console.log(`affected ${u.applicationId}\t${u.reason}`);
|
|
294
|
+
}
|
|
295
|
+
for (const c of report.proxy?.cases ?? []) {
|
|
296
|
+
console.log(`proxy ${c.url}\t${c.applicationId ?? '-'}\t${c.status}\t${c.reason ?? ''}`);
|
|
297
|
+
}
|
|
298
|
+
for (const d of report.diagnostics || []) {
|
|
299
|
+
const fn = d.severity === 'error' ? log.error : log.warn;
|
|
300
|
+
fn(`${d.code}: ${d.path}: ${d.message}`);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
return data.diagnostics.some((d) => d.severity === 'error') ? 1 : 0;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* @param {string} pathArg
|
|
307
|
+
* @param {string} nativeFn
|
|
308
|
+
*/
|
|
309
|
+
function runHostPackageReport(pathArg, nativeFn) {
|
|
310
|
+
const { project } = resolveWorkspaceDirs({ path: pathArg });
|
|
311
|
+
const packages = resolveWorkspacePackages(project);
|
|
312
|
+
const roots = packages.map((p) => p.root);
|
|
313
|
+
if (!roots.includes(project))
|
|
314
|
+
roots.unshift(project);
|
|
315
|
+
const native = loadNative();
|
|
316
|
+
if (typeof native[nativeFn] !== 'function') {
|
|
317
|
+
throw new Error(`${nativeFn} missing — rebuild native (pnpm napi:build)`);
|
|
318
|
+
}
|
|
319
|
+
const json = native[nativeFn](project, roots);
|
|
320
|
+
const data = JSON.parse(json);
|
|
321
|
+
return { project, json, data };
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* @param {string} pathArg
|
|
325
|
+
*/
|
|
326
|
+
export function runCheck(pathArg) {
|
|
327
|
+
const { project } = resolveWorkspaceDirs({ path: pathArg });
|
|
328
|
+
const packages = resolveWorkspacePackages(project);
|
|
329
|
+
const roots = packages.map((p) => p.root);
|
|
330
|
+
// Always include host root so a local package.json#vmz.application is visible.
|
|
331
|
+
if (!roots.includes(project))
|
|
332
|
+
roots.unshift(project);
|
|
333
|
+
const native = loadNative();
|
|
334
|
+
if (typeof native.checkApplicationsJson !== 'function') {
|
|
335
|
+
throw new Error('checkApplicationsJson missing — rebuild native (pnpm napi:build)');
|
|
336
|
+
}
|
|
337
|
+
const json = native.checkApplicationsJson(project, roots);
|
|
338
|
+
const data = JSON.parse(json);
|
|
339
|
+
return { project, json, data };
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* @param {string} hostRoot
|
|
343
|
+
* @returns {boolean}
|
|
344
|
+
*/
|
|
345
|
+
export function hasApplicationsConfig(hostRoot) {
|
|
346
|
+
return existsSync(path.join(hostRoot, 'applications.config.json5'));
|
|
347
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundler adapter (session) — consumes Deployment IR; does not invent VMZ semantics.
|
|
3
|
+
*
|
|
4
|
+
* Vite/Rolldown may call these helpers; they must not reverse the arrow.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {object} DeploymentUnit
|
|
8
|
+
* @property {string} chunkId
|
|
9
|
+
* @property {string} kind
|
|
10
|
+
* @property {string} source
|
|
11
|
+
* @property {string} clientEntry
|
|
12
|
+
* @property {string} programIr
|
|
13
|
+
* @property {string[]} [dependsOn]
|
|
14
|
+
* @property {string[]} [dependedBy]
|
|
15
|
+
* @property {boolean} [rebuilt]
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {object} DeploymentIr
|
|
19
|
+
* @property {string} schema
|
|
20
|
+
* @property {DeploymentUnit[]} units
|
|
21
|
+
* @property {string[]} [affectedChunks]
|
|
22
|
+
* @property {string[]} [seedChunks]
|
|
23
|
+
* @property {boolean} [islandHmr]
|
|
24
|
+
* @property {boolean} [full]
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} outDir
|
|
28
|
+
* @returns {DeploymentIr}
|
|
29
|
+
*/
|
|
30
|
+
export declare function loadDeploymentIr(outDir: any): any;
|
|
31
|
+
/**
|
|
32
|
+
* Map Deployment IR → bundler entry points (absolute paths under outDir).
|
|
33
|
+
* @param {string} outDir
|
|
34
|
+
* @param {DeploymentIr} [ir]
|
|
35
|
+
*/
|
|
36
|
+
export declare function planBundleInputs(outDir: any, ir?: any): any;
|
|
37
|
+
/**
|
|
38
|
+
* Entries that were rebuilt in the last emit (HMR / incremental pack).
|
|
39
|
+
* @param {string} outDir
|
|
40
|
+
* @param {DeploymentIr} [ir]
|
|
41
|
+
*/
|
|
42
|
+
export declare function planAffectedBundleInputs(outDir: any, ir?: any): any;
|
|
43
|
+
/**
|
|
44
|
+
* Thin Vite plugin factory: only reads Deployment IR. No `.vmz` transform hooks.
|
|
45
|
+
* @param {{ outDir?: string, root?: string }} [options]
|
|
46
|
+
*/
|
|
47
|
+
export declare function createVitePluginVmzAdapter(options?: {}): {
|
|
48
|
+
name: string;
|
|
49
|
+
buildStart(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Expose IR to other plugins via meta (optional).
|
|
52
|
+
*/
|
|
53
|
+
configResolved(): void;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Thin Rolldown plugin factory (deployment) — same contract as Vite adapter: read Deployment IR only.
|
|
57
|
+
* @param {{ outDir?: string, root?: string }} [options]
|
|
58
|
+
*/
|
|
59
|
+
export declare function createRolldownPluginVmzAdapter(options?: {}): {
|
|
60
|
+
name: string;
|
|
61
|
+
buildStart(): void;
|
|
62
|
+
options(inputOptions: any): any;
|
|
63
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Bundler adapter (session) — consumes Deployment IR; does not invent VMZ semantics.
|
|
4
|
+
*
|
|
5
|
+
* Vite/Rolldown may call these helpers; they must not reverse the arrow.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {object} DeploymentUnit
|
|
11
|
+
* @property {string} chunkId
|
|
12
|
+
* @property {string} kind
|
|
13
|
+
* @property {string} source
|
|
14
|
+
* @property {string} clientEntry
|
|
15
|
+
* @property {string} programIr
|
|
16
|
+
* @property {string[]} [dependsOn]
|
|
17
|
+
* @property {string[]} [dependedBy]
|
|
18
|
+
* @property {boolean} [rebuilt]
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {object} DeploymentIr
|
|
22
|
+
* @property {string} schema
|
|
23
|
+
* @property {DeploymentUnit[]} units
|
|
24
|
+
* @property {string[]} [affectedChunks]
|
|
25
|
+
* @property {string[]} [seedChunks]
|
|
26
|
+
* @property {boolean} [islandHmr]
|
|
27
|
+
* @property {boolean} [full]
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} outDir
|
|
31
|
+
* @returns {DeploymentIr}
|
|
32
|
+
*/
|
|
33
|
+
export function loadDeploymentIr(outDir) {
|
|
34
|
+
const file = path.join(outDir, 'vmz-deployment.json');
|
|
35
|
+
if (!existsSync(file)) {
|
|
36
|
+
throw new Error(`Deployment IR missing: ${file} (run vmz build first)`);
|
|
37
|
+
}
|
|
38
|
+
const ir = JSON.parse(readFileSync(file, 'utf8'));
|
|
39
|
+
if (ir.schema !== 'vmz.deployment.v0') {
|
|
40
|
+
throw new Error(`unsupported deployment schema: ${ir.schema}`);
|
|
41
|
+
}
|
|
42
|
+
return ir;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Map Deployment IR → bundler entry points (absolute paths under outDir).
|
|
46
|
+
* @param {string} outDir
|
|
47
|
+
* @param {DeploymentIr} [ir]
|
|
48
|
+
*/
|
|
49
|
+
export function planBundleInputs(outDir, ir = loadDeploymentIr(outDir)) {
|
|
50
|
+
return (ir.units || []).map((u) => ({
|
|
51
|
+
chunkId: u.chunkId,
|
|
52
|
+
kind: u.kind,
|
|
53
|
+
entry: path.join(outDir, u.clientEntry),
|
|
54
|
+
programIr: path.join(outDir, u.programIr),
|
|
55
|
+
source: u.source,
|
|
56
|
+
rebuilt: Boolean(u.rebuilt),
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Entries that were rebuilt in the last emit (HMR / incremental pack).
|
|
61
|
+
* @param {string} outDir
|
|
62
|
+
* @param {DeploymentIr} [ir]
|
|
63
|
+
*/
|
|
64
|
+
export function planAffectedBundleInputs(outDir, ir = loadDeploymentIr(outDir)) {
|
|
65
|
+
const affected = new Set(ir.affectedChunks || []);
|
|
66
|
+
return planBundleInputs(outDir, ir).filter((e) => e.rebuilt || affected.has(e.chunkId));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Thin Vite plugin factory: only reads Deployment IR. No `.vmz` transform hooks.
|
|
70
|
+
* @param {{ outDir?: string, root?: string }} [options]
|
|
71
|
+
*/
|
|
72
|
+
export function createVitePluginVmzAdapter(options = {}) {
|
|
73
|
+
const outDir = options.outDir ?? 'dist';
|
|
74
|
+
return {
|
|
75
|
+
name: 'vmz-deployment-adapter',
|
|
76
|
+
// Enforce direction: bundler consumes IR, never owns VMZ semantics.
|
|
77
|
+
buildStart() {
|
|
78
|
+
const abs = path.isAbsolute(outDir) ? outDir : path.join(options.root ?? process.cwd(), outDir);
|
|
79
|
+
if (!existsSync(path.join(abs, 'vmz-deployment.json'))) {
|
|
80
|
+
this.warn?.(`[vmz] ${abs}/vmz-deployment.json missing — run \`vmz build\` before bundling`);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
/**
|
|
84
|
+
* Expose IR to other plugins via meta (optional).
|
|
85
|
+
*/
|
|
86
|
+
configResolved() {
|
|
87
|
+
/* no-op — presence documents the adapter surface */
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Thin Rolldown plugin factory (deployment) — same contract as Vite adapter: read Deployment IR only.
|
|
93
|
+
* @param {{ outDir?: string, root?: string }} [options]
|
|
94
|
+
*/
|
|
95
|
+
export function createRolldownPluginVmzAdapter(options = {}) {
|
|
96
|
+
const outDir = options.outDir ?? 'dist';
|
|
97
|
+
return {
|
|
98
|
+
name: 'vmz-deployment-adapter-rolldown',
|
|
99
|
+
buildStart() {
|
|
100
|
+
const abs = path.isAbsolute(outDir) ? outDir : path.join(options.root ?? process.cwd(), outDir);
|
|
101
|
+
if (!existsSync(path.join(abs, 'vmz-deployment.json'))) {
|
|
102
|
+
this.warn?.(`[vmz] ${abs}/vmz-deployment.json missing — run \`vmz build\` before bundling`);
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
// Rolldown may call `options` / `buildStart`; keep surface identical and semantic-free.
|
|
106
|
+
options(inputOptions) {
|
|
107
|
+
return inputOptions;
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node CLI command implementations .
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* @param {string[]} argv
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseArgs(argv: any): {
|
|
8
|
+
_: any[];
|
|
9
|
+
};
|
|
10
|
+
export declare function printGlobalHelp(): void;
|
|
11
|
+
export declare function printProjectHelp(): void;
|
|
12
|
+
/** @deprecated use printProjectHelp / printGlobalHelp */
|
|
13
|
+
export declare function printHelp(): void;
|
|
14
|
+
/**
|
|
15
|
+
* @param {string[]} argv
|
|
16
|
+
* @param {{
|
|
17
|
+
* cwd?: string,
|
|
18
|
+
* thisPackageRoot?: string,
|
|
19
|
+
* reexec?: (bin: string, argv: string[]) => Promise<number>,
|
|
20
|
+
* }} [opts]
|
|
21
|
+
* @returns {Promise<number>}
|
|
22
|
+
*/
|
|
23
|
+
export declare function runCli(argv: any, opts?: {}): Promise<any>;
|