@keepkit/core 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -139,4 +139,4 @@ export {
139
139
  reconcileKeepItems,
140
140
  KeepStore
141
141
  };
142
- //# sourceMappingURL=chunk-J7NKIOXV.js.map
142
+ //# sourceMappingURL=chunk-L4KP6M5R.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/query.ts","../src/revalidation.ts","../src/store.ts"],"sourcesContent":["import type { KeepItem } from \"./types\";\n\nexport type KeepListOptions<TMeta = Record<string, unknown>> = {\n targetType?: string;\n tag?: string;\n tags?: string[];\n sort?: {\n by: \"savedAt\" | \"updatedAt\";\n direction?: \"asc\" | \"desc\";\n };\n searchQuery?: string;\n search?: {\n query: string;\n mode?: \"and\" | \"or\";\n tokenize?: boolean;\n fields?: Array<\"note\" | \"meta\" | \"tags\">;\n };\n sortBy?: \"savedAt\" | \"updatedAt\";\n order?: \"asc\" | \"desc\";\n limit?: number;\n offset?: number;\n filter?: (item: KeepItem<TMeta>) => boolean;\n filterFn?: (item: KeepItem<TMeta>) => boolean;\n savedBetween?: readonly [Date | number, Date | number];\n};\n\nexport type QueryKeepItemsResult<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n totalCount: number;\n tagCounts: Record<string, number>;\n};\n\n/** Apply the same filtering and pagination rules as useKeepList without React. */\nexport function queryKeepItems<TMeta = Record<string, unknown>>(\n source: KeepItem<TMeta>[],\n options: KeepListOptions<TMeta> = {},\n): QueryKeepItemsResult<TMeta> {\n const filtered = source.filter((item) => {\n const [from, to] = options.savedBetween ?? [];\n const savedAt = item.savedAt;\n const lowerBound = from === undefined ? undefined : toTimestamp(from);\n const upperBound = to === undefined ? undefined : toTimestamp(to);\n return (\n (options.targetType === undefined || item.targetType === options.targetType) &&\n (options.tag === undefined || item.tags?.includes(options.tag) === true) &&\n (options.tags === undefined || options.tags.every((tag) => item.tags?.includes(tag))) &&\n (lowerBound === undefined || savedAt >= lowerBound) &&\n (upperBound === undefined || savedAt <= upperBound) &&\n matchesSearch(item, options.searchQuery, options.search) &&\n (options.filter?.(item) ?? true) &&\n (options.filterFn?.(item) ?? true)\n );\n });\n const tagCounts = getTagCounts(filtered);\n const sortBy = options.sortBy ?? options.sort?.by;\n const direction = (options.order ?? options.sort?.direction) === \"asc\" ? 1 : -1;\n const sorted = sortBy ? [...filtered].sort((a, b) => (a[sortBy] - b[sortBy]) * direction) : filtered;\n const offset = Math.max(0, options.offset ?? 0);\n const items =\n options.limit === undefined ? sorted.slice(offset) : sorted.slice(offset, offset + Math.max(0, options.limit));\n return { items, totalCount: sorted.length, tagCounts };\n}\n\nexport function getTagCounts<TMeta = Record<string, unknown>>(items: KeepItem<TMeta>[]): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const item of items) {\n for (const tag of item.tags ?? []) counts[tag] = (counts[tag] ?? 0) + 1;\n }\n return Object.fromEntries(Object.entries(counts).sort(([a], [b]) => a.localeCompare(b)));\n}\n\nfunction matchesSearch<TMeta>(\n item: KeepItem<TMeta>,\n searchQuery?: string,\n search?: KeepListOptions<TMeta>[\"search\"],\n): boolean {\n const query = search?.query ?? searchQuery;\n if (!query?.trim()) return true;\n const fields = search?.fields ?? [\"note\", \"meta\", \"tags\"];\n const values = fields.map((field) => {\n if (field === \"note\") return item.note ?? \"\";\n if (field === \"tags\") return (item.tags ?? []).join(\" \");\n try {\n return JSON.stringify(item.meta) ?? \"\";\n } catch {\n return String(item.meta);\n }\n });\n const text = values.join(\" \").toLocaleLowerCase();\n if (!search) return text.includes(query.trim().toLocaleLowerCase());\n const normalized = query.trim().toLocaleLowerCase();\n const needles = search.tokenize === false ? [normalized] : normalized.split(/\\s+/).filter(Boolean);\n const matches = needles.map((needle) => text.includes(needle));\n return search.mode === \"or\" ? matches.some(Boolean) : matches.every(Boolean);\n}\n\nfunction toTimestamp(value: Date | number): number {\n return value instanceof Date ? value.getTime() : value;\n}\n","import type { KeepItem, StorageAdapter } from \"./types\";\n\nexport type KeepItemStatus = \"available\" | \"deleted\" | \"private\" | \"expired\" | \"unknown\";\n\nexport type KeepItemRevalidationResult<TMeta = Record<string, unknown>> =\n | { status: \"available\"; meta?: TMeta }\n | { status: Exclude<KeepItemStatus, \"available\">; reason?: string };\n\nexport type KeepItemRevalidator<TMeta = Record<string, unknown>> = (\n item: KeepItem<TMeta>,\n) =>\n | KeepItemRevalidationResult<TMeta>\n | KeepItemRevalidationResult<TMeta>[\"status\"]\n | Promise<KeepItemRevalidationResult<TMeta> | KeepItemRevalidationResult<TMeta>[\"status\"]>;\n\nexport type KeepItemMetadataRefresher<TMeta = Record<string, unknown>> = (\n item: KeepItem<TMeta>,\n) => TMeta | Promise<TMeta>;\n\n/** Return whether source metadata should be fetched again based on its age. */\nexport function isKeepItemMetadataStale<TMeta>(\n item: KeepItem<TMeta>,\n maxAgeMs: number,\n now: () => number = Date.now,\n): boolean {\n return item.metaUpdatedAt === undefined || now() - item.metaUpdatedAt >= maxAgeMs;\n}\n\nexport type KeepItemRevalidationRecord<TMeta = Record<string, unknown>> = {\n item: KeepItem<TMeta>;\n status: KeepItemStatus;\n reason?: string;\n updated: boolean;\n};\n\nexport type RevalidateKeepItemsOptions = {\n /** Statuses that should be removed after they are detected. Detection is the default. */\n removeStatuses?: Array<Exclude<KeepItemStatus, \"available\">>;\n now?: () => number;\n};\n\nexport type KeepItemRevalidationSummary<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n checked: number;\n updated: number;\n removed: number;\n updatedItems: KeepItem<TMeta>[];\n removedIds: string[];\n results: KeepItemRevalidationRecord<TMeta>[];\n};\n\n/** Revalidate saved items without coupling the checker to a network client. */\nexport async function revalidateKeepItems<TMeta = Record<string, unknown>>(\n source: KeepItem<TMeta>[],\n revalidator: KeepItemRevalidator<TMeta>,\n options: RevalidateKeepItemsOptions = {},\n): Promise<KeepItemRevalidationSummary<TMeta>> {\n const removeStatuses = new Set(options.removeStatuses ?? []);\n const now = options.now ?? Date.now;\n const items: KeepItem<TMeta>[] = [];\n const updatedItems: KeepItem<TMeta>[] = [];\n const removedIds: string[] = [];\n const results: KeepItemRevalidationRecord<TMeta>[] = [];\n\n for (const item of source) {\n const rawResult = await revalidator(item);\n const result: KeepItemRevalidationResult<TMeta> = typeof rawResult === \"string\" ? { status: rawResult } : rawResult;\n if (result.status === \"available\") {\n const timestamp = now();\n const updated =\n result.meta === undefined\n ? item\n : { ...item, meta: result.meta, metaUpdatedAt: timestamp, updatedAt: timestamp };\n const didUpdate = updated !== item;\n items.push(updated);\n if (didUpdate) updatedItems.push(updated);\n results.push({ item: updated, status: \"available\", updated: didUpdate });\n continue;\n }\n\n const shouldRemove = removeStatuses.has(result.status);\n if (shouldRemove) removedIds.push(item.id);\n else items.push(item);\n results.push({ item, status: result.status, reason: result.reason, updated: false });\n }\n\n return {\n items,\n checked: source.length,\n updated: updatedItems.length,\n removed: removedIds.length,\n updatedItems,\n removedIds,\n results,\n };\n}\n\n/** Revalidate and persist saved items for framework-neutral applications. */\nexport async function reconcileKeepItems<TMeta = Record<string, unknown>>(\n storage: StorageAdapter<TMeta>,\n revalidator: KeepItemRevalidator<TMeta>,\n options: RevalidateKeepItemsOptions = {},\n): Promise<KeepItemRevalidationSummary<TMeta>> {\n const source = await storage.getAll();\n const summary = await revalidateKeepItems(source, revalidator, options);\n if (summary.updatedItems.length > 0) await persistItems(storage, summary.updatedItems);\n if (summary.removedIds.length > 0) await removeItems(storage, summary.removedIds);\n return summary;\n}\n\nasync function persistItems<TMeta>(storage: StorageAdapter<TMeta>, items: KeepItem<TMeta>[]): Promise<void> {\n if (storage.setMany) {\n await storage.setMany(items);\n return;\n }\n for (const item of items) await storage.set(item);\n}\n\nasync function removeItems<TMeta>(storage: StorageAdapter<TMeta>, ids: string[]): Promise<void> {\n if (storage.removeMany) {\n await storage.removeMany(ids);\n return;\n }\n for (const id of ids) await storage.remove(id);\n}\n","import type {\n KeepItemMetadataRefresher,\n KeepItemRevalidationSummary,\n KeepItemRevalidator,\n RevalidateKeepItemsOptions,\n} from \"./revalidation\";\nimport type { KeepItem } from \"./types\";\n\nexport type KeepStoreState<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n isLoading: boolean;\n isHydrated: boolean;\n isMutating: boolean;\n error: unknown | null;\n};\n\nexport type KeepStoreActions<TMeta = Record<string, unknown>> = {\n saveItem: (item: KeepItem<TMeta>) => Promise<void>;\n updateNote: (id: string, note?: string) => Promise<void>;\n updateTags: (id: string, tags?: string[]) => Promise<void>;\n updateTagsBatch: (ids: string[], tags?: string[]) => Promise<void>;\n addTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeItem: (id: string) => Promise<void>;\n removeItems: (ids: string[]) => Promise<void>;\n clear: () => Promise<void>;\n refresh: () => Promise<void>;\n refreshItemMetadata: (id: string, refresh: KeepItemMetadataRefresher<TMeta>) => Promise<void>;\n revalidateItems: (\n revalidator: KeepItemRevalidator<TMeta>,\n options?: RevalidateKeepItemsOptions,\n ) => Promise<KeepItemRevalidationSummary<TMeta>>;\n};\n\nexport class KeepStore<TMeta = Record<string, unknown>> {\n private state: KeepStoreState<TMeta>;\n private readonly listeners = new Set<() => void>();\n\n constructor(initialState: KeepStoreState<TMeta>) {\n this.state = initialState;\n }\n\n getSnapshot = (): KeepStoreState<TMeta> => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n setState(next: Partial<KeepStoreState<TMeta>>): void {\n let changed = false;\n for (const key of Object.keys(next) as Array<keyof KeepStoreState<TMeta>>) {\n if (!Object.is(this.state[key], next[key])) {\n changed = true;\n break;\n }\n }\n if (!changed) return;\n this.state = { ...this.state, ...next };\n for (const listener of this.listeners) listener();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/query.ts","../src/revalidation.ts","../src/store.ts"],"sourcesContent":["import type { KeepItem } from \"./types\";\n\nexport type KeepListOptions<TMeta = Record<string, unknown>> = {\n targetType?: string;\n tag?: string;\n tags?: string[];\n sort?: {\n by: \"savedAt\" | \"updatedAt\";\n direction?: \"asc\" | \"desc\";\n };\n searchQuery?: string;\n search?: {\n query: string;\n mode?: \"and\" | \"or\";\n tokenize?: boolean;\n fields?: Array<\"note\" | \"meta\" | \"tags\">;\n };\n sortBy?: \"savedAt\" | \"updatedAt\";\n order?: \"asc\" | \"desc\";\n limit?: number;\n offset?: number;\n filter?: (item: KeepItem<TMeta>) => boolean;\n filterFn?: (item: KeepItem<TMeta>) => boolean;\n savedBetween?: readonly [Date | number, Date | number];\n};\n\nexport type QueryKeepItemsResult<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n totalCount: number;\n tagCounts: Record<string, number>;\n};\n\n/** Apply the same filtering and pagination rules as useKeepList without React. */\nexport function queryKeepItems<TMeta = Record<string, unknown>>(\n source: KeepItem<TMeta>[],\n options: KeepListOptions<TMeta> = {},\n): QueryKeepItemsResult<TMeta> {\n const filtered = source.filter((item) => {\n const [from, to] = options.savedBetween ?? [];\n const savedAt = item.savedAt;\n const lowerBound = from === undefined ? undefined : toTimestamp(from);\n const upperBound = to === undefined ? undefined : toTimestamp(to);\n return (\n (options.targetType === undefined || item.targetType === options.targetType) &&\n (options.tag === undefined || item.tags?.includes(options.tag) === true) &&\n (options.tags === undefined || options.tags.every((tag) => item.tags?.includes(tag))) &&\n (lowerBound === undefined || savedAt >= lowerBound) &&\n (upperBound === undefined || savedAt <= upperBound) &&\n matchesSearch(item, options.searchQuery, options.search) &&\n (options.filter?.(item) ?? true) &&\n (options.filterFn?.(item) ?? true)\n );\n });\n const tagCounts = getTagCounts(filtered);\n const sortBy = options.sortBy ?? options.sort?.by;\n const direction = (options.order ?? options.sort?.direction) === \"asc\" ? 1 : -1;\n const sorted = sortBy ? [...filtered].sort((a, b) => (a[sortBy] - b[sortBy]) * direction) : filtered;\n const offset = Math.max(0, options.offset ?? 0);\n const items =\n options.limit === undefined ? sorted.slice(offset) : sorted.slice(offset, offset + Math.max(0, options.limit));\n return { items, totalCount: sorted.length, tagCounts };\n}\n\nexport function getTagCounts<TMeta = Record<string, unknown>>(items: KeepItem<TMeta>[]): Record<string, number> {\n const counts: Record<string, number> = {};\n for (const item of items) {\n for (const tag of item.tags ?? []) counts[tag] = (counts[tag] ?? 0) + 1;\n }\n return Object.fromEntries(Object.entries(counts).sort(([a], [b]) => a.localeCompare(b)));\n}\n\nfunction matchesSearch<TMeta>(\n item: KeepItem<TMeta>,\n searchQuery?: string,\n search?: KeepListOptions<TMeta>[\"search\"],\n): boolean {\n const query = search?.query ?? searchQuery;\n if (!query?.trim()) return true;\n const fields = search?.fields ?? [\"note\", \"meta\", \"tags\"];\n const values = fields.map((field) => {\n if (field === \"note\") return item.note ?? \"\";\n if (field === \"tags\") return (item.tags ?? []).join(\" \");\n try {\n return JSON.stringify(item.meta) ?? \"\";\n } catch {\n return String(item.meta);\n }\n });\n const text = values.join(\" \").toLocaleLowerCase();\n if (!search) return text.includes(query.trim().toLocaleLowerCase());\n const normalized = query.trim().toLocaleLowerCase();\n const needles = search.tokenize === false ? [normalized] : normalized.split(/\\s+/).filter(Boolean);\n const matches = needles.map((needle) => text.includes(needle));\n return search.mode === \"or\" ? matches.some(Boolean) : matches.every(Boolean);\n}\n\nfunction toTimestamp(value: Date | number): number {\n return value instanceof Date ? value.getTime() : value;\n}\n","import type { KeepItem, StorageAdapter } from \"./types\";\n\nexport type KeepItemStatus = \"available\" | \"deleted\" | \"private\" | \"expired\" | \"unknown\";\n\nexport type KeepItemRevalidationResult<TMeta = Record<string, unknown>> =\n | { status: \"available\"; meta?: TMeta }\n | { status: Exclude<KeepItemStatus, \"available\">; reason?: string };\n\nexport type KeepItemRevalidator<TMeta = Record<string, unknown>> = (\n item: KeepItem<TMeta>,\n) =>\n | KeepItemRevalidationResult<TMeta>\n | KeepItemRevalidationResult<TMeta>[\"status\"]\n | Promise<KeepItemRevalidationResult<TMeta> | KeepItemRevalidationResult<TMeta>[\"status\"]>;\n\nexport type KeepItemMetadataRefresher<TMeta = Record<string, unknown>> = (\n item: KeepItem<TMeta>,\n) => TMeta | Promise<TMeta>;\n\n/** Return whether source metadata should be fetched again based on its age. */\nexport function isKeepItemMetadataStale<TMeta>(\n item: KeepItem<TMeta>,\n maxAgeMs: number,\n now: () => number = Date.now,\n): boolean {\n return item.metaUpdatedAt === undefined || now() - item.metaUpdatedAt >= maxAgeMs;\n}\n\nexport type KeepItemRevalidationRecord<TMeta = Record<string, unknown>> = {\n item: KeepItem<TMeta>;\n status: KeepItemStatus;\n reason?: string;\n updated: boolean;\n};\n\nexport type RevalidateKeepItemsOptions = {\n /** Statuses that should be removed after they are detected. Detection is the default. */\n removeStatuses?: Array<Exclude<KeepItemStatus, \"available\">>;\n now?: () => number;\n};\n\nexport type KeepItemRevalidationSummary<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n checked: number;\n updated: number;\n removed: number;\n updatedItems: KeepItem<TMeta>[];\n removedIds: string[];\n results: KeepItemRevalidationRecord<TMeta>[];\n};\n\n/** Revalidate saved items without coupling the checker to a network client. */\nexport async function revalidateKeepItems<TMeta = Record<string, unknown>>(\n source: KeepItem<TMeta>[],\n revalidator: KeepItemRevalidator<TMeta>,\n options: RevalidateKeepItemsOptions = {},\n): Promise<KeepItemRevalidationSummary<TMeta>> {\n const removeStatuses = new Set(options.removeStatuses ?? []);\n const now = options.now ?? Date.now;\n const items: KeepItem<TMeta>[] = [];\n const updatedItems: KeepItem<TMeta>[] = [];\n const removedIds: string[] = [];\n const results: KeepItemRevalidationRecord<TMeta>[] = [];\n\n for (const item of source) {\n const rawResult = await revalidator(item);\n const result: KeepItemRevalidationResult<TMeta> = typeof rawResult === \"string\" ? { status: rawResult } : rawResult;\n if (result.status === \"available\") {\n const timestamp = now();\n const updated =\n result.meta === undefined\n ? item\n : { ...item, meta: result.meta, metaUpdatedAt: timestamp, updatedAt: timestamp };\n const didUpdate = updated !== item;\n items.push(updated);\n if (didUpdate) updatedItems.push(updated);\n results.push({ item: updated, status: \"available\", updated: didUpdate });\n continue;\n }\n\n const shouldRemove = removeStatuses.has(result.status);\n if (shouldRemove) removedIds.push(item.id);\n else items.push(item);\n results.push({ item, status: result.status, reason: result.reason, updated: false });\n }\n\n return {\n items,\n checked: source.length,\n updated: updatedItems.length,\n removed: removedIds.length,\n updatedItems,\n removedIds,\n results,\n };\n}\n\n/** Revalidate and persist saved items for framework-neutral applications. */\nexport async function reconcileKeepItems<TMeta = Record<string, unknown>>(\n storage: StorageAdapter<TMeta>,\n revalidator: KeepItemRevalidator<TMeta>,\n options: RevalidateKeepItemsOptions = {},\n): Promise<KeepItemRevalidationSummary<TMeta>> {\n const source = await storage.getAll();\n const summary = await revalidateKeepItems(source, revalidator, options);\n if (summary.updatedItems.length > 0) await persistItems(storage, summary.updatedItems);\n if (summary.removedIds.length > 0) await removeItems(storage, summary.removedIds);\n return summary;\n}\n\nasync function persistItems<TMeta>(storage: StorageAdapter<TMeta>, items: KeepItem<TMeta>[]): Promise<void> {\n if (storage.setMany) {\n await storage.setMany(items);\n return;\n }\n for (const item of items) await storage.set(item);\n}\n\nasync function removeItems<TMeta>(storage: StorageAdapter<TMeta>, ids: string[]): Promise<void> {\n if (storage.removeMany) {\n await storage.removeMany(ids);\n return;\n }\n for (const id of ids) await storage.remove(id);\n}\n","import type {\n KeepItemMetadataRefresher,\n KeepItemRevalidationSummary,\n KeepItemRevalidator,\n RevalidateKeepItemsOptions,\n} from \"./revalidation\";\nimport type { KeepChangeContext, KeepItem } from \"./types\";\n\nexport type KeepStoreState<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n isLoading: boolean;\n isHydrated: boolean;\n isMutating: boolean;\n error: unknown | null;\n lastChange?: KeepChangeContext<TMeta>;\n};\n\nexport type KeepStoreActions<TMeta = Record<string, unknown>> = {\n saveItem: (item: KeepItem<TMeta>) => Promise<void>;\n updateNote: (id: string, note?: string) => Promise<void>;\n updateTags: (id: string, tags?: string[]) => Promise<void>;\n updateTagsBatch: (ids: string[], tags?: string[]) => Promise<void>;\n addTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeItem: (id: string) => Promise<void>;\n removeItems: (ids: string[]) => Promise<void>;\n clear: () => Promise<void>;\n refresh: () => Promise<void>;\n refreshItemMetadata: (id: string, refresh: KeepItemMetadataRefresher<TMeta>) => Promise<void>;\n revalidateItems: (\n revalidator: KeepItemRevalidator<TMeta>,\n options?: RevalidateKeepItemsOptions,\n ) => Promise<KeepItemRevalidationSummary<TMeta>>;\n};\n\nexport class KeepStore<TMeta = Record<string, unknown>> {\n private state: KeepStoreState<TMeta>;\n private readonly listeners = new Set<() => void>();\n\n constructor(initialState: KeepStoreState<TMeta>) {\n this.state = initialState;\n }\n\n getSnapshot = (): KeepStoreState<TMeta> => this.state;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n };\n\n setState(next: Partial<KeepStoreState<TMeta>>): void {\n let changed = false;\n for (const key of Object.keys(next) as Array<keyof KeepStoreState<TMeta>>) {\n if (!Object.is(this.state[key], next[key])) {\n changed = true;\n break;\n }\n }\n if (!changed) return;\n this.state = { ...this.state, ...next };\n for (const listener of this.listeners) listener();\n }\n}\n"],"mappings":"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","names":[]}
package/dist/core.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { K as KeepSchema, b as KeepInvalidItemPolicy, a as KeepItem, S as StorageAdapter, c as KeepPluginContext, d as KeepPlugin } from './types-BRfvVnCA.js';
2
2
  export { e as KeepAction, f as KeepChangeContext, g as KeepChangePhase, h as KeepConflictContext, i as KeepConflictResolver, j as KeepErrorContext, k as KeepErrorHandler, l as KeepEventHandlers, m as KeepItemInput, n as KeepSchemaParseResult, o as KeepStorageAccessError, p as KeepStorageError, q as KeepStorageOperation, r as KeepStorageParseError, s as KeepStorageQuotaError, t as KeepSyncState, u as KeepSyncStatus, R as RemoteSyncDriver, v as RemoteSyncResult, w as SyncCapableStorageAdapter, x as SyncOperation, y as SyncQueueAdapter, z as normalizeKeepTags } from './types-BRfvVnCA.js';
