@tanstack/db-sqlite-persistence-core 0.4.4 → 0.4.7
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 +14 -6
- package/dist/cjs/index.cjs +5 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/persisted.cjs +12 -10
- package/dist/cjs/persisted.cjs.map +1 -1
- package/dist/cjs/persisted.d.cts +7 -1
- package/dist/cjs/remote-subset-wire.cjs +100 -73
- package/dist/cjs/remote-subset-wire.cjs.map +1 -1
- package/dist/cjs/remote-subset-wire.d.cts +2 -0
- package/dist/cjs/sqlite-core-adapter.cjs +136 -28
- package/dist/cjs/sqlite-core-adapter.cjs.map +1 -1
- package/dist/cjs/sqlite-value.cjs +51 -0
- package/dist/cjs/sqlite-value.cjs.map +1 -1
- package/dist/cjs/sqlite-value.d.cts +12 -0
- package/dist/esm/index.js +8 -3
- package/dist/esm/persisted.d.ts +7 -1
- package/dist/esm/persisted.js +14 -12
- package/dist/esm/persisted.js.map +1 -1
- package/dist/esm/remote-subset-wire.d.ts +2 -0
- package/dist/esm/remote-subset-wire.js +101 -74
- package/dist/esm/remote-subset-wire.js.map +1 -1
- package/dist/esm/sqlite-core-adapter.js +138 -30
- package/dist/esm/sqlite-core-adapter.js.map +1 -1
- package/dist/esm/sqlite-value.d.ts +12 -0
- package/dist/esm/sqlite-value.js +53 -2
- package/dist/esm/sqlite-value.js.map +1 -1
- package/package.json +4 -3
- package/src/persisted.ts +31 -16
- package/src/remote-subset-wire.ts +149 -79
- package/src/sqlite-core-adapter.ts +221 -34
- package/src/sqlite-value.ts +98 -1
|
@@ -22,10 +22,61 @@ function serializeSQLiteBigInt(value) {
|
|
|
22
22
|
[PERSISTED_VALUE_TAG]: value.toString()
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
+
function sqliteTemporalKind(value) {
|
|
26
|
+
if (value === null || typeof value !== `object`) return;
|
|
27
|
+
const tag = value[Symbol.toStringTag];
|
|
28
|
+
if (tag === `Temporal.Instant` || tag === `Temporal.PlainDate`) return tag;
|
|
29
|
+
return void 0;
|
|
30
|
+
}
|
|
31
|
+
function requireSQLiteTemporalConstructor(kind) {
|
|
32
|
+
const name = kind.slice(`Temporal.`.length);
|
|
33
|
+
const constructor = globalThis.Temporal?.[name];
|
|
34
|
+
if (typeof constructor?.from !== `function` || typeof constructor.prototype.toString !== `function`) {
|
|
35
|
+
throw new errors.InvalidPersistedCollectionConfigError(
|
|
36
|
+
`Missing global ${kind} constructor for SQLite persistence`
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return constructor;
|
|
40
|
+
}
|
|
41
|
+
function reviveSQLiteTemporal(kind, value) {
|
|
42
|
+
return requireSQLiteTemporalConstructor(kind).from(value);
|
|
43
|
+
}
|
|
44
|
+
function serializeSQLiteTemporal(value) {
|
|
45
|
+
if (value === null || typeof value !== `object`) return;
|
|
46
|
+
const prototype = Object.getPrototypeOf(value);
|
|
47
|
+
if (prototype === null || prototype === Object.prototype) return;
|
|
48
|
+
const tag = value[Symbol.toStringTag];
|
|
49
|
+
if (typeof tag !== `string` || !tag.startsWith(`Temporal.`)) return;
|
|
50
|
+
const kind = sqliteTemporalKind(value);
|
|
51
|
+
if (!kind)
|
|
52
|
+
throw new errors.InvalidPersistedCollectionConfigError(
|
|
53
|
+
`Unsupported ${tag} value for SQLite persistence`
|
|
54
|
+
);
|
|
55
|
+
const constructor = requireSQLiteTemporalConstructor(kind);
|
|
56
|
+
let text;
|
|
57
|
+
try {
|
|
58
|
+
text = constructor.prototype.toString.call(value);
|
|
59
|
+
} catch {
|
|
60
|
+
throw new errors.InvalidPersistedCollectionConfigError(
|
|
61
|
+
`Invalid ${kind} value for the registered global constructor`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
const native = constructor.from(text);
|
|
65
|
+
const iso = kind === `Temporal.PlainDate` ? native.withCalendar(`iso8601`) : void 0;
|
|
66
|
+
const order = iso ? `${String(iso.year + 1e6).padStart(7, `0`)}${String(iso.month).padStart(2, `0`)}${String(iso.day).padStart(2, `0`)}` : (native.epochNanoseconds + 10000000000000000000000n).toString().padStart(23, `0`);
|
|
67
|
+
return { [PERSISTED_TYPE_TAG]: kind, [PERSISTED_VALUE_TAG]: text, order };
|
|
68
|
+
}
|
|
69
|
+
function sqliteTemporalIdentity(value) {
|
|
70
|
+
return `${value[PERSISTED_TYPE_TAG]}:${value[PERSISTED_VALUE_TAG]}`;
|
|
71
|
+
}
|
|
25
72
|
exports.PERSISTED_TYPE_TAG = PERSISTED_TYPE_TAG;
|
|
26
73
|
exports.PERSISTED_VALUE_TAG = PERSISTED_VALUE_TAG;
|
|
27
74
|
exports.SQLITE_BIGINT_MAX = SQLITE_BIGINT_MAX;
|
|
28
75
|
exports.SQLITE_BIGINT_MIN = SQLITE_BIGINT_MIN;
|
|
29
76
|
exports.assertSQLiteBigIntInRange = assertSQLiteBigIntInRange;
|
|
77
|
+
exports.reviveSQLiteTemporal = reviveSQLiteTemporal;
|
|
30
78
|
exports.serializeSQLiteBigInt = serializeSQLiteBigInt;
|
|
79
|
+
exports.serializeSQLiteTemporal = serializeSQLiteTemporal;
|
|
80
|
+
exports.sqliteTemporalIdentity = sqliteTemporalIdentity;
|
|
81
|
+
exports.sqliteTemporalKind = sqliteTemporalKind;
|
|
31
82
|
//# sourceMappingURL=sqlite-value.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-value.cjs","sources":["../../src/sqlite-value.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"sqlite-value.cjs","sources":["../../src/sqlite-value.ts"],"sourcesContent":["import {\n InvalidPersistedCollectionConfigError,\n SQLiteBigIntOutOfRangeError,\n} from './errors'\n\nexport const SQLITE_BIGINT_MIN = -9_223_372_036_854_775_808n\nexport const SQLITE_BIGINT_MAX = 9_223_372_036_854_775_807n\nexport const PERSISTED_TYPE_TAG = `__tanstack_db_persisted_type__`\nexport const PERSISTED_VALUE_TAG = `value`\n\nexport type SerializedSQLiteBigInt = {\n [PERSISTED_TYPE_TAG]: `bigint`\n [PERSISTED_VALUE_TAG]: string\n}\n\nexport function assertSQLiteBigIntInRange(value: bigint): bigint {\n if (value < SQLITE_BIGINT_MIN || value > SQLITE_BIGINT_MAX) {\n throw new SQLiteBigIntOutOfRangeError(\n value,\n SQLITE_BIGINT_MIN,\n SQLITE_BIGINT_MAX,\n )\n }\n return value\n}\n\nexport function serializeSQLiteBigInt(value: bigint): SerializedSQLiteBigInt {\n assertSQLiteBigIntInRange(value)\n return {\n [PERSISTED_TYPE_TAG]: `bigint`,\n [PERSISTED_VALUE_TAG]: value.toString(),\n }\n}\n\ntype SQLiteTemporalKind = `Temporal.Instant` | `Temporal.PlainDate`\ntype SQLiteTemporal = {\n epochNanoseconds: bigint\n year: number\n month: number\n day: number\n withCalendar: (calendar: string) => SQLiteTemporal\n}\ntype TemporalConstructor = {\n from: (value: string) => SQLiteTemporal\n prototype: { toString: () => string }\n}\n\nexport type SerializedSQLiteTemporal = {\n [PERSISTED_TYPE_TAG]: SQLiteTemporalKind\n [PERSISTED_VALUE_TAG]: string\n order: string\n}\n\nexport function sqliteTemporalKind(\n value: unknown,\n): SQLiteTemporalKind | undefined {\n if (value === null || typeof value !== `object`) return\n const tag = (value as { [Symbol.toStringTag]?: unknown })[Symbol.toStringTag]\n if (tag === `Temporal.Instant` || tag === `Temporal.PlainDate`) return tag\n return undefined\n}\n\nfunction requireSQLiteTemporalConstructor(\n kind: SQLiteTemporalKind,\n): TemporalConstructor {\n const name = kind.slice(`Temporal.`.length)\n const constructor = (\n globalThis as { Temporal?: Record<string, TemporalConstructor> }\n ).Temporal?.[name]\n if (\n typeof constructor?.from !== `function` ||\n typeof constructor.prototype.toString !== `function`\n ) {\n throw new InvalidPersistedCollectionConfigError(\n `Missing global ${kind} constructor for SQLite persistence`,\n )\n }\n return constructor\n}\n\nexport function reviveSQLiteTemporal(\n kind: SQLiteTemporalKind,\n value: string,\n): unknown {\n return requireSQLiteTemporalConstructor(kind).from(value)\n}\n\n/** Registered prototype methods validate the brand; user toString is ignored. */\nexport function serializeSQLiteTemporal(\n value: unknown,\n): SerializedSQLiteTemporal | undefined {\n if (value === null || typeof value !== `object`) return\n const prototype = Object.getPrototypeOf(value)\n if (prototype === null || prototype === Object.prototype) return\n const tag = (value as { [Symbol.toStringTag]?: unknown })[Symbol.toStringTag]\n if (typeof tag !== `string` || !tag.startsWith(`Temporal.`)) return\n const kind = sqliteTemporalKind(value)\n if (!kind)\n throw new InvalidPersistedCollectionConfigError(\n `Unsupported ${tag} value for SQLite persistence`,\n )\n const constructor = requireSQLiteTemporalConstructor(kind)\n let text: string\n try {\n text = constructor.prototype.toString.call(value)\n } catch {\n throw new InvalidPersistedCollectionConfigError(\n `Invalid ${kind} value for the registered global constructor`,\n )\n }\n const native = constructor.from(text)\n const iso =\n kind === `Temporal.PlainDate` ? native.withCalendar(`iso8601`) : undefined\n // Text keys avoid both floating-point precision loss and SQLite's int64 cap.\n const order = iso\n ? `${String(iso.year + 1_000_000).padStart(7, `0`)}${String(iso.month).padStart(2, `0`)}${String(iso.day).padStart(2, `0`)}`\n : (native.epochNanoseconds + 10_000_000_000_000_000_000_000n)\n .toString()\n .padStart(23, `0`)\n return { [PERSISTED_TYPE_TAG]: kind, [PERSISTED_VALUE_TAG]: text, order }\n}\n\nexport function sqliteTemporalIdentity(\n value: SerializedSQLiteTemporal,\n): string {\n return `${value[PERSISTED_TYPE_TAG]}:${value[PERSISTED_VALUE_TAG]}`\n}\n"],"names":["SQLiteBigIntOutOfRangeError","InvalidPersistedCollectionConfigError"],"mappings":";;;AAKO,MAAM,oBAAoB,CAAC;AAC3B,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAC3B,MAAM,sBAAsB;AAO5B,SAAS,0BAA0B,OAAuB;AAC/D,MAAI,QAAQ,qBAAqB,QAAQ,mBAAmB;AAC1D,UAAM,IAAIA,OAAAA;AAAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AACA,SAAO;AACT;AAEO,SAAS,sBAAsB,OAAuC;AAC3E,4BAA0B,KAAK;AAC/B,SAAO;AAAA,IACL,CAAC,kBAAkB,GAAG;AAAA,IACtB,CAAC,mBAAmB,GAAG,MAAM,SAAA;AAAA,EAAS;AAE1C;AAqBO,SAAS,mBACd,OACgC;AAChC,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU;AACjD,QAAM,MAAO,MAA6C,OAAO,WAAW;AAC5E,MAAI,QAAQ,sBAAsB,QAAQ,qBAAsB,QAAO;AACvE,SAAO;AACT;AAEA,SAAS,iCACP,MACqB;AACrB,QAAM,OAAO,KAAK,MAAM,YAAY,MAAM;AAC1C,QAAM,cACJ,WACA,WAAW,IAAI;AACjB,MACE,OAAO,aAAa,SAAS,cAC7B,OAAO,YAAY,UAAU,aAAa,YAC1C;AACA,UAAM,IAAIC,OAAAA;AAAAA,MACR,kBAAkB,IAAI;AAAA,IAAA;AAAA,EAE1B;AACA,SAAO;AACT;AAEO,SAAS,qBACd,MACA,OACS;AACT,SAAO,iCAAiC,IAAI,EAAE,KAAK,KAAK;AAC1D;AAGO,SAAS,wBACd,OACsC;AACtC,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU;AACjD,QAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,MAAI,cAAc,QAAQ,cAAc,OAAO,UAAW;AAC1D,QAAM,MAAO,MAA6C,OAAO,WAAW;AAC5E,MAAI,OAAO,QAAQ,YAAY,CAAC,IAAI,WAAW,WAAW,EAAG;AAC7D,QAAM,OAAO,mBAAmB,KAAK;AACrC,MAAI,CAAC;AACH,UAAM,IAAIA,OAAAA;AAAAA,MACR,eAAe,GAAG;AAAA,IAAA;AAEtB,QAAM,cAAc,iCAAiC,IAAI;AACzD,MAAI;AACJ,MAAI;AACF,WAAO,YAAY,UAAU,SAAS,KAAK,KAAK;AAAA,EAClD,QAAQ;AACN,UAAM,IAAIA,OAAAA;AAAAA,MACR,WAAW,IAAI;AAAA,IAAA;AAAA,EAEnB;AACA,QAAM,SAAS,YAAY,KAAK,IAAI;AACpC,QAAM,MACJ,SAAS,uBAAuB,OAAO,aAAa,SAAS,IAAI;AAEnE,QAAM,QAAQ,MACV,GAAG,OAAO,IAAI,OAAO,GAAS,EAAE,SAAS,GAAG,GAAG,CAAC,GAAG,OAAO,IAAI,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC,GAAG,OAAO,IAAI,GAAG,EAAE,SAAS,GAAG,GAAG,CAAC,MACvH,OAAO,mBAAmB,0BACxB,WACA,SAAS,IAAI,GAAG;AACvB,SAAO,EAAE,CAAC,kBAAkB,GAAG,MAAM,CAAC,mBAAmB,GAAG,MAAM,MAAA;AACpE;AAEO,SAAS,uBACd,OACQ;AACR,SAAO,GAAG,MAAM,kBAAkB,CAAC,IAAI,MAAM,mBAAmB,CAAC;AACnE;;;;;;;;;;;"}
|
|
@@ -8,3 +8,15 @@ export type SerializedSQLiteBigInt = {
|
|
|
8
8
|
};
|
|
9
9
|
export declare function assertSQLiteBigIntInRange(value: bigint): bigint;
|
|
10
10
|
export declare function serializeSQLiteBigInt(value: bigint): SerializedSQLiteBigInt;
|
|
11
|
+
type SQLiteTemporalKind = `Temporal.Instant` | `Temporal.PlainDate`;
|
|
12
|
+
export type SerializedSQLiteTemporal = {
|
|
13
|
+
[PERSISTED_TYPE_TAG]: SQLiteTemporalKind;
|
|
14
|
+
[PERSISTED_VALUE_TAG]: string;
|
|
15
|
+
order: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function sqliteTemporalKind(value: unknown): SQLiteTemporalKind | undefined;
|
|
18
|
+
export declare function reviveSQLiteTemporal(kind: SQLiteTemporalKind, value: string): unknown;
|
|
19
|
+
/** Registered prototype methods validate the brand; user toString is ignored. */
|
|
20
|
+
export declare function serializeSQLiteTemporal(value: unknown): SerializedSQLiteTemporal | undefined;
|
|
21
|
+
export declare function sqliteTemporalIdentity(value: SerializedSQLiteTemporal): string;
|
|
22
|
+
export {};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { SQLITE_DRIVER_SHARED_LOGICAL_SCHEDULING_KEY, SingleProcessCoordinator, createPersistedTableName, decodePersistedStorageKey, encodePersistedStorageKey, forwardSQLiteDriverSharedLogicalScheduling, persistedCollectionOptions, validatePersistedCollectionCoordinator } from "./persisted.js";
|
|
2
2
|
import { DuplicateRemoteSubsetOwnerError, IndeterminateCommitError, InvalidPersistedCollectionConfigError, InvalidPersistedCollectionCoordinatorError, InvalidPersistedStorageKeyEncodingError, InvalidPersistedStorageKeyError, InvalidPersistenceAdapterError, InvalidSyncConfigError, PersistedCollectionCoreError, PersistedCollectionDurabilityError, PersistenceUnavailableError, RetryableRemoteSubsetAcquisitionError, SQLiteBigIntOutOfRangeError, toPersistedCollectionDurabilityError } from "./errors.js";
|
|
3
3
|
import { DEFAULT_APPLIED_TX_PRUNE_MAX_AGE_SECONDS, DEFAULT_APPLIED_TX_PRUNE_MAX_ROWS, SQLiteCorePersistenceAdapter, createSQLiteCorePersistenceAdapter } from "./sqlite-core-adapter.js";
|
|
4
|
-
import { PERSISTED_TYPE_TAG, PERSISTED_VALUE_TAG, SQLITE_BIGINT_MAX, SQLITE_BIGINT_MIN, assertSQLiteBigIntInRange, serializeSQLiteBigInt } from "./sqlite-value.js";
|
|
5
|
-
import { RemoteSubsetWireValueError, toProcessLocalLoadSubsetOptions, toTransportedLoadSubsetOptions } from "./remote-subset-wire.js";
|
|
4
|
+
import { PERSISTED_TYPE_TAG, PERSISTED_VALUE_TAG, SQLITE_BIGINT_MAX, SQLITE_BIGINT_MIN, assertSQLiteBigIntInRange, reviveSQLiteTemporal, serializeSQLiteBigInt, serializeSQLiteTemporal, sqliteTemporalIdentity, sqliteTemporalKind } from "./sqlite-value.js";
|
|
5
|
+
import { RemoteSubsetWireValueError, toProcessLocalLoadSubsetOptions, toTransportedLoadSubsetOptions, validateRemoteSubsetOptions } from "./remote-subset-wire.js";
|
|
6
6
|
import { safeRandomUUID } from "@tanstack/db";
|
|
7
7
|
export {
|
|
8
8
|
DEFAULT_APPLIED_TX_PRUNE_MAX_AGE_SECONDS,
|
|
@@ -35,11 +35,16 @@ export {
|
|
|
35
35
|
encodePersistedStorageKey,
|
|
36
36
|
forwardSQLiteDriverSharedLogicalScheduling,
|
|
37
37
|
persistedCollectionOptions,
|
|
38
|
+
reviveSQLiteTemporal,
|
|
38
39
|
safeRandomUUID,
|
|
39
40
|
serializeSQLiteBigInt,
|
|
41
|
+
serializeSQLiteTemporal,
|
|
42
|
+
sqliteTemporalIdentity,
|
|
43
|
+
sqliteTemporalKind,
|
|
40
44
|
toPersistedCollectionDurabilityError,
|
|
41
45
|
toProcessLocalLoadSubsetOptions,
|
|
42
46
|
toTransportedLoadSubsetOptions,
|
|
43
|
-
validatePersistedCollectionCoordinator
|
|
47
|
+
validatePersistedCollectionCoordinator,
|
|
48
|
+
validateRemoteSubsetOptions
|
|
44
49
|
};
|
|
45
50
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/persisted.d.ts
CHANGED
|
@@ -358,6 +358,12 @@ export interface PersistedCollectionCoordinator {
|
|
|
358
358
|
*/
|
|
359
359
|
requestEnsurePersistedIndex: (collectionId: string, signature: string, spec: PersistedIndexSpec, scopedAdapter?: HydrationPersistenceAdapter, localEnsureCompleted?: boolean) => Promise<void>;
|
|
360
360
|
requestApplyLocalMutations?: (collectionId: string, mutations: Array<PersistedMutationEnvelope>) => Promise<ApplyLocalMutationsResponse>;
|
|
361
|
+
/**
|
|
362
|
+
* Applies a committed transaction through the supplied adapter when present.
|
|
363
|
+
* Wrappers must forward this leader-local loan: scheduling it again can wait
|
|
364
|
+
* on the hydration that is awaiting this call. Never serialize or retain the
|
|
365
|
+
* loan after the call; ordinary work uses the registered collection adapter.
|
|
366
|
+
*/
|
|
361
367
|
requestApplyCommittedTx: (collectionId: string, tx: PersistedTx, scopedAdapter?: HydrationPersistenceAdapter) => Promise<ApplyCommittedTxResponse>;
|
|
362
368
|
/** The scoped adapter is leader-local and is never serialized to a follower. */
|
|
363
369
|
pullSince?: (collectionId: string, fromRowVersion: number, scopedAdapter?: HydrationPersistenceAdapter) => Promise<PullSinceResponse>;
|
|
@@ -433,7 +439,7 @@ export declare class SingleProcessCoordinator implements PersistedCollectionCoor
|
|
|
433
439
|
registerRemoteSubsetOwner(collectionId: string, owner: RemoteSubsetOwner): () => void;
|
|
434
440
|
requestEnsurePersistedIndex(): Promise<void>;
|
|
435
441
|
setAdapterForCollection(collectionId: string, adapter: PersistenceAdapter): void;
|
|
436
|
-
requestApplyCommittedTx(collectionId: string, tx: PersistedTx): Promise<ApplyCommittedTxResponse>;
|
|
442
|
+
requestApplyCommittedTx(collectionId: string, tx: PersistedTx, scopedAdapter?: HydrationPersistenceAdapter): Promise<ApplyCommittedTxResponse>;
|
|
437
443
|
pullSince(): Promise<PullSinceResponse>;
|
|
438
444
|
}
|
|
439
445
|
export declare function validatePersistedCollectionCoordinator(coordinator: PersistedCollectionCoordinator): void;
|
package/dist/esm/persisted.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { safeRandomUUID, withCollectionConfigFactory, whenSyncAccepted, SyncTransactionAbortedError, getLoadSubsetDemandKey, compileSingleRowExpression, toBooleanPredicate, SYNC_PERSISTENCE_VERSION, SYNC_PERSISTENCE_PROTOCOL, PERSISTED_READINESS, NoPendingSyncTransactionCommitError, NoPendingSyncTransactionWriteError, withAcceptedReceipt } from "@tanstack/db";
|
|
2
2
|
import { InvalidPersistedCollectionConfigError, DuplicateRemoteSubsetOwnerError, toPersistedCollectionDurabilityError, InvalidPersistedStorageKeyEncodingError, InvalidPersistedStorageKeyError, InvalidSyncConfigError, InvalidPersistedCollectionCoordinatorError, PersistedCollectionDurabilityError, InvalidPersistenceAdapterError } from "./errors.js";
|
|
3
|
-
import { serializeSQLiteBigInt } from "./sqlite-value.js";
|
|
4
|
-
import { toTransportedLoadSubsetOptions, toProcessLocalLoadSubsetOptions } from "./remote-subset-wire.js";
|
|
3
|
+
import { serializeSQLiteBigInt, serializeSQLiteTemporal } from "./sqlite-value.js";
|
|
4
|
+
import { toTransportedLoadSubsetOptions, toProcessLocalLoadSubsetOptions, validateRemoteSubsetOptions } from "./remote-subset-wire.js";
|
|
5
5
|
import { reportRemoteSubsetOwnerError, unloadRemoteSubsetOwner } from "./remote-subset-owner.js";
|
|
6
6
|
const SQLITE_DRIVER_SHARED_LOGICAL_SCHEDULING_KEY = /* @__PURE__ */ Symbol.for(
|
|
7
7
|
`tanstack-db.sqlite-driver-supports-shared-logical-scheduling`
|
|
@@ -176,8 +176,8 @@ class SingleProcessCoordinator {
|
|
|
176
176
|
setAdapterForCollection(collectionId, adapter) {
|
|
177
177
|
this.collectionAdapters.set(collectionId, adapter);
|
|
178
178
|
}
|
|
179
|
-
async requestApplyCommittedTx(collectionId, tx) {
|
|
180
|
-
const adapter = this.collectionAdapters.get(collectionId);
|
|
179
|
+
async requestApplyCommittedTx(collectionId, tx, scopedAdapter) {
|
|
180
|
+
const adapter = scopedAdapter ?? this.collectionAdapters.get(collectionId);
|
|
181
181
|
if (!adapter) {
|
|
182
182
|
throw new InvalidPersistedCollectionConfigError(
|
|
183
183
|
`SingleProcessCoordinator has no persistence adapter configured for collection "${collectionId}"`
|
|
@@ -333,6 +333,8 @@ function toStableSerializable(value) {
|
|
|
333
333
|
case `undefined`:
|
|
334
334
|
return void 0;
|
|
335
335
|
}
|
|
336
|
+
const temporal = serializeSQLiteTemporal(value);
|
|
337
|
+
if (temporal) return temporal;
|
|
336
338
|
if (value instanceof Date) {
|
|
337
339
|
return value.toISOString();
|
|
338
340
|
}
|
|
@@ -745,7 +747,6 @@ class PersistedCollectionRuntime {
|
|
|
745
747
|
await this.hydrateSubsetUnsafe(
|
|
746
748
|
baseline,
|
|
747
749
|
{
|
|
748
|
-
requestRemoteEnsure: false,
|
|
749
750
|
lifecycleGeneration,
|
|
750
751
|
bindKeySetEvidence: true
|
|
751
752
|
},
|
|
@@ -828,6 +829,7 @@ class PersistedCollectionRuntime {
|
|
|
828
829
|
const subsetKey = this.getSubsetKey(options);
|
|
829
830
|
const truncateGeneration = this.sourceTruncateGeneration;
|
|
830
831
|
const routeRemoteDemandDuringHydration = this.canRouteRemoteDemandThroughCoordinator();
|
|
832
|
+
if (routeRemoteDemandDuringHydration) validateRemoteSubsetOptions(options);
|
|
831
833
|
this.activeSubsets.set(subsetKey, options);
|
|
832
834
|
const appliedCursor = this.appliedReceiptSequence;
|
|
833
835
|
try {
|
|
@@ -837,7 +839,6 @@ class PersistedCollectionRuntime {
|
|
|
837
839
|
(adapter) => this.hydrateSubsetUnsafe(
|
|
838
840
|
options,
|
|
839
841
|
{
|
|
840
|
-
requestRemoteEnsure: this.mode === `sync-present` && !routeRemoteDemandDuringHydration,
|
|
841
842
|
lifecycleGeneration,
|
|
842
843
|
requestLocalLoadFailure: true,
|
|
843
844
|
rejectBufferedReplayFailure: true
|
|
@@ -853,6 +854,9 @@ class PersistedCollectionRuntime {
|
|
|
853
854
|
});
|
|
854
855
|
if (lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
855
856
|
await this.waitForAppliedReceiptsAfter(appliedCursor);
|
|
857
|
+
if (!routeRemoteDemandDuringHydration && this.canRouteRemoteDemandThroughCoordinator()) {
|
|
858
|
+
validateRemoteSubsetOptions(options);
|
|
859
|
+
}
|
|
856
860
|
} catch (error) {
|
|
857
861
|
if (this.activeSubsets.get(subsetKey) === options) {
|
|
858
862
|
this.activeSubsets.delete(subsetKey);
|
|
@@ -962,7 +966,6 @@ class PersistedCollectionRuntime {
|
|
|
962
966
|
(adapter) => this.hydrateSubsetUnsafe(
|
|
963
967
|
options,
|
|
964
968
|
{
|
|
965
|
-
requestRemoteEnsure: false,
|
|
966
969
|
lifecycleGeneration,
|
|
967
970
|
rejectBufferedReplayFailure: true
|
|
968
971
|
},
|
|
@@ -1215,9 +1218,6 @@ class PersistedCollectionRuntime {
|
|
|
1215
1218
|
if (config.lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
1216
1219
|
replayFailure = await this.flushQueuedHydrationTransactionsUnsafe(adapter);
|
|
1217
1220
|
if (config.lifecycleGeneration !== this.lifecycleGeneration) return;
|
|
1218
|
-
if (config.requestRemoteEnsure && !replayFailure) {
|
|
1219
|
-
this.queueRemoteSubsetEnsure(options);
|
|
1220
|
-
}
|
|
1221
1221
|
} catch (error) {
|
|
1222
1222
|
if (config.requestLocalLoadFailure && !rowsLoaded) {
|
|
1223
1223
|
this.hydratingGeneration = config.lifecycleGeneration;
|
|
@@ -1810,6 +1810,7 @@ class PersistedCollectionRuntime {
|
|
|
1810
1810
|
}
|
|
1811
1811
|
const subsetKey = this.getSubsetKey(options);
|
|
1812
1812
|
if (this.activeSubsets.get(subsetKey) !== options) return;
|
|
1813
|
+
validateRemoteSubsetOptions(options);
|
|
1813
1814
|
this.pendingRemoteSubsetEnsures.set(subsetKey, options);
|
|
1814
1815
|
void this.flushPendingRemoteSubsetEnsures();
|
|
1815
1816
|
}
|
|
@@ -2212,8 +2213,8 @@ class PersistedCollectionRuntime {
|
|
|
2212
2213
|
await this.requestCoordinatorPersistedIndex(indexMetadata, completedLocally);
|
|
2213
2214
|
}
|
|
2214
2215
|
async ensureLocalPersistedIndex(indexMetadata, adapter) {
|
|
2215
|
-
const spec = this.buildPersistedIndexSpec(indexMetadata);
|
|
2216
2216
|
try {
|
|
2217
|
+
const spec = this.buildPersistedIndexSpec(indexMetadata);
|
|
2217
2218
|
await adapter.ensureIndex(
|
|
2218
2219
|
this.collectionId,
|
|
2219
2220
|
indexMetadata.signature,
|
|
@@ -2226,8 +2227,8 @@ class PersistedCollectionRuntime {
|
|
|
2226
2227
|
}
|
|
2227
2228
|
}
|
|
2228
2229
|
async requestCoordinatorPersistedIndex(indexMetadata, completedLocally) {
|
|
2229
|
-
const spec = this.buildPersistedIndexSpec(indexMetadata);
|
|
2230
2230
|
try {
|
|
2231
|
+
const spec = this.buildPersistedIndexSpec(indexMetadata);
|
|
2231
2232
|
await this.persistence.coordinator.requestEnsurePersistedIndex(
|
|
2232
2233
|
this.collectionId,
|
|
2233
2234
|
indexMetadata.signature,
|
|
@@ -2835,6 +2836,7 @@ function createWrappedSyncConfig(sourceSyncConfig, runtime, persistedReadiness)
|
|
|
2835
2836
|
settleRuntimeTransaction(openTransaction, applied2);
|
|
2836
2837
|
return visibleAfterDurable(openTransaction, applied2);
|
|
2837
2838
|
}
|
|
2839
|
+
openTransaction.hydrationSequence = void 0;
|
|
2838
2840
|
let applied;
|
|
2839
2841
|
try {
|
|
2840
2842
|
applied = runtime.applyHydrationBufferedTransaction(transaction);
|