@vireocodedev/sqlite 0.2.0 → 0.2.1
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/dist/concurrency/createSqliteOperationCoordinator.d.ts +24 -0
- package/dist/core/sqliteCrud.d.ts +4 -0
- package/dist/core/sqliteEntityFactory.d.ts +134 -0
- package/dist/core/sqliteRequestHandlers.d.ts +7 -0
- package/dist/core/sqliteRuntime.d.ts +7 -0
- package/dist/core/sqliteTypes.d.ts +12 -0
- package/dist/core/sqliteWorkerProtocol.d.ts +18 -0
- package/dist/core/sqliteWorkerRuntime.d.ts +19 -0
- package/dist/devtools/createSqlConsoleClient.d.ts +20 -0
- package/dist/hydration/createHydrationContributorRegistry.d.ts +11 -0
- package/dist/hydration/createHydrationController.d.ts +60 -0
- package/dist/hydration/createHydrationEntityClient.d.ts +16 -0
- package/dist/hydration/createHydrationGate.d.ts +22 -0
- package/dist/hydration/createHydrationRequestQueue.d.ts +22 -0
- package/dist/hydration/createHydrationStatus.d.ts +26 -0
- package/dist/hydration/createLocalReflectionQueue.d.ts +11 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +1508 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle/createDatabaseOwnerStore.d.ts +11 -0
- package/dist/lifecycle/createOfflineDataLifecycle.d.ts +26 -0
- package/dist/lifecycle/createOpfsDatabaseFiles.d.ts +15 -0
- package/dist/offline/hydration/hydratePagedSnapshot.d.ts +14 -0
- package/dist/offline/index.d.ts +7 -0
- package/dist/offline/index.js +99 -0
- package/dist/offline/index.js.map +1 -0
- package/dist/offline/mutations/offlineMutations.d.ts +20 -0
- package/dist/offline/queue/queueingHeaders.d.ts +4 -0
- package/dist/offline/queue/queueingPolicy.d.ts +2 -0
- package/dist/offline/queue/queueingTypes.d.ts +18 -0
- package/dist/offline/status/offlineStatusRuntime.d.ts +2 -0
- package/dist/offline/status/offlineStatusTypes.d.ts +23 -0
- package/dist/offline-queue/createOfflineQueueCapture.d.ts +16 -0
- package/dist/offline-queue/createOfflineQueueClient.d.ts +23 -0
- package/dist/offline-queue/createOfflineQueueStatus.d.ts +18 -0
- package/dist/offline-queue/offlineQueueStateSqlite.d.ts +30 -0
- package/dist/offline-queue/replayOfflineSyncBatch.d.ts +29 -0
- package/dist/queueingHeaders-B7TBifLV.js +20 -0
- package/dist/queueingHeaders-B7TBifLV.js.map +1 -0
- package/dist/runtime/contracts.d.ts +54 -0
- package/dist/runtime/createManagedSqliteRuntime.d.ts +23 -0
- package/dist/runtime/createSqliteEntityClient.d.ts +32 -0
- package/dist/runtime/createSqliteTransport.d.ts +17 -0
- package/dist/runtime/hydrationEntityStateSqlite.d.ts +20 -0
- package/dist/runtime/sqlConsoleSqlite.d.ts +20 -0
- package/dist/sqliteWorkerConfig.d.ts +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/core/sqliteCrud.ts","../src/core/sqliteRequestHandlers.ts","../src/core/sqliteEntityFactory.ts","../src/concurrency/createSqliteOperationCoordinator.ts","../src/devtools/createSqlConsoleClient.ts","../src/hydration/createHydrationContributorRegistry.ts","../src/hydration/createHydrationController.ts","../src/hydration/createHydrationEntityClient.ts","../src/hydration/createHydrationGate.ts","../src/hydration/createHydrationRequestQueue.ts","../src/hydration/createHydrationStatus.ts","../src/hydration/createLocalReflectionQueue.ts","../src/lifecycle/createDatabaseOwnerStore.ts","../src/lifecycle/createOfflineDataLifecycle.ts","../src/lifecycle/createOpfsDatabaseFiles.ts","../src/offline-queue/createOfflineQueueCapture.ts","../src/offline-queue/offlineQueueStateSqlite.ts","../src/offline-queue/createOfflineQueueClient.ts","../src/offline-queue/createOfflineQueueStatus.ts","../src/offline-queue/replayOfflineSyncBatch.ts","../src/runtime/createManagedSqliteRuntime.ts","../src/runtime/createSqliteEntityClient.ts","../src/runtime/createSqliteTransport.ts","../src/core/sqliteRuntime.ts","../src/core/sqliteWorkerRuntime.ts","../src/sqliteWorkerConfig.ts","../src/runtime/hydrationEntityStateSqlite.ts","../src/runtime/sqlConsoleSqlite.ts"],"sourcesContent":["import { type SqliteDatabase } from \"./sqliteTypes\";\n\nexport function runSqliteTransaction(db: SqliteDatabase, action: () => void): void {\n db.exec(\"BEGIN;\");\n\n try {\n action();\n db.exec(\"COMMIT;\");\n } catch (error) {\n db.exec(\"ROLLBACK;\");\n throw error;\n }\n}\n\nexport function listSqliteRows<T>(db: SqliteDatabase, sql: string, mapRow: (row: unknown[]) => T): T[] {\n const statement = db.prepare(sql);\n const rows: T[] = [];\n\n try {\n while (statement.step()) {\n rows.push(mapRow(statement.get([])));\n }\n } finally {\n statement.finalize();\n }\n\n return rows;\n}\n\nexport function deleteSqliteRowsByKey(\n db: SqliteDatabase,\n table: string,\n keyColumn: string,\n values: Array<number | string>,\n): void {\n if (values.length === 0) {\n return;\n }\n\n runSqliteTransaction(db, () => {\n for (const value of values) {\n const statement = db.prepare(`DELETE FROM ${table} WHERE ${keyColumn} = ?;`);\n\n try {\n statement.bind([value]);\n statement.step();\n } finally {\n statement.finalize();\n }\n }\n });\n}\n","import { type SqliteDatabase } from \"./sqliteTypes\";\nimport { type WorkerRequest, type WorkerResponseResult } from \"./sqliteWorkerProtocol\";\n\nexport type SqliteRequestHandler = (\n db: SqliteDatabase,\n request: WorkerRequest,\n) => WorkerResponseResult | Promise<WorkerResponseResult>;\n\nexport type SqliteRequestHandlers = Partial<Record<string, SqliteRequestHandler>>;\n\nexport function createSqliteRequestHandlers<THandlers extends SqliteRequestHandlers>(handlers: THandlers): THandlers {\n return handlers;\n}\n\nexport function mergeSqliteRequestHandlers(...handlersList: SqliteRequestHandlers[]): SqliteRequestHandlers {\n const merged: SqliteRequestHandlers = {};\n\n for (const handlers of handlersList) {\n for (const [operation, handler] of Object.entries(handlers)) {\n if (operation in merged) {\n throw new Error(`SQLite request handler operation \"${operation}\" is registered more than once.`);\n }\n\n merged[operation] = handler;\n }\n }\n\n return merged;\n}\n\nexport async function dispatchSqliteRequest(\n db: SqliteDatabase,\n request: WorkerRequest,\n handlers: SqliteRequestHandlers,\n): Promise<WorkerResponseResult | undefined> {\n const handler = handlers[request.type];\n if (!handler) {\n return undefined;\n }\n\n return await handler(db, request);\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n/* eslint-disable @typescript-eslint/no-empty-object-type */\nimport { deleteSqliteRowsByKey, listSqliteRows, runSqliteTransaction } from \"./sqliteCrud\";\nimport { createSqliteRequestHandlers, type SqliteRequestHandlers } from \"./sqliteRequestHandlers\";\nimport { type SqliteDatabase } from \"./sqliteTypes\";\n\ntype SqliteEntityField<TValue> = {\n column: string;\n id?: boolean;\n toDb?: (value: TValue) => unknown;\n fromDb: (value: unknown) => TValue;\n};\n\ntype SqliteEntityFields = Record<string, SqliteEntityField<any>>;\n\ntype SqliteEntityFieldValue<TField> = TField extends SqliteEntityField<infer TValue> ? TValue : never;\n\ntype SqliteEntityRecordFromFields<TFields extends SqliteEntityFields> = {\n [\n TProperty in keyof TFields as undefined extends SqliteEntityFieldValue<TFields[TProperty]> ? never : TProperty\n ]: SqliteEntityFieldValue<TFields[TProperty]>;\n} & {\n [\n TProperty in keyof TFields as undefined extends SqliteEntityFieldValue<TFields[TProperty]> ? TProperty : never\n ]?: Exclude<SqliteEntityFieldValue<TFields[TProperty]>, undefined>;\n};\n\ntype SqliteEntityIdPropertyName<TFields extends SqliteEntityFields> = {\n [TProperty in keyof TFields]: TFields[TProperty] extends { id: true } ? TProperty : never;\n}[keyof TFields] &\n string;\n\ntype SqliteEntityDeletePayloadFromFields<TFields extends SqliteEntityFields> = Pick<\n SqliteEntityRecordFromFields<TFields>,\n Extract<SqliteEntityIdPropertyName<TFields>, keyof SqliteEntityRecordFromFields<TFields>>\n>;\n\ntype SqliteEntityOperationNames<TSingular extends string, TPlural extends string> = {\n replace: `replace${TPlural}`;\n upsert: `upsert${TSingular}`;\n list: `list${TPlural}`;\n delete: `delete${TPlural}`;\n};\n\nexport type SqliteEntitySseConfig<\n TFields extends SqliteEntityFields,\n TSseEntity extends string,\n TSseContext extends object,\n> = {\n entity: TSseEntity;\n hydrationEntityKey?: string;\n mapCreate?: (\n payload: SqliteEntityRecordFromFields<TFields>,\n context: TSseContext,\n ) => SqliteEntityRecordFromFields<TFields> | null;\n mapUpdate?: (\n payload: SqliteEntityRecordFromFields<TFields>,\n context: TSseContext,\n ) => SqliteEntityRecordFromFields<TFields> | null;\n mapDeleteKeys?: (\n payload: SqliteEntityDeletePayloadFromFields<TFields>,\n context: TSseContext,\n ) => Array<number | string>;\n};\n\nexport type SqliteEntitySpec<\n TFields extends SqliteEntityFields = SqliteEntityFields,\n TSingular extends string = string,\n TPlural extends string = string,\n TRequestKeys extends { replace: string; upsert: string; delete: string } = {\n replace: string;\n upsert: string;\n delete: string;\n },\n TSseEntity extends string = string,\n TSseContext extends object = object,\n> = {\n entityNameSingular: TSingular;\n entityNamePlural: TPlural;\n tableName: string;\n fields: TFields;\n keywordFields?: Array<keyof TFields & string>;\n softDelete?: {\n enabled: boolean;\n columnName?: string;\n };\n orderBy?: string;\n requestKeys: TRequestKeys;\n sse?: SqliteEntitySseConfig<TFields, TSseEntity, TSseContext>;\n hydration?: {\n key: string;\n hydrate: () => Promise<{ rowCount: number }>;\n };\n};\n\nexport type SqliteEntityBundle<\n TFields extends SqliteEntityFields,\n TOperationNames extends { replace: string; upsert: string; list: string; delete: string },\n TRequestKeys extends { replace: string; upsert: string; delete: string },\n TSseEntity extends string,\n TSseContext extends object,\n> = {\n __sqliteEntityBundle: true;\n fields: TFields;\n operationNames: TOperationNames;\n requestKeys: TRequestKeys;\n tableName: string;\n entityNameSingular: string;\n entityNamePlural: string;\n hydration?: {\n key: string;\n hydrate: () => Promise<{ rowCount: number }>;\n };\n replaceRows: (db: SqliteDatabase, rows: SqliteEntityRecordFromFields<TFields>[]) => void;\n upsertRow: (db: SqliteDatabase, row: SqliteEntityRecordFromFields<TFields>) => void;\n listRows: (db: SqliteDatabase) => SqliteEntityRecordFromFields<TFields>[];\n deleteRows: (db: SqliteDatabase, keys: Array<number | string>) => void;\n sse?: SqliteEntitySseConfig<TFields, TSseEntity, TSseContext>;\n requestHandlers: SqliteRequestHandlers;\n operationMap: {\n [TReplace in TOperationNames[\"replace\"]]: {\n request: { [TReplaceKey in TRequestKeys[\"replace\"]]: SqliteEntityRecordFromFields<TFields>[] };\n response: null;\n };\n } & {\n [TUpsert in TOperationNames[\"upsert\"]]: {\n request: { [TUpsertKey in TRequestKeys[\"upsert\"]]: SqliteEntityRecordFromFields<TFields> };\n response: null;\n };\n } & {\n [TList in TOperationNames[\"list\"]]: {\n request: {};\n response: SqliteEntityRecordFromFields<TFields>[];\n };\n } & {\n [TDelete in TOperationNames[\"delete\"]]: {\n request: { [TDeleteKey in TRequestKeys[\"delete\"]]: Array<number | string> };\n response: null;\n };\n };\n};\n\nexport type SqliteEntityOperationMapFromBundle<\n TBundle extends { operationMap: Record<string, { request: unknown; response: unknown }> },\n> = TBundle[\"operationMap\"];\n\nexport type SqliteEntityRecordFromBundle<TBundle> = TBundle extends { upsertRow: (...args: infer TArgs) => void }\n ? TArgs extends [SqliteDatabase, infer TRow]\n ? TRow\n : never\n : never;\n\nfunction buildKeywordValue<TRecord extends Record<string, unknown>>(\n record: TRecord,\n fields: Array<keyof TRecord & string>,\n): string {\n return fields\n .map(field => record[field])\n .filter(value => value != null)\n .map(value => String(value).trim())\n .filter(value => value.length > 0)\n .join(\" \")\n .trim();\n}\n\nfunction assertNonEmpty(value: string, name: string): void {\n if (value.trim().length === 0) {\n throw new Error(`${name} must be a non-empty string.`);\n }\n}\n\nexport function createSqliteEntityBundle<\n const TFields extends SqliteEntityFields,\n const TSingular extends string,\n const TPlural extends string,\n const TRequestKeys extends { replace: string; upsert: string; delete: string },\n const TSseEntity extends string = string,\n const TSseContext extends object = object,\n>(\n spec: SqliteEntitySpec<TFields, TSingular, TPlural, TRequestKeys, TSseEntity, TSseContext>,\n): SqliteEntityBundle<TFields, SqliteEntityOperationNames<TSingular, TPlural>, TRequestKeys, TSseEntity, TSseContext> {\n type TRecord = SqliteEntityRecordFromFields<TFields>;\n const fieldEntries = Object.entries(spec.fields) as Array<[keyof TFields & string, TFields[keyof TFields & string]]>;\n\n assertNonEmpty(spec.entityNameSingular, \"entityNameSingular\");\n assertNonEmpty(spec.entityNamePlural, \"entityNamePlural\");\n assertNonEmpty(spec.tableName, \"tableName\");\n assertNonEmpty(spec.requestKeys.replace, \"requestKeys.replace\");\n assertNonEmpty(spec.requestKeys.upsert, \"requestKeys.upsert\");\n assertNonEmpty(spec.requestKeys.delete, \"requestKeys.delete\");\n\n for (const [property, field] of fieldEntries) {\n assertNonEmpty(field.column, `fields.${property}.column`);\n }\n\n const idFields = fieldEntries.filter(([, field]) => field.id === true);\n if (idFields.length !== 1) {\n throw new Error(`Sqlite entity spec for ${spec.entityNameSingular} must define exactly one field with id: true.`);\n }\n\n const keyField = idFields[0][1];\n const keyColumn = keyField.column;\n\n const entityNamePlural = spec.entityNamePlural;\n\n const operationNames = {\n replace: `replace${entityNamePlural}`,\n upsert: `upsert${spec.entityNameSingular}`,\n list: `list${entityNamePlural}`,\n delete: `delete${entityNamePlural}`,\n } as SqliteEntityOperationNames<TSingular, TPlural>;\n\n const requestKeys = spec.requestKeys;\n\n const softDeleteEnabled = spec.softDelete?.enabled ?? true;\n const softDeleteColumnName = spec.softDelete?.columnName ?? \"deleted\";\n const keywordsColumnName = \"keywords\";\n\n const mappedColumns = fieldEntries.map(([, field]) => field.column);\n const mappedProperties = fieldEntries.map(([property]) => property);\n\n if (new Set(mappedColumns).size !== mappedColumns.length) {\n throw new Error(`Sqlite entity spec for ${spec.entityNameSingular} maps more than one field to the same column.`);\n }\n\n const generatedColumns = [keywordsColumnName, ...(softDeleteEnabled ? [softDeleteColumnName] : [])];\n const conflictingColumn = generatedColumns.find(column => mappedColumns.includes(column));\n if (conflictingColumn) {\n throw new Error(\n `Sqlite entity spec for ${spec.entityNameSingular} maps field column \"${conflictingColumn}\", which is managed by the entity runtime.`,\n );\n }\n\n if (new Set(generatedColumns).size !== generatedColumns.length) {\n throw new Error(`Sqlite entity spec for ${spec.entityNameSingular} configures duplicate generated columns.`);\n }\n\n const insertColumns = [...mappedColumns, keywordsColumnName];\n if (softDeleteEnabled) {\n insertColumns.push(softDeleteColumnName);\n }\n\n const keywordFields = (spec.keywordFields ?? mappedProperties) as Array<keyof TRecord & string>;\n\n function getFieldValueForDb<TProperty extends keyof TRecord & string>(\n property: TProperty,\n field: SqliteEntityField<TRecord[TProperty]>,\n row: TRecord,\n ): unknown {\n const raw = row[property];\n if (field.toDb) {\n return field.toDb(raw);\n }\n\n return raw;\n }\n\n function toInsertValues(row: TRecord): unknown[] {\n const values = fieldEntries.map(([property, field]) =>\n getFieldValueForDb(property as keyof TRecord & string, field as SqliteEntityField<any>, row),\n );\n values.push(buildKeywordValue<TRecord>(row, keywordFields));\n if (softDeleteEnabled) {\n values.push(0);\n }\n\n return values;\n }\n\n const insertPlaceholders = insertColumns.map(() => \"?\").join(\", \");\n const conflictUpdateColumns = insertColumns.filter(column => column !== keyColumn);\n\n function replaceRows(db: SqliteDatabase, rows: TRecord[]): void {\n runSqliteTransaction(db, () => {\n db.exec(`DELETE FROM ${spec.tableName};`);\n\n for (const row of rows) {\n const statement = db.prepare(`\n INSERT INTO ${spec.tableName} (${insertColumns.join(\", \")})\n VALUES (${insertPlaceholders});\n `);\n\n try {\n statement.bind(toInsertValues(row));\n statement.step();\n } finally {\n statement.finalize();\n }\n }\n });\n }\n\n function upsertRow(db: SqliteDatabase, row: TRecord): void {\n const statement = db.prepare(`\n INSERT INTO ${spec.tableName} (${insertColumns.join(\", \")})\n VALUES (${insertPlaceholders})\n ON CONFLICT(${keyColumn}) DO UPDATE SET\n ${conflictUpdateColumns.map(column => `${column} = excluded.${column}`).join(\", \")};\n `);\n\n try {\n statement.bind(toInsertValues(row));\n statement.step();\n } finally {\n statement.finalize();\n }\n }\n\n function listRows(db: SqliteDatabase): TRecord[] {\n const whereClause = softDeleteEnabled ? `WHERE ${softDeleteColumnName} = 0` : \"\";\n const orderBy = spec.orderBy ?? keyColumn;\n\n return listSqliteRows(\n db,\n `\n SELECT ${mappedColumns.join(\", \")}\n FROM ${spec.tableName}\n ${whereClause}\n ORDER BY ${orderBy} ASC;\n `,\n row => {\n const mapped = {} as Record<string, unknown>;\n\n for (let index = 0; index < fieldEntries.length; index += 1) {\n const [property, field] = fieldEntries[index];\n const value = row[index];\n mapped[property] = field.fromDb(value);\n }\n\n return mapped as TRecord;\n },\n );\n }\n\n function deleteRows(db: SqliteDatabase, keys: Array<number | string>): void {\n deleteSqliteRowsByKey(db, spec.tableName, keyColumn, keys);\n }\n\n const requestHandlers = createSqliteRequestHandlers({\n [operationNames.replace]: (db: SqliteDatabase, request: Record<string, unknown>) => {\n replaceRows(db, request[requestKeys.replace] as TRecord[]);\n return null;\n },\n [operationNames.upsert]: (db: SqliteDatabase, request: Record<string, unknown>) => {\n upsertRow(db, request[requestKeys.upsert] as TRecord);\n return null;\n },\n [operationNames.list]: (db: SqliteDatabase) => {\n return listRows(db);\n },\n [operationNames.delete]: (db: SqliteDatabase, request: Record<string, unknown>) => {\n deleteRows(db, request[requestKeys.delete] as Array<number | string>);\n return null;\n },\n }) as SqliteRequestHandlers;\n\n return {\n __sqliteEntityBundle: true,\n tableName: spec.tableName,\n entityNameSingular: spec.entityNameSingular,\n entityNamePlural: spec.entityNamePlural,\n operationNames,\n requestKeys,\n fields: spec.fields,\n hydration: spec.hydration,\n replaceRows,\n upsertRow,\n listRows,\n deleteRows,\n sse: spec.sse,\n requestHandlers,\n operationMap: undefined as unknown as SqliteEntityBundle<\n TFields,\n SqliteEntityOperationNames<TSingular, TPlural>,\n TRequestKeys,\n TSseEntity,\n TSseContext\n >[\"operationMap\"],\n };\n}\n","const sqliteOperationLockOwnerBrand: unique symbol = Symbol(\"sqliteOperationLockOwner\");\n\nexport type SqliteOperationLockOwner = { readonly [sqliteOperationLockOwnerBrand]: true };\n\nexport type ExclusiveLockManager = {\n request: <T>(name: string, options: { mode: \"exclusive\" }, callback: () => Promise<T>) => Promise<T>;\n};\n\nexport type CreateSqliteOperationCoordinatorConfig = {\n lockName: string;\n getLockManager?: () => ExclusiveLockManager | null;\n createAbortReason?: (reason: string) => unknown;\n};\n\nexport type SqliteOperationCoordinator = {\n runDatabaseExclusive: <T>(\n operation: (lockOwner: SqliteOperationLockOwner) => Promise<T>,\n lockOwner?: SqliteOperationLockOwner,\n ) => Promise<T>;\n runEntityExclusive: <T>(\n entityKey: string,\n operation: (lockOwner: SqliteOperationLockOwner) => Promise<T>,\n lockOwner?: SqliteOperationLockOwner,\n ) => Promise<T>;\n runHydrationExclusive: (\n operation: (signal: AbortSignal, lockOwner: SqliteOperationLockOwner) => Promise<void>,\n ) => Promise<void>;\n abortHydration: (reason?: string) => void;\n awaitHydrationIdle: () => Promise<void>;\n};\n\nfunction defaultAbortReason(reason: string): unknown {\n return typeof DOMException === \"undefined\" ? new Error(reason) : new DOMException(reason, \"AbortError\");\n}\n\n/** Creates isolated local queues with optional cross-context serialization through Web Locks. */\nexport function createSqliteOperationCoordinator(\n config: CreateSqliteOperationCoordinatorConfig,\n): SqliteOperationCoordinator {\n const entityOperationTails = new Map<string, Promise<void>>();\n const activeLockOwners = new WeakSet<SqliteOperationLockOwner>();\n let localDatabaseOperationTail: Promise<void> = Promise.resolve();\n let inFlightHydration: Promise<void> | null = null;\n let hydrationAbortController: AbortController | null = null;\n\n const runLocalExclusive = async <T>(operation: () => Promise<T>): Promise<T> => {\n const previous = localDatabaseOperationTail;\n const result = previous.catch(() => undefined).then(operation);\n localDatabaseOperationTail = result.then(\n () => undefined,\n () => undefined,\n );\n return await result;\n };\n\n const runDatabaseExclusive = async <T>(\n operation: (lockOwner: SqliteOperationLockOwner) => Promise<T>,\n lockOwner?: SqliteOperationLockOwner,\n ): Promise<T> => {\n if (lockOwner != null && activeLockOwners.has(lockOwner)) return await operation(lockOwner);\n\n const runOwned = async () => {\n const activeLockOwner = {} as SqliteOperationLockOwner;\n activeLockOwners.add(activeLockOwner);\n try {\n return await operation(activeLockOwner);\n } finally {\n activeLockOwners.delete(activeLockOwner);\n }\n };\n\n const lockManager = config.getLockManager?.() ?? null;\n return lockManager\n ? await lockManager.request(config.lockName, { mode: \"exclusive\" }, runOwned)\n : await runLocalExclusive(runOwned);\n };\n\n const runEntityQueueExclusive = async <T>(entityKey: string, operation: () => Promise<T>): Promise<T> => {\n const previous = entityOperationTails.get(entityKey) ?? Promise.resolve();\n const result = previous.catch(() => undefined).then(operation);\n const tail = result.then(\n () => undefined,\n () => undefined,\n );\n entityOperationTails.set(entityKey, tail);\n\n try {\n return await result;\n } finally {\n if (entityOperationTails.get(entityKey) === tail) entityOperationTails.delete(entityKey);\n }\n };\n\n const runEntityExclusive = async <T>(\n entityKey: string,\n operation: (lockOwner: SqliteOperationLockOwner) => Promise<T>,\n lockOwner?: SqliteOperationLockOwner,\n ): Promise<T> =>\n await runDatabaseExclusive(\n activeLockOwner => runEntityQueueExclusive(entityKey, () => operation(activeLockOwner)),\n lockOwner,\n );\n\n const runHydrationExclusive = async (\n operation: (signal: AbortSignal, lockOwner: SqliteOperationLockOwner) => Promise<void>,\n ): Promise<void> => {\n if (inFlightHydration) return await inFlightHydration;\n\n hydrationAbortController = new AbortController();\n const controller = hydrationAbortController;\n inFlightHydration = runDatabaseExclusive(lockOwner => {\n controller.signal.throwIfAborted();\n return operation(controller.signal, lockOwner);\n }).finally(() => {\n inFlightHydration = null;\n if (hydrationAbortController === controller) hydrationAbortController = null;\n });\n return await inFlightHydration;\n };\n\n return {\n runDatabaseExclusive,\n runEntityExclusive,\n runHydrationExclusive,\n abortHydration(reason = \"SQLite hydration was cancelled.\") {\n hydrationAbortController?.abort((config.createAbortReason ?? defaultAbortReason)(reason));\n },\n async awaitHydrationIdle() {\n await inFlightHydration?.catch(() => undefined);\n },\n };\n}\n","import { type SqliteTransport } from \"../runtime/createSqliteTransport\";\nimport { type SqlExecutionResult, type SqlPagedQueryRequest, type SqlPagedQueryResult } from \"../runtime/contracts\";\n\nexport type SqlConsoleClient = {\n executeScript: (script: string) => Promise<SqlExecutionResult>;\n executePagedQuery: (request: SqlPagedQueryRequest) => Promise<SqlPagedQueryResult>;\n};\n\nexport type CreateSqlConsoleClientConfig = {\n runtime: { shouldUseInMemoryFallback: () => boolean };\n transport: Pick<SqliteTransport, \"sendWorkerRequest\">;\n requestTypes?: { executeScript: string; executePagedQuery: string };\n now?: () => number;\n log?: (message: string, ...details: unknown[]) => void;\n createUnavailableError?: (operation: \"script\" | \"paged-query\") => Error;\n};\n\nfunction defaultNow(): number {\n return typeof performance !== \"undefined\" && typeof performance.now === \"function\" ? performance.now() : Date.now();\n}\n\nfunction stableStringify(value: unknown): string {\n if (value == null || typeof value !== \"object\") return JSON.stringify(value) ?? String(value);\n if (Array.isArray(value)) return `[${value.map(item => stableStringify(item)).join(\",\")}]`;\n\n const entries = Object.entries(value as Record<string, unknown>).sort(([left], [right]) => left.localeCompare(right));\n return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`).join(\",\")}}`;\n}\n\nexport function createSqlConsoleClient(config: CreateSqlConsoleClientConfig): SqlConsoleClient {\n const inFlightPagedQueries = new Map<string, Promise<SqlPagedQueryResult>>();\n const now = config.now ?? defaultNow;\n const requestTypes = config.requestTypes ?? {\n executeScript: \"executeSqlScript\",\n executePagedQuery: \"executePagedQuery\",\n };\n const unavailableError =\n config.createUnavailableError ??\n (operation =>\n new Error(`SQLite ${operation === \"script\" ? \"SQL console\" : \"paged query execution\"} is unavailable.`));\n\n return {\n async executeScript(script) {\n if (config.runtime.shouldUseInMemoryFallback()) throw unavailableError(\"script\");\n return await config.transport.sendWorkerRequest<SqlExecutionResult>({\n type: requestTypes.executeScript,\n script,\n });\n },\n async executePagedQuery(request) {\n if (config.runtime.shouldUseInMemoryFallback()) throw unavailableError(\"paged-query\");\n\n const dedupeKey = stableStringify(request);\n const existing = inFlightPagedQueries.get(dedupeKey);\n if (existing) {\n config.log?.(\"executePagedQuery dedupe hit\");\n return await existing;\n }\n\n const promise = config.transport.sendWorkerRequest<SqlPagedQueryResult>({\n type: requestTypes.executePagedQuery,\n ...request,\n clientSentAtMs: now(),\n });\n inFlightPagedQueries.set(dedupeKey, promise);\n\n try {\n return await promise;\n } finally {\n inFlightPagedQueries.delete(dedupeKey);\n }\n },\n };\n}\n","export type HydrationContributor = {\n key: string;\n hydrate: (signal: AbortSignal) => Promise<{ rowCount: number }>;\n};\n\nexport type HydrationContributorRegistry = {\n register: (contributors: HydrationContributor[]) => void;\n list: () => HydrationContributor[];\n};\n\nexport function createHydrationContributorRegistry(): HydrationContributorRegistry {\n const contributorsByKey = new Map<string, HydrationContributor>();\n\n return {\n register(contributors) {\n for (const contributor of contributors) contributorsByKey.set(contributor.key, contributor);\n },\n list: () => [...contributorsByKey.values()].sort((left, right) => left.key.localeCompare(right.key)),\n };\n}\n","import { type HydrationContributor } from \"./createHydrationContributorRegistry\";\nimport { type HydrationRequestBatch, type HydrationRequestQueue } from \"./createHydrationRequestQueue\";\nimport { type SqliteHydrationEntityStateRecord } from \"../runtime/contracts\";\n\nexport type RemoteHydrationVersion = { entity: string; revision: number };\nexport type HydrationRunContext = { heartbeatEnabled?: boolean; heartbeatConnected?: boolean };\nexport type HydrationLogDetails = Record<string, unknown>;\n\nexport type HydrationControllerEvents = {\n registerEntities: (keys: string[]) => void;\n markRunning: (running: boolean) => void;\n markEntityRunning: (key: string) => void;\n markEntitySuccess: (key: string, rowCount: number) => void;\n markEntityError: (key: string, message: string) => void;\n startGate: () => void;\n resetGate: () => void;\n finishGate: () => void;\n markDataReady: () => void;\n setErrorMessage: (message: string | null) => void;\n};\n\nexport type CreateHydrationControllerConfig<TLockOwner = unknown> = {\n getContributors: () => HydrationContributor[];\n entityStateClient: {\n list: () => Promise<SqliteHydrationEntityStateRecord[]>;\n upsert: (state: SqliteHydrationEntityStateRecord) => Promise<void>;\n };\n requests: Pick<HydrationRequestQueue, \"consume\" | \"hasPending\" | \"rejectPending\" | \"settle\" | \"reject\">;\n runHydrationExclusive: (operation: (signal: AbortSignal, lockOwner: TLockOwner) => Promise<void>) => Promise<void>;\n runEntityExclusive: (entityKey: string, operation: () => Promise<void>, lockOwner: TLockOwner) => Promise<void>;\n fetchRemoteVersions: (entityKeys: string[], signal: AbortSignal) => Promise<{ versions: RemoteHydrationVersion[] }>;\n events: HydrationControllerEvents;\n remoteVersionsTimeoutMs: number;\n entityTimeoutMs: (entityKey: string) => number;\n retryBaseMs: number;\n retryMaxMs: number;\n retryExponentLimit?: number;\n elapsedNow?: () => number;\n timestampNow?: () => number;\n schedule?: (callback: () => void, delayMs: number) => ReturnType<typeof setTimeout>;\n cancelScheduled?: (handle: ReturnType<typeof setTimeout>) => void;\n isCancellationError?: (error: unknown) => boolean;\n debug?: (message: string, details?: HydrationLogDetails) => void;\n warn?: (message: string, details?: HydrationLogDetails) => void;\n error?: (message: string, details?: HydrationLogDetails) => void;\n};\n\nexport type HydrationController = {\n run: (context?: HydrationRunContext) => Promise<void>;\n requestRetry: () => void;\n reset: (pendingRequestReason: string) => void;\n cancelScheduledRetry: () => void;\n dispose: () => void;\n isRunning: () => boolean;\n};\n\nfunction defaultElapsedNow(): number {\n return typeof performance === \"undefined\" ? Date.now() : performance.now();\n}\n\nfunction abortReason(message: string, name: string): Error {\n return typeof DOMException === \"undefined\" ? new Error(message) : new DOMException(message, name);\n}\n\nexport function createHydrationController<TLockOwner = unknown>(\n config: CreateHydrationControllerConfig<TLockOwner>,\n): HydrationController {\n const elapsedNow = config.elapsedNow ?? defaultElapsedNow;\n const timestampNow = config.timestampNow ?? Date.now;\n const schedule = config.schedule ?? setTimeout;\n const cancelScheduled = config.cancelScheduled ?? clearTimeout;\n const isCancellationError =\n config.isCancellationError ??\n (error => typeof DOMException !== \"undefined\" && error instanceof DOMException && error.name === \"AbortError\");\n let runningPromise: Promise<void> | null = null;\n let retryCount = 0;\n let retryHandle: ReturnType<typeof setTimeout> | null = null;\n let disposed = false;\n\n const clearRetry = () => {\n if (retryHandle != null) cancelScheduled(retryHandle);\n retryHandle = null;\n };\n\n const scheduleRetry = (message: string) => {\n if (retryHandle != null || disposed) return;\n const retryNumber = ++retryCount;\n const retryDelayMs = Math.min(\n config.retryBaseMs * 2 ** Math.min(retryNumber - 1, config.retryExponentLimit ?? 6),\n config.retryMaxMs,\n );\n config.debug?.(message, { retryNumber, retryDelayMs });\n retryHandle = schedule(() => {\n retryHandle = null;\n if (!disposed) config.events.resetGate();\n }, retryDelayMs);\n };\n\n const withTimeout = async <T>(\n operation: (signal: AbortSignal) => Promise<T>,\n parentSignal: AbortSignal,\n timeoutMs: number,\n timeoutMessage: string,\n ): Promise<T> => {\n const controller = new AbortController();\n let timedOut = false;\n const abortFromParent = () => controller.abort(parentSignal.reason);\n parentSignal.addEventListener(\"abort\", abortFromParent, { once: true });\n const timeoutHandle = schedule(() => {\n timedOut = true;\n controller.abort(abortReason(timeoutMessage, \"TimeoutError\"));\n }, timeoutMs);\n\n try {\n const result = await operation(controller.signal);\n controller.signal.throwIfAborted();\n return result;\n } catch (error) {\n if (timedOut) throw new Error(timeoutMessage);\n throw error;\n } finally {\n cancelScheduled(timeoutHandle);\n parentSignal.removeEventListener(\"abort\", abortFromParent);\n }\n };\n\n const execute = async (context: HydrationRunContext): Promise<void> => {\n const contributors = config.getContributors();\n config.events.registerEntities(contributors.map(entity => entity.key));\n let activeRequestBatch: HydrationRequestBatch | null = null;\n\n try {\n await config.runHydrationExclusive(async (hydrationSignal, databaseLockOwner) => {\n const requestBatch = config.requests.consume();\n activeRequestBatch = requestBatch;\n const hydrationStartedAt = elapsedNow();\n config.events.markRunning(true);\n config.events.startGate();\n config.events.setErrorMessage(null);\n config.debug?.(\"Hydration started\", {\n entityCount: contributors.length,\n heartbeatEnabled: context.heartbeatEnabled ?? false,\n heartbeatConnected: context.heartbeatConnected ?? false,\n });\n\n try {\n const hydrationEntityKeys = contributors.map(entity => entity.key).sort((a, b) => a.localeCompare(b));\n const localStateStartedAt = elapsedNow();\n const localStateList = await config.entityStateClient.list();\n config.debug?.(\"Loaded local hydration metadata\", {\n elapsedMs: Math.round(elapsedNow() - localStateStartedAt),\n entityCount: localStateList.length,\n });\n const localStateByKey = new Map(localStateList.map(state => [state.entityKey, state]));\n const remoteRevisionByKey = new Map<string, number>();\n const failedEntityKeys = new Set<string>();\n let hydrationSucceeded = true;\n let remoteRevisionValidationSucceeded = true;\n let canCompareAgainstRemoteVersions = true;\n\n const remoteVersionsStartedAt = elapsedNow();\n try {\n const remoteVersions = await withTimeout(\n signal => config.fetchRemoteVersions(hydrationEntityKeys, signal),\n hydrationSignal,\n config.remoteVersionsTimeoutMs,\n \"Fetching hydration versions timed out.\",\n );\n for (const version of remoteVersions.versions) {\n remoteRevisionByKey.set(version.entity.toLowerCase(), Number(version.revision ?? 0));\n }\n config.debug?.(\"Fetched remote entity revisions\", {\n elapsedMs: Math.round(elapsedNow() - remoteVersionsStartedAt),\n entityCount: remoteVersions.versions.length,\n });\n } catch (error) {\n if (hydrationSignal.aborted) throw error;\n canCompareAgainstRemoteVersions = false;\n remoteRevisionValidationSucceeded = false;\n config.warn?.(\"Could not fetch remote entity revisions; every entity will be hydrated\", {\n elapsedMs: Math.round(elapsedNow() - remoteVersionsStartedAt),\n error,\n });\n }\n\n for (const entity of contributors) {\n hydrationSignal.throwIfAborted();\n const entityStartedAt = elapsedNow();\n config.events.markEntityRunning(entity.key);\n const localState = localStateByKey.get(entity.key);\n const remoteRevision = remoteRevisionByKey.get(entity.key.toLowerCase()) ?? 0;\n const canCompareEntity =\n canCompareAgainstRemoteVersions && remoteRevisionByKey.has(entity.key.toLowerCase());\n const canClearValidationOnlyStaleState =\n canCompareEntity &&\n localState?.isStale === true &&\n localState.lastError == null &&\n localState.appliedRevision === remoteRevision;\n const shouldHydrate =\n requestBatch.forcedKeys.has(entity.key) ||\n !canCompareEntity ||\n localState == null ||\n (localState.isStale && !canClearValidationOnlyStaleState) ||\n localState.appliedRevision !== remoteRevision;\n\n if (!shouldHydrate) {\n if (canClearValidationOnlyStaleState) {\n await config.entityStateClient.upsert({ ...localState, isStale: false, lastError: null });\n }\n config.events.markEntitySuccess(entity.key, localState.lastRowCount ?? 0);\n config.debug?.(\"Entity is current; skipped hydration\", {\n entity: entity.key,\n elapsedMs: Math.round(elapsedNow() - entityStartedAt),\n revision: remoteRevision,\n rowCount: localState.lastRowCount ?? 0,\n });\n continue;\n }\n\n config.debug?.(\"Hydrating entity\", {\n entity: entity.key,\n reason: requestBatch.forcedKeys.has(entity.key)\n ? \"manual-request\"\n : !canCompareEntity\n ? \"remote-revision-unavailable\"\n : localState == null\n ? \"no-local-state\"\n : localState.isStale\n ? \"local-state-stale\"\n : \"revision-mismatch\",\n localRevision: localState?.appliedRevision ?? null,\n remoteRevision: canCompareEntity ? remoteRevision : null,\n });\n\n await config.runEntityExclusive(\n entity.key,\n async () => {\n try {\n const timeoutMs = config.entityTimeoutMs(entity.key);\n const result = await withTimeout(\n signal => entity.hydrate(signal),\n hydrationSignal,\n timeoutMs,\n `Hydration timed out after ${timeoutMs}ms for entity \"${entity.key}\".`,\n );\n hydrationSignal.throwIfAborted();\n const latestState = (await config.entityStateClient.list()).find(\n state => state.entityKey === entity.key,\n );\n hydrationSignal.throwIfAborted();\n const appliedRevision = canCompareEntity\n ? Math.max(remoteRevision, latestState?.appliedRevision ?? 0)\n : (latestState?.appliedRevision ?? localState?.appliedRevision ?? 0);\n\n await config.entityStateClient.upsert({\n entityKey: entity.key,\n appliedRevision,\n isStale: !canCompareEntity,\n lastHydratedAt: timestampNow(),\n lastRowCount: result.rowCount,\n lastError: null,\n });\n config.events.markEntitySuccess(entity.key, result.rowCount);\n config.debug?.(\"Entity hydration completed\", {\n entity: entity.key,\n elapsedMs: Math.round(elapsedNow() - entityStartedAt),\n rowCount: result.rowCount,\n });\n } catch (error) {\n if (hydrationSignal.aborted) throw error;\n hydrationSucceeded = false;\n failedEntityKeys.add(entity.key);\n const message = error instanceof Error ? error.message : \"Unknown hydration error.\";\n config.events.setErrorMessage(message);\n await config.entityStateClient.upsert({\n entityKey: entity.key,\n appliedRevision: localState?.appliedRevision ?? 0,\n isStale: true,\n lastHydratedAt: localState?.lastHydratedAt ?? null,\n lastRowCount: localState?.lastRowCount ?? null,\n lastError: message,\n });\n config.events.markEntityError(entity.key, message);\n config.error?.(\"Entity hydration failed\", {\n entity: entity.key,\n elapsedMs: Math.round(elapsedNow() - entityStartedAt),\n error,\n });\n }\n },\n databaseLockOwner,\n );\n }\n\n if (hydrationSucceeded && remoteRevisionValidationSucceeded) {\n retryCount = 0;\n clearRetry();\n config.events.markDataReady();\n } else {\n scheduleRetry(\"Hydration retry scheduled\");\n }\n config.requests.settle(requestBatch, failedEntityKeys);\n } finally {\n config.debug?.(\"Hydration finished\", { elapsedMs: Math.round(elapsedNow() - hydrationStartedAt) });\n config.events.markRunning(false);\n if (config.requests.hasPending()) config.events.resetGate();\n else config.events.finishGate();\n }\n });\n } catch (error) {\n if (activeRequestBatch) config.requests.reject(activeRequestBatch, error);\n if (isCancellationError(error)) {\n config.debug?.(\"Hydration cancelled\", {\n reason: error instanceof Error ? error.message : \"Request cancelled\",\n });\n return;\n }\n\n const message = error instanceof Error ? error.message : \"Unknown SQLite storage error.\";\n config.events.setErrorMessage(message);\n for (const entity of contributors) config.events.markEntityError(entity.key, message);\n config.error?.(\"Hydration failed unexpectedly\", { error });\n scheduleRetry(\"Hydration retry scheduled after an unexpected SQLite failure\");\n }\n };\n\n return {\n async run(context = {}) {\n if (disposed) throw new Error(\"Hydration controller has been disposed.\");\n runningPromise ??= execute(context).finally(() => {\n runningPromise = null;\n });\n return await runningPromise;\n },\n requestRetry() {\n clearRetry();\n config.events.setErrorMessage(null);\n config.events.resetGate();\n },\n reset(pendingRequestReason) {\n config.requests.rejectPending(pendingRequestReason);\n clearRetry();\n retryCount = 0;\n config.events.setErrorMessage(null);\n config.events.resetGate();\n },\n cancelScheduledRetry: clearRetry,\n dispose() {\n disposed = true;\n clearRetry();\n },\n isRunning: () => runningPromise != null,\n };\n}\n","import { type InMemorySqliteStore } from \"../runtime/createManagedSqliteRuntime\";\nimport { type SqliteTransport } from \"../runtime/createSqliteTransport\";\nimport { type SqliteHydrationEntityStateRecord } from \"../runtime/contracts\";\n\nexport type HydrationEntityClientRuntime = {\n shouldUseInMemoryFallback: () => boolean;\n registerInMemoryStore: (store: InMemorySqliteStore) => () => void;\n};\n\nexport type HydrationEntityClient = {\n list: () => Promise<SqliteHydrationEntityStateRecord[]>;\n upsert: (state: SqliteHydrationEntityStateRecord) => Promise<void>;\n dispose: () => void;\n};\n\nexport function createHydrationEntityClient(config: {\n runtime: HydrationEntityClientRuntime;\n transport: Pick<SqliteTransport, \"sendWorkerRequest\">;\n}): HydrationEntityClient {\n const inMemoryStates = new Map<string, SqliteHydrationEntityStateRecord>();\n const unregisterStore = config.runtime.registerInMemoryStore(inMemoryStates);\n\n return {\n async list() {\n if (config.runtime.shouldUseInMemoryFallback()) {\n return [...inMemoryStates.values()].sort((left, right) => left.entityKey.localeCompare(right.entityKey));\n }\n return await config.transport.sendWorkerRequest<SqliteHydrationEntityStateRecord[]>({\n type: \"listHydrationEntityStates\",\n });\n },\n async upsert(state) {\n if (config.runtime.shouldUseInMemoryFallback()) {\n inMemoryStates.set(state.entityKey, state);\n return;\n }\n await config.transport.sendWorkerRequest<null>({ type: \"upsertHydrationEntityState\", state });\n },\n dispose: unregisterStore,\n };\n}\n","export type HydrationGatePhase = \"idle\" | \"running\" | \"finished\";\n\nexport type HydrationGateSnapshot = {\n phase: HydrationGatePhase;\n startedAt: number | null;\n dataReady: boolean;\n errorMessage: string | null;\n retryRequestTick: number;\n};\n\nexport type HydrationGate = {\n getSnapshot: () => HydrationGateSnapshot;\n subscribe: (listener: (snapshot: HydrationGateSnapshot) => void) => () => void;\n setErrorMessage: (message: string | null) => void;\n requestRetry: () => void;\n reset: () => void;\n start: () => void;\n finish: () => void;\n markDataReady: () => void;\n};\n\nexport type CreateHydrationGateConfig = { now?: () => number };\n\nconst INITIAL_SNAPSHOT: HydrationGateSnapshot = {\n phase: \"idle\",\n startedAt: null,\n dataReady: false,\n errorMessage: null,\n retryRequestTick: 0,\n};\n\nexport function createHydrationGate(config: CreateHydrationGateConfig = {}): HydrationGate {\n const now = config.now ?? Date.now;\n const listeners = new Set<(snapshot: HydrationGateSnapshot) => void>();\n let snapshot = INITIAL_SNAPSHOT;\n\n const publish = (next: HydrationGateSnapshot) => {\n if (\n next.phase === snapshot.phase &&\n next.startedAt === snapshot.startedAt &&\n next.dataReady === snapshot.dataReady &&\n next.errorMessage === snapshot.errorMessage &&\n next.retryRequestTick === snapshot.retryRequestTick\n ) {\n return;\n }\n snapshot = next;\n for (const listener of listeners) listener(snapshot);\n };\n\n return {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n setErrorMessage(errorMessage) {\n publish({ ...snapshot, errorMessage });\n },\n requestRetry() {\n publish({ ...snapshot, retryRequestTick: snapshot.retryRequestTick + 1 });\n },\n reset() {\n publish({ ...snapshot, phase: \"idle\", startedAt: null, dataReady: false });\n },\n start() {\n publish({ ...snapshot, phase: \"running\", startedAt: snapshot.startedAt ?? now() });\n },\n finish() {\n publish({ ...snapshot, phase: \"finished\" });\n },\n markDataReady() {\n publish({ ...snapshot, dataReady: true });\n },\n };\n}\n","export type HydrationRequest = {\n keys: Set<string>;\n resolve: () => void;\n reject: (error: Error) => void;\n};\n\nexport type HydrationRequestBatch = {\n requests: HydrationRequest[];\n forcedKeys: Set<string>;\n};\n\nexport type HydrationRequestQueue = {\n request: (keys: string[]) => Promise<void>;\n consume: () => HydrationRequestBatch;\n hasPending: () => boolean;\n rejectPending: (reason: string) => void;\n settle: (batch: HydrationRequestBatch, failedKeys: ReadonlySet<string>) => void;\n reject: (batch: HydrationRequestBatch, error: unknown) => void;\n};\n\nexport type CreateHydrationRequestQueueConfig = {\n onRequestQueued?: () => void;\n createUnexpectedError?: () => Error;\n};\n\nexport function createHydrationRequestQueue(config: CreateHydrationRequestQueueConfig = {}): HydrationRequestQueue {\n const pendingRequests: HydrationRequest[] = [];\n\n return {\n request(keys) {\n const normalizedKeys = new Set(keys.map(key => key.trim()).filter(Boolean));\n if (normalizedKeys.size === 0) return Promise.resolve();\n\n const promise = new Promise<void>((resolve, reject) => {\n pendingRequests.push({ keys: normalizedKeys, resolve, reject });\n });\n config.onRequestQueued?.();\n return promise;\n },\n consume() {\n const requests = pendingRequests.splice(0);\n return { requests, forcedKeys: new Set(requests.flatMap(request => [...request.keys])) };\n },\n hasPending: () => pendingRequests.length > 0,\n rejectPending(reason) {\n const error = new Error(reason);\n for (const request of pendingRequests.splice(0)) request.reject(error);\n },\n settle(batch, failedKeys) {\n for (const request of batch.requests) {\n const failedRequestedKeys = [...request.keys].filter(key => failedKeys.has(key));\n if (failedRequestedKeys.length === 0) request.resolve();\n else request.reject(new Error(`Hydration failed for: ${failedRequestedKeys.join(\", \")}.`));\n }\n },\n reject(batch, error) {\n const requestError =\n error instanceof Error\n ? error\n : (config.createUnexpectedError?.() ?? new Error(\"Hydration failed unexpectedly.\"));\n for (const request of batch.requests) request.reject(requestError);\n },\n };\n}\n","export type HydrationEntityStatus = {\n key: string;\n state: \"idle\" | \"running\" | \"success\" | \"error\";\n lastAttemptAt: number | null;\n lastSuccessAt: number | null;\n rowCount: number | null;\n errorMessage: string | null;\n};\n\nexport type HydrationStatusSnapshot = {\n entities: HydrationEntityStatus[];\n running: boolean;\n};\n\nexport type HydrationStatus = {\n getSnapshot: () => HydrationStatusSnapshot;\n subscribe: (listener: (snapshot: HydrationStatusSnapshot) => void) => () => void;\n registerEntities: (keys: string[]) => void;\n markRunning: (running: boolean) => void;\n markEntityRunning: (key: string) => void;\n markEntitySuccess: (key: string, rowCount: number) => void;\n markEntityError: (key: string, errorMessage: string) => void;\n reset: () => void;\n};\n\nexport type CreateHydrationStatusConfig = { now?: () => number };\n\nfunction idleEntity(key: string): HydrationEntityStatus {\n return {\n key,\n state: \"idle\",\n lastAttemptAt: null,\n lastSuccessAt: null,\n rowCount: null,\n errorMessage: null,\n };\n}\n\nexport function createHydrationStatus(config: CreateHydrationStatusConfig = {}): HydrationStatus {\n const now = config.now ?? Date.now;\n const listeners = new Set<(snapshot: HydrationStatusSnapshot) => void>();\n let entitiesByKey: Record<string, HydrationEntityStatus> = {};\n let running = false;\n\n const getSnapshot = (): HydrationStatusSnapshot => ({\n running,\n entities: Object.values(entitiesByKey).sort((left, right) => left.key.localeCompare(right.key)),\n });\n const publish = () => {\n const snapshot = getSnapshot();\n for (const listener of listeners) listener(snapshot);\n };\n const upsert = (key: string, status: Partial<HydrationEntityStatus>) => {\n entitiesByKey = { ...entitiesByKey, [key]: { ...(entitiesByKey[key] ?? idleEntity(key)), ...status } };\n publish();\n };\n\n return {\n getSnapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n registerEntities(keys) {\n let changed = false;\n let next = entitiesByKey;\n for (const key of keys) {\n if (next[key]) continue;\n changed = true;\n next = { ...next, [key]: idleEntity(key) };\n }\n if (changed) {\n entitiesByKey = next;\n publish();\n }\n },\n markRunning(value) {\n if (running === value) return;\n running = value;\n publish();\n },\n markEntityRunning(key) {\n upsert(key, { state: \"running\", lastAttemptAt: now(), errorMessage: null });\n },\n markEntitySuccess(key, rowCount) {\n upsert(key, { state: \"success\", lastSuccessAt: now(), rowCount, errorMessage: null });\n },\n markEntityError(key, errorMessage) {\n upsert(key, { state: \"error\", errorMessage });\n },\n reset() {\n if (!running && Object.keys(entitiesByKey).length === 0) return;\n running = false;\n entitiesByKey = {};\n publish();\n },\n };\n}\n","export type LocalReflectionQueue = {\n enqueue: (entityKey: string, operation: () => Promise<void>) => void;\n awaitIdle: () => Promise<void>;\n getPendingCount: () => number;\n};\n\nexport type CreateLocalReflectionQueueConfig = {\n runEntityExclusive: (entityKey: string, operation: () => Promise<void>) => Promise<void>;\n onError?: (entityKey: string, error: unknown) => void;\n onPendingCountChange?: (pendingCount: number) => void;\n};\n\nexport function createLocalReflectionQueue(config: CreateLocalReflectionQueueConfig): LocalReflectionQueue {\n const pending = new Set<Promise<void>>();\n const publishCount = () => config.onPendingCountChange?.(pending.size);\n\n return {\n enqueue(entityKey, operation) {\n const reflection = config.runEntityExclusive(entityKey, operation);\n pending.add(reflection);\n publishCount();\n void reflection\n .catch(error => config.onError?.(entityKey, error))\n .finally(() => {\n pending.delete(reflection);\n publishCount();\n });\n },\n async awaitIdle() {\n while (pending.size > 0) await Promise.allSettled([...pending]);\n },\n getPendingCount: () => pending.size,\n };\n}\n","export type KeyValueStorage = Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n\nexport type DatabaseOwnerStore = {\n read: () => string | null;\n persist: (owner: string) => void;\n clear: () => void;\n};\n\nexport type CreateDatabaseOwnerStoreConfig = {\n key: string;\n getStorage: () => KeyValueStorage;\n};\n\nexport function createDatabaseOwnerStore({ key, getStorage }: CreateDatabaseOwnerStoreConfig): DatabaseOwnerStore {\n return {\n read() {\n const owner = getStorage().getItem(key);\n return owner != null && owner.length > 0 ? owner : null;\n },\n persist(owner) {\n getStorage().setItem(key, owner);\n },\n clear() {\n getStorage().removeItem(key);\n },\n };\n}\n","export type OfflineDataLifecyclePhase = \"hydration\" | \"queue\" | \"storage\";\nexport type OfflineDataLifecycleOptions = { onPhase?: (phase: OfflineDataLifecyclePhase) => void };\n\nexport type CreateOfflineDataLifecycleConfig = {\n readOwner: () => string | null;\n persistOwner: (owner: string) => void;\n resolveDatabaseFileName: (owner: string, legacyOwner: string | null) => string;\n abortHydration: (reason: string) => void;\n awaitHydrationIdle: () => Promise<void>;\n awaitLocalReflectionIdle: () => Promise<void>;\n awaitQueueFlushIdle: () => Promise<void>;\n resetHydrationGate: () => void;\n resetHydrationStatus: () => void;\n resetQueueStatus: () => void;\n resetRuntime: () => void;\n clearInMemoryStores: () => void;\n deleteDatabaseFiles: (fileName?: string) => Promise<void>;\n hydrationAbortReason?: string;\n};\n\nexport type OfflineDataLifecycle = {\n release: (options?: OfflineDataLifecycleOptions) => Promise<void>;\n purge: (options?: OfflineDataLifecycleOptions) => Promise<void>;\n ensureOwnedBy: (owner: string) => Promise<boolean>;\n};\n\nexport function createOfflineDataLifecycle(config: CreateOfflineDataLifecycleConfig): OfflineDataLifecycle {\n let inFlightOwnerReconciliation: Promise<boolean> | null = null;\n\n const quiesce = async (options: OfflineDataLifecycleOptions) => {\n options.onPhase?.(\"hydration\");\n config.abortHydration(config.hydrationAbortReason ?? \"SQLite hydration was cancelled before purging local data.\");\n await config.awaitHydrationIdle();\n await config.awaitLocalReflectionIdle();\n\n options.onPhase?.(\"queue\");\n await config.awaitQueueFlushIdle();\n config.resetHydrationGate();\n config.resetHydrationStatus();\n config.resetQueueStatus();\n config.resetRuntime();\n config.clearInMemoryStores();\n };\n\n const release = async (options: OfflineDataLifecycleOptions = {}) => {\n await quiesce(options);\n options.onPhase?.(\"storage\");\n };\n\n const purge = async (options: OfflineDataLifecycleOptions = {}) => {\n const owner = config.readOwner();\n const fileName = owner == null ? undefined : config.resolveDatabaseFileName(owner, owner);\n await quiesce(options);\n options.onPhase?.(\"storage\");\n await config.deleteDatabaseFiles(fileName);\n };\n\n const reconcileOwner = async (owner: string): Promise<boolean> => {\n const previousOwner = config.readOwner();\n if (previousOwner === owner) {\n config.resolveDatabaseFileName(owner, previousOwner);\n return false;\n }\n\n if (previousOwner != null) await release();\n config.persistOwner(owner);\n config.resolveDatabaseFileName(owner, previousOwner);\n return previousOwner != null;\n };\n\n return {\n release,\n purge,\n async ensureOwnedBy(owner) {\n inFlightOwnerReconciliation ??= reconcileOwner(owner).finally(() => {\n inFlightOwnerReconciliation = null;\n });\n return await inFlightOwnerReconciliation;\n },\n };\n}\n","import { type KeyValueStorage } from \"./createDatabaseOwnerStore\";\n\nexport type OpfsDatabaseFiles = {\n getFileName: (owner: string, legacyOwner: string | null) => string;\n deleteFiles: (fileName?: string) => Promise<void>;\n};\n\nexport type CreateOpfsDatabaseFilesConfig = {\n legacyFileName: string;\n mappingKeyPrefix: string;\n getStorage: () => KeyValueStorage;\n getDirectory: () => Promise<FileSystemDirectoryHandle> | null;\n createScopedFileName: (encodedOwner: string) => string;\n lockRetryDelayMs?: number;\n wait?: (delayMs: number) => Promise<void>;\n};\n\nconst LOCKED_ERROR_NAMES: ReadonlySet<string> = new Set([\n \"NoModificationAllowedError\",\n \"InvalidStateError\",\n \"InvalidModificationError\",\n]);\n\nfunction encodeOwner(owner: string): string {\n return Array.from(new TextEncoder().encode(owner), byte => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nfunction isErrorNamed(error: unknown, name: string): boolean {\n return error instanceof Error && error.name === name;\n}\n\nasync function listDatabaseEntryNames(root: FileSystemDirectoryHandle, fileName: string): Promise<string[]> {\n const iterableRoot = root as FileSystemDirectoryHandle & { keys?: () => AsyncIterableIterator<string> };\n if (typeof iterableRoot.keys !== \"function\") return [fileName];\n\n const names: string[] = [];\n for await (const name of iterableRoot.keys()) {\n if (name === fileName || name.startsWith(`${fileName}-`)) names.push(name);\n }\n return names;\n}\n\nasync function removeEntryIfPresent(root: FileSystemDirectoryHandle, name: string): Promise<void> {\n try {\n await root.removeEntry(name, { recursive: true });\n } catch (error) {\n if (!isErrorNamed(error, \"NotFoundError\")) throw error;\n }\n}\n\nexport function createOpfsDatabaseFiles(config: CreateOpfsDatabaseFilesConfig): OpfsDatabaseFiles {\n const retryDelayMs = config.lockRetryDelayMs ?? 50;\n const wait = config.wait ?? (delayMs => new Promise(resolve => setTimeout(resolve, delayMs)));\n\n return {\n getFileName(owner, legacyOwner) {\n const encodedOwner = encodeOwner(owner);\n const mappingKey = `${config.mappingKeyPrefix}${encodedOwner}`;\n const storage = config.getStorage();\n const existing = storage.getItem(mappingKey);\n if (existing != null) return existing;\n\n const fileName = legacyOwner === owner ? config.legacyFileName : config.createScopedFileName(encodedOwner);\n storage.setItem(mappingKey, fileName);\n return fileName;\n },\n async deleteFiles(fileName = config.legacyFileName) {\n const directory = config.getDirectory();\n if (!directory) return;\n\n const root = await directory;\n for (const entryName of await listDatabaseEntryNames(root, fileName)) {\n try {\n await removeEntryIfPresent(root, entryName);\n } catch (error) {\n if (!(error instanceof Error) || !LOCKED_ERROR_NAMES.has(error.name)) throw error;\n await wait(retryDelayMs);\n await removeEntryIfPresent(root, entryName);\n }\n }\n },\n };\n}\n","import { extractReplayHeaders, normalizeHeaders } from \"../offline/queue/queueingHeaders\";\nimport { type OfflineSyncCommand } from \"../offline/queue/queueingTypes\";\n\nexport type OfflineQueueCaptureRequest = {\n method?: string;\n body?: unknown;\n headers?: Record<string, unknown>;\n};\n\nexport type CreateOfflineQueueCaptureConfig<TRequest extends OfflineQueueCaptureRequest> = {\n resolveUrl: (request: TRequest) => string;\n createCommandId: () => string;\n now: () => number;\n enqueue: (command: OfflineSyncCommand) => Promise<void>;\n markEnqueued: () => void;\n refreshStatus: () => Promise<void>;\n};\n\n/** Captures a transport request as a replayable command; transport-specific URL resolution stays injected. */\nexport function createOfflineQueueCapture<TRequest extends OfflineQueueCaptureRequest>(\n config: CreateOfflineQueueCaptureConfig<TRequest>,\n): (request: TRequest) => Promise<OfflineSyncCommand> {\n return async request => {\n const command: OfflineSyncCommand = {\n commandId: config.createCommandId(),\n method: (request.method ?? \"get\").toUpperCase(),\n url: config.resolveUrl(request),\n body: request.body ?? null,\n headers: extractReplayHeaders(normalizeHeaders(request.headers)),\n createdAt: config.now(),\n };\n\n await config.enqueue(command);\n config.markEnqueued();\n await config.refreshStatus();\n return command;\n };\n}\n","import { runSqliteTransaction } from \"../core/sqliteCrud\";\nimport { createSqliteRequestHandlers } from \"../core/sqliteRequestHandlers\";\nimport { type SqliteDatabase } from \"../core/sqliteTypes\";\nimport { type OfflineSyncCommandRecord } from \"../runtime/contracts\";\n\nconst OFFLINE_QUEUE_TABLE = \"offline_sync_commands\";\n\nexport const OFFLINE_QUEUE_PENDING = \"PENDING\";\nexport const OFFLINE_QUEUE_PERMANENTLY_FAILED = \"PERMANENTLY_FAILED\";\n\nexport type OfflineQueuedCommandStatus = typeof OFFLINE_QUEUE_PENDING | typeof OFFLINE_QUEUE_PERMANENTLY_FAILED;\n\nexport type OfflineQueuedCommand = OfflineSyncCommandRecord & {\n status: OfflineQueuedCommandStatus;\n retryCount: number;\n lastError: string | null;\n};\n\nexport type OfflineQueueStatusCounts = {\n pending: number;\n permanentlyFailed: number;\n};\n\nfunction parseJsonValue(value: string, commandId: string, column: string): unknown {\n try {\n return JSON.parse(value) as unknown;\n } catch {\n throw new Error(`Offline command \"${commandId}\" contains invalid JSON in ${column}.`);\n }\n}\n\nfunction parseHeaders(value: string, commandId: string): Record<string, string> {\n const parsed = parseJsonValue(value, commandId, \"headers_json\");\n if (\n parsed == null ||\n typeof parsed !== \"object\" ||\n Array.isArray(parsed) ||\n Object.values(parsed).some(header => typeof header !== \"string\")\n ) {\n throw new Error(`Offline command \"${commandId}\" contains invalid headers_json.`);\n }\n\n return parsed as Record<string, string>;\n}\n\nfunction assertPositiveInteger(value: number, name: string): void {\n if (!Number.isInteger(value) || value <= 0) {\n throw new Error(`${name} must be a positive integer.`);\n }\n}\n\nfunction toQueueStatus(value: unknown): OfflineQueuedCommandStatus {\n return String(value ?? OFFLINE_QUEUE_PENDING) === OFFLINE_QUEUE_PERMANENTLY_FAILED\n ? OFFLINE_QUEUE_PERMANENTLY_FAILED\n : OFFLINE_QUEUE_PENDING;\n}\n\nexport function enqueueOfflineCommand(db: SqliteDatabase, command: OfflineSyncCommandRecord): void {\n const statement = db.prepare(`\n INSERT OR REPLACE INTO ${OFFLINE_QUEUE_TABLE}\n (command_id, method, url, body_json, headers_json, created_at)\n VALUES (?, ?, ?, ?, ?, ?);\n `);\n\n try {\n statement.bind([\n command.commandId,\n command.method,\n command.url,\n JSON.stringify(command.body ?? null),\n JSON.stringify(command.headers),\n command.createdAt,\n ]);\n statement.step();\n } finally {\n statement.finalize();\n }\n}\n\nexport function getPendingOfflineCommands(db: SqliteDatabase, batchSize: number): OfflineQueuedCommand[] {\n assertPositiveInteger(batchSize, \"batchSize\");\n const statement = db.prepare(`\n SELECT command_id, method, url, body_json, headers_json, created_at, status, retry_count, last_error\n FROM ${OFFLINE_QUEUE_TABLE}\n WHERE status = '${OFFLINE_QUEUE_PENDING}'\n ORDER BY created_at ASC\n LIMIT ?;\n `);\n const commands: OfflineQueuedCommand[] = [];\n\n try {\n statement.bind([batchSize]);\n while (statement.step()) {\n const row = statement.get([]);\n const commandId = String(row[0] ?? \"\");\n commands.push({\n commandId,\n method: String(row[1] ?? \"\"),\n url: String(row[2] ?? \"\"),\n body: parseJsonValue(String(row[3] ?? \"null\"), commandId, \"body_json\"),\n headers: parseHeaders(String(row[4] ?? \"{}\"), commandId),\n createdAt: Number(row[5] ?? 0),\n status: toQueueStatus(row[6]),\n retryCount: Number(row[7] ?? 0),\n lastError: row[8] == null ? null : String(row[8]),\n });\n }\n } finally {\n statement.finalize();\n }\n\n return commands;\n}\n\nexport function deleteOfflineCommands(db: SqliteDatabase, commandIds: string[]): void {\n if (commandIds.length === 0) return;\n\n runSqliteTransaction(db, () => {\n for (const commandId of commandIds) {\n const statement = db.prepare(`DELETE FROM ${OFFLINE_QUEUE_TABLE} WHERE command_id = ?;`);\n try {\n statement.bind([commandId]);\n statement.step();\n } finally {\n statement.finalize();\n }\n }\n });\n}\n\nexport function getOfflineQueueSize(db: SqliteDatabase): number {\n const statement = db.prepare(`SELECT COUNT(1) AS count FROM ${OFFLINE_QUEUE_TABLE};`);\n try {\n return statement.step() ? Number(statement.get([])[0] ?? 0) : 0;\n } finally {\n statement.finalize();\n }\n}\n\nexport function getOfflineQueueStatusCounts(db: SqliteDatabase): OfflineQueueStatusCounts {\n const statement = db.prepare(`\n SELECT status, COUNT(1) AS count\n FROM ${OFFLINE_QUEUE_TABLE}\n GROUP BY status;\n `);\n const counts: OfflineQueueStatusCounts = { pending: 0, permanentlyFailed: 0 };\n\n try {\n while (statement.step()) {\n const row = statement.get([]);\n const count = Number(row[1] ?? 0);\n if (toQueueStatus(row[0]) === OFFLINE_QUEUE_PERMANENTLY_FAILED) counts.permanentlyFailed = count;\n else counts.pending = count;\n }\n } finally {\n statement.finalize();\n }\n\n return counts;\n}\n\nexport function markOfflineCommandsRetryable(\n db: SqliteDatabase,\n commandIds: string[],\n lastError: string | null,\n maxRetryCount: number,\n): void {\n if (commandIds.length === 0) return;\n assertPositiveInteger(maxRetryCount, \"maxRetryCount\");\n\n runSqliteTransaction(db, () => {\n for (const commandId of commandIds) {\n const statement = db.prepare(`\n UPDATE ${OFFLINE_QUEUE_TABLE}\n SET retry_count = retry_count + 1,\n last_error = ?,\n status = CASE\n WHEN retry_count + 1 >= ? THEN '${OFFLINE_QUEUE_PERMANENTLY_FAILED}'\n ELSE status\n END\n WHERE command_id = ?;\n `);\n try {\n statement.bind([lastError, maxRetryCount, commandId]);\n statement.step();\n } finally {\n statement.finalize();\n }\n }\n });\n}\n\nexport function markOfflineCommandsPermanentlyFailed(\n db: SqliteDatabase,\n commandIds: string[],\n lastError: string | null,\n): void {\n if (commandIds.length === 0) return;\n\n runSqliteTransaction(db, () => {\n for (const commandId of commandIds) {\n const statement = db.prepare(`\n UPDATE ${OFFLINE_QUEUE_TABLE}\n SET status = '${OFFLINE_QUEUE_PERMANENTLY_FAILED}', last_error = ?\n WHERE command_id = ?;\n `);\n try {\n statement.bind([lastError, commandId]);\n statement.step();\n } finally {\n statement.finalize();\n }\n }\n });\n}\n\nexport const OFFLINE_QUEUE_STATE_SQLITE_REQUEST_HANDLERS = createSqliteRequestHandlers({\n enqueue: (db: SqliteDatabase, request) => {\n enqueueOfflineCommand(db, (request as unknown as { command: OfflineSyncCommandRecord }).command);\n return null;\n },\n getPendingBatch: (db: SqliteDatabase, request) =>\n getPendingOfflineCommands(db, (request as unknown as { batchSize: number }).batchSize),\n deleteCommands: (db: SqliteDatabase, request) => {\n deleteOfflineCommands(db, (request as unknown as { commandIds: string[] }).commandIds);\n return null;\n },\n getQueueSize: (db: SqliteDatabase) => getOfflineQueueSize(db),\n getStatusCounts: (db: SqliteDatabase) => getOfflineQueueStatusCounts(db),\n markCommandsRetryable: (db: SqliteDatabase, request) => {\n const typedRequest = request as unknown as {\n commandIds: string[];\n lastError: string | null;\n maxRetryCount: number;\n };\n markOfflineCommandsRetryable(db, typedRequest.commandIds, typedRequest.lastError, typedRequest.maxRetryCount);\n return null;\n },\n markCommandsPermanentlyFailed: (db: SqliteDatabase, request) => {\n const typedRequest = request as unknown as { commandIds: string[]; lastError: string | null };\n markOfflineCommandsPermanentlyFailed(db, typedRequest.commandIds, typedRequest.lastError);\n return null;\n },\n});\n","import {\n OFFLINE_QUEUE_PENDING,\n OFFLINE_QUEUE_PERMANENTLY_FAILED,\n type OfflineQueuedCommand,\n type OfflineQueueStatusCounts,\n} from \"./offlineQueueStateSqlite\";\nimport { type InMemorySqliteStore } from \"../runtime/createManagedSqliteRuntime\";\nimport { type SqliteTransport } from \"../runtime/createSqliteTransport\";\nimport { type OfflineSyncCommand } from \"../offline/queue/queueingTypes\";\n\nexport type OfflineQueueClientRuntime = {\n shouldUseInMemoryFallback: () => boolean;\n registerInMemoryStore: (store: InMemorySqliteStore) => () => void;\n};\n\nexport type OfflineQueueClient = {\n enqueue: (command: OfflineSyncCommand) => Promise<void>;\n getBatch: (batchSize: number) => Promise<OfflineQueuedCommand[]>;\n delete: (commandIds: string[]) => Promise<void>;\n markRetryable: (commandIds: string[], lastError: string | null, maxRetryCount: number) => Promise<void>;\n markPermanentlyFailed: (commandIds: string[], lastError: string | null) => Promise<void>;\n getSize: () => Promise<number>;\n getStatusCounts: () => Promise<OfflineQueueStatusCounts>;\n dispose: () => void;\n};\n\nexport type CreateOfflineQueueClientConfig = {\n runtime: OfflineQueueClientRuntime;\n transport: Pick<SqliteTransport, \"sendWorkerRequest\">;\n};\n\nexport function createOfflineQueueClient(config: CreateOfflineQueueClientConfig): OfflineQueueClient {\n const inMemoryQueue = new Map<string, OfflineQueuedCommand>();\n const unregisterStore = config.runtime.registerInMemoryStore(inMemoryQueue);\n\n return {\n async enqueue(command) {\n if (config.runtime.shouldUseInMemoryFallback()) {\n inMemoryQueue.set(command.commandId, {\n ...command,\n status: OFFLINE_QUEUE_PENDING,\n retryCount: 0,\n lastError: null,\n });\n return;\n }\n await config.transport.sendWorkerRequest<null>({ type: \"enqueue\", command });\n },\n async getBatch(batchSize) {\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new Error(\"batchSize must be a positive integer.\");\n }\n if (config.runtime.shouldUseInMemoryFallback()) {\n return [...inMemoryQueue.values()]\n .filter(command => command.status === OFFLINE_QUEUE_PENDING)\n .sort((left, right) => left.createdAt - right.createdAt)\n .slice(0, batchSize);\n }\n return await config.transport.sendWorkerRequest<OfflineQueuedCommand[]>({ type: \"getPendingBatch\", batchSize });\n },\n async delete(commandIds) {\n if (config.runtime.shouldUseInMemoryFallback()) {\n for (const commandId of commandIds) inMemoryQueue.delete(commandId);\n return;\n }\n await config.transport.sendWorkerRequest<null>({ type: \"deleteCommands\", commandIds });\n },\n async markRetryable(commandIds, lastError, maxRetryCount) {\n if (commandIds.length === 0) return;\n if (!Number.isInteger(maxRetryCount) || maxRetryCount <= 0) {\n throw new Error(\"maxRetryCount must be a positive integer.\");\n }\n if (config.runtime.shouldUseInMemoryFallback()) {\n for (const commandId of commandIds) {\n const command = inMemoryQueue.get(commandId);\n if (!command) continue;\n const retryCount = command.retryCount + 1;\n inMemoryQueue.set(commandId, {\n ...command,\n retryCount,\n lastError,\n status: retryCount >= maxRetryCount ? OFFLINE_QUEUE_PERMANENTLY_FAILED : command.status,\n });\n }\n return;\n }\n await config.transport.sendWorkerRequest<null>({\n type: \"markCommandsRetryable\",\n commandIds,\n lastError,\n maxRetryCount,\n });\n },\n async markPermanentlyFailed(commandIds, lastError) {\n if (commandIds.length === 0) return;\n if (config.runtime.shouldUseInMemoryFallback()) {\n for (const commandId of commandIds) {\n const command = inMemoryQueue.get(commandId);\n if (command) {\n inMemoryQueue.set(commandId, { ...command, lastError, status: OFFLINE_QUEUE_PERMANENTLY_FAILED });\n }\n }\n return;\n }\n await config.transport.sendWorkerRequest<null>({\n type: \"markCommandsPermanentlyFailed\",\n commandIds,\n lastError,\n });\n },\n async getSize() {\n if (config.runtime.shouldUseInMemoryFallback()) return inMemoryQueue.size;\n return await config.transport.sendWorkerRequest<number>({ type: \"getQueueSize\" });\n },\n async getStatusCounts() {\n if (!config.runtime.shouldUseInMemoryFallback()) {\n return await config.transport.sendWorkerRequest<OfflineQueueStatusCounts>({ type: \"getStatusCounts\" });\n }\n\n let pending = 0;\n let permanentlyFailed = 0;\n for (const command of inMemoryQueue.values()) {\n if (command.status === OFFLINE_QUEUE_PERMANENTLY_FAILED) permanentlyFailed += 1;\n else pending += 1;\n }\n return { pending, permanentlyFailed };\n },\n dispose: unregisterStore,\n };\n}\n","import { type OfflineQueueStatusCounts } from \"./offlineQueueStateSqlite\";\n\nexport type OfflineQueueStatusSnapshot = OfflineQueueStatusCounts & { enqueueTick: number };\nexport type OfflineQueueStatusListener = (snapshot: OfflineQueueStatusSnapshot) => void;\n\nexport type OfflineQueueStatus = {\n getSnapshot: () => OfflineQueueStatusSnapshot;\n subscribe: (listener: OfflineQueueStatusListener) => () => void;\n markEnqueued: () => void;\n refresh: () => Promise<void>;\n resetCounts: () => void;\n};\n\nexport type CreateOfflineQueueStatusConfig = {\n readStatusCounts: () => Promise<OfflineQueueStatusCounts>;\n onReadError?: (error: unknown) => void;\n};\n\nconst INITIAL_COUNTS: OfflineQueueStatusCounts = { pending: 0, permanentlyFailed: 0 };\n\n/** Framework-neutral observable queue status with non-blocking persistence refreshes. */\nexport function createOfflineQueueStatus(config: CreateOfflineQueueStatusConfig): OfflineQueueStatus {\n const listeners = new Set<OfflineQueueStatusListener>();\n let snapshot: OfflineQueueStatusSnapshot = { ...INITIAL_COUNTS, enqueueTick: 0 };\n\n const publish = (next: OfflineQueueStatusSnapshot) => {\n if (\n next.pending === snapshot.pending &&\n next.permanentlyFailed === snapshot.permanentlyFailed &&\n next.enqueueTick === snapshot.enqueueTick\n ) {\n return;\n }\n snapshot = next;\n for (const listener of listeners) listener(snapshot);\n };\n\n return {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n markEnqueued() {\n publish({ ...snapshot, enqueueTick: snapshot.enqueueTick + 1 });\n },\n async refresh() {\n try {\n const counts = await config.readStatusCounts();\n publish({ ...counts, enqueueTick: snapshot.enqueueTick });\n } catch (error) {\n config.onReadError?.(error);\n }\n },\n resetCounts() {\n publish({ ...INITIAL_COUNTS, enqueueTick: snapshot.enqueueTick });\n },\n };\n}\n","import { type OfflineSyncCommand } from \"../offline/queue/queueingTypes\";\n\nexport type OfflineSyncResultReason = \"APPLIED\" | \"ALREADY_APPLIED\" | \"RETRYABLE\" | \"REJECTED\" | \"RETRY_LIMIT_EXCEEDED\";\n\nexport type OfflineSyncCommandResult = {\n commandId: string;\n success: boolean;\n status: number;\n error: string | null;\n reason?: OfflineSyncResultReason | null;\n};\n\nexport type OfflineSyncBatchResponse = {\n accepted: number;\n failed: number;\n results: OfflineSyncCommandResult[];\n};\n\nexport type OfflineSyncCommandDto = Pick<OfflineSyncCommand, \"commandId\" | \"method\" | \"url\" | \"body\" | \"headers\">;\n\nexport type OfflineSyncReplayDependencies = {\n getBatch: (batchSize: number) => Promise<OfflineSyncCommand[]>;\n sendBatch: (commands: OfflineSyncCommandDto[]) => Promise<OfflineSyncBatchResponse>;\n cleanupSuccessfulCommands: (commands: OfflineSyncCommand[]) => Promise<void>;\n deleteSuccessful: (commandIds: string[]) => Promise<void>;\n markPermanentlyFailed: (commandIds: string[], lastError: string | null) => Promise<void>;\n markRetryable: (commandIds: string[], lastError: string | null, maxAttempts: number) => Promise<void>;\n refreshStatus: () => Promise<void>;\n};\n\nconst PERMANENT_FAILURE_REASONS: ReadonlySet<string> = new Set<OfflineSyncResultReason>([\n \"REJECTED\",\n \"RETRY_LIMIT_EXCEEDED\",\n]);\n\nfunction isPermanentFailure(result: OfflineSyncCommandResult): boolean {\n return !result.success && result.reason != null && PERMANENT_FAILURE_REASONS.has(result.reason);\n}\n\nfunction toSyncCommandDto(command: OfflineSyncCommand): OfflineSyncCommandDto {\n return {\n commandId: command.commandId,\n method: command.method,\n url: command.url,\n body: command.body,\n headers: command.headers,\n };\n}\n\nexport async function replayOfflineSyncBatch(args: {\n batchSize: number;\n maxAttempts: number;\n dependencies: OfflineSyncReplayDependencies;\n}): Promise<number> {\n const { batchSize, maxAttempts, dependencies } = args;\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new Error(\"batchSize must be a positive integer.\");\n }\n if (!Number.isInteger(maxAttempts) || maxAttempts <= 0) {\n throw new Error(\"maxAttempts must be a positive integer.\");\n }\n const batch = await dependencies.getBatch(batchSize);\n if (batch.length === 0) return 0;\n\n const response = await dependencies.sendBatch(batch.map(toSyncCommandDto));\n const resultsByCommandId = new Map(response.results.map(result => [result.commandId, result]));\n const successfulCommandIds: string[] = [];\n const permanentlyFailedCommandIds: string[] = [];\n const retryableCommandIds: string[] = [];\n let lastPermanentError: string | null = null;\n let lastRetryableError: string | null = null;\n\n for (const command of batch) {\n const result = resultsByCommandId.get(command.commandId);\n if (!result) {\n retryableCommandIds.push(command.commandId);\n } else if (result.success) {\n successfulCommandIds.push(command.commandId);\n } else if (isPermanentFailure(result)) {\n permanentlyFailedCommandIds.push(command.commandId);\n lastPermanentError = result.error ?? lastPermanentError;\n } else {\n retryableCommandIds.push(command.commandId);\n lastRetryableError = result.error ?? lastRetryableError;\n }\n }\n\n const successfulIds = new Set(successfulCommandIds);\n await dependencies.cleanupSuccessfulCommands(batch.filter(command => successfulIds.has(command.commandId)));\n if (successfulCommandIds.length > 0) await dependencies.deleteSuccessful(successfulCommandIds);\n await dependencies.markPermanentlyFailed(permanentlyFailedCommandIds, lastPermanentError);\n await dependencies.markRetryable(retryableCommandIds, lastRetryableError, maxAttempts);\n await dependencies.refreshStatus();\n return successfulCommandIds.length;\n}\n","import {\n type WorkerRequest,\n type WorkerRequestInput,\n type WorkerResponse,\n type WorkerResponseResult,\n} from \"../core/sqliteWorkerProtocol\";\n\nexport type InMemorySqliteStore = { clear: () => void };\n\nexport type ManagedSqliteRuntimeConfig = {\n workerFactory: () => Worker;\n shouldUseInMemoryFallback?: () => boolean;\n debug?: boolean;\n bootLogPrefix?: string;\n now?: () => number;\n};\n\nexport type ManagedSqliteRuntime = {\n registerInMemoryStore: (store: InMemorySqliteStore) => () => void;\n clearInMemoryStores: () => void;\n shouldUseInMemoryFallback: () => boolean;\n send: <T extends WorkerResponseResult>(payload: WorkerRequestInput) => Promise<T>;\n ensureInitialized: () => Promise<void>;\n warmup: () => Promise<void>;\n reset: () => void;\n dispose: () => void;\n};\n\nfunction defaultNow(): number {\n return typeof performance !== \"undefined\" && typeof performance.now === \"function\" ? performance.now() : Date.now();\n}\n\n/** Owns worker lifecycle, initialization, pending requests, fallback stores and deterministic teardown. */\nexport function createManagedSqliteRuntime(config: ManagedSqliteRuntimeConfig): ManagedSqliteRuntime {\n const bootLogPrefix = config.bootLogPrefix ?? \"[SQLITE-BOOT]\";\n const now = config.now ?? defaultNow;\n const inMemoryStores = new Set<InMemorySqliteStore>();\n const pending = new Map<\n number,\n { resolve: (value: WorkerResponseResult) => void; reject: (reason?: unknown) => void }\n >();\n\n let worker: Worker | null = null;\n let nextRequestId = 1;\n let initialized = false;\n let initializingPromise: Promise<void> | null = null;\n let initializationGeneration = 0;\n let disposed = false;\n\n const log = (message: string, ...details: unknown[]) => {\n if (config.debug) console.debug(`${bootLogPrefix} ${message}`, ...details);\n };\n\n const assertActive = () => {\n if (disposed) throw new Error(\"SQLite runtime has been disposed.\");\n };\n\n const rejectPending = (reason: Error) => {\n for (const handler of pending.values()) handler.reject(reason);\n pending.clear();\n };\n\n const teardownWorker = (reason: Error) => {\n worker?.terminate();\n worker = null;\n initialized = false;\n initializingPromise = null;\n initializationGeneration += 1;\n rejectPending(reason);\n };\n\n const getWorker = () => {\n assertActive();\n if (worker) return worker;\n\n worker = config.workerFactory();\n worker.addEventListener(\"message\", event => {\n const message = event.data as WorkerResponse;\n const handler = pending.get(message.id);\n if (!handler) return;\n\n pending.delete(message.id);\n if (message.ok) handler.resolve(message.result);\n else handler.reject(new Error(message.error));\n });\n worker.addEventListener(\"error\", event => {\n const error = event.error instanceof Error ? event.error : new Error(event.message);\n teardownWorker(error);\n });\n worker.addEventListener(\"messageerror\", () => {\n teardownWorker(new Error(\"SQLite worker returned an unreadable message.\"));\n });\n return worker;\n };\n\n const send = async <T extends WorkerResponseResult>(payload: WorkerRequestInput): Promise<T> => {\n const id = nextRequestId++;\n const activeWorker = getWorker();\n\n return await new Promise<T>((resolve, reject) => {\n pending.set(id, { resolve: value => resolve(value as T), reject });\n try {\n activeWorker.postMessage({ id, ...payload } as WorkerRequest);\n } catch (error) {\n pending.delete(id);\n reject(error);\n }\n });\n };\n\n const ensureInitialized = async (): Promise<void> => {\n assertActive();\n if (initialized) return;\n if (initializingPromise) return await initializingPromise;\n\n const startedAt = now();\n const generation = ++initializationGeneration;\n log(\"client init request -> worker\");\n const currentInitialization = (async () => {\n try {\n await send<null>({ type: \"init\" });\n initialized = true;\n log(`client init completed in ${Math.round(now() - startedAt)}ms`);\n } catch (error) {\n log(`client init failed after ${Math.round(now() - startedAt)}ms`, error);\n throw error;\n } finally {\n if (initializationGeneration === generation) initializingPromise = null;\n }\n })();\n initializingPromise = currentInitialization;\n await currentInitialization;\n };\n\n return {\n registerInMemoryStore(store) {\n inMemoryStores.add(store);\n return () => inMemoryStores.delete(store);\n },\n clearInMemoryStores() {\n for (const store of inMemoryStores) store.clear();\n },\n shouldUseInMemoryFallback: () => config.shouldUseInMemoryFallback?.() ?? false,\n send,\n ensureInitialized,\n warmup: ensureInitialized,\n reset() {\n assertActive();\n teardownWorker(new Error(\"SQLite runtime was reset.\"));\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n teardownWorker(new Error(\"SQLite runtime was disposed.\"));\n inMemoryStores.clear();\n },\n };\n}\n","import { type InMemorySqliteStore } from \"./createManagedSqliteRuntime\";\nimport { type SqliteTransport } from \"./createSqliteTransport\";\n\ntype SqliteEntityClientRequest = { type: string; payloadKey: string };\n\nexport type SqliteEntityClient<TRecord, TKey> = {\n replace: (records: TRecord[]) => Promise<void>;\n upsert: (record: TRecord) => Promise<void>;\n list: () => Promise<TRecord[]>;\n delete: (keys: TKey[]) => Promise<void>;\n};\n\nexport type SqliteEntityClientRuntime = {\n shouldUseInMemoryFallback: () => boolean;\n registerInMemoryStore: (store: InMemorySqliteStore) => () => void;\n};\n\nexport type SqliteEntityClientConfig<TRecord, TKey> = {\n runtime: SqliteEntityClientRuntime;\n transport: Pick<SqliteTransport, \"sendWorkerRequest\">;\n getKey: (record: TRecord) => TKey;\n compare: (left: TRecord, right: TRecord) => number;\n requests: {\n replace: SqliteEntityClientRequest;\n upsert: SqliteEntityClientRequest;\n list: { type: string };\n delete: SqliteEntityClientRequest;\n };\n};\n\nfunction requestWithPayload(type: string, payloadKey: string, payload: unknown) {\n return { type, [payloadKey]: payload };\n}\n\nexport function createSqliteEntityClient<TRecord, TKey>(\n config: SqliteEntityClientConfig<TRecord, TKey>,\n): SqliteEntityClient<TRecord, TKey> {\n const inMemoryRecords = new Map<TKey, TRecord>();\n config.runtime.registerInMemoryStore(inMemoryRecords);\n\n return {\n async replace(records) {\n if (config.runtime.shouldUseInMemoryFallback()) {\n inMemoryRecords.clear();\n for (const record of records) inMemoryRecords.set(config.getKey(record), record);\n return;\n }\n await config.transport.sendWorkerRequest<null>(\n requestWithPayload(config.requests.replace.type, config.requests.replace.payloadKey, records),\n );\n },\n async upsert(record) {\n if (config.runtime.shouldUseInMemoryFallback()) {\n inMemoryRecords.set(config.getKey(record), record);\n return;\n }\n await config.transport.sendWorkerRequest<null>(\n requestWithPayload(config.requests.upsert.type, config.requests.upsert.payloadKey, record),\n );\n },\n async list() {\n if (config.runtime.shouldUseInMemoryFallback()) return [...inMemoryRecords.values()].sort(config.compare);\n return await config.transport.sendWorkerRequest<TRecord[]>({ type: config.requests.list.type });\n },\n async delete(keys) {\n if (config.runtime.shouldUseInMemoryFallback()) {\n for (const key of keys) inMemoryRecords.delete(key);\n return;\n }\n await config.transport.sendWorkerRequest<null>(\n requestWithPayload(config.requests.delete.type, config.requests.delete.payloadKey, keys),\n );\n },\n };\n}\n","import { type WorkerRequestInput, type WorkerResponseResult } from \"../core/sqliteWorkerProtocol\";\n\nexport type SqliteTransportRuntime = {\n shouldUseInMemoryFallback: () => boolean;\n ensureInitialized: () => Promise<void>;\n send: <T extends WorkerResponseResult>(payload: WorkerRequestInput) => Promise<T>;\n};\n\nexport type SqliteTransport = {\n sendRequest: <TResponse = unknown>(type: string, payload?: Record<string, unknown>) => Promise<TResponse>;\n sendWorkerRequest: <T extends WorkerResponseResult>(\n payload: { type: string } & Record<string, unknown>,\n ) => Promise<T>;\n};\n\nexport type CreateSqliteTransportConfig = {\n runtime: SqliteTransportRuntime;\n createUnavailableError?: (requestType: string) => Error;\n};\n\nexport function createSqliteTransport({\n runtime,\n createUnavailableError,\n}: CreateSqliteTransportConfig): SqliteTransport {\n const unavailableError =\n createUnavailableError ??\n (requestType => new Error(`SQLite request '${requestType}' is unavailable in this runtime.`));\n\n return {\n async sendRequest<TResponse = unknown>(type: string, payload?: Record<string, unknown>): Promise<TResponse> {\n if (runtime.shouldUseInMemoryFallback()) throw unavailableError(type);\n await runtime.ensureInitialized();\n return (await runtime.send({ type, ...(payload ?? {}) })) as TResponse;\n },\n async sendWorkerRequest<T extends WorkerResponseResult>(\n payload: { type: string } & Record<string, unknown>,\n ): Promise<T> {\n await runtime.ensureInitialized();\n return await runtime.send<T>(payload);\n },\n };\n}\n","import sqlite3InitModule from \"@sqlite.org/sqlite-wasm\";\nimport { type SqliteDatabase, type SqliteMigration } from \"./sqliteTypes\";\n\nconst SQLITE_BOOT_LOG_PREFIX = \"[SQLITE-BOOT]\";\nconst debug = import.meta.env.DEV;\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n\n return Date.now();\n}\n\nfunction logSqliteBoot(message: string, ...details: unknown[]): void {\n if (!debug) {\n return;\n }\n\n console.debug(`${SQLITE_BOOT_LOG_PREFIX} ${message}`, ...details);\n}\n\ntype SqliteModule = {\n oo1: {\n DB: new (filename?: string, flags?: string) => SqliteDatabase;\n OpfsDb?: new (filename?: string, flags?: string) => SqliteDatabase;\n };\n opfs?: unknown;\n};\n\nexport function mapSqliteRuntimeError(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n\n return \"Unknown worker error\";\n}\n\nfunction getOpfsDiagnostics(module: SqliteModule): Record<string, boolean> {\n const hasNavigator = typeof navigator !== \"undefined\";\n const hasStorage = hasNavigator && navigator.storage != null;\n\n return {\n crossOriginIsolated: globalThis.crossOriginIsolated === true,\n hasSharedArrayBuffer: typeof SharedArrayBuffer !== \"undefined\",\n hasNavigator,\n hasNavigatorStorage: hasStorage,\n hasStorageGetDirectory: hasStorage && typeof navigator.storage.getDirectory === \"function\",\n hasOpfsDbCtor: typeof module.oo1.OpfsDb === \"function\",\n hasSqliteOpfsNamespace: module.opfs != null,\n };\n}\n\nfunction formatOpfsDiagnostics(module: SqliteModule): string {\n const diagnostics = getOpfsDiagnostics(module);\n return Object.entries(diagnostics)\n .map(([key, value]) => `${key}=${String(value)}`)\n .join(\", \");\n}\n\nfunction openDatabase(module: SqliteModule, dbFile: string): SqliteDatabase {\n if (typeof module.oo1.OpfsDb !== \"function\") {\n throw new Error(\n `[offline-sqlite] OPFS database constructor is unavailable. Diagnostics: ${formatOpfsDiagnostics(module)}.`,\n );\n }\n\n try {\n return new module.oo1.OpfsDb(dbFile);\n } catch (error) {\n throw new Error(\n `[offline-sqlite] Failed to open OPFS SQLite database: ${mapSqliteRuntimeError(\n error,\n )}. Diagnostics: ${formatOpfsDiagnostics(module)}.`,\n );\n }\n}\n\nexport function querySingleNumber(db: SqliteDatabase, sql: string): number {\n const statement = db.prepare(sql);\n\n try {\n if (!statement.step()) {\n return 0;\n }\n\n const row = statement.get([]);\n return Number(row[0] ?? 0);\n } finally {\n statement.finalize();\n }\n}\n\nexport function getSchemaVersion(db: SqliteDatabase): number {\n return querySingleNumber(db, \"PRAGMA user_version;\");\n}\n\nexport function setSchemaVersion(db: SqliteDatabase, version: number): void {\n db.exec(`PRAGMA user_version = ${version};`);\n}\n\nexport function applySqliteMigrations(db: SqliteDatabase, migrations: SqliteMigration[]): void {\n const startedAt = nowMs();\n db.exec(\"BEGIN;\");\n\n try {\n const currentVersion = getSchemaVersion(db);\n logSqliteBoot(`migrations start (current=${currentVersion}, target=${migrations.length})`);\n\n for (let index = currentVersion; index < migrations.length; index += 1) {\n const migrationStartedAt = nowMs();\n migrations[index](db);\n setSchemaVersion(db, index + 1);\n logSqliteBoot(`migration ${index + 1} applied in ${Math.round(nowMs() - migrationStartedAt)}ms`);\n }\n\n if (getSchemaVersion(db) > migrations.length) {\n throw new Error(\"Database schema version is newer than supported client version.\");\n }\n\n db.exec(\"COMMIT;\");\n logSqliteBoot(`migrations done in ${Math.round(nowMs() - startedAt)}ms`);\n } catch (error) {\n db.exec(\"ROLLBACK;\");\n logSqliteBoot(`migrations failed after ${Math.round(nowMs() - startedAt)}ms`, error);\n throw error;\n }\n}\n\nexport async function initializeSqliteDatabase(dbFile: string, migrations: SqliteMigration[]): Promise<SqliteDatabase> {\n const totalStartedAt = nowMs();\n logSqliteBoot(\"sqlite runtime init start\");\n\n const wasmStartedAt = nowMs();\n const module = (await sqlite3InitModule()) as unknown as SqliteModule;\n logSqliteBoot(`sqlite wasm module ready in ${Math.round(nowMs() - wasmStartedAt)}ms`);\n\n const openStartedAt = nowMs();\n const db = openDatabase(module, dbFile);\n logSqliteBoot(`sqlite db open in ${Math.round(nowMs() - openStartedAt)}ms`);\n\n const migrationsStartedAt = nowMs();\n applySqliteMigrations(db, migrations);\n logSqliteBoot(`sqlite migrations stage in ${Math.round(nowMs() - migrationsStartedAt)}ms`);\n logSqliteBoot(`sqlite runtime init done in ${Math.round(nowMs() - totalStartedAt)}ms`);\n return db;\n}\n","import { dispatchSqliteRequest, type SqliteRequestHandlers } from \"./sqliteRequestHandlers\";\nimport { initializeSqliteDatabase, mapSqliteRuntimeError } from \"./sqliteRuntime\";\nimport { type SqliteDatabase, type SqliteMigration } from \"./sqliteTypes\";\nimport { type WorkerRequest, type WorkerResponse, type WorkerResponseResult } from \"./sqliteWorkerProtocol\";\n\ntype WorkerLike = {\n addEventListener: (type: \"message\", listener: (event: MessageEvent<unknown>) => void | Promise<void>) => void;\n postMessage: (message: unknown) => void;\n};\n\nexport type SqliteWorkerRuntimeConfig = {\n dbFile: string;\n migrations: SqliteMigration[];\n requestHandlers: SqliteRequestHandlers;\n debug?: boolean;\n bootLogPrefix?: string;\n};\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n\n return Date.now();\n}\n\nexport function createSqliteWorkerRuntime(config: SqliteWorkerRuntimeConfig) {\n const bootLogPrefix = config.bootLogPrefix ?? \"[SQLITE-BOOT]\";\n\n let sqliteDb: SqliteDatabase | null = null;\n let sqliteDbInitializingPromise: Promise<void> | null = null;\n\n function logSqliteBoot(message: string, ...details: unknown[]): void {\n if (!config.debug) {\n return;\n }\n\n console.debug(`${bootLogPrefix} ${message}`, ...details);\n }\n\n function postResponse(worker: WorkerLike, response: WorkerResponse): void {\n worker.postMessage(response);\n }\n\n function requireDatabase(): SqliteDatabase {\n if (sqliteDb == null) {\n throw new Error(\"SQLite database is not initialized.\");\n }\n\n return sqliteDb;\n }\n\n async function ensureInitialized(): Promise<void> {\n if (sqliteDb != null) {\n return;\n }\n\n if (sqliteDbInitializingPromise != null) {\n logSqliteBoot(\"worker init wait for in-flight initialization\");\n await sqliteDbInitializingPromise;\n return;\n }\n\n const startedAt = nowMs();\n logSqliteBoot(\"worker init start\");\n\n sqliteDbInitializingPromise = (async () => {\n try {\n sqliteDb = await initializeSqliteDatabase(config.dbFile, config.migrations);\n logSqliteBoot(`worker init done in ${Math.round(nowMs() - startedAt)}ms`);\n } finally {\n sqliteDbInitializingPromise = null;\n }\n })();\n\n await sqliteDbInitializingPromise;\n }\n\n async function tryHandleSqliteRequest(request: WorkerRequest): Promise<WorkerResponseResult | undefined> {\n return await dispatchSqliteRequest(requireDatabase(), request, config.requestHandlers);\n }\n\n async function handleRequest(worker: WorkerLike, request: WorkerRequest): Promise<void> {\n try {\n await ensureInitialized();\n\n if (request.type === \"init\") {\n postResponse(worker, { id: request.id, ok: true, result: null });\n return;\n }\n\n const requestResult = await tryHandleSqliteRequest(request);\n if (requestResult !== undefined) {\n postResponse(worker, { id: request.id, ok: true, result: requestResult });\n return;\n }\n\n throw new Error(`Unsupported worker request: ${JSON.stringify(request)}`);\n } catch (error) {\n postResponse(worker, { id: request.id, ok: false, error: mapSqliteRuntimeError(error) });\n }\n }\n\n function attach(worker: WorkerLike): void {\n worker.addEventListener(\"message\", async event => {\n await handleRequest(worker, event.data as WorkerRequest);\n });\n }\n\n return {\n attach,\n handleRequest,\n };\n}\n","import { mergeSqliteRequestHandlers } from \"./core/sqliteRequestHandlers\";\nimport { type SqliteWorkerRuntimeConfig } from \"./core/sqliteWorkerRuntime\";\nimport { type CreateSqliteWorkerRuntimeConfigInput } from \"./runtime/contracts\";\n\nexport function createSqliteWorkerRuntimeConfig(\n input: CreateSqliteWorkerRuntimeConfigInput,\n): SqliteWorkerRuntimeConfig {\n if (input.dbFile.trim().length === 0) {\n throw new Error(\"SQLite worker configuration requires a non-empty dbFile.\");\n }\n\n return {\n dbFile: input.dbFile,\n migrations: input.migrations,\n debug: input.debug,\n requestHandlers: mergeSqliteRequestHandlers(\n ...input.entityBundles.map(bundle => bundle.requestHandlers),\n ...(input.extraRequestHandlers ?? []),\n ),\n };\n}\n","import { createSqliteRequestHandlers } from \"../core/sqliteRequestHandlers\";\nimport { type SqliteDatabase } from \"../core/sqliteTypes\";\nimport { type SqliteHydrationEntityStateRecord } from \"./contracts\";\n\nexport type HydrationEntityStateSqliteOperationMap = {\n listHydrationEntityStates: { request: Record<string, never>; response: SqliteHydrationEntityStateRecord[] };\n upsertHydrationEntityState: { request: { state: SqliteHydrationEntityStateRecord }; response: null };\n};\n\nconst HYDRATION_ENTITY_STATE_TABLE = \"hydration_entity_state\";\n\nexport function listHydrationEntityStates(db: SqliteDatabase): SqliteHydrationEntityStateRecord[] {\n const statement = db.prepare(`\n SELECT entity_key, applied_revision, is_stale, last_hydrated_at, last_row_count, last_error\n FROM ${HYDRATION_ENTITY_STATE_TABLE}\n ORDER BY entity_key ASC;\n `);\n\n const rows: SqliteHydrationEntityStateRecord[] = [];\n\n try {\n while (statement.step()) {\n const row = statement.get([]);\n rows.push({\n entityKey: String(row[0] ?? \"\"),\n appliedRevision: Number(row[1] ?? 0),\n isStale: Number(row[2] ?? 0) === 1,\n lastHydratedAt: row[3] == null ? null : Number(row[3]),\n lastRowCount: row[4] == null ? null : Number(row[4]),\n lastError: row[5] == null ? null : String(row[5]),\n });\n }\n } finally {\n statement.finalize();\n }\n\n return rows;\n}\n\nexport function upsertHydrationEntityState(db: SqliteDatabase, state: SqliteHydrationEntityStateRecord): void {\n const statement = db.prepare(`\n INSERT INTO ${HYDRATION_ENTITY_STATE_TABLE}\n (entity_key, applied_revision, is_stale, last_hydrated_at, last_row_count, last_error)\n VALUES (?, ?, ?, ?, ?, ?)\n ON CONFLICT(entity_key) DO UPDATE SET\n applied_revision = excluded.applied_revision,\n is_stale = excluded.is_stale,\n last_hydrated_at = excluded.last_hydrated_at,\n last_row_count = excluded.last_row_count,\n last_error = excluded.last_error;\n `);\n\n try {\n statement.bind([\n state.entityKey,\n state.appliedRevision,\n state.isStale ? 1 : 0,\n state.lastHydratedAt,\n state.lastRowCount,\n state.lastError,\n ]);\n statement.step();\n } finally {\n statement.finalize();\n }\n}\n\nexport const HYDRATION_ENTITY_STATE_SQLITE_REQUEST_HANDLERS = createSqliteRequestHandlers({\n listHydrationEntityStates: (db: SqliteDatabase) => {\n return listHydrationEntityStates(db);\n },\n upsertHydrationEntityState: (db: SqliteDatabase, request) => {\n const typedRequest = request as unknown as { state: SqliteHydrationEntityStateRecord };\n upsertHydrationEntityState(db, typedRequest.state);\n return null;\n },\n});\n","import { createSqliteRequestHandlers } from \"../core/sqliteRequestHandlers\";\nimport { type SqliteDatabase } from \"../core/sqliteTypes\";\nimport {\n type SqlExecutionResult,\n type SqlExecutionStatementResult,\n type SqlPagedQueryRequest,\n type SqlPagedQueryResult,\n} from \"./contracts\";\n\nexport type SqlConsoleSqliteOperationMap = {\n executeSqlScript: { request: { script: string }; response: SqlExecutionResult };\n executePagedQuery: { request: SqlPagedQueryRequest; response: SqlPagedQueryResult };\n};\n\nfunction nowMs(): number {\n if (typeof performance !== \"undefined\" && typeof performance.now === \"function\") {\n return performance.now();\n }\n\n return Date.now();\n}\n\nfunction querySingleNumber(db: SqliteDatabase, sql: string): number {\n const statement = db.prepare(sql);\n\n try {\n if (!statement.step()) {\n return 0;\n }\n\n const row = statement.get([]);\n return Number(row[0] ?? 0);\n } finally {\n statement.finalize();\n }\n}\n\nfunction splitSqlStatements(script: string): string[] {\n return script\n .split(\";\")\n .map(part => part.trim())\n .filter(part => part.length > 0);\n}\n\nexport function executeSqlScript(db: SqliteDatabase, script: string): SqlExecutionResult {\n const statements = splitSqlStatements(script);\n\n if (statements.length === 0) {\n return { statements: [] };\n }\n\n const results: SqlExecutionStatementResult[] = [];\n\n for (const statementSql of statements) {\n const statement = db.prepare(statementSql);\n\n try {\n const columns = statement.getColumnNames?.([]) ?? [];\n const rows: unknown[][] = [];\n\n while (statement.step()) {\n rows.push(statement.get([]));\n }\n\n const rowsAffected = querySingleNumber(db, \"SELECT changes();\");\n\n results.push({\n statement: statementSql,\n columns,\n rows,\n rowsAffected,\n });\n } finally {\n statement.finalize();\n }\n }\n\n return { statements: results };\n}\n\nexport function executePagedQuery(db: SqliteDatabase, request: SqlPagedQueryRequest): SqlPagedQueryResult {\n const workerStartedAt = nowMs();\n const queueWaitMs =\n Number.isFinite(request.clientSentAtMs) && request.clientSentAtMs != null\n ? Math.max(0, Math.round(workerStartedAt - request.clientSentAtMs))\n : undefined;\n\n const paginationParts: string[] = [];\n if (request.limit != null && request.limit > 0) {\n paginationParts.push(`LIMIT ${request.limit}`);\n if (request.offset != null && request.offset > 0) {\n paginationParts.push(`OFFSET ${request.offset}`);\n }\n }\n\n const pageSql = `\n SELECT ${request.selectSql}\n FROM ${request.fromSql}\n WHERE ${request.whereSql}\n ORDER BY ${request.orderBySql}\n ${paginationParts.join(\" \")};\n `;\n\n const pageStatement = db.prepare(pageSql);\n let columns: string[] = [];\n const rows: unknown[][] = [];\n\n try {\n columns = pageStatement.getColumnNames?.([]) ?? [];\n\n while (pageStatement.step()) {\n rows.push(pageStatement.get([]));\n }\n } finally {\n pageStatement.finalize();\n }\n\n if (request.includeTotalCount === false) {\n return {\n columns,\n rows,\n totalElements: null,\n queueWaitMs,\n workerExecMs: Math.round(nowMs() - workerStartedAt),\n };\n }\n\n const countSql = `\n SELECT COUNT(*) AS total_elements\n FROM ${request.fromSql}\n WHERE ${request.whereSql};\n `;\n\n const countStatement = db.prepare(countSql);\n\n try {\n if (!countStatement.step()) {\n return {\n columns,\n rows,\n totalElements: 0,\n queueWaitMs,\n workerExecMs: Math.round(nowMs() - workerStartedAt),\n };\n }\n\n const row = countStatement.get([]);\n return {\n columns,\n rows,\n totalElements: Number(row[0] ?? 0),\n queueWaitMs,\n workerExecMs: Math.round(nowMs() - workerStartedAt),\n };\n } finally {\n countStatement.finalize();\n }\n}\n\nexport const SQL_CONSOLE_SQLITE_REQUEST_HANDLERS = createSqliteRequestHandlers({\n executeSqlScript: (db: SqliteDatabase, request) => {\n const typedRequest = request as unknown as { script: string };\n return executeSqlScript(db, typedRequest.script);\n },\n executePagedQuery: (db: SqliteDatabase, request) => {\n return executePagedQuery(db, request as unknown as SqlPagedQueryRequest);\n },\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type KeyValueStorage = Pick<Storage, "getItem" | "setItem" | "removeItem">;
|
|
2
|
+
export type DatabaseOwnerStore = {
|
|
3
|
+
read: () => string | null;
|
|
4
|
+
persist: (owner: string) => void;
|
|
5
|
+
clear: () => void;
|
|
6
|
+
};
|
|
7
|
+
export type CreateDatabaseOwnerStoreConfig = {
|
|
8
|
+
key: string;
|
|
9
|
+
getStorage: () => KeyValueStorage;
|
|
10
|
+
};
|
|
11
|
+
export declare function createDatabaseOwnerStore({ key, getStorage }: CreateDatabaseOwnerStoreConfig): DatabaseOwnerStore;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type OfflineDataLifecyclePhase = "hydration" | "queue" | "storage";
|
|
2
|
+
export type OfflineDataLifecycleOptions = {
|
|
3
|
+
onPhase?: (phase: OfflineDataLifecyclePhase) => void;
|
|
4
|
+
};
|
|
5
|
+
export type CreateOfflineDataLifecycleConfig = {
|
|
6
|
+
readOwner: () => string | null;
|
|
7
|
+
persistOwner: (owner: string) => void;
|
|
8
|
+
resolveDatabaseFileName: (owner: string, legacyOwner: string | null) => string;
|
|
9
|
+
abortHydration: (reason: string) => void;
|
|
10
|
+
awaitHydrationIdle: () => Promise<void>;
|
|
11
|
+
awaitLocalReflectionIdle: () => Promise<void>;
|
|
12
|
+
awaitQueueFlushIdle: () => Promise<void>;
|
|
13
|
+
resetHydrationGate: () => void;
|
|
14
|
+
resetHydrationStatus: () => void;
|
|
15
|
+
resetQueueStatus: () => void;
|
|
16
|
+
resetRuntime: () => void;
|
|
17
|
+
clearInMemoryStores: () => void;
|
|
18
|
+
deleteDatabaseFiles: (fileName?: string) => Promise<void>;
|
|
19
|
+
hydrationAbortReason?: string;
|
|
20
|
+
};
|
|
21
|
+
export type OfflineDataLifecycle = {
|
|
22
|
+
release: (options?: OfflineDataLifecycleOptions) => Promise<void>;
|
|
23
|
+
purge: (options?: OfflineDataLifecycleOptions) => Promise<void>;
|
|
24
|
+
ensureOwnedBy: (owner: string) => Promise<boolean>;
|
|
25
|
+
};
|
|
26
|
+
export declare function createOfflineDataLifecycle(config: CreateOfflineDataLifecycleConfig): OfflineDataLifecycle;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { KeyValueStorage } from './createDatabaseOwnerStore';
|
|
2
|
+
export type OpfsDatabaseFiles = {
|
|
3
|
+
getFileName: (owner: string, legacyOwner: string | null) => string;
|
|
4
|
+
deleteFiles: (fileName?: string) => Promise<void>;
|
|
5
|
+
};
|
|
6
|
+
export type CreateOpfsDatabaseFilesConfig = {
|
|
7
|
+
legacyFileName: string;
|
|
8
|
+
mappingKeyPrefix: string;
|
|
9
|
+
getStorage: () => KeyValueStorage;
|
|
10
|
+
getDirectory: () => Promise<FileSystemDirectoryHandle> | null;
|
|
11
|
+
createScopedFileName: (encodedOwner: string) => string;
|
|
12
|
+
lockRetryDelayMs?: number;
|
|
13
|
+
wait?: (delayMs: number) => Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
export declare function createOpfsDatabaseFiles(config: CreateOpfsDatabaseFilesConfig): OpfsDatabaseFiles;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type PageResult<TRow> = {
|
|
2
|
+
content: TRow[];
|
|
3
|
+
totalPages: number;
|
|
4
|
+
};
|
|
5
|
+
export type FetchPage<TRow> = (page: number) => Promise<PageResult<TRow>>;
|
|
6
|
+
export type MapRow<TRow, TSnapshotRow> = (row: TRow) => TSnapshotRow | null;
|
|
7
|
+
export type ReplaceSnapshot<TSnapshotRow> = (rows: TSnapshotRow[]) => Promise<void>;
|
|
8
|
+
export declare function hydratePagedSnapshot<TRow, TSnapshotRow>(args: {
|
|
9
|
+
fetchPage: FetchPage<TRow>;
|
|
10
|
+
mapRow: MapRow<TRow, TSnapshotRow>;
|
|
11
|
+
replaceSnapshot: ReplaceSnapshot<TSnapshotRow>;
|
|
12
|
+
}): Promise<{
|
|
13
|
+
rowCount: number;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './hydration/hydratePagedSnapshot';
|
|
2
|
+
export * from './mutations/offlineMutations';
|
|
3
|
+
export * from './queue/queueingHeaders';
|
|
4
|
+
export * from './queue/queueingPolicy';
|
|
5
|
+
export * from './queue/queueingTypes';
|
|
6
|
+
export * from './status/offlineStatusRuntime';
|
|
7
|
+
export * from './status/offlineStatusTypes';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { i as e, n as t, r as n, t as r } from "../queueingHeaders-B7TBifLV.js";
|
|
2
|
+
//#region src/offline/hydration/hydratePagedSnapshot.ts
|
|
3
|
+
async function i(e) {
|
|
4
|
+
let t = [], n = 0;
|
|
5
|
+
for (;;) {
|
|
6
|
+
let r = await e.fetchPage(n);
|
|
7
|
+
if (t.push(...r.content), n + 1 >= r.totalPages) break;
|
|
8
|
+
n += 1;
|
|
9
|
+
}
|
|
10
|
+
let r = t.map(e.mapRow).filter((e) => e != null);
|
|
11
|
+
return await e.replaceSnapshot(r), { rowCount: r.length };
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/offline/mutations/offlineMutations.ts
|
|
15
|
+
async function a(e) {
|
|
16
|
+
let { input: t, persistLocal: n, enqueue: r, buildResult: i } = e;
|
|
17
|
+
return await n(t), await r(t), i(t);
|
|
18
|
+
}
|
|
19
|
+
async function o(e) {
|
|
20
|
+
let { id: t, deleteLocal: n, enqueue: r } = e;
|
|
21
|
+
await n(t), await r(t);
|
|
22
|
+
}
|
|
23
|
+
async function s(e) {
|
|
24
|
+
let { input: t, allocateTempId: n, buildLocalEntity: r, persistLocal: i, enqueue: a } = e, o = n(), s = r(t, o);
|
|
25
|
+
return await i(s), await a(t, o), s;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/offline/queue/queueingPolicy.ts
|
|
29
|
+
var c = /* @__PURE__ */ new Set([
|
|
30
|
+
"POST",
|
|
31
|
+
"PUT",
|
|
32
|
+
"PATCH",
|
|
33
|
+
"DELETE"
|
|
34
|
+
]);
|
|
35
|
+
function l(e, t) {
|
|
36
|
+
let n = new Set((t?.includeMethods ?? [...c]).map((e) => e.toUpperCase())), r = (e.method ?? "GET").toUpperCase();
|
|
37
|
+
if (!n.has(r)) return !1;
|
|
38
|
+
let i = t?.apiPrefix ?? "/api/";
|
|
39
|
+
return !(!e.url.startsWith(i) || (t?.excludedPrefixes ?? ["/api/auth", "/api/offline/"]).some((t) => e.url.startsWith(t)) || (t?.excludeSearchPosts ?? !0) && r === "POST" && e.url.split("?")[0].endsWith("/search"));
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/offline/status/offlineStatusRuntime.ts
|
|
43
|
+
function u(e) {
|
|
44
|
+
let t = e?.staleAfterMs ?? 15e3, n = e?.bootstrapAssumeOnlineMs ?? 6e3, r = e?.tickMs ?? 1e3, i = e?.now ?? (() => Date.now()), a = {
|
|
45
|
+
browserOnline: typeof navigator > "u" || navigator.onLine,
|
|
46
|
+
heartbeatEnabled: !1,
|
|
47
|
+
heartbeatEnabledAt: null,
|
|
48
|
+
backendReachableOverride: null,
|
|
49
|
+
heartbeatConnected: !1,
|
|
50
|
+
syncInProgress: !1,
|
|
51
|
+
lastHeartbeatAt: null
|
|
52
|
+
}, o = () => a.backendReachableOverride === !1 || !a.browserOnline ? !1 : a.heartbeatEnabled ? a.lastHeartbeatAt == null ? a.heartbeatEnabledAt != null && i() - a.heartbeatEnabledAt <= n : i() - a.lastHeartbeatAt <= t : !0, s = () => ({
|
|
53
|
+
online: o(),
|
|
54
|
+
heartbeatEnabled: a.heartbeatEnabled,
|
|
55
|
+
heartbeatConnected: a.heartbeatConnected,
|
|
56
|
+
syncInProgress: a.syncInProgress,
|
|
57
|
+
lastHeartbeatAt: a.lastHeartbeatAt
|
|
58
|
+
}), c = (e) => {
|
|
59
|
+
a.heartbeatEnabled !== e && (a.heartbeatEnabled = e, a.heartbeatEnabledAt = e ? i() : null, a.backendReachableOverride = null, e || (a.heartbeatConnected = !1, a.lastHeartbeatAt = null, a.syncInProgress = !1));
|
|
60
|
+
}, l = () => {
|
|
61
|
+
a.backendReachableOverride = !0, a.heartbeatConnected = !0, a.lastHeartbeatAt = i();
|
|
62
|
+
}, u = () => {
|
|
63
|
+
a.heartbeatConnected &&= !1;
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
start: () => {
|
|
67
|
+
if (typeof window > "u") return () => void 0;
|
|
68
|
+
let e = () => {
|
|
69
|
+
a.browserOnline = !0;
|
|
70
|
+
}, n = () => {
|
|
71
|
+
a.browserOnline = !1;
|
|
72
|
+
};
|
|
73
|
+
window.addEventListener("online", e), window.addEventListener("offline", n);
|
|
74
|
+
let o = window.setInterval(() => {
|
|
75
|
+
!a.heartbeatEnabled || a.lastHeartbeatAt == null || i() - a.lastHeartbeatAt > t && u();
|
|
76
|
+
}, r);
|
|
77
|
+
return () => {
|
|
78
|
+
window.removeEventListener("online", e), window.removeEventListener("offline", n), window.clearInterval(o);
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
getSnapshot: s,
|
|
82
|
+
setHeartbeatEnabled: c,
|
|
83
|
+
markHeartbeatConnected: l,
|
|
84
|
+
markHeartbeatDisconnected: u,
|
|
85
|
+
markHeartbeatReceived: (e) => {
|
|
86
|
+
a.backendReachableOverride = !0, a.heartbeatConnected = !0, a.lastHeartbeatAt = i(), a.syncInProgress = e;
|
|
87
|
+
},
|
|
88
|
+
markBackendUnavailable: () => {
|
|
89
|
+
a.backendReachableOverride = !1;
|
|
90
|
+
},
|
|
91
|
+
markBackendAvailable: () => {
|
|
92
|
+
a.backendReachableOverride = !0;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
export { r as OFFLINE_TEMP_ID_HEADER, t as OFFLINE_TEMP_PRODUCT_ID_LEGACY_HEADER, u as createOfflineStatusRuntime, n as extractReplayHeaders, i as hydratePagedSnapshot, l as isOfflineQueueableRequest, e as normalizeHeaders, s as runOfflineCreateWithTempId, o as runOfflineDelete, a as runOfflineUpdate };
|
|
98
|
+
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/offline/hydration/hydratePagedSnapshot.ts","../../src/offline/mutations/offlineMutations.ts","../../src/offline/queue/queueingPolicy.ts","../../src/offline/status/offlineStatusRuntime.ts"],"sourcesContent":["export type PageResult<TRow> = {\n content: TRow[];\n totalPages: number;\n};\n\nexport type FetchPage<TRow> = (page: number) => Promise<PageResult<TRow>>;\n\nexport type MapRow<TRow, TSnapshotRow> = (row: TRow) => TSnapshotRow | null;\n\nexport type ReplaceSnapshot<TSnapshotRow> = (rows: TSnapshotRow[]) => Promise<void>;\n\nexport async function hydratePagedSnapshot<TRow, TSnapshotRow>(args: {\n fetchPage: FetchPage<TRow>;\n mapRow: MapRow<TRow, TSnapshotRow>;\n replaceSnapshot: ReplaceSnapshot<TSnapshotRow>;\n}): Promise<{ rowCount: number }> {\n const rows: TRow[] = [];\n let page = 0;\n\n while (true) {\n const response = await args.fetchPage(page);\n rows.push(...response.content);\n\n if (page + 1 >= response.totalPages) {\n break;\n }\n\n page += 1;\n }\n\n const snapshotRows = rows.map(args.mapRow).filter((row): row is TSnapshotRow => row != null);\n await args.replaceSnapshot(snapshotRows);\n\n return { rowCount: snapshotRows.length };\n}\n","export async function runOfflineUpdate<TInput, TResult>(args: {\n input: TInput;\n persistLocal: (input: TInput) => Promise<void>;\n enqueue: (input: TInput) => Promise<void>;\n buildResult: (input: TInput) => TResult;\n}): Promise<TResult> {\n const { input, persistLocal, enqueue, buildResult } = args;\n\n await persistLocal(input);\n await enqueue(input);\n return buildResult(input);\n}\n\nexport async function runOfflineDelete<TId>(args: {\n id: TId;\n deleteLocal: (id: TId) => Promise<void>;\n enqueue: (id: TId) => Promise<void>;\n}): Promise<void> {\n const { id, deleteLocal, enqueue } = args;\n\n await deleteLocal(id);\n await enqueue(id);\n}\n\nexport async function runOfflineCreateWithTempId<TCreate, TTempId, TEntity extends { id: TTempId }>(args: {\n input: TCreate;\n allocateTempId: () => TTempId;\n buildLocalEntity: (input: TCreate, tempId: TTempId) => TEntity;\n persistLocal: (entity: TEntity) => Promise<void>;\n enqueue: (input: TCreate, tempId: TTempId) => Promise<void>;\n}): Promise<TEntity> {\n const { input, allocateTempId, buildLocalEntity, persistLocal, enqueue } = args;\n\n const tempId = allocateTempId();\n const localEntity = buildLocalEntity(input, tempId);\n\n await persistLocal(localEntity);\n await enqueue(input, tempId);\n return localEntity;\n}\n","import { type QueueableRequest, type QueueingPolicyOptions } from \"./queueingTypes\";\n\nconst DEFAULT_METHODS = new Set([\"POST\", \"PUT\", \"PATCH\", \"DELETE\"]);\n\nexport function isOfflineQueueableRequest(request: QueueableRequest, options?: QueueingPolicyOptions): boolean {\n const methods = new Set((options?.includeMethods ?? [...DEFAULT_METHODS]).map(method => method.toUpperCase()));\n const method = (request.method ?? \"GET\").toUpperCase();\n\n if (!methods.has(method)) {\n return false;\n }\n\n const apiPrefix = options?.apiPrefix ?? \"/api/\";\n if (!request.url.startsWith(apiPrefix)) {\n return false;\n }\n\n const excludedPrefixes = options?.excludedPrefixes ?? [\"/api/auth\", \"/api/offline/\"];\n if (excludedPrefixes.some(prefix => request.url.startsWith(prefix))) {\n return false;\n }\n\n if ((options?.excludeSearchPosts ?? true) && method === \"POST\") {\n const pathname = request.url.split(\"?\")[0];\n if (pathname.endsWith(\"/search\")) {\n return false;\n }\n }\n\n return true;\n}\n","import {\n type OfflineStatusRuntime,\n type OfflineStatusRuntimeOptions,\n type OfflineStatusSnapshot,\n} from \"./offlineStatusTypes\";\n\ntype OfflineStatusState = {\n browserOnline: boolean;\n heartbeatEnabled: boolean;\n heartbeatEnabledAt: number | null;\n backendReachableOverride: boolean | null;\n heartbeatConnected: boolean;\n syncInProgress: boolean;\n lastHeartbeatAt: number | null;\n};\n\nexport function createOfflineStatusRuntime(options?: OfflineStatusRuntimeOptions): OfflineStatusRuntime {\n const staleAfterMs = options?.staleAfterMs ?? 15_000;\n const bootstrapAssumeOnlineMs = options?.bootstrapAssumeOnlineMs ?? 6_000;\n const tickMs = options?.tickMs ?? 1_000;\n const now = options?.now ?? (() => Date.now());\n\n const state: OfflineStatusState = {\n browserOnline: typeof navigator === \"undefined\" ? true : navigator.onLine,\n heartbeatEnabled: false,\n heartbeatEnabledAt: null,\n backendReachableOverride: null,\n heartbeatConnected: false,\n syncInProgress: false,\n lastHeartbeatAt: null,\n };\n\n const computeOnline = (): boolean => {\n if (state.backendReachableOverride === false) {\n return false;\n }\n\n if (!state.browserOnline) {\n return false;\n }\n\n if (!state.heartbeatEnabled) {\n return true;\n }\n\n if (state.lastHeartbeatAt == null) {\n if (state.heartbeatEnabledAt == null) {\n return false;\n }\n\n return now() - state.heartbeatEnabledAt <= bootstrapAssumeOnlineMs;\n }\n\n return now() - state.lastHeartbeatAt <= staleAfterMs;\n };\n\n const getSnapshot = (): OfflineStatusSnapshot => {\n return {\n online: computeOnline(),\n heartbeatEnabled: state.heartbeatEnabled,\n heartbeatConnected: state.heartbeatConnected,\n syncInProgress: state.syncInProgress,\n lastHeartbeatAt: state.lastHeartbeatAt,\n };\n };\n\n const setHeartbeatEnabled = (enabled: boolean): void => {\n if (state.heartbeatEnabled === enabled) {\n return;\n }\n\n state.heartbeatEnabled = enabled;\n state.heartbeatEnabledAt = enabled ? now() : null;\n state.backendReachableOverride = null;\n\n if (!enabled) {\n state.heartbeatConnected = false;\n state.lastHeartbeatAt = null;\n state.syncInProgress = false;\n }\n };\n\n const markHeartbeatConnected = (): void => {\n state.backendReachableOverride = true;\n state.heartbeatConnected = true;\n state.lastHeartbeatAt = now();\n };\n\n const markHeartbeatDisconnected = (): void => {\n if (!state.heartbeatConnected) {\n return;\n }\n\n state.heartbeatConnected = false;\n };\n\n const markHeartbeatReceived = (syncInProgress: boolean): void => {\n state.backendReachableOverride = true;\n state.heartbeatConnected = true;\n state.lastHeartbeatAt = now();\n state.syncInProgress = syncInProgress;\n };\n\n const markBackendUnavailable = (): void => {\n state.backendReachableOverride = false;\n };\n\n const markBackendAvailable = (): void => {\n state.backendReachableOverride = true;\n };\n\n const start = (): (() => void) => {\n if (typeof window === \"undefined\") {\n return () => undefined;\n }\n\n const onBrowserOnline = (): void => {\n state.browserOnline = true;\n };\n\n const onBrowserOffline = (): void => {\n state.browserOnline = false;\n };\n\n window.addEventListener(\"online\", onBrowserOnline);\n window.addEventListener(\"offline\", onBrowserOffline);\n\n const intervalId = window.setInterval(() => {\n if (!state.heartbeatEnabled || state.lastHeartbeatAt == null) {\n return;\n }\n\n if (now() - state.lastHeartbeatAt > staleAfterMs) {\n markHeartbeatDisconnected();\n }\n }, tickMs);\n\n return () => {\n window.removeEventListener(\"online\", onBrowserOnline);\n window.removeEventListener(\"offline\", onBrowserOffline);\n window.clearInterval(intervalId);\n };\n };\n\n return {\n start,\n getSnapshot,\n setHeartbeatEnabled,\n markHeartbeatConnected,\n markHeartbeatDisconnected,\n markHeartbeatReceived,\n markBackendUnavailable,\n markBackendAvailable,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare function runOfflineUpdate<TInput, TResult>(args: {
|
|
2
|
+
input: TInput;
|
|
3
|
+
persistLocal: (input: TInput) => Promise<void>;
|
|
4
|
+
enqueue: (input: TInput) => Promise<void>;
|
|
5
|
+
buildResult: (input: TInput) => TResult;
|
|
6
|
+
}): Promise<TResult>;
|
|
7
|
+
export declare function runOfflineDelete<TId>(args: {
|
|
8
|
+
id: TId;
|
|
9
|
+
deleteLocal: (id: TId) => Promise<void>;
|
|
10
|
+
enqueue: (id: TId) => Promise<void>;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
export declare function runOfflineCreateWithTempId<TCreate, TTempId, TEntity extends {
|
|
13
|
+
id: TTempId;
|
|
14
|
+
}>(args: {
|
|
15
|
+
input: TCreate;
|
|
16
|
+
allocateTempId: () => TTempId;
|
|
17
|
+
buildLocalEntity: (input: TCreate, tempId: TTempId) => TEntity;
|
|
18
|
+
persistLocal: (entity: TEntity) => Promise<void>;
|
|
19
|
+
enqueue: (input: TCreate, tempId: TTempId) => Promise<void>;
|
|
20
|
+
}): Promise<TEntity>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const OFFLINE_TEMP_ID_HEADER = "X-Offline-Temp-Id";
|
|
2
|
+
export declare const OFFLINE_TEMP_PRODUCT_ID_LEGACY_HEADER = "X-Offline-Temp-Product-Id";
|
|
3
|
+
export declare function normalizeHeaders(input: Record<string, unknown> | undefined): Record<string, string>;
|
|
4
|
+
export declare function extractReplayHeaders(headers: Record<string, unknown> | undefined): Record<string, string>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type OfflineSyncCommand = {
|
|
2
|
+
commandId: string;
|
|
3
|
+
method: string;
|
|
4
|
+
url: string;
|
|
5
|
+
body: unknown | null;
|
|
6
|
+
headers: Record<string, string>;
|
|
7
|
+
createdAt: number;
|
|
8
|
+
};
|
|
9
|
+
export type QueueableRequest = {
|
|
10
|
+
method?: string;
|
|
11
|
+
url: string;
|
|
12
|
+
};
|
|
13
|
+
export type QueueingPolicyOptions = {
|
|
14
|
+
includeMethods?: string[];
|
|
15
|
+
apiPrefix?: string;
|
|
16
|
+
excludedPrefixes?: string[];
|
|
17
|
+
excludeSearchPosts?: boolean;
|
|
18
|
+
};
|