@keepkit/core 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/features/items/types.ts","../src/features/persistence/scope.ts","../src/storage/sync.ts","../src/storage/index.ts"],"sourcesContent":["export type KeepItemStatus = \"available\" | \"expired\" | \"removed\" | \"deleted\" | \"private\" | \"unknown\";\n\nexport type SyncScope = {\n userId?: string;\n tenantId?: string;\n};\n\nexport type KeepItem<TMeta = Record<string, unknown>> = {\n id: string;\n savedAt: number;\n updatedAt: number;\n meta: TMeta;\n /** Optional zero-based position in the user's custom viewing order. */\n order?: number;\n targetType?: string;\n note?: string;\n tags?: string[];\n schemaVersion?: number;\n /** Optional server-provided revision used by synchronizing adapters. */\n revision?: string;\n /** Timestamp for the last successful refresh of source metadata. */\n metaUpdatedAt?: number;\n /** Source availability as last determined by a revalidator. Omitted means available. */\n status?: KeepItemStatus;\n /** Optional human-readable or machine-provided reason for a non-available status. */\n statusReason?: string;\n /** Optional user/tenant scope used by a synchronizing adapter. */\n scope?: SyncScope;\n};\n\n/** The minimal item description accepted by save controls and hooks. */\nexport type KeepItemInput<TMeta = Record<string, unknown>> = {\n id: string;\n meta: TMeta;\n order?: number;\n targetType?: string;\n note?: string;\n tags?: string[];\n};\n\nexport interface StorageAdapter<TMeta = Record<string, unknown>> {\n getAll(): Promise<KeepItem<TMeta>[]>;\n set(item: KeepItem<TMeta>): Promise<void>;\n setMany?(items: KeepItem<TMeta>[]): Promise<void>;\n remove(id: string): Promise<void>;\n removeMany?(ids: string[]): Promise<void>;\n clear(): Promise<void>;\n merge?(localItems: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]>;\n subscribe?(listener: () => void): () => void;\n readonly storageKey?: string;\n}\n\nexport type KeepAction =\n | \"refresh\"\n | \"import\"\n | \"export\"\n | \"save\"\n | \"updateNote\"\n | \"updateTags\"\n | \"updateTagsBatch\"\n | \"revalidate\"\n | \"remove\"\n | \"removeBatch\"\n | \"undo\"\n | \"reorder\"\n | \"clear\";\n\nexport type KeepChangePhase = \"local\" | \"synced\";\n\nexport type KeepChangeContext<TMeta = Record<string, unknown>> = {\n action: KeepAction;\n id?: string;\n item?: KeepItem<TMeta>;\n items?: KeepItem<TMeta>[];\n phase: KeepChangePhase;\n};\n\nexport type KeepPluginContext<TMeta = Record<string, unknown>> = {\n action: KeepAction;\n id?: string;\n item?: KeepItem<TMeta>;\n items?: KeepItem<TMeta>[];\n};\n\nexport type KeepPlugin<TMeta = Record<string, unknown>> = {\n name?: string;\n before?: (context: KeepPluginContext<TMeta>) => void | Promise<void>;\n after?: (context: KeepPluginContext<TMeta>) => void | Promise<void>;\n onError?: (error: unknown, context: KeepErrorContext) => void;\n};\n\nexport type KeepSchemaParseResult<T> = { success: true; data: T } | { success: false; error?: unknown };\n\nexport type KeepSchema<T> =\n | { parse: (value: unknown) => T | Promise<T> }\n | { safeParse: (value: unknown) => KeepSchemaParseResult<T> | Promise<KeepSchemaParseResult<T>> }\n | {\n \"~standard\": {\n validate: (\n value: unknown,\n ) => { value?: T; issues?: readonly unknown[] } | Promise<{ value?: T; issues?: readonly unknown[] }>;\n };\n };\n\nexport type KeepInvalidItemPolicy = \"error\" | \"drop\";\n\nexport type KeepSyncStatus = \"idle\" | \"pending\" | \"syncing\" | \"synced\" | \"conflict\" | \"error\";\n\nexport type KeepSyncResolution = \"local\" | \"remote\" | \"manual\";\n\nexport type KeepSyncConflict<TMeta = Record<string, unknown>> = {\n id: string;\n operation: SyncOperation<TMeta>;\n remote: KeepItem<TMeta>;\n revision?: string;\n};\n\nexport type KeepSyncState<TMeta = Record<string, unknown>> = {\n status: KeepSyncStatus;\n pendingCount: number;\n conflictIds: string[];\n /** Detailed conflict records when the adapter supports interactive resolution. */\n conflicts?: KeepSyncConflict<TMeta>[];\n lastSyncedAt?: number;\n error?: unknown;\n};\n\nexport type SyncOperation<TMeta = Record<string, unknown>> = {\n operationId: string;\n type: \"upsert\" | \"remove\";\n id: string;\n item?: KeepItem<TMeta>;\n createdAt: number;\n baseRevision?: string;\n attempts?: number;\n scope?: SyncScope;\n};\n\nexport type KeepSyncAuthStatus = 401 | 403;\n\n/** Indicates that a sync request needs the host application to re-authenticate. */\nexport class KeepSyncAuthError<TMeta = Record<string, unknown>> extends Error {\n readonly status: KeepSyncAuthStatus;\n readonly operation?: SyncOperation<TMeta>;\n readonly scope?: SyncScope;\n readonly cause?: unknown;\n\n constructor(\n status: KeepSyncAuthStatus,\n options: { operation?: SyncOperation<TMeta>; scope?: SyncScope; cause?: unknown },\n ) {\n super(`KeepKit sync authorization failed with status ${status}.`);\n this.name = \"KeepSyncAuthError\";\n this.status = status;\n this.operation = options.operation;\n this.scope = options.scope;\n if (options.cause !== undefined) this.cause = options.cause;\n }\n}\n\nexport function isKeepSyncAuthError(error: unknown): error is KeepSyncAuthError {\n return error instanceof KeepSyncAuthError;\n}\n\nexport type RemoteSyncResult<TMeta = Record<string, unknown>> =\n | { type: \"synced\"; item?: KeepItem<TMeta>; revision?: string }\n | { type: \"conflict\"; remote: KeepItem<TMeta>; revision?: string };\n\nexport type KeepConflictContext<TMeta = Record<string, unknown>> = {\n operation: SyncOperation<TMeta>;\n remoteRevision?: string;\n};\n\nexport type KeepConflictResolver<TMeta = Record<string, unknown>> = (\n local: KeepItem<TMeta> | undefined,\n remote: KeepItem<TMeta>,\n context: KeepConflictContext<TMeta>,\n) => KeepItem<TMeta> | undefined | Promise<KeepItem<TMeta> | undefined>;\n\nexport interface RemoteSyncDriver<TMeta = Record<string, unknown>> {\n push(operation: SyncOperation<TMeta>): Promise<RemoteSyncResult<TMeta>>;\n pull?: () => Promise<KeepItem<TMeta>[]>;\n}\n\nexport interface SyncQueueAdapter<TMeta = Record<string, unknown>> {\n getAll(): Promise<SyncOperation<TMeta>[]>;\n setMany(operations: SyncOperation<TMeta>[]): Promise<void>;\n remove(operationIds: string[]): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport interface SyncCapableStorageAdapter<TMeta = Record<string, unknown>> extends StorageAdapter<TMeta> {\n getSyncState(): KeepSyncState<TMeta>;\n subscribeSync(listener: () => void): () => void;\n subscribeScope?(listener: () => void): () => void;\n flushSync(): Promise<void>;\n retrySync?(): Promise<void>;\n resolveSyncConflict?(id: string, resolution: KeepSyncResolution, item?: KeepItem<TMeta>): Promise<void>;\n dispose?(): void;\n}\n\nexport type KeepStorageOperation = \"getAll\" | \"set\" | \"remove\" | \"clear\" | \"merge\";\n\nexport class KeepStorageError extends Error {\n readonly operation: KeepStorageOperation;\n readonly storageKey?: string;\n readonly cause?: unknown;\n\n constructor(\n message: string,\n options: {\n operation: KeepStorageOperation;\n storageKey?: string;\n cause?: unknown;\n },\n ) {\n super(message);\n this.name = \"KeepStorageError\";\n this.operation = options.operation;\n this.storageKey = options.storageKey;\n if (options.cause !== undefined) this.cause = options.cause;\n }\n}\n\nexport class KeepStorageQuotaError extends KeepStorageError {\n constructor(options: { operation: KeepStorageOperation; storageKey?: string; cause?: unknown }) {\n super(\"KeepKit storage quota was exceeded.\", options);\n this.name = \"KeepStorageQuotaError\";\n }\n}\n\nexport class KeepStorageAccessError extends KeepStorageError {\n constructor(options: { operation: KeepStorageOperation; storageKey?: string; cause?: unknown }) {\n super(\"KeepKit could not access the configured storage.\", options);\n this.name = \"KeepStorageAccessError\";\n }\n}\n\nexport class KeepStorageParseError extends KeepStorageError {\n constructor(options: { operation: KeepStorageOperation; storageKey?: string; cause?: unknown }) {\n super(\"KeepKit found invalid data in the configured storage.\", options);\n this.name = \"KeepStorageParseError\";\n }\n}\n\nexport type KeepErrorContext = {\n action: KeepAction;\n id?: string;\n};\n\nexport type KeepErrorHandler = (error: unknown, context: KeepErrorContext) => void;\n\nexport type KeepEventHandlers<TMeta = Record<string, unknown>> = {\n onSave?: (item: KeepItem<TMeta>) => void;\n onRemove?: (item: KeepItem<TMeta>) => void;\n onNoteUpdate?: (id: string, note?: string) => void;\n onTagsUpdate?: (id: string, tags?: string[]) => void;\n onChange?: (context: KeepChangeContext<TMeta>) => void | Promise<void>;\n onUndo?: (items: KeepItem<TMeta>[]) => void;\n onError?: KeepErrorHandler;\n};\n\nexport type KeepUndoState = {\n canUndo: boolean;\n ids: string[];\n startedAt?: number;\n expiresAt?: number;\n};\n\nexport function normalizeKeepTags(tags?: string[]): string[] | undefined {\n if (!tags) return undefined;\n const normalized = [...new Set(tags.map((tag) => tag.trim()).filter(Boolean))];\n return normalized.length > 0 ? normalized : undefined;\n}\n","import type { KeepItem, StorageAdapter, SyncOperation, SyncQueueAdapter, SyncScope } from \"../items/types\";\n\nexport type KeepScope = SyncScope;\n\n/** Return a stable, human-readable namespace for browser storage and queues. */\nexport function getKeepScopeKey(scope?: KeepScope): string {\n if (!scope?.userId && !scope?.tenantId) return \"\";\n return `:${encodeURIComponent(scope.tenantId ?? \"_\")}:${encodeURIComponent(scope.userId ?? \"_\")}`;\n}\n\nexport function isSameKeepScope(left: KeepScope | undefined, right: KeepScope | undefined): boolean {\n return left?.userId === right?.userId && left?.tenantId === right?.tenantId;\n}\n\n/**\n * Adds an isolated user/tenant view over any StorageAdapter. Writes preserve\n * records belonging to other scopes, which makes account switching safe even\n * when applications share one physical localStorage key.\n */\nexport class ScopedStorageAdapter<TMeta = Record<string, unknown>> implements StorageAdapter<TMeta> {\n readonly storageKey?: string;\n private readonly base: StorageAdapter<TMeta>;\n private readonly scope?: KeepScope;\n\n constructor(base: StorageAdapter<TMeta>, scope?: KeepScope) {\n this.base = base;\n this.scope = scope;\n const scopeKey = getKeepScopeKey(scope);\n this.storageKey = base.storageKey\n ? base.storageKey.endsWith(scopeKey) && scopeKey\n ? base.storageKey\n : `${base.storageKey}${scopeKey}`\n : undefined;\n }\n\n async getAll(): Promise<KeepItem<TMeta>[]> {\n const items = await this.base.getAll();\n return this.scope ? items.filter((item) => isSameKeepScope(item.scope, this.scope)) : items;\n }\n\n async set(item: KeepItem<TMeta>): Promise<void> {\n await this.setMany([item]);\n }\n\n async setMany(items: KeepItem<TMeta>[]): Promise<void> {\n const current = await this.base.getAll();\n const scoped = items.map((item) => ({ ...item, ...(this.scope ? { scope: this.scope } : {}) }));\n const ids = new Set(scoped.map((item) => item.id));\n const next = current.filter((item) => !ids.has(item.id) || !isSameKeepScope(item.scope, this.scope));\n await writeAll(this.base, [...next, ...scoped]);\n }\n\n async remove(id: string): Promise<void> {\n const current = await this.base.getAll();\n await writeAll(\n this.base,\n current.filter((item) => item.id !== id || !isSameKeepScope(item.scope, this.scope)),\n );\n }\n\n async removeMany(ids: string[]): Promise<void> {\n const idSet = new Set(ids);\n const current = await this.base.getAll();\n await writeAll(\n this.base,\n current.filter((item) => !idSet.has(item.id) || !isSameKeepScope(item.scope, this.scope)),\n );\n }\n\n async clear(): Promise<void> {\n const current = await this.base.getAll();\n await writeAll(\n this.base,\n current.filter((item) => !isSameKeepScope(item.scope, this.scope)),\n );\n }\n\n async merge(items: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n await this.setMany(items);\n return this.getAll();\n }\n\n subscribe(listener: () => void): () => void {\n return this.base.subscribe?.(listener) ?? (() => undefined);\n }\n}\n\nexport function createScopedStorageAdapter<TMeta = Record<string, unknown>>(\n base: StorageAdapter<TMeta>,\n scope?: KeepScope,\n): ScopedStorageAdapter<TMeta> {\n return new ScopedStorageAdapter(base, scope);\n}\n\n/** Scope a durable synchronization queue so a user switch cannot flush another user's operations. */\nexport class ScopedSyncQueueAdapter<TMeta = Record<string, unknown>> implements SyncQueueAdapter<TMeta> {\n private readonly base: SyncQueueAdapter<TMeta>;\n private readonly scope?: KeepScope;\n\n constructor(base: SyncQueueAdapter<TMeta>, scope?: KeepScope) {\n this.base = base;\n this.scope = scope;\n }\n\n async getAll(): Promise<SyncOperation<TMeta>[]> {\n const operations = await this.base.getAll();\n return this.scope ? operations.filter((operation) => isSameKeepScope(operation.scope, this.scope)) : operations;\n }\n\n async setMany(operations: SyncOperation<TMeta>[]): Promise<void> {\n const current = await this.base.getAll();\n const scoped = operations.map((operation) => ({ ...operation, ...(this.scope ? { scope: this.scope } : {}) }));\n const ids = new Set(scoped.map((operation) => operation.operationId));\n await this.base.setMany([\n ...current.filter(\n (operation) => !ids.has(operation.operationId) && !isSameKeepScope(operation.scope, this.scope),\n ),\n ...scoped,\n ]);\n }\n\n remove(operationIds: string[]): Promise<void> {\n return this.base.remove(operationIds);\n }\n\n clear(): Promise<void> {\n return this.base\n .getAll()\n .then((operations) =>\n this.base.setMany(operations.filter((operation) => !isSameKeepScope(operation.scope, this.scope))),\n );\n }\n}\n\nasync function writeAll<TMeta>(base: StorageAdapter<TMeta>, items: KeepItem<TMeta>[]): Promise<void> {\n if (base.setMany) {\n await base.setMany(items);\n return;\n }\n const existing = await base.getAll();\n const ids = new Set(items.map((item) => item.id));\n for (const item of existing) {\n if (!ids.has(item.id)) await base.remove(item.id);\n }\n for (const item of items) await base.set(item);\n}\n","import type {\n KeepConflictResolver,\n KeepItem,\n KeepSyncConflict,\n KeepSyncResolution,\n KeepSyncState,\n RemoteSyncDriver,\n RemoteSyncResult,\n StorageAdapter,\n SyncCapableStorageAdapter,\n SyncOperation,\n SyncQueueAdapter,\n SyncScope,\n} from \"../features/items/types\";\nimport { isKeepSyncAuthError } from \"../features/items/types\";\n\nexport type LocalStorageSyncQueueOptions = {\n key?: string;\n storage?: Storage;\n};\n\nexport type IndexedDBSyncQueueOptions = {\n databaseName?: string;\n storeName?: string;\n version?: number;\n indexedDB?: IDBFactory;\n};\n\nexport type FallbackSyncQueueAdapterOptions<TMeta = Record<string, unknown>> = {\n primary: SyncQueueAdapter<TMeta>;\n fallback: SyncQueueAdapter<TMeta>;\n shouldFallback?: (error: unknown) => boolean;\n};\n\nexport type SyncStorageAdapterOptions<TMeta = Record<string, unknown>> = {\n local: StorageAdapter<TMeta>;\n remote: RemoteSyncDriver<TMeta>;\n queue?: SyncQueueAdapter<TMeta>;\n queueKey?: string;\n queueDatabaseName?: string;\n clientId?: string;\n now?: () => number;\n resolveConflict?: KeepConflictResolver<TMeta>;\n userId?: string;\n tenantId?: string;\n maxRetries?: number;\n retryDelayMs?: number;\n retryBackoff?: number;\n scope?: SyncScope;\n};\n\nexport const DEFAULT_SYNC_QUEUE_KEY = \"keepkit:sync-queue\";\nexport const DEFAULT_SYNC_QUEUE_DATABASE = \"keepkit-sync\";\nexport const DEFAULT_SYNC_QUEUE_STORE = \"sync-queue\";\n\nexport class LocalStorageSyncQueueAdapter<TMeta = Record<string, unknown>> implements SyncQueueAdapter<TMeta> {\n private readonly key: string;\n private readonly storage: Storage | undefined;\n\n constructor(options: LocalStorageSyncQueueOptions = {}) {\n this.key = options.key ?? DEFAULT_SYNC_QUEUE_KEY;\n this.storage = options.storage ?? getBrowserStorage();\n }\n\n async getAll(): Promise<SyncOperation<TMeta>[]> {\n if (!this.storage) return [];\n const raw = this.storage.getItem(this.key);\n if (!raw) return [];\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch (cause) {\n throw Object.assign(new Error(\"KeepKit sync queue contains invalid JSON.\"), { cause });\n }\n if (!Array.isArray(value) || !value.every(isSyncOperation)) {\n throw new Error(\"KeepKit sync queue contains invalid operations.\");\n }\n return value as SyncOperation<TMeta>[];\n }\n\n async setMany(operations: SyncOperation<TMeta>[]): Promise<void> {\n if (!this.storage) return;\n this.storage.setItem(this.key, JSON.stringify(operations));\n }\n\n async remove(operationIds: string[]): Promise<void> {\n const ids = new Set(operationIds);\n const current = await this.getAll();\n await this.setMany(current.filter((operation) => !ids.has(operation.operationId)));\n }\n\n async clear(): Promise<void> {\n this.storage?.removeItem(this.key);\n }\n}\n\nexport class IndexedDBSyncQueueAdapter<TMeta = Record<string, unknown>> implements SyncQueueAdapter<TMeta> {\n private readonly databaseName: string;\n private readonly storeName: string;\n private readonly version: number;\n private readonly indexedDB: IDBFactory | undefined;\n private databasePromise: Promise<IDBDatabase | undefined> | undefined;\n\n constructor(options: IndexedDBSyncQueueOptions = {}) {\n this.databaseName = options.databaseName ?? DEFAULT_SYNC_QUEUE_DATABASE;\n this.storeName = options.storeName ?? DEFAULT_SYNC_QUEUE_STORE;\n this.version = options.version ?? 1;\n this.indexedDB = options.indexedDB ?? getBrowserIndexedDB();\n }\n\n async getAll(): Promise<SyncOperation<TMeta>[]> {\n const database = await this.open();\n if (!database) return [];\n const transaction = database.transaction(this.storeName, \"readonly\");\n const value: unknown = await requestToPromise(transaction.objectStore(this.storeName).getAll());\n if (!Array.isArray(value) || !value.every(isSyncOperation)) {\n throw new Error(\"KeepKit sync queue contains invalid operations.\");\n }\n return value as SyncOperation<TMeta>[];\n }\n\n async setMany(operations: SyncOperation<TMeta>[]): Promise<void> {\n const database = await this.open();\n if (!database) return;\n const transaction = database.transaction(this.storeName, \"readwrite\");\n const store = transaction.objectStore(this.storeName);\n for (const operation of operations) store.put(operation);\n await transactionToPromise(transaction);\n }\n\n async remove(operationIds: string[]): Promise<void> {\n const database = await this.open();\n if (!database) return;\n const transaction = database.transaction(this.storeName, \"readwrite\");\n const store = transaction.objectStore(this.storeName);\n for (const operationId of new Set(operationIds)) store.delete(operationId);\n await transactionToPromise(transaction);\n }\n\n async clear(): Promise<void> {\n const database = await this.open();\n if (!database) return;\n const transaction = database.transaction(this.storeName, \"readwrite\");\n transaction.objectStore(this.storeName).clear();\n await transactionToPromise(transaction);\n }\n\n private open(): Promise<IDBDatabase | undefined> {\n if (!this.indexedDB) return Promise.resolve(undefined);\n if (!this.databasePromise) {\n this.databasePromise = new Promise((resolve, reject) => {\n let request: IDBOpenDBRequest;\n try {\n request = this.indexedDB?.open(this.databaseName, this.version) as IDBOpenDBRequest;\n } catch (cause) {\n reject(cause);\n return;\n }\n request.onupgradeneeded = () => {\n if (!request.result.objectStoreNames.contains(this.storeName)) {\n request.result.createObjectStore(this.storeName, { keyPath: \"operationId\" });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n request.onblocked = () => reject(request.error ?? new Error(\"IndexedDB open was blocked.\"));\n });\n }\n return this.databasePromise.catch((cause) => {\n this.databasePromise = undefined;\n throw cause;\n });\n }\n}\n\n/** Keeps the durable sync queue available when IndexedDB is blocked or fails. */\nexport class FallbackSyncQueueAdapter<TMeta = Record<string, unknown>> implements SyncQueueAdapter<TMeta> {\n private readonly primary: SyncQueueAdapter<TMeta>;\n private readonly fallback: SyncQueueAdapter<TMeta>;\n private readonly shouldFallback: (error: unknown) => boolean;\n private active: \"primary\" | \"fallback\" = \"primary\";\n\n constructor(options: FallbackSyncQueueAdapterOptions<TMeta>) {\n this.primary = options.primary;\n this.fallback = options.fallback;\n this.shouldFallback = options.shouldFallback ?? (() => true);\n }\n\n get isUsingFallback(): boolean {\n return this.active === \"fallback\";\n }\n\n getAll(): Promise<SyncOperation<TMeta>[]> {\n return this.execute((adapter) => adapter.getAll());\n }\n\n setMany(operations: SyncOperation<TMeta>[]): Promise<void> {\n return this.execute((adapter) => adapter.setMany(operations));\n }\n\n remove(operationIds: string[]): Promise<void> {\n return this.execute((adapter) => adapter.remove(operationIds));\n }\n\n clear(): Promise<void> {\n return this.execute((adapter) => adapter.clear());\n }\n\n private async execute<TResult>(operation: (adapter: SyncQueueAdapter<TMeta>) => Promise<TResult>): Promise<TResult> {\n const adapter = this.active === \"primary\" ? this.primary : this.fallback;\n try {\n return await operation(adapter);\n } catch (error) {\n if (this.active !== \"primary\" || !this.shouldFallback(error)) throw error;\n this.active = \"fallback\";\n return operation(this.fallback);\n }\n }\n}\n\n/** A local-first adapter that persists remote operations until they are acknowledged. */\nexport class SyncStorageAdapter<TMeta = Record<string, unknown>> implements SyncCapableStorageAdapter<TMeta> {\n readonly storageKey?: string;\n private readonly local: StorageAdapter<TMeta>;\n private readonly remote: RemoteSyncDriver<TMeta>;\n private readonly queue: SyncQueueAdapter<TMeta>;\n private readonly clientId: string;\n private readonly now: () => number;\n private readonly resolveConflict?: KeepConflictResolver<TMeta>;\n private readonly scope?: SyncScope;\n private readonly maxRetries: number;\n private readonly retryDelayMs: number;\n private readonly retryBackoff: number;\n private readonly listeners = new Set<() => void>();\n private readonly dataListeners = new Set<() => void>();\n private queueItems: SyncOperation<TMeta>[] = [];\n private queueLoaded = false;\n private queueLoadPromise: Promise<void> | undefined;\n private flushPromise: Promise<void> | undefined;\n private state: KeepSyncState<TMeta> = { status: \"idle\", pendingCount: 0, conflictIds: [], conflicts: [] };\n private readonly conflicts = new Map<string, KeepSyncConflict<TMeta>>();\n private onlineHandler?: () => void;\n private disposed = false;\n\n constructor(options: SyncStorageAdapterOptions<TMeta>) {\n this.local = options.local;\n this.remote = options.remote;\n this.queue = options.queue ?? createDefaultQueue<TMeta>(options);\n this.clientId = options.clientId ?? createId();\n this.now = options.now ?? Date.now;\n this.resolveConflict = options.resolveConflict;\n this.scope = getSyncScope(options);\n this.maxRetries = Math.max(0, options.maxRetries ?? 3);\n this.retryDelayMs = Math.max(0, options.retryDelayMs ?? 0);\n this.retryBackoff = Math.max(1, options.retryBackoff ?? 2);\n this.storageKey = this.local.storageKey;\n if (typeof window !== \"undefined\") {\n this.onlineHandler = () => void this.flushSync();\n window.addEventListener(\"online\", this.onlineHandler);\n }\n void this.resumeQueue();\n }\n\n getSyncState = (): KeepSyncState<TMeta> => this.state;\n\n subscribeSync = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n subscribe = (listener: () => void): (() => void) => {\n this.dataListeners.add(listener);\n const unsubscribeLocal = this.local.subscribe?.(listener) ?? (() => undefined);\n return () => {\n this.dataListeners.delete(listener);\n unsubscribeLocal();\n };\n };\n\n async getAll(): Promise<KeepItem<TMeta>[]> {\n const items = await this.local.getAll();\n const scope = this.scope;\n if (!scope) return items;\n return items.filter((item) => sameScope(item.scope, scope));\n }\n\n async set(item: KeepItem<TMeta>): Promise<void> {\n const scopedItem = this.applyScope(item);\n const operation = this.createOperation(\"upsert\", scopedItem.id, scopedItem);\n await this.enqueueBeforeLocalWrite(operation);\n try {\n await this.local.set(scopedItem);\n } catch (cause) {\n await this.removeQueued(operation.operationId);\n throw cause;\n }\n this.notifyDataListeners();\n this.setPendingState();\n }\n\n async setMany(items: KeepItem<TMeta>[]): Promise<void> {\n const scopedItems = items.map((item) => this.applyScope(item));\n const operations = scopedItems.map((item) => this.createOperation(\"upsert\", item.id, item));\n await this.enqueueManyBeforeLocalWrite(operations);\n try {\n if (this.local.setMany) await this.local.setMany(scopedItems);\n else for (const item of scopedItems) await this.local.set(item);\n } catch (cause) {\n await this.removeQueued(operations.map((operation) => operation.operationId));\n throw cause;\n }\n this.notifyDataListeners();\n this.setPendingState();\n }\n\n async remove(id: string): Promise<void> {\n const operation = this.createOperation(\"remove\", id);\n await this.enqueueBeforeLocalWrite(operation);\n try {\n await this.local.remove(id);\n } catch (cause) {\n await this.removeQueued(operation.operationId);\n throw cause;\n }\n this.notifyDataListeners();\n this.setPendingState();\n }\n\n async removeMany(ids: string[]): Promise<void> {\n const operations = [...new Set(ids)].map((id) => this.createOperation(\"remove\", id));\n await this.enqueueManyBeforeLocalWrite(operations);\n try {\n if (this.local.removeMany) await this.local.removeMany(ids);\n else for (const id of ids) await this.local.remove(id);\n } catch (cause) {\n await this.removeQueued(operations.map((operation) => operation.operationId));\n throw cause;\n }\n this.notifyDataListeners();\n this.setPendingState();\n }\n\n async clear(): Promise<void> {\n const items = await this.getAll();\n await this.removeMany(items.map((item) => item.id));\n await this.local.clear();\n }\n\n async merge(localItems: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n const merged = this.local.merge\n ? await this.local.merge(localItems)\n : await mergeLocalItems(localItems, this.local);\n await this.setMany(localItems);\n return merged;\n }\n\n async flushSync(): Promise<void> {\n if (this.flushPromise) return this.flushPromise;\n this.flushPromise = this.runFlush().finally(() => {\n this.flushPromise = undefined;\n });\n return this.flushPromise;\n }\n\n retrySync(): Promise<void> {\n return this.flushSync();\n }\n\n async resolveSyncConflict(id: string, resolution: KeepSyncResolution, item?: KeepItem<TMeta>): Promise<void> {\n await this.loadQueue();\n const conflict = this.conflicts.get(id);\n if (!conflict) return;\n if (resolution === \"manual\" && !item) {\n throw new Error(`KeepKit manual conflict resolution requires an item for \"${id}\".`);\n }\n\n if (resolution === \"remote\") {\n await this.local.set(this.applyScope(conflict.remote));\n await this.removeQueued(conflict.operation.operationId);\n } else {\n const retry = item\n ? this.createOperation(\"upsert\", item.id, {\n ...item,\n revision: conflict.revision ?? item.revision,\n })\n : {\n ...conflict.operation,\n operationId: `${this.clientId}:${this.now()}:${createId()}`,\n createdAt: this.now(),\n baseRevision: conflict.revision,\n attempts: 0,\n };\n if (retry.item) await this.local.set(this.applyScope(retry.item));\n await this.replaceQueued(conflict.operation, retry);\n }\n\n this.conflicts.delete(id);\n this.updateState({\n status: this.queueItems.length > 0 ? \"pending\" : \"synced\",\n pendingCount: this.queueItems.length,\n conflictIds: [...this.conflicts.keys()],\n conflicts: [...this.conflicts.values()],\n });\n if (resolution !== \"remote\" && this.queueItems.length > 0) await this.flushSync();\n }\n\n dispose(): void {\n this.disposed = true;\n if (this.onlineHandler) window.removeEventListener(\"online\", this.onlineHandler);\n this.listeners.clear();\n this.dataListeners.clear();\n }\n\n private async runFlush(): Promise<void> {\n await this.loadQueue();\n if (this.disposed) return;\n if (!(await this.pullRemote())) return;\n if (this.queueItems.length === 0) {\n this.updateState({ status: \"synced\", pendingCount: 0, error: undefined });\n return;\n }\n this.updateState({ status: \"syncing\", error: undefined });\n for (const operation of [...this.queueItems]) {\n if (this.disposed) return;\n try {\n const result = await this.pushWithRetry(operation);\n if (result.type === \"conflict\") {\n const local = operation.item;\n const resolved = this.resolveConflict\n ? await this.resolveConflict(local, result.remote, {\n operation,\n remoteRevision: result.revision,\n })\n : undefined;\n if (!resolved) {\n const conflict: KeepSyncConflict<TMeta> = {\n id: operation.id,\n operation,\n remote: result.remote,\n ...(result.revision ? { revision: result.revision } : {}),\n };\n this.conflicts.set(operation.id, conflict);\n this.updateState({\n status: \"conflict\",\n conflictIds: [...this.conflicts.keys()],\n conflicts: [...this.conflicts.values()],\n });\n continue;\n }\n const retry = this.createOperation(\"upsert\", resolved.id, {\n ...resolved,\n revision: result.revision ?? resolved.revision,\n });\n await this.local.set(this.applyScope(retry.item as KeepItem<TMeta>));\n await this.replaceQueued(operation, retry);\n continue;\n }\n if (result.item) {\n await this.local.set(\n this.applyScope({\n ...result.item,\n ...(result.revision ? { revision: result.revision } : {}),\n }),\n );\n this.notifyDataListeners();\n }\n await this.removeQueued(operation.operationId);\n this.updateState({\n status: this.queueItems.length > 0 ? \"syncing\" : \"synced\",\n lastSyncedAt: this.now(),\n conflictIds: [...this.conflicts.keys()].filter((id) => id !== operation.id),\n conflicts: [...this.conflicts.values()].filter((conflict) => conflict.id !== operation.id),\n });\n } catch (error) {\n this.updateState({ status: \"error\", error });\n return;\n }\n }\n if (this.queueItems.length === 0) this.updateState({ status: \"synced\", pendingCount: 0 });\n }\n\n private createOperation(\n type: SyncOperation<TMeta>[\"type\"],\n id: string,\n item?: KeepItem<TMeta>,\n ): SyncOperation<TMeta> {\n return {\n operationId: `${this.clientId}:${this.now()}:${createId()}`,\n type,\n id,\n ...(item ? { item } : {}),\n createdAt: this.now(),\n ...(item?.revision ? { baseRevision: item.revision } : {}),\n ...(this.scope ? { scope: this.scope } : {}),\n };\n }\n\n private applyScope(item: KeepItem<TMeta>): KeepItem<TMeta> {\n return this.scope ? { ...item, scope: this.scope } : item;\n }\n\n private async pushWithRetry(operation: SyncOperation<TMeta>): Promise<RemoteSyncResult<TMeta>> {\n let attempt = 0;\n while (true) {\n try {\n return await this.remote.push({ ...operation, attempts: attempt });\n } catch (error) {\n if (isKeepSyncAuthError(error) || attempt >= this.maxRetries) throw error;\n attempt += 1;\n const delay = this.retryDelayMs * this.retryBackoff ** (attempt - 1);\n if (delay > 0) await wait(delay);\n }\n }\n }\n\n private async enqueueBeforeLocalWrite(operation: SyncOperation<TMeta>): Promise<void> {\n await this.enqueueManyBeforeLocalWrite([operation]);\n }\n\n private async enqueueManyBeforeLocalWrite(operations: SyncOperation<TMeta>[]): Promise<void> {\n await this.loadQueue();\n const next = [...this.queueItems];\n for (const operation of operations) {\n for (let index = next.length - 1; index >= 0; index -= 1) {\n if (next[index]?.id !== operation.id) continue;\n next.splice(index, 1);\n }\n next.push(operation);\n }\n await this.persistQueue(next);\n this.updateState({ status: \"pending\", pendingCount: this.queueItems.length });\n }\n\n private async loadQueue(): Promise<void> {\n if (this.queueLoaded) return;\n if (!this.queueLoadPromise) {\n this.queueLoadPromise = this.queue\n .getAll()\n .then((items) => {\n this.queueItems = items;\n this.queueLoaded = true;\n })\n .catch((error) => {\n this.queueLoadPromise = undefined;\n throw error;\n });\n }\n await this.queueLoadPromise;\n }\n\n private async resumeQueue(): Promise<void> {\n try {\n await this.loadQueue();\n if (this.disposed) return;\n if (this.queueItems.length === 0) return;\n this.updateState({ status: \"pending\", pendingCount: this.queueItems.length });\n if (isBrowserOnline()) await this.flushSync();\n } catch (error) {\n this.updateState({ status: \"error\", error });\n }\n }\n\n private async persistQueue(next: SyncOperation<TMeta>[]): Promise<void> {\n const previousIds = new Set(this.queueItems.map((operation) => operation.operationId));\n const nextIds = new Set(next.map((operation) => operation.operationId));\n const removed = [...previousIds].filter((id) => !nextIds.has(id));\n if (removed.length > 0) await this.queue.remove(removed);\n if (next.length > 0) await this.queue.setMany(next);\n this.queueItems = next;\n }\n\n private async removeQueued(operationIds: string | string[]): Promise<void> {\n await this.loadQueue();\n const ids = new Set(typeof operationIds === \"string\" ? [operationIds] : operationIds);\n await this.queue.remove([...ids]);\n this.queueItems = this.queueItems.filter((operation) => !ids.has(operation.operationId));\n this.setPendingState();\n }\n\n private async replaceQueued(previous: SyncOperation<TMeta>, next: SyncOperation<TMeta>): Promise<void> {\n await this.persistQueue(\n this.queueItems.map((operation) => (operation.operationId === previous.operationId ? next : operation)),\n );\n this.setPendingState();\n }\n\n private setPendingState(): void {\n this.updateState({\n status: this.queueItems.length > 0 ? \"pending\" : \"synced\",\n pendingCount: this.queueItems.length,\n });\n }\n\n private async pullRemote(): Promise<boolean> {\n if (!this.remote.pull) return true;\n try {\n const remoteItems = await this.remote.pull();\n const pendingIds = new Set(this.queueItems.map((operation) => operation.id));\n const localItems = await this.getAll();\n const localById = new Map(localItems.map((item) => [item.id, item]));\n const incoming = remoteItems\n .filter((item) => {\n if (this.scope && item.scope && !sameScope(item.scope, this.scope)) return false;\n const current = localById.get(item.id);\n return !pendingIds.has(item.id) && (!current || item.updatedAt >= current.updatedAt);\n })\n .map((item) => this.applyScope(item));\n if (incoming.length === 0) return true;\n if (this.local.setMany) await this.local.setMany(incoming);\n else for (const item of incoming) await this.local.set(item);\n this.notifyDataListeners();\n return true;\n } catch (error) {\n this.updateState({ status: \"error\", error });\n return false;\n }\n }\n\n private notifyDataListeners(): void {\n for (const listener of this.dataListeners) listener();\n }\n\n private updateState(next: Partial<KeepSyncState<TMeta>>): void {\n this.state = {\n ...this.state,\n ...next,\n pendingCount: next.pendingCount ?? this.queueItems.length,\n };\n for (const listener of this.listeners) listener();\n }\n}\n\nasync function mergeLocalItems<TMeta>(\n localItems: KeepItem<TMeta>[],\n target: StorageAdapter<TMeta>,\n): Promise<KeepItem<TMeta>[]> {\n const remoteItems = await target.getAll();\n const byId = new Map(remoteItems.map((item) => [item.id, item]));\n for (const item of localItems) {\n const current = byId.get(item.id);\n if (!current || item.updatedAt > current.updatedAt) byId.set(item.id, item);\n }\n const merged = [...byId.values()].sort((a, b) => b.updatedAt - a.updatedAt);\n if (target.setMany) await target.setMany(merged);\n else for (const item of merged) await target.set(item);\n return merged;\n}\n\nfunction isSyncOperation(value: unknown): value is SyncOperation {\n if (!isRecord(value)) return false;\n return (\n typeof value.operationId === \"string\" &&\n (value.type === \"upsert\" || value.type === \"remove\") &&\n typeof value.id === \"string\" &&\n typeof value.createdAt === \"number\"\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction createId(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) return crypto.randomUUID();\n return Math.random().toString(36).slice(2);\n}\n\nfunction getBrowserStorage(): Storage | undefined {\n if (typeof window === \"undefined\") return undefined;\n try {\n return window.localStorage;\n } catch {\n return undefined;\n }\n}\n\nfunction getBrowserIndexedDB(): IDBFactory | undefined {\n if (typeof indexedDB === \"undefined\") return undefined;\n return indexedDB;\n}\n\nfunction isBrowserOnline(): boolean {\n return typeof navigator === \"undefined\" || navigator.onLine !== false;\n}\n\nfunction createDefaultQueue<TMeta>(options: SyncStorageAdapterOptions<TMeta>): SyncQueueAdapter<TMeta> {\n const scopeKey = getScopeKey(options);\n const queueKey = `${options.queueKey ?? `${DEFAULT_SYNC_QUEUE_KEY}:${options.local.storageKey ?? \"default\"}`}${scopeKey}`;\n const fallback = new LocalStorageSyncQueueAdapter<TMeta>({ key: queueKey });\n const indexedDB = getBrowserIndexedDB();\n if (!indexedDB) return fallback;\n return new FallbackSyncQueueAdapter<TMeta>({\n primary: new IndexedDBSyncQueueAdapter<TMeta>({\n databaseName: `${options.queueDatabaseName ?? DEFAULT_SYNC_QUEUE_DATABASE}${scopeKey}`,\n indexedDB,\n }),\n fallback,\n });\n}\n\nfunction getSyncScope<TMeta>(options: SyncStorageAdapterOptions<TMeta>): SyncScope | undefined {\n if (options.scope) return options.scope;\n if (!options.userId && !options.tenantId) return undefined;\n return {\n ...(options.userId ? { userId: options.userId } : {}),\n ...(options.tenantId ? { tenantId: options.tenantId } : {}),\n };\n}\n\nfunction getScopeKey<TMeta>(options: SyncStorageAdapterOptions<TMeta>): string {\n const scope = getSyncScope(options);\n if (!scope) return \"\";\n return `:${encodeURIComponent(scope.tenantId ?? \"_\")}:${encodeURIComponent(scope.userId ?? \"_\")}`;\n}\n\nfunction sameScope(left: SyncScope | undefined, right: SyncScope): boolean {\n return left?.userId === right.userId && left?.tenantId === right.tenantId;\n}\n\nfunction wait(delay: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, delay));\n}\n\nfunction requestToPromise<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nfunction transactionToPromise(transaction: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n transaction.oncomplete = () => resolve();\n transaction.onerror = () => reject(transaction.error);\n transaction.onabort = () => reject(transaction.error ?? new Error(\"IndexedDB transaction aborted.\"));\n });\n}\n","import {\n type KeepItem,\n KeepStorageAccessError,\n KeepStorageError,\n type KeepStorageOperation,\n KeepStorageParseError,\n KeepStorageQuotaError,\n type StorageAdapter,\n} from \"../features/items/types\";\nimport { createScopedStorageAdapter, getKeepScopeKey, type KeepScope } from \"../features/persistence/scope\";\n\nexport const DEFAULT_STORAGE_KEY = \"keepkit:items\";\n\nexport type LocalStorageAdapterOptions = {\n key?: string;\n storage?: Storage;\n};\n\nexport type IndexedDBAdapterOptions = {\n databaseName?: string;\n dbName?: string;\n /** Alias for databaseName, useful when switching from LocalStorageAdapter. */\n key?: string;\n storeName?: string;\n version?: number;\n indexedDB?: IDBFactory;\n};\n\nexport const DEFAULT_INDEXEDDB_DATABASE = \"keepkit\";\nexport const DEFAULT_INDEXEDDB_STORE = \"items\";\n\nexport type StorageAdapterFactoryOptions<TMeta = Record<string, unknown>> = {\n getAll: () => KeepItem<TMeta>[] | Promise<KeepItem<TMeta>[]>;\n set: (item: KeepItem<TMeta>) => void | Promise<void>;\n setMany?: (items: KeepItem<TMeta>[]) => void | Promise<void>;\n remove: (id: string) => void | Promise<void>;\n removeMany?: (ids: string[]) => void | Promise<void>;\n clear: () => void | Promise<void>;\n merge?: (localItems: KeepItem<TMeta>[]) => KeepItem<TMeta>[] | Promise<KeepItem<TMeta>[]>;\n subscribe?: (listener: () => void) => undefined | (() => void);\n storageKey?: string;\n};\n\nexport type FallbackStorageAdapterOptions<TMeta = Record<string, unknown>> = {\n primary: StorageAdapter<TMeta>;\n fallback: StorageAdapter<TMeta>;\n /** Decide which primary adapter failures should activate the fallback. */\n shouldFallback?: (error: unknown) => boolean;\n onFallback?: (error: unknown) => void;\n /** Copy fallback data into an empty primary on the first read. */\n migrateFallbackOnEmpty?: boolean;\n /** Keep the fallback current while the primary is healthy. */\n mirrorWrites?: boolean;\n};\n\n/**\n * A storage adapter that switches to a fallback after an availability failure.\n * Parse errors remain visible so corrupt data is never silently hidden.\n */\nexport class FallbackStorageAdapter<TMeta = Record<string, unknown>> implements StorageAdapter<TMeta> {\n public readonly storageKey: string | undefined;\n private readonly primary: StorageAdapter<TMeta>;\n private readonly fallback: StorageAdapter<TMeta>;\n private readonly shouldFallback: (error: unknown) => boolean;\n private readonly onFallback?: (error: unknown) => void;\n private readonly migrateFallbackOnEmpty: boolean;\n private readonly mirrorWrites: boolean;\n private active: \"primary\" | \"fallback\" = \"primary\";\n private readonly listeners = new Set<() => void>();\n\n constructor(options: FallbackStorageAdapterOptions<TMeta>) {\n this.primary = options.primary;\n this.fallback = options.fallback;\n this.shouldFallback = options.shouldFallback ?? isRecoverableStorageError;\n this.onFallback = options.onFallback;\n this.migrateFallbackOnEmpty = options.migrateFallbackOnEmpty ?? false;\n this.mirrorWrites = options.mirrorWrites ?? false;\n this.storageKey = options.fallback.storageKey ?? options.primary.storageKey;\n }\n\n get isUsingFallback(): boolean {\n return this.active === \"fallback\";\n }\n\n getAll(): Promise<KeepItem<TMeta>[]> {\n return this.readAll();\n }\n\n set(item: KeepItem<TMeta>): Promise<void> {\n return this.executeWrite((adapter) => adapter.set(item));\n }\n\n setMany(items: KeepItem<TMeta>[]): Promise<void> {\n return this.executeWrite((adapter) =>\n adapter.setMany\n ? adapter.setMany(items)\n : Promise.all(items.map((item) => adapter.set(item))).then(() => undefined),\n );\n }\n\n remove(id: string): Promise<void> {\n return this.executeWrite((adapter) => adapter.remove(id));\n }\n\n removeMany(ids: string[]): Promise<void> {\n return this.executeWrite((adapter) =>\n adapter.removeMany\n ? adapter.removeMany(ids)\n : Promise.all(ids.map((id) => adapter.remove(id))).then(() => undefined),\n );\n }\n\n clear(): Promise<void> {\n return this.executeWrite((adapter) => adapter.clear());\n }\n\n merge(localItems: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n return this.execute(async (adapter) => {\n const merged = adapter.merge ? await adapter.merge(localItems) : await mergeItems(adapter, localItems);\n if (this.active === \"primary\" && this.mirrorWrites) {\n try {\n if (this.fallback.setMany) await this.fallback.setMany(merged);\n else for (const item of merged) await this.fallback.set(item);\n } catch {\n // The fallback is best-effort while the primary is healthy.\n }\n }\n return merged;\n });\n }\n\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener);\n const notify = (source: \"primary\" | \"fallback\") => {\n if (source === this.active) listener();\n };\n const unsubscribePrimary = this.primary.subscribe?.(() => notify(\"primary\"));\n const unsubscribeFallback = this.fallback.subscribe?.(() => notify(\"fallback\"));\n return () => {\n this.listeners.delete(listener);\n unsubscribePrimary?.();\n unsubscribeFallback?.();\n };\n }\n\n private async readAll(): Promise<KeepItem<TMeta>[]> {\n if (this.active === \"fallback\") return this.fallback.getAll();\n let items: KeepItem<TMeta>[];\n try {\n items = await this.primary.getAll();\n } catch (error) {\n if (!this.shouldFallback(error)) throw error;\n this.activateFallback(error);\n return this.fallback.getAll();\n }\n if (!this.migrateFallbackOnEmpty || items.length > 0) return items;\n\n const fallbackItems = await this.fallback.getAll();\n if (fallbackItems.length === 0) return items;\n try {\n if (this.primary.setMany) await this.primary.setMany(fallbackItems);\n else for (const item of fallbackItems) await this.primary.set(item);\n return fallbackItems;\n } catch (error) {\n if (!this.shouldFallback(error)) throw error;\n this.activateFallback(error);\n return fallbackItems;\n }\n }\n\n private activateFallback(error: unknown): void {\n this.active = \"fallback\";\n this.onFallback?.(error);\n for (const listener of this.listeners) listener();\n }\n\n private async executeWrite<TResult>(\n operation: (adapter: StorageAdapter<TMeta>) => Promise<TResult>,\n ): Promise<TResult> {\n const result = await this.execute(operation);\n if (this.active === \"primary\" && this.mirrorWrites) {\n try {\n await operation(this.fallback);\n } catch {\n // The fallback is best-effort while the primary is healthy.\n }\n }\n return result;\n }\n\n private async execute<TResult>(operation: (adapter: StorageAdapter<TMeta>) => Promise<TResult>): Promise<TResult> {\n const adapter = this.active === \"primary\" ? this.primary : this.fallback;\n try {\n return await operation(adapter);\n } catch (error) {\n if (this.active !== \"primary\" || !this.shouldFallback(error)) throw error;\n this.activateFallback(error);\n return operation(this.fallback);\n }\n }\n}\n\nexport type BrowserStorageAdapterOptions = {\n key?: string;\n databaseName?: string;\n storeName?: string;\n version?: number;\n indexedDB?: IDBFactory;\n storage?: Storage;\n scope?: KeepScope;\n};\n\n/** IndexedDB-first browser storage with localStorage fallback. */\nexport function createBrowserStorageAdapter<TMeta = Record<string, unknown>>(\n options: BrowserStorageAdapterOptions = {},\n): StorageAdapter<TMeta> {\n const browserIndexedDB = options.indexedDB ?? getBrowserIndexedDB();\n const scopeKey = getKeepScopeKey(options.scope);\n const storageKey = options.key\n ? `${options.key}${scopeKey}`\n : scopeKey\n ? `${DEFAULT_STORAGE_KEY}${scopeKey}`\n : undefined;\n const fallback = new LocalStorageAdapter<TMeta>({ key: storageKey, storage: options.storage });\n if (!browserIndexedDB) return options.scope ? createScopedStorageAdapter(fallback, options.scope) : fallback;\n const adapter = new FallbackStorageAdapter<TMeta>({\n primary: new IndexedDBAdapter<TMeta>({\n databaseName: options.databaseName ? `${options.databaseName}${scopeKey}` : undefined,\n storeName: options.storeName,\n version: options.version,\n indexedDB: browserIndexedDB,\n }),\n fallback,\n migrateFallbackOnEmpty: true,\n mirrorWrites: true,\n });\n return options.scope ? createScopedStorageAdapter(adapter, options.scope) : adapter;\n}\n\n/** Adapt sync or async persistence functions to the StorageAdapter contract. */\nexport function createStorageAdapter<TMeta = Record<string, unknown>>(\n options: StorageAdapterFactoryOptions<TMeta>,\n): StorageAdapter<TMeta> {\n const merge = options.merge;\n const subscribe = options.subscribe;\n const setMany = options.setMany;\n const removeMany = options.removeMany;\n return {\n getAll: async () => options.getAll(),\n set: async (item) => options.set(item),\n ...(setMany ? { setMany: async (items: KeepItem<TMeta>[]) => setMany(items) } : {}),\n remove: async (id) => options.remove(id),\n ...(removeMany ? { removeMany: async (ids: string[]) => removeMany(ids) } : {}),\n clear: async () => options.clear(),\n ...(merge ? { merge: async (items: KeepItem<TMeta>[]) => merge(items) } : {}),\n ...(subscribe\n ? {\n subscribe: (listener: () => void) => subscribe(listener) ?? (() => undefined),\n }\n : {}),\n ...(options.storageKey ? { storageKey: options.storageKey } : {}),\n };\n}\n\nexport type { KeepScope } from \"../features/persistence/scope\";\nexport { createScopedStorageAdapter, ScopedStorageAdapter } from \"../features/persistence/scope\";\n\nasync function mergeItems<TMeta>(\n adapter: StorageAdapter<TMeta>,\n localItems: KeepItem<TMeta>[],\n): Promise<KeepItem<TMeta>[]> {\n const remoteItems = await adapter.getAll();\n const byId = new Map(remoteItems.map((item) => [item.id, item]));\n for (const item of localItems) {\n const current = byId.get(item.id);\n if (!current || item.updatedAt > current.updatedAt) byId.set(item.id, item);\n }\n const merged = [...byId.values()].sort((a, b) => b.updatedAt - a.updatedAt);\n if (adapter.setMany) await adapter.setMany(merged);\n else for (const item of merged) await adapter.set(item);\n return merged;\n}\n\n/** An async StorageAdapter backed by browser localStorage. */\nexport class LocalStorageAdapter<TMeta = Record<string, unknown>> implements StorageAdapter<TMeta> {\n public readonly storageKey: string;\n private readonly storage: Storage | undefined;\n\n constructor(options: LocalStorageAdapterOptions = {}) {\n this.storageKey = options.key ?? DEFAULT_STORAGE_KEY;\n this.storage = options.storage ?? getBrowserStorage();\n }\n\n async getAll(): Promise<KeepItem<TMeta>[]> {\n if (!this.storage) return [];\n\n let raw: string | null;\n try {\n raw = this.storage.getItem(this.storageKey);\n } catch (cause) {\n throw new KeepStorageAccessError({\n operation: \"getAll\",\n storageKey: this.storageKey,\n cause,\n });\n }\n\n if (!raw) return [];\n\n try {\n const value: unknown = JSON.parse(raw);\n if (!isKeepItemArray(value)) {\n throw new KeepStorageParseError({\n operation: \"getAll\",\n storageKey: this.storageKey,\n });\n }\n return value as KeepItem<TMeta>[];\n } catch (cause) {\n if (cause instanceof KeepStorageParseError) throw cause;\n throw new KeepStorageParseError({\n operation: \"getAll\",\n storageKey: this.storageKey,\n cause,\n });\n }\n }\n\n async set(item: KeepItem<TMeta>): Promise<void> {\n await this.setMany([item]);\n }\n\n async setMany(items: KeepItem<TMeta>[]): Promise<void> {\n const current = await this.getAll();\n const byId = new Map(current.map((item) => [item.id, item]));\n for (const item of items) byId.set(item.id, item);\n this.write([...byId.values()], \"set\");\n }\n\n async remove(id: string): Promise<void> {\n await this.removeMany([id]);\n }\n\n async removeMany(ids: string[]): Promise<void> {\n const idSet = new Set(ids);\n const items = await this.getAll();\n this.write(\n items.filter((item) => !idSet.has(item.id)),\n \"remove\",\n );\n }\n\n async clear(): Promise<void> {\n if (!this.storage) return;\n try {\n this.storage.removeItem(this.storageKey);\n } catch (cause) {\n throw new KeepStorageAccessError({\n operation: \"clear\",\n storageKey: this.storageKey,\n cause,\n });\n }\n }\n\n async merge(localItems: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n const remoteItems = await this.getAll();\n const byId = new Map(remoteItems.map((item) => [item.id, item]));\n\n for (const localItem of localItems) {\n const remoteItem = byId.get(localItem.id);\n if (!remoteItem || localItem.updatedAt > remoteItem.updatedAt) {\n byId.set(localItem.id, localItem);\n }\n }\n\n const merged = [...byId.values()].sort((a, b) => b.updatedAt - a.updatedAt);\n this.write(merged, \"merge\");\n return merged;\n }\n\n subscribe(listener: () => void): () => void {\n if (typeof window === \"undefined\") return () => undefined;\n\n const handleStorage = (event: StorageEvent) => {\n if (event.key !== null && event.key !== this.storageKey) return;\n listener();\n };\n\n window.addEventListener(\"storage\", handleStorage);\n return () => window.removeEventListener(\"storage\", handleStorage);\n }\n\n private write(items: KeepItem<TMeta>[], operation: KeepStorageOperation): void {\n if (!this.storage) return;\n try {\n this.storage.setItem(this.storageKey, JSON.stringify(items));\n } catch (cause) {\n if (isQuotaExceededError(cause)) {\n throw new KeepStorageQuotaError({\n operation,\n storageKey: this.storageKey,\n cause,\n });\n }\n throw new KeepStorageAccessError({\n operation,\n storageKey: this.storageKey,\n cause,\n });\n }\n }\n}\n\n/** An async StorageAdapter backed by IndexedDB, with one object store per adapter. */\nexport class IndexedDBAdapter<TMeta = Record<string, unknown>> implements StorageAdapter<TMeta> {\n public readonly storageKey: string;\n private readonly databaseName: string;\n private readonly storeName: string;\n private readonly version: number;\n private readonly indexedDB: IDBFactory | undefined;\n private databasePromise: Promise<IDBDatabase | undefined> | undefined;\n\n constructor(options: IndexedDBAdapterOptions = {}) {\n this.databaseName = options.databaseName ?? options.dbName ?? options.key ?? DEFAULT_INDEXEDDB_DATABASE;\n this.storeName = options.storeName ?? DEFAULT_INDEXEDDB_STORE;\n this.version = options.version ?? 1;\n this.indexedDB = options.indexedDB ?? getBrowserIndexedDB();\n this.storageKey = `${this.databaseName}:${this.storeName}`;\n }\n\n async getAll(): Promise<KeepItem<TMeta>[]> {\n const database = await this.open(\"getAll\");\n if (!database) return [];\n try {\n const transaction = database.transaction(this.storeName, \"readonly\");\n const value: unknown = await requestToPromise(transaction.objectStore(this.storeName).getAll());\n if (!isKeepItemArray(value)) {\n throw new KeepStorageParseError({ operation: \"getAll\", storageKey: this.storageKey });\n }\n return value as KeepItem<TMeta>[];\n } catch (cause) {\n if (cause instanceof KeepStorageParseError) throw cause;\n throw new KeepStorageAccessError({ operation: \"getAll\", storageKey: this.storageKey, cause });\n }\n }\n\n async set(item: KeepItem<TMeta>): Promise<void> {\n return this.setMany([item]);\n }\n\n async setMany(items: KeepItem<TMeta>[]): Promise<void> {\n const database = await this.open(\"set\");\n if (!database) return;\n try {\n const transaction = database.transaction(this.storeName, \"readwrite\");\n const objectStore = transaction.objectStore(this.storeName);\n for (const item of items) objectStore.put(item);\n await transactionToPromise(transaction);\n this.notifySubscribers();\n } catch (cause) {\n if (isQuotaExceededError(cause)) {\n throw new KeepStorageQuotaError({ operation: \"set\", storageKey: this.storageKey, cause });\n }\n throw new KeepStorageAccessError({ operation: \"set\", storageKey: this.storageKey, cause });\n }\n }\n\n async remove(id: string): Promise<void> {\n return this.removeMany([id]);\n }\n\n async removeMany(ids: string[]): Promise<void> {\n const database = await this.open(\"remove\");\n if (!database) return;\n try {\n const transaction = database.transaction(this.storeName, \"readwrite\");\n const objectStore = transaction.objectStore(this.storeName);\n for (const id of new Set(ids)) objectStore.delete(id);\n await transactionToPromise(transaction);\n this.notifySubscribers();\n } catch (cause) {\n throw new KeepStorageAccessError({ operation: \"remove\", storageKey: this.storageKey, cause });\n }\n }\n\n async clear(): Promise<void> {\n const database = await this.open(\"clear\");\n if (!database) return;\n try {\n const transaction = database.transaction(this.storeName, \"readwrite\");\n transaction.objectStore(this.storeName).clear();\n await transactionToPromise(transaction);\n this.notifySubscribers();\n } catch (cause) {\n throw new KeepStorageAccessError({ operation: \"clear\", storageKey: this.storageKey, cause });\n }\n }\n\n async merge(localItems: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n try {\n const remoteItems = await this.getAll();\n const byId = new Map(remoteItems.map((item) => [item.id, item]));\n for (const localItem of localItems) {\n const remoteItem = byId.get(localItem.id);\n if (!remoteItem || localItem.updatedAt > remoteItem.updatedAt) byId.set(localItem.id, localItem);\n }\n const merged = [...byId.values()].sort((a, b) => b.updatedAt - a.updatedAt);\n await this.setMany(merged);\n return merged;\n } catch (cause) {\n if (cause instanceof KeepStorageError) throw cause;\n throw new KeepStorageAccessError({ operation: \"merge\", storageKey: this.storageKey, cause });\n }\n }\n\n subscribe(listener: () => void): () => void {\n if (!this.indexedDB || typeof BroadcastChannel === \"undefined\") return () => undefined;\n const channel = new BroadcastChannel(`keepkit:${this.storageKey}`);\n channel.onmessage = () => listener();\n return () => channel.close();\n }\n\n private notifySubscribers(): void {\n if (!this.indexedDB || typeof BroadcastChannel === \"undefined\") return;\n const channel = new BroadcastChannel(`keepkit:${this.storageKey}`);\n channel.postMessage({ type: \"keepkit:changed\" });\n channel.close();\n }\n\n private open(operation: KeepStorageOperation): Promise<IDBDatabase | undefined> {\n if (!this.indexedDB) return Promise.resolve(undefined);\n if (!this.databasePromise) {\n this.databasePromise = new Promise((resolve, reject) => {\n let request: IDBOpenDBRequest;\n try {\n request = this.indexedDB?.open(this.databaseName, this.version) as IDBOpenDBRequest;\n } catch (cause) {\n reject(new KeepStorageAccessError({ operation, storageKey: this.storageKey, cause }));\n return;\n }\n request.onupgradeneeded = () => {\n if (!request.result.objectStoreNames.contains(this.storeName)) {\n request.result.createObjectStore(this.storeName, { keyPath: \"id\" });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n request.onblocked = () => reject(request.error ?? new Error(\"IndexedDB open was blocked.\"));\n });\n }\n return this.databasePromise.catch((cause) => {\n this.databasePromise = undefined;\n if (cause instanceof KeepStorageError) throw cause;\n throw new KeepStorageAccessError({ operation, storageKey: this.storageKey, cause });\n });\n }\n}\n\nfunction isKeepItemArray(value: unknown): value is KeepItem[] {\n return (\n Array.isArray(value) &&\n value.every(\n (item) =>\n isRecord(item) &&\n typeof item.id === \"string\" &&\n typeof item.savedAt === \"number\" &&\n Number.isFinite(item.savedAt) &&\n typeof item.updatedAt === \"number\" &&\n Number.isFinite(item.updatedAt) &&\n \"meta\" in item &&\n (item.order === undefined || (typeof item.order === \"number\" && Number.isFinite(item.order))) &&\n (item.targetType === undefined || typeof item.targetType === \"string\") &&\n (item.note === undefined || typeof item.note === \"string\") &&\n (item.schemaVersion === undefined ||\n (typeof item.schemaVersion === \"number\" && Number.isFinite(item.schemaVersion))) &&\n (item.revision === undefined || typeof item.revision === \"string\") &&\n (item.metaUpdatedAt === undefined ||\n (typeof item.metaUpdatedAt === \"number\" && Number.isFinite(item.metaUpdatedAt))) &&\n (item.status === undefined ||\n item.status === \"available\" ||\n item.status === \"expired\" ||\n item.status === \"removed\" ||\n item.status === \"deleted\" ||\n item.status === \"private\" ||\n item.status === \"unknown\") &&\n (item.statusReason === undefined || typeof item.statusReason === \"string\") &&\n (item.scope === undefined || isSyncScope(item.scope)) &&\n (item.tags === undefined || (Array.isArray(item.tags) && item.tags.every((tag) => typeof tag === \"string\"))),\n )\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction isSyncScope(value: unknown): boolean {\n return (\n isRecord(value) &&\n (value.userId === undefined || typeof value.userId === \"string\") &&\n (value.tenantId === undefined || typeof value.tenantId === \"string\")\n );\n}\n\nfunction getBrowserStorage(): Storage | undefined {\n if (typeof window === \"undefined\") return undefined;\n try {\n return window.localStorage;\n } catch {\n return undefined;\n }\n}\n\nfunction getBrowserIndexedDB(): IDBFactory | undefined {\n if (typeof indexedDB === \"undefined\") return undefined;\n return indexedDB;\n}\n\nfunction isRecoverableStorageError(error: unknown): boolean {\n return error instanceof KeepStorageAccessError || error instanceof KeepStorageQuotaError;\n}\n\nfunction requestToPromise<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\nfunction transactionToPromise(transaction: IDBTransaction): Promise<void> {\n return new Promise((resolve, reject) => {\n transaction.oncomplete = () => resolve();\n transaction.onerror = () => reject(transaction.error);\n transaction.onabort = () => reject(transaction.error ?? new Error(\"IndexedDB transaction aborted.\"));\n });\n}\n\nfunction isQuotaExceededError(cause: unknown): boolean {\n if (!isRecord(cause)) return false;\n return (\n cause.name === \"QuotaExceededError\" ||\n cause.name === \"NS_ERROR_DOM_QUOTA_REACHED\" ||\n cause.code === 22 ||\n cause.code === 1014\n );\n}\n\nexport { ScopedSyncQueueAdapter } from \"../features/persistence/scope\";\nexport {\n DEFAULT_SYNC_QUEUE_DATABASE,\n DEFAULT_SYNC_QUEUE_KEY,\n DEFAULT_SYNC_QUEUE_STORE,\n FallbackSyncQueueAdapter,\n type FallbackSyncQueueAdapterOptions,\n IndexedDBSyncQueueAdapter,\n type IndexedDBSyncQueueOptions,\n LocalStorageSyncQueueAdapter,\n type LocalStorageSyncQueueOptions,\n SyncStorageAdapter,\n type SyncStorageAdapterOptions,\n} from \"./sync\";\n"],"mappings":"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","names":["indexedDB","getBrowserIndexedDB","getBrowserStorage","requestToPromise","transactionToPromise","isRecord"]}
package/dist/core.d.ts CHANGED
@@ -1,27 +1,12 @@
1
- export { D as DEFAULT_KEEP_URL_PARAMS, I as ImportItemsOptions, a as ImportItemsResult, K as KEEP_BACKUP_FORMAT, b as KEEP_BACKUP_VERSION, c as KeepAutoRevalidationOptions, d as KeepBackup, e as KeepBackupImportError, f as KeepBackupParseError, g as KeepItemMetadataRefresher, h as KeepItemResolver, i as KeepItemRevalidationRecord, j as KeepItemRevalidationResult, k as KeepItemRevalidationSummary, l as KeepItemRevalidator, m as KeepListQuery, n as KeepNavigationState, o as KeepStore, p as KeepStoreActions, q as KeepStoreState, r as KeepUrlParamNames, s as KeepUrlState, t as KeepUrlSyncOptions, Q as QueryKeepItemsResult, R as RevalidateKeepItemsOptions, u as decodeKeepListQuery, v as encodeKeepListQuery, w as exportItems, x as getKeepNavigationState, y as getTagCounts, z as importItems, A as isKeepItemMetadataStale, B as mergeKeepListQueryFromUrl, C as moveKeepItem, E as orderKeepItems, F as queryKeepItems, G as reconcileKeepItems, H as reorderKeepItems, J as revalidateKeepItems, L as serializeKeepListQuery } from './url-Blx4SPKD.js';
2
- import { e as KeepPluginContext, f as KeepPlugin, a as KeepItem, b as StorageAdapter, R as RemoteSyncDriver, d as SyncOperation, S as SyncScope, g as SyncCapableStorageAdapter, h as RemoteSyncResult, i as KeepSyncAuthError } from './types-B3xc8-Pi.js';
3
- export { j as KeepAction, k as KeepChangeContext, l as KeepChangePhase, m as KeepConflictContext, n as KeepConflictResolver, o as KeepErrorContext, p as KeepErrorHandler, q as KeepEventHandlers, r as KeepInvalidItemPolicy, s as KeepItemInput, t as KeepItemStatus, K as KeepSchema, u as KeepSchemaParseResult, v as KeepStorageAccessError, w as KeepStorageError, x as KeepStorageOperation, y as KeepStorageParseError, z as KeepStorageQuotaError, A as KeepSyncAuthStatus, B as KeepSyncConflict, C as KeepSyncResolution, D as KeepSyncState, E as KeepSyncStatus, F as KeepUndoState, c as SyncQueueAdapter, G as isKeepSyncAuthError, H as normalizeKeepTags } from './types-B3xc8-Pi.js';
4
- import { K as KeepScope } from './scope-D52NbAWR.js';
5
- export { S as ScopedStorageAdapter, a as ScopedSyncQueueAdapter, c as createScopedStorageAdapter, g as getKeepScopeKey, i as isSameKeepScope } from './scope-D52NbAWR.js';
1
+ export { D as DEFAULT_KEEP_URL_PARAMS, I as ImportItemsOptions, a as ImportItemsResult, K as KEEP_BACKUP_FORMAT, b as KEEP_BACKUP_VERSION, c as KeepAutoRevalidationOptions, d as KeepBackup, e as KeepBackupImportError, f as KeepBackupParseError, g as KeepItemMetadataRefresher, h as KeepItemResolver, i as KeepItemRevalidationRecord, j as KeepItemRevalidationResult, k as KeepItemRevalidationSummary, l as KeepItemRevalidator, m as KeepListQuery, n as KeepNavigationState, o as KeepStore, p as KeepStoreActions, q as KeepStoreState, r as KeepUrlParamNames, s as KeepUrlState, t as KeepUrlSyncOptions, Q as QueryKeepItemsResult, R as RevalidateKeepItemsOptions, u as decodeKeepListQuery, v as encodeKeepListQuery, w as exportItems, x as getKeepNavigationState, y as getTagCounts, z as importItems, A as isKeepItemMetadataStale, B as mergeKeepListQueryFromUrl, C as moveKeepItem, E as orderKeepItems, F as queryKeepItems, G as reconcileKeepItems, H as reorderKeepItems, J as revalidateKeepItems, L as serializeKeepListQuery } from './store-Cm35R_ho.js';
2
+ import { K as KeepScope } from './scope-Dk5FTVz8.js';
3
+ export { S as ScopedStorageAdapter, a as ScopedSyncQueueAdapter, c as createScopedStorageAdapter, g as getKeepScopeKey, i as isSameKeepScope } from './scope-Dk5FTVz8.js';
4
+ import { R as RemoteSyncDriver, a as StorageAdapter, K as KeepItem, d as KeepPluginContext, e as KeepPlugin, c as SyncOperation, S as SyncScope, f as SyncCapableStorageAdapter, g as RemoteSyncResult, h as KeepSyncAuthError } from './types-Aoc0Eyvk.js';
5
+ export { i as KeepAction, j as KeepChangeContext, k as KeepChangePhase, l as KeepConflictContext, m as KeepConflictResolver, n as KeepErrorContext, o as KeepErrorHandler, p as KeepEventHandlers, q as KeepInvalidItemPolicy, r as KeepItemInput, s as KeepItemStatus, t as KeepSchema, u as KeepSchemaParseResult, v as KeepStorageAccessError, w as KeepStorageError, x as KeepStorageOperation, y as KeepStorageParseError, z as KeepStorageQuotaError, A as KeepSyncAuthStatus, B as KeepSyncConflict, C as KeepSyncResolution, D as KeepSyncState, E as KeepSyncStatus, F as KeepUndoState, b as SyncQueueAdapter, G as isKeepSyncAuthError, H as normalizeKeepTags } from './types-Aoc0Eyvk.js';
6
6
  export { KeepSchemaValidationError, parseKeepMeta, validateKeepItem } from './schema.js';
