MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / createD1ExecutorDb

Function createD1ExecutorDb

apps/host-cloudflare/src/db/d1.ts:29–75  ·  view source on GitHub ↗
(
  db: D1Database,
  blobs: R2Bucket | undefined,
)

Source from the content-addressed store, hash-verified

27// ---------------------------------------------------------------------------
28
29export const createD1ExecutorDb = async (
30 db: D1Database,
31 blobs: R2Bucket | undefined,
32): Promise<ExecutorDbHandle> => {
33 const options = {
34 tables: collectTables(),
35 namespace: CLOUDFLARE_NAMESPACE,
36 version: CLOUDFLARE_SCHEMA_VERSION,
37 provider: "sqlite" as const,
38 };
39
40 const schema = createDrizzleRuntimeSchemaFromTables(options);
41 const drizzleDb = drizzle(db, { schema });
42
43 // D1 rejects SQL `BEGIN TRANSACTION` / `SAVEPOINT` (it requires the JS batch
44 // API), and the shared ensure wraps its DDL in a transaction when the handle
45 // exposes one. The bring-up is idempotent `CREATE TABLE IF NOT EXISTS`, so run
46 // it WITHOUT a transaction by handing the ensure a run-only view of the handle.
47 await ensureDrizzleRuntimeSchemaFromTables({ run: (query) => drizzleDb.run(query) }, options);
48 await runCloudflareDataMigrations(db, blobs);
49
50 // `interactiveTransactions: false` — D1 rejects interactive transactions, so
51 // the fuma adapter runs transaction callbacks directly (auto-commit per
52 // statement). Without this, every runtime write that wraps in a transaction
53 // (adding a source, etc.) emits `BEGIN` and 500s. libSQL keeps real
54 // transactions; D1 (same `provider: "sqlite"`) opts out here.
55 const { db: fumaDb, fuma } = createExecutorFumaDb(drizzleDb, {
56 ...options,
57 interactiveTransactions: false,
58 // D1 caps bound parameters at 100 per query; createMany batches to fit
59 // (otherwise a wide table like `tool` overflows with "too many SQL
60 // variables" when a source derives many tools).
61 maxBoundParameters: 100,
62 });
63
64 return {
65 db: fumaDb,
66 fuma,
67 // The D1 binding owns its own lifecycle; nothing to release.
68 close: async () => {},
69 // Multi-MB values (resolved OpenAPI specs, introspection snapshots) go
70 // through the blob seam straight to R2 — they never enter D1, which caps
71 // a value at ~1-2MB. Without a bucket bound, the executor falls back to
72 // the FumaDB blob table (small values only).
73 blobs: blobs ? makeR2BlobStore(blobs) : undefined,
74 };
75};

Callers 2

makeCloudflareAppFunction · 0.90
openSessionDbMethod · 0.90

Calls 6

makeR2BlobStoreFunction · 0.90
collectTablesFunction · 0.85
createExecutorFumaDbFunction · 0.85

Tested by

no test coverage detected