@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.
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sources":["../../src/main.ts"],"sourcesContent":["import { InvalidPersistedCollectionConfigError } from '@tanstack/db-sqlite-persistence-core'\nimport {\n DEFAULT_ELECTRON_PERSISTENCE_CHANNEL,\n ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n} from './protocol'\nimport type {\n PersistedCollectionPersistence,\n PersistenceAdapter,\n SQLitePullSinceResult,\n} from '@tanstack/db-sqlite-persistence-core'\nimport type {\n ElectronPersistedKey,\n ElectronPersistedRow,\n ElectronPersistenceRequestEnvelope,\n ElectronPersistenceResponseEnvelope,\n ElectronSerializedError,\n} from './protocol'\n\ntype ElectronMainPersistenceAdapter = PersistenceAdapter & {\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: ElectronPersistedKey\n value: ElectronPersistedRow\n metadata?: unknown\n }>\n >\n pullSince?: (\n collectionId: string,\n fromRowVersion: number,\n ) => Promise<SQLitePullSinceResult<ElectronPersistedKey>>\n getStreamPosition?: (collectionId: string) => Promise<{\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }>\n}\n\nfunction serializeError(error: unknown): ElectronSerializedError {\n const fallbackMessage = `Unknown electron persistence error`\n\n if (!(error instanceof Error)) {\n return {\n name: `Error`,\n message: fallbackMessage,\n code: undefined,\n }\n }\n\n const detailedError = error as Error & { code?: unknown; path?: unknown }\n const path = detailedError.path\n return {\n name: error.name || `Error`,\n message: error.message || fallbackMessage,\n stack: error.stack,\n code:\n typeof detailedError.code === `string` ||\n typeof detailedError.code === `number`\n ? detailedError.code\n : undefined,\n path:\n typeof path === `string` ||\n (Array.isArray(path) &&\n path.every(\n (segment: unknown) =>\n typeof segment === `string` || typeof segment === `number`,\n ))\n ? (path as string | ReadonlyArray<string | number>)\n : undefined,\n }\n}\n\nfunction createErrorResponse(\n request: ElectronPersistenceRequestEnvelope,\n error: unknown,\n): ElectronPersistenceResponseEnvelope {\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: false,\n error: serializeError(error),\n }\n}\n\nfunction assertValidRequest(request: ElectronPersistenceRequestEnvelope): void {\n if (request.v !== ELECTRON_PERSISTENCE_PROTOCOL_VERSION) {\n throw new InvalidPersistedCollectionConfigError(\n `Unsupported electron persistence protocol version \"${request.v}\"`,\n )\n }\n\n if (\n typeof request.requestId !== `string` ||\n request.requestId.trim().length === 0\n ) {\n throw new InvalidPersistedCollectionConfigError(\n `Electron persistence requestId cannot be empty`,\n )\n }\n\n if (\n typeof request.collectionId !== `string` ||\n request.collectionId.trim().length === 0\n ) {\n throw new InvalidPersistedCollectionConfigError(\n `Electron persistence collectionId cannot be empty`,\n )\n }\n}\n\nasync function executeRequestAgainstAdapter(\n request: ElectronPersistenceRequestEnvelope,\n adapter: ElectronMainPersistenceAdapter,\n): Promise<ElectronPersistenceResponseEnvelope> {\n switch (request.method) {\n case `loadSubset`: {\n const result = await adapter.loadSubset(\n request.collectionId,\n request.payload.options,\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `loadResumeSnapshot`: {\n const result = await adapter.loadResumeSnapshot(\n request.collectionId,\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `loadCollectionMetadata`: {\n if (!adapter.loadCollectionMetadata) {\n throw new InvalidPersistedCollectionConfigError(\n `loadCollectionMetadata is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.loadCollectionMetadata(request.collectionId)\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `scanRows`: {\n if (!adapter.scanRows) {\n throw new InvalidPersistedCollectionConfigError(\n `scanRows is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.scanRows(\n request.collectionId,\n request.payload.options,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `applyCommittedTx`: {\n await adapter.applyCommittedTx(request.collectionId, request.payload.tx)\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: null,\n }\n }\n\n case `reconcileCommittedTx`: {\n const result = adapter.reconcileCommittedTx\n ? await adapter.reconcileCommittedTx(\n request.collectionId,\n request.payload.tx,\n request.payload.anchor,\n )\n : { kind: `unknown` as const }\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `ensureIndex`: {\n await adapter.ensureIndex(\n request.collectionId,\n request.payload.signature,\n request.payload.spec,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: null,\n }\n }\n\n case `markIndexRemoved`: {\n if (!adapter.markIndexRemoved) {\n throw new InvalidPersistedCollectionConfigError(\n `markIndexRemoved is not supported by the configured electron persistence adapter`,\n )\n }\n await adapter.markIndexRemoved(\n request.collectionId,\n request.payload.signature,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: null,\n }\n }\n\n case `pullSince`: {\n if (!adapter.pullSince) {\n throw new InvalidPersistedCollectionConfigError(\n `pullSince is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.pullSince(\n request.collectionId,\n request.payload.fromRowVersion,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `reserveLeadershipTerm`: {\n if (!adapter.reserveLeadershipTerm) {\n throw new InvalidPersistedCollectionConfigError(\n `reserveLeadershipTerm is not supported by the configured electron persistence adapter`,\n )\n }\n const position = await adapter.reserveLeadershipTerm(\n request.collectionId,\n request.payload.observedTerm,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: position,\n }\n }\n\n case `getStreamPosition`: {\n if (!adapter.getStreamPosition) {\n throw new InvalidPersistedCollectionConfigError(\n `getStreamPosition is not supported by the configured electron persistence adapter`,\n )\n }\n const position = await adapter.getStreamPosition(request.collectionId)\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: position,\n }\n }\n }\n}\n\nfunction resolveModeAwarePersistence(\n persistence: PersistedCollectionPersistence,\n request: ElectronPersistenceRequestEnvelope,\n): PersistedCollectionPersistence {\n const mode = request.resolution?.mode ?? `sync-absent`\n const schemaVersion = request.resolution?.schemaVersion\n const collectionAwarePersistence =\n persistence.resolvePersistenceForCollection?.({\n collectionId: request.collectionId,\n mode,\n schemaVersion,\n })\n if (collectionAwarePersistence) {\n return collectionAwarePersistence\n }\n\n const modeAwarePersistence = persistence.resolvePersistenceForMode?.(mode)\n return modeAwarePersistence ?? persistence\n}\n\nexport type ElectronIpcMainLike = {\n handle: (\n channel: string,\n listener: (\n event: unknown,\n request: ElectronPersistenceRequestEnvelope,\n ) => Promise<ElectronPersistenceResponseEnvelope>,\n ) => void\n removeHandler?: (channel: string) => void\n}\n\nexport type ElectronSQLiteMainProcessOptions = {\n persistence: PersistedCollectionPersistence\n ipcMain: ElectronIpcMainLike\n channel?: string\n}\n\nexport function exposeElectronSQLitePersistence(\n options: ElectronSQLiteMainProcessOptions,\n): () => void {\n const channel = options.channel ?? DEFAULT_ELECTRON_PERSISTENCE_CHANNEL\n options.ipcMain.handle(\n channel,\n async (\n _event,\n request: ElectronPersistenceRequestEnvelope,\n ): Promise<ElectronPersistenceResponseEnvelope> => {\n try {\n assertValidRequest(request)\n const modeAwarePersistence = resolveModeAwarePersistence(\n options.persistence,\n request,\n )\n return await executeRequestAgainstAdapter(\n request,\n modeAwarePersistence.adapter,\n )\n } catch (error) {\n return createErrorResponse(request, error)\n }\n },\n )\n\n return () => {\n options.ipcMain.removeHandler?.(channel)\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sources":["../../src/main.ts"],"sourcesContent":["import {\n InvalidPersistedCollectionConfigError,\n resolvePersistedStorageTarget,\n} from '@tanstack/db-sqlite-persistence-core'\nimport {\n DEFAULT_ELECTRON_PERSISTENCE_CHANNEL,\n ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n} from './protocol'\nimport type {\n PersistedCollectionPersistence,\n PersistedStorageTarget,\n PersistenceAdapter,\n SQLitePullSinceResult,\n} from '@tanstack/db-sqlite-persistence-core'\nimport type {\n ElectronPersistedKey,\n ElectronPersistedRow,\n ElectronPersistenceRequestEnvelope,\n ElectronPersistenceResponseEnvelope,\n ElectronSerializedError,\n} from './protocol'\n\ntype ElectronMainPersistenceAdapter = PersistenceAdapter & {\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: ElectronPersistedKey\n value: ElectronPersistedRow\n metadata?: unknown\n }>\n >\n pullSince?: (\n target: PersistedStorageTarget,\n fromRowVersion: number,\n ctx?: { cacheGenerationClaimId?: string },\n ) => Promise<SQLitePullSinceResult<ElectronPersistedKey>>\n getStreamPosition?: (\n target: PersistedStorageTarget,\n ctx?: { cacheGenerationClaimId?: string },\n ) => Promise<{\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }>\n}\n\nfunction serializeError(error: unknown): ElectronSerializedError {\n const fallbackMessage = `Unknown electron persistence error`\n\n if (!(error instanceof Error)) {\n return {\n name: `Error`,\n message: fallbackMessage,\n code: undefined,\n }\n }\n\n const detailedError = error as Error & { code?: unknown; path?: unknown }\n const path = detailedError.path\n return {\n name: error.name || `Error`,\n message: error.message || fallbackMessage,\n stack: error.stack,\n code:\n typeof detailedError.code === `string` ||\n typeof detailedError.code === `number`\n ? detailedError.code\n : undefined,\n path:\n typeof path === `string` ||\n (Array.isArray(path) &&\n path.every(\n (segment: unknown) =>\n typeof segment === `string` || typeof segment === `number`,\n ))\n ? (path as string | ReadonlyArray<string | number>)\n : undefined,\n }\n}\n\nfunction createErrorResponse(\n request: ElectronPersistenceRequestEnvelope,\n error: unknown,\n): ElectronPersistenceResponseEnvelope {\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: false,\n error: serializeError(error),\n }\n}\n\nfunction assertValidRequest(request: ElectronPersistenceRequestEnvelope): void {\n if (request.v !== ELECTRON_PERSISTENCE_PROTOCOL_VERSION) {\n throw new InvalidPersistedCollectionConfigError(\n `Unsupported electron persistence protocol version \"${request.v}\"`,\n )\n }\n\n if (\n typeof request.requestId !== `string` ||\n request.requestId.trim().length === 0\n ) {\n throw new InvalidPersistedCollectionConfigError(\n `Electron persistence requestId cannot be empty`,\n )\n }\n\n if (\n typeof request.collectionId !== `string` ||\n request.collectionId.trim().length === 0\n ) {\n throw new InvalidPersistedCollectionConfigError(\n `Electron persistence collectionId cannot be empty`,\n )\n }\n}\n\nfunction requireStorageTarget(\n request: ElectronPersistenceRequestEnvelope,\n): PersistedStorageTarget {\n const target = request.storageTarget\n if (!target) {\n throw new InvalidPersistedCollectionConfigError(\n `Electron persistence data request requires an explicit storage target`,\n )\n }\n if (\n resolvePersistedStorageTarget(target).collectionId !== request.collectionId\n ) {\n throw new InvalidPersistedCollectionConfigError(\n `Electron persistence storage target does not match its collectionId`,\n )\n }\n return target\n}\n\nasync function executeRequestAgainstAdapter(\n request: ElectronPersistenceRequestEnvelope,\n adapter: ElectronMainPersistenceAdapter,\n): Promise<ElectronPersistenceResponseEnvelope> {\n switch (request.method) {\n case `loadSubset`: {\n const result = await adapter.loadSubset(\n requireStorageTarget(request),\n request.payload.options,\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `loadResumeSnapshot`: {\n const result = await adapter.loadResumeSnapshot(\n requireStorageTarget(request),\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `loadCollectionMetadata`: {\n if (!adapter.loadCollectionMetadata) {\n throw new InvalidPersistedCollectionConfigError(\n `loadCollectionMetadata is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.loadCollectionMetadata(\n requireStorageTarget(request),\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `scanRows`: {\n if (!adapter.scanRows) {\n throw new InvalidPersistedCollectionConfigError(\n `scanRows is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.scanRows(\n requireStorageTarget(request),\n request.payload.options,\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `applyCommittedTx`: {\n await adapter.applyCommittedTx(\n requireStorageTarget(request),\n request.payload.tx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: null,\n }\n }\n\n case `reconcileCommittedTx`: {\n const result = adapter.reconcileCommittedTx\n ? await adapter.reconcileCommittedTx(\n requireStorageTarget(request),\n request.payload.tx,\n request.payload.anchor,\n )\n : { kind: `unknown` as const }\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `ensureIndex`: {\n await adapter.ensureIndex(\n requireStorageTarget(request),\n request.payload.signature,\n request.payload.spec,\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: null,\n }\n }\n\n case `markIndexRemoved`: {\n if (!adapter.markIndexRemoved) {\n throw new InvalidPersistedCollectionConfigError(\n `markIndexRemoved is not supported by the configured electron persistence adapter`,\n )\n }\n await adapter.markIndexRemoved(\n requireStorageTarget(request),\n request.payload.signature,\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: null,\n }\n }\n\n case `pullSince`: {\n if (!adapter.pullSince) {\n throw new InvalidPersistedCollectionConfigError(\n `pullSince is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.pullSince(\n requireStorageTarget(request),\n request.payload.fromRowVersion,\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `reserveLeadershipTerm`: {\n if (!adapter.reserveLeadershipTerm) {\n throw new InvalidPersistedCollectionConfigError(\n `reserveLeadershipTerm is not supported by the configured electron persistence adapter`,\n )\n }\n const position = await adapter.reserveLeadershipTerm(\n requireStorageTarget(request),\n request.payload.observedTerm,\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: position,\n }\n }\n\n case `getStreamPosition`: {\n if (!adapter.getStreamPosition) {\n throw new InvalidPersistedCollectionConfigError(\n `getStreamPosition is not supported by the configured electron persistence adapter`,\n )\n }\n const position = await adapter.getStreamPosition(\n requireStorageTarget(request),\n request.payload.ctx,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: position,\n }\n }\n\n case `claimCacheGeneration`: {\n if (!adapter.claimCacheGeneration) {\n throw new InvalidPersistedCollectionConfigError(\n `claimCacheGeneration is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.claimCacheGeneration(request.collectionId)\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `rotateCacheGeneration`: {\n if (!adapter.rotateCacheGeneration) {\n throw new InvalidPersistedCollectionConfigError(\n `rotateCacheGeneration is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.rotateCacheGeneration(\n request.collectionId,\n request.payload.claimId,\n request.payload.resetMetadata,\n request.payload.expectedStorageCollectionId,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `renewCacheGenerationClaim`: {\n if (!adapter.renewCacheGenerationClaim) {\n throw new InvalidPersistedCollectionConfigError(\n `renewCacheGenerationClaim is not supported by the configured electron persistence adapter`,\n )\n }\n const result = await adapter.renewCacheGenerationClaim(\n request.payload.storageCollectionId,\n request.payload.claimId,\n )\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result,\n }\n }\n\n case `releaseCacheGenerationClaim`: {\n if (!adapter.releaseCacheGenerationClaim) {\n throw new InvalidPersistedCollectionConfigError(\n `releaseCacheGenerationClaim is not supported by the configured electron persistence adapter`,\n )\n }\n await adapter.releaseCacheGenerationClaim(request.payload.claimId)\n return {\n v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,\n requestId: request.requestId,\n method: request.method,\n ok: true,\n result: null,\n }\n }\n }\n}\n\nfunction resolveModeAwarePersistence(\n persistence: PersistedCollectionPersistence,\n request: ElectronPersistenceRequestEnvelope,\n): PersistedCollectionPersistence {\n if (\n request.storageTarget?.kind === `managed` &&\n !request.resolution?.logicalCollectionId\n ) {\n throw new InvalidPersistedCollectionConfigError(\n `Electron managed cache request requires a logical Collection ID`,\n )\n }\n const mode = request.resolution?.mode ?? `sync-absent`\n const schemaVersion = request.resolution?.schemaVersion\n const collectionAwarePersistence =\n persistence.resolvePersistenceForCollection?.({\n collectionId:\n request.resolution?.logicalCollectionId ?? request.collectionId,\n mode,\n schemaVersion,\n })\n if (collectionAwarePersistence) {\n return collectionAwarePersistence\n }\n\n const modeAwarePersistence = persistence.resolvePersistenceForMode?.(mode)\n return modeAwarePersistence ?? persistence\n}\n\nexport type ElectronIpcMainLike = {\n handle: (\n channel: string,\n listener: (\n event: unknown,\n request: ElectronPersistenceRequestEnvelope,\n ) => Promise<ElectronPersistenceResponseEnvelope>,\n ) => void\n removeHandler?: (channel: string) => void\n}\n\nexport type ElectronSQLiteMainProcessOptions = {\n persistence: PersistedCollectionPersistence\n ipcMain: ElectronIpcMainLike\n channel?: string\n}\n\nexport function exposeElectronSQLitePersistence(\n options: ElectronSQLiteMainProcessOptions,\n): () => void {\n const channel = options.channel ?? DEFAULT_ELECTRON_PERSISTENCE_CHANNEL\n options.ipcMain.handle(\n channel,\n async (\n _event,\n request: ElectronPersistenceRequestEnvelope,\n ): Promise<ElectronPersistenceResponseEnvelope> => {\n try {\n assertValidRequest(request)\n const modeAwarePersistence = resolveModeAwarePersistence(\n options.persistence,\n request,\n )\n return await executeRequestAgainstAdapter(\n request,\n modeAwarePersistence.adapter,\n )\n } catch (error) {\n return createErrorResponse(request, error)\n }\n },\n )\n\n return () => {\n options.ipcMain.removeHandler?.(channel)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,32 +1,42 @@
1
1
  import { LoadSubsetOptions } from '@tanstack/db';
2
- import { CommittedTxAnchor, PersistedCollectionMode, PersistedIndexSpec, PersistedKeySetEvidence, PersistedTx, ReconciledCommittedTx, SQLitePullSinceResult } from '@tanstack/db-sqlite-persistence-core';
3
- export declare const ELECTRON_PERSISTENCE_PROTOCOL_VERSION: 4;
2
+ import { CommittedTxAnchor, PersistedCacheGenerationClaim, PersistedCollectionMode, PersistedIndexSpec, PersistedKeySetEvidence, PersistedStorageTarget, PersistedTx, ReconciledCommittedTx, SQLitePullSinceResult } from '@tanstack/db-sqlite-persistence-core';
3
+ export declare const ELECTRON_PERSISTENCE_PROTOCOL_VERSION: 6;
4
4
  export declare const DEFAULT_ELECTRON_PERSISTENCE_CHANNEL = "tanstack-db:sqlite-persistence";
5
5
  export type ElectronPersistedRow = Record<string, unknown>;
6
6
  export type ElectronPersistedKey = string | number;
7
7
  export type ElectronPersistenceResolution = {
8
8
  mode: PersistedCollectionMode;
9
9
  schemaVersion?: number;
10
+ logicalCollectionId?: string;
10
11
  };
11
- export type ElectronPersistenceMethod = `loadSubset` | `loadResumeSnapshot` | `loadCollectionMetadata` | `scanRows` | `applyCommittedTx` | `reconcileCommittedTx` | `ensureIndex` | `markIndexRemoved` | `pullSince` | `getStreamPosition` | `reserveLeadershipTerm`;
12
+ export type ElectronPersistenceMethod = `loadSubset` | `loadResumeSnapshot` | `loadCollectionMetadata` | `scanRows` | `applyCommittedTx` | `reconcileCommittedTx` | `ensureIndex` | `markIndexRemoved` | `pullSince` | `getStreamPosition` | `claimCacheGeneration` | `rotateCacheGeneration` | `renewCacheGenerationClaim` | `releaseCacheGenerationClaim` | `reserveLeadershipTerm`;
12
13
  export type ElectronPersistencePayloadMap = {
13
14
  loadSubset: {
14
15
  options: LoadSubsetOptions;
15
16
  ctx?: {
16
17
  requiredIndexSignatures?: ReadonlyArray<string>;
18
+ cacheGenerationClaimId?: string;
17
19
  };
18
20
  };
19
21
  loadResumeSnapshot: {
20
22
  ctx?: {
21
23
  requiredIndexSignatures?: ReadonlyArray<string>;
22
24
  includeRows?: boolean;
25
+ cacheGenerationClaimId?: string;
26
+ };
27
+ };
28
+ loadCollectionMetadata: {
29
+ ctx?: {
30
+ cacheGenerationClaimId?: string;
23
31
  };
24
32
  };
25
- loadCollectionMetadata: {};
26
33
  scanRows: {
27
34
  options?: {
28
35
  metadataOnly?: boolean;
29
36
  };
37
+ ctx?: {
38
+ cacheGenerationClaimId?: string;
39
+ };
30
40
  };
31
41
  applyCommittedTx: {
32
42
  tx: PersistedTx<ElectronPersistedRow, ElectronPersistedKey>;
@@ -38,16 +48,48 @@ export type ElectronPersistencePayloadMap = {
38
48
  ensureIndex: {
39
49
  signature: string;
40
50
  spec: PersistedIndexSpec;
51
+ ctx?: {
52
+ cacheGenerationClaimId?: string;
53
+ };
41
54
  };
42
55
  markIndexRemoved: {
43
56
  signature: string;
57
+ ctx?: {
58
+ cacheGenerationClaimId?: string;
59
+ };
44
60
  };
45
61
  pullSince: {
46
62
  fromRowVersion: number;
63
+ ctx?: {
64
+ cacheGenerationClaimId?: string;
65
+ };
66
+ };
67
+ getStreamPosition: {
68
+ ctx?: {
69
+ cacheGenerationClaimId?: string;
70
+ };
71
+ };
72
+ claimCacheGeneration: {};
73
+ rotateCacheGeneration: {
74
+ claimId: string;
75
+ resetMetadata?: {
76
+ key: string;
77
+ value: unknown;
78
+ };
79
+ expectedStorageCollectionId?: string;
80
+ };
81
+ renewCacheGenerationClaim: {
82
+ storageCollectionId: string;
83
+ claimId: string;
84
+ };
85
+ releaseCacheGenerationClaim: {
86
+ claimId: string;
47
87
  };
48
- getStreamPosition: {};
49
88
  reserveLeadershipTerm: {
50
89
  observedTerm: number;
90
+ ctx?: {
91
+ cacheGenerationClaimId?: string;
92
+ };
51
93
  };
52
94
  };
53
95
  export type ElectronPersistenceResultMap = {
@@ -90,6 +132,10 @@ export type ElectronPersistenceResultMap = {
90
132
  latestSeq: number;
91
133
  latestRowVersion: number;
92
134
  };
135
+ claimCacheGeneration: PersistedCacheGenerationClaim;
136
+ rotateCacheGeneration: PersistedCacheGenerationClaim;
137
+ renewCacheGenerationClaim: number | undefined;
138
+ releaseCacheGenerationClaim: null;
93
139
  reserveLeadershipTerm: {
94
140
  latestTerm: number;
95
141
  latestSeq: number;
@@ -108,6 +154,8 @@ export type ElectronPersistenceRequestByMethod = {
108
154
  v: number;
109
155
  requestId: string;
110
156
  collectionId: string;
157
+ /** Required for data operations; preserves eager or managed identity across IPC. */
158
+ storageTarget?: PersistedStorageTarget;
111
159
  resolution?: ElectronPersistenceResolution;
112
160
  method: Method;
113
161
  payload: ElectronPersistencePayloadMap[Method];
@@ -1,4 +1,4 @@
1
- const ELECTRON_PERSISTENCE_PROTOCOL_VERSION = 4;
1
+ const ELECTRON_PERSISTENCE_PROTOCOL_VERSION = 6;
2
2
  const DEFAULT_ELECTRON_PERSISTENCE_CHANNEL = `tanstack-db:sqlite-persistence`;
3
3
  export {
4
4
  DEFAULT_ELECTRON_PERSISTENCE_CHANNEL,
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sources":["../../src/protocol.ts"],"sourcesContent":["import type { LoadSubsetOptions } from '@tanstack/db'\nimport type {\n CommittedTxAnchor,\n PersistedCollectionMode,\n PersistedIndexSpec,\n PersistedKeySetEvidence,\n PersistedTx,\n ReconciledCommittedTx,\n SQLitePullSinceResult,\n} from '@tanstack/db-sqlite-persistence-core'\n\nexport const ELECTRON_PERSISTENCE_PROTOCOL_VERSION = 4 as const\nexport const DEFAULT_ELECTRON_PERSISTENCE_CHANNEL = `tanstack-db:sqlite-persistence`\n\nexport type ElectronPersistedRow = Record<string, unknown>\nexport type ElectronPersistedKey = string | number\n\nexport type ElectronPersistenceResolution = {\n mode: PersistedCollectionMode\n schemaVersion?: number\n}\n\nexport type ElectronPersistenceMethod =\n | `loadSubset`\n | `loadResumeSnapshot`\n | `loadCollectionMetadata`\n | `scanRows`\n | `applyCommittedTx`\n | `reconcileCommittedTx`\n | `ensureIndex`\n | `markIndexRemoved`\n | `pullSince`\n | `getStreamPosition`\n | `reserveLeadershipTerm`\n\nexport type ElectronPersistencePayloadMap = {\n loadSubset: {\n options: LoadSubsetOptions\n ctx?: { requiredIndexSignatures?: ReadonlyArray<string> }\n }\n loadResumeSnapshot: {\n ctx?: {\n requiredIndexSignatures?: ReadonlyArray<string>\n includeRows?: boolean\n }\n }\n loadCollectionMetadata: {}\n scanRows: {\n options?: {\n metadataOnly?: boolean\n }\n }\n applyCommittedTx: {\n tx: PersistedTx<ElectronPersistedRow, ElectronPersistedKey>\n }\n reconcileCommittedTx: {\n tx: PersistedTx<ElectronPersistedRow, ElectronPersistedKey>\n anchor: CommittedTxAnchor\n }\n ensureIndex: {\n signature: string\n spec: PersistedIndexSpec\n }\n markIndexRemoved: {\n signature: string\n }\n pullSince: {\n fromRowVersion: number\n }\n getStreamPosition: {}\n reserveLeadershipTerm: { observedTerm: number }\n}\n\nexport type ElectronPersistenceResultMap = {\n loadSubset: Array<{ key: ElectronPersistedKey; value: ElectronPersistedRow }>\n loadResumeSnapshot: {\n rows: Array<{\n key: ElectronPersistedKey\n value: ElectronPersistedRow\n metadata?: unknown\n }>\n keySet?: PersistedKeySetEvidence\n collectionMetadata: Array<{ key: string; value: unknown }>\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n resetEpoch: number\n }\n loadCollectionMetadata: Array<{ key: string; value: unknown }>\n scanRows: Array<{\n key: ElectronPersistedKey\n value: ElectronPersistedRow\n metadata?: unknown\n }>\n applyCommittedTx: null\n reconcileCommittedTx: ReconciledCommittedTx\n ensureIndex: null\n markIndexRemoved: null\n pullSince: SQLitePullSinceResult<ElectronPersistedKey>\n getStreamPosition: {\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }\n reserveLeadershipTerm: {\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }\n}\n\nexport type ElectronSerializedError = {\n name: string\n message: string\n stack?: string\n code?: string | number\n path?: string | ReadonlyArray<string | number>\n}\n\nexport type ElectronPersistenceRequestByMethod = {\n [Method in ElectronPersistenceMethod]: {\n v: number\n requestId: string\n collectionId: string\n resolution?: ElectronPersistenceResolution\n method: Method\n payload: ElectronPersistencePayloadMap[Method]\n }\n}\n\nexport type ElectronPersistenceRequest<\n TMethod extends ElectronPersistenceMethod = ElectronPersistenceMethod,\n> = ElectronPersistenceRequestByMethod[TMethod]\n\nexport type ElectronPersistenceRequestEnvelope =\n ElectronPersistenceRequestByMethod[ElectronPersistenceMethod]\n\ntype ElectronPersistenceSuccessResponseByMethod = {\n [Method in ElectronPersistenceMethod]: {\n v: number\n requestId: string\n method: Method\n ok: true\n result: ElectronPersistenceResultMap[Method]\n }\n}\n\ntype ElectronPersistenceErrorResponseByMethod = {\n [Method in ElectronPersistenceMethod]: {\n v: number\n requestId: string\n method: Method\n ok: false\n error: ElectronSerializedError\n }\n}\n\nexport type ElectronPersistenceResponse<\n TMethod extends ElectronPersistenceMethod = ElectronPersistenceMethod,\n> =\n | ElectronPersistenceSuccessResponseByMethod[TMethod]\n | ElectronPersistenceErrorResponseByMethod[TMethod]\n\nexport type ElectronPersistenceResponseEnvelope =\n ElectronPersistenceResponse<ElectronPersistenceMethod>\n\nexport type ElectronPersistenceRequestHandler = (\n request: ElectronPersistenceRequestEnvelope,\n) => Promise<ElectronPersistenceResponseEnvelope>\n\nexport type ElectronPersistenceInvoke = (\n channel: string,\n request: ElectronPersistenceRequestEnvelope,\n) => Promise<ElectronPersistenceResponseEnvelope>\n"],"names":[],"mappings":"AAWO,MAAM,wCAAwC;AAC9C,MAAM,uCAAuC;"}
1
+ {"version":3,"file":"protocol.js","sources":["../../src/protocol.ts"],"sourcesContent":["import type { LoadSubsetOptions } from '@tanstack/db'\nimport type {\n CommittedTxAnchor,\n PersistedCacheGenerationClaim,\n PersistedCollectionMode,\n PersistedIndexSpec,\n PersistedKeySetEvidence,\n PersistedStorageTarget,\n PersistedTx,\n ReconciledCommittedTx,\n SQLitePullSinceResult,\n} from '@tanstack/db-sqlite-persistence-core'\n\nexport const ELECTRON_PERSISTENCE_PROTOCOL_VERSION = 6 as const\nexport const DEFAULT_ELECTRON_PERSISTENCE_CHANNEL = `tanstack-db:sqlite-persistence`\n\nexport type ElectronPersistedRow = Record<string, unknown>\nexport type ElectronPersistedKey = string | number\n\nexport type ElectronPersistenceResolution = {\n mode: PersistedCollectionMode\n schemaVersion?: number\n logicalCollectionId?: string\n}\n\nexport type ElectronPersistenceMethod =\n | `loadSubset`\n | `loadResumeSnapshot`\n | `loadCollectionMetadata`\n | `scanRows`\n | `applyCommittedTx`\n | `reconcileCommittedTx`\n | `ensureIndex`\n | `markIndexRemoved`\n | `pullSince`\n | `getStreamPosition`\n | `claimCacheGeneration`\n | `rotateCacheGeneration`\n | `renewCacheGenerationClaim`\n | `releaseCacheGenerationClaim`\n | `reserveLeadershipTerm`\n\nexport type ElectronPersistencePayloadMap = {\n loadSubset: {\n options: LoadSubsetOptions\n ctx?: {\n requiredIndexSignatures?: ReadonlyArray<string>\n cacheGenerationClaimId?: string\n }\n }\n loadResumeSnapshot: {\n ctx?: {\n requiredIndexSignatures?: ReadonlyArray<string>\n includeRows?: boolean\n cacheGenerationClaimId?: string\n }\n }\n loadCollectionMetadata: { ctx?: { cacheGenerationClaimId?: string } }\n scanRows: {\n options?: {\n metadataOnly?: boolean\n }\n ctx?: { cacheGenerationClaimId?: string }\n }\n applyCommittedTx: {\n tx: PersistedTx<ElectronPersistedRow, ElectronPersistedKey>\n }\n reconcileCommittedTx: {\n tx: PersistedTx<ElectronPersistedRow, ElectronPersistedKey>\n anchor: CommittedTxAnchor\n }\n ensureIndex: {\n signature: string\n spec: PersistedIndexSpec\n ctx?: { cacheGenerationClaimId?: string }\n }\n markIndexRemoved: {\n signature: string\n ctx?: { cacheGenerationClaimId?: string }\n }\n pullSince: {\n fromRowVersion: number\n ctx?: { cacheGenerationClaimId?: string }\n }\n getStreamPosition: { ctx?: { cacheGenerationClaimId?: string } }\n claimCacheGeneration: {}\n rotateCacheGeneration: {\n claimId: string\n resetMetadata?: { key: string; value: unknown }\n expectedStorageCollectionId?: string\n }\n renewCacheGenerationClaim: {\n storageCollectionId: string\n claimId: string\n }\n releaseCacheGenerationClaim: { claimId: string }\n reserveLeadershipTerm: {\n observedTerm: number\n ctx?: { cacheGenerationClaimId?: string }\n }\n}\n\nexport type ElectronPersistenceResultMap = {\n loadSubset: Array<{ key: ElectronPersistedKey; value: ElectronPersistedRow }>\n loadResumeSnapshot: {\n rows: Array<{\n key: ElectronPersistedKey\n value: ElectronPersistedRow\n metadata?: unknown\n }>\n keySet?: PersistedKeySetEvidence\n collectionMetadata: Array<{ key: string; value: unknown }>\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n resetEpoch: number\n }\n loadCollectionMetadata: Array<{ key: string; value: unknown }>\n scanRows: Array<{\n key: ElectronPersistedKey\n value: ElectronPersistedRow\n metadata?: unknown\n }>\n applyCommittedTx: null\n reconcileCommittedTx: ReconciledCommittedTx\n ensureIndex: null\n markIndexRemoved: null\n pullSince: SQLitePullSinceResult<ElectronPersistedKey>\n getStreamPosition: {\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }\n claimCacheGeneration: PersistedCacheGenerationClaim\n rotateCacheGeneration: PersistedCacheGenerationClaim\n renewCacheGenerationClaim: number | undefined\n releaseCacheGenerationClaim: null\n reserveLeadershipTerm: {\n latestTerm: number\n latestSeq: number\n latestRowVersion: number\n }\n}\n\nexport type ElectronSerializedError = {\n name: string\n message: string\n stack?: string\n code?: string | number\n path?: string | ReadonlyArray<string | number>\n}\n\nexport type ElectronPersistenceRequestByMethod = {\n [Method in ElectronPersistenceMethod]: {\n v: number\n requestId: string\n collectionId: string\n /** Required for data operations; preserves eager or managed identity across IPC. */\n storageTarget?: PersistedStorageTarget\n resolution?: ElectronPersistenceResolution\n method: Method\n payload: ElectronPersistencePayloadMap[Method]\n }\n}\n\nexport type ElectronPersistenceRequest<\n TMethod extends ElectronPersistenceMethod = ElectronPersistenceMethod,\n> = ElectronPersistenceRequestByMethod[TMethod]\n\nexport type ElectronPersistenceRequestEnvelope =\n ElectronPersistenceRequestByMethod[ElectronPersistenceMethod]\n\ntype ElectronPersistenceSuccessResponseByMethod = {\n [Method in ElectronPersistenceMethod]: {\n v: number\n requestId: string\n method: Method\n ok: true\n result: ElectronPersistenceResultMap[Method]\n }\n}\n\ntype ElectronPersistenceErrorResponseByMethod = {\n [Method in ElectronPersistenceMethod]: {\n v: number\n requestId: string\n method: Method\n ok: false\n error: ElectronSerializedError\n }\n}\n\nexport type ElectronPersistenceResponse<\n TMethod extends ElectronPersistenceMethod = ElectronPersistenceMethod,\n> =\n | ElectronPersistenceSuccessResponseByMethod[TMethod]\n | ElectronPersistenceErrorResponseByMethod[TMethod]\n\nexport type ElectronPersistenceResponseEnvelope =\n ElectronPersistenceResponse<ElectronPersistenceMethod>\n\nexport type ElectronPersistenceRequestHandler = (\n request: ElectronPersistenceRequestEnvelope,\n) => Promise<ElectronPersistenceResponseEnvelope>\n\nexport type ElectronPersistenceInvoke = (\n channel: string,\n request: ElectronPersistenceRequestEnvelope,\n) => Promise<ElectronPersistenceResponseEnvelope>\n"],"names":[],"mappings":"AAaO,MAAM,wCAAwC;AAC9C,MAAM,uCAAuC;"}
@@ -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;
@@ -1,4 +1,4 @@
1
- import { SingleProcessCoordinator, InvalidPersistedCollectionConfigError } from "@tanstack/db-sqlite-persistence-core";
1
+ import { SingleProcessCoordinator, InvalidPersistedCollectionConfigError, resolvePersistedStorageTarget } from "@tanstack/db-sqlite-persistence-core";
2
2
  import { ElectronCollectionCoordinator } from "./electron-coordinator.js";
3
3
  import { DEFAULT_ELECTRON_PERSISTENCE_CHANNEL, ELECTRON_PERSISTENCE_PROTOCOL_VERSION } from "./protocol.js";
4
4
  const DEFAULT_REQUEST_TIMEOUT_MS = 5e3;
@@ -52,13 +52,24 @@ function createSerializableLoadSubsetOptions(subsetOptions) {
52
52
  function createRendererRequestExecutor(options) {
53
53
  const channel = options.channel ?? DEFAULT_ELECTRON_PERSISTENCE_CHANNEL;
54
54
  const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
55
- return async (method, collectionId, payload, resolution) => {
55
+ return async (method, target, payload, resolution) => {
56
+ const storageTarget = typeof target === `string` ? void 0 : target;
57
+ const collectionId = storageTarget ? resolvePersistedStorageTarget(storageTarget).collectionId : target;
58
+ const isGenerationRequest = method === `claimCacheGeneration` || method === `rotateCacheGeneration` || method === `renewCacheGenerationClaim` || method === `releaseCacheGenerationClaim`;
59
+ const managedTarget = storageTarget?.kind === `managed`;
60
+ const logicalCollectionId = resolution?.logicalCollectionId ?? (managedTarget ? options.claimCollections.get(storageTarget.claimId) : isGenerationRequest ? collectionId : void 0);
61
+ if ((managedTarget || isGenerationRequest) && !logicalCollectionId) {
62
+ throw new InvalidPersistedCollectionConfigError(
63
+ `Electron managed cache request requires a known logical Collection ID`
64
+ );
65
+ }
56
66
  const request = {
57
67
  v: ELECTRON_PERSISTENCE_PROTOCOL_VERSION,
58
68
  requestId: createRequestId(),
59
69
  collectionId,
70
+ storageTarget,
60
71
  method,
61
- resolution,
72
+ resolution: managedTarget || isGenerationRequest ? { ...resolution, mode: `sync-present`, logicalCollectionId } : resolution,
62
73
  payload
63
74
  };
64
75
  const response = await withTimeout(
@@ -85,105 +96,219 @@ function createRendererRequestExecutor(options) {
85
96
  return response.result;
86
97
  };
87
98
  }
88
- function createResolvedRendererAdapter(executeRequest, resolution) {
89
- return {
90
- loadSubset: async (collectionId, subsetOptions, ctx) => {
99
+ function createResolvedRendererAdapter(executeRequest, claimCollections, managedCacheGenerations, resolution) {
100
+ const adapter = {
101
+ loadSubset: async (target, subsetOptions, ctx) => {
102
+ const access = resolvePersistedStorageTarget(
103
+ target,
104
+ ctx?.cacheGenerationClaimId
105
+ );
91
106
  const result = await executeRequest(
92
107
  `loadSubset`,
93
- collectionId,
108
+ target,
94
109
  {
95
110
  options: createSerializableLoadSubsetOptions(subsetOptions),
96
- ctx
111
+ ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
97
112
  },
98
113
  resolution
99
114
  );
100
115
  return result;
101
116
  },
102
- loadResumeSnapshot: async (collectionId, ctx) => {
117
+ loadResumeSnapshot: async (target, ctx) => {
118
+ const access = resolvePersistedStorageTarget(
119
+ target,
120
+ ctx?.cacheGenerationClaimId
121
+ );
103
122
  return executeRequest(
104
123
  `loadResumeSnapshot`,
105
- collectionId,
106
- { ctx },
124
+ target,
125
+ { ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },
107
126
  resolution
108
127
  );
109
128
  },
110
- applyCommittedTx: async (collectionId, tx) => {
129
+ applyCommittedTx: async (target, tx) => {
130
+ const access = resolvePersistedStorageTarget(
131
+ target,
132
+ tx.cacheGenerationClaimId
133
+ );
111
134
  await executeRequest(
112
135
  `applyCommittedTx`,
113
- collectionId,
136
+ target,
114
137
  {
115
- tx
138
+ tx: { ...tx, cacheGenerationClaimId: access.claimId }
116
139
  },
117
140
  resolution
118
141
  );
119
142
  },
120
- reconcileCommittedTx: async (collectionId, tx, anchor) => {
143
+ reconcileCommittedTx: async (target, tx, anchor) => {
144
+ const access = resolvePersistedStorageTarget(
145
+ target,
146
+ tx.cacheGenerationClaimId
147
+ );
121
148
  return executeRequest(
122
149
  `reconcileCommittedTx`,
123
- collectionId,
124
- { tx, anchor },
150
+ target,
151
+ { tx: { ...tx, cacheGenerationClaimId: access.claimId }, anchor },
125
152
  resolution
126
153
  );
127
154
  },
128
- loadCollectionMetadata: async (collectionId) => {
155
+ loadCollectionMetadata: async (target, ctx) => {
156
+ const access = resolvePersistedStorageTarget(
157
+ target,
158
+ ctx?.cacheGenerationClaimId
159
+ );
129
160
  return executeRequest(
130
161
  `loadCollectionMetadata`,
131
- collectionId,
132
- {},
162
+ target,
163
+ { ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },
133
164
  resolution
134
165
  );
135
166
  },
136
- scanRows: async (collectionId, options) => {
167
+ scanRows: async (target, options, ctx) => {
168
+ const access = resolvePersistedStorageTarget(
169
+ target,
170
+ ctx?.cacheGenerationClaimId
171
+ );
137
172
  const result = await executeRequest(
138
173
  `scanRows`,
139
- collectionId,
140
- { options },
174
+ target,
175
+ { options, ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },
141
176
  resolution
142
177
  );
143
178
  return result;
144
179
  },
145
- ensureIndex: async (collectionId, signature, spec) => {
180
+ ensureIndex: async (target, signature, spec, ctx) => {
181
+ const access = resolvePersistedStorageTarget(
182
+ target,
183
+ ctx?.cacheGenerationClaimId
184
+ );
146
185
  await executeRequest(
147
186
  `ensureIndex`,
148
- collectionId,
187
+ target,
149
188
  {
150
189
  signature,
151
- spec
190
+ spec,
191
+ ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
152
192
  },
153
193
  resolution
154
194
  );
155
195
  },
156
- markIndexRemoved: async (collectionId, signature) => {
196
+ markIndexRemoved: async (target, signature, ctx) => {
197
+ const access = resolvePersistedStorageTarget(
198
+ target,
199
+ ctx?.cacheGenerationClaimId
200
+ );
157
201
  await executeRequest(
158
202
  `markIndexRemoved`,
159
- collectionId,
203
+ target,
160
204
  {
161
- signature
205
+ signature,
206
+ ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
162
207
  },
163
208
  resolution
164
209
  );
165
210
  },
166
- pullSince: async (collectionId, fromRowVersion) => {
211
+ pullSince: async (target, fromRowVersion, ctx) => {
212
+ const access = resolvePersistedStorageTarget(
213
+ target,
214
+ ctx?.cacheGenerationClaimId
215
+ );
167
216
  const result = await executeRequest(
168
217
  `pullSince`,
169
- collectionId,
218
+ target,
170
219
  {
171
- fromRowVersion
220
+ fromRowVersion,
221
+ ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
172
222
  },
173
223
  resolution
174
224
  );
175
225
  return result;
176
226
  },
177
- getStreamPosition: async (collectionId) => {
178
- return executeRequest(`getStreamPosition`, collectionId, {}, resolution);
227
+ getStreamPosition: async (target, ctx) => {
228
+ const access = resolvePersistedStorageTarget(
229
+ target,
230
+ ctx?.cacheGenerationClaimId
231
+ );
232
+ return executeRequest(
233
+ `getStreamPosition`,
234
+ target,
235
+ { ctx: { ...ctx, cacheGenerationClaimId: access.claimId } },
236
+ resolution
237
+ );
179
238
  },
180
- reserveLeadershipTerm: async (collectionId, observedTerm) => executeRequest(
181
- `reserveLeadershipTerm`,
182
- collectionId,
183
- { observedTerm },
184
- resolution
185
- )
239
+ claimCacheGeneration: async (collectionId) => {
240
+ const claim = await executeRequest(
241
+ `claimCacheGeneration`,
242
+ collectionId,
243
+ {},
244
+ resolution
245
+ );
246
+ claimCollections.set(claim.claimId, collectionId);
247
+ return claim;
248
+ },
249
+ rotateCacheGeneration: async (collectionId, claimId, resetMetadata, expectedStorageCollectionId) => {
250
+ const claim = await executeRequest(
251
+ `rotateCacheGeneration`,
252
+ collectionId,
253
+ { claimId, resetMetadata, expectedStorageCollectionId },
254
+ resolution
255
+ );
256
+ claimCollections.delete(claimId);
257
+ claimCollections.set(claim.claimId, collectionId);
258
+ return claim;
259
+ },
260
+ renewCacheGenerationClaim: (storageCollectionId, claimId) => {
261
+ const collectionId = claimCollections.get(claimId);
262
+ if (!collectionId) {
263
+ throw new InvalidPersistedCollectionConfigError(
264
+ `Unknown electron persisted cache claim "${claimId}"`
265
+ );
266
+ }
267
+ return executeRequest(
268
+ `renewCacheGenerationClaim`,
269
+ collectionId,
270
+ { storageCollectionId, claimId },
271
+ resolution
272
+ );
273
+ },
274
+ releaseCacheGenerationClaim: async (claimId) => {
275
+ const collectionId = claimCollections.get(claimId);
276
+ if (!collectionId) {
277
+ throw new InvalidPersistedCollectionConfigError(
278
+ `Unknown electron persisted cache claim "${claimId}"`
279
+ );
280
+ }
281
+ await executeRequest(
282
+ `releaseCacheGenerationClaim`,
283
+ collectionId,
284
+ { claimId },
285
+ resolution
286
+ );
287
+ claimCollections.delete(claimId);
288
+ },
289
+ reserveLeadershipTerm: async (target, observedTerm, ctx) => {
290
+ const access = resolvePersistedStorageTarget(
291
+ target,
292
+ ctx?.cacheGenerationClaimId
293
+ );
294
+ return executeRequest(
295
+ `reserveLeadershipTerm`,
296
+ target,
297
+ {
298
+ observedTerm,
299
+ ctx: { ...ctx, cacheGenerationClaimId: access.claimId }
300
+ },
301
+ resolution
302
+ );
303
+ }
186
304
  };
305
+ if (!managedCacheGenerations) {
306
+ adapter.claimCacheGeneration = void 0;
307
+ adapter.rotateCacheGeneration = void 0;
308
+ adapter.renewCacheGenerationClaim = void 0;
309
+ adapter.releaseCacheGenerationClaim = void 0;
310
+ }
311
+ return adapter;
187
312
  }
188
313
  function resolveInvoke(options) {
189
314
  if (options.invoke) {
@@ -199,28 +324,31 @@ function resolveInvoke(options) {
199
324
  function createElectronSQLitePersistence(options) {
200
325
  const invoke = resolveInvoke(options);
201
326
  const coordinator = options.coordinator ?? new SingleProcessCoordinator();
327
+ const claimCollections = /* @__PURE__ */ new Map();
202
328
  const executeRequest = createRendererRequestExecutor({
203
329
  invoke,
204
330
  channel: options.channel,
205
- timeoutMs: options.timeoutMs
331
+ timeoutMs: options.timeoutMs,
332
+ claimCollections
206
333
  });
207
334
  const adapterCache = /* @__PURE__ */ new Map();
208
- const getAdapterForCollection = (mode, schemaVersion) => {
209
- const schemaVersionKey = schemaVersion === void 0 ? `schema:default` : `schema:${schemaVersion}`;
210
- const cacheKey = `mode:${mode}|${schemaVersionKey}`;
335
+ const getAdapterForCollection = (collectionId, mode, schemaVersion) => {
336
+ const cacheKey = JSON.stringify([collectionId, mode, schemaVersion]);
211
337
  const cachedAdapter = adapterCache.get(cacheKey);
212
338
  if (cachedAdapter) {
213
339
  return cachedAdapter;
214
340
  }
215
- const adapter = createResolvedRendererAdapter(executeRequest, {
216
- mode,
217
- schemaVersion
218
- });
341
+ const adapter = createResolvedRendererAdapter(
342
+ executeRequest,
343
+ claimCollections,
344
+ options.managedCacheGenerations ?? true,
345
+ { mode, schemaVersion, logicalCollectionId: collectionId }
346
+ );
219
347
  adapterCache.set(cacheKey, adapter);
220
348
  return adapter;
221
349
  };
222
350
  const createCollectionPersistence = (collectionId, mode, schemaVersion) => {
223
- const adapter = getAdapterForCollection(mode, schemaVersion);
351
+ const adapter = getAdapterForCollection(collectionId, mode, schemaVersion);
224
352
  if (coordinator instanceof ElectronCollectionCoordinator) {
225
353
  if (collectionId === void 0) {
226
354
  coordinator.setAdapter(adapter);