From 24a1acdf5ba96c6032587450871f2ca87cc4d2ed Mon Sep 17 00:00:00 2001 From: shamspias Date: Sat, 18 Jul 2026 12:10:47 +0600 Subject: [PATCH] fix(ci): run the TS job on Node 22 and load node:sqlite lazily MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CLI reflects a database via the built-in node:sqlite, which was added in Node 22.5 — so cli.test.ts failed to load on the CI's Node 20 ("No such built-in module: node:sqlite"), which had been red since the CLI landed (M7.5d). - .github/workflows/ci.yml: the js job now runs on Node 22 (matching the CLI's real requirement), so node:sqlite is present and the suite passes. - packages/js/src/cli/cli.ts: node:sqlite is now loaded lazily via createRequire, so cli.js still imports on Node < 22 and only a database command errors — with a clear 'the reins CLI needs Node 22+' hint — instead of a raw module crash at import time. Verified: make js-check green — 152 tests (151 pass, 1 skip); the built bin still reflects a database (node:sqlite present) and reports the Node-22 hint when absent. --- .github/workflows/ci.yml | 3 ++- packages/js/src/cli/cli.ts | 30 ++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8713426..8f4fa9c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,8 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: "20" + # 22+: the CLI reflects a database via the built-in node:sqlite, added in 22.5. + node-version: "22" - name: Install deps run: make js-setup - name: Run the TS gate diff --git a/packages/js/src/cli/cli.ts b/packages/js/src/cli/cli.ts index cb3e17c..920e3df 100644 --- a/packages/js/src/cli/cli.ts +++ b/packages/js/src/cli/cli.ts @@ -1,4 +1,5 @@ -import { DatabaseSync } from 'node:sqlite'; +import { createRequire } from 'node:module'; +import type { DatabaseSync } from 'node:sqlite'; import type { Model } from '../model.js'; import type { BoundCapability } from '../capability.js'; import { Agent } from '../loop.js'; @@ -15,13 +16,38 @@ import { fromSqlite } from './sqlite.js'; /** A sink for one line of output. */ export type Writer = (line: string) => void; +type SqliteCtor = new (path: string) => DatabaseSync; +let cachedCtor: SqliteCtor | undefined; + +/** + * Load node:sqlite lazily, so the CLI module still imports on Node < 22 (where the + * built-in is absent) and only errors — with a clear hint — when a database command + * actually runs. node:sqlite was added in Node 22.5. + */ +function loadSqlite(): SqliteCtor { + if (cachedCtor) { + return cachedCtor; + } + try { + const req = createRequire(import.meta.url); + cachedCtor = (req('node:sqlite') as { DatabaseSync: SqliteCtor }).DatabaseSync; + return cachedCtor; + } catch { + throw new ReinsError( + 'the reins CLI needs Node 22+ (its built-in node:sqlite is unavailable)', + 'upgrade Node to 22 or newer, then retry', + ); + } +} + /** * Open a SQLite database from a URL: a bare path, `:memory:`, a `sqlite://` URL * (scheme stripped), or a `file:` URI (passed through). */ export function openDb(dbUrl: string): DatabaseSync { + const Ctor = loadSqlite(); // throws a clear Node-22 hint if node:sqlite is missing try { - return new DatabaseSync(sqlitePath(dbUrl)); + return new Ctor(sqlitePath(dbUrl)); } catch (e) { throw new ReinsError( `cannot open database: ${message(e)}`,