3
- export { K as KeepItemMetadataRefresher, a as KeepItemRevalidationRecord, b as KeepItemRevalidationResult, c as KeepItemRevalidationSummary, d as KeepItemRevalidator, e as KeepItemStatus, f as KeepListOptions, g as KeepStore, h as KeepStoreActions, i as KeepStoreState, Q as QueryKeepItemsResult, R as RevalidateKeepItemsOptions, j as getTagCounts, k as isKeepItemMetadataStale, q as queryKeepItems, r as reconcileKeepItems, l as revalidateKeepItems } from './store-DyjKY0s4.js';
3
+ export { K as KeepItemMetadataRefresher, a as KeepItemRevalidationRecord, b as KeepItemRevalidationResult, c as KeepItemRevalidationSummary, d as KeepItemRevalidator, e as KeepItemStatus, f as KeepListOptions, g as KeepStore, h as KeepStoreActions, i as KeepStoreState, Q as QueryKeepItemsResult, R as RevalidateKeepItemsOptions, j as getTagCounts, k as isKeepItemMetadataStale, q as queryKeepItems, r as reconcileKeepItems, l as revalidateKeepItems } from './store-B-pEydSU.js';
4
4
  export { KeepSchemaValidationError, parseKeepMeta, validateKeepItem } from './schema.js';
5
5
  export { BrowserStorageAdapterOptions, DEFAULT_INDEXEDDB_DATABASE, DEFAULT_INDEXEDDB_STORE, DEFAULT_STORAGE_KEY, DEFAULT_SYNC_QUEUE_DATABASE, DEFAULT_SYNC_QUEUE_KEY, DEFAULT_SYNC_QUEUE_STORE, FallbackStorageAdapter, FallbackStorageAdapterOptions, FallbackSyncQueueAdapter, FallbackSyncQueueAdapterOptions, IndexedDBAdapter, IndexedDBAdapterOptions, IndexedDBSyncQueueAdapter, IndexedDBSyncQueueOptions, LocalStorageAdapter, LocalStorageAdapterOptions, LocalStorageSyncQueueAdapter, LocalStorageSyncQueueOptions, StorageAdapterFactoryOptions, SyncStorageAdapter, SyncStorageAdapterOptions, createBrowserStorageAdapter, createStorageAdapter } from './storage.js';
6
6
 
package/dist/core.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  queryKeepItems,
6
6
  reconcileKeepItems,
7
7
  revalidateKeepItems
8
- } from "./chunk-J7NKIOXV.js";
8
+ } from "./chunk-L4KP6M5R.js";
9
9
  import {
10
10
  KeepSchemaValidationError,
11
11
  parseKeepMeta,
package/dist/react.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode, ButtonHTMLAttributes, MouseEvent, HTMLAttributes, ReactElement, PropsWithChildren, ComponentType } from 'react';
3
- import { K as KeepItemMetadataRefresher, d as KeepItemRevalidator, R as RevalidateKeepItemsOptions, c as KeepItemRevalidationSummary, f as KeepListOptions, g as KeepStore, h as KeepStoreActions } from './store-DyjKY0s4.js';
4
- export { b as KeepItemRevalidationResult, e as KeepItemStatus, k as isKeepItemMetadataStale } from './store-DyjKY0s4.js';
5
- import { m as KeepItemInput, a as KeepItem, l as KeepEventHandlers, S as StorageAdapter, d as KeepPlugin, K as KeepSchema, b as KeepInvalidItemPolicy, t as KeepSyncState } from './types-BRfvVnCA.js';
3
+ import { K as KeepItemMetadataRefresher, d as KeepItemRevalidator, R as RevalidateKeepItemsOptions, c as KeepItemRevalidationSummary, f as KeepListOptions, g as KeepStore, h as KeepStoreActions } from './store-B-pEydSU.js';
4
+ export { b as KeepItemRevalidationResult, e as KeepItemStatus, k as isKeepItemMetadataStale } from './store-B-pEydSU.js';
5
+ import { m as KeepItemInput, a as KeepItem, l as KeepEventHandlers, S as StorageAdapter, d as KeepPlugin, K as KeepSchema, b as KeepInvalidItemPolicy, f as KeepChangeContext, t as KeepSyncState } from './types-BRfvVnCA.js';
6
6
 
7
7
  type UseKeepItemResult<TMeta = Record<string, unknown>> = {
8
8
  item: KeepItem<TMeta> | undefined;
@@ -98,6 +98,7 @@ type KeepContextValue<TMeta = Record<string, unknown>> = {
98
98
  isHydrated: boolean;
99
99
  isMutating: boolean;
100
100
  error: unknown | null;
101
+ lastChange?: KeepChangeContext<TMeta>;
101
102
  syncState: KeepSyncState;
102
103
  saveItem: (item: KeepItem<TMeta>) => Promise<void>;
103
104
  updateNote: (id: string, note?: string) => Promise<void>;
package/dist/react.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  isKeepItemMetadataStale,
5
5
  queryKeepItems,
6
6
  revalidateKeepItems
7
- } from "./chunk-J7NKIOXV.js";
7
+ } from "./chunk-L4KP6M5R.js";
8
8
  import {
9
9
  parseKeepMeta
10
10
  } from "./chunk-THZ3ACR2.js";
@@ -55,12 +55,13 @@ function KeepProvider({
55
55
  isLoading: true,
56
56
  isHydrated: false,
57
57
  isMutating: false,
58
- error: null
58
+ error: null,
59
+ lastChange: void 0
59
60
  });
60
61
  }
61
62
  const store = storeRef.current;
62
63
  const state = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
63
- const { items, isLoading, isHydrated, isMutating, error } = state;
64
+ const { items, isLoading, isHydrated, isMutating, error, lastChange } = state;
64
65
  const itemsRef = useRef(items);
65
66
  const pluginsRef = useRef(plugins);
66
67
  pluginsRef.current = plugins;
