@keepkit/core 0.28.6 → 0.28.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/features/items/activity.ts","../src/features/items/collections.ts","../src/features/items/presets.ts","../src/features/items/progress.ts","../src/features/items/saved-views.ts","../src/features/items/url.ts","../src/features/sync/integrations.ts","../src/features/sync/templates/auth-sync.ts"],"sourcesContent":["export type KeepHistoryEntry = {\n itemId: string;\n lastViewedAt: number;\n context?: KeepHistoryContext;\n};\n\n/** Application-owned revisit details such as language or deck. */\nexport type KeepHistoryContext = Record<string, string>;\n\nexport type KeepViewingRecord = {\n id: string;\n itemId: string;\n viewedAt: number;\n /** Omitted on legacy records written before timestamp tracking was added. */\n createdAt?: number;\n /** Omitted on legacy records written before timestamp tracking was added. */\n updatedAt?: number;\n note?: string;\n};\n\nexport interface KeepHistoryStorage {\n getAll(): Promise<KeepHistoryEntry[]>;\n getLimit(): Promise<number>;\n setLimit(limit: number): Promise<void>;\n record(itemId: string, viewedAt?: number, context?: KeepHistoryContext): Promise<KeepHistoryEntry[]>;\n remove(itemId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport interface KeepViewingRecordStorage {\n getAll(itemId?: string): Promise<KeepViewingRecord[]>;\n set(record: KeepViewingRecord): Promise<void>;\n add(itemId: string, options?: { viewedAt?: number; note?: string }): Promise<KeepViewingRecord>;\n remove(id: string): Promise<void>;\n removeForItem(itemId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport type LocalStorageActivityOptions = {\n key?: string;\n storage?: Storage;\n maxEntries?: number;\n now?: () => number;\n createId?: () => string;\n};\n\nexport const DEFAULT_KEEP_HISTORY_KEY = \"keepkit:view-history\";\nexport const DEFAULT_KEEP_VIEWING_RECORDS_KEY = \"keepkit:viewing-records\";\nexport const DEFAULT_KEEP_HISTORY_LIMIT = 100;\n\n/** Local history of opened guides. It never reads or mutates saved items. */\nexport class LocalStorageKeepHistoryStorage implements KeepHistoryStorage {\n private readonly key: string;\n private readonly limitKey: string;\n private readonly storage: Storage | undefined;\n private readonly initialLimit: number;\n private readonly now: () => number;\n private writes: Promise<unknown> = Promise.resolve();\n\n constructor(options: LocalStorageActivityOptions = {}) {\n this.key = options.key ?? DEFAULT_KEEP_HISTORY_KEY;\n this.limitKey = `${this.key}:limit`;\n this.storage = options.storage ?? getBrowserStorage();\n this.initialLimit = normalizeLimit(options.maxEntries ?? DEFAULT_KEEP_HISTORY_LIMIT);\n this.now = options.now ?? Date.now;\n }\n\n async getAll(): Promise<KeepHistoryEntry[]> {\n return (await this.read<KeepHistoryEntry[]>(this.key, isHistoryEntryArray, \"history\")).sort(\n (left, right) => right.lastViewedAt - left.lastViewedAt,\n );\n }\n\n async getLimit(): Promise<number> {\n if (!this.storage) return this.initialLimit;\n const raw = this.readRaw(this.limitKey, \"history-limit\");\n if (raw === null) return this.initialLimit;\n const parsed: unknown = parseJson(raw, this.limitKey, \"history-limit\");\n if (typeof parsed !== \"number\" || !Number.isInteger(parsed) || parsed < 1) {\n throw new KeepActivityStorageError(\"KeepKit history limit is invalid.\", this.limitKey);\n }\n return parsed;\n }\n\n async setLimit(limit: number): Promise<void> {\n const normalized = normalizeLimit(limit);\n await this.withWriteLock(async () => {\n this.writeRaw(this.limitKey, JSON.stringify(normalized), \"history-limit\");\n const entries = await this.getAll();\n await this.writeEntries(entries.slice(0, normalized));\n });\n }\n\n async record(itemId: string, viewedAt = this.now(), context?: KeepHistoryContext): Promise<KeepHistoryEntry[]> {\n const normalizedId = normalizeId(itemId);\n assertTimestamp(viewedAt);\n return this.withWriteLock(async () => {\n const entries = await this.getAll();\n const previous = entries.find((entry) => entry.itemId === normalizedId);\n const isNewer = viewedAt >= (previous?.lastViewedAt ?? -1);\n const nextContext = isNewer ? normalizeHistoryContext(context) : previous?.context;\n const next = [\n {\n itemId: normalizedId,\n lastViewedAt: Math.max(previous?.lastViewedAt ?? 0, viewedAt),\n ...(nextContext ? { context: nextContext } : {}),\n },\n ...entries.filter((entry) => entry.itemId !== normalizedId),\n ]\n .sort((left, right) => right.lastViewedAt - left.lastViewedAt)\n .slice(0, await this.getLimit());\n await this.writeEntries(next);\n return cloneHistoryEntries(next);\n });\n }\n\n async remove(itemId: string): Promise<void> {\n const normalizedId = normalizeId(itemId);\n await this.withWriteLock(async () =>\n this.writeEntries((await this.getAll()).filter((entry) => entry.itemId !== normalizedId)),\n );\n }\n\n async clear(): Promise<void> {\n await this.withWriteLock(async () => this.writeRaw(this.key, \"[]\", \"history\"));\n }\n\n private async writeEntries(entries: KeepHistoryEntry[]): Promise<void> {\n this.writeRaw(this.key, JSON.stringify(entries), \"history\");\n }\n\n private withWriteLock<T>(operation: () => Promise<T>): Promise<T> {\n const next = this.writes.then(operation);\n this.writes = next.catch(() => undefined);\n return next;\n }\n\n private async read<T>(key: string, validate: (value: unknown) => value is T, label: string): Promise<T> {\n const raw = this.readRaw(key, label);\n if (raw === null) return [] as T;\n const value = parseJson(raw, key, label);\n if (!validate(value)) throw new KeepActivityStorageError(`KeepKit ${label} data is invalid.`, key);\n return value;\n }\n\n private readRaw(key: string, label: string): string | null {\n try {\n return this.storage?.getItem(key) ?? null;\n } catch (cause) {\n throw new KeepActivityStorageError(`KeepKit could not read ${label} data.`, key, cause);\n }\n }\n\n private writeRaw(key: string, value: string, label: string): void {\n if (!this.storage)\n throw new KeepActivityStorageError(`KeepKit cannot persist ${label} data without browser storage.`, key);\n try {\n this.storage.setItem(key, value);\n } catch (cause) {\n throw new KeepActivityStorageError(`KeepKit could not write ${label} data.`, key, cause);\n }\n }\n}\n\n/** Explicit user-reported viewing events, kept separate from open history and saved items. */\nexport class LocalStorageKeepViewingRecordStorage implements KeepViewingRecordStorage {\n private readonly key: string;\n private readonly storage: Storage | undefined;\n private readonly now: () => number;\n private readonly createId: () => string;\n private writes: Promise<unknown> = Promise.resolve();\n\n constructor(options: LocalStorageActivityOptions = {}) {\n this.key = options.key ?? DEFAULT_KEEP_VIEWING_RECORDS_KEY;\n this.storage = options.storage ?? getBrowserStorage();\n this.now = options.now ?? Date.now;\n this.createId = options.createId ?? createRecordId;\n }\n\n async getAll(itemId?: string): Promise<KeepViewingRecord[]> {\n const records = await this.readRecords();\n const filtered = itemId === undefined ? records : records.filter((record) => record.itemId === itemId);\n return filtered.sort((left, right) => right.viewedAt - left.viewedAt).map((record) => ({ ...record }));\n }\n\n async set(record: KeepViewingRecord): Promise<void> {\n await this.saveRecord(record);\n }\n\n async add(itemId: string, options: { viewedAt?: number; note?: string } = {}): Promise<KeepViewingRecord> {\n const timestamp = this.now();\n const record: KeepViewingRecord = {\n id: this.createId(),\n itemId: normalizeId(itemId),\n viewedAt: options.viewedAt ?? timestamp,\n createdAt: timestamp,\n updatedAt: timestamp,\n ...(options.note?.trim() ? { note: options.note.trim() } : {}),\n };\n return this.saveRecord(record);\n }\n\n private async saveRecord(record: KeepViewingRecord): Promise<KeepViewingRecord> {\n const normalized = normalizeViewingRecord(record);\n return this.withWriteLock(async () => {\n const records = await this.readRecords();\n const previous = records.find((entry) => entry.id === normalized.id);\n const now = this.now();\n const next = {\n ...normalized,\n createdAt: previous?.createdAt ?? normalized.createdAt ?? now,\n updatedAt: now,\n };\n this.writeRecords([...records.filter((entry) => entry.id !== normalized.id), next]);\n return { ...next };\n });\n }\n\n async remove(id: string): Promise<void> {\n await this.withWriteLock(async () =>\n this.writeRecords((await this.readRecords()).filter((record) => record.id !== id)),\n );\n }\n\n async removeForItem(itemId: string): Promise<void> {\n const normalizedId = normalizeId(itemId);\n await this.withWriteLock(async () =>\n this.writeRecords((await this.readRecords()).filter((record) => record.itemId !== normalizedId)),\n );\n }\n\n async clear(): Promise<void> {\n await this.withWriteLock(async () => this.writeRecords([]));\n }\n\n private async readRecords(): Promise<KeepViewingRecord[]> {\n const raw = this.readRaw();\n if (raw === null) return [];\n const value = parseJson(raw, this.key, \"viewing records\");\n if (!isViewingRecordArray(value)) {\n throw new KeepActivityStorageError(\"KeepKit viewing record data is invalid.\", this.key);\n }\n return value;\n }\n\n private readRaw(): string | null {\n try {\n return this.storage?.getItem(this.key) ?? null;\n } catch (cause) {\n throw new KeepActivityStorageError(\"KeepKit could not read viewing records.\", this.key, cause);\n }\n }\n\n private writeRecords(records: KeepViewingRecord[]): void {\n if (!this.storage) {\n throw new KeepActivityStorageError(\"KeepKit cannot persist viewing records without browser storage.\", this.key);\n }\n try {\n this.storage.setItem(this.key, JSON.stringify(records));\n } catch (cause) {\n throw new KeepActivityStorageError(\"KeepKit could not write viewing records.\", this.key, cause);\n }\n }\n\n private withWriteLock<T>(operation: () => Promise<T>): Promise<T> {\n const next = this.writes.then(operation);\n this.writes = next.catch(() => undefined);\n return next;\n }\n}\n\nexport class KeepActivityStorageError extends Error {\n readonly storageKey: string;\n readonly cause?: unknown;\n\n constructor(message: string, storageKey: string, cause?: unknown) {\n super(message);\n this.name = \"KeepActivityStorageError\";\n this.storageKey = storageKey;\n this.cause = cause;\n }\n}\n\nfunction isHistoryEntryArray(value: unknown): value is KeepHistoryEntry[] {\n return (\n Array.isArray(value) &&\n value.every(\n (entry) =>\n isRecord(entry) &&\n typeof entry.itemId === \"string\" &&\n entry.itemId.length > 0 &&\n typeof entry.lastViewedAt === \"number\" &&\n Number.isFinite(entry.lastViewedAt) &&\n (entry.context === undefined || isHistoryContext(entry.context)),\n )\n );\n}\n\nfunction isViewingRecordArray(value: unknown): value is KeepViewingRecord[] {\n return Array.isArray(value) && value.every(isViewingRecord);\n}\n\nfunction isViewingRecord(value: unknown): value is KeepViewingRecord {\n return (\n isRecord(value) &&\n typeof value.id === \"string\" &&\n value.id.length > 0 &&\n typeof value.itemId === \"string\" &&\n value.itemId.length > 0 &&\n typeof value.viewedAt === \"number\" &&\n Number.isFinite(value.viewedAt) &&\n value.viewedAt >= 0 &&\n (value.createdAt === undefined || (typeof value.createdAt === \"number\" && Number.isFinite(value.createdAt))) &&\n (value.updatedAt === undefined || (typeof value.updatedAt === \"number\" && Number.isFinite(value.updatedAt))) &&\n (value.note === undefined || typeof value.note === \"string\")\n );\n}\n\nfunction normalizeViewingRecord(record: KeepViewingRecord): KeepViewingRecord {\n const normalized: KeepViewingRecord = {\n id: normalizeId(record.id),\n itemId: normalizeId(record.itemId),\n viewedAt: record.viewedAt,\n ...(record.createdAt !== undefined ? { createdAt: record.createdAt } : {}),\n ...(record.updatedAt !== undefined ? { updatedAt: record.updatedAt } : {}),\n ...(record.note?.trim() ? { note: record.note.trim() } : {}),\n };\n assertTimestamp(normalized.viewedAt);\n return normalized;\n}\n\nfunction normalizeId(value: string): string {\n const normalized = value.trim();\n if (!normalized) throw new TypeError(\"KeepKit item ids must not be empty.\");\n return normalized;\n}\n\nfunction normalizeLimit(value: number): number {\n if (!Number.isInteger(value) || value < 1) throw new RangeError(\"KeepKit history limit must be a positive integer.\");\n return value;\n}\n\nfunction assertTimestamp(value: number): void {\n if (!Number.isFinite(value) || value < 0) throw new TypeError(\"KeepKit timestamps must be non-negative numbers.\");\n}\n\nfunction cloneHistoryEntries(entries: KeepHistoryEntry[]): KeepHistoryEntry[] {\n return entries.map((entry) => ({ ...entry, ...(entry.context ? { context: { ...entry.context } } : {}) }));\n}\n\nfunction normalizeHistoryContext(context?: KeepHistoryContext): KeepHistoryContext | undefined {\n if (!context) return undefined;\n const entries = Object.entries(context).filter(([key, value]) => key.trim() && typeof value === \"string\");\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nfunction isHistoryContext(value: unknown): value is KeepHistoryContext {\n return isRecord(value) && Object.values(value).every((entry) => typeof entry === \"string\");\n}\n\nfunction parseJson(raw: string, key: string, label: string): unknown {\n try {\n return JSON.parse(raw) as unknown;\n } catch (cause) {\n throw new KeepActivityStorageError(`KeepKit ${label} data is not valid JSON.`, key, cause);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\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 createRecordId(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) return crypto.randomUUID();\n return `keepkit-view-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n","import type { KeepCollectionMembership, KeepItem, StorageAdapter } from \"./types\";\n\nexport async function getKeepCollectionItems<TMeta>(\n storage: StorageAdapter<TMeta>,\n collectionId: string,\n): Promise<KeepItem<TMeta>[]> {\n const memberships = await requireMemberships(storage);\n const items = await storage.getAll();\n const itemsById = new Map(items.map((item) => [item.id, item]));\n return memberships\n .filter((membership) => membership.collectionId === collectionId)\n .sort((left, right) => left.order - right.order)\n .flatMap((membership) => {\n const item = itemsById.get(membership.itemId);\n return item ? [item] : [];\n });\n}\n\nexport async function addKeepItemToCollection<TMeta>(\n storage: StorageAdapter<TMeta>,\n collectionId: string,\n itemId: string,\n order?: number,\n): Promise<KeepCollectionMembership> {\n if (!(await storage.getAll()).some((item) => item.id === itemId)) {\n throw new Error(`KeepKit cannot add missing item \"${itemId}\" to a collection.`);\n }\n const collectionMemberships = (await requireMemberships(storage))\n .filter((membership) => membership.collectionId === collectionId)\n .filter((membership) => membership.itemId !== itemId)\n .sort((left, right) => left.order - right.order);\n const insertionIndex = order ?? collectionMemberships.length;\n if (!Number.isInteger(insertionIndex) || insertionIndex < 0) {\n throw new RangeError(\"Collection order must be a non-negative integer.\");\n }\n collectionMemberships.splice(Math.min(insertionIndex, collectionMemberships.length), 0, {\n collectionId,\n itemId,\n order: insertionIndex,\n });\n const reordered = collectionMemberships.map((membership, index) => ({ ...membership, order: index }));\n for (const membership of reordered) await storage.setCollectionMembership?.(membership);\n const added = reordered.find((membership) => membership.itemId === itemId);\n if (!added) throw new Error(\"KeepKit failed to add the collection membership.\");\n return added;\n}\n\nexport async function removeKeepItemFromCollection<TMeta>(\n storage: StorageAdapter<TMeta>,\n collectionId: string,\n itemId: string,\n): Promise<void> {\n const memberships = await requireMemberships(storage);\n await storage.removeCollectionMembership?.(collectionId, itemId);\n const remaining = memberships\n .filter((membership) => membership.collectionId === collectionId && membership.itemId !== itemId)\n .sort((left, right) => left.order - right.order)\n .map((membership, order) => ({ ...membership, order }));\n for (const membership of remaining) await storage.setCollectionMembership?.(membership);\n}\n\n/** Reorders only the requested collection and leaves other course membership orders untouched. */\nexport async function reorderKeepCollectionItems<TMeta>(\n storage: StorageAdapter<TMeta>,\n collectionId: string,\n itemIds: string[],\n): Promise<KeepCollectionMembership[]> {\n const allMemberships = await requireMemberships(storage);\n const current = allMemberships\n .filter((membership) => membership.collectionId === collectionId)\n .sort((left, right) => left.order - right.order);\n const currentIds = new Set(current.map((membership) => membership.itemId));\n const orderedIds = [...itemIds.filter((id, index) => currentIds.has(id) && itemIds.indexOf(id) === index)];\n for (const membership of current) {\n if (!orderedIds.includes(membership.itemId)) orderedIds.push(membership.itemId);\n }\n const currentByItemId = new Map(current.map((membership) => [membership.itemId, membership]));\n const reordered = orderedIds.map((itemId, order) => ({\n ...(currentByItemId.get(itemId) ?? {}),\n collectionId,\n itemId,\n order,\n }));\n for (const membership of reordered) await storage.setCollectionMembership?.(membership);\n return reordered;\n}\n\nasync function requireMemberships<TMeta>(storage: StorageAdapter<TMeta>): Promise<KeepCollectionMembership[]> {\n if (!storage.getCollectionMemberships || !storage.setCollectionMembership || !storage.removeCollectionMembership) {\n throw new Error(\"KeepKit storage adapter does not support collection memberships.\");\n }\n return storage.getCollectionMemberships();\n}\n","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","export type KeepCourseProgress = {\n kind: \"course\";\n courseId: string;\n currentItemId?: string;\n updatedAt: number;\n};\n\nexport type KeepItemProgress = {\n kind: \"item\";\n itemId: string;\n audioPositionMs?: number;\n /** App-defined heading ID or legacy numeric offset. */\n readingPosition?: number | string;\n audioId?: string;\n language?: string;\n contentVersion?: string;\n updatedAt: number;\n};\n\nexport type KeepProgressRecord = KeepCourseProgress | KeepItemProgress;\n\nexport type KeepProgressCompatibility = {\n language?: string;\n contentVersion?: string;\n audioId?: string;\n};\n\nexport interface KeepProgressStorage {\n getAll(): Promise<KeepProgressRecord[]>;\n getCourse(courseId: string): Promise<KeepCourseProgress | undefined>;\n getItem(itemId: string, compatibility?: KeepProgressCompatibility): Promise<KeepItemProgress | undefined>;\n saveCourse(courseId: string, currentItemId?: string): Promise<KeepCourseProgress>;\n saveItem(\n itemId: string,\n progress: Omit<KeepItemProgress, \"kind\" | \"itemId\" | \"updatedAt\">,\n ): Promise<KeepItemProgress>;\n set(record: KeepProgressRecord): Promise<void>;\n resetCourse(courseId: string): Promise<void>;\n resetItem(itemId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport type LocalStorageProgressOptions = {\n key?: string;\n storage?: Storage;\n now?: () => number;\n};\n\nexport const DEFAULT_KEEP_PROGRESS_KEY = \"keepkit:progress\";\n\n/** Stores course and reader progress independently of saved items and open history. */\nexport class LocalStorageKeepProgressStorage implements KeepProgressStorage {\n private readonly key: string;\n private readonly storage: Storage | undefined;\n private readonly now: () => number;\n private writes: Promise<unknown> = Promise.resolve();\n\n constructor(options: LocalStorageProgressOptions = {}) {\n this.key = options.key ?? DEFAULT_KEEP_PROGRESS_KEY;\n this.storage = options.storage ?? getBrowserStorage();\n this.now = options.now ?? Date.now;\n }\n\n async getAll(): Promise<KeepProgressRecord[]> {\n const raw = this.readRaw();\n if (raw === null) return [];\n let value: unknown;\n try {\n value = JSON.parse(raw) as unknown;\n } catch (cause) {\n throw new KeepProgressStorageError(\"KeepKit progress data is not valid JSON.\", this.key, cause);\n }\n if (!Array.isArray(value) || !value.every(isProgressRecord)) {\n throw new KeepProgressStorageError(\"KeepKit progress data is invalid.\", this.key);\n }\n return value.map((record) => ({ ...record }));\n }\n\n async getCourse(courseId: string): Promise<KeepCourseProgress | undefined> {\n const id = normalizeId(courseId, \"course\");\n const record = (await this.getAll()).find((entry) => entry.kind === \"course\" && entry.courseId === id);\n return record?.kind === \"course\" ? record : undefined;\n }\n\n async getItem(itemId: string, compatibility?: KeepProgressCompatibility): Promise<KeepItemProgress | undefined> {\n const id = normalizeId(itemId, \"item\");\n const record = (await this.getAll()).find((entry) => entry.kind === \"item\" && entry.itemId === id);\n if (record?.kind !== \"item\") return undefined;\n if (!isProgressCompatible(record, compatibility)) return undefined;\n return record;\n }\n\n async saveCourse(courseId: string, currentItemId?: string): Promise<KeepCourseProgress> {\n const record: KeepCourseProgress = {\n kind: \"course\",\n courseId: normalizeId(courseId, \"course\"),\n ...(currentItemId?.trim() ? { currentItemId: currentItemId.trim() } : {}),\n updatedAt: this.now(),\n };\n await this.set(record);\n return record;\n }\n\n async saveItem(\n itemId: string,\n progress: Omit<KeepItemProgress, \"kind\" | \"itemId\" | \"updatedAt\">,\n ): Promise<KeepItemProgress> {\n const record: KeepItemProgress = {\n kind: \"item\",\n itemId: normalizeId(itemId, \"item\"),\n ...progress,\n ...(progress.audioId?.trim() ? { audioId: progress.audioId.trim() } : {}),\n updatedAt: this.now(),\n };\n await this.set(record);\n return record;\n }\n\n async set(record: KeepProgressRecord): Promise<void> {\n await this.withWriteLock(async () => {\n const normalized = normalizeProgressRecord(record);\n const records = await this.getAll();\n const identity = getProgressIdentity(normalized);\n this.writeRecords([...records.filter((entry) => getProgressIdentity(entry) !== identity), normalized]);\n });\n }\n\n async resetCourse(courseId: string): Promise<void> {\n const id = normalizeId(courseId, \"course\");\n await this.withWriteLock(async () =>\n this.writeRecords((await this.getAll()).filter((entry) => entry.kind !== \"course\" || entry.courseId !== id)),\n );\n }\n\n async resetItem(itemId: string): Promise<void> {\n const id = normalizeId(itemId, \"item\");\n await this.withWriteLock(async () =>\n this.writeRecords((await this.getAll()).filter((entry) => entry.kind !== \"item\" || entry.itemId !== id)),\n );\n }\n\n async clear(): Promise<void> {\n await this.withWriteLock(async () => this.writeRecords([]));\n }\n\n private readRaw(): string | null {\n try {\n return this.storage?.getItem(this.key) ?? null;\n } catch (cause) {\n throw new KeepProgressStorageError(\"KeepKit could not read progress data.\", this.key, cause);\n }\n }\n\n private writeRecords(records: KeepProgressRecord[]): void {\n if (!this.storage) {\n throw new KeepProgressStorageError(\"KeepKit cannot persist progress without browser storage.\", this.key);\n }\n try {\n this.storage.setItem(this.key, JSON.stringify(records));\n } catch (cause) {\n throw new KeepProgressStorageError(\"KeepKit could not write progress data.\", this.key, cause);\n }\n }\n\n private withWriteLock<T>(operation: () => Promise<T>): Promise<T> {\n const next = this.writes.then(operation);\n this.writes = next.catch(() => undefined);\n return next;\n }\n}\n\n/** Reject stale reader offsets when the selected language or content revision changed. */\nexport function isProgressCompatible(record: KeepItemProgress, compatibility?: KeepProgressCompatibility): boolean {\n if (record.language !== undefined && record.language !== compatibility?.language) return false;\n if (record.contentVersion !== undefined && record.contentVersion !== compatibility?.contentVersion) return false;\n if (compatibility?.language !== undefined && record.language !== compatibility.language) return false;\n if (compatibility?.contentVersion !== undefined && record.contentVersion !== compatibility.contentVersion)\n return false;\n if (record.audioId !== undefined && record.audioId !== compatibility?.audioId) return false;\n if (compatibility?.audioId !== undefined && record.audioId !== compatibility.audioId) return false;\n return true;\n}\n\nexport class KeepProgressStorageError extends Error {\n readonly storageKey: string;\n readonly cause?: unknown;\n\n constructor(message: string, storageKey: string, cause?: unknown) {\n super(message);\n this.name = \"KeepProgressStorageError\";\n this.storageKey = storageKey;\n this.cause = cause;\n }\n}\n\nfunction isProgressRecord(value: unknown): value is KeepProgressRecord {\n if (\n !isRecord(value) ||\n typeof value.updatedAt !== \"number\" ||\n !Number.isFinite(value.updatedAt) ||\n value.updatedAt < 0\n )\n return false;\n if (value.kind === \"course\") {\n return (\n typeof value.courseId === \"string\" &&\n value.courseId.length > 0 &&\n (value.currentItemId === undefined || typeof value.currentItemId === \"string\")\n );\n }\n if (value.kind !== \"item\") return false;\n return (\n typeof value.itemId === \"string\" &&\n value.itemId.length > 0 &&\n (value.audioPositionMs === undefined ||\n (typeof value.audioPositionMs === \"number\" &&\n Number.isFinite(value.audioPositionMs) &&\n value.audioPositionMs >= 0)) &&\n (value.readingPosition === undefined ||\n (typeof value.readingPosition === \"number\" &&\n Number.isFinite(value.readingPosition) &&\n value.readingPosition >= 0) ||\n (typeof value.readingPosition === \"string\" && value.readingPosition.trim().length > 0)) &&\n (value.audioId === undefined || (typeof value.audioId === \"string\" && value.audioId.length > 0)) &&\n (value.language === undefined || typeof value.language === \"string\") &&\n (value.contentVersion === undefined || typeof value.contentVersion === \"string\")\n );\n}\n\nfunction normalizeProgressRecord(record: KeepProgressRecord): KeepProgressRecord {\n if (!isProgressRecord(record)) throw new TypeError(\"KeepKit progress record is invalid.\");\n if (record.kind === \"course\") {\n return {\n kind: \"course\",\n courseId: normalizeId(record.courseId, \"course\"),\n ...(record.currentItemId?.trim() ? { currentItemId: record.currentItemId.trim() } : {}),\n updatedAt: record.updatedAt,\n };\n }\n return {\n kind: \"item\",\n itemId: normalizeId(record.itemId, \"item\"),\n ...(record.audioPositionMs !== undefined ? { audioPositionMs: record.audioPositionMs } : {}),\n ...(record.readingPosition !== undefined ? { readingPosition: record.readingPosition } : {}),\n ...(record.audioId !== undefined ? { audioId: record.audioId } : {}),\n ...(record.language !== undefined ? { language: record.language } : {}),\n ...(record.contentVersion !== undefined ? { contentVersion: record.contentVersion } : {}),\n updatedAt: record.updatedAt,\n };\n}\n\nfunction getProgressIdentity(record: KeepProgressRecord): string {\n return record.kind === \"course\" ? `course:${record.courseId}` : `item:${record.itemId}`;\n}\n\nfunction normalizeId(value: string, kind: string): string {\n const normalized = value.trim();\n if (!normalized) throw new TypeError(`KeepKit ${kind} ids must not be empty.`);\n return normalized;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\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","import type { KeepListQuery } from \"./query\";\n\nexport type KeepSavedView<TMeta = Record<string, unknown>> = {\n id: string;\n name: string;\n query: KeepListQuery<TMeta>;\n pinned?: boolean;\n createdAt: number;\n updatedAt: number;\n};\n\nexport interface KeepSavedViewStorage<TMeta = Record<string, unknown>> {\n getAll(): Promise<KeepSavedView<TMeta>[]>;\n get(id: string): Promise<KeepSavedView<TMeta> | undefined>;\n set(view: KeepSavedView<TMeta>): Promise<void>;\n remove(id: string): Promise<void>;\n}\n\nexport const DEFAULT_SAVED_VIEWS_STORAGE_KEY = \"keepkit:saved-views\";\n\n/** Local-first Saved View storage kept separate from item storage. */\nexport class LocalStorageKeepSavedViewStorage<TMeta = Record<string, unknown>> implements KeepSavedViewStorage<TMeta> {\n private readonly key: string;\n private readonly storage?: Storage;\n\n constructor(options: { key?: string; storage?: Storage } = {}) {\n this.key = options.key ?? DEFAULT_SAVED_VIEWS_STORAGE_KEY;\n this.storage = options.storage;\n }\n\n async getAll(): Promise<KeepSavedView<TMeta>[]> {\n const raw = this.getStorage().getItem(this.key);\n if (!raw) return [];\n const data: unknown = JSON.parse(raw);\n if (!Array.isArray(data) || !data.every(isSavedView)) throw new Error(\"KeepKit saved-view data is invalid.\");\n return data as KeepSavedView<TMeta>[];\n }\n\n async set(view: KeepSavedView<TMeta>): Promise<void> {\n const range = view.query.savedBetween;\n const normalized = {\n ...view,\n query: {\n ...view.query,\n ...(range\n ? {\n savedBetween: [\n range[0] instanceof Date ? range[0].getTime() : range[0],\n range[1] instanceof Date ? range[1].getTime() : range[1],\n ] as const,\n }\n : {}),\n },\n };\n if (!isSavedView(normalized)) throw new Error(\"KeepKit Saved View is invalid.\");\n const views = await this.getAll();\n const next = [...views.filter((current) => current.id !== normalized.id), normalized];\n this.getStorage().setItem(this.key, JSON.stringify(next));\n }\n\n async get(id: string): Promise<KeepSavedView<TMeta> | undefined> {\n return (await this.getAll()).find((view) => view.id === id);\n }\n\n async remove(id: string): Promise<void> {\n const views = await this.getAll();\n this.getStorage().setItem(this.key, JSON.stringify(views.filter((view) => view.id !== id)));\n }\n\n private getStorage(): Storage {\n if (this.storage) return this.storage;\n if (typeof localStorage === \"undefined\")\n throw new Error(\"KeepKit Saved Views require browser storage or an injected adapter.\");\n return localStorage;\n }\n}\n\nfunction isSavedView(value: unknown): value is KeepSavedView {\n if (typeof value !== \"object\" || value === null) return false;\n const view = value as Record<string, unknown>;\n return (\n typeof view.id === \"string\" &&\n view.id.length > 0 &&\n typeof view.name === \"string\" &&\n view.name.trim().length > 0 &&\n Number.isFinite(view.createdAt) &&\n Number.isFinite(view.updatedAt) &&\n isKeepListQuery(view.query) &&\n (view.pinned === undefined || typeof view.pinned === \"boolean\")\n );\n}\n\nfunction isKeepListQuery(value: unknown): boolean {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const query = value as Record<string, unknown>;\n if (query.filter !== undefined) return false;\n if (query.tags !== undefined && (!Array.isArray(query.tags) || !query.tags.every((tag) => typeof tag === \"string\"))) {\n return false;\n }\n if (query.collectionId !== undefined && typeof query.collectionId !== \"string\") return false;\n if (query.targetType !== undefined && typeof query.targetType !== \"string\") return false;\n if (query.archived !== undefined && typeof query.archived !== \"boolean\") return false;\n if (query.archiveScope !== undefined && ![\"active\", \"archived\", \"all\"].includes(String(query.archiveScope))) {\n return false;\n }\n if (query.pinnedFirst !== undefined && typeof query.pinnedFirst !== \"boolean\") return false;\n if (query.sort !== undefined) {\n if (!isRecord(query.sort) || ![\"savedAt\", \"updatedAt\", \"lastOpenedAt\"].includes(String(query.sort.by)))\n return false;\n if (query.sort.direction !== undefined && query.sort.direction !== \"asc\" && query.sort.direction !== \"desc\")\n return false;\n }\n if (query.search !== undefined) {\n if (!isRecord(query.search)) return false;\n if (query.search.query !== undefined && typeof query.search.query !== \"string\") return false;\n if (query.search.mode !== undefined && query.search.mode !== \"and\" && query.search.mode !== \"or\") return false;\n if (query.search.tokenize !== undefined && typeof query.search.tokenize !== \"boolean\") return false;\n if (\n query.search.fields !== undefined &&\n (!Array.isArray(query.search.fields) ||\n !query.search.fields.every((field) => field === \"note\" || field === \"meta\" || field === \"tags\"))\n ) {\n return false;\n }\n }\n if (query.activity !== undefined) {\n if (!isRecord(query.activity)) return false;\n if (query.activity.opened !== undefined && query.activity.opened !== \"ever\" && query.activity.opened !== \"never\") {\n return false;\n }\n if (\n [query.activity.lastOpenedBefore, query.activity.lastOpenedAfter, query.activity.inactiveForMs].some(\n isInvalidNumber,\n )\n ) {\n return false;\n }\n }\n if (\n query.savedBetween !== undefined &&\n (!Array.isArray(query.savedBetween) || query.savedBetween.length !== 2 || query.savedBetween.some(isInvalidNumber))\n ) {\n return false;\n }\n if (query.pagination !== undefined) {\n if (!isRecord(query.pagination) || [query.pagination.page, query.pagination.pageSize].some(isInvalidNumber))\n return false;\n }\n const organization = query.organization;\n if (organization !== undefined) {\n if (typeof organization !== \"object\" || organization === null || Array.isArray(organization)) return false;\n const fields = organization as Record<string, unknown>;\n if (\n [fields.collection, fields.tags, fields.note].some(\n (field) => field !== undefined && field !== \"assigned\" && field !== \"unassigned\",\n )\n ) {\n return false;\n }\n }\n return true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isInvalidNumber(value: unknown): boolean {\n return value !== undefined && (typeof value !== \"number\" || !Number.isFinite(value));\n}\n","import type { KeepListQuery } from \"./query\";\n\nexport type KeepUrlParamNames = {\n search: string;\n tags: string;\n sort: string;\n page: string;\n archived: string;\n archiveScope: string;\n collection: string;\n pinnedFirst: string;\n activityOpened?: string;\n lastOpenedBefore?: string;\n lastOpenedAfter?: string;\n inactiveForMs?: string;\n organizationCollection?: string;\n organizationTags?: string;\n organizationNote?: string;\n savedAfter?: string;\n savedBefore?: 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: Required<KeepUrlParamNames> = {\n search: \"q\",\n tags: \"tag\",\n sort: \"sort\",\n page: \"page\",\n archived: \"archived\",\n archiveScope: \"archiveScope\",\n collection: \"collection\",\n pinnedFirst: \"pinned\",\n activityOpened: \"opened\",\n lastOpenedBefore: \"openedBefore\",\n lastOpenedAfter: \"openedAfter\",\n inactiveForMs: \"inactiveFor\",\n organizationCollection: \"collectionState\",\n organizationTags: \"tagsState\",\n organizationNote: \"noteState\",\n savedAfter: \"savedAfter\",\n savedBefore: \"savedBefore\",\n};\n\nexport type KeepUrlState = Pick<\n KeepListQuery,\n | \"search\"\n | \"tags\"\n | \"sort\"\n | \"pagination\"\n | \"archived\"\n | \"archiveScope\"\n | \"collectionId\"\n | \"pinnedFirst\"\n | \"activity\"\n | \"organization\"\n | \"savedBetween\"\n>;\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: Required<KeepUrlParamNames> = { ...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 if (query.archiveScope !== undefined) result.set(params.archiveScope, query.archiveScope);\n else if (query.archived !== undefined) result.set(params.archived, query.archived ? \"true\" : \"false\");\n if (query.collectionId) result.set(params.collection, query.collectionId);\n for (const [key, value] of [\n [params.organizationCollection, query.organization?.collection],\n [params.organizationTags, query.organization?.tags],\n [params.organizationNote, query.organization?.note],\n ] as const) {\n if (value !== undefined) result.set(key, value);\n }\n if (query.pinnedFirst) result.set(params.pinnedFirst, \"true\");\n if (query.savedBetween) {\n const [from, to] = query.savedBetween.map((value) => (value instanceof Date ? value.getTime() : value));\n if (Number.isFinite(from) && Number.isFinite(to)) {\n result.set(params.savedAfter, String(from));\n result.set(params.savedBefore, String(to));\n }\n }\n if (query.activity?.opened) result.set(params.activityOpened, query.activity.opened);\n for (const [key, value] of [\n [params.lastOpenedBefore, query.activity?.lastOpenedBefore],\n [params.lastOpenedAfter, query.activity?.lastOpenedAfter],\n [params.inactiveForMs, query.activity?.inactiveForMs],\n ] as const) {\n if (value !== undefined && Number.isFinite(value)) result.set(key, String(value));\n }\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: Required<KeepUrlParamNames> = { ...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\" || sortValue?.[0] === \"lastOpenedAt\"\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 const archiveScopeValue = searchParams.get(params.archiveScope);\n const archiveScope =\n archiveScopeValue === \"active\" || archiveScopeValue === \"archived\" || archiveScopeValue === \"all\"\n ? archiveScopeValue\n : undefined;\n const archivedValue = searchParams.get(params.archived);\n const archived =\n archiveScope === \"archived\" || archivedValue === \"true\"\n ? true\n : archiveScope === \"active\" || archivedValue === \"false\"\n ? false\n : undefined;\n const collectionId = searchParams.get(params.collection)?.trim() || undefined;\n const organizationCollection = parseOrganizationState(searchParams.get(params.organizationCollection));\n const organizationTags = parseOrganizationState(searchParams.get(params.organizationTags));\n const organizationNote = parseOrganizationState(searchParams.get(params.organizationNote));\n const organization =\n organizationCollection || organizationTags || organizationNote\n ? {\n ...(organizationCollection ? { collection: organizationCollection } : {}),\n ...(organizationTags ? { tags: organizationTags } : {}),\n ...(organizationNote ? { note: organizationNote } : {}),\n }\n : undefined;\n const pinnedFirst = searchParams.get(params.pinnedFirst) === \"true\" ? true : undefined;\n const parseSavedDate = (name: string): number | undefined => {\n const rawValue = searchParams.get(name);\n if (rawValue === null || rawValue.trim() === \"\") return undefined;\n const value = Number(rawValue);\n return Number.isFinite(value) ? value : undefined;\n };\n const savedAfter = parseSavedDate(params.savedAfter);\n const savedBefore = parseSavedDate(params.savedBefore);\n const savedBetween =\n savedAfter === undefined || savedBefore === undefined ? undefined : ([savedAfter, savedBefore] as const);\n const activityOpenedValue = searchParams.get(params.activityOpened);\n const activityOpened: \"ever\" | \"never\" | undefined =\n activityOpenedValue === \"ever\" || activityOpenedValue === \"never\" ? activityOpenedValue : undefined;\n const parseActivityNumber = (name: string): number | undefined => {\n const rawValue = searchParams.get(name);\n if (rawValue === null || rawValue.trim() === \"\") return undefined;\n const value = Number(rawValue);\n return Number.isFinite(value) ? value : undefined;\n };\n const lastOpenedBefore = parseActivityNumber(params.lastOpenedBefore);\n const lastOpenedAfter = parseActivityNumber(params.lastOpenedAfter);\n const inactiveForMs = parseActivityNumber(params.inactiveForMs);\n const activity =\n activityOpened !== undefined ||\n lastOpenedBefore !== undefined ||\n lastOpenedAfter !== undefined ||\n inactiveForMs !== undefined\n ? {\n ...(activityOpened === undefined ? {} : { opened: activityOpened }),\n ...(lastOpenedBefore === undefined ? {} : { lastOpenedBefore }),\n ...(lastOpenedAfter === undefined ? {} : { lastOpenedAfter }),\n ...(inactiveForMs === undefined ? {} : { inactiveForMs }),\n }\n : undefined;\n return {\n ...(search ? { search: { query: search } } : {}),\n ...(tags.length > 0 ? { tags } : {}),\n ...(sort ? { sort } : {}),\n ...(page ? { pagination: { page } } : {}),\n ...(archived === undefined ? {} : { archived }),\n ...(archiveScope === undefined ? {} : { archiveScope }),\n ...(collectionId ? { collectionId } : {}),\n ...(organization ? { organization } : {}),\n ...(pinnedFirst ? { pinnedFirst } : {}),\n ...(savedBetween ? { savedBetween } : {}),\n ...(activity === undefined ? {} : { activity }),\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 archived: decoded.archived ?? query.archived,\n archiveScope: decoded.archiveScope ?? query.archiveScope,\n activity: decoded.activity ?? query.activity,\n organization: decoded.organization ?? query.organization,\n savedBetween: decoded.savedBetween ?? query.savedBetween,\n };\n}\n\nfunction parseOrganizationState(value: string | null): \"assigned\" | \"unassigned\" | undefined {\n return value === \"assigned\" || value === \"unassigned\" ? value : undefined;\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 KeepCollectionDefinition,\n KeepCollectionMembership,\n KeepCollectionSyncOperation,\n KeepItem,\n KeepMembershipSyncOperation,\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 collectionOperation?: KeepCollectionSyncOperation;\n membershipOperation?: KeepMembershipSyncOperation;\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 pushCollection?: (\n operation: KeepCollectionSyncOperation,\n context: AuthenticatedSyncRequestContext<TMeta>,\n ) => Promise<void>;\n pullCollections?: (context: AuthenticatedSyncRequestContext<TMeta>) => Promise<KeepCollectionDefinition[]>;\n pushMembership?: (\n operation: KeepMembershipSyncOperation,\n context: AuthenticatedSyncRequestContext<TMeta>,\n ) => Promise<void>;\n pullMemberships?: (context: AuthenticatedSyncRequestContext<TMeta>) => Promise<KeepCollectionMembership[]>;\n};\n\nexport type AuthenticatedSyncAuthContext<TMeta = Record<string, unknown>> = {\n operation?: SyncOperation<TMeta>;\n collectionOperation?: KeepCollectionSyncOperation;\n membershipOperation?: KeepMembershipSyncOperation;\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 readonly getCollections?: () => Promise<KeepCollectionDefinition[]>;\n readonly setCollection?: (collection: KeepCollectionDefinition) => Promise<void>;\n readonly removeCollection?: (id: string, scope?: SyncScope) => Promise<void>;\n readonly getCollectionMemberships?: () => Promise<KeepCollectionMembership[]>;\n readonly setCollectionMembership?: (membership: KeepCollectionMembership) => Promise<void>;\n readonly removeCollectionMembership?: (collectionId: string, itemId: string, scope?: SyncScope) => Promise<void>;\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 if (this.current.getCollections && this.current.setCollection && this.current.removeCollection) {\n this.getCollections = async () => {\n await this.ensureScope();\n return this.current.getCollections?.() ?? [];\n };\n this.setCollection = async (collection) => {\n await this.ensureScope();\n await this.current.setCollection?.(collection);\n };\n this.removeCollection = async (id) => {\n await this.ensureScope();\n await this.current.removeCollection?.(id);\n };\n }\n if (\n this.current.getCollectionMemberships &&\n this.current.setCollectionMembership &&\n this.current.removeCollectionMembership\n ) {\n this.getCollectionMemberships = async () => {\n await this.ensureScope();\n return this.current.getCollectionMemberships?.() ?? [];\n };\n this.setCollectionMembership = async (membership) => {\n await this.ensureScope();\n await this.current.setCollectionMembership?.(membership);\n };\n this.removeCollectionMembership = async (collectionId, itemId) => {\n await this.ensureScope();\n await this.current.removeCollectionMembership?.(collectionId, itemId);\n };\n }\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 const pullCollections = options.transport.pullCollections;\n const pullMemberships = options.transport.pullMemberships;\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 pushCollection: options.transport.pushCollection\n ? async (collectionOperation) => {\n try {\n const token = await options.getAuthToken();\n await options.transport.pushCollection?.(collectionOperation, { token, scope, collectionOperation });\n } catch (cause) {\n return handleAuthFailure(cause, options, { collectionOperation, scope });\n }\n }\n : undefined,\n pullCollections: pullCollections\n ? async () => {\n try {\n const token = await options.getAuthToken();\n return await pullCollections({ token, scope });\n } catch (cause) {\n return handleAuthFailure(cause, options, { scope });\n }\n }\n : undefined,\n pushMembership: options.transport.pushMembership\n ? async (membershipOperation) => {\n try {\n const token = await options.getAuthToken();\n await options.transport.pushMembership?.(membershipOperation, { token, scope, membershipOperation });\n } catch (cause) {\n return handleAuthFailure(cause, options, { membershipOperation, scope });\n }\n }\n : undefined,\n pullMemberships: pullMemberships\n ? async () => {\n try {\n const token = await options.getAuthToken();\n return await pullMemberships({ 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":["getBrowserStorage","normalizeId","isRecord","isRecord"]}
1
+ {"version":3,"sources":["../src/features/persistence/write-lock.ts","../src/features/items/activity.ts","../src/features/items/collections.ts","../src/features/items/presets.ts","../src/features/items/progress.ts","../src/features/items/saved-views.ts","../src/features/items/url.ts","../src/features/sync/integrations.ts","../src/features/sync/templates/auth-sync.ts"],"sourcesContent":["const writeQueues = new Map<string, Promise<unknown>>();\n\n/** Serialize same-key writes in one realm and, where available, across browser tabs. */\nexport function withLocalStorageWriteLock<T>(\n key: string,\n operation: () => Promise<T>,\n lockUnavailableError: Error,\n): Promise<T> {\n const lockName = `keepkit:local-storage:${key}`;\n if (typeof navigator !== \"undefined\" && navigator.locks) {\n return navigator.locks.request(lockName, operation);\n }\n if (typeof window !== \"undefined\") return Promise.reject(lockUnavailableError);\n\n const previous = writeQueues.get(lockName) ?? Promise.resolve();\n const next = previous.catch(() => undefined).then(operation);\n writeQueues.set(lockName, next);\n return next.finally(() => {\n if (writeQueues.get(lockName) === next) writeQueues.delete(lockName);\n });\n}\n","import { withLocalStorageWriteLock } from \"../persistence/write-lock\";\n\nexport type KeepHistoryEntry = {\n itemId: string;\n lastViewedAt: number;\n context?: KeepHistoryContext;\n};\n\n/** Application-owned revisit details such as language or deck. */\nexport type KeepHistoryContext = Record<string, string>;\n\nexport type KeepViewingRecord = {\n id: string;\n itemId: string;\n viewedAt: number;\n /** Omitted on legacy records written before timestamp tracking was added. */\n createdAt?: number;\n /** Omitted on legacy records written before timestamp tracking was added. */\n updatedAt?: number;\n note?: string;\n};\n\nexport interface KeepHistoryStorage {\n getAll(): Promise<KeepHistoryEntry[]>;\n getLimit(): Promise<number>;\n setLimit(limit: number): Promise<void>;\n record(itemId: string, viewedAt?: number, context?: KeepHistoryContext): Promise<KeepHistoryEntry[]>;\n remove(itemId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport interface KeepViewingRecordStorage {\n getAll(itemId?: string): Promise<KeepViewingRecord[]>;\n set(record: KeepViewingRecord): Promise<void>;\n add(itemId: string, options?: { viewedAt?: number; note?: string }): Promise<KeepViewingRecord>;\n remove(id: string): Promise<void>;\n removeForItem(itemId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport type LocalStorageActivityOptions = {\n key?: string;\n storage?: Storage;\n maxEntries?: number;\n now?: () => number;\n createId?: () => string;\n};\n\nexport const DEFAULT_KEEP_HISTORY_KEY = \"keepkit:view-history\";\nexport const DEFAULT_KEEP_VIEWING_RECORDS_KEY = \"keepkit:viewing-records\";\nexport const DEFAULT_KEEP_HISTORY_LIMIT = 100;\n\n/** Local history of opened guides. It never reads or mutates saved items. */\nexport class LocalStorageKeepHistoryStorage implements KeepHistoryStorage {\n private readonly key: string;\n private readonly limitKey: string;\n private readonly storage: Storage | undefined;\n private readonly initialLimit: number;\n private readonly now: () => number;\n\n constructor(options: LocalStorageActivityOptions = {}) {\n this.key = options.key ?? DEFAULT_KEEP_HISTORY_KEY;\n this.limitKey = `${this.key}:limit`;\n this.storage = options.storage ?? getBrowserStorage();\n this.initialLimit = normalizeLimit(options.maxEntries ?? DEFAULT_KEEP_HISTORY_LIMIT);\n this.now = options.now ?? Date.now;\n }\n\n async getAll(): Promise<KeepHistoryEntry[]> {\n return (await this.read<KeepHistoryEntry[]>(this.key, isHistoryEntryArray, \"history\")).sort(\n (left, right) => right.lastViewedAt - left.lastViewedAt,\n );\n }\n\n async getLimit(): Promise<number> {\n if (!this.storage) return this.initialLimit;\n const raw = this.readRaw(this.limitKey, \"history-limit\");\n if (raw === null) return this.initialLimit;\n const parsed: unknown = parseJson(raw, this.limitKey, \"history-limit\");\n if (typeof parsed !== \"number\" || !Number.isInteger(parsed) || parsed < 1) {\n throw new KeepActivityStorageError(\"KeepKit history limit is invalid.\", this.limitKey);\n }\n return parsed;\n }\n\n async setLimit(limit: number): Promise<void> {\n const normalized = normalizeLimit(limit);\n await this.withWriteLock(async () => {\n this.writeRaw(this.limitKey, JSON.stringify(normalized), \"history-limit\");\n const entries = await this.getAll();\n await this.writeEntries(entries.slice(0, normalized));\n });\n }\n\n async record(itemId: string, viewedAt = this.now(), context?: KeepHistoryContext): Promise<KeepHistoryEntry[]> {\n const normalizedId = normalizeId(itemId);\n assertTimestamp(viewedAt);\n return this.withWriteLock(async () => {\n const entries = await this.getAll();\n const previous = entries.find((entry) => entry.itemId === normalizedId);\n const isNewer = viewedAt >= (previous?.lastViewedAt ?? -1);\n const nextContext = isNewer ? normalizeHistoryContext(context) : previous?.context;\n const next = [\n {\n itemId: normalizedId,\n lastViewedAt: Math.max(previous?.lastViewedAt ?? 0, viewedAt),\n ...(nextContext ? { context: nextContext } : {}),\n },\n ...entries.filter((entry) => entry.itemId !== normalizedId),\n ]\n .sort((left, right) => right.lastViewedAt - left.lastViewedAt)\n .slice(0, await this.getLimit());\n await this.writeEntries(next);\n return cloneHistoryEntries(next);\n });\n }\n\n async remove(itemId: string): Promise<void> {\n const normalizedId = normalizeId(itemId);\n await this.withWriteLock(async () =>\n this.writeEntries((await this.getAll()).filter((entry) => entry.itemId !== normalizedId)),\n );\n }\n\n async clear(): Promise<void> {\n await this.withWriteLock(async () => this.writeRaw(this.key, \"[]\", \"history\"));\n }\n\n private async writeEntries(entries: KeepHistoryEntry[]): Promise<void> {\n this.writeRaw(this.key, JSON.stringify(entries), \"history\");\n }\n\n private withWriteLock<T>(operation: () => Promise<T>): Promise<T> {\n if (!this.storage) return operation();\n return withLocalStorageWriteLock(\n this.key,\n operation,\n new KeepActivityStorageError(\"KeepKit needs the Web Locks API to safely update history across tabs.\", this.key),\n );\n }\n\n private async read<T>(key: string, validate: (value: unknown) => value is T, label: string): Promise<T> {\n const raw = this.readRaw(key, label);\n if (raw === null) return [] as T;\n const value = parseJson(raw, key, label);\n if (!validate(value)) throw new KeepActivityStorageError(`KeepKit ${label} data is invalid.`, key);\n return value;\n }\n\n private readRaw(key: string, label: string): string | null {\n try {\n return this.storage?.getItem(key) ?? null;\n } catch (cause) {\n throw new KeepActivityStorageError(`KeepKit could not read ${label} data.`, key, cause);\n }\n }\n\n private writeRaw(key: string, value: string, label: string): void {\n if (!this.storage)\n throw new KeepActivityStorageError(`KeepKit cannot persist ${label} data without browser storage.`, key);\n try {\n this.storage.setItem(key, value);\n } catch (cause) {\n throw new KeepActivityStorageError(`KeepKit could not write ${label} data.`, key, cause);\n }\n }\n}\n\n/** Explicit user-reported viewing events, kept separate from open history and saved items. */\nexport class LocalStorageKeepViewingRecordStorage implements KeepViewingRecordStorage {\n private readonly key: string;\n private readonly storage: Storage | undefined;\n private readonly now: () => number;\n private readonly createId: () => string;\n\n constructor(options: LocalStorageActivityOptions = {}) {\n this.key = options.key ?? DEFAULT_KEEP_VIEWING_RECORDS_KEY;\n this.storage = options.storage ?? getBrowserStorage();\n this.now = options.now ?? Date.now;\n this.createId = options.createId ?? createRecordId;\n }\n\n async getAll(itemId?: string): Promise<KeepViewingRecord[]> {\n const records = await this.readRecords();\n const filtered = itemId === undefined ? records : records.filter((record) => record.itemId === itemId);\n return filtered.sort((left, right) => right.viewedAt - left.viewedAt).map((record) => ({ ...record }));\n }\n\n async set(record: KeepViewingRecord): Promise<void> {\n await this.saveRecord(record);\n }\n\n async add(itemId: string, options: { viewedAt?: number; note?: string } = {}): Promise<KeepViewingRecord> {\n const timestamp = this.now();\n const record: KeepViewingRecord = {\n id: this.createId(),\n itemId: normalizeId(itemId),\n viewedAt: options.viewedAt ?? timestamp,\n createdAt: timestamp,\n updatedAt: timestamp,\n ...(options.note?.trim() ? { note: options.note.trim() } : {}),\n };\n return this.saveRecord(record);\n }\n\n private async saveRecord(record: KeepViewingRecord): Promise<KeepViewingRecord> {\n const normalized = normalizeViewingRecord(record);\n return this.withWriteLock(async () => {\n const records = await this.readRecords();\n const previous = records.find((entry) => entry.id === normalized.id);\n if (\n previous?.updatedAt !== undefined &&\n normalized.updatedAt !== undefined &&\n previous.updatedAt > normalized.updatedAt\n ) {\n return { ...previous };\n }\n const now = this.now();\n const next = {\n ...normalized,\n createdAt: previous?.createdAt ?? normalized.createdAt ?? now,\n updatedAt: Math.max(now, (previous?.updatedAt ?? -1) + 1, normalized.updatedAt ?? -1),\n };\n this.writeRecords([...records.filter((entry) => entry.id !== normalized.id), next]);\n return { ...next };\n });\n }\n\n async remove(id: string): Promise<void> {\n await this.withWriteLock(async () =>\n this.writeRecords((await this.readRecords()).filter((record) => record.id !== id)),\n );\n }\n\n async removeForItem(itemId: string): Promise<void> {\n const normalizedId = normalizeId(itemId);\n await this.withWriteLock(async () =>\n this.writeRecords((await this.readRecords()).filter((record) => record.itemId !== normalizedId)),\n );\n }\n\n async clear(): Promise<void> {\n await this.withWriteLock(async () => this.writeRecords([]));\n }\n\n private async readRecords(): Promise<KeepViewingRecord[]> {\n const raw = this.readRaw();\n if (raw === null) return [];\n const value = parseJson(raw, this.key, \"viewing records\");\n if (!isViewingRecordArray(value)) {\n throw new KeepActivityStorageError(\"KeepKit viewing record data is invalid.\", this.key);\n }\n return value;\n }\n\n private readRaw(): string | null {\n try {\n return this.storage?.getItem(this.key) ?? null;\n } catch (cause) {\n throw new KeepActivityStorageError(\"KeepKit could not read viewing records.\", this.key, cause);\n }\n }\n\n private writeRecords(records: KeepViewingRecord[]): void {\n if (!this.storage) {\n throw new KeepActivityStorageError(\"KeepKit cannot persist viewing records without browser storage.\", this.key);\n }\n try {\n this.storage.setItem(this.key, JSON.stringify(records));\n } catch (cause) {\n throw new KeepActivityStorageError(\"KeepKit could not write viewing records.\", this.key, cause);\n }\n }\n\n private withWriteLock<T>(operation: () => Promise<T>): Promise<T> {\n if (!this.storage) return operation();\n return withLocalStorageWriteLock(\n this.key,\n operation,\n new KeepActivityStorageError(\n \"KeepKit needs the Web Locks API to safely update viewing records across tabs.\",\n this.key,\n ),\n );\n }\n}\n\nexport class KeepActivityStorageError extends Error {\n readonly storageKey: string;\n readonly cause?: unknown;\n\n constructor(message: string, storageKey: string, cause?: unknown) {\n super(message);\n this.name = \"KeepActivityStorageError\";\n this.storageKey = storageKey;\n this.cause = cause;\n }\n}\n\nfunction isHistoryEntryArray(value: unknown): value is KeepHistoryEntry[] {\n return (\n Array.isArray(value) &&\n value.every(\n (entry) =>\n isRecord(entry) &&\n typeof entry.itemId === \"string\" &&\n entry.itemId.length > 0 &&\n typeof entry.lastViewedAt === \"number\" &&\n Number.isFinite(entry.lastViewedAt) &&\n (entry.context === undefined || isHistoryContext(entry.context)),\n )\n );\n}\n\nfunction isViewingRecordArray(value: unknown): value is KeepViewingRecord[] {\n return Array.isArray(value) && value.every(isViewingRecord);\n}\n\nfunction isViewingRecord(value: unknown): value is KeepViewingRecord {\n return (\n isRecord(value) &&\n typeof value.id === \"string\" &&\n value.id.length > 0 &&\n typeof value.itemId === \"string\" &&\n value.itemId.length > 0 &&\n typeof value.viewedAt === \"number\" &&\n Number.isFinite(value.viewedAt) &&\n value.viewedAt >= 0 &&\n (value.createdAt === undefined || (typeof value.createdAt === \"number\" && Number.isFinite(value.createdAt))) &&\n (value.updatedAt === undefined || (typeof value.updatedAt === \"number\" && Number.isFinite(value.updatedAt))) &&\n (value.note === undefined || typeof value.note === \"string\")\n );\n}\n\nfunction normalizeViewingRecord(record: KeepViewingRecord): KeepViewingRecord {\n const normalized: KeepViewingRecord = {\n id: normalizeId(record.id),\n itemId: normalizeId(record.itemId),\n viewedAt: record.viewedAt,\n ...(record.createdAt !== undefined ? { createdAt: record.createdAt } : {}),\n ...(record.updatedAt !== undefined ? { updatedAt: record.updatedAt } : {}),\n ...(record.note?.trim() ? { note: record.note.trim() } : {}),\n };\n assertTimestamp(normalized.viewedAt);\n return normalized;\n}\n\nfunction normalizeId(value: string): string {\n const normalized = value.trim();\n if (!normalized) throw new TypeError(\"KeepKit item ids must not be empty.\");\n return normalized;\n}\n\nfunction normalizeLimit(value: number): number {\n if (!Number.isInteger(value) || value < 1) throw new RangeError(\"KeepKit history limit must be a positive integer.\");\n return value;\n}\n\nfunction assertTimestamp(value: number): void {\n if (!Number.isFinite(value) || value < 0) throw new TypeError(\"KeepKit timestamps must be non-negative numbers.\");\n}\n\nfunction cloneHistoryEntries(entries: KeepHistoryEntry[]): KeepHistoryEntry[] {\n return entries.map((entry) => ({ ...entry, ...(entry.context ? { context: { ...entry.context } } : {}) }));\n}\n\nfunction normalizeHistoryContext(context?: KeepHistoryContext): KeepHistoryContext | undefined {\n if (!context) return undefined;\n const entries = Object.entries(context).filter(([key, value]) => key.trim() && typeof value === \"string\");\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n}\n\nfunction isHistoryContext(value: unknown): value is KeepHistoryContext {\n return isRecord(value) && Object.values(value).every((entry) => typeof entry === \"string\");\n}\n\nfunction parseJson(raw: string, key: string, label: string): unknown {\n try {\n return JSON.parse(raw) as unknown;\n } catch (cause) {\n throw new KeepActivityStorageError(`KeepKit ${label} data is not valid JSON.`, key, cause);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\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 createRecordId(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) return crypto.randomUUID();\n return `keepkit-view-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n","import type { KeepCollectionMembership, KeepItem, StorageAdapter } from \"./types\";\n\nconst collectionMutationQueues = new WeakMap<object, Promise<unknown>>();\n\nexport async function getKeepCollectionItems<TMeta>(\n storage: StorageAdapter<TMeta>,\n collectionId: string,\n): Promise<KeepItem<TMeta>[]> {\n const memberships = await requireMemberships(storage);\n const items = await storage.getAll();\n const itemsById = new Map(items.map((item) => [item.id, item]));\n return memberships\n .filter((membership) => membership.collectionId === collectionId)\n .sort((left, right) => left.order - right.order)\n .flatMap((membership) => {\n const item = itemsById.get(membership.itemId);\n return item ? [item] : [];\n });\n}\n\nexport async function addKeepItemToCollection<TMeta>(\n storage: StorageAdapter<TMeta>,\n collectionId: string,\n itemId: string,\n order?: number,\n): Promise<KeepCollectionMembership> {\n return withCollectionMutationLock(storage, async () => {\n if (!(await storage.getAll()).some((item) => item.id === itemId)) {\n throw new Error(`KeepKit cannot add missing item \"${itemId}\" to a collection.`);\n }\n const collectionMemberships = (await requireMemberships(storage))\n .filter((membership) => membership.collectionId === collectionId)\n .filter((membership) => membership.itemId !== itemId)\n .sort((left, right) => left.order - right.order);\n const insertionIndex = order ?? collectionMemberships.length;\n if (!Number.isInteger(insertionIndex) || insertionIndex < 0) {\n throw new RangeError(\"Collection order must be a non-negative integer.\");\n }\n collectionMemberships.splice(Math.min(insertionIndex, collectionMemberships.length), 0, {\n collectionId,\n itemId,\n order: insertionIndex,\n });\n const reordered = collectionMemberships.map((membership, index) => ({ ...membership, order: index }));\n for (const membership of reordered) await storage.setCollectionMembership?.(membership);\n const added = reordered.find((membership) => membership.itemId === itemId);\n if (!added) throw new Error(\"KeepKit failed to add the collection membership.\");\n return added;\n });\n}\n\nexport async function removeKeepItemFromCollection<TMeta>(\n storage: StorageAdapter<TMeta>,\n collectionId: string,\n itemId: string,\n): Promise<void> {\n await withCollectionMutationLock(storage, async () => {\n const memberships = await requireMemberships(storage);\n await storage.removeCollectionMembership?.(collectionId, itemId);\n const remaining = memberships\n .filter((membership) => membership.collectionId === collectionId && membership.itemId !== itemId)\n .sort((left, right) => left.order - right.order)\n .map((membership, order) => ({ ...membership, order }));\n for (const membership of remaining) await storage.setCollectionMembership?.(membership);\n });\n}\n\n/** Reorders only the requested collection and leaves other course membership orders untouched. */\nexport async function reorderKeepCollectionItems<TMeta>(\n storage: StorageAdapter<TMeta>,\n collectionId: string,\n itemIds: string[],\n): Promise<KeepCollectionMembership[]> {\n return withCollectionMutationLock(storage, async () => {\n const allMemberships = await requireMemberships(storage);\n const current = allMemberships\n .filter((membership) => membership.collectionId === collectionId)\n .sort((left, right) => left.order - right.order);\n const currentIds = new Set(current.map((membership) => membership.itemId));\n const orderedIds = [...itemIds.filter((id, index) => currentIds.has(id) && itemIds.indexOf(id) === index)];\n for (const membership of current) {\n if (!orderedIds.includes(membership.itemId)) orderedIds.push(membership.itemId);\n }\n const currentByItemId = new Map(current.map((membership) => [membership.itemId, membership]));\n const reordered = orderedIds.map((itemId, order) => ({\n ...(currentByItemId.get(itemId) ?? {}),\n collectionId,\n itemId,\n order,\n }));\n for (const membership of reordered) await storage.setCollectionMembership?.(membership);\n return reordered;\n });\n}\n\nfunction withCollectionMutationLock<TMeta, TResult>(\n storage: StorageAdapter<TMeta>,\n operation: () => Promise<TResult>,\n): Promise<TResult> {\n const previous = collectionMutationQueues.get(storage) ?? Promise.resolve();\n const next = previous.catch(() => undefined).then(operation);\n collectionMutationQueues.set(storage, next);\n return next.finally(() => {\n if (collectionMutationQueues.get(storage) === next) collectionMutationQueues.delete(storage);\n });\n}\n\nasync function requireMemberships<TMeta>(storage: StorageAdapter<TMeta>): Promise<KeepCollectionMembership[]> {\n if (!storage.getCollectionMemberships || !storage.setCollectionMembership || !storage.removeCollectionMembership) {\n throw new Error(\"KeepKit storage adapter does not support collection memberships.\");\n }\n return storage.getCollectionMemberships();\n}\n","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 { withLocalStorageWriteLock } from \"../persistence/write-lock\";\n\nexport type KeepCourseProgress = {\n kind: \"course\";\n courseId: string;\n currentItemId?: string;\n updatedAt: number;\n};\n\nexport type KeepItemProgress = {\n kind: \"item\";\n itemId: string;\n audioPositionMs?: number;\n /** App-defined heading ID or legacy numeric offset. */\n readingPosition?: number | string;\n audioId?: string;\n language?: string;\n contentVersion?: string;\n updatedAt: number;\n};\n\nexport type KeepProgressRecord = KeepCourseProgress | KeepItemProgress;\n\nexport type KeepProgressCompatibility = {\n language?: string;\n contentVersion?: string;\n audioId?: string;\n};\n\nexport interface KeepProgressStorage {\n getAll(): Promise<KeepProgressRecord[]>;\n getCourse(courseId: string): Promise<KeepCourseProgress | undefined>;\n getItem(itemId: string, compatibility?: KeepProgressCompatibility): Promise<KeepItemProgress | undefined>;\n saveCourse(courseId: string, currentItemId?: string): Promise<KeepCourseProgress>;\n saveItem(\n itemId: string,\n progress: Omit<KeepItemProgress, \"kind\" | \"itemId\" | \"updatedAt\">,\n ): Promise<KeepItemProgress>;\n set(record: KeepProgressRecord): Promise<void>;\n resetCourse(courseId: string): Promise<void>;\n resetItem(itemId: string): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport type LocalStorageProgressOptions = {\n key?: string;\n storage?: Storage;\n now?: () => number;\n};\n\nexport const DEFAULT_KEEP_PROGRESS_KEY = \"keepkit:progress\";\n\n/** Stores course and reader progress independently of saved items and open history. */\nexport class LocalStorageKeepProgressStorage implements KeepProgressStorage {\n private readonly key: string;\n private readonly storage: Storage | undefined;\n private readonly now: () => number;\n\n constructor(options: LocalStorageProgressOptions = {}) {\n this.key = options.key ?? DEFAULT_KEEP_PROGRESS_KEY;\n this.storage = options.storage ?? getBrowserStorage();\n this.now = options.now ?? Date.now;\n }\n\n async getAll(): Promise<KeepProgressRecord[]> {\n const raw = this.readRaw();\n if (raw === null) return [];\n let value: unknown;\n try {\n value = JSON.parse(raw) as unknown;\n } catch (cause) {\n throw new KeepProgressStorageError(\"KeepKit progress data is not valid JSON.\", this.key, cause);\n }\n if (!Array.isArray(value) || !value.every(isProgressRecord)) {\n throw new KeepProgressStorageError(\"KeepKit progress data is invalid.\", this.key);\n }\n return value.map((record) => ({ ...record }));\n }\n\n async getCourse(courseId: string): Promise<KeepCourseProgress | undefined> {\n const id = normalizeId(courseId, \"course\");\n const record = (await this.getAll()).find((entry) => entry.kind === \"course\" && entry.courseId === id);\n return record?.kind === \"course\" ? record : undefined;\n }\n\n async getItem(itemId: string, compatibility?: KeepProgressCompatibility): Promise<KeepItemProgress | undefined> {\n const id = normalizeId(itemId, \"item\");\n const record = (await this.getAll()).find((entry) => entry.kind === \"item\" && entry.itemId === id);\n if (record?.kind !== \"item\") return undefined;\n if (!isProgressCompatible(record, compatibility)) return undefined;\n return record;\n }\n\n async saveCourse(courseId: string, currentItemId?: string): Promise<KeepCourseProgress> {\n const id = normalizeId(courseId, \"course\");\n return this.withWriteLock(async () => {\n const records = await this.getAll();\n const previous = records.find((entry) => entry.kind === \"course\" && entry.courseId === id);\n const record: KeepCourseProgress = {\n kind: \"course\",\n courseId: id,\n ...(currentItemId?.trim() ? { currentItemId: currentItemId.trim() } : {}),\n updatedAt: Math.max(this.now(), (previous?.updatedAt ?? -1) + 1),\n };\n this.writeRecords([\n ...records.filter((entry) => getProgressIdentity(entry) !== getProgressIdentity(record)),\n record,\n ]);\n return record;\n });\n }\n\n async saveItem(\n itemId: string,\n progress: Omit<KeepItemProgress, \"kind\" | \"itemId\" | \"updatedAt\">,\n ): Promise<KeepItemProgress> {\n const id = normalizeId(itemId, \"item\");\n return this.withWriteLock(async () => {\n const records = await this.getAll();\n const previous = records.find((entry) => entry.kind === \"item\" && entry.itemId === id);\n const record: KeepItemProgress = {\n ...previous,\n ...progress,\n kind: \"item\",\n itemId: id,\n ...(progress.audioId !== undefined\n ? progress.audioId.trim()\n ? { audioId: progress.audioId.trim() }\n : { audioId: undefined }\n : {}),\n updatedAt: Math.max(this.now(), (previous?.updatedAt ?? -1) + 1),\n };\n const normalized = normalizeProgressRecord(record);\n if (normalized.kind !== \"item\") throw new TypeError(\"KeepKit progress record is invalid.\");\n this.writeRecords([\n ...records.filter((entry) => getProgressIdentity(entry) !== getProgressIdentity(normalized)),\n normalized,\n ]);\n return normalized;\n });\n }\n\n async set(record: KeepProgressRecord): Promise<void> {\n await this.withWriteLock(async () => {\n const normalized = normalizeProgressRecord(record);\n const records = await this.getAll();\n const identity = getProgressIdentity(normalized);\n const previous = records.find((entry) => getProgressIdentity(entry) === identity);\n const resolved = previous && previous.updatedAt > normalized.updatedAt ? previous : normalized;\n this.writeRecords([...records.filter((entry) => getProgressIdentity(entry) !== identity), resolved]);\n });\n }\n\n async resetCourse(courseId: string): Promise<void> {\n const id = normalizeId(courseId, \"course\");\n await this.withWriteLock(async () =>\n this.writeRecords((await this.getAll()).filter((entry) => entry.kind !== \"course\" || entry.courseId !== id)),\n );\n }\n\n async resetItem(itemId: string): Promise<void> {\n const id = normalizeId(itemId, \"item\");\n await this.withWriteLock(async () =>\n this.writeRecords((await this.getAll()).filter((entry) => entry.kind !== \"item\" || entry.itemId !== id)),\n );\n }\n\n async clear(): Promise<void> {\n await this.withWriteLock(async () => this.writeRecords([]));\n }\n\n private readRaw(): string | null {\n try {\n return this.storage?.getItem(this.key) ?? null;\n } catch (cause) {\n throw new KeepProgressStorageError(\"KeepKit could not read progress data.\", this.key, cause);\n }\n }\n\n private writeRecords(records: KeepProgressRecord[]): void {\n if (!this.storage) {\n throw new KeepProgressStorageError(\"KeepKit cannot persist progress without browser storage.\", this.key);\n }\n try {\n this.storage.setItem(this.key, JSON.stringify(records));\n } catch (cause) {\n throw new KeepProgressStorageError(\"KeepKit could not write progress data.\", this.key, cause);\n }\n }\n\n private withWriteLock<T>(operation: () => Promise<T>): Promise<T> {\n if (!this.storage) return operation();\n return withLocalStorageWriteLock(\n this.key,\n operation,\n new KeepProgressStorageError(\"KeepKit needs the Web Locks API to safely update progress across tabs.\", this.key),\n );\n }\n}\n\n/** Reject stale reader offsets when the selected language or content revision changed. */\nexport function isProgressCompatible(record: KeepItemProgress, compatibility?: KeepProgressCompatibility): boolean {\n if (record.language !== undefined && record.language !== compatibility?.language) return false;\n if (record.contentVersion !== undefined && record.contentVersion !== compatibility?.contentVersion) return false;\n if (compatibility?.language !== undefined && record.language !== compatibility.language) return false;\n if (compatibility?.contentVersion !== undefined && record.contentVersion !== compatibility.contentVersion)\n return false;\n if (record.audioId !== undefined && record.audioId !== compatibility?.audioId) return false;\n if (compatibility?.audioId !== undefined && record.audioId !== compatibility.audioId) return false;\n return true;\n}\n\nexport class KeepProgressStorageError extends Error {\n readonly storageKey: string;\n readonly cause?: unknown;\n\n constructor(message: string, storageKey: string, cause?: unknown) {\n super(message);\n this.name = \"KeepProgressStorageError\";\n this.storageKey = storageKey;\n this.cause = cause;\n }\n}\n\nfunction isProgressRecord(value: unknown): value is KeepProgressRecord {\n if (\n !isRecord(value) ||\n typeof value.updatedAt !== \"number\" ||\n !Number.isFinite(value.updatedAt) ||\n value.updatedAt < 0\n )\n return false;\n if (value.kind === \"course\") {\n return (\n typeof value.courseId === \"string\" &&\n value.courseId.length > 0 &&\n (value.currentItemId === undefined || typeof value.currentItemId === \"string\")\n );\n }\n if (value.kind !== \"item\") return false;\n return (\n typeof value.itemId === \"string\" &&\n value.itemId.length > 0 &&\n (value.audioPositionMs === undefined ||\n (typeof value.audioPositionMs === \"number\" &&\n Number.isFinite(value.audioPositionMs) &&\n value.audioPositionMs >= 0)) &&\n (value.readingPosition === undefined ||\n (typeof value.readingPosition === \"number\" &&\n Number.isFinite(value.readingPosition) &&\n value.readingPosition >= 0) ||\n (typeof value.readingPosition === \"string\" && value.readingPosition.trim().length > 0)) &&\n (value.audioId === undefined || (typeof value.audioId === \"string\" && value.audioId.length > 0)) &&\n (value.language === undefined || typeof value.language === \"string\") &&\n (value.contentVersion === undefined || typeof value.contentVersion === \"string\")\n );\n}\n\nfunction normalizeProgressRecord(record: KeepProgressRecord): KeepProgressRecord {\n if (!isProgressRecord(record)) throw new TypeError(\"KeepKit progress record is invalid.\");\n if (record.kind === \"course\") {\n return {\n kind: \"course\",\n courseId: normalizeId(record.courseId, \"course\"),\n ...(record.currentItemId?.trim() ? { currentItemId: record.currentItemId.trim() } : {}),\n updatedAt: record.updatedAt,\n };\n }\n return {\n kind: \"item\",\n itemId: normalizeId(record.itemId, \"item\"),\n ...(record.audioPositionMs !== undefined ? { audioPositionMs: record.audioPositionMs } : {}),\n ...(record.readingPosition !== undefined ? { readingPosition: record.readingPosition } : {}),\n ...(record.audioId !== undefined ? { audioId: record.audioId } : {}),\n ...(record.language !== undefined ? { language: record.language } : {}),\n ...(record.contentVersion !== undefined ? { contentVersion: record.contentVersion } : {}),\n updatedAt: record.updatedAt,\n };\n}\n\nfunction getProgressIdentity(record: KeepProgressRecord): string {\n return record.kind === \"course\" ? `course:${record.courseId}` : `item:${record.itemId}`;\n}\n\nfunction normalizeId(value: string, kind: string): string {\n const normalized = value.trim();\n if (!normalized) throw new TypeError(`KeepKit ${kind} ids must not be empty.`);\n return normalized;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\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","import type { KeepListQuery } from \"./query\";\n\nexport type KeepSavedView<TMeta = Record<string, unknown>> = {\n id: string;\n name: string;\n query: KeepListQuery<TMeta>;\n pinned?: boolean;\n createdAt: number;\n updatedAt: number;\n};\n\nexport interface KeepSavedViewStorage<TMeta = Record<string, unknown>> {\n getAll(): Promise<KeepSavedView<TMeta>[]>;\n get(id: string): Promise<KeepSavedView<TMeta> | undefined>;\n set(view: KeepSavedView<TMeta>): Promise<void>;\n remove(id: string): Promise<void>;\n}\n\nexport const DEFAULT_SAVED_VIEWS_STORAGE_KEY = \"keepkit:saved-views\";\n\n/** Local-first Saved View storage kept separate from item storage. */\nexport class LocalStorageKeepSavedViewStorage<TMeta = Record<string, unknown>> implements KeepSavedViewStorage<TMeta> {\n private readonly key: string;\n private readonly storage?: Storage;\n\n constructor(options: { key?: string; storage?: Storage } = {}) {\n this.key = options.key ?? DEFAULT_SAVED_VIEWS_STORAGE_KEY;\n this.storage = options.storage;\n }\n\n async getAll(): Promise<KeepSavedView<TMeta>[]> {\n const raw = this.getStorage().getItem(this.key);\n if (!raw) return [];\n const data: unknown = JSON.parse(raw);\n if (!Array.isArray(data) || !data.every(isSavedView)) throw new Error(\"KeepKit saved-view data is invalid.\");\n return data as KeepSavedView<TMeta>[];\n }\n\n async set(view: KeepSavedView<TMeta>): Promise<void> {\n const range = view.query.savedBetween;\n const normalized = {\n ...view,\n query: {\n ...view.query,\n ...(range\n ? {\n savedBetween: [\n range[0] instanceof Date ? range[0].getTime() : range[0],\n range[1] instanceof Date ? range[1].getTime() : range[1],\n ] as const,\n }\n : {}),\n },\n };\n if (!isSavedView(normalized)) throw new Error(\"KeepKit Saved View is invalid.\");\n const views = await this.getAll();\n const next = [...views.filter((current) => current.id !== normalized.id), normalized];\n this.getStorage().setItem(this.key, JSON.stringify(next));\n }\n\n async get(id: string): Promise<KeepSavedView<TMeta> | undefined> {\n return (await this.getAll()).find((view) => view.id === id);\n }\n\n async remove(id: string): Promise<void> {\n const views = await this.getAll();\n this.getStorage().setItem(this.key, JSON.stringify(views.filter((view) => view.id !== id)));\n }\n\n private getStorage(): Storage {\n if (this.storage) return this.storage;\n if (typeof localStorage === \"undefined\")\n throw new Error(\"KeepKit Saved Views require browser storage or an injected adapter.\");\n return localStorage;\n }\n}\n\nfunction isSavedView(value: unknown): value is KeepSavedView {\n if (typeof value !== \"object\" || value === null) return false;\n const view = value as Record<string, unknown>;\n return (\n typeof view.id === \"string\" &&\n view.id.length > 0 &&\n typeof view.name === \"string\" &&\n view.name.trim().length > 0 &&\n Number.isFinite(view.createdAt) &&\n Number.isFinite(view.updatedAt) &&\n isKeepListQuery(view.query) &&\n (view.pinned === undefined || typeof view.pinned === \"boolean\")\n );\n}\n\nfunction isKeepListQuery(value: unknown): boolean {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false;\n const query = value as Record<string, unknown>;\n if (query.filter !== undefined) return false;\n if (query.tags !== undefined && (!Array.isArray(query.tags) || !query.tags.every((tag) => typeof tag === \"string\"))) {\n return false;\n }\n if (query.collectionId !== undefined && typeof query.collectionId !== \"string\") return false;\n if (query.targetType !== undefined && typeof query.targetType !== \"string\") return false;\n if (query.archived !== undefined && typeof query.archived !== \"boolean\") return false;\n if (query.archiveScope !== undefined && ![\"active\", \"archived\", \"all\"].includes(String(query.archiveScope))) {\n return false;\n }\n if (query.pinnedFirst !== undefined && typeof query.pinnedFirst !== \"boolean\") return false;\n if (query.sort !== undefined) {\n if (!isRecord(query.sort) || ![\"savedAt\", \"updatedAt\", \"lastOpenedAt\"].includes(String(query.sort.by)))\n return false;\n if (query.sort.direction !== undefined && query.sort.direction !== \"asc\" && query.sort.direction !== \"desc\")\n return false;\n }\n if (query.search !== undefined) {\n if (!isRecord(query.search)) return false;\n if (query.search.query !== undefined && typeof query.search.query !== \"string\") return false;\n if (query.search.mode !== undefined && query.search.mode !== \"and\" && query.search.mode !== \"or\") return false;\n if (query.search.tokenize !== undefined && typeof query.search.tokenize !== \"boolean\") return false;\n if (\n query.search.fields !== undefined &&\n (!Array.isArray(query.search.fields) ||\n !query.search.fields.every((field) => field === \"note\" || field === \"meta\" || field === \"tags\"))\n ) {\n return false;\n }\n }\n if (query.activity !== undefined) {\n if (!isRecord(query.activity)) return false;\n if (query.activity.opened !== undefined && query.activity.opened !== \"ever\" && query.activity.opened !== \"never\") {\n return false;\n }\n if (\n [query.activity.lastOpenedBefore, query.activity.lastOpenedAfter, query.activity.inactiveForMs].some(\n isInvalidNumber,\n )\n ) {\n return false;\n }\n }\n if (\n query.savedBetween !== undefined &&\n (!Array.isArray(query.savedBetween) || query.savedBetween.length !== 2 || query.savedBetween.some(isInvalidNumber))\n ) {\n return false;\n }\n if (query.pagination !== undefined) {\n if (!isRecord(query.pagination) || [query.pagination.page, query.pagination.pageSize].some(isInvalidNumber))\n return false;\n }\n const organization = query.organization;\n if (organization !== undefined) {\n if (typeof organization !== \"object\" || organization === null || Array.isArray(organization)) return false;\n const fields = organization as Record<string, unknown>;\n if (\n [fields.collection, fields.tags, fields.note].some(\n (field) => field !== undefined && field !== \"assigned\" && field !== \"unassigned\",\n )\n ) {\n return false;\n }\n }\n return true;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isInvalidNumber(value: unknown): boolean {\n return value !== undefined && (typeof value !== \"number\" || !Number.isFinite(value));\n}\n","import type { KeepListQuery } from \"./query\";\n\nexport type KeepUrlParamNames = {\n search: string;\n tags: string;\n sort: string;\n page: string;\n archived: string;\n archiveScope: string;\n collection: string;\n pinnedFirst: string;\n activityOpened?: string;\n lastOpenedBefore?: string;\n lastOpenedAfter?: string;\n inactiveForMs?: string;\n organizationCollection?: string;\n organizationTags?: string;\n organizationNote?: string;\n savedAfter?: string;\n savedBefore?: 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: Required<KeepUrlParamNames> = {\n search: \"q\",\n tags: \"tag\",\n sort: \"sort\",\n page: \"page\",\n archived: \"archived\",\n archiveScope: \"archiveScope\",\n collection: \"collection\",\n pinnedFirst: \"pinned\",\n activityOpened: \"opened\",\n lastOpenedBefore: \"openedBefore\",\n lastOpenedAfter: \"openedAfter\",\n inactiveForMs: \"inactiveFor\",\n organizationCollection: \"collectionState\",\n organizationTags: \"tagsState\",\n organizationNote: \"noteState\",\n savedAfter: \"savedAfter\",\n savedBefore: \"savedBefore\",\n};\n\nexport type KeepUrlState = Pick<\n KeepListQuery,\n | \"search\"\n | \"tags\"\n | \"sort\"\n | \"pagination\"\n | \"archived\"\n | \"archiveScope\"\n | \"collectionId\"\n | \"pinnedFirst\"\n | \"activity\"\n | \"organization\"\n | \"savedBetween\"\n>;\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: Required<KeepUrlParamNames> = { ...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 if (query.archiveScope !== undefined) result.set(params.archiveScope, query.archiveScope);\n else if (query.archived !== undefined) result.set(params.archived, query.archived ? \"true\" : \"false\");\n if (query.collectionId) result.set(params.collection, query.collectionId);\n for (const [key, value] of [\n [params.organizationCollection, query.organization?.collection],\n [params.organizationTags, query.organization?.tags],\n [params.organizationNote, query.organization?.note],\n ] as const) {\n if (value !== undefined) result.set(key, value);\n }\n if (query.pinnedFirst) result.set(params.pinnedFirst, \"true\");\n if (query.savedBetween) {\n const [from, to] = query.savedBetween.map((value) => (value instanceof Date ? value.getTime() : value));\n if (Number.isFinite(from) && Number.isFinite(to)) {\n result.set(params.savedAfter, String(from));\n result.set(params.savedBefore, String(to));\n }\n }\n if (query.activity?.opened) result.set(params.activityOpened, query.activity.opened);\n for (const [key, value] of [\n [params.lastOpenedBefore, query.activity?.lastOpenedBefore],\n [params.lastOpenedAfter, query.activity?.lastOpenedAfter],\n [params.inactiveForMs, query.activity?.inactiveForMs],\n ] as const) {\n if (value !== undefined && Number.isFinite(value)) result.set(key, String(value));\n }\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: Required<KeepUrlParamNames> = { ...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\" || sortValue?.[0] === \"lastOpenedAt\"\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 const archiveScopeValue = searchParams.get(params.archiveScope);\n const archiveScope =\n archiveScopeValue === \"active\" || archiveScopeValue === \"archived\" || archiveScopeValue === \"all\"\n ? archiveScopeValue\n : undefined;\n const archivedValue = searchParams.get(params.archived);\n const archived =\n archiveScope === \"archived\" || archivedValue === \"true\"\n ? true\n : archiveScope === \"active\" || archivedValue === \"false\"\n ? false\n : undefined;\n const collectionId = searchParams.get(params.collection)?.trim() || undefined;\n const organizationCollection = parseOrganizationState(searchParams.get(params.organizationCollection));\n const organizationTags = parseOrganizationState(searchParams.get(params.organizationTags));\n const organizationNote = parseOrganizationState(searchParams.get(params.organizationNote));\n const organization =\n organizationCollection || organizationTags || organizationNote\n ? {\n ...(organizationCollection ? { collection: organizationCollection } : {}),\n ...(organizationTags ? { tags: organizationTags } : {}),\n ...(organizationNote ? { note: organizationNote } : {}),\n }\n : undefined;\n const pinnedFirst = searchParams.get(params.pinnedFirst) === \"true\" ? true : undefined;\n const parseSavedDate = (name: string): number | undefined => {\n const rawValue = searchParams.get(name);\n if (rawValue === null || rawValue.trim() === \"\") return undefined;\n const value = Number(rawValue);\n return Number.isFinite(value) ? value : undefined;\n };\n const savedAfter = parseSavedDate(params.savedAfter);\n const savedBefore = parseSavedDate(params.savedBefore);\n const savedBetween =\n savedAfter === undefined || savedBefore === undefined ? undefined : ([savedAfter, savedBefore] as const);\n const activityOpenedValue = searchParams.get(params.activityOpened);\n const activityOpened: \"ever\" | \"never\" | undefined =\n activityOpenedValue === \"ever\" || activityOpenedValue === \"never\" ? activityOpenedValue : undefined;\n const parseActivityNumber = (name: string): number | undefined => {\n const rawValue = searchParams.get(name);\n if (rawValue === null || rawValue.trim() === \"\") return undefined;\n const value = Number(rawValue);\n return Number.isFinite(value) ? value : undefined;\n };\n const lastOpenedBefore = parseActivityNumber(params.lastOpenedBefore);\n const lastOpenedAfter = parseActivityNumber(params.lastOpenedAfter);\n const inactiveForMs = parseActivityNumber(params.inactiveForMs);\n const activity =\n activityOpened !== undefined ||\n lastOpenedBefore !== undefined ||\n lastOpenedAfter !== undefined ||\n inactiveForMs !== undefined\n ? {\n ...(activityOpened === undefined ? {} : { opened: activityOpened }),\n ...(lastOpenedBefore === undefined ? {} : { lastOpenedBefore }),\n ...(lastOpenedAfter === undefined ? {} : { lastOpenedAfter }),\n ...(inactiveForMs === undefined ? {} : { inactiveForMs }),\n }\n : undefined;\n return {\n ...(search ? { search: { query: search } } : {}),\n ...(tags.length > 0 ? { tags } : {}),\n ...(sort ? { sort } : {}),\n ...(page ? { pagination: { page } } : {}),\n ...(archived === undefined ? {} : { archived }),\n ...(archiveScope === undefined ? {} : { archiveScope }),\n ...(collectionId ? { collectionId } : {}),\n ...(organization ? { organization } : {}),\n ...(pinnedFirst ? { pinnedFirst } : {}),\n ...(savedBetween ? { savedBetween } : {}),\n ...(activity === undefined ? {} : { activity }),\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 archived: decoded.archived ?? query.archived,\n archiveScope: decoded.archiveScope ?? query.archiveScope,\n activity: decoded.activity ?? query.activity,\n organization: decoded.organization ?? query.organization,\n savedBetween: decoded.savedBetween ?? query.savedBetween,\n };\n}\n\nfunction parseOrganizationState(value: string | null): \"assigned\" | \"unassigned\" | undefined {\n return value === \"assigned\" || value === \"unassigned\" ? value : undefined;\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 KeepCollectionDefinition,\n KeepCollectionMembership,\n KeepCollectionSyncOperation,\n KeepItem,\n KeepMembershipSyncOperation,\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 collectionOperation?: KeepCollectionSyncOperation;\n membershipOperation?: KeepMembershipSyncOperation;\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 pushCollection?: (\n operation: KeepCollectionSyncOperation,\n context: AuthenticatedSyncRequestContext<TMeta>,\n ) => Promise<void>;\n pullCollections?: (context: AuthenticatedSyncRequestContext<TMeta>) => Promise<KeepCollectionDefinition[]>;\n pushMembership?: (\n operation: KeepMembershipSyncOperation,\n context: AuthenticatedSyncRequestContext<TMeta>,\n ) => Promise<void>;\n pullMemberships?: (context: AuthenticatedSyncRequestContext<TMeta>) => Promise<KeepCollectionMembership[]>;\n};\n\nexport type AuthenticatedSyncAuthContext<TMeta = Record<string, unknown>> = {\n operation?: SyncOperation<TMeta>;\n collectionOperation?: KeepCollectionSyncOperation;\n membershipOperation?: KeepMembershipSyncOperation;\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 readonly getCollections?: () => Promise<KeepCollectionDefinition[]>;\n readonly setCollection?: (collection: KeepCollectionDefinition) => Promise<void>;\n readonly removeCollection?: (id: string, scope?: SyncScope) => Promise<void>;\n readonly getCollectionMemberships?: () => Promise<KeepCollectionMembership[]>;\n readonly setCollectionMembership?: (membership: KeepCollectionMembership) => Promise<void>;\n readonly removeCollectionMembership?: (collectionId: string, itemId: string, scope?: SyncScope) => Promise<void>;\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 if (this.current.getCollections && this.current.setCollection && this.current.removeCollection) {\n this.getCollections = async () => {\n await this.ensureScope();\n return this.current.getCollections?.() ?? [];\n };\n this.setCollection = async (collection) => {\n await this.ensureScope();\n await this.current.setCollection?.(collection);\n };\n this.removeCollection = async (id) => {\n await this.ensureScope();\n await this.current.removeCollection?.(id);\n };\n }\n if (\n this.current.getCollectionMemberships &&\n this.current.setCollectionMembership &&\n this.current.removeCollectionMembership\n ) {\n this.getCollectionMemberships = async () => {\n await this.ensureScope();\n return this.current.getCollectionMemberships?.() ?? [];\n };\n this.setCollectionMembership = async (membership) => {\n await this.ensureScope();\n await this.current.setCollectionMembership?.(membership);\n };\n this.removeCollectionMembership = async (collectionId, itemId) => {\n await this.ensureScope();\n await this.current.removeCollectionMembership?.(collectionId, itemId);\n };\n }\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 const pullCollections = options.transport.pullCollections;\n const pullMemberships = options.transport.pullMemberships;\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 pushCollection: options.transport.pushCollection\n ? async (collectionOperation) => {\n try {\n const token = await options.getAuthToken();\n await options.transport.pushCollection?.(collectionOperation, { token, scope, collectionOperation });\n } catch (cause) {\n return handleAuthFailure(cause, options, { collectionOperation, scope });\n }\n }\n : undefined,\n pullCollections: pullCollections\n ? async () => {\n try {\n const token = await options.getAuthToken();\n return await pullCollections({ token, scope });\n } catch (cause) {\n return handleAuthFailure(cause, options, { scope });\n }\n }\n : undefined,\n pushMembership: options.transport.pushMembership\n ? async (membershipOperation) => {\n try {\n const token = await options.getAuthToken();\n await options.transport.pushMembership?.(membershipOperation, { token, scope, membershipOperation });\n } catch (cause) {\n return handleAuthFailure(cause, options, { membershipOperation, scope });\n }\n }\n : undefined,\n pullMemberships: pullMemberships\n ? async () => {\n try {\n const token = await options.getAuthToken();\n return await pullMemberships({ 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAM,cAAc,oBAAI,IAA8B;AAG/C,SAAS,0BACd,KACA,WACA,sBACY;AACZ,QAAM,WAAW,yBAAyB,GAAG;AAC7C,MAAI,OAAO,cAAc,eAAe,UAAU,OAAO;AACvD,WAAO,UAAU,MAAM,QAAQ,UAAU,SAAS;AAAA,EACpD;AACA,MAAI,OAAO,WAAW,YAAa,QAAO,QAAQ,OAAO,oBAAoB;AAE7E,QAAM,WAAW,YAAY,IAAI,QAAQ,KAAK,QAAQ,QAAQ;AAC9D,QAAM,OAAO,SAAS,MAAM,MAAM,MAAS,EAAE,KAAK,SAAS;AAC3D,cAAY,IAAI,UAAU,IAAI;AAC9B,SAAO,KAAK,QAAQ,MAAM;AACxB,QAAI,YAAY,IAAI,QAAQ,MAAM,KAAM,aAAY,OAAO,QAAQ;AAAA,EACrE,CAAC;AACH;;;AC4BO,IAAM,2BAA2B;AACjC,IAAM,mCAAmC;AACzC,IAAM,6BAA6B;AAGnC,IAAM,iCAAN,MAAmE;AAAA,EAOxE,YAAY,UAAuC,CAAC,GAAG;AACrD,SAAK,MAAM,QAAQ,OAAO;AAC1B,SAAK,WAAW,GAAG,KAAK,GAAG;AAC3B,SAAK,UAAU,QAAQ,WAAW,kBAAkB;AACpD,SAAK,eAAe,eAAe,QAAQ,cAAc,0BAA0B;AACnF,SAAK,MAAM,QAAQ,OAAO,KAAK;AAAA,EACjC;AAAA,EAEA,MAAM,SAAsC;AAC1C,YAAQ,MAAM,KAAK,KAAyB,KAAK,KAAK,qBAAqB,SAAS,GAAG;AAAA,MACrF,CAAC,MAAM,UAAU,MAAM,eAAe,KAAK;AAAA,IAC7C;AAAA,EACF;AAAA,EAEA,MAAM,WAA4B;AAChC,QAAI,CAAC,KAAK,QAAS,QAAO,KAAK;AAC/B,UAAM,MAAM,KAAK,QAAQ,KAAK,UAAU,eAAe;AACvD,QAAI,QAAQ,KAAM,QAAO,KAAK;AAC9B,UAAM,SAAkB,UAAU,KAAK,KAAK,UAAU,eAAe;AACrE,QAAI,OAAO,WAAW,YAAY,CAAC,OAAO,UAAU,MAAM,KAAK,SAAS,GAAG;AACzE,YAAM,IAAI,yBAAyB,qCAAqC,KAAK,QAAQ;AAAA,IACvF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,OAA8B;AAC3C,UAAM,aAAa,eAAe,KAAK;AACvC,UAAM,KAAK,cAAc,YAAY;AACnC,WAAK,SAAS,KAAK,UAAU,KAAK,UAAU,UAAU,GAAG,eAAe;AACxE,YAAM,UAAU,MAAM,KAAK,OAAO;AAClC,YAAM,KAAK,aAAa,QAAQ,MAAM,GAAG,UAAU,CAAC;AAAA,IACtD,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,QAAgB,WAAW,KAAK,IAAI,GAAG,SAA2D;AAC7G,UAAM,eAAe,YAAY,MAAM;AACvC,oBAAgB,QAAQ;AACxB,WAAO,KAAK,cAAc,YAAY;AACpC,YAAM,UAAU,MAAM,KAAK,OAAO;AAClC,YAAM,WAAW,QAAQ,KAAK,CAAC,UAAU,MAAM,WAAW,YAAY;AACtE,YAAM,UAAU,aAAa,UAAU,gBAAgB;AACvD,YAAM,cAAc,UAAU,wBAAwB,OAAO,IAAI,UAAU;AAC3E,YAAM,OAAO;AAAA,QACX;AAAA,UACE,QAAQ;AAAA,UACR,cAAc,KAAK,IAAI,UAAU,gBAAgB,GAAG,QAAQ;AAAA,UAC5D,GAAI,cAAc,EAAE,SAAS,YAAY,IAAI,CAAC;AAAA,QAChD;AAAA,QACA,GAAG,QAAQ,OAAO,CAAC,UAAU,MAAM,WAAW,YAAY;AAAA,MAC5D,EACG,KAAK,CAAC,MAAM,UAAU,MAAM,eAAe,KAAK,YAAY,EAC5D,MAAM,GAAG,MAAM,KAAK,SAAS,CAAC;AACjC,YAAM,KAAK,aAAa,IAAI;AAC5B,aAAO,oBAAoB,IAAI;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,QAA+B;AAC1C,UAAM,eAAe,YAAY,MAAM;AACvC,UAAM,KAAK;AAAA,MAAc,YACvB,KAAK,cAAc,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,UAAU,MAAM,WAAW,YAAY,CAAC;AAAA,IAC1F;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,cAAc,YAAY,KAAK,SAAS,KAAK,KAAK,MAAM,SAAS,CAAC;AAAA,EAC/E;AAAA,EAEA,MAAc,aAAa,SAA4C;AACrE,SAAK,SAAS,KAAK,KAAK,KAAK,UAAU,OAAO,GAAG,SAAS;AAAA,EAC5D;AAAA,EAEQ,cAAiB,WAAyC;AAChE,QAAI,CAAC,KAAK,QAAS,QAAO,UAAU;AACpC,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,IAAI,yBAAyB,yEAAyE,KAAK,GAAG;AAAA,IAChH;AAAA,EACF;AAAA,EAEA,MAAc,KAAQ,KAAa,UAA0C,OAA2B;AACtG,UAAM,MAAM,KAAK,QAAQ,KAAK,KAAK;AACnC,QAAI,QAAQ,KAAM,QAAO,CAAC;AAC1B,UAAM,QAAQ,UAAU,KAAK,KAAK,KAAK;AACvC,QAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,yBAAyB,WAAW,KAAK,qBAAqB,GAAG;AACjG,WAAO;AAAA,EACT;AAAA,EAEQ,QAAQ,KAAa,OAA8B;AACzD,QAAI;AACF,aAAO,KAAK,SAAS,QAAQ,GAAG,KAAK;AAAA,IACvC,SAAS,OAAO;AACd,YAAM,IAAI,yBAAyB,0BAA0B,KAAK,UAAU,KAAK,KAAK;AAAA,IACxF;AAAA,EACF;AAAA,EAEQ,SAAS,KAAa,OAAe,OAAqB;AAChE,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,yBAAyB,0BAA0B,KAAK,kCAAkC,GAAG;AACzG,QAAI;AACF,WAAK,QAAQ,QAAQ,KAAK,KAAK;AAAA,IACjC,SAAS,OAAO;AACd,YAAM,IAAI,yBAAyB,2BAA2B,KAAK,UAAU,KAAK,KAAK;AAAA,IACzF;AAAA,EACF;AACF;AAGO,IAAM,uCAAN,MAA+E;AAAA,EAMpF,YAAY,UAAuC,CAAC,GAAG;AACrD,SAAK,MAAM,QAAQ,OAAO;AAC1B,SAAK,UAAU,QAAQ,WAAW,kBAAkB;AACpD,SAAK,MAAM,QAAQ,OAAO,KAAK;AAC/B,SAAK,WAAW,QAAQ,YAAY;AAAA,EACtC;AAAA,EAEA,MAAM,OAAO,QAA+C;AAC1D,UAAM,UAAU,MAAM,KAAK,YAAY;AACvC,UAAM,WAAW,WAAW,SAAY,UAAU,QAAQ,OAAO,CAAC,WAAW,OAAO,WAAW,MAAM;AACrG,WAAO,SAAS,KAAK,CAAC,MAAM,UAAU,MAAM,WAAW,KAAK,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,GAAG,OAAO,EAAE;AAAA,EACvG;AAAA,EAEA,MAAM,IAAI,QAA0C;AAClD,UAAM,KAAK,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEA,MAAM,IAAI,QAAgB,UAAgD,CAAC,GAA+B;AACxG,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,SAA4B;AAAA,MAChC,IAAI,KAAK,SAAS;AAAA,MAClB,QAAQ,YAAY,MAAM;AAAA,MAC1B,UAAU,QAAQ,YAAY;AAAA,MAC9B,WAAW;AAAA,MACX,WAAW;AAAA,MACX,GAAI,QAAQ,MAAM,KAAK,IAAI,EAAE,MAAM,QAAQ,KAAK,KAAK,EAAE,IAAI,CAAC;AAAA,IAC9D;AACA,WAAO,KAAK,WAAW,MAAM;AAAA,EAC/B;AAAA,EAEA,MAAc,WAAW,QAAuD;AAC9E,UAAM,aAAa,uBAAuB,MAAM;AAChD,WAAO,KAAK,cAAc,YAAY;AACpC,YAAM,UAAU,MAAM,KAAK,YAAY;AACvC,YAAM,WAAW,QAAQ,KAAK,CAAC,UAAU,MAAM,OAAO,WAAW,EAAE;AACnE,UACE,UAAU,cAAc,UACxB,WAAW,cAAc,UACzB,SAAS,YAAY,WAAW,WAChC;AACA,eAAO,EAAE,GAAG,SAAS;AAAA,MACvB;AACA,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,OAAO;AAAA,QACX,GAAG;AAAA,QACH,WAAW,UAAU,aAAa,WAAW,aAAa;AAAA,QAC1D,WAAW,KAAK,IAAI,MAAM,UAAU,aAAa,MAAM,GAAG,WAAW,aAAa,EAAE;AAAA,MACtF;AACA,WAAK,aAAa,CAAC,GAAG,QAAQ,OAAO,CAAC,UAAU,MAAM,OAAO,WAAW,EAAE,GAAG,IAAI,CAAC;AAClF,aAAO,EAAE,GAAG,KAAK;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,KAAK;AAAA,MAAc,YACvB,KAAK,cAAc,MAAM,KAAK,YAAY,GAAG,OAAO,CAAC,WAAW,OAAO,OAAO,EAAE,CAAC;AAAA,IACnF;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,QAA+B;AACjD,UAAM,eAAe,YAAY,MAAM;AACvC,UAAM,KAAK;AAAA,MAAc,YACvB,KAAK,cAAc,MAAM,KAAK,YAAY,GAAG,OAAO,CAAC,WAAW,OAAO,WAAW,YAAY,CAAC;AAAA,IACjG;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,cAAc,YAAY,KAAK,aAAa,CAAC,CAAC,CAAC;AAAA,EAC5D;AAAA,EAEA,MAAc,cAA4C;AACxD,UAAM,MAAM,KAAK,QAAQ;AACzB,QAAI,QAAQ,KAAM,QAAO,CAAC;AAC1B,UAAM,QAAQ,UAAU,KAAK,KAAK,KAAK,iBAAiB;AACxD,QAAI,CAAC,qBAAqB,KAAK,GAAG;AAChC,YAAM,IAAI,yBAAyB,2CAA2C,KAAK,GAAG;AAAA,IACxF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,UAAyB;AAC/B,QAAI;AACF,aAAO,KAAK,SAAS,QAAQ,KAAK,GAAG,KAAK;AAAA,IAC5C,SAAS,OAAO;AACd,YAAM,IAAI,yBAAyB,2CAA2C,KAAK,KAAK,KAAK;AAAA,IAC/F;AAAA,EACF;AAAA,EAEQ,aAAa,SAAoC;AACvD,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI,yBAAyB,mEAAmE,KAAK,GAAG;AAAA,IAChH;AACA,QAAI;AACF,WAAK,QAAQ,QAAQ,KAAK,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,IACxD,SAAS,OAAO;AACd,YAAM,IAAI,yBAAyB,4CAA4C,KAAK,KAAK,KAAK;AAAA,IAChG;AAAA,EACF;AAAA,EAEQ,cAAiB,WAAyC;AAChE,QAAI,CAAC,KAAK,QAAS,QAAO,UAAU;AACpC,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,IAAI;AAAA,QACF;AAAA,QACA,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,2BAAN,cAAuC,MAAM;AAAA,EAIlD,YAAY,SAAiB,YAAoB,OAAiB;AAChE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,QAAQ;AAAA,EACf;AACF;AAEA,SAAS,oBAAoB,OAA6C;AACxE,SACE,MAAM,QAAQ,KAAK,KACnB,MAAM;AAAA,IACJ,CAAC,UACC,SAAS,KAAK,KACd,OAAO,MAAM,WAAW,YACxB,MAAM,OAAO,SAAS,KACtB,OAAO,MAAM,iBAAiB,YAC9B,OAAO,SAAS,MAAM,YAAY,MACjC,MAAM,YAAY,UAAa,iBAAiB,MAAM,OAAO;AAAA,EAClE;AAEJ;AAEA,SAAS,qBAAqB,OAA8C;AAC1E,SAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,eAAe;AAC5D;AAEA,SAAS,gBAAgB,OAA4C;AACnE,SACE,SAAS,KAAK,KACd,OAAO,MAAM,OAAO,YACpB,MAAM,GAAG,SAAS,KAClB,OAAO,MAAM,WAAW,YACxB,MAAM,OAAO,SAAS,KACtB,OAAO,MAAM,aAAa,YAC1B,OAAO,SAAS,MAAM,QAAQ,KAC9B,MAAM,YAAY,MACjB,MAAM,cAAc,UAAc,OAAO,MAAM,cAAc,YAAY,OAAO,SAAS,MAAM,SAAS,OACxG,MAAM,cAAc,UAAc,OAAO,MAAM,cAAc,YAAY,OAAO,SAAS,MAAM,SAAS,OACxG,MAAM,SAAS,UAAa,OAAO,MAAM,SAAS;AAEvD;AAEA,SAAS,uBAAuB,QAA8C;AAC5E,QAAM,aAAgC;AAAA,IACpC,IAAI,YAAY,OAAO,EAAE;AAAA,IACzB,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,UAAU,OAAO;AAAA,IACjB,GAAI,OAAO,cAAc,SAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,IACxE,GAAI,OAAO,cAAc,SAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,IACxE,GAAI,OAAO,MAAM,KAAK,IAAI,EAAE,MAAM,OAAO,KAAK,KAAK,EAAE,IAAI,CAAC;AAAA,EAC5D;AACA,kBAAgB,WAAW,QAAQ;AACnC,SAAO;AACT;AAEA,SAAS,YAAY,OAAuB;AAC1C,QAAM,aAAa,MAAM,KAAK;AAC9B,MAAI,CAAC,WAAY,OAAM,IAAI,UAAU,qCAAqC;AAC1E,SAAO;AACT;AAEA,SAAS,eAAe,OAAuB;AAC7C,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,EAAG,OAAM,IAAI,WAAW,mDAAmD;AACnH,SAAO;AACT;AAEA,SAAS,gBAAgB,OAAqB;AAC5C,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,EAAG,OAAM,IAAI,UAAU,kDAAkD;AAClH;AAEA,SAAS,oBAAoB,SAAiD;AAC5E,SAAO,QAAQ,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,GAAI,MAAM,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,QAAQ,EAAE,IAAI,CAAC,EAAG,EAAE;AAC3G;AAEA,SAAS,wBAAwB,SAA8D;AAC7F,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,UAAU,OAAO,QAAQ,OAAO,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,OAAO,UAAU,QAAQ;AACxG,SAAO,QAAQ,SAAS,IAAI,OAAO,YAAY,OAAO,IAAI;AAC5D;AAEA,SAAS,iBAAiB,OAA6C;AACrE,SAAO,SAAS,KAAK,KAAK,OAAO,OAAO,KAAK,EAAE,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ;AAC3F;AAEA,SAAS,UAAU,KAAa,KAAa,OAAwB;AACnE,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,SAAS,OAAO;AACd,UAAM,IAAI,yBAAyB,WAAW,KAAK,4BAA4B,KAAK,KAAK;AAAA,EAC3F;AACF;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,oBAAyC;AAChD,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI;AACF,WAAO,OAAO;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,iBAAyB;AAChC,MAAI,OAAO,WAAW,eAAe,gBAAgB,OAAQ,QAAO,OAAO,WAAW;AACtF,SAAO,gBAAgB,KAAK,IAAI,EAAE,SAAS,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACvF;;;AC9YA,IAAM,2BAA2B,oBAAI,QAAkC;AAEvE,eAAsB,uBACpB,SACA,cAC4B;AAC5B,QAAM,cAAc,MAAM,mBAAmB,OAAO;AACpD,QAAM,QAAQ,MAAM,QAAQ,OAAO;AACnC,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC9D,SAAO,YACJ,OAAO,CAAC,eAAe,WAAW,iBAAiB,YAAY,EAC/D,KAAK,CAAC,MAAM,UAAU,KAAK,QAAQ,MAAM,KAAK,EAC9C,QAAQ,CAAC,eAAe;AACvB,UAAM,OAAO,UAAU,IAAI,WAAW,MAAM;AAC5C,WAAO,OAAO,CAAC,IAAI,IAAI,CAAC;AAAA,EAC1B,CAAC;AACL;AAEA,eAAsB,wBACpB,SACA,cACA,QACA,OACmC;AACnC,SAAO,2BAA2B,SAAS,YAAY;AACrD,QAAI,EAAE,MAAM,QAAQ,OAAO,GAAG,KAAK,CAAC,SAAS,KAAK,OAAO,MAAM,GAAG;AAChE,YAAM,IAAI,MAAM,oCAAoC,MAAM,oBAAoB;AAAA,IAChF;AACA,UAAM,yBAAyB,MAAM,mBAAmB,OAAO,GAC5D,OAAO,CAAC,eAAe,WAAW,iBAAiB,YAAY,EAC/D,OAAO,CAAC,eAAe,WAAW,WAAW,MAAM,EACnD,KAAK,CAAC,MAAM,UAAU,KAAK,QAAQ,MAAM,KAAK;AACjD,UAAM,iBAAiB,SAAS,sBAAsB;AACtD,QAAI,CAAC,OAAO,UAAU,cAAc,KAAK,iBAAiB,GAAG;AAC3D,YAAM,IAAI,WAAW,kDAAkD;AAAA,IACzE;AACA,0BAAsB,OAAO,KAAK,IAAI,gBAAgB,sBAAsB,MAAM,GAAG,GAAG;AAAA,MACtF;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT,CAAC;AACD,UAAM,YAAY,sBAAsB,IAAI,CAAC,YAAY,WAAW,EAAE,GAAG,YAAY,OAAO,MAAM,EAAE;AACpG,eAAW,cAAc,UAAW,OAAM,QAAQ,0BAA0B,UAAU;AACtF,UAAM,QAAQ,UAAU,KAAK,CAAC,eAAe,WAAW,WAAW,MAAM;AACzE,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kDAAkD;AAC9E,WAAO;AAAA,EACT,CAAC;AACH;AAEA,eAAsB,6BACpB,SACA,cACA,QACe;AACf,QAAM,2BAA2B,SAAS,YAAY;AACpD,UAAM,cAAc,MAAM,mBAAmB,OAAO;AACpD,UAAM,QAAQ,6BAA6B,cAAc,MAAM;AAC/D,UAAM,YAAY,YACf,OAAO,CAAC,eAAe,WAAW,iBAAiB,gBAAgB,WAAW,WAAW,MAAM,EAC/F,KAAK,CAAC,MAAM,UAAU,KAAK,QAAQ,MAAM,KAAK,EAC9C,IAAI,CAAC,YAAY,WAAW,EAAE,GAAG,YAAY,MAAM,EAAE;AACxD,eAAW,cAAc,UAAW,OAAM,QAAQ,0BAA0B,UAAU;AAAA,EACxF,CAAC;AACH;AAGA,eAAsB,2BACpB,SACA,cACA,SACqC;AACrC,SAAO,2BAA2B,SAAS,YAAY;AACrD,UAAM,iBAAiB,MAAM,mBAAmB,OAAO;AACvD,UAAM,UAAU,eACb,OAAO,CAAC,eAAe,WAAW,iBAAiB,YAAY,EAC/D,KAAK,CAAC,MAAM,UAAU,KAAK,QAAQ,MAAM,KAAK;AACjD,UAAM,aAAa,IAAI,IAAI,QAAQ,IAAI,CAAC,eAAe,WAAW,MAAM,CAAC;AACzE,UAAM,aAAa,CAAC,GAAG,QAAQ,OAAO,CAAC,IAAI,UAAU,WAAW,IAAI,EAAE,KAAK,QAAQ,QAAQ,EAAE,MAAM,KAAK,CAAC;AACzG,eAAW,cAAc,SAAS;AAChC,UAAI,CAAC,WAAW,SAAS,WAAW,MAAM,EAAG,YAAW,KAAK,WAAW,MAAM;AAAA,IAChF;AACA,UAAM,kBAAkB,IAAI,IAAI,QAAQ,IAAI,CAAC,eAAe,CAAC,WAAW,QAAQ,UAAU,CAAC,CAAC;AAC5F,UAAM,YAAY,WAAW,IAAI,CAAC,QAAQ,WAAW;AAAA,MACnD,GAAI,gBAAgB,IAAI,MAAM,KAAK,CAAC;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE;AACF,eAAW,cAAc,UAAW,OAAM,QAAQ,0BAA0B,UAAU;AACtF,WAAO;AAAA,EACT,CAAC;AACH;AAEA,SAAS,2BACP,SACA,WACkB;AAClB,QAAM,WAAW,yBAAyB,IAAI,OAAO,KAAK,QAAQ,QAAQ;AAC1E,QAAM,OAAO,SAAS,MAAM,MAAM,MAAS,EAAE,KAAK,SAAS;AAC3D,2BAAyB,IAAI,SAAS,IAAI;AAC1C,SAAO,KAAK,QAAQ,MAAM;AACxB,QAAI,yBAAyB,IAAI,OAAO,MAAM,KAAM,0BAAyB,OAAO,OAAO;AAAA,EAC7F,CAAC;AACH;AAEA,eAAe,mBAA0B,SAAqE;AAC5G,MAAI,CAAC,QAAQ,4BAA4B,CAAC,QAAQ,2BAA2B,CAAC,QAAQ,4BAA4B;AAChH,UAAM,IAAI,MAAM,kEAAkE;AAAA,EACpF;AACA,SAAO,QAAQ,yBAAyB;AAC1C;;;ACrFO,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;;;ACR3B,IAAM,4BAA4B;AAGlC,IAAM,kCAAN,MAAqE;AAAA,EAK1E,YAAY,UAAuC,CAAC,GAAG;AACrD,SAAK,MAAM,QAAQ,OAAO;AAC1B,SAAK,UAAU,QAAQ,WAAWA,mBAAkB;AACpD,SAAK,MAAM,QAAQ,OAAO,KAAK;AAAA,EACjC;AAAA,EAEA,MAAM,SAAwC;AAC5C,UAAM,MAAM,KAAK,QAAQ;AACzB,QAAI,QAAQ,KAAM,QAAO,CAAC;AAC1B,QAAI;AACJ,QAAI;AACF,cAAQ,KAAK,MAAM,GAAG;AAAA,IACxB,SAAS,OAAO;AACd,YAAM,IAAI,yBAAyB,4CAA4C,KAAK,KAAK,KAAK;AAAA,IAChG;AACA,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,MAAM,gBAAgB,GAAG;AAC3D,YAAM,IAAI,yBAAyB,qCAAqC,KAAK,GAAG;AAAA,IAClF;AACA,WAAO,MAAM,IAAI,CAAC,YAAY,EAAE,GAAG,OAAO,EAAE;AAAA,EAC9C;AAAA,EAEA,MAAM,UAAU,UAA2D;AACzE,UAAM,KAAKC,aAAY,UAAU,QAAQ;AACzC,UAAM,UAAU,MAAM,KAAK,OAAO,GAAG,KAAK,CAAC,UAAU,MAAM,SAAS,YAAY,MAAM,aAAa,EAAE;AACrG,WAAO,QAAQ,SAAS,WAAW,SAAS;AAAA,EAC9C;AAAA,EAEA,MAAM,QAAQ,QAAgB,eAAkF;AAC9G,UAAM,KAAKA,aAAY,QAAQ,MAAM;AACrC,UAAM,UAAU,MAAM,KAAK,OAAO,GAAG,KAAK,CAAC,UAAU,MAAM,SAAS,UAAU,MAAM,WAAW,EAAE;AACjG,QAAI,QAAQ,SAAS,OAAQ,QAAO;AACpC,QAAI,CAAC,qBAAqB,QAAQ,aAAa,EAAG,QAAO;AACzD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,UAAkB,eAAqD;AACtF,UAAM,KAAKA,aAAY,UAAU,QAAQ;AACzC,WAAO,KAAK,cAAc,YAAY;AACpC,YAAM,UAAU,MAAM,KAAK,OAAO;AAClC,YAAM,WAAW,QAAQ,KAAK,CAAC,UAAU,MAAM,SAAS,YAAY,MAAM,aAAa,EAAE;AACzF,YAAM,SAA6B;AAAA,QACjC,MAAM;AAAA,QACN,UAAU;AAAA,QACV,GAAI,eAAe,KAAK,IAAI,EAAE,eAAe,cAAc,KAAK,EAAE,IAAI,CAAC;AAAA,QACvE,WAAW,KAAK,IAAI,KAAK,IAAI,IAAI,UAAU,aAAa,MAAM,CAAC;AAAA,MACjE;AACA,WAAK,aAAa;AAAA,QAChB,GAAG,QAAQ,OAAO,CAAC,UAAU,oBAAoB,KAAK,MAAM,oBAAoB,MAAM,CAAC;AAAA,QACvF;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,SACJ,QACA,UAC2B;AAC3B,UAAM,KAAKA,aAAY,QAAQ,MAAM;AACrC,WAAO,KAAK,cAAc,YAAY;AACpC,YAAM,UAAU,MAAM,KAAK,OAAO;AAClC,YAAM,WAAW,QAAQ,KAAK,CAAC,UAAU,MAAM,SAAS,UAAU,MAAM,WAAW,EAAE;AACrF,YAAM,SAA2B;AAAA,QAC/B,GAAG;AAAA,QACH,GAAG;AAAA,QACH,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,GAAI,SAAS,YAAY,SACrB,SAAS,QAAQ,KAAK,IACpB,EAAE,SAAS,SAAS,QAAQ,KAAK,EAAE,IACnC,EAAE,SAAS,OAAU,IACvB,CAAC;AAAA,QACL,WAAW,KAAK,IAAI,KAAK,IAAI,IAAI,UAAU,aAAa,MAAM,CAAC;AAAA,MACjE;AACA,YAAM,aAAa,wBAAwB,MAAM;AACjD,UAAI,WAAW,SAAS,OAAQ,OAAM,IAAI,UAAU,qCAAqC;AACzF,WAAK,aAAa;AAAA,QAChB,GAAG,QAAQ,OAAO,CAAC,UAAU,oBAAoB,KAAK,MAAM,oBAAoB,UAAU,CAAC;AAAA,QAC3F;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,IAAI,QAA2C;AACnD,UAAM,KAAK,cAAc,YAAY;AACnC,YAAM,aAAa,wBAAwB,MAAM;AACjD,YAAM,UAAU,MAAM,KAAK,OAAO;AAClC,YAAM,WAAW,oBAAoB,UAAU;AAC/C,YAAM,WAAW,QAAQ,KAAK,CAAC,UAAU,oBAAoB,KAAK,MAAM,QAAQ;AAChF,YAAM,WAAW,YAAY,SAAS,YAAY,WAAW,YAAY,WAAW;AACpF,WAAK,aAAa,CAAC,GAAG,QAAQ,OAAO,CAAC,UAAU,oBAAoB,KAAK,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAAA,IACrG,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YAAY,UAAiC;AACjD,UAAM,KAAKA,aAAY,UAAU,QAAQ;AACzC,UAAM,KAAK;AAAA,MAAc,YACvB,KAAK,cAAc,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,UAAU,MAAM,SAAS,YAAY,MAAM,aAAa,EAAE,CAAC;AAAA,IAC7G;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,QAA+B;AAC7C,UAAM,KAAKA,aAAY,QAAQ,MAAM;AACrC,UAAM,KAAK;AAAA,MAAc,YACvB,KAAK,cAAc,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,UAAU,MAAM,SAAS,UAAU,MAAM,WAAW,EAAE,CAAC;AAAA,IACzG;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,UAAM,KAAK,cAAc,YAAY,KAAK,aAAa,CAAC,CAAC,CAAC;AAAA,EAC5D;AAAA,EAEQ,UAAyB;AAC/B,QAAI;AACF,aAAO,KAAK,SAAS,QAAQ,KAAK,GAAG,KAAK;AAAA,IAC5C,SAAS,OAAO;AACd,YAAM,IAAI,yBAAyB,yCAAyC,KAAK,KAAK,KAAK;AAAA,IAC7F;AAAA,EACF;AAAA,EAEQ,aAAa,SAAqC;AACxD,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,IAAI,yBAAyB,4DAA4D,KAAK,GAAG;AAAA,IACzG;AACA,QAAI;AACF,WAAK,QAAQ,QAAQ,KAAK,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,IACxD,SAAS,OAAO;AACd,YAAM,IAAI,yBAAyB,0CAA0C,KAAK,KAAK,KAAK;AAAA,IAC9F;AAAA,EACF;AAAA,EAEQ,cAAiB,WAAyC;AAChE,QAAI,CAAC,KAAK,QAAS,QAAO,UAAU;AACpC,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,IAAI,yBAAyB,0EAA0E,KAAK,GAAG;AAAA,IACjH;AAAA,EACF;AACF;AAGO,SAAS,qBAAqB,QAA0B,eAAoD;AACjH,MAAI,OAAO,aAAa,UAAa,OAAO,aAAa,eAAe,SAAU,QAAO;AACzF,MAAI,OAAO,mBAAmB,UAAa,OAAO,mBAAmB,eAAe,eAAgB,QAAO;AAC3G,MAAI,eAAe,aAAa,UAAa,OAAO,aAAa,cAAc,SAAU,QAAO;AAChG,MAAI,eAAe,mBAAmB,UAAa,OAAO,mBAAmB,cAAc;AACzF,WAAO;AACT,MAAI,OAAO,YAAY,UAAa,OAAO,YAAY,eAAe,QAAS,QAAO;AACtF,MAAI,eAAe,YAAY,UAAa,OAAO,YAAY,cAAc,QAAS,QAAO;AAC7F,SAAO;AACT;AAEO,IAAM,2BAAN,cAAuC,MAAM;AAAA,EAIlD,YAAY,SAAiB,YAAoB,OAAiB;AAChE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,QAAQ;AAAA,EACf;AACF;AAEA,SAAS,iBAAiB,OAA6C;AACrE,MACE,CAACC,UAAS,KAAK,KACf,OAAO,MAAM,cAAc,YAC3B,CAAC,OAAO,SAAS,MAAM,SAAS,KAChC,MAAM,YAAY;AAElB,WAAO;AACT,MAAI,MAAM,SAAS,UAAU;AAC3B,WACE,OAAO,MAAM,aAAa,YAC1B,MAAM,SAAS,SAAS,MACvB,MAAM,kBAAkB,UAAa,OAAO,MAAM,kBAAkB;AAAA,EAEzE;AACA,MAAI,MAAM,SAAS,OAAQ,QAAO;AAClC,SACE,OAAO,MAAM,WAAW,YACxB,MAAM,OAAO,SAAS,MACrB,MAAM,oBAAoB,UACxB,OAAO,MAAM,oBAAoB,YAChC,OAAO,SAAS,MAAM,eAAe,KACrC,MAAM,mBAAmB,OAC5B,MAAM,oBAAoB,UACxB,OAAO,MAAM,oBAAoB,YAChC,OAAO,SAAS,MAAM,eAAe,KACrC,MAAM,mBAAmB,KAC1B,OAAO,MAAM,oBAAoB,YAAY,MAAM,gBAAgB,KAAK,EAAE,SAAS,OACrF,MAAM,YAAY,UAAc,OAAO,MAAM,YAAY,YAAY,MAAM,QAAQ,SAAS,OAC5F,MAAM,aAAa,UAAa,OAAO,MAAM,aAAa,cAC1D,MAAM,mBAAmB,UAAa,OAAO,MAAM,mBAAmB;AAE3E;AAEA,SAAS,wBAAwB,QAAgD;AAC/E,MAAI,CAAC,iBAAiB,MAAM,EAAG,OAAM,IAAI,UAAU,qCAAqC;AACxF,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAUD,aAAY,OAAO,UAAU,QAAQ;AAAA,MAC/C,GAAI,OAAO,eAAe,KAAK,IAAI,EAAE,eAAe,OAAO,cAAc,KAAK,EAAE,IAAI,CAAC;AAAA,MACrF,WAAW,OAAO;AAAA,IACpB;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQA,aAAY,OAAO,QAAQ,MAAM;AAAA,IACzC,GAAI,OAAO,oBAAoB,SAAY,EAAE,iBAAiB,OAAO,gBAAgB,IAAI,CAAC;AAAA,IAC1F,GAAI,OAAO,oBAAoB,SAAY,EAAE,iBAAiB,OAAO,gBAAgB,IAAI,CAAC;AAAA,IAC1F,GAAI,OAAO,YAAY,SAAY,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;AAAA,IAClE,GAAI,OAAO,aAAa,SAAY,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,IACrE,GAAI,OAAO,mBAAmB,SAAY,EAAE,gBAAgB,OAAO,eAAe,IAAI,CAAC;AAAA,IACvF,WAAW,OAAO;AAAA,EACpB;AACF;AAEA,SAAS,oBAAoB,QAAoC;AAC/D,SAAO,OAAO,SAAS,WAAW,UAAU,OAAO,QAAQ,KAAK,QAAQ,OAAO,MAAM;AACvF;AAEA,SAASA,aAAY,OAAe,MAAsB;AACxD,QAAM,aAAa,MAAM,KAAK;AAC9B,MAAI,CAAC,WAAY,OAAM,IAAI,UAAU,WAAW,IAAI,yBAAyB;AAC7E,SAAO;AACT;AAEA,SAASC,UAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAASF,qBAAyC;AAChD,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI;AACF,WAAO,OAAO;AAAA,EAChB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC3RO,IAAM,kCAAkC;AAGxC,IAAM,mCAAN,MAA+G;AAAA,EAIpH,YAAY,UAA+C,CAAC,GAAG;AAC7D,SAAK,MAAM,QAAQ,OAAO;AAC1B,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA,EAEA,MAAM,SAA0C;AAC9C,UAAM,MAAM,KAAK,WAAW,EAAE,QAAQ,KAAK,GAAG;AAC9C,QAAI,CAAC,IAAK,QAAO,CAAC;AAClB,UAAM,OAAgB,KAAK,MAAM,GAAG;AACpC,QAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC,KAAK,MAAM,WAAW,EAAG,OAAM,IAAI,MAAM,qCAAqC;AAC3G,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,IAAI,MAA2C;AACnD,UAAM,QAAQ,KAAK,MAAM;AACzB,UAAM,aAAa;AAAA,MACjB,GAAG;AAAA,MACH,OAAO;AAAA,QACL,GAAG,KAAK;AAAA,QACR,GAAI,QACA;AAAA,UACE,cAAc;AAAA,YACZ,MAAM,CAAC,aAAa,OAAO,MAAM,CAAC,EAAE,QAAQ,IAAI,MAAM,CAAC;AAAA,YACvD,MAAM,CAAC,aAAa,OAAO,MAAM,CAAC,EAAE,QAAQ,IAAI,MAAM,CAAC;AAAA,UACzD;AAAA,QACF,IACA,CAAC;AAAA,MACP;AAAA,IACF;AACA,QAAI,CAAC,YAAY,UAAU,EAAG,OAAM,IAAI,MAAM,gCAAgC;AAC9E,UAAM,QAAQ,MAAM,KAAK,OAAO;AAChC,UAAM,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,YAAY,QAAQ,OAAO,WAAW,EAAE,GAAG,UAAU;AACpF,SAAK,WAAW,EAAE,QAAQ,KAAK,KAAK,KAAK,UAAU,IAAI,CAAC;AAAA,EAC1D;AAAA,EAEA,MAAM,IAAI,IAAuD;AAC/D,YAAQ,MAAM,KAAK,OAAO,GAAG,KAAK,CAAC,SAAS,KAAK,OAAO,EAAE;AAAA,EAC5D;AAAA,EAEA,MAAM,OAAO,IAA2B;AACtC,UAAM,QAAQ,MAAM,KAAK,OAAO;AAChC,SAAK,WAAW,EAAE,QAAQ,KAAK,KAAK,KAAK,UAAU,MAAM,OAAO,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC,CAAC;AAAA,EAC5F;AAAA,EAEQ,aAAsB;AAC5B,QAAI,KAAK,QAAS,QAAO,KAAK;AAC9B,QAAI,OAAO,iBAAiB;AAC1B,YAAM,IAAI,MAAM,qEAAqE;AACvF,WAAO;AAAA,EACT;AACF;AAEA,SAAS,YAAY,OAAwC;AAC3D,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,OAAO;AACb,SACE,OAAO,KAAK,OAAO,YACnB,KAAK,GAAG,SAAS,KACjB,OAAO,KAAK,SAAS,YACrB,KAAK,KAAK,KAAK,EAAE,SAAS,KAC1B,OAAO,SAAS,KAAK,SAAS,KAC9B,OAAO,SAAS,KAAK,SAAS,KAC9B,gBAAgB,KAAK,KAAK,MACzB,KAAK,WAAW,UAAa,OAAO,KAAK,WAAW;AAEzD;AAEA,SAAS,gBAAgB,OAAyB;AAChD,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,EAAG,QAAO;AAChF,QAAM,QAAQ;AACd,MAAI,MAAM,WAAW,OAAW,QAAO;AACvC,MAAI,MAAM,SAAS,WAAc,CAAC,MAAM,QAAQ,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,QAAQ,OAAO,QAAQ,QAAQ,IAAI;AACnH,WAAO;AAAA,EACT;AACA,MAAI,MAAM,iBAAiB,UAAa,OAAO,MAAM,iBAAiB,SAAU,QAAO;AACvF,MAAI,MAAM,eAAe,UAAa,OAAO,MAAM,eAAe,SAAU,QAAO;AACnF,MAAI,MAAM,aAAa,UAAa,OAAO,MAAM,aAAa,UAAW,QAAO;AAChF,MAAI,MAAM,iBAAiB,UAAa,CAAC,CAAC,UAAU,YAAY,KAAK,EAAE,SAAS,OAAO,MAAM,YAAY,CAAC,GAAG;AAC3G,WAAO;AAAA,EACT;AACA,MAAI,MAAM,gBAAgB,UAAa,OAAO,MAAM,gBAAgB,UAAW,QAAO;AACtF,MAAI,MAAM,SAAS,QAAW;AAC5B,QAAI,CAACG,UAAS,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,aAAa,cAAc,EAAE,SAAS,OAAO,MAAM,KAAK,EAAE,CAAC;AACnG,aAAO;AACT,QAAI,MAAM,KAAK,cAAc,UAAa,MAAM,KAAK,cAAc,SAAS,MAAM,KAAK,cAAc;AACnG,aAAO;AAAA,EACX;AACA,MAAI,MAAM,WAAW,QAAW;AAC9B,QAAI,CAACA,UAAS,MAAM,MAAM,EAAG,QAAO;AACpC,QAAI,MAAM,OAAO,UAAU,UAAa,OAAO,MAAM,OAAO,UAAU,SAAU,QAAO;AACvF,QAAI,MAAM,OAAO,SAAS,UAAa,MAAM,OAAO,SAAS,SAAS,MAAM,OAAO,SAAS,KAAM,QAAO;AACzG,QAAI,MAAM,OAAO,aAAa,UAAa,OAAO,MAAM,OAAO,aAAa,UAAW,QAAO;AAC9F,QACE,MAAM,OAAO,WAAW,WACvB,CAAC,MAAM,QAAQ,MAAM,OAAO,MAAM,KACjC,CAAC,MAAM,OAAO,OAAO,MAAM,CAAC,UAAU,UAAU,UAAU,UAAU,UAAU,UAAU,MAAM,IAChG;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,MAAM,aAAa,QAAW;AAChC,QAAI,CAACA,UAAS,MAAM,QAAQ,EAAG,QAAO;AACtC,QAAI,MAAM,SAAS,WAAW,UAAa,MAAM,SAAS,WAAW,UAAU,MAAM,SAAS,WAAW,SAAS;AAChH,aAAO;AAAA,IACT;AACA,QACE,CAAC,MAAM,SAAS,kBAAkB,MAAM,SAAS,iBAAiB,MAAM,SAAS,aAAa,EAAE;AAAA,MAC9F;AAAA,IACF,GACA;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,MACE,MAAM,iBAAiB,WACtB,CAAC,MAAM,QAAQ,MAAM,YAAY,KAAK,MAAM,aAAa,WAAW,KAAK,MAAM,aAAa,KAAK,eAAe,IACjH;AACA,WAAO;AAAA,EACT;AACA,MAAI,MAAM,eAAe,QAAW;AAClC,QAAI,CAACA,UAAS,MAAM,UAAU,KAAK,CAAC,MAAM,WAAW,MAAM,MAAM,WAAW,QAAQ,EAAE,KAAK,eAAe;AACxG,aAAO;AAAA,EACX;AACA,QAAM,eAAe,MAAM;AAC3B,MAAI,iBAAiB,QAAW;AAC9B,QAAI,OAAO,iBAAiB,YAAY,iBAAiB,QAAQ,MAAM,QAAQ,YAAY,EAAG,QAAO;AACrG,UAAM,SAAS;AACf,QACE,CAAC,OAAO,YAAY,OAAO,MAAM,OAAO,IAAI,EAAE;AAAA,MAC5C,CAAC,UAAU,UAAU,UAAa,UAAU,cAAc,UAAU;AAAA,IACtE,GACA;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAASA,UAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,gBAAgB,OAAyB;AAChD,SAAO,UAAU,WAAc,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK;AACpF;;;AC1IO,IAAM,0BAAuD;AAAA,EAClE,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,wBAAwB;AAAA,EACxB,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,aAAa;AACf;AAkBO,SAAS,oBACd,QAA8B,CAAC,GAC/B,UAA8C,CAAC,GAC9B;AACjB,QAAM,SAAsC,EAAE,GAAG,yBAAyB,GAAG,QAAQ,OAAO;AAC5F,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,MAAI,MAAM,iBAAiB,OAAW,QAAO,IAAI,OAAO,cAAc,MAAM,YAAY;AAAA,WAC/E,MAAM,aAAa,OAAW,QAAO,IAAI,OAAO,UAAU,MAAM,WAAW,SAAS,OAAO;AACpG,MAAI,MAAM,aAAc,QAAO,IAAI,OAAO,YAAY,MAAM,YAAY;AACxE,aAAW,CAAC,KAAK,KAAK,KAAK;AAAA,IACzB,CAAC,OAAO,wBAAwB,MAAM,cAAc,UAAU;AAAA,IAC9D,CAAC,OAAO,kBAAkB,MAAM,cAAc,IAAI;AAAA,IAClD,CAAC,OAAO,kBAAkB,MAAM,cAAc,IAAI;AAAA,EACpD,GAAY;AACV,QAAI,UAAU,OAAW,QAAO,IAAI,KAAK,KAAK;AAAA,EAChD;AACA,MAAI,MAAM,YAAa,QAAO,IAAI,OAAO,aAAa,MAAM;AAC5D,MAAI,MAAM,cAAc;AACtB,UAAM,CAAC,MAAM,EAAE,IAAI,MAAM,aAAa,IAAI,CAAC,UAAW,iBAAiB,OAAO,MAAM,QAAQ,IAAI,KAAM;AACtG,QAAI,OAAO,SAAS,IAAI,KAAK,OAAO,SAAS,EAAE,GAAG;AAChD,aAAO,IAAI,OAAO,YAAY,OAAO,IAAI,CAAC;AAC1C,aAAO,IAAI,OAAO,aAAa,OAAO,EAAE,CAAC;AAAA,IAC3C;AAAA,EACF;AACA,MAAI,MAAM,UAAU,OAAQ,QAAO,IAAI,OAAO,gBAAgB,MAAM,SAAS,MAAM;AACnF,aAAW,CAAC,KAAK,KAAK,KAAK;AAAA,IACzB,CAAC,OAAO,kBAAkB,MAAM,UAAU,gBAAgB;AAAA,IAC1D,CAAC,OAAO,iBAAiB,MAAM,UAAU,eAAe;AAAA,IACxD,CAAC,OAAO,eAAe,MAAM,UAAU,aAAa;AAAA,EACtD,GAAY;AACV,QAAI,UAAU,UAAa,OAAO,SAAS,KAAK,EAAG,QAAO,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,EAClF;AACA,SAAO;AACT;AAGO,SAAS,oBACd,OACA,UAA8C,CAAC,GACjC;AACd,QAAM,SAAsC,EAAE,GAAG,yBAAyB,GAAG,QAAQ,OAAO;AAC5F,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,eAAe,YAAY,CAAC,MAAM,iBACjF;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,QAAM,oBAAoB,aAAa,IAAI,OAAO,YAAY;AAC9D,QAAM,eACJ,sBAAsB,YAAY,sBAAsB,cAAc,sBAAsB,QACxF,oBACA;AACN,QAAM,gBAAgB,aAAa,IAAI,OAAO,QAAQ;AACtD,QAAM,WACJ,iBAAiB,cAAc,kBAAkB,SAC7C,OACA,iBAAiB,YAAY,kBAAkB,UAC7C,QACA;AACR,QAAM,eAAe,aAAa,IAAI,OAAO,UAAU,GAAG,KAAK,KAAK;AACpE,QAAM,yBAAyB,uBAAuB,aAAa,IAAI,OAAO,sBAAsB,CAAC;AACrG,QAAM,mBAAmB,uBAAuB,aAAa,IAAI,OAAO,gBAAgB,CAAC;AACzF,QAAM,mBAAmB,uBAAuB,aAAa,IAAI,OAAO,gBAAgB,CAAC;AACzF,QAAM,eACJ,0BAA0B,oBAAoB,mBAC1C;AAAA,IACE,GAAI,yBAAyB,EAAE,YAAY,uBAAuB,IAAI,CAAC;AAAA,IACvE,GAAI,mBAAmB,EAAE,MAAM,iBAAiB,IAAI,CAAC;AAAA,IACrD,GAAI,mBAAmB,EAAE,MAAM,iBAAiB,IAAI,CAAC;AAAA,EACvD,IACA;AACN,QAAM,cAAc,aAAa,IAAI,OAAO,WAAW,MAAM,SAAS,OAAO;AAC7E,QAAM,iBAAiB,CAAC,SAAqC;AAC3D,UAAM,WAAW,aAAa,IAAI,IAAI;AACtC,QAAI,aAAa,QAAQ,SAAS,KAAK,MAAM,GAAI,QAAO;AACxD,UAAM,QAAQ,OAAO,QAAQ;AAC7B,WAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAAA,EAC1C;AACA,QAAM,aAAa,eAAe,OAAO,UAAU;AACnD,QAAM,cAAc,eAAe,OAAO,WAAW;AACrD,QAAM,eACJ,eAAe,UAAa,gBAAgB,SAAY,SAAa,CAAC,YAAY,WAAW;AAC/F,QAAM,sBAAsB,aAAa,IAAI,OAAO,cAAc;AAClE,QAAM,iBACJ,wBAAwB,UAAU,wBAAwB,UAAU,sBAAsB;AAC5F,QAAM,sBAAsB,CAAC,SAAqC;AAChE,UAAM,WAAW,aAAa,IAAI,IAAI;AACtC,QAAI,aAAa,QAAQ,SAAS,KAAK,MAAM,GAAI,QAAO;AACxD,UAAM,QAAQ,OAAO,QAAQ;AAC7B,WAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAAA,EAC1C;AACA,QAAM,mBAAmB,oBAAoB,OAAO,gBAAgB;AACpE,QAAM,kBAAkB,oBAAoB,OAAO,eAAe;AAClE,QAAM,gBAAgB,oBAAoB,OAAO,aAAa;AAC9D,QAAM,WACJ,mBAAmB,UACnB,qBAAqB,UACrB,oBAAoB,UACpB,kBAAkB,SACd;AAAA,IACE,GAAI,mBAAmB,SAAY,CAAC,IAAI,EAAE,QAAQ,eAAe;AAAA,IACjE,GAAI,qBAAqB,SAAY,CAAC,IAAI,EAAE,iBAAiB;AAAA,IAC7D,GAAI,oBAAoB,SAAY,CAAC,IAAI,EAAE,gBAAgB;AAAA,IAC3D,GAAI,kBAAkB,SAAY,CAAC,IAAI,EAAE,cAAc;AAAA,EACzD,IACA;AACN,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,IACvC,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,IAC7C,GAAI,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa;AAAA,IACrD,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,IACrC,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,aAAa,SAAY,CAAC,IAAI,EAAE,SAAS;AAAA,EAC/C;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,IACxF,UAAU,QAAQ,YAAY,MAAM;AAAA,IACpC,cAAc,QAAQ,gBAAgB,MAAM;AAAA,IAC5C,UAAU,QAAQ,YAAY,MAAM;AAAA,IACpC,cAAc,QAAQ,gBAAgB,MAAM;AAAA,IAC5C,cAAc,QAAQ,gBAAgB,MAAM;AAAA,EAC9C;AACF;AAEA,SAAS,uBAAuB,OAA6D;AAC3F,SAAO,UAAU,cAAc,UAAU,eAAe,QAAQ;AAClE;;;ACvOO,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;;;AC0EO,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,EAkBpH,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;AACxB,QAAI,KAAK,QAAQ,kBAAkB,KAAK,QAAQ,iBAAiB,KAAK,QAAQ,kBAAkB;AAC9F,WAAK,iBAAiB,YAAY;AAChC,cAAM,KAAK,YAAY;AACvB,eAAO,KAAK,QAAQ,iBAAiB,KAAK,CAAC;AAAA,MAC7C;AACA,WAAK,gBAAgB,OAAO,eAAe;AACzC,cAAM,KAAK,YAAY;AACvB,cAAM,KAAK,QAAQ,gBAAgB,UAAU;AAAA,MAC/C;AACA,WAAK,mBAAmB,OAAO,OAAO;AACpC,cAAM,KAAK,YAAY;AACvB,cAAM,KAAK,QAAQ,mBAAmB,EAAE;AAAA,MAC1C;AAAA,IACF;AACA,QACE,KAAK,QAAQ,4BACb,KAAK,QAAQ,2BACb,KAAK,QAAQ,4BACb;AACA,WAAK,2BAA2B,YAAY;AAC1C,cAAM,KAAK,YAAY;AACvB,eAAO,KAAK,QAAQ,2BAA2B,KAAK,CAAC;AAAA,MACvD;AACA,WAAK,0BAA0B,OAAO,eAAe;AACnD,cAAM,KAAK,YAAY;AACvB,cAAM,KAAK,QAAQ,0BAA0B,UAAU;AAAA,MACzD;AACA,WAAK,6BAA6B,OAAO,cAAc,WAAW;AAChE,cAAM,KAAK,YAAY;AACvB,cAAM,KAAK,QAAQ,6BAA6B,cAAc,MAAM;AAAA,MACtE;AAAA,IACF;AAAA,EACF;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,QAAM,kBAAkB,QAAQ,UAAU;AAC1C,QAAM,kBAAkB,QAAQ,UAAU;AAC1C,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,IACJ,gBAAgB,QAAQ,UAAU,iBAC9B,OAAO,wBAAwB;AAC7B,UAAI;AACF,cAAM,QAAQ,MAAM,QAAQ,aAAa;AACzC,cAAM,QAAQ,UAAU,iBAAiB,qBAAqB,EAAE,OAAO,OAAO,oBAAoB,CAAC;AAAA,MACrG,SAAS,OAAO;AACd,eAAO,kBAAkB,OAAO,SAAS,EAAE,qBAAqB,MAAM,CAAC;AAAA,MACzE;AAAA,IACF,IACA;AAAA,IACJ,iBAAiB,kBACb,YAAY;AACV,UAAI;AACF,cAAM,QAAQ,MAAM,QAAQ,aAAa;AACzC,eAAO,MAAM,gBAAgB,EAAE,OAAO,MAAM,CAAC;AAAA,MAC/C,SAAS,OAAO;AACd,eAAO,kBAAkB,OAAO,SAAS,EAAE,MAAM,CAAC;AAAA,MACpD;AAAA,IACF,IACA;AAAA,IACJ,gBAAgB,QAAQ,UAAU,iBAC9B,OAAO,wBAAwB;AAC7B,UAAI;AACF,cAAM,QAAQ,MAAM,QAAQ,aAAa;AACzC,cAAM,QAAQ,UAAU,iBAAiB,qBAAqB,EAAE,OAAO,OAAO,oBAAoB,CAAC;AAAA,MACrG,SAAS,OAAO;AACd,eAAO,kBAAkB,OAAO,SAAS,EAAE,qBAAqB,MAAM,CAAC;AAAA,MACzE;AAAA,IACF,IACA;AAAA,IACJ,iBAAiB,kBACb,YAAY;AACV,UAAI;AACF,cAAM,QAAQ,MAAM,QAAQ,aAAa;AACzC,eAAO,MAAM,gBAAgB,EAAE,OAAO,MAAM,CAAC;AAAA,MAC/C,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;","names":["getBrowserStorage","normalizeId","isRecord","isRecord"]}
package/dist/react.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  queryKeepItems,
12
12
  reorderKeepItems,
13
13
  revalidateKeepItems
14
- } from "./chunk-5XSSH3TO.js";
14
+ } from "./chunk-EMOPFB5D.js";
15
15
  import {
16
16
  parseKeepMeta
17
17
  } from "./chunk-5W4QSJHV.js";
@@ -21,7 +21,7 @@ import {
21
21
  normalizeKeepTags,
22
22
  persistKeepItems,
23
23
  removeKeepItems
24
- } from "./chunk-QRPQYE7K.js";
24
+ } from "./chunk-SLH4DFYQ.js";
25
25
 
26
26
  // src/react/components/KeepButton.tsx
27
27
  import {
package/dist/storage.d.ts CHANGED
@@ -243,6 +243,7 @@ declare class LocalStorageAdapter<TMeta = Record<string, unknown>> implements St
243
243
  setCollection(collection: KeepCollectionDefinition): Promise<void>;
244
244
  removeCollection(id: string, scope?: KeepScope): Promise<void>;
245
245
  getCollectionMemberships(): Promise<KeepCollectionMembership[]>;
246
+ private readMemberships;
246
247
  setCollectionMembership(membership: KeepCollectionMembership): Promise<void>;
247
248
  removeCollectionMembership(collectionId: string, itemId: string, scope?: KeepScope): Promise<void>;
248
249
  set(item: KeepItem<TMeta>): Promise<void>;
package/dist/storage.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  createBrowserStorageAdapter,
18
18
  createScopedStorageAdapter,
19
19
  createStorageAdapter
20
- } from "./chunk-QRPQYE7K.js";
20
+ } from "./chunk-SLH4DFYQ.js";
21
21
  export {
22
22
  DEFAULT_INDEXEDDB_DATABASE,
23
23
  DEFAULT_INDEXEDDB_STORE,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keepkit/core",
3
- "version": "0.28.6",
3
+ "version": "0.28.7",
4
4
  "description": "A flexible save-and-collect toolkit for React apps.",
5
5
  "type": "module",
6
6
  "license": "MIT",