@stratasync/storage-idb 0.2.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/README.md +52 -0
- package/dist/adapter.d.ts +67 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +453 -0
- package/dist/adapter.js.map +1 -0
- package/dist/database-manager.d.ts +10 -0
- package/dist/database-manager.d.ts.map +1 -0
- package/dist/database-manager.js +38 -0
- package/dist/database-manager.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/store-names.d.ts +15 -0
- package/dist/store-names.d.ts.map +1 -0
- package/dist/store-names.js +38 -0
- package/dist/store-names.js.map +1 -0
- package/dist/stores/coverage.d.ts +30 -0
- package/dist/stores/coverage.d.ts.map +1 -0
- package/dist/stores/coverage.js +49 -0
- package/dist/stores/coverage.js.map +1 -0
- package/dist/stores/meta.d.ts +56 -0
- package/dist/stores/meta.d.ts.map +1 -0
- package/dist/stores/meta.js +163 -0
- package/dist/stores/meta.js.map +1 -0
- package/dist/stores/outbox.d.ts +59 -0
- package/dist/stores/outbox.d.ts.map +1 -0
- package/dist/stores/outbox.js +141 -0
- package/dist/stores/outbox.js.map +1 -0
- package/dist/types.d.ts +34 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# @stratasync/storage-idb
|
|
2
|
+
|
|
3
|
+
IndexedDB storage adapter for client-side persistence in the Done.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
sync-storage-idb provides offline-capable persistence using IndexedDB:
|
|
8
|
+
|
|
9
|
+
- **IndexedDB abstraction** via the `idb` library
|
|
10
|
+
- **Schema migrations** with versioned database upgrades
|
|
11
|
+
- **Transactional writes** for data consistency
|
|
12
|
+
- **Offline data persistence** for local-first architecture
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @stratasync/storage-idb
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Dependency: `idb` ^8.0.0
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { createIdbStorage } from "@stratasync/storage-idb";
|
|
26
|
+
|
|
27
|
+
const storage = createIdbStorage({
|
|
28
|
+
dbName: "lse-sync",
|
|
29
|
+
version: 1,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Pass to SyncClient configuration
|
|
33
|
+
const client = new SyncClient({
|
|
34
|
+
storage,
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The storage adapter handles:
|
|
39
|
+
|
|
40
|
+
- Persisting model instances to IndexedDB
|
|
41
|
+
- Loading cached data on startup for instant UI
|
|
42
|
+
- Managing schema migrations when the database version changes
|
|
43
|
+
- Transactional writes to prevent partial updates
|
|
44
|
+
|
|
45
|
+
## Testing
|
|
46
|
+
|
|
47
|
+
Tests use `fake-indexeddb` to mock the IndexedDB API in Node.js:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm run test
|
|
51
|
+
# Runs: node --import tsx --test "tests/**/*.test.ts"
|
|
52
|
+
```
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { SyncAction, Transaction } from "@stratasync/core";
|
|
2
|
+
import type { BatchOperation, ModelPersistenceMeta, StorageAdapter, StorageMeta, StorageOptions } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* IndexedDB storage adapter implementation
|
|
5
|
+
*/
|
|
6
|
+
export declare class IndexedDbStorageAdapter implements StorageAdapter {
|
|
7
|
+
private db;
|
|
8
|
+
private registry;
|
|
9
|
+
private dbName;
|
|
10
|
+
private schemaVersion;
|
|
11
|
+
private schemaHash;
|
|
12
|
+
private readonly storeNames;
|
|
13
|
+
private readonly partialDbs;
|
|
14
|
+
private readonly databaseManager;
|
|
15
|
+
open(options: StorageOptions): Promise<void>;
|
|
16
|
+
private initializeRegistry;
|
|
17
|
+
private resolveSchemaVersion;
|
|
18
|
+
private populateStoreNames;
|
|
19
|
+
private openDatabase;
|
|
20
|
+
private openDatabaseWithSchemaVersion;
|
|
21
|
+
private static isVersionError;
|
|
22
|
+
private getExistingDatabaseVersion;
|
|
23
|
+
private syncDatabaseInfo;
|
|
24
|
+
private upgradeDatabase;
|
|
25
|
+
private static ensureMetaStore;
|
|
26
|
+
private static ensureTransactionStore;
|
|
27
|
+
private static ensureSyncActionStore;
|
|
28
|
+
private ensureModelStores;
|
|
29
|
+
private static createModelStore;
|
|
30
|
+
private static createFieldIndexes;
|
|
31
|
+
private static createGroupIndex;
|
|
32
|
+
private static createModelIndexes;
|
|
33
|
+
close(): Promise<void>;
|
|
34
|
+
get<T>(modelName: string, id: string): Promise<T | null>;
|
|
35
|
+
getAll<T>(modelName: string): Promise<T[]>;
|
|
36
|
+
put<T extends Record<string, unknown>>(modelName: string, row: T): Promise<void>;
|
|
37
|
+
delete(modelName: string, id: string): Promise<void>;
|
|
38
|
+
getByIndex<T>(modelName: string, indexName: string, key: string): Promise<T[]>;
|
|
39
|
+
writeBatch(ops: BatchOperation[]): Promise<void>;
|
|
40
|
+
getMeta(): Promise<StorageMeta>;
|
|
41
|
+
setMeta(updates: Partial<StorageMeta>): Promise<void>;
|
|
42
|
+
getModelPersistence(modelName: string): Promise<ModelPersistenceMeta>;
|
|
43
|
+
setModelPersistence(modelName: string, persisted: boolean): Promise<void>;
|
|
44
|
+
getOutbox(): Promise<Transaction[]>;
|
|
45
|
+
addToOutbox(tx: Transaction): Promise<void>;
|
|
46
|
+
removeFromOutbox(clientTxId: string): Promise<void>;
|
|
47
|
+
updateOutboxTransaction(clientTxId: string, updates: Partial<Transaction>): Promise<void>;
|
|
48
|
+
hasPartialIndex(modelName: string, indexedKey: string, keyValue: string): Promise<boolean>;
|
|
49
|
+
setPartialIndex(modelName: string, indexedKey: string, keyValue: string): Promise<void>;
|
|
50
|
+
addSyncActions(actions: SyncAction[]): Promise<void>;
|
|
51
|
+
getSyncActions(afterSyncId?: string, limit?: number): Promise<SyncAction[]>;
|
|
52
|
+
clearSyncActions(): Promise<void>;
|
|
53
|
+
clear(options?: {
|
|
54
|
+
preserveOutbox?: boolean;
|
|
55
|
+
}): Promise<void>;
|
|
56
|
+
count(modelName: string): Promise<number>;
|
|
57
|
+
private ensureOpen;
|
|
58
|
+
private getStoreName;
|
|
59
|
+
private ensureMetadataInitialized;
|
|
60
|
+
private openPartialDatabases;
|
|
61
|
+
private getPartialDb;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Creates an IndexedDB storage adapter
|
|
65
|
+
*/
|
|
66
|
+
export declare const createIndexedDbStorage: () => StorageAdapter;
|
|
67
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import { compareSyncId, isSyncIdGreaterThan, ModelRegistry, } from "@stratasync/core";
|
|
2
|
+
import { openDB } from "idb";
|
|
3
|
+
import { LinearDatabaseManager } from "./database-manager.js";
|
|
4
|
+
import { computeModelStoreName, computePartialDatabaseName, computeWorkspaceDatabaseName, } from "./store-names.js";
|
|
5
|
+
import { createPartialIndexKey, PARTIAL_INDEX_STORE, } from "./stores/coverage.js";
|
|
6
|
+
import { getMetadata, getModelPersistence as getModelPersistenceMeta, initializeMetadata, META_STORE, setMetadata, setModelPersistence as setModelPersistenceMeta, } from "./stores/meta.js";
|
|
7
|
+
import { addTransaction, getAllTransactions, removeTransaction, SYNC_ACTION_STORE, TRANSACTION_STORE, updateTransaction, } from "./stores/outbox.js";
|
|
8
|
+
/**
|
|
9
|
+
* IndexedDB storage adapter implementation
|
|
10
|
+
*/
|
|
11
|
+
export class IndexedDbStorageAdapter {
|
|
12
|
+
db = null;
|
|
13
|
+
registry = null;
|
|
14
|
+
dbName = "";
|
|
15
|
+
schemaVersion = 1;
|
|
16
|
+
schemaHash = "";
|
|
17
|
+
storeNames = new Map();
|
|
18
|
+
partialDbs = new Map();
|
|
19
|
+
databaseManager = new LinearDatabaseManager();
|
|
20
|
+
async open(options) {
|
|
21
|
+
this.initializeRegistry(options);
|
|
22
|
+
const userId = options.userId ?? "anonymous";
|
|
23
|
+
const version = options.version ?? 1;
|
|
24
|
+
const userVersion = options.userVersion ?? 1;
|
|
25
|
+
this.dbName =
|
|
26
|
+
options.name ??
|
|
27
|
+
computeWorkspaceDatabaseName({ userId, userVersion, version });
|
|
28
|
+
await this.databaseManager.open();
|
|
29
|
+
const existingInfo = await this.databaseManager.getDatabaseInfo(this.dbName);
|
|
30
|
+
this.schemaVersion = this.resolveSchemaVersion(existingInfo);
|
|
31
|
+
this.populateStoreNames();
|
|
32
|
+
await this.openDatabase();
|
|
33
|
+
await this.syncDatabaseInfo(existingInfo, { userId, userVersion, version });
|
|
34
|
+
await this.ensureMetadataInitialized();
|
|
35
|
+
await this.openPartialDatabases();
|
|
36
|
+
}
|
|
37
|
+
initializeRegistry(options) {
|
|
38
|
+
this.registry = new ModelRegistry(options.schema ?? ModelRegistry.snapshot());
|
|
39
|
+
this.schemaHash = this.registry.getSchemaHash();
|
|
40
|
+
}
|
|
41
|
+
resolveSchemaVersion(existingInfo) {
|
|
42
|
+
if (!existingInfo) {
|
|
43
|
+
return 1;
|
|
44
|
+
}
|
|
45
|
+
return existingInfo.schemaHash === this.schemaHash
|
|
46
|
+
? existingInfo.schemaVersion
|
|
47
|
+
: existingInfo.schemaVersion + 1;
|
|
48
|
+
}
|
|
49
|
+
populateStoreNames() {
|
|
50
|
+
this.storeNames.clear();
|
|
51
|
+
if (!this.registry) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
for (const model of this.registry.getAllModels()) {
|
|
55
|
+
const modelName = model.name ?? "";
|
|
56
|
+
if (!modelName) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
this.storeNames.set(modelName, computeModelStoreName(modelName, this.schemaVersion, this.registry));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async openDatabase() {
|
|
63
|
+
try {
|
|
64
|
+
this.db = await this.openDatabaseWithSchemaVersion(this.schemaVersion, true);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (!IndexedDbStorageAdapter.isVersionError(error)) {
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
const existingVersion = await this.getExistingDatabaseVersion();
|
|
71
|
+
this.schemaVersion = existingVersion + 1;
|
|
72
|
+
// Recompute store name hashes for the updated schemaVersion. Without
|
|
73
|
+
// this, the storeNames map still holds hashes for the original version,
|
|
74
|
+
// the upgrade creates stores with those stale names, and syncDatabaseInfo
|
|
75
|
+
// persists the new (higher) schemaVersion. On the next open the computed
|
|
76
|
+
// hashes won't match the actual store names → "Unknown model store".
|
|
77
|
+
this.populateStoreNames();
|
|
78
|
+
this.db = await this.openDatabaseWithSchemaVersion(this.schemaVersion, false);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async openDatabaseWithSchemaVersion(schemaVersion, includeBlockingHandlers) {
|
|
82
|
+
const baseOptions = {
|
|
83
|
+
upgrade: (database) => {
|
|
84
|
+
this.upgradeDatabase(database);
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
if (!includeBlockingHandlers) {
|
|
88
|
+
return (await openDB(this.dbName, schemaVersion, baseOptions));
|
|
89
|
+
}
|
|
90
|
+
return (await openDB(this.dbName, schemaVersion, {
|
|
91
|
+
...baseOptions,
|
|
92
|
+
blocked: () => {
|
|
93
|
+
// Another tab has the database open with an older version
|
|
94
|
+
},
|
|
95
|
+
blocking: () => {
|
|
96
|
+
// This connection is blocking an upgrade in another tab
|
|
97
|
+
this.db?.close();
|
|
98
|
+
},
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
static isVersionError(error) {
|
|
102
|
+
return error instanceof DOMException && error.name === "VersionError";
|
|
103
|
+
}
|
|
104
|
+
async getExistingDatabaseVersion() {
|
|
105
|
+
const existing = await openDB(this.dbName);
|
|
106
|
+
const existingVersion = existing.version;
|
|
107
|
+
existing.close();
|
|
108
|
+
return existingVersion;
|
|
109
|
+
}
|
|
110
|
+
async syncDatabaseInfo(existingInfo, context) {
|
|
111
|
+
const now = Date.now();
|
|
112
|
+
if (!existingInfo) {
|
|
113
|
+
await this.databaseManager.saveDatabase({
|
|
114
|
+
name: this.dbName,
|
|
115
|
+
schemaHash: this.schemaHash,
|
|
116
|
+
schemaVersion: this.schemaVersion,
|
|
117
|
+
updatedAt: now,
|
|
118
|
+
userId: context.userId,
|
|
119
|
+
userVersion: context.userVersion,
|
|
120
|
+
version: context.version,
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (existingInfo.schemaHash !== this.schemaHash) {
|
|
125
|
+
await this.databaseManager.saveDatabase({
|
|
126
|
+
...existingInfo,
|
|
127
|
+
schemaHash: this.schemaHash,
|
|
128
|
+
schemaVersion: this.schemaVersion,
|
|
129
|
+
updatedAt: now,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
upgradeDatabase(db) {
|
|
134
|
+
IndexedDbStorageAdapter.ensureMetaStore(db);
|
|
135
|
+
IndexedDbStorageAdapter.ensureTransactionStore(db);
|
|
136
|
+
IndexedDbStorageAdapter.ensureSyncActionStore(db);
|
|
137
|
+
this.ensureModelStores(db);
|
|
138
|
+
}
|
|
139
|
+
static ensureMetaStore(db) {
|
|
140
|
+
if (db.objectStoreNames.contains(META_STORE)) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
db.createObjectStore(META_STORE);
|
|
144
|
+
}
|
|
145
|
+
static ensureTransactionStore(db) {
|
|
146
|
+
if (db.objectStoreNames.contains(TRANSACTION_STORE)) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const txStore = db.createObjectStore(TRANSACTION_STORE, {
|
|
150
|
+
keyPath: "clientTxId",
|
|
151
|
+
});
|
|
152
|
+
txStore.createIndex("byState", "state");
|
|
153
|
+
txStore.createIndex("byCreatedAt", "createdAt");
|
|
154
|
+
txStore.createIndex("byBatchIndex", "batchIndex");
|
|
155
|
+
}
|
|
156
|
+
static ensureSyncActionStore(db) {
|
|
157
|
+
if (db.objectStoreNames.contains(SYNC_ACTION_STORE)) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
db.createObjectStore(SYNC_ACTION_STORE, { keyPath: "id" });
|
|
161
|
+
}
|
|
162
|
+
ensureModelStores(db) {
|
|
163
|
+
if (!this.registry) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
for (const model of this.registry.getAllModels()) {
|
|
167
|
+
const modelName = model.name ?? "";
|
|
168
|
+
if (!modelName) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const storeName = this.storeNames.get(modelName) ?? modelName;
|
|
172
|
+
if (db.objectStoreNames.contains(storeName)) {
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
IndexedDbStorageAdapter.createModelStore(db, storeName, model);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
static createModelStore(db, storeName, model) {
|
|
179
|
+
const primaryKey = model.primaryKey ?? "id";
|
|
180
|
+
const store = db.createObjectStore(storeName, { keyPath: primaryKey });
|
|
181
|
+
IndexedDbStorageAdapter.createFieldIndexes(store, model);
|
|
182
|
+
IndexedDbStorageAdapter.createGroupIndex(store, model);
|
|
183
|
+
IndexedDbStorageAdapter.createModelIndexes(store, model);
|
|
184
|
+
}
|
|
185
|
+
static createFieldIndexes(store, model) {
|
|
186
|
+
for (const [fieldName, field] of Object.entries(model.fields ?? {})) {
|
|
187
|
+
if (field.indexed) {
|
|
188
|
+
store.createIndex(fieldName, fieldName);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
static createGroupIndex(store, model) {
|
|
193
|
+
if (!model.groupKey) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (!store.indexNames.contains(model.groupKey)) {
|
|
197
|
+
store.createIndex(model.groupKey, model.groupKey);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
static createModelIndexes(store, model) {
|
|
201
|
+
for (const index of model.indexes ?? []) {
|
|
202
|
+
const indexName = index.fields.join("_");
|
|
203
|
+
if (!store.indexNames.contains(indexName)) {
|
|
204
|
+
store.createIndex(indexName, index.fields, {
|
|
205
|
+
unique: index.unique,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async close() {
|
|
211
|
+
for (const db of this.partialDbs.values()) {
|
|
212
|
+
db.close();
|
|
213
|
+
}
|
|
214
|
+
this.partialDbs.clear();
|
|
215
|
+
await this.databaseManager.close();
|
|
216
|
+
this.db?.close();
|
|
217
|
+
this.db = null;
|
|
218
|
+
}
|
|
219
|
+
async get(modelName, id) {
|
|
220
|
+
const db = this.ensureOpen();
|
|
221
|
+
const storeName = this.getStoreName(modelName);
|
|
222
|
+
const result = await db.get(storeName, id);
|
|
223
|
+
return result ?? null;
|
|
224
|
+
}
|
|
225
|
+
getAll(modelName) {
|
|
226
|
+
const db = this.ensureOpen();
|
|
227
|
+
const storeName = this.getStoreName(modelName);
|
|
228
|
+
return db.getAll(storeName);
|
|
229
|
+
}
|
|
230
|
+
async put(modelName, row) {
|
|
231
|
+
const db = this.ensureOpen();
|
|
232
|
+
const storeName = this.getStoreName(modelName);
|
|
233
|
+
await db.put(storeName, row);
|
|
234
|
+
}
|
|
235
|
+
async delete(modelName, id) {
|
|
236
|
+
const db = this.ensureOpen();
|
|
237
|
+
const storeName = this.getStoreName(modelName);
|
|
238
|
+
await db.delete(storeName, id);
|
|
239
|
+
}
|
|
240
|
+
getByIndex(modelName, indexName, key) {
|
|
241
|
+
const db = this.ensureOpen();
|
|
242
|
+
const storeName = this.getStoreName(modelName);
|
|
243
|
+
return db.getAllFromIndex(storeName, indexName, key);
|
|
244
|
+
}
|
|
245
|
+
async writeBatch(ops) {
|
|
246
|
+
const db = this.ensureOpen();
|
|
247
|
+
const tx = db.transaction(ops.map((op) => this.getStoreName(op.modelName)), "readwrite");
|
|
248
|
+
const promises = [];
|
|
249
|
+
for (const op of ops) {
|
|
250
|
+
const storeName = this.getStoreName(op.modelName);
|
|
251
|
+
const store = tx.objectStore(storeName);
|
|
252
|
+
if (op.type === "put" && op.data) {
|
|
253
|
+
promises.push(store.put(op.data));
|
|
254
|
+
}
|
|
255
|
+
else if (op.type === "delete" && op.id) {
|
|
256
|
+
promises.push(store.delete(op.id));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
await Promise.all([...promises, tx.done]);
|
|
260
|
+
}
|
|
261
|
+
getMeta() {
|
|
262
|
+
const db = this.ensureOpen();
|
|
263
|
+
return getMetadata(db);
|
|
264
|
+
}
|
|
265
|
+
async setMeta(updates) {
|
|
266
|
+
const db = this.ensureOpen();
|
|
267
|
+
const current = await getMetadata(db);
|
|
268
|
+
await setMetadata(db, {
|
|
269
|
+
...current,
|
|
270
|
+
...updates,
|
|
271
|
+
schemaHash: updates.schemaHash ?? (current.schemaHash || this.schemaHash),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
getModelPersistence(modelName) {
|
|
275
|
+
const db = this.ensureOpen();
|
|
276
|
+
return getModelPersistenceMeta(db, modelName);
|
|
277
|
+
}
|
|
278
|
+
async setModelPersistence(modelName, persisted) {
|
|
279
|
+
const db = this.ensureOpen();
|
|
280
|
+
await setModelPersistenceMeta(db, modelName, persisted);
|
|
281
|
+
}
|
|
282
|
+
getOutbox() {
|
|
283
|
+
const db = this.ensureOpen();
|
|
284
|
+
return getAllTransactions(db);
|
|
285
|
+
}
|
|
286
|
+
async addToOutbox(tx) {
|
|
287
|
+
const db = this.ensureOpen();
|
|
288
|
+
await addTransaction(db, tx);
|
|
289
|
+
}
|
|
290
|
+
async removeFromOutbox(clientTxId) {
|
|
291
|
+
const db = this.ensureOpen();
|
|
292
|
+
await removeTransaction(db, clientTxId);
|
|
293
|
+
}
|
|
294
|
+
async updateOutboxTransaction(clientTxId, updates) {
|
|
295
|
+
const db = this.ensureOpen();
|
|
296
|
+
await updateTransaction(db, clientTxId, updates);
|
|
297
|
+
}
|
|
298
|
+
async hasPartialIndex(modelName, indexedKey, keyValue) {
|
|
299
|
+
this.ensureOpen();
|
|
300
|
+
const db = await this.getPartialDb(modelName);
|
|
301
|
+
const key = createPartialIndexKey(indexedKey, keyValue);
|
|
302
|
+
const result = await db.getKey(PARTIAL_INDEX_STORE, key);
|
|
303
|
+
return result !== undefined;
|
|
304
|
+
}
|
|
305
|
+
async setPartialIndex(modelName, indexedKey, keyValue) {
|
|
306
|
+
this.ensureOpen();
|
|
307
|
+
const db = await this.getPartialDb(modelName);
|
|
308
|
+
const key = createPartialIndexKey(indexedKey, keyValue);
|
|
309
|
+
await db.put(PARTIAL_INDEX_STORE, {
|
|
310
|
+
indexedKey,
|
|
311
|
+
keyValue,
|
|
312
|
+
modelName,
|
|
313
|
+
updatedAt: Date.now(),
|
|
314
|
+
}, key);
|
|
315
|
+
}
|
|
316
|
+
async addSyncActions(actions) {
|
|
317
|
+
const db = this.ensureOpen();
|
|
318
|
+
if (actions.length === 0) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
if (!db.objectStoreNames.contains(SYNC_ACTION_STORE)) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
const tx = db.transaction(SYNC_ACTION_STORE, "readwrite");
|
|
325
|
+
const store = tx.objectStore(SYNC_ACTION_STORE);
|
|
326
|
+
for (const action of actions) {
|
|
327
|
+
await store.put(action);
|
|
328
|
+
}
|
|
329
|
+
await tx.done;
|
|
330
|
+
}
|
|
331
|
+
async getSyncActions(afterSyncId = "0", limit) {
|
|
332
|
+
const db = this.ensureOpen();
|
|
333
|
+
if (!db.objectStoreNames.contains(SYNC_ACTION_STORE)) {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
const all = (await db.getAll(SYNC_ACTION_STORE));
|
|
337
|
+
const filtered = all
|
|
338
|
+
.filter((action) => isSyncIdGreaterThan(action.id, afterSyncId))
|
|
339
|
+
.toSorted((a, b) => compareSyncId(a.id, b.id));
|
|
340
|
+
if (typeof limit === "number") {
|
|
341
|
+
return filtered.slice(0, limit);
|
|
342
|
+
}
|
|
343
|
+
return filtered;
|
|
344
|
+
}
|
|
345
|
+
async clearSyncActions() {
|
|
346
|
+
const db = this.ensureOpen();
|
|
347
|
+
if (!db.objectStoreNames.contains(SYNC_ACTION_STORE)) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
const tx = db.transaction(SYNC_ACTION_STORE, "readwrite");
|
|
351
|
+
await tx.objectStore(SYNC_ACTION_STORE).clear();
|
|
352
|
+
await tx.done;
|
|
353
|
+
}
|
|
354
|
+
async clear(options) {
|
|
355
|
+
const db = this.ensureOpen();
|
|
356
|
+
const preserveOutbox = options?.preserveOutbox === true;
|
|
357
|
+
const storeNames = [
|
|
358
|
+
META_STORE,
|
|
359
|
+
SYNC_ACTION_STORE,
|
|
360
|
+
// oxlint-disable-next-line no-useless-spread
|
|
361
|
+
...[...this.storeNames.values()],
|
|
362
|
+
];
|
|
363
|
+
if (!preserveOutbox) {
|
|
364
|
+
storeNames.push(TRANSACTION_STORE);
|
|
365
|
+
}
|
|
366
|
+
const existing = storeNames.filter((store) => db.objectStoreNames.contains(store));
|
|
367
|
+
const tx = db.transaction(existing, "readwrite");
|
|
368
|
+
const promises = [];
|
|
369
|
+
for (const storeName of existing) {
|
|
370
|
+
promises.push(tx.objectStore(storeName).clear());
|
|
371
|
+
}
|
|
372
|
+
await Promise.all([...promises, tx.done]);
|
|
373
|
+
for (const partialDb of this.partialDbs.values()) {
|
|
374
|
+
const partialTx = partialDb.transaction(PARTIAL_INDEX_STORE, "readwrite");
|
|
375
|
+
await partialTx.objectStore(PARTIAL_INDEX_STORE).clear();
|
|
376
|
+
await partialTx.done;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
count(modelName) {
|
|
380
|
+
const db = this.ensureOpen();
|
|
381
|
+
const storeName = this.getStoreName(modelName);
|
|
382
|
+
return db.count(storeName);
|
|
383
|
+
}
|
|
384
|
+
ensureOpen() {
|
|
385
|
+
if (!this.db) {
|
|
386
|
+
throw new Error("Database not open. Call open() first.");
|
|
387
|
+
}
|
|
388
|
+
return this.db;
|
|
389
|
+
}
|
|
390
|
+
getStoreName(modelName) {
|
|
391
|
+
const storeName = this.storeNames.get(modelName);
|
|
392
|
+
if (storeName && this.db?.objectStoreNames.contains(storeName)) {
|
|
393
|
+
return storeName;
|
|
394
|
+
}
|
|
395
|
+
throw new Error(`Unknown model store: ${modelName}`);
|
|
396
|
+
}
|
|
397
|
+
async ensureMetadataInitialized() {
|
|
398
|
+
const db = this.ensureOpen();
|
|
399
|
+
const modelNames = this.registry
|
|
400
|
+
? this.registry
|
|
401
|
+
.getAllModels()
|
|
402
|
+
.map((m) => m.name ?? "")
|
|
403
|
+
.filter(Boolean)
|
|
404
|
+
: [];
|
|
405
|
+
await initializeMetadata(db, this.schemaHash, modelNames);
|
|
406
|
+
const meta = await getMetadata(db);
|
|
407
|
+
const storedHash = meta.schemaHash ?? "";
|
|
408
|
+
const hashMatches = storedHash.length > 0 && storedHash === this.schemaHash;
|
|
409
|
+
if (meta.bootstrapComplete && hashMatches && this.registry) {
|
|
410
|
+
for (const model of this.registry.getBootstrapModels()) {
|
|
411
|
+
const modelName = model.name ?? "";
|
|
412
|
+
if (!modelName) {
|
|
413
|
+
continue;
|
|
414
|
+
}
|
|
415
|
+
await this.setModelPersistence(modelName, true);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
async openPartialDatabases() {
|
|
420
|
+
if (!this.registry) {
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
for (const model of this.registry.getPartialModels()) {
|
|
424
|
+
const modelName = model.name ?? "";
|
|
425
|
+
if (!modelName) {
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
await this.getPartialDb(modelName);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
async getPartialDb(modelName) {
|
|
432
|
+
const existing = this.partialDbs.get(modelName);
|
|
433
|
+
if (existing) {
|
|
434
|
+
return existing;
|
|
435
|
+
}
|
|
436
|
+
const storeName = this.storeNames.get(modelName) ?? modelName;
|
|
437
|
+
const dbName = computePartialDatabaseName(storeName);
|
|
438
|
+
const db = await openDB(dbName, 1, {
|
|
439
|
+
upgrade: (database) => {
|
|
440
|
+
if (!database.objectStoreNames.contains(PARTIAL_INDEX_STORE)) {
|
|
441
|
+
database.createObjectStore(PARTIAL_INDEX_STORE);
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
});
|
|
445
|
+
this.partialDbs.set(modelName, db);
|
|
446
|
+
return db;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Creates an IndexedDB storage adapter
|
|
451
|
+
*/
|
|
452
|
+
export const createIndexedDbStorage = () => new IndexedDbStorageAdapter();
|
|
453
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { LinearDatabaseInfo } from "./types.js";
|
|
2
|
+
export declare class LinearDatabaseManager {
|
|
3
|
+
private db;
|
|
4
|
+
open(): Promise<void>;
|
|
5
|
+
close(): void;
|
|
6
|
+
getDatabaseInfo(name: string): Promise<LinearDatabaseInfo | null>;
|
|
7
|
+
saveDatabase(info: LinearDatabaseInfo): Promise<void>;
|
|
8
|
+
private ensureOpen;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=database-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-manager.d.ts","sourceRoot":"","sources":["../src/database-manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAYrD,qBAAa,qBAAqB;IAChC,OAAO,CAAC,EAAE,CAAoD;IAExD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAc3B,KAAK,IAAI,IAAI;IAKP,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAMjE,YAAY,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3D,OAAO,CAAC,UAAU;CAMnB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { openDB } from "idb";
|
|
2
|
+
const DATABASES_DB = "linear_databases";
|
|
3
|
+
const DATABASES_STORE = "databases";
|
|
4
|
+
export class LinearDatabaseManager {
|
|
5
|
+
db = null;
|
|
6
|
+
async open() {
|
|
7
|
+
if (this.db) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
this.db = await openDB(DATABASES_DB, 1, {
|
|
11
|
+
upgrade: (database) => {
|
|
12
|
+
if (!database.objectStoreNames.contains(DATABASES_STORE)) {
|
|
13
|
+
database.createObjectStore(DATABASES_STORE, { keyPath: "name" });
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
close() {
|
|
19
|
+
this.db?.close();
|
|
20
|
+
this.db = null;
|
|
21
|
+
}
|
|
22
|
+
async getDatabaseInfo(name) {
|
|
23
|
+
const db = this.ensureOpen();
|
|
24
|
+
const info = await db.get(DATABASES_STORE, name);
|
|
25
|
+
return info ?? null;
|
|
26
|
+
}
|
|
27
|
+
async saveDatabase(info) {
|
|
28
|
+
const db = this.ensureOpen();
|
|
29
|
+
await db.put(DATABASES_STORE, info);
|
|
30
|
+
}
|
|
31
|
+
ensureOpen() {
|
|
32
|
+
if (!this.db) {
|
|
33
|
+
throw new Error("Database manager not open. Call open() first.");
|
|
34
|
+
}
|
|
35
|
+
return this.db;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=database-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database-manager.js","sourceRoot":"","sources":["../src/database-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAK7B,MAAM,YAAY,GAAG,kBAAkB,CAAC;AACxC,MAAM,eAAe,GAAG,WAAW,CAAC;AASpC,MAAM,OAAO,qBAAqB;IACxB,EAAE,GAA+C,IAAI,CAAC;IAE9D,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QAED,IAAI,CAAC,EAAE,GAAG,MAAM,MAAM,CAAwB,YAAY,EAAE,CAAC,EAAE;YAC7D,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;gBACpB,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;oBACzD,QAAQ,CAAC,iBAAiB,CAAC,eAAe,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;gBACnE,CAAC;YACH,CAAC;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;QACjB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,IAAY;QAChC,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;QACjD,OAAQ,IAAuC,IAAI,IAAI,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAwB;QACzC,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAC7B,MAAM,EAAE,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED