Compare commits

...

2 Commits

Author SHA1 Message Date
Diego Rodrigues de Sa e Souza
7fa65dcc8a Merge branch 'release/v3.8.50' into fix/pack-boot-sqljs-paths 2026-08-23 13:18:42 -03:00
Xiangzhe
6fb444ef64 fix(build): align pack-boot sql.js expectations with dependency-based packaging (#11242)
check:pack-artifact and check:pack-boot have been self-contradictory since
05/08, blocking the v3.8.50 publish in ci.yml (build:cli job) and
npm-publish.yml:

- check:pack-artifact FAILS any tarball path containing a node_modules
  segment (PACK_ARTIFACT_NEVER_ALLOWED_SEGMENTS; files[] also excludes
  "!**/node_modules/**").
- check:pack-boot REQUIRED sql.js under the vendored
  dist/node_modules/sql.js location — a path the tarball can never carry,
  so both gates could never be green at once.

The packaging model is now dependency-based: sql.js and node-machine-id
are declared `dependencies` (a clean install places them under
<packageRoot>/node_modules/), and better-sqlite3 is an optionalDependency
installed natively per platform (^13.0.2 — which also covers the
darwin-arm64 prebuild gap from #11242 by construction). The runtime
already resolves the WASM at <cwd>/node_modules/sql.js/dist/sql-wasm.wasm
(src/lib/db/adapters/sqljsAdapter.ts).

Changes:
- scripts/check/check-pack-boot.mjs: REQUIRED_SQLJS_RUNTIME_FILES now
  points at node_modules/sql.js/{package.json,dist/sql-wasm.js,
  dist/sql-wasm.wasm} — the dependency-installed location the clean-prefix
  install actually produces. REQUIRED_MACHINE_TOKEN_RUNTIME_FILES was
  already correct and is unchanged.
- bin/cli/runtime/sqliteRuntime.mjs: BETTER_SQLITE3_VERSION bumped
  ^12.10.1 -> ^13.0.2 to match optionalDependencies (the lazy runtime
  install was pulling the wrong major), and exported for the guard.
- tests/unit/pack-boot-runtime-paths.test.ts (new, TDD: RED -> GREEN):
  pins that (a) no pack-boot required path references a never-publishable
  vendored dist/<segment> location (driven by
  PACK_ARTIFACT_NEVER_ALLOWED_SEGMENTS), (b) sql.js/node-machine-id stay
  declared dependencies, (c) the lazy-install spec stays on the declared
  optionalDependency major.
- tests/unit/check-pack-boot.test.ts: the sql.js contract test pinned the
  old vendored path; updated to node_modules/sql.js/dist/sql-wasm.wasm.
  This is alignment to the real new contract (vendoring ended), not
  masking — the same test still asserts the find-missing behavior.

Electron is unaffected: the vendored dist/node_modules bundle still
exists for Electron packaging (postinstall.mjs and assembleStandalone.mjs
untouched).

Refs #11242
Refs #10296
2026-08-23 13:13:32 -03:00
4 changed files with 95 additions and 6 deletions

View File

@@ -6,7 +6,9 @@ import { pathToFileURL } from "node:url";
import { validateBinaryMagic, platformBinaryLabel } from "./magicBytes.mjs";
const RUNTIME_DIR = join(homedir(), ".omniroute", "runtime");
const BETTER_SQLITE3_VERSION = "better-sqlite3@^12.10.1";
// Exported so the packaging coherence guard (tests/unit/pack-boot-runtime-paths.test.ts)
// can assert this stays on the same major as optionalDependencies.better-sqlite3 (#11242).
export const BETTER_SQLITE3_VERSION = "better-sqlite3@^13.0.2";
let resolvedCached = null;

View File

@@ -26,10 +26,16 @@ const MAX_SERVER_OUTPUT_CHARS = 1_000_000;
const SQLJS_STARTUP_MARKER = "Pre-initializing sql.js WASM";
const DEFAULT_CLI_SALT = "omniroute-cli-auth-v1";
// Dependency-based packaging (#11242): the tarball can never contain a node_modules
// path (files[] has "!**/node_modules/**" and check:pack-artifact fails on the
// segment), so sql.js must be required where a clean `npm install` of the declared
// `dependencies` places it — <packageRoot>/node_modules/sql.js — NOT under the old
// vendored dist/node_modules location. The runtime resolves the WASM the same way
// (src/lib/db/adapters/sqljsAdapter.ts → <cwd>/node_modules/sql.js/dist/sql-wasm.wasm).
export const REQUIRED_SQLJS_RUNTIME_FILES = Object.freeze([
"dist/node_modules/sql.js/package.json",
"dist/node_modules/sql.js/dist/sql-wasm.js",
"dist/node_modules/sql.js/dist/sql-wasm.wasm",
"node_modules/sql.js/package.json",
"node_modules/sql.js/dist/sql-wasm.js",
"node_modules/sql.js/dist/sql-wasm.wasm",
]);
export const REQUIRED_MACHINE_TOKEN_RUNTIME_FILES = Object.freeze([

View File

@@ -71,10 +71,13 @@ test("installed package contract requires sql.js metadata, entrypoint, and WASM"
[]
);
present.delete(path.join("/pkg", "dist/node_modules/sql.js/dist/sql-wasm.wasm"));
// Dependency-based packaging (#11242): sql.js is a declared dependency, so the
// contract path is the npm-installed <packageRoot>/node_modules/sql.js location,
// never the old vendored dist/node_modules one (banned from the tarball).
present.delete(path.join("/pkg", "node_modules/sql.js/dist/sql-wasm.wasm"));
assert.deepEqual(
findMissingSqlJsRuntimeFiles("/pkg", (file) => present.has(file)),
["dist/node_modules/sql.js/dist/sql-wasm.wasm"]
["node_modules/sql.js/dist/sql-wasm.wasm"]
);
});

View File

@@ -0,0 +1,78 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import {
REQUIRED_MACHINE_TOKEN_RUNTIME_FILES,
REQUIRED_SQLJS_RUNTIME_FILES,
} from "../../scripts/check/check-pack-boot.mjs";
import { PACK_ARTIFACT_NEVER_ALLOWED_SEGMENTS } from "../../scripts/build/pack-artifact-policy.ts";
import * as sqliteRuntime from "../../bin/cli/runtime/sqliteRuntime.mjs";
// Coherence guard for the v3.8.50 publish blocker (#11242): check:pack-artifact
// FAILS any tarball path containing a node_modules segment (files[] excludes them
// via "!**/node_modules/**"), while check:pack-boot REQUIRED sql.js under the
// vendored dist/node_modules/ location — a path the tarball can never contain,
// so the two gates could never be green at the same time. The npm packaging
// model is now dependency-based: sql.js and node-machine-id are declared
// `dependencies` that a clean install places under <packageRoot>/node_modules/,
// and better-sqlite3 is an optionalDependency installed natively per platform.
// These tests pin that contract so neither gate can drift back into conflict.
const REPO_ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
const PKG = JSON.parse(readFileSync(path.join(REPO_ROOT, "package.json"), "utf8")) as {
dependencies?: Record<string, string>;
optionalDependencies?: Record<string, string>;
};
test("pack-boot required runtime files never reference a never-publishable vendored path", () => {
const requiredFiles = [...REQUIRED_SQLJS_RUNTIME_FILES, ...REQUIRED_MACHINE_TOKEN_RUNTIME_FILES];
assert.ok(requiredFiles.length > 0, "pack-boot must require at least one runtime file");
for (const requiredPath of requiredFiles) {
for (const segment of PACK_ARTIFACT_NEVER_ALLOWED_SEGMENTS) {
const vendoredPrefix = `dist/${segment}/`;
assert.ok(
!requiredPath.includes(vendoredPrefix),
`"${requiredPath}" lives under ${vendoredPrefix} — check:pack-artifact bans any ` +
`tarball path with a "${segment}" segment, so check:pack-boot must require the ` +
`dependency-installed location (node_modules/<pkg>) instead (#11242)`
);
}
}
});
test("sql.js and node-machine-id are declared runtime dependencies (npm installs them)", () => {
assert.ok(
PKG.dependencies?.["sql.js"],
"sql.js must stay in dependencies so a clean install provides node_modules/sql.js"
);
assert.ok(
PKG.dependencies?.["node-machine-id"],
"node-machine-id must stay in dependencies so a clean install provides node_modules/node-machine-id"
);
});
test("the lazy better-sqlite3 runtime install targets the declared optionalDependency major", () => {
const spec = (sqliteRuntime as Record<string, unknown>).BETTER_SQLITE3_VERSION;
assert.equal(
typeof spec,
"string",
"bin/cli/runtime/sqliteRuntime.mjs must export BETTER_SQLITE3_VERSION"
);
const declared = PKG.optionalDependencies?.["better-sqlite3"];
assert.ok(declared, "package.json must declare better-sqlite3 as an optionalDependency");
const majorOf = (versionSpec: string): number => {
const match = versionSpec.match(/(\d+)\./);
assert.ok(match, `"${versionSpec}" must contain a semver major`);
return Number(match[1]);
};
assert.equal(
majorOf(spec as string),
majorOf(declared),
`lazy runtime install "${spec}" drifted from optionalDependencies.better-sqlite3 ` +
`"${declared}" — the fallback install must track the same major (#11242)`
);
});