@vmz/vmz 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/author-input.d.ts +19 -0
- package/dist/author-input.js +52 -0
- package/dist/build-assemble.js +18 -7
- package/dist/cdn-policy.js +5 -4
- package/dist/cli.js +106 -38
- package/dist/content-addressed-assets.d.ts +23 -2
- package/dist/content-addressed-assets.js +178 -32
- package/dist/delivery-profile.d.ts +30 -2
- package/dist/delivery-profile.js +139 -5
- package/dist/dev-session.d.ts +1 -0
- package/dist/dev-session.js +269 -65
- package/dist/dev-watch-roots.d.ts +80 -0
- package/dist/dev-watch-roots.js +245 -0
- package/dist/document-build.d.ts +4 -3
- package/dist/document-build.js +104 -82
- package/dist/document-check.d.ts +24 -5
- package/dist/document-check.js +64 -101
- package/dist/document-cmd.js +2 -9
- package/dist/document-enrich.d.ts +2 -1
- package/dist/document-enrich.js +15 -4
- package/dist/document-integrate.js +29 -21
- package/dist/document-layout-render.d.ts +20 -0
- package/dist/document-layout-render.js +87 -0
- package/dist/document-routing-config.d.ts +17 -0
- package/dist/document-routing-config.js +31 -0
- package/dist/document-schema.js +8 -1
- package/dist/embedded-packaging.js +2 -1
- package/dist/index.d.ts +18 -2
- package/dist/index.js +63 -4
- package/dist/locale-check.js +81 -183
- package/dist/locale-cmd.js +13 -45
- package/dist/locale-route-emit.d.ts +4 -1
- package/dist/locale-route-emit.js +7 -32
- package/dist/locale-router.js +26 -8
- package/dist/native-addon.d.ts +9 -0
- package/dist/native-addon.js +84 -0
- package/dist/pack.js +3 -2
- package/dist/pretty-json.d.ts +19 -0
- package/dist/pretty-json.js +43 -0
- package/dist/production-observability.js +3 -2
- package/dist/production-test-pack.js +4 -3
- package/dist/public-static-assets.d.ts +24 -0
- package/dist/public-static-assets.js +140 -0
- package/dist/release-pack.js +5 -18
- package/dist/route-path.d.ts +35 -0
- package/dist/route-path.js +77 -0
- package/dist/server-artifact.js +4 -3
- package/dist/site-delivery.js +4 -3
- package/dist/site-favicon.d.ts +31 -0
- package/dist/site-favicon.js +140 -0
- package/dist/static-emit.d.ts +21 -0
- package/dist/static-emit.js +134 -97
- package/dist/test-cmd.js +2 -1
- package/dist/wechat-packaging.d.ts +22 -0
- package/dist/wechat-packaging.js +59 -0
- package/package.json +13 -14
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Degrade author JSON5/JSON text to a plain object via Rust (not a semantic plan API).
|
|
3
|
+
* @param {string} source
|
|
4
|
+
* @returns {any}
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseAuthorInput(source: any): any;
|
|
7
|
+
/**
|
|
8
|
+
* @param {string} projectRoot
|
|
9
|
+
*/
|
|
10
|
+
export declare function loadLocalePlan(projectRoot: any): any;
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} projectRoot
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadDocumentRoutePlan(projectRoot: any): any;
|
|
15
|
+
/**
|
|
16
|
+
* Map Rust ReportedDiagnostic rows into host `{ code, severity, message, path }` rows.
|
|
17
|
+
* @param {Array<{ code?: string, severity?: string, message?: string, path?: string }>} rows
|
|
18
|
+
*/
|
|
19
|
+
export declare function mapPlanDiagnostics(rows: any): any;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Author declaration input via Rust N-API (no JS JSON5 package).
|
|
4
|
+
*
|
|
5
|
+
* Locale/document policy: loadLocalePlan / loadDocumentRoutePlan.
|
|
6
|
+
* Catalogs / transitional tables: parseAuthorInput → Rust degrade → JSON.parse.
|
|
7
|
+
*/
|
|
8
|
+
import { requireNativeAddon } from './native-addon.js';
|
|
9
|
+
/**
|
|
10
|
+
* Degrade author JSON5/JSON text to a plain object via Rust (not a semantic plan API).
|
|
11
|
+
* @param {string} source
|
|
12
|
+
* @returns {any}
|
|
13
|
+
*/
|
|
14
|
+
export function parseAuthorInput(source) {
|
|
15
|
+
const native = requireNativeAddon();
|
|
16
|
+
if (typeof native.authorJson5ToCanonicalJson !== 'function') {
|
|
17
|
+
throw new Error('native missing authorJson5ToCanonicalJson — run `pnpm napi:build`');
|
|
18
|
+
}
|
|
19
|
+
return JSON.parse(native.authorJson5ToCanonicalJson(String(source)));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} projectRoot
|
|
23
|
+
*/
|
|
24
|
+
export function loadLocalePlan(projectRoot) {
|
|
25
|
+
const native = requireNativeAddon();
|
|
26
|
+
if (typeof native.loadLocalePlan !== 'function') {
|
|
27
|
+
throw new Error('native missing loadLocalePlan — run `pnpm napi:build`');
|
|
28
|
+
}
|
|
29
|
+
return JSON.parse(native.loadLocalePlan(String(projectRoot)));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} projectRoot
|
|
33
|
+
*/
|
|
34
|
+
export function loadDocumentRoutePlan(projectRoot) {
|
|
35
|
+
const native = requireNativeAddon();
|
|
36
|
+
if (typeof native.loadDocumentRoutePlan !== 'function') {
|
|
37
|
+
throw new Error('native missing loadDocumentRoutePlan — run `pnpm napi:build`');
|
|
38
|
+
}
|
|
39
|
+
return JSON.parse(native.loadDocumentRoutePlan(String(projectRoot)));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Map Rust ReportedDiagnostic rows into host `{ code, severity, message, path }` rows.
|
|
43
|
+
* @param {Array<{ code?: string, severity?: string, message?: string, path?: string }>} rows
|
|
44
|
+
*/
|
|
45
|
+
export function mapPlanDiagnostics(rows) {
|
|
46
|
+
return (rows || []).map((d) => ({
|
|
47
|
+
code: d.code || 'vmz::unknown',
|
|
48
|
+
severity: d.severity === 'advice' ? 'warning' : d.severity || 'error',
|
|
49
|
+
message: d.message || '',
|
|
50
|
+
path: d.path || undefined,
|
|
51
|
+
}));
|
|
52
|
+
}
|
package/dist/build-assemble.js
CHANGED
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
* B5 Assemble dispatch + B6 build-proof (per-build semantic id slots).
|
|
3
3
|
*/
|
|
4
4
|
// @ts-nocheck
|
|
5
|
-
import { mkdirSync
|
|
5
|
+
import { mkdirSync } from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { semanticIdsForAssembly, sha256Hex, canonicalJson } from './delivery-profile.js';
|
|
8
8
|
import { emitServerArtifact } from './server-artifact.js';
|
|
9
9
|
import { emitEmbeddedPackaging } from './embedded-packaging.js';
|
|
10
10
|
import { emitSiteDelivery } from './site-delivery.js';
|
|
11
|
+
import { emitSiteFavicon } from './site-favicon.js';
|
|
12
|
+
import { emitPublicStaticAssets } from './public-static-assets.js';
|
|
11
13
|
import { emitWebStatic } from './static-emit.js';
|
|
14
|
+
import { writePrettyJsonFile } from './pretty-json.js';
|
|
12
15
|
export const BUILD_PROOF_SCHEMA = 'vmz.build.proof.v0';
|
|
13
16
|
export const ASSEMBLE_MANIFEST_SCHEMA = 'vmz.assemble.manifest.v0';
|
|
14
17
|
/**
|
|
@@ -25,10 +28,13 @@ export async function assembleDelivery(outDir, ctx) {
|
|
|
25
28
|
serverRuntime: selection.serverRuntime || null,
|
|
26
29
|
steps: [],
|
|
27
30
|
};
|
|
28
|
-
if (assembly === 'static
|
|
29
|
-
const staticResult = await emitWebStatic(outDir, {
|
|
31
|
+
if (assembly === 'web-static' || assembly === 'cdn+server') {
|
|
32
|
+
const staticResult = await emitWebStatic(outDir, {
|
|
33
|
+
origin: ctx.origin,
|
|
34
|
+
projectRoot: ctx.projectRoot,
|
|
35
|
+
});
|
|
30
36
|
result.steps.push({
|
|
31
|
-
kind: 'static
|
|
37
|
+
kind: 'web-static',
|
|
32
38
|
digest: staticResult.digest,
|
|
33
39
|
htmlFiles: staticResult.htmlFiles?.length ?? 0,
|
|
34
40
|
skipped: staticResult.skipped?.length ?? 0,
|
|
@@ -39,6 +45,11 @@ export async function assembleDelivery(outDir, ctx) {
|
|
|
39
45
|
skipped: staticResult.skipped,
|
|
40
46
|
};
|
|
41
47
|
}
|
|
48
|
+
else if (assembly === 'server-host' || assembly === 'local-static') {
|
|
49
|
+
// SSR / local packs: favicon + opaque public/ for serve-host.
|
|
50
|
+
emitSiteFavicon(outDir, { projectRoot: ctx.projectRoot });
|
|
51
|
+
emitPublicStaticAssets(outDir, { projectRoot: ctx.projectRoot });
|
|
52
|
+
}
|
|
42
53
|
if (assembly === 'local-static') {
|
|
43
54
|
result.steps.push({
|
|
44
55
|
kind: 'local-static',
|
|
@@ -106,7 +117,7 @@ export async function assembleDelivery(outDir, ctx) {
|
|
|
106
117
|
const vmzDir = path.join(outDir, '_vmz');
|
|
107
118
|
mkdirSync(vmzDir, { recursive: true });
|
|
108
119
|
const file = path.join(vmzDir, 'assemble-manifest.json');
|
|
109
|
-
|
|
120
|
+
writePrettyJsonFile(file, result);
|
|
110
121
|
return { manifest: result, path: file };
|
|
111
122
|
}
|
|
112
123
|
/**
|
|
@@ -123,7 +134,7 @@ export function emitBuildProof(outDir, ctx) {
|
|
|
123
134
|
};
|
|
124
135
|
for (const id of semanticIds) {
|
|
125
136
|
if (id === 'static-delivery') {
|
|
126
|
-
const step = (ctx.assemble?.steps || []).find((s) => s.kind === 'static
|
|
137
|
+
const step = (ctx.assemble?.steps || []).find((s) => s.kind === 'web-static');
|
|
127
138
|
slots[id] = step
|
|
128
139
|
? { status: 'emitted', detail: `digest=${String(step.digest).slice(0, 12)}` }
|
|
129
140
|
: { status: 'pending', detail: 'assembly requires static emit' };
|
|
@@ -186,6 +197,6 @@ export function emitBuildProof(outDir, ctx) {
|
|
|
186
197
|
const vmzDir = path.join(outDir, '_vmz');
|
|
187
198
|
mkdirSync(vmzDir, { recursive: true });
|
|
188
199
|
const file = path.join(vmzDir, 'build-proof.json');
|
|
189
|
-
|
|
200
|
+
writePrettyJsonFile(file, body);
|
|
190
201
|
return { proof: body, path: file };
|
|
191
202
|
}
|
package/dist/cdn-policy.js
CHANGED
|
@@ -8,6 +8,7 @@ import fs from 'node:fs';
|
|
|
8
8
|
import http from 'node:http';
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { assertLocaleCacheKey, localeAwareCacheKey } from './locale-router.js';
|
|
11
|
+
import { writePrettyJsonFile } from './pretty-json.js';
|
|
11
12
|
export const CDN_POLICY_MANIFEST_SCHEMA = 'vmz.cdn.policy_manifest.v0';
|
|
12
13
|
export const CDN_ADAPTER_PROJECTION_SCHEMA = 'vmz.cdn.adapter_projection.v0';
|
|
13
14
|
/** HTML: revalidate. Hashed/static assets: long immutable. */
|
|
@@ -85,7 +86,7 @@ export function buildCdnPolicyManifest(staticManifest, opts = {}) {
|
|
|
85
86
|
const body = {
|
|
86
87
|
schema: CDN_POLICY_MANIFEST_SCHEMA,
|
|
87
88
|
applicationId: staticManifest.applicationId || null,
|
|
88
|
-
deliveryProfile: '
|
|
89
|
+
deliveryProfile: 'static',
|
|
89
90
|
origin,
|
|
90
91
|
spaFallback: false,
|
|
91
92
|
staticManifestDigest: staticManifest.manifestDigest || null,
|
|
@@ -145,14 +146,14 @@ export function emitCdnPolicy(distDir, staticManifest, opts = {}) {
|
|
|
145
146
|
const policy = buildCdnPolicyManifest(staticManifest, { ...opts, localeArtifact });
|
|
146
147
|
const vmzDir = path.join(distDir, '_vmz');
|
|
147
148
|
fs.mkdirSync(vmzDir, { recursive: true });
|
|
148
|
-
|
|
149
|
+
writePrettyJsonFile(path.join(vmzDir, 'cdn-policy-manifest.json'), policy);
|
|
149
150
|
const local = projectCdnAdapter(policy, 'local-static');
|
|
150
151
|
const netlify = projectCdnAdapter(policy, 'netlify');
|
|
151
152
|
const adaptersDir = path.join(vmzDir, 'adapters');
|
|
152
153
|
fs.mkdirSync(path.join(adaptersDir, 'local-static'), { recursive: true });
|
|
153
154
|
fs.mkdirSync(path.join(adaptersDir, 'netlify'), { recursive: true });
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
writePrettyJsonFile(path.join(adaptersDir, 'local-static', 'projection.json'), local);
|
|
156
|
+
writePrettyJsonFile(path.join(adaptersDir, 'netlify', 'projection.json'), netlify);
|
|
156
157
|
fs.writeFileSync(path.join(adaptersDir, 'netlify', '_headers'), String(netlify.files['_headers'] || ''), 'utf8');
|
|
157
158
|
fs.writeFileSync(path.join(adaptersDir, 'netlify', '_redirects'), String(netlify.files['_redirects'] || ''), 'utf8');
|
|
158
159
|
return { policy, adapters: { 'local-static': local, netlify } };
|
package/dist/cli.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Node CLI command implementations .
|
|
4
4
|
*/
|
|
5
5
|
import { spawn } from 'node:child_process';
|
|
6
|
-
import {
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
|
-
import { HOST_PROTOCOL, createWorkspace, getProtocolVersions, resolveCoreRuntimeDist } from './index.js';
|
|
8
|
+
import { HOST_PROTOCOL, createWorkspace, getProtocolVersions, materializeServeHostRuntime, resolveCoreRuntimeDist, resolveNativePath, } from './index.js';
|
|
9
9
|
import { createDevSession } from './dev-session.js';
|
|
10
10
|
import { gateGlobalProjectCommand, getInvocationContext, isGlobalAllowedCommand } from './invocation.js';
|
|
11
11
|
import { log } from './log.js';
|
|
@@ -23,7 +23,7 @@ import { cmdRefactor } from './refactor-cmd.js';
|
|
|
23
23
|
import { cmdExplain } from './explain-cmd.js';
|
|
24
24
|
import { resolveNativeVmzCli } from './resolve-native-cli.js';
|
|
25
25
|
import { loadVmzConfig } from './plugin-host.js';
|
|
26
|
-
import { normalizeDeliveryAuthoring, selectBuildProfile } from './delivery-profile.js';
|
|
26
|
+
import { normalizeDeliveryAuthoring, resolveProfileArtifactDir, selectBuildProfile } from './delivery-profile.js';
|
|
27
27
|
import { packFromDeploymentIr } from './pack.js';
|
|
28
28
|
import { assembleDelivery, emitBuildProof } from './build-assemble.js';
|
|
29
29
|
/**
|
|
@@ -104,10 +104,10 @@ export function printProjectHelp() {
|
|
|
104
104
|
Usage:
|
|
105
105
|
vmz new|init <dir> Scaffold a minimal app (native CLI)
|
|
106
106
|
vmz check [path] Check project via Workspace
|
|
107
|
-
vmz build [path] [options] Build project via Workspace
|
|
107
|
+
vmz build [path] [options] Build project via Workspace; --target mini-program-wechat packs dist/wechat
|
|
108
108
|
vmz serve [path] [options] Serve dist (optional --build)
|
|
109
|
-
vmz dev [path] [options]
|
|
110
|
-
vmz format [path] [--check] Format .vmz via N-API (oxc
|
|
109
|
+
vmz dev [path] [options] Rebuild session; --target mini-program-wechat packs dist/wechat
|
|
110
|
+
vmz format [path] [--check] Format .vmz via N-API (oxc formatter + EditorConfig)
|
|
111
111
|
vmz lint [path] [--deny-warnings] Lint (= check) via N-API
|
|
112
112
|
vmz test [path] [options] Native test discover / report
|
|
113
113
|
vmz document|docs <cmd> Project /documents domain
|
|
@@ -121,10 +121,11 @@ Usage:
|
|
|
121
121
|
vmz help Show this help
|
|
122
122
|
|
|
123
123
|
Options:
|
|
124
|
-
--out-dir, -o <dir>
|
|
124
|
+
--out-dir, -o <dir> Workspace output root (default: dist). Profile artifacts land in <out-dir>/<name> (name defaults to profile id; CDN: name:'cdn' → dist/cdn)
|
|
125
125
|
--release Release build (omit serve-host; pack minify slot; proof)
|
|
126
|
-
--profile <name> Delivery profile (default from config; builtins: web-ssr|
|
|
127
|
-
--
|
|
126
|
+
--profile <name> Delivery profile (default from config; builtins: web-ssr|static|web-client|web-hybrid)
|
|
127
|
+
--target <id> browser (default) | mini-program-wechat (pack dist/wechat for WeChat DevTools; build+dev)
|
|
128
|
+
--origin <url> Site origin for web-static canonical/sitemap
|
|
128
129
|
--host <host> Listen host (default: 127.0.0.1)
|
|
129
130
|
--port <port> Listen port (dev: omit = auto from 5173; set = lock)
|
|
130
131
|
--poll-ms <ms> Dev watch poll interval (default: 300)
|
|
@@ -332,28 +333,35 @@ async function runWithPlugins(ws, project, outDir, fn) {
|
|
|
332
333
|
*/
|
|
333
334
|
async function cmdBuild(args) {
|
|
334
335
|
const pathArg = args._[0] ?? '.';
|
|
335
|
-
const
|
|
336
|
+
const targetRaw = typeof args.target === 'string' ? args.target : 'browser';
|
|
337
|
+
if (targetRaw !== 'browser' && targetRaw !== 'mini-program-wechat') {
|
|
338
|
+
log.error(`unknown --target ${targetRaw} (browser | mini-program-wechat)`);
|
|
339
|
+
return 1;
|
|
340
|
+
}
|
|
341
|
+
const wechatPack = targetRaw === 'mini-program-wechat';
|
|
342
|
+
const { project, outDir: outDirRoot } = resolveWorkspaceDirs({
|
|
336
343
|
path: pathArg,
|
|
337
344
|
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
338
345
|
});
|
|
339
|
-
|
|
346
|
+
const cfg = await loadVmzConfig(project);
|
|
347
|
+
const cliProfile = typeof args.profile === 'string' ? args.profile : '';
|
|
348
|
+
const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
|
|
349
|
+
if (!norm.ok) {
|
|
350
|
+
log.diagnostics(norm.diagnostics ?? []);
|
|
351
|
+
log.error('delivery authoring invalid');
|
|
352
|
+
return 1;
|
|
353
|
+
}
|
|
354
|
+
const selected = selectBuildProfile(norm.table, cliProfile);
|
|
355
|
+
if (!selected.ok) {
|
|
356
|
+
log.diagnostics(selected.diagnostics ?? []);
|
|
357
|
+
log.error(`unknown build --profile ${cliProfile || norm.table.default}`);
|
|
358
|
+
return 1;
|
|
359
|
+
}
|
|
360
|
+
const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
|
|
361
|
+
log.info(`build ${project} → ${outDir}${wechatPack ? ' (target=mini-program-wechat)' : ''} (out-dir=${outDirRoot}, name=${selected.profile.name})`);
|
|
340
362
|
const ws = createWorkspace({ root: project, outDir });
|
|
341
363
|
try {
|
|
342
|
-
|
|
343
|
-
const cliProfile = typeof args.profile === 'string' ? args.profile : '';
|
|
344
|
-
const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
|
|
345
|
-
if (!norm.ok) {
|
|
346
|
-
log.diagnostics(norm.diagnostics ?? []);
|
|
347
|
-
log.error('delivery authoring invalid');
|
|
348
|
-
return 1;
|
|
349
|
-
}
|
|
350
|
-
const selected = selectBuildProfile(norm.table, cliProfile);
|
|
351
|
-
if (!selected.ok) {
|
|
352
|
-
log.diagnostics(selected.diagnostics ?? []);
|
|
353
|
-
log.error(`unknown build --profile ${cliProfile || norm.table.default}`);
|
|
354
|
-
return 1;
|
|
355
|
-
}
|
|
356
|
-
log.info(`delivery profile ${selected.selection.profileId} (assembly=${selected.selection.assembly})`);
|
|
364
|
+
log.info(`delivery profile ${selected.selection.profileId} (assembly=${selected.selection.assembly}, name=${selected.profile.name})`);
|
|
357
365
|
const code = await runWithPlugins(ws, project, outDir, () => {
|
|
358
366
|
const report = ws.build(Boolean(args.release));
|
|
359
367
|
const errors = log.diagnostics(report.diagnostics ?? []);
|
|
@@ -394,6 +402,29 @@ async function cmdBuild(args) {
|
|
|
394
402
|
if (!docs.ok)
|
|
395
403
|
return 1;
|
|
396
404
|
}
|
|
405
|
+
if (wechatPack) {
|
|
406
|
+
if (typeof ws.lowerMiniprogramWechatPackaging !== 'function') {
|
|
407
|
+
log.error('wechat pack: workspace missing lowerMiniprogramWechatPackaging');
|
|
408
|
+
return 1;
|
|
409
|
+
}
|
|
410
|
+
let report;
|
|
411
|
+
try {
|
|
412
|
+
const raw = ws.lowerMiniprogramWechatPackaging();
|
|
413
|
+
report = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
414
|
+
}
|
|
415
|
+
catch (err) {
|
|
416
|
+
log.error(`wechat pack failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
417
|
+
return 1;
|
|
418
|
+
}
|
|
419
|
+
log.diagnostics(report.diagnostics ?? []);
|
|
420
|
+
if (report.status !== 'ready') {
|
|
421
|
+
log.error(`wechat pack ${report.status || 'failed'}`);
|
|
422
|
+
return 1;
|
|
423
|
+
}
|
|
424
|
+
const packRoot = report.packRoot || 'dist/wechat';
|
|
425
|
+
log.info(`wechat pack ok → ${path.join(project, packRoot)} (open in WeChat DevTools)`);
|
|
426
|
+
return 0;
|
|
427
|
+
}
|
|
397
428
|
let pack = null;
|
|
398
429
|
try {
|
|
399
430
|
pack = packFromDeploymentIr(outDir, {
|
|
@@ -419,8 +450,8 @@ async function cmdBuild(args) {
|
|
|
419
450
|
const origin = typeof args.origin === 'string' ? args.origin : undefined;
|
|
420
451
|
let assemble = null;
|
|
421
452
|
try {
|
|
422
|
-
if (selected.selection.assembly === 'static
|
|
423
|
-
log.info(`
|
|
453
|
+
if (selected.selection.assembly === 'web-static') {
|
|
454
|
+
log.info(`static emit ${outDir}`);
|
|
424
455
|
}
|
|
425
456
|
assemble = await assembleDelivery(outDir, {
|
|
426
457
|
selection: selected.selection,
|
|
@@ -431,10 +462,11 @@ async function cmdBuild(args) {
|
|
|
431
462
|
siteId: cfg.application?.id || undefined,
|
|
432
463
|
origin,
|
|
433
464
|
pack: pack.manifest,
|
|
465
|
+
projectRoot: project,
|
|
434
466
|
});
|
|
435
467
|
for (const step of assemble.manifest.steps || []) {
|
|
436
|
-
if (step.kind === 'static
|
|
437
|
-
log.info(`
|
|
468
|
+
if (step.kind === 'web-static') {
|
|
469
|
+
log.info(`static ok (${step.htmlFiles} html, ${step.skipped} skipped, digest=${String(step.digest).slice(0, 12)}…)`);
|
|
438
470
|
}
|
|
439
471
|
else if (step.kind === 'site-delivery' && step.digest) {
|
|
440
472
|
log.info(`site-delivery ok (digest=${String(step.digest).slice(0, 12)}…)`);
|
|
@@ -465,20 +497,33 @@ async function cmdServe(args) {
|
|
|
465
497
|
if (code !== 0)
|
|
466
498
|
return code;
|
|
467
499
|
}
|
|
468
|
-
const { project, outDir } = resolveWorkspaceDirs({
|
|
500
|
+
const { project, outDir: outDirRoot } = resolveWorkspaceDirs({
|
|
469
501
|
path: pathArg,
|
|
470
502
|
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
471
503
|
});
|
|
504
|
+
const cfg = await loadVmzConfig(project);
|
|
505
|
+
const cliProfile = typeof args.profile === 'string' ? args.profile : '';
|
|
506
|
+
const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
|
|
507
|
+
if (!norm.ok) {
|
|
508
|
+
log.diagnostics(norm.diagnostics ?? []);
|
|
509
|
+
log.error('delivery authoring invalid');
|
|
510
|
+
return 1;
|
|
511
|
+
}
|
|
512
|
+
const selected = selectBuildProfile(norm.table, cliProfile);
|
|
513
|
+
if (!selected.ok) {
|
|
514
|
+
log.diagnostics(selected.diagnostics ?? []);
|
|
515
|
+
log.error(`unknown build --profile ${cliProfile || norm.table.default}`);
|
|
516
|
+
return 1;
|
|
517
|
+
}
|
|
518
|
+
const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
|
|
472
519
|
const hostJs = path.join(outDir, 'vmz-serve-host.mjs');
|
|
473
520
|
if (!existsSync(hostJs)) {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
if (src && existsSync(src)) {
|
|
477
|
-
copyFileSync(src, hostJs);
|
|
521
|
+
try {
|
|
522
|
+
materializeServeHostRuntime(outDir);
|
|
478
523
|
log.info(`materialized ${hostJs} from @vmz/core (release builds omit it)`);
|
|
479
524
|
}
|
|
480
|
-
|
|
481
|
-
log.error(`missing ${hostJs} — run \`vmz build\` (without --release) or ensure @vmz/core is installed`);
|
|
525
|
+
catch (err) {
|
|
526
|
+
log.error(`missing ${hostJs} — run \`vmz build\` (without --release) or ensure @vmz/core is installed (${err instanceof Error ? err.message : err})`);
|
|
482
527
|
return 1;
|
|
483
528
|
}
|
|
484
529
|
}
|
|
@@ -493,6 +538,8 @@ async function cmdServe(args) {
|
|
|
493
538
|
VMZ_DIST: outDir,
|
|
494
539
|
VMZ_PORT: String(port),
|
|
495
540
|
VMZ_HOST: host,
|
|
541
|
+
VMZ_PROJECT_ROOT: project,
|
|
542
|
+
VMZ_NATIVE_NODE: resolveNativePath(),
|
|
496
543
|
},
|
|
497
544
|
stdio: 'inherit',
|
|
498
545
|
});
|
|
@@ -517,10 +564,25 @@ async function cmdServe(args) {
|
|
|
517
564
|
*/
|
|
518
565
|
async function cmdDev(args) {
|
|
519
566
|
const pathArg = args._[0] ?? '.';
|
|
520
|
-
const { project, outDir } = resolveWorkspaceDirs({
|
|
567
|
+
const { project, outDir: outDirRoot } = resolveWorkspaceDirs({
|
|
521
568
|
path: pathArg,
|
|
522
569
|
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
523
570
|
});
|
|
571
|
+
const cfg = await loadVmzConfig(project);
|
|
572
|
+
const cliProfile = typeof args.profile === 'string' ? args.profile : '';
|
|
573
|
+
const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
|
|
574
|
+
if (!norm.ok) {
|
|
575
|
+
log.diagnostics(norm.diagnostics ?? []);
|
|
576
|
+
log.error('delivery authoring invalid');
|
|
577
|
+
return 1;
|
|
578
|
+
}
|
|
579
|
+
const selected = selectBuildProfile(norm.table, cliProfile);
|
|
580
|
+
if (!selected.ok) {
|
|
581
|
+
log.diagnostics(selected.diagnostics ?? []);
|
|
582
|
+
log.error(`unknown build --profile ${cliProfile || norm.table.default}`);
|
|
583
|
+
return 1;
|
|
584
|
+
}
|
|
585
|
+
const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
|
|
524
586
|
const host = typeof args.host === 'string' ? args.host : '127.0.0.1';
|
|
525
587
|
const portLocked = Object.prototype.hasOwnProperty.call(args, 'port');
|
|
526
588
|
let port;
|
|
@@ -539,6 +601,11 @@ async function cmdDev(args) {
|
|
|
539
601
|
}
|
|
540
602
|
}
|
|
541
603
|
const pollMs = Number(args['poll-ms'] ?? 300);
|
|
604
|
+
const targetRaw = typeof args.target === 'string' ? args.target : 'browser';
|
|
605
|
+
if (targetRaw !== 'browser' && targetRaw !== 'mini-program-wechat') {
|
|
606
|
+
log.error(`unknown --target ${targetRaw} (browser | mini-program-wechat)`);
|
|
607
|
+
return 1;
|
|
608
|
+
}
|
|
542
609
|
const ac = new AbortController();
|
|
543
610
|
const onSig = () => {
|
|
544
611
|
log.info('shutting down…');
|
|
@@ -552,6 +619,7 @@ async function cmdDev(args) {
|
|
|
552
619
|
host,
|
|
553
620
|
port,
|
|
554
621
|
pollMs,
|
|
622
|
+
target: targetRaw,
|
|
555
623
|
signal: ac.signal,
|
|
556
624
|
});
|
|
557
625
|
try {
|
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* A3: content-addressed assets/<hash> layout for immutable CDN objects.
|
|
3
|
-
* Logical paths stay available for serve/dev;
|
|
4
|
-
*
|
|
3
|
+
* Logical paths stay available for serve/dev; static HTML rewrites to hashed URLs.
|
|
4
|
+
* CSS aggregators (vmz.css) rewrite `@import` to hashed sibling paths under assets/.
|
|
5
|
+
* JS under assets/ always rewrites ESM `./` → `../` so barrels (vmz-dom → dom-core)
|
|
6
|
+
* resolve at dist root — never prefer hashed siblings for JS (second-hop 404).
|
|
5
7
|
*/
|
|
6
8
|
export declare const CONTENT_ADDRESSED_ASSETS_SCHEMA = "vmz.content_addressed_assets.v0";
|
|
9
|
+
/**
|
|
10
|
+
* Rewrite relative `@import "./foo.css"` to hashed paths under assets/.
|
|
11
|
+
* @param {string} cssText
|
|
12
|
+
* @param {Record<string, string>} rewrites logical (no leading slash) or `/logical` → `assets/hash.ext`
|
|
13
|
+
*/
|
|
14
|
+
export declare function rewriteCssImports(cssText: any, rewrites: any): any;
|
|
15
|
+
/**
|
|
16
|
+
* Rewrite relative ESM so a file served from `/assets/<hash>.js` resolves against
|
|
17
|
+
* dist root (static `from "./x"` / `export * from "./x"` + dynamic `import("./"+…)`).
|
|
18
|
+
*
|
|
19
|
+
* Always use `../…` (Fix A). Do **not** prefer hashed siblings under `assets/`:
|
|
20
|
+
* barrels like `vmz-dom.js` (`export * from './dom-core.js'`) would then resolve
|
|
21
|
+
* as `/assets/dom-core.js` and 404. `rewrites` is accepted for API parity with CSS
|
|
22
|
+
* but intentionally ignored for JS path choice.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} jsText
|
|
25
|
+
* @param {Record<string, string>} [_rewrites]
|
|
26
|
+
*/
|
|
27
|
+
export declare function rewriteJsEntryRelativeImports(jsText: any, _rewrites?: {}): string;
|
|
7
28
|
/**
|
|
8
29
|
* Emit `assets/<sha256>.<ext>` copies and rewrite HTML href/src to hashed URLs.
|
|
9
30
|
* @param {string} distDir
|