@vmz/test 0.1.9 → 0.1.11

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.
@@ -2,9 +2,56 @@
2
2
  * Browser Host U2 — real VMZ serve-host lifecycle + RouteId → path resolution.
3
3
  */
4
4
  import { spawn } from 'node:child_process';
5
+ import { createRequire } from 'node:module';
5
6
  import fs from 'node:fs';
6
7
  import net from 'node:net';
7
8
  import path from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ const require = createRequire(import.meta.url);
11
+ /** Same discovery as `vmz serve` / conformance `serveHostChildEnv`. */
12
+ function resolveNativeNodePath() {
13
+ const { platform, arch } = process;
14
+ let triple = `${platform}-${arch}`;
15
+ if (platform === 'win32' && arch === 'x64')
16
+ triple = 'win32-x64-msvc';
17
+ else if (platform === 'win32' && arch === 'arm64')
18
+ triple = 'win32-arm64-msvc';
19
+ else if (platform === 'darwin' && arch === 'arm64')
20
+ triple = 'darwin-arm64';
21
+ else if (platform === 'darwin' && arch === 'x64')
22
+ triple = 'darwin-x64';
23
+ else if (platform === 'linux' && arch === 'x64')
24
+ triple = 'linux-x64-gnu';
25
+ else if (platform === 'linux' && arch === 'arm64')
26
+ triple = 'linux-arm64-gnu';
27
+ const short = triple === 'win32-x64-msvc'
28
+ ? 'win32-x64'
29
+ : triple === 'win32-arm64-msvc'
30
+ ? 'win32-arm64'
31
+ : triple === 'linux-x64-gnu'
32
+ ? 'linux-x64'
33
+ : triple === 'linux-arm64-gnu'
34
+ ? 'linux-arm64'
35
+ : triple;
36
+ const name = `@vmz/vmz-${short}`;
37
+ /** @type {string[]} */
38
+ const candidates = [];
39
+ try {
40
+ const pkgJson = require.resolve(`${name}/package.json`);
41
+ const dir = path.dirname(pkgJson);
42
+ candidates.push(path.join(dir, `vmz.${triple}.node`), path.join(dir, 'vmz.node'));
43
+ }
44
+ catch {
45
+ /* optional dep missing */
46
+ }
47
+ const here = path.dirname(fileURLToPath(import.meta.url));
48
+ candidates.push(path.join(here, '..', '..', '..', 'runtimes', `vmz-${short}`, `vmz.${triple}.node`), path.join(here, '..', '..', '..', 'runtimes', `vmz-${short}`, 'vmz.node'));
49
+ for (const p of candidates) {
50
+ if (fs.existsSync(p))
51
+ return path.resolve(p);
52
+ }
53
+ throw new Error(`serve host: vmz native addon not found for ${name}. Run pnpm napi:build\nLooked in:\n${candidates.map((c) => ` - ${c}`).join('\n')}`);
54
+ }
8
55
  function freePort() {
9
56
  return new Promise((resolve, reject) => {
10
57
  const s = net.createServer();
@@ -99,7 +146,13 @@ export async function startServeHost(outDir) {
99
146
  const port = await freePort();
100
147
  const child = spawn(process.execPath, [hostJs], {
101
148
  cwd: outDir,
102
- env: { ...process.env, VMZ_DIST: outDir, VMZ_HOST: '127.0.0.1', VMZ_PORT: String(port) },
149
+ env: {
150
+ ...process.env,
151
+ VMZ_DIST: outDir,
152
+ VMZ_HOST: '127.0.0.1',
153
+ VMZ_PORT: String(port),
154
+ VMZ_NATIVE_NODE: resolveNativeNodePath(),
155
+ },
103
156
  stdio: ['ignore', 'pipe', 'pipe'],
104
157
  });
105
158
  const kill = () => {
package/dist/browser.js CHANGED
@@ -16,6 +16,7 @@ import http from 'node:http';
16
16
  import net from 'node:net';
17
17
  import os from 'node:os';
18
18
  import path from 'node:path';
19
+ import { resolveComponentEntries } from '@vmz/core/component-registry';
19
20
  import { resolveChunkArtifacts } from './compile.js';
20
21
  import { createArtifactsDir, writeFailureEvidence, writeTimingOnly } from './browser-evidence.js';
21
22
  import { isServeHostManifest, resolveRoutePath, startServeHost } from './browser-serve.js';
@@ -304,8 +305,13 @@ export async function runBrowserManifest(manifest, ctx) {
304
305
  page = await browser.newPage();
305
306
  page.setDefaultTimeout(15000);
306
307
  page.on('console', (msg) => {
307
- if (msg.type() === 'error')
308
- consoleErrors.push(msg.text());
308
+ if (msg.type() !== 'error')
309
+ return;
310
+ const text = msg.text();
311
+ // Chrome also logs network 404s here; requestfailed gate carries URL + resource-type filters.
312
+ if (/Failed to load resource:.+404/i.test(text))
313
+ return;
314
+ consoleErrors.push(text);
309
315
  });
310
316
  page.on('pageerror', (err) => {
311
317
  consoleErrors.push(err instanceof Error ? err.message : String(err));
@@ -327,13 +333,18 @@ export async function runBrowserManifest(manifest, ctx) {
327
333
  }
328
334
  else {
329
335
  await page.goto(`${origin}/__vmz/harness`, { waitUntil: 'domcontentloaded' });
330
- const components = program.components && typeof program.components === 'object' ? program.components : {};
336
+ const explicitComponents = program.components && typeof program.components === 'object' ? program.components : undefined;
337
+ const registryStrict = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
338
+ const registryEntries = await resolveComponentEntries(ctx.outDir, explicitComponents, {
339
+ strict: registryStrict,
340
+ closureRoots: [chunkId.replace(/\\/g, '/')],
341
+ });
331
342
  const boot = await page.evaluate(async (cfg) => {
332
343
  const dom = await import(/* @vite-ignore */ `${cfg.origin}/vmz-dom.js`);
333
344
  const Comp = (await import(/* @vite-ignore */ `${cfg.origin}/${cfg.chunkPath}.client.js`)).default;
334
345
  const map = {};
335
- for (const [name, chunk] of Object.entries(cfg.components)) {
336
- map[name] = (await import(/* @vite-ignore */ `${cfg.origin}/${chunk}.client.js`)).default;
346
+ for (const { name, entry } of cfg.registry) {
347
+ map[name] = (await import(/* @vite-ignore */ `${cfg.origin}/${entry}`)).default;
337
348
  }
338
349
  if (Object.keys(map).length && typeof dom.registerComponents === 'function') {
339
350
  dom.registerComponents(map);
@@ -357,7 +368,7 @@ export async function runBrowserManifest(manifest, ctx) {
357
368
  }, {
358
369
  origin,
359
370
  chunkPath: chunkId.replace(/\\/g, '/'),
360
- components,
371
+ registry: registryEntries,
361
372
  });
362
373
  if (!boot?.ok) {
363
374
  fail(`browser boot: ${boot?.error || 'unknown'}`);
package/dist/logic.js CHANGED
@@ -5,6 +5,7 @@ import fs from 'node:fs';
5
5
  import path from 'node:path';
6
6
  import { pathToFileURL } from 'node:url';
7
7
  import { createRequire } from 'node:module';
8
+ import { createRenderHost } from '@vmz/core/render-host';
8
9
  import { resolveChunkArtifacts } from './compile.js';
9
10
  const require = createRequire(import.meta.url);
10
11
  function loadLinkedom() {
@@ -41,16 +42,13 @@ export async function createLogicHost(opts) {
41
42
  if (!Component?.__vmzDirect || typeof Component.__vmzCreate !== 'function') {
42
43
  throw new Error('logic host requires Direct __vmzCreate (rebuild with current compiler)');
43
44
  }
44
- if (opts.components && typeof dom.registerComponents === 'function') {
45
- const map = {};
46
- for (const [name, chunk] of Object.entries(opts.components)) {
47
- const cArts = resolveChunkArtifacts(opts.outDir, chunk);
48
- if (!cArts.clientPath)
49
- throw new Error(`registerComponents: missing ${chunk}.client.js`);
50
- map[name] = (await import(pathToFileURL(cArts.clientPath).href)).default;
51
- }
52
- dom.registerComponents(map);
53
- }
45
+ const strict = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
46
+ const renderHost = await createRenderHost(opts.outDir, {
47
+ strictDeployment: strict,
48
+ preload: 'none',
49
+ explicit: opts.components,
50
+ });
51
+ await renderHost.ensureComponents([opts.chunkId.replace(/\\/g, '/')]);
54
52
  if (typeof dom.__vmzPrecisionEnable === 'function') {
55
53
  dom.__vmzPrecisionEnable(true);
56
54
  }
package/dist/resume.js CHANGED
@@ -2,8 +2,8 @@
2
2
  * Resume host for `vmz test --mode resume` (/ first slice).
3
3
  * SSR shell → resume adopt → event patch; onMount must not run.
4
4
  */
5
- import path from 'node:path';
6
5
  import { pathToFileURL } from 'node:url';
6
+ import { createRenderHost } from '@vmz/core/render-host';
7
7
  import { resolveChunkArtifacts } from './compile.js';
8
8
  import { installHeadlessDocument } from './logic.js';
9
9
  export async function runResumeManifest(manifest, ctx) {
@@ -25,29 +25,24 @@ export async function runResumeManifest(manifest, ctx) {
25
25
  }
26
26
  installHeadlessDocument();
27
27
  globalThis.requestIdleCallback = (cb) => setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 1 }), 0);
28
- let dom;
28
+ const components = program.components && typeof program.components === 'object' ? program.components : undefined;
29
+ let renderHost;
29
30
  let Page;
31
+ let loaded = {};
30
32
  try {
31
- dom = await import(pathToFileURL(path.join(ctx.outDir, 'vmz-dom.js')).href);
33
+ renderHost = await createRenderHost(ctx.outDir, {
34
+ strictDeployment: process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true',
35
+ preload: 'none',
36
+ explicit: components,
37
+ });
38
+ loaded = await renderHost.ensureComponents([chunkId.replace(/\\/g, '/')]);
32
39
  Page = (await import(pathToFileURL(arts.clientPath).href)).default;
33
40
  }
34
41
  catch (e) {
35
42
  fail(`import dist: ${e instanceof Error ? e.message : String(e)}`);
36
43
  return { status: 'error', diagnostics, planId: null, programId };
37
44
  }
38
- const components = program.components && typeof program.components === 'object' ? program.components : undefined;
39
- const loaded = {};
40
- if (components) {
41
- for (const [name, chunk] of Object.entries(components)) {
42
- const cArts = resolveChunkArtifacts(ctx.outDir, chunk);
43
- if (!cArts.clientPath) {
44
- fail(`missing component ${chunk}`);
45
- continue;
46
- }
47
- loaded[name] = (await import(pathToFileURL(cArts.clientPath).href)).default;
48
- }
49
- dom.registerComponents(loaded);
50
- }
45
+ const dom = renderHost.dom;
51
46
  let html = '';
52
47
  let island = null;
53
48
  let inst = null;
package/dist/ssr.js CHANGED
@@ -2,8 +2,8 @@
2
2
  * SSR / hydrate / stream host for `vmz test --mode ssr` .
3
3
  * Same Direct schedule as production via linkedom + renderToString / renderToStream / hydrate.
4
4
  */
5
- import path from 'node:path';
6
5
  import { pathToFileURL } from 'node:url';
6
+ import { createRenderHost } from '@vmz/core/render-host';
7
7
  import { resolveChunkArtifacts } from './compile.js';
8
8
  import { installHeadlessDocument } from './logic.js';
9
9
  export async function runSsrManifest(manifest, ctx) {
@@ -24,29 +24,23 @@ export async function runSsrManifest(manifest, ctx) {
24
24
  return { status: 'failed', diagnostics, planId: null, programId };
25
25
  }
26
26
  installHeadlessDocument();
27
- let dom;
27
+ const components = program.components && typeof program.components === 'object' ? program.components : undefined;
28
+ let renderHost;
28
29
  let Component;
29
30
  try {
30
- dom = await import(pathToFileURL(path.join(ctx.outDir, 'vmz-dom.js')).href);
31
+ renderHost = await createRenderHost(ctx.outDir, {
32
+ strictDeployment: process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true',
33
+ preload: 'none',
34
+ explicit: components,
35
+ });
36
+ await renderHost.ensureComponents([chunkId.replace(/\\/g, '/')]);
31
37
  Component = (await import(pathToFileURL(arts.clientPath).href)).default;
32
38
  }
33
39
  catch (e) {
34
40
  fail(`import dist: ${e instanceof Error ? e.message : String(e)}`);
35
41
  return { status: 'error', diagnostics, planId: null, programId };
36
42
  }
37
- const components = program.components && typeof program.components === 'object' ? program.components : undefined;
38
- if (components) {
39
- const map = {};
40
- for (const [name, chunk] of Object.entries(components)) {
41
- const cArts = resolveChunkArtifacts(ctx.outDir, chunk);
42
- if (!cArts.clientPath) {
43
- fail(`missing component ${chunk}`);
44
- continue;
45
- }
46
- map[name] = (await import(pathToFileURL(cArts.clientPath).href)).default;
47
- }
48
- dom.registerComponents(map);
49
- }
43
+ const dom = renderHost.dom;
50
44
  let html = '';
51
45
  let streamChunks = [];
52
46
  let streamAborted = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/test",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "description": "VMZ native test protocol + Compile/Logic/Browser/SSR/Resume/Deployment hosts",
6
6
  "main": "./dist/index.js",
@@ -27,8 +27,8 @@
27
27
  "build": "tsc -p tsconfig.json"
28
28
  },
29
29
  "dependencies": {
30
- "@vmz/core": "0.1.9",
31
- "@vmz/protocol": "0.1.9",
30
+ "@vmz/core": "0.1.11",
31
+ "@vmz/protocol": "0.1.11",
32
32
  "linkedom": "^0.18.13",
33
33
  "puppeteer-core": "^24.11.2"
34
34
  },