@earendil-works/pi-durable 1.1.0 → 1.3.0
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/CHANGELOG.md +55 -0
- package/README.md +164 -11
- package/dist/codemode/codemode.d.ts +173 -0
- package/dist/codemode/codemode.d.ts.map +1 -0
- package/dist/codemode/codemode.js +886 -0
- package/dist/codemode/codemode.js.map +1 -0
- package/dist/codemode/describe.d.ts +38 -0
- package/dist/codemode/describe.d.ts.map +1 -0
- package/dist/codemode/describe.js +119 -0
- package/dist/codemode/describe.js.map +1 -0
- package/dist/codemode/index.d.ts +3 -0
- package/dist/codemode/index.d.ts.map +1 -0
- package/dist/codemode/index.js +3 -0
- package/dist/codemode/index.js.map +1 -0
- package/dist/codemode/models.d.ts +28 -0
- package/dist/codemode/models.d.ts.map +1 -0
- package/dist/codemode/models.js +231 -0
- package/dist/codemode/models.js.map +1 -0
- package/dist/codemode/output.d.ts +41 -0
- package/dist/codemode/output.d.ts.map +1 -0
- package/dist/codemode/output.js +167 -0
- package/dist/codemode/output.js.map +1 -0
- package/dist/env/index.d.ts +43 -0
- package/dist/env/index.d.ts.map +1 -1
- package/dist/env/index.js.map +1 -1
- package/dist/errors.d.ts +20 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +34 -5
- package/dist/errors.js.map +1 -1
- package/dist/harness/agent.d.ts +5 -2
- package/dist/harness/agent.d.ts.map +1 -1
- package/dist/harness/agent.js +69 -25
- package/dist/harness/agent.js.map +1 -1
- package/dist/harness/compaction.d.ts +6 -1
- package/dist/harness/compaction.d.ts.map +1 -1
- package/dist/harness/compaction.js +10 -7
- package/dist/harness/compaction.js.map +1 -1
- package/dist/harness/context.d.ts +5 -0
- package/dist/harness/context.d.ts.map +1 -1
- package/dist/harness/context.js +46 -12
- package/dist/harness/context.js.map +1 -1
- package/dist/harness/events.d.ts +35 -15
- package/dist/harness/events.d.ts.map +1 -1
- package/dist/harness/events.js +77 -23
- package/dist/harness/events.js.map +1 -1
- package/dist/harness/generation.d.ts +2 -0
- package/dist/harness/generation.d.ts.map +1 -1
- package/dist/harness/generation.js +31 -8
- package/dist/harness/generation.js.map +1 -1
- package/dist/harness/harness.d.ts +7 -0
- package/dist/harness/harness.d.ts.map +1 -1
- package/dist/harness/harness.js +53 -26
- package/dist/harness/harness.js.map +1 -1
- package/dist/harness/inbox.d.ts +16 -4
- package/dist/harness/inbox.d.ts.map +1 -1
- package/dist/harness/inbox.js +26 -3
- package/dist/harness/inbox.js.map +1 -1
- package/dist/harness/live.d.ts +74 -17
- package/dist/harness/live.d.ts.map +1 -1
- package/dist/harness/live.js +66 -14
- package/dist/harness/live.js.map +1 -1
- package/dist/harness/scheduler.d.ts +18 -5
- package/dist/harness/scheduler.d.ts.map +1 -1
- package/dist/harness/scheduler.js +696 -163
- package/dist/harness/scheduler.js.map +1 -1
- package/dist/harness/submissions.d.ts +7 -4
- package/dist/harness/submissions.d.ts.map +1 -1
- package/dist/harness/submissions.js +32 -13
- package/dist/harness/submissions.js.map +1 -1
- package/dist/harness/task-graph.d.ts +1 -1
- package/dist/harness/task-graph.d.ts.map +1 -1
- package/dist/harness/task-graph.js +15 -10
- package/dist/harness/task-graph.js.map +1 -1
- package/dist/harness/tool.d.ts +45 -5
- package/dist/harness/tool.d.ts.map +1 -1
- package/dist/harness/tool.js +378 -63
- package/dist/harness/tool.js.map +1 -1
- package/dist/harness/types.d.ts +153 -13
- package/dist/harness/types.d.ts.map +1 -1
- package/dist/harness/types.js.map +1 -1
- package/dist/harness/util.d.ts +6 -1
- package/dist/harness/util.d.ts.map +1 -1
- package/dist/harness/util.js +5 -2
- package/dist/harness/util.js.map +1 -1
- package/dist/harness/view.d.ts +6 -2
- package/dist/harness/view.d.ts.map +1 -1
- package/dist/harness/view.js +22 -12
- package/dist/harness/view.js.map +1 -1
- package/dist/images/cloudflare.d.ts +4 -0
- package/dist/images/cloudflare.d.ts.map +1 -0
- package/dist/images/cloudflare.js +9 -0
- package/dist/images/cloudflare.js.map +1 -0
- package/dist/images/exif.d.ts +3 -0
- package/dist/images/exif.d.ts.map +1 -0
- package/dist/images/exif.js +71 -0
- package/dist/images/exif.js.map +1 -0
- package/dist/images/index.d.ts +18 -0
- package/dist/images/index.d.ts.map +1 -0
- package/dist/images/index.js +125 -0
- package/dist/images/index.js.map +1 -0
- package/dist/images/node-worker.d.ts +17 -0
- package/dist/images/node-worker.d.ts.map +1 -0
- package/dist/images/node-worker.js +16 -0
- package/dist/images/node-worker.js.map +1 -0
- package/dist/images/node.d.ts +21 -0
- package/dist/images/node.d.ts.map +1 -0
- package/dist/images/node.js +121 -0
- package/dist/images/node.js.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/search.d.ts +13 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +85 -0
- package/dist/search.js.map +1 -0
- package/dist/session/observation.d.ts +10 -3
- package/dist/session/observation.d.ts.map +1 -1
- package/dist/session/observation.js +24 -34
- package/dist/session/observation.js.map +1 -1
- package/dist/session/session.d.ts +68 -5
- package/dist/session/session.d.ts.map +1 -1
- package/dist/session/session.js +461 -49
- package/dist/session/session.js.map +1 -1
- package/dist/session/transaction.d.ts.map +1 -1
- package/dist/session/transaction.js +1 -0
- package/dist/session/transaction.js.map +1 -1
- package/dist/storage/jsonl/storage.d.ts +4 -0
- package/dist/storage/jsonl/storage.d.ts.map +1 -1
- package/dist/storage/jsonl/storage.js +2 -1
- package/dist/storage/jsonl/storage.js.map +1 -1
- package/dist/storage/memory.d.ts.map +1 -1
- package/dist/storage/memory.js +8 -10
- package/dist/storage/memory.js.map +1 -1
- package/dist/storage/scan.d.ts.map +1 -1
- package/dist/storage/scan.js +5 -4
- package/dist/storage/scan.js.map +1 -1
- package/dist/storage/sqlite/cloudflare.d.ts +17 -5
- package/dist/storage/sqlite/cloudflare.d.ts.map +1 -1
- package/dist/storage/sqlite/cloudflare.js +57 -21
- package/dist/storage/sqlite/cloudflare.js.map +1 -1
- package/dist/storage/sqlite/index.d.ts +1 -1
- package/dist/storage/sqlite/index.d.ts.map +1 -1
- package/dist/storage/sqlite/index.js.map +1 -1
- package/dist/storage/sqlite/migrations.d.ts +5 -1
- package/dist/storage/sqlite/migrations.d.ts.map +1 -1
- package/dist/storage/sqlite/migrations.js +94 -84
- package/dist/storage/sqlite/migrations.js.map +1 -1
- package/dist/storage/sqlite/node.d.ts +6 -4
- package/dist/storage/sqlite/node.d.ts.map +1 -1
- package/dist/storage/sqlite/node.js +6 -2
- package/dist/storage/sqlite/node.js.map +1 -1
- package/dist/storage/sqlite/schema.d.ts +47 -0
- package/dist/storage/sqlite/schema.d.ts.map +1 -0
- package/dist/storage/sqlite/schema.js +57 -0
- package/dist/storage/sqlite/schema.js.map +1 -0
- package/dist/storage/sqlite/storage.d.ts +9 -1
- package/dist/storage/sqlite/storage.d.ts.map +1 -1
- package/dist/storage/sqlite/storage.js +56 -55
- package/dist/storage/sqlite/storage.js.map +1 -1
- package/dist/testing/env-conformance.d.ts.map +1 -1
- package/dist/testing/env-conformance.js +100 -0
- package/dist/testing/env-conformance.js.map +1 -1
- package/dist/testing/runner.d.ts +1 -1
- package/dist/testing/runner.d.ts.map +1 -1
- package/dist/testing/runner.js.map +1 -1
- package/dist/testing/storage-conformance.d.ts.map +1 -1
- package/dist/testing/storage-conformance.js +3 -2
- package/dist/testing/storage-conformance.js.map +1 -1
- package/dist/testing/types.d.ts +2 -0
- package/dist/testing/types.d.ts.map +1 -1
- package/dist/testing/types.js.map +1 -1
- package/dist/tool-search/index.d.ts +2 -0
- package/dist/tool-search/index.d.ts.map +1 -0
- package/dist/tool-search/index.js +2 -0
- package/dist/tool-search/index.js.map +1 -0
- package/dist/tool-search/tool-search.d.ts +23 -0
- package/dist/tool-search/tool-search.d.ts.map +1 -0
- package/dist/tool-search/tool-search.js +84 -0
- package/dist/tool-search/tool-search.js.map +1 -0
- package/dist/tools/bash.d.ts +10 -2
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +27 -9
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.js +1 -1
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/image-processor.d.ts +50 -0
- package/dist/tools/image-processor.d.ts.map +1 -0
- package/dist/tools/image-processor.js +20 -0
- package/dist/tools/image-processor.js.map +1 -0
- package/dist/tools/image.d.ts +8 -0
- package/dist/tools/image.d.ts.map +1 -1
- package/dist/tools/image.js +47 -0
- package/dist/tools/image.js.map +1 -1
- package/dist/tools/index.d.ts +25 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +13 -5
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/read.d.ts +10 -2
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +88 -29
- package/dist/tools/read.js.map +1 -1
- package/dist/tools/write.js +1 -1
- package/dist/tools/write.js.map +1 -1
- package/dist/truncate.d.ts +3 -2
- package/dist/truncate.d.ts.map +1 -1
- package/dist/truncate.js +4 -34
- package/dist/truncate.js.map +1 -1
- package/dist/types.d.ts +59 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +43 -4
- package/dist/harness/output.d.ts +0 -69
- package/dist/harness/output.d.ts.map +0 -1
- package/dist/harness/output.js +0 -318
- package/dist/harness/output.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../src/storage/sqlite/cloudflare.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SqliteDatabase, SqliteExecutor, SqliteValue } from \"./database.ts\";\nimport { SqliteStorage } from \"./storage.ts\";\n\n/** Values a Durable Object SQL binding accepts and returns. */\ntype DurableObjectSqlValue = ArrayBuffer | string | number | null;\n\n/**\n * The parts of a SQLite-backed Durable Object's `ctx.storage` this adapter uses, typed structurally so the package\n * needs no Workers type dependency.\n */\nexport type DurableObjectSqliteStorage = {\n\treadonly sql: {\n\t\texec(query: string, ...bindings: DurableObjectSqlValue[]): { toArray(): Record<string, DurableObjectSqlValue>[] };\n\t};\n\ttransaction<T>(closure: () => Promise<T>): Promise<T>;\n};\n\n/** Runs operations one at a time in call order, so a transaction excludes every other operation. */\nclass SerialQueue {\n\tprivate tail: Promise<unknown> = Promise.resolve();\n\n\trun<T>(operation: () => T | Promise<T>): Promise<T> {\n\t\tconst result = this.tail.then(operation);\n\t\tthis.tail = result.catch(() => {});\n\t\treturn result;\n\t}\n}\n\n/** Durable Object SQL binds numbers as doubles: a `bigint` outside the safe integer range would lose precision. */\nfunction bindValue(value: SqliteValue): DurableObjectSqlValue {\n\tif (value instanceof Uint8Array) return value.slice().buffer as ArrayBuffer;\n\tif (typeof value !== \"bigint\") return value;\n\tif (value < BigInt(Number.MIN_SAFE_INTEGER) || value > BigInt(Number.MAX_SAFE_INTEGER)) {\n\t\tthrow new RangeError(`Durable Object SQL cannot bind ${value} without losing precision`);\n\t}\n\treturn Number(value);\n}\n\nconst bind = (params: readonly SqliteValue[]): DurableObjectSqlValue[] => params.map(bindValue);\n\n/** Rows as returned, with `BLOB` columns converted to `Uint8Array` in place; no other copy is made. */\nfunction rows<T>(rows: Record<string, DurableObjectSqlValue>[]): T[] {\n\tfor (const row of rows) {\n\t\tfor (const key in row) {\n\t\t\tconst value = row[key];\n\t\t\tif (value instanceof ArrayBuffer) (row as Record<string, unknown>)[key] = new Uint8Array(value);\n\t\t}\n\t}\n\treturn rows as T[];\n}\n\n/** Executes SQL through `ctx.storage.sql`, which has no separate prepare step. */\nclass DurableObjectSqliteExecutor implements SqliteExecutor {\n\tprotected readonly storage: DurableObjectSqliteStorage;\n\n\tconstructor(storage: DurableObjectSqliteStorage) {\n\t\tthis.storage = storage;\n\t}\n\n\tasync exec(sql: string): Promise<void> {\n\t\tthis.check();\n\t\tthis.storage.sql.exec(sql);\n\t}\n\n\tasync run(sql: string, ...params: SqliteValue[]): Promise<void> {\n\t\tthis.check();\n\t\tthis.storage.sql.exec(sql, ...bind(params));\n\t}\n\n\tasync get<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T | undefined> {\n\t\tthis.check();\n\t\treturn rows<T>(this.storage.sql.exec(sql, ...bind(params)).toArray())[0];\n\t}\n\n\tasync all<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T[]> {\n\t\tthis.check();\n\t\treturn rows<T>(this.storage.sql.exec(sql, ...bind(params)).toArray());\n\t}\n\n\t/** Throws when this handle may no longer run SQL. */\n\tprotected check(): void {}\n}\n\n/** The handle a transaction callback receives; invalid once the callback settles. */\nclass DurableObjectSqliteTransaction extends DurableObjectSqliteExecutor {\n\tactive = true;\n\n\tprotected override check(): void {\n\t\tif (!this.active) throw new Error(\"SQLite transaction handle is no longer active\");\n\t}\n}\n\n/**\n * `SqliteDatabase` adapter for the SQLite storage of a Cloudflare Durable Object. Integers are JavaScript numbers;\n * binding a `bigint` outside the safe integer range throws.\n */\nexport class DurableObjectSqliteDatabase extends DurableObjectSqliteExecutor implements SqliteDatabase {\n\tprivate readonly queue = new SerialQueue();\n\n\toverride exec(sql: string): Promise<void> {\n\t\treturn this.queue.run(() => super.exec(sql));\n\t}\n\n\toverride run(sql: string, ...params: SqliteValue[]): Promise<void> {\n\t\treturn this.queue.run(() => super.run(sql, ...params));\n\t}\n\n\toverride get<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T | undefined> {\n\t\treturn this.queue.run(() => super.get<T>(sql, ...params));\n\t}\n\n\toverride all<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T[]> {\n\t\treturn this.queue.run(() => super.all<T>(sql, ...params));\n\t}\n\n\t/** `ctx.storage.transaction()` commits when the callback resolves and rolls back when it rejects. */\n\ttransaction<T>(callback: (transaction: SqliteExecutor) => Promise<T>): Promise<T> {\n\t\treturn this.queue.run(() =>\n\t\t\tthis.storage.transaction(async () => {\n\t\t\t\tconst transaction = new DurableObjectSqliteTransaction(this.storage);\n\t\t\t\ttry {\n\t\t\t\t\treturn await callback(transaction);\n\t\t\t\t} finally {\n\t\t\t\t\ttransaction.active = false;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\t/** Waits for queued work. The Durable Object owns its storage, so nothing else closes. */\n\tclose(): Promise<void> {\n\t\treturn this.queue.run(() => {});\n\t}\n}\n\n/** Open durable storage on a SQLite-backed Durable Object's `ctx.storage`. */\nexport function openDurableObjectSqliteStorage(storage: DurableObjectSqliteStorage): Promise<SqliteStorage> {\n\treturn SqliteStorage.open(new DurableObjectSqliteDatabase(storage));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../../src/storage/sqlite/cloudflare.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SqliteDatabase, SqliteExecutor, SqliteValue } from \"./database.ts\";\nimport { SqliteStorage, type SqliteStorageOptions } from \"./storage.ts\";\n\n/** Values a Durable Object SQL binding accepts and returns. */\ntype DurableObjectSqlValue = ArrayBuffer | string | number | null;\n\n/**\n * The parts of a SQLite-backed Durable Object's `ctx.storage` this adapter uses, typed structurally so the package\n * needs no Workers type dependency.\n */\nexport type DurableObjectSqliteStorage = {\n\treadonly sql: {\n\t\texec(\n\t\t\tquery: string,\n\t\t\t...bindings: DurableObjectSqlValue[]\n\t\t): {\n\t\t\tnext():\n\t\t\t\t| { readonly done?: false; readonly value: Record<string, DurableObjectSqlValue> }\n\t\t\t\t| { readonly done: true; readonly value?: undefined };\n\t\t\ttoArray(): Record<string, DurableObjectSqlValue>[];\n\t\t};\n\t};\n\ttransaction<T>(closure: () => Promise<T>): Promise<T>;\n};\n\n/** Runs synchronous operations immediately when idle and holds queued calls behind a transaction. */\nclass SerialQueue {\n\tprivate tail: Promise<void> = Promise.resolve();\n\tprivate pending = 0;\n\n\trun<T>(operation: () => T | Promise<T>): Promise<T> {\n\t\tif (this.pending > 0) return this.enqueue(operation);\n\t\ttry {\n\t\t\treturn Promise.resolve(operation());\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t}\n\n\thold<T>(operation: () => Promise<T>): Promise<T> {\n\t\treturn this.enqueue(operation);\n\t}\n\n\tprivate enqueue<T>(operation: () => T | Promise<T>): Promise<T> {\n\t\tthis.pending++;\n\t\tconst result = this.tail.then(operation).finally(() => {\n\t\t\tthis.pending--;\n\t\t});\n\t\tthis.tail = result.then(\n\t\t\t() => {},\n\t\t\t() => {},\n\t\t);\n\t\treturn result;\n\t}\n}\n\nconst storageQueues = new WeakMap<DurableObjectSqliteStorage, SerialQueue>();\n\nfunction queueFor(storage: DurableObjectSqliteStorage): SerialQueue {\n\tlet queue = storageQueues.get(storage);\n\tif (queue === undefined) {\n\t\tqueue = new SerialQueue();\n\t\tstorageQueues.set(storage, queue);\n\t}\n\treturn queue;\n}\n\n/** Durable Object SQL binds numbers as doubles: a `bigint` outside the safe integer range would lose precision. */\nfunction bindValue(value: SqliteValue): DurableObjectSqlValue {\n\tif (value instanceof Uint8Array) return value.slice().buffer as ArrayBuffer;\n\tif (typeof value !== \"bigint\") return value;\n\tif (value < BigInt(Number.MIN_SAFE_INTEGER) || value > BigInt(Number.MAX_SAFE_INTEGER)) {\n\t\tthrow new RangeError(`Durable Object SQL cannot bind ${value} without losing precision`);\n\t}\n\treturn Number(value);\n}\n\nconst bind = (params: readonly SqliteValue[]): DurableObjectSqlValue[] => params.map(bindValue);\n\n/** A row as returned, with `BLOB` columns converted to `Uint8Array` in place; no other copy is made. */\nfunction row<T>(row: Record<string, DurableObjectSqlValue>): T {\n\tfor (const key in row) {\n\t\tconst value = row[key];\n\t\tif (value instanceof ArrayBuffer) (row as Record<string, unknown>)[key] = new Uint8Array(value);\n\t}\n\treturn row as T;\n}\n\n/** Executes SQL through `ctx.storage.sql`, which has no separate prepare step. */\nclass DurableObjectSqliteExecutor implements SqliteExecutor {\n\tprotected readonly storage: DurableObjectSqliteStorage;\n\n\tconstructor(storage: DurableObjectSqliteStorage) {\n\t\tthis.storage = storage;\n\t}\n\n\tasync exec(sql: string): Promise<void> {\n\t\tthis.check();\n\t\tthis.storage.sql.exec(sql);\n\t}\n\n\tasync run(sql: string, ...params: SqliteValue[]): Promise<void> {\n\t\tthis.check();\n\t\tthis.storage.sql.exec(sql, ...bind(params));\n\t}\n\n\tasync get<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T | undefined> {\n\t\tthis.check();\n\t\tconst result = this.storage.sql.exec(sql, ...bind(params)).next();\n\t\treturn result.done ? undefined : row<T>(result.value);\n\t}\n\n\tasync all<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T[]> {\n\t\tthis.check();\n\t\treturn this.storage.sql\n\t\t\t.exec(sql, ...bind(params))\n\t\t\t.toArray()\n\t\t\t.map((value) => row<T>(value));\n\t}\n\n\t/** Throws when this handle may no longer run SQL. */\n\tprotected check(): void {}\n}\n\n/** The handle a transaction callback receives; invalid once the callback settles. */\nclass DurableObjectSqliteTransaction extends DurableObjectSqliteExecutor {\n\tactive = true;\n\n\tprotected override check(): void {\n\t\tif (!this.active) throw new Error(\"SQLite transaction handle is no longer active\");\n\t}\n}\n\n/**\n * `SqliteDatabase` adapter for the SQLite storage of a Cloudflare Durable Object. Adapters given the same storage\n * object share a queue; direct calls to the underlying storage bypass it. Integers are JavaScript numbers; binding a\n * `bigint` outside the safe integer range throws.\n */\nexport class DurableObjectSqliteDatabase extends DurableObjectSqliteExecutor implements SqliteDatabase {\n\tprivate readonly queue: SerialQueue;\n\n\tconstructor(storage: DurableObjectSqliteStorage) {\n\t\tsuper(storage);\n\t\tthis.queue = queueFor(storage);\n\t}\n\n\toverride exec(sql: string): Promise<void> {\n\t\treturn this.queue.run(() => super.exec(sql));\n\t}\n\n\toverride run(sql: string, ...params: SqliteValue[]): Promise<void> {\n\t\treturn this.queue.run(() => super.run(sql, ...params));\n\t}\n\n\toverride get<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T | undefined> {\n\t\treturn this.queue.run(() => super.get<T>(sql, ...params));\n\t}\n\n\toverride all<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T[]> {\n\t\treturn this.queue.run(() => super.all<T>(sql, ...params));\n\t}\n\n\t/** `ctx.storage.transaction()` commits when the callback resolves and rolls back when it rejects. */\n\ttransaction<T>(callback: (transaction: SqliteExecutor) => Promise<T>): Promise<T> {\n\t\treturn this.queue.hold(() =>\n\t\t\tthis.storage.transaction(async () => {\n\t\t\t\tconst transaction = new DurableObjectSqliteTransaction(this.storage);\n\t\t\t\ttry {\n\t\t\t\t\treturn await callback(transaction);\n\t\t\t\t} finally {\n\t\t\t\t\ttransaction.active = false;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t}\n\n\t/** Waits for queued work. The Durable Object owns its storage, so nothing else closes. */\n\tclose(): Promise<void> {\n\t\treturn this.queue.run(() => {});\n\t}\n}\n\n/**\n * Open durable storage on a SQLite-backed Durable Object, optionally under a table prefix. Calls given the same\n * storage object share an operation queue.\n */\nexport function openDurableObjectSqliteStorage(\n\tstorage: DurableObjectSqliteStorage,\n\toptions: SqliteStorageOptions = {},\n): Promise<SqliteStorage> {\n\treturn SqliteStorage.open(new DurableObjectSqliteDatabase(storage), options);\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export type { SqliteDatabase, SqliteExecutor, SqliteValue } from "./database.ts";
|
|
2
2
|
export { applySqliteMigrations, CURRENT_SQLITE_SCHEMA_VERSION, SQLITE_MIGRATIONS, type SqliteMigration, } from "./migrations.ts";
|
|
3
|
-
export { SqliteStorage } from "./storage.ts";
|
|
3
|
+
export { SqliteStorage, type SqliteStorageOptions } from "./storage.ts";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EACN,qBAAqB,EACrB,6BAA6B,EAC7B,iBAAiB,EACjB,KAAK,eAAe,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EACN,qBAAqB,EACrB,6BAA6B,EAC7B,iBAAiB,EACjB,KAAK,eAAe,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/sqlite/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,qBAAqB,EACrB,6BAA6B,EAC7B,iBAAiB,GAEjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/storage/sqlite/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,qBAAqB,EACrB,6BAA6B,EAC7B,iBAAiB,GAEjB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAA6B,MAAM,cAAc,CAAC","sourcesContent":["export type { SqliteDatabase, SqliteExecutor, SqliteValue } from \"./database.ts\";\nexport {\n\tapplySqliteMigrations,\n\tCURRENT_SQLITE_SCHEMA_VERSION,\n\tSQLITE_MIGRATIONS,\n\ttype SqliteMigration,\n} from \"./migrations.ts\";\nexport { SqliteStorage, type SqliteStorageOptions } from \"./storage.ts\";\n"]}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { SqliteDatabase } from "./database.ts";
|
|
2
|
+
import { type SqliteSchema } from "./schema.ts";
|
|
2
3
|
export type SqliteMigration = {
|
|
3
4
|
readonly version: number;
|
|
4
5
|
readonly statements: readonly string[];
|
|
5
6
|
};
|
|
6
|
-
/**
|
|
7
|
+
/** Build immutable, ordered schema history for a set of SQLite identifiers. */
|
|
8
|
+
export declare function createSqliteMigrations(schema: SqliteSchema): readonly SqliteMigration[];
|
|
7
9
|
export declare const SQLITE_MIGRATIONS: readonly SqliteMigration[];
|
|
8
10
|
export declare const CURRENT_SQLITE_SCHEMA_VERSION: number;
|
|
9
11
|
/** Apply all pending schema migrations atomically. */
|
|
10
12
|
export declare function applySqliteMigrations(database: SqliteDatabase, migrations?: readonly SqliteMigration[]): Promise<void>;
|
|
13
|
+
/** Apply migrations rendered for a particular schema. */
|
|
14
|
+
export declare function applySqliteMigrationsForSchema(database: SqliteDatabase, schema: SqliteSchema, migrations?: readonly SqliteMigration[]): Promise<void>;
|
|
11
15
|
//# sourceMappingURL=migrations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,eAAe,EAAE,CAiFvF;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EAAkD,CAAC;AAE3G,eAAO,MAAM,6BAA6B,QAAyC,CAAC;AAIpF,sDAAsD;AACtD,wBAAsB,qBAAqB,CAC1C,QAAQ,EAAE,cAAc,EACxB,UAAU,GAAE,SAAS,eAAe,EAAsB,GACxD,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,yDAAyD;AACzD,wBAAsB,8BAA8B,CACnD,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,YAAY,EACpB,UAAU,GAAE,SAAS,eAAe,EAAmC,GACrE,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
|
|
@@ -1,98 +1,108 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
1
|
+
import { DEFAULT_SQLITE_SCHEMA } from "./schema.js";
|
|
2
|
+
/** Build immutable, ordered schema history for a set of SQLite identifiers. */
|
|
3
|
+
export function createSqliteMigrations(schema) {
|
|
4
|
+
const { tables, indexes } = schema;
|
|
5
|
+
// next_id is TEXT because node:sqlite rejects INTEGER results outside JavaScript's safe integer range.
|
|
6
|
+
const initialSchema = [
|
|
7
|
+
`CREATE TABLE ${tables.durableMetadata} (
|
|
8
|
+
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
9
|
+
next_id TEXT NOT NULL,
|
|
10
|
+
next_seq INTEGER NOT NULL
|
|
11
|
+
) STRICT`,
|
|
12
|
+
`INSERT INTO ${tables.durableMetadata} (singleton, next_id, next_seq) VALUES (1, '2', 1)`,
|
|
13
|
+
`CREATE TABLE ${tables.recordIds} (
|
|
14
|
+
id INTEGER PRIMARY KEY,
|
|
15
|
+
record_type TEXT NOT NULL CHECK (record_type IN ('conversation', 'entry', 'task', 'submission', 'document'))
|
|
16
|
+
) STRICT`,
|
|
17
|
+
`CREATE TABLE ${tables.conversations} (
|
|
18
|
+
id INTEGER PRIMARY KEY,
|
|
19
|
+
owner_conversation_id INTEGER,
|
|
20
|
+
owner_task_id INTEGER,
|
|
21
|
+
record TEXT NOT NULL CHECK (json_valid(record))
|
|
22
|
+
) STRICT`,
|
|
23
|
+
`CREATE INDEX ${indexes.conversationsByOwnerConversation} ON ${tables.conversations} (owner_conversation_id, id)`,
|
|
24
|
+
`CREATE INDEX ${indexes.conversationsByOwnerTask} ON ${tables.conversations} (owner_task_id, id)`,
|
|
25
|
+
`CREATE TABLE ${tables.entries} (
|
|
26
|
+
id INTEGER PRIMARY KEY,
|
|
27
|
+
conversation_id INTEGER NOT NULL,
|
|
28
|
+
head INTEGER,
|
|
29
|
+
commit_seq INTEGER NOT NULL,
|
|
30
|
+
record TEXT NOT NULL CHECK (json_valid(record))
|
|
31
|
+
) STRICT`,
|
|
32
|
+
`CREATE INDEX ${indexes.entriesByConversation} ON ${tables.entries} (conversation_id, id DESC)`,
|
|
33
|
+
`CREATE INDEX ${indexes.entryHeadsByConversation} ON ${tables.entries} (conversation_id, id DESC) WHERE head IS NOT NULL`,
|
|
34
|
+
`CREATE TABLE ${tables.tasks} (
|
|
35
|
+
id INTEGER PRIMARY KEY,
|
|
36
|
+
conversation_id INTEGER NOT NULL,
|
|
37
|
+
kind TEXT NOT NULL,
|
|
38
|
+
status TEXT NOT NULL CHECK (status IN ('pending', 'running', 'waiting', 'completing', 'terminal')),
|
|
39
|
+
abort_requested INTEGER NOT NULL CHECK (abort_requested IN (0, 1)),
|
|
40
|
+
background INTEGER NOT NULL CHECK (background IN (0, 1)),
|
|
41
|
+
record TEXT NOT NULL CHECK (json_valid(record))
|
|
42
|
+
) STRICT`,
|
|
43
|
+
`CREATE INDEX ${indexes.tasksByStatus} ON ${tables.tasks} (status, id)`,
|
|
44
|
+
`CREATE INDEX ${indexes.tasksByConversation} ON ${tables.tasks} (conversation_id, id)`,
|
|
45
|
+
`CREATE INDEX ${indexes.tasksByKind} ON ${tables.tasks} (kind, id)`,
|
|
46
|
+
`CREATE INDEX ${indexes.tasksByAbortRequested} ON ${tables.tasks} (abort_requested, id)`,
|
|
47
|
+
`CREATE INDEX ${indexes.tasksByBackground} ON ${tables.tasks} (background, id)`,
|
|
48
|
+
`CREATE TABLE ${tables.submissions} (
|
|
49
|
+
id INTEGER PRIMARY KEY,
|
|
50
|
+
conversation_id INTEGER NOT NULL,
|
|
51
|
+
request_id TEXT,
|
|
52
|
+
status TEXT NOT NULL CHECK (status IN ('queued', 'placed', 'done', 'unanswered')),
|
|
53
|
+
record TEXT NOT NULL CHECK (json_valid(record))
|
|
54
|
+
) STRICT`,
|
|
55
|
+
`CREATE INDEX ${indexes.submissionsByRequest} ON ${tables.submissions} (conversation_id, request_id)`,
|
|
56
|
+
`CREATE INDEX ${indexes.submissionsByConversation} ON ${tables.submissions} (conversation_id, id)`,
|
|
57
|
+
`CREATE INDEX ${indexes.submissionsByStatus} ON ${tables.submissions} (status, id)`,
|
|
58
|
+
`CREATE TABLE ${tables.documents} (
|
|
59
|
+
id INTEGER PRIMARY KEY,
|
|
60
|
+
kind TEXT NOT NULL,
|
|
61
|
+
family INTEGER NOT NULL CHECK (family IN (0, 1)),
|
|
62
|
+
key_value TEXT NOT NULL,
|
|
63
|
+
scope_kind TEXT NOT NULL CHECK (scope_kind IN ('session', 'conversation', 'task')),
|
|
64
|
+
owner_id INTEGER NOT NULL,
|
|
65
|
+
created_at INTEGER NOT NULL,
|
|
66
|
+
retired_at INTEGER,
|
|
67
|
+
record TEXT NOT NULL CHECK (json_valid(record))
|
|
68
|
+
) STRICT`,
|
|
69
|
+
`CREATE INDEX ${indexes.documentsByAddress}
|
|
70
|
+
ON ${tables.documents} (kind, scope_kind, owner_id, family, key_value, created_at DESC, retired_at)`,
|
|
71
|
+
`CREATE INDEX ${indexes.documentsByScope} ON ${tables.documents} (scope_kind, owner_id, id)`,
|
|
72
|
+
`CREATE INDEX ${indexes.documentsByScopeKind} ON ${tables.documents} (scope_kind, owner_id, kind, id)`,
|
|
73
|
+
`CREATE TABLE ${tables.documentRevisions} (
|
|
74
|
+
document_id INTEGER NOT NULL,
|
|
75
|
+
seq INTEGER NOT NULL,
|
|
76
|
+
kind TEXT NOT NULL CHECK (kind IN ('base', 'delta')),
|
|
77
|
+
version INTEGER NOT NULL,
|
|
78
|
+
content TEXT NOT NULL CHECK (json_valid(content)),
|
|
79
|
+
PRIMARY KEY (document_id, seq)
|
|
80
|
+
) STRICT`,
|
|
81
|
+
`CREATE INDEX ${indexes.documentRevisionsByKind} ON ${tables.documentRevisions} (document_id, kind, seq DESC)`,
|
|
82
|
+
];
|
|
83
|
+
return [{ version: 1, statements: initialSchema }];
|
|
84
|
+
}
|
|
85
|
+
export const SQLITE_MIGRATIONS = createSqliteMigrations(DEFAULT_SQLITE_SCHEMA);
|
|
81
86
|
export const CURRENT_SQLITE_SCHEMA_VERSION = SQLITE_MIGRATIONS.at(-1)?.version ?? 0;
|
|
82
87
|
/** Apply all pending schema migrations atomically. */
|
|
83
88
|
export async function applySqliteMigrations(database, migrations = SQLITE_MIGRATIONS) {
|
|
89
|
+
await applySqliteMigrationsForSchema(database, DEFAULT_SQLITE_SCHEMA, migrations);
|
|
90
|
+
}
|
|
91
|
+
/** Apply migrations rendered for a particular schema. */
|
|
92
|
+
export async function applySqliteMigrationsForSchema(database, schema, migrations = createSqliteMigrations(schema)) {
|
|
84
93
|
for (let index = 0; index < migrations.length; index++) {
|
|
85
94
|
if (migrations[index]?.version !== index + 1) {
|
|
86
95
|
throw new Error("Durable SQLite migrations must have contiguous versions starting at 1");
|
|
87
96
|
}
|
|
88
97
|
}
|
|
98
|
+
const { durableSchema } = schema.tables;
|
|
89
99
|
await database.transaction(async (transaction) => {
|
|
90
|
-
await transaction.exec(`CREATE TABLE IF NOT EXISTS
|
|
100
|
+
await transaction.exec(`CREATE TABLE IF NOT EXISTS ${durableSchema} (
|
|
91
101
|
singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
|
|
92
102
|
version INTEGER NOT NULL CHECK (version >= 0)
|
|
93
103
|
) STRICT`);
|
|
94
|
-
await transaction.run(
|
|
95
|
-
const row = await transaction.get(
|
|
104
|
+
await transaction.run(`INSERT OR IGNORE INTO ${durableSchema} (singleton, version) VALUES (1, 0)`);
|
|
105
|
+
const row = await transaction.get(`SELECT version FROM ${durableSchema} WHERE singleton = 1`);
|
|
96
106
|
if (row === undefined)
|
|
97
107
|
throw new Error("Durable SQLite schema metadata is missing");
|
|
98
108
|
const currentVersion = migrations.at(-1)?.version ?? 0;
|
|
@@ -104,7 +114,7 @@ export async function applySqliteMigrations(database, migrations = SQLITE_MIGRAT
|
|
|
104
114
|
continue;
|
|
105
115
|
for (const statement of migration.statements)
|
|
106
116
|
await transaction.exec(statement);
|
|
107
|
-
await transaction.run(
|
|
117
|
+
await transaction.run(`UPDATE ${durableSchema} SET version = ? WHERE singleton = 1`, migration.version);
|
|
108
118
|
}
|
|
109
119
|
});
|
|
110
120
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../src/storage/sqlite/migrations.ts"],"names":[],"mappings":"AAOA,uGAAuG;AACvG,MAAM,cAAc,GAAsB;IACzC;;;;UAIS;IACT,gFAAgF;IAChF;;;UAGS;IACT;;;;;UAKS;IACT,+FAA+F;IAC/F,+EAA+E;IAC/E;;;;;;UAMS;IACT,4EAA4E;IAC5E,uGAAuG;IACvG;;;;;;;;UAQS;IACT,oDAAoD;IACpD,mEAAmE;IACnE,gDAAgD;IAChD,sEAAsE;IACtE,4DAA4D;IAC5D;;;;;;UAMS;IACT,kFAAkF;IAClF,+EAA+E;IAC/E,gEAAgE;IAChE;;;;;;;;;;UAUS;IACT;4FAC2F;IAC3F,yEAAyE;IACzE,oFAAoF;IACpF;;;;;;;UAOS;IACT,6FAA6F;CAC7F,CAAC;AAEF,+FAA+F;AAC/F,MAAM,CAAC,MAAM,iBAAiB,GAA+B,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,CAAC;AAE1G,MAAM,CAAC,MAAM,6BAA6B,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC;AAIpF,sDAAsD;AACtD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAC1C,QAAwB,EACxB,UAAU,GAA+B,iBAAiB;IAE1D,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QACxD,IAAI,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,KAAK,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;QAC1F,CAAC;IACF,CAAC;IAED,MAAM,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAChD,MAAM,WAAW,CAAC,IAAI,CAAC;;;WAGd,CAAC,CAAC;QACX,MAAM,WAAW,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;QACjG,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,GAAG,CAAY,wDAAwD,CAAC,CAAC;QACvG,IAAI,GAAG,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACpF,MAAM,cAAc,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC;QACvD,IAAI,GAAG,CAAC,OAAO,GAAG,cAAc,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CACd,iCAAiC,GAAG,CAAC,OAAO,oCAAoC,cAAc,EAAE,CAChG,CAAC;QACH,CAAC;QACD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACpC,IAAI,SAAS,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO;gBAAE,SAAS;YAC/C,KAAK,MAAM,SAAS,IAAI,SAAS,CAAC,UAAU;gBAAE,MAAM,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAChF,MAAM,WAAW,CAAC,GAAG,CAAC,2DAA2D,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QACvG,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type { SqliteDatabase } from \"./database.ts\";\n\nexport type SqliteMigration = {\n\treadonly version: number;\n\treadonly statements: readonly string[];\n};\n\n// next_id is TEXT because node:sqlite rejects INTEGER results outside JavaScript's safe integer range.\nconst INITIAL_SCHEMA: readonly string[] = [\n\t`CREATE TABLE durable_metadata (\n\t\tsingleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n\t\tnext_id TEXT NOT NULL,\n\t\tnext_seq INTEGER NOT NULL\n\t) STRICT`,\n\t`INSERT INTO durable_metadata (singleton, next_id, next_seq) VALUES (1, '2', 1)`,\n\t`CREATE TABLE record_ids (\n\t\tid INTEGER PRIMARY KEY,\n\t\trecord_type TEXT NOT NULL CHECK (record_type IN ('conversation', 'entry', 'task', 'submission', 'document'))\n\t) STRICT`,\n\t`CREATE TABLE conversations (\n\t\tid INTEGER PRIMARY KEY,\n\t\towner_conversation_id INTEGER,\n\t\towner_task_id INTEGER,\n\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t) STRICT`,\n\t\"CREATE INDEX conversations_by_owner_conversation ON conversations (owner_conversation_id, id)\",\n\t\"CREATE INDEX conversations_by_owner_task ON conversations (owner_task_id, id)\",\n\t`CREATE TABLE entries (\n\t\tid INTEGER PRIMARY KEY,\n\t\tconversation_id INTEGER NOT NULL,\n\t\thead INTEGER,\n\t\tcommit_seq INTEGER NOT NULL,\n\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t) STRICT`,\n\t\"CREATE INDEX entries_by_conversation ON entries (conversation_id, id DESC)\",\n\t\"CREATE INDEX entry_heads_by_conversation ON entries (conversation_id, id DESC) WHERE head IS NOT NULL\",\n\t`CREATE TABLE tasks (\n\t\tid INTEGER PRIMARY KEY,\n\t\tconversation_id INTEGER NOT NULL,\n\t\tkind TEXT NOT NULL,\n\t\tstatus TEXT NOT NULL CHECK (status IN ('pending', 'running', 'waiting', 'completing', 'terminal')),\n\t\tabort_requested INTEGER NOT NULL CHECK (abort_requested IN (0, 1)),\n\t\tbackground INTEGER NOT NULL CHECK (background IN (0, 1)),\n\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t) STRICT`,\n\t\"CREATE INDEX tasks_by_status ON tasks (status, id)\",\n\t\"CREATE INDEX tasks_by_conversation ON tasks (conversation_id, id)\",\n\t\"CREATE INDEX tasks_by_kind ON tasks (kind, id)\",\n\t\"CREATE INDEX tasks_by_abort_requested ON tasks (abort_requested, id)\",\n\t\"CREATE INDEX tasks_by_background ON tasks (background, id)\",\n\t`CREATE TABLE submissions (\n\t\tid INTEGER PRIMARY KEY,\n\t\tconversation_id INTEGER NOT NULL,\n\t\trequest_id TEXT,\n\t\tstatus TEXT NOT NULL CHECK (status IN ('queued', 'placed', 'done', 'unanswered')),\n\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t) STRICT`,\n\t\"CREATE INDEX submissions_by_request ON submissions (conversation_id, request_id)\",\n\t\"CREATE INDEX submissions_by_conversation ON submissions (conversation_id, id)\",\n\t\"CREATE INDEX submissions_by_status ON submissions (status, id)\",\n\t`CREATE TABLE documents (\n\t\tid INTEGER PRIMARY KEY,\n\t\tkind TEXT NOT NULL,\n\t\tfamily INTEGER NOT NULL CHECK (family IN (0, 1)),\n\t\tkey_value TEXT NOT NULL,\n\t\tscope_kind TEXT NOT NULL CHECK (scope_kind IN ('session', 'conversation', 'task')),\n\t\towner_id INTEGER NOT NULL,\n\t\tcreated_at INTEGER NOT NULL,\n\t\tretired_at INTEGER,\n\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t) STRICT`,\n\t`CREATE INDEX documents_by_address\n\t\tON documents (kind, scope_kind, owner_id, family, key_value, created_at DESC, retired_at)`,\n\t\"CREATE INDEX documents_by_scope ON documents (scope_kind, owner_id, id)\",\n\t\"CREATE INDEX documents_by_scope_kind ON documents (scope_kind, owner_id, kind, id)\",\n\t`CREATE TABLE document_revisions (\n\t\tdocument_id INTEGER NOT NULL,\n\t\tseq INTEGER NOT NULL,\n\t\tkind TEXT NOT NULL CHECK (kind IN ('base', 'delta')),\n\t\tversion INTEGER NOT NULL,\n\t\tcontent TEXT NOT NULL CHECK (json_valid(content)),\n\t\tPRIMARY KEY (document_id, seq)\n\t) STRICT`,\n\t\"CREATE INDEX document_revisions_by_kind ON document_revisions (document_id, kind, seq DESC)\",\n];\n\n/** Immutable, ordered schema history. Append new migrations after the initial schema ships. */\nexport const SQLITE_MIGRATIONS: readonly SqliteMigration[] = [{ version: 1, statements: INITIAL_SCHEMA }];\n\nexport const CURRENT_SQLITE_SCHEMA_VERSION = SQLITE_MIGRATIONS.at(-1)?.version ?? 0;\n\ntype SchemaRow = { readonly version: number };\n\n/** Apply all pending schema migrations atomically. */\nexport async function applySqliteMigrations(\n\tdatabase: SqliteDatabase,\n\tmigrations: readonly SqliteMigration[] = SQLITE_MIGRATIONS,\n): Promise<void> {\n\tfor (let index = 0; index < migrations.length; index++) {\n\t\tif (migrations[index]?.version !== index + 1) {\n\t\t\tthrow new Error(\"Durable SQLite migrations must have contiguous versions starting at 1\");\n\t\t}\n\t}\n\n\tawait database.transaction(async (transaction) => {\n\t\tawait transaction.exec(`CREATE TABLE IF NOT EXISTS durable_schema (\n\t\t\tsingleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n\t\t\tversion INTEGER NOT NULL CHECK (version >= 0)\n\t\t) STRICT`);\n\t\tawait transaction.run(\"INSERT OR IGNORE INTO durable_schema (singleton, version) VALUES (1, 0)\");\n\t\tconst row = await transaction.get<SchemaRow>(\"SELECT version FROM durable_schema WHERE singleton = 1\");\n\t\tif (row === undefined) throw new Error(\"Durable SQLite schema metadata is missing\");\n\t\tconst currentVersion = migrations.at(-1)?.version ?? 0;\n\t\tif (row.version > currentVersion) {\n\t\t\tthrow new Error(\n\t\t\t\t`Durable SQLite schema version ${row.version} is newer than supported version ${currentVersion}`,\n\t\t\t);\n\t\t}\n\t\tfor (const migration of migrations) {\n\t\t\tif (migration.version <= row.version) continue;\n\t\t\tfor (const statement of migration.statements) await transaction.exec(statement);\n\t\t\tawait transaction.run(\"UPDATE durable_schema SET version = ? WHERE singleton = 1\", migration.version);\n\t\t}\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../src/storage/sqlite/migrations.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SqliteDatabase } from \"./database.ts\";\nimport { DEFAULT_SQLITE_SCHEMA, type SqliteSchema } from \"./schema.ts\";\n\nexport type SqliteMigration = {\n\treadonly version: number;\n\treadonly statements: readonly string[];\n};\n\n/** Build immutable, ordered schema history for a set of SQLite identifiers. */\nexport function createSqliteMigrations(schema: SqliteSchema): readonly SqliteMigration[] {\n\tconst { tables, indexes } = schema;\n\t// next_id is TEXT because node:sqlite rejects INTEGER results outside JavaScript's safe integer range.\n\tconst initialSchema: readonly string[] = [\n\t\t`CREATE TABLE ${tables.durableMetadata} (\n\t\t\tsingleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n\t\t\tnext_id TEXT NOT NULL,\n\t\t\tnext_seq INTEGER NOT NULL\n\t\t) STRICT`,\n\t\t`INSERT INTO ${tables.durableMetadata} (singleton, next_id, next_seq) VALUES (1, '2', 1)`,\n\t\t`CREATE TABLE ${tables.recordIds} (\n\t\t\tid INTEGER PRIMARY KEY,\n\t\t\trecord_type TEXT NOT NULL CHECK (record_type IN ('conversation', 'entry', 'task', 'submission', 'document'))\n\t\t) STRICT`,\n\t\t`CREATE TABLE ${tables.conversations} (\n\t\t\tid INTEGER PRIMARY KEY,\n\t\t\towner_conversation_id INTEGER,\n\t\t\towner_task_id INTEGER,\n\t\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t\t) STRICT`,\n\t\t`CREATE INDEX ${indexes.conversationsByOwnerConversation} ON ${tables.conversations} (owner_conversation_id, id)`,\n\t\t`CREATE INDEX ${indexes.conversationsByOwnerTask} ON ${tables.conversations} (owner_task_id, id)`,\n\t\t`CREATE TABLE ${tables.entries} (\n\t\t\tid INTEGER PRIMARY KEY,\n\t\t\tconversation_id INTEGER NOT NULL,\n\t\t\thead INTEGER,\n\t\t\tcommit_seq INTEGER NOT NULL,\n\t\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t\t) STRICT`,\n\t\t`CREATE INDEX ${indexes.entriesByConversation} ON ${tables.entries} (conversation_id, id DESC)`,\n\t\t`CREATE INDEX ${indexes.entryHeadsByConversation} ON ${tables.entries} (conversation_id, id DESC) WHERE head IS NOT NULL`,\n\t\t`CREATE TABLE ${tables.tasks} (\n\t\t\tid INTEGER PRIMARY KEY,\n\t\t\tconversation_id INTEGER NOT NULL,\n\t\t\tkind TEXT NOT NULL,\n\t\t\tstatus TEXT NOT NULL CHECK (status IN ('pending', 'running', 'waiting', 'completing', 'terminal')),\n\t\t\tabort_requested INTEGER NOT NULL CHECK (abort_requested IN (0, 1)),\n\t\t\tbackground INTEGER NOT NULL CHECK (background IN (0, 1)),\n\t\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t\t) STRICT`,\n\t\t`CREATE INDEX ${indexes.tasksByStatus} ON ${tables.tasks} (status, id)`,\n\t\t`CREATE INDEX ${indexes.tasksByConversation} ON ${tables.tasks} (conversation_id, id)`,\n\t\t`CREATE INDEX ${indexes.tasksByKind} ON ${tables.tasks} (kind, id)`,\n\t\t`CREATE INDEX ${indexes.tasksByAbortRequested} ON ${tables.tasks} (abort_requested, id)`,\n\t\t`CREATE INDEX ${indexes.tasksByBackground} ON ${tables.tasks} (background, id)`,\n\t\t`CREATE TABLE ${tables.submissions} (\n\t\t\tid INTEGER PRIMARY KEY,\n\t\t\tconversation_id INTEGER NOT NULL,\n\t\t\trequest_id TEXT,\n\t\t\tstatus TEXT NOT NULL CHECK (status IN ('queued', 'placed', 'done', 'unanswered')),\n\t\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t\t) STRICT`,\n\t\t`CREATE INDEX ${indexes.submissionsByRequest} ON ${tables.submissions} (conversation_id, request_id)`,\n\t\t`CREATE INDEX ${indexes.submissionsByConversation} ON ${tables.submissions} (conversation_id, id)`,\n\t\t`CREATE INDEX ${indexes.submissionsByStatus} ON ${tables.submissions} (status, id)`,\n\t\t`CREATE TABLE ${tables.documents} (\n\t\t\tid INTEGER PRIMARY KEY,\n\t\t\tkind TEXT NOT NULL,\n\t\t\tfamily INTEGER NOT NULL CHECK (family IN (0, 1)),\n\t\t\tkey_value TEXT NOT NULL,\n\t\t\tscope_kind TEXT NOT NULL CHECK (scope_kind IN ('session', 'conversation', 'task')),\n\t\t\towner_id INTEGER NOT NULL,\n\t\t\tcreated_at INTEGER NOT NULL,\n\t\t\tretired_at INTEGER,\n\t\t\trecord TEXT NOT NULL CHECK (json_valid(record))\n\t\t) STRICT`,\n\t\t`CREATE INDEX ${indexes.documentsByAddress}\n\t\t\tON ${tables.documents} (kind, scope_kind, owner_id, family, key_value, created_at DESC, retired_at)`,\n\t\t`CREATE INDEX ${indexes.documentsByScope} ON ${tables.documents} (scope_kind, owner_id, id)`,\n\t\t`CREATE INDEX ${indexes.documentsByScopeKind} ON ${tables.documents} (scope_kind, owner_id, kind, id)`,\n\t\t`CREATE TABLE ${tables.documentRevisions} (\n\t\t\tdocument_id INTEGER NOT NULL,\n\t\t\tseq INTEGER NOT NULL,\n\t\t\tkind TEXT NOT NULL CHECK (kind IN ('base', 'delta')),\n\t\t\tversion INTEGER NOT NULL,\n\t\t\tcontent TEXT NOT NULL CHECK (json_valid(content)),\n\t\t\tPRIMARY KEY (document_id, seq)\n\t\t) STRICT`,\n\t\t`CREATE INDEX ${indexes.documentRevisionsByKind} ON ${tables.documentRevisions} (document_id, kind, seq DESC)`,\n\t];\n\treturn [{ version: 1, statements: initialSchema }];\n}\n\nexport const SQLITE_MIGRATIONS: readonly SqliteMigration[] = createSqliteMigrations(DEFAULT_SQLITE_SCHEMA);\n\nexport const CURRENT_SQLITE_SCHEMA_VERSION = SQLITE_MIGRATIONS.at(-1)?.version ?? 0;\n\ntype SchemaRow = { readonly version: number };\n\n/** Apply all pending schema migrations atomically. */\nexport async function applySqliteMigrations(\n\tdatabase: SqliteDatabase,\n\tmigrations: readonly SqliteMigration[] = SQLITE_MIGRATIONS,\n): Promise<void> {\n\tawait applySqliteMigrationsForSchema(database, DEFAULT_SQLITE_SCHEMA, migrations);\n}\n\n/** Apply migrations rendered for a particular schema. */\nexport async function applySqliteMigrationsForSchema(\n\tdatabase: SqliteDatabase,\n\tschema: SqliteSchema,\n\tmigrations: readonly SqliteMigration[] = createSqliteMigrations(schema),\n): Promise<void> {\n\tfor (let index = 0; index < migrations.length; index++) {\n\t\tif (migrations[index]?.version !== index + 1) {\n\t\t\tthrow new Error(\"Durable SQLite migrations must have contiguous versions starting at 1\");\n\t\t}\n\t}\n\n\tconst { durableSchema } = schema.tables;\n\tawait database.transaction(async (transaction) => {\n\t\tawait transaction.exec(`CREATE TABLE IF NOT EXISTS ${durableSchema} (\n\t\t\tsingleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n\t\t\tversion INTEGER NOT NULL CHECK (version >= 0)\n\t\t) STRICT`);\n\t\tawait transaction.run(`INSERT OR IGNORE INTO ${durableSchema} (singleton, version) VALUES (1, 0)`);\n\t\tconst row = await transaction.get<SchemaRow>(`SELECT version FROM ${durableSchema} WHERE singleton = 1`);\n\t\tif (row === undefined) throw new Error(\"Durable SQLite schema metadata is missing\");\n\t\tconst currentVersion = migrations.at(-1)?.version ?? 0;\n\t\tif (row.version > currentVersion) {\n\t\t\tthrow new Error(\n\t\t\t\t`Durable SQLite schema version ${row.version} is newer than supported version ${currentVersion}`,\n\t\t\t);\n\t\t}\n\t\tfor (const migration of migrations) {\n\t\t\tif (migration.version <= row.version) continue;\n\t\t\tfor (const statement of migration.statements) await transaction.exec(statement);\n\t\t\tawait transaction.run(`UPDATE ${durableSchema} SET version = ? WHERE singleton = 1`, migration.version);\n\t\t}\n\t});\n}\n"]}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { StatementSync } from "node:sqlite";
|
|
2
2
|
import { DatabaseSync } from "node:sqlite";
|
|
3
3
|
import type { SqliteDatabase, SqliteExecutor, SqliteValue } from "./database.ts";
|
|
4
|
-
import { SqliteStorage } from "./storage.ts";
|
|
4
|
+
import { SqliteStorage, type SqliteStorageOptions } from "./storage.ts";
|
|
5
5
|
/** Node SQLite connection settings for a durable storage file. */
|
|
6
|
-
export type
|
|
6
|
+
export type NodeSqliteDatabaseOptions = {
|
|
7
7
|
/** SQLite WAL auto-checkpoint threshold. SQLite and this adapter default to 1,000 pages; 0 disables it. */
|
|
8
8
|
readonly walAutoCheckpointPages?: number;
|
|
9
9
|
/** Time SQLite waits for a competing file lock. SQLite defaults to 0; this adapter defaults to 5,000 ms. */
|
|
10
10
|
readonly busyTimeoutMs?: number;
|
|
11
11
|
};
|
|
12
|
+
/** Node SQLite connection settings plus durable storage options. */
|
|
13
|
+
export type NodeSqliteStorageOptions = NodeSqliteDatabaseOptions & SqliteStorageOptions;
|
|
12
14
|
/**
|
|
13
15
|
* Executes SQL on one connection. Prepared statements are cached per connection by SQL text, so the
|
|
14
16
|
* database and its transaction handles share them across transactions.
|
|
@@ -34,8 +36,8 @@ export declare class NodeSqliteDatabase extends NodeSqliteExecutor implements Sq
|
|
|
34
36
|
protected runOperation<T>(operation: () => T): Promise<T>;
|
|
35
37
|
}
|
|
36
38
|
/** Open and configure a Node-backed SQLite database facade. */
|
|
37
|
-
export declare function openNodeSqliteDatabase(path: string, options?:
|
|
38
|
-
/** Open or create file-backed durable storage using Node's built-in SQLite. */
|
|
39
|
+
export declare function openNodeSqliteDatabase(path: string, options?: NodeSqliteDatabaseOptions): Promise<NodeSqliteDatabase>;
|
|
40
|
+
/** Open or create file-backed durable storage using Node's built-in SQLite, optionally under a table prefix. */
|
|
39
41
|
export declare function openNodeSqliteStorage(path: string, options?: NodeSqliteStorageOptions): Promise<SqliteStorage>;
|
|
40
42
|
export {};
|
|
41
43
|
//# sourceMappingURL=node.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/node.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/node.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjF,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAExE,kEAAkE;AAClE,MAAM,MAAM,yBAAyB,GAAG;IACvC,2GAA2G;IAC3G,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,4GAA4G;IAC5G,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,oEAAoE;AACpE,MAAM,MAAM,wBAAwB,GAAG,yBAAyB,GAAG,oBAAoB,CAAC;AA0DxF;;;GAGG;AACH,uBAAe,kBAAmB,YAAW,cAAc;IAC1D,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAC1C,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAE1D,YAAY,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAGzE;IAED,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/B;IAED,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAIxD;IAED,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAEnF;IAED,GAAG,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAEzE;IAED,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAEnE,OAAO,CAAC,SAAS;CAQjB;AAgBD,wEAAwE;AACxE,qBAAa,kBAAmB,SAAQ,kBAAmB,YAAW,cAAc;IACnF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,MAAM,CAAS;IAEvB,YAAY,QAAQ,EAAE,YAAY,EAEjC;IAED,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,WAAW,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAmBhF;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAWrB;IAED,SAAS,CAAC,YAAY,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAExD;CACD;AAED,+DAA+D;AAC/D,wBAAsB,sBAAsB,CAC3C,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,yBAA8B,GACrC,OAAO,CAAC,kBAAkB,CAAC,CAmB7B;AAED,gHAAgH;AAChH,wBAAsB,qBAAqB,CAC1C,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,wBAA6B,GACpC,OAAO,CAAC,aAAa,CAAC,CAIxB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdir } from "node:fs/promises";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
3
|
import { DatabaseSync } from "node:sqlite";
|
|
4
|
+
import { validateSqliteSchemaPrefix } from "./schema.js";
|
|
4
5
|
import { SqliteStorage } from "./storage.js";
|
|
5
6
|
const DEFAULT_WAL_AUTO_CHECKPOINT_PAGES = 1_000;
|
|
6
7
|
const DEFAULT_BUSY_TIMEOUT_MS = 5_000;
|
|
@@ -172,8 +173,11 @@ export async function openNodeSqliteDatabase(path, options = {}) {
|
|
|
172
173
|
throw error;
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
|
-
/** Open or create file-backed durable storage using Node's built-in SQLite. */
|
|
176
|
+
/** Open or create file-backed durable storage using Node's built-in SQLite, optionally under a table prefix. */
|
|
176
177
|
export async function openNodeSqliteStorage(path, options = {}) {
|
|
177
|
-
|
|
178
|
+
const { prefix, ...databaseOptions } = options;
|
|
179
|
+
if (prefix !== undefined)
|
|
180
|
+
validateSqliteSchemaPrefix(prefix);
|
|
181
|
+
return SqliteStorage.open(await openNodeSqliteDatabase(path, databaseOptions), { prefix });
|
|
178
182
|
}
|
|
179
183
|
//# sourceMappingURL=node.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../../src/storage/sqlite/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { StatementSync } from \"node:sqlite\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport type { SqliteDatabase, SqliteExecutor, SqliteValue } from \"./database.ts\";\nimport { SqliteStorage } from \"./storage.ts\";\n\n/** Node SQLite connection settings for a durable storage file. */\nexport type NodeSqliteStorageOptions = {\n\t/** SQLite WAL auto-checkpoint threshold. SQLite and this adapter default to 1,000 pages; 0 disables it. */\n\treadonly walAutoCheckpointPages?: number;\n\t/** Time SQLite waits for a competing file lock. SQLite defaults to 0; this adapter defaults to 5,000 ms. */\n\treadonly busyTimeoutMs?: number;\n};\n\nconst DEFAULT_WAL_AUTO_CHECKPOINT_PAGES = 1_000;\nconst DEFAULT_BUSY_TIMEOUT_MS = 5_000;\n\ntype TransactionScope = { active: boolean };\n\nconst ignore = (): void => {};\n\n/**\n * Runs operations in call order. An operation starts immediately when nothing is running or waiting;\n * otherwise it waits for everything before it. An asynchronous operation holds the queue until it settles.\n */\nclass SerialOperationQueue {\n\tprivate tail: Promise<void> = Promise.resolve();\n\tprivate pending = 0;\n\n\trun<T>(operation: () => T): Promise<T> {\n\t\tif (this.pending > 0) return this.enqueue(operation);\n\t\ttry {\n\t\t\treturn Promise.resolve(operation());\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t}\n\n\trunAsync<T>(operation: () => Promise<T>): Promise<T> {\n\t\tif (this.pending > 0) return this.enqueue(operation);\n\t\tthis.pending++;\n\t\t// Publish the barrier before the operation starts, so calls it makes synchronously wait behind it.\n\t\tconst { promise: barrier, resolve: releaseBarrier } = Promise.withResolvers<void>();\n\t\tthis.tail = barrier;\n\t\tlet started: Promise<T>;\n\t\ttry {\n\t\t\tstarted = operation();\n\t\t} catch (error) {\n\t\t\tstarted = Promise.reject(error);\n\t\t}\n\t\treturn started.finally(() => {\n\t\t\tthis.pending--;\n\t\t\treleaseBarrier();\n\t\t});\n\t}\n\n\tprivate enqueue<T>(operation: () => T | Promise<T>): Promise<T> {\n\t\tthis.pending++;\n\t\treturn this.release(this.tail.then(operation));\n\t}\n\n\tprivate release<T>(operation: Promise<T>): Promise<T> {\n\t\tconst settled = operation.finally(() => {\n\t\t\tthis.pending--;\n\t\t});\n\t\tthis.tail = settled.then(ignore, ignore);\n\t\treturn settled;\n\t}\n}\n\n/**\n * Executes SQL on one connection. Prepared statements are cached per connection by SQL text, so the\n * database and its transaction handles share them across transactions.\n */\nabstract class NodeSqliteExecutor implements SqliteExecutor {\n\tprotected readonly database: DatabaseSync;\n\tprotected readonly statements: Map<string, StatementSync>;\n\n\tconstructor(database: DatabaseSync, statements: Map<string, StatementSync>) {\n\t\tthis.database = database;\n\t\tthis.statements = statements;\n\t}\n\n\texec(sql: string): Promise<void> {\n\t\treturn this.runOperation(() => {\n\t\t\tthis.database.exec(sql);\n\t\t});\n\t}\n\n\trun(sql: string, ...params: SqliteValue[]): Promise<void> {\n\t\treturn this.runOperation(() => {\n\t\t\tthis.statement(sql).run(...params);\n\t\t});\n\t}\n\n\tget<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T | undefined> {\n\t\treturn this.runOperation(() => this.statement(sql).get(...params) as T | undefined);\n\t}\n\n\tall<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T[]> {\n\t\treturn this.runOperation(() => this.statement(sql).all(...params) as T[]);\n\t}\n\n\tprotected abstract runOperation<T>(operation: () => T): Promise<T>;\n\n\tprivate statement(sql: string): StatementSync {\n\t\tlet statement = this.statements.get(sql);\n\t\tif (statement === undefined) {\n\t\t\tstatement = this.database.prepare(sql);\n\t\t\tthis.statements.set(sql, statement);\n\t\t}\n\t\treturn statement;\n\t}\n}\n\nclass NodeSqliteTransaction extends NodeSqliteExecutor {\n\tprivate readonly scope: TransactionScope;\n\n\tconstructor(database: DatabaseSync, statements: Map<string, StatementSync>, scope: TransactionScope) {\n\t\tsuper(database, statements);\n\t\tthis.scope = scope;\n\t}\n\n\tprotected async runOperation<T>(operation: () => T): Promise<T> {\n\t\tif (!this.scope.active) throw new Error(\"SQLite transaction handle is no longer active\");\n\t\treturn operation();\n\t}\n}\n\n/** `SqliteDatabase` adapter backed by Node's built-in `node:sqlite`. */\nexport class NodeSqliteDatabase extends NodeSqliteExecutor implements SqliteDatabase {\n\tprivate readonly access = new SerialOperationQueue();\n\tprivate closed = false;\n\n\tconstructor(database: DatabaseSync) {\n\t\tsuper(database, new Map());\n\t}\n\n\ttransaction<T>(callback: (transaction: SqliteExecutor) => Promise<T>): Promise<T> {\n\t\treturn this.access.runAsync(async () => {\n\t\t\tthis.database.exec(\"BEGIN IMMEDIATE\");\n\t\t\tconst scope = { active: true };\n\t\t\ttry {\n\t\t\t\tconst result = await callback(new NodeSqliteTransaction(this.database, this.statements, scope));\n\t\t\t\tscope.active = false;\n\t\t\t\tthis.database.exec(\"COMMIT\");\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tscope.active = false;\n\t\t\t\ttry {\n\t\t\t\t\tthis.database.exec(\"ROLLBACK\");\n\t\t\t\t} catch (rollbackError) {\n\t\t\t\t\tthrow new AggregateError([error, rollbackError], \"SQLite transaction failed and rollback failed\");\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\t}\n\n\tclose(): Promise<void> {\n\t\treturn this.access.run(() => {\n\t\t\tif (this.closed) return;\n\t\t\tthis.closed = true;\n\t\t\tthis.statements.clear();\n\t\t\ttry {\n\t\t\t\tthis.database.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n\t\t\t} finally {\n\t\t\t\tthis.database.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tprotected runOperation<T>(operation: () => T): Promise<T> {\n\t\treturn this.access.run(operation);\n\t}\n}\n\n/** Open and configure a Node-backed SQLite database facade. */\nexport async function openNodeSqliteDatabase(\n\tpath: string,\n\toptions: NodeSqliteStorageOptions = {},\n): Promise<NodeSqliteDatabase> {\n\tconst checkpointPages = options.walAutoCheckpointPages ?? DEFAULT_WAL_AUTO_CHECKPOINT_PAGES;\n\tconst timeout = options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS;\n\tif (path !== \":memory:\") await mkdir(dirname(path), { recursive: true });\n\tconst database = new DatabaseSync(path, { timeout });\n\tconst adapter = new NodeSqliteDatabase(database);\n\ttry {\n\t\tawait adapter.exec(\"PRAGMA journal_mode = WAL\");\n\t\tawait adapter.exec(\"PRAGMA synchronous = NORMAL\");\n\t\tawait adapter.exec(`PRAGMA wal_autocheckpoint = ${checkpointPages}`);\n\t\treturn adapter;\n\t} catch (error) {\n\t\ttry {\n\t\t\tawait adapter.close();\n\t\t} catch {\n\t\t\t// Preserve the configuration failure.\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Open or create file-backed durable storage using Node's built-in SQLite. */\nexport async function openNodeSqliteStorage(\n\tpath: string,\n\toptions: NodeSqliteStorageOptions = {},\n): Promise<SqliteStorage> {\n\treturn SqliteStorage.open(await openNodeSqliteDatabase(path, options));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../../src/storage/sqlite/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAA6B,MAAM,cAAc,CAAC;AAaxE,MAAM,iCAAiC,GAAG,KAAK,CAAC;AAChD,MAAM,uBAAuB,GAAG,KAAK,CAAC;AAItC,MAAM,MAAM,GAAG,GAAS,EAAE,GAAE,CAAC,CAAC;AAE9B;;;GAGG;AACH,MAAM,oBAAoB;IACjB,IAAI,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IACxC,OAAO,GAAG,CAAC,CAAC;IAEpB,GAAG,CAAI,SAAkB;QACxB,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,CAAC;YACJ,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACF,CAAC;IAED,QAAQ,CAAI,SAA2B;QACtC,IAAI,IAAI,CAAC,OAAO,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACrD,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,mGAAmG;QACnG,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC;QACpB,IAAI,OAAmB,CAAC;QACxB,IAAI,CAAC;YACJ,OAAO,GAAG,SAAS,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE;YAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,cAAc,EAAE,CAAC;QAClB,CAAC,CAAC,CAAC;IACJ,CAAC;IAEO,OAAO,CAAI,SAA+B;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IAChD,CAAC;IAEO,OAAO,CAAI,SAAqB;QACvC,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,OAAO,EAAE,CAAC;QAChB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC;IAChB,CAAC;CACD;AAED;;;GAGG;AACH,MAAe,kBAAkB;IACb,QAAQ,CAAe;IACvB,UAAU,CAA6B;IAE1D,YAAY,QAAsB,EAAE,UAAsC;QACzE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,GAAW;QACf,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE;YAC7B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,GAAG,MAAqB;QACxC,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE;YAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,GAAG,CAAmB,GAAW,EAAE,GAAG,MAAqB;QAC1D,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAkB,CAAC,CAAC;IACrF,CAAC;IAED,GAAG,CAAmB,GAAW,EAAE,GAAG,MAAqB;QAC1D,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAQ,CAAC,CAAC;IAC3E,CAAC;IAIO,SAAS,CAAC,GAAW;QAC5B,IAAI,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC7B,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;CACD;AAED,MAAM,qBAAsB,SAAQ,kBAAkB;IACpC,KAAK,CAAmB;IAEzC,YAAY,QAAsB,EAAE,UAAsC,EAAE,KAAuB;QAClG,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAES,KAAK,CAAC,YAAY,CAAI,SAAkB;QACjD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACzF,OAAO,SAAS,EAAE,CAAC;IACpB,CAAC;CACD;AAED,wEAAwE;AACxE,MAAM,OAAO,kBAAmB,SAAQ,kBAAkB;IACxC,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,GAAG,KAAK,CAAC;IAEvB,YAAY,QAAsB;QACjC,KAAK,CAAC,QAAQ,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,WAAW,CAAI,QAAqD;QACnE,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YACtC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACtC,MAAM,KAAK,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;gBAChG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;gBACrB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC7B,OAAO,MAAM,CAAC;YACf,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;gBACrB,IAAI,CAAC;oBACJ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAChC,CAAC;gBAAC,OAAO,aAAa,EAAE,CAAC;oBACxB,MAAM,IAAI,cAAc,CAAC,CAAC,KAAK,EAAE,aAAa,CAAC,EAAE,+CAA+C,CAAC,CAAC;gBACnG,CAAC;gBACD,MAAM,KAAK,CAAC;YACb,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,KAAK;QACJ,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;YAC3B,IAAI,IAAI,CAAC,MAAM;gBAAE,OAAO;YACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACxB,IAAI,CAAC;gBACJ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;YACvD,CAAC;oBAAS,CAAC;gBACV,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC;IAES,YAAY,CAAI,SAAkB;QAC3C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;CACD;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,IAAY,EACZ,OAAO,GAA8B,EAAE;IAEvC,MAAM,eAAe,GAAG,OAAO,CAAC,sBAAsB,IAAI,iCAAiC,CAAC;IAC5F,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,IAAI,uBAAuB,CAAC;IACjE,IAAI,IAAI,KAAK,UAAU;QAAE,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,CAAC;QACJ,MAAM,OAAO,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QAChD,MAAM,OAAO,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAClD,MAAM,OAAO,CAAC,IAAI,CAAC,+BAA+B,eAAe,EAAE,CAAC,CAAC;QACrE,OAAO,OAAO,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,CAAC;YACJ,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACR,sCAAsC;QACvC,CAAC;QACD,MAAM,KAAK,CAAC;IACb,CAAC;AACF,CAAC;AAED,gHAAgH;AAChH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAC1C,IAAY,EACZ,OAAO,GAA6B,EAAE;IAEtC,MAAM,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;IAC/C,IAAI,MAAM,KAAK,SAAS;QAAE,0BAA0B,CAAC,MAAM,CAAC,CAAC;IAC7D,OAAO,aAAa,CAAC,IAAI,CAAC,MAAM,sBAAsB,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAC5F,CAAC","sourcesContent":["import { mkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport type { StatementSync } from \"node:sqlite\";\nimport { DatabaseSync } from \"node:sqlite\";\nimport type { SqliteDatabase, SqliteExecutor, SqliteValue } from \"./database.ts\";\nimport { validateSqliteSchemaPrefix } from \"./schema.ts\";\nimport { SqliteStorage, type SqliteStorageOptions } from \"./storage.ts\";\n\n/** Node SQLite connection settings for a durable storage file. */\nexport type NodeSqliteDatabaseOptions = {\n\t/** SQLite WAL auto-checkpoint threshold. SQLite and this adapter default to 1,000 pages; 0 disables it. */\n\treadonly walAutoCheckpointPages?: number;\n\t/** Time SQLite waits for a competing file lock. SQLite defaults to 0; this adapter defaults to 5,000 ms. */\n\treadonly busyTimeoutMs?: number;\n};\n\n/** Node SQLite connection settings plus durable storage options. */\nexport type NodeSqliteStorageOptions = NodeSqliteDatabaseOptions & SqliteStorageOptions;\n\nconst DEFAULT_WAL_AUTO_CHECKPOINT_PAGES = 1_000;\nconst DEFAULT_BUSY_TIMEOUT_MS = 5_000;\n\ntype TransactionScope = { active: boolean };\n\nconst ignore = (): void => {};\n\n/**\n * Runs operations in call order. An operation starts immediately when nothing is running or waiting;\n * otherwise it waits for everything before it. An asynchronous operation holds the queue until it settles.\n */\nclass SerialOperationQueue {\n\tprivate tail: Promise<void> = Promise.resolve();\n\tprivate pending = 0;\n\n\trun<T>(operation: () => T): Promise<T> {\n\t\tif (this.pending > 0) return this.enqueue(operation);\n\t\ttry {\n\t\t\treturn Promise.resolve(operation());\n\t\t} catch (error) {\n\t\t\treturn Promise.reject(error);\n\t\t}\n\t}\n\n\trunAsync<T>(operation: () => Promise<T>): Promise<T> {\n\t\tif (this.pending > 0) return this.enqueue(operation);\n\t\tthis.pending++;\n\t\t// Publish the barrier before the operation starts, so calls it makes synchronously wait behind it.\n\t\tconst { promise: barrier, resolve: releaseBarrier } = Promise.withResolvers<void>();\n\t\tthis.tail = barrier;\n\t\tlet started: Promise<T>;\n\t\ttry {\n\t\t\tstarted = operation();\n\t\t} catch (error) {\n\t\t\tstarted = Promise.reject(error);\n\t\t}\n\t\treturn started.finally(() => {\n\t\t\tthis.pending--;\n\t\t\treleaseBarrier();\n\t\t});\n\t}\n\n\tprivate enqueue<T>(operation: () => T | Promise<T>): Promise<T> {\n\t\tthis.pending++;\n\t\treturn this.release(this.tail.then(operation));\n\t}\n\n\tprivate release<T>(operation: Promise<T>): Promise<T> {\n\t\tconst settled = operation.finally(() => {\n\t\t\tthis.pending--;\n\t\t});\n\t\tthis.tail = settled.then(ignore, ignore);\n\t\treturn settled;\n\t}\n}\n\n/**\n * Executes SQL on one connection. Prepared statements are cached per connection by SQL text, so the\n * database and its transaction handles share them across transactions.\n */\nabstract class NodeSqliteExecutor implements SqliteExecutor {\n\tprotected readonly database: DatabaseSync;\n\tprotected readonly statements: Map<string, StatementSync>;\n\n\tconstructor(database: DatabaseSync, statements: Map<string, StatementSync>) {\n\t\tthis.database = database;\n\t\tthis.statements = statements;\n\t}\n\n\texec(sql: string): Promise<void> {\n\t\treturn this.runOperation(() => {\n\t\t\tthis.database.exec(sql);\n\t\t});\n\t}\n\n\trun(sql: string, ...params: SqliteValue[]): Promise<void> {\n\t\treturn this.runOperation(() => {\n\t\t\tthis.statement(sql).run(...params);\n\t\t});\n\t}\n\n\tget<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T | undefined> {\n\t\treturn this.runOperation(() => this.statement(sql).get(...params) as T | undefined);\n\t}\n\n\tall<T extends object>(sql: string, ...params: SqliteValue[]): Promise<T[]> {\n\t\treturn this.runOperation(() => this.statement(sql).all(...params) as T[]);\n\t}\n\n\tprotected abstract runOperation<T>(operation: () => T): Promise<T>;\n\n\tprivate statement(sql: string): StatementSync {\n\t\tlet statement = this.statements.get(sql);\n\t\tif (statement === undefined) {\n\t\t\tstatement = this.database.prepare(sql);\n\t\t\tthis.statements.set(sql, statement);\n\t\t}\n\t\treturn statement;\n\t}\n}\n\nclass NodeSqliteTransaction extends NodeSqliteExecutor {\n\tprivate readonly scope: TransactionScope;\n\n\tconstructor(database: DatabaseSync, statements: Map<string, StatementSync>, scope: TransactionScope) {\n\t\tsuper(database, statements);\n\t\tthis.scope = scope;\n\t}\n\n\tprotected async runOperation<T>(operation: () => T): Promise<T> {\n\t\tif (!this.scope.active) throw new Error(\"SQLite transaction handle is no longer active\");\n\t\treturn operation();\n\t}\n}\n\n/** `SqliteDatabase` adapter backed by Node's built-in `node:sqlite`. */\nexport class NodeSqliteDatabase extends NodeSqliteExecutor implements SqliteDatabase {\n\tprivate readonly access = new SerialOperationQueue();\n\tprivate closed = false;\n\n\tconstructor(database: DatabaseSync) {\n\t\tsuper(database, new Map());\n\t}\n\n\ttransaction<T>(callback: (transaction: SqliteExecutor) => Promise<T>): Promise<T> {\n\t\treturn this.access.runAsync(async () => {\n\t\t\tthis.database.exec(\"BEGIN IMMEDIATE\");\n\t\t\tconst scope = { active: true };\n\t\t\ttry {\n\t\t\t\tconst result = await callback(new NodeSqliteTransaction(this.database, this.statements, scope));\n\t\t\t\tscope.active = false;\n\t\t\t\tthis.database.exec(\"COMMIT\");\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tscope.active = false;\n\t\t\t\ttry {\n\t\t\t\t\tthis.database.exec(\"ROLLBACK\");\n\t\t\t\t} catch (rollbackError) {\n\t\t\t\t\tthrow new AggregateError([error, rollbackError], \"SQLite transaction failed and rollback failed\");\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\t}\n\n\tclose(): Promise<void> {\n\t\treturn this.access.run(() => {\n\t\t\tif (this.closed) return;\n\t\t\tthis.closed = true;\n\t\t\tthis.statements.clear();\n\t\t\ttry {\n\t\t\t\tthis.database.exec(\"PRAGMA wal_checkpoint(TRUNCATE)\");\n\t\t\t} finally {\n\t\t\t\tthis.database.close();\n\t\t\t}\n\t\t});\n\t}\n\n\tprotected runOperation<T>(operation: () => T): Promise<T> {\n\t\treturn this.access.run(operation);\n\t}\n}\n\n/** Open and configure a Node-backed SQLite database facade. */\nexport async function openNodeSqliteDatabase(\n\tpath: string,\n\toptions: NodeSqliteDatabaseOptions = {},\n): Promise<NodeSqliteDatabase> {\n\tconst checkpointPages = options.walAutoCheckpointPages ?? DEFAULT_WAL_AUTO_CHECKPOINT_PAGES;\n\tconst timeout = options.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS;\n\tif (path !== \":memory:\") await mkdir(dirname(path), { recursive: true });\n\tconst database = new DatabaseSync(path, { timeout });\n\tconst adapter = new NodeSqliteDatabase(database);\n\ttry {\n\t\tawait adapter.exec(\"PRAGMA journal_mode = WAL\");\n\t\tawait adapter.exec(\"PRAGMA synchronous = NORMAL\");\n\t\tawait adapter.exec(`PRAGMA wal_autocheckpoint = ${checkpointPages}`);\n\t\treturn adapter;\n\t} catch (error) {\n\t\ttry {\n\t\t\tawait adapter.close();\n\t\t} catch {\n\t\t\t// Preserve the configuration failure.\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/** Open or create file-backed durable storage using Node's built-in SQLite, optionally under a table prefix. */\nexport async function openNodeSqliteStorage(\n\tpath: string,\n\toptions: NodeSqliteStorageOptions = {},\n): Promise<SqliteStorage> {\n\tconst { prefix, ...databaseOptions } = options;\n\tif (prefix !== undefined) validateSqliteSchemaPrefix(prefix);\n\treturn SqliteStorage.open(await openNodeSqliteDatabase(path, databaseOptions), { prefix });\n}\n"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Immutable identifier history for migrations and runtime queries. Never change or remove an existing value; a
|
|
3
|
+
* rename adds a new entry so historical migrations keep rendering their original object names.
|
|
4
|
+
*/
|
|
5
|
+
declare const TABLE_NAMES: {
|
|
6
|
+
readonly durableSchema: "durable_schema";
|
|
7
|
+
readonly durableMetadata: "durable_metadata";
|
|
8
|
+
readonly recordIds: "record_ids";
|
|
9
|
+
readonly conversations: "conversations";
|
|
10
|
+
readonly entries: "entries";
|
|
11
|
+
readonly tasks: "tasks";
|
|
12
|
+
readonly submissions: "submissions";
|
|
13
|
+
readonly documents: "documents";
|
|
14
|
+
readonly documentRevisions: "document_revisions";
|
|
15
|
+
};
|
|
16
|
+
declare const INDEX_NAMES: {
|
|
17
|
+
readonly conversationsByOwnerConversation: "conversations_by_owner_conversation";
|
|
18
|
+
readonly conversationsByOwnerTask: "conversations_by_owner_task";
|
|
19
|
+
readonly entriesByConversation: "entries_by_conversation";
|
|
20
|
+
readonly entryHeadsByConversation: "entry_heads_by_conversation";
|
|
21
|
+
readonly tasksByStatus: "tasks_by_status";
|
|
22
|
+
readonly tasksByConversation: "tasks_by_conversation";
|
|
23
|
+
readonly tasksByKind: "tasks_by_kind";
|
|
24
|
+
readonly tasksByAbortRequested: "tasks_by_abort_requested";
|
|
25
|
+
readonly tasksByBackground: "tasks_by_background";
|
|
26
|
+
readonly submissionsByRequest: "submissions_by_request";
|
|
27
|
+
readonly submissionsByConversation: "submissions_by_conversation";
|
|
28
|
+
readonly submissionsByStatus: "submissions_by_status";
|
|
29
|
+
readonly documentsByAddress: "documents_by_address";
|
|
30
|
+
readonly documentsByScope: "documents_by_scope";
|
|
31
|
+
readonly documentsByScopeKind: "documents_by_scope_kind";
|
|
32
|
+
readonly documentRevisionsByKind: "document_revisions_by_kind";
|
|
33
|
+
};
|
|
34
|
+
type SqliteIdentifiers<T extends Record<string, string>> = {
|
|
35
|
+
readonly [K in keyof T]: string;
|
|
36
|
+
};
|
|
37
|
+
export type SqliteSchema = {
|
|
38
|
+
readonly tables: SqliteIdentifiers<typeof TABLE_NAMES>;
|
|
39
|
+
readonly indexes: SqliteIdentifiers<typeof INDEX_NAMES>;
|
|
40
|
+
};
|
|
41
|
+
/** Validate a prefix before using it as part of a SQLite identifier. */
|
|
42
|
+
export declare function validateSqliteSchemaPrefix(prefix: string): void;
|
|
43
|
+
/** Build the identifiers used by every migration and storage query. */
|
|
44
|
+
export declare function createSqliteSchema(prefix?: string): SqliteSchema;
|
|
45
|
+
export declare const DEFAULT_SQLITE_SCHEMA: SqliteSchema;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/storage/sqlite/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,QAAA,MAAM,WAAW;aAChB,aAAa,EAAE,gBAAgB;aAC/B,eAAe,EAAE,kBAAkB;aACnC,SAAS,EAAE,YAAY;aACvB,aAAa,EAAE,eAAe;aAC9B,OAAO,EAAE,SAAS;aAClB,KAAK,EAAE,OAAO;aACd,WAAW,EAAE,aAAa;aAC1B,SAAS,EAAE,WAAW;aACtB,iBAAiB,EAAE,oBAAoB;CAC9B,CAAC;AAEX,QAAA,MAAM,WAAW;aAChB,gCAAgC,EAAE,qCAAqC;aACvE,wBAAwB,EAAE,6BAA6B;aACvD,qBAAqB,EAAE,yBAAyB;aAChD,wBAAwB,EAAE,6BAA6B;aACvD,aAAa,EAAE,iBAAiB;aAChC,mBAAmB,EAAE,uBAAuB;aAC5C,WAAW,EAAE,eAAe;aAC5B,qBAAqB,EAAE,0BAA0B;aACjD,iBAAiB,EAAE,qBAAqB;aACxC,oBAAoB,EAAE,wBAAwB;aAC9C,yBAAyB,EAAE,6BAA6B;aACxD,mBAAmB,EAAE,uBAAuB;aAC5C,kBAAkB,EAAE,sBAAsB;aAC1C,gBAAgB,EAAE,oBAAoB;aACtC,oBAAoB,EAAE,yBAAyB;aAC/C,uBAAuB,EAAE,4BAA4B;CAC5C,CAAC;AAEX,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI;IAAE,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM;CAAE,CAAC;AAE/F,MAAM,MAAM,YAAY,GAAG;IAC1B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC,OAAO,WAAW,CAAC,CAAC;IACvD,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,OAAO,WAAW,CAAC,CAAC;CACxD,CAAC;AAEF,wEAAwE;AACxE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAO/D;AAQD,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAOhE;AAED,eAAO,MAAM,qBAAqB,cAAuB,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Immutable identifier history for migrations and runtime queries. Never change or remove an existing value; a
|
|
3
|
+
* rename adds a new entry so historical migrations keep rendering their original object names.
|
|
4
|
+
*/
|
|
5
|
+
const TABLE_NAMES = {
|
|
6
|
+
durableSchema: "durable_schema",
|
|
7
|
+
durableMetadata: "durable_metadata",
|
|
8
|
+
recordIds: "record_ids",
|
|
9
|
+
conversations: "conversations",
|
|
10
|
+
entries: "entries",
|
|
11
|
+
tasks: "tasks",
|
|
12
|
+
submissions: "submissions",
|
|
13
|
+
documents: "documents",
|
|
14
|
+
documentRevisions: "document_revisions",
|
|
15
|
+
};
|
|
16
|
+
const INDEX_NAMES = {
|
|
17
|
+
conversationsByOwnerConversation: "conversations_by_owner_conversation",
|
|
18
|
+
conversationsByOwnerTask: "conversations_by_owner_task",
|
|
19
|
+
entriesByConversation: "entries_by_conversation",
|
|
20
|
+
entryHeadsByConversation: "entry_heads_by_conversation",
|
|
21
|
+
tasksByStatus: "tasks_by_status",
|
|
22
|
+
tasksByConversation: "tasks_by_conversation",
|
|
23
|
+
tasksByKind: "tasks_by_kind",
|
|
24
|
+
tasksByAbortRequested: "tasks_by_abort_requested",
|
|
25
|
+
tasksByBackground: "tasks_by_background",
|
|
26
|
+
submissionsByRequest: "submissions_by_request",
|
|
27
|
+
submissionsByConversation: "submissions_by_conversation",
|
|
28
|
+
submissionsByStatus: "submissions_by_status",
|
|
29
|
+
documentsByAddress: "documents_by_address",
|
|
30
|
+
documentsByScope: "documents_by_scope",
|
|
31
|
+
documentsByScopeKind: "documents_by_scope_kind",
|
|
32
|
+
documentRevisionsByKind: "document_revisions_by_kind",
|
|
33
|
+
};
|
|
34
|
+
/** Validate a prefix before using it as part of a SQLite identifier. */
|
|
35
|
+
export function validateSqliteSchemaPrefix(prefix) {
|
|
36
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(prefix)) {
|
|
37
|
+
throw new Error(`Invalid SQLite schema prefix ${JSON.stringify(prefix)}`);
|
|
38
|
+
}
|
|
39
|
+
if (prefix.toLowerCase().startsWith("sqlite_")) {
|
|
40
|
+
throw new Error(`SQLite schema prefix ${JSON.stringify(prefix)} is reserved`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function prefixIdentifiers(names, prefix) {
|
|
44
|
+
return Object.fromEntries(Object.entries(names).map(([key, name]) => [key, `${prefix}${name}`]));
|
|
45
|
+
}
|
|
46
|
+
/** Build the identifiers used by every migration and storage query. */
|
|
47
|
+
export function createSqliteSchema(prefix) {
|
|
48
|
+
if (prefix !== undefined)
|
|
49
|
+
validateSqliteSchemaPrefix(prefix);
|
|
50
|
+
const actualPrefix = prefix ?? "";
|
|
51
|
+
return {
|
|
52
|
+
tables: prefixIdentifiers(TABLE_NAMES, actualPrefix),
|
|
53
|
+
indexes: prefixIdentifiers(INDEX_NAMES, actualPrefix),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export const DEFAULT_SQLITE_SCHEMA = createSqliteSchema();
|
|
57
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/storage/sqlite/schema.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,GAAG;IACnB,aAAa,EAAE,gBAAgB;IAC/B,eAAe,EAAE,kBAAkB;IACnC,SAAS,EAAE,YAAY;IACvB,aAAa,EAAE,eAAe;IAC9B,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,WAAW,EAAE,aAAa;IAC1B,SAAS,EAAE,WAAW;IACtB,iBAAiB,EAAE,oBAAoB;CAC9B,CAAC;AAEX,MAAM,WAAW,GAAG;IACnB,gCAAgC,EAAE,qCAAqC;IACvE,wBAAwB,EAAE,6BAA6B;IACvD,qBAAqB,EAAE,yBAAyB;IAChD,wBAAwB,EAAE,6BAA6B;IACvD,aAAa,EAAE,iBAAiB;IAChC,mBAAmB,EAAE,uBAAuB;IAC5C,WAAW,EAAE,eAAe;IAC5B,qBAAqB,EAAE,0BAA0B;IACjD,iBAAiB,EAAE,qBAAqB;IACxC,oBAAoB,EAAE,wBAAwB;IAC9C,yBAAyB,EAAE,6BAA6B;IACxD,mBAAmB,EAAE,uBAAuB;IAC5C,kBAAkB,EAAE,sBAAsB;IAC1C,gBAAgB,EAAE,oBAAoB;IACtC,oBAAoB,EAAE,yBAAyB;IAC/C,uBAAuB,EAAE,4BAA4B;CAC5C,CAAC;AASX,wEAAwE;AACxE,MAAM,UAAU,0BAA0B,CAAC,MAAc;IACxD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAC/E,CAAC;AACF,CAAC;AAED,SAAS,iBAAiB,CAAmC,KAAQ,EAAE,MAAc;IACpF,OAAO,MAAM,CAAC,WAAW,CACxB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC,CAC7C,CAAC;AAC3B,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,kBAAkB,CAAC,MAAe;IACjD,IAAI,MAAM,KAAK,SAAS;QAAE,0BAA0B,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,MAAM,IAAI,EAAE,CAAC;IAClC,OAAO;QACN,MAAM,EAAE,iBAAiB,CAAC,WAAW,EAAE,YAAY,CAAC;QACpD,OAAO,EAAE,iBAAiB,CAAC,WAAW,EAAE,YAAY,CAAC;KACrD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAAkB,EAAE,CAAC","sourcesContent":["/**\n * Immutable identifier history for migrations and runtime queries. Never change or remove an existing value; a\n * rename adds a new entry so historical migrations keep rendering their original object names.\n */\nconst TABLE_NAMES = {\n\tdurableSchema: \"durable_schema\",\n\tdurableMetadata: \"durable_metadata\",\n\trecordIds: \"record_ids\",\n\tconversations: \"conversations\",\n\tentries: \"entries\",\n\ttasks: \"tasks\",\n\tsubmissions: \"submissions\",\n\tdocuments: \"documents\",\n\tdocumentRevisions: \"document_revisions\",\n} as const;\n\nconst INDEX_NAMES = {\n\tconversationsByOwnerConversation: \"conversations_by_owner_conversation\",\n\tconversationsByOwnerTask: \"conversations_by_owner_task\",\n\tentriesByConversation: \"entries_by_conversation\",\n\tentryHeadsByConversation: \"entry_heads_by_conversation\",\n\ttasksByStatus: \"tasks_by_status\",\n\ttasksByConversation: \"tasks_by_conversation\",\n\ttasksByKind: \"tasks_by_kind\",\n\ttasksByAbortRequested: \"tasks_by_abort_requested\",\n\ttasksByBackground: \"tasks_by_background\",\n\tsubmissionsByRequest: \"submissions_by_request\",\n\tsubmissionsByConversation: \"submissions_by_conversation\",\n\tsubmissionsByStatus: \"submissions_by_status\",\n\tdocumentsByAddress: \"documents_by_address\",\n\tdocumentsByScope: \"documents_by_scope\",\n\tdocumentsByScopeKind: \"documents_by_scope_kind\",\n\tdocumentRevisionsByKind: \"document_revisions_by_kind\",\n} as const;\n\ntype SqliteIdentifiers<T extends Record<string, string>> = { readonly [K in keyof T]: string };\n\nexport type SqliteSchema = {\n\treadonly tables: SqliteIdentifiers<typeof TABLE_NAMES>;\n\treadonly indexes: SqliteIdentifiers<typeof INDEX_NAMES>;\n};\n\n/** Validate a prefix before using it as part of a SQLite identifier. */\nexport function validateSqliteSchemaPrefix(prefix: string): void {\n\tif (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(prefix)) {\n\t\tthrow new Error(`Invalid SQLite schema prefix ${JSON.stringify(prefix)}`);\n\t}\n\tif (prefix.toLowerCase().startsWith(\"sqlite_\")) {\n\t\tthrow new Error(`SQLite schema prefix ${JSON.stringify(prefix)} is reserved`);\n\t}\n}\n\nfunction prefixIdentifiers<T extends Record<string, string>>(names: T, prefix: string): SqliteIdentifiers<T> {\n\treturn Object.fromEntries(\n\t\tObject.entries(names).map(([key, name]) => [key, `${prefix}${name}`]),\n\t) as SqliteIdentifiers<T>;\n}\n\n/** Build the identifiers used by every migration and storage query. */\nexport function createSqliteSchema(prefix?: string): SqliteSchema {\n\tif (prefix !== undefined) validateSqliteSchemaPrefix(prefix);\n\tconst actualPrefix = prefix ?? \"\";\n\treturn {\n\t\ttables: prefixIdentifiers(TABLE_NAMES, actualPrefix),\n\t\tindexes: prefixIdentifiers(INDEX_NAMES, actualPrefix),\n\t};\n}\n\nexport const DEFAULT_SQLITE_SCHEMA = createSqliteSchema();\n"]}
|