@vmz/vmz 0.3.12 → 0.3.14
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/bin/vmz.js +4 -0
- package/delivery-runtime-files.json +2 -0
- package/dist/cli/cli.js +46 -23
- package/dist/cli/format-cmd.d.ts +9 -17
- package/dist/cli/format-cmd.js +37 -49
- package/dist/cli/format-config.d.ts +6 -9
- package/dist/cli/format-config.js +5 -29
- package/dist/delivery/delivery-profile.js +1 -1
- package/dist/dev/dev-incremental.d.ts +0 -2
- package/dist/dev/dev-incremental.js +0 -1
- package/dist/dev/dev-session.d.ts +53 -1
- package/dist/dev/dev-session.js +368 -65
- package/dist/document/document-base-css.d.ts +15 -0
- package/dist/document/document-base-css.js +578 -0
- package/dist/document/document-build.d.ts +1 -0
- package/dist/document/document-build.js +94 -78
- package/dist/document/document-client.d.ts +13 -0
- package/dist/document/document-client.js +217 -0
- package/dist/document/document-cmd.js +3 -1
- package/dist/document/document-designs.d.ts +9 -3
- package/dist/document/document-designs.js +20 -34
- package/dist/document/document-enrich.d.ts +9 -0
- package/dist/document/document-enrich.js +55 -0
- package/dist/document/document-highlight.d.ts +26 -0
- package/dist/document/document-highlight.js +54 -0
- package/dist/document/document-integrate.d.ts +5 -0
- package/dist/document/document-integrate.js +1 -0
- package/dist/document/document-interactive.js +10 -2
- package/dist/document/document-layout-render.js +6 -2
- package/dist/document/document-schema.d.ts +5 -0
- package/dist/workspace/build-assemble.js +18 -6
- package/dist/workspace/content-addressed-assets.d.ts +6 -17
- package/dist/workspace/content-addressed-assets.js +10 -95
- package/dist/workspace/delivery-runtime-imports.js +9 -0
- package/dist/workspace/native-addon.d.ts +4 -0
- package/dist/workspace/pack-native.d.ts +151 -0
- package/dist/workspace/pack-native.js +280 -0
- package/dist/workspace/pack.d.ts +131 -32
- package/dist/workspace/pack.js +381 -65
- package/dist/workspace/plugin-host.d.ts +4 -4
- package/dist/workspace/plugin-host.js +6 -6
- package/dist/workspace/production-observability.d.ts +2 -0
- package/dist/workspace/production-observability.js +6 -2
- package/dist/workspace/project-build.js +26 -4
- package/dist/workspace/public-api.d.ts +7 -3
- package/dist/workspace/public-api.js +5 -3
- package/dist/workspace/static-emit.d.ts +30 -0
- package/dist/workspace/static-emit.js +211 -18
- package/dist/workspace/user-config.d.ts +112 -0
- package/dist/workspace/user-config.js +12 -0
- package/host-runtime-files.json +1 -0
- package/locales/en-US/cli.json +5 -4
- package/locales/en-US/diag.json +2 -0
- package/locales/zh-CN/diag.json +2 -0
- package/package.json +20 -20
- package/dist/workspace/pack-client-packages.d.ts +0 -34
- package/dist/workspace/pack-client-packages.js +0 -550
|
@@ -9,9 +9,11 @@ import { normalizeDeliveryAuthoring, resolveProfileArtifactDir, selectBuildProfi
|
|
|
9
9
|
import { buildIntegratedDocuments, projectHasDocuments } from '../document/document-integrate.js';
|
|
10
10
|
import { emitLocaleRuntimeModules, localeHasErrors } from '../locale/locale-check.js';
|
|
11
11
|
import { emitLocaleRouteRealization } from '../locale/locale-route-emit.js';
|
|
12
|
-
import { packFromDeploymentIr } from './pack.js';
|
|
12
|
+
import { ensureRuntimeCompanions, packFromDeploymentIr, packSsrFromDeploymentIr } from './pack.js';
|
|
13
13
|
import { loadVmzConfig } from './plugin-host.js';
|
|
14
14
|
import { emitRouteCatalog } from './route-catalog-emit.js';
|
|
15
|
+
import { resolveCoreRuntimeDist } from './runtime-dist.js';
|
|
16
|
+
import { emitStaticBootstrapEntries } from './static-emit.js';
|
|
15
17
|
function dedupeDiagnostics(list) {
|
|
16
18
|
const seen = new Set();
|
|
17
19
|
const out = [];
|
|
@@ -81,7 +83,7 @@ export async function buildProjectToOutDirRoot(project, outDirRoot, opts = {}) {
|
|
|
81
83
|
const assembly = String(selected.selection.assembly || '');
|
|
82
84
|
const profileId = String(selected.selection.profileId || '');
|
|
83
85
|
// Dynamic import avoids init cycle with `./index.js` re-exports.
|
|
84
|
-
const { createWorkspace
|
|
86
|
+
const { createWorkspace } = await import('./public-api.js');
|
|
85
87
|
const ws = createWorkspace({ root: project, outDir: artifactDir });
|
|
86
88
|
try {
|
|
87
89
|
const code = await runWithPlugins(ws, project, artifactDir, () => {
|
|
@@ -141,8 +143,26 @@ export async function buildProjectToOutDirRoot(project, outDirRoot, opts = {}) {
|
|
|
141
143
|
error: routeCatalog.error || 'route catalog emit failed',
|
|
142
144
|
};
|
|
143
145
|
}
|
|
146
|
+
try {
|
|
147
|
+
// Node graph must be packed before any SSR consumer (document build,
|
|
148
|
+
// static emit, render host) imports a compiled chunk. Companions are
|
|
149
|
+
// copied first so the Node graph sees the delivery runtime beside the
|
|
150
|
+
// client modules.
|
|
151
|
+
ensureRuntimeCompanions(artifactDir, resolveCoreRuntimeDist());
|
|
152
|
+
packSsrFromDeploymentIr(artifactDir, { projectRoot: project });
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
return {
|
|
156
|
+
ok: false,
|
|
157
|
+
outDirRoot: root,
|
|
158
|
+
artifactDir,
|
|
159
|
+
deliveryName,
|
|
160
|
+
diagnostics,
|
|
161
|
+
error: `node pack failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
144
164
|
if (projectHasDocuments(project)) {
|
|
145
|
-
const docs = await buildIntegratedDocuments({ projectRoot: project, outDir: artifactDir });
|
|
165
|
+
const docs = await buildIntegratedDocuments({ projectRoot: project, outDir: artifactDir, engines: cfg.engines });
|
|
146
166
|
if (!docs.ok) {
|
|
147
167
|
return {
|
|
148
168
|
ok: false,
|
|
@@ -156,11 +176,13 @@ export async function buildProjectToOutDirRoot(project, outDirRoot, opts = {}) {
|
|
|
156
176
|
}
|
|
157
177
|
let pack;
|
|
158
178
|
try {
|
|
179
|
+
// Browser pack entries are the static bootstrap modules; static emit
|
|
180
|
+
// runs after pack (HTML resolves `_vmz/pack/`), so write them first.
|
|
181
|
+
emitStaticBootstrapEntries(artifactDir);
|
|
159
182
|
pack = packFromDeploymentIr(artifactDir, {
|
|
160
183
|
release: Boolean(opts.release),
|
|
161
184
|
profileId,
|
|
162
185
|
assembly,
|
|
163
|
-
coreDist: resolveCoreRuntimeDist(),
|
|
164
186
|
projectRoot: project,
|
|
165
187
|
});
|
|
166
188
|
}
|
|
@@ -96,7 +96,7 @@ export { registerApplicationCommands, runCheck as runApplicationCheck } from '..
|
|
|
96
96
|
export { registerArtifactCommands, runArtifact } from '../cli/release-cmd.js';
|
|
97
97
|
export { ARTIFACT_DIFF_SCHEMA, DELIVERY_ARTIFACT_MANIFEST_SCHEMA, RELEASE_ENVELOPE_SCHEMA, ROUTE_REALIZATION_TABLE_SCHEMA, atomicWritePointer, canonicalJson, diffArtifacts, loadReleaseEnvelope, packRelease, publishRelease, readPointer, rollbackRelease, sha256File, sha256Hex, } from './release-pack.js';
|
|
98
98
|
export { STATIC_DELIVERY_MANIFEST_SCHEMA, emitWebStatic } from './static-emit.js';
|
|
99
|
-
export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, rewriteCssImports,
|
|
99
|
+
export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, rewriteCssImports, } from './content-addressed-assets.js';
|
|
100
100
|
export { SITE_FAVICON_SCHEMA, emitSiteFavicon, readSiteFaviconHeadHtml, packPngsIntoIco } from './site-favicon.js';
|
|
101
101
|
export { PUBLIC_STATIC_ASSETS_SCHEMA, emitPublicStaticAssets } from './public-static-assets.js';
|
|
102
102
|
export { CDN_POLICY_MANIFEST_SCHEMA, CDN_ADAPTER_PROJECTION_SCHEMA, CACHE_HTML, CACHE_ASSET_IMMUTABLE, CACHE_META, buildCdnPolicyManifest, emitCdnPolicy, projectCdnAdapter, createLocalStaticHandler, listenLocalStaticHost, matchGlob, } from './cdn-policy.js';
|
|
@@ -105,7 +105,9 @@ export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging } from './embedde
|
|
|
105
105
|
export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
|
|
106
106
|
export { WECHAT_PACKAGING_SCHEMA, WECHAT_PACKAGING_REL, wechatPackagingFromDelivery, materializeWechatPackaging, prepareWechatPackaging, } from './wechat-packaging.js';
|
|
107
107
|
export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, pickDeliveryPackaging, normalizeProfileArtifactName, resolveProfileArtifactDir, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from '../delivery/delivery-profile.js';
|
|
108
|
-
export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
|
|
108
|
+
export { PACK_MANIFEST_SCHEMA, PACK_OUTPUT_DIR_REL, PACK_PUBLIC_BASE, PACK_NODE_MANIFEST_SCHEMA, PACK_NODE_OUTPUT_DIR_REL, PACK_NODE_MANIFEST_REL, packFromDeploymentIr, packSsrFromDeploymentIr, packEntryHref, packNodeEntryFile, ensureRuntimeCompanions, } from './pack.js';
|
|
109
|
+
export { buildPackRequest, runPackPlan, runPackWrite, PackNativeError } from './pack-native.js';
|
|
110
|
+
export type { PackNativeBinding, PackPlan, PackPlanResponse, PackDiagnostic, PackRequest, PackRequestEntry, PackRequestUse, PackTarget, } from './pack-native.js';
|
|
109
111
|
export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
|
|
110
112
|
export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof } from './build-assemble.js';
|
|
111
113
|
export { buildProjectToOutDirRoot, type BuildProjectOptions, type BuildProjectResult } from './project-build.js';
|
|
@@ -116,7 +118,9 @@ export { absoluteUrl, assertLocaleCacheKey, buildLocalePageMeta, buildLocaleRout
|
|
|
116
118
|
export { LOCALE_ROUTE_REALIZATION_ARTIFACT_SCHEMA, emitLocaleRouteRealization } from '../locale/locale-route-emit.js';
|
|
117
119
|
export { assertHostMessageInvariant, assertServerErrorEnvelope, assertServerFormatContext, buildLocaleDeliveryResolution, checkLocaleDelivery, fallbackDigest, messageCatalogHash, proveMiniPackageMessages, validateNativeLocalePack, } from '../locale/locale-delivery.js';
|
|
118
120
|
export { checkLocaleConformance, diffLocaleCatalogs, explainLocaleMessage, extractHardcodedText, pseudoLocalizeCatalog, } from '../locale/locale-tooling.js';
|
|
119
|
-
export { applyPlugins, contentHash,
|
|
121
|
+
export { applyPlugins, contentHash, definePlugin, loadVmzConfig } from './plugin-host.js';
|
|
122
|
+
export { defineConfig } from './user-config.js';
|
|
123
|
+
export type { DeliveryAssembly, DeliveryAuthoring, DeliveryPackagingAuthoring, DeliveryProfileAuthoring, DeliveryServerRuntime, SiteDeliveryAuthoring, VmzFormatConfig, VmzUserConfig, WechatPackagingAuthoring, } from './user-config.js';
|
|
120
124
|
export { createRolldownPluginVmzAdapter, createVitePluginVmzAdapter, loadDeploymentIr, planAffectedBundleInputs, planBundleInputs, } from './bundler-adapter.js';
|
|
121
125
|
declare const _default: {
|
|
122
126
|
HOST_PROTOCOL: string;
|
|
@@ -284,7 +284,7 @@ export { ARTIFACT_DIFF_SCHEMA, DELIVERY_ARTIFACT_MANIFEST_SCHEMA, RELEASE_ENVELO
|
|
|
284
284
|
// APPLICATION_ARTIFACT_SCHEMA lives in @vmz/protocol (already re-exported above);
|
|
285
285
|
// release-pack keeps a local constant for envelope writes — do not dual-export the name.
|
|
286
286
|
export { STATIC_DELIVERY_MANIFEST_SCHEMA, emitWebStatic } from './static-emit.js';
|
|
287
|
-
export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, rewriteCssImports,
|
|
287
|
+
export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, rewriteCssImports, } from './content-addressed-assets.js';
|
|
288
288
|
export { SITE_FAVICON_SCHEMA, emitSiteFavicon, readSiteFaviconHeadHtml, packPngsIntoIco } from './site-favicon.js';
|
|
289
289
|
export { PUBLIC_STATIC_ASSETS_SCHEMA, emitPublicStaticAssets } from './public-static-assets.js';
|
|
290
290
|
export { CDN_POLICY_MANIFEST_SCHEMA, CDN_ADAPTER_PROJECTION_SCHEMA, CACHE_HTML, CACHE_ASSET_IMMUTABLE, CACHE_META, buildCdnPolicyManifest, emitCdnPolicy, projectCdnAdapter, createLocalStaticHandler, listenLocalStaticHost, matchGlob, } from './cdn-policy.js';
|
|
@@ -293,7 +293,8 @@ export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging } from './embedde
|
|
|
293
293
|
export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
|
|
294
294
|
export { WECHAT_PACKAGING_SCHEMA, WECHAT_PACKAGING_REL, wechatPackagingFromDelivery, materializeWechatPackaging, prepareWechatPackaging, } from './wechat-packaging.js';
|
|
295
295
|
export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, pickDeliveryPackaging, normalizeProfileArtifactName, resolveProfileArtifactDir, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from '../delivery/delivery-profile.js';
|
|
296
|
-
export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
|
|
296
|
+
export { PACK_MANIFEST_SCHEMA, PACK_OUTPUT_DIR_REL, PACK_PUBLIC_BASE, PACK_NODE_MANIFEST_SCHEMA, PACK_NODE_OUTPUT_DIR_REL, PACK_NODE_MANIFEST_REL, packFromDeploymentIr, packSsrFromDeploymentIr, packEntryHref, packNodeEntryFile, ensureRuntimeCompanions, } from './pack.js';
|
|
297
|
+
export { buildPackRequest, runPackPlan, runPackWrite, PackNativeError } from './pack-native.js';
|
|
297
298
|
export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
|
|
298
299
|
export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof } from './build-assemble.js';
|
|
299
300
|
export { buildProjectToOutDirRoot } from './project-build.js';
|
|
@@ -304,7 +305,8 @@ export { absoluteUrl, assertLocaleCacheKey, buildLocalePageMeta, buildLocaleRout
|
|
|
304
305
|
export { LOCALE_ROUTE_REALIZATION_ARTIFACT_SCHEMA, emitLocaleRouteRealization } from '../locale/locale-route-emit.js';
|
|
305
306
|
export { assertHostMessageInvariant, assertServerErrorEnvelope, assertServerFormatContext, buildLocaleDeliveryResolution, checkLocaleDelivery, fallbackDigest, messageCatalogHash, proveMiniPackageMessages, validateNativeLocalePack, } from '../locale/locale-delivery.js';
|
|
306
307
|
export { checkLocaleConformance, diffLocaleCatalogs, explainLocaleMessage, extractHardcodedText, pseudoLocalizeCatalog, } from '../locale/locale-tooling.js';
|
|
307
|
-
export { applyPlugins, contentHash,
|
|
308
|
+
export { applyPlugins, contentHash, definePlugin, loadVmzConfig } from './plugin-host.js';
|
|
309
|
+
export { defineConfig } from './user-config.js';
|
|
308
310
|
export { createRolldownPluginVmzAdapter, createVitePluginVmzAdapter, loadDeploymentIr, planAffectedBundleInputs, planBundleInputs, } from './bundler-adapter.js';
|
|
309
311
|
export default {
|
|
310
312
|
HOST_PROTOCOL,
|
|
@@ -9,6 +9,12 @@ export type EmitWebStaticOpts = {
|
|
|
9
9
|
applicationId?: string;
|
|
10
10
|
staticParams?: Record<string, Array<Record<string, string>>>;
|
|
11
11
|
projectRoot?: string;
|
|
12
|
+
/** Assembly recorded in the manifest (`local-static` overrides the static default). */
|
|
13
|
+
deliveryProfile?: string;
|
|
14
|
+
/** Build cancellation signal, forwarded into the SSR `onMount` budget race. */
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
/** Per-instance SSR `onMount` budget in ms (runtime default applies when unset). */
|
|
17
|
+
onMountBudgetMs?: number;
|
|
12
18
|
};
|
|
13
19
|
type StaticDeliveryManifest = {
|
|
14
20
|
schema: string;
|
|
@@ -134,4 +140,28 @@ export declare function emitWebStatic(distDir: string, opts?: EmitWebStaticOpts)
|
|
|
134
140
|
};
|
|
135
141
|
};
|
|
136
142
|
}>;
|
|
143
|
+
/**
|
|
144
|
+
* Write the browser bootstrap modules ahead of the pack stage: `pack` needs the
|
|
145
|
+
* literal dynamic-import tables in `entry-client.js` / `entry-event.js` as graph
|
|
146
|
+
* entries and must run before HTML emit (HTML resolves `_vmz/pack/` URLs). The
|
|
147
|
+
* static emit stage re-runs the same function, so both passes produce identical
|
|
148
|
+
* bytes.
|
|
149
|
+
* @param {string} distDir
|
|
150
|
+
* @returns {string[]} written bootstrap file names
|
|
151
|
+
*/
|
|
152
|
+
export declare function emitStaticBootstrapEntries(distDir: any): string[];
|
|
153
|
+
/**
|
|
154
|
+
* Prune the web-static delivery to its final browser set after HTML emit:
|
|
155
|
+
* remove the Node-only serve-host material (`_vmz/host/`, `vmz-serve-host.mjs`)
|
|
156
|
+
* and every unpacked module JS/map that `_vmz/pack/` chunks supersede
|
|
157
|
+
* (bootstrap entries, page/component/layout units, server faces, `#server/`,
|
|
158
|
+
* `ssr/`). The `/dom.browser.js` face closure stays — the packed navigation
|
|
159
|
+
* keeps that root-URL load by contract. JSON metadata and assets are untouched.
|
|
160
|
+
* Only `vmz serve` re-materializes the host (`materializeServeHostRuntime`);
|
|
161
|
+
* static hosting never needs it.
|
|
162
|
+
*/
|
|
163
|
+
export declare function pruneWebStaticDelivery(outDir: string): {
|
|
164
|
+
removed: number;
|
|
165
|
+
keptFaces: string[];
|
|
166
|
+
};
|
|
137
167
|
export {};
|
|
@@ -6,7 +6,7 @@ import crypto from 'node:crypto';
|
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { pathToFileURL } from 'node:url';
|
|
9
|
-
import { listClientComponentsSync } from '@vmz/core/component-registry';
|
|
9
|
+
import { collectDependsOnClosure, listClientComponentsSync, readDeploymentDocument } from '@vmz/core/component-registry';
|
|
10
10
|
import { createRenderHost } from '@vmz/core/render-host';
|
|
11
11
|
import { resolveRouteLayoutChain } from '@vmz/core/route-layout-chain';
|
|
12
12
|
import { emitCdnPolicy } from './cdn-policy.js';
|
|
@@ -14,6 +14,7 @@ import { emitContentAddressedAssets, hashedAssetHref } from './content-addressed
|
|
|
14
14
|
import { LOCALE_LINK_PLAN_REL } from '../locale/locale-route-emit.js';
|
|
15
15
|
import { absoluteUrl, applyLocaleLinkPlan, buildLocaleLinkPlan, buildLocalePageMeta, linkRouteAliasesFromUnits, } from '../locale/locale-router.js';
|
|
16
16
|
import { requireNativeAddon } from './native-addon.js';
|
|
17
|
+
import { PACK_NODE_MANIFEST_REL, PACK_NODE_OUTPUT_DIR_REL, packEntryHref, packNodeEntryFile } from './pack.js';
|
|
17
18
|
import { writePrettyJsonFile } from './pretty-json.js';
|
|
18
19
|
import { emitPublicStaticAssets } from './public-static-assets.js';
|
|
19
20
|
import { emitRouteCatalog, loadRouteCatalog, ROUTE_CATALOG_SCHEMA } from './route-catalog-emit.js';
|
|
@@ -23,6 +24,7 @@ export const STATIC_EMIT_PLAN_SCHEMA = 'vmz.static.emit_plan.v0';
|
|
|
23
24
|
export async function emitWebStatic(distDir, opts = {}) {
|
|
24
25
|
const origin = String(opts.origin || process.env.VMZ_SITE_ORIGIN || 'https://example.test').replace(/\/$/, '');
|
|
25
26
|
const applicationId = opts.applicationId || path.basename(path.dirname(distDir));
|
|
27
|
+
const deliveryProfile = String(opts.deliveryProfile || 'static');
|
|
26
28
|
const domPath = path.join(distDir, 'vmz-dom.js');
|
|
27
29
|
if (!fs.existsSync(domPath)) {
|
|
28
30
|
throw new Error(`emitWebStatic: missing ${domPath} — run vmz build first`);
|
|
@@ -32,6 +34,9 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
32
34
|
const publicAssets = emitPublicStaticAssets(distDir, { projectRoot: opts.projectRoot });
|
|
33
35
|
const host = await createRenderHost(distDir, { strictDeployment: true, preload: 'none' });
|
|
34
36
|
const { renderToString, renderToStream } = host;
|
|
37
|
+
// One budget/signal pair for every SSR render of this build: a hung or
|
|
38
|
+
// aborted `onMount` fails the page build instead of stalling it.
|
|
39
|
+
const renderOpts = { signal: opts.signal ?? undefined, onMountBudgetMs: opts.onMountBudgetMs };
|
|
35
40
|
const pageCatalog = listPageClientFiles(distDir);
|
|
36
41
|
const generations = [];
|
|
37
42
|
const skipped = [];
|
|
@@ -41,7 +46,9 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
41
46
|
const assets = emitContentAddressedAssets(distDir);
|
|
42
47
|
const cssLogical = readCssEntry(distDir);
|
|
43
48
|
const cssEntry = hashedAssetHref(assets.rewrites, cssLogical) || hashedAssetHref(assets.rewrites, 'vmz.css');
|
|
44
|
-
|
|
49
|
+
// Packed browser JS is final-named under `_vmz/pack/` — resolve via the pack
|
|
50
|
+
// manifest entryFiles mapping; unpacked root bytes are never a fallback.
|
|
51
|
+
const moduleScriptSrc = packEntryHref(distDir, 'entry-client.js');
|
|
45
52
|
const localeArt = loadLocaleArtifact(distDir);
|
|
46
53
|
const localeLinkPlan = loadLocaleLinkPlan(distDir) || buildLocaleLinkPlan(withLinkRouteAliases(localeArt, distDir, pageCatalog));
|
|
47
54
|
for (const page of pageCatalog) {
|
|
@@ -99,14 +106,23 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
99
106
|
const layoutChain = resolveRouteLayoutChain(distDir, page.chunkId);
|
|
100
107
|
await host.ensureComponents([page.chunkId, ...layoutChain]);
|
|
101
108
|
let bodyHtml = '';
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
try {
|
|
110
|
+
for await (const chunk of renderToStream(Page, props, renderOpts)) {
|
|
111
|
+
bodyHtml += chunk;
|
|
112
|
+
}
|
|
113
|
+
for (let i = layoutChain.length - 1; i >= 0; i--) {
|
|
114
|
+
const Layout = await loadCtor(distDir, layoutChain[i]);
|
|
115
|
+
if (!Layout)
|
|
116
|
+
continue;
|
|
117
|
+
bodyHtml = await renderToString(Layout, {}, { ...renderOpts, slotHtml: bodyHtml });
|
|
118
|
+
}
|
|
104
119
|
}
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
120
|
+
catch (err) {
|
|
121
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
122
|
+
throw new Error(`emitWebStatic: SSR render failed for route ${pattern} (${page.chunkId}): ${detail}`, { cause: err });
|
|
123
|
+
}
|
|
124
|
+
if (opts.signal?.aborted) {
|
|
125
|
+
throw new Error(`emitWebStatic: build aborted during SSR render for route ${pattern} (${page.chunkId})`);
|
|
110
126
|
}
|
|
111
127
|
const localeWrites = expandLocaleStaticGenerations({
|
|
112
128
|
localeArt,
|
|
@@ -188,7 +204,7 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
188
204
|
const manifest = {
|
|
189
205
|
schema: STATIC_DELIVERY_MANIFEST_SCHEMA,
|
|
190
206
|
applicationId,
|
|
191
|
-
deliveryProfile
|
|
207
|
+
deliveryProfile,
|
|
192
208
|
origin,
|
|
193
209
|
generatedAt: new Date().toISOString(),
|
|
194
210
|
spaFallback: false,
|
|
@@ -232,7 +248,7 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
232
248
|
writePrettyJsonFile(path.join(vmzDir, 'static-emit-plan.json'), {
|
|
233
249
|
schema: STATIC_EMIT_PLAN_SCHEMA,
|
|
234
250
|
applicationId,
|
|
235
|
-
deliveryProfile
|
|
251
|
+
deliveryProfile,
|
|
236
252
|
origin,
|
|
237
253
|
localeLinks: localeLinkPlan,
|
|
238
254
|
assetPlanPath: '_vmz/asset-plan.json',
|
|
@@ -331,8 +347,11 @@ function htmlPathForRoute(pathname) {
|
|
|
331
347
|
* @param {string} chunkId
|
|
332
348
|
*/
|
|
333
349
|
async function loadCtor(distDir, chunkId) {
|
|
334
|
-
|
|
335
|
-
|
|
350
|
+
// Node chunk identity comes from `_vmz/pack-node-manifest.json`; the
|
|
351
|
+
// unpacked root `${chunkId}.client.js` is not a fallback. No `?t=` cache
|
|
352
|
+
// bust: packed chunks are shared instance URLs.
|
|
353
|
+
const href = pathToFileURL(packNodeEntryFile(distDir, chunkId)).href;
|
|
354
|
+
const mod = await import(href);
|
|
336
355
|
return mod.default;
|
|
337
356
|
}
|
|
338
357
|
/**
|
|
@@ -559,9 +578,14 @@ function buildSitemap(_origin, generations) {
|
|
|
559
578
|
return native.generateSitemapXml(urls);
|
|
560
579
|
}
|
|
561
580
|
/**
|
|
562
|
-
* Static CDN must ship entry-client/event like serve-host
|
|
581
|
+
* Static CDN must ship entry-client/event like serve-host. The bootstrap tables
|
|
582
|
+
* are literal dynamic-import maps: page/layout units are keyed by chunkId
|
|
583
|
+
* (`data-vmz-page` / `data-vmz-layout` lookups) and islands are enumerated
|
|
584
|
+
* explicitly — unknown names throw at runtime by design, never via fallback
|
|
585
|
+
* specifier concatenation.
|
|
563
586
|
* @param {string} distDir
|
|
564
587
|
* @param {Array<{ chunkId: string }>} pageCatalog
|
|
588
|
+
* @returns {string[]} written bootstrap file names
|
|
565
589
|
*/
|
|
566
590
|
function emitStaticClientEntries(distDir, pageCatalog) {
|
|
567
591
|
const componentEntries = listClientComponentsSync(distDir, { strict: true });
|
|
@@ -571,16 +595,74 @@ function emitStaticClientEntries(distDir, pageCatalog) {
|
|
|
571
595
|
.filter((e) => isEventResumeStrategy(e.strategy))
|
|
572
596
|
.map((e) => e.component)
|
|
573
597
|
.filter(Boolean));
|
|
574
|
-
|
|
575
|
-
|
|
598
|
+
// Pages/layouts resolve `<chunkId>.client.js` at the dist root (SSR loadCtor
|
|
599
|
+
// uses the same path); they must be in the table or hydration throws.
|
|
600
|
+
const pageEntries = pageCatalog.map((p) => ({ name: p.chunkId, entry: `${p.chunkId}.client.js` }));
|
|
601
|
+
const layoutNames = new Set();
|
|
602
|
+
for (const page of pageCatalog) {
|
|
603
|
+
for (const id of resolveRouteLayoutChain(distDir, page.chunkId))
|
|
604
|
+
layoutNames.add(String(id));
|
|
605
|
+
}
|
|
606
|
+
const layoutEntries = [...layoutNames].sort().map((id) => ({ name: id, entry: `${id}.client.js` }));
|
|
607
|
+
// 引导表只登记从页面/布局可达的组件:部署 IR 的 `dependsOn` 闭包之外的
|
|
608
|
+
// 组件没有任何模板引用,进入表只会变成 pack 死字节;不登记后 pack 图
|
|
609
|
+
// 不可达,prune 同时清掉未打包的散落模块。
|
|
610
|
+
const deployment = readDeploymentDocument(distDir, { strict: true });
|
|
611
|
+
const closure = collectDependsOnClosure(deployment, [...pageCatalog.map((p) => p.chunkId), ...layoutNames]);
|
|
612
|
+
const reachableComponents = componentEntries.filter((e) => closure.has(e.chunkId));
|
|
613
|
+
const eagerComponents = reachableComponents.filter((e) => !lazySet.has(e.name));
|
|
614
|
+
const lazyComponents = reachableComponents.filter((e) => lazySet.has(e.name));
|
|
615
|
+
const eager = [...eagerComponents, ...pageEntries, ...layoutEntries];
|
|
576
616
|
const native = requireNativeAddon();
|
|
577
617
|
if (typeof native.generateServeEntryClient !== 'function') {
|
|
578
618
|
throw new Error('vmz native addon missing generateServeEntryClient — rebuild with `pnpm napi:build`');
|
|
579
619
|
}
|
|
580
|
-
|
|
620
|
+
const written = ['entry-client.js'];
|
|
621
|
+
fs.writeFileSync(path.join(distDir, 'entry-client.js'), native.generateServeEntryClient(eager, lazyComponents, ''), 'utf8');
|
|
581
622
|
if (typeof native.generateServeEntryEvent === 'function') {
|
|
582
|
-
|
|
623
|
+
// Event shell islands: event-strategy components + document islands whose
|
|
624
|
+
// compiled module exists in the component set (explicit enumeration).
|
|
625
|
+
const islandNames = readDocumentIslandNames(distDir);
|
|
626
|
+
const islands = [...lazyComponents];
|
|
627
|
+
for (const entry of eagerComponents) {
|
|
628
|
+
if (islandNames.has(entry.name))
|
|
629
|
+
islands.push(entry);
|
|
630
|
+
}
|
|
631
|
+
fs.writeFileSync(path.join(distDir, 'entry-event.js'), native.generateServeEntryEvent([], islands, ''), 'utf8');
|
|
632
|
+
written.push('entry-event.js');
|
|
583
633
|
}
|
|
634
|
+
return written;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Write the browser bootstrap modules ahead of the pack stage: `pack` needs the
|
|
638
|
+
* literal dynamic-import tables in `entry-client.js` / `entry-event.js` as graph
|
|
639
|
+
* entries and must run before HTML emit (HTML resolves `_vmz/pack/` URLs). The
|
|
640
|
+
* static emit stage re-runs the same function, so both passes produce identical
|
|
641
|
+
* bytes.
|
|
642
|
+
* @param {string} distDir
|
|
643
|
+
* @returns {string[]} written bootstrap file names
|
|
644
|
+
*/
|
|
645
|
+
export function emitStaticBootstrapEntries(distDir) {
|
|
646
|
+
return emitStaticClientEntries(distDir, listPageClientFiles(distDir));
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Island names from an integrated document surface (`document.islands.json`,
|
|
650
|
+
* written by the document build into the same dist). Absent file → no islands.
|
|
651
|
+
* @param {string} distDir
|
|
652
|
+
*/
|
|
653
|
+
function readDocumentIslandNames(distDir) {
|
|
654
|
+
const names = new Set();
|
|
655
|
+
try {
|
|
656
|
+
const plan = JSON.parse(fs.readFileSync(path.join(distDir, 'document.islands.json'), 'utf8'));
|
|
657
|
+
for (const island of plan?.islands || []) {
|
|
658
|
+
if (typeof island?.name === 'string' && island.name)
|
|
659
|
+
names.add(island.name);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
catch {
|
|
663
|
+
/* no document surface */
|
|
664
|
+
}
|
|
665
|
+
return names;
|
|
584
666
|
}
|
|
585
667
|
/**
|
|
586
668
|
* @param {string} distDir
|
|
@@ -605,3 +687,114 @@ function loadPageResumeEntriesSync(distDir, chunkId) {
|
|
|
605
687
|
function isEventResumeStrategy(strategy) {
|
|
606
688
|
return strategy === 'event' || strategy === 'click' || String(strategy).startsWith('event:');
|
|
607
689
|
}
|
|
690
|
+
/** Runtime face barrel loaded by URL (`import('/dom.browser.js')`) in the packed client navigation. */
|
|
691
|
+
const FACE_ENTRY_REL = 'dom.browser.js';
|
|
692
|
+
/**
|
|
693
|
+
* Transitive closure of the URL-loaded browser face: start at `dom.browser.js`
|
|
694
|
+
* and follow relative import specifiers that resolve to files in the dist tree.
|
|
695
|
+
* Everything else that is executable JS is either packed into `_vmz/pack/` or
|
|
696
|
+
* Node-side, so it must not ship in a web-static delivery.
|
|
697
|
+
*/
|
|
698
|
+
function collectFaceClosure(abs) {
|
|
699
|
+
const closure = new Set();
|
|
700
|
+
if (!fs.existsSync(path.join(abs, FACE_ENTRY_REL)))
|
|
701
|
+
return closure;
|
|
702
|
+
const queue = [FACE_ENTRY_REL];
|
|
703
|
+
while (queue.length) {
|
|
704
|
+
const rel = queue.shift();
|
|
705
|
+
if (closure.has(rel))
|
|
706
|
+
continue;
|
|
707
|
+
closure.add(rel);
|
|
708
|
+
let text;
|
|
709
|
+
try {
|
|
710
|
+
text = fs.readFileSync(path.join(abs, ...rel.split('/')), 'utf8');
|
|
711
|
+
}
|
|
712
|
+
catch {
|
|
713
|
+
continue;
|
|
714
|
+
}
|
|
715
|
+
const specs = [
|
|
716
|
+
...text.matchAll(/from\s+['"](\.[^'"]+)['"]/g),
|
|
717
|
+
...text.matchAll(/import\(\s*['"](\.[^'"]+)['"]/g),
|
|
718
|
+
];
|
|
719
|
+
for (const m of specs) {
|
|
720
|
+
const next = path.posix.normalize(`${path.posix.dirname(rel)}/${m[1]}`);
|
|
721
|
+
if (next.startsWith('..'))
|
|
722
|
+
continue;
|
|
723
|
+
if (!fs.existsSync(path.join(abs, ...next.split('/'))))
|
|
724
|
+
continue;
|
|
725
|
+
if (!closure.has(next))
|
|
726
|
+
queue.push(next);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
return closure;
|
|
730
|
+
}
|
|
731
|
+
function listFilesRecursive(abs, rel = '') {
|
|
732
|
+
const out = [];
|
|
733
|
+
for (const entry of fs.readdirSync(path.join(abs, ...rel.split('/')), { withFileTypes: true })) {
|
|
734
|
+
const nextRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
735
|
+
if (entry.isDirectory())
|
|
736
|
+
out.push(...listFilesRecursive(abs, nextRel));
|
|
737
|
+
else if (entry.isFile())
|
|
738
|
+
out.push(nextRel);
|
|
739
|
+
}
|
|
740
|
+
return out;
|
|
741
|
+
}
|
|
742
|
+
function removeEmptyDirsBottomUp(abs, rel = '') {
|
|
743
|
+
for (const entry of fs.readdirSync(path.join(abs, ...rel.split('/')), { withFileTypes: true })) {
|
|
744
|
+
if (!entry.isDirectory())
|
|
745
|
+
continue;
|
|
746
|
+
const nextRel = rel ? `${rel}/${entry.name}` : entry.name;
|
|
747
|
+
if (nextRel === '_vmz/pack' || nextRel.startsWith('_vmz/pack/'))
|
|
748
|
+
continue;
|
|
749
|
+
removeEmptyDirsBottomUp(abs, nextRel);
|
|
750
|
+
if (nextRel === '_vmz')
|
|
751
|
+
continue;
|
|
752
|
+
if (fs.readdirSync(path.join(abs, ...nextRel.split('/'))).length === 0) {
|
|
753
|
+
fs.rmdirSync(path.join(abs, ...nextRel.split('/')));
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* Prune the web-static delivery to its final browser set after HTML emit:
|
|
759
|
+
* remove the Node-only serve-host material (`_vmz/host/`, `vmz-serve-host.mjs`)
|
|
760
|
+
* and every unpacked module JS/map that `_vmz/pack/` chunks supersede
|
|
761
|
+
* (bootstrap entries, page/component/layout units, server faces, `#server/`,
|
|
762
|
+
* `ssr/`). The `/dom.browser.js` face closure stays — the packed navigation
|
|
763
|
+
* keeps that root-URL load by contract. JSON metadata and assets are untouched.
|
|
764
|
+
* Only `vmz serve` re-materializes the host (`materializeServeHostRuntime`);
|
|
765
|
+
* static hosting never needs it.
|
|
766
|
+
*/
|
|
767
|
+
export function pruneWebStaticDelivery(outDir) {
|
|
768
|
+
const abs = path.resolve(outDir);
|
|
769
|
+
if (!fs.existsSync(abs))
|
|
770
|
+
throw new Error(`pruneWebStaticDelivery: missing dist ${abs}`);
|
|
771
|
+
const faceClosure = collectFaceClosure(abs);
|
|
772
|
+
let removed = 0;
|
|
773
|
+
for (const rel of listFilesRecursive(abs)) {
|
|
774
|
+
if (rel.startsWith('_vmz/pack/') || rel.startsWith('assets/'))
|
|
775
|
+
continue;
|
|
776
|
+
const isHost = rel.startsWith('_vmz/host/');
|
|
777
|
+
const isJs = rel.endsWith('.js') || rel.endsWith('.mjs') || rel.endsWith('.map');
|
|
778
|
+
if (!isHost && (!isJs || faceClosure.has(rel)))
|
|
779
|
+
continue;
|
|
780
|
+
fs.rmSync(path.join(abs, ...rel.split('/')), { force: true });
|
|
781
|
+
removed++;
|
|
782
|
+
}
|
|
783
|
+
// Node pack 是构建期产物:静态托管不会执行它,浏览器集已由 `_vmz/pack/`
|
|
784
|
+
// 定型。这里显式清掉 Node chunk 目录与 manifest,避免把服务端字节一起交付。
|
|
785
|
+
const nodePackDir = path.join(abs, ...PACK_NODE_OUTPUT_DIR_REL.split('/'));
|
|
786
|
+
if (fs.existsSync(nodePackDir)) {
|
|
787
|
+
for (const entry of fs.readdirSync(nodePackDir, { recursive: true, withFileTypes: true })) {
|
|
788
|
+
if (entry.isFile())
|
|
789
|
+
removed++;
|
|
790
|
+
}
|
|
791
|
+
fs.rmSync(nodePackDir, { recursive: true, force: true });
|
|
792
|
+
}
|
|
793
|
+
const nodeManifestPath = path.join(abs, ...PACK_NODE_MANIFEST_REL.split('/'));
|
|
794
|
+
if (fs.existsSync(nodeManifestPath)) {
|
|
795
|
+
fs.rmSync(nodeManifestPath, { force: true });
|
|
796
|
+
removed++;
|
|
797
|
+
}
|
|
798
|
+
removeEmptyDirsBottomUp(abs);
|
|
799
|
+
return { removed, keptFaces: [...faceClosure].sort() };
|
|
800
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application authoring config surface — `defineConfig` + `VmzUserConfig`.
|
|
3
|
+
*
|
|
4
|
+
* Ownership: the application config entry belongs to the `vmz` package (CLI /
|
|
5
|
+
* workspace host). `@vmz/plugin` keeps the plugin author surface (`definePlugin`,
|
|
6
|
+
* protocol types). Plugin-facing types (`VmzPlugin`, `VmzEngines`) stay in
|
|
7
|
+
* `@vmz/plugin` and are referenced here by type import only.
|
|
8
|
+
*/
|
|
9
|
+
import type { VmzEngines, VmzPlugin } from '@vmz/plugin';
|
|
10
|
+
/**
|
|
11
|
+
* Format options (`vmz format` reads `vmz.config` `format`).
|
|
12
|
+
*
|
|
13
|
+
* Scope is always the explicit CLI path; config can only narrow it. There is
|
|
14
|
+
* no `includes` / language toggle here — `vmz format <path>` formats the
|
|
15
|
+
* given file or directory and nothing else.
|
|
16
|
+
*/
|
|
17
|
+
export interface VmzFormatConfig {
|
|
18
|
+
/** Skip paths under these globs inside an explicit directory target. */
|
|
19
|
+
excludes?: string[];
|
|
20
|
+
/** Biome-style formatter config (default: `biome.json` at project root). */
|
|
21
|
+
style?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface VmzUserConfig {
|
|
24
|
+
plugins?: Array<string | VmzPlugin | Promise<VmzPlugin>>;
|
|
25
|
+
engines?: VmzEngines;
|
|
26
|
+
/** Format excludes / style (`vmz format` scope is the explicit CLI path). */
|
|
27
|
+
format?: VmzFormatConfig;
|
|
28
|
+
/** Application identity (optional authoring). */
|
|
29
|
+
application?: {
|
|
30
|
+
id?: string;
|
|
31
|
+
[key: string]: unknown;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Delivery: named profiles (`default` + `profiles`) or legacy site sugar.
|
|
35
|
+
* Pure data only; never a parallel `vmz.site.ts` entry.
|
|
36
|
+
*/
|
|
37
|
+
delivery?: DeliveryAuthoring;
|
|
38
|
+
}
|
|
39
|
+
/** Site resource sources (embedded | filesystem | remote) — orthogonal to assembly. */
|
|
40
|
+
export interface SiteDeliveryAuthoring {
|
|
41
|
+
artifact: string;
|
|
42
|
+
siteId?: string;
|
|
43
|
+
sources: Array<{
|
|
44
|
+
id: string;
|
|
45
|
+
kind: 'embedded' | 'filesystem' | 'remote';
|
|
46
|
+
directory?: string;
|
|
47
|
+
baseUrl?: string;
|
|
48
|
+
artifact?: string;
|
|
49
|
+
trust?: string;
|
|
50
|
+
timeoutMs?: number;
|
|
51
|
+
priority?: number;
|
|
52
|
+
integrity?: unknown;
|
|
53
|
+
signaturePolicy?: string;
|
|
54
|
+
}>;
|
|
55
|
+
resolution?: {
|
|
56
|
+
mode?: 'release';
|
|
57
|
+
fallback?: string[];
|
|
58
|
+
};
|
|
59
|
+
activation?: 'atomic';
|
|
60
|
+
expectedCompatibility?: unknown;
|
|
61
|
+
failure?: unknown;
|
|
62
|
+
failurePolicy?: unknown;
|
|
63
|
+
update?: unknown;
|
|
64
|
+
updatePolicy?: unknown;
|
|
65
|
+
rollback?: unknown;
|
|
66
|
+
rollbackPolicy?: unknown;
|
|
67
|
+
security?: unknown;
|
|
68
|
+
securityPolicy?: unknown;
|
|
69
|
+
}
|
|
70
|
+
export type DeliveryAssembly = 'local-static' | 'web-static' | 'server-host' | 'cdn+server' | 'rust-embedded';
|
|
71
|
+
export type DeliveryServerRuntime = 'node' | 'worker' | 'deno' | 'bun' | 'rust-host';
|
|
72
|
+
export interface DeliveryProfileAuthoring {
|
|
73
|
+
host?: 'browser';
|
|
74
|
+
assembly: DeliveryAssembly;
|
|
75
|
+
/**
|
|
76
|
+
* Artifact directory under CLI `--out-dir` (default = profile id).
|
|
77
|
+
* Example: profile `static` + `name: 'cdn'` → `dist/cdn`.
|
|
78
|
+
*/
|
|
79
|
+
name?: string;
|
|
80
|
+
serverRuntime?: DeliveryServerRuntime;
|
|
81
|
+
/** Inline site sources or `defineSite({...})`. */
|
|
82
|
+
sources?: SiteDeliveryAuthoring | SiteDeliveryAuthoring['sources'];
|
|
83
|
+
artifact?: string;
|
|
84
|
+
resolution?: SiteDeliveryAuthoring['resolution'];
|
|
85
|
+
activation?: SiteDeliveryAuthoring['activation'];
|
|
86
|
+
}
|
|
87
|
+
/** WeChat DevTools project identity. Pure data; not WeChat JSON / wx.* APIs. */
|
|
88
|
+
export interface WechatPackagingAuthoring {
|
|
89
|
+
/** Registered AppID. Omit for WeChat tourist mode (`touristappid`). */
|
|
90
|
+
appId?: string;
|
|
91
|
+
projectName?: string;
|
|
92
|
+
/** `app.json` `window.navigationBarTitleText`. */
|
|
93
|
+
title?: string;
|
|
94
|
+
}
|
|
95
|
+
/** Vendor packaging identity under `defineConfig({ delivery })`. */
|
|
96
|
+
export interface DeliveryPackagingAuthoring {
|
|
97
|
+
wechat?: WechatPackagingAuthoring;
|
|
98
|
+
}
|
|
99
|
+
/** Named profiles (preferred) or legacy site-only sugar. */
|
|
100
|
+
export type DeliveryAuthoring = {
|
|
101
|
+
default?: string;
|
|
102
|
+
profiles: Record<string, DeliveryProfileAuthoring>;
|
|
103
|
+
packaging?: DeliveryPackagingAuthoring;
|
|
104
|
+
} | (SiteDeliveryAuthoring & {
|
|
105
|
+
default?: string;
|
|
106
|
+
assembly?: DeliveryAssembly;
|
|
107
|
+
host?: 'browser';
|
|
108
|
+
serverRuntime?: DeliveryServerRuntime;
|
|
109
|
+
packaging?: DeliveryPackagingAuthoring;
|
|
110
|
+
});
|
|
111
|
+
/** Identity helper for `vmz.config.ts` inference. */
|
|
112
|
+
export declare function defineConfig(config: VmzUserConfig): VmzUserConfig;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application authoring config surface — `defineConfig` + `VmzUserConfig`.
|
|
3
|
+
*
|
|
4
|
+
* Ownership: the application config entry belongs to the `vmz` package (CLI /
|
|
5
|
+
* workspace host). `@vmz/plugin` keeps the plugin author surface (`definePlugin`,
|
|
6
|
+
* protocol types). Plugin-facing types (`VmzPlugin`, `VmzEngines`) stay in
|
|
7
|
+
* `@vmz/plugin` and are referenced here by type import only.
|
|
8
|
+
*/
|
|
9
|
+
/** Identity helper for `vmz.config.ts` inference. */
|
|
10
|
+
export function defineConfig(config) {
|
|
11
|
+
return config ?? {};
|
|
12
|
+
}
|
package/host-runtime-files.json
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
{ "src": "host/serve/hmr-dev.js", "out": "_vmz/host/serve/hmr-dev.js", "rewriteVmzRuntimeImport": true },
|
|
15
15
|
{ "src": "host/serve/page-render.js", "out": "_vmz/host/serve/page-render.js", "rewriteVmzRuntimeImport": true },
|
|
16
16
|
{ "src": "host/serve/page-catalog.js", "out": "_vmz/host/serve/page-catalog.js" },
|
|
17
|
+
{ "src": "host/serve/pack-entry.js", "out": "_vmz/host/serve/pack-entry.js" },
|
|
17
18
|
{ "src": "host/serve/locale-theme.js", "out": "_vmz/host/serve/locale-theme.js" },
|
|
18
19
|
{ "src": "host/serve/constants.js", "out": "_vmz/host/serve/constants.js" },
|
|
19
20
|
{ "src": "host/serve/route-catalog.js", "out": "_vmz/host/serve/route-catalog.js" },
|
package/locales/en-US/cli.json
CHANGED
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
"cli.cmd.build": "Build project via Workspace",
|
|
6
6
|
"cli.cmd.serve": "Serve dist (optional --build)",
|
|
7
7
|
"cli.cmd.dev": "Rebuild session",
|
|
8
|
-
"cli.cmd.format": "Format
|
|
9
|
-
"cli.opt.format-
|
|
10
|
-
"cli.opt.format-no-
|
|
11
|
-
"cli.opt.format-no-
|
|
8
|
+
"cli.cmd.format": "Format an explicit file/directory path (JS/TS, .vmz, .rs with --rust)",
|
|
9
|
+
"cli.opt.format-rust": "Also format .rs files under a directory target via rustfmt",
|
|
10
|
+
"cli.opt.format-no-javascript": "Reject JS/TS targets",
|
|
11
|
+
"cli.opt.format-no-rust": "Reject .rs targets",
|
|
12
|
+
"cli.opt.format-no-vmz": "Skip .vmz targets",
|
|
12
13
|
"cli.cmd.lint": "Lint (= check) via N-API",
|
|
13
14
|
"cli.cmd.test": "Native test discover / report",
|
|
14
15
|
"cli.cmd.document": "Project /documents domain",
|
package/locales/en-US/diag.json
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
"vmz::template::illegal_directive": "Illegal or unsupported directive in `<template>`: {detail}",
|
|
11
11
|
"vmz::template::parse_failed": "Failed to parse `<template>`: {detail}",
|
|
12
12
|
"vmz::template::invalid_expr": "Invalid template expression: {detail}",
|
|
13
|
+
"vmz::template::v_model_invalid_target": "`v-model` target must be an assignable identifier or member expression: `{expr}`",
|
|
14
|
+
"vmz::template::v_model_on_file_input": "`v-model` cannot bind an `<input type=\"file\">`",
|
|
13
15
|
"vmz::template::each_missing_key": "`v-for` on `<{tag}>` should declare a `:key`",
|
|
14
16
|
"vmz::template::each_static_key": "`v-for` on `<{tag}>` must not use a static key `{key}`",
|
|
15
17
|
"vmz::template::each_literal_key": "`v-for` on `<{tag}>` must not use a literal key `{key}`",
|