@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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAEtD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ // biome-ignore-all lint/performance/noBarrelFile: public API
2
+ export { createIndexedDbStorage } from "./adapter.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ModelMetadata } from "@stratasync/core";
2
+ interface RegistryLike {
3
+ getPropertyNames(modelName: string): string[];
4
+ getModelMetadata(modelName: string): ModelMetadata | undefined;
5
+ getPrimaryKey?(modelName: string): string;
6
+ }
7
+ export declare const computeModelStoreName: (modelName: string, schemaVersion: number, registry?: RegistryLike) => string;
8
+ export declare const computeWorkspaceDatabaseName: (params: {
9
+ userId: string;
10
+ version: number;
11
+ userVersion: number;
12
+ }) => string;
13
+ export declare const computePartialDatabaseName: (storeName: string) => string;
14
+ export {};
15
+ //# sourceMappingURL=store-names.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-names.d.ts","sourceRoot":"","sources":["../src/store-names.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAuBtD,UAAU,YAAY;IACpB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC9C,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IAC/D,aAAa,CAAC,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3C;AAYD,eAAO,MAAM,qBAAqB,GAChC,WAAW,MAAM,EACjB,eAAe,MAAM,EACrB,WAAU,YAA4B,KACrC,MAWF,CAAC;AAEF,eAAO,MAAM,4BAA4B,GAAI,QAAQ;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,KAAG,MAGH,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAI,WAAW,MAAM,KAAG,MACvC,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { ModelRegistry } from "@stratasync/core";
2
+ const HASH_MODULUS = 2 ** 32;
3
+ const simpleHash = (input) => {
4
+ let hash = 5381;
5
+ for (let i = 0; i < input.length; i += 1) {
6
+ const char = input.codePointAt(i) ?? 0;
7
+ hash = (hash * 33 + char) % HASH_MODULUS;
8
+ }
9
+ return hash;
10
+ };
11
+ const toHex = (num) => num.toString(16).padStart(8, "0");
12
+ const hash32 = (input) => {
13
+ const parts = [0, 1, 2, 3].map((suffix) => toHex(simpleHash(`${input}:${suffix}`)));
14
+ return parts.join("");
15
+ };
16
+ const getPropertyNames = (modelName, registry) => {
17
+ const names = new Set(registry.getPropertyNames(modelName));
18
+ const primaryKey = registry.getPrimaryKey?.(modelName) ?? "id";
19
+ names.add(primaryKey);
20
+ return [...names].toSorted();
21
+ };
22
+ export const computeModelStoreName = (modelName, schemaVersion, registry = ModelRegistry) => {
23
+ const meta = registry.getModelMetadata(modelName);
24
+ const payload = {
25
+ name: modelName,
26
+ partial: meta?.loadStrategy === "partial" || undefined,
27
+ partialLoadMode: meta?.partialLoadMode,
28
+ properties: getPropertyNames(modelName, registry),
29
+ schemaVersion,
30
+ };
31
+ return hash32(JSON.stringify(payload));
32
+ };
33
+ export const computeWorkspaceDatabaseName = (params) => {
34
+ const { userId, version, userVersion } = params;
35
+ return `linear_${hash32(`${userId}:${version}:${userVersion}`)}`;
36
+ };
37
+ export const computePartialDatabaseName = (storeName) => `${storeName}_partial`;
38
+ //# sourceMappingURL=store-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-names.js","sourceRoot":"","sources":["../src/store-names.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,CAAC;AAE7B,MAAM,UAAU,GAAG,CAAC,KAAa,EAAU,EAAE;IAC3C,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,YAAY,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,KAAK,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAEzE,MAAM,MAAM,GAAG,CAAC,KAAa,EAAU,EAAE;IACvC,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CACxC,KAAK,CAAC,UAAU,CAAC,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC,CAAC,CACxC,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC,CAAC;AAQF,MAAM,gBAAgB,GAAG,CACvB,SAAiB,EACjB,QAAsB,EACZ,EAAE;IACZ,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,QAAQ,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;IAC/D,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC;AAC/B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,SAAiB,EACjB,aAAqB,EACrB,WAAyB,aAAa,EAC9B,EAAE;IACV,MAAM,IAAI,GAAG,QAAQ,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,OAAO,GAAG;QACd,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,IAAI,EAAE,YAAY,KAAK,SAAS,IAAI,SAAS;QACtD,eAAe,EAAE,IAAI,EAAE,eAAe;QACtC,UAAU,EAAE,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC;QACjD,aAAa;KACd,CAAC;IAEF,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;AACzC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,MAI5C,EAAU,EAAE;IACX,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAChD,OAAO,UAAU,MAAM,CAAC,GAAG,MAAM,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC,EAAE,CAAC;AACnE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,SAAiB,EAAU,EAAE,CACtE,GAAG,SAAS,UAAU,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { IDBPDatabase } from "idb";
2
+ import type { PartialIndexEntry } from "../types.js";
3
+ /**
4
+ * Store name for partial index tracking */
5
+ export declare const PARTIAL_INDEX_STORE = "partial_index";
6
+ /**
7
+ * Creates a partial index key from indexedKey and keyValue */
8
+ export declare const createPartialIndexKey: (indexedKey: string, keyValue: string) => string;
9
+ /**
10
+ * Parses a partial index key into indexedKey and keyValue */
11
+ export declare const parsePartialIndexKey: (key: string) => {
12
+ indexedKey: string;
13
+ keyValue: string;
14
+ };
15
+ /**
16
+ * Gets a partial index entry from the database */
17
+ export declare const getPartialIndex: (db: IDBPDatabase, indexedKey: string, keyValue: string) => Promise<PartialIndexEntry | null>;
18
+ /**
19
+ * Sets a partial index entry in the database */
20
+ export declare const setPartialIndex: (db: IDBPDatabase, entry: PartialIndexEntry) => Promise<void>;
21
+ /**
22
+ * Checks if a partial index key is present */
23
+ export declare const hasPartialIndex: (db: IDBPDatabase, indexedKey: string, keyValue: string) => Promise<boolean>;
24
+ /**
25
+ * Gets all partial index entries */
26
+ export declare const getAllPartialIndexes: (db: IDBPDatabase) => Promise<PartialIndexEntry[]>;
27
+ /**
28
+ * Clears all partial index entries */
29
+ export declare const clearPartialIndexes: (db: IDBPDatabase) => Promise<void>;
30
+ //# sourceMappingURL=coverage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/stores/coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAExC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;2CAC2C;AAC3C,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AAEnD;8DAC8D;AAC9D,eAAO,MAAM,qBAAqB,GAChC,YAAY,MAAM,EAClB,UAAU,MAAM,KACf,MAAqC,CAAC;AAEzC;6DAC6D;AAC7D,eAAO,MAAM,oBAAoB,GAC/B,KAAK,MAAM,KACV;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAOlB,CAAC;AAEF;kDACkD;AAClD,eAAO,MAAM,eAAe,GAC1B,IAAI,YAAY,EAChB,YAAY,MAAM,EAClB,UAAU,MAAM,KACf,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAIlC,CAAC;AAEF;gDACgD;AAChD,eAAO,MAAM,eAAe,GAC1B,IAAI,YAAY,EAChB,OAAO,iBAAiB,KACvB,OAAO,CAAC,IAAI,CAUd,CAAC;AAEF;8CAC8C;AAC9C,eAAO,MAAM,eAAe,GAC1B,IAAI,YAAY,EAChB,YAAY,MAAM,EAClB,UAAU,MAAM,KACf,OAAO,CAAC,OAAO,CAIjB,CAAC;AAEF;oCACoC;AACpC,eAAO,MAAM,oBAAoB,GAC/B,IAAI,YAAY,KACf,OAAO,CAAC,iBAAiB,EAAE,CACkC,CAAC;AAEjE;sCACsC;AACtC,eAAO,MAAM,mBAAmB,GAAU,IAAI,YAAY,KAAG,OAAO,CAAC,IAAI,CAIxE,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Store name for partial index tracking */
3
+ export const PARTIAL_INDEX_STORE = "partial_index";
4
+ /**
5
+ * Creates a partial index key from indexedKey and keyValue */
6
+ export const createPartialIndexKey = (indexedKey, keyValue) => `${indexedKey}:${keyValue}`;
7
+ /**
8
+ * Parses a partial index key into indexedKey and keyValue */
9
+ export const parsePartialIndexKey = (key) => {
10
+ const [indexedKey, ...rest] = key.split(":");
11
+ return {
12
+ indexedKey: indexedKey ?? key,
13
+ keyValue: rest.join(":"),
14
+ };
15
+ };
16
+ /**
17
+ * Gets a partial index entry from the database */
18
+ export const getPartialIndex = async (db, indexedKey, keyValue) => {
19
+ const key = createPartialIndexKey(indexedKey, keyValue);
20
+ const result = await db.get(PARTIAL_INDEX_STORE, key);
21
+ return result ?? null;
22
+ };
23
+ /**
24
+ * Sets a partial index entry in the database */
25
+ export const setPartialIndex = async (db, entry) => {
26
+ const key = createPartialIndexKey(entry.indexedKey, entry.keyValue);
27
+ await db.put(PARTIAL_INDEX_STORE, {
28
+ ...entry,
29
+ updatedAt: entry.updatedAt ?? Date.now(),
30
+ }, key);
31
+ };
32
+ /**
33
+ * Checks if a partial index key is present */
34
+ export const hasPartialIndex = async (db, indexedKey, keyValue) => {
35
+ const key = createPartialIndexKey(indexedKey, keyValue);
36
+ const result = await db.getKey(PARTIAL_INDEX_STORE, key);
37
+ return result !== undefined;
38
+ };
39
+ /**
40
+ * Gets all partial index entries */
41
+ export const getAllPartialIndexes = (db) => db.getAll(PARTIAL_INDEX_STORE);
42
+ /**
43
+ * Clears all partial index entries */
44
+ export const clearPartialIndexes = async (db) => {
45
+ const tx = db.transaction(PARTIAL_INDEX_STORE, "readwrite");
46
+ await tx.objectStore(PARTIAL_INDEX_STORE).clear();
47
+ await tx.done;
48
+ };
49
+ //# sourceMappingURL=coverage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/stores/coverage.ts"],"names":[],"mappings":"AAIA;2CAC2C;AAC3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAEnD;8DAC8D;AAC9D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,UAAkB,EAClB,QAAgB,EACR,EAAE,CAAC,GAAG,UAAU,IAAI,QAAQ,EAAE,CAAC;AAEzC;6DAC6D;AAC7D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,GAAW,EAIX,EAAE;IACF,MAAM,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO;QACL,UAAU,EAAE,UAAU,IAAI,GAAG;QAC7B,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;KACzB,CAAC;AACJ,CAAC,CAAC;AAEF;kDACkD;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,EAAgB,EAChB,UAAkB,EAClB,QAAgB,EACmB,EAAE;IACrC,MAAM,GAAG,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;IACtD,OAAQ,MAAwC,IAAI,IAAI,CAAC;AAC3D,CAAC,CAAC;AAEF;gDACgD;AAChD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,EAAgB,EAChB,KAAwB,EACT,EAAE;IACjB,MAAM,GAAG,GAAG,qBAAqB,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACpE,MAAM,EAAE,CAAC,GAAG,CACV,mBAAmB,EACnB;QACE,GAAG,KAAK;QACR,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;KACzC,EACD,GAAG,CACJ,CAAC;AACJ,CAAC,CAAC;AAEF;8CAC8C;AAC9C,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAClC,EAAgB,EAChB,UAAkB,EAClB,QAAgB,EACE,EAAE;IACpB,MAAM,GAAG,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;IACzD,OAAO,MAAM,KAAK,SAAS,CAAC;AAC9B,CAAC,CAAC;AAEF;oCACoC;AACpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,EAAgB,EACc,EAAE,CAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAiC,CAAC;AAEjE;sCACsC;AACtC,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,EAAgB,EAAiB,EAAE;IAC3E,MAAM,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAC;IAC5D,MAAM,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC,KAAK,EAAE,CAAC;IAClD,MAAM,EAAE,CAAC,IAAI,CAAC;AAChB,CAAC,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { IDBPDatabase } from "idb";
2
+ import type { ModelPersistenceMeta, StorageMeta } from "../types.js";
3
+ /**
4
+ * Store name for sync metadata
5
+ */
6
+ export declare const META_STORE = "_meta";
7
+ /**
8
+ * Key for the metadata record
9
+ */
10
+ export declare const SYNC_META_KEY = "_metadata_";
11
+ /**
12
+ * Default metadata values
13
+ */
14
+ export declare const DEFAULT_META: StorageMeta;
15
+ /**
16
+ * Gets the sync metadata from the database
17
+ */
18
+ export declare const getMetadata: (db: IDBPDatabase) => Promise<StorageMeta>;
19
+ /**
20
+ * Sets the sync metadata in the database
21
+ */
22
+ export declare const setMetadata: (db: IDBPDatabase, meta: StorageMeta) => Promise<void>;
23
+ /**
24
+ * Updates specific fields in the metadata
25
+ */
26
+ export declare const updateMetadata: (db: IDBPDatabase, updates: Partial<StorageMeta>) => Promise<StorageMeta>;
27
+ /**
28
+ * Adds a group to the subscribed groups
29
+ */
30
+ export declare const addGroup: (db: IDBPDatabase, groupId: string) => Promise<void>;
31
+ /**
32
+ * Removes a group from the subscribed groups
33
+ */
34
+ export declare const removeGroup: (db: IDBPDatabase, groupId: string) => Promise<void>;
35
+ /**
36
+ * Gets the persistence state for a model
37
+ */
38
+ export declare const getModelPersistence: (db: IDBPDatabase, modelName: string) => Promise<ModelPersistenceMeta>;
39
+ /**
40
+ * Sets the persistence state for a model
41
+ */
42
+ export declare const setModelPersistence: (db: IDBPDatabase, modelName: string, persisted: boolean) => Promise<void>;
43
+ /**
44
+ * Checks if all models are persisted
45
+ */
46
+ export declare const areModelsPersisted: (db: IDBPDatabase, modelNames: string[]) => Promise<boolean>;
47
+ /**
48
+ * Sets the persistence state for multiple models
49
+ */
50
+ export declare const setModelsPersisted: (db: IDBPDatabase, modelNames: string[], persisted: boolean) => Promise<void>;
51
+ /**
52
+ * Seeds default metadata and model persistence records if they don't exist.
53
+ * Runs in a single transaction for atomicity.
54
+ */
55
+ export declare const initializeMetadata: (db: IDBPDatabase, schemaHash: string, modelNames: string[]) => Promise<void>;
56
+ //# sourceMappingURL=meta.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../src/stores/meta.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAExC,OAAO,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAErE;;GAEG;AACH,eAAO,MAAM,UAAU,UAAU,CAAC;AAElC;;GAEG;AACH,eAAO,MAAM,aAAa,eAAe,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,WAO1B,CAAC;AAsBF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAU,IAAI,YAAY,KAAG,OAAO,CAAC,WAAW,CAUvE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,IAAI,YAAY,EAChB,MAAM,WAAW,KAChB,OAAO,CAAC,IAAI,CAGd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GACzB,IAAI,YAAY,EAChB,SAAS,OAAO,CAAC,WAAW,CAAC,KAC5B,OAAO,CAAC,WAAW,CASrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,QAAQ,GACnB,IAAI,YAAY,EAChB,SAAS,MAAM,KACd,OAAO,CAAC,IAAI,CAQd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,IAAI,YAAY,EAChB,SAAS,MAAM,KACd,OAAO,CAAC,IAAI,CAMd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC9B,IAAI,YAAY,EAChB,WAAW,MAAM,KAChB,OAAO,CAAC,oBAAoB,CAQ9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC9B,IAAI,YAAY,EAChB,WAAW,MAAM,EACjB,WAAW,OAAO,KACjB,OAAO,CAAC,IAAI,CAUd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,YAAY,EAChB,YAAY,MAAM,EAAE,KACnB,OAAO,CAAC,OAAO,CAQjB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,YAAY,EAChB,YAAY,MAAM,EAAE,EACpB,WAAW,OAAO,KACjB,OAAO,CAAC,IAAI,CAgBd,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,YAAY,EAChB,YAAY,MAAM,EAClB,YAAY,MAAM,EAAE,KACnB,OAAO,CAAC,IAAI,CA+Bd,CAAC"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Store name for sync metadata
3
+ */
4
+ export const META_STORE = "_meta";
5
+ /**
6
+ * Key for the metadata record
7
+ */
8
+ export const SYNC_META_KEY = "_metadata_";
9
+ /**
10
+ * Default metadata values
11
+ */
12
+ export const DEFAULT_META = {
13
+ bootstrapComplete: false,
14
+ clientId: "",
15
+ firstSyncId: "0",
16
+ lastSyncId: "0",
17
+ schemaHash: "",
18
+ subscribedSyncGroups: [],
19
+ };
20
+ /** Normalizes a sync ID from storage, handling legacy numeric values */
21
+ const normalizeSyncIdValue = (value) => {
22
+ if (typeof value === "string") {
23
+ return value;
24
+ }
25
+ if (typeof value === "number") {
26
+ return String(value);
27
+ }
28
+ return "0";
29
+ };
30
+ const normalizeMeta = (meta) => ({
31
+ ...DEFAULT_META,
32
+ ...meta,
33
+ firstSyncId: normalizeSyncIdValue(meta.firstSyncId),
34
+ lastSyncId: normalizeSyncIdValue(meta.lastSyncId),
35
+ subscribedSyncGroups: meta.subscribedSyncGroups ?? DEFAULT_META.subscribedSyncGroups,
36
+ });
37
+ /**
38
+ * Gets the sync metadata from the database
39
+ */
40
+ export const getMetadata = async (db) => {
41
+ const syncMeta = (await db.get(META_STORE, SYNC_META_KEY));
42
+ if (syncMeta) {
43
+ return normalizeMeta(syncMeta);
44
+ }
45
+ return { ...DEFAULT_META };
46
+ };
47
+ /**
48
+ * Sets the sync metadata in the database
49
+ */
50
+ export const setMetadata = async (db, meta) => {
51
+ const normalized = normalizeMeta(meta);
52
+ await db.put(META_STORE, normalized, SYNC_META_KEY);
53
+ };
54
+ /**
55
+ * Updates specific fields in the metadata
56
+ */
57
+ export const updateMetadata = async (db, updates) => {
58
+ const current = await getMetadata(db);
59
+ const updated = {
60
+ ...current,
61
+ ...updates,
62
+ updatedAt: Date.now(),
63
+ };
64
+ await setMetadata(db, updated);
65
+ return updated;
66
+ };
67
+ /**
68
+ * Adds a group to the subscribed groups
69
+ */
70
+ export const addGroup = async (db, groupId) => {
71
+ const meta = await getMetadata(db);
72
+ const current = meta.subscribedSyncGroups ?? [];
73
+ if (!current.includes(groupId)) {
74
+ await updateMetadata(db, {
75
+ subscribedSyncGroups: [...current, groupId],
76
+ });
77
+ }
78
+ };
79
+ /**
80
+ * Removes a group from the subscribed groups
81
+ */
82
+ export const removeGroup = async (db, groupId) => {
83
+ const meta = await getMetadata(db);
84
+ const current = meta.subscribedSyncGroups ?? [];
85
+ await updateMetadata(db, {
86
+ subscribedSyncGroups: current.filter((g) => g !== groupId),
87
+ });
88
+ };
89
+ /**
90
+ * Gets the persistence state for a model
91
+ */
92
+ export const getModelPersistence = async (db, modelName) => {
93
+ const record = await db.get(META_STORE, modelName);
94
+ return (record ?? {
95
+ modelName,
96
+ persisted: false,
97
+ });
98
+ };
99
+ /**
100
+ * Sets the persistence state for a model
101
+ */
102
+ export const setModelPersistence = async (db, modelName, persisted) => {
103
+ await db.put(META_STORE, {
104
+ modelName,
105
+ persisted,
106
+ updatedAt: Date.now(),
107
+ }, modelName);
108
+ };
109
+ /**
110
+ * Checks if all models are persisted
111
+ */
112
+ export const areModelsPersisted = async (db, modelNames) => {
113
+ for (const modelName of modelNames) {
114
+ const record = await getModelPersistence(db, modelName);
115
+ if (!record.persisted) {
116
+ return false;
117
+ }
118
+ }
119
+ return true;
120
+ };
121
+ /**
122
+ * Sets the persistence state for multiple models
123
+ */
124
+ export const setModelsPersisted = async (db, modelNames, persisted) => {
125
+ const tx = db.transaction(META_STORE, "readwrite");
126
+ const store = tx.objectStore(META_STORE);
127
+ for (const modelName of modelNames) {
128
+ await store.put({
129
+ modelName,
130
+ persisted,
131
+ updatedAt: Date.now(),
132
+ }, modelName);
133
+ }
134
+ await tx.done;
135
+ };
136
+ /**
137
+ * Seeds default metadata and model persistence records if they don't exist.
138
+ * Runs in a single transaction for atomicity.
139
+ */
140
+ export const initializeMetadata = async (db, schemaHash, modelNames) => {
141
+ const tx = db.transaction(META_STORE, "readwrite");
142
+ const store = tx.objectStore(META_STORE);
143
+ const syncMeta = await store.get(SYNC_META_KEY);
144
+ if (!syncMeta) {
145
+ await store.put({
146
+ ...DEFAULT_META,
147
+ schemaHash,
148
+ updatedAt: Date.now(),
149
+ }, SYNC_META_KEY);
150
+ }
151
+ for (const modelName of modelNames) {
152
+ const existing = await store.get(modelName);
153
+ if (!existing) {
154
+ await store.put({
155
+ modelName,
156
+ persisted: false,
157
+ updatedAt: Date.now(),
158
+ }, modelName);
159
+ }
160
+ }
161
+ await tx.done;
162
+ };
163
+ //# sourceMappingURL=meta.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"meta.js","sourceRoot":"","sources":["../../src/stores/meta.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { Transaction, TransactionState } from "@stratasync/core";
2
+ import type { IDBPDatabase } from "idb";
3
+ /**
4
+ * Store name for the transaction outbox
5
+ */
6
+ export declare const TRANSACTION_STORE = "_transaction";
7
+ /**
8
+ * Store name for sync actions
9
+ */
10
+ export declare const SYNC_ACTION_STORE = "_sync_action";
11
+ /**
12
+ * Maximum retry count before marking transaction as failed
13
+ */
14
+ export declare const MAX_RETRY_COUNT = 5;
15
+ /**
16
+ * Gets all transactions from the outbox
17
+ */
18
+ export declare const getAllTransactions: (db: IDBPDatabase) => Promise<Transaction[]>;
19
+ /**
20
+ * Gets transactions by state
21
+ */
22
+ export declare const getTransactionsByState: (db: IDBPDatabase, state: TransactionState) => Promise<Transaction[]>;
23
+ /**
24
+ * Gets a transaction by its client transaction ID
25
+ */
26
+ export declare const getTransaction: (db: IDBPDatabase, clientTxId: string) => Promise<Transaction | null>;
27
+ /**
28
+ * Adds a transaction to the outbox
29
+ */
30
+ export declare const addTransaction: (db: IDBPDatabase, tx: Transaction) => Promise<void>;
31
+ /**
32
+ * Updates a transaction in the outbox
33
+ */
34
+ export declare const updateTransaction: (db: IDBPDatabase, clientTxId: string, updates: Partial<Transaction>) => Promise<void>;
35
+ /**
36
+ * Removes a transaction from the outbox
37
+ */
38
+ export declare const removeTransaction: (db: IDBPDatabase, clientTxId: string) => Promise<void>;
39
+ /**
40
+ * Marks a transaction as failed
41
+ */
42
+ export declare const markTransactionFailed: (db: IDBPDatabase, clientTxId: string, error: string) => Promise<void>;
43
+ /**
44
+ * Requeues a failed transaction for retry
45
+ */
46
+ export declare const requeueTransaction: (db: IDBPDatabase, clientTxId: string) => Promise<boolean>;
47
+ /**
48
+ * Resets sent transactions back to queued (for reconnection)
49
+ */
50
+ export declare const resetSentToQueued: (db: IDBPDatabase) => Promise<number>;
51
+ /**
52
+ * Gets the count of pending transactions
53
+ */
54
+ export declare const getPendingCount: (db: IDBPDatabase) => Promise<number>;
55
+ /**
56
+ * Clears all transactions from the outbox
57
+ */
58
+ export declare const clearOutbox: (db: IDBPDatabase) => Promise<void>;
59
+ //# sourceMappingURL=outbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/stores/outbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAExC;;GAEG;AACH,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD;;GAEG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAKjC;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,YAAY,KACf,OAAO,CAAC,WAAW,EAAE,CAKvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GACjC,IAAI,YAAY,EAChB,OAAO,gBAAgB,KACtB,OAAO,CAAC,WAAW,EAAE,CAOvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GACzB,IAAI,YAAY,EAChB,YAAY,MAAM,KACjB,OAAO,CAAC,WAAW,GAAG,IAAI,CAM5B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GACzB,IAAI,YAAY,EAChB,IAAI,WAAW,KACd,OAAO,CAAC,IAAI,CAKd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC5B,IAAI,YAAY,EAChB,YAAY,MAAM,EAClB,SAAS,OAAO,CAAC,WAAW,CAAC,KAC5B,OAAO,CAAC,IAAI,CAQd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC5B,IAAI,YAAY,EAChB,YAAY,MAAM,KACjB,OAAO,CAAC,IAAI,CAKd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAChC,IAAI,YAAY,EAChB,YAAY,MAAM,EAClB,OAAO,MAAM,KACZ,OAAO,CAAC,IAAI,CASd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,YAAY,EAChB,YAAY,MAAM,KACjB,OAAO,CAAC,OAAO,CAgBjB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAU,IAAI,YAAY,KAAG,OAAO,CAAC,MAAM,CAgBxE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAU,IAAI,YAAY,KAAG,OAAO,CAAC,MAAM,CAWtE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,GAAU,IAAI,YAAY,KAAG,OAAO,CAAC,IAAI,CAOhE,CAAC"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Store name for the transaction outbox
3
+ */
4
+ export const TRANSACTION_STORE = "_transaction";
5
+ /**
6
+ * Store name for sync actions
7
+ */
8
+ export const SYNC_ACTION_STORE = "_sync_action";
9
+ /**
10
+ * Maximum retry count before marking transaction as failed
11
+ */
12
+ export const MAX_RETRY_COUNT = 5;
13
+ const hasTransactionStore = (db) => db.objectStoreNames.contains(TRANSACTION_STORE);
14
+ /**
15
+ * Gets all transactions from the outbox
16
+ */
17
+ export const getAllTransactions = (db) => {
18
+ if (!hasTransactionStore(db)) {
19
+ return Promise.resolve([]);
20
+ }
21
+ return db.getAll(TRANSACTION_STORE);
22
+ };
23
+ /**
24
+ * Gets transactions by state
25
+ */
26
+ export const getTransactionsByState = (db, state) => {
27
+ if (!hasTransactionStore(db)) {
28
+ return Promise.resolve([]);
29
+ }
30
+ return db.getAllFromIndex(TRANSACTION_STORE, "byState", state);
31
+ };
32
+ /**
33
+ * Gets a transaction by its client transaction ID
34
+ */
35
+ export const getTransaction = async (db, clientTxId) => {
36
+ if (!hasTransactionStore(db)) {
37
+ return null;
38
+ }
39
+ const result = await db.get(TRANSACTION_STORE, clientTxId);
40
+ return result ? result : null;
41
+ };
42
+ /**
43
+ * Adds a transaction to the outbox
44
+ */
45
+ export const addTransaction = async (db, tx) => {
46
+ if (!hasTransactionStore(db)) {
47
+ return;
48
+ }
49
+ await db.put(TRANSACTION_STORE, tx);
50
+ };
51
+ /**
52
+ * Updates a transaction in the outbox
53
+ */
54
+ export const updateTransaction = async (db, clientTxId, updates) => {
55
+ if (!hasTransactionStore(db)) {
56
+ return;
57
+ }
58
+ const tx = await db.get(TRANSACTION_STORE, clientTxId);
59
+ if (tx) {
60
+ await db.put(TRANSACTION_STORE, { ...tx, ...updates });
61
+ }
62
+ };
63
+ /**
64
+ * Removes a transaction from the outbox
65
+ */
66
+ export const removeTransaction = async (db, clientTxId) => {
67
+ if (!hasTransactionStore(db)) {
68
+ return;
69
+ }
70
+ await db.delete(TRANSACTION_STORE, clientTxId);
71
+ };
72
+ /**
73
+ * Marks a transaction as failed
74
+ */
75
+ export const markTransactionFailed = async (db, clientTxId, error) => {
76
+ const tx = await getTransaction(db, clientTxId);
77
+ if (tx) {
78
+ await updateTransaction(db, clientTxId, {
79
+ lastError: error,
80
+ retryCount: tx.retryCount + 1,
81
+ state: "failed",
82
+ });
83
+ }
84
+ };
85
+ /**
86
+ * Requeues a failed transaction for retry
87
+ */
88
+ export const requeueTransaction = async (db, clientTxId) => {
89
+ const tx = await getTransaction(db, clientTxId);
90
+ if (!tx) {
91
+ return false;
92
+ }
93
+ if (tx.retryCount >= MAX_RETRY_COUNT) {
94
+ return false;
95
+ }
96
+ await updateTransaction(db, clientTxId, {
97
+ retryCount: tx.retryCount + 1,
98
+ state: "queued",
99
+ });
100
+ return true;
101
+ };
102
+ /**
103
+ * Resets sent transactions back to queued (for reconnection)
104
+ */
105
+ export const resetSentToQueued = async (db) => {
106
+ const sentTxs = await getTransactionsByState(db, "sent");
107
+ if (sentTxs.length === 0) {
108
+ return 0;
109
+ }
110
+ const tx = db.transaction(TRANSACTION_STORE, "readwrite");
111
+ const store = tx.objectStore(TRANSACTION_STORE);
112
+ const promises = [];
113
+ for (const sentTx of sentTxs) {
114
+ promises.push(store.put({ ...sentTx, state: "queued" }));
115
+ }
116
+ await Promise.all([...promises, tx.done]);
117
+ return sentTxs.length;
118
+ };
119
+ /**
120
+ * Gets the count of pending transactions
121
+ */
122
+ export const getPendingCount = async (db) => {
123
+ if (!hasTransactionStore(db)) {
124
+ return 0;
125
+ }
126
+ const queued = await db.countFromIndex(TRANSACTION_STORE, "byState", "queued");
127
+ const sent = await db.countFromIndex(TRANSACTION_STORE, "byState", "sent");
128
+ return queued + sent;
129
+ };
130
+ /**
131
+ * Clears all transactions from the outbox
132
+ */
133
+ export const clearOutbox = async (db) => {
134
+ if (!hasTransactionStore(db)) {
135
+ return;
136
+ }
137
+ const tx = db.transaction(TRANSACTION_STORE, "readwrite");
138
+ await tx.objectStore(TRANSACTION_STORE).clear();
139
+ await tx.done;
140
+ };
141
+ //# sourceMappingURL=outbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/stores/outbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ export type { BatchOperation, ModelPersistenceMeta, StorageAdapter, StorageMeta, StorageOptions, } from "@stratasync/client";
2
+ /**
3
+ * Registry info stored in the linear_databases database
4
+ */
5
+ export interface LinearDatabaseInfo {
6
+ /** Workspace database name (e.g. linear_<hash>) */
7
+ name: string;
8
+ /** User ID used in name derivation */
9
+ userId: string;
10
+ /** Client version used in name derivation */
11
+ version: number;
12
+ /** Per-user version used in name derivation */
13
+ userVersion: number;
14
+ /** Schema hash for this database */
15
+ schemaHash: string;
16
+ /** Schema version used as the IndexedDB version */
17
+ schemaVersion: number;
18
+ /** Last update timestamp */
19
+ updatedAt: number;
20
+ }
21
+ /**
22
+ * Partial index entry for lazy hydration tracking
23
+ */
24
+ export interface PartialIndexEntry {
25
+ /** Model name */
26
+ modelName: string;
27
+ /** Indexed key used for hydration */
28
+ indexedKey: string;
29
+ /** Key value used for hydration */
30
+ keyValue: string;
31
+ /** Timestamp of last update */
32
+ updatedAt?: number;
33
+ }
34
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,WAAW,EACX,cAAc,GACf,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iBAAiB;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map