@tanstack/electron-db-sqlite-persistence 0.2.9 → 0.2.11
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 +9 -1
- package/dist/cjs/main.cjs +118 -17
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/protocol.cjs +1 -1
- package/dist/cjs/protocol.cjs.map +1 -1
- package/dist/cjs/protocol.d.cts +53 -5
- package/dist/cjs/renderer.cjs +176 -48
- package/dist/cjs/renderer.cjs.map +1 -1
- package/dist/cjs/renderer.d.cts +2 -0
- package/dist/esm/main.js +119 -18
- package/dist/esm/main.js.map +1 -1
- package/dist/esm/protocol.d.ts +53 -5
- package/dist/esm/protocol.js +1 -1
- package/dist/esm/protocol.js.map +1 -1
- package/dist/esm/renderer.d.ts +2 -0
- package/dist/esm/renderer.js +177 -49
- package/dist/esm/renderer.js.map +1 -1
- package/package.json +2 -2
- package/src/main.ts +141 -17
- package/src/protocol.ts +40 -5
- package/src/renderer.ts +229 -49
- package/dist/cjs/errors.d.cts +0 -33
- package/dist/esm/errors.d.ts +0 -33
- package/src/errors.ts +0 -110
package/dist/cjs/renderer.cjs
CHANGED
|
@@ -54,13 +54,24 @@ function createSerializableLoadSubsetOptions(subsetOptions) {
|
|
|
54
54
|
function createRendererRequestExecutor(options) {
|
|
55
55
|
const channel = options.channel ?? protocol.DEFAULT_ELECTRON_PERSISTENCE_CHANNEL;
|
|
56
56
|
const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
57
|
-
return async (method,
|
|
57
|
+
return async (method, target, payload, resolution) => {
|
|
58
|
+
const storageTarget = typeof target === `string` ? void 0 : target;
|
|
59
|
+
const collectionId = storageTarget ? dbSqlitePersistenceCore.resolvePersistedStorageTarget(storageTarget).collectionId : target;
|
|
60
|
+
const isGenerationRequest = method === `claimCacheGeneration` || method === `rotateCacheGeneration` || method === `renewCacheGenerationClaim` || method === `releaseCacheGenerationClaim`;
|
|
61
|
+
const managedTarget = storageTarget?.kind === `managed`;
|
|
62
|
+
const logicalCollectionId = resolution?.logicalCollectionId ?? (managedTarget ? options.claimCollections.get(storageTarget.claimId) : isGenerationRequest ? collectionId : void 0);
|
|
63
|
+
if ((managedTarget || isGenerationRequest) && !logicalCollectionId) {
|
|
64
|
+
throw new dbSqlitePersistenceCore.InvalidPersistedCollectionConfigError(
|
|
65
|
+
`Electron managed cache request requires a known logical Collection ID`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
58
68
|
const request = {
|
|
59
69
|
v: protocol.ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
60
70
|
requestId: createRequestId(),
|
|
61
71
|
collectionId,
|
|
72
|
+
storageTarget,
|
|
62
73
|
method,
|
|
63
|
-
resolution,
|
|
74
|
+
resolution: managedTarget || isGenerationRequest ? { ...resolution, mode: `sync-present`, logicalCollectionId } : resolution,
|
|
64
75
|
payload
|
|
65
76
|
};
|
|
66
77
|
const response = await withTimeout(
|
|
@@ -87,105 +98,219 @@ function createRendererRequestExecutor(options) {
|
|
|
87
98
|
return response.result;
|
|
88
99
|
};
|
|
89
100
|
}
|
|
90
|
-
function createResolvedRendererAdapter(executeRequest, resolution) {
|
|
91
|
-
|
|
92
|
-
loadSubset: async (
|
|
101
|
+
function createResolvedRendererAdapter(executeRequest, claimCollections, managedCacheGenerations, resolution) {
|
|
102
|
+
const adapter = {
|
|
103
|
+
loadSubset: async (target, subsetOptions, ctx) => {
|
|
104
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
105
|
+
target,
|
|
106
|
+
ctx?.cacheGenerationClaimId
|
|
107
|
+
);
|
|
93
108
|
const result = await executeRequest(
|
|
94
109
|
`loadSubset`,
|
|
95
|
-
|
|
110
|
+
target,
|
|
96
111
|
{
|
|
97
112
|
options: createSerializableLoadSubsetOptions(subsetOptions),
|
|
98
|
-
ctx
|
|
113
|
+
ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
|
|
99
114
|
},
|
|
100
115
|
resolution
|
|
101
116
|
);
|
|
102
117
|
return result;
|
|
103
118
|
},
|
|
104
|
-
loadResumeSnapshot: async (
|
|
119
|
+
loadResumeSnapshot: async (target, ctx) => {
|
|
120
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
121
|
+
target,
|
|
122
|
+
ctx?.cacheGenerationClaimId
|
|
123
|
+
);
|
|
105
124
|
return executeRequest(
|
|
106
125
|
`loadResumeSnapshot`,
|
|
107
|
-
|
|
108
|
-
{ ctx },
|
|
126
|
+
target,
|
|
127
|
+
{ ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },
|
|
109
128
|
resolution
|
|
110
129
|
);
|
|
111
130
|
},
|
|
112
|
-
applyCommittedTx: async (
|
|
131
|
+
applyCommittedTx: async (target, tx) => {
|
|
132
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
133
|
+
target,
|
|
134
|
+
tx.cacheGenerationClaimId
|
|
135
|
+
);
|
|
113
136
|
await executeRequest(
|
|
114
137
|
`applyCommittedTx`,
|
|
115
|
-
|
|
138
|
+
target,
|
|
116
139
|
{
|
|
117
|
-
tx
|
|
140
|
+
tx: { ...tx, cacheGenerationClaimId: access.claimId }
|
|
118
141
|
},
|
|
119
142
|
resolution
|
|
120
143
|
);
|
|
121
144
|
},
|
|
122
|
-
reconcileCommittedTx: async (
|
|
145
|
+
reconcileCommittedTx: async (target, tx, anchor) => {
|
|
146
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
147
|
+
target,
|
|
148
|
+
tx.cacheGenerationClaimId
|
|
149
|
+
);
|
|
123
150
|
return executeRequest(
|
|
124
151
|
`reconcileCommittedTx`,
|
|
125
|
-
|
|
126
|
-
{ tx, anchor },
|
|
152
|
+
target,
|
|
153
|
+
{ tx: { ...tx, cacheGenerationClaimId: access.claimId }, anchor },
|
|
127
154
|
resolution
|
|
128
155
|
);
|
|
129
156
|
},
|
|
130
|
-
loadCollectionMetadata: async (
|
|
157
|
+
loadCollectionMetadata: async (target, ctx) => {
|
|
158
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
159
|
+
target,
|
|
160
|
+
ctx?.cacheGenerationClaimId
|
|
161
|
+
);
|
|
131
162
|
return executeRequest(
|
|
132
163
|
`loadCollectionMetadata`,
|
|
133
|
-
|
|
134
|
-
{},
|
|
164
|
+
target,
|
|
165
|
+
{ ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },
|
|
135
166
|
resolution
|
|
136
167
|
);
|
|
137
168
|
},
|
|
138
|
-
scanRows: async (
|
|
169
|
+
scanRows: async (target, options, ctx) => {
|
|
170
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
171
|
+
target,
|
|
172
|
+
ctx?.cacheGenerationClaimId
|
|
173
|
+
);
|
|
139
174
|
const result = await executeRequest(
|
|
140
175
|
`scanRows`,
|
|
141
|
-
|
|
142
|
-
{ options },
|
|
176
|
+
target,
|
|
177
|
+
{ options, ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },
|
|
143
178
|
resolution
|
|
144
179
|
);
|
|
145
180
|
return result;
|
|
146
181
|
},
|
|
147
|
-
ensureIndex: async (
|
|
182
|
+
ensureIndex: async (target, signature, spec, ctx) => {
|
|
183
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
184
|
+
target,
|
|
185
|
+
ctx?.cacheGenerationClaimId
|
|
186
|
+
);
|
|
148
187
|
await executeRequest(
|
|
149
188
|
`ensureIndex`,
|
|
150
|
-
|
|
189
|
+
target,
|
|
151
190
|
{
|
|
152
191
|
signature,
|
|
153
|
-
spec
|
|
192
|
+
spec,
|
|
193
|
+
ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
|
|
154
194
|
},
|
|
155
195
|
resolution
|
|
156
196
|
);
|
|
157
197
|
},
|
|
158
|
-
markIndexRemoved: async (
|
|
198
|
+
markIndexRemoved: async (target, signature, ctx) => {
|
|
199
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
200
|
+
target,
|
|
201
|
+
ctx?.cacheGenerationClaimId
|
|
202
|
+
);
|
|
159
203
|
await executeRequest(
|
|
160
204
|
`markIndexRemoved`,
|
|
161
|
-
|
|
205
|
+
target,
|
|
162
206
|
{
|
|
163
|
-
signature
|
|
207
|
+
signature,
|
|
208
|
+
ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
|
|
164
209
|
},
|
|
165
210
|
resolution
|
|
166
211
|
);
|
|
167
212
|
},
|
|
168
|
-
pullSince: async (
|
|
213
|
+
pullSince: async (target, fromRowVersion, ctx) => {
|
|
214
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
215
|
+
target,
|
|
216
|
+
ctx?.cacheGenerationClaimId
|
|
217
|
+
);
|
|
169
218
|
const result = await executeRequest(
|
|
170
219
|
`pullSince`,
|
|
171
|
-
|
|
220
|
+
target,
|
|
172
221
|
{
|
|
173
|
-
fromRowVersion
|
|
222
|
+
fromRowVersion,
|
|
223
|
+
ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
|
|
174
224
|
},
|
|
175
225
|
resolution
|
|
176
226
|
);
|
|
177
227
|
return result;
|
|
178
228
|
},
|
|
179
|
-
getStreamPosition: async (
|
|
180
|
-
|
|
229
|
+
getStreamPosition: async (target, ctx) => {
|
|
230
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
231
|
+
target,
|
|
232
|
+
ctx?.cacheGenerationClaimId
|
|
233
|
+
);
|
|
234
|
+
return executeRequest(
|
|
235
|
+
`getStreamPosition`,
|
|
236
|
+
target,
|
|
237
|
+
{ ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },
|
|
238
|
+
resolution
|
|
239
|
+
);
|
|
181
240
|
},
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
241
|
+
claimCacheGeneration: async (collectionId) => {
|
|
242
|
+
const claim = await executeRequest(
|
|
243
|
+
`claimCacheGeneration`,
|
|
244
|
+
collectionId,
|
|
245
|
+
{},
|
|
246
|
+
resolution
|
|
247
|
+
);
|
|
248
|
+
claimCollections.set(claim.claimId, collectionId);
|
|
249
|
+
return claim;
|
|
250
|
+
},
|
|
251
|
+
rotateCacheGeneration: async (collectionId, claimId, resetMetadata, expectedStorageCollectionId) => {
|
|
252
|
+
const claim = await executeRequest(
|
|
253
|
+
`rotateCacheGeneration`,
|
|
254
|
+
collectionId,
|
|
255
|
+
{ claimId, resetMetadata, expectedStorageCollectionId },
|
|
256
|
+
resolution
|
|
257
|
+
);
|
|
258
|
+
claimCollections.delete(claimId);
|
|
259
|
+
claimCollections.set(claim.claimId, collectionId);
|
|
260
|
+
return claim;
|
|
261
|
+
},
|
|
262
|
+
renewCacheGenerationClaim: (storageCollectionId, claimId) => {
|
|
263
|
+
const collectionId = claimCollections.get(claimId);
|
|
264
|
+
if (!collectionId) {
|
|
265
|
+
throw new dbSqlitePersistenceCore.InvalidPersistedCollectionConfigError(
|
|
266
|
+
`Unknown electron persisted cache claim "${claimId}"`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
return executeRequest(
|
|
270
|
+
`renewCacheGenerationClaim`,
|
|
271
|
+
collectionId,
|
|
272
|
+
{ storageCollectionId, claimId },
|
|
273
|
+
resolution
|
|
274
|
+
);
|
|
275
|
+
},
|
|
276
|
+
releaseCacheGenerationClaim: async (claimId) => {
|
|
277
|
+
const collectionId = claimCollections.get(claimId);
|
|
278
|
+
if (!collectionId) {
|
|
279
|
+
throw new dbSqlitePersistenceCore.InvalidPersistedCollectionConfigError(
|
|
280
|
+
`Unknown electron persisted cache claim "${claimId}"`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
await executeRequest(
|
|
284
|
+
`releaseCacheGenerationClaim`,
|
|
285
|
+
collectionId,
|
|
286
|
+
{ claimId },
|
|
287
|
+
resolution
|
|
288
|
+
);
|
|
289
|
+
claimCollections.delete(claimId);
|
|
290
|
+
},
|
|
291
|
+
reserveLeadershipTerm: async (target, observedTerm, ctx) => {
|
|
292
|
+
const access = dbSqlitePersistenceCore.resolvePersistedStorageTarget(
|
|
293
|
+
target,
|
|
294
|
+
ctx?.cacheGenerationClaimId
|
|
295
|
+
);
|
|
296
|
+
return executeRequest(
|
|
297
|
+
`reserveLeadershipTerm`,
|
|
298
|
+
target,
|
|
299
|
+
{
|
|
300
|
+
observedTerm,
|
|
301
|
+
ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
|
|
302
|
+
},
|
|
303
|
+
resolution
|
|
304
|
+
);
|
|
305
|
+
}
|
|
188
306
|
};
|
|
307
|
+
if (!managedCacheGenerations) {
|
|
308
|
+
adapter.claimCacheGeneration = void 0;
|
|
309
|
+
adapter.rotateCacheGeneration = void 0;
|
|
310
|
+
adapter.renewCacheGenerationClaim = void 0;
|
|
311
|
+
adapter.releaseCacheGenerationClaim = void 0;
|
|
312
|
+
}
|
|
313
|
+
return adapter;
|
|
189
314
|
}
|
|
190
315
|
function resolveInvoke(options) {
|
|
191
316
|
if (options.invoke) {
|
|
@@ -201,28 +326,31 @@ function resolveInvoke(options) {
|
|
|
201
326
|
function createElectronSQLitePersistence(options) {
|
|
202
327
|
const invoke = resolveInvoke(options);
|
|
203
328
|
const coordinator = options.coordinator ?? new dbSqlitePersistenceCore.SingleProcessCoordinator();
|
|
329
|
+
const claimCollections = /* @__PURE__ */ new Map();
|
|
204
330
|
const executeRequest = createRendererRequestExecutor({
|
|
205
331
|
invoke,
|
|
206
332
|
channel: options.channel,
|
|
207
|
-
timeoutMs: options.timeoutMs
|
|
333
|
+
timeoutMs: options.timeoutMs,
|
|
334
|
+
claimCollections
|
|
208
335
|
});
|
|
209
336
|
const adapterCache = /* @__PURE__ */ new Map();
|
|
210
|
-
const getAdapterForCollection = (mode, schemaVersion) => {
|
|
211
|
-
const
|
|
212
|
-
const cacheKey = `mode:${mode}|${schemaVersionKey}`;
|
|
337
|
+
const getAdapterForCollection = (collectionId, mode, schemaVersion) => {
|
|
338
|
+
const cacheKey = JSON.stringify([collectionId, mode, schemaVersion]);
|
|
213
339
|
const cachedAdapter = adapterCache.get(cacheKey);
|
|
214
340
|
if (cachedAdapter) {
|
|
215
341
|
return cachedAdapter;
|
|
216
342
|
}
|
|
217
|
-
const adapter = createResolvedRendererAdapter(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
343
|
+
const adapter = createResolvedRendererAdapter(
|
|
344
|
+
executeRequest,
|
|
345
|
+
claimCollections,
|
|
346
|
+
options.managedCacheGenerations ?? true,
|
|
347
|
+
{ mode, schemaVersion, logicalCollectionId: collectionId }
|
|
348
|
+
);
|
|
221
349
|
adapterCache.set(cacheKey, adapter);
|
|
222
350
|
return adapter;
|
|
223
351
|
};
|
|
224
352
|
const createCollectionPersistence = (collectionId, mode, schemaVersion) => {
|
|
225
|
-
const adapter = getAdapterForCollection(mode, schemaVersion);
|
|
353
|
+
const adapter = getAdapterForCollection(collectionId, mode, schemaVersion);
|
|
226
354
|
if (coordinator instanceof electronCoordinator.ElectronCollectionCoordinator) {
|
|
227
355
|
if (collectionId === void 0) {
|
|
228
356
|
coordinator.setAdapter(adapter);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.cjs","sources":["../../src/renderer.ts"],"sourcesContent":["import {\n InvalidPersistedCollectionConfigError,\n SingleProcessCoordinator,\n} from '@tanstack/db-sqlite-persistence-core'\nimport { ElectronCollectionCoordinator } from './electron-coordinator'\nimport {\n DEFAULT_ELECTRON_PERSISTENCE_CHANNEL,\n ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n} from './protocol'\nimport type {\n CommittedTxAnchor,\n PersistedCollectionCoordinator,\n PersistedCollectionMode,\n PersistedCollectionPersistence,\n PersistedIndexSpec,\n PersistedTx,\n ReconciledCommittedTx,\n SQLitePullSinceResult,\n} from '@tanstack/db-sqlite-persistence-core'\nimport type {\n ElectronPersistedKey,\n ElectronPersistedRow,\n ElectronPersistenceInvoke,\n ElectronPersistenceMethod,\n ElectronPersistencePayloadMap,\n ElectronPersistenceRequest,\n ElectronPersistenceRequestEnvelope,\n ElectronPersistenceResolution,\n ElectronPersistenceResponseEnvelope,\n ElectronPersistenceResultMap,\n} from './protocol'\nimport type { LoadSubsetOptions } from '@tanstack/db'\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 5_000\nlet nextRequestId = 1\n\nfunction createRequestId(): string {\n const requestId = nextRequestId\n nextRequestId++\n return `electron-persistence-${requestId}`\n}\n\nfunction withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n timeoutMessage: string,\n): Promise<T> {\n if (timeoutMs <= 0) {\n return promise\n }\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new InvalidPersistedCollectionConfigError(timeoutMessage))\n }, timeoutMs)\n\n promise.then(\n (value) => {\n clearTimeout(timer)\n resolve(value)\n },\n (error: unknown) => {\n clearTimeout(timer)\n reject(error)\n },\n )\n })\n}\n\nfunction assertValidResponse(\n response: ElectronPersistenceResponseEnvelope,\n request: ElectronPersistenceRequestEnvelope,\n): void {\n if (response.v !== ELECTRON_PERSISTENCE_PROTOCOL_VERSION) {\n throw new InvalidPersistedCollectionConfigError(\n `Unexpected electron persistence protocol version \"${response.v}\" in response`,\n )\n }\n\n if (response.requestId !== request.requestId) {\n throw new InvalidPersistedCollectionConfigError(\n `Mismatched electron persistence response request id. Expected \"${request.requestId}\", received \"${response.requestId}\"`,\n )\n }\n\n if (response.method !== request.method) {\n throw new InvalidPersistedCollectionConfigError(\n `Mismatched electron persistence response method. Expected \"${request.method}\", received \"${response.method}\"`,\n )\n }\n}\n\nfunction createSerializableLoadSubsetOptions(\n subsetOptions: LoadSubsetOptions,\n): LoadSubsetOptions {\n const { subscription: _subscription, ...serializableOptions } = subsetOptions\n return serializableOptions\n}\n\ntype RendererRequestExecutor = <TMethod extends ElectronPersistenceMethod>(\n method: TMethod,\n collectionId: string,\n payload: ElectronPersistencePayloadMap[TMethod],\n resolution?: ElectronPersistenceResolution,\n) => Promise<ElectronPersistenceResultMap[TMethod]>\n\nfunction createRendererRequestExecutor(options: {\n invoke: ElectronPersistenceInvoke\n channel?: string\n timeoutMs?: number\n}): RendererRequestExecutor {\n const channel = options.channel ?? DEFAULT_ELECTRON_PERSISTENCE_CHANNEL\n const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS\n\n return async <TMethod extends ElectronPersistenceMethod>(\n method: TMethod,\n collectionId: string,\n payload: ElectronPersistencePayloadMap[TMethod],\n resolution?: ElectronPersistenceResolution,\n ) => {\n const request = {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: createRequestId(),\n collectionId,\n method,\n resolution,\n payload,\n } as ElectronPersistenceRequest\n\n const response = await withTimeout(\n options.invoke(channel, request),\n timeoutMs,\n `Electron persistence request timed out (method=${method}, collection=${collectionId}, timeoutMs=${timeoutMs})`,\n )\n assertValidResponse(response, request)\n\n if (!response.ok) {\n const remoteError = new InvalidPersistedCollectionConfigError(\n `${response.error.name}: ${response.error.message}`,\n )\n if (typeof response.error.stack === `string`) {\n remoteError.stack = response.error.stack\n }\n if (\n typeof response.error.code === `string` ||\n typeof response.error.code === `number`\n ) {\n ;(remoteError as Error & { code?: string | number }).code =\n response.error.code\n }\n if (response.error.path !== undefined) {\n ;(\n remoteError as Error & {\n path?: string | ReadonlyArray<string | number>\n }\n ).path = response.error.path\n }\n throw remoteError\n }\n\n return response.result as ElectronPersistenceResultMap[TMethod]\n }\n}\n\ntype ElectronRendererResolvedAdapter =\n PersistedCollectionPersistence[`adapter`] & {\n loadCollectionMetadata: (\n collectionId: string,\n ) => Promise<Array<{ key: string; value: unknown }>>\n scanRows: (\n collectionId: string,\n options?: { metadataOnly?: boolean },\n ) => Promise<\n Array<{\n key: string | number\n value: Record<string, unknown>\n metadata?: unknown\n }>\n >\n pullSince: (\n collectionId: string,\n fromRowVersion: number,\n ) => Promise<SQLitePullSinceResult<string | number>>\n getStreamPosition: (collectionId: string) => Promise<{\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }>\n reserveLeadershipTerm: (\n collectionId: string,\n observedTerm: number,\n ) => Promise<{\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }>\n }\n\nfunction createResolvedRendererAdapter(\n executeRequest: RendererRequestExecutor,\n resolution?: ElectronPersistenceResolution,\n): ElectronRendererResolvedAdapter {\n return {\n loadSubset: async (\n collectionId: string,\n subsetOptions: LoadSubsetOptions,\n ctx?: { requiredIndexSignatures?: ReadonlyArray<string> },\n ) => {\n const result = await executeRequest(\n `loadSubset`,\n collectionId,\n {\n options: createSerializableLoadSubsetOptions(subsetOptions),\n ctx,\n },\n resolution,\n )\n\n return result as Array<{\n key: string | number\n value: Record<string, unknown>\n }>\n },\n loadResumeSnapshot: async (\n collectionId: string,\n ctx?: {\n requiredIndexSignatures?: ReadonlyArray<string>\n includeRows?: boolean\n },\n ) => {\n return executeRequest(\n `loadResumeSnapshot`,\n collectionId,\n { ctx },\n resolution,\n )\n },\n applyCommittedTx: async (\n collectionId: string,\n tx: PersistedTx<Record<string, unknown>, string | number>,\n ): Promise<void> => {\n await executeRequest(\n `applyCommittedTx`,\n collectionId,\n {\n tx: tx as PersistedTx<ElectronPersistedRow, ElectronPersistedKey>,\n },\n resolution,\n )\n },\n reconcileCommittedTx: async (\n collectionId: string,\n tx: PersistedTx<Record<string, unknown>, string | number>,\n anchor: CommittedTxAnchor,\n ): Promise<ReconciledCommittedTx> => {\n return executeRequest(\n `reconcileCommittedTx`,\n collectionId,\n { tx, anchor },\n resolution,\n )\n },\n loadCollectionMetadata: async (\n collectionId: string,\n ): Promise<Array<{ key: string; value: unknown }>> => {\n return executeRequest(\n `loadCollectionMetadata`,\n collectionId,\n {},\n resolution,\n )\n },\n scanRows: async (\n collectionId: string,\n options?: { metadataOnly?: boolean },\n ): Promise<\n Array<{\n key: string | number\n value: Record<string, unknown>\n metadata?: unknown\n }>\n > => {\n const result = await executeRequest(\n `scanRows`,\n collectionId,\n { options },\n resolution,\n )\n return result as Array<{\n key: string | number\n value: Record<string, unknown>\n metadata?: unknown\n }>\n },\n ensureIndex: async (\n collectionId: string,\n signature: string,\n spec: PersistedIndexSpec,\n ): Promise<void> => {\n await executeRequest(\n `ensureIndex`,\n collectionId,\n {\n signature,\n spec,\n },\n resolution,\n )\n },\n markIndexRemoved: async (\n collectionId: string,\n signature: string,\n ): Promise<void> => {\n await executeRequest(\n `markIndexRemoved`,\n collectionId,\n {\n signature,\n },\n resolution,\n )\n },\n pullSince: async (\n collectionId: string,\n fromRowVersion: number,\n ): Promise<SQLitePullSinceResult<string | number>> => {\n const result = await executeRequest(\n `pullSince`,\n collectionId,\n {\n fromRowVersion,\n },\n resolution,\n )\n return result as SQLitePullSinceResult<string | number>\n },\n getStreamPosition: async (\n collectionId: string,\n ): Promise<{\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }> => {\n return executeRequest(`getStreamPosition`, collectionId, {}, resolution)\n },\n reserveLeadershipTerm: async (collectionId, observedTerm) =>\n executeRequest(\n `reserveLeadershipTerm`,\n collectionId,\n { observedTerm },\n resolution,\n ),\n }\n}\n\nexport type ElectronIpcRendererLike = {\n invoke: (\n channel: string,\n request: ElectronPersistenceRequestEnvelope,\n ) => Promise<ElectronPersistenceResponseEnvelope>\n}\n\nexport type ElectronSQLitePersistenceOptions = {\n invoke?: ElectronPersistenceInvoke\n ipcRenderer?: ElectronIpcRendererLike\n channel?: string\n timeoutMs?: number\n coordinator?: PersistedCollectionCoordinator\n}\n\nfunction resolveInvoke(\n options: ElectronSQLitePersistenceOptions,\n): ElectronPersistenceInvoke {\n if (options.invoke) {\n return options.invoke\n }\n\n if (options.ipcRenderer) {\n return (channel, request) => options.ipcRenderer!.invoke(channel, request)\n }\n\n throw new InvalidPersistedCollectionConfigError(\n `Electron renderer persistence requires either invoke or ipcRenderer`,\n )\n}\n\nexport function createElectronSQLitePersistence(\n options: ElectronSQLitePersistenceOptions,\n): PersistedCollectionPersistence {\n const invoke = resolveInvoke(options)\n const coordinator = options.coordinator ?? new SingleProcessCoordinator()\n const executeRequest = createRendererRequestExecutor({\n invoke,\n channel: options.channel,\n timeoutMs: options.timeoutMs,\n })\n const adapterCache = new Map<string, ElectronRendererResolvedAdapter>()\n\n const getAdapterForCollection = (\n mode: PersistedCollectionMode,\n schemaVersion: number | undefined,\n ) => {\n const schemaVersionKey =\n schemaVersion === undefined ? `schema:default` : `schema:${schemaVersion}`\n const cacheKey = `mode:${mode}|${schemaVersionKey}`\n const cachedAdapter = adapterCache.get(cacheKey)\n if (cachedAdapter) {\n return cachedAdapter\n }\n\n const adapter = createResolvedRendererAdapter(executeRequest, {\n mode,\n schemaVersion,\n })\n adapterCache.set(cacheKey, adapter)\n return adapter\n }\n\n const createCollectionPersistence = (\n collectionId: string | undefined,\n mode: PersistedCollectionMode,\n schemaVersion: number | undefined,\n ): PersistedCollectionPersistence => {\n const adapter = getAdapterForCollection(mode, schemaVersion)\n if (coordinator instanceof ElectronCollectionCoordinator) {\n if (collectionId === undefined) {\n coordinator.setAdapter(adapter)\n } else {\n coordinator.setAdapterForCollection(collectionId, adapter)\n }\n }\n return { adapter, coordinator }\n }\n\n const defaultPersistence = createCollectionPersistence(\n undefined,\n `sync-absent`,\n undefined,\n )\n if (coordinator instanceof ElectronCollectionCoordinator) {\n coordinator.setAdapter(defaultPersistence.adapter)\n }\n\n return {\n ...defaultPersistence,\n resolvePersistenceForCollection: ({ collectionId, mode, schemaVersion }) =>\n createCollectionPersistence(collectionId, mode, schemaVersion),\n // Backward compatible fallback for older callers.\n resolvePersistenceForMode: (mode) =>\n createCollectionPersistence(undefined, mode, undefined),\n }\n}\n"],"names":["InvalidPersistedCollectionConfigError","ELECTRON_PERSISTENCE_PROTOCOL_VERSION","DEFAULT_ELECTRON_PERSISTENCE_CHANNEL","SingleProcessCoordinator","ElectronCollectionCoordinator"],"mappings":";;;;;AAiCA,MAAM,6BAA6B;AACnC,IAAI,gBAAgB;AAEpB,SAAS,kBAA0B;AACjC,QAAM,YAAY;AAClB;AACA,SAAO,wBAAwB,SAAS;AAC1C;AAEA,SAAS,YACP,SACA,WACA,gBACY;AACZ,MAAI,aAAa,GAAG;AAClB,WAAO;AAAA,EACT;AAEA,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,UAAM,QAAQ,WAAW,MAAM;AAC7B,aAAO,IAAIA,8DAAsC,cAAc,CAAC;AAAA,IAClE,GAAG,SAAS;AAEZ,YAAQ;AAAA,MACN,CAAC,UAAU;AACT,qBAAa,KAAK;AAClB,gBAAQ,KAAK;AAAA,MACf;AAAA,MACA,CAAC,UAAmB;AAClB,qBAAa,KAAK;AAClB,eAAO,KAAK;AAAA,MACd;AAAA,IAAA;AAAA,EAEJ,CAAC;AACH;AAEA,SAAS,oBACP,UACA,SACM;AACN,MAAI,SAAS,MAAMC,gDAAuC;AACxD,UAAM,IAAID,wBAAAA;AAAAA,MACR,qDAAqD,SAAS,CAAC;AAAA,IAAA;AAAA,EAEnE;AAEA,MAAI,SAAS,cAAc,QAAQ,WAAW;AAC5C,UAAM,IAAIA,wBAAAA;AAAAA,MACR,kEAAkE,QAAQ,SAAS,gBAAgB,SAAS,SAAS;AAAA,IAAA;AAAA,EAEzH;AAEA,MAAI,SAAS,WAAW,QAAQ,QAAQ;AACtC,UAAM,IAAIA,wBAAAA;AAAAA,MACR,8DAA8D,QAAQ,MAAM,gBAAgB,SAAS,MAAM;AAAA,IAAA;AAAA,EAE/G;AACF;AAEA,SAAS,oCACP,eACmB;AACnB,QAAM,EAAE,cAAc,eAAe,GAAG,wBAAwB;AAChE,SAAO;AACT;AASA,SAAS,8BAA8B,SAIX;AAC1B,QAAM,UAAU,QAAQ,WAAWE,SAAAA;AACnC,QAAM,YAAY,QAAQ,aAAa;AAEvC,SAAO,OACL,QACA,cACA,SACA,eACG;AACH,UAAM,UAAU;AAAA,MACd,GAAGD,SAAAA;AAAAA,MACH,WAAW,gBAAA;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAGF,UAAM,WAAW,MAAM;AAAA,MACrB,QAAQ,OAAO,SAAS,OAAO;AAAA,MAC/B;AAAA,MACA,kDAAkD,MAAM,gBAAgB,YAAY,eAAe,SAAS;AAAA,IAAA;AAE9G,wBAAoB,UAAU,OAAO;AAErC,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,cAAc,IAAID,wBAAAA;AAAAA,QACtB,GAAG,SAAS,MAAM,IAAI,KAAK,SAAS,MAAM,OAAO;AAAA,MAAA;AAEnD,UAAI,OAAO,SAAS,MAAM,UAAU,UAAU;AAC5C,oBAAY,QAAQ,SAAS,MAAM;AAAA,MACrC;AACA,UACE,OAAO,SAAS,MAAM,SAAS,YAC/B,OAAO,SAAS,MAAM,SAAS,UAC/B;AACE,oBAAmD,OACnD,SAAS,MAAM;AAAA,MACnB;AACA,UAAI,SAAS,MAAM,SAAS,QAAW;AAEnC,oBAGA,OAAO,SAAS,MAAM;AAAA,MAC1B;AACA,YAAM;AAAA,IACR;AAEA,WAAO,SAAS;AAAA,EAClB;AACF;AAoCA,SAAS,8BACP,gBACA,YACiC;AACjC,SAAO;AAAA,IACL,YAAY,OACV,cACA,eACA,QACG;AACH,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,UACE,SAAS,oCAAoC,aAAa;AAAA,UAC1D;AAAA,QAAA;AAAA,QAEF;AAAA,MAAA;AAGF,aAAO;AAAA,IAIT;AAAA,IACA,oBAAoB,OAClB,cACA,QAIG;AACH,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,EAAE,IAAA;AAAA,QACF;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,kBAAkB,OAChB,cACA,OACkB;AAClB,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,QAAA;AAAA,QAEF;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,sBAAsB,OACpB,cACA,IACA,WACmC;AACnC,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,EAAE,IAAI,OAAA;AAAA,QACN;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,wBAAwB,OACtB,iBACoD;AACpD,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,CAAA;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,UAAU,OACR,cACA,YAOG;AACH,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,QACA,EAAE,QAAA;AAAA,QACF;AAAA,MAAA;AAEF,aAAO;AAAA,IAKT;AAAA,IACA,aAAa,OACX,cACA,WACA,SACkB;AAClB,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,UACA;AAAA,QAAA;AAAA,QAEF;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,kBAAkB,OAChB,cACA,cACkB;AAClB,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,QAAA;AAAA,QAEF;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,WAAW,OACT,cACA,mBACoD;AACpD,YAAM,SAAS,MAAM;AAAA,QACnB;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,QAAA;AAAA,QAEF;AAAA,MAAA;AAEF,aAAO;AAAA,IACT;AAAA,IACA,mBAAmB,OACjB,iBAKI;AACJ,aAAO,eAAe,qBAAqB,cAAc,CAAA,GAAI,UAAU;AAAA,IACzE;AAAA,IACA,uBAAuB,OAAO,cAAc,iBAC1C;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE,aAAA;AAAA,MACF;AAAA,IAAA;AAAA,EACF;AAEN;AAiBA,SAAS,cACP,SAC2B;AAC3B,MAAI,QAAQ,QAAQ;AAClB,WAAO,QAAQ;AAAA,EACjB;AAEA,MAAI,QAAQ,aAAa;AACvB,WAAO,CAAC,SAAS,YAAY,QAAQ,YAAa,OAAO,SAAS,OAAO;AAAA,EAC3E;AAEA,QAAM,IAAIA,wBAAAA;AAAAA,IACR;AAAA,EAAA;AAEJ;AAEO,SAAS,gCACd,SACgC;AAChC,QAAM,SAAS,cAAc,OAAO;AACpC,QAAM,cAAc,QAAQ,eAAe,IAAIG,wBAAAA,yBAAA;AAC/C,QAAM,iBAAiB,8BAA8B;AAAA,IACnD;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,WAAW,QAAQ;AAAA,EAAA,CACpB;AACD,QAAM,mCAAmB,IAAA;AAEzB,QAAM,0BAA0B,CAC9B,MACA,kBACG;AACH,UAAM,mBACJ,kBAAkB,SAAY,mBAAmB,UAAU,aAAa;AAC1E,UAAM,WAAW,QAAQ,IAAI,IAAI,gBAAgB;AACjD,UAAM,gBAAgB,aAAa,IAAI,QAAQ;AAC/C,QAAI,eAAe;AACjB,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,8BAA8B,gBAAgB;AAAA,MAC5D;AAAA,MACA;AAAA,IAAA,CACD;AACD,iBAAa,IAAI,UAAU,OAAO;AAClC,WAAO;AAAA,EACT;AAEA,QAAM,8BAA8B,CAClC,cACA,MACA,kBACmC;AACnC,UAAM,UAAU,wBAAwB,MAAM,aAAa;AAC3D,QAAI,uBAAuBC,oBAAAA,+BAA+B;AACxD,UAAI,iBAAiB,QAAW;AAC9B,oBAAY,WAAW,OAAO;AAAA,MAChC,OAAO;AACL,oBAAY,wBAAwB,cAAc,OAAO;AAAA,MAC3D;AAAA,IACF;AACA,WAAO,EAAE,SAAS,YAAA;AAAA,EACpB;AAEA,QAAM,qBAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,MAAI,uBAAuBA,oBAAAA,+BAA+B;AACxD,gBAAY,WAAW,mBAAmB,OAAO;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,iCAAiC,CAAC,EAAE,cAAc,MAAM,oBACtD,4BAA4B,cAAc,MAAM,aAAa;AAAA;AAAA,IAE/D,2BAA2B,CAAC,SAC1B,4BAA4B,QAAW,MAAM,MAAS;AAAA,EAAA;AAE5D;;"}
|
|
1
|
+
{"version":3,"file":"renderer.cjs","sources":["../../src/renderer.ts"],"sourcesContent":["import {\n InvalidPersistedCollectionConfigError,\n SingleProcessCoordinator,\n resolvePersistedStorageTarget,\n} from '@tanstack/db-sqlite-persistence-core'\nimport { ElectronCollectionCoordinator } from './electron-coordinator'\nimport {\n DEFAULT_ELECTRON_PERSISTENCE_CHANNEL,\n ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n} from './protocol'\nimport type {\n CommittedTxAnchor,\n PersistedCacheGenerationClaim,\n PersistedCollectionCoordinator,\n PersistedCollectionMode,\n PersistedCollectionPersistence,\n PersistedIndexSpec,\n PersistedStorageTarget,\n PersistedTx,\n ReconciledCommittedTx,\n SQLitePullSinceResult,\n} from '@tanstack/db-sqlite-persistence-core'\nimport type {\n ElectronPersistedKey,\n ElectronPersistedRow,\n ElectronPersistenceInvoke,\n ElectronPersistenceMethod,\n ElectronPersistencePayloadMap,\n ElectronPersistenceRequest,\n ElectronPersistenceRequestEnvelope,\n ElectronPersistenceResolution,\n ElectronPersistenceResponseEnvelope,\n ElectronPersistenceResultMap,\n} from './protocol'\nimport type { LoadSubsetOptions } from '@tanstack/db'\n\nconst DEFAULT_REQUEST_TIMEOUT_MS = 5_000\nlet nextRequestId = 1\n\nfunction createRequestId(): string {\n const requestId = nextRequestId\n nextRequestId++\n return `electron-persistence-${requestId}`\n}\n\nfunction withTimeout<T>(\n promise: Promise<T>,\n timeoutMs: number,\n timeoutMessage: string,\n): Promise<T> {\n if (timeoutMs <= 0) {\n return promise\n }\n\n return new Promise<T>((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new InvalidPersistedCollectionConfigError(timeoutMessage))\n }, timeoutMs)\n\n promise.then(\n (value) => {\n clearTimeout(timer)\n resolve(value)\n },\n (error: unknown) => {\n clearTimeout(timer)\n reject(error)\n },\n )\n })\n}\n\nfunction assertValidResponse(\n response: ElectronPersistenceResponseEnvelope,\n request: ElectronPersistenceRequestEnvelope,\n): void {\n if (response.v !== ELECTRON_PERSISTENCE_PROTOCOL_VERSION) {\n throw new InvalidPersistedCollectionConfigError(\n `Unexpected electron persistence protocol version \"${response.v}\" in response`,\n )\n }\n\n if (response.requestId !== request.requestId) {\n throw new InvalidPersistedCollectionConfigError(\n `Mismatched electron persistence response request id. Expected \"${request.requestId}\", received \"${response.requestId}\"`,\n )\n }\n\n if (response.method !== request.method) {\n throw new InvalidPersistedCollectionConfigError(\n `Mismatched electron persistence response method. Expected \"${request.method}\", received \"${response.method}\"`,\n )\n }\n}\n\nfunction createSerializableLoadSubsetOptions(\n subsetOptions: LoadSubsetOptions,\n): LoadSubsetOptions {\n const { subscription: _subscription, ...serializableOptions } = subsetOptions\n return serializableOptions\n}\n\ntype RendererRequestExecutor = <TMethod extends ElectronPersistenceMethod>(\n method: TMethod,\n target: string | PersistedStorageTarget,\n payload: ElectronPersistencePayloadMap[TMethod],\n resolution?: ElectronPersistenceResolution,\n) => Promise<ElectronPersistenceResultMap[TMethod]>\n\nfunction createRendererRequestExecutor(options: {\n invoke: ElectronPersistenceInvoke\n channel?: string\n timeoutMs?: number\n claimCollections: Map<string, string>\n}): RendererRequestExecutor {\n const channel = options.channel ?? DEFAULT_ELECTRON_PERSISTENCE_CHANNEL\n const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS\n\n return async <TMethod extends ElectronPersistenceMethod>(\n method: TMethod,\n target: string | PersistedStorageTarget,\n payload: ElectronPersistencePayloadMap[TMethod],\n resolution?: ElectronPersistenceResolution,\n ) => {\n const storageTarget = typeof target === `string` ? undefined : target\n const collectionId = storageTarget\n ? resolvePersistedStorageTarget(storageTarget).collectionId\n : target\n const isGenerationRequest =\n method === `claimCacheGeneration` ||\n method === `rotateCacheGeneration` ||\n method === `renewCacheGenerationClaim` ||\n method === `releaseCacheGenerationClaim`\n const managedTarget = storageTarget?.kind === `managed`\n const logicalCollectionId =\n resolution?.logicalCollectionId ??\n (managedTarget\n ? options.claimCollections.get(storageTarget.claimId)\n : isGenerationRequest\n ? collectionId\n : undefined)\n if ((managedTarget || isGenerationRequest) && !logicalCollectionId) {\n throw new InvalidPersistedCollectionConfigError(\n `Electron managed cache request requires a known logical Collection ID`,\n )\n }\n const request = {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: createRequestId(),\n collectionId,\n storageTarget,\n method,\n resolution:\n managedTarget || isGenerationRequest\n ? { ...resolution, mode: `sync-present`, logicalCollectionId }\n : resolution,\n payload,\n } as ElectronPersistenceRequest\n\n const response = await withTimeout(\n options.invoke(channel, request),\n timeoutMs,\n `Electron persistence request timed out (method=${method}, collection=${collectionId}, timeoutMs=${timeoutMs})`,\n )\n assertValidResponse(response, request)\n\n if (!response.ok) {\n const remoteError = new InvalidPersistedCollectionConfigError(\n `${response.error.name}: ${response.error.message}`,\n )\n if (typeof response.error.stack === `string`) {\n remoteError.stack = response.error.stack\n }\n if (\n typeof response.error.code === `string` ||\n typeof response.error.code === `number`\n ) {\n ;(remoteError as Error & { code?: string | number }).code =\n response.error.code\n }\n if (response.error.path !== undefined) {\n ;(\n remoteError as Error & {\n path?: string | ReadonlyArray<string | number>\n }\n ).path = response.error.path\n }\n throw remoteError\n }\n\n return response.result as ElectronPersistenceResultMap[TMethod]\n }\n}\n\ntype ElectronRendererResolvedAdapter =\n PersistedCollectionPersistence[`adapter`] & {\n loadCollectionMetadata: (\n target: PersistedStorageTarget,\n ctx?: { cacheGenerationClaimId?: string },\n ) => Promise<Array<{ key: string; value: unknown }>>\n scanRows: (\n target: PersistedStorageTarget,\n options?: { metadataOnly?: boolean },\n ctx?: { cacheGenerationClaimId?: string },\n ) => Promise<\n Array<{\n key: string | number\n value: Record<string, unknown>\n metadata?: unknown\n }>\n >\n pullSince: (\n target: PersistedStorageTarget,\n fromRowVersion: number,\n ctx?: { cacheGenerationClaimId?: string },\n ) => Promise<SQLitePullSinceResult<string | number>>\n getStreamPosition: (\n target: PersistedStorageTarget,\n ctx?: { cacheGenerationClaimId?: string },\n ) => Promise<{\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }>\n reserveLeadershipTerm: (\n target: PersistedStorageTarget,\n observedTerm: number,\n ctx?: { cacheGenerationClaimId?: string },\n ) => Promise<{\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }>\n }\n\nfunction createResolvedRendererAdapter(\n executeRequest: RendererRequestExecutor,\n claimCollections: Map<string, string>,\n managedCacheGenerations: boolean,\n resolution?: ElectronPersistenceResolution,\n): ElectronRendererResolvedAdapter {\n const adapter: ElectronRendererResolvedAdapter = {\n loadSubset: async (\n target: PersistedStorageTarget,\n subsetOptions: LoadSubsetOptions,\n ctx?: {\n requiredIndexSignatures?: ReadonlyArray<string>\n cacheGenerationClaimId?: string\n },\n ) => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n const result = await executeRequest(\n `loadSubset`,\n target,\n {\n options: createSerializableLoadSubsetOptions(subsetOptions),\n ctx: { ...ctx, cacheGenerationClaimId: access.claimId },\n },\n resolution,\n )\n\n return result as Array<{\n key: string | number\n value: Record<string, unknown>\n }>\n },\n loadResumeSnapshot: async (\n target: PersistedStorageTarget,\n ctx?: {\n requiredIndexSignatures?: ReadonlyArray<string>\n includeRows?: boolean\n cacheGenerationClaimId?: string\n },\n ) => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n return executeRequest(\n `loadResumeSnapshot`,\n target,\n { ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },\n resolution,\n )\n },\n applyCommittedTx: async (\n target: PersistedStorageTarget,\n tx: PersistedTx<Record<string, unknown>, string | number>,\n ): Promise<void> => {\n const access = resolvePersistedStorageTarget(\n target,\n tx.cacheGenerationClaimId,\n )\n await executeRequest(\n `applyCommittedTx`,\n target,\n {\n tx: { ...tx, cacheGenerationClaimId: access.claimId } as PersistedTx<\n ElectronPersistedRow,\n ElectronPersistedKey\n >,\n },\n resolution,\n )\n },\n reconcileCommittedTx: async (\n target: PersistedStorageTarget,\n tx: PersistedTx<Record<string, unknown>, string | number>,\n anchor: CommittedTxAnchor,\n ): Promise<ReconciledCommittedTx> => {\n const access = resolvePersistedStorageTarget(\n target,\n tx.cacheGenerationClaimId,\n )\n return executeRequest(\n `reconcileCommittedTx`,\n target,\n { tx: { ...tx, cacheGenerationClaimId: access.claimId }, anchor },\n resolution,\n )\n },\n loadCollectionMetadata: async (\n target: PersistedStorageTarget,\n ctx?: { cacheGenerationClaimId?: string },\n ): Promise<Array<{ key: string; value: unknown }>> => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n return executeRequest(\n `loadCollectionMetadata`,\n target,\n { ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },\n resolution,\n )\n },\n scanRows: async (\n target: PersistedStorageTarget,\n options?: { metadataOnly?: boolean },\n ctx?: { cacheGenerationClaimId?: string },\n ): Promise<\n Array<{\n key: string | number\n value: Record<string, unknown>\n metadata?: unknown\n }>\n > => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n const result = await executeRequest(\n `scanRows`,\n target,\n { options, ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },\n resolution,\n )\n return result as Array<{\n key: string | number\n value: Record<string, unknown>\n metadata?: unknown\n }>\n },\n ensureIndex: async (\n target: PersistedStorageTarget,\n signature: string,\n spec: PersistedIndexSpec,\n ctx?: { cacheGenerationClaimId?: string },\n ): Promise<void> => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n await executeRequest(\n `ensureIndex`,\n target,\n {\n signature,\n spec,\n ctx: { ...ctx, cacheGenerationClaimId: access.claimId },\n },\n resolution,\n )\n },\n markIndexRemoved: async (\n target: PersistedStorageTarget,\n signature: string,\n ctx?: { cacheGenerationClaimId?: string },\n ): Promise<void> => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n await executeRequest(\n `markIndexRemoved`,\n target,\n {\n signature,\n ctx: { ...ctx, cacheGenerationClaimId: access.claimId },\n },\n resolution,\n )\n },\n pullSince: async (\n target: PersistedStorageTarget,\n fromRowVersion: number,\n ctx?: { cacheGenerationClaimId?: string },\n ): Promise<SQLitePullSinceResult<string | number>> => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n const result = await executeRequest(\n `pullSince`,\n target,\n {\n fromRowVersion,\n ctx: { ...ctx, cacheGenerationClaimId: access.claimId },\n },\n resolution,\n )\n return result as SQLitePullSinceResult<string | number>\n },\n getStreamPosition: async (\n target: PersistedStorageTarget,\n ctx?: { cacheGenerationClaimId?: string },\n ): Promise<{\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }> => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n return executeRequest(\n `getStreamPosition`,\n target,\n { ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },\n resolution,\n )\n },\n claimCacheGeneration: async (\n collectionId: string,\n ): Promise<PersistedCacheGenerationClaim> => {\n const claim = await executeRequest(\n `claimCacheGeneration`,\n collectionId,\n {},\n resolution,\n )\n claimCollections.set(claim.claimId, collectionId)\n return claim\n },\n rotateCacheGeneration: async (\n collectionId: string,\n claimId: string,\n resetMetadata?: { key: string; value: unknown },\n expectedStorageCollectionId?: string,\n ): Promise<PersistedCacheGenerationClaim> => {\n const claim = await executeRequest(\n `rotateCacheGeneration`,\n collectionId,\n { claimId, resetMetadata, expectedStorageCollectionId },\n resolution,\n )\n claimCollections.delete(claimId)\n claimCollections.set(claim.claimId, collectionId)\n return claim\n },\n renewCacheGenerationClaim: (\n storageCollectionId: string,\n claimId: string,\n ): Promise<number | undefined> => {\n const collectionId = claimCollections.get(claimId)\n if (!collectionId) {\n throw new InvalidPersistedCollectionConfigError(\n `Unknown electron persisted cache claim \"${claimId}\"`,\n )\n }\n return executeRequest(\n `renewCacheGenerationClaim`,\n collectionId,\n { storageCollectionId, claimId },\n resolution,\n )\n },\n releaseCacheGenerationClaim: async (claimId: string): Promise<void> => {\n const collectionId = claimCollections.get(claimId)\n if (!collectionId) {\n throw new InvalidPersistedCollectionConfigError(\n `Unknown electron persisted cache claim \"${claimId}\"`,\n )\n }\n await executeRequest(\n `releaseCacheGenerationClaim`,\n collectionId,\n { claimId },\n resolution,\n )\n claimCollections.delete(claimId)\n },\n reserveLeadershipTerm: async (target, observedTerm, ctx) => {\n const access = resolvePersistedStorageTarget(\n target,\n ctx?.cacheGenerationClaimId,\n )\n return executeRequest(\n `reserveLeadershipTerm`,\n target,\n {\n observedTerm,\n ctx: { ...ctx, cacheGenerationClaimId: access.claimId },\n },\n resolution,\n )\n },\n }\n if (!managedCacheGenerations) {\n adapter.claimCacheGeneration = undefined\n adapter.rotateCacheGeneration = undefined\n adapter.renewCacheGenerationClaim = undefined\n adapter.releaseCacheGenerationClaim = undefined\n }\n return adapter\n}\n\nexport type ElectronIpcRendererLike = {\n invoke: (\n channel: string,\n request: ElectronPersistenceRequestEnvelope,\n ) => Promise<ElectronPersistenceResponseEnvelope>\n}\n\nexport type ElectronSQLitePersistenceOptions = {\n invoke?: ElectronPersistenceInvoke\n ipcRenderer?: ElectronIpcRendererLike\n channel?: string\n timeoutMs?: number\n coordinator?: PersistedCollectionCoordinator\n /** Set false when a custom main-process adapter does not manage cache generations. */\n managedCacheGenerations?: boolean\n}\n\nfunction resolveInvoke(\n options: ElectronSQLitePersistenceOptions,\n): ElectronPersistenceInvoke {\n if (options.invoke) {\n return options.invoke\n }\n\n if (options.ipcRenderer) {\n return (channel, request) => options.ipcRenderer!.invoke(channel, request)\n }\n\n throw new InvalidPersistedCollectionConfigError(\n `Electron renderer persistence requires either invoke or ipcRenderer`,\n )\n}\n\nexport function createElectronSQLitePersistence(\n options: ElectronSQLitePersistenceOptions,\n): PersistedCollectionPersistence {\n const invoke = resolveInvoke(options)\n const coordinator = options.coordinator ?? new SingleProcessCoordinator()\n const claimCollections = new Map<string, string>()\n const executeRequest = createRendererRequestExecutor({\n invoke,\n channel: options.channel,\n timeoutMs: options.timeoutMs,\n claimCollections,\n })\n const adapterCache = new Map<string, ElectronRendererResolvedAdapter>()\n\n const getAdapterForCollection = (\n collectionId: string | undefined,\n mode: PersistedCollectionMode,\n schemaVersion: number | undefined,\n ) => {\n const cacheKey = JSON.stringify([collectionId, mode, schemaVersion])\n const cachedAdapter = adapterCache.get(cacheKey)\n if (cachedAdapter) {\n return cachedAdapter\n }\n\n const adapter = createResolvedRendererAdapter(\n executeRequest,\n claimCollections,\n options.managedCacheGenerations ?? true,\n { mode, schemaVersion, logicalCollectionId: collectionId },\n )\n adapterCache.set(cacheKey, adapter)\n return adapter\n }\n\n const createCollectionPersistence = (\n collectionId: string | undefined,\n mode: PersistedCollectionMode,\n schemaVersion: number | undefined,\n ): PersistedCollectionPersistence => {\n const adapter = getAdapterForCollection(collectionId, mode, schemaVersion)\n if (coordinator instanceof ElectronCollectionCoordinator) {\n if (collectionId === undefined) {\n coordinator.setAdapter(adapter)\n } else {\n coordinator.setAdapterForCollection(collectionId, adapter)\n }\n }\n return { adapter, coordinator }\n }\n\n const defaultPersistence = createCollectionPersistence(\n undefined,\n `sync-absent`,\n undefined,\n )\n if (coordinator instanceof ElectronCollectionCoordinator) {\n coordinator.setAdapter(defaultPersistence.adapter)\n }\n\n return {\n ...defaultPersistence,\n resolvePersistenceForCollection: ({ collectionId, mode, schemaVersion }) =>\n createCollectionPersistence(collectionId, mode, schemaVersion),\n // Backward compatible fallback for older callers.\n resolvePersistenceForMode: (mode) =>\n createCollectionPersistence(undefined, mode, undefined),\n }\n}\n"],"names":["InvalidPersistedCollectionConfigError","ELECTRON_PERSISTENCE_PROTOCOL_VERSION","DEFAULT_ELECTRON_PERSISTENCE_CHANNEL","resolvePersistedStorageTarget","SingleProcessCoordinator","ElectronCollectionCoordinator"],"mappings":"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"}
|
package/dist/cjs/renderer.d.cts
CHANGED
|
@@ -9,5 +9,7 @@ export type ElectronSQLitePersistenceOptions = {
|
|
|
9
9
|
channel?: string;
|
|
10
10
|
timeoutMs?: number;
|
|
11
11
|
coordinator?: PersistedCollectionCoordinator;
|
|
12
|
+
/** Set false when a custom main-process adapter does not manage cache generations. */
|
|
13
|
+
managedCacheGenerations?: boolean;
|
|
12
14
|
};
|
|
13
15
|
export declare function createElectronSQLitePersistence(options: ElectronSQLitePersistenceOptions): PersistedCollectionPersistence;
|
package/dist/esm/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InvalidPersistedCollectionConfigError } from "@tanstack/db-sqlite-persistence-core";
|
|
1
|
+
import { InvalidPersistedCollectionConfigError, resolvePersistedStorageTarget } from "@tanstack/db-sqlite-persistence-core";
|
|
2
2
|
import { DEFAULT_ELECTRON_PERSISTENCE_CHANNEL, ELECTRON_PERSISTENCE_PROTOCOL_VERSION } from "./protocol.js";
|
|
3
3
|
function serializeError(error) {
|
|
4
4
|
const fallbackMessage = `Unknown electron persistence error`;
|
|
@@ -47,11 +47,25 @@ function assertValidRequest(request) {
|
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
+
function requireStorageTarget(request) {
|
|
51
|
+
const target = request.storageTarget;
|
|
52
|
+
if (!target) {
|
|
53
|
+
throw new InvalidPersistedCollectionConfigError(
|
|
54
|
+
`Electron persistence data request requires an explicit storage target`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
if (resolvePersistedStorageTarget(target).collectionId !== request.collectionId) {
|
|
58
|
+
throw new InvalidPersistedCollectionConfigError(
|
|
59
|
+
`Electron persistence storage target does not match its collectionId`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
return target;
|
|
63
|
+
}
|
|
50
64
|
async function executeRequestAgainstAdapter(request, adapter) {
|
|
51
65
|
switch (request.method) {
|
|
52
66
|
case `loadSubset`: {
|
|
53
67
|
const result = await adapter.loadSubset(
|
|
54
|
-
request
|
|
68
|
+
requireStorageTarget(request),
|
|
55
69
|
request.payload.options,
|
|
56
70
|
request.payload.ctx
|
|
57
71
|
);
|
|
@@ -65,7 +79,7 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
65
79
|
}
|
|
66
80
|
case `loadResumeSnapshot`: {
|
|
67
81
|
const result = await adapter.loadResumeSnapshot(
|
|
68
|
-
request
|
|
82
|
+
requireStorageTarget(request),
|
|
69
83
|
request.payload.ctx
|
|
70
84
|
);
|
|
71
85
|
return {
|
|
@@ -82,7 +96,10 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
82
96
|
`loadCollectionMetadata is not supported by the configured electron persistence adapter`
|
|
83
97
|
);
|
|
84
98
|
}
|
|
85
|
-
const result = await adapter.loadCollectionMetadata(
|
|
99
|
+
const result = await adapter.loadCollectionMetadata(
|
|
100
|
+
requireStorageTarget(request),
|
|
101
|
+
request.payload.ctx
|
|
102
|
+
);
|
|
86
103
|
return {
|
|
87
104
|
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
88
105
|
requestId: request.requestId,
|
|
@@ -98,8 +115,9 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
98
115
|
);
|
|
99
116
|
}
|
|
100
117
|
const result = await adapter.scanRows(
|
|
101
|
-
request
|
|
102
|
-
request.payload.options
|
|
118
|
+
requireStorageTarget(request),
|
|
119
|
+
request.payload.options,
|
|
120
|
+
request.payload.ctx
|
|
103
121
|
);
|
|
104
122
|
return {
|
|
105
123
|
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
@@ -110,7 +128,10 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
110
128
|
};
|
|
111
129
|
}
|
|
112
130
|
case `applyCommittedTx`: {
|
|
113
|
-
await adapter.applyCommittedTx(
|
|
131
|
+
await adapter.applyCommittedTx(
|
|
132
|
+
requireStorageTarget(request),
|
|
133
|
+
request.payload.tx
|
|
134
|
+
);
|
|
114
135
|
return {
|
|
115
136
|
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
116
137
|
requestId: request.requestId,
|
|
@@ -121,7 +142,7 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
121
142
|
}
|
|
122
143
|
case `reconcileCommittedTx`: {
|
|
123
144
|
const result = adapter.reconcileCommittedTx ? await adapter.reconcileCommittedTx(
|
|
124
|
-
request
|
|
145
|
+
requireStorageTarget(request),
|
|
125
146
|
request.payload.tx,
|
|
126
147
|
request.payload.anchor
|
|
127
148
|
) : { kind: `unknown` };
|
|
@@ -135,9 +156,10 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
135
156
|
}
|
|
136
157
|
case `ensureIndex`: {
|
|
137
158
|
await adapter.ensureIndex(
|
|
138
|
-
request
|
|
159
|
+
requireStorageTarget(request),
|
|
139
160
|
request.payload.signature,
|
|
140
|
-
request.payload.spec
|
|
161
|
+
request.payload.spec,
|
|
162
|
+
request.payload.ctx
|
|
141
163
|
);
|
|
142
164
|
return {
|
|
143
165
|
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
@@ -154,8 +176,9 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
154
176
|
);
|
|
155
177
|
}
|
|
156
178
|
await adapter.markIndexRemoved(
|
|
157
|
-
request
|
|
158
|
-
request.payload.signature
|
|
179
|
+
requireStorageTarget(request),
|
|
180
|
+
request.payload.signature,
|
|
181
|
+
request.payload.ctx
|
|
159
182
|
);
|
|
160
183
|
return {
|
|
161
184
|
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
@@ -172,8 +195,9 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
172
195
|
);
|
|
173
196
|
}
|
|
174
197
|
const result = await adapter.pullSince(
|
|
175
|
-
request
|
|
176
|
-
request.payload.fromRowVersion
|
|
198
|
+
requireStorageTarget(request),
|
|
199
|
+
request.payload.fromRowVersion,
|
|
200
|
+
request.payload.ctx
|
|
177
201
|
);
|
|
178
202
|
return {
|
|
179
203
|
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
@@ -190,8 +214,9 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
190
214
|
);
|
|
191
215
|
}
|
|
192
216
|
const position = await adapter.reserveLeadershipTerm(
|
|
193
|
-
request
|
|
194
|
-
request.payload.observedTerm
|
|
217
|
+
requireStorageTarget(request),
|
|
218
|
+
request.payload.observedTerm,
|
|
219
|
+
request.payload.ctx
|
|
195
220
|
);
|
|
196
221
|
return {
|
|
197
222
|
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
@@ -207,7 +232,10 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
207
232
|
`getStreamPosition is not supported by the configured electron persistence adapter`
|
|
208
233
|
);
|
|
209
234
|
}
|
|
210
|
-
const position = await adapter.getStreamPosition(
|
|
235
|
+
const position = await adapter.getStreamPosition(
|
|
236
|
+
requireStorageTarget(request),
|
|
237
|
+
request.payload.ctx
|
|
238
|
+
);
|
|
211
239
|
return {
|
|
212
240
|
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
213
241
|
requestId: request.requestId,
|
|
@@ -216,13 +244,86 @@ async function executeRequestAgainstAdapter(request, adapter) {
|
|
|
216
244
|
result: position
|
|
217
245
|
};
|
|
218
246
|
}
|
|
247
|
+
case `claimCacheGeneration`: {
|
|
248
|
+
if (!adapter.claimCacheGeneration) {
|
|
249
|
+
throw new InvalidPersistedCollectionConfigError(
|
|
250
|
+
`claimCacheGeneration is not supported by the configured electron persistence adapter`
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
const result = await adapter.claimCacheGeneration(request.collectionId);
|
|
254
|
+
return {
|
|
255
|
+
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
256
|
+
requestId: request.requestId,
|
|
257
|
+
method: request.method,
|
|
258
|
+
ok: true,
|
|
259
|
+
result
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
case `rotateCacheGeneration`: {
|
|
263
|
+
if (!adapter.rotateCacheGeneration) {
|
|
264
|
+
throw new InvalidPersistedCollectionConfigError(
|
|
265
|
+
`rotateCacheGeneration is not supported by the configured electron persistence adapter`
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
const result = await adapter.rotateCacheGeneration(
|
|
269
|
+
request.collectionId,
|
|
270
|
+
request.payload.claimId,
|
|
271
|
+
request.payload.resetMetadata,
|
|
272
|
+
request.payload.expectedStorageCollectionId
|
|
273
|
+
);
|
|
274
|
+
return {
|
|
275
|
+
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
276
|
+
requestId: request.requestId,
|
|
277
|
+
method: request.method,
|
|
278
|
+
ok: true,
|
|
279
|
+
result
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
case `renewCacheGenerationClaim`: {
|
|
283
|
+
if (!adapter.renewCacheGenerationClaim) {
|
|
284
|
+
throw new InvalidPersistedCollectionConfigError(
|
|
285
|
+
`renewCacheGenerationClaim is not supported by the configured electron persistence adapter`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
const result = await adapter.renewCacheGenerationClaim(
|
|
289
|
+
request.payload.storageCollectionId,
|
|
290
|
+
request.payload.claimId
|
|
291
|
+
);
|
|
292
|
+
return {
|
|
293
|
+
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
294
|
+
requestId: request.requestId,
|
|
295
|
+
method: request.method,
|
|
296
|
+
ok: true,
|
|
297
|
+
result
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
case `releaseCacheGenerationClaim`: {
|
|
301
|
+
if (!adapter.releaseCacheGenerationClaim) {
|
|
302
|
+
throw new InvalidPersistedCollectionConfigError(
|
|
303
|
+
`releaseCacheGenerationClaim is not supported by the configured electron persistence adapter`
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
await adapter.releaseCacheGenerationClaim(request.payload.claimId);
|
|
307
|
+
return {
|
|
308
|
+
v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
|
|
309
|
+
requestId: request.requestId,
|
|
310
|
+
method: request.method,
|
|
311
|
+
ok: true,
|
|
312
|
+
result: null
|
|
313
|
+
};
|
|
314
|
+
}
|
|
219
315
|
}
|
|
220
316
|
}
|
|
221
317
|
function resolveModeAwarePersistence(persistence, request) {
|
|
318
|
+
if (request.storageTarget?.kind === `managed` && !request.resolution?.logicalCollectionId) {
|
|
319
|
+
throw new InvalidPersistedCollectionConfigError(
|
|
320
|
+
`Electron managed cache request requires a logical Collection ID`
|
|
321
|
+
);
|
|
322
|
+
}
|
|
222
323
|
const mode = request.resolution?.mode ?? `sync-absent`;
|
|
223
324
|
const schemaVersion = request.resolution?.schemaVersion;
|
|
224
325
|
const collectionAwarePersistence = persistence.resolvePersistenceForCollection?.({
|
|
225
|
-
collectionId: request.collectionId,
|
|
326
|
+
collectionId: request.resolution?.logicalCollectionId ?? request.collectionId,
|
|
226
327
|
mode,
|
|
227
328
|
schemaVersion
|
|
228
329
|
});
|