@vmz/vmz 0.1.20 → 0.1.22
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/dev-session.js +121 -3
- package/dist/document-integrate.js +8 -0
- package/dist/index.js +1 -0
- package/dist/locale-check.d.ts +13 -0
- package/dist/locale-check.js +69 -3
- package/dist/locale-router.d.ts +3 -11
- package/dist/locale-router.js +2 -52
- package/dist/log.js +4 -2
- package/dist/pack.js +1 -1
- package/dist/plugin-host.js +16 -12
- package/dist/route-path.d.ts +2 -2
- package/dist/route-path.js +7 -5
- package/dist/server-artifact.d.ts +5 -53
- package/dist/server-artifact.js +28 -167
- package/dist/static-emit.js +12 -40
- package/locales/en-US/cli.json +1 -2
- package/locales/en-US/diag.json +154 -0
- package/locales/locales.json +4 -1
- package/locales/zh-CN/diag.json +154 -0
- package/package.json +14 -14
package/dist/server-artifact.js
CHANGED
|
@@ -1,109 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* P4 ServerArtifact —
|
|
3
|
-
*
|
|
2
|
+
* P4 ServerArtifact — thin host write of Rust/N-API normalized Plan.
|
|
3
|
+
* Assembly / digests / adapters live in vmz-artifacts via N-API.
|
|
4
4
|
*/
|
|
5
|
-
import crypto from 'node:crypto';
|
|
6
5
|
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
7
6
|
import path from 'node:path';
|
|
8
|
-
import {
|
|
7
|
+
import { requireNativeAddon } from './native-addon.js';
|
|
9
8
|
import { writePrettyJsonFile } from './pretty-json.js';
|
|
10
9
|
export const SERVER_ARTIFACT_SCHEMA = 'vmz.server.artifact.v0';
|
|
11
10
|
export const HTTP_CONTRACT_SCHEMA = 'vmz.http.contract.v0';
|
|
12
11
|
export const SERVER_RUNTIME_ADAPTER_SCHEMA = 'vmz.server.runtime_adapter.v0';
|
|
13
|
-
const DEFAULT_RPC_PATH = '/__vmz/rpc';
|
|
14
12
|
export function emitServerArtifact(outDir, opts = {}) {
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
})
|
|
29
|
-
const
|
|
30
|
-
/** @type {Array<Record<string, unknown>>} */
|
|
31
|
-
const internalCapabilities = [];
|
|
32
|
-
for (const u of units) {
|
|
33
|
-
const moduleId = u.serverModuleId != null ? String(u.serverModuleId) : '';
|
|
34
|
-
if (!moduleId)
|
|
35
|
-
continue;
|
|
36
|
-
const caps = Array.isArray(u.capabilities) ? u.capabilities.map(String) : [];
|
|
37
|
-
for (const method of caps) {
|
|
38
|
-
const key = `${moduleId}::${method}`;
|
|
39
|
-
if (publicKeys.has(key))
|
|
40
|
-
continue;
|
|
41
|
-
internalCapabilities.push({
|
|
42
|
-
chunkId: String(u.chunkId || ''),
|
|
43
|
-
moduleId,
|
|
44
|
-
method,
|
|
45
|
-
visibility: 'internal',
|
|
46
|
-
kind: 'capability',
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
const routeDecisionTree = [
|
|
51
|
-
{
|
|
52
|
-
id: 'rpc',
|
|
53
|
-
match: { method: 'POST', path: DEFAULT_RPC_PATH },
|
|
54
|
-
action: 'invoke-rpc',
|
|
55
|
-
visibility: 'internal-transport',
|
|
56
|
-
},
|
|
57
|
-
...publicRoutes.map((r, i) => ({
|
|
58
|
-
id: `public-route-${i}`,
|
|
59
|
-
match: { method: r.verb, path: r.path },
|
|
60
|
-
action: 'invoke-server-route',
|
|
61
|
-
target: { moduleId: r.moduleId, method: r.method },
|
|
62
|
-
visibility: 'public',
|
|
63
|
-
})),
|
|
64
|
-
];
|
|
65
|
-
const httpContractBody = {
|
|
66
|
-
schema: HTTP_CONTRACT_SCHEMA,
|
|
67
|
-
rpcPath: DEFAULT_RPC_PATH,
|
|
68
|
-
publicRoutes: publicRoutes.map((r) => ({
|
|
69
|
-
verb: r.verb,
|
|
70
|
-
path: r.path,
|
|
71
|
-
moduleId: r.moduleId,
|
|
72
|
-
method: r.method,
|
|
73
|
-
})),
|
|
74
|
-
internalCapabilityCount: internalCapabilities.length,
|
|
75
|
-
entry: 'fetch',
|
|
76
|
-
};
|
|
77
|
-
const httpContractDigest = sha256Hex(canonicalJson(httpContractBody));
|
|
78
|
-
const artifact = {
|
|
79
|
-
schema: SERVER_ARTIFACT_SCHEMA,
|
|
80
|
-
profileId: opts.profileId || null,
|
|
81
|
-
assembly: opts.assembly || null,
|
|
82
|
-
selectedRuntime,
|
|
83
|
-
entry: {
|
|
84
|
-
kind: 'fetch',
|
|
85
|
-
standards: ['Request', 'Response', 'Streams', 'AbortSignal'],
|
|
86
|
-
rpcPath: DEFAULT_RPC_PATH,
|
|
87
|
-
},
|
|
88
|
-
httpContract: {
|
|
89
|
-
schema: HTTP_CONTRACT_SCHEMA,
|
|
90
|
-
digest: httpContractDigest,
|
|
91
|
-
},
|
|
92
|
-
publicRoutes,
|
|
93
|
-
internalCapabilities,
|
|
94
|
-
middlewareUnits: [],
|
|
95
|
-
routeDecisionTree,
|
|
96
|
-
deploymentSchema: deployment.schema || null,
|
|
97
|
-
packDigest: opts.packDigest || null,
|
|
98
|
-
adapters: {
|
|
99
|
-
node: { kind: 'node-http', status: 'runtime', entry: 'handleNodeRequest' },
|
|
100
|
-
worker: { kind: 'fetch', status: 'runtime', entry: 'handleFetchRequest' },
|
|
101
|
-
deno: { kind: 'fetch', status: 'projected', entry: 'handleFetchRequest' },
|
|
102
|
-
bun: { kind: 'fetch', status: 'projected', entry: 'handleFetchRequest' },
|
|
103
|
-
'rust-host': { kind: 'contract-projection', status: 'projected', entry: 'fetch' },
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
artifact.artifactDigest = sha256Hex(canonicalJson({ ...artifact, artifactDigest: undefined }));
|
|
13
|
+
const deploymentPath = path.join(outDir, 'vmz-deployment.json');
|
|
14
|
+
const routesPath = path.join(outDir, 'vmz-routes.json');
|
|
15
|
+
const deploymentJson = existsSync(deploymentPath) ? readFileSync(deploymentPath, 'utf8') : '{}';
|
|
16
|
+
const routesJson = existsSync(routesPath) ? readFileSync(routesPath, 'utf8') : '[]';
|
|
17
|
+
const native = requireNativeAddon();
|
|
18
|
+
if (typeof native.normalizeServerArtifactJson !== 'function') {
|
|
19
|
+
throw new Error('vmz native addon missing normalizeServerArtifactJson — rebuild with `pnpm napi:build`');
|
|
20
|
+
}
|
|
21
|
+
const artifactJson = native.normalizeServerArtifactJson(deploymentJson, routesJson, {
|
|
22
|
+
profileId: opts.profileId ?? null,
|
|
23
|
+
assembly: opts.assembly ?? null,
|
|
24
|
+
serverRuntime: opts.serverRuntime ?? null,
|
|
25
|
+
packDigest: opts.packDigest ?? null,
|
|
26
|
+
});
|
|
27
|
+
const artifact = JSON.parse(artifactJson);
|
|
107
28
|
const vmzDir = path.join(outDir, '_vmz');
|
|
108
29
|
mkdirSync(vmzDir, { recursive: true });
|
|
109
30
|
const file = path.join(vmzDir, 'server-artifact.json');
|
|
@@ -116,79 +37,19 @@ export function emitServerArtifact(outDir, opts = {}) {
|
|
|
116
37
|
mkdirSync(dir, { recursive: true });
|
|
117
38
|
writePrettyJsonFile(path.join(dir, 'adapter.json'), projection);
|
|
118
39
|
}
|
|
119
|
-
return {
|
|
40
|
+
return {
|
|
41
|
+
artifact,
|
|
42
|
+
path: file,
|
|
43
|
+
httpContractDigest: artifact.httpContract?.digest || null,
|
|
44
|
+
};
|
|
120
45
|
}
|
|
121
46
|
/**
|
|
122
|
-
*
|
|
123
|
-
* @param {string} adapterId
|
|
47
|
+
* Project a runtime adapter document from a normalized artifact (N-API).
|
|
124
48
|
*/
|
|
125
49
|
export function projectServerRuntimeAdapter(artifact, adapterId) {
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
throw new Error(
|
|
129
|
-
}
|
|
130
|
-
const base = {
|
|
131
|
-
schema: SERVER_RUNTIME_ADAPTER_SCHEMA,
|
|
132
|
-
adapterId: id,
|
|
133
|
-
artifactDigest: artifact.artifactDigest,
|
|
134
|
-
httpContractDigest: artifact.httpContract?.digest || null,
|
|
135
|
-
spaFallback: false,
|
|
136
|
-
entry: artifact.entry,
|
|
137
|
-
publicRouteCount: Array.isArray(artifact.publicRoutes) ? artifact.publicRoutes.length : 0,
|
|
138
|
-
internalCapabilityCount: Array.isArray(artifact.internalCapabilities) ? artifact.internalCapabilities.length : 0,
|
|
139
|
-
};
|
|
140
|
-
if (id === 'node') {
|
|
141
|
-
return { ...base, host: 'node:http', invoke: 'handleNodeRequest', status: 'runtime' };
|
|
142
|
-
}
|
|
143
|
-
if (id === 'worker' || id === 'deno' || id === 'bun') {
|
|
144
|
-
return {
|
|
145
|
-
...base,
|
|
146
|
-
host: 'fetch',
|
|
147
|
-
invoke: 'handleFetchRequest',
|
|
148
|
-
status: id === 'worker' ? 'runtime' : 'projected',
|
|
149
|
-
note: id === 'worker'
|
|
150
|
-
? 'Fetch entry; live thin gated via worker-shaped subprocess host'
|
|
151
|
-
: 'Fetch contract projection; live runtime not gated',
|
|
152
|
-
};
|
|
50
|
+
const native = requireNativeAddon();
|
|
51
|
+
if (typeof native.projectServerRuntimeAdapterJson !== 'function') {
|
|
52
|
+
throw new Error('vmz native addon missing projectServerRuntimeAdapterJson — rebuild with `pnpm napi:build`');
|
|
153
53
|
}
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
...base,
|
|
157
|
-
host: 'rust-fetch-consumer',
|
|
158
|
-
invoke: 'fetch',
|
|
159
|
-
status: 'projected',
|
|
160
|
-
note: 'contract projection only — live Rust host binary parity not gated',
|
|
161
|
-
consumes: ['server-artifact.json', 'vmz-routes.json', 'vmz-deployment.json'],
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function normalizeRuntime(raw) {
|
|
165
|
-
const v = String(raw || 'node').trim();
|
|
166
|
-
return SERVER_RUNTIMES.includes(v) ? v : 'node';
|
|
167
|
-
}
|
|
168
|
-
function readJson(file) {
|
|
169
|
-
if (!existsSync(file))
|
|
170
|
-
return null;
|
|
171
|
-
try {
|
|
172
|
-
return JSON.parse(readFileSync(file, 'utf8'));
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
function canonicalJson(value) {
|
|
179
|
-
return JSON.stringify(sortKeys(value));
|
|
180
|
-
}
|
|
181
|
-
function sortKeys(value) {
|
|
182
|
-
if (Array.isArray(value))
|
|
183
|
-
return value.map(sortKeys);
|
|
184
|
-
if (value && typeof value === 'object') {
|
|
185
|
-
const out = {};
|
|
186
|
-
for (const k of Object.keys(value).sort())
|
|
187
|
-
out[k] = sortKeys(value[k]);
|
|
188
|
-
return out;
|
|
189
|
-
}
|
|
190
|
-
return value;
|
|
191
|
-
}
|
|
192
|
-
function sha256Hex(text) {
|
|
193
|
-
return crypto.createHash('sha256').update(text, 'utf8').digest('hex');
|
|
54
|
+
return JSON.parse(native.projectServerRuntimeAdapterJson(JSON.stringify(artifact), String(adapterId || '').trim()));
|
|
194
55
|
}
|
package/dist/static-emit.js
CHANGED
|
@@ -15,7 +15,7 @@ import { absoluteUrl, buildLocalePageMeta, localizeBodyLinks } from './locale-ro
|
|
|
15
15
|
import { requireNativeAddon } from './native-addon.js';
|
|
16
16
|
import { writePrettyJsonFile } from './pretty-json.js';
|
|
17
17
|
import { emitPublicStaticAssets } from './public-static-assets.js';
|
|
18
|
-
import {
|
|
18
|
+
import { listPublicPageUnits, parsePathPattern, unitBrowserPathPattern } from './route-path.js';
|
|
19
19
|
import { emitSiteFavicon, readSiteFaviconHeadHtml } from './site-favicon.js';
|
|
20
20
|
export const STATIC_DELIVERY_MANIFEST_SCHEMA = 'vmz.static.delivery_manifest.v0';
|
|
21
21
|
export async function emitWebStatic(distDir, opts = {}) {
|
|
@@ -265,53 +265,25 @@ function sortKeys(value) {
|
|
|
265
265
|
*/
|
|
266
266
|
function listPageClientFiles(distDir) {
|
|
267
267
|
const fromDep = listPagesFromDeployment(distDir);
|
|
268
|
-
if (fromDep.length)
|
|
269
|
-
|
|
270
|
-
const root = path.join(distDir, 'pages');
|
|
271
|
-
/** @type {Array<{ chunkId: string, segs: ReturnType<typeof parsePathPattern>, pathPattern: string }>} */
|
|
272
|
-
const out = [];
|
|
273
|
-
function walk(abs, relParts) {
|
|
274
|
-
let ents;
|
|
275
|
-
try {
|
|
276
|
-
ents = fs.readdirSync(abs, { withFileTypes: true });
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
for (const e of ents) {
|
|
282
|
-
if (e.isDirectory())
|
|
283
|
-
walk(path.join(abs, e.name), [...relParts, e.name]);
|
|
284
|
-
else if (e.isFile() && e.name.endsWith('.client.js')) {
|
|
285
|
-
const stem = e.name.replace(/\.client\.js$/, '');
|
|
286
|
-
if (isRouteBoundaryStem(stem))
|
|
287
|
-
continue;
|
|
288
|
-
const chunkId = ['pages', ...relParts, stem].join('/');
|
|
289
|
-
const pathPattern = filePathPatternFromChunk(chunkId);
|
|
290
|
-
out.push({ chunkId, pathPattern, segs: parsePathPattern(pathPattern) });
|
|
291
|
-
}
|
|
292
|
-
}
|
|
268
|
+
if (!fromDep.length) {
|
|
269
|
+
throw new Error(`emitWebStatic: no page units with pathPattern in ${path.join(distDir, 'vmz-deployment.json')} (plan-only host)`);
|
|
293
270
|
}
|
|
294
|
-
|
|
295
|
-
return out;
|
|
271
|
+
return fromDep;
|
|
296
272
|
}
|
|
297
273
|
/**
|
|
298
274
|
* @param {string} distDir
|
|
299
275
|
*/
|
|
300
276
|
function listPagesFromDeployment(distDir) {
|
|
301
277
|
const deploymentPath = path.join(distDir, 'vmz-deployment.json');
|
|
302
|
-
if (!fs.existsSync(deploymentPath))
|
|
303
|
-
|
|
304
|
-
try {
|
|
305
|
-
const deployment = JSON.parse(fs.readFileSync(deploymentPath, 'utf8'));
|
|
306
|
-
return listPublicPageUnits(deployment).map((u) => {
|
|
307
|
-
const chunkId = String(u.chunkId || '').replace(/\\/g, '/');
|
|
308
|
-
const pathPattern = unitBrowserPathPattern(u);
|
|
309
|
-
return { chunkId, pathPattern, segs: parsePathPattern(pathPattern) };
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
catch {
|
|
313
|
-
return [];
|
|
278
|
+
if (!fs.existsSync(deploymentPath)) {
|
|
279
|
+
throw new Error(`emitWebStatic: missing ${deploymentPath} (plan-only host)`);
|
|
314
280
|
}
|
|
281
|
+
const deployment = JSON.parse(fs.readFileSync(deploymentPath, 'utf8'));
|
|
282
|
+
return listPublicPageUnits(deployment).map((u) => {
|
|
283
|
+
const chunkId = String(u.chunkId || '').replace(/\\/g, '/');
|
|
284
|
+
const pathPattern = unitBrowserPathPattern(u);
|
|
285
|
+
return { chunkId, pathPattern, segs: parsePathPattern(pathPattern) };
|
|
286
|
+
});
|
|
315
287
|
}
|
|
316
288
|
/**
|
|
317
289
|
* @param {ReturnType<typeof parsePathPattern>} segs
|
package/locales/en-US/cli.json
CHANGED
|
@@ -100,6 +100,5 @@
|
|
|
100
100
|
"cli.err.global_needs_project": "this `vmz` is a global install (mode=global); project commands need a project install.",
|
|
101
101
|
"cli.err.global_install_hint": "Install in the app: pnpm add -D @vmz/vmz",
|
|
102
102
|
"cli.err.global_run_hint": "Then run: pnpm exec vmz <command>",
|
|
103
|
-
"cli.err.global_developer_hint": "(developer mode: run from vmz-framework packages/runtimes/vmz source — full CLI)"
|
|
104
|
-
"diag.message": "{message}"
|
|
103
|
+
"cli.err.global_developer_hint": "(developer mode: run from vmz-framework packages/runtimes/vmz source — full CLI)"
|
|
105
104
|
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
{
|
|
2
|
+
"diag.message": "{message}",
|
|
3
|
+
"diag.detail": "{detail}",
|
|
4
|
+
|
|
5
|
+
"vmz::template::jsx_rejected": "JSX / single-brace expressions are rejected in `<template>`: {detail}",
|
|
6
|
+
"vmz::template::illegal_directive": "Illegal or unsupported directive in `<template>`: {detail}",
|
|
7
|
+
"vmz::template::parse_failed": "Failed to parse `<template>`: {detail}",
|
|
8
|
+
"vmz::template::invalid_expr": "Invalid template expression: {detail}",
|
|
9
|
+
"vmz::template::each_missing_key": "`v-for` on `<{tag}>` should declare a `:key`",
|
|
10
|
+
"vmz::template::each_static_key": "`v-for` on `<{tag}>` must not use a static key `{key}`",
|
|
11
|
+
"vmz::template::each_literal_key": "`v-for` on `<{tag}>` must not use a literal key `{key}`",
|
|
12
|
+
"vmz::template::each_object_key": "`v-for` on `<{tag}>` object form should bind `:key` to `{as}`",
|
|
13
|
+
|
|
14
|
+
"vmz::style::unknown_design_token": "Unknown design token `{name}`: {detail}",
|
|
15
|
+
"vmz::style::unused_design_token": "Unused design token `{name}` (`{var}`): {detail}",
|
|
16
|
+
"vmz::style::unreferenced_global_style": "Unreferenced global style `{path}`: {detail}",
|
|
17
|
+
"vmz::style::token_json_invalid": "Invalid design token JSON: {detail}",
|
|
18
|
+
"vmz::style::theme_id_collision": "Style theme id collision: `{id}`",
|
|
19
|
+
"vmz::style::theme_json_unreadable": "Style theme JSON is unreadable",
|
|
20
|
+
"vmz::style::theme_json_invalid": "Style theme JSON is invalid",
|
|
21
|
+
"vmz::style::prefers_scheme_empty": "Empty prefers-color-scheme mapping for `{scheme}`",
|
|
22
|
+
|
|
23
|
+
"vmz::locale::manifest_missing": "Locale manifest missing: {detail}",
|
|
24
|
+
"vmz::locale::id_invalid": "{detail}",
|
|
25
|
+
"vmz::locale::id_collision": "{detail}",
|
|
26
|
+
"vmz::locale::default_missing": "{detail}",
|
|
27
|
+
"vmz::locale::fallback_cycle": "{detail}",
|
|
28
|
+
"vmz::locale::fallback_unknown": "{detail}",
|
|
29
|
+
"vmz::locale::dir_orphan": "{detail}",
|
|
30
|
+
"vmz::locale::dir_missing": "{detail}",
|
|
31
|
+
"vmz::locale::layout_illegal": "{detail}",
|
|
32
|
+
"vmz::locale::message_missing_default": "{detail}",
|
|
33
|
+
"vmz::locale::message_missing_variant": "{detail}",
|
|
34
|
+
"vmz::locale::message_parameter_mismatch": "{detail}",
|
|
35
|
+
"vmz::locale::message_syntax_invalid": "{detail}",
|
|
36
|
+
"vmz::locale::message_array_forbidden": "{detail}",
|
|
37
|
+
"vmz::locale::message_unused": "{detail}",
|
|
38
|
+
"vmz::locale::message_html_forbidden": "{detail}",
|
|
39
|
+
"vmz::locale::catalog_parse": "{detail}",
|
|
40
|
+
"vmz::locale::catalog_conflict": "{detail}",
|
|
41
|
+
"vmz::locale::formatter_context_incomplete": "{detail}",
|
|
42
|
+
"vmz::locale::formatter_version_mismatch": "{detail}",
|
|
43
|
+
"vmz::locale::digest_mismatch": "{detail}",
|
|
44
|
+
"vmz::locale::transition_partial": "{detail}",
|
|
45
|
+
"vmz::locale::transition_unsupported": "{detail}",
|
|
46
|
+
"vmz::locale::transition_load_failed": "{detail}",
|
|
47
|
+
"vmz::locale::machine_default_forbidden": "{detail}",
|
|
48
|
+
"vmz::locale::message_mixed_locale": "{detail}",
|
|
49
|
+
"vmz::locale::stale_generation": "{detail}",
|
|
50
|
+
"vmz::locale::route_collision": "{detail}",
|
|
51
|
+
"vmz::locale::canonical_missing": "{detail}",
|
|
52
|
+
"vmz::locale::hreflang_incomplete": "{detail}",
|
|
53
|
+
"vmz::locale::meta_locale_mismatch": "{detail}",
|
|
54
|
+
"vmz::locale::link_hardcoded_path": "{detail}",
|
|
55
|
+
"vmz::locale::cache_key_steals_content": "{detail}",
|
|
56
|
+
"vmz::locale::prefix_omit_without_redirect": "{detail}",
|
|
57
|
+
"vmz::locale::delivery_full_bundle": "{detail}",
|
|
58
|
+
"vmz::locale::chunk_hash_mismatch": "{detail}",
|
|
59
|
+
"vmz::locale::native_pack_unsigned": "{detail}",
|
|
60
|
+
"vmz::locale::native_pack_has_js": "{detail}",
|
|
61
|
+
"vmz::locale::native_pack_app_mismatch": "{detail}",
|
|
62
|
+
"vmz::locale::mini_cross_package_unproven": "{detail}",
|
|
63
|
+
"vmz::locale::server_translated_error": "{detail}",
|
|
64
|
+
"vmz::locale::server_format_without_context": "{detail}",
|
|
65
|
+
"vmz::locale::host_message_divergence": "{detail}",
|
|
66
|
+
"vmz::locale::message_dynamic_id_unbounded": "{detail}",
|
|
67
|
+
"vmz::locale::hardcoded_text": "{detail}",
|
|
68
|
+
"vmz::locale::pseudo_production_forbidden": "{detail}",
|
|
69
|
+
"vmz::locale::conformance_divergence": "{detail}",
|
|
70
|
+
"vmz::locale::explain_unknown": "{detail}",
|
|
71
|
+
|
|
72
|
+
"vmz::format::would_reformat": "File would be reformatted",
|
|
73
|
+
"vmz::format::failed": "Format failed: {detail}",
|
|
74
|
+
|
|
75
|
+
"vmz::convention::layout_suffix": "Named layout `{stem}` should end with `Layout`",
|
|
76
|
+
"vmz::convention::pascal_case_file": "Prefer PascalCase file name `{hint}` (got `{name}`)",
|
|
77
|
+
"vmz::convention::prefer_application_shell": "Prefer `Application.vmz` as the application shell",
|
|
78
|
+
"vmz::convention::prefer_pascal_index": "Prefer `Index.vmz` over `index.vmz` for pages",
|
|
79
|
+
|
|
80
|
+
"vmz::io::read_failed": "Failed to read file: {error}",
|
|
81
|
+
"vmz::sfc::parse_failed": "Failed to parse `.vmz` SFC: {detail}",
|
|
82
|
+
|
|
83
|
+
"vmz::script::client_parse_failed": "Failed to parse client script: {detail}",
|
|
84
|
+
"vmz::script::client_export_required": "Client script must `export default class`",
|
|
85
|
+
"vmz::script::forbidden_factory": "Forbidden factory `{name}` (use class + public props)",
|
|
86
|
+
"vmz::script::server_parse_failed": "Failed to parse server script: {detail}",
|
|
87
|
+
"vmz::script::server_export_required": "Server script must export a default class or function",
|
|
88
|
+
"vmz::script::server_struct_required": "Rust server script must declare a public struct",
|
|
89
|
+
|
|
90
|
+
"vmz::router::link_invalid": "Invalid route link: {detail}",
|
|
91
|
+
"vmz::router::route_table_invalid": "Invalid route table: {detail}",
|
|
92
|
+
"vmz::router::path_deviation": "Route path `{explicit}` differs from file `{file}`",
|
|
93
|
+
|
|
94
|
+
"vmz::runtime::missing": "Missing runtime `{name}` under `{root}`",
|
|
95
|
+
"vmz::emit::server_tree_failed": "Failed to emit server tree: {error}",
|
|
96
|
+
"vmz::emit::client_module_failed": "Failed to emit client module: {error}",
|
|
97
|
+
"vmz::emit::client_js_print_failed": "Failed to print client JS: {error}",
|
|
98
|
+
"vmz::emit::client_failed": "Failed to emit client: {error}",
|
|
99
|
+
"vmz::emit::server_failed": "Failed to emit server: {error}",
|
|
100
|
+
|
|
101
|
+
"vmz::program::unknown_widen": "Unknown widen via `{via}` for field `{field}`: {reason}",
|
|
102
|
+
|
|
103
|
+
"vmz::server::server_slice_not_browser_safe": "Server slice is not browser-safe: {detail}",
|
|
104
|
+
"vmz::server::client_mock_provider_forbidden": "{detail}",
|
|
105
|
+
"vmz::server::secret_client_leak": "{detail}",
|
|
106
|
+
"vmz::server::secret_binding_missing": "{detail}",
|
|
107
|
+
|
|
108
|
+
"vmz::tw::theme_load_failed": "Failed to load Tailwind theme: {detail}",
|
|
109
|
+
"vmz::tw::dynamic_style_tw": "Dynamic `style:tw` expression `{expr}` cannot be collected statically",
|
|
110
|
+
"vmz::tw::unbalanced_at_tailwind": "Unbalanced `@tailwind` block: {detail}",
|
|
111
|
+
|
|
112
|
+
"vmz::scss::compile_failed": "SCSS compile failed: {detail}",
|
|
113
|
+
|
|
114
|
+
"vmz::plugin::analyzer": "Plugin `{plugin}` analyzer `{id}`: {detail}",
|
|
115
|
+
|
|
116
|
+
"vmz::dx::class_name_mismatch": "{detail}",
|
|
117
|
+
|
|
118
|
+
"vmz::application::duplicate_id": "{detail}",
|
|
119
|
+
"vmz::application::unknown_reference": "{detail}",
|
|
120
|
+
"vmz::application::mount_collision": "{detail}",
|
|
121
|
+
"vmz::application::invalid_schema": "{detail}",
|
|
122
|
+
"vmz::application::invalid_config": "{detail}",
|
|
123
|
+
"vmz::application::invalid_descriptor": "{detail}",
|
|
124
|
+
"vmz::application::invalid_route_base": "{detail}",
|
|
125
|
+
"vmz::application::duplicate_mount": "{detail}",
|
|
126
|
+
"vmz::application::non_relocatable_url": "{detail}",
|
|
127
|
+
"vmz::application::invalid_base": "{detail}",
|
|
128
|
+
"vmz::application::artifact_integrity": "{detail}",
|
|
129
|
+
"vmz::application::cross_runtime_reference": "{detail}",
|
|
130
|
+
"vmz::application::isolation_unproven": "{detail}",
|
|
131
|
+
"vmz::application::failure_containment": "{detail}",
|
|
132
|
+
"vmz::application::route_not_public": "{detail}",
|
|
133
|
+
"vmz::application::mount_unreachable": "{detail}",
|
|
134
|
+
"vmz::application::session_shared": "{detail}",
|
|
135
|
+
"vmz::application::proxy_misroute": "{detail}",
|
|
136
|
+
"vmz::application::affected_leak": "{detail}",
|
|
137
|
+
|
|
138
|
+
"document::config::missing": "{detail}",
|
|
139
|
+
"document::config::invalid": "{detail}",
|
|
140
|
+
"document::config::default_locale": "{detail}",
|
|
141
|
+
"document::fallback::silent_forbidden": "{detail}",
|
|
142
|
+
|
|
143
|
+
"vmz::target::dom_leak_in_plan": "{detail}",
|
|
144
|
+
"vmz::target::unknown_view_op": "{detail}",
|
|
145
|
+
"vmz::target::platform_unsupported": "{detail}",
|
|
146
|
+
"vmz::target::profile_invalid": "{detail}",
|
|
147
|
+
"vmz::target::artifact_invalid": "{detail}",
|
|
148
|
+
"vmz::target::mini_missing_adapter": "{detail}",
|
|
149
|
+
"vmz::target::mini_adapter_semantic_core": "{detail}",
|
|
150
|
+
"vmz::target::mini_platform_private_schema": "{detail}",
|
|
151
|
+
"vmz::target::mini_shared_fork": "{detail}",
|
|
152
|
+
"vmz::target::mini_static_slice_catalog_only": "{detail}",
|
|
153
|
+
"vmz::target::mini_route_server_style_catalog_only": "{detail}"
|
|
154
|
+
}
|
package/locales/locales.json
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"defaultLocale": "en-US",
|
|
3
|
-
"locales": [{ "id": "en-US", "label": "English", "direction": "ltr" }]
|
|
3
|
+
"locales": [{ "id": "en-US", "label": "English", "direction": "ltr" }, { "id": "zh-CN", "label": "简体中文", "direction": "ltr" }],
|
|
4
|
+
"fallback": {
|
|
5
|
+
"zh-CN": ["en-US"]
|
|
6
|
+
}
|
|
4
7
|
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
{
|
|
2
|
+
"diag.message": "{message}",
|
|
3
|
+
"diag.detail": "{detail}",
|
|
4
|
+
|
|
5
|
+
"vmz::template::jsx_rejected": "`<template>` 拒绝 JSX / 单花括号表达式:{detail}",
|
|
6
|
+
"vmz::template::illegal_directive": "`<template>` 中存在非法或不支持的指令:{detail}",
|
|
7
|
+
"vmz::template::parse_failed": "解析 `<template>` 失败:{detail}",
|
|
8
|
+
"vmz::template::invalid_expr": "模板表达式无效:{detail}",
|
|
9
|
+
"vmz::template::each_missing_key": "`<{tag}>` 上的 `v-for` 应声明 `:key`",
|
|
10
|
+
"vmz::template::each_static_key": "`<{tag}>` 上的 `v-for` 不得使用静态 key `{key}`",
|
|
11
|
+
"vmz::template::each_literal_key": "`<{tag}>` 上的 `v-for` 不得使用字面量 key `{key}`",
|
|
12
|
+
"vmz::template::each_object_key": "`<{tag}>` 上的 `v-for` 对象形式应将 `:key` 绑定到 `{as}`",
|
|
13
|
+
|
|
14
|
+
"vmz::style::unknown_design_token": "未知设计令牌 `{name}`:{detail}",
|
|
15
|
+
"vmz::style::unused_design_token": "未使用的设计令牌 `{name}`(`{var}`):{detail}",
|
|
16
|
+
"vmz::style::unreferenced_global_style": "未被引用的全局样式 `{path}`:{detail}",
|
|
17
|
+
"vmz::style::token_json_invalid": "设计令牌 JSON 无效:{detail}",
|
|
18
|
+
"vmz::style::theme_id_collision": "样式主题 id 冲突:`{id}`",
|
|
19
|
+
"vmz::style::theme_json_unreadable": "无法读取样式主题 JSON",
|
|
20
|
+
"vmz::style::theme_json_invalid": "样式主题 JSON 无效",
|
|
21
|
+
"vmz::style::prefers_scheme_empty": "`{scheme}` 的 prefers-color-scheme 映射为空",
|
|
22
|
+
|
|
23
|
+
"vmz::locale::manifest_missing": "缺少 locale 清单:{detail}",
|
|
24
|
+
"vmz::locale::id_invalid": "{detail}",
|
|
25
|
+
"vmz::locale::id_collision": "{detail}",
|
|
26
|
+
"vmz::locale::default_missing": "{detail}",
|
|
27
|
+
"vmz::locale::fallback_cycle": "{detail}",
|
|
28
|
+
"vmz::locale::fallback_unknown": "{detail}",
|
|
29
|
+
"vmz::locale::dir_orphan": "{detail}",
|
|
30
|
+
"vmz::locale::dir_missing": "{detail}",
|
|
31
|
+
"vmz::locale::layout_illegal": "{detail}",
|
|
32
|
+
"vmz::locale::message_missing_default": "{detail}",
|
|
33
|
+
"vmz::locale::message_missing_variant": "{detail}",
|
|
34
|
+
"vmz::locale::message_parameter_mismatch": "{detail}",
|
|
35
|
+
"vmz::locale::message_syntax_invalid": "{detail}",
|
|
36
|
+
"vmz::locale::message_array_forbidden": "{detail}",
|
|
37
|
+
"vmz::locale::message_unused": "{detail}",
|
|
38
|
+
"vmz::locale::message_html_forbidden": "{detail}",
|
|
39
|
+
"vmz::locale::catalog_parse": "{detail}",
|
|
40
|
+
"vmz::locale::catalog_conflict": "{detail}",
|
|
41
|
+
"vmz::locale::formatter_context_incomplete": "{detail}",
|
|
42
|
+
"vmz::locale::formatter_version_mismatch": "{detail}",
|
|
43
|
+
"vmz::locale::digest_mismatch": "{detail}",
|
|
44
|
+
"vmz::locale::transition_partial": "{detail}",
|
|
45
|
+
"vmz::locale::transition_unsupported": "{detail}",
|
|
46
|
+
"vmz::locale::transition_load_failed": "{detail}",
|
|
47
|
+
"vmz::locale::machine_default_forbidden": "{detail}",
|
|
48
|
+
"vmz::locale::message_mixed_locale": "{detail}",
|
|
49
|
+
"vmz::locale::stale_generation": "{detail}",
|
|
50
|
+
"vmz::locale::route_collision": "{detail}",
|
|
51
|
+
"vmz::locale::canonical_missing": "{detail}",
|
|
52
|
+
"vmz::locale::hreflang_incomplete": "{detail}",
|
|
53
|
+
"vmz::locale::meta_locale_mismatch": "{detail}",
|
|
54
|
+
"vmz::locale::link_hardcoded_path": "{detail}",
|
|
55
|
+
"vmz::locale::cache_key_steals_content": "{detail}",
|
|
56
|
+
"vmz::locale::prefix_omit_without_redirect": "{detail}",
|
|
57
|
+
"vmz::locale::delivery_full_bundle": "{detail}",
|
|
58
|
+
"vmz::locale::chunk_hash_mismatch": "{detail}",
|
|
59
|
+
"vmz::locale::native_pack_unsigned": "{detail}",
|
|
60
|
+
"vmz::locale::native_pack_has_js": "{detail}",
|
|
61
|
+
"vmz::locale::native_pack_app_mismatch": "{detail}",
|
|
62
|
+
"vmz::locale::mini_cross_package_unproven": "{detail}",
|
|
63
|
+
"vmz::locale::server_translated_error": "{detail}",
|
|
64
|
+
"vmz::locale::server_format_without_context": "{detail}",
|
|
65
|
+
"vmz::locale::host_message_divergence": "{detail}",
|
|
66
|
+
"vmz::locale::message_dynamic_id_unbounded": "{detail}",
|
|
67
|
+
"vmz::locale::hardcoded_text": "{detail}",
|
|
68
|
+
"vmz::locale::pseudo_production_forbidden": "{detail}",
|
|
69
|
+
"vmz::locale::conformance_divergence": "{detail}",
|
|
70
|
+
"vmz::locale::explain_unknown": "{detail}",
|
|
71
|
+
|
|
72
|
+
"vmz::format::would_reformat": "文件将被重新格式化",
|
|
73
|
+
"vmz::format::failed": "格式化失败:{detail}",
|
|
74
|
+
|
|
75
|
+
"vmz::convention::layout_suffix": "命名布局 `{stem}` 应以 `Layout` 结尾",
|
|
76
|
+
"vmz::convention::pascal_case_file": "文件名建议使用 PascalCase `{hint}`(当前为 `{name}`)",
|
|
77
|
+
"vmz::convention::prefer_application_shell": "应用壳优先使用 `Application.vmz`",
|
|
78
|
+
"vmz::convention::prefer_pascal_index": "页面优先使用 `Index.vmz` 而非 `index.vmz`",
|
|
79
|
+
|
|
80
|
+
"vmz::io::read_failed": "读取文件失败:{error}",
|
|
81
|
+
"vmz::sfc::parse_failed": "解析 `.vmz` SFC 失败:{detail}",
|
|
82
|
+
|
|
83
|
+
"vmz::script::client_parse_failed": "解析 client script 失败:{detail}",
|
|
84
|
+
"vmz::script::client_export_required": "client script 必须 `export default class`",
|
|
85
|
+
"vmz::script::forbidden_factory": "禁止使用工厂函数 `{name}`(请用 class + public props)",
|
|
86
|
+
"vmz::script::server_parse_failed": "解析 server script 失败:{detail}",
|
|
87
|
+
"vmz::script::server_export_required": "server script 必须导出默认 class 或函数",
|
|
88
|
+
"vmz::script::server_struct_required": "Rust server script 必须声明 public struct",
|
|
89
|
+
|
|
90
|
+
"vmz::router::link_invalid": "路由链接无效:{detail}",
|
|
91
|
+
"vmz::router::route_table_invalid": "路由表无效:{detail}",
|
|
92
|
+
"vmz::router::path_deviation": "路由路径 `{explicit}` 与文件 `{file}` 不一致",
|
|
93
|
+
|
|
94
|
+
"vmz::runtime::missing": "在 `{root}` 下缺少运行时 `{name}`",
|
|
95
|
+
"vmz::emit::server_tree_failed": "生成 server tree 失败:{error}",
|
|
96
|
+
"vmz::emit::client_module_failed": "生成 client module 失败:{error}",
|
|
97
|
+
"vmz::emit::client_js_print_failed": "打印 client JS 失败:{error}",
|
|
98
|
+
"vmz::emit::client_failed": "生成 client 失败:{error}",
|
|
99
|
+
"vmz::emit::server_failed": "生成 server 失败:{error}",
|
|
100
|
+
|
|
101
|
+
"vmz::program::unknown_widen": "字段 `{field}` 经 `{via}` 未知 widen:{reason}",
|
|
102
|
+
|
|
103
|
+
"vmz::server::server_slice_not_browser_safe": "server slice 对浏览器不安全:{detail}",
|
|
104
|
+
"vmz::server::client_mock_provider_forbidden": "{detail}",
|
|
105
|
+
"vmz::server::secret_client_leak": "{detail}",
|
|
106
|
+
"vmz::server::secret_binding_missing": "{detail}",
|
|
107
|
+
|
|
108
|
+
"vmz::tw::theme_load_failed": "加载 Tailwind 主题失败:{detail}",
|
|
109
|
+
"vmz::tw::dynamic_style_tw": "动态 `style:tw` 表达式 `{expr}` 无法静态收集",
|
|
110
|
+
"vmz::tw::unbalanced_at_tailwind": "`@tailwind` 块括号不匹配:{detail}",
|
|
111
|
+
|
|
112
|
+
"vmz::scss::compile_failed": "SCSS 编译失败:{detail}",
|
|
113
|
+
|
|
114
|
+
"vmz::plugin::analyzer": "插件 `{plugin}` 分析器 `{id}`:{detail}",
|
|
115
|
+
|
|
116
|
+
"vmz::dx::class_name_mismatch": "{detail}",
|
|
117
|
+
|
|
118
|
+
"vmz::application::duplicate_id": "{detail}",
|
|
119
|
+
"vmz::application::unknown_reference": "{detail}",
|
|
120
|
+
"vmz::application::mount_collision": "{detail}",
|
|
121
|
+
"vmz::application::invalid_schema": "{detail}",
|
|
122
|
+
"vmz::application::invalid_config": "{detail}",
|
|
123
|
+
"vmz::application::invalid_descriptor": "{detail}",
|
|
124
|
+
"vmz::application::invalid_route_base": "{detail}",
|
|
125
|
+
"vmz::application::duplicate_mount": "{detail}",
|
|
126
|
+
"vmz::application::non_relocatable_url": "{detail}",
|
|
127
|
+
"vmz::application::invalid_base": "{detail}",
|
|
128
|
+
"vmz::application::artifact_integrity": "{detail}",
|
|
129
|
+
"vmz::application::cross_runtime_reference": "{detail}",
|
|
130
|
+
"vmz::application::isolation_unproven": "{detail}",
|
|
131
|
+
"vmz::application::failure_containment": "{detail}",
|
|
132
|
+
"vmz::application::route_not_public": "{detail}",
|
|
133
|
+
"vmz::application::mount_unreachable": "{detail}",
|
|
134
|
+
"vmz::application::session_shared": "{detail}",
|
|
135
|
+
"vmz::application::proxy_misroute": "{detail}",
|
|
136
|
+
"vmz::application::affected_leak": "{detail}",
|
|
137
|
+
|
|
138
|
+
"document::config::missing": "{detail}",
|
|
139
|
+
"document::config::invalid": "{detail}",
|
|
140
|
+
"document::config::default_locale": "{detail}",
|
|
141
|
+
"document::fallback::silent_forbidden": "{detail}",
|
|
142
|
+
|
|
143
|
+
"vmz::target::dom_leak_in_plan": "{detail}",
|
|
144
|
+
"vmz::target::unknown_view_op": "{detail}",
|
|
145
|
+
"vmz::target::platform_unsupported": "{detail}",
|
|
146
|
+
"vmz::target::profile_invalid": "{detail}",
|
|
147
|
+
"vmz::target::artifact_invalid": "{detail}",
|
|
148
|
+
"vmz::target::mini_missing_adapter": "{detail}",
|
|
149
|
+
"vmz::target::mini_adapter_semantic_core": "{detail}",
|
|
150
|
+
"vmz::target::mini_platform_private_schema": "{detail}",
|
|
151
|
+
"vmz::target::mini_shared_fork": "{detail}",
|
|
152
|
+
"vmz::target::mini_static_slice_catalog_only": "{detail}",
|
|
153
|
+
"vmz::target::mini_route_server_style_catalog_only": "{detail}"
|
|
154
|
+
}
|