@prisma/streams-server 0.1.1 → 0.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/streams-server",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Bun-only self-hosted Prisma Streams server.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,5 @@
1
+ export type HostRuntime = "bun" | "node";
2
+
3
+ export function detectHostRuntime(): HostRuntime {
4
+ return typeof (globalThis as any).Bun !== "undefined" || Boolean(process.versions?.bun) ? "bun" : "node";
5
+ }
@@ -1,13 +1,16 @@
1
1
  import { parentPort, workerData } from "node:worker_threads";
2
2
  import type { Config } from "../config.ts";
3
3
  import { SqliteDurableStore } from "../db/db.ts";
4
+ import type { HostRuntime } from "../runtime/host_runtime.ts";
5
+ import { setSqliteRuntimeOverride } from "../sqlite/adapter.ts";
4
6
  import { Segmenter, type SegmenterHooks, type SegmenterOptions } from "./segmenter.ts";
5
7
  import { initConsoleLogging } from "../util/log.ts";
6
8
 
7
9
  initConsoleLogging();
8
10
 
9
- const data = workerData as { config: Config; opts?: SegmenterOptions };
11
+ const data = workerData as { config: Config; hostRuntime?: HostRuntime; opts?: SegmenterOptions };
10
12
  const cfg = data.config;
13
+ setSqliteRuntimeOverride(data.hostRuntime ?? null);
11
14
  // The main server process initializes/migrates schema; workers should avoid
12
15
  // concurrent migrations on the same sqlite file.
13
16
  const db = new SqliteDurableStore(cfg.dbPath, { cacheBytes: cfg.sqliteCacheBytes, skipMigrations: true });
@@ -3,6 +3,7 @@ import { resolve } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { Worker } from "node:worker_threads";
5
5
  import type { Config } from "../config";
6
+ import { detectHostRuntime } from "../runtime/host_runtime.ts";
6
7
  import type { SegmenterHooks, SegmenterOptions } from "./segmenter";
7
8
 
8
9
  export type SegmenterController = {
@@ -63,6 +64,7 @@ export class SegmenterWorkerPool implements SegmenterController {
63
64
  const worker = new Worker(workerSpec, {
64
65
  workerData: {
65
66
  config: this.config,
67
+ hostRuntime: detectHostRuntime(),
66
68
  opts: this.opts,
67
69
  },
68
70
  type: "module",
@@ -1,3 +1,6 @@
1
+ import { createRequire } from "node:module";
2
+ import type { HostRuntime } from "../runtime/host_runtime.ts";
3
+ import { detectHostRuntime } from "../runtime/host_runtime.ts";
1
4
  import { dsError } from "../util/ds_error.ts";
2
5
  export interface SqliteStatement {
3
6
  get(...params: any[]): any;
@@ -149,16 +152,37 @@ class NodeDatabaseAdapter implements SqliteDatabase {
149
152
  }
150
153
 
151
154
  let openImpl: ((path: string) => SqliteDatabase) | null = null;
155
+ let openImplRuntime: HostRuntime | null = null;
156
+ let runtimeOverride: HostRuntime | null = null;
157
+ const require = createRequire(import.meta.url);
152
158
 
153
- if (typeof (globalThis as any).Bun !== "undefined") {
154
- const { Database } = await import("bun:sqlite");
155
- openImpl = (path: string) => new BunDatabaseAdapter(new Database(path));
156
- } else {
157
- const { DatabaseSync } = await import("node:sqlite");
158
- openImpl = (path: string) => new NodeDatabaseAdapter(new DatabaseSync(path));
159
+ function selectedRuntime(): HostRuntime {
160
+ return runtimeOverride ?? detectHostRuntime();
161
+ }
162
+
163
+ function buildOpenImpl(runtime: HostRuntime): (path: string) => SqliteDatabase {
164
+ if (runtime === "bun") {
165
+ const { Database } = require("bun:sqlite") as { Database: new (path: string) => any };
166
+ return (path: string) => new BunDatabaseAdapter(new Database(path));
167
+ }
168
+ const { DatabaseSync } = require("node:sqlite") as { DatabaseSync: new (path: string) => any };
169
+ return (path: string) => new NodeDatabaseAdapter(new DatabaseSync(path));
170
+ }
171
+
172
+ export function setSqliteRuntimeOverride(runtime: HostRuntime | null): void {
173
+ runtimeOverride = runtime;
174
+ if (runtimeOverride && openImplRuntime && runtimeOverride !== openImplRuntime) {
175
+ openImpl = null;
176
+ openImplRuntime = null;
177
+ }
159
178
  }
160
179
 
161
180
  export function openSqliteDatabase(path: string): SqliteDatabase {
181
+ const runtime = selectedRuntime();
182
+ if (!openImpl || openImplRuntime !== runtime) {
183
+ openImpl = buildOpenImpl(runtime);
184
+ openImplRuntime = runtime;
185
+ }
162
186
  if (!openImpl) throw dsError("sqlite adapter not initialized");
163
187
  return openImpl(path);
164
188
  }
@@ -2,6 +2,8 @@ import { parentPort, workerData } from "node:worker_threads";
2
2
  import { Result } from "better-result";
3
3
  import type { Config } from "../config.ts";
4
4
  import { SqliteDurableStore } from "../db/db.ts";
5
+ import type { HostRuntime } from "../runtime/host_runtime.ts";
6
+ import { setSqliteRuntimeOverride } from "../sqlite/adapter.ts";
5
7
  import { initConsoleLogging } from "../util/log.ts";
6
8
  import type { ProcessRequest } from "./worker_protocol.ts";
7
9
  import { interpretRecordToChanges } from "./engine.ts";
@@ -10,8 +12,11 @@ import { isTouchEnabled } from "./spec.ts";
10
12
 
11
13
  initConsoleLogging();
12
14
 
13
- const data = workerData as { config: Config };
15
+ const data = workerData as { config: Config; hostRuntime?: HostRuntime };
14
16
  const cfg = data.config;
17
+ // Bun worker_threads can miss the Bun globals that the main thread sees.
18
+ // Use the parent host runtime hint before the worker opens SQLite.
19
+ setSqliteRuntimeOverride(data.hostRuntime ?? null);
15
20
  // The main server process initializes/migrates schema; workers should avoid
16
21
  // concurrent migrations on the same sqlite file.
17
22
  const db = new SqliteDurableStore(cfg.dbPath, { cacheBytes: cfg.sqliteCacheBytes, skipMigrations: true });
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
4
4
  import { Worker } from "node:worker_threads";
5
5
  import { Result } from "better-result";
6
6
  import type { Config } from "../config";
7
+ import { detectHostRuntime } from "../runtime/host_runtime.ts";
7
8
  import type { ProcessRequest, ProcessResult, WorkerMessage } from "./worker_protocol";
8
9
  import { dsError } from "../util/ds_error.ts";
9
10
 
@@ -123,7 +124,7 @@ export class TouchInterpreterWorkerPool {
123
124
  }
124
125
 
125
126
  const worker = new Worker(workerSpec, {
126
- workerData: { config: this.cfg },
127
+ workerData: { config: this.cfg, hostRuntime: detectHostRuntime() },
127
128
  type: "module",
128
129
  smol: true,
129
130
  } as any);