Skip to content

Commit a09aa95

Browse files
os-zhuangclaude
andauthored
fix(example-showcase): route external-datasource fixture through the sqlite fallback (#2890)
`setupShowcaseExternalDatasource` (run from the showcase app's `onEnable` at boot) built its MANAGED provisioning driver with a raw `new SqlDriver({ client: 'better-sqlite3' })`. `better-sqlite3` loads its native addon lazily at first query, so a `NODE_MODULE_VERSION` ABI mismatch (e.g. after a Node upgrade) threw `ERR_DLOPEN_FAILED` here — which propagated through `onEnable` -> `AppPlugin.start()` and bricked `plugin.app.com.example.showcase`, failing `pnpm dev` entirely, even though the default datasource had already stepped down to wasm SQLite. Every other sqlite construction site was hoisted onto the shared `resolveSqliteDriver` native -> wasm -> in-memory step-down (#2229); this fixture site was missed. Route it through the same helper so a native ABI/load failure degrades to wasm in dev (real SQL + on-disk persistence) instead of crashing boot, and still fails closed in production. Adds `@objectstack/service-datasource` (which exports `resolveSqliteDriver`) as a dependency of the example. Claude-Session: https://claude.ai/code/session_01UUWGgTT5s7XgBb2eLtzhfU Co-authored-by: Claude <noreply@anthropic.com>
1 parent 5caeaa4 commit a09aa95

3 files changed

Lines changed: 24 additions & 6 deletions

File tree

examples/app-showcase/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"@objectstack/connector-slack": "workspace:*",
2828
"@objectstack/driver-sql": "workspace:*",
2929
"@objectstack/runtime": "workspace:*",
30+
"@objectstack/service-datasource": "workspace:*",
3031
"@objectstack/spec": "workspace:*"
3132
},
3233
"devDependencies": {

examples/app-showcase/src/system/datasources/external-fixture.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.
22

3-
import { SqlDriver } from '@objectstack/driver-sql';
3+
import { resolveSqliteDriver } from '@objectstack/service-datasource';
44

55
/**
66
* Fixture provisioning for the external-datasource federation demo
@@ -11,6 +11,14 @@ import { SqlDriver } from '@objectstack/driver-sql';
1111
* driver — DDL allowed) so `os dev` needs no external server. It runs from the
1212
* stack's `onEnable` hook at boot.
1313
*
14+
* The MANAGED driver is built via the shared `resolveSqliteDriver` step-down
15+
* (#2229) rather than a raw `new SqlDriver({ client: 'better-sqlite3' })`: in dev
16+
* a native `better-sqlite3` ABI/load failure (e.g. a `NODE_MODULE_VERSION`
17+
* mismatch after a Node upgrade) steps down to wasm SQLite instead of throwing.
18+
* Without this, an ABI mismatch here crashed the whole `onEnable` hook —
19+
* bricking `plugin.app.<showcase>` boot even though the default datasource had
20+
* already fallen back to wasm.
21+
*
1422
* **It no longer registers a driver or syncs object schemas (ADR-0062 D8).** The
1523
* declared `external` datasource (see `showcase-external.datasource.ts`) now
1624
* AUTO-CONNECTS: at boot the runtime's `DatasourceConnectionService` builds the
@@ -71,11 +79,17 @@ interface OnEnableContext {
7179
* datasource auto-connects at boot (ADR-0062 D1/D8).
7280
*/
7381
export async function setupShowcaseExternalDatasource(ctx: OnEnableContext): Promise<void> {
74-
const fixture = new SqlDriver({
75-
client: 'better-sqlite3',
76-
connection: { filename: EXTERNAL_DB_FILE },
77-
useNullAsDefault: true,
78-
}) as unknown as {
82+
// Build the managed provisioning driver through the shared native → wasm →
83+
// in-memory step-down (#2229). In dev, a native better-sqlite3 ABI/load
84+
// failure steps down to wasm SQLite (real SQL + on-disk persistence) so the
85+
// fixture — and therefore `onEnable` / app-plugin boot — never crashes on a
86+
// `NODE_MODULE_VERSION` mismatch; in production it returns the native driver
87+
// unprobed (fail-closed), preserving the historical behavior.
88+
const resolved = await resolveSqliteDriver({
89+
filename: EXTERNAL_DB_FILE,
90+
warn: (m: string) => ctx.logger?.warn?.(m),
91+
});
92+
const fixture = resolved.driver as unknown as {
7993
name: string;
8094
connect: () => Promise<void>;
8195
disconnect: () => Promise<void>;

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)