7
7
  import { SyncStorageAdapterOptions, BrowserStorageAdapterOptions } from './storage.js';
8
8
  export { DEFAULT_INDEXEDDB_DATABASE, DEFAULT_INDEXEDDB_STORE, DEFAULT_STORAGE_KEY, DEFAULT_SYNC_QUEUE_DATABASE, DEFAULT_SYNC_QUEUE_KEY, DEFAULT_SYNC_QUEUE_STORE, FallbackStorageAdapter, FallbackStorageAdapterOptions, FallbackSyncQueueAdapter, FallbackSyncQueueAdapterOptions, IndexedDBAdapter, IndexedDBAdapterOptions, IndexedDBSyncQueueAdapter, IndexedDBSyncQueueOptions, LocalStorageAdapter, LocalStorageAdapterOptions, LocalStorageSyncQueueAdapter, LocalStorageSyncQueueOptions, StorageAdapterFactoryOptions, SyncStorageAdapter, createBrowserStorageAdapter, createStorageAdapter } from './storage.js';
9
9
 
10
- type KeepInvalidationPluginOptions<TMeta = Record<string, unknown>> = {
11
- /** Query keys to invalidate after a successful local KeepKit mutation. */
12
- queryKeys: readonly unknown[] | ((context: KeepPluginContext<TMeta>) => readonly (readonly unknown[])[]);
13
- /** Connect this callback to queryClient.invalidateQueries or SWR mutate. */
14
- invalidate: (queryKey: readonly unknown[], context: KeepPluginContext<TMeta>) => void | Promise<void>;
15
- name?: string;
16
- };
17
- /** Framework-neutral bridge for TanStack Query, SWR, and similar caches. */
18
- declare function createKeepInvalidationPlugin<TMeta = Record<string, unknown>>(options: KeepInvalidationPluginOptions<TMeta>): KeepPlugin<TMeta>;
19
-
20
- /** Merge anonymous local items into a signed-in or remote adapter. */
21
- declare function mergeKeepItems<TMeta>(localItems: KeepItem<TMeta>[], target: StorageAdapter<TMeta>): Promise<KeepItem<TMeta>[]>;
22
- /** Read anonymous items, merge them into the target, then clear the source. */
23
- declare function migrateKeepItems<TMeta>(source: StorageAdapter<TMeta>, target: StorageAdapter<TMeta>): Promise<KeepItem<TMeta>[]>;
24
-
25
10
  type KeepKitPresetMode = "local" | "sync" | "backup";
