From 6b8b140c858d3f1fb59cfd73597f465718ead9ba Mon Sep 17 00:00:00 2001 From: Cristina Poncela Cubeiro <140309543+cristinaponcela@users.noreply.github.com> Date: Thu, 13 Aug 2026 12:08:51 +0200 Subject: [PATCH] feat(sqlite): scaffold storage --- .../sqlite-node/src/sqlite/index.ts | 1 + .../sqlite-node/src/sqlite/storage.ts | 108 ++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 packages/session-backends/sqlite-node/src/sqlite/storage.ts diff --git a/packages/session-backends/sqlite-node/src/sqlite/index.ts b/packages/session-backends/sqlite-node/src/sqlite/index.ts index 1bdb8800a..c73d3d522 100644 --- a/packages/session-backends/sqlite-node/src/sqlite/index.ts +++ b/packages/session-backends/sqlite-node/src/sqlite/index.ts @@ -1,5 +1,6 @@ export * from "./repo.ts"; export * from "./sql.ts"; +export * from "./storage.ts"; export type { SqliteDatabase, SqliteDatabaseFactory, diff --git a/packages/session-backends/sqlite-node/src/sqlite/storage.ts b/packages/session-backends/sqlite-node/src/sqlite/storage.ts new file mode 100644 index 000000000..1af15077b --- /dev/null +++ b/packages/session-backends/sqlite-node/src/sqlite/storage.ts @@ -0,0 +1,108 @@ +import type { + BranchScan, + CommitResult, + Entry, + EntryScan, + EntryStructure, + Register, + RegisterNamespace, + SessionStats, + Storage, + StorageBranchScan, + Transaction, + UsageRow, + UsageScan, +} from "@earendil-works/pi-agent-core"; +import type { SqliteDatabase } from "./types.ts"; + +export interface SqliteStorageOptions { + now?: () => number; +} + +export class SqliteStorage implements Storage { + private readonly db: SqliteDatabase; + private readonly now: () => number; + private commitQueue: Promise = Promise.resolve(); + private state: "open" | "closing" | "closed" = "open"; + private closePromise: Promise | undefined; + + constructor(db: SqliteDatabase, options: SqliteStorageOptions = {}) { + this.db = db; + this.now = options.now ?? Date.now; + } + + commit(_transaction: Transaction): Promise { + this.assertOpen(); + // TODO: Implement atomic SQLite commits in one BEGIN IMMEDIATE transaction. + void this.db; + void this.now; + return Promise.reject(new Error("SqliteStorage.commit is not implemented")); + } + + getEntries(_ids: string[]): Promise> { + this.assertOpen(); + // TODO: Implement using session/entries.ts helpers. + return Promise.reject(new Error("SqliteStorage.getEntries is not implemented")); + } + + getRegister( + _namespace: TNamespace, + _key: string, + ): Promise | undefined> { + this.assertOpen(); + // TODO: Implement using session/registers.ts helpers. + return Promise.reject(new Error("SqliteStorage.getRegister is not implemented")); + } + + listRegisters( + _namespace: TNamespace, + _keyPrefix?: string, + ): Promise[]> { + this.assertOpen(); + // TODO: Implement using session/registers.ts helpers. + return Promise.reject(new Error("SqliteStorage.listRegisters is not implemented")); + } + + scanBranch(_query: StorageBranchScan): Promise { + this.assertOpen(); + // TODO: Implement using the private branch index. + return Promise.reject(new Error("SqliteStorage.scanBranch is not implemented")); + } + + scanBranchStructure(_query: BranchScan & { start: string }): Promise { + this.assertOpen(); + // TODO: Implement using the private branch index. + return Promise.reject(new Error("SqliteStorage.scanBranchStructure is not implemented")); + } + + scanEntries(_query: EntryScan): Promise { + this.assertOpen(); + // TODO: Implement using session/entries.ts helpers. + return Promise.reject(new Error("SqliteStorage.scanEntries is not implemented")); + } + + scanUsage(_query: UsageScan): Promise { + this.assertOpen(); + // TODO: Implement using session/usage-ledger.ts helpers. + return Promise.reject(new Error("SqliteStorage.scanUsage is not implemented")); + } + + getStats(): Promise { + this.assertOpen(); + // TODO: Implement using session/session-stats.ts helpers. + return Promise.reject(new Error("SqliteStorage.getStats is not implemented")); + } + + close(): Promise { + if (this.closePromise !== undefined) return this.closePromise; + this.state = "closing"; + this.closePromise = this.commitQueue.then(() => { + this.state = "closed"; + }); + return this.closePromise; + } + + private assertOpen(): void { + if (this.state !== "open") throw new Error("SqliteStorage is closed"); + } +}