@@ -194,6 +195,7 @@ function KeepProvider({
194
195
  if (plan.pluginContext) await runAfterPlugins(plan.pluginContext);
195
196
  if (plan.pluginContext) {
196
197
  const change = { ...plan.pluginContext, phase: "local" };
198
+ store.setState({ lastChange: change });
197
199
  void Promise.resolve(handlersRef.current.onChange?.(change)).catch(
198
200
  (cause) => reportError(cause, { action, id })
199
201
  );
@@ -467,6 +469,7 @@ function KeepProvider({
467
469
  isHydrated,
468
470
  isMutating,
469
471
  error,
472
+ lastChange,
470
473
  syncState,
471
474
  saveItem,
472
475
  updateNote,
@@ -485,6 +488,7 @@ function KeepProvider({
485
488
  [
486
489
  clear,
487
490
  error,
491
+ lastChange,
488
492
  flushSync,
489
493
  isHydrated,
490
494
  isLoading,
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/hooks/useKeepItem.ts","../src/KeepProvider.tsx","../src/hooks/useKeepStoreSelector.ts","../src/hooks/useKeepList.ts","../src/hooks/useKeepShortcut.ts","../src/KeepButton.tsx","../src/createKeepKit.tsx"],"sourcesContent":["import { useCallback } from \"react\";\nimport { useKeepStore } from \"../KeepProvider\";\nimport type { KeepItemMetadataRefresher } from \"../revalidation\";\nimport type { KeepItem, KeepItemInput } from \"../types\";\nimport { useKeepStoreSelector } from \"./useKeepStoreSelector\";\n\nexport type UseKeepItemResult<TMeta = Record<string, unknown>> = {\n item: KeepItem<TMeta> | undefined;\n isSaved: boolean;\n isLoading: boolean;\n isMutating: boolean;\n error: unknown | null;\n save: () => Promise<void>;\n remove: () => Promise<void>;\n toggle: () => Promise<void>;\n updateNote: (note?: string) => Promise<void>;\n updateTags: (tags?: string[]) => Promise<void>;\n refreshMetadata: (refresh: KeepItemMetadataRefresher<TMeta>) => Promise<void>;\n};\n\nexport function useKeepItem<TMeta = Record<string, unknown>>(\n id: string,\n itemPayload?: KeepItemInput<TMeta>,\n): UseKeepItemResult<TMeta> {\n const { store, actions } = useKeepStore<TMeta>();\n const item = useKeepStoreSelector(\n store,\n useCallback((state) => state.items.find((current) => current.id === id), [id]),\n );\n const isLoading = useKeepStoreSelector(\n store,\n useCallback((state) => state.isLoading, []),\n );\n const isMutating = useKeepStoreSelector(\n store,\n useCallback((state) => state.isMutating, []),\n );\n const error = useKeepStoreSelector(\n store,\n useCallback((state) => state.error, []),\n );\n\n const save = useCallback(async () => {\n if (!itemPayload) {\n throw new Error(`An itemPayload is required to save item \"${id}\".`);\n }\n const now = Date.now();\n await actions.saveItem({\n id,\n ...itemPayload,\n savedAt: item?.savedAt ?? now,\n updatedAt: now,\n });\n }, [actions, id, item?.savedAt, itemPayload]);\n\n const remove = useCallback(() => actions.removeItem(id), [actions, id]);\n const toggle = useCallback(() => (item ? remove() : save()), [item, remove, save]);\n const updateNote = useCallback((note?: string) => actions.updateNote(id, note), [actions, id]);\n const updateTags = useCallback((tags?: string[]) => actions.updateTags(id, tags), [actions, id]);\n const refreshMetadata = useCallback(\n (refresh: KeepItemMetadataRefresher<TMeta>) => actions.refreshItemMetadata(id, refresh),\n [actions, id],\n );\n\n return {\n item,\n isSaved: Boolean(item),\n isLoading,\n isMutating,\n error,\n save,\n remove,\n toggle,\n updateNote,\n updateTags,\n refreshMetadata,\n };\n}\n","import {\n createContext,\n type PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport {\n type KeepItemMetadataRefresher,\n type KeepItemRevalidationSummary,\n type KeepItemRevalidator,\n type RevalidateKeepItemsOptions,\n revalidateKeepItems,\n} from \"./revalidation\";\nimport { parseKeepMeta } from \"./schema\";\nimport { createBrowserStorageAdapter } from \"./storage\";\nimport { KeepStore, type KeepStoreActions } from \"./store\";\nimport type {\n KeepAction,\n KeepChangeContext,\n KeepErrorContext,\n KeepErrorHandler,\n KeepEventHandlers,\n KeepInvalidItemPolicy,\n KeepItem,\n KeepPlugin,\n KeepSchema,\n KeepSyncState,\n StorageAdapter,\n SyncCapableStorageAdapter,\n} from \"./types\";\nimport { normalizeKeepTags } from \"./types\";\n\nexport type KeepContextValue<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n isLoading: boolean;\n isHydrated: boolean;\n isMutating: boolean;\n error: unknown | null;\n syncState: KeepSyncState;\n saveItem: (item: KeepItem<TMeta>) => Promise<void>;\n updateNote: (id: string, note?: string) => Promise<void>;\n updateTags: (id: string, tags?: string[]) => Promise<void>;\n updateTagsBatch: (ids: string[], tags?: string[]) => Promise<void>;\n addTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeItem: (id: string) => Promise<void>;\n removeItems: (ids: string[]) => Promise<void>;\n clear: () => Promise<void>;\n refresh: () => Promise<void>;\n flushSync: () => Promise<void>;\n refreshItemMetadata: (id: string, refresh: KeepItemMetadataRefresher<TMeta>) => Promise<void>;\n revalidateItems: (\n revalidator: KeepItemRevalidator<TMeta>,\n options?: RevalidateKeepItemsOptions,\n ) => Promise<KeepItemRevalidationSummary<TMeta>>;\n};\n\nexport type KeepProviderProps<TMeta = Record<string, unknown>> = PropsWithChildren<\n KeepEventHandlers<TMeta> & {\n storage?: StorageAdapter<TMeta>;\n /**\n * Optional server-provided snapshot rendered before the client adapter\n * finishes hydrating. The adapter remains the source of truth after the\n * first refresh.\n */\n initialItems?: KeepItem<TMeta>[];\n plugins?: KeepPlugin<TMeta>[];\n schemaVersion?: number;\n schema?: KeepSchema<TMeta>;\n invalidItemPolicy?: KeepInvalidItemPolicy;\n onInvalidItem?: (error: unknown, item: KeepItem<unknown>) => void;\n migrateMeta?: (\n meta: unknown,\n fromVersion: number,\n toVersion: number,\n item: KeepItem<TMeta>,\n ) => TMeta | Promise<TMeta>;\n }\n>;\n\nconst defaultStorage = createBrowserStorageAdapter();\nconst KeepContext = createContext<KeepContextValue<unknown> | null>(null);\nconst KeepStoreContext = createContext<KeepStoreAccess<unknown> | null>(null);\n\ntype KeepStoreAccess<TMeta> = {\n store: KeepStore<TMeta>;\n actions: KeepStoreActions<TMeta>;\n};\n\ntype MutationPlan<TMeta> = {\n next: KeepItem<TMeta>[];\n persist: () => Promise<void>;\n onSuccess?: () => void;\n pluginContext?: {\n action: KeepAction;\n id?: string;\n item?: KeepItem<TMeta>;\n items?: KeepItem<TMeta>[];\n };\n};\n\nexport function KeepProvider<TMeta = Record<string, unknown>>({\n storage = defaultStorage as StorageAdapter<TMeta>,\n initialItems,\n onSave,\n onRemove,\n onNoteUpdate,\n onTagsUpdate,\n onChange,\n onError,\n plugins = [],\n schemaVersion,\n schema,\n invalidItemPolicy = \"error\",\n onInvalidItem,\n migrateMeta,\n children,\n}: KeepProviderProps<TMeta>) {\n const storeRef = useRef<KeepStore<TMeta> | null>(null);\n if (!storeRef.current) {\n storeRef.current = new KeepStore<TMeta>({\n items: initialItems ? [...initialItems] : [],\n isLoading: true,\n isHydrated: false,\n isMutating: false,\n error: null,\n });\n }\n const store = storeRef.current;\n const state = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n const { items, isLoading, isHydrated, isMutating, error } = state;\n const itemsRef = useRef(items);\n const pluginsRef = useRef(plugins);\n pluginsRef.current = plugins;\n const handlersRef = useRef({ onSave, onRemove, onNoteUpdate, onTagsUpdate, onChange, onError });\n handlersRef.current = { onSave, onRemove, onNoteUpdate, onTagsUpdate, onChange, onError };\n const migrationRef = useRef({\n schemaVersion,\n migrateMeta,\n schema,\n invalidItemPolicy,\n onInvalidItem,\n });\n migrationRef.current = { schemaVersion, migrateMeta, schema, invalidItemPolicy, onInvalidItem };\n const operationTailRef = useRef<Promise<unknown>>(Promise.resolve());\n const pendingRefreshesRef = useRef(0);\n const pendingMutationsRef = useRef(0);\n const syncStorage = isSyncCapableStorage(storage) ? storage : undefined;\n const getSyncState = useCallback(() => syncStorage?.getSyncState() ?? IDLE_SYNC_STATE, [syncStorage]);\n const subscribeSync = useCallback(\n (listener: () => void) => syncStorage?.subscribeSync(listener) ?? (() => undefined),\n [syncStorage],\n );\n const syncState = useSyncExternalStore(subscribeSync, getSyncState, getSyncState);\n\n const reportError = useCallback(\n (cause: unknown, context: KeepErrorContext) => {\n store.setState({ error: cause });\n handlersRef.current.onError?.(cause, context);\n for (const plugin of pluginsRef.current) plugin.onError?.(cause, context);\n },\n [store],\n );\n\n const setItems = useCallback(\n (next: KeepItem<TMeta>[]) => {\n itemsRef.current = next;\n store.setState({ items: next });\n },\n [store],\n );\n\n const runBeforePlugins = useCallback(async (context: NonNullable<MutationPlan<TMeta>[\"pluginContext\"]>) => {\n for (const plugin of pluginsRef.current) await plugin.before?.(context);\n return context;\n }, []);\n\n const runAfterPlugins = useCallback(async (context: NonNullable<MutationPlan<TMeta>[\"pluginContext\"]>) => {\n for (const plugin of pluginsRef.current) await plugin.after?.(context);\n }, []);\n\n const enqueueOperation = useCallback(<T,>(operation: () => Promise<T>): Promise<T> => {\n const run = operationTailRef.current.then(operation, operation);\n operationTailRef.current = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }, []);\n\n const refresh = useCallback(async () => {\n pendingRefreshesRef.current += 1;\n store.setState({ isLoading: true });\n\n try {\n await enqueueOperation(async () => {\n try {\n let next = await storage.getAll();\n let needsMigrationPersist = false;\n if (migrationRef.current.schemaVersion !== undefined) {\n const migrated = await Promise.all(\n next.map(async (item) => {\n const currentSchemaVersion = migrationRef.current.schemaVersion as number;\n if (item.schemaVersion === currentSchemaVersion) return item;\n const meta = migrationRef.current.migrateMeta\n ? await migrationRef.current.migrateMeta(\n item.meta,\n item.schemaVersion ?? 0,\n currentSchemaVersion,\n item,\n )\n : item.meta;\n return { ...item, meta, schemaVersion: currentSchemaVersion };\n }),\n );\n if (migrated.some((item, index) => item !== next[index])) {\n next = migrated;\n needsMigrationPersist = true;\n }\n }\n if (migrationRef.current.schema) {\n const validated: KeepItem<TMeta>[] = [];\n for (const item of next) {\n try {\n validated.push(await parseKeepMetaItem(item, migrationRef.current.schema));\n } catch (cause) {\n migrationRef.current.onInvalidItem?.(cause, item);\n if (migrationRef.current.invalidItemPolicy === \"drop\") continue;\n throw cause;\n }\n }\n next = validated;\n }\n if (needsMigrationPersist) {\n if (storage.setMany) await storage.setMany(next);\n else for (const item of next) await storage.set(item);\n }\n setItems(next);\n store.setState({ error: null });\n } catch (cause) {\n reportError(cause, { action: \"refresh\" });\n }\n });\n } finally {\n pendingRefreshesRef.current -= 1;\n if (pendingRefreshesRef.current === 0) store.setState({ isLoading: false });\n store.setState({ isHydrated: true });\n }\n }, [enqueueOperation, reportError, setItems, storage, store]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n useEffect(() => {\n if (!storage.subscribe) return;\n return storage.subscribe(() => void refresh());\n }, [refresh, storage]);\n\n const runMutation = useCallback(\n (\n action: Exclude<KeepAction, \"refresh\">,\n id: string | undefined,\n createPlan: (previous: KeepItem<TMeta>[]) => MutationPlan<TMeta> | undefined,\n ): Promise<void> => {\n pendingMutationsRef.current += 1;\n store.setState({ isMutating: true });\n\n const run = enqueueOperation(async () => {\n const previous = itemsRef.current;\n const plan = createPlan(previous);\n if (!plan) return;\n\n try {\n if (plan.pluginContext) await runBeforePlugins(plan.pluginContext);\n setItems(plan.next);\n store.setState({ error: null });\n await plan.persist();\n plan.onSuccess?.();\n if (plan.pluginContext) await runAfterPlugins(plan.pluginContext);\n if (plan.pluginContext) {\n const change: KeepChangeContext<TMeta> = { ...plan.pluginContext, phase: \"local\" };\n void Promise.resolve(handlersRef.current.onChange?.(change)).catch((cause) =>\n reportError(cause, { action, id }),\n );\n }\n } catch (cause) {\n setItems(previous);\n reportError(cause, { action, id });\n throw cause;\n }\n });\n\n return run.finally(() => {\n pendingMutationsRef.current -= 1;\n if (pendingMutationsRef.current === 0) store.setState({ isMutating: false });\n });\n },\n [enqueueOperation, reportError, runAfterPlugins, runBeforePlugins, setItems, store],\n );\n\n const saveItem = useCallback(\n async (item: KeepItem<TMeta>) => {\n let normalizedItem: KeepItem<TMeta>;\n try {\n const meta = migrationRef.current.schema\n ? await parseKeepMeta(migrationRef.current.schema, item.meta)\n : item.meta;\n normalizedItem = {\n ...item,\n meta,\n tags: normalizeKeepTags(item.tags),\n ...(migrationRef.current.schemaVersion === undefined\n ? {}\n : { schemaVersion: migrationRef.current.schemaVersion }),\n };\n } catch (cause) {\n reportError(cause, { action: \"save\", id: item.id });\n throw cause;\n }\n await runMutation(\"save\", normalizedItem.id, (previous) => ({\n next: [...previous.filter((current) => current.id !== normalizedItem.id), normalizedItem].sort(\n (a, b) => b.updatedAt - a.updatedAt,\n ),\n persist: () => storage.set(normalizedItem),\n onSuccess: () => handlersRef.current.onSave?.(normalizedItem),\n pluginContext: { action: \"save\", id: normalizedItem.id, item: normalizedItem },\n }));\n },\n [reportError, runMutation, storage],\n );\n\n const updateNote = useCallback(\n async (id: string, note?: string) => {\n const nextNote = note?.trim() || undefined;\n await runMutation(\"updateNote\", id, (previous) => {\n const current = previous.find((item) => item.id === id);\n if (!current) return undefined;\n const next = { ...current, note: nextNote, updatedAt: Date.now() };\n return {\n next: previous.map((item) => (item.id === id ? next : item)),\n persist: () => storage.set(next),\n onSuccess: () => handlersRef.current.onNoteUpdate?.(id, nextNote),\n pluginContext: { action: \"updateNote\", id, item: next },\n };\n });\n },\n [runMutation, storage],\n );\n\n const updateTags = useCallback(\n async (id: string, tags?: string[]) => {\n const nextTags = normalizeKeepTags(tags);\n await runMutation(\"updateTags\", id, (previous) => {\n const current = previous.find((item) => item.id === id);\n if (!current) return undefined;\n const next = { ...current, tags: nextTags, updatedAt: Date.now() };\n return {\n next: previous.map((item) => (item.id === id ? next : item)),\n persist: () => storage.set(next),\n onSuccess: () => handlersRef.current.onTagsUpdate?.(id, nextTags),\n pluginContext: { action: \"updateTags\", id, item: next },\n };\n });\n },\n [runMutation, storage],\n );\n\n const updateTagsBatch = useCallback(\n async (ids: string[], tags?: string[]) => {\n const idSet = new Set(ids);\n const nextTags = normalizeKeepTags(tags);\n await runMutation(\"updateTagsBatch\", undefined, (previous) => {\n const currentItems = previous.filter((item) => idSet.has(item.id));\n if (currentItems.length === 0) return undefined;\n const updatedItems = currentItems.map((item) => ({\n ...item,\n tags: nextTags,\n updatedAt: Date.now(),\n }));\n const updatedById = new Map(updatedItems.map((item) => [item.id, item]));\n return {\n next: previous.map((item) => updatedById.get(item.id) ?? item),\n persist: async () => {\n if (storage.setMany) {\n await storage.setMany(updatedItems);\n return;\n }\n const completed: KeepItem<TMeta>[] = [];\n try {\n for (const item of updatedItems) {\n await storage.set(item);\n completed.push(item);\n }\n } catch (cause) {\n const previousById = new Map(currentItems.map((item) => [item.id, item]));\n await Promise.allSettled(\n completed.map((item) => {\n const previousItem = previousById.get(item.id);\n return previousItem ? storage.set(previousItem) : Promise.resolve();\n }),\n );\n throw cause;\n }\n },\n onSuccess: () => {\n updatedItems.forEach((item) => {\n handlersRef.current.onTagsUpdate?.(item.id, nextTags);\n });\n },\n pluginContext: { action: \"updateTagsBatch\", items: updatedItems },\n };\n });\n },\n [runMutation, storage],\n );\n\n const addTagsBatch = useCallback(\n async (ids: string[], tags: string[]) => {\n const additions = normalizeKeepTags(tags) ?? [];\n const idSet = new Set(ids);\n const currentItems = itemsRef.current.filter((item) => idSet.has(item.id));\n await Promise.all(\n currentItems.map((item) => updateTags(item.id, normalizeKeepTags([...(item.tags ?? []), ...additions]))),\n );\n },\n [updateTags],\n );\n\n const removeTagsBatch = useCallback(\n async (ids: string[], tags: string[]) => {\n const removals = new Set(normalizeKeepTags(tags) ?? []);\n const idSet = new Set(ids);\n const currentItems = itemsRef.current.filter((item) => idSet.has(item.id));\n await Promise.all(\n currentItems.map((item) =>\n updateTags(item.id, normalizeKeepTags((item.tags ?? []).filter((tag) => !removals.has(tag)))),\n ),\n );\n },\n [updateTags],\n );\n\n const removeItem = useCallback(\n async (id: string) => {\n await runMutation(\"remove\", id, (previous) => {\n const current = previous.find((item) => item.id === id);\n if (!current) return undefined;\n return {\n next: previous.filter((item) => item.id !== id),\n persist: () => storage.remove(id),\n onSuccess: () => handlersRef.current.onRemove?.(current),\n pluginContext: { action: \"remove\", id, item: current },\n };\n });\n },\n [runMutation, storage],\n );\n\n const removeItems = useCallback(\n async (ids: string[]) => {\n const idSet = new Set(ids);\n await runMutation(\"removeBatch\", undefined, (previous) => {\n const removedItems = previous.filter((item) => idSet.has(item.id));\n if (removedItems.length === 0) return undefined;\n return {\n next: previous.filter((item) => !idSet.has(item.id)),\n persist: async () => {\n if (storage.removeMany) {\n await storage.removeMany(removedItems.map((item) => item.id));\n return;\n }\n const completed: KeepItem<TMeta>[] = [];\n try {\n for (const item of removedItems) {\n await storage.remove(item.id);\n completed.push(item);\n }\n } catch (cause) {\n await Promise.allSettled(completed.map((item) => storage.set(item)));\n throw cause;\n }\n },\n onSuccess: () => {\n removedItems.forEach((item) => {\n handlersRef.current.onRemove?.(item);\n });\n },\n pluginContext: { action: \"removeBatch\", items: removedItems },\n };\n });\n },\n [runMutation, storage],\n );\n\n const clear = useCallback(\n () =>\n runMutation(\"clear\", undefined, (_previous) => ({\n next: [],\n persist: () => storage.clear(),\n pluginContext: { action: \"clear\", items: [] },\n })),\n [runMutation, storage],\n );\n\n const revalidateItems = useCallback(\n async (\n revalidator: KeepItemRevalidator<TMeta>,\n options: RevalidateKeepItemsOptions = {},\n ): Promise<KeepItemRevalidationSummary<TMeta>> => {\n pendingMutationsRef.current += 1;\n store.setState({ isMutating: true });\n const run = enqueueOperation(async () => {\n const previous = itemsRef.current;\n let persistenceStarted = false;\n try {\n const summary = await revalidateKeepItems(previous, revalidator, options);\n const pluginContext = { action: \"revalidate\" as const, items: summary.updatedItems };\n await runBeforePlugins(pluginContext);\n if (summary.updatedItems.length > 0) {\n persistenceStarted = true;\n if (storage.setMany) await storage.setMany(summary.updatedItems);\n else for (const item of summary.updatedItems) await storage.set(item);\n }\n if (summary.removedIds.length > 0) {\n persistenceStarted = true;\n if (storage.removeMany) await storage.removeMany(summary.removedIds);\n else for (const id of summary.removedIds) await storage.remove(id);\n }\n setItems(summary.items);\n store.setState({ error: null });\n const removedIdSet = new Set(summary.removedIds);\n for (const result of summary.results) {\n if (removedIdSet.has(result.item.id)) handlersRef.current.onRemove?.(result.item);\n }\n await runAfterPlugins(pluginContext);\n void Promise.resolve(handlersRef.current.onChange?.({ ...pluginContext, phase: \"local\" })).catch((cause) =>\n reportError(cause, { action: \"revalidate\" }),\n );\n return summary;\n } catch (cause) {\n if (persistenceStarted) await restoreItems(storage, previous);\n setItems(previous);\n reportError(cause, { action: \"revalidate\" });\n throw cause;\n }\n });\n return run.finally(() => {\n pendingMutationsRef.current -= 1;\n if (pendingMutationsRef.current === 0) store.setState({ isMutating: false });\n });\n },\n [enqueueOperation, reportError, runAfterPlugins, runBeforePlugins, setItems, storage, store],\n );\n\n const refreshItemMetadata = useCallback(\n async (id: string, refresh: KeepItemMetadataRefresher<TMeta>): Promise<void> => {\n if (!itemsRef.current.some((item) => item.id === id)) {\n throw new Error(`Cannot refresh metadata for missing item \"${id}\".`);\n }\n await revalidateItems(async (item) => {\n if (item.id !== id) return \"available\";\n return { status: \"available\", meta: await refresh(item) };\n });\n },\n [revalidateItems],\n );\n const flushSync = useCallback(() => (syncStorage ? syncStorage.flushSync() : Promise.resolve()), [syncStorage]);\n\n const value = useMemo<KeepContextValue<TMeta>>(\n () => ({\n items,\n isLoading,\n isHydrated,\n isMutating,\n error,\n syncState,\n saveItem,\n updateNote,\n updateTags,\n updateTagsBatch,\n addTagsBatch,\n removeTagsBatch,\n removeItem,\n removeItems,\n clear,\n refresh,\n flushSync,\n refreshItemMetadata,\n revalidateItems,\n }),\n [\n clear,\n error,\n flushSync,\n isHydrated,\n isLoading,\n isMutating,\n items,\n syncState,\n refresh,\n removeItem,\n saveItem,\n updateNote,\n updateTags,\n updateTagsBatch,\n addTagsBatch,\n removeTagsBatch,\n removeItems,\n refreshItemMetadata,\n revalidateItems,\n ],\n );\n\n const actions = useMemo<KeepStoreActions<TMeta>>(\n () => ({\n saveItem,\n updateNote,\n updateTags,\n updateTagsBatch,\n addTagsBatch,\n removeTagsBatch,\n removeItem,\n removeItems,\n clear,\n refresh,\n refreshItemMetadata,\n revalidateItems,\n }),\n [\n addTagsBatch,\n clear,\n refresh,\n removeItem,\n removeItems,\n removeTagsBatch,\n saveItem,\n updateNote,\n updateTags,\n updateTagsBatch,\n refreshItemMetadata,\n revalidateItems,\n ],\n );\n const storeAccess = useMemo<KeepStoreAccess<TMeta>>(() => ({ store, actions }), [actions, store]);\n\n return (\n <KeepStoreContext.Provider value={storeAccess as KeepStoreAccess<unknown>}>\n <KeepContext.Provider value={value as unknown as KeepContextValue<unknown>}>{children}</KeepContext.Provider>\n </KeepStoreContext.Provider>\n );\n}\n\nconst IDLE_SYNC_STATE: KeepSyncState = Object.freeze({\n status: \"idle\",\n pendingCount: 0,\n conflictIds: [],\n});\n\nfunction isSyncCapableStorage<TMeta>(storage: StorageAdapter<TMeta>): storage is SyncCapableStorageAdapter<TMeta> {\n return (\n \"getSyncState\" in storage &&\n typeof storage.getSyncState === \"function\" &&\n \"subscribeSync\" in storage &&\n typeof storage.subscribeSync === \"function\" &&\n \"flushSync\" in storage &&\n typeof storage.flushSync === \"function\"\n );\n}\n\nasync function parseKeepMetaItem<TMeta>(item: KeepItem<unknown>, schema: KeepSchema<TMeta>): Promise<KeepItem<TMeta>> {\n return { ...item, meta: await parseKeepMeta(schema, item.meta) };\n}\n\nasync function restoreItems<TMeta>(storage: StorageAdapter<TMeta>, items: KeepItem<TMeta>[]): Promise<void> {\n try {\n if (storage.setMany) {\n await storage.setMany(items);\n return;\n }\n for (const item of items) await storage.set(item);\n } catch {\n // The original operation's error is more useful to the caller than a best-effort rollback error.\n }\n}\n\nexport function useKeepContext<TMeta = Record<string, unknown>>(): KeepContextValue<TMeta> {\n const context = useContext(KeepContext);\n if (!context) throw new Error(\"Keep hooks must be used inside a KeepProvider\");\n return context as unknown as KeepContextValue<TMeta>;\n}\n\nexport function useKeepStore<TMeta = Record<string, unknown>>(): KeepStoreAccess<TMeta> {\n const context = useContext(KeepStoreContext);\n if (!context) throw new Error(\"Keep hooks must be used inside a KeepProvider\");\n return context as unknown as KeepStoreAccess<TMeta>;\n}\n\nexport type { KeepErrorHandler };\n","import { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport type { KeepStore, KeepStoreState } from \"../store\";\n\nexport function useKeepStoreSelector<TMeta, TSelected>(\n store: KeepStore<TMeta>,\n selector: (state: KeepStoreState<TMeta>) => TSelected,\n): TSelected {\n const cacheRef = useRef<{\n snapshot: KeepStoreState<TMeta>;\n selector: (state: KeepStoreState<TMeta>) => TSelected;\n selected: TSelected;\n } | null>(null);\n const getSelectedSnapshot = useCallback(() => {\n const snapshot = store.getSnapshot();\n const cached = cacheRef.current;\n if (cached?.snapshot === snapshot && cached.selector === selector) return cached.selected;\n const selected = selector(snapshot);\n cacheRef.current = { snapshot, selector, selected };\n return selected;\n }, [selector, store]);\n\n return useSyncExternalStore(store.subscribe, getSelectedSnapshot, getSelectedSnapshot);\n}\n","import { useCallback, useMemo } from \"react\";\nimport { useKeepStore } from \"../KeepProvider\";\nimport { type KeepListOptions, type QueryKeepItemsResult, queryKeepItems } from \"../query\";\nimport type { KeepItemRevalidationSummary, KeepItemRevalidator, RevalidateKeepItemsOptions } from \"../revalidation\";\nimport type { KeepItem } from \"../types\";\nimport { useKeepStoreSelector } from \"./useKeepStoreSelector\";\n\nexport type { KeepListOptions } from \"../query\";\n\nexport type UseKeepListResult<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n totalCount: number;\n tags: string[];\n tagCounts: Record<string, number>;\n isLoading: boolean;\n isHydrated: boolean;\n isMutating: boolean;\n error: unknown | null;\n remove: (id: string) => Promise<void>;\n removeBatch: (ids: string[]) => Promise<void>;\n updateTagsBatch: (ids: string[], tags?: string[]) => Promise<void>;\n addTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n clear: () => Promise<void>;\n refresh: () => Promise<void>;\n revalidate: (\n revalidator: KeepItemRevalidator<TMeta>,\n options?: RevalidateKeepItemsOptions,\n ) => Promise<KeepItemRevalidationSummary<TMeta>>;\n};\n\nexport function useKeepList<TMeta = Record<string, unknown>>(\n options: KeepListOptions<TMeta> = {},\n): UseKeepListResult<TMeta> {\n const { store, actions } = useKeepStore<TMeta>();\n const {\n filter,\n filterFn,\n limit,\n offset,\n order,\n savedBetween,\n search,\n searchQuery,\n sort,\n sortBy,\n tag,\n tags: queryTags,\n targetType,\n } = options;\n const queryOptions = useMemo<KeepListOptions<TMeta>>(\n () => ({\n filter,\n filterFn,\n limit,\n offset,\n order,\n savedBetween,\n search,\n searchQuery,\n sort,\n sortBy,\n tag,\n tags: queryTags,\n targetType,\n }),\n [\n filter,\n filterFn,\n limit,\n offset,\n order,\n savedBetween,\n search,\n searchQuery,\n sort,\n sortBy,\n tag,\n queryTags,\n targetType,\n ],\n );\n const selector = useMemo(() => {\n let previousResult: QueryKeepItemsResult<TMeta> | undefined;\n return (state: { items: KeepItem<TMeta>[] }) => {\n const next = queryKeepItems(state.items, queryOptions);\n if (\n previousResult &&\n previousResult.totalCount === next.totalCount &&\n sameItems(previousResult.items, next.items) &&\n sameCounts(previousResult.tagCounts, next.tagCounts)\n ) {\n return previousResult;\n }\n previousResult = next;\n return previousResult;\n };\n }, [queryOptions]);\n const query = useKeepStoreSelector(store, selector);\n const tagsSelector = useMemo(() => {\n let previous: string[] | undefined;\n return (state: { items: KeepItem<TMeta>[] }) => {\n const next = [...new Set(state.items.flatMap((item) => item.tags ?? []))].sort();\n if (previous?.length === next.length && previous.every((tag, index) => tag === next[index])) {\n return previous;\n }\n previous = next;\n return next;\n };\n }, []);\n const items = query.items;\n const totalCount = query.totalCount;\n const tagCounts = query.tagCounts;\n const tags = useKeepStoreSelector(store, tagsSelector);\n const isLoading = useKeepStoreSelector(\n store,\n useCallback((state) => state.isLoading, []),\n );\n const isHydrated = useKeepStoreSelector(\n store,\n useCallback((state) => state.isHydrated, []),\n );\n const isMutating = useKeepStoreSelector(\n store,\n useCallback((state) => state.isMutating, []),\n );\n const error = useKeepStoreSelector(\n store,\n useCallback((state) => state.error, []),\n );\n const remove = useCallback((id: string) => actions.removeItem(id), [actions]);\n const removeBatch = useCallback((ids: string[]) => actions.removeItems(ids), [actions]);\n const updateTagsBatch = useCallback(\n (ids: string[], tags?: string[]) => actions.updateTagsBatch(ids, tags),\n [actions],\n );\n const addTagsBatch = useCallback((ids: string[], tags: string[]) => actions.addTagsBatch(ids, tags), [actions]);\n const removeTagsBatch = useCallback((ids: string[], tags: string[]) => actions.removeTagsBatch(ids, tags), [actions]);\n\n return {\n items,\n totalCount,\n tags,\n tagCounts,\n isLoading,\n isHydrated,\n isMutating,\n error,\n remove,\n removeBatch,\n updateTagsBatch,\n addTagsBatch,\n removeTagsBatch,\n clear: actions.clear,\n refresh: actions.refresh,\n revalidate: actions.revalidateItems,\n };\n}\n\nfunction sameItems<TMeta>(left: KeepItem<TMeta>[], right: KeepItem<TMeta>[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nfunction sameCounts(left: Record<string, number>, right: Record<string, number>): boolean {\n const leftEntries = Object.entries(left);\n const rightEntries = Object.entries(right);\n return (\n leftEntries.length === rightEntries.length &&\n leftEntries.every(([key, value], index) => {\n const [rightKey, rightValue] = rightEntries[index] ?? [];\n return key === rightKey && value === rightValue;\n })\n );\n}\n","import { useEffect } from \"react\";\nimport type { KeepItemInput } from \"../types\";\nimport { useKeepItem } from \"./useKeepItem\";\n\nexport type KeepShortcutModifier = \"meta\" | \"ctrl\" | \"alt\" | \"shift\";\n\nexport type KeepShortcutOptions<TMeta = Record<string, unknown>> = {\n key: string;\n modifier?: KeepShortcutModifier;\n id?: string;\n itemPayload?: KeepItemInput<TMeta>;\n action?: \"toggle\" | \"save\" | \"remove\";\n enabled?: boolean;\n preventDefault?: boolean;\n allowInEditable?: boolean;\n onTrigger?: (event: KeyboardEvent) => void | Promise<void>;\n onError?: (error: unknown) => void;\n};\n\n/** Bind a keyboard shortcut to a Keep action or an arbitrary command. */\nexport function useKeepShortcut<TMeta = Record<string, unknown>>(options: KeepShortcutOptions<TMeta>): void {\n const item = useKeepItem(options.id ?? \"\", options.itemPayload);\n const {\n action = \"toggle\",\n allowInEditable = false,\n enabled = true,\n key,\n modifier,\n onError,\n onTrigger,\n preventDefault = true,\n } = options;\n\n useEffect(() => {\n if (!enabled) return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!allowInEditable && isEditableTarget(event.target)) return;\n if (!matchesShortcut(event, key, modifier)) return;\n if (preventDefault) event.preventDefault();\n const run = onTrigger\n ? onTrigger(event)\n : options.id\n ? action === \"save\"\n ? item.save()\n : action === \"remove\"\n ? item.remove()\n : item.toggle()\n : undefined;\n if (run) void Promise.resolve(run).catch((error) => onError?.(error));\n };\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [\n action,\n allowInEditable,\n enabled,\n item.remove,\n item.save,\n item.toggle,\n key,\n modifier,\n onError,\n onTrigger,\n options.id,\n preventDefault,\n ]);\n}\n\nfunction matchesShortcut(event: KeyboardEvent, key: string, modifier?: KeepShortcutModifier): boolean {\n if (event.key.toLocaleLowerCase() !== key.toLocaleLowerCase()) return false;\n const modifiers = {\n meta: event.metaKey,\n ctrl: event.ctrlKey,\n alt: event.altKey,\n shift: event.shiftKey,\n };\n if (modifier ? !modifiers[modifier] : Object.values(modifiers).some(Boolean)) return false;\n return Object.entries(modifiers).every(([name, pressed]) => name === modifier || !pressed);\n}\n\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false;\n return (\n target.isContentEditable ||\n target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.tagName === \"SELECT\"\n );\n}\n","import {\n type ButtonHTMLAttributes,\n Children,\n cloneElement,\n type HTMLAttributes,\n isValidElement,\n type KeyboardEvent,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport { useKeepItem } from \"./hooks/useKeepItem\";\nimport type { KeepItemInput } from \"./types\";\n\nexport type KeepButtonItem<TMeta = Record<string, unknown>> = KeepItemInput<TMeta> & {\n id: string;\n};\n\ntype KeepButtonSharedProps<TMeta> = {\n item: KeepButtonItem<TMeta>;\n children?: ReactNode | ((state: KeepButtonState<TMeta>) => ReactNode);\n savedLabel?: ReactNode;\n unsavedLabel?: ReactNode;\n savedAriaLabel?: string;\n unsavedAriaLabel?: string;\n getAriaLabel?: (state: KeepButtonState<TMeta>) => string;\n disabled?: boolean;\n onToggleError?: (error: unknown) => void;\n};\n\nexport type KeepButtonProps<TMeta = Record<string, unknown>> = KeepButtonSharedProps<TMeta> &\n (\n | (Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\" | \"onClick\" | \"aria-pressed\"> & {\n asChild?: false;\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\n })\n | (Omit<HTMLAttributes<HTMLElement>, \"children\" | \"onClick\" | \"aria-pressed\"> & {\n asChild: true;\n children: ReactElement | ((state: KeepButtonState<TMeta>) => ReactElement);\n onClick?: (event: MouseEvent<HTMLElement>) => void;\n })\n );\n\nexport type KeepButtonState<TMeta = Record<string, unknown>> = {\n item: ReturnType<typeof useKeepItem<TMeta>>[\"item\"];\n isSaved: boolean;\n isLoading: boolean;\n isMutating: boolean;\n error: unknown | null;\n save: () => Promise<void>;\n remove: () => Promise<void>;\n toggle: () => Promise<void>;\n updateNote: (note?: string) => Promise<void>;\n updateTags: (tags?: string[]) => Promise<void>;\n};\n\n/** A style-free accessible save toggle. Consumers provide all visual styling. */\nexport function KeepButton<TMeta = Record<string, unknown>>({\n item,\n children,\n savedLabel = \"Saved\",\n unsavedLabel = \"Save\",\n savedAriaLabel,\n unsavedAriaLabel,\n getAriaLabel,\n asChild = false,\n onToggleError,\n onClick,\n disabled,\n ...buttonProps\n}: KeepButtonProps<TMeta>) {\n const state = useKeepItem(item.id, {\n meta: item.meta,\n targetType: item.targetType,\n note: item.note,\n tags: item.tags,\n });\n const { isSaved, toggle } = state;\n const isDisabled = disabled ?? state.isMutating;\n\n async function handleClick(event: MouseEvent<HTMLElement>) {\n if (isDisabled) return;\n if (asChild) {\n (onClick as ((event: MouseEvent<HTMLElement>) => void) | undefined)?.(event);\n } else {\n (onClick as ((event: MouseEvent<HTMLButtonElement>) => void) | undefined)?.(\n event as MouseEvent<HTMLButtonElement>,\n );\n }\n if (event.defaultPrevented) return;\n try {\n await toggle();\n } catch (error) {\n onToggleError?.(error);\n }\n }\n\n const content =\n typeof children === \"function\" ? children(state) : (children ?? (isSaved ? savedLabel : unsavedLabel));\n function handleElementClick(event: MouseEvent<HTMLElement>) {\n if (isDisabled) return;\n if (asChild && isValidElement<{ onClick?: (event: MouseEvent<HTMLElement>) => void }>(content)) {\n content.props.onClick?.(event);\n }\n if (!event.defaultPrevented) void handleClick(event);\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLElement>) {\n if (asChild && isValidElement<{ onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void }>(content)) {\n content.props.onKeyDown?.(event);\n }\n (buttonProps as { onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void }).onKeyDown?.(event);\n if (!event.defaultPrevented && !isDisabled && asChild && (event.key === \"Enter\" || event.key === \" \")) {\n void handleClick(event as unknown as MouseEvent<HTMLElement>);\n event.preventDefault();\n }\n }\n\n const child = asChild ? Children.only(content) : undefined;\n if (asChild && !isValidElement(child)) {\n throw new Error(\"KeepButton with asChild requires a single React element child.\");\n }\n\n const commonProps = {\n ...buttonProps,\n \"aria-pressed\": isSaved,\n \"aria-label\":\n (\"aria-label\" in buttonProps ? buttonProps[\"aria-label\"] : undefined) ??\n getAriaLabel?.(state) ??\n (isSaved ? savedAriaLabel : unsavedAriaLabel) ??\n getAccessibleLabel(isSaved, item, asChild),\n ...(asChild\n ? {\n \"aria-disabled\": isDisabled,\n role: buttonProps.role ?? \"button\",\n tabIndex: isDisabled ? -1 : (buttonProps.tabIndex ?? 0),\n }\n : { disabled: isDisabled }),\n onClick: handleElementClick,\n onKeyDown: handleKeyDown,\n };\n\n if (asChild) {\n return cloneElement(child as ReactElement, commonProps);\n }\n\n return (\n <button {...commonProps} type={\"type\" in buttonProps ? (buttonProps.type ?? \"button\") : \"button\"}>\n {content}\n </button>\n );\n}\n\nfunction getAccessibleLabel<TMeta>(isSaved: boolean, item: KeepButtonItem<TMeta>, asChild: boolean): string {\n if (!asChild) return isSaved ? \"Remove saved item\" : \"Save item\";\n const title = getMetaTitle(item.meta);\n const subject = title ? `${item.targetType ?? \"item\"}: ${title}` : (item.targetType ?? \"item\");\n return `${isSaved ? \"Remove\" : \"Save\"} ${subject}`;\n}\n\nfunction getMetaTitle<TMeta>(meta: TMeta): string | undefined {\n if (typeof meta !== \"object\" || meta === null || !(\"title\" in meta)) return undefined;\n const title = (meta as { title?: unknown }).title;\n return typeof title === \"string\" && title.trim() ? title.trim() : undefined;\n}\n","import type { ComponentType } from \"react\";\nimport { type UseKeepItemResult, useKeepItem } from \"./hooks/useKeepItem\";\nimport { type UseKeepListResult, useKeepList } from \"./hooks/useKeepList\";\nimport { type KeepShortcutOptions, useKeepShortcut } from \"./hooks/useKeepShortcut\";\nimport { KeepButton, type KeepButtonProps } from \"./KeepButton\";\nimport { KeepProvider, type KeepProviderProps, useKeepContext } from \"./KeepProvider\";\nimport type { KeepListOptions } from \"./query\";\nimport type { KeepInvalidItemPolicy, KeepItemInput, KeepPlugin, KeepSchema } from \"./types\";\n\nexport type CreateKeepKitOptions<TMeta = Record<string, unknown>> = {\n initialItems?: KeepProviderProps<TMeta>[\"initialItems\"];\n plugins?: KeepPlugin<TMeta>[];\n schemaVersion?: number;\n schema?: KeepSchema<TMeta>;\n invalidItemPolicy?: KeepInvalidItemPolicy;\n onInvalidItem?: KeepProviderProps<TMeta>[\"onInvalidItem\"];\n migrateMeta?: KeepProviderProps<TMeta>[\"migrateMeta\"];\n};\n\nexport type KeepKit<TMeta> = {\n KeepProvider: ComponentType<KeepProviderProps<TMeta>>;\n KeepButton: ComponentType<KeepButtonProps<TMeta>>;\n useKeepContext: () => ReturnType<typeof useKeepContext<TMeta>>;\n useKeepItem: (id: string, itemPayload?: KeepItemInput<TMeta>) => UseKeepItemResult<TMeta>;\n useKeepList: (options?: KeepListOptions<TMeta>) => UseKeepListResult<TMeta>;\n useKeepShortcut: (options: KeepShortcutOptions<TMeta>) => void;\n};\n\n/** Create an app-specific, fully typed set of KeepKit components and hooks. */\nexport function createKeepKit<TMeta = Record<string, unknown>>(\n options: CreateKeepKitOptions<TMeta> = {},\n): KeepKit<TMeta> {\n return {\n KeepProvider: (props) => <KeepProvider<TMeta> {...options} {...props} />,\n KeepButton: (props) => <KeepButton<TMeta> {...props} />,\n useKeepContext: () => useKeepContext<TMeta>(),\n useKeepItem: (id, itemPayload) => useKeepItem<TMeta>(id, itemPayload),\n useKeepList: (options) => useKeepList<TMeta>(options),\n useKeepShortcut: (shortcutOptions) => useKeepShortcut<TMeta>(shortcutOptions),\n };\n}\n"],"mappings":"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","names":["useCallback","refresh","useCallback","useRef","useSyncExternalStore","useCallback","useCallback","useMemo","useMemo","tag","useCallback","tags","useEffect","useEffect","jsx","jsx","options"]}
1
+ {"version":3,"sources":["../src/hooks/useKeepItem.ts","../src/KeepProvider.tsx","../src/hooks/useKeepStoreSelector.ts","../src/hooks/useKeepList.ts","../src/hooks/useKeepShortcut.ts","../src/KeepButton.tsx","../src/createKeepKit.tsx"],"sourcesContent":["import { useCallback } from \"react\";\nimport { useKeepStore } from \"../KeepProvider\";\nimport type { KeepItemMetadataRefresher } from \"../revalidation\";\nimport type { KeepItem, KeepItemInput } from \"../types\";\nimport { useKeepStoreSelector } from \"./useKeepStoreSelector\";\n\nexport type UseKeepItemResult<TMeta = Record<string, unknown>> = {\n item: KeepItem<TMeta> | undefined;\n isSaved: boolean;\n isLoading: boolean;\n isMutating: boolean;\n error: unknown | null;\n save: () => Promise<void>;\n remove: () => Promise<void>;\n toggle: () => Promise<void>;\n updateNote: (note?: string) => Promise<void>;\n updateTags: (tags?: string[]) => Promise<void>;\n refreshMetadata: (refresh: KeepItemMetadataRefresher<TMeta>) => Promise<void>;\n};\n\nexport function useKeepItem<TMeta = Record<string, unknown>>(\n id: string,\n itemPayload?: KeepItemInput<TMeta>,\n): UseKeepItemResult<TMeta> {\n const { store, actions } = useKeepStore<TMeta>();\n const item = useKeepStoreSelector(\n store,\n useCallback((state) => state.items.find((current) => current.id === id), [id]),\n );\n const isLoading = useKeepStoreSelector(\n store,\n useCallback((state) => state.isLoading, []),\n );\n const isMutating = useKeepStoreSelector(\n store,\n useCallback((state) => state.isMutating, []),\n );\n const error = useKeepStoreSelector(\n store,\n useCallback((state) => state.error, []),\n );\n\n const save = useCallback(async () => {\n if (!itemPayload) {\n throw new Error(`An itemPayload is required to save item \"${id}\".`);\n }\n const now = Date.now();\n await actions.saveItem({\n id,\n ...itemPayload,\n savedAt: item?.savedAt ?? now,\n updatedAt: now,\n });\n }, [actions, id, item?.savedAt, itemPayload]);\n\n const remove = useCallback(() => actions.removeItem(id), [actions, id]);\n const toggle = useCallback(() => (item ? remove() : save()), [item, remove, save]);\n const updateNote = useCallback((note?: string) => actions.updateNote(id, note), [actions, id]);\n const updateTags = useCallback((tags?: string[]) => actions.updateTags(id, tags), [actions, id]);\n const refreshMetadata = useCallback(\n (refresh: KeepItemMetadataRefresher<TMeta>) => actions.refreshItemMetadata(id, refresh),\n [actions, id],\n );\n\n return {\n item,\n isSaved: Boolean(item),\n isLoading,\n isMutating,\n error,\n save,\n remove,\n toggle,\n updateNote,\n updateTags,\n refreshMetadata,\n };\n}\n","import {\n createContext,\n type PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport {\n type KeepItemMetadataRefresher,\n type KeepItemRevalidationSummary,\n type KeepItemRevalidator,\n type RevalidateKeepItemsOptions,\n revalidateKeepItems,\n} from \"./revalidation\";\nimport { parseKeepMeta } from \"./schema\";\nimport { createBrowserStorageAdapter } from \"./storage\";\nimport { KeepStore, type KeepStoreActions } from \"./store\";\nimport type {\n KeepAction,\n KeepChangeContext,\n KeepErrorContext,\n KeepErrorHandler,\n KeepEventHandlers,\n KeepInvalidItemPolicy,\n KeepItem,\n KeepPlugin,\n KeepSchema,\n KeepSyncState,\n StorageAdapter,\n SyncCapableStorageAdapter,\n} from \"./types\";\nimport { normalizeKeepTags } from \"./types\";\n\nexport type KeepContextValue<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n isLoading: boolean;\n isHydrated: boolean;\n isMutating: boolean;\n error: unknown | null;\n lastChange?: KeepChangeContext<TMeta>;\n syncState: KeepSyncState;\n saveItem: (item: KeepItem<TMeta>) => Promise<void>;\n updateNote: (id: string, note?: string) => Promise<void>;\n updateTags: (id: string, tags?: string[]) => Promise<void>;\n updateTagsBatch: (ids: string[], tags?: string[]) => Promise<void>;\n addTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeItem: (id: string) => Promise<void>;\n removeItems: (ids: string[]) => Promise<void>;\n clear: () => Promise<void>;\n refresh: () => Promise<void>;\n flushSync: () => Promise<void>;\n refreshItemMetadata: (id: string, refresh: KeepItemMetadataRefresher<TMeta>) => Promise<void>;\n revalidateItems: (\n revalidator: KeepItemRevalidator<TMeta>,\n options?: RevalidateKeepItemsOptions,\n ) => Promise<KeepItemRevalidationSummary<TMeta>>;\n};\n\nexport type KeepProviderProps<TMeta = Record<string, unknown>> = PropsWithChildren<\n KeepEventHandlers<TMeta> & {\n storage?: StorageAdapter<TMeta>;\n /**\n * Optional server-provided snapshot rendered before the client adapter\n * finishes hydrating. The adapter remains the source of truth after the\n * first refresh.\n */\n initialItems?: KeepItem<TMeta>[];\n plugins?: KeepPlugin<TMeta>[];\n schemaVersion?: number;\n schema?: KeepSchema<TMeta>;\n invalidItemPolicy?: KeepInvalidItemPolicy;\n onInvalidItem?: (error: unknown, item: KeepItem<unknown>) => void;\n migrateMeta?: (\n meta: unknown,\n fromVersion: number,\n toVersion: number,\n item: KeepItem<TMeta>,\n ) => TMeta | Promise<TMeta>;\n }\n>;\n\nconst defaultStorage = createBrowserStorageAdapter();\nconst KeepContext = createContext<KeepContextValue<unknown> | null>(null);\nconst KeepStoreContext = createContext<KeepStoreAccess<unknown> | null>(null);\n\ntype KeepStoreAccess<TMeta> = {\n store: KeepStore<TMeta>;\n actions: KeepStoreActions<TMeta>;\n};\n\ntype MutationPlan<TMeta> = {\n next: KeepItem<TMeta>[];\n persist: () => Promise<void>;\n onSuccess?: () => void;\n pluginContext?: {\n action: KeepAction;\n id?: string;\n item?: KeepItem<TMeta>;\n items?: KeepItem<TMeta>[];\n };\n};\n\nexport function KeepProvider<TMeta = Record<string, unknown>>({\n storage = defaultStorage as StorageAdapter<TMeta>,\n initialItems,\n onSave,\n onRemove,\n onNoteUpdate,\n onTagsUpdate,\n onChange,\n onError,\n plugins = [],\n schemaVersion,\n schema,\n invalidItemPolicy = \"error\",\n onInvalidItem,\n migrateMeta,\n children,\n}: KeepProviderProps<TMeta>) {\n const storeRef = useRef<KeepStore<TMeta> | null>(null);\n if (!storeRef.current) {\n storeRef.current = new KeepStore<TMeta>({\n items: initialItems ? [...initialItems] : [],\n isLoading: true,\n isHydrated: false,\n isMutating: false,\n error: null,\n lastChange: undefined,\n });\n }\n const store = storeRef.current;\n const state = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n const { items, isLoading, isHydrated, isMutating, error, lastChange } = state;\n const itemsRef = useRef(items);\n const pluginsRef = useRef(plugins);\n pluginsRef.current = plugins;\n const handlersRef = useRef({ onSave, onRemove, onNoteUpdate, onTagsUpdate, onChange, onError });\n handlersRef.current = { onSave, onRemove, onNoteUpdate, onTagsUpdate, onChange, onError };\n const migrationRef = useRef({\n schemaVersion,\n migrateMeta,\n schema,\n invalidItemPolicy,\n onInvalidItem,\n });\n migrationRef.current = { schemaVersion, migrateMeta, schema, invalidItemPolicy, onInvalidItem };\n const operationTailRef = useRef<Promise<unknown>>(Promise.resolve());\n const pendingRefreshesRef = useRef(0);\n const pendingMutationsRef = useRef(0);\n const syncStorage = isSyncCapableStorage(storage) ? storage : undefined;\n const getSyncState = useCallback(() => syncStorage?.getSyncState() ?? IDLE_SYNC_STATE, [syncStorage]);\n const subscribeSync = useCallback(\n (listener: () => void) => syncStorage?.subscribeSync(listener) ?? (() => undefined),\n [syncStorage],\n );\n const syncState = useSyncExternalStore(subscribeSync, getSyncState, getSyncState);\n\n const reportError = useCallback(\n (cause: unknown, context: KeepErrorContext) => {\n store.setState({ error: cause });\n handlersRef.current.onError?.(cause, context);\n for (const plugin of pluginsRef.current) plugin.onError?.(cause, context);\n },\n [store],\n );\n\n const setItems = useCallback(\n (next: KeepItem<TMeta>[]) => {\n itemsRef.current = next;\n store.setState({ items: next });\n },\n [store],\n );\n\n const runBeforePlugins = useCallback(async (context: NonNullable<MutationPlan<TMeta>[\"pluginContext\"]>) => {\n for (const plugin of pluginsRef.current) await plugin.before?.(context);\n return context;\n }, []);\n\n const runAfterPlugins = useCallback(async (context: NonNullable<MutationPlan<TMeta>[\"pluginContext\"]>) => {\n for (const plugin of pluginsRef.current) await plugin.after?.(context);\n }, []);\n\n const enqueueOperation = useCallback(<T,>(operation: () => Promise<T>): Promise<T> => {\n const run = operationTailRef.current.then(operation, operation);\n operationTailRef.current = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }, []);\n\n const refresh = useCallback(async () => {\n pendingRefreshesRef.current += 1;\n store.setState({ isLoading: true });\n\n try {\n await enqueueOperation(async () => {\n try {\n let next = await storage.getAll();\n let needsMigrationPersist = false;\n if (migrationRef.current.schemaVersion !== undefined) {\n const migrated = await Promise.all(\n next.map(async (item) => {\n const currentSchemaVersion = migrationRef.current.schemaVersion as number;\n if (item.schemaVersion === currentSchemaVersion) return item;\n const meta = migrationRef.current.migrateMeta\n ? await migrationRef.current.migrateMeta(\n item.meta,\n item.schemaVersion ?? 0,\n currentSchemaVersion,\n item,\n )\n : item.meta;\n return { ...item, meta, schemaVersion: currentSchemaVersion };\n }),\n );\n if (migrated.some((item, index) => item !== next[index])) {\n next = migrated;\n needsMigrationPersist = true;\n }\n }\n if (migrationRef.current.schema) {\n const validated: KeepItem<TMeta>[] = [];\n for (const item of next) {\n try {\n validated.push(await parseKeepMetaItem(item, migrationRef.current.schema));\n } catch (cause) {\n migrationRef.current.onInvalidItem?.(cause, item);\n if (migrationRef.current.invalidItemPolicy === \"drop\") continue;\n throw cause;\n }\n }\n next = validated;\n }\n if (needsMigrationPersist) {\n if (storage.setMany) await storage.setMany(next);\n else for (const item of next) await storage.set(item);\n }\n setItems(next);\n store.setState({ error: null });\n } catch (cause) {\n reportError(cause, { action: \"refresh\" });\n }\n });\n } finally {\n pendingRefreshesRef.current -= 1;\n if (pendingRefreshesRef.current === 0) store.setState({ isLoading: false });\n store.setState({ isHydrated: true });\n }\n }, [enqueueOperation, reportError, setItems, storage, store]);\n\n useEffect(() => {\n void refresh();\n }, [refresh]);\n\n useEffect(() => {\n if (!storage.subscribe) return;\n return storage.subscribe(() => void refresh());\n }, [refresh, storage]);\n\n const runMutation = useCallback(\n (\n action: Exclude<KeepAction, \"refresh\">,\n id: string | undefined,\n createPlan: (previous: KeepItem<TMeta>[]) => MutationPlan<TMeta> | undefined,\n ): Promise<void> => {\n pendingMutationsRef.current += 1;\n store.setState({ isMutating: true });\n\n const run = enqueueOperation(async () => {\n const previous = itemsRef.current;\n const plan = createPlan(previous);\n if (!plan) return;\n\n try {\n if (plan.pluginContext) await runBeforePlugins(plan.pluginContext);\n setItems(plan.next);\n store.setState({ error: null });\n await plan.persist();\n plan.onSuccess?.();\n if (plan.pluginContext) await runAfterPlugins(plan.pluginContext);\n if (plan.pluginContext) {\n const change: KeepChangeContext<TMeta> = { ...plan.pluginContext, phase: \"local\" };\n store.setState({ lastChange: change });\n void Promise.resolve(handlersRef.current.onChange?.(change)).catch((cause) =>\n reportError(cause, { action, id }),\n );\n }\n } catch (cause) {\n setItems(previous);\n reportError(cause, { action, id });\n throw cause;\n }\n });\n\n return run.finally(() => {\n pendingMutationsRef.current -= 1;\n if (pendingMutationsRef.current === 0) store.setState({ isMutating: false });\n });\n },\n [enqueueOperation, reportError, runAfterPlugins, runBeforePlugins, setItems, store],\n );\n\n const saveItem = useCallback(\n async (item: KeepItem<TMeta>) => {\n let normalizedItem: KeepItem<TMeta>;\n try {\n const meta = migrationRef.current.schema\n ? await parseKeepMeta(migrationRef.current.schema, item.meta)\n : item.meta;\n normalizedItem = {\n ...item,\n meta,\n tags: normalizeKeepTags(item.tags),\n ...(migrationRef.current.schemaVersion === undefined\n ? {}\n : { schemaVersion: migrationRef.current.schemaVersion }),\n };\n } catch (cause) {\n reportError(cause, { action: \"save\", id: item.id });\n throw cause;\n }\n await runMutation(\"save\", normalizedItem.id, (previous) => ({\n next: [...previous.filter((current) => current.id !== normalizedItem.id), normalizedItem].sort(\n (a, b) => b.updatedAt - a.updatedAt,\n ),\n persist: () => storage.set(normalizedItem),\n onSuccess: () => handlersRef.current.onSave?.(normalizedItem),\n pluginContext: { action: \"save\", id: normalizedItem.id, item: normalizedItem },\n }));\n },\n [reportError, runMutation, storage],\n );\n\n const updateNote = useCallback(\n async (id: string, note?: string) => {\n const nextNote = note?.trim() || undefined;\n await runMutation(\"updateNote\", id, (previous) => {\n const current = previous.find((item) => item.id === id);\n if (!current) return undefined;\n const next = { ...current, note: nextNote, updatedAt: Date.now() };\n return {\n next: previous.map((item) => (item.id === id ? next : item)),\n persist: () => storage.set(next),\n onSuccess: () => handlersRef.current.onNoteUpdate?.(id, nextNote),\n pluginContext: { action: \"updateNote\", id, item: next },\n };\n });\n },\n [runMutation, storage],\n );\n\n const updateTags = useCallback(\n async (id: string, tags?: string[]) => {\n const nextTags = normalizeKeepTags(tags);\n await runMutation(\"updateTags\", id, (previous) => {\n const current = previous.find((item) => item.id === id);\n if (!current) return undefined;\n const next = { ...current, tags: nextTags, updatedAt: Date.now() };\n return {\n next: previous.map((item) => (item.id === id ? next : item)),\n persist: () => storage.set(next),\n onSuccess: () => handlersRef.current.onTagsUpdate?.(id, nextTags),\n pluginContext: { action: \"updateTags\", id, item: next },\n };\n });\n },\n [runMutation, storage],\n );\n\n const updateTagsBatch = useCallback(\n async (ids: string[], tags?: string[]) => {\n const idSet = new Set(ids);\n const nextTags = normalizeKeepTags(tags);\n await runMutation(\"updateTagsBatch\", undefined, (previous) => {\n const currentItems = previous.filter((item) => idSet.has(item.id));\n if (currentItems.length === 0) return undefined;\n const updatedItems = currentItems.map((item) => ({\n ...item,\n tags: nextTags,\n updatedAt: Date.now(),\n }));\n const updatedById = new Map(updatedItems.map((item) => [item.id, item]));\n return {\n next: previous.map((item) => updatedById.get(item.id) ?? item),\n persist: async () => {\n if (storage.setMany) {\n await storage.setMany(updatedItems);\n return;\n }\n const completed: KeepItem<TMeta>[] = [];\n try {\n for (const item of updatedItems) {\n await storage.set(item);\n completed.push(item);\n }\n } catch (cause) {\n const previousById = new Map(currentItems.map((item) => [item.id, item]));\n await Promise.allSettled(\n completed.map((item) => {\n const previousItem = previousById.get(item.id);\n return previousItem ? storage.set(previousItem) : Promise.resolve();\n }),\n );\n throw cause;\n }\n },\n onSuccess: () => {\n updatedItems.forEach((item) => {\n handlersRef.current.onTagsUpdate?.(item.id, nextTags);\n });\n },\n pluginContext: { action: \"updateTagsBatch\", items: updatedItems },\n };\n });\n },\n [runMutation, storage],\n );\n\n const addTagsBatch = useCallback(\n async (ids: string[], tags: string[]) => {\n const additions = normalizeKeepTags(tags) ?? [];\n const idSet = new Set(ids);\n const currentItems = itemsRef.current.filter((item) => idSet.has(item.id));\n await Promise.all(\n currentItems.map((item) => updateTags(item.id, normalizeKeepTags([...(item.tags ?? []), ...additions]))),\n );\n },\n [updateTags],\n );\n\n const removeTagsBatch = useCallback(\n async (ids: string[], tags: string[]) => {\n const removals = new Set(normalizeKeepTags(tags) ?? []);\n const idSet = new Set(ids);\n const currentItems = itemsRef.current.filter((item) => idSet.has(item.id));\n await Promise.all(\n currentItems.map((item) =>\n updateTags(item.id, normalizeKeepTags((item.tags ?? []).filter((tag) => !removals.has(tag)))),\n ),\n );\n },\n [updateTags],\n );\n\n const removeItem = useCallback(\n async (id: string) => {\n await runMutation(\"remove\", id, (previous) => {\n const current = previous.find((item) => item.id === id);\n if (!current) return undefined;\n return {\n next: previous.filter((item) => item.id !== id),\n persist: () => storage.remove(id),\n onSuccess: () => handlersRef.current.onRemove?.(current),\n pluginContext: { action: \"remove\", id, item: current },\n };\n });\n },\n [runMutation, storage],\n );\n\n const removeItems = useCallback(\n async (ids: string[]) => {\n const idSet = new Set(ids);\n await runMutation(\"removeBatch\", undefined, (previous) => {\n const removedItems = previous.filter((item) => idSet.has(item.id));\n if (removedItems.length === 0) return undefined;\n return {\n next: previous.filter((item) => !idSet.has(item.id)),\n persist: async () => {\n if (storage.removeMany) {\n await storage.removeMany(removedItems.map((item) => item.id));\n return;\n }\n const completed: KeepItem<TMeta>[] = [];\n try {\n for (const item of removedItems) {\n await storage.remove(item.id);\n completed.push(item);\n }\n } catch (cause) {\n await Promise.allSettled(completed.map((item) => storage.set(item)));\n throw cause;\n }\n },\n onSuccess: () => {\n removedItems.forEach((item) => {\n handlersRef.current.onRemove?.(item);\n });\n },\n pluginContext: { action: \"removeBatch\", items: removedItems },\n };\n });\n },\n [runMutation, storage],\n );\n\n const clear = useCallback(\n () =>\n runMutation(\"clear\", undefined, (_previous) => ({\n next: [],\n persist: () => storage.clear(),\n pluginContext: { action: \"clear\", items: [] },\n })),\n [runMutation, storage],\n );\n\n const revalidateItems = useCallback(\n async (\n revalidator: KeepItemRevalidator<TMeta>,\n options: RevalidateKeepItemsOptions = {},\n ): Promise<KeepItemRevalidationSummary<TMeta>> => {\n pendingMutationsRef.current += 1;\n store.setState({ isMutating: true });\n const run = enqueueOperation(async () => {\n const previous = itemsRef.current;\n let persistenceStarted = false;\n try {\n const summary = await revalidateKeepItems(previous, revalidator, options);\n const pluginContext = { action: \"revalidate\" as const, items: summary.updatedItems };\n await runBeforePlugins(pluginContext);\n if (summary.updatedItems.length > 0) {\n persistenceStarted = true;\n if (storage.setMany) await storage.setMany(summary.updatedItems);\n else for (const item of summary.updatedItems) await storage.set(item);\n }\n if (summary.removedIds.length > 0) {\n persistenceStarted = true;\n if (storage.removeMany) await storage.removeMany(summary.removedIds);\n else for (const id of summary.removedIds) await storage.remove(id);\n }\n setItems(summary.items);\n store.setState({ error: null });\n const removedIdSet = new Set(summary.removedIds);\n for (const result of summary.results) {\n if (removedIdSet.has(result.item.id)) handlersRef.current.onRemove?.(result.item);\n }\n await runAfterPlugins(pluginContext);\n void Promise.resolve(handlersRef.current.onChange?.({ ...pluginContext, phase: \"local\" })).catch((cause) =>\n reportError(cause, { action: \"revalidate\" }),\n );\n return summary;\n } catch (cause) {\n if (persistenceStarted) await restoreItems(storage, previous);\n setItems(previous);\n reportError(cause, { action: \"revalidate\" });\n throw cause;\n }\n });\n return run.finally(() => {\n pendingMutationsRef.current -= 1;\n if (pendingMutationsRef.current === 0) store.setState({ isMutating: false });\n });\n },\n [enqueueOperation, reportError, runAfterPlugins, runBeforePlugins, setItems, storage, store],\n );\n\n const refreshItemMetadata = useCallback(\n async (id: string, refresh: KeepItemMetadataRefresher<TMeta>): Promise<void> => {\n if (!itemsRef.current.some((item) => item.id === id)) {\n throw new Error(`Cannot refresh metadata for missing item \"${id}\".`);\n }\n await revalidateItems(async (item) => {\n if (item.id !== id) return \"available\";\n return { status: \"available\", meta: await refresh(item) };\n });\n },\n [revalidateItems],\n );\n const flushSync = useCallback(() => (syncStorage ? syncStorage.flushSync() : Promise.resolve()), [syncStorage]);\n\n const value = useMemo<KeepContextValue<TMeta>>(\n () => ({\n items,\n isLoading,\n isHydrated,\n isMutating,\n error,\n lastChange,\n syncState,\n saveItem,\n updateNote,\n updateTags,\n updateTagsBatch,\n addTagsBatch,\n removeTagsBatch,\n removeItem,\n removeItems,\n clear,\n refresh,\n flushSync,\n refreshItemMetadata,\n revalidateItems,\n }),\n [\n clear,\n error,\n lastChange,\n flushSync,\n isHydrated,\n isLoading,\n isMutating,\n items,\n syncState,\n refresh,\n removeItem,\n saveItem,\n updateNote,\n updateTags,\n updateTagsBatch,\n addTagsBatch,\n removeTagsBatch,\n removeItems,\n refreshItemMetadata,\n revalidateItems,\n ],\n );\n\n const actions = useMemo<KeepStoreActions<TMeta>>(\n () => ({\n saveItem,\n updateNote,\n updateTags,\n updateTagsBatch,\n addTagsBatch,\n removeTagsBatch,\n removeItem,\n removeItems,\n clear,\n refresh,\n refreshItemMetadata,\n revalidateItems,\n }),\n [\n addTagsBatch,\n clear,\n refresh,\n removeItem,\n removeItems,\n removeTagsBatch,\n saveItem,\n updateNote,\n updateTags,\n updateTagsBatch,\n refreshItemMetadata,\n revalidateItems,\n ],\n );\n const storeAccess = useMemo<KeepStoreAccess<TMeta>>(() => ({ store, actions }), [actions, store]);\n\n return (\n <KeepStoreContext.Provider value={storeAccess as KeepStoreAccess<unknown>}>\n <KeepContext.Provider value={value as unknown as KeepContextValue<unknown>}>{children}</KeepContext.Provider>\n </KeepStoreContext.Provider>\n );\n}\n\nconst IDLE_SYNC_STATE: KeepSyncState = Object.freeze({\n status: \"idle\",\n pendingCount: 0,\n conflictIds: [],\n});\n\nfunction isSyncCapableStorage<TMeta>(storage: StorageAdapter<TMeta>): storage is SyncCapableStorageAdapter<TMeta> {\n return (\n \"getSyncState\" in storage &&\n typeof storage.getSyncState === \"function\" &&\n \"subscribeSync\" in storage &&\n typeof storage.subscribeSync === \"function\" &&\n \"flushSync\" in storage &&\n typeof storage.flushSync === \"function\"\n );\n}\n\nasync function parseKeepMetaItem<TMeta>(item: KeepItem<unknown>, schema: KeepSchema<TMeta>): Promise<KeepItem<TMeta>> {\n return { ...item, meta: await parseKeepMeta(schema, item.meta) };\n}\n\nasync function restoreItems<TMeta>(storage: StorageAdapter<TMeta>, items: KeepItem<TMeta>[]): Promise<void> {\n try {\n if (storage.setMany) {\n await storage.setMany(items);\n return;\n }\n for (const item of items) await storage.set(item);\n } catch {\n // The original operation's error is more useful to the caller than a best-effort rollback error.\n }\n}\n\nexport function useKeepContext<TMeta = Record<string, unknown>>(): KeepContextValue<TMeta> {\n const context = useContext(KeepContext);\n if (!context) throw new Error(\"Keep hooks must be used inside a KeepProvider\");\n return context as unknown as KeepContextValue<TMeta>;\n}\n\nexport function useKeepStore<TMeta = Record<string, unknown>>(): KeepStoreAccess<TMeta> {\n const context = useContext(KeepStoreContext);\n if (!context) throw new Error(\"Keep hooks must be used inside a KeepProvider\");\n return context as unknown as KeepStoreAccess<TMeta>;\n}\n\nexport type { KeepErrorHandler };\n","import { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport type { KeepStore, KeepStoreState } from \"../store\";\n\nexport function useKeepStoreSelector<TMeta, TSelected>(\n store: KeepStore<TMeta>,\n selector: (state: KeepStoreState<TMeta>) => TSelected,\n): TSelected {\n const cacheRef = useRef<{\n snapshot: KeepStoreState<TMeta>;\n selector: (state: KeepStoreState<TMeta>) => TSelected;\n selected: TSelected;\n } | null>(null);\n const getSelectedSnapshot = useCallback(() => {\n const snapshot = store.getSnapshot();\n const cached = cacheRef.current;\n if (cached?.snapshot === snapshot && cached.selector === selector) return cached.selected;\n const selected = selector(snapshot);\n cacheRef.current = { snapshot, selector, selected };\n return selected;\n }, [selector, store]);\n\n return useSyncExternalStore(store.subscribe, getSelectedSnapshot, getSelectedSnapshot);\n}\n","import { useCallback, useMemo } from \"react\";\nimport { useKeepStore } from \"../KeepProvider\";\nimport { type KeepListOptions, type QueryKeepItemsResult, queryKeepItems } from \"../query\";\nimport type { KeepItemRevalidationSummary, KeepItemRevalidator, RevalidateKeepItemsOptions } from \"../revalidation\";\nimport type { KeepItem } from \"../types\";\nimport { useKeepStoreSelector } from \"./useKeepStoreSelector\";\n\nexport type { KeepListOptions } from \"../query\";\n\nexport type UseKeepListResult<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n totalCount: number;\n tags: string[];\n tagCounts: Record<string, number>;\n isLoading: boolean;\n isHydrated: boolean;\n isMutating: boolean;\n error: unknown | null;\n remove: (id: string) => Promise<void>;\n removeBatch: (ids: string[]) => Promise<void>;\n updateTagsBatch: (ids: string[], tags?: string[]) => Promise<void>;\n addTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n removeTagsBatch: (ids: string[], tags: string[]) => Promise<void>;\n clear: () => Promise<void>;\n refresh: () => Promise<void>;\n revalidate: (\n revalidator: KeepItemRevalidator<TMeta>,\n options?: RevalidateKeepItemsOptions,\n ) => Promise<KeepItemRevalidationSummary<TMeta>>;\n};\n\nexport function useKeepList<TMeta = Record<string, unknown>>(\n options: KeepListOptions<TMeta> = {},\n): UseKeepListResult<TMeta> {\n const { store, actions } = useKeepStore<TMeta>();\n const {\n filter,\n filterFn,\n limit,\n offset,\n order,\n savedBetween,\n search,\n searchQuery,\n sort,\n sortBy,\n tag,\n tags: queryTags,\n targetType,\n } = options;\n const queryOptions = useMemo<KeepListOptions<TMeta>>(\n () => ({\n filter,\n filterFn,\n limit,\n offset,\n order,\n savedBetween,\n search,\n searchQuery,\n sort,\n sortBy,\n tag,\n tags: queryTags,\n targetType,\n }),\n [\n filter,\n filterFn,\n limit,\n offset,\n order,\n savedBetween,\n search,\n searchQuery,\n sort,\n sortBy,\n tag,\n queryTags,\n targetType,\n ],\n );\n const selector = useMemo(() => {\n let previousResult: QueryKeepItemsResult<TMeta> | undefined;\n return (state: { items: KeepItem<TMeta>[] }) => {\n const next = queryKeepItems(state.items, queryOptions);\n if (\n previousResult &&\n previousResult.totalCount === next.totalCount &&\n sameItems(previousResult.items, next.items) &&\n sameCounts(previousResult.tagCounts, next.tagCounts)\n ) {\n return previousResult;\n }\n previousResult = next;\n return previousResult;\n };\n }, [queryOptions]);\n const query = useKeepStoreSelector(store, selector);\n const tagsSelector = useMemo(() => {\n let previous: string[] | undefined;\n return (state: { items: KeepItem<TMeta>[] }) => {\n const next = [...new Set(state.items.flatMap((item) => item.tags ?? []))].sort();\n if (previous?.length === next.length && previous.every((tag, index) => tag === next[index])) {\n return previous;\n }\n previous = next;\n return next;\n };\n }, []);\n const items = query.items;\n const totalCount = query.totalCount;\n const tagCounts = query.tagCounts;\n const tags = useKeepStoreSelector(store, tagsSelector);\n const isLoading = useKeepStoreSelector(\n store,\n useCallback((state) => state.isLoading, []),\n );\n const isHydrated = useKeepStoreSelector(\n store,\n useCallback((state) => state.isHydrated, []),\n );\n const isMutating = useKeepStoreSelector(\n store,\n useCallback((state) => state.isMutating, []),\n );\n const error = useKeepStoreSelector(\n store,\n useCallback((state) => state.error, []),\n );\n const remove = useCallback((id: string) => actions.removeItem(id), [actions]);\n const removeBatch = useCallback((ids: string[]) => actions.removeItems(ids), [actions]);\n const updateTagsBatch = useCallback(\n (ids: string[], tags?: string[]) => actions.updateTagsBatch(ids, tags),\n [actions],\n );\n const addTagsBatch = useCallback((ids: string[], tags: string[]) => actions.addTagsBatch(ids, tags), [actions]);\n const removeTagsBatch = useCallback((ids: string[], tags: string[]) => actions.removeTagsBatch(ids, tags), [actions]);\n\n return {\n items,\n totalCount,\n tags,\n tagCounts,\n isLoading,\n isHydrated,\n isMutating,\n error,\n remove,\n removeBatch,\n updateTagsBatch,\n addTagsBatch,\n removeTagsBatch,\n clear: actions.clear,\n refresh: actions.refresh,\n revalidate: actions.revalidateItems,\n };\n}\n\nfunction sameItems<TMeta>(left: KeepItem<TMeta>[], right: KeepItem<TMeta>[]): boolean {\n return left.length === right.length && left.every((item, index) => item === right[index]);\n}\n\nfunction sameCounts(left: Record<string, number>, right: Record<string, number>): boolean {\n const leftEntries = Object.entries(left);\n const rightEntries = Object.entries(right);\n return (\n leftEntries.length === rightEntries.length &&\n leftEntries.every(([key, value], index) => {\n const [rightKey, rightValue] = rightEntries[index] ?? [];\n return key === rightKey && value === rightValue;\n })\n );\n}\n","import { useEffect } from \"react\";\nimport type { KeepItemInput } from \"../types\";\nimport { useKeepItem } from \"./useKeepItem\";\n\nexport type KeepShortcutModifier = \"meta\" | \"ctrl\" | \"alt\" | \"shift\";\n\nexport type KeepShortcutOptions<TMeta = Record<string, unknown>> = {\n key: string;\n modifier?: KeepShortcutModifier;\n id?: string;\n itemPayload?: KeepItemInput<TMeta>;\n action?: \"toggle\" | \"save\" | \"remove\";\n enabled?: boolean;\n preventDefault?: boolean;\n allowInEditable?: boolean;\n onTrigger?: (event: KeyboardEvent) => void | Promise<void>;\n onError?: (error: unknown) => void;\n};\n\n/** Bind a keyboard shortcut to a Keep action or an arbitrary command. */\nexport function useKeepShortcut<TMeta = Record<string, unknown>>(options: KeepShortcutOptions<TMeta>): void {\n const item = useKeepItem(options.id ?? \"\", options.itemPayload);\n const {\n action = \"toggle\",\n allowInEditable = false,\n enabled = true,\n key,\n modifier,\n onError,\n onTrigger,\n preventDefault = true,\n } = options;\n\n useEffect(() => {\n if (!enabled) return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!allowInEditable && isEditableTarget(event.target)) return;\n if (!matchesShortcut(event, key, modifier)) return;\n if (preventDefault) event.preventDefault();\n const run = onTrigger\n ? onTrigger(event)\n : options.id\n ? action === \"save\"\n ? item.save()\n : action === \"remove\"\n ? item.remove()\n : item.toggle()\n : undefined;\n if (run) void Promise.resolve(run).catch((error) => onError?.(error));\n };\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => window.removeEventListener(\"keydown\", handleKeyDown);\n }, [\n action,\n allowInEditable,\n enabled,\n item.remove,\n item.save,\n item.toggle,\n key,\n modifier,\n onError,\n onTrigger,\n options.id,\n preventDefault,\n ]);\n}\n\nfunction matchesShortcut(event: KeyboardEvent, key: string, modifier?: KeepShortcutModifier): boolean {\n if (event.key.toLocaleLowerCase() !== key.toLocaleLowerCase()) return false;\n const modifiers = {\n meta: event.metaKey,\n ctrl: event.ctrlKey,\n alt: event.altKey,\n shift: event.shiftKey,\n };\n if (modifier ? !modifiers[modifier] : Object.values(modifiers).some(Boolean)) return false;\n return Object.entries(modifiers).every(([name, pressed]) => name === modifier || !pressed);\n}\n\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false;\n return (\n target.isContentEditable ||\n target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.tagName === \"SELECT\"\n );\n}\n","import {\n type ButtonHTMLAttributes,\n Children,\n cloneElement,\n type HTMLAttributes,\n isValidElement,\n type KeyboardEvent,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n} from \"react\";\nimport { useKeepItem } from \"./hooks/useKeepItem\";\nimport type { KeepItemInput } from \"./types\";\n\nexport type KeepButtonItem<TMeta = Record<string, unknown>> = KeepItemInput<TMeta> & {\n id: string;\n};\n\ntype KeepButtonSharedProps<TMeta> = {\n item: KeepButtonItem<TMeta>;\n children?: ReactNode | ((state: KeepButtonState<TMeta>) => ReactNode);\n savedLabel?: ReactNode;\n unsavedLabel?: ReactNode;\n savedAriaLabel?: string;\n unsavedAriaLabel?: string;\n getAriaLabel?: (state: KeepButtonState<TMeta>) => string;\n disabled?: boolean;\n onToggleError?: (error: unknown) => void;\n};\n\nexport type KeepButtonProps<TMeta = Record<string, unknown>> = KeepButtonSharedProps<TMeta> &\n (\n | (Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"children\" | \"onClick\" | \"aria-pressed\"> & {\n asChild?: false;\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\n })\n | (Omit<HTMLAttributes<HTMLElement>, \"children\" | \"onClick\" | \"aria-pressed\"> & {\n asChild: true;\n children: ReactElement | ((state: KeepButtonState<TMeta>) => ReactElement);\n onClick?: (event: MouseEvent<HTMLElement>) => void;\n })\n );\n\nexport type KeepButtonState<TMeta = Record<string, unknown>> = {\n item: ReturnType<typeof useKeepItem<TMeta>>[\"item\"];\n isSaved: boolean;\n isLoading: boolean;\n isMutating: boolean;\n error: unknown | null;\n save: () => Promise<void>;\n remove: () => Promise<void>;\n toggle: () => Promise<void>;\n updateNote: (note?: string) => Promise<void>;\n updateTags: (tags?: string[]) => Promise<void>;\n};\n\n/** A style-free accessible save toggle. Consumers provide all visual styling. */\nexport function KeepButton<TMeta = Record<string, unknown>>({\n item,\n children,\n savedLabel = \"Saved\",\n unsavedLabel = \"Save\",\n savedAriaLabel,\n unsavedAriaLabel,\n getAriaLabel,\n asChild = false,\n onToggleError,\n onClick,\n disabled,\n ...buttonProps\n}: KeepButtonProps<TMeta>) {\n const state = useKeepItem(item.id, {\n meta: item.meta,\n targetType: item.targetType,\n note: item.note,\n tags: item.tags,\n });\n const { isSaved, toggle } = state;\n const isDisabled = disabled ?? state.isMutating;\n\n async function handleClick(event: MouseEvent<HTMLElement>) {\n if (isDisabled) return;\n if (asChild) {\n (onClick as ((event: MouseEvent<HTMLElement>) => void) | undefined)?.(event);\n } else {\n (onClick as ((event: MouseEvent<HTMLButtonElement>) => void) | undefined)?.(\n event as MouseEvent<HTMLButtonElement>,\n );\n }\n if (event.defaultPrevented) return;\n try {\n await toggle();\n } catch (error) {\n onToggleError?.(error);\n }\n }\n\n const content =\n typeof children === \"function\" ? children(state) : (children ?? (isSaved ? savedLabel : unsavedLabel));\n function handleElementClick(event: MouseEvent<HTMLElement>) {\n if (isDisabled) return;\n if (asChild && isValidElement<{ onClick?: (event: MouseEvent<HTMLElement>) => void }>(content)) {\n content.props.onClick?.(event);\n }\n if (!event.defaultPrevented) void handleClick(event);\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLElement>) {\n if (asChild && isValidElement<{ onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void }>(content)) {\n content.props.onKeyDown?.(event);\n }\n (buttonProps as { onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void }).onKeyDown?.(event);\n if (!event.defaultPrevented && !isDisabled && asChild && (event.key === \"Enter\" || event.key === \" \")) {\n void handleClick(event as unknown as MouseEvent<HTMLElement>);\n event.preventDefault();\n }\n }\n\n const child = asChild ? Children.only(content) : undefined;\n if (asChild && !isValidElement(child)) {\n throw new Error(\"KeepButton with asChild requires a single React element child.\");\n }\n\n const commonProps = {\n ...buttonProps,\n \"aria-pressed\": isSaved,\n \"aria-label\":\n (\"aria-label\" in buttonProps ? buttonProps[\"aria-label\"] : undefined) ??\n getAriaLabel?.(state) ??\n (isSaved ? savedAriaLabel : unsavedAriaLabel) ??\n getAccessibleLabel(isSaved, item, asChild),\n ...(asChild\n ? {\n \"aria-disabled\": isDisabled,\n role: buttonProps.role ?? \"button\",\n tabIndex: isDisabled ? -1 : (buttonProps.tabIndex ?? 0),\n }\n : { disabled: isDisabled }),\n onClick: handleElementClick,\n onKeyDown: handleKeyDown,\n };\n\n if (asChild) {\n return cloneElement(child as ReactElement, commonProps);\n }\n\n return (\n <button {...commonProps} type={\"type\" in buttonProps ? (buttonProps.type ?? \"button\") : \"button\"}>\n {content}\n </button>\n );\n}\n\nfunction getAccessibleLabel<TMeta>(isSaved: boolean, item: KeepButtonItem<TMeta>, asChild: boolean): string {\n if (!asChild) return isSaved ? \"Remove saved item\" : \"Save item\";\n const title = getMetaTitle(item.meta);\n const subject = title ? `${item.targetType ?? \"item\"}: ${title}` : (item.targetType ?? \"item\");\n return `${isSaved ? \"Remove\" : \"Save\"} ${subject}`;\n}\n\nfunction getMetaTitle<TMeta>(meta: TMeta): string | undefined {\n if (typeof meta !== \"object\" || meta === null || !(\"title\" in meta)) return undefined;\n const title = (meta as { title?: unknown }).title;\n return typeof title === \"string\" && title.trim() ? title.trim() : undefined;\n}\n","import type { ComponentType } from \"react\";\nimport { type UseKeepItemResult, useKeepItem } from \"./hooks/useKeepItem\";\nimport { type UseKeepListResult, useKeepList } from \"./hooks/useKeepList\";\nimport { type KeepShortcutOptions, useKeepShortcut } from \"./hooks/useKeepShortcut\";\nimport { KeepButton, type KeepButtonProps } from \"./KeepButton\";\nimport { KeepProvider, type KeepProviderProps, useKeepContext } from \"./KeepProvider\";\nimport type { KeepListOptions } from \"./query\";\nimport type { KeepInvalidItemPolicy, KeepItemInput, KeepPlugin, KeepSchema } from \"./types\";\n\nexport type CreateKeepKitOptions<TMeta = Record<string, unknown>> = {\n initialItems?: KeepProviderProps<TMeta>[\"initialItems\"];\n plugins?: KeepPlugin<TMeta>[];\n schemaVersion?: number;\n schema?: KeepSchema<TMeta>;\n invalidItemPolicy?: KeepInvalidItemPolicy;\n onInvalidItem?: KeepProviderProps<TMeta>[\"onInvalidItem\"];\n migrateMeta?: KeepProviderProps<TMeta>[\"migrateMeta\"];\n};\n\nexport type KeepKit<TMeta> = {\n KeepProvider: ComponentType<KeepProviderProps<TMeta>>;\n KeepButton: ComponentType<KeepButtonProps<TMeta>>;\n useKeepContext: () => ReturnType<typeof useKeepContext<TMeta>>;\n useKeepItem: (id: string, itemPayload?: KeepItemInput<TMeta>) => UseKeepItemResult<TMeta>;\n useKeepList: (options?: KeepListOptions<TMeta>) => UseKeepListResult<TMeta>;\n useKeepShortcut: (options: KeepShortcutOptions<TMeta>) => void;\n};\n\n/** Create an app-specific, fully typed set of KeepKit components and hooks. */\nexport function createKeepKit<TMeta = Record<string, unknown>>(\n options: CreateKeepKitOptions<TMeta> = {},\n): KeepKit<TMeta> {\n return {\n KeepProvider: (props) => <KeepProvider<TMeta> {...options} {...props} />,\n KeepButton: (props) => <KeepButton<TMeta> {...props} />,\n useKeepContext: () => useKeepContext<TMeta>(),\n useKeepItem: (id, itemPayload) => useKeepItem<TMeta>(id, itemPayload),\n useKeepList: (options) => useKeepList<TMeta>(options),\n useKeepShortcut: (shortcutOptions) => useKeepShortcut<TMeta>(shortcutOptions),\n };\n}\n"],"mappings":"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","names":["useCallback","refresh","useCallback","useRef","useSyncExternalStore","useCallback","useCallback","useMemo","useMemo","tag","useCallback","tags","useEffect","useEffect","jsx","jsx","options"]}
@@ -1,4 +1,4 @@
1
- import { a as KeepItem, S as StorageAdapter } from './types-BRfvVnCA.js';
1
+ import { a as KeepItem, S as StorageAdapter, f as KeepChangeContext } from './types-BRfvVnCA.js';
2
2
 
3
3
  type KeepListOptions<TMeta = Record<string, unknown>> = {
4
4
  targetType?: string;
@@ -75,6 +75,7 @@ type KeepStoreState<TMeta = Record<string, unknown>> = {
75
75
  isHydrated: boolean;
76
76
  isMutating: boolean;
77
77
  error: unknown | null;
78
+ lastChange?: KeepChangeContext<TMeta>;
78
79
  };
79
80
  type KeepStoreActions<TMeta = Record<string, unknown>> = {
80
81
  saveItem: (item: KeepItem<TMeta>) => Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keepkit/core",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "A flexible save-and-collect toolkit for React apps.",
5
5
  "type": "module",
6
6
  "license": "MIT",