@vmz/vmz 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/bin/vmz.js +9 -1
- package/dist/cli/cli.js +24 -17
- package/dist/dev/config-cycle-worker.d.ts +7 -0
- package/dist/dev/config-cycle-worker.js +83 -0
- package/dist/dev/config-cycle.d.ts +45 -0
- package/dist/dev/config-cycle.js +152 -0
- package/dist/dev/dev-session.d.ts +11 -0
- package/dist/dev/dev-session.js +89 -15
- package/dist/dev/dev-watch-roots.d.ts +7 -0
- package/dist/dev/dev-watch-roots.js +65 -2
- package/dist/document/document-integrate.js +6 -0
- package/dist/document/document-markdown.d.ts +1 -1
- package/dist/document/document-markdown.js +7 -21
- package/dist/workspace/log.d.ts +2 -0
- package/dist/workspace/log.js +2 -2
- package/dist/workspace/plugin-host.d.ts +3 -5
- package/dist/workspace/plugin-host.js +52 -16
- package/dist/workspace/public-api.d.ts +5 -1
- package/dist/workspace/public-api.js +6 -22
- package/dist/workspace/wechat-packaging.d.ts +9 -2
- package/dist/workspace/wechat-packaging.js +15 -20
- package/locales/en-US/diag.json +8 -1
- package/locales/zh-CN/diag.json +4 -1
- package/package.json +23 -21
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# `@vmz/vmz` (bin: `vmz`)
|
|
2
2
|
|
|
3
|
+
Requires Node `>=24.12.0`. Project `vmz.config.ts|mts` loads through native ESM (erasable TypeScript only, no runtime
|
|
4
|
+
transpiler).
|
|
5
|
+
|
|
3
6
|
CLI / N-API toolchain host. Runtime mental entry is **`@vmz/core`**; optional official UI is **`@vmz/ui`**; plugins are
|
|
4
7
|
**`@vmz/plugin-*`**. Shelved umbrella name: `@vmz/vmz`.
|
|
5
8
|
|
package/bin/vmz.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
const [major = 0, minor = 0] = process.versions.node.split('.').map((part) => Number.parseInt(part, 10));
|
|
3
|
+
if (major < 24 || (major === 24 && minor < 12)) {
|
|
4
|
+
process.stderr.write(
|
|
5
|
+
`vmz: Node >=24.12.0 is required (found ${process.versions.node}).\n` +
|
|
6
|
+
' Why: project `vmz.config.*` and plugin entries load through native ESM type stripping.\n',
|
|
7
|
+
);
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
const { runCli } = await import('../dist/cli/cli.js');
|
|
3
11
|
const code = await runCli(process.argv.slice(2));
|
|
4
12
|
process.exit(code ?? 0);
|
package/dist/cli/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ import { registerDocumentCommands } from '../document/document-cmd.js';
|
|
|
13
13
|
import { buildIntegratedDocuments, projectHasDocuments } from '../document/document-integrate.js';
|
|
14
14
|
import { registerExplainCommand } from './explain-cmd.js';
|
|
15
15
|
import { registerGithubActionsCommand } from './github-actions-cmd.js';
|
|
16
|
-
import { createWorkspace, getProtocolVersions, HOST_PROTOCOL, materializeServeHostRuntime, resolveCoreRuntimeDist, resolveNativePath, } from '../workspace/public-api.js';
|
|
16
|
+
import { createWorkspace, getProtocolVersions, HOST_PROTOCOL, materializeServeHostRuntime, materializeWechatPackaging, resolveCoreRuntimeDist, resolveNativePath, } from '../workspace/public-api.js';
|
|
17
17
|
import { gateGlobalProjectCommand, getInvocationContext, isGlobalAllowedCommand } from '../workspace/invocation.js';
|
|
18
18
|
import { emitLocaleRuntimeModules, localeHasErrors } from '../locale/locale-check.js';
|
|
19
19
|
import { registerLocaleCommands } from '../locale/locale-cmd.js';
|
|
@@ -46,6 +46,9 @@ function buildProductCli(opts = {}) {
|
|
|
46
46
|
const cli = createCli('vmz')
|
|
47
47
|
.locales(resolveCliLocalesRoot(), {
|
|
48
48
|
envKeys: ['VMZ_LOCALE', 'LOCALE', 'LANG', 'LC_ALL'],
|
|
49
|
+
})
|
|
50
|
+
.onDiagnostic((diagnostic, context) => {
|
|
51
|
+
log.diagnostic(diagnostic, { locale: context.locale });
|
|
49
52
|
})
|
|
50
53
|
.intro(introId);
|
|
51
54
|
// Global install: only version (help is derived). Project commands need a project bin.
|
|
@@ -53,32 +56,29 @@ function buildProductCli(opts = {}) {
|
|
|
53
56
|
cli.command('version', 'cli.cmd.version').action(() => cmdVersion());
|
|
54
57
|
return cli;
|
|
55
58
|
}
|
|
56
|
-
const
|
|
59
|
+
const withCoreOpts = (cmd) => cmd
|
|
57
60
|
.option('--out-dir, -o <dir>', 'cli.opt.out-dir')
|
|
58
61
|
.option('--release', 'cli.opt.release')
|
|
59
62
|
.option('--profile <name>', 'cli.opt.profile')
|
|
60
63
|
.option('--target <id>', 'cli.opt.target')
|
|
61
64
|
.option('--origin <url>', 'cli.opt.origin')
|
|
62
|
-
.option('--host <host>', 'cli.opt.host')
|
|
63
|
-
.option('--port <port>', 'cli.opt.port')
|
|
64
|
-
.option('--poll-ms <ms>', 'cli.opt.poll-ms')
|
|
65
|
-
.option('--build', 'cli.opt.build')
|
|
66
65
|
.option('--check', 'cli.opt.check')
|
|
67
66
|
.option('--deny-warnings', 'cli.opt.deny-warnings');
|
|
68
|
-
|
|
67
|
+
const withServeExtras = (cmd) => cmd.option('--host <host>', 'cli.opt.host').option('--port <port>', 'cli.opt.port').option('--poll-ms <ms>', 'cli.opt.poll-ms').option('--build', 'cli.opt.build');
|
|
68
|
+
withCoreOpts(cli.command('check', 'cli.cmd.check'))
|
|
69
69
|
.option('--level <level>', 'cli.opt.level')
|
|
70
70
|
.option('--info', 'cli.opt.info-level')
|
|
71
71
|
.option('--style <style>', 'cli.opt.diag-style')
|
|
72
72
|
.action((options) => cmdCheck(options));
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
withCoreOpts(cli.command('build', 'cli.cmd.build')).action((options) => cmdBuild(options));
|
|
74
|
+
withServeExtras(withCoreOpts(cli.command('serve', 'cli.cmd.serve'))).action((options) => cmdServe(options));
|
|
75
|
+
withServeExtras(withCoreOpts(cli.command('dev', 'cli.cmd.dev'))).action((options) => cmdDev(options));
|
|
76
|
+
withCoreOpts(cli.command('format', 'cli.cmd.format'))
|
|
77
77
|
.option('--no-javascript', 'cli.opt.format-no-javascript')
|
|
78
78
|
.option('--no-rust', 'cli.opt.format-no-rust')
|
|
79
79
|
.option('--no-vmz', 'cli.opt.format-no-vmz')
|
|
80
80
|
.action((options) => cmdFormat(options));
|
|
81
|
-
|
|
81
|
+
withCoreOpts(cli.command('lint', 'cli.cmd.lint'))
|
|
82
82
|
.option('--level <level>', 'cli.opt.level')
|
|
83
83
|
.option('--info', 'cli.opt.info-level')
|
|
84
84
|
.option('--style <style>', 'cli.opt.diag-style')
|
|
@@ -152,9 +152,10 @@ async function cmdCheck(args) {
|
|
|
152
152
|
});
|
|
153
153
|
const meta = readPackageMeta(project);
|
|
154
154
|
log.info(`check ${project}${meta?.name ? ` (${meta.name})` : ''}`);
|
|
155
|
+
const cfg = await loadVmzConfig(project);
|
|
155
156
|
const ws = createWorkspace({ root: project, outDir });
|
|
156
157
|
try {
|
|
157
|
-
return runWithPlugins(ws, project, outDir, async () => {
|
|
158
|
+
return runWithPlugins(ws, cfg, project, outDir, async () => {
|
|
158
159
|
const report = ws.check();
|
|
159
160
|
const { checkLocales, localeHasErrors } = await import('../locale/locale-check.js');
|
|
160
161
|
const localeReport = checkLocales({ projectRoot: project, checkUnused: false });
|
|
@@ -182,9 +183,9 @@ function dedupeDiagnostics(list) {
|
|
|
182
183
|
}
|
|
183
184
|
return out;
|
|
184
185
|
}
|
|
185
|
-
async function runWithPlugins(ws, project, outDir, fn) {
|
|
186
|
-
const {
|
|
187
|
-
const { plugins, engines } =
|
|
186
|
+
async function runWithPlugins(ws, cfg, project, outDir, fn) {
|
|
187
|
+
const { applyPlugins } = await import('../workspace/plugin-host.js');
|
|
188
|
+
const { plugins, engines } = cfg;
|
|
188
189
|
if (plugins.length) {
|
|
189
190
|
await applyPlugins(ws, plugins, { project, outDir, engines });
|
|
190
191
|
}
|
|
@@ -218,10 +219,12 @@ async function cmdBuild(args) {
|
|
|
218
219
|
}
|
|
219
220
|
const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
|
|
220
221
|
log.info(`build ${project} → ${outDir}${wechatPack ? ' (target=mini-program-wechat)' : ''} (out-dir=${outDirRoot}, name=${selected.profile.name})`);
|
|
222
|
+
if (wechatPack)
|
|
223
|
+
materializeWechatPackaging(project, cfg.delivery);
|
|
221
224
|
const ws = createWorkspace({ root: project, outDir });
|
|
222
225
|
try {
|
|
223
226
|
log.info(`delivery profile ${selected.selection.profileId} (assembly=${selected.selection.assembly}, name=${selected.profile.name})`);
|
|
224
|
-
const code = await runWithPlugins(ws, project, outDir, () => {
|
|
227
|
+
const code = await runWithPlugins(ws, cfg, project, outDir, () => {
|
|
225
228
|
const report = ws.build(Boolean(args.release));
|
|
226
229
|
const errors = log.diagnostics(report.diagnostics ?? []);
|
|
227
230
|
if (errors)
|
|
@@ -485,6 +488,7 @@ async function cmdDev(args) {
|
|
|
485
488
|
port,
|
|
486
489
|
pollMs,
|
|
487
490
|
target: targetRaw,
|
|
491
|
+
delivery: cfg.delivery,
|
|
488
492
|
signal: ac.signal,
|
|
489
493
|
});
|
|
490
494
|
try {
|
|
@@ -494,6 +498,9 @@ async function cmdDev(args) {
|
|
|
494
498
|
catch (err) {
|
|
495
499
|
if (ac.signal.aborted)
|
|
496
500
|
return 0;
|
|
501
|
+
// Config/plugin failures carry a product diagnostic: let the CLI boundary print once.
|
|
502
|
+
if (err && typeof err === 'object' && 'diagnostic' in err)
|
|
503
|
+
throw err;
|
|
497
504
|
log.error(String(err));
|
|
498
505
|
return 1;
|
|
499
506
|
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Child process for one dev config build cycle.
|
|
3
|
+
*
|
|
4
|
+
* Evaluates `vmz.config.*`, applies plugin contributions into the workspace,
|
|
5
|
+
* then writes a data-only report (no functions across the process boundary).
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { applyPlugins, loadVmzConfig } from '../workspace/plugin-host.js';
|
|
10
|
+
import { createWorkspace } from '../workspace/public-api.js';
|
|
11
|
+
function errorDetail(err) {
|
|
12
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13
|
+
const cause = err instanceof Error && err.cause ? `: ${errorDetail(err.cause)}` : '';
|
|
14
|
+
return `${message}${cause}`;
|
|
15
|
+
}
|
|
16
|
+
function writeReport(reportPath, report) {
|
|
17
|
+
let text;
|
|
18
|
+
try {
|
|
19
|
+
text = JSON.stringify(report, (_key, value) => (typeof value === 'function' ? undefined : value));
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
text = JSON.stringify({
|
|
23
|
+
ok: false,
|
|
24
|
+
configPath: null,
|
|
25
|
+
pluginPath: null,
|
|
26
|
+
plugins: [],
|
|
27
|
+
engines: {},
|
|
28
|
+
delivery: null,
|
|
29
|
+
error: {
|
|
30
|
+
code: 'vmz::config::load_failed',
|
|
31
|
+
severity: 'error',
|
|
32
|
+
args: { detail: `config report is not serializable: ${errorDetail(err)}` },
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
writeFileSync(reportPath, text);
|
|
37
|
+
}
|
|
38
|
+
const [inputPath, reportPath] = process.argv.slice(2);
|
|
39
|
+
if (!inputPath || !reportPath) {
|
|
40
|
+
process.stderr.write('config-cycle-worker: <input.json> <report.json> required\n');
|
|
41
|
+
process.exit(2);
|
|
42
|
+
}
|
|
43
|
+
const input = JSON.parse(readFileSync(inputPath, 'utf8'));
|
|
44
|
+
let ws = null;
|
|
45
|
+
try {
|
|
46
|
+
const cfg = await loadVmzConfig(input.project);
|
|
47
|
+
ws = createWorkspace({ root: input.project, outDir: input.outDir });
|
|
48
|
+
if (cfg.plugins.length) {
|
|
49
|
+
await applyPlugins(ws, cfg.plugins, { project: input.project, outDir: input.outDir, engines: cfg.engines });
|
|
50
|
+
}
|
|
51
|
+
writeReport(reportPath, {
|
|
52
|
+
ok: true,
|
|
53
|
+
configPath: cfg.path,
|
|
54
|
+
pluginPath: cfg.pluginPath,
|
|
55
|
+
plugins: cfg.plugins.map((p) => ({
|
|
56
|
+
name: p.manifest.name,
|
|
57
|
+
version: p.manifest.version,
|
|
58
|
+
stages: p.manifest.stages ?? [],
|
|
59
|
+
})),
|
|
60
|
+
engines: cfg.engines,
|
|
61
|
+
delivery: cfg.delivery ?? null,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
const diagnostic = err?.diagnostic ?? {
|
|
66
|
+
code: 'vmz::config::load_failed',
|
|
67
|
+
severity: 'error',
|
|
68
|
+
path: path.join(input.project, 'vmz.config.ts'),
|
|
69
|
+
args: { detail: errorDetail(err) },
|
|
70
|
+
};
|
|
71
|
+
writeReport(reportPath, {
|
|
72
|
+
ok: false,
|
|
73
|
+
configPath: null,
|
|
74
|
+
pluginPath: null,
|
|
75
|
+
plugins: [],
|
|
76
|
+
engines: {},
|
|
77
|
+
delivery: null,
|
|
78
|
+
error: diagnostic,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
ws?.dispose();
|
|
83
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev config build cycle.
|
|
3
|
+
*
|
|
4
|
+
* Each cycle runs config evaluation + plugin contribution in its own Node process.
|
|
5
|
+
* Functions and plugin objects stay in that process; the parent receives data only.
|
|
6
|
+
* Config/IPS changes restart the cycle: the old process is cancelled and awaited
|
|
7
|
+
* before a new one may write plugin artifacts.
|
|
8
|
+
*/
|
|
9
|
+
export interface ConfigCycleDiagnostic {
|
|
10
|
+
code: string;
|
|
11
|
+
severity?: 'error';
|
|
12
|
+
path?: string;
|
|
13
|
+
args?: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
export interface ConfigCycleReport {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
configPath: string | null;
|
|
18
|
+
pluginPath: string | null;
|
|
19
|
+
plugins: Array<{
|
|
20
|
+
name: string;
|
|
21
|
+
version: string;
|
|
22
|
+
stages: string[];
|
|
23
|
+
}>;
|
|
24
|
+
engines: Record<string, string>;
|
|
25
|
+
delivery: unknown;
|
|
26
|
+
error?: ConfigCycleDiagnostic;
|
|
27
|
+
}
|
|
28
|
+
export interface ConfigCycleOptions {
|
|
29
|
+
project: string;
|
|
30
|
+
outDir: string;
|
|
31
|
+
/** Built worker (`dist/dev/config-cycle-worker.js`); defaults next to this module. */
|
|
32
|
+
workerPath?: string;
|
|
33
|
+
nodePath?: string;
|
|
34
|
+
timeoutMs?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface ConfigCycle {
|
|
37
|
+
start(): Promise<ConfigCycleReport>;
|
|
38
|
+
restart(): Promise<ConfigCycleReport>;
|
|
39
|
+
cancel(): Promise<void>;
|
|
40
|
+
running(): boolean;
|
|
41
|
+
}
|
|
42
|
+
export declare class ConfigCycleCancelledError extends Error {
|
|
43
|
+
constructor();
|
|
44
|
+
}
|
|
45
|
+
export declare function createConfigCycle(options: ConfigCycleOptions): ConfigCycle;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev config build cycle.
|
|
3
|
+
*
|
|
4
|
+
* Each cycle runs config evaluation + plugin contribution in its own Node process.
|
|
5
|
+
* Functions and plugin objects stay in that process; the parent receives data only.
|
|
6
|
+
* Config/IPS changes restart the cycle: the old process is cancelled and awaited
|
|
7
|
+
* before a new one may write plugin artifacts.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'node:child_process';
|
|
10
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import os from 'node:os';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
export class ConfigCycleCancelledError extends Error {
|
|
15
|
+
constructor() {
|
|
16
|
+
super('vmz dev: config build process cancelled');
|
|
17
|
+
this.name = 'ConfigCycleCancelledError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function defaultWorkerPath() {
|
|
21
|
+
return fileURLToPath(new URL('./config-cycle-worker.js', import.meta.url));
|
|
22
|
+
}
|
|
23
|
+
function emptyReport(project, error) {
|
|
24
|
+
return {
|
|
25
|
+
ok: !error,
|
|
26
|
+
configPath: null,
|
|
27
|
+
pluginPath: null,
|
|
28
|
+
plugins: [],
|
|
29
|
+
engines: {},
|
|
30
|
+
delivery: null,
|
|
31
|
+
...(error ? { error } : {}),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function syntheticFailure(project, detail, configPath) {
|
|
35
|
+
return emptyReport(project, {
|
|
36
|
+
code: 'vmz::config::load_failed',
|
|
37
|
+
severity: 'error',
|
|
38
|
+
path: configPath ?? path.join(project, 'vmz.config.ts'),
|
|
39
|
+
args: { detail },
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
export function createConfigCycle(options) {
|
|
43
|
+
const project = path.resolve(options.project);
|
|
44
|
+
const outDir = path.resolve(options.outDir);
|
|
45
|
+
const workerPath = options.workerPath ?? defaultWorkerPath();
|
|
46
|
+
const nodePath = options.nodePath ?? process.env.VMZ_NODE ?? process.execPath;
|
|
47
|
+
const timeoutMs = options.timeoutMs ?? 120_000;
|
|
48
|
+
let child = null;
|
|
49
|
+
let exited = null;
|
|
50
|
+
let cancelled = false;
|
|
51
|
+
async function cancel() {
|
|
52
|
+
if (!child)
|
|
53
|
+
return;
|
|
54
|
+
cancelled = true;
|
|
55
|
+
const proc = child;
|
|
56
|
+
const done = exited;
|
|
57
|
+
try {
|
|
58
|
+
proc.kill();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
/* already gone */
|
|
62
|
+
}
|
|
63
|
+
if (done)
|
|
64
|
+
await Promise.race([done, new Promise((r) => setTimeout(r, 5000))]);
|
|
65
|
+
if (proc.exitCode == null && proc.signalCode == null) {
|
|
66
|
+
try {
|
|
67
|
+
proc.kill('SIGKILL');
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
/* already gone */
|
|
71
|
+
}
|
|
72
|
+
if (done)
|
|
73
|
+
await Promise.race([done, new Promise((r) => setTimeout(r, 2000))]);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async function start() {
|
|
77
|
+
if (child)
|
|
78
|
+
throw new Error('vmz dev: config build process already running');
|
|
79
|
+
if (!existsSync(workerPath)) {
|
|
80
|
+
throw new Error(`vmz dev: missing config cycle worker ${workerPath} — run build:js`);
|
|
81
|
+
}
|
|
82
|
+
cancelled = false;
|
|
83
|
+
const tmp = mkdtempSync(path.join(os.tmpdir(), 'vmz-config-cycle-'));
|
|
84
|
+
const inputPath = path.join(tmp, 'input.json');
|
|
85
|
+
const reportPath = path.join(tmp, 'report.json');
|
|
86
|
+
writeFileSync(inputPath, JSON.stringify({ project, outDir }));
|
|
87
|
+
let stderr = '';
|
|
88
|
+
let timedOut = false;
|
|
89
|
+
const proc = spawn(nodePath, [workerPath, inputPath, reportPath], {
|
|
90
|
+
cwd: project,
|
|
91
|
+
env: { ...process.env, VMZ_PROJECT_ROOT: project, VMZ_DIST: outDir },
|
|
92
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
93
|
+
windowsHide: true,
|
|
94
|
+
});
|
|
95
|
+
child = proc;
|
|
96
|
+
proc.stderr?.on('data', (chunk) => {
|
|
97
|
+
if (stderr.length < 16_384)
|
|
98
|
+
stderr += chunk.toString();
|
|
99
|
+
});
|
|
100
|
+
exited = new Promise((resolve) => {
|
|
101
|
+
proc.once('exit', (code, signal) => resolve({ code, signal }));
|
|
102
|
+
});
|
|
103
|
+
const timer = setTimeout(() => {
|
|
104
|
+
timedOut = true;
|
|
105
|
+
try {
|
|
106
|
+
proc.kill();
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
/* already gone */
|
|
110
|
+
}
|
|
111
|
+
}, timeoutMs);
|
|
112
|
+
const result = await exited;
|
|
113
|
+
clearTimeout(timer);
|
|
114
|
+
child = null;
|
|
115
|
+
exited = null;
|
|
116
|
+
let report = null;
|
|
117
|
+
if (!cancelled) {
|
|
118
|
+
try {
|
|
119
|
+
report = JSON.parse(readFileSync(reportPath, 'utf8'));
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
report = null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
126
|
+
if (cancelled)
|
|
127
|
+
throw new ConfigCycleCancelledError();
|
|
128
|
+
if (!report) {
|
|
129
|
+
const detail = timedOut
|
|
130
|
+
? `config build process timed out after ${timeoutMs}ms`
|
|
131
|
+
: `config build process exited with code ${String(result.code)}${result.signal ? ` (${result.signal})` : ''}${stderr.trim() ? `: ${stderr.trim().split('\n').slice(0, 4).join(' | ')}` : ''}`;
|
|
132
|
+
return syntheticFailure(project, detail);
|
|
133
|
+
}
|
|
134
|
+
if (!report.ok && report.error) {
|
|
135
|
+
if (!report.error.args?.detail && stderr.trim()) {
|
|
136
|
+
report.error.args = { ...(report.error.args ?? {}), detail: stderr.trim().split('\n').slice(0, 4).join(' | ') };
|
|
137
|
+
}
|
|
138
|
+
return report;
|
|
139
|
+
}
|
|
140
|
+
return report;
|
|
141
|
+
}
|
|
142
|
+
async function restart() {
|
|
143
|
+
await cancel();
|
|
144
|
+
return start();
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
start,
|
|
148
|
+
restart,
|
|
149
|
+
cancel,
|
|
150
|
+
running: () => child != null,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* 3. Soft reload failure → **auto-respawn** serve-host (fresh ESM graph), not "keep broken host".
|
|
11
11
|
*/
|
|
12
12
|
import { createWorkspace } from '../workspace/public-api.js';
|
|
13
|
+
import { type ConfigCycle } from './config-cycle.js';
|
|
13
14
|
interface DevSessionOptions {
|
|
14
15
|
project: string;
|
|
15
16
|
outDir: string;
|
|
@@ -17,6 +18,8 @@ interface DevSessionOptions {
|
|
|
17
18
|
port?: number;
|
|
18
19
|
pollMs?: number;
|
|
19
20
|
target?: 'browser' | 'mini-program-wechat';
|
|
21
|
+
/** Delivery snapshot evaluated by the config host; the package contract is prepared from it. */
|
|
22
|
+
delivery?: unknown;
|
|
20
23
|
signal?: AbortSignal;
|
|
21
24
|
createWorkspaceFn?: typeof createWorkspace;
|
|
22
25
|
spawnHostFn?: (opts: {
|
|
@@ -26,6 +29,14 @@ interface DevSessionOptions {
|
|
|
26
29
|
port: number;
|
|
27
30
|
}) => import('node:child_process').ChildProcess;
|
|
28
31
|
softReloadFn?: (host: string, port: number, payload?: object) => Promise<void>;
|
|
32
|
+
/** Override the detached config build process (tests). */
|
|
33
|
+
configCycleFn?: (opts: {
|
|
34
|
+
project: string;
|
|
35
|
+
outDir: string;
|
|
36
|
+
workerPath?: string;
|
|
37
|
+
}) => ConfigCycle;
|
|
38
|
+
/** Built config cycle worker path (defaults to `dist/dev/config-cycle-worker.js`). */
|
|
39
|
+
configCycleWorkerPath?: string;
|
|
29
40
|
}
|
|
30
41
|
export declare function createDevSession(options: DevSessionOptions): {
|
|
31
42
|
ws: any;
|
package/dist/dev/dev-session.js
CHANGED
|
@@ -14,13 +14,20 @@ import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
|
14
14
|
import path from 'node:path';
|
|
15
15
|
import { buildIntegratedDocuments, projectHasDocuments } from '../document/document-integrate.js';
|
|
16
16
|
import { createWorkspace, resolveNativePath } from '../workspace/public-api.js';
|
|
17
|
+
import { materializeWechatPackaging } from '../workspace/wechat-packaging.js';
|
|
17
18
|
import { emitLocaleRuntimeModules, localeHasErrors } from '../locale/locale-check.js';
|
|
18
19
|
import { log } from '../workspace/log.js';
|
|
19
|
-
import { coalesceRootBurst, collectDevWatchRoots, classifyWatchRoot, isDependencyPath, mergeDirtySets,
|
|
20
|
+
import { coalesceRootBurst, collectDevWatchRoots, classifyWatchRoot, isDependencyPath, mergeDirtySets, collectConfigDependencies, configCandidatePaths, configFingerprintMap, } from './dev-watch-roots.js';
|
|
21
|
+
import { createConfigCycle } from './config-cycle.js';
|
|
20
22
|
import { buildReloadPayload, filterGenerationIgnore, parseHmrPlan, registerWrittenOutputsIgnore, shouldSoftReload, staticRevisionFromArtifact, } from './dev-incremental.js';
|
|
21
23
|
import { diffFingerprints, fileFingerprintMap } from '../workspace/watch-diff.js';
|
|
22
24
|
/** Track serve-host so a failed/killed launcher cannot leave an orphan port. */
|
|
23
25
|
const DEV_HOST_PID = '.vmz-dev-host.pid';
|
|
26
|
+
function cycleFailure(report) {
|
|
27
|
+
const detail = report.error?.args?.detail ?? 'config build process failed';
|
|
28
|
+
const error = new Error(detail);
|
|
29
|
+
return report.error ? Object.assign(error, { diagnostic: report.error }) : error;
|
|
30
|
+
}
|
|
24
31
|
export function createDevSession(options) {
|
|
25
32
|
const project = options.project;
|
|
26
33
|
const outDir = options.outDir;
|
|
@@ -28,9 +35,13 @@ export function createDevSession(options) {
|
|
|
28
35
|
const port = options.port ?? 5173;
|
|
29
36
|
const pollMs = Math.max(50, options.pollMs ?? 300);
|
|
30
37
|
const wechatPreview = options.target === 'mini-program-wechat';
|
|
38
|
+
let delivery = options.delivery ?? null;
|
|
31
39
|
const createWs = options.createWorkspaceFn ?? createWorkspace;
|
|
32
40
|
const spawnHost = options.spawnHostFn ?? defaultSpawnHost;
|
|
33
41
|
const softReload = options.softReloadFn ?? defaultSoftReload;
|
|
42
|
+
const makeConfigCycle = options.configCycleFn ?? createConfigCycle;
|
|
43
|
+
const configCandidates = configCandidatePaths(project);
|
|
44
|
+
let configCycle = null;
|
|
34
45
|
const ws = createWs({ root: project, outDir });
|
|
35
46
|
let child = null;
|
|
36
47
|
let stopped = false;
|
|
@@ -119,6 +130,8 @@ export function createDevSession(options) {
|
|
|
119
130
|
}
|
|
120
131
|
let report;
|
|
121
132
|
try {
|
|
133
|
+
// Same prepared snapshot for this build cycle; native pack never reads config.
|
|
134
|
+
materializeWechatPackaging(project, delivery);
|
|
122
135
|
const raw = ws.lowerMiniprogramWechatPackaging();
|
|
123
136
|
report = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
124
137
|
}
|
|
@@ -191,15 +204,15 @@ export function createDevSession(options) {
|
|
|
191
204
|
if (!existsSync(src)) {
|
|
192
205
|
throw new Error(`vmz dev: missing src/ under ${project}`);
|
|
193
206
|
}
|
|
194
|
-
//
|
|
195
|
-
//
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
207
|
+
// Config evaluation + plugin contributions run in a detached build process.
|
|
208
|
+
// Functions/plugin objects never cross the boundary; only the data report does.
|
|
209
|
+
if (configCandidates.some((p) => existsSync(p))) {
|
|
210
|
+
configCycle = makeConfigCycle({ project, outDir, ...(options.configCycleWorkerPath ? { workerPath: options.configCycleWorkerPath } : {}) });
|
|
211
|
+
const report = await configCycle.start();
|
|
212
|
+
if (!report.ok)
|
|
213
|
+
throw cycleFailure(report);
|
|
214
|
+
delivery = report.delivery ?? delivery;
|
|
215
|
+
log.info(`config build process ready${report.plugins.length ? ` (${report.plugins.map((p) => p.name).join(', ')})` : ''}`);
|
|
203
216
|
}
|
|
204
217
|
log.info('initial build (N-API workspace, full)…');
|
|
205
218
|
const initialPair = planAndRebuild();
|
|
@@ -238,7 +251,14 @@ export function createDevSession(options) {
|
|
|
238
251
|
const designsRoot = path.join(project, 'designs');
|
|
239
252
|
const watched = collectDevWatchRoots({ project, outDir });
|
|
240
253
|
const publicRoot = watched.publicRoot;
|
|
241
|
-
|
|
254
|
+
/** Candidate config files plus their local reachable deps; refreshed after each cycle. */
|
|
255
|
+
const refreshConfigPaths = () => {
|
|
256
|
+
const deps = configCandidates
|
|
257
|
+
.filter((p) => existsSync(p))
|
|
258
|
+
.flatMap((p) => collectConfigDependencies(p, project));
|
|
259
|
+
return [...new Set([...configCandidates, ...deps])];
|
|
260
|
+
};
|
|
261
|
+
let configPaths = refreshConfigPaths();
|
|
242
262
|
/** @type {string[]} */
|
|
243
263
|
const watchRoots = [...watched.roots];
|
|
244
264
|
/** @type {string[]} */
|
|
@@ -359,14 +379,66 @@ export function createDevSession(options) {
|
|
|
359
379
|
continue;
|
|
360
380
|
}
|
|
361
381
|
if (batch.configDirty) {
|
|
362
|
-
log.info('vmz.config change detected —
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
382
|
+
log.info('vmz.config change detected — restarting the config build process…');
|
|
383
|
+
let cycleReport = null;
|
|
384
|
+
if (configCandidates.some((p) => existsSync(p))) {
|
|
385
|
+
let failure = null;
|
|
386
|
+
try {
|
|
387
|
+
if (!configCycle) {
|
|
388
|
+
configCycle = makeConfigCycle({
|
|
389
|
+
project,
|
|
390
|
+
outDir,
|
|
391
|
+
...(options.configCycleWorkerPath ? { workerPath: options.configCycleWorkerPath } : {}),
|
|
392
|
+
});
|
|
393
|
+
cycleReport = await configCycle.start();
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
// Old process is cancelled and awaited before the new one writes artifacts.
|
|
397
|
+
cycleReport = await configCycle.restart();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
catch (err) {
|
|
401
|
+
failure = err instanceof Error ? err : new Error(String(err));
|
|
402
|
+
}
|
|
403
|
+
configPaths = refreshConfigPaths();
|
|
404
|
+
configFingerprints = configFingerprintMap(configPaths);
|
|
405
|
+
commitFingerprints();
|
|
406
|
+
if (failure) {
|
|
407
|
+
log.warn(`config build process restart failed: ${failure.message}`);
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
if (cycleReport && !cycleReport.ok) {
|
|
411
|
+
if (cycleReport.error)
|
|
412
|
+
log.diagnostic(cycleReport.error);
|
|
413
|
+
else
|
|
414
|
+
log.error('config build process failed');
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
if (cycleReport)
|
|
418
|
+
delivery = cycleReport.delivery ?? delivery;
|
|
419
|
+
}
|
|
420
|
+
else if (configCycle) {
|
|
421
|
+
await configCycle.cancel();
|
|
422
|
+
configCycle = null;
|
|
423
|
+
configPaths = refreshConfigPaths();
|
|
424
|
+
configFingerprints = configFingerprintMap(configPaths);
|
|
425
|
+
commitFingerprints();
|
|
426
|
+
log.warn('vmz.config removed — config build process stopped, last artifacts kept');
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
configFingerprints = configFingerprintMap(configPaths);
|
|
431
|
+
commitFingerprints();
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
366
434
|
const report = rebuild();
|
|
367
435
|
if (printReport(report, 'rebuild')) {
|
|
368
436
|
lastOutputRevision = report.outputRevision ?? report.output_revision ?? null;
|
|
369
437
|
await emitPublicAndTrack();
|
|
438
|
+
if (wechatPreview)
|
|
439
|
+
packWechatPreview();
|
|
440
|
+
else
|
|
441
|
+
await respawnHost('config-changed');
|
|
370
442
|
}
|
|
371
443
|
continue;
|
|
372
444
|
}
|
|
@@ -605,6 +677,8 @@ export function createDevSession(options) {
|
|
|
605
677
|
stopped = true;
|
|
606
678
|
killChild(child);
|
|
607
679
|
child = null;
|
|
680
|
+
await configCycle?.cancel().catch(() => { });
|
|
681
|
+
configCycle = null;
|
|
608
682
|
clearDevHostPid(outDir, null);
|
|
609
683
|
try {
|
|
610
684
|
ws.dispose();
|
|
@@ -7,8 +7,15 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/** Author-facing vs generated dev input bucket. */
|
|
9
9
|
export type DevInputKind = 'author' | 'dependency' | 'public' | 'devControl' | 'locales' | 'docs' | 'designs' | 'other';
|
|
10
|
+
/** All supported `vmz.config.*` candidate paths, existing or not (so creation is detected). */
|
|
11
|
+
export declare function configCandidatePaths(project: string): string[];
|
|
10
12
|
/** `vmz.config.*` at project root (devControl). */
|
|
11
13
|
export declare function collectDevConfigPaths(project: string): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Reachable local ESM dependencies of a config file (bounded, project-root only).
|
|
16
|
+
* These changes restart the dev config build process.
|
|
17
|
+
*/
|
|
18
|
+
export declare function collectConfigDependencies(configPath: string, project: string): string[];
|
|
12
19
|
/** Fingerprint map for explicit config files (not directory walks). */
|
|
13
20
|
export declare function configFingerprintMap(configPaths: string[]): Map<string, string>;
|
|
14
21
|
export interface DirtySet {
|
|
@@ -8,11 +8,74 @@
|
|
|
8
8
|
import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { diffFingerprints, fileFingerprintMap } from '../workspace/watch-diff.js';
|
|
11
|
-
const CONFIG_BASENAMES = ['vmz.config.ts', 'vmz.config.js', 'vmz.config.mjs', 'vmz.config.cjs'];
|
|
11
|
+
const CONFIG_BASENAMES = ['vmz.config.ts', 'vmz.config.mts', 'vmz.config.js', 'vmz.config.mjs', 'vmz.config.cjs'];
|
|
12
|
+
const LOCAL_MODULE_EXTENSIONS = ['.ts', '.mts', '.js', '.mjs', '.cts', '.cjs'];
|
|
13
|
+
/** All supported `vmz.config.*` candidate paths, existing or not (so creation is detected). */
|
|
14
|
+
export function configCandidatePaths(project) {
|
|
15
|
+
const root = path.resolve(project);
|
|
16
|
+
return CONFIG_BASENAMES.map((name) => path.join(root, name));
|
|
17
|
+
}
|
|
12
18
|
/** `vmz.config.*` at project root (devControl). */
|
|
13
19
|
export function collectDevConfigPaths(project) {
|
|
20
|
+
return configCandidatePaths(project).filter((p) => existsSync(p));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Reachable local ESM dependencies of a config file (bounded, project-root only).
|
|
24
|
+
* These changes restart the dev config build process.
|
|
25
|
+
*/
|
|
26
|
+
export function collectConfigDependencies(configPath, project) {
|
|
14
27
|
const root = path.resolve(project);
|
|
15
|
-
|
|
28
|
+
const underRoot = (file) => file === root || file.startsWith(root + path.sep);
|
|
29
|
+
const seen = new Set();
|
|
30
|
+
const out = [];
|
|
31
|
+
const visit = (file, depth) => {
|
|
32
|
+
if (depth > 24 || seen.size > 200 || !existsSync(file) || !underRoot(file))
|
|
33
|
+
return;
|
|
34
|
+
if (seen.has(file))
|
|
35
|
+
return;
|
|
36
|
+
seen.add(file);
|
|
37
|
+
let text;
|
|
38
|
+
try {
|
|
39
|
+
text = readFileSync(file, 'utf8');
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const specs = new Set();
|
|
45
|
+
for (const match of text.matchAll(/\b(?:import|export)\s+(?:[^'";]*?\s+from\s+)?['"]([^'"]+)['"]/g)) {
|
|
46
|
+
if (match[1])
|
|
47
|
+
specs.add(match[1]);
|
|
48
|
+
}
|
|
49
|
+
for (const match of text.matchAll(/\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/g)) {
|
|
50
|
+
if (match[1])
|
|
51
|
+
specs.add(match[1]);
|
|
52
|
+
}
|
|
53
|
+
for (const spec of specs) {
|
|
54
|
+
if (!spec.startsWith('.'))
|
|
55
|
+
continue;
|
|
56
|
+
const base = path.resolve(path.dirname(file), spec);
|
|
57
|
+
const candidates = [
|
|
58
|
+
base,
|
|
59
|
+
...LOCAL_MODULE_EXTENSIONS.map((ext) => base + ext),
|
|
60
|
+
...LOCAL_MODULE_EXTENSIONS.map((ext) => path.join(base, `index${ext}`)),
|
|
61
|
+
];
|
|
62
|
+
for (const candidate of candidates) {
|
|
63
|
+
try {
|
|
64
|
+
if (existsSync(candidate) && statSync(candidate).isFile()) {
|
|
65
|
+
if (!seen.has(candidate))
|
|
66
|
+
out.push(candidate);
|
|
67
|
+
visit(candidate, depth + 1);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
/* keep looking */
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
visit(path.resolve(configPath), 0);
|
|
78
|
+
return out;
|
|
16
79
|
}
|
|
17
80
|
/** Fingerprint map for explicit config files (not directory walks). */
|
|
18
81
|
export function configFingerprintMap(configPaths) {
|
|
@@ -9,6 +9,8 @@ import { resolveDocumentsRoot } from './document-check.js';
|
|
|
9
9
|
import { pageHtmlRel } from './document-enrich.js';
|
|
10
10
|
import { loadLocalesRouting } from './document-routing-config.js';
|
|
11
11
|
import { ensureLocaleImportsRewritten } from '../locale/locale-check.js';
|
|
12
|
+
import { ensureRuntimeCompanions } from '../workspace/pack.js';
|
|
13
|
+
import { resolveCoreRuntimeDist } from '../workspace/runtime-dist.js';
|
|
12
14
|
import { log } from '../workspace/log.js';
|
|
13
15
|
import { requireNativeAddon } from '../workspace/native-addon.js';
|
|
14
16
|
export function projectHasDocuments(projectRoot) {
|
|
@@ -30,6 +32,10 @@ export async function buildIntegratedDocuments(opts) {
|
|
|
30
32
|
log.error(locales.error || 'locale import rewrite incomplete');
|
|
31
33
|
return { ok: false, error: locales.error || 'locale rewrite', pages: 0 };
|
|
32
34
|
}
|
|
35
|
+
// Document layout chunks import the delivery runtime (dom-core.js) at mount
|
|
36
|
+
// time, but pack only materializes it afterwards. Ensure companions first so
|
|
37
|
+
// a clean or partially-written outDir does not fail with an opaque module error.
|
|
38
|
+
ensureRuntimeCompanions(outDir, resolveCoreRuntimeDist());
|
|
33
39
|
const result = await buildDocuments({
|
|
34
40
|
projectRoot,
|
|
35
41
|
outDir,
|
|
@@ -1,36 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Document — resolve engines.markdown via the official plugin runtime.
|
|
2
|
+
* Document — resolve engines.markdown via the official plugin runtime export.
|
|
3
3
|
*/
|
|
4
|
-
import { createRequire } from 'node:module';
|
|
5
|
-
import { existsSync } from 'node:fs';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
import { fileURLToPath } from 'node:url';
|
|
8
|
-
import { importMaybeTs } from '../workspace/plugin-host.js';
|
|
9
|
-
const require = createRequire(import.meta.url);
|
|
10
4
|
export async function resolveMarkdownEngine(opts = {}) {
|
|
11
5
|
const id = opts.engines?.markdown || 'markdown-it';
|
|
12
6
|
if (id !== 'markdown-it') {
|
|
13
7
|
throw new Error(`unsupported engines.markdown ${JSON.stringify(id)} (markdown-it only)`);
|
|
14
8
|
}
|
|
15
|
-
let
|
|
9
|
+
let mod;
|
|
16
10
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
// Public JS runtime export of the plugin package; never read the package directory.
|
|
12
|
+
mod = await import('@vmz/plugin-markdown-it/runtime');
|
|
19
13
|
}
|
|
20
|
-
catch {
|
|
21
|
-
// Developer mode: monorepo source checkout.
|
|
22
|
-
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
const fallback = path.resolve(here, '../../../plugins/vmz-plugin-markdown-it/runtime.ts');
|
|
24
|
-
if (existsSync(fallback))
|
|
25
|
-
runtimeFile = fallback;
|
|
26
|
-
}
|
|
27
|
-
if (!runtimeFile || !existsSync(runtimeFile)) {
|
|
14
|
+
catch (err) {
|
|
28
15
|
throw new Error('markdown engine needs `@vmz/plugin-markdown-it` (optional peer of `@vmz/vmz`).\n' +
|
|
29
|
-
' Install: pnpm add -D @vmz/plugin-markdown-it');
|
|
16
|
+
' Install: pnpm add -D @vmz/plugin-markdown-it', { cause: err });
|
|
30
17
|
}
|
|
31
|
-
const mod = await importMaybeTs(runtimeFile);
|
|
32
18
|
if (typeof mod.analyzeMarkdown !== 'function') {
|
|
33
|
-
throw new Error(
|
|
19
|
+
throw new Error('cannot load markdown engine markdown-it: runtime export is missing analyzeMarkdown');
|
|
34
20
|
}
|
|
35
21
|
return {
|
|
36
22
|
engine: id,
|
package/dist/workspace/log.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type DiagnosticLike = {
|
|
|
16
16
|
export type DiagnosticLogOptions = {
|
|
17
17
|
denyWarnings?: boolean;
|
|
18
18
|
level?: CliLogLevel;
|
|
19
|
+
locale?: string;
|
|
19
20
|
};
|
|
20
21
|
export declare const log: {
|
|
21
22
|
info(...args: unknown[]): void;
|
|
@@ -25,6 +26,7 @@ export declare const log: {
|
|
|
25
26
|
errorId(id: string, args?: Record<string, string>): void;
|
|
26
27
|
diagnostic(d: DiagnosticLike, opts?: {
|
|
27
28
|
level?: CliLogLevel;
|
|
29
|
+
locale?: string;
|
|
28
30
|
}): boolean;
|
|
29
31
|
/** Failing count: errors, and warnings when `denyWarnings` (independent of print level). */
|
|
30
32
|
diagnostics(diagnostics: DiagnosticLike[] | null | undefined, opts?: DiagnosticLogOptions): number;
|
package/dist/workspace/log.js
CHANGED
|
@@ -38,7 +38,7 @@ export const log = {
|
|
|
38
38
|
return false;
|
|
39
39
|
const hasCode = Boolean(d.code && String(d.code).length);
|
|
40
40
|
const code = hasCode ? String(d.code) : 'diag.message';
|
|
41
|
-
const locale = resolveVmzLocale();
|
|
41
|
+
const locale = opts.locale ?? resolveVmzLocale();
|
|
42
42
|
const catalog = loadCliCatalog(locale);
|
|
43
43
|
const path = d.path || '';
|
|
44
44
|
const style = getCliLogStyle();
|
|
@@ -68,7 +68,7 @@ export const log = {
|
|
|
68
68
|
const items = diagnostics ?? [];
|
|
69
69
|
const visible = items.filter((d) => diagnosticVisible(normalizeSeverity(d.severity), level));
|
|
70
70
|
for (let i = 0; i < visible.length; i += 1) {
|
|
71
|
-
this.diagnostic(visible[i], { level });
|
|
71
|
+
this.diagnostic(visible[i], { level, locale: opts.locale });
|
|
72
72
|
if (style === 'pretty' && i + 1 < visible.length)
|
|
73
73
|
console.error('');
|
|
74
74
|
}
|
|
@@ -4,11 +4,9 @@
|
|
|
4
4
|
import { contentHash, defineConfig, definePlugin } from '@vmz/plugin';
|
|
5
5
|
export { contentHash, defineConfig, definePlugin };
|
|
6
6
|
export declare const PLUGIN_PROTOCOL = "0.1.0";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*/
|
|
11
|
-
export declare function importMaybeTs(full: any): Promise<any>;
|
|
7
|
+
export declare const CONFIG_NAMES: string[];
|
|
8
|
+
export declare const CONFIG_LOAD_FAILED = "vmz::config::load_failed";
|
|
9
|
+
export declare const PLUGIN_ENTRY_INVALID = "vmz::plugin::invalid_entry";
|
|
12
10
|
/**
|
|
13
11
|
* Load `vmz.config.*` from project root (+ optional root `vmz.plugin.*`).
|
|
14
12
|
* @param {string} project
|
|
@@ -4,30 +4,57 @@
|
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { pathToFileURL } from 'node:url';
|
|
7
|
-
import { createJiti } from 'jiti';
|
|
8
7
|
import { PLUGIN_PROTOCOL as PLUGIN_PROTOCOL_PKG, contentHash, defineConfig, definePlugin } from '@vmz/plugin';
|
|
9
8
|
import { log } from './log.js';
|
|
10
9
|
import { resolveWorkspacePackages } from './packages.js';
|
|
11
10
|
export { contentHash, defineConfig, definePlugin };
|
|
12
11
|
export const PLUGIN_PROTOCOL = PLUGIN_PROTOCOL_PKG;
|
|
13
|
-
const CONFIG_NAMES = ['vmz.config.ts', 'vmz.config.mts', 'vmz.config.mjs', 'vmz.config.js'];
|
|
12
|
+
export const CONFIG_NAMES = ['vmz.config.ts', 'vmz.config.mts', 'vmz.config.mjs', 'vmz.config.js'];
|
|
14
13
|
const ROOT_PLUGIN_NAMES = ['vmz.plugin.ts', 'vmz.plugin.mts', 'vmz.plugin.mjs', 'vmz.plugin.js'];
|
|
14
|
+
export const CONFIG_LOAD_FAILED = 'vmz::config::load_failed';
|
|
15
|
+
export const PLUGIN_ENTRY_INVALID = 'vmz::plugin::invalid_entry';
|
|
15
16
|
/**
|
|
17
|
+
* Load an ES module through the Node host (native `import()`).
|
|
18
|
+
* Project config and plugin entries must be erasable TS or JS: the host never
|
|
19
|
+
* runs a runtime TypeScript transpiler.
|
|
16
20
|
* @param {string} full
|
|
17
21
|
* @returns {Promise<any>}
|
|
18
22
|
*/
|
|
19
|
-
|
|
20
|
-
const ext = path.extname(full).toLowerCase();
|
|
21
|
-
if (ext === '.ts' || ext === '.mts') {
|
|
22
|
-
const jiti = createJiti(import.meta.url, {
|
|
23
|
-
interopDefault: true,
|
|
24
|
-
moduleCache: false,
|
|
25
|
-
});
|
|
26
|
-
return jiti(full);
|
|
27
|
-
}
|
|
23
|
+
async function importHostModule(full) {
|
|
28
24
|
const mod = await import(pathToFileURL(full).href);
|
|
29
25
|
return mod.default ?? mod;
|
|
30
26
|
}
|
|
27
|
+
function errorDetail(err) {
|
|
28
|
+
const parts = [];
|
|
29
|
+
let cur = err;
|
|
30
|
+
for (let i = 0; cur && i < 4; i += 1) {
|
|
31
|
+
const message = cur instanceof Error ? cur.message : String(cur);
|
|
32
|
+
if (message && !parts.includes(message))
|
|
33
|
+
parts.push(message);
|
|
34
|
+
cur = cur && typeof cur === 'object' && 'cause' in cur ? cur.cause : null;
|
|
35
|
+
}
|
|
36
|
+
return parts.join(' ← ') || 'unknown error';
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build a host error carrying a product diagnostic (one print at the CLI boundary).
|
|
40
|
+
* @param {string} code
|
|
41
|
+
* @param {string} sourcePath
|
|
42
|
+
* @param {unknown} err
|
|
43
|
+
*/
|
|
44
|
+
function configDiagnosticError(code, sourcePath, err) {
|
|
45
|
+
const detail = errorDetail(err);
|
|
46
|
+
const error = new Error(detail);
|
|
47
|
+
if (err instanceof Error)
|
|
48
|
+
error.cause = err;
|
|
49
|
+
return Object.assign(error, {
|
|
50
|
+
diagnostic: {
|
|
51
|
+
code,
|
|
52
|
+
severity: 'error',
|
|
53
|
+
path: sourcePath,
|
|
54
|
+
args: { detail },
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
31
58
|
/**
|
|
32
59
|
* Load `vmz.config.*` from project root (+ optional root `vmz.plugin.*`).
|
|
33
60
|
* @param {string} project
|
|
@@ -61,7 +88,13 @@ export async function loadVmzConfig(project) {
|
|
|
61
88
|
if (!existsSync(full))
|
|
62
89
|
continue;
|
|
63
90
|
configPath = full;
|
|
64
|
-
|
|
91
|
+
let cfg;
|
|
92
|
+
try {
|
|
93
|
+
cfg = await importHostModule(full);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
throw configDiagnosticError(CONFIG_LOAD_FAILED, full, err);
|
|
97
|
+
}
|
|
65
98
|
const raw = cfg?.plugins ?? [];
|
|
66
99
|
engines = cfg?.engines && typeof cfg.engines === 'object' ? { ...cfg.engines } : {};
|
|
67
100
|
if (cfg?.delivery && typeof cfg.delivery === 'object') {
|
|
@@ -96,9 +129,11 @@ async function resolvePluginEntry(project, entry) {
|
|
|
96
129
|
let value = entry;
|
|
97
130
|
if (typeof value === 'string') {
|
|
98
131
|
const resolved = path.isAbsolute(value) ? value : path.join(project, value);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
132
|
+
try {
|
|
133
|
+
value = await importHostModule(resolved);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
throw configDiagnosticError(PLUGIN_ENTRY_INVALID, resolved, err);
|
|
102
137
|
}
|
|
103
138
|
}
|
|
104
139
|
value = await value;
|
|
@@ -106,7 +141,8 @@ async function resolvePluginEntry(project, entry) {
|
|
|
106
141
|
return value;
|
|
107
142
|
if (value?.name && value?.stages)
|
|
108
143
|
return definePlugin(value);
|
|
109
|
-
|
|
144
|
+
const sourcePath = typeof entry === 'string' ? (path.isAbsolute(entry) ? entry : path.join(project, entry)) : '';
|
|
145
|
+
throw configDiagnosticError(PLUGIN_ENTRY_INVALID, sourcePath, new Error(`invalid vmz plugin entry: ${String(entry)}`));
|
|
110
146
|
}
|
|
111
147
|
/**
|
|
112
148
|
* Collect + apply contribution batches for the given stages onto a Workspace.
|
|
@@ -46,6 +46,10 @@ export declare function lowerMiniprogramBindingEventJson(rootPath: string): stri
|
|
|
46
46
|
export declare function lowerMiniprogramStructureJson(rootPath: string): string;
|
|
47
47
|
export declare function lowerMiniprogramRouteServerStyleJson(rootPath: string): string;
|
|
48
48
|
export declare function lowerMiniprogramToolingDeployJson(rootPath: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Consume the prepared `dist/_vmz/wechat-packaging.json` snapshot.
|
|
51
|
+
* Callers that start from a config must `await prepareWechatPackaging(rootPath)` first.
|
|
52
|
+
*/
|
|
49
53
|
export declare function lowerMiniprogramWechatPackagingJson(rootPath: string): string;
|
|
50
54
|
export declare function lowerMiniprogramMultiAdapterJson(rootPath: string): string;
|
|
51
55
|
import { createMiniHost } from './mini-host.js';
|
|
@@ -99,7 +103,7 @@ export { CDN_POLICY_MANIFEST_SCHEMA, CDN_ADAPTER_PROJECTION_SCHEMA, CACHE_HTML,
|
|
|
99
103
|
export { SITE_DELIVERY_CONTRACT_SCHEMA, SITE_DELIVERY_RESOLUTION_SCHEMA, defineSite, normalizeSiteDelivery, normalizeSourceProbe, resolveSiteRelease, probeReleaseDirectory, emitSiteDelivery, } from './site-delivery.js';
|
|
100
104
|
export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging } from './embedded-packaging.js';
|
|
101
105
|
export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
|
|
102
|
-
export { WECHAT_PACKAGING_SCHEMA, WECHAT_PACKAGING_REL, wechatPackagingFromDelivery, materializeWechatPackaging } from './wechat-packaging.js';
|
|
106
|
+
export { WECHAT_PACKAGING_SCHEMA, WECHAT_PACKAGING_REL, wechatPackagingFromDelivery, materializeWechatPackaging, prepareWechatPackaging, } from './wechat-packaging.js';
|
|
103
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';
|
|
104
108
|
export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
|
|
105
109
|
export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
|
|
@@ -8,7 +8,6 @@ import path from 'node:path';
|
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { materializeServeHostRuntime, SERVE_HOST_RUNTIME_FILES } from '../host-materialize/serve-host-runtime.js';
|
|
10
10
|
import { resolveCoreRuntimeDist } from './runtime-dist.js';
|
|
11
|
-
import { materializeWechatPackaging } from './wechat-packaging.js';
|
|
12
11
|
export { resolveCoreRuntimeDist } from './runtime-dist.js';
|
|
13
12
|
export { loadHostRuntimeFilesManifest, serveHostRuntimeFilePairs } from '../host-materialize/host-runtime-files.js';
|
|
14
13
|
export { materializeServeHostRuntime, SERVE_HOST_RUNTIME_FILES } from '../host-materialize/serve-host-runtime.js';
|
|
@@ -125,25 +124,7 @@ export function createWorkspace(options) {
|
|
|
125
124
|
pluginProtocol: protocol.pluginProtocol,
|
|
126
125
|
},
|
|
127
126
|
});
|
|
128
|
-
|
|
129
|
-
const wrappedPack = () => {
|
|
130
|
-
materializeWechatPackaging(options.root);
|
|
131
|
-
return pack();
|
|
132
|
-
};
|
|
133
|
-
try {
|
|
134
|
-
ws.lowerMiniprogramWechatPackaging = wrappedPack;
|
|
135
|
-
return ws;
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
return new Proxy(ws, {
|
|
139
|
-
get(target, prop, receiver) {
|
|
140
|
-
if (prop === 'lowerMiniprogramWechatPackaging')
|
|
141
|
-
return wrappedPack;
|
|
142
|
-
const value = Reflect.get(target, prop, receiver);
|
|
143
|
-
return typeof value === 'function' ? value.bind(target) : value;
|
|
144
|
-
},
|
|
145
|
-
});
|
|
146
|
-
}
|
|
127
|
+
return ws;
|
|
147
128
|
}
|
|
148
129
|
/** frozen application composition protocol catalog. */
|
|
149
130
|
export function queryApplicationProtocolCatalog() {
|
|
@@ -183,9 +164,12 @@ export function lowerMiniprogramToolingDeployJson(rootPath) {
|
|
|
183
164
|
const native = loadNative();
|
|
184
165
|
return native.lowerMiniprogramToolingDeployJson(rootPath);
|
|
185
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Consume the prepared `dist/_vmz/wechat-packaging.json` snapshot.
|
|
169
|
+
* Callers that start from a config must `await prepareWechatPackaging(rootPath)` first.
|
|
170
|
+
*/
|
|
186
171
|
export function lowerMiniprogramWechatPackagingJson(rootPath) {
|
|
187
172
|
const native = loadNative();
|
|
188
|
-
materializeWechatPackaging(rootPath);
|
|
189
173
|
return native.lowerMiniprogramWechatPackagingJson(rootPath);
|
|
190
174
|
}
|
|
191
175
|
export function lowerMiniprogramMultiAdapterJson(rootPath) {
|
|
@@ -307,7 +291,7 @@ export { CDN_POLICY_MANIFEST_SCHEMA, CDN_ADAPTER_PROJECTION_SCHEMA, CACHE_HTML,
|
|
|
307
291
|
export { SITE_DELIVERY_CONTRACT_SCHEMA, SITE_DELIVERY_RESOLUTION_SCHEMA, defineSite, normalizeSiteDelivery, normalizeSourceProbe, resolveSiteRelease, probeReleaseDirectory, emitSiteDelivery, } from './site-delivery.js';
|
|
308
292
|
export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging } from './embedded-packaging.js';
|
|
309
293
|
export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
|
|
310
|
-
export { WECHAT_PACKAGING_SCHEMA, WECHAT_PACKAGING_REL, wechatPackagingFromDelivery, materializeWechatPackaging } from './wechat-packaging.js';
|
|
294
|
+
export { WECHAT_PACKAGING_SCHEMA, WECHAT_PACKAGING_REL, wechatPackagingFromDelivery, materializeWechatPackaging, prepareWechatPackaging, } from './wechat-packaging.js';
|
|
311
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';
|
|
312
296
|
export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
|
|
313
297
|
export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
|
|
@@ -16,8 +16,15 @@ interface WechatPackagingSpec {
|
|
|
16
16
|
}
|
|
17
17
|
export declare function wechatPackagingFromDelivery(delivery: unknown): WechatPackagingSpec;
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Write the WeChat packaging contract from an already-evaluated delivery snapshot.
|
|
20
|
+
* Sync by contract: the native packer must consume prepared data, never read a config.
|
|
21
|
+
* @param {string} project
|
|
22
|
+
* @param {unknown} delivery
|
|
23
|
+
*/
|
|
24
|
+
export declare function materializeWechatPackaging(project: string, delivery: unknown): WechatPackagingSpec;
|
|
25
|
+
/**
|
|
26
|
+
* Async host entry: evaluate `vmz.config.*` once, then prepare the packaging snapshot.
|
|
20
27
|
* @param {string} project
|
|
21
28
|
*/
|
|
22
|
-
export declare function
|
|
29
|
+
export declare function prepareWechatPackaging(project: string): Promise<WechatPackagingSpec>;
|
|
23
30
|
export {};
|
|
@@ -2,27 +2,13 @@
|
|
|
2
2
|
* Materialize `defineConfig({ delivery: { packaging: { wechat } } })` for wechat_pack.
|
|
3
3
|
* Pure data only. Writes `dist/_vmz/wechat-packaging.json` (not a second config entry).
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { mkdirSync } from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
|
-
import { createJiti } from 'jiti';
|
|
8
7
|
import { pickDeliveryPackaging } from '../delivery/delivery-profile.js';
|
|
9
8
|
import { writePrettyJsonFile } from './pretty-json.js';
|
|
9
|
+
import { loadVmzConfig } from './plugin-host.js';
|
|
10
10
|
export const WECHAT_PACKAGING_SCHEMA = 'vmz.target.wechat_packaging.v0';
|
|
11
11
|
export const WECHAT_PACKAGING_REL = 'dist/_vmz/wechat-packaging.json';
|
|
12
|
-
const CONFIG_NAMES = ['vmz.config.ts', 'vmz.config.mts', 'vmz.config.mjs', 'vmz.config.js'];
|
|
13
|
-
function loadConfigSync(project) {
|
|
14
|
-
for (const name of CONFIG_NAMES) {
|
|
15
|
-
const full = path.join(project, name);
|
|
16
|
-
if (!existsSync(full))
|
|
17
|
-
continue;
|
|
18
|
-
const jiti = createJiti(import.meta.url, {
|
|
19
|
-
interopDefault: true,
|
|
20
|
-
moduleCache: false,
|
|
21
|
-
});
|
|
22
|
-
return jiti(full);
|
|
23
|
-
}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
12
|
export function wechatPackagingFromDelivery(delivery) {
|
|
27
13
|
const diagnostics = [];
|
|
28
14
|
const packaging = pickDeliveryPackaging(delivery && typeof delivery === 'object' ? delivery : {}, diagnostics);
|
|
@@ -40,14 +26,23 @@ export function wechatPackagingFromDelivery(delivery) {
|
|
|
40
26
|
return out;
|
|
41
27
|
}
|
|
42
28
|
/**
|
|
43
|
-
*
|
|
29
|
+
* Write the WeChat packaging contract from an already-evaluated delivery snapshot.
|
|
30
|
+
* Sync by contract: the native packer must consume prepared data, never read a config.
|
|
44
31
|
* @param {string} project
|
|
32
|
+
* @param {unknown} delivery
|
|
45
33
|
*/
|
|
46
|
-
export function materializeWechatPackaging(project) {
|
|
47
|
-
const
|
|
48
|
-
const spec = wechatPackagingFromDelivery(cfg?.delivery);
|
|
34
|
+
export function materializeWechatPackaging(project, delivery) {
|
|
35
|
+
const spec = wechatPackagingFromDelivery(delivery);
|
|
49
36
|
const abs = path.join(project, WECHAT_PACKAGING_REL);
|
|
50
37
|
mkdirSync(path.dirname(abs), { recursive: true });
|
|
51
38
|
writePrettyJsonFile(abs, spec);
|
|
52
39
|
return spec;
|
|
53
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Async host entry: evaluate `vmz.config.*` once, then prepare the packaging snapshot.
|
|
43
|
+
* @param {string} project
|
|
44
|
+
*/
|
|
45
|
+
export async function prepareWechatPackaging(project) {
|
|
46
|
+
const cfg = await loadVmzConfig(project);
|
|
47
|
+
return materializeWechatPackaging(project, cfg.delivery);
|
|
48
|
+
}
|
package/locales/en-US/diag.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"diag.message": "{message}",
|
|
3
3
|
"diag.detail": "{detail}",
|
|
4
|
+
"commander::action_failed": "Command failed: {message}",
|
|
5
|
+
"commander::unknown_command": "Unknown command `{cmd}`.",
|
|
6
|
+
"commander::unknown_option": "Unknown option `{option}`.",
|
|
7
|
+
"commander::missing_option_value": "Missing value for option `{option}`.",
|
|
8
|
+
"commander::parse_failed": "Parse failed: {detail}",
|
|
4
9
|
|
|
5
10
|
"vmz::template::illegal_directive": "Illegal or unsupported directive in `<template>`: {detail}",
|
|
6
11
|
"vmz::template::parse_failed": "Failed to parse `<template>`: {detail}",
|
|
@@ -149,5 +154,7 @@
|
|
|
149
154
|
"vmz::target::mini_platform_private_schema": "{detail}",
|
|
150
155
|
"vmz::target::mini_shared_fork": "{detail}",
|
|
151
156
|
"vmz::target::mini_static_slice_catalog_only": "{detail}",
|
|
152
|
-
"vmz::target::mini_route_server_style_catalog_only": "{detail}"
|
|
157
|
+
"vmz::target::mini_route_server_style_catalog_only": "{detail}",
|
|
158
|
+
"vmz::config::load_failed": "failed to load project config: {detail}",
|
|
159
|
+
"vmz::plugin::invalid_entry": "invalid plugin entry: {detail}"
|
|
153
160
|
}
|
package/locales/zh-CN/diag.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"diag.message": "{message}",
|
|
3
3
|
"diag.detail": "{detail}",
|
|
4
|
+
"commander::action_failed": "命令执行失败:{message}",
|
|
4
5
|
|
|
5
6
|
"vmz::template::illegal_directive": "`<template>` 中存在非法或不支持的指令:{detail}",
|
|
6
7
|
"vmz::template::parse_failed": "解析 `<template>` 失败:{detail}",
|
|
@@ -149,5 +150,7 @@
|
|
|
149
150
|
"vmz::target::mini_platform_private_schema": "{detail}",
|
|
150
151
|
"vmz::target::mini_shared_fork": "{detail}",
|
|
151
152
|
"vmz::target::mini_static_slice_catalog_only": "{detail}",
|
|
152
|
-
"vmz::target::mini_route_server_style_catalog_only": "{detail}"
|
|
153
|
+
"vmz::target::mini_route_server_style_catalog_only": "{detail}",
|
|
154
|
+
"vmz::config::load_failed": "无法加载项目配置:{detail}",
|
|
155
|
+
"vmz::plugin::invalid_entry": "插件入口无效:{detail}"
|
|
153
156
|
}
|
package/package.json
CHANGED
|
@@ -3,24 +3,26 @@
|
|
|
3
3
|
"vmz": "./bin/vmz.js"
|
|
4
4
|
},
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@vmz/commander": "0.3.
|
|
7
|
-
"@vmz/core": "0.3.
|
|
8
|
-
"@vmz/diagnostic": "0.3.
|
|
9
|
-
"@vmz/plugin": "0.3.
|
|
10
|
-
"@vmz/protocol": "0.3.
|
|
11
|
-
"jiti": "^2.6.1"
|
|
6
|
+
"@vmz/commander": "0.3.7",
|
|
7
|
+
"@vmz/core": "0.3.7",
|
|
8
|
+
"@vmz/diagnostic": "0.3.7",
|
|
9
|
+
"@vmz/plugin": "0.3.7",
|
|
10
|
+
"@vmz/protocol": "0.3.7"
|
|
12
11
|
},
|
|
13
12
|
"description": "VMZ Node toolchain — N-API workspace session + CLI (publish name @vmz/vmz)",
|
|
14
13
|
"devDependencies": {
|
|
15
14
|
"@types/node": "^22.15.0",
|
|
16
|
-
"@vmz/plugin": "0.3.
|
|
17
|
-
"@vmz/plugin-katex": "0.3.
|
|
18
|
-
"@vmz/plugin-markdown-it": "0.3.
|
|
19
|
-
"@vmz/plugin-shiki": "0.3.
|
|
20
|
-
"@vmz/test": "0.3.
|
|
15
|
+
"@vmz/plugin": "0.3.7",
|
|
16
|
+
"@vmz/plugin-katex": "0.3.7",
|
|
17
|
+
"@vmz/plugin-markdown-it": "0.3.7",
|
|
18
|
+
"@vmz/plugin-shiki": "0.3.7",
|
|
19
|
+
"@vmz/test": "0.3.7",
|
|
21
20
|
"linkedom": "^0.18.13",
|
|
22
21
|
"typescript": "^5.8.3",
|
|
23
|
-
"vmz-plugin-conformance": "0.3.
|
|
22
|
+
"vmz-plugin-conformance": "0.3.7"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=24.12.0"
|
|
24
26
|
},
|
|
25
27
|
"exports": {
|
|
26
28
|
".": {
|
|
@@ -78,16 +80,16 @@
|
|
|
78
80
|
"main": "./dist/index.js",
|
|
79
81
|
"name": "@vmz/vmz",
|
|
80
82
|
"optionalDependencies": {
|
|
81
|
-
"@vmz/vmz-darwin-arm64": "0.3.
|
|
82
|
-
"@vmz/vmz-darwin-x64": "0.3.
|
|
83
|
-
"@vmz/vmz-linux-arm64": "0.3.
|
|
84
|
-
"@vmz/vmz-linux-x64": "0.3.
|
|
85
|
-
"@vmz/vmz-win32-arm64": "0.3.
|
|
86
|
-
"@vmz/vmz-win32-x64": "0.3.
|
|
83
|
+
"@vmz/vmz-darwin-arm64": "0.3.7",
|
|
84
|
+
"@vmz/vmz-darwin-x64": "0.3.7",
|
|
85
|
+
"@vmz/vmz-linux-arm64": "0.3.7",
|
|
86
|
+
"@vmz/vmz-linux-x64": "0.3.7",
|
|
87
|
+
"@vmz/vmz-win32-arm64": "0.3.7",
|
|
88
|
+
"@vmz/vmz-win32-x64": "0.3.7"
|
|
87
89
|
},
|
|
88
90
|
"peerDependencies": {
|
|
89
|
-
"@vmz/plugin-markdown-it": "0.3.
|
|
90
|
-
"@vmz/test": "0.3.
|
|
91
|
+
"@vmz/plugin-markdown-it": "0.3.7",
|
|
92
|
+
"@vmz/test": "0.3.7",
|
|
91
93
|
"typescript": "^5.8.3"
|
|
92
94
|
},
|
|
93
95
|
"peerDependenciesMeta": {
|
|
@@ -120,5 +122,5 @@
|
|
|
120
122
|
},
|
|
121
123
|
"type": "module",
|
|
122
124
|
"types": "./dist/index.d.ts",
|
|
123
|
-
"version": "0.3.
|
|
125
|
+
"version": "0.3.7"
|
|
124
126
|
}
|