@framers/sql-storage-adapter 0.7.2 → 0.7.4
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/README.md +41 -0
- package/dist/adapters/electron/preload.cjs +289 -0
- package/dist/adapters/electron/renderer.d.ts +9 -0
- package/dist/adapters/electron/renderer.d.ts.map +1 -0
- package/dist/adapters/electron/renderer.js +8 -0
- package/dist/adapters/electron/renderer.js.map +1 -0
- package/dist/cjs/adapters/__tests__/indexedDbAdapter.spec.d.ts +2 -0
- package/dist/cjs/adapters/__tests__/indexedDbAdapter.spec.js +133 -0
- package/dist/cjs/adapters/baseStorageAdapter.d.ts +368 -0
- package/dist/cjs/adapters/baseStorageAdapter.js +744 -0
- package/dist/cjs/adapters/betterSqliteAdapter.d.ts +124 -0
- package/dist/cjs/adapters/betterSqliteAdapter.js +334 -0
- package/dist/cjs/adapters/capacitorSqliteAdapter.d.ts +83 -0
- package/dist/cjs/adapters/capacitorSqliteAdapter.js +250 -0
- package/dist/cjs/adapters/electron/electronMainAdapter.d.ts +251 -0
- package/dist/cjs/adapters/electron/electronMainAdapter.js +392 -0
- package/dist/cjs/adapters/electron/electronRendererAdapter.d.ts +177 -0
- package/dist/cjs/adapters/electron/electronRendererAdapter.js +283 -0
- package/dist/cjs/adapters/electron/index.d.ts +74 -0
- package/dist/cjs/adapters/electron/index.js +86 -0
- package/dist/cjs/adapters/electron/ipc/channels.d.ts +196 -0
- package/dist/cjs/adapters/electron/ipc/channels.js +127 -0
- package/dist/cjs/adapters/electron/ipc/index.d.ts +11 -0
- package/dist/cjs/adapters/electron/ipc/index.js +38 -0
- package/dist/cjs/adapters/electron/ipc/protocol.d.ts +78 -0
- package/dist/cjs/adapters/electron/ipc/protocol.js +341 -0
- package/dist/cjs/adapters/electron/ipc/types.d.ts +248 -0
- package/dist/cjs/adapters/electron/ipc/types.js +15 -0
- package/dist/cjs/adapters/electron/migration/autoMigrator.d.ts +184 -0
- package/dist/cjs/adapters/electron/migration/autoMigrator.js +441 -0
- package/dist/cjs/adapters/electron/migration/index.d.ts +9 -0
- package/dist/cjs/adapters/electron/migration/index.js +29 -0
- package/dist/cjs/adapters/electron/preload.d.ts +126 -0
- package/dist/cjs/adapters/electron/preload.js +233 -0
- package/dist/cjs/adapters/electron/recovery/corruptionDetector.d.ts +214 -0
- package/dist/cjs/adapters/electron/recovery/corruptionDetector.js +359 -0
- package/dist/cjs/adapters/electron/recovery/index.d.ts +11 -0
- package/dist/cjs/adapters/electron/recovery/index.js +34 -0
- package/dist/cjs/adapters/electron/recovery/walCheckpoint.d.ts +186 -0
- package/dist/cjs/adapters/electron/recovery/walCheckpoint.js +263 -0
- package/dist/cjs/adapters/electron/renderer.d.ts +9 -0
- package/dist/cjs/adapters/electron/renderer.js +33 -0
- package/dist/cjs/adapters/electron/window/index.d.ts +9 -0
- package/dist/cjs/adapters/electron/window/index.js +29 -0
- package/dist/cjs/adapters/electron/window/windowManager.d.ts +190 -0
- package/dist/cjs/adapters/electron/window/windowManager.js +321 -0
- package/dist/cjs/adapters/indexedDbAdapter.d.ts +490 -0
- package/dist/cjs/adapters/indexedDbAdapter.js +993 -0
- package/dist/cjs/adapters/postgresAdapter.d.ts +424 -0
- package/dist/cjs/adapters/postgresAdapter.js +889 -0
- package/dist/cjs/adapters/sqlJsAdapter.d.ts +64 -0
- package/dist/cjs/adapters/sqlJsAdapter.js +268 -0
- package/dist/cjs/adapters/supabase.d.ts +58 -0
- package/dist/cjs/adapters/supabase.js +401 -0
- package/dist/cjs/codecs/BrowserBlobCodec.d.ts +14 -0
- package/dist/cjs/codecs/BrowserBlobCodec.js +57 -0
- package/dist/cjs/codecs/NodeBlobCodec.d.ts +14 -0
- package/dist/cjs/codecs/NodeBlobCodec.js +59 -0
- package/dist/cjs/core/contracts/blobCodec.d.ts +15 -0
- package/dist/cjs/core/contracts/blobCodec.js +15 -0
- package/dist/cjs/core/contracts/context.d.ts +221 -0
- package/dist/cjs/core/contracts/context.js +15 -0
- package/dist/cjs/core/contracts/dialect.d.ts +154 -0
- package/dist/cjs/core/contracts/dialect.js +15 -0
- package/dist/cjs/core/contracts/events.d.ts +225 -0
- package/dist/cjs/core/contracts/events.js +15 -0
- package/dist/cjs/core/contracts/exporter.d.ts +13 -0
- package/dist/cjs/core/contracts/exporter.js +15 -0
- package/dist/cjs/core/contracts/extensions.d.ts +73 -0
- package/dist/cjs/core/contracts/extensions.js +15 -0
- package/dist/cjs/core/contracts/features.d.ts +25 -0
- package/dist/cjs/core/contracts/features.js +61 -0
- package/dist/cjs/core/contracts/fts.d.ts +66 -0
- package/dist/cjs/core/contracts/fts.js +15 -0
- package/dist/cjs/core/contracts/hooks.d.ts +481 -0
- package/dist/cjs/core/contracts/hooks.js +140 -0
- package/dist/cjs/core/contracts/index.d.ts +260 -0
- package/dist/cjs/core/contracts/index.js +41 -0
- package/dist/cjs/core/contracts/limitations.d.ts +46 -0
- package/dist/cjs/core/contracts/limitations.js +218 -0
- package/dist/cjs/core/contracts/performance.d.ts +308 -0
- package/dist/cjs/core/contracts/performance.js +144 -0
- package/dist/cjs/core/database.d.ts +220 -0
- package/dist/cjs/core/database.js +136 -0
- package/dist/cjs/core/portable.d.ts +24 -0
- package/dist/cjs/core/portable.js +68 -0
- package/dist/cjs/core/resolver.d.ts +77 -0
- package/dist/cjs/core/resolver.js +235 -0
- package/dist/cjs/dialects/PostgresDialect.d.ts +35 -0
- package/dist/cjs/dialects/PostgresDialect.js +143 -0
- package/dist/cjs/dialects/SqliteDialect.d.ts +35 -0
- package/dist/cjs/dialects/SqliteDialect.js +142 -0
- package/dist/cjs/dialects/shared.d.ts +17 -0
- package/dist/cjs/dialects/shared.js +90 -0
- package/dist/cjs/exporters/PostgresExporter.d.ts +14 -0
- package/dist/cjs/exporters/PostgresExporter.js +61 -0
- package/dist/cjs/exporters/SqliteFileExporter.d.ts +16 -0
- package/dist/cjs/exporters/SqliteFileExporter.js +43 -0
- package/dist/cjs/features/auth/authJsAdapter.d.ts +110 -0
- package/dist/cjs/features/auth/authJsAdapter.js +251 -0
- package/dist/cjs/features/backup/cloudBackup.d.ts +219 -0
- package/dist/cjs/features/backup/cloudBackup.js +209 -0
- package/dist/cjs/features/kv/idb.d.ts +79 -0
- package/dist/cjs/features/kv/idb.js +32 -0
- package/dist/cjs/features/kv/index.d.ts +14 -0
- package/dist/cjs/features/kv/index.js +40 -0
- package/dist/cjs/features/kv/indexedDbKeyValueStore.d.ts +77 -0
- package/dist/cjs/features/kv/indexedDbKeyValueStore.js +116 -0
- package/dist/cjs/features/kv/keyValueStore.d.ts +48 -0
- package/dist/cjs/features/kv/keyValueStore.js +67 -0
- package/dist/cjs/features/kv/sqlKeyValueStore.d.ts +34 -0
- package/dist/cjs/features/kv/sqlKeyValueStore.js +81 -0
- package/dist/cjs/features/kv/valueCodec.d.ts +35 -0
- package/dist/cjs/features/kv/valueCodec.js +426 -0
- package/dist/cjs/features/migrations/dataExport.d.ts +77 -0
- package/dist/cjs/features/migrations/dataExport.js +194 -0
- package/dist/cjs/features/migrations/dataImport.d.ts +54 -0
- package/dist/cjs/features/migrations/dataImport.js +300 -0
- package/dist/cjs/features/migrations/migration.d.ts +89 -0
- package/dist/cjs/features/migrations/migration.js +187 -0
- package/dist/cjs/features/migrations/schemaMigrations.d.ts +93 -0
- package/dist/cjs/features/migrations/schemaMigrations.js +220 -0
- package/dist/cjs/features/sync/conflicts/conflictResolver.d.ts +222 -0
- package/dist/cjs/features/sync/conflicts/conflictResolver.js +366 -0
- package/dist/cjs/features/sync/conflicts/index.d.ts +9 -0
- package/dist/cjs/features/sync/conflicts/index.js +21 -0
- package/dist/cjs/features/sync/crossPlatformSync.d.ts +281 -0
- package/dist/cjs/features/sync/crossPlatformSync.js +551 -0
- package/dist/cjs/features/sync/devices/deviceManager.d.ts +243 -0
- package/dist/cjs/features/sync/devices/deviceManager.js +450 -0
- package/dist/cjs/features/sync/devices/index.d.ts +10 -0
- package/dist/cjs/features/sync/devices/index.js +21 -0
- package/dist/cjs/features/sync/index.d.ts +37 -0
- package/dist/cjs/features/sync/index.js +111 -0
- package/dist/cjs/features/sync/protocol/index.d.ts +11 -0
- package/dist/cjs/features/sync/protocol/index.js +23 -0
- package/dist/cjs/features/sync/protocol/messages.d.ts +348 -0
- package/dist/cjs/features/sync/protocol/messages.js +215 -0
- package/dist/cjs/features/sync/protocol/vectorClock.d.ts +164 -0
- package/dist/cjs/features/sync/protocol/vectorClock.js +256 -0
- package/dist/cjs/features/sync/syncManager.d.ts +348 -0
- package/dist/cjs/features/sync/syncManager.js +455 -0
- package/dist/cjs/features/sync/tables/index.d.ts +10 -0
- package/dist/cjs/features/sync/tables/index.js +21 -0
- package/dist/cjs/features/sync/tables/syncLogManager.d.ts +216 -0
- package/dist/cjs/features/sync/tables/syncLogManager.js +423 -0
- package/dist/cjs/features/sync/transport/httpTransport.d.ts +123 -0
- package/dist/cjs/features/sync/transport/httpTransport.js +346 -0
- package/dist/cjs/features/sync/transport/index.d.ts +12 -0
- package/dist/cjs/features/sync/transport/index.js +25 -0
- package/dist/cjs/features/sync/transport/transport.d.ts +259 -0
- package/dist/cjs/features/sync/transport/transport.js +163 -0
- package/dist/cjs/features/sync/transport/websocketTransport.d.ts +126 -0
- package/dist/cjs/features/sync/transport/websocketTransport.js +342 -0
- package/dist/cjs/fts/PostgresFts.d.ts +29 -0
- package/dist/cjs/fts/PostgresFts.js +77 -0
- package/dist/cjs/fts/SqliteFts5.d.ts +22 -0
- package/dist/cjs/fts/SqliteFts5.js +58 -0
- package/dist/cjs/index.d.ts +31 -0
- package/dist/cjs/index.js +103 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/shared/connectionGate.d.ts +94 -0
- package/dist/cjs/shared/connectionGate.js +77 -0
- package/dist/cjs/shared/errors.d.ts +23 -0
- package/dist/cjs/shared/errors.js +45 -0
- package/dist/cjs/shared/logger.d.ts +26 -0
- package/dist/cjs/shared/logger.js +40 -0
- package/dist/cjs/shared/parameterUtils.d.ts +16 -0
- package/dist/cjs/shared/parameterUtils.js +59 -0
- package/dist/cjs/shared/postgresTarget.d.ts +11 -0
- package/dist/cjs/shared/postgresTarget.js +30 -0
- package/dist/cjs/shared/segment.d.ts +43 -0
- package/dist/cjs/shared/segment.js +63 -0
- package/dist/cjs/shared/serializedTransaction.d.ts +14 -0
- package/dist/cjs/shared/serializedTransaction.js +74 -0
- package/dist/cjs/shared/splitSqlStatements.d.ts +27 -0
- package/dist/cjs/shared/splitSqlStatements.js +163 -0
- package/dist/cjs/shared/sqlPlaceholders.d.ts +48 -0
- package/dist/cjs/shared/sqlPlaceholders.js +263 -0
- package/dist/cjs/types/index.d.ts +29 -0
- package/dist/cjs/types/index.js +33 -0
- package/dist/core/portable.d.ts +24 -0
- package/dist/core/portable.d.ts.map +1 -0
- package/dist/core/portable.js +24 -0
- package/dist/core/portable.js.map +1 -0
- package/dist/features/auth/authJsAdapter.d.ts +110 -0
- package/dist/features/auth/authJsAdapter.d.ts.map +1 -0
- package/dist/features/auth/authJsAdapter.js +248 -0
- package/dist/features/auth/authJsAdapter.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +149 -24
package/README.md
CHANGED
|
@@ -78,6 +78,27 @@ npm install sql.js # WASM SQLite (auto-included for IndexedDB
|
|
|
78
78
|
|
|
79
79
|
> `better-sqlite3` 13 needs Node-API 10: Node.js 22.14+ or 23.6+, or Electron 35+ (whose Node is 22.14). On an older runtime (Node.js 20, Node.js 22.13 and earlier, Electron 34 and earlier) install `better-sqlite3@12`; with 13 installed there, the adapter refuses to open, so the resolver falls back to `sql.js`, rather than letting the native binding crash the process. `better-sqlite3` 13 ships prebuilt binaries, but npm can still run `node-gyp rebuild` for it, which needs the build tools above (Python, and make and a C++ compiler, or the Visual Studio Build Tools on Windows): always when it installs from a lockfile (`npm ci`, or `npm install` with a `package-lock.json`), and on some platforms on a fresh install too ([WiseLibs/better-sqlite3#1516](https://github.com/WiseLibs/better-sqlite3/issues/1516)).
|
|
80
80
|
|
|
81
|
+
### Entries
|
|
82
|
+
|
|
83
|
+
The root entry exports everything and imports every adapter. A server takes its adapter from that adapter's own entry, with the rest from `./core`, so its bundle carries neither sql.js nor the S3 client:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import { createPostgresAdapter } from '@framers/sql-storage-adapter/postgres';
|
|
87
|
+
import { createStorageFeatures, runSchemaMigrations, isUniqueViolation } from '@framers/sql-storage-adapter/core';
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Entry | Holds |
|
|
91
|
+
| --- | --- |
|
|
92
|
+
| `@framers/sql-storage-adapter` | Everything, with `createDatabase` and the resolver |
|
|
93
|
+
| `./core` | Contracts and errors, dialects, full-text search, codecs, exporters, `createStorageFeatures`, the schema-migration runner, `isUniqueViolation`, the logger. No adapter |
|
|
94
|
+
| `./postgres`, `./better-sqlite3`, `./sqljs`, `./indexeddb`, `./capacitor` | One adapter each |
|
|
95
|
+
| `./backup` | S3-compatible backups (`@aws-sdk/client-s3`) |
|
|
96
|
+
| `./authjs` | The Auth.js database adapter (also in `./core`) |
|
|
97
|
+
| `./electron`, `./electron/renderer`, `./electron/preload` | The Electron adapters. `./electron/renderer` holds only what a window uses; `require('./electron/preload')` gives one bundled CommonJS file for a sandboxed preload |
|
|
98
|
+
| `./sync`, `./kv`, `./types` | Cross-platform sync, the key-value store, the types |
|
|
99
|
+
|
|
100
|
+
Every entry has an `import` and a `require` condition. The CommonJS build under `dist/cjs` is made from the ES module build file by file, so a class has one identity whichever entry a caller takes it from. It carries its own declarations, so a CommonJS TypeScript consumer under `node16` resolution type-checks against them. CI packs the package, installs it in a new project and checks each of these: `require()` of every entry, what each server entry bundles, and the preload.
|
|
101
|
+
|
|
81
102
|
## Quick Start
|
|
82
103
|
|
|
83
104
|
```typescript
|
|
@@ -361,6 +382,26 @@ const status = await schemaMigrationStatus(db, migrations); // { appl
|
|
|
361
382
|
- **Outside a transaction.** A file whose first line is `-- outside transaction` (`outsideTransactionMarker`) runs outside a transaction, for `CREATE INDEX CONCURRENTLY` or `VACUUM`. On PostgreSQL it runs under the session lock on one held connection (`withConnection`).
|
|
362
383
|
- **Unknown rows.** `unknown: 'ignore'` lets a run go on past ledger rows the list lacks.
|
|
363
384
|
|
|
385
|
+
### Auth.js
|
|
386
|
+
|
|
387
|
+
`createAuthJsAdapter(db)` is an Auth.js database adapter. It keeps users, accounts, sessions and verification tokens in the product's own database through this library, on PostgreSQL or SQLite. Pass it to NextAuth v5 or `@auth/core`; it has the shape of `Adapter` from `@auth/core/adapters`, which CI checks, and needs no dependency on it.
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
import NextAuth from 'next-auth';
|
|
391
|
+
import { createDatabase } from '@framers/sql-storage-adapter';
|
|
392
|
+
import { createAuthJsAdapter, ensureAuthJsTables } from '@framers/sql-storage-adapter/authjs';
|
|
393
|
+
|
|
394
|
+
const db = await createDatabase({ url: process.env.DATABASE_URL, strict: true });
|
|
395
|
+
await ensureAuthJsTables(db); // or put authJsTablesSql(db) in a migration
|
|
396
|
+
export const { handlers, auth, signIn, signOut } = NextAuth({ adapter: createAuthJsAdapter(db), providers: [/* ... */] });
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
- **Tables.** They are `auth_users`, `auth_accounts`, `auth_sessions` and `auth_verification_tokens`; `tablePrefix` changes the `auth_`. Ids are text, from `crypto.randomUUID()` unless Auth.js passes one or `generateId` is given. Times are `timestamptz` on PostgreSQL and ISO 8601 text on SQLite, and Dates either way in JavaScript.
|
|
400
|
+
- **Deletes.** `deleteUser` deletes the user's sessions and accounts first, in one transaction, so it holds on engines that leave foreign keys off.
|
|
401
|
+
- **Verification tokens.** `useVerificationToken` deletes and returns the token in one statement (`DELETE ... RETURNING`), so a token works once.
|
|
402
|
+
- **Passkeys.** WebAuthn authenticators are not stored.
|
|
403
|
+
- **Tests.** Auth.js's own adapter test suite runs against it on PostgreSQL, better-sqlite3 and sql.js.
|
|
404
|
+
|
|
364
405
|
### Values
|
|
365
406
|
|
|
366
407
|
On SQLite, values convert as they bind, positional and named alike:
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/adapters/electron/preload.ts
|
|
21
|
+
var preload_exports = {};
|
|
22
|
+
__export(preload_exports, {
|
|
23
|
+
sqlStorageApi: () => sqlStorageApi
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(preload_exports);
|
|
26
|
+
var import_electron = require("electron");
|
|
27
|
+
|
|
28
|
+
// src/adapters/electron/ipc/channels.ts
|
|
29
|
+
var DB_CHANNELS = {
|
|
30
|
+
/** Execute a mutation (INSERT/UPDATE/DELETE) */
|
|
31
|
+
RUN: "sql-storage:db:run",
|
|
32
|
+
/** Get a single row */
|
|
33
|
+
GET: "sql-storage:db:get",
|
|
34
|
+
/** Get all matching rows */
|
|
35
|
+
ALL: "sql-storage:db:all",
|
|
36
|
+
/** Execute a SQL script */
|
|
37
|
+
EXEC: "sql-storage:db:exec",
|
|
38
|
+
/** Execute batch operations */
|
|
39
|
+
BATCH: "sql-storage:db:batch",
|
|
40
|
+
/** Open database connection */
|
|
41
|
+
OPEN: "sql-storage:db:open",
|
|
42
|
+
/** Close database connection */
|
|
43
|
+
CLOSE: "sql-storage:db:close",
|
|
44
|
+
/** Check if database is open */
|
|
45
|
+
IS_OPEN: "sql-storage:db:is-open",
|
|
46
|
+
/** Get adapter capabilities */
|
|
47
|
+
CAPABILITIES: "sql-storage:db:capabilities"
|
|
48
|
+
};
|
|
49
|
+
var TRANSACTION_CHANNELS = {
|
|
50
|
+
/** Begin a transaction */
|
|
51
|
+
BEGIN: "sql-storage:transaction:begin",
|
|
52
|
+
/** Commit current transaction */
|
|
53
|
+
COMMIT: "sql-storage:transaction:commit",
|
|
54
|
+
/** Rollback current transaction */
|
|
55
|
+
ROLLBACK: "sql-storage:transaction:rollback",
|
|
56
|
+
/** Execute operation within transaction context */
|
|
57
|
+
EXECUTE: "sql-storage:transaction:execute"
|
|
58
|
+
};
|
|
59
|
+
var SYNC_CHANNELS = {
|
|
60
|
+
/** Get sync status */
|
|
61
|
+
STATUS: "sql-storage:sync:status",
|
|
62
|
+
/** Trigger manual sync */
|
|
63
|
+
TRIGGER: "sql-storage:sync:trigger",
|
|
64
|
+
/** Sync progress updates (main -> renderer) */
|
|
65
|
+
PROGRESS: "sql-storage:sync:progress",
|
|
66
|
+
/** Sync completed (main -> renderer) */
|
|
67
|
+
COMPLETE: "sql-storage:sync:complete",
|
|
68
|
+
/** Sync error (main -> renderer) */
|
|
69
|
+
ERROR: "sql-storage:sync:error"
|
|
70
|
+
};
|
|
71
|
+
var BROADCAST_CHANNELS = {
|
|
72
|
+
/** Database change notification */
|
|
73
|
+
DB_CHANGE: "sql-storage:broadcast:db-change",
|
|
74
|
+
/** Connection state change */
|
|
75
|
+
CONNECTION_STATE: "sql-storage:broadcast:connection-state",
|
|
76
|
+
/** Error notification */
|
|
77
|
+
ERROR: "sql-storage:broadcast:error"
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// src/adapters/electron/preload.ts
|
|
81
|
+
function generateMessageId() {
|
|
82
|
+
return `msg_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
|
|
83
|
+
}
|
|
84
|
+
function createRequest(payload) {
|
|
85
|
+
return {
|
|
86
|
+
messageId: generateMessageId(),
|
|
87
|
+
payload,
|
|
88
|
+
timestamp: Date.now()
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async function invokeIpc(channel, payload) {
|
|
92
|
+
const request = createRequest(payload);
|
|
93
|
+
const response = await import_electron.ipcRenderer.invoke(channel, request);
|
|
94
|
+
if (!response.success) {
|
|
95
|
+
const error = new Error(response.error?.message ?? "Unknown IPC error");
|
|
96
|
+
error.name = response.error?.code ?? "IpcError";
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
return response.data;
|
|
100
|
+
}
|
|
101
|
+
var sqlStorageApi = {
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Database Operations
|
|
104
|
+
// ============================================================================
|
|
105
|
+
/**
|
|
106
|
+
* Open the database connection.
|
|
107
|
+
*/
|
|
108
|
+
async open(options) {
|
|
109
|
+
const payload = { options };
|
|
110
|
+
await invokeIpc(DB_CHANNELS.OPEN, payload);
|
|
111
|
+
},
|
|
112
|
+
/**
|
|
113
|
+
* Close the database connection.
|
|
114
|
+
*/
|
|
115
|
+
async close() {
|
|
116
|
+
await invokeIpc(DB_CHANNELS.CLOSE, void 0);
|
|
117
|
+
},
|
|
118
|
+
/**
|
|
119
|
+
* Check if the database is open.
|
|
120
|
+
*/
|
|
121
|
+
async isOpen() {
|
|
122
|
+
return invokeIpc(DB_CHANNELS.IS_OPEN, void 0);
|
|
123
|
+
},
|
|
124
|
+
/**
|
|
125
|
+
* Get adapter capabilities.
|
|
126
|
+
*/
|
|
127
|
+
async getCapabilities() {
|
|
128
|
+
return invokeIpc(DB_CHANNELS.CAPABILITIES, void 0);
|
|
129
|
+
},
|
|
130
|
+
/**
|
|
131
|
+
* Execute a mutation statement (INSERT, UPDATE, DELETE).
|
|
132
|
+
*/
|
|
133
|
+
async run(statement, parameters) {
|
|
134
|
+
const payload = { statement, parameters };
|
|
135
|
+
return invokeIpc(DB_CHANNELS.RUN, payload);
|
|
136
|
+
},
|
|
137
|
+
/**
|
|
138
|
+
* Get a single row.
|
|
139
|
+
*/
|
|
140
|
+
async get(statement, parameters) {
|
|
141
|
+
const payload = { statement, parameters };
|
|
142
|
+
return invokeIpc(DB_CHANNELS.GET, payload);
|
|
143
|
+
},
|
|
144
|
+
/**
|
|
145
|
+
* Get all matching rows.
|
|
146
|
+
*/
|
|
147
|
+
async all(statement, parameters) {
|
|
148
|
+
const payload = { statement, parameters };
|
|
149
|
+
return invokeIpc(DB_CHANNELS.ALL, payload);
|
|
150
|
+
},
|
|
151
|
+
/**
|
|
152
|
+
* Execute a SQL script.
|
|
153
|
+
*/
|
|
154
|
+
async exec(script) {
|
|
155
|
+
const payload = { script };
|
|
156
|
+
await invokeIpc(DB_CHANNELS.EXEC, payload);
|
|
157
|
+
},
|
|
158
|
+
/**
|
|
159
|
+
* Execute batch operations.
|
|
160
|
+
*/
|
|
161
|
+
async batch(operations) {
|
|
162
|
+
const payload = { operations };
|
|
163
|
+
return invokeIpc(DB_CHANNELS.BATCH, payload);
|
|
164
|
+
},
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// Transaction Operations
|
|
167
|
+
// ============================================================================
|
|
168
|
+
/**
|
|
169
|
+
* Begin a transaction.
|
|
170
|
+
*/
|
|
171
|
+
async beginTransaction() {
|
|
172
|
+
return invokeIpc(TRANSACTION_CHANNELS.BEGIN, void 0);
|
|
173
|
+
},
|
|
174
|
+
/**
|
|
175
|
+
* Commit a transaction.
|
|
176
|
+
*/
|
|
177
|
+
async commitTransaction(transactionId) {
|
|
178
|
+
await invokeIpc(TRANSACTION_CHANNELS.COMMIT, { transactionId });
|
|
179
|
+
},
|
|
180
|
+
/**
|
|
181
|
+
* Rollback a transaction.
|
|
182
|
+
*/
|
|
183
|
+
async rollbackTransaction(transactionId) {
|
|
184
|
+
await invokeIpc(TRANSACTION_CHANNELS.ROLLBACK, { transactionId });
|
|
185
|
+
},
|
|
186
|
+
/**
|
|
187
|
+
* Execute an operation within a transaction.
|
|
188
|
+
*/
|
|
189
|
+
async executeInTransaction(transactionId, statement, parameters) {
|
|
190
|
+
const payload = {
|
|
191
|
+
transactionId,
|
|
192
|
+
operation: { statement, parameters }
|
|
193
|
+
};
|
|
194
|
+
return invokeIpc(TRANSACTION_CHANNELS.EXECUTE, payload);
|
|
195
|
+
},
|
|
196
|
+
/**
|
|
197
|
+
* Execute a callback within a transaction (convenience method).
|
|
198
|
+
* Automatically handles begin/commit/rollback.
|
|
199
|
+
*/
|
|
200
|
+
async transaction(fn) {
|
|
201
|
+
const ctx = await this.beginTransaction();
|
|
202
|
+
const trx = {
|
|
203
|
+
run: async (statement, parameters) => {
|
|
204
|
+
const result = await this.executeInTransaction(ctx.transactionId, statement, parameters);
|
|
205
|
+
return result;
|
|
206
|
+
},
|
|
207
|
+
get: async (statement, parameters) => {
|
|
208
|
+
const result = await this.executeInTransaction(ctx.transactionId, statement, parameters);
|
|
209
|
+
return Array.isArray(result) ? result[0] ?? null : null;
|
|
210
|
+
},
|
|
211
|
+
all: async (statement, parameters) => {
|
|
212
|
+
const result = await this.executeInTransaction(ctx.transactionId, statement, parameters);
|
|
213
|
+
return Array.isArray(result) ? result : [];
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
try {
|
|
217
|
+
const result = await fn(trx);
|
|
218
|
+
await this.commitTransaction(ctx.transactionId);
|
|
219
|
+
return result;
|
|
220
|
+
} catch (error) {
|
|
221
|
+
await this.rollbackTransaction(ctx.transactionId).catch(() => {
|
|
222
|
+
});
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
// ============================================================================
|
|
227
|
+
// Sync Operations
|
|
228
|
+
// ============================================================================
|
|
229
|
+
/**
|
|
230
|
+
* Get sync status.
|
|
231
|
+
*/
|
|
232
|
+
async getSyncStatus() {
|
|
233
|
+
return invokeIpc(SYNC_CHANNELS.STATUS, void 0);
|
|
234
|
+
},
|
|
235
|
+
/**
|
|
236
|
+
* Trigger manual sync.
|
|
237
|
+
*/
|
|
238
|
+
async triggerSync() {
|
|
239
|
+
await invokeIpc(SYNC_CHANNELS.TRIGGER, void 0);
|
|
240
|
+
},
|
|
241
|
+
// ============================================================================
|
|
242
|
+
// Event Subscriptions
|
|
243
|
+
// ============================================================================
|
|
244
|
+
/**
|
|
245
|
+
* Subscribe to database change events.
|
|
246
|
+
*/
|
|
247
|
+
onDatabaseChange(callback) {
|
|
248
|
+
const handler = (_, event) => {
|
|
249
|
+
callback(event);
|
|
250
|
+
};
|
|
251
|
+
import_electron.ipcRenderer.on(BROADCAST_CHANNELS.DB_CHANGE, handler);
|
|
252
|
+
return () => import_electron.ipcRenderer.removeListener(BROADCAST_CHANNELS.DB_CHANGE, handler);
|
|
253
|
+
},
|
|
254
|
+
/**
|
|
255
|
+
* Subscribe to sync progress events.
|
|
256
|
+
*/
|
|
257
|
+
onSyncProgress(callback) {
|
|
258
|
+
const handler = (_, progress) => {
|
|
259
|
+
callback(progress);
|
|
260
|
+
};
|
|
261
|
+
import_electron.ipcRenderer.on(SYNC_CHANNELS.PROGRESS, handler);
|
|
262
|
+
return () => import_electron.ipcRenderer.removeListener(SYNC_CHANNELS.PROGRESS, handler);
|
|
263
|
+
},
|
|
264
|
+
/**
|
|
265
|
+
* Subscribe to sync complete events.
|
|
266
|
+
*/
|
|
267
|
+
onSyncComplete(callback) {
|
|
268
|
+
const handler = () => callback();
|
|
269
|
+
import_electron.ipcRenderer.on(SYNC_CHANNELS.COMPLETE, handler);
|
|
270
|
+
return () => import_electron.ipcRenderer.removeListener(SYNC_CHANNELS.COMPLETE, handler);
|
|
271
|
+
},
|
|
272
|
+
/**
|
|
273
|
+
* Subscribe to sync error events.
|
|
274
|
+
*/
|
|
275
|
+
onSyncError(callback) {
|
|
276
|
+
const handler = (_, error) => {
|
|
277
|
+
callback(new Error(error.message));
|
|
278
|
+
};
|
|
279
|
+
import_electron.ipcRenderer.on(SYNC_CHANNELS.ERROR, handler);
|
|
280
|
+
return () => import_electron.ipcRenderer.removeListener(SYNC_CHANNELS.ERROR, handler);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
if (import_electron.contextBridge) {
|
|
284
|
+
import_electron.contextBridge.exposeInMainWorld("sqlStorage", sqlStorageApi);
|
|
285
|
+
}
|
|
286
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
287
|
+
0 && (module.exports = {
|
|
288
|
+
sqlStorageApi
|
|
289
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The renderer-process entry, `@framers/sql-storage-adapter/electron/renderer`: the adapter a window uses over IPC,
|
|
3
|
+
* and nothing from the main process (better-sqlite3, the window manager, recovery, migration).
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export { ElectronRendererAdapter, createElectronRendererAdapter, isElectronRenderer, isPreloadApiAvailable, type ElectronRendererAdapterOptions, } from './electronRendererAdapter.js';
|
|
8
|
+
export type { DbChangeEvent, SyncStatus } from './ipc/types.js';
|
|
9
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/adapters/electron/renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,8BAA8B,GACpC,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The renderer-process entry, `@framers/sql-storage-adapter/electron/renderer`: the adapter a window uses over IPC,
|
|
3
|
+
* and nothing from the main process (better-sqlite3, the window manager, recovery, migration).
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
export { ElectronRendererAdapter, createElectronRendererAdapter, isElectronRenderer, isPreloadApiAvailable, } from './electronRendererAdapter.js';
|
|
8
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../../src/adapters/electron/renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,kBAAkB,EAClB,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
var import_vitest = require("vitest");
|
|
2
|
+
var import_indexedDbAdapter = require("../indexedDbAdapter.js");
|
|
3
|
+
const setupIndexedDbMock = () => {
|
|
4
|
+
const stores = /* @__PURE__ */ new Map();
|
|
5
|
+
global.indexedDB = {
|
|
6
|
+
open: (_name, _version) => {
|
|
7
|
+
const req = {
|
|
8
|
+
result: {
|
|
9
|
+
objectStoreNames: { contains: () => false },
|
|
10
|
+
createObjectStore: (_storeName) => {
|
|
11
|
+
stores.set(_storeName, /* @__PURE__ */ new Map());
|
|
12
|
+
},
|
|
13
|
+
transaction: (_storeName, _mode) => ({
|
|
14
|
+
objectStore: (name) => {
|
|
15
|
+
const store = stores.get(name) || /* @__PURE__ */ new Map();
|
|
16
|
+
return {
|
|
17
|
+
get: (key) => ({
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
onsuccess: null,
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
onerror: null,
|
|
22
|
+
result: store.get(key)
|
|
23
|
+
}),
|
|
24
|
+
put: (value, key) => {
|
|
25
|
+
store.set(key, value);
|
|
26
|
+
return {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
onsuccess: null,
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
+
onerror: null
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}),
|
|
36
|
+
close: () => {
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
setTimeout(() => {
|
|
41
|
+
if (req.onupgradeneeded)
|
|
42
|
+
req.onupgradeneeded();
|
|
43
|
+
if (req.onsuccess)
|
|
44
|
+
req.onsuccess();
|
|
45
|
+
}, 0);
|
|
46
|
+
return req;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
(0, import_vitest.describe)("IndexedDbAdapter", () => {
|
|
51
|
+
let adapter;
|
|
52
|
+
(0, import_vitest.beforeEach)(async () => {
|
|
53
|
+
setupIndexedDbMock();
|
|
54
|
+
adapter = new import_indexedDbAdapter.IndexedDbAdapter({
|
|
55
|
+
dbName: "test-db",
|
|
56
|
+
autoSave: false
|
|
57
|
+
// Disable for tests
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
(0, import_vitest.afterEach)(async () => {
|
|
61
|
+
if (adapter) {
|
|
62
|
+
await adapter.close();
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
(0, import_vitest.it)("should initialize with correct capabilities", () => {
|
|
66
|
+
(0, import_vitest.expect)(adapter.kind).toBe("indexeddb");
|
|
67
|
+
(0, import_vitest.expect)(adapter.capabilities.has("transactions")).toBe(true);
|
|
68
|
+
(0, import_vitest.expect)(adapter.capabilities.has("persistence")).toBe(true);
|
|
69
|
+
});
|
|
70
|
+
(0, import_vitest.it)("should open database successfully", async () => {
|
|
71
|
+
await adapter.open();
|
|
72
|
+
(0, import_vitest.expect)(true).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
(0, import_vitest.it)("should create table and insert data", async () => {
|
|
75
|
+
await adapter.open();
|
|
76
|
+
await adapter.run("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)");
|
|
77
|
+
const result = await adapter.run("INSERT INTO test (name) VALUES (?)", ["Alice"]);
|
|
78
|
+
(0, import_vitest.expect)(result.changes).toBe(1);
|
|
79
|
+
(0, import_vitest.expect)(result.lastInsertRowid).toBeDefined();
|
|
80
|
+
});
|
|
81
|
+
(0, import_vitest.it)("should retrieve inserted data", async () => {
|
|
82
|
+
await adapter.open();
|
|
83
|
+
await adapter.run("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)");
|
|
84
|
+
await adapter.run("INSERT INTO test (name) VALUES (?)", ["Bob"]);
|
|
85
|
+
const row = await adapter.get("SELECT * FROM test WHERE name = ?", ["Bob"]);
|
|
86
|
+
(0, import_vitest.expect)(row).toBeDefined();
|
|
87
|
+
(0, import_vitest.expect)(row?.name).toBe("Bob");
|
|
88
|
+
});
|
|
89
|
+
(0, import_vitest.it)("should return all rows", async () => {
|
|
90
|
+
await adapter.open();
|
|
91
|
+
await adapter.run("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)");
|
|
92
|
+
await adapter.run("INSERT INTO test (name) VALUES (?)", ["Alice"]);
|
|
93
|
+
await adapter.run("INSERT INTO test (name) VALUES (?)", ["Bob"]);
|
|
94
|
+
const rows = await adapter.all("SELECT * FROM test");
|
|
95
|
+
(0, import_vitest.expect)(rows.length).toBe(2);
|
|
96
|
+
(0, import_vitest.expect)(rows.map((r) => r.name)).toContain("Alice");
|
|
97
|
+
(0, import_vitest.expect)(rows.map((r) => r.name)).toContain("Bob");
|
|
98
|
+
});
|
|
99
|
+
(0, import_vitest.it)("should support transactions", async () => {
|
|
100
|
+
await adapter.open();
|
|
101
|
+
await adapter.run("CREATE TABLE test (id INTEGER PRIMARY KEY, value INTEGER)");
|
|
102
|
+
await adapter.beginTransaction();
|
|
103
|
+
await adapter.run("INSERT INTO test (value) VALUES (?)", [100]);
|
|
104
|
+
await adapter.run("INSERT INTO test (value) VALUES (?)", [200]);
|
|
105
|
+
await adapter.commit();
|
|
106
|
+
const rows = await adapter.all("SELECT value FROM test");
|
|
107
|
+
(0, import_vitest.expect)(rows.length).toBe(2);
|
|
108
|
+
(0, import_vitest.expect)(rows.map((r) => r.value)).toEqual([100, 200]);
|
|
109
|
+
});
|
|
110
|
+
(0, import_vitest.it)("should rollback transactions", async () => {
|
|
111
|
+
await adapter.open();
|
|
112
|
+
await adapter.run("CREATE TABLE test (id INTEGER PRIMARY KEY, value INTEGER)");
|
|
113
|
+
await adapter.beginTransaction();
|
|
114
|
+
await adapter.run("INSERT INTO test (value) VALUES (?)", [100]);
|
|
115
|
+
await adapter.rollback();
|
|
116
|
+
const rows = await adapter.all("SELECT * FROM test");
|
|
117
|
+
(0, import_vitest.expect)(rows.length).toBe(0);
|
|
118
|
+
});
|
|
119
|
+
(0, import_vitest.it)("should export and import database", async () => {
|
|
120
|
+
await adapter.open();
|
|
121
|
+
await adapter.run("CREATE TABLE test (id INTEGER PRIMARY KEY, name TEXT)");
|
|
122
|
+
await adapter.run("INSERT INTO test (name) VALUES (?)", ["Export Test"]);
|
|
123
|
+
const exported = adapter.exportDatabase();
|
|
124
|
+
(0, import_vitest.expect)(exported).toBeInstanceOf(Uint8Array);
|
|
125
|
+
(0, import_vitest.expect)(exported.length).toBeGreaterThan(0);
|
|
126
|
+
const adapter2 = new import_indexedDbAdapter.IndexedDbAdapter({ dbName: "test-db-2", autoSave: false });
|
|
127
|
+
await adapter2.open();
|
|
128
|
+
await adapter2.importDatabase(exported);
|
|
129
|
+
const row = await adapter2.get("SELECT * FROM test WHERE name = ?", ["Export Test"]);
|
|
130
|
+
(0, import_vitest.expect)(row?.name).toBe("Export Test");
|
|
131
|
+
await adapter2.close();
|
|
132
|
+
});
|
|
133
|
+
});
|