26
11
  type KeepKitPresetOptions<TMeta = Record<string, unknown>> = {
27
12
  mode?: KeepKitPresetMode;
@@ -43,6 +28,21 @@ type KeepKitSetup<TMeta = Record<string, unknown>> = {
43
28
  declare function createKeepKitPreset<TMeta = Record<string, unknown>>(options?: KeepKitPresetOptions<TMeta>): KeepKitSetup<TMeta>;
44
29
  declare const createKeepKitSetup: typeof createKeepKitPreset;
45
30
 
31
+ /** Merge anonymous local items into a signed-in or remote adapter. */
32
+ declare function mergeKeepItems<TMeta>(localItems: KeepItem<TMeta>[], target: StorageAdapter<TMeta>): Promise<KeepItem<TMeta>[]>;
33
+ /** Read anonymous items, merge them into the target, then clear the source. */
34
+ declare function migrateKeepItems<TMeta>(source: StorageAdapter<TMeta>, target: StorageAdapter<TMeta>): Promise<KeepItem<TMeta>[]>;
35
+
36
+ type KeepInvalidationPluginOptions<TMeta = Record<string, unknown>> = {
37
+ /** Query keys to invalidate after a successful local KeepKit mutation. */
38
+ queryKeys: readonly unknown[] | ((context: KeepPluginContext<TMeta>) => readonly (readonly unknown[])[]);
39
+ /** Connect this callback to queryClient.invalidateQueries or SWR mutate. */
40
+ invalidate: (queryKey: readonly unknown[], context: KeepPluginContext<TMeta>) => void | Promise<void>;
41
+ name?: string;
42
+ };
43
+ /** Framework-neutral bridge for TanStack Query, SWR, and similar caches. */
44
+ declare function createKeepInvalidationPlugin<TMeta = Record<string, unknown>>(options: KeepInvalidationPluginOptions<TMeta>): KeepPlugin<TMeta>;
45
+
46
46
  type AuthenticatedSyncRequestContext<TMeta = Record<string, unknown>> = {
47
47
  token: string | null;
48
48
  scope?: SyncScope;
package/dist/core.js CHANGED
@@ -17,12 +17,12 @@ import {
17
17
  reconcileKeepItems,
18
18
  reorderKeepItems,
19
19
  revalidateKeepItems
20
- } from "./chunk-XWZ6GRD4.js";
20
+ } from "./chunk-62I2YZYI.js";
21
21
  import {
22
22
  KeepSchemaValidationError,
23
23
  parseKeepMeta,
24
24
  validateKeepItem
25
- } from "./chunk-THZ3ACR2.js";
25
+ } from "./chunk-5W4QSJHV.js";
26
26
  import {
27
27
  DEFAULT_INDEXEDDB_DATABASE,
28
28
  DEFAULT_INDEXEDDB_STORE,
@@ -51,20 +51,9 @@ import {
51
51
  isKeepSyncAuthError,
52
52
  isSameKeepScope,
53
53
  normalizeKeepTags
54
- } from "./chunk-XIBTMJ4R.js";
54
+ } from "./chunk-PNP7OALR.js";
55
55
 
56
- // src/integrations.ts
57
- function createKeepInvalidationPlugin(options) {
58
- return {
59
- name: options.name ?? "keepkit-cache-invalidation",
60
- after: async (context) => {
61
- const keys = typeof options.queryKeys === "function" ? options.queryKeys(context) : [options.queryKeys];
62
- await Promise.all(keys.map((queryKey) => options.invalidate(queryKey, context)));
63
- }
64
- };
65
- }
66
-
67
- // src/presets.ts
56
+ // src/features/items/presets.ts
68
57
  function createKeepKitPreset(options = {}) {
69
58
  const mode = options.mode ?? "local";
70
59
  const local = options.storage ? options.scope ? createScopedStorageAdapter(options.storage, options.scope) : options.storage : createBrowserStorageAdapter({ key: options.key, scope: options.scope });
@@ -91,7 +80,78 @@ function createKeepKitPreset(options = {}) {
91
80
  }
92
81
  var createKeepKitSetup = createKeepKitPreset;
93
82
 
94
- // src/templates/auth-sync.ts
83
+ // src/features/items/url.ts
84
+ var DEFAULT_KEEP_URL_PARAMS = {
85
+ search: "q",
86
+ tags: "tag",
87
+ sort: "sort",
88
+ page: "page"
89
+ };
90
+ function encodeKeepListQuery(query = {}, options = {}) {
91
+ const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };
92
+ const result = new URLSearchParams();
93
+ const search = query.search?.query?.trim();
94
+ if (search) result.set(params.search, search);
95
+ for (const tag of query.tags ?? []) {
96
+ const normalized = tag.trim();
97
+ if (normalized) result.append(params.tags, normalized);
98
+ }
99
+ if (query.sort?.by) result.set(params.sort, `${query.sort.by}:${query.sort.direction ?? "desc"}`);
100
+ const page = query.pagination?.page;
101
+ if (page !== void 0 && Number.isFinite(page) && page > 1) result.set(params.page, String(Math.floor(page)));
102
+ return result;
103
+ }
104
+ function decodeKeepListQuery(input, options = {}) {
105
+ const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };
106
+ const searchParams = input instanceof URLSearchParams ? input : new URL(input, "http://keepkit.invalid").searchParams;
107
+ const search = searchParams.get(params.search)?.trim();
108
+ const tags = [
109
+ ...new Set(
110
+ searchParams.getAll(params.tags).map((tag) => tag.trim()).filter(Boolean)
111
+ )
112
+ ];
113
+ const sortValue = searchParams.get(params.sort)?.split(":");
114
+ const sort = sortValue?.[0] === "savedAt" || sortValue?.[0] === "updatedAt" ? {
115
+ by: sortValue[0],
116
+ direction: sortValue[1] === "asc" ? "asc" : "desc"
117
+ } : void 0;
118
+ const rawPage = Number(searchParams.get(params.page));
119
+ const page = Number.isInteger(rawPage) && rawPage > 0 ? rawPage : void 0;
120
+ return {
121
+ ...search ? { search: { query: search } } : {},
122
+ ...tags.length > 0 ? { tags } : {},
123
+ ...sort ? { sort } : {},
124
+ ...page ? { pagination: { page } } : {}
125
+ };
126
+ }
127
+ function serializeKeepListQuery(query = {}, options = {}) {
128
+ const value = encodeKeepListQuery(query, options).toString();
129
+ return value ? `?${value}` : "";
130
+ }
131
+ function mergeKeepListQueryFromUrl(query, input, options = {}) {
132
+ const decoded = decodeKeepListQuery(input, options);
133
+ return {
134
+ ...query,
135
+ ...decoded,
136
+ search: decoded.search ?? query.search,
137
+ tags: decoded.tags ?? query.tags,
138
+ sort: decoded.sort ?? query.sort,
139
+ pagination: decoded.pagination ? { ...query.pagination, ...decoded.pagination } : query.pagination
140
+ };
141
+ }
142
+
143
+ // src/features/sync/integrations.ts
144
+ function createKeepInvalidationPlugin(options) {
145
+ return {
146
+ name: options.name ?? "keepkit-cache-invalidation",
147
+ after: async (context) => {
148
+ const keys = typeof options.queryKeys === "function" ? options.queryKeys(context) : [options.queryKeys];
149
+ await Promise.all(keys.map((queryKey) => options.invalidate(queryKey, context)));
150
+ }
151
+ };
152
+ }
153
+
154
+ // src/features/sync/templates/auth-sync.ts
95
155
  function createAuthenticatedSyncKit(options) {
96
156
  const controller = new AuthenticatedSyncStorageController(options);
97
157
  return {
@@ -284,66 +344,6 @@ function getAuthStatus(error) {
284
344
  if (candidate.response?.status === 401 || candidate.response?.status === 403) return candidate.response.status;
285
345
  return candidate.cause ? getAuthStatus(candidate.cause) : void 0;
286
346
  }
287
-
288
- // src/url.ts
289
- var DEFAULT_KEEP_URL_PARAMS = {
290
- search: "q",
291
- tags: "tag",
292
- sort: "sort",
293
- page: "page"
294
- };
295
- function encodeKeepListQuery(query = {}, options = {}) {
296
- const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };
297
- const result = new URLSearchParams();
298
- const search = query.search?.query?.trim();
299
- if (search) result.set(params.search, search);
300
- for (const tag of query.tags ?? []) {
301
- const normalized = tag.trim();
302
- if (normalized) result.append(params.tags, normalized);
303
- }
304
- if (query.sort?.by) result.set(params.sort, `${query.sort.by}:${query.sort.direction ?? "desc"}`);
305
- const page = query.pagination?.page;
306
- if (page !== void 0 && Number.isFinite(page) && page > 1) result.set(params.page, String(Math.floor(page)));
307
- return result;
308
- }
309
- function decodeKeepListQuery(input, options = {}) {
310
- const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };
311
- const searchParams = input instanceof URLSearchParams ? input : new URL(input, "http://keepkit.invalid").searchParams;
312
- const search = searchParams.get(params.search)?.trim();
313
- const tags = [
314
- ...new Set(
315
- searchParams.getAll(params.tags).map((tag) => tag.trim()).filter(Boolean)
316
- )
317
- ];
318
- const sortValue = searchParams.get(params.sort)?.split(":");
319
- const sort = sortValue?.[0] === "savedAt" || sortValue?.[0] === "updatedAt" ? {
320
- by: sortValue[0],
321
- direction: sortValue[1] === "asc" ? "asc" : "desc"
322
- } : void 0;
323
- const rawPage = Number(searchParams.get(params.page));
324
- const page = Number.isInteger(rawPage) && rawPage > 0 ? rawPage : void 0;
325
- return {
326
- ...search ? { search: { query: search } } : {},
327
- ...tags.length > 0 ? { tags } : {},
328
- ...sort ? { sort } : {},
329
- ...page ? { pagination: { page } } : {}
330
- };
331
- }
332
- function serializeKeepListQuery(query = {}, options = {}) {
333
- const value = encodeKeepListQuery(query, options).toString();
334
- return value ? `?${value}` : "";
335
- }
336
- function mergeKeepListQueryFromUrl(query, input, options = {}) {
337
- const decoded = decodeKeepListQuery(input, options);
338
- return {
339
- ...query,
340
- ...decoded,
341
- search: decoded.search ?? query.search,
342
- tags: decoded.tags ?? query.tags,
343
- sort: decoded.sort ?? query.sort,
344
- pagination: decoded.pagination ? { ...query.pagination, ...decoded.pagination } : query.pagination
345
- };
346
- }
347
347
  export {
348
348
  DEFAULT_INDEXEDDB_DATABASE,
349
349
  DEFAULT_INDEXEDDB_STORE,
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/integrations.ts","../src/presets.ts","../src/templates/auth-sync.ts","../src/url.ts"],"sourcesContent":["import type { KeepPlugin, KeepPluginContext } from \"./types\";\n\nexport type KeepInvalidationPluginOptions<TMeta = Record<string, unknown>> = {\n /** Query keys to invalidate after a successful local KeepKit mutation. */\n queryKeys: readonly unknown[] | ((context: KeepPluginContext<TMeta>) => readonly (readonly unknown[])[]);\n /** Connect this callback to queryClient.invalidateQueries or SWR mutate. */\n invalidate: (queryKey: readonly unknown[], context: KeepPluginContext<TMeta>) => void | Promise<void>;\n name?: string;\n};\n\n/** Framework-neutral bridge for TanStack Query, SWR, and similar caches. */\nexport function createKeepInvalidationPlugin<TMeta = Record<string, unknown>>(\n options: KeepInvalidationPluginOptions<TMeta>,\n): KeepPlugin<TMeta> {\n return {\n name: options.name ?? \"keepkit-cache-invalidation\",\n after: async (context) => {\n const keys = typeof options.queryKeys === \"function\" ? options.queryKeys(context) : [options.queryKeys];\n await Promise.all(keys.map((queryKey) => options.invalidate(queryKey, context)));\n },\n };\n}\n","import { exportItems } from \"./backup\";\nimport { createScopedStorageAdapter, type KeepScope } from \"./scope\";\nimport { createBrowserStorageAdapter } from \"./storage/index\";\nimport { SyncStorageAdapter } from \"./storage/sync\";\nimport type { RemoteSyncDriver, StorageAdapter } from \"./types\";\n\nexport type KeepKitPresetMode = \"local\" | \"sync\" | \"backup\";\n\nexport type KeepKitPresetOptions<TMeta = Record<string, unknown>> = {\n mode?: KeepKitPresetMode;\n key?: string;\n scope?: KeepScope;\n remote?: RemoteSyncDriver<TMeta>;\n storage?: StorageAdapter<TMeta>;\n};\n\nexport type KeepKitSetup<TMeta = Record<string, unknown>> = {\n mode: KeepKitPresetMode;\n scope?: KeepScope;\n storage: StorageAdapter<TMeta>;\n exportBackup: () => Promise<string>;\n};\n\n/**\n * Build the recommended local/sync/backup wiring without imposing an auth or\n * API client. Pass the current user and tenant scope whenever the account changes.\n */\nexport function createKeepKitPreset<TMeta = Record<string, unknown>>(\n options: KeepKitPresetOptions<TMeta> = {},\n): KeepKitSetup<TMeta> {\n const mode = options.mode ?? \"local\";\n const local = options.storage\n ? options.scope\n ? createScopedStorageAdapter(options.storage, options.scope)\n : options.storage\n : createBrowserStorageAdapter<TMeta>({ key: options.key, scope: options.scope });\n if (mode === \"sync\" && !options.remote) {\n throw new Error('createKeepKitPreset({ mode: \"sync\" }) requires a remote driver.');\n }\n let storage: StorageAdapter<TMeta> = local;\n if (mode === \"sync\") {\n const remote = options.remote;\n if (!remote) throw new Error('createKeepKitPreset({ mode: \"sync\" }) requires a remote driver.');\n storage = new SyncStorageAdapter<TMeta>({\n local,\n remote,\n userId: options.scope?.userId,\n tenantId: options.scope?.tenantId,\n });\n }\n return {\n mode,\n scope: options.scope,\n storage,\n exportBackup: () => exportItems(storage),\n };\n}\n\nexport const createKeepKitSetup = createKeepKitPreset;\n","import { exportItems } from \"../backup\";\nimport { createScopedStorageAdapter, getKeepScopeKey, isSameKeepScope, ScopedSyncQueueAdapter } from \"../scope\";\nimport { type BrowserStorageAdapterOptions, createBrowserStorageAdapter } from \"../storage\";\nimport { SyncStorageAdapter, type SyncStorageAdapterOptions } from \"../storage/sync\";\nimport type {\n KeepItem,\n KeepSyncAuthError,\n KeepSyncAuthStatus,\n KeepSyncState,\n RemoteSyncDriver,\n RemoteSyncResult,\n StorageAdapter,\n SyncCapableStorageAdapter,\n SyncOperation,\n SyncScope,\n} from \"../types\";\nimport { KeepSyncAuthError as KeepSyncAuthErrorClass } from \"../types\";\n\nexport type AuthenticatedSyncRequestContext<TMeta = Record<string, unknown>> = {\n token: string | null;\n scope?: SyncScope;\n operation?: SyncOperation<TMeta>;\n};\n\n/** Transport boundary for auth-aware requests; cookies and bearer tokens remain host concerns. */\nexport type AuthenticatedSyncTransport<TMeta = Record<string, unknown>> = {\n push: (\n operation: SyncOperation<TMeta>,\n context: AuthenticatedSyncRequestContext<TMeta>,\n ) => Promise<RemoteSyncResult<TMeta>>;\n pull?: (context: AuthenticatedSyncRequestContext<TMeta>) => Promise<KeepItem<TMeta>[]>;\n};\n\nexport type AuthenticatedSyncAuthContext<TMeta = Record<string, unknown>> = {\n operation?: SyncOperation<TMeta>;\n scope?: SyncScope;\n};\n\nexport type AuthenticatedSyncKitOptions<TMeta = Record<string, unknown>> = Omit<\n SyncStorageAdapterOptions<TMeta>,\n \"local\" | \"remote\" | \"scope\"\n> & {\n /** Optional custom local adapter. Browser storage is used when omitted. */\n local?: StorageAdapter<TMeta>;\n key?: BrowserStorageAdapterOptions[\"key\"];\n databaseName?: BrowserStorageAdapterOptions[\"databaseName\"];\n scope?: SyncScope;\n /** Resolve the active account or tenant before storage operations. */\n getScope?: () => SyncScope | undefined | Promise<SyncScope | undefined>;\n getAuthToken: () => Promise<string | null>;\n transport: AuthenticatedSyncTransport<TMeta>;\n onAuthError?: (error: KeepSyncAuthError<TMeta>, context: AuthenticatedSyncAuthContext<TMeta>) => void | Promise<void>;\n onReauthenticate?: (\n error: KeepSyncAuthError<TMeta>,\n context: AuthenticatedSyncAuthContext<TMeta>,\n ) => void | Promise<void>;\n onScopeChange?: (next: SyncScope | undefined, previous: SyncScope | undefined) => void | Promise<void>;\n};\n\nexport type AuthenticatedSyncKit<TMeta = Record<string, unknown>> = {\n readonly mode: \"sync\";\n readonly storage: SyncCapableStorageAdapter<TMeta>;\n readonly scope?: SyncScope;\n readonly scopeKey: string;\n getScope(): SyncScope | undefined;\n setScope(scope?: SyncScope): Promise<void>;\n subscribeScope(listener: () => void): () => void;\n exportBackup(): Promise<string>;\n dispose(): void;\n};\n\n/** Creates auth-independent sync wiring with per-request tokens and isolated account scopes. */\nexport function createAuthenticatedSyncKit<TMeta = Record<string, unknown>>(\n options: AuthenticatedSyncKitOptions<TMeta>,\n): AuthenticatedSyncKit<TMeta> {\n const controller = new AuthenticatedSyncStorageController(options);\n return {\n mode: \"sync\",\n storage: controller,\n get scope() {\n return controller.scope;\n },\n get scopeKey() {\n return controller.scopeKey;\n },\n getScope: () => controller.scope,\n setScope: (scope) => controller.setScope(scope),\n subscribeScope: (listener) => controller.subscribeScope(listener),\n exportBackup: () => controller.exportBackup(),\n dispose: () => controller.dispose(),\n };\n}\n\nclass AuthenticatedSyncStorageController<TMeta = Record<string, unknown>> implements SyncCapableStorageAdapter<TMeta> {\n private readonly options: AuthenticatedSyncKitOptions<TMeta>;\n private currentScope: SyncScope | undefined;\n private current: SyncStorageAdapter<TMeta>;\n private readonly scopeListeners = new Set<() => void>();\n private readonly dataListeners = new Set<() => void>();\n private readonly syncListeners = new Set<() => void>();\n private unsubscribeData: () => void = () => undefined;\n private unsubscribeSync: () => void = () => undefined;\n private transition = Promise.resolve();\n private disposed = false;\n\n constructor(options: AuthenticatedSyncKitOptions<TMeta>) {\n this.options = options;\n this.currentScope = options.scope;\n this.current = this.createAdapter(this.currentScope);\n this.attach(this.current);\n }\n\n get storageKey(): string | undefined {\n return this.current.storageKey;\n }\n\n get scope(): SyncScope | undefined {\n return this.currentScope;\n }\n\n get scopeKey(): string {\n return getKeepScopeKey(this.currentScope);\n }\n\n async getAll(): Promise<KeepItem<TMeta>[]> {\n await this.ensureScope();\n return this.current.getAll();\n }\n\n async set(item: KeepItem<TMeta>): Promise<void> {\n await this.ensureScope();\n return this.current.set(item);\n }\n\n async setMany(items: KeepItem<TMeta>[]): Promise<void> {\n await this.ensureScope();\n return this.current.setMany(items);\n }\n\n async remove(id: string): Promise<void> {\n await this.ensureScope();\n return this.current.remove(id);\n }\n\n async removeMany(ids: string[]): Promise<void> {\n await this.ensureScope();\n return this.current.removeMany(ids);\n }\n\n async clear(): Promise<void> {\n await this.ensureScope();\n return this.current.clear();\n }\n\n async merge(items: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n await this.ensureScope();\n return this.current.merge(items);\n }\n\n subscribe(listener: () => void): () => void {\n this.dataListeners.add(listener);\n return () => this.dataListeners.delete(listener);\n }\n\n getSyncState(): KeepSyncState<TMeta> {\n return this.current.getSyncState();\n }\n\n subscribeSync(listener: () => void): () => void {\n this.syncListeners.add(listener);\n return () => this.syncListeners.delete(listener);\n }\n\n async flushSync(): Promise<void> {\n await this.ensureScope();\n return this.current.flushSync();\n }\n\n async retrySync(): Promise<void> {\n await this.ensureScope();\n return this.current.retrySync?.() ?? this.current.flushSync();\n }\n\n async resolveSyncConflict(\n id: string,\n resolution: \"local\" | \"remote\" | \"manual\",\n item?: KeepItem<TMeta>,\n ): Promise<void> {\n await this.ensureScope();\n if (!this.current.resolveSyncConflict) {\n throw new Error(\"The authenticated sync adapter does not support conflict resolution.\");\n }\n return this.current.resolveSyncConflict(id, resolution, item);\n }\n\n async setScope(nextScope?: SyncScope): Promise<void> {\n const run = this.transition.then(async () => {\n if (isSameKeepScope(this.currentScope, nextScope)) return;\n if (this.disposed) throw new Error(\"AuthenticatedSyncKit has been disposed.\");\n const previousScope = this.currentScope;\n this.unsubscribeData();\n this.unsubscribeSync();\n this.current.dispose?.();\n this.currentScope = nextScope;\n this.current = this.createAdapter(nextScope);\n this.attach(this.current);\n await this.options.onScopeChange?.(nextScope, previousScope);\n this.notify(this.scopeListeners);\n this.notify(this.dataListeners);\n this.notify(this.syncListeners);\n });\n this.transition = run.catch(() => undefined);\n return run;\n }\n\n subscribeScope(listener: () => void): () => void {\n this.scopeListeners.add(listener);\n return () => this.scopeListeners.delete(listener);\n }\n\n async exportBackup(): Promise<string> {\n await this.ensureScope();\n return exportItems(this.current);\n }\n\n dispose(): void {\n this.disposed = true;\n this.unsubscribeData();\n this.unsubscribeSync();\n this.current.dispose?.();\n this.scopeListeners.clear();\n this.dataListeners.clear();\n this.syncListeners.clear();\n }\n\n private createAdapter(scope: SyncScope | undefined): SyncStorageAdapter<TMeta> {\n const local = this.options.local\n ? scope\n ? createScopedStorageAdapter(this.options.local, scope)\n : this.options.local\n : createBrowserStorageAdapter<TMeta>({ key: this.options.key, databaseName: this.options.databaseName, scope });\n const queue =\n this.options.queue && scope ? new ScopedSyncQueueAdapter(this.options.queue, scope) : this.options.queue;\n const remote = createAuthenticatedRemote(this.options, scope);\n return new SyncStorageAdapter<TMeta>({\n ...this.options,\n local,\n remote,\n queue,\n scope,\n });\n }\n\n private attach(adapter: SyncStorageAdapter<TMeta>): void {\n this.unsubscribeData = adapter.subscribe?.(() => this.notify(this.dataListeners)) ?? (() => undefined);\n this.unsubscribeSync = adapter.subscribeSync(() => this.notify(this.syncListeners));\n }\n\n private async ensureScope(): Promise<void> {\n if (!this.options.getScope) return;\n await this.setScope(await this.options.getScope());\n }\n\n private notify(listeners: Set<() => void>): void {\n for (const listener of listeners) listener();\n }\n}\n\nfunction createAuthenticatedRemote<TMeta>(\n options: AuthenticatedSyncKitOptions<TMeta>,\n scope: SyncScope | undefined,\n): RemoteSyncDriver<TMeta> {\n const pull = options.transport.pull;\n return {\n push: async (operation) => {\n try {\n const token = await options.getAuthToken();\n return await options.transport.push(operation, { token, scope, operation });\n } catch (cause) {\n return handleAuthFailure(cause, options, { operation, scope });\n }\n },\n pull: pull\n ? async () => {\n try {\n const token = await options.getAuthToken();\n return await pull({ token, scope });\n } catch (cause) {\n return handleAuthFailure(cause, options, { scope });\n }\n }\n : undefined,\n };\n}\n\nasync function handleAuthFailure<TMeta>(\n cause: unknown,\n options: AuthenticatedSyncKitOptions<TMeta>,\n context: AuthenticatedSyncAuthContext<TMeta>,\n): Promise<never> {\n const status = getAuthStatus(cause);\n if (!status) throw cause;\n const error =\n cause instanceof KeepSyncAuthErrorClass\n ? cause\n : new KeepSyncAuthErrorClass(status, { operation: context.operation, scope: context.scope, cause });\n await options.onAuthError?.(error, context);\n await options.onReauthenticate?.(error, context);\n throw error;\n}\n\nfunction getAuthStatus(error: unknown): KeepSyncAuthStatus | undefined {\n if (error instanceof KeepSyncAuthErrorClass) return error.status;\n if (!error || typeof error !== \"object\") return undefined;\n const candidate = error as { status?: unknown; response?: { status?: unknown }; cause?: unknown };\n if (candidate.status === 401 || candidate.status === 403) return candidate.status;\n if (candidate.response?.status === 401 || candidate.response?.status === 403) return candidate.response.status;\n return candidate.cause ? getAuthStatus(candidate.cause) : undefined;\n}\n","import type { KeepListQuery } from \"./query\";\n\nexport type KeepUrlParamNames = {\n search: string;\n tags: string;\n sort: string;\n page: string;\n};\n\nexport type KeepUrlSyncOptions = {\n /** Parameters are intentionally short so shared collection URLs stay readable. */\n params?: Partial<KeepUrlParamNames>;\n /** Push is the default so browser back/forward restores collection states. */\n history?: \"replace\" | \"push\";\n /** URL to read/write. Defaults to the current browser URL. */\n url?: string;\n};\n\nexport const DEFAULT_KEEP_URL_PARAMS: KeepUrlParamNames = {\n search: \"q\",\n tags: \"tag\",\n sort: \"sort\",\n page: \"page\",\n};\n\nexport type KeepUrlState = Pick<KeepListQuery, \"search\" | \"tags\" | \"sort\" | \"pagination\">;\n\n/** Convert a list query to stable URLSearchParams without serializing functions or unsupported filters. */\nexport function encodeKeepListQuery<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta> = {},\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): URLSearchParams {\n const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };\n const result = new URLSearchParams();\n const search = query.search?.query?.trim();\n if (search) result.set(params.search, search);\n for (const tag of query.tags ?? []) {\n const normalized = tag.trim();\n if (normalized) result.append(params.tags, normalized);\n }\n if (query.sort?.by) result.set(params.sort, `${query.sort.by}:${query.sort.direction ?? \"desc\"}`);\n const page = query.pagination?.page;\n if (page !== undefined && Number.isFinite(page) && page > 1) result.set(params.page, String(Math.floor(page)));\n return result;\n}\n\n/** Parse a URL into the query fields supported by KeepCollection. Invalid values are ignored. */\nexport function decodeKeepListQuery(\n input: string | URL | URLSearchParams,\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): KeepUrlState {\n const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };\n const searchParams = input instanceof URLSearchParams ? input : new URL(input, \"http://keepkit.invalid\").searchParams;\n const search = searchParams.get(params.search)?.trim();\n const tags = [\n ...new Set(\n searchParams\n .getAll(params.tags)\n .map((tag) => tag.trim())\n .filter(Boolean),\n ),\n ];\n const sortValue = searchParams.get(params.sort)?.split(\":\");\n const sort: KeepListQuery[\"sort\"] =\n sortValue?.[0] === \"savedAt\" || sortValue?.[0] === \"updatedAt\"\n ? {\n by: sortValue[0],\n direction: sortValue[1] === \"asc\" ? (\"asc\" as const) : (\"desc\" as const),\n }\n : undefined;\n const rawPage = Number(searchParams.get(params.page));\n const page = Number.isInteger(rawPage) && rawPage > 0 ? rawPage : undefined;\n return {\n ...(search ? { search: { query: search } } : {}),\n ...(tags.length > 0 ? { tags } : {}),\n ...(sort ? { sort } : {}),\n ...(page ? { pagination: { page } } : {}),\n };\n}\n\nexport function serializeKeepListQuery<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta> = {},\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): string {\n const value = encodeKeepListQuery(query, options).toString();\n return value ? `?${value}` : \"\";\n}\n\nexport function mergeKeepListQueryFromUrl<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta>,\n input: string | URL | URLSearchParams,\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): KeepListQuery<TMeta> {\n const decoded = decodeKeepListQuery(input, options);\n return {\n ...query,\n ...decoded,\n search: decoded.search ?? query.search,\n tags: decoded.tags ?? query.tags,\n sort: decoded.sort ?? query.sort,\n pagination: decoded.pagination ? { ...query.pagination, ...decoded.pagination } : query.pagination,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWO,SAAS,6BACd,SACmB;AACnB,SAAO;AAAA,IACL,MAAM,QAAQ,QAAQ;AAAA,IACtB,OAAO,OAAO,YAAY;AACxB,YAAM,OAAO,OAAO,QAAQ,cAAc,aAAa,QAAQ,UAAU,OAAO,IAAI,CAAC,QAAQ,SAAS;AACtG,YAAM,QAAQ,IAAI,KAAK,IAAI,CAAC,aAAa,QAAQ,WAAW,UAAU,OAAO,CAAC,CAAC;AAAA,IACjF;AAAA,EACF;AACF;;;ACMO,SAAS,oBACd,UAAuC,CAAC,GACnB;AACrB,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,QAAQ,QAAQ,UAClB,QAAQ,QACN,2BAA2B,QAAQ,SAAS,QAAQ,KAAK,IACzD,QAAQ,UACV,4BAAmC,EAAE,KAAK,QAAQ,KAAK,OAAO,QAAQ,MAAM,CAAC;AACjF,MAAI,SAAS,UAAU,CAAC,QAAQ,QAAQ;AACtC,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACnF;AACA,MAAI,UAAiC;AACrC,MAAI,SAAS,QAAQ;AACnB,UAAM,SAAS,QAAQ;AACvB,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,iEAAiE;AAC9F,cAAU,IAAI,mBAA0B;AAAA,MACtC;AAAA,MACA;AAAA,MACA,QAAQ,QAAQ,OAAO;AAAA,MACvB,UAAU,QAAQ,OAAO;AAAA,IAC3B,CAAC;AAAA,EACH;AACA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,QAAQ;AAAA,IACf;AAAA,IACA,cAAc,MAAM,YAAY,OAAO;AAAA,EACzC;AACF;AAEO,IAAM,qBAAqB;;;ACc3B,SAAS,2BACd,SAC6B;AAC7B,QAAM,aAAa,IAAI,mCAAmC,OAAO;AACjE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,IAAI,QAAQ;AACV,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,IAAI,WAAW;AACb,aAAO,WAAW;AAAA,IACpB;AAAA,IACA,UAAU,MAAM,WAAW;AAAA,IAC3B,UAAU,CAAC,UAAU,WAAW,SAAS,KAAK;AAAA,IAC9C,gBAAgB,CAAC,aAAa,WAAW,eAAe,QAAQ;AAAA,IAChE,cAAc,MAAM,WAAW,aAAa;AAAA,IAC5C,SAAS,MAAM,WAAW,QAAQ;AAAA,EACpC;AACF;AAEA,IAAM,qCAAN,MAAsH;AAAA,EAYpH,YAAY,SAA6C;AARzD,SAAiB,iBAAiB,oBAAI,IAAgB;AACtD,SAAiB,gBAAgB,oBAAI,IAAgB;AACrD,SAAiB,gBAAgB,oBAAI,IAAgB;AACrD,SAAQ,kBAA8B,MAAM;AAC5C,SAAQ,kBAA8B,MAAM;AAC5C,SAAQ,aAAa,QAAQ,QAAQ;AACrC,SAAQ,WAAW;AAGjB,SAAK,UAAU;AACf,SAAK,eAAe,QAAQ;AAC5B,SAAK,UAAU,KAAK,cAAc,KAAK,YAAY;AACnD,SAAK,OAAO,KAAK,OAAO;AAAA,EAC1B;AAAA,EAEA,IAAI,aAAiC;AACnC,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA,EAEA,IAAI,QAA+B;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,gBAAgB,KAAK,YAAY;AAAA,EAC1C;AAAA,EAEA,MAAM,SAAqC;AACzC,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAAA,EAEA,MAAM,IAAI,MAAsC;AAC9C,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,EAC9B;AAAA,EAEA,MAAM,QAAQ,OAAyC;AACrD,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,QAAQ,KAAK;AAAA,EACnC;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,OAAO,EAAE;AAAA,EAC/B;AAAA,EAEA,MAAM,WAAW,KAA8B;AAC7C,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,WAAW,GAAG;AAAA,EACpC;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B;AAAA,EAEA,MAAM,MAAM,OAAsD;AAChE,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,MAAM,KAAK;AAAA,EACjC;AAAA,EAEA,UAAU,UAAkC;AAC1C,SAAK,cAAc,IAAI,QAAQ;AAC/B,WAAO,MAAM,KAAK,cAAc,OAAO,QAAQ;AAAA,EACjD;AAAA,EAEA,eAAqC;AACnC,WAAO,KAAK,QAAQ,aAAa;AAAA,EACnC;AAAA,EAEA,cAAc,UAAkC;AAC9C,SAAK,cAAc,IAAI,QAAQ;AAC/B,WAAO,MAAM,KAAK,cAAc,OAAO,QAAQ;AAAA,EACjD;AAAA,EAEA,MAAM,YAA2B;AAC/B,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,UAAU;AAAA,EAChC;AAAA,EAEA,MAAM,YAA2B;AAC/B,UAAM,KAAK,YAAY;AACvB,WAAO,KAAK,QAAQ,YAAY,KAAK,KAAK,QAAQ,UAAU;AAAA,EAC9D;AAAA,EAEA,MAAM,oBACJ,IACA,YACA,MACe;AACf,UAAM,KAAK,YAAY;AACvB,QAAI,CAAC,KAAK,QAAQ,qBAAqB;AACrC,YAAM,IAAI,MAAM,sEAAsE;AAAA,IACxF;AACA,WAAO,KAAK,QAAQ,oBAAoB,IAAI,YAAY,IAAI;AAAA,EAC9D;AAAA,EAEA,MAAM,SAAS,WAAsC;AACnD,UAAM,MAAM,KAAK,WAAW,KAAK,YAAY;AAC3C,UAAI,gBAAgB,KAAK,cAAc,SAAS,EAAG;AACnD,UAAI,KAAK,SAAU,OAAM,IAAI,MAAM,yCAAyC;AAC5E,YAAM,gBAAgB,KAAK;AAC3B,WAAK,gBAAgB;AACrB,WAAK,gBAAgB;AACrB,WAAK,QAAQ,UAAU;AACvB,WAAK,eAAe;AACpB,WAAK,UAAU,KAAK,cAAc,SAAS;AAC3C,WAAK,OAAO,KAAK,OAAO;AACxB,YAAM,KAAK,QAAQ,gBAAgB,WAAW,aAAa;AAC3D,WAAK,OAAO,KAAK,cAAc;AAC/B,WAAK,OAAO,KAAK,aAAa;AAC9B,WAAK,OAAO,KAAK,aAAa;AAAA,IAChC,CAAC;AACD,SAAK,aAAa,IAAI,MAAM,MAAM,MAAS;AAC3C,WAAO;AAAA,EACT;AAAA,EAEA,eAAe,UAAkC;AAC/C,SAAK,eAAe,IAAI,QAAQ;AAChC,WAAO,MAAM,KAAK,eAAe,OAAO,QAAQ;AAAA,EAClD;AAAA,EAEA,MAAM,eAAgC;AACpC,UAAM,KAAK,YAAY;AACvB,WAAO,YAAY,KAAK,OAAO;AAAA,EACjC;AAAA,EAEA,UAAgB;AACd,SAAK,WAAW;AAChB,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AACrB,SAAK,QAAQ,UAAU;AACvB,SAAK,eAAe,MAAM;AAC1B,SAAK,cAAc,MAAM;AACzB,SAAK,cAAc,MAAM;AAAA,EAC3B;AAAA,EAEQ,cAAc,OAAyD;AAC7E,UAAM,QAAQ,KAAK,QAAQ,QACvB,QACE,2BAA2B,KAAK,QAAQ,OAAO,KAAK,IACpD,KAAK,QAAQ,QACf,4BAAmC,EAAE,KAAK,KAAK,QAAQ,KAAK,cAAc,KAAK,QAAQ,cAAc,MAAM,CAAC;AAChH,UAAM,QACJ,KAAK,QAAQ,SAAS,QAAQ,IAAI,uBAAuB,KAAK,QAAQ,OAAO,KAAK,IAAI,KAAK,QAAQ;AACrG,UAAM,SAAS,0BAA0B,KAAK,SAAS,KAAK;AAC5D,WAAO,IAAI,mBAA0B;AAAA,MACnC,GAAG,KAAK;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,OAAO,SAA0C;AACvD,SAAK,kBAAkB,QAAQ,YAAY,MAAM,KAAK,OAAO,KAAK,aAAa,CAAC,MAAM,MAAM;AAC5F,SAAK,kBAAkB,QAAQ,cAAc,MAAM,KAAK,OAAO,KAAK,aAAa,CAAC;AAAA,EACpF;AAAA,EAEA,MAAc,cAA6B;AACzC,QAAI,CAAC,KAAK,QAAQ,SAAU;AAC5B,UAAM,KAAK,SAAS,MAAM,KAAK,QAAQ,SAAS,CAAC;AAAA,EACnD;AAAA,EAEQ,OAAO,WAAkC;AAC/C,eAAW,YAAY,UAAW,UAAS;AAAA,EAC7C;AACF;AAEA,SAAS,0BACP,SACA,OACyB;AACzB,QAAM,OAAO,QAAQ,UAAU;AAC/B,SAAO;AAAA,IACL,MAAM,OAAO,cAAc;AACzB,UAAI;AACF,cAAM,QAAQ,MAAM,QAAQ,aAAa;AACzC,eAAO,MAAM,QAAQ,UAAU,KAAK,WAAW,EAAE,OAAO,OAAO,UAAU,CAAC;AAAA,MAC5E,SAAS,OAAO;AACd,eAAO,kBAAkB,OAAO,SAAS,EAAE,WAAW,MAAM,CAAC;AAAA,MAC/D;AAAA,IACF;AAAA,IACA,MAAM,OACF,YAAY;AACV,UAAI;AACF,cAAM,QAAQ,MAAM,QAAQ,aAAa;AACzC,eAAO,MAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,MACpC,SAAS,OAAO;AACd,eAAO,kBAAkB,OAAO,SAAS,EAAE,MAAM,CAAC;AAAA,MACpD;AAAA,IACF,IACA;AAAA,EACN;AACF;AAEA,eAAe,kBACb,OACA,SACA,SACgB;AAChB,QAAM,SAAS,cAAc,KAAK;AAClC,MAAI,CAAC,OAAQ,OAAM;AACnB,QAAM,QACJ,iBAAiB,oBACb,QACA,IAAI,kBAAuB,QAAQ,EAAE,WAAW,QAAQ,WAAW,OAAO,QAAQ,OAAO,MAAM,CAAC;AACtG,QAAM,QAAQ,cAAc,OAAO,OAAO;AAC1C,QAAM,QAAQ,mBAAmB,OAAO,OAAO;AAC/C,QAAM;AACR;AAEA,SAAS,cAAc,OAAgD;AACrE,MAAI,iBAAiB,kBAAwB,QAAO,MAAM;AAC1D,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,YAAY;AAClB,MAAI,UAAU,WAAW,OAAO,UAAU,WAAW,IAAK,QAAO,UAAU;AAC3E,MAAI,UAAU,UAAU,WAAW,OAAO,UAAU,UAAU,WAAW,IAAK,QAAO,UAAU,SAAS;AACxG,SAAO,UAAU,QAAQ,cAAc,UAAU,KAAK,IAAI;AAC5D;;;AC5SO,IAAM,0BAA6C;AAAA,EACxD,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAKO,SAAS,oBACd,QAA8B,CAAC,GAC/B,UAA8C,CAAC,GAC9B;AACjB,QAAM,SAAS,EAAE,GAAG,yBAAyB,GAAG,QAAQ,OAAO;AAC/D,QAAM,SAAS,IAAI,gBAAgB;AACnC,QAAM,SAAS,MAAM,QAAQ,OAAO,KAAK;AACzC,MAAI,OAAQ,QAAO,IAAI,OAAO,QAAQ,MAAM;AAC5C,aAAW,OAAO,MAAM,QAAQ,CAAC,GAAG;AAClC,UAAM,aAAa,IAAI,KAAK;AAC5B,QAAI,WAAY,QAAO,OAAO,OAAO,MAAM,UAAU;AAAA,EACvD;AACA,MAAI,MAAM,MAAM,GAAI,QAAO,IAAI,OAAO,MAAM,GAAG,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK,aAAa,MAAM,EAAE;AAChG,QAAM,OAAO,MAAM,YAAY;AAC/B,MAAI,SAAS,UAAa,OAAO,SAAS,IAAI,KAAK,OAAO,EAAG,QAAO,IAAI,OAAO,MAAM,OAAO,KAAK,MAAM,IAAI,CAAC,CAAC;AAC7G,SAAO;AACT;AAGO,SAAS,oBACd,OACA,UAA8C,CAAC,GACjC;AACd,QAAM,SAAS,EAAE,GAAG,yBAAyB,GAAG,QAAQ,OAAO;AAC/D,QAAM,eAAe,iBAAiB,kBAAkB,QAAQ,IAAI,IAAI,OAAO,wBAAwB,EAAE;AACzG,QAAM,SAAS,aAAa,IAAI,OAAO,MAAM,GAAG,KAAK;AACrD,QAAM,OAAO;AAAA,IACX,GAAG,IAAI;AAAA,MACL,aACG,OAAO,OAAO,IAAI,EAClB,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,EACvB,OAAO,OAAO;AAAA,IACnB;AAAA,EACF;AACA,QAAM,YAAY,aAAa,IAAI,OAAO,IAAI,GAAG,MAAM,GAAG;AAC1D,QAAM,OACJ,YAAY,CAAC,MAAM,aAAa,YAAY,CAAC,MAAM,cAC/C;AAAA,IACE,IAAI,UAAU,CAAC;AAAA,IACf,WAAW,UAAU,CAAC,MAAM,QAAS,QAAmB;AAAA,EAC1D,IACA;AACN,QAAM,UAAU,OAAO,aAAa,IAAI,OAAO,IAAI,CAAC;AACpD,QAAM,OAAO,OAAO,UAAU,OAAO,KAAK,UAAU,IAAI,UAAU;AAClE,SAAO;AAAA,IACL,GAAI,SAAS,EAAE,QAAQ,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC;AAAA,IAC9C,GAAI,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,IAClC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,GAAI,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,CAAC;AAAA,EACzC;AACF;AAEO,SAAS,uBACd,QAA8B,CAAC,GAC/B,UAA8C,CAAC,GACvC;AACR,QAAM,QAAQ,oBAAoB,OAAO,OAAO,EAAE,SAAS;AAC3D,SAAO,QAAQ,IAAI,KAAK,KAAK;AAC/B;AAEO,SAAS,0BACd,OACA,OACA,UAA8C,CAAC,GACzB;AACtB,QAAM,UAAU,oBAAoB,OAAO,OAAO;AAClD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,QAAQ,QAAQ,UAAU,MAAM;AAAA,IAChC,MAAM,QAAQ,QAAQ,MAAM;AAAA,IAC5B,MAAM,QAAQ,QAAQ,MAAM;AAAA,IAC5B,YAAY,QAAQ,aAAa,EAAE,GAAG,MAAM,YAAY,GAAG,QAAQ,WAAW,IAAI,MAAM;AAAA,EAC1F;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/features/items/presets.ts","../src/features/items/url.ts","../src/features/sync/integrations.ts","../src/features/sync/templates/auth-sync.ts"],"sourcesContent":["import { createBrowserStorageAdapter } from \"../../storage/index\";\nimport { SyncStorageAdapter } from \"../../storage/sync\";\nimport { exportItems } from \"../persistence/backup\";\nimport { createScopedStorageAdapter, type KeepScope } from \"../persistence/scope\";\nimport type { RemoteSyncDriver, StorageAdapter } from \"./types\";\n\nexport type KeepKitPresetMode = \"local\" | \"sync\" | \"backup\";\n\nexport type KeepKitPresetOptions<TMeta = Record<string, unknown>> = {\n mode?: KeepKitPresetMode;\n key?: string;\n scope?: KeepScope;\n remote?: RemoteSyncDriver<TMeta>;\n storage?: StorageAdapter<TMeta>;\n};\n\nexport type KeepKitSetup<TMeta = Record<string, unknown>> = {\n mode: KeepKitPresetMode;\n scope?: KeepScope;\n storage: StorageAdapter<TMeta>;\n exportBackup: () => Promise<string>;\n};\n\n/**\n * Build the recommended local/sync/backup wiring without imposing an auth or\n * API client. Pass the current user and tenant scope whenever the account changes.\n */\nexport function createKeepKitPreset<TMeta = Record<string, unknown>>(\n options: KeepKitPresetOptions<TMeta> = {},\n): KeepKitSetup<TMeta> {\n const mode = options.mode ?? \"local\";\n const local = options.storage\n ? options.scope\n ? createScopedStorageAdapter(options.storage, options.scope)\n : options.storage\n : createBrowserStorageAdapter<TMeta>({ key: options.key, scope: options.scope });\n if (mode === \"sync\" && !options.remote) {\n throw new Error('createKeepKitPreset({ mode: \"sync\" }) requires a remote driver.');\n }\n let storage: StorageAdapter<TMeta> = local;\n if (mode === \"sync\") {\n const remote = options.remote;\n if (!remote) throw new Error('createKeepKitPreset({ mode: \"sync\" }) requires a remote driver.');\n storage = new SyncStorageAdapter<TMeta>({\n local,\n remote,\n userId: options.scope?.userId,\n tenantId: options.scope?.tenantId,\n });\n }\n return {\n mode,\n scope: options.scope,\n storage,\n exportBackup: () => exportItems(storage),\n };\n}\n\nexport const createKeepKitSetup = createKeepKitPreset;\n","import type { KeepListQuery } from \"./query\";\n\nexport type KeepUrlParamNames = {\n search: string;\n tags: string;\n sort: string;\n page: string;\n};\n\nexport type KeepUrlSyncOptions = {\n /** Parameters are intentionally short so shared collection URLs stay readable. */\n params?: Partial<KeepUrlParamNames>;\n /** Push is the default so browser back/forward restores collection states. */\n history?: \"replace\" | \"push\";\n /** URL to read/write. Defaults to the current browser URL. */\n url?: string;\n};\n\nexport const DEFAULT_KEEP_URL_PARAMS: KeepUrlParamNames = {\n search: \"q\",\n tags: \"tag\",\n sort: \"sort\",\n page: \"page\",\n};\n\nexport type KeepUrlState = Pick<KeepListQuery, \"search\" | \"tags\" | \"sort\" | \"pagination\">;\n\n/** Convert a list query to stable URLSearchParams without serializing functions or unsupported filters. */\nexport function encodeKeepListQuery<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta> = {},\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): URLSearchParams {\n const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };\n const result = new URLSearchParams();\n const search = query.search?.query?.trim();\n if (search) result.set(params.search, search);\n for (const tag of query.tags ?? []) {\n const normalized = tag.trim();\n if (normalized) result.append(params.tags, normalized);\n }\n if (query.sort?.by) result.set(params.sort, `${query.sort.by}:${query.sort.direction ?? \"desc\"}`);\n const page = query.pagination?.page;\n if (page !== undefined && Number.isFinite(page) && page > 1) result.set(params.page, String(Math.floor(page)));\n return result;\n}\n\n/** Parse a URL into the query fields supported by KeepCollection. Invalid values are ignored. */\nexport function decodeKeepListQuery(\n input: string | URL | URLSearchParams,\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): KeepUrlState {\n const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };\n const searchParams = input instanceof URLSearchParams ? input : new URL(input, \"http://keepkit.invalid\").searchParams;\n const search = searchParams.get(params.search)?.trim();\n const tags = [\n ...new Set(\n searchParams\n .getAll(params.tags)\n .map((tag) => tag.trim())\n .filter(Boolean),\n ),\n ];\n const sortValue = searchParams.get(params.sort)?.split(\":\");\n const sort: KeepListQuery[\"sort\"] =\n sortValue?.[0] === \"savedAt\" || sortValue?.[0] === \"updatedAt\"\n ? {\n by: sortValue[0],\n direction: sortValue[1] === \"asc\" ? (\"asc\" as const) : (\"desc\" as const),\n }\n : undefined;\n const rawPage = Number(searchParams.get(params.page));\n const page = Number.isInteger(rawPage) && rawPage > 0 ? rawPage : undefined;\n return {\n ...(search ? { search: { query: search } } : {}),\n ...(tags.length > 0 ? { tags } : {}),\n ...(sort ? { sort } : {}),\n ...(page ? { pagination: { page } } : {}),\n };\n}\n\nexport function serializeKeepListQuery<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta> = {},\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): string {\n const value = encodeKeepListQuery(query, options).toString();\n return value ? `?${value}` : \"\";\n}\n\nexport function mergeKeepListQueryFromUrl<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta>,\n input: string | URL | URLSearchParams,\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): KeepListQuery<TMeta> {\n const decoded = decodeKeepListQuery(input, options);\n return {\n ...query,\n ...decoded,\n search: decoded.search ?? query.search,\n tags: decoded.tags ?? query.tags,\n sort: decoded.sort ?? query.sort,\n pagination: decoded.pagination ? { ...query.pagination, ...decoded.pagination } : query.pagination,\n };\n}\n","import type { KeepPlugin, KeepPluginContext } from \"../items/types\";\n\nexport type KeepInvalidationPluginOptions<TMeta = Record<string, unknown>> = {\n /** Query keys to invalidate after a successful local KeepKit mutation. */\n queryKeys: readonly unknown[] | ((context: KeepPluginContext<TMeta>) => readonly (readonly unknown[])[]);\n /** Connect this callback to queryClient.invalidateQueries or SWR mutate. */\n invalidate: (queryKey: readonly unknown[], context: KeepPluginContext<TMeta>) => void | Promise<void>;\n name?: string;\n};\n\n/** Framework-neutral bridge for TanStack Query, SWR, and similar caches. */\nexport function createKeepInvalidationPlugin<TMeta = Record<string, unknown>>(\n options: KeepInvalidationPluginOptions<TMeta>,\n): KeepPlugin<TMeta> {\n return {\n name: options.name ?? \"keepkit-cache-invalidation\",\n after: async (context) => {\n const keys = typeof options.queryKeys === \"function\" ? options.queryKeys(context) : [options.queryKeys];\n await Promise.all(keys.map((queryKey) => options.invalidate(queryKey, context)));\n },\n };\n}\n","import { type BrowserStorageAdapterOptions, createBrowserStorageAdapter } from \"../../../storage\";\nimport { SyncStorageAdapter, type SyncStorageAdapterOptions } from \"../../../storage/sync\";\nimport type {\n KeepItem,\n KeepSyncAuthError,\n KeepSyncAuthStatus,\n KeepSyncState,\n RemoteSyncDriver,\n RemoteSyncResult,\n StorageAdapter,\n SyncCapableStorageAdapter,\n SyncOperation,\n SyncScope,\n} from \"../../items/types\";\nimport { KeepSyncAuthError as KeepSyncAuthErrorClass } from \"../../items/types\";\nimport { exportItems } from \"../../persistence/backup\";\nimport {\n createScopedStorageAdapter,\n getKeepScopeKey,\n isSameKeepScope,\n ScopedSyncQueueAdapter,\n} from \"../../persistence/scope\";\n\nexport type AuthenticatedSyncRequestContext<TMeta = Record<string, unknown>> = {\n token: string | null;\n scope?: SyncScope;\n operation?: SyncOperation<TMeta>;\n};\n\n/** Transport boundary for auth-aware requests; cookies and bearer tokens remain host concerns. */\nexport type AuthenticatedSyncTransport<TMeta = Record<string, unknown>> = {\n push: (\n operation: SyncOperation<TMeta>,\n context: AuthenticatedSyncRequestContext<TMeta>,\n ) => Promise<RemoteSyncResult<TMeta>>;\n pull?: (context: AuthenticatedSyncRequestContext<TMeta>) => Promise<KeepItem<TMeta>[]>;\n};\n\nexport type AuthenticatedSyncAuthContext<TMeta = Record<string, unknown>> = {\n operation?: SyncOperation<TMeta>;\n scope?: SyncScope;\n};\n\nexport type AuthenticatedSyncKitOptions<TMeta = Record<string, unknown>> = Omit<\n SyncStorageAdapterOptions<TMeta>,\n \"local\" | \"remote\" | \"scope\"\n> & {\n /** Optional custom local adapter. Browser storage is used when omitted. */\n local?: StorageAdapter<TMeta>;\n key?: BrowserStorageAdapterOptions[\"key\"];\n databaseName?: BrowserStorageAdapterOptions[\"databaseName\"];\n scope?: SyncScope;\n /** Resolve the active account or tenant before storage operations. */\n getScope?: () => SyncScope | undefined | Promise<SyncScope | undefined>;\n getAuthToken: () => Promise<string | null>;\n transport: AuthenticatedSyncTransport<TMeta>;\n onAuthError?: (error: KeepSyncAuthError<TMeta>, context: AuthenticatedSyncAuthContext<TMeta>) => void | Promise<void>;\n onReauthenticate?: (\n error: KeepSyncAuthError<TMeta>,\n context: AuthenticatedSyncAuthContext<TMeta>,\n ) => void | Promise<void>;\n onScopeChange?: (next: SyncScope | undefined, previous: SyncScope | undefined) => void | Promise<void>;\n};\n\nexport type AuthenticatedSyncKit<TMeta = Record<string, unknown>> = {\n readonly mode: \"sync\";\n readonly storage: SyncCapableStorageAdapter<TMeta>;\n readonly scope?: SyncScope;\n readonly scopeKey: string;\n getScope(): SyncScope | undefined;\n setScope(scope?: SyncScope): Promise<void>;\n subscribeScope(listener: () => void): () => void;\n exportBackup(): Promise<string>;\n dispose(): void;\n};\n\n/** Creates auth-independent sync wiring with per-request tokens and isolated account scopes. */\nexport function createAuthenticatedSyncKit<TMeta = Record<string, unknown>>(\n options: AuthenticatedSyncKitOptions<TMeta>,\n): AuthenticatedSyncKit<TMeta> {\n const controller = new AuthenticatedSyncStorageController(options);\n return {\n mode: \"sync\",\n storage: controller,\n get scope() {\n return controller.scope;\n },\n get scopeKey() {\n return controller.scopeKey;\n },\n getScope: () => controller.scope,\n setScope: (scope) => controller.setScope(scope),\n subscribeScope: (listener) => controller.subscribeScope(listener),\n exportBackup: () => controller.exportBackup(),\n dispose: () => controller.dispose(),\n };\n}\n\nclass AuthenticatedSyncStorageController<TMeta = Record<string, unknown>> implements SyncCapableStorageAdapter<TMeta> {\n private readonly options: AuthenticatedSyncKitOptions<TMeta>;\n private currentScope: SyncScope | undefined;\n private current: SyncStorageAdapter<TMeta>;\n private readonly scopeListeners = new Set<() => void>();\n private readonly dataListeners = new Set<() => void>();\n private readonly syncListeners = new Set<() => void>();\n private unsubscribeData: () => void = () => undefined;\n private unsubscribeSync: () => void = () => undefined;\n private transition = Promise.resolve();\n private disposed = false;\n\n constructor(options: AuthenticatedSyncKitOptions<TMeta>) {\n this.options = options;\n this.currentScope = options.scope;\n this.current = this.createAdapter(this.currentScope);\n this.attach(this.current);\n }\n\n get storageKey(): string | undefined {\n return this.current.storageKey;\n }\n\n get scope(): SyncScope | undefined {\n return this.currentScope;\n }\n\n get scopeKey(): string {\n return getKeepScopeKey(this.currentScope);\n }\n\n async getAll(): Promise<KeepItem<TMeta>[]> {\n await this.ensureScope();\n return this.current.getAll();\n }\n\n async set(item: KeepItem<TMeta>): Promise<void> {\n await this.ensureScope();\n return this.current.set(item);\n }\n\n async setMany(items: KeepItem<TMeta>[]): Promise<void> {\n await this.ensureScope();\n return this.current.setMany(items);\n }\n\n async remove(id: string): Promise<void> {\n await this.ensureScope();\n return this.current.remove(id);\n }\n\n async removeMany(ids: string[]): Promise<void> {\n await this.ensureScope();\n return this.current.removeMany(ids);\n }\n\n async clear(): Promise<void> {\n await this.ensureScope();\n return this.current.clear();\n }\n\n async merge(items: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n await this.ensureScope();\n return this.current.merge(items);\n }\n\n subscribe(listener: () => void): () => void {\n this.dataListeners.add(listener);\n return () => this.dataListeners.delete(listener);\n }\n\n getSyncState(): KeepSyncState<TMeta> {\n return this.current.getSyncState();\n }\n\n subscribeSync(listener: () => void): () => void {\n this.syncListeners.add(listener);\n return () => this.syncListeners.delete(listener);\n }\n\n async flushSync(): Promise<void> {\n await this.ensureScope();\n return this.current.flushSync();\n }\n\n async retrySync(): Promise<void> {\n await this.ensureScope();\n return this.current.retrySync?.() ?? this.current.flushSync();\n }\n\n async resolveSyncConflict(\n id: string,\n resolution: \"local\" | \"remote\" | \"manual\",\n item?: KeepItem<TMeta>,\n ): Promise<void> {\n await this.ensureScope();\n if (!this.current.resolveSyncConflict) {\n throw new Error(\"The authenticated sync adapter does not support conflict resolution.\");\n }\n return this.current.resolveSyncConflict(id, resolution, item);\n }\n\n async setScope(nextScope?: SyncScope): Promise<void> {\n const run = this.transition.then(async () => {\n if (isSameKeepScope(this.currentScope, nextScope)) return;\n if (this.disposed) throw new Error(\"AuthenticatedSyncKit has been disposed.\");\n const previousScope = this.currentScope;\n this.unsubscribeData();\n this.unsubscribeSync();\n this.current.dispose?.();\n this.currentScope = nextScope;\n this.current = this.createAdapter(nextScope);\n this.attach(this.current);\n await this.options.onScopeChange?.(nextScope, previousScope);\n this.notify(this.scopeListeners);\n this.notify(this.dataListeners);\n this.notify(this.syncListeners);\n });\n this.transition = run.catch(() => undefined);\n return run;\n }\n\n subscribeScope(listener: () => void): () => void {\n this.scopeListeners.add(listener);\n return () => this.scopeListeners.delete(listener);\n }\n\n async exportBackup(): Promise<string> {\n await this.ensureScope();\n return exportItems(this.current);\n }\n\n dispose(): void {\n this.disposed = true;\n this.unsubscribeData();\n this.unsubscribeSync();\n this.current.dispose?.();\n this.scopeListeners.clear();\n this.dataListeners.clear();\n this.syncListeners.clear();\n }\n\n private createAdapter(scope: SyncScope | undefined): SyncStorageAdapter<TMeta> {\n const local = this.options.local\n ? scope\n ? createScopedStorageAdapter(this.options.local, scope)\n : this.options.local\n : createBrowserStorageAdapter<TMeta>({ key: this.options.key, databaseName: this.options.databaseName, scope });\n const queue =\n this.options.queue && scope ? new ScopedSyncQueueAdapter(this.options.queue, scope) : this.options.queue;\n const remote = createAuthenticatedRemote(this.options, scope);\n return new SyncStorageAdapter<TMeta>({\n ...this.options,\n local,\n remote,\n queue,\n scope,\n });\n }\n\n private attach(adapter: SyncStorageAdapter<TMeta>): void {\n this.unsubscribeData = adapter.subscribe?.(() => this.notify(this.dataListeners)) ?? (() => undefined);\n this.unsubscribeSync = adapter.subscribeSync(() => this.notify(this.syncListeners));\n }\n\n private async ensureScope(): Promise<void> {\n if (!this.options.getScope) return;\n await this.setScope(await this.options.getScope());\n }\n\n private notify(listeners: Set<() => void>): void {\n for (const listener of listeners) listener();\n }\n}\n\nfunction createAuthenticatedRemote<TMeta>(\n options: AuthenticatedSyncKitOptions<TMeta>,\n scope: SyncScope | undefined,\n): RemoteSyncDriver<TMeta> {\n const pull = options.transport.pull;\n return {\n push: async (operation) => {\n try {\n const token = await options.getAuthToken();\n return await options.transport.push(operation, { token, scope, operation });\n } catch (cause) {\n return handleAuthFailure(cause, options, { operation, scope });\n }\n },\n pull: pull\n ? async () => {\n try {\n const token = await options.getAuthToken();\n return await pull({ token, scope });\n } catch (cause) {\n return handleAuthFailure(cause, options, { scope });\n }\n }\n : undefined,\n };\n}\n\nasync function handleAuthFailure<TMeta>(\n cause: unknown,\n options: AuthenticatedSyncKitOptions<TMeta>,\n context: AuthenticatedSyncAuthContext<TMeta>,\n): Promise<never> {\n const status = getAuthStatus(cause);\n if (!status) throw cause;\n const error =\n cause instanceof KeepSyncAuthErrorClass\n ? cause\n : new KeepSyncAuthErrorClass(status, { operation: context.operation, scope: context.scope, cause });\n await options.onAuthError?.(error, context);\n await options.onReauthenticate?.(error, context);\n throw error;\n}\n\nfunction getAuthStatus(error: unknown): KeepSyncAuthStatus | undefined {\n if (error instanceof KeepSyncAuthErrorClass) return error.status;\n if (!error || typeof error !== \"object\") return undefined;\n const candidate = error as { status?: unknown; response?: { status?: unknown }; cause?: unknown };\n if (candidate.status === 401 || candidate.status === 403) return candidate.status;\n if (candidate.response?.status === 401 || candidate.response?.status === 403) return candidate.response.status;\n return candidate.cause ? getAuthStatus(candidate.cause) : undefined;\n}\n"],"mappings":"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","names":[]}