@framers/sql-storage-adapter 0.1.0 → 0.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/LICENSE +20 -20
- package/README.md +241 -363
- package/dist/adapters/__tests__/indexedDbAdapter.spec.d.ts +2 -0
- package/dist/adapters/__tests__/indexedDbAdapter.spec.d.ts.map +1 -0
- package/dist/adapters/__tests__/indexedDbAdapter.spec.js +137 -0
- package/dist/adapters/__tests__/indexedDbAdapter.spec.js.map +1 -0
- package/dist/adapters/baseStorageAdapter.d.ts +1 -1
- package/dist/adapters/baseStorageAdapter.d.ts.map +1 -1
- package/dist/adapters/betterSqliteAdapter.d.ts +27 -1
- package/dist/adapters/betterSqliteAdapter.d.ts.map +1 -1
- package/dist/adapters/betterSqliteAdapter.js +81 -16
- package/dist/adapters/betterSqliteAdapter.js.map +1 -1
- package/dist/adapters/capacitorSqliteAdapter.d.ts +1 -1
- package/dist/adapters/capacitorSqliteAdapter.d.ts.map +1 -1
- package/dist/adapters/capacitorSqliteAdapter.js +27 -4
- package/dist/adapters/capacitorSqliteAdapter.js.map +1 -1
- package/dist/adapters/indexedDbAdapter.d.ts +189 -0
- package/dist/adapters/indexedDbAdapter.d.ts.map +1 -0
- package/dist/adapters/indexedDbAdapter.js +367 -0
- package/dist/adapters/indexedDbAdapter.js.map +1 -0
- package/dist/adapters/postgresAdapter.d.ts +7 -1
- package/dist/adapters/postgresAdapter.d.ts.map +1 -1
- package/dist/adapters/postgresAdapter.js +19 -2
- package/dist/adapters/postgresAdapter.js.map +1 -1
- package/dist/adapters/sqlJsAdapter.d.ts +1 -1
- package/dist/adapters/sqlJsAdapter.d.ts.map +1 -1
- package/dist/adapters/sqlJsAdapter.js +16 -2
- package/dist/adapters/sqlJsAdapter.js.map +1 -1
- package/dist/adapters/supabase.d.ts +3 -3
- package/dist/adapters/supabase.d.ts.map +1 -1
- package/dist/adapters/supabase.js +11 -7
- package/dist/adapters/supabase.js.map +1 -1
- package/dist/agentos/AgentOSStorageAdapter.d.ts +320 -0
- package/dist/agentos/AgentOSStorageAdapter.d.ts.map +1 -0
- package/dist/agentos/AgentOSStorageAdapter.js +406 -0
- package/dist/agentos/AgentOSStorageAdapter.js.map +1 -0
- package/dist/agentos/index.d.ts +7 -0
- package/dist/agentos/index.d.ts.map +1 -0
- package/dist/agentos/index.js +7 -0
- package/dist/agentos/index.js.map +1 -0
- package/dist/{types → core/contracts}/context.d.ts +2 -2
- package/dist/core/contracts/context.d.ts.map +1 -0
- package/dist/core/contracts/context.js.map +1 -0
- package/dist/{types → core/contracts}/events.d.ts +1 -1
- package/dist/core/contracts/events.d.ts.map +1 -0
- package/dist/core/contracts/events.js.map +1 -0
- package/dist/{types → core/contracts}/extensions.d.ts +3 -3
- package/dist/core/contracts/extensions.d.ts.map +1 -0
- package/dist/core/contracts/extensions.js.map +1 -0
- package/dist/{types.d.ts → core/contracts/index.d.ts} +1 -1
- package/dist/core/contracts/index.d.ts.map +1 -0
- package/dist/{types.js → core/contracts/index.js} +1 -1
- package/dist/core/contracts/index.js.map +1 -0
- package/dist/core/contracts/limitations.d.ts.map +1 -0
- package/dist/core/contracts/limitations.js.map +1 -0
- package/dist/{database.d.ts → core/database.d.ts} +16 -3
- package/dist/core/database.d.ts.map +1 -0
- package/dist/{database.js → core/database.js} +39 -8
- package/dist/core/database.js.map +1 -0
- package/dist/{resolver.d.ts → core/resolver.d.ts} +4 -4
- package/dist/core/resolver.d.ts.map +1 -0
- package/dist/{resolver.js → core/resolver.js} +24 -8
- package/dist/core/resolver.js.map +1 -0
- package/dist/{utils → features/backup}/cloudBackup.d.ts +1 -1
- package/dist/features/backup/cloudBackup.d.ts.map +1 -0
- package/dist/{utils → features/backup}/cloudBackup.js +2 -2
- package/dist/features/backup/cloudBackup.js.map +1 -0
- package/dist/{utils → features/migrations}/dataExport.d.ts +1 -1
- package/dist/features/migrations/dataExport.d.ts.map +1 -0
- package/dist/features/migrations/dataExport.js.map +1 -0
- package/dist/{utils → features/migrations}/dataImport.d.ts +1 -1
- package/dist/features/migrations/dataImport.d.ts.map +1 -0
- package/dist/features/migrations/dataImport.js.map +1 -0
- package/dist/{utils → features/migrations}/migration.d.ts +2 -2
- package/dist/features/migrations/migration.d.ts.map +1 -0
- package/dist/{utils → features/migrations}/migration.js +6 -6
- package/dist/features/migrations/migration.js.map +1 -0
- package/dist/{utils → features/sync}/syncManager.d.ts +11 -5
- package/dist/features/sync/syncManager.d.ts.map +1 -0
- package/dist/{utils → features/sync}/syncManager.js +40 -10
- package/dist/features/sync/syncManager.js.map +1 -0
- package/dist/index.d.ts +12 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -19
- package/dist/index.js.map +1 -1
- package/dist/{utils → shared}/parameterUtils.d.ts +1 -1
- package/dist/shared/parameterUtils.d.ts.map +1 -0
- package/dist/shared/parameterUtils.js.map +1 -0
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +22 -6
- package/dist/database.d.ts.map +0 -1
- package/dist/database.js.map +0 -1
- package/dist/resolver.d.ts.map +0 -1
- package/dist/resolver.js.map +0 -1
- package/dist/types/context.d.ts.map +0 -1
- package/dist/types/context.js.map +0 -1
- package/dist/types/events.d.ts.map +0 -1
- package/dist/types/events.js.map +0 -1
- package/dist/types/extensions.d.ts.map +0 -1
- package/dist/types/extensions.js.map +0 -1
- package/dist/types/limitations.d.ts.map +0 -1
- package/dist/types/limitations.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/cloudBackup.d.ts.map +0 -1
- package/dist/utils/cloudBackup.js.map +0 -1
- package/dist/utils/dataExport.d.ts.map +0 -1
- package/dist/utils/dataExport.js.map +0 -1
- package/dist/utils/dataImport.d.ts.map +0 -1
- package/dist/utils/dataImport.js.map +0 -1
- package/dist/utils/migration.d.ts.map +0 -1
- package/dist/utils/migration.js.map +0 -1
- package/dist/utils/parameterUtils.d.ts.map +0 -1
- package/dist/utils/parameterUtils.js.map +0 -1
- package/dist/utils/syncManager.d.ts.map +0 -1
- package/dist/utils/syncManager.js.map +0 -1
- /package/dist/{types → core/contracts}/context.js +0 -0
- /package/dist/{types → core/contracts}/events.js +0 -0
- /package/dist/{types → core/contracts}/extensions.js +0 -0
- /package/dist/{types → core/contracts}/limitations.d.ts +0 -0
- /package/dist/{types → core/contracts}/limitations.js +0 -0
- /package/dist/{utils → features/migrations}/dataExport.js +0 -0
- /package/dist/{utils → features/migrations}/dataImport.js +0 -0
- /package/dist/{utils → shared}/parameterUtils.js +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview IndexedDB Storage Adapter for AgentOS
|
|
3
|
+
* @description Browser-native SQL storage using IndexedDB with sql.js for full client-side operation.
|
|
4
|
+
* Supports transactions, persistence to IndexedDB, and offline-first workflows.
|
|
5
|
+
*
|
|
6
|
+
* **Use cases:**
|
|
7
|
+
* - Fully client-side AgentOS (no backend needed)
|
|
8
|
+
* - Progressive Web Apps (PWAs)
|
|
9
|
+
* - Offline-capable agents
|
|
10
|
+
* - Privacy-first applications (data never leaves browser)
|
|
11
|
+
*
|
|
12
|
+
* **Architecture:**
|
|
13
|
+
* - Uses sql.js (SQLite compiled to WebAssembly) for SQL execution
|
|
14
|
+
* - Persists database to IndexedDB for durability across sessions
|
|
15
|
+
* - Auto-saves after each transaction
|
|
16
|
+
* - Supports import/export for data portability
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { IndexedDbAdapter } from '../adapters/indexedDbAdapter';
|
|
21
|
+
*
|
|
22
|
+
* const adapter = new IndexedDbAdapter({
|
|
23
|
+
* dbName: 'agentos-client-db',
|
|
24
|
+
* autoSave: true,
|
|
25
|
+
* saveIntervalMs: 5000,
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* await adapter.open();
|
|
29
|
+
* await adapter.run('CREATE TABLE sessions (id TEXT PRIMARY KEY, data TEXT)');
|
|
30
|
+
* await adapter.run('INSERT INTO sessions VALUES (?, ?)', ['session-1', '{"events": []}']);
|
|
31
|
+
*
|
|
32
|
+
* const session = await adapter.get('SELECT * FROM sessions WHERE id = ?', ['session-1']);
|
|
33
|
+
* console.log(session);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import type { StorageAdapter, StorageCapability, StorageOpenOptions, StorageParameters, StorageRunResult } from '../core/contracts';
|
|
37
|
+
/**
|
|
38
|
+
* Configuration for IndexedDB adapter.
|
|
39
|
+
*/
|
|
40
|
+
export interface IndexedDbAdapterOptions {
|
|
41
|
+
/** IndexedDB database name (default: 'agentos-db') */
|
|
42
|
+
dbName?: string;
|
|
43
|
+
/** IndexedDB object store name (default: 'sqliteDb') */
|
|
44
|
+
storeName?: string;
|
|
45
|
+
/** Auto-save to IndexedDB after each write (default: true) */
|
|
46
|
+
autoSave?: boolean;
|
|
47
|
+
/** Save interval in milliseconds for batched writes (default: 5000) */
|
|
48
|
+
saveIntervalMs?: number;
|
|
49
|
+
/** sql.js configuration (e.g., locateFile for wasm) */
|
|
50
|
+
sqlJsConfig?: any;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Storage adapter using IndexedDB + sql.js for client-side SQL persistence.
|
|
54
|
+
*
|
|
55
|
+
* **Capabilities:**
|
|
56
|
+
* - ✅ Transactions
|
|
57
|
+
* - ✅ Persistence (IndexedDB)
|
|
58
|
+
* - ✅ Full SQL support (via sql.js)
|
|
59
|
+
* - ✅ Export/import
|
|
60
|
+
* - ❌ Concurrent writes (single-threaded)
|
|
61
|
+
* - ❌ Server-side (browser only)
|
|
62
|
+
*
|
|
63
|
+
* **Performance:**
|
|
64
|
+
* - Fast reads (in-memory SQL)
|
|
65
|
+
* - Moderate writes (IndexedDB persistence)
|
|
66
|
+
* - Auto-save batching reduces IDB overhead
|
|
67
|
+
*
|
|
68
|
+
* @example Client-side AgentOS
|
|
69
|
+
* ```typescript
|
|
70
|
+
* const adapter = new IndexedDbAdapter({ dbName: 'my-app-db' });
|
|
71
|
+
* const agentos = new AgentOS();
|
|
72
|
+
* await agentos.initialize({
|
|
73
|
+
* storageAdapter: adapter,
|
|
74
|
+
* // ... other config
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare class IndexedDbAdapter implements StorageAdapter {
|
|
79
|
+
readonly kind = "indexeddb";
|
|
80
|
+
readonly capabilities: ReadonlySet<StorageCapability>;
|
|
81
|
+
private SQL;
|
|
82
|
+
private db;
|
|
83
|
+
private idb;
|
|
84
|
+
private saveTimer;
|
|
85
|
+
private dirty;
|
|
86
|
+
private readonly dbName;
|
|
87
|
+
private readonly storeName;
|
|
88
|
+
private readonly autoSave;
|
|
89
|
+
private readonly saveIntervalMs;
|
|
90
|
+
private readonly sqlJsConfig;
|
|
91
|
+
constructor(options?: IndexedDbAdapterOptions);
|
|
92
|
+
/**
|
|
93
|
+
* Opens IndexedDB and initializes sql.js database.
|
|
94
|
+
* Loads existing database from IndexedDB if present.
|
|
95
|
+
*/
|
|
96
|
+
open(_options?: StorageOpenOptions): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* Executes a SQL statement that doesn't return rows (INSERT, UPDATE, DELETE, CREATE, etc.).
|
|
99
|
+
* @param statement SQL statement with ? or :name placeholders
|
|
100
|
+
* @param parameters Positional array or named object
|
|
101
|
+
* @returns Result with changes count and last insert row ID
|
|
102
|
+
*/
|
|
103
|
+
run(statement: string, parameters?: StorageParameters): Promise<StorageRunResult>;
|
|
104
|
+
/**
|
|
105
|
+
* Executes a SQL query and returns the first row.
|
|
106
|
+
* @param statement SELECT statement
|
|
107
|
+
* @param parameters Query parameters
|
|
108
|
+
* @returns First row as object or null if no results
|
|
109
|
+
*/
|
|
110
|
+
get<T>(statement: string, parameters?: StorageParameters): Promise<T | null>;
|
|
111
|
+
/**
|
|
112
|
+
* Executes a SQL query and returns all matching rows.
|
|
113
|
+
* @param statement SELECT statement
|
|
114
|
+
* @param parameters Query parameters
|
|
115
|
+
* @returns Array of result rows as objects
|
|
116
|
+
*/
|
|
117
|
+
all<T>(statement: string, parameters?: StorageParameters): Promise<T[]>;
|
|
118
|
+
/**
|
|
119
|
+
* Executes a script containing multiple SQL statements.
|
|
120
|
+
*/
|
|
121
|
+
exec(script: string): Promise<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Executes a callback within a database transaction.
|
|
124
|
+
*/
|
|
125
|
+
transaction<T>(fn: (trx: StorageAdapter) => Promise<T>): Promise<T>;
|
|
126
|
+
/**
|
|
127
|
+
* Begins a transaction. sql.js executes all statements in implicit transactions,
|
|
128
|
+
* so this is a no-op for compatibility.
|
|
129
|
+
*/
|
|
130
|
+
beginTransaction(): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Commits the current transaction.
|
|
133
|
+
*/
|
|
134
|
+
commit(): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Rolls back the current transaction.
|
|
137
|
+
*/
|
|
138
|
+
rollback(): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* Closes the database and persists final state to IndexedDB.
|
|
141
|
+
*/
|
|
142
|
+
close(): Promise<void>;
|
|
143
|
+
/**
|
|
144
|
+
* Exports the database as a Uint8Array (SQLite file format).
|
|
145
|
+
* Can be downloaded or stored externally.
|
|
146
|
+
* @returns SQLite database file as binary
|
|
147
|
+
*/
|
|
148
|
+
exportDatabase(): Uint8Array;
|
|
149
|
+
/**
|
|
150
|
+
* Imports a database from a Uint8Array (SQLite file).
|
|
151
|
+
* Replaces the current database.
|
|
152
|
+
* @param data SQLite database file
|
|
153
|
+
*/
|
|
154
|
+
importDatabase(data: Uint8Array): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Opens or creates the IndexedDB database.
|
|
157
|
+
*/
|
|
158
|
+
private openIndexedDb;
|
|
159
|
+
/**
|
|
160
|
+
* Loads the SQLite database from IndexedDB.
|
|
161
|
+
* @returns Binary database or null if not found
|
|
162
|
+
*/
|
|
163
|
+
private loadFromIndexedDb;
|
|
164
|
+
/**
|
|
165
|
+
* Saves the SQLite database to IndexedDB.
|
|
166
|
+
*/
|
|
167
|
+
private saveToIndexedDb;
|
|
168
|
+
/**
|
|
169
|
+
* Persists to IndexedDB if auto-save is enabled.
|
|
170
|
+
*/
|
|
171
|
+
private persistIfNeeded;
|
|
172
|
+
/**
|
|
173
|
+
* Starts auto-save interval.
|
|
174
|
+
*/
|
|
175
|
+
private startAutoSave;
|
|
176
|
+
/**
|
|
177
|
+
* Ensures the database is open.
|
|
178
|
+
*/
|
|
179
|
+
private ensureOpen;
|
|
180
|
+
/**
|
|
181
|
+
* Normalizes last insert row ID to string or number.
|
|
182
|
+
*/
|
|
183
|
+
private normaliseRowId;
|
|
184
|
+
/**
|
|
185
|
+
* Prepares a SQL statement for execution.
|
|
186
|
+
*/
|
|
187
|
+
private prepareInternal;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=indexedDbAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexedDbAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/indexedDbAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAG3B;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,sDAAsD;IACtD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,uDAAuD;IAEvD,WAAW,CAAC,EAAE,GAAG,CAAC;CACnB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,gBAAiB,YAAW,cAAc;IACrD,SAAgB,IAAI,eAAe;IACnC,SAAgB,YAAY,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAA4C;IAExG,OAAO,CAAC,GAAG,CAA4B;IACvC,OAAO,CAAC,EAAE,CAA8B;IACxC,OAAO,CAAC,GAAG,CAA4B;IACvC,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAM;gBAEtB,OAAO,GAAE,uBAA4B;IAQjD;;;OAGG;IACU,IAAI,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB/D;;;;;OAKG;IACU,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4B9F;;;;;OAKG;IACU,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAKzF;;;;;OAKG;IACU,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IA8BpF;;OAEG;IACU,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOhD;;OAEG;IACU,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAehF;;;OAGG;IACU,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAK9C;;OAEG;IACU,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAMpC;;OAEG;IACU,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAItC;;OAEG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBnC;;;;OAIG;IACI,cAAc,IAAI,UAAU;IAKnC;;;;OAIG;IACU,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ5D;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;;OAGG;YACW,iBAAiB;IAa/B;;OAEG;YACW,eAAe;IAkB7B;;OAEG;YACW,eAAe;IAO7B;;OAEG;IACH,OAAO,CAAC,aAAa;IAQrB;;OAEG;IACH,OAAO,CAAC,UAAU;IAMlB;;OAEG;IACH,OAAO,CAAC,cAAc;IAUtB;;OAEG;IACH,OAAO,CAAC,eAAe;CAIxB"}
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview IndexedDB Storage Adapter for AgentOS
|
|
3
|
+
* @description Browser-native SQL storage using IndexedDB with sql.js for full client-side operation.
|
|
4
|
+
* Supports transactions, persistence to IndexedDB, and offline-first workflows.
|
|
5
|
+
*
|
|
6
|
+
* **Use cases:**
|
|
7
|
+
* - Fully client-side AgentOS (no backend needed)
|
|
8
|
+
* - Progressive Web Apps (PWAs)
|
|
9
|
+
* - Offline-capable agents
|
|
10
|
+
* - Privacy-first applications (data never leaves browser)
|
|
11
|
+
*
|
|
12
|
+
* **Architecture:**
|
|
13
|
+
* - Uses sql.js (SQLite compiled to WebAssembly) for SQL execution
|
|
14
|
+
* - Persists database to IndexedDB for durability across sessions
|
|
15
|
+
* - Auto-saves after each transaction
|
|
16
|
+
* - Supports import/export for data portability
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* import { IndexedDbAdapter } from '../adapters/indexedDbAdapter';
|
|
21
|
+
*
|
|
22
|
+
* const adapter = new IndexedDbAdapter({
|
|
23
|
+
* dbName: 'agentos-client-db',
|
|
24
|
+
* autoSave: true,
|
|
25
|
+
* saveIntervalMs: 5000,
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* await adapter.open();
|
|
29
|
+
* await adapter.run('CREATE TABLE sessions (id TEXT PRIMARY KEY, data TEXT)');
|
|
30
|
+
* await adapter.run('INSERT INTO sessions VALUES (?, ?)', ['session-1', '{"events": []}']);
|
|
31
|
+
*
|
|
32
|
+
* const session = await adapter.get('SELECT * FROM sessions WHERE id = ?', ['session-1']);
|
|
33
|
+
* console.log(session);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
import initSqlJs from 'sql.js';
|
|
37
|
+
import { normaliseParameters } from '../shared/parameterUtils';
|
|
38
|
+
const DB_VERSION = 1;
|
|
39
|
+
/**
|
|
40
|
+
* Storage adapter using IndexedDB + sql.js for client-side SQL persistence.
|
|
41
|
+
*
|
|
42
|
+
* **Capabilities:**
|
|
43
|
+
* - ✅ Transactions
|
|
44
|
+
* - ✅ Persistence (IndexedDB)
|
|
45
|
+
* - ✅ Full SQL support (via sql.js)
|
|
46
|
+
* - ✅ Export/import
|
|
47
|
+
* - ❌ Concurrent writes (single-threaded)
|
|
48
|
+
* - ❌ Server-side (browser only)
|
|
49
|
+
*
|
|
50
|
+
* **Performance:**
|
|
51
|
+
* - Fast reads (in-memory SQL)
|
|
52
|
+
* - Moderate writes (IndexedDB persistence)
|
|
53
|
+
* - Auto-save batching reduces IDB overhead
|
|
54
|
+
*
|
|
55
|
+
* @example Client-side AgentOS
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const adapter = new IndexedDbAdapter({ dbName: 'my-app-db' });
|
|
58
|
+
* const agentos = new AgentOS();
|
|
59
|
+
* await agentos.initialize({
|
|
60
|
+
* storageAdapter: adapter,
|
|
61
|
+
* // ... other config
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export class IndexedDbAdapter {
|
|
66
|
+
constructor(options = {}) {
|
|
67
|
+
this.kind = 'indexeddb';
|
|
68
|
+
this.capabilities = new Set(['transactions', 'persistence']);
|
|
69
|
+
this.SQL = null;
|
|
70
|
+
this.db = null;
|
|
71
|
+
this.idb = null;
|
|
72
|
+
this.saveTimer = null;
|
|
73
|
+
this.dirty = false;
|
|
74
|
+
this.dbName = options.dbName || 'agentos-db';
|
|
75
|
+
this.storeName = options.storeName || 'sqliteDb';
|
|
76
|
+
this.autoSave = options.autoSave ?? true;
|
|
77
|
+
this.saveIntervalMs = options.saveIntervalMs || 5000;
|
|
78
|
+
this.sqlJsConfig = options.sqlJsConfig || {};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Opens IndexedDB and initializes sql.js database.
|
|
82
|
+
* Loads existing database from IndexedDB if present.
|
|
83
|
+
*/
|
|
84
|
+
async open(_options) {
|
|
85
|
+
if (this.db) {
|
|
86
|
+
return; // Already open
|
|
87
|
+
}
|
|
88
|
+
// Initialize sql.js
|
|
89
|
+
this.SQL = await initSqlJs(this.sqlJsConfig);
|
|
90
|
+
// Open IndexedDB
|
|
91
|
+
this.idb = await this.openIndexedDb();
|
|
92
|
+
// Load existing database from IndexedDB or create new
|
|
93
|
+
const existingData = await this.loadFromIndexedDb();
|
|
94
|
+
if (existingData) {
|
|
95
|
+
this.db = new this.SQL.Database(existingData);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
this.db = new this.SQL.Database();
|
|
99
|
+
}
|
|
100
|
+
// Start auto-save interval
|
|
101
|
+
if (this.autoSave) {
|
|
102
|
+
this.startAutoSave();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Executes a SQL statement that doesn't return rows (INSERT, UPDATE, DELETE, CREATE, etc.).
|
|
107
|
+
* @param statement SQL statement with ? or :name placeholders
|
|
108
|
+
* @param parameters Positional array or named object
|
|
109
|
+
* @returns Result with changes count and last insert row ID
|
|
110
|
+
*/
|
|
111
|
+
async run(statement, parameters) {
|
|
112
|
+
this.ensureOpen();
|
|
113
|
+
const stmt = this.db.prepare(statement);
|
|
114
|
+
try {
|
|
115
|
+
const { named, positional } = normaliseParameters(parameters);
|
|
116
|
+
if (named) {
|
|
117
|
+
stmt.bind(named);
|
|
118
|
+
}
|
|
119
|
+
else if (positional) {
|
|
120
|
+
stmt.bind(positional);
|
|
121
|
+
}
|
|
122
|
+
stmt.step();
|
|
123
|
+
const rowIdResult = this.db.exec('SELECT last_insert_rowid() AS id');
|
|
124
|
+
const rawRowId = rowIdResult[0]?.values?.[0]?.[0];
|
|
125
|
+
const lastInsertRowid = this.normaliseRowId(rawRowId);
|
|
126
|
+
this.dirty = true;
|
|
127
|
+
await this.persistIfNeeded();
|
|
128
|
+
return {
|
|
129
|
+
changes: this.db.getRowsModified(),
|
|
130
|
+
lastInsertRowid,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
stmt.free();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Executes a SQL query and returns the first row.
|
|
139
|
+
* @param statement SELECT statement
|
|
140
|
+
* @param parameters Query parameters
|
|
141
|
+
* @returns First row as object or null if no results
|
|
142
|
+
*/
|
|
143
|
+
async get(statement, parameters) {
|
|
144
|
+
const rows = await this.all(statement, parameters);
|
|
145
|
+
return rows.length > 0 ? rows[0] : null;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Executes a SQL query and returns all matching rows.
|
|
149
|
+
* @param statement SELECT statement
|
|
150
|
+
* @param parameters Query parameters
|
|
151
|
+
* @returns Array of result rows as objects
|
|
152
|
+
*/
|
|
153
|
+
async all(statement, parameters) {
|
|
154
|
+
this.ensureOpen();
|
|
155
|
+
const stmt = this.db.prepare(statement);
|
|
156
|
+
try {
|
|
157
|
+
const { named, positional } = normaliseParameters(parameters);
|
|
158
|
+
if (named) {
|
|
159
|
+
stmt.bind(named);
|
|
160
|
+
}
|
|
161
|
+
else if (positional) {
|
|
162
|
+
stmt.bind(positional);
|
|
163
|
+
}
|
|
164
|
+
const results = [];
|
|
165
|
+
const columnNames = stmt.getColumnNames();
|
|
166
|
+
while (stmt.step()) {
|
|
167
|
+
const row = stmt.get();
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
169
|
+
const obj = {};
|
|
170
|
+
columnNames.forEach((col, idx) => {
|
|
171
|
+
obj[col] = row[idx];
|
|
172
|
+
});
|
|
173
|
+
results.push(obj);
|
|
174
|
+
}
|
|
175
|
+
return results;
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
stmt.free();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Executes a script containing multiple SQL statements.
|
|
183
|
+
*/
|
|
184
|
+
async exec(script) {
|
|
185
|
+
this.ensureOpen();
|
|
186
|
+
this.db.exec(script);
|
|
187
|
+
this.dirty = true;
|
|
188
|
+
await this.persistIfNeeded();
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Executes a callback within a database transaction.
|
|
192
|
+
*/
|
|
193
|
+
async transaction(fn) {
|
|
194
|
+
this.ensureOpen();
|
|
195
|
+
await this.run('BEGIN TRANSACTION');
|
|
196
|
+
try {
|
|
197
|
+
const result = await fn(this);
|
|
198
|
+
await this.run('COMMIT');
|
|
199
|
+
this.dirty = true;
|
|
200
|
+
await this.persistIfNeeded();
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
await this.run('ROLLBACK');
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Begins a transaction. sql.js executes all statements in implicit transactions,
|
|
210
|
+
* so this is a no-op for compatibility.
|
|
211
|
+
*/
|
|
212
|
+
async beginTransaction() {
|
|
213
|
+
// sql.js uses auto-commit; explicit BEGIN is optional
|
|
214
|
+
await this.run('BEGIN');
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Commits the current transaction.
|
|
218
|
+
*/
|
|
219
|
+
async commit() {
|
|
220
|
+
await this.run('COMMIT');
|
|
221
|
+
this.dirty = true;
|
|
222
|
+
await this.persistIfNeeded();
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Rolls back the current transaction.
|
|
226
|
+
*/
|
|
227
|
+
async rollback() {
|
|
228
|
+
await this.run('ROLLBACK');
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Closes the database and persists final state to IndexedDB.
|
|
232
|
+
*/
|
|
233
|
+
async close() {
|
|
234
|
+
if (this.saveTimer) {
|
|
235
|
+
clearInterval(this.saveTimer);
|
|
236
|
+
this.saveTimer = null;
|
|
237
|
+
}
|
|
238
|
+
if (this.dirty) {
|
|
239
|
+
await this.saveToIndexedDb();
|
|
240
|
+
}
|
|
241
|
+
if (this.db) {
|
|
242
|
+
this.db.close();
|
|
243
|
+
this.db = null;
|
|
244
|
+
}
|
|
245
|
+
if (this.idb) {
|
|
246
|
+
this.idb.close();
|
|
247
|
+
this.idb = null;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Exports the database as a Uint8Array (SQLite file format).
|
|
252
|
+
* Can be downloaded or stored externally.
|
|
253
|
+
* @returns SQLite database file as binary
|
|
254
|
+
*/
|
|
255
|
+
exportDatabase() {
|
|
256
|
+
this.ensureOpen();
|
|
257
|
+
return this.db.export();
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Imports a database from a Uint8Array (SQLite file).
|
|
261
|
+
* Replaces the current database.
|
|
262
|
+
* @param data SQLite database file
|
|
263
|
+
*/
|
|
264
|
+
async importDatabase(data) {
|
|
265
|
+
this.ensureOpen();
|
|
266
|
+
this.db.close();
|
|
267
|
+
this.db = new this.SQL.Database(data);
|
|
268
|
+
this.dirty = true;
|
|
269
|
+
await this.saveToIndexedDb();
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Opens or creates the IndexedDB database.
|
|
273
|
+
*/
|
|
274
|
+
openIndexedDb() {
|
|
275
|
+
return new Promise((resolve, reject) => {
|
|
276
|
+
const req = indexedDB.open(this.dbName, DB_VERSION);
|
|
277
|
+
req.onupgradeneeded = () => {
|
|
278
|
+
const db = req.result;
|
|
279
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
280
|
+
db.createObjectStore(this.storeName);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
req.onsuccess = () => resolve(req.result);
|
|
284
|
+
req.onerror = () => reject(req.error);
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Loads the SQLite database from IndexedDB.
|
|
289
|
+
* @returns Binary database or null if not found
|
|
290
|
+
*/
|
|
291
|
+
async loadFromIndexedDb() {
|
|
292
|
+
if (!this.idb)
|
|
293
|
+
return null;
|
|
294
|
+
return new Promise((resolve, reject) => {
|
|
295
|
+
const tx = this.idb.transaction(this.storeName, 'readonly');
|
|
296
|
+
const store = tx.objectStore(this.storeName);
|
|
297
|
+
const req = store.get('db');
|
|
298
|
+
req.onsuccess = () => resolve(req.result || null);
|
|
299
|
+
req.onerror = () => reject(req.error);
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Saves the SQLite database to IndexedDB.
|
|
304
|
+
*/
|
|
305
|
+
async saveToIndexedDb() {
|
|
306
|
+
if (!this.idb || !this.db)
|
|
307
|
+
return;
|
|
308
|
+
const data = this.db.export();
|
|
309
|
+
return new Promise((resolve, reject) => {
|
|
310
|
+
const tx = this.idb.transaction(this.storeName, 'readwrite');
|
|
311
|
+
const store = tx.objectStore(this.storeName);
|
|
312
|
+
const req = store.put(data, 'db');
|
|
313
|
+
req.onsuccess = () => {
|
|
314
|
+
this.dirty = false;
|
|
315
|
+
resolve();
|
|
316
|
+
};
|
|
317
|
+
req.onerror = () => reject(req.error);
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Persists to IndexedDB if auto-save is enabled.
|
|
322
|
+
*/
|
|
323
|
+
async persistIfNeeded() {
|
|
324
|
+
if (this.autoSave && !this.saveTimer) {
|
|
325
|
+
// Immediate save on first write, then batched
|
|
326
|
+
await this.saveToIndexedDb();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Starts auto-save interval.
|
|
331
|
+
*/
|
|
332
|
+
startAutoSave() {
|
|
333
|
+
this.saveTimer = setInterval(async () => {
|
|
334
|
+
if (this.dirty) {
|
|
335
|
+
await this.saveToIndexedDb();
|
|
336
|
+
}
|
|
337
|
+
}, this.saveIntervalMs);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Ensures the database is open.
|
|
341
|
+
*/
|
|
342
|
+
ensureOpen() {
|
|
343
|
+
if (!this.db) {
|
|
344
|
+
throw new Error('IndexedDbAdapter: Database not open. Call open() first.');
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Normalizes last insert row ID to string or number.
|
|
349
|
+
*/
|
|
350
|
+
normaliseRowId(value) {
|
|
351
|
+
if (typeof value === 'number' || typeof value === 'string') {
|
|
352
|
+
return value;
|
|
353
|
+
}
|
|
354
|
+
if (typeof value === 'bigint') {
|
|
355
|
+
return value.toString();
|
|
356
|
+
}
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Prepares a SQL statement for execution.
|
|
361
|
+
*/
|
|
362
|
+
prepareInternal(statement) {
|
|
363
|
+
this.ensureOpen();
|
|
364
|
+
return this.db.prepare(statement);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
//# sourceMappingURL=indexedDbAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexedDbAdapter.js","sourceRoot":"","sources":["../../src/adapters/indexedDbAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { StorageAdapter, StorageCapability, StorageOpenOptions, StorageParameters, StorageRunResult } from '../
|
|
1
|
+
import type { StorageAdapter, StorageCapability, StorageOpenOptions, StorageParameters, StorageRunResult } from '../core/contracts';
|
|
2
2
|
/**
|
|
3
3
|
* Configuration options for PostgreSQL adapter.
|
|
4
4
|
* Supports both connection strings and granular configuration.
|
|
@@ -137,6 +137,12 @@ export interface PostgresAdapterOptions {
|
|
|
137
137
|
* - Connection pool handles transient failures
|
|
138
138
|
* - Falls back to SQLite if PostgreSQL unavailable
|
|
139
139
|
*/
|
|
140
|
+
/**
|
|
141
|
+
* Production-grade PostgreSQL adapter backed by pg.Pool.
|
|
142
|
+
*
|
|
143
|
+
* Safe to import in browser bundles; will only throw if `open()` is invoked
|
|
144
|
+
* in a browser environment.
|
|
145
|
+
*/
|
|
140
146
|
export declare class PostgresAdapter implements StorageAdapter {
|
|
141
147
|
readonly kind = "postgres";
|
|
142
148
|
readonly capabilities: ReadonlySet<StorageCapability>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgresAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/postgresAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"postgresAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/postgresAdapter.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGpI;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,GAAG,CAAC,EAAE,OAAO,GAAG;QAAE,kBAAkB,CAAC,EAAE,OAAO,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3F,yCAAyC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAgDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkGG;AACH;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,cAAc;IACpD,SAAgB,IAAI,cAAc;IAClC,SAAgB,YAAY,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAQzD;IAEH,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,mBAAmB,CAA2B;gBAE1C,OAAO,EAAE,sBAAsB,GAAG,MAAM;IASvC,IAAI,CAAC,WAAW,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDrD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAWjF,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAO5E,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAOvE,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoBnE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAOrB,WAAW;CAS1B;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,cAAc,CAAC;AAEhF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,CAAC"}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
// NOTE: Browser safety - we avoid throwing at module load so bundlers can include
|
|
2
|
+
// this file without crashing. A runtime error will be thrown inside `open()` if
|
|
3
|
+
// execution actually occurs in a browser.
|
|
4
|
+
const __isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
1
5
|
import { Pool } from 'pg';
|
|
2
|
-
import { normaliseParameters } from '../
|
|
6
|
+
import { normaliseParameters } from '../shared/parameterUtils';
|
|
3
7
|
const isPositional = (statement) => statement.includes('?');
|
|
4
8
|
const buildNamedStatement = (statement, named) => {
|
|
5
9
|
const order = [];
|
|
@@ -134,6 +138,12 @@ const splitStatements = (script) => script
|
|
|
134
138
|
* - Connection pool handles transient failures
|
|
135
139
|
* - Falls back to SQLite if PostgreSQL unavailable
|
|
136
140
|
*/
|
|
141
|
+
/**
|
|
142
|
+
* Production-grade PostgreSQL adapter backed by pg.Pool.
|
|
143
|
+
*
|
|
144
|
+
* Safe to import in browser bundles; will only throw if `open()` is invoked
|
|
145
|
+
* in a browser environment.
|
|
146
|
+
*/
|
|
137
147
|
export class PostgresAdapter {
|
|
138
148
|
constructor(options) {
|
|
139
149
|
this.kind = 'postgres';
|
|
@@ -160,6 +170,9 @@ export class PostgresAdapter {
|
|
|
160
170
|
if (this.pool) {
|
|
161
171
|
return;
|
|
162
172
|
}
|
|
173
|
+
if (__isBrowser) {
|
|
174
|
+
throw new Error('[StorageAdapter] PostgreSQL adapter cannot be opened in a browser environment.');
|
|
175
|
+
}
|
|
163
176
|
// Build pool configuration
|
|
164
177
|
const poolConfig = {};
|
|
165
178
|
// Use connection string if provided
|
|
@@ -207,7 +220,11 @@ export class PostgresAdapter {
|
|
|
207
220
|
const executor = await this.getExecutor();
|
|
208
221
|
const { text, values } = prepareStatement(statement, parameters);
|
|
209
222
|
const result = await executor.query(text, values);
|
|
210
|
-
|
|
223
|
+
const firstRow = result.rows?.[0];
|
|
224
|
+
const lastInsertRowid = (firstRow && typeof firstRow === 'object' && 'id' in firstRow)
|
|
225
|
+
? firstRow.id
|
|
226
|
+
: null;
|
|
227
|
+
return { changes: result.rowCount ?? 0, lastInsertRowid };
|
|
211
228
|
}
|
|
212
229
|
async get(statement, parameters) {
|
|
213
230
|
const executor = await this.getExecutor();
|