@keepkit/core 0.28.0 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/{chunk-XUHRDJD6.js → chunk-HDML3IDX.js} +55 -68
- package/dist/chunk-HDML3IDX.js.map +1 -0
- package/dist/{chunk-O6FNZ5N2.js → chunk-JGGKIE3O.js} +42 -38
- package/dist/chunk-JGGKIE3O.js.map +1 -0
- package/dist/core.d.ts +5 -5
- package/dist/core.js +39 -6
- package/dist/core.js.map +1 -1
- package/dist/react.d.ts +18 -6
- package/dist/react.js +80 -79
- package/dist/react.js.map +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/{scope-kVcPskvM.d.ts → scope-BsU6xvN9.d.ts} +1 -1
- package/dist/storage.d.ts +3 -3
- package/dist/storage.js +1 -1
- package/dist/{store-pfMOz7sn.d.ts → store-DbAAC4yU.d.ts} +23 -5
- package/dist/{types-6ex9EBjM.d.ts → types-CJIbuqTO.d.ts} +3 -1
- package/package.json +1 -1
- package/dist/chunk-O6FNZ5N2.js.map +0 -1
- package/dist/chunk-XUHRDJD6.js.map +0 -1
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
validateKeepItem
|
|
3
3
|
} from "./chunk-5W4QSJHV.js";
|
|
4
|
+
import {
|
|
5
|
+
isKeepItem,
|
|
6
|
+
isRecord,
|
|
7
|
+
mergeKeepItemLists,
|
|
8
|
+
persistKeepItems,
|
|
9
|
+
removeKeepItems
|
|
10
|
+
} from "./chunk-HDML3IDX.js";
|
|
4
11
|
|
|
5
12
|
// src/features/items/navigation.ts
|
|
6
13
|
function orderKeepItems(items) {
|
|
@@ -64,15 +71,7 @@ function moveKeepItem(source, id, targetIndex) {
|
|
|
64
71
|
// src/features/persistence/migration.ts
|
|
65
72
|
async function mergeKeepItems(localItems, target) {
|
|
66
73
|
if (target.merge) return target.merge(localItems);
|
|
67
|
-
const
|
|
68
|
-
const byId = new Map(remoteItems.map((item) => [item.id, item]));
|
|
69
|
-
for (const localItem of localItems) {
|
|
70
|
-
const remoteItem = byId.get(localItem.id);
|
|
71
|
-
if (!remoteItem || localItem.updatedAt > remoteItem.updatedAt) {
|
|
72
|
-
byId.set(localItem.id, localItem);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
const merged = [...byId.values()].sort((a, b) => b.updatedAt - a.updatedAt);
|
|
74
|
+
const merged = mergeKeepItemLists(await target.getAll(), localItems);
|
|
76
75
|
await Promise.all(merged.map((item) => target.set(item)));
|
|
77
76
|
return merged;
|
|
78
77
|
}
|
|
@@ -186,30 +185,28 @@ function parseBackup(data) {
|
|
|
186
185
|
}
|
|
187
186
|
return value;
|
|
188
187
|
}
|
|
189
|
-
function isKeepItem(value) {
|
|
190
|
-
if (!isRecord(value)) return false;
|
|
191
|
-
return typeof value.id === "string" && typeof value.savedAt === "number" && Number.isFinite(value.savedAt) && typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) && "meta" in value && (value.order === void 0 || typeof value.order === "number" && Number.isFinite(value.order)) && (value.archived === void 0 || typeof value.archived === "boolean") && (value.pinned === void 0 || typeof value.pinned === "boolean") && (value.collectionId === void 0 || typeof value.collectionId === "string") && (value.targetType === void 0 || typeof value.targetType === "string") && (value.note === void 0 || typeof value.note === "string") && (value.schemaVersion === void 0 || typeof value.schemaVersion === "number" && Number.isFinite(value.schemaVersion)) && (value.revision === void 0 || typeof value.revision === "string") && (value.metaUpdatedAt === void 0 || typeof value.metaUpdatedAt === "number" && Number.isFinite(value.metaUpdatedAt)) && (value.status === void 0 || value.status === "available" || value.status === "expired" || value.status === "removed" || value.status === "deleted" || value.status === "private" || value.status === "unknown") && (value.statusReason === void 0 || typeof value.statusReason === "string") && (value.scope === void 0 || isSyncScope(value.scope)) && (value.tags === void 0 || Array.isArray(value.tags) && value.tags.every((tag) => typeof tag === "string"));
|
|
192
|
-
}
|
|
193
|
-
function isRecord(value) {
|
|
194
|
-
return typeof value === "object" && value !== null;
|
|
195
|
-
}
|
|
196
|
-
function isSyncScope(value) {
|
|
197
|
-
return isRecord(value) && (value.userId === void 0 || typeof value.userId === "string") && (value.tenantId === void 0 || typeof value.tenantId === "string");
|
|
198
|
-
}
|
|
199
188
|
|
|
200
189
|
// src/features/items/query.ts
|
|
190
|
+
var DEFAULT_REDISCOVERY_INACTIVE_FOR_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
191
|
+
function createRediscoveryQuery(options) {
|
|
192
|
+
if (options.strategy === "never-opened") return { activity: { opened: "never" } };
|
|
193
|
+
if (options.strategy === "recently-opened") {
|
|
194
|
+
return { activity: { opened: "ever" }, sort: { by: "lastOpenedAt", direction: "desc" } };
|
|
195
|
+
}
|
|
196
|
+
return { activity: { inactiveForMs: options.inactiveForMs ?? DEFAULT_REDISCOVERY_INACTIVE_FOR_MS } };
|
|
197
|
+
}
|
|
201
198
|
function queryKeepItems(source, query = {}) {
|
|
202
199
|
const filtered = source.filter((item) => {
|
|
203
200
|
const [from, to] = query.savedBetween ?? [];
|
|
204
201
|
const savedAt = item.savedAt;
|
|
205
202
|
const lowerBound = from === void 0 ? void 0 : toTimestamp(from);
|
|
206
203
|
const upperBound = to === void 0 ? void 0 : toTimestamp(to);
|
|
207
|
-
return (query.targetType === void 0 || item.targetType === query.targetType) && (query.tags === void 0 || query.tags.every((tag) => item.tags?.includes(tag))) && matchesArchiveScope(item, query) && (query.collectionId === void 0 || item.collectionId === query.collectionId) && (lowerBound === void 0 || savedAt >= lowerBound) && (upperBound === void 0 || savedAt <= upperBound) && matchesSearch(item, query.search) && (query.filter?.(item) ?? true);
|
|
204
|
+
return (query.targetType === void 0 || item.targetType === query.targetType) && (query.tags === void 0 || query.tags.every((tag) => item.tags?.includes(tag))) && matchesArchiveScope(item, query) && (query.collectionId === void 0 || item.collectionId === query.collectionId) && matchesActivity(item, query.activity) && (lowerBound === void 0 || savedAt >= lowerBound) && (upperBound === void 0 || savedAt <= upperBound) && matchesSearch(item, query.search) && (query.filter?.(item) ?? true);
|
|
208
205
|
});
|
|
209
206
|
const tagCounts = getTagCounts(filtered);
|
|
210
207
|
const sortBy = query.sort?.by;
|
|
211
208
|
const direction = query.sort?.direction === "asc" ? 1 : -1;
|
|
212
|
-
const sortedBase = sortBy ? filtered.map((item, index) => ({ item, index })).sort((a, b) => (a.item[sortBy]
|
|
209
|
+
const sortedBase = sortBy ? filtered.map((item, index) => ({ item, index })).sort((a, b) => compareSortValues(a.item[sortBy], b.item[sortBy], direction) || a.index - b.index).map(({ item }) => item) : orderKeepItems(filtered);
|
|
213
210
|
const sorted = query.pinnedFirst ? [...sortedBase.filter((item) => item.pinned === true), ...sortedBase.filter((item) => item.pinned !== true)] : sortedBase;
|
|
214
211
|
const pageSize = Math.max(1, query.pagination?.pageSize ?? (sorted.length || 1));
|
|
215
212
|
const pageCount = Math.max(1, Math.ceil(sorted.length / pageSize));
|
|
@@ -225,6 +222,26 @@ function queryKeepItems(source, query = {}) {
|
|
|
225
222
|
hasPreviousPage: page > 1
|
|
226
223
|
};
|
|
227
224
|
}
|
|
225
|
+
function matchesActivity(item, activity) {
|
|
226
|
+
if (!activity) return true;
|
|
227
|
+
const lastOpenedAt = item.lastOpenedAt;
|
|
228
|
+
const opened = lastOpenedAt !== void 0;
|
|
229
|
+
if (activity.opened === "ever" && !opened) return false;
|
|
230
|
+
if (activity.opened === "never" && opened) return false;
|
|
231
|
+
if (activity.lastOpenedBefore !== void 0 && (!opened || lastOpenedAt >= activity.lastOpenedBefore)) return false;
|
|
232
|
+
if (activity.lastOpenedAfter !== void 0 && (!opened || lastOpenedAt <= activity.lastOpenedAfter)) return false;
|
|
233
|
+
if (activity.inactiveForMs !== void 0) {
|
|
234
|
+
const cutoff = Date.now() - activity.inactiveForMs;
|
|
235
|
+
if (opened && lastOpenedAt > cutoff) return false;
|
|
236
|
+
}
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
function compareSortValues(left, right, direction) {
|
|
240
|
+
if (left === void 0 && right === void 0) return 0;
|
|
241
|
+
if (left === void 0) return 1;
|
|
242
|
+
if (right === void 0) return -1;
|
|
243
|
+
return (left - right) * direction;
|
|
244
|
+
}
|
|
228
245
|
function matchesArchiveScope(item, query) {
|
|
229
246
|
if (query.archiveScope === "all") return true;
|
|
230
247
|
if (query.archiveScope === "archived") return item.archived === true;
|
|
@@ -317,24 +334,10 @@ async function revalidateKeepItems(source, revalidator, options = {}) {
|
|
|
317
334
|
async function reconcileKeepItems(storage, revalidator, options = {}) {
|
|
318
335
|
const source = await storage.getAll();
|
|
319
336
|
const summary = await revalidateKeepItems(source, revalidator, options);
|
|
320
|
-
if (summary.updatedItems.length > 0) await
|
|
321
|
-
if (summary.removedIds.length > 0) await
|
|
337
|
+
if (summary.updatedItems.length > 0) await persistKeepItems(storage, summary.updatedItems);
|
|
338
|
+
if (summary.removedIds.length > 0) await removeKeepItems(storage, summary.removedIds);
|
|
322
339
|
return summary;
|
|
323
340
|
}
|
|
324
|
-
async function persistItems(storage, items) {
|
|
325
|
-
if (storage.setMany) {
|
|
326
|
-
await storage.setMany(items);
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
for (const item of items) await storage.set(item);
|
|
330
|
-
}
|
|
331
|
-
async function removeItems(storage, ids) {
|
|
332
|
-
if (storage.removeMany) {
|
|
333
|
-
await storage.removeMany(ids);
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
for (const id of ids) await storage.remove(id);
|
|
337
|
-
}
|
|
338
341
|
function clearItemStatus(item) {
|
|
339
342
|
const next = { ...item };
|
|
340
343
|
delete next.status;
|
|
@@ -380,6 +383,7 @@ export {
|
|
|
380
383
|
KeepBackupImportError,
|
|
381
384
|
exportItems,
|
|
382
385
|
importItems,
|
|
386
|
+
createRediscoveryQuery,
|
|
383
387
|
queryKeepItems,
|
|
384
388
|
getTagCounts,
|
|
385
389
|
isKeepItemMetadataStale,
|
|
@@ -387,4 +391,4 @@ export {
|
|
|
387
391
|
reconcileKeepItems,
|
|
388
392
|
KeepStore
|
|
389
393
|
};
|
|
390
|
-
//# sourceMappingURL=chunk-
|
|
394
|
+
//# sourceMappingURL=chunk-JGGKIE3O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features/items/navigation.ts","../src/features/persistence/migration.ts","../src/features/persistence/backup.ts","../src/features/items/query.ts","../src/features/items/revalidation.ts","../src/features/store/store.ts"],"sourcesContent":["import type { KeepItem } from \"./types\";\n\nexport type KeepNavigationState<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n currentIndex: number;\n currentPosition: number | null;\n currentItem: KeepItem<TMeta> | null;\n hasNext: boolean;\n hasPrev: boolean;\n nextItem: KeepItem<TMeta> | null;\n prevItem: KeepItem<TMeta> | null;\n};\n\n/** Return items in their persisted custom order, leaving legacy items stable. */\nexport function orderKeepItems<TMeta>(items: readonly KeepItem<TMeta>[]): KeepItem<TMeta>[] {\n if (!items.some((item) => item.order !== undefined)) return [...items];\n return items\n .map((item, index) => ({ item, index }))\n .sort((left, right) => {\n const leftOrder = left.item.order;\n const rightOrder = right.item.order;\n if (leftOrder === undefined && rightOrder !== undefined) return 1;\n if (leftOrder !== undefined && rightOrder === undefined) return -1;\n if (leftOrder !== undefined && rightOrder !== undefined && leftOrder !== rightOrder) {\n return leftOrder - rightOrder;\n }\n return left.index - right.index;\n })\n .map(({ item }) => item);\n}\n\n/** Derive the previous/current/next view for a list and an item id or index. */\nexport function getKeepNavigationState<TMeta = Record<string, unknown>>(\n source: readonly KeepItem<TMeta>[],\n current?: string | number,\n): KeepNavigationState<TMeta> {\n const items = orderKeepItems(source);\n const currentIndex =\n typeof current === \"number\"\n ? Number.isInteger(current) && current >= 0 && current < items.length\n ? current\n : -1\n : current === undefined\n ? -1\n : items.findIndex((item) => item.id === current);\n const currentItem = currentIndex >= 0 ? (items[currentIndex] ?? null) : null;\n return {\n items,\n currentIndex,\n currentPosition: currentIndex >= 0 ? currentIndex + 1 : null,\n currentItem,\n hasNext: currentIndex >= 0 && currentIndex < items.length - 1,\n hasPrev: currentIndex > 0,\n nextItem: currentIndex >= 0 ? (items[currentIndex + 1] ?? null) : null,\n prevItem: currentIndex > 0 ? (items[currentIndex - 1] ?? null) : null,\n };\n}\n\n/** Apply a partial or complete id order and assign stable zero-based positions. */\nexport function reorderKeepItems<TMeta = Record<string, unknown>>(\n source: readonly KeepItem<TMeta>[],\n orderedIds: readonly string[],\n): KeepItem<TMeta>[] {\n const byId = new Map(source.map((item) => [item.id, item]));\n const seen = new Set<string>();\n for (const id of orderedIds) {\n if (!byId.has(id)) throw new Error(`Cannot reorder unknown Keep item \"${id}\".`);\n if (seen.has(id)) throw new Error(`Cannot reorder Keep items with duplicate id \"${id}\".`);\n seen.add(id);\n }\n const current = orderKeepItems(source);\n const sequence = [...orderedIds, ...current.map((item) => item.id).filter((id) => !seen.has(id))];\n return sequence.map((id, order) => {\n const item = byId.get(id);\n if (!item) throw new Error(`Cannot reorder unknown Keep item \"${id}\".`);\n return { ...item, order };\n });\n}\n\n/** Move one item within the current custom/legacy order. */\nexport function moveKeepItem<TMeta = Record<string, unknown>>(\n source: readonly KeepItem<TMeta>[],\n id: string,\n targetIndex: number,\n): KeepItem<TMeta>[] {\n const items = orderKeepItems(source);\n const currentIndex = items.findIndex((item) => item.id === id);\n if (currentIndex < 0) throw new Error(`Cannot move unknown Keep item \"${id}\".`);\n if (!Number.isInteger(targetIndex)) throw new Error(\"Keep item targetIndex must be an integer.\");\n const nextIndex = Math.min(Math.max(0, targetIndex), items.length - 1);\n const [item] = items.splice(currentIndex, 1);\n items.splice(nextIndex, 0, item);\n return reorderKeepItems(\n items,\n items.map((entry) => entry.id),\n );\n}\n","import type { KeepItem, StorageAdapter } from \"../items/types\";\nimport { mergeKeepItemLists } from \"./helpers\";\n\n/** Merge anonymous local items into a signed-in or remote adapter. */\nexport async function mergeKeepItems<TMeta>(\n localItems: KeepItem<TMeta>[],\n target: StorageAdapter<TMeta>,\n): Promise<KeepItem<TMeta>[]> {\n if (target.merge) return target.merge(localItems);\n\n const merged = mergeKeepItemLists(await target.getAll(), localItems);\n await Promise.all(merged.map((item) => target.set(item)));\n return merged;\n}\n\n/** Read anonymous items, merge them into the target, then clear the source. */\nexport async function migrateKeepItems<TMeta>(\n source: StorageAdapter<TMeta>,\n target: StorageAdapter<TMeta>,\n): Promise<KeepItem<TMeta>[]> {\n const localItems = await source.getAll();\n const merged = await mergeKeepItems(localItems, target);\n await source.clear();\n return merged;\n}\n","import type { KeepInvalidItemPolicy, KeepItem, KeepSchema, StorageAdapter } from \"../items/types\";\nimport { isKeepItem, isRecord } from \"./helpers\";\nimport { mergeKeepItems } from \"./migration\";\nimport { validateKeepItem } from \"./schema\";\n\nexport const KEEP_BACKUP_FORMAT = \"keepkit\";\nexport const KEEP_BACKUP_VERSION = 1;\n\nexport type KeepBackup<TMeta = Record<string, unknown>> = {\n format: typeof KEEP_BACKUP_FORMAT;\n version: typeof KEEP_BACKUP_VERSION;\n exportedAt: number;\n items: KeepItem<TMeta>[];\n};\n\nexport type ImportItemsOptions<TMeta = unknown> = {\n mode?: \"replace\" | \"merge\";\n schema?: KeepSchema<TMeta>;\n invalidItemPolicy?: KeepInvalidItemPolicy;\n onInvalidItem?: (error: unknown, item: KeepItem<unknown>) => void;\n};\n\nexport type ImportItemsResult<TMeta = Record<string, unknown>> = {\n mode: \"replace\" | \"merge\";\n imported: number;\n failed: number;\n total: number;\n items: KeepItem<TMeta>[];\n};\n\nexport class KeepBackupParseError extends Error {\n readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = \"KeepBackupParseError\";\n if (options?.cause !== undefined) this.cause = options.cause;\n }\n}\n\nexport class KeepBackupImportError extends Error {\n readonly mode: \"replace\" | \"merge\";\n readonly imported: number;\n readonly failed: number;\n readonly cause?: unknown;\n\n constructor(\n message: string,\n options: {\n mode: \"replace\" | \"merge\";\n imported: number;\n failed: number;\n cause?: unknown;\n },\n ) {\n super(message);\n this.name = \"KeepBackupImportError\";\n this.mode = options.mode;\n this.imported = options.imported;\n this.failed = options.failed;\n if (options.cause !== undefined) this.cause = options.cause;\n }\n}\n\n/** Serialize all adapter data into a versioned JSON backup. */\nexport async function exportItems<TMeta>(adapter: StorageAdapter<TMeta>): Promise<string> {\n const backup: KeepBackup<TMeta> = {\n format: KEEP_BACKUP_FORMAT,\n version: KEEP_BACKUP_VERSION,\n exportedAt: Date.now(),\n items: await adapter.getAll(),\n };\n return JSON.stringify(backup, null, 2);\n}\n\n/** Validate and restore a backup, either replacing or merging existing data. */\nexport async function importItems<TMeta>(\n adapter: StorageAdapter<TMeta>,\n data: string | KeepBackup<TMeta>,\n options: ImportItemsOptions<TMeta> = {},\n): Promise<ImportItemsResult<TMeta>> {\n const backup = parseBackup<TMeta>(data);\n const mode = options.mode ?? \"merge\";\n const validItems: KeepItem<TMeta>[] = [];\n let failed = 0;\n for (const item of backup.items) {\n if (!options.schema) {\n validItems.push(item);\n continue;\n }\n try {\n validItems.push(await validateKeepItem(item, options.schema));\n } catch (cause) {\n options.onInvalidItem?.(cause, item);\n if ((options.invalidItemPolicy ?? \"error\") === \"drop\") {\n failed += 1;\n continue;\n }\n throw cause;\n }\n }\n let items: KeepItem<TMeta>[];\n\n if (mode === \"merge\") {\n try {\n items = await mergeKeepItems(validItems, adapter);\n } catch (cause) {\n throw new KeepBackupImportError(\"KeepKit could not merge the backup.\", {\n mode,\n imported: 0,\n failed: validItems.length + failed,\n cause,\n });\n }\n } else {\n let imported = 0;\n try {\n await adapter.clear();\n for (const item of validItems) {\n await adapter.set(item);\n imported += 1;\n }\n items = await adapter.getAll();\n } catch (cause) {\n throw new KeepBackupImportError(\"KeepKit could not replace the stored items.\", {\n mode,\n imported,\n failed: validItems.length + failed - imported,\n cause,\n });\n }\n }\n\n return { mode, imported: validItems.length, failed, total: items.length, items };\n}\n\nfunction parseBackup<TMeta>(data: string | KeepBackup<TMeta>): KeepBackup<TMeta> {\n let value: unknown = data;\n if (typeof data === \"string\") {\n try {\n value = JSON.parse(data);\n } catch (cause) {\n throw new KeepBackupParseError(\"KeepKit backup is not valid JSON.\", { cause });\n }\n }\n\n if (!isRecord(value)) throw new KeepBackupParseError(\"KeepKit backup must be an object.\");\n if (value.format !== KEEP_BACKUP_FORMAT || value.version !== KEEP_BACKUP_VERSION) {\n throw new KeepBackupParseError(\"KeepKit backup format or version is unsupported.\");\n }\n if (typeof value.exportedAt !== \"number\" || !Number.isFinite(value.exportedAt)) {\n throw new KeepBackupParseError(\"KeepKit backup has an invalid export timestamp.\");\n }\n if (!Array.isArray(value.items) || !value.items.every(isKeepItem)) {\n throw new KeepBackupParseError(\"KeepKit backup contains invalid items.\");\n }\n return value as KeepBackup<TMeta>;\n}\n","import { orderKeepItems } from \"./navigation\";\nimport type { KeepItem } from \"./types\";\n\nexport type KeepListQuery<TMeta = Record<string, unknown>> = {\n targetType?: string;\n tags?: string[];\n /** Defaults to active (not archived) items; true selects archived items. */\n archived?: boolean;\n /** Optional explicit archive scope. When provided, this takes precedence over `archived`. */\n archiveScope?: \"active\" | \"archived\" | \"all\";\n collectionId?: string;\n pinnedFirst?: boolean;\n activity?: {\n opened?: \"ever\" | \"never\";\n lastOpenedBefore?: number;\n lastOpenedAfter?: number;\n inactiveForMs?: number;\n };\n sort?: {\n by: \"savedAt\" | \"updatedAt\" | \"lastOpenedAt\";\n direction?: \"asc\" | \"desc\";\n };\n search?: {\n query?: string;\n mode?: \"and\" | \"or\";\n tokenize?: boolean;\n fields?: Array<\"note\" | \"meta\" | \"tags\">;\n };\n pagination?: {\n page?: number;\n pageSize?: number;\n };\n filter?: (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 page: number;\n pageCount: number;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n};\n\nexport type KeepRediscoveryStrategy = \"never-opened\" | \"forgotten\" | \"recently-opened\";\n\nexport type KeepRediscoveryOptions = {\n strategy: KeepRediscoveryStrategy;\n inactiveForMs?: number;\n};\n\nconst DEFAULT_REDISCOVERY_INACTIVE_FOR_MS = 30 * 24 * 60 * 60 * 1000;\n\n/** Build a serializable query for common rediscovery views. */\nexport function createRediscoveryQuery<TMeta = Record<string, unknown>>(\n options: KeepRediscoveryOptions,\n): KeepListQuery<TMeta> {\n if (options.strategy === \"never-opened\") return { activity: { opened: \"never\" } };\n if (options.strategy === \"recently-opened\") {\n return { activity: { opened: \"ever\" }, sort: { by: \"lastOpenedAt\", direction: \"desc\" } };\n }\n return { activity: { inactiveForMs: options.inactiveForMs ?? DEFAULT_REDISCOVERY_INACTIVE_FOR_MS } };\n}\n\n/** Apply the collection query and one-based pagination without React. */\nexport function queryKeepItems<TMeta = Record<string, unknown>>(\n source: KeepItem<TMeta>[],\n query: KeepListQuery<TMeta> = {},\n): QueryKeepItemsResult<TMeta> {\n const filtered = source.filter((item) => {\n const [from, to] = query.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 (query.targetType === undefined || item.targetType === query.targetType) &&\n (query.tags === undefined || query.tags.every((tag) => item.tags?.includes(tag))) &&\n matchesArchiveScope(item, query) &&\n (query.collectionId === undefined || item.collectionId === query.collectionId) &&\n matchesActivity(item, query.activity) &&\n (lowerBound === undefined || savedAt >= lowerBound) &&\n (upperBound === undefined || savedAt <= upperBound) &&\n matchesSearch(item, query.search) &&\n (query.filter?.(item) ?? true)\n );\n });\n const tagCounts = getTagCounts(filtered);\n const sortBy = query.sort?.by;\n const direction = query.sort?.direction === \"asc\" ? 1 : -1;\n const sortedBase = sortBy\n ? filtered\n .map((item, index) => ({ item, index }))\n .sort((a, b) => compareSortValues(a.item[sortBy], b.item[sortBy], direction) || a.index - b.index)\n .map(({ item }) => item)\n : orderKeepItems(filtered);\n const sorted = query.pinnedFirst\n ? [...sortedBase.filter((item) => item.pinned === true), ...sortedBase.filter((item) => item.pinned !== true)]\n : sortedBase;\n const pageSize = Math.max(1, query.pagination?.pageSize ?? (sorted.length || 1));\n const pageCount = Math.max(1, Math.ceil(sorted.length / pageSize));\n const page = Math.min(Math.max(1, query.pagination?.page ?? 1), pageCount);\n const offset = (page - 1) * pageSize;\n\n return {\n items: sorted.slice(offset, offset + pageSize),\n totalCount: sorted.length,\n tagCounts,\n page,\n pageCount,\n hasNextPage: page < pageCount,\n hasPreviousPage: page > 1,\n };\n}\n\nfunction matchesActivity<TMeta>(item: KeepItem<TMeta>, activity?: KeepListQuery<TMeta>[\"activity\"]): boolean {\n if (!activity) return true;\n const lastOpenedAt = item.lastOpenedAt;\n const opened = lastOpenedAt !== undefined;\n if (activity.opened === \"ever\" && !opened) return false;\n if (activity.opened === \"never\" && opened) return false;\n if (activity.lastOpenedBefore !== undefined && (!opened || lastOpenedAt >= activity.lastOpenedBefore)) return false;\n if (activity.lastOpenedAfter !== undefined && (!opened || lastOpenedAt <= activity.lastOpenedAfter)) return false;\n if (activity.inactiveForMs !== undefined) {\n const cutoff = Date.now() - activity.inactiveForMs;\n if (opened && lastOpenedAt > cutoff) return false;\n }\n return true;\n}\n\nfunction compareSortValues(left: number | undefined, right: number | undefined, direction: 1 | -1): number {\n if (left === undefined && right === undefined) return 0;\n if (left === undefined) return 1;\n if (right === undefined) return -1;\n return (left - right) * direction;\n}\n\nfunction matchesArchiveScope<TMeta>(item: KeepItem<TMeta>, query: KeepListQuery<TMeta>): boolean {\n if (query.archiveScope === \"all\") return true;\n if (query.archiveScope === \"archived\") return item.archived === true;\n if (query.archiveScope === \"active\") return item.archived !== true;\n return query.archived === true ? item.archived === true : item.archived !== true;\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>(item: KeepItem<TMeta>, search?: KeepListQuery<TMeta>[\"search\"]): boolean {\n const query = search?.query;\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 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 { persistKeepItems, removeKeepItems } from \"../persistence/helpers\";\nimport type { KeepItem, KeepItemStatus, StorageAdapter } from \"./types\";\n\nexport type { KeepItemStatus } from \"./types\";\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 KeepItemResolver<TMeta = Record<string, unknown>> = (\n item: KeepItem<TMeta>,\n result: KeepItemRevalidationResult<TMeta>,\n) => KeepItem<TMeta> | undefined | Promise<KeepItem<TMeta> | undefined>;\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<TMeta = Record<string, unknown>> = {\n /** Statuses that should be removed after they are detected. Detection is the default. */\n removeStatuses?: Array<Exclude<KeepItemStatus, \"available\">>;\n now?: () => number;\n resolveItem?: KeepItemResolver<TMeta>;\n};\n\nexport type KeepAutoRevalidationOptions<TMeta = Record<string, unknown>> = {\n /** Revalidate after the provider hydrates. Defaults to true when validateItem is supplied. */\n onMount?: boolean;\n /** Revalidate when the browser returns online. Defaults to true. */\n onReconnect?: boolean;\n /** Revalidate repeatedly while mounted. Disabled by default. */\n intervalMs?: number;\n removeStatuses?: Array<Exclude<KeepItemStatus, \"available\">>;\n revalidator?: KeepItemRevalidator<TMeta>;\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<TMeta> = {},\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 const reason = result.status === \"available\" ? undefined : result.reason;\n const defaultResolved = {\n ...item,\n status: result.status,\n ...(result.status === \"available\" ? { statusReason: undefined } : { statusReason: reason }),\n };\n const resolved = options.resolveItem\n ? await (options.resolveItem as KeepItemResolver<TMeta>)(item, result)\n : defaultResolved;\n if (resolved === undefined) {\n removedIds.push(item.id);\n results.push({ item, status: result.status, reason, updated: false });\n continue;\n }\n if (result.status === \"available\") {\n const timestamp = now();\n const availableItem = clearItemStatus(resolved);\n const updated =\n result.meta === undefined\n ? availableItem\n : { ...availableItem, 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 withStatus = { ...resolved, status: result.status, ...(reason ? { statusReason: reason } : {}) };\n const shouldRemove = removeStatuses.has(result.status);\n if (shouldRemove) removedIds.push(item.id);\n else items.push(withStatus);\n if (!shouldRemove && withStatus !== item) updatedItems.push(withStatus);\n results.push({ item: withStatus, status: result.status, reason, updated: !shouldRemove && withStatus !== item });\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<TMeta> = {},\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 persistKeepItems(storage, summary.updatedItems);\n if (summary.removedIds.length > 0) await removeKeepItems(storage, summary.removedIds);\n return summary;\n}\n\nfunction clearItemStatus<TMeta>(item: KeepItem<TMeta>): KeepItem<TMeta> {\n const next = { ...item };\n delete next.status;\n delete next.statusReason;\n return next;\n}\n","import type {\n KeepItemMetadataRefresher,\n KeepItemRevalidationSummary,\n KeepItemRevalidator,\n RevalidateKeepItemsOptions,\n} from \"../items/revalidation\";\nimport type { KeepChangeContext, KeepItem, KeepUndoState } from \"../items/types\";\n\nexport type KeepCollectionMeta = { name: string };\n\nexport type KeepStoreState<TMeta = Record<string, unknown>> = {\n items: KeepItem<TMeta>[];\n collections: Record<string, KeepCollectionMeta>;\n isLoading: boolean;\n isHydrated: boolean;\n isMutating: boolean;\n error: unknown | null;\n lastChange?: KeepChangeContext<TMeta>;\n undo?: KeepUndoState;\n};\n\nexport type KeepStoreActions<TMeta = Record<string, unknown>> = {\n saveItem: (item: KeepItem<TMeta>) => Promise<void>;\n recordOpen: (id: string, openedAt?: number) => Promise<void>;\n updateNote: (id: string, note?: string) => Promise<void>;\n updateTags: (id: string, tags?: string[]) => Promise<void>;\n toggleArchive: (id: string) => Promise<void>;\n archiveItem: (id: string) => Promise<void>;\n unarchiveItem: (id: string) => Promise<void>;\n togglePin: (id: string) => Promise<void>;\n moveToCollection: (id: string, collectionId?: string) => Promise<void>;\n createCollection: (id: string, name: string) => Promise<void>;\n renameCollection: (id: string, name: string) => Promise<void>;\n removeCollection: (id: 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 removeItemWithUndo: (id: string) => Promise<void>;\n removeItemsWithUndo: (ids: string[]) => Promise<void>;\n undoLastRemoval: () => 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<TMeta>,\n ) => Promise<KeepItemRevalidationSummary<TMeta>>;\n reorderItems: (orderedIds: string[]) => Promise<void>;\n moveItem: (id: string, targetIndex: number) => Promise<void>;\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":";;;;;;;;;;;;AAcO,SAAS,eAAsB,OAAsD;AAC1F,MAAI,CAAC,MAAM,KAAK,CAAC,SAAS,KAAK,UAAU,MAAS,EAAG,QAAO,CAAC,GAAG,KAAK;AACrE,SAAO,MACJ,IAAI,CAAC,MAAM,WAAW,EAAE,MAAM,MAAM,EAAE,EACtC,KAAK,CAAC,MAAM,UAAU;AACrB,UAAM,YAAY,KAAK,KAAK;AAC5B,UAAM,aAAa,MAAM,KAAK;AAC9B,QAAI,cAAc,UAAa,eAAe,OAAW,QAAO;AAChE,QAAI,cAAc,UAAa,eAAe,OAAW,QAAO;AAChE,QAAI,cAAc,UAAa,eAAe,UAAa,cAAc,YAAY;AACnF,aAAO,YAAY;AAAA,IACrB;AACA,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B,CAAC,EACA,IAAI,CAAC,EAAE,KAAK,MAAM,IAAI;AAC3B;AAGO,SAAS,uBACd,QACA,SAC4B;AAC5B,QAAM,QAAQ,eAAe,MAAM;AACnC,QAAM,eACJ,OAAO,YAAY,WACf,OAAO,UAAU,OAAO,KAAK,WAAW,KAAK,UAAU,MAAM,SAC3D,UACA,KACF,YAAY,SACV,KACA,MAAM,UAAU,CAAC,SAAS,KAAK,OAAO,OAAO;AACrD,QAAM,cAAc,gBAAgB,IAAK,MAAM,YAAY,KAAK,OAAQ;AACxE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,iBAAiB,gBAAgB,IAAI,eAAe,IAAI;AAAA,IACxD;AAAA,IACA,SAAS,gBAAgB,KAAK,eAAe,MAAM,SAAS;AAAA,IAC5D,SAAS,eAAe;AAAA,IACxB,UAAU,gBAAgB,IAAK,MAAM,eAAe,CAAC,KAAK,OAAQ;AAAA,IAClE,UAAU,eAAe,IAAK,MAAM,eAAe,CAAC,KAAK,OAAQ;AAAA,EACnE;AACF;AAGO,SAAS,iBACd,QACA,YACmB;AACnB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC1D,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,MAAM,YAAY;AAC3B,QAAI,CAAC,KAAK,IAAI,EAAE,EAAG,OAAM,IAAI,MAAM,qCAAqC,EAAE,IAAI;AAC9E,QAAI,KAAK,IAAI,EAAE,EAAG,OAAM,IAAI,MAAM,gDAAgD,EAAE,IAAI;AACxF,SAAK,IAAI,EAAE;AAAA,EACb;AACA,QAAM,UAAU,eAAe,MAAM;AACrC,QAAM,WAAW,CAAC,GAAG,YAAY,GAAG,QAAQ,IAAI,CAAC,SAAS,KAAK,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AAChG,SAAO,SAAS,IAAI,CAAC,IAAI,UAAU;AACjC,UAAM,OAAO,KAAK,IAAI,EAAE;AACxB,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,qCAAqC,EAAE,IAAI;AACtE,WAAO,EAAE,GAAG,MAAM,MAAM;AAAA,EAC1B,CAAC;AACH;AAGO,SAAS,aACd,QACA,IACA,aACmB;AACnB,QAAM,QAAQ,eAAe,MAAM;AACnC,QAAM,eAAe,MAAM,UAAU,CAACA,UAASA,MAAK,OAAO,EAAE;AAC7D,MAAI,eAAe,EAAG,OAAM,IAAI,MAAM,kCAAkC,EAAE,IAAI;AAC9E,MAAI,CAAC,OAAO,UAAU,WAAW,EAAG,OAAM,IAAI,MAAM,2CAA2C;AAC/F,QAAM,YAAY,KAAK,IAAI,KAAK,IAAI,GAAG,WAAW,GAAG,MAAM,SAAS,CAAC;AACrE,QAAM,CAAC,IAAI,IAAI,MAAM,OAAO,cAAc,CAAC;AAC3C,QAAM,OAAO,WAAW,GAAG,IAAI;AAC/B,SAAO;AAAA,IACL;AAAA,IACA,MAAM,IAAI,CAAC,UAAU,MAAM,EAAE;AAAA,EAC/B;AACF;;;AC5FA,eAAsB,eACpB,YACA,QAC4B;AAC5B,MAAI,OAAO,MAAO,QAAO,OAAO,MAAM,UAAU;AAEhD,QAAM,SAAS,mBAAmB,MAAM,OAAO,OAAO,GAAG,UAAU;AACnE,QAAM,QAAQ,IAAI,OAAO,IAAI,CAAC,SAAS,OAAO,IAAI,IAAI,CAAC,CAAC;AACxD,SAAO;AACT;AAGA,eAAsB,iBACpB,QACA,QAC4B;AAC5B,QAAM,aAAa,MAAM,OAAO,OAAO;AACvC,QAAM,SAAS,MAAM,eAAe,YAAY,MAAM;AACtD,QAAM,OAAO,MAAM;AACnB,SAAO;AACT;;;ACnBO,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAwB5B,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAG9C,YAAY,SAAiB,SAA+B;AAC1D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,QAAI,SAAS,UAAU,OAAW,MAAK,QAAQ,QAAQ;AAAA,EACzD;AACF;AAEO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAM/C,YACE,SACA,SAMA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AACpB,SAAK,WAAW,QAAQ;AACxB,SAAK,SAAS,QAAQ;AACtB,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AAAA,EACxD;AACF;AAGA,eAAsB,YAAmB,SAAiD;AACxF,QAAM,SAA4B;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,YAAY,KAAK,IAAI;AAAA,IACrB,OAAO,MAAM,QAAQ,OAAO;AAAA,EAC9B;AACA,SAAO,KAAK,UAAU,QAAQ,MAAM,CAAC;AACvC;AAGA,eAAsB,YACpB,SACA,MACA,UAAqC,CAAC,GACH;AACnC,QAAM,SAAS,YAAmB,IAAI;AACtC,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,aAAgC,CAAC;AACvC,MAAI,SAAS;AACb,aAAW,QAAQ,OAAO,OAAO;AAC/B,QAAI,CAAC,QAAQ,QAAQ;AACnB,iBAAW,KAAK,IAAI;AACpB;AAAA,IACF;AACA,QAAI;AACF,iBAAW,KAAK,MAAM,iBAAiB,MAAM,QAAQ,MAAM,CAAC;AAAA,IAC9D,SAAS,OAAO;AACd,cAAQ,gBAAgB,OAAO,IAAI;AACnC,WAAK,QAAQ,qBAAqB,aAAa,QAAQ;AACrD,kBAAU;AACV;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI;AAEJ,MAAI,SAAS,SAAS;AACpB,QAAI;AACF,cAAQ,MAAM,eAAe,YAAY,OAAO;AAAA,IAClD,SAAS,OAAO;AACd,YAAM,IAAI,sBAAsB,uCAAuC;AAAA,QACrE;AAAA,QACA,UAAU;AAAA,QACV,QAAQ,WAAW,SAAS;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,OAAO;AACL,QAAI,WAAW;AACf,QAAI;AACF,YAAM,QAAQ,MAAM;AACpB,iBAAW,QAAQ,YAAY;AAC7B,cAAM,QAAQ,IAAI,IAAI;AACtB,oBAAY;AAAA,MACd;AACA,cAAQ,MAAM,QAAQ,OAAO;AAAA,IAC/B,SAAS,OAAO;AACd,YAAM,IAAI,sBAAsB,+CAA+C;AAAA,QAC7E;AAAA,QACA;AAAA,QACA,QAAQ,WAAW,SAAS,SAAS;AAAA,QACrC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,UAAU,WAAW,QAAQ,QAAQ,OAAO,MAAM,QAAQ,MAAM;AACjF;AAEA,SAAS,YAAmB,MAAqD;AAC/E,MAAI,QAAiB;AACrB,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI;AACF,cAAQ,KAAK,MAAM,IAAI;AAAA,IACzB,SAAS,OAAO;AACd,YAAM,IAAI,qBAAqB,qCAAqC,EAAE,MAAM,CAAC;AAAA,IAC/E;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,qBAAqB,mCAAmC;AACxF,MAAI,MAAM,WAAW,sBAAsB,MAAM,YAAY,qBAAqB;AAChF,UAAM,IAAI,qBAAqB,kDAAkD;AAAA,EACnF;AACA,MAAI,OAAO,MAAM,eAAe,YAAY,CAAC,OAAO,SAAS,MAAM,UAAU,GAAG;AAC9E,UAAM,IAAI,qBAAqB,iDAAiD;AAAA,EAClF;AACA,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC,MAAM,MAAM,MAAM,UAAU,GAAG;AACjE,UAAM,IAAI,qBAAqB,wCAAwC;AAAA,EACzE;AACA,SAAO;AACT;;;ACxGA,IAAM,sCAAsC,KAAK,KAAK,KAAK,KAAK;AAGzD,SAAS,uBACd,SACsB;AACtB,MAAI,QAAQ,aAAa,eAAgB,QAAO,EAAE,UAAU,EAAE,QAAQ,QAAQ,EAAE;AAChF,MAAI,QAAQ,aAAa,mBAAmB;AAC1C,WAAO,EAAE,UAAU,EAAE,QAAQ,OAAO,GAAG,MAAM,EAAE,IAAI,gBAAgB,WAAW,OAAO,EAAE;AAAA,EACzF;AACA,SAAO,EAAE,UAAU,EAAE,eAAe,QAAQ,iBAAiB,oCAAoC,EAAE;AACrG;AAGO,SAAS,eACd,QACA,QAA8B,CAAC,GACF;AAC7B,QAAM,WAAW,OAAO,OAAO,CAAC,SAAS;AACvC,UAAM,CAAC,MAAM,EAAE,IAAI,MAAM,gBAAgB,CAAC;AAC1C,UAAM,UAAU,KAAK;AACrB,UAAM,aAAa,SAAS,SAAY,SAAY,YAAY,IAAI;AACpE,UAAM,aAAa,OAAO,SAAY,SAAY,YAAY,EAAE;AAChE,YACG,MAAM,eAAe,UAAa,KAAK,eAAe,MAAM,gBAC5D,MAAM,SAAS,UAAa,MAAM,KAAK,MAAM,CAAC,QAAQ,KAAK,MAAM,SAAS,GAAG,CAAC,MAC/E,oBAAoB,MAAM,KAAK,MAC9B,MAAM,iBAAiB,UAAa,KAAK,iBAAiB,MAAM,iBACjE,gBAAgB,MAAM,MAAM,QAAQ,MACnC,eAAe,UAAa,WAAW,gBACvC,eAAe,UAAa,WAAW,eACxC,cAAc,MAAM,MAAM,MAAM,MAC/B,MAAM,SAAS,IAAI,KAAK;AAAA,EAE7B,CAAC;AACD,QAAM,YAAY,aAAa,QAAQ;AACvC,QAAM,SAAS,MAAM,MAAM;AAC3B,QAAM,YAAY,MAAM,MAAM,cAAc,QAAQ,IAAI;AACxD,QAAM,aAAa,SACf,SACG,IAAI,CAAC,MAAM,WAAW,EAAE,MAAM,MAAM,EAAE,EACtC,KAAK,CAAC,GAAG,MAAM,kBAAkB,EAAE,KAAK,MAAM,GAAG,EAAE,KAAK,MAAM,GAAG,SAAS,KAAK,EAAE,QAAQ,EAAE,KAAK,EAChG,IAAI,CAAC,EAAE,KAAK,MAAM,IAAI,IACzB,eAAe,QAAQ;AAC3B,QAAM,SAAS,MAAM,cACjB,CAAC,GAAG,WAAW,OAAO,CAAC,SAAS,KAAK,WAAW,IAAI,GAAG,GAAG,WAAW,OAAO,CAAC,SAAS,KAAK,WAAW,IAAI,CAAC,IAC3G;AACJ,QAAM,WAAW,KAAK,IAAI,GAAG,MAAM,YAAY,aAAa,OAAO,UAAU,EAAE;AAC/E,QAAM,YAAY,KAAK,IAAI,GAAG,KAAK,KAAK,OAAO,SAAS,QAAQ,CAAC;AACjE,QAAM,OAAO,KAAK,IAAI,KAAK,IAAI,GAAG,MAAM,YAAY,QAAQ,CAAC,GAAG,SAAS;AACzE,QAAM,UAAU,OAAO,KAAK;AAE5B,SAAO;AAAA,IACL,OAAO,OAAO,MAAM,QAAQ,SAAS,QAAQ;AAAA,IAC7C,YAAY,OAAO;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,OAAO;AAAA,IACpB,iBAAiB,OAAO;AAAA,EAC1B;AACF;AAEA,SAAS,gBAAuB,MAAuB,UAAsD;AAC3G,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,eAAe,KAAK;AAC1B,QAAM,SAAS,iBAAiB;AAChC,MAAI,SAAS,WAAW,UAAU,CAAC,OAAQ,QAAO;AAClD,MAAI,SAAS,WAAW,WAAW,OAAQ,QAAO;AAClD,MAAI,SAAS,qBAAqB,WAAc,CAAC,UAAU,gBAAgB,SAAS,kBAAmB,QAAO;AAC9G,MAAI,SAAS,oBAAoB,WAAc,CAAC,UAAU,gBAAgB,SAAS,iBAAkB,QAAO;AAC5G,MAAI,SAAS,kBAAkB,QAAW;AACxC,UAAM,SAAS,KAAK,IAAI,IAAI,SAAS;AACrC,QAAI,UAAU,eAAe,OAAQ,QAAO;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,MAA0B,OAA2B,WAA2B;AACzG,MAAI,SAAS,UAAa,UAAU,OAAW,QAAO;AACtD,MAAI,SAAS,OAAW,QAAO;AAC/B,MAAI,UAAU,OAAW,QAAO;AAChC,UAAQ,OAAO,SAAS;AAC1B;AAEA,SAAS,oBAA2B,MAAuB,OAAsC;AAC/F,MAAI,MAAM,iBAAiB,MAAO,QAAO;AACzC,MAAI,MAAM,iBAAiB,WAAY,QAAO,KAAK,aAAa;AAChE,MAAI,MAAM,iBAAiB,SAAU,QAAO,KAAK,aAAa;AAC9D,SAAO,MAAM,aAAa,OAAO,KAAK,aAAa,OAAO,KAAK,aAAa;AAC9E;AAEO,SAAS,aAA8C,OAAkD;AAC9G,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,OAAO;AACxB,eAAW,OAAO,KAAK,QAAQ,CAAC,EAAG,QAAO,GAAG,KAAK,OAAO,GAAG,KAAK,KAAK;AAAA,EACxE;AACA,SAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;AACzF;AAEA,SAAS,cAAqB,MAAuB,QAAkD;AACrG,QAAM,QAAQ,QAAQ;AACtB,MAAI,CAAC,OAAO,KAAK,EAAG,QAAO;AAC3B,QAAM,SAAS,QAAQ,UAAU,CAAC,QAAQ,QAAQ,MAAM;AACxD,QAAM,SAAS,OAAO,IAAI,CAAC,UAAU;AACnC,QAAI,UAAU,OAAQ,QAAO,KAAK,QAAQ;AAC1C,QAAI,UAAU,OAAQ,SAAQ,KAAK,QAAQ,CAAC,GAAG,KAAK,GAAG;AACvD,QAAI;AACF,aAAO,KAAK,UAAU,KAAK,IAAI,KAAK;AAAA,IACtC,QAAQ;AACN,aAAO,OAAO,KAAK,IAAI;AAAA,IACzB;AAAA,EACF,CAAC;AACD,QAAM,OAAO,OAAO,KAAK,GAAG,EAAE,kBAAkB;AAChD,QAAM,aAAa,MAAM,KAAK,EAAE,kBAAkB;AAClD,QAAM,UAAU,QAAQ,aAAa,QAAQ,CAAC,UAAU,IAAI,WAAW,MAAM,KAAK,EAAE,OAAO,OAAO;AAClG,QAAM,UAAU,QAAQ,IAAI,CAAC,WAAW,KAAK,SAAS,MAAM,CAAC;AAC7D,SAAO,QAAQ,SAAS,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,MAAM,OAAO;AAC9E;AAEA,SAAS,YAAY,OAA8B;AACjD,SAAO,iBAAiB,OAAO,MAAM,QAAQ,IAAI;AACnD;;;ACrJO,SAAS,wBACd,MACA,UACA,MAAoB,KAAK,KAChB;AACT,SAAO,KAAK,kBAAkB,UAAa,IAAI,IAAI,KAAK,iBAAiB;AAC3E;AAsCA,eAAsB,oBACpB,QACA,aACA,UAA6C,CAAC,GACD;AAC7C,QAAM,iBAAiB,IAAI,IAAI,QAAQ,kBAAkB,CAAC,CAAC;AAC3D,QAAM,MAAM,QAAQ,OAAO,KAAK;AAChC,QAAM,QAA2B,CAAC;AAClC,QAAM,eAAkC,CAAC;AACzC,QAAM,aAAuB,CAAC;AAC9B,QAAM,UAA+C,CAAC;AAEtD,aAAW,QAAQ,QAAQ;AACzB,UAAM,YAAY,MAAM,YAAY,IAAI;AACxC,UAAM,SAA4C,OAAO,cAAc,WAAW,EAAE,QAAQ,UAAU,IAAI;AAC1G,UAAM,SAAS,OAAO,WAAW,cAAc,SAAY,OAAO;AAClE,UAAM,kBAAkB;AAAA,MACtB,GAAG;AAAA,MACH,QAAQ,OAAO;AAAA,MACf,GAAI,OAAO,WAAW,cAAc,EAAE,cAAc,OAAU,IAAI,EAAE,cAAc,OAAO;AAAA,IAC3F;AACA,UAAM,WAAW,QAAQ,cACrB,MAAO,QAAQ,YAAwC,MAAM,MAAM,IACnE;AACJ,QAAI,aAAa,QAAW;AAC1B,iBAAW,KAAK,KAAK,EAAE;AACvB,cAAQ,KAAK,EAAE,MAAM,QAAQ,OAAO,QAAQ,QAAQ,SAAS,MAAM,CAAC;AACpE;AAAA,IACF;AACA,QAAI,OAAO,WAAW,aAAa;AACjC,YAAM,YAAY,IAAI;AACtB,YAAM,gBAAgB,gBAAgB,QAAQ;AAC9C,YAAM,UACJ,OAAO,SAAS,SACZ,gBACA,EAAE,GAAG,eAAe,MAAM,OAAO,MAAM,eAAe,WAAW,WAAW,UAAU;AAC5F,YAAM,YAAY,YAAY;AAC9B,YAAM,KAAK,OAAO;AAClB,UAAI,UAAW,cAAa,KAAK,OAAO;AACxC,cAAQ,KAAK,EAAE,MAAM,SAAS,QAAQ,aAAa,SAAS,UAAU,CAAC;AACvE;AAAA,IACF;AAEA,UAAM,aAAa,EAAE,GAAG,UAAU,QAAQ,OAAO,QAAQ,GAAI,SAAS,EAAE,cAAc,OAAO,IAAI,CAAC,EAAG;AACrG,UAAM,eAAe,eAAe,IAAI,OAAO,MAAM;AACrD,QAAI,aAAc,YAAW,KAAK,KAAK,EAAE;AAAA,QACpC,OAAM,KAAK,UAAU;AAC1B,QAAI,CAAC,gBAAgB,eAAe,KAAM,cAAa,KAAK,UAAU;AACtE,YAAQ,KAAK,EAAE,MAAM,YAAY,QAAQ,OAAO,QAAQ,QAAQ,SAAS,CAAC,gBAAgB,eAAe,KAAK,CAAC;AAAA,EACjH;AAEA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,OAAO;AAAA,IAChB,SAAS,aAAa;AAAA,IACtB,SAAS,WAAW;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGA,eAAsB,mBACpB,SACA,aACA,UAA6C,CAAC,GACD;AAC7C,QAAM,SAAS,MAAM,QAAQ,OAAO;AACpC,QAAM,UAAU,MAAM,oBAAoB,QAAQ,aAAa,OAAO;AACtE,MAAI,QAAQ,aAAa,SAAS,EAAG,OAAM,iBAAiB,SAAS,QAAQ,YAAY;AACzF,MAAI,QAAQ,WAAW,SAAS,EAAG,OAAM,gBAAgB,SAAS,QAAQ,UAAU;AACpF,SAAO;AACT;AAEA,SAAS,gBAAuB,MAAwC;AACtE,QAAM,OAAO,EAAE,GAAG,KAAK;AACvB,SAAO,KAAK;AACZ,SAAO,KAAK;AACZ,SAAO;AACT;;;ACjGO,IAAM,YAAN,MAAiD;AAAA,EAItD,YAAY,cAAqC;AAFjD,SAAiB,YAAY,oBAAI,IAAgB;AAMjD,uBAAc,MAA6B,KAAK;AAEhD,qBAAY,CAAC,aAAuC;AAClD,WAAK,UAAU,IAAI,QAAQ;AAC3B,aAAO,MAAM,KAAK,UAAU,OAAO,QAAQ;AAAA,IAC7C;AARE,SAAK,QAAQ;AAAA,EACf;AAAA,EASA,SAAS,MAA4C;AACnD,QAAI,UAAU;AACd,eAAW,OAAO,OAAO,KAAK,IAAI,GAAyC;AACzE,UAAI,CAAC,OAAO,GAAG,KAAK,MAAM,GAAG,GAAG,KAAK,GAAG,CAAC,GAAG;AAC1C,kBAAU;AACV;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,QAAS;AACd,SAAK,QAAQ,EAAE,GAAG,KAAK,OAAO,GAAG,KAAK;AACtC,eAAW,YAAY,KAAK,UAAW,UAAS;AAAA,EAClD;AACF;","names":["item"]}
|
package/dist/core.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { D as DEFAULT_KEEP_URL_PARAMS, I as ImportItemsOptions, a as ImportItemsResult, K as KEEP_BACKUP_FORMAT, b as KEEP_BACKUP_VERSION, c as KeepAutoRevalidationOptions, d as KeepBackup, e as KeepBackupImportError, f as KeepBackupParseError, g as KeepCollectionMeta, h as KeepItemMetadataRefresher, i as KeepItemResolver, j as KeepItemRevalidationRecord, k as KeepItemRevalidationResult, l as KeepItemRevalidationSummary, m as KeepItemRevalidator, n as KeepListQuery, o as KeepNavigationState, p as
|
|
2
|
-
import { K as KeepScope } from './scope-
|
|
3
|
-
export { S as ScopedStorageAdapter, a as ScopedSyncQueueAdapter, c as createScopedStorageAdapter, g as getKeepScopeKey, i as isSameKeepScope } from './scope-
|
|
4
|
-
import { R as RemoteSyncDriver, a as StorageAdapter, K as KeepItem, d as KeepPluginContext, e as KeepPlugin, c as SyncOperation, S as SyncScope, f as SyncCapableStorageAdapter, g as RemoteSyncResult, h as KeepSyncAuthError } from './types-
|
|
5
|
-
export { i as KeepAction, j as KeepChangeContext, k as KeepChangePhase, l as KeepConflictContext, m as KeepConflictResolver, n as KeepErrorContext, o as KeepErrorHandler, p as KeepEventHandlers, q as KeepInvalidItemPolicy, r as KeepItemInput, s as KeepItemStatus, t as KeepSchema, u as KeepSchemaParseResult, v as KeepStorageAccessError, w as KeepStorageError, x as KeepStorageOperation, y as KeepStorageParseError, z as KeepStorageQuotaError, A as KeepSyncAuthStatus, B as KeepSyncConflict, C as KeepSyncResolution, D as KeepSyncState, E as KeepSyncStatus, F as KeepUndoState, b as SyncQueueAdapter, G as isKeepSyncAuthError, H as normalizeKeepTags } from './types-
|
|
1
|
+
export { D as DEFAULT_KEEP_URL_PARAMS, I as ImportItemsOptions, a as ImportItemsResult, K as KEEP_BACKUP_FORMAT, b as KEEP_BACKUP_VERSION, c as KeepAutoRevalidationOptions, d as KeepBackup, e as KeepBackupImportError, f as KeepBackupParseError, g as KeepCollectionMeta, h as KeepItemMetadataRefresher, i as KeepItemResolver, j as KeepItemRevalidationRecord, k as KeepItemRevalidationResult, l as KeepItemRevalidationSummary, m as KeepItemRevalidator, n as KeepListQuery, o as KeepNavigationState, p as KeepRediscoveryOptions, q as KeepRediscoveryStrategy, r as KeepStore, s as KeepStoreActions, t as KeepStoreState, u as KeepUrlParamNames, v as KeepUrlState, w as KeepUrlSyncOptions, Q as QueryKeepItemsResult, R as RevalidateKeepItemsOptions, x as createRediscoveryQuery, y as decodeKeepListQuery, z as encodeKeepListQuery, A as exportItems, B as getKeepNavigationState, C as getTagCounts, E as importItems, F as isKeepItemMetadataStale, G as mergeKeepListQueryFromUrl, H as moveKeepItem, J as orderKeepItems, L as queryKeepItems, M as reconcileKeepItems, N as reorderKeepItems, O as revalidateKeepItems, P as serializeKeepListQuery } from './store-DbAAC4yU.js';
|
|
2
|
+
import { K as KeepScope } from './scope-BsU6xvN9.js';
|
|
3
|
+
export { S as ScopedStorageAdapter, a as ScopedSyncQueueAdapter, c as createScopedStorageAdapter, g as getKeepScopeKey, i as isSameKeepScope } from './scope-BsU6xvN9.js';
|
|
4
|
+
import { R as RemoteSyncDriver, a as StorageAdapter, K as KeepItem, d as KeepPluginContext, e as KeepPlugin, c as SyncOperation, S as SyncScope, f as SyncCapableStorageAdapter, g as RemoteSyncResult, h as KeepSyncAuthError } from './types-CJIbuqTO.js';
|
|
5
|
+
export { i as KeepAction, j as KeepChangeContext, k as KeepChangePhase, l as KeepConflictContext, m as KeepConflictResolver, n as KeepErrorContext, o as KeepErrorHandler, p as KeepEventHandlers, q as KeepInvalidItemPolicy, r as KeepItemInput, s as KeepItemStatus, t as KeepSchema, u as KeepSchemaParseResult, v as KeepStorageAccessError, w as KeepStorageError, x as KeepStorageOperation, y as KeepStorageParseError, z as KeepStorageQuotaError, A as KeepSyncAuthStatus, B as KeepSyncConflict, C as KeepSyncResolution, D as KeepSyncState, E as KeepSyncStatus, F as KeepUndoState, b as SyncQueueAdapter, G as isKeepSyncAuthError, H as normalizeKeepTags } from './types-CJIbuqTO.js';
|
|
6
6
|
export { KeepSchemaValidationError, parseKeepMeta, validateKeepItem } from './schema.js';
|
|
7
7
|
import { SyncStorageAdapterOptions, BrowserStorageAdapterOptions } from './storage.js';
|
|
8
8
|
export { DEFAULT_INDEXEDDB_DATABASE, DEFAULT_INDEXEDDB_STORE, DEFAULT_STORAGE_KEY, DEFAULT_SYNC_QUEUE_DATABASE, DEFAULT_SYNC_QUEUE_KEY, DEFAULT_SYNC_QUEUE_STORE, FallbackStorageAdapter, FallbackStorageAdapterOptions, FallbackSyncQueueAdapter, FallbackSyncQueueAdapterOptions, IndexedDBAdapter, IndexedDBAdapterOptions, IndexedDBSyncQueueAdapter, IndexedDBSyncQueueOptions, LocalStorageAdapter, LocalStorageAdapterOptions, LocalStorageSyncQueueAdapter, LocalStorageSyncQueueOptions, StorageAdapterFactoryOptions, SyncStorageAdapter, createBrowserStorageAdapter, createStorageAdapter } from './storage.js';
|
package/dist/core.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
KeepBackupImportError,
|
|
5
5
|
KeepBackupParseError,
|
|
6
6
|
KeepStore,
|
|
7
|
+
createRediscoveryQuery,
|
|
7
8
|
exportItems,
|
|
8
9
|
getKeepNavigationState,
|
|
9
10
|
getTagCounts,
|
|
@@ -17,7 +18,7 @@ import {
|
|
|
17
18
|
reconcileKeepItems,
|
|
18
19
|
reorderKeepItems,
|
|
19
20
|
revalidateKeepItems
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-JGGKIE3O.js";
|
|
21
22
|
import {
|
|
22
23
|
KeepSchemaValidationError,
|
|
23
24
|
parseKeepMeta,
|
|
@@ -51,7 +52,7 @@ import {
|
|
|
51
52
|
isKeepSyncAuthError,
|
|
52
53
|
isSameKeepScope,
|
|
53
54
|
normalizeKeepTags
|
|
54
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-HDML3IDX.js";
|
|
55
56
|
|
|
56
57
|
// src/features/items/presets.ts
|
|
57
58
|
function createKeepKitPreset(options = {}) {
|
|
@@ -89,7 +90,11 @@ var DEFAULT_KEEP_URL_PARAMS = {
|
|
|
89
90
|
archived: "archived",
|
|
90
91
|
archiveScope: "archiveScope",
|
|
91
92
|
collection: "collection",
|
|
92
|
-
pinnedFirst: "pinned"
|
|
93
|
+
pinnedFirst: "pinned",
|
|
94
|
+
activityOpened: "opened",
|
|
95
|
+
lastOpenedBefore: "openedBefore",
|
|
96
|
+
lastOpenedAfter: "openedAfter",
|
|
97
|
+
inactiveForMs: "inactiveFor"
|
|
93
98
|
};
|
|
94
99
|
function encodeKeepListQuery(query = {}, options = {}) {
|
|
95
100
|
const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };
|
|
@@ -107,6 +112,14 @@ function encodeKeepListQuery(query = {}, options = {}) {
|
|
|
107
112
|
else if (query.archived !== void 0) result.set(params.archived, query.archived ? "true" : "false");
|
|
108
113
|
if (query.collectionId) result.set(params.collection, query.collectionId);
|
|
109
114
|
if (query.pinnedFirst) result.set(params.pinnedFirst, "true");
|
|
115
|
+
if (query.activity?.opened) result.set(params.activityOpened, query.activity.opened);
|
|
116
|
+
for (const [key, value] of [
|
|
117
|
+
[params.lastOpenedBefore, query.activity?.lastOpenedBefore],
|
|
118
|
+
[params.lastOpenedAfter, query.activity?.lastOpenedAfter],
|
|
119
|
+
[params.inactiveForMs, query.activity?.inactiveForMs]
|
|
120
|
+
]) {
|
|
121
|
+
if (value !== void 0 && Number.isFinite(value)) result.set(key, String(value));
|
|
122
|
+
}
|
|
110
123
|
return result;
|
|
111
124
|
}
|
|
112
125
|
function decodeKeepListQuery(input, options = {}) {
|
|
@@ -119,7 +132,7 @@ function decodeKeepListQuery(input, options = {}) {
|
|
|
119
132
|
)
|
|
120
133
|
];
|
|
121
134
|
const sortValue = searchParams.get(params.sort)?.split(":");
|
|
122
|
-
const sort = sortValue?.[0] === "savedAt" || sortValue?.[0] === "updatedAt" ? {
|
|
135
|
+
const sort = sortValue?.[0] === "savedAt" || sortValue?.[0] === "updatedAt" || sortValue?.[0] === "lastOpenedAt" ? {
|
|
123
136
|
by: sortValue[0],
|
|
124
137
|
direction: sortValue[1] === "asc" ? "asc" : "desc"
|
|
125
138
|
} : void 0;
|
|
@@ -131,6 +144,23 @@ function decodeKeepListQuery(input, options = {}) {
|
|
|
131
144
|
const archived = archiveScope === "archived" || archivedValue === "true" ? true : archiveScope === "active" || archivedValue === "false" ? false : void 0;
|
|
132
145
|
const collectionId = searchParams.get(params.collection)?.trim() || void 0;
|
|
133
146
|
const pinnedFirst = searchParams.get(params.pinnedFirst) === "true" ? true : void 0;
|
|
147
|
+
const activityOpenedValue = searchParams.get(params.activityOpened);
|
|
148
|
+
const activityOpened = activityOpenedValue === "ever" || activityOpenedValue === "never" ? activityOpenedValue : void 0;
|
|
149
|
+
const parseActivityNumber = (name) => {
|
|
150
|
+
const rawValue = searchParams.get(name);
|
|
151
|
+
if (rawValue === null || rawValue.trim() === "") return void 0;
|
|
152
|
+
const value = Number(rawValue);
|
|
153
|
+
return Number.isFinite(value) ? value : void 0;
|
|
154
|
+
};
|
|
155
|
+
const lastOpenedBefore = parseActivityNumber(params.lastOpenedBefore);
|
|
156
|
+
const lastOpenedAfter = parseActivityNumber(params.lastOpenedAfter);
|
|
157
|
+
const inactiveForMs = parseActivityNumber(params.inactiveForMs);
|
|
158
|
+
const activity = activityOpened !== void 0 || lastOpenedBefore !== void 0 || lastOpenedAfter !== void 0 || inactiveForMs !== void 0 ? {
|
|
159
|
+
...activityOpened === void 0 ? {} : { opened: activityOpened },
|
|
160
|
+
...lastOpenedBefore === void 0 ? {} : { lastOpenedBefore },
|
|
161
|
+
...lastOpenedAfter === void 0 ? {} : { lastOpenedAfter },
|
|
162
|
+
...inactiveForMs === void 0 ? {} : { inactiveForMs }
|
|
163
|
+
} : void 0;
|
|
134
164
|
return {
|
|
135
165
|
...search ? { search: { query: search } } : {},
|
|
136
166
|
...tags.length > 0 ? { tags } : {},
|
|
@@ -139,7 +169,8 @@ function decodeKeepListQuery(input, options = {}) {
|
|
|
139
169
|
...archived === void 0 ? {} : { archived },
|
|
140
170
|
...archiveScope === void 0 ? {} : { archiveScope },
|
|
141
171
|
...collectionId ? { collectionId } : {},
|
|
142
|
-
...pinnedFirst ? { pinnedFirst } : {}
|
|
172
|
+
...pinnedFirst ? { pinnedFirst } : {},
|
|
173
|
+
...activity === void 0 ? {} : { activity }
|
|
143
174
|
};
|
|
144
175
|
}
|
|
145
176
|
function serializeKeepListQuery(query = {}, options = {}) {
|
|
@@ -156,7 +187,8 @@ function mergeKeepListQueryFromUrl(query, input, options = {}) {
|
|
|
156
187
|
sort: decoded.sort ?? query.sort,
|
|
157
188
|
pagination: decoded.pagination ? { ...query.pagination, ...decoded.pagination } : query.pagination,
|
|
158
189
|
archived: decoded.archived ?? query.archived,
|
|
159
|
-
archiveScope: decoded.archiveScope ?? query.archiveScope
|
|
190
|
+
archiveScope: decoded.archiveScope ?? query.archiveScope,
|
|
191
|
+
activity: decoded.activity ?? query.activity
|
|
160
192
|
};
|
|
161
193
|
}
|
|
162
194
|
|
|
@@ -397,6 +429,7 @@ export {
|
|
|
397
429
|
createKeepInvalidationPlugin,
|
|
398
430
|
createKeepKitPreset,
|
|
399
431
|
createKeepKitSetup,
|
|
432
|
+
createRediscoveryQuery,
|
|
400
433
|
createScopedStorageAdapter,
|
|
401
434
|
createStorageAdapter,
|
|
402
435
|
decodeKeepListQuery,
|
package/dist/core.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/features/items/presets.ts","../src/features/items/url.ts","../src/features/sync/integrations.ts","../src/features/sync/templates/auth-sync.ts"],"sourcesContent":["import { createBrowserStorageAdapter } from \"../../storage/index\";\nimport { SyncStorageAdapter } from \"../../storage/sync\";\nimport { exportItems } from \"../persistence/backup\";\nimport { createScopedStorageAdapter, type KeepScope } from \"../persistence/scope\";\nimport type { RemoteSyncDriver, StorageAdapter } from \"./types\";\n\nexport type KeepKitPresetMode = \"local\" | \"sync\" | \"backup\";\n\nexport type KeepKitPresetOptions<TMeta = Record<string, unknown>> = {\n mode?: KeepKitPresetMode;\n key?: string;\n scope?: KeepScope;\n remote?: RemoteSyncDriver<TMeta>;\n storage?: StorageAdapter<TMeta>;\n};\n\nexport type KeepKitSetup<TMeta = Record<string, unknown>> = {\n mode: KeepKitPresetMode;\n scope?: KeepScope;\n storage: StorageAdapter<TMeta>;\n exportBackup: () => Promise<string>;\n};\n\n/**\n * Build the recommended local/sync/backup wiring without imposing an auth or\n * API client. Pass the current user and tenant scope whenever the account changes.\n */\nexport function createKeepKitPreset<TMeta = Record<string, unknown>>(\n options: KeepKitPresetOptions<TMeta> = {},\n): KeepKitSetup<TMeta> {\n const mode = options.mode ?? \"local\";\n const local = options.storage\n ? options.scope\n ? createScopedStorageAdapter(options.storage, options.scope)\n : options.storage\n : createBrowserStorageAdapter<TMeta>({ key: options.key, scope: options.scope });\n if (mode === \"sync\" && !options.remote) {\n throw new Error('createKeepKitPreset({ mode: \"sync\" }) requires a remote driver.');\n }\n let storage: StorageAdapter<TMeta> = local;\n if (mode === \"sync\") {\n const remote = options.remote;\n if (!remote) throw new Error('createKeepKitPreset({ mode: \"sync\" }) requires a remote driver.');\n storage = new SyncStorageAdapter<TMeta>({\n local,\n remote,\n userId: options.scope?.userId,\n tenantId: options.scope?.tenantId,\n });\n }\n return {\n mode,\n scope: options.scope,\n storage,\n exportBackup: () => exportItems(storage),\n };\n}\n\nexport const createKeepKitSetup = createKeepKitPreset;\n","import type { KeepListQuery } from \"./query\";\n\nexport type KeepUrlParamNames = {\n search: string;\n tags: string;\n sort: string;\n page: string;\n archived: string;\n archiveScope: string;\n collection: string;\n pinnedFirst: string;\n};\n\nexport type KeepUrlSyncOptions = {\n /** Parameters are intentionally short so shared collection URLs stay readable. */\n params?: Partial<KeepUrlParamNames>;\n /** Push is the default so browser back/forward restores collection states. */\n history?: \"replace\" | \"push\";\n /** URL to read/write. Defaults to the current browser URL. */\n url?: string;\n};\n\nexport const DEFAULT_KEEP_URL_PARAMS: KeepUrlParamNames = {\n search: \"q\",\n tags: \"tag\",\n sort: \"sort\",\n page: \"page\",\n archived: \"archived\",\n archiveScope: \"archiveScope\",\n collection: \"collection\",\n pinnedFirst: \"pinned\",\n};\n\nexport type KeepUrlState = Pick<\n KeepListQuery,\n \"search\" | \"tags\" | \"sort\" | \"pagination\" | \"archived\" | \"archiveScope\" | \"collectionId\" | \"pinnedFirst\"\n>;\n\n/** Convert a list query to stable URLSearchParams without serializing functions or unsupported filters. */\nexport function encodeKeepListQuery<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta> = {},\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): URLSearchParams {\n const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };\n const result = new URLSearchParams();\n const search = query.search?.query?.trim();\n if (search) result.set(params.search, search);\n for (const tag of query.tags ?? []) {\n const normalized = tag.trim();\n if (normalized) result.append(params.tags, normalized);\n }\n if (query.sort?.by) result.set(params.sort, `${query.sort.by}:${query.sort.direction ?? \"desc\"}`);\n const page = query.pagination?.page;\n if (page !== undefined && Number.isFinite(page) && page > 1) result.set(params.page, String(Math.floor(page)));\n if (query.archiveScope !== undefined) result.set(params.archiveScope, query.archiveScope);\n else if (query.archived !== undefined) result.set(params.archived, query.archived ? \"true\" : \"false\");\n if (query.collectionId) result.set(params.collection, query.collectionId);\n if (query.pinnedFirst) result.set(params.pinnedFirst, \"true\");\n return result;\n}\n\n/** Parse a URL into the query fields supported by KeepCollection. Invalid values are ignored. */\nexport function decodeKeepListQuery(\n input: string | URL | URLSearchParams,\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): KeepUrlState {\n const params = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };\n const searchParams = input instanceof URLSearchParams ? input : new URL(input, \"http://keepkit.invalid\").searchParams;\n const search = searchParams.get(params.search)?.trim();\n const tags = [\n ...new Set(\n searchParams\n .getAll(params.tags)\n .map((tag) => tag.trim())\n .filter(Boolean),\n ),\n ];\n const sortValue = searchParams.get(params.sort)?.split(\":\");\n const sort: KeepListQuery[\"sort\"] =\n sortValue?.[0] === \"savedAt\" || sortValue?.[0] === \"updatedAt\"\n ? {\n by: sortValue[0],\n direction: sortValue[1] === \"asc\" ? (\"asc\" as const) : (\"desc\" as const),\n }\n : undefined;\n const rawPage = Number(searchParams.get(params.page));\n const page = Number.isInteger(rawPage) && rawPage > 0 ? rawPage : undefined;\n const archiveScopeValue = searchParams.get(params.archiveScope);\n const archiveScope =\n archiveScopeValue === \"active\" || archiveScopeValue === \"archived\" || archiveScopeValue === \"all\"\n ? archiveScopeValue\n : undefined;\n const archivedValue = searchParams.get(params.archived);\n const archived =\n archiveScope === \"archived\" || archivedValue === \"true\"\n ? true\n : archiveScope === \"active\" || archivedValue === \"false\"\n ? false\n : undefined;\n const collectionId = searchParams.get(params.collection)?.trim() || undefined;\n const pinnedFirst = searchParams.get(params.pinnedFirst) === \"true\" ? true : undefined;\n return {\n ...(search ? { search: { query: search } } : {}),\n ...(tags.length > 0 ? { tags } : {}),\n ...(sort ? { sort } : {}),\n ...(page ? { pagination: { page } } : {}),\n ...(archived === undefined ? {} : { archived }),\n ...(archiveScope === undefined ? {} : { archiveScope }),\n ...(collectionId ? { collectionId } : {}),\n ...(pinnedFirst ? { pinnedFirst } : {}),\n };\n}\n\nexport function serializeKeepListQuery<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta> = {},\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): string {\n const value = encodeKeepListQuery(query, options).toString();\n return value ? `?${value}` : \"\";\n}\n\nexport function mergeKeepListQueryFromUrl<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta>,\n input: string | URL | URLSearchParams,\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): KeepListQuery<TMeta> {\n const decoded = decodeKeepListQuery(input, options);\n return {\n ...query,\n ...decoded,\n search: decoded.search ?? query.search,\n tags: decoded.tags ?? query.tags,\n sort: decoded.sort ?? query.sort,\n pagination: decoded.pagination ? { ...query.pagination, ...decoded.pagination } : query.pagination,\n archived: decoded.archived ?? query.archived,\n archiveScope: decoded.archiveScope ?? query.archiveScope,\n };\n}\n","import type { KeepPlugin, KeepPluginContext } from \"../items/types\";\n\nexport type KeepInvalidationPluginOptions<TMeta = Record<string, unknown>> = {\n /** Query keys to invalidate after a successful local KeepKit mutation. */\n queryKeys: readonly unknown[] | ((context: KeepPluginContext<TMeta>) => readonly (readonly unknown[])[]);\n /** Connect this callback to queryClient.invalidateQueries or SWR mutate. */\n invalidate: (queryKey: readonly unknown[], context: KeepPluginContext<TMeta>) => void | Promise<void>;\n name?: string;\n};\n\n/** Framework-neutral bridge for TanStack Query, SWR, and similar caches. */\nexport function createKeepInvalidationPlugin<TMeta = Record<string, unknown>>(\n options: KeepInvalidationPluginOptions<TMeta>,\n): KeepPlugin<TMeta> {\n return {\n name: options.name ?? \"keepkit-cache-invalidation\",\n after: async (context) => {\n const keys = typeof options.queryKeys === \"function\" ? options.queryKeys(context) : [options.queryKeys];\n await Promise.all(keys.map((queryKey) => options.invalidate(queryKey, context)));\n },\n };\n}\n","import { type BrowserStorageAdapterOptions, createBrowserStorageAdapter } from \"../../../storage\";\nimport { SyncStorageAdapter, type SyncStorageAdapterOptions } from \"../../../storage/sync\";\nimport type {\n KeepItem,\n KeepSyncAuthError,\n KeepSyncAuthStatus,\n KeepSyncState,\n RemoteSyncDriver,\n RemoteSyncResult,\n StorageAdapter,\n SyncCapableStorageAdapter,\n SyncOperation,\n SyncScope,\n} from \"../../items/types\";\nimport { KeepSyncAuthError as KeepSyncAuthErrorClass } from \"../../items/types\";\nimport { exportItems } from \"../../persistence/backup\";\nimport {\n createScopedStorageAdapter,\n getKeepScopeKey,\n isSameKeepScope,\n ScopedSyncQueueAdapter,\n} from \"../../persistence/scope\";\n\nexport type AuthenticatedSyncRequestContext<TMeta = Record<string, unknown>> = {\n token: string | null;\n scope?: SyncScope;\n operation?: SyncOperation<TMeta>;\n};\n\n/** Transport boundary for auth-aware requests; cookies and bearer tokens remain host concerns. */\nexport type AuthenticatedSyncTransport<TMeta = Record<string, unknown>> = {\n push: (\n operation: SyncOperation<TMeta>,\n context: AuthenticatedSyncRequestContext<TMeta>,\n ) => Promise<RemoteSyncResult<TMeta>>;\n pull?: (context: AuthenticatedSyncRequestContext<TMeta>) => Promise<KeepItem<TMeta>[]>;\n};\n\nexport type AuthenticatedSyncAuthContext<TMeta = Record<string, unknown>> = {\n operation?: SyncOperation<TMeta>;\n scope?: SyncScope;\n};\n\nexport type AuthenticatedSyncKitOptions<TMeta = Record<string, unknown>> = Omit<\n SyncStorageAdapterOptions<TMeta>,\n \"local\" | \"remote\" | \"scope\"\n> & {\n /** Optional custom local adapter. Browser storage is used when omitted. */\n local?: StorageAdapter<TMeta>;\n key?: BrowserStorageAdapterOptions[\"key\"];\n databaseName?: BrowserStorageAdapterOptions[\"databaseName\"];\n scope?: SyncScope;\n /** Resolve the active account or tenant before storage operations. */\n getScope?: () => SyncScope | undefined | Promise<SyncScope | undefined>;\n getAuthToken: () => Promise<string | null>;\n transport: AuthenticatedSyncTransport<TMeta>;\n onAuthError?: (error: KeepSyncAuthError<TMeta>, context: AuthenticatedSyncAuthContext<TMeta>) => void | Promise<void>;\n onReauthenticate?: (\n error: KeepSyncAuthError<TMeta>,\n context: AuthenticatedSyncAuthContext<TMeta>,\n ) => void | Promise<void>;\n onScopeChange?: (next: SyncScope | undefined, previous: SyncScope | undefined) => void | Promise<void>;\n};\n\nexport type AuthenticatedSyncKit<TMeta = Record<string, unknown>> = {\n readonly mode: \"sync\";\n readonly storage: SyncCapableStorageAdapter<TMeta>;\n readonly scope?: SyncScope;\n readonly scopeKey: string;\n getScope(): SyncScope | undefined;\n setScope(scope?: SyncScope): Promise<void>;\n subscribeScope(listener: () => void): () => void;\n exportBackup(): Promise<string>;\n dispose(): void;\n};\n\n/** Creates auth-independent sync wiring with per-request tokens and isolated account scopes. */\nexport function createAuthenticatedSyncKit<TMeta = Record<string, unknown>>(\n options: AuthenticatedSyncKitOptions<TMeta>,\n): AuthenticatedSyncKit<TMeta> {\n const controller = new AuthenticatedSyncStorageController(options);\n return {\n mode: \"sync\",\n storage: controller,\n get scope() {\n return controller.scope;\n },\n get scopeKey() {\n return controller.scopeKey;\n },\n getScope: () => controller.scope,\n setScope: (scope) => controller.setScope(scope),\n subscribeScope: (listener) => controller.subscribeScope(listener),\n exportBackup: () => controller.exportBackup(),\n dispose: () => controller.dispose(),\n };\n}\n\nclass AuthenticatedSyncStorageController<TMeta = Record<string, unknown>> implements SyncCapableStorageAdapter<TMeta> {\n private readonly options: AuthenticatedSyncKitOptions<TMeta>;\n private currentScope: SyncScope | undefined;\n private current: SyncStorageAdapter<TMeta>;\n private readonly scopeListeners = new Set<() => void>();\n private readonly dataListeners = new Set<() => void>();\n private readonly syncListeners = new Set<() => void>();\n private unsubscribeData: () => void = () => undefined;\n private unsubscribeSync: () => void = () => undefined;\n private transition = Promise.resolve();\n private disposed = false;\n\n constructor(options: AuthenticatedSyncKitOptions<TMeta>) {\n this.options = options;\n this.currentScope = options.scope;\n this.current = this.createAdapter(this.currentScope);\n this.attach(this.current);\n }\n\n get storageKey(): string | undefined {\n return this.current.storageKey;\n }\n\n get scope(): SyncScope | undefined {\n return this.currentScope;\n }\n\n get scopeKey(): string {\n return getKeepScopeKey(this.currentScope);\n }\n\n async getAll(): Promise<KeepItem<TMeta>[]> {\n await this.ensureScope();\n return this.current.getAll();\n }\n\n async set(item: KeepItem<TMeta>): Promise<void> {\n await this.ensureScope();\n return this.current.set(item);\n }\n\n async setMany(items: KeepItem<TMeta>[]): Promise<void> {\n await this.ensureScope();\n return this.current.setMany(items);\n }\n\n async remove(id: string): Promise<void> {\n await this.ensureScope();\n return this.current.remove(id);\n }\n\n async removeMany(ids: string[]): Promise<void> {\n await this.ensureScope();\n return this.current.removeMany(ids);\n }\n\n async clear(): Promise<void> {\n await this.ensureScope();\n return this.current.clear();\n }\n\n async merge(items: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n await this.ensureScope();\n return this.current.merge(items);\n }\n\n subscribe(listener: () => void): () => void {\n this.dataListeners.add(listener);\n return () => this.dataListeners.delete(listener);\n }\n\n getSyncState(): KeepSyncState<TMeta> {\n return this.current.getSyncState();\n }\n\n subscribeSync(listener: () => void): () => void {\n this.syncListeners.add(listener);\n return () => this.syncListeners.delete(listener);\n }\n\n async flushSync(): Promise<void> {\n await this.ensureScope();\n return this.current.flushSync();\n }\n\n async retrySync(): Promise<void> {\n await this.ensureScope();\n return this.current.retrySync?.() ?? this.current.flushSync();\n }\n\n async resolveSyncConflict(\n id: string,\n resolution: \"local\" | \"remote\" | \"manual\",\n item?: KeepItem<TMeta>,\n ): Promise<void> {\n await this.ensureScope();\n if (!this.current.resolveSyncConflict) {\n throw new Error(\"The authenticated sync adapter does not support conflict resolution.\");\n }\n return this.current.resolveSyncConflict(id, resolution, item);\n }\n\n async setScope(nextScope?: SyncScope): Promise<void> {\n const run = this.transition.then(async () => {\n if (isSameKeepScope(this.currentScope, nextScope)) return;\n if (this.disposed) throw new Error(\"AuthenticatedSyncKit has been disposed.\");\n const previousScope = this.currentScope;\n this.unsubscribeData();\n this.unsubscribeSync();\n this.current.dispose?.();\n this.currentScope = nextScope;\n this.current = this.createAdapter(nextScope);\n this.attach(this.current);\n await this.options.onScopeChange?.(nextScope, previousScope);\n this.notify(this.scopeListeners);\n this.notify(this.dataListeners);\n this.notify(this.syncListeners);\n });\n this.transition = run.catch(() => undefined);\n return run;\n }\n\n subscribeScope(listener: () => void): () => void {\n this.scopeListeners.add(listener);\n return () => this.scopeListeners.delete(listener);\n }\n\n async exportBackup(): Promise<string> {\n await this.ensureScope();\n return exportItems(this.current);\n }\n\n dispose(): void {\n this.disposed = true;\n this.unsubscribeData();\n this.unsubscribeSync();\n this.current.dispose?.();\n this.scopeListeners.clear();\n this.dataListeners.clear();\n this.syncListeners.clear();\n }\n\n private createAdapter(scope: SyncScope | undefined): SyncStorageAdapter<TMeta> {\n const local = this.options.local\n ? scope\n ? createScopedStorageAdapter(this.options.local, scope)\n : this.options.local\n : createBrowserStorageAdapter<TMeta>({ key: this.options.key, databaseName: this.options.databaseName, scope });\n const queue =\n this.options.queue && scope ? new ScopedSyncQueueAdapter(this.options.queue, scope) : this.options.queue;\n const remote = createAuthenticatedRemote(this.options, scope);\n return new SyncStorageAdapter<TMeta>({\n ...this.options,\n local,\n remote,\n queue,\n scope,\n });\n }\n\n private attach(adapter: SyncStorageAdapter<TMeta>): void {\n this.unsubscribeData = adapter.subscribe?.(() => this.notify(this.dataListeners)) ?? (() => undefined);\n this.unsubscribeSync = adapter.subscribeSync(() => this.notify(this.syncListeners));\n }\n\n private async ensureScope(): Promise<void> {\n if (!this.options.getScope) return;\n await this.setScope(await this.options.getScope());\n }\n\n private notify(listeners: Set<() => void>): void {\n for (const listener of listeners) listener();\n }\n}\n\nfunction createAuthenticatedRemote<TMeta>(\n options: AuthenticatedSyncKitOptions<TMeta>,\n scope: SyncScope | undefined,\n): RemoteSyncDriver<TMeta> {\n const pull = options.transport.pull;\n return {\n push: async (operation) => {\n try {\n const token = await options.getAuthToken();\n return await options.transport.push(operation, { token, scope, operation });\n } catch (cause) {\n return handleAuthFailure(cause, options, { operation, scope });\n }\n },\n pull: pull\n ? async () => {\n try {\n const token = await options.getAuthToken();\n return await pull({ token, scope });\n } catch (cause) {\n return handleAuthFailure(cause, options, { scope });\n }\n }\n : undefined,\n };\n}\n\nasync function handleAuthFailure<TMeta>(\n cause: unknown,\n options: AuthenticatedSyncKitOptions<TMeta>,\n context: AuthenticatedSyncAuthContext<TMeta>,\n): Promise<never> {\n const status = getAuthStatus(cause);\n if (!status) throw cause;\n const error =\n cause instanceof KeepSyncAuthErrorClass\n ? cause\n : new KeepSyncAuthErrorClass(status, { operation: context.operation, scope: context.scope, cause });\n await options.onAuthError?.(error, context);\n await options.onReauthenticate?.(error, context);\n throw error;\n}\n\nfunction getAuthStatus(error: unknown): KeepSyncAuthStatus | undefined {\n if (error instanceof KeepSyncAuthErrorClass) return error.status;\n if (!error || typeof error !== \"object\") return undefined;\n const candidate = error as { status?: unknown; response?: { status?: unknown }; cause?: unknown };\n if (candidate.status === 401 || candidate.status === 403) return candidate.status;\n if (candidate.response?.status === 401 || candidate.response?.status === 403) return candidate.response.status;\n return candidate.cause ? getAuthStatus(candidate.cause) : undefined;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/features/items/presets.ts","../src/features/items/url.ts","../src/features/sync/integrations.ts","../src/features/sync/templates/auth-sync.ts"],"sourcesContent":["import { createBrowserStorageAdapter } from \"../../storage/index\";\nimport { SyncStorageAdapter } from \"../../storage/sync\";\nimport { exportItems } from \"../persistence/backup\";\nimport { createScopedStorageAdapter, type KeepScope } from \"../persistence/scope\";\nimport type { RemoteSyncDriver, StorageAdapter } from \"./types\";\n\nexport type KeepKitPresetMode = \"local\" | \"sync\" | \"backup\";\n\nexport type KeepKitPresetOptions<TMeta = Record<string, unknown>> = {\n mode?: KeepKitPresetMode;\n key?: string;\n scope?: KeepScope;\n remote?: RemoteSyncDriver<TMeta>;\n storage?: StorageAdapter<TMeta>;\n};\n\nexport type KeepKitSetup<TMeta = Record<string, unknown>> = {\n mode: KeepKitPresetMode;\n scope?: KeepScope;\n storage: StorageAdapter<TMeta>;\n exportBackup: () => Promise<string>;\n};\n\n/**\n * Build the recommended local/sync/backup wiring without imposing an auth or\n * API client. Pass the current user and tenant scope whenever the account changes.\n */\nexport function createKeepKitPreset<TMeta = Record<string, unknown>>(\n options: KeepKitPresetOptions<TMeta> = {},\n): KeepKitSetup<TMeta> {\n const mode = options.mode ?? \"local\";\n const local = options.storage\n ? options.scope\n ? createScopedStorageAdapter(options.storage, options.scope)\n : options.storage\n : createBrowserStorageAdapter<TMeta>({ key: options.key, scope: options.scope });\n if (mode === \"sync\" && !options.remote) {\n throw new Error('createKeepKitPreset({ mode: \"sync\" }) requires a remote driver.');\n }\n let storage: StorageAdapter<TMeta> = local;\n if (mode === \"sync\") {\n const remote = options.remote;\n if (!remote) throw new Error('createKeepKitPreset({ mode: \"sync\" }) requires a remote driver.');\n storage = new SyncStorageAdapter<TMeta>({\n local,\n remote,\n userId: options.scope?.userId,\n tenantId: options.scope?.tenantId,\n });\n }\n return {\n mode,\n scope: options.scope,\n storage,\n exportBackup: () => exportItems(storage),\n };\n}\n\nexport const createKeepKitSetup = createKeepKitPreset;\n","import type { KeepListQuery } from \"./query\";\n\nexport type KeepUrlParamNames = {\n search: string;\n tags: string;\n sort: string;\n page: string;\n archived: string;\n archiveScope: string;\n collection: string;\n pinnedFirst: string;\n activityOpened?: string;\n lastOpenedBefore?: string;\n lastOpenedAfter?: string;\n inactiveForMs?: string;\n};\n\nexport type KeepUrlSyncOptions = {\n /** Parameters are intentionally short so shared collection URLs stay readable. */\n params?: Partial<KeepUrlParamNames>;\n /** Push is the default so browser back/forward restores collection states. */\n history?: \"replace\" | \"push\";\n /** URL to read/write. Defaults to the current browser URL. */\n url?: string;\n};\n\nexport const DEFAULT_KEEP_URL_PARAMS: Required<KeepUrlParamNames> = {\n search: \"q\",\n tags: \"tag\",\n sort: \"sort\",\n page: \"page\",\n archived: \"archived\",\n archiveScope: \"archiveScope\",\n collection: \"collection\",\n pinnedFirst: \"pinned\",\n activityOpened: \"opened\",\n lastOpenedBefore: \"openedBefore\",\n lastOpenedAfter: \"openedAfter\",\n inactiveForMs: \"inactiveFor\",\n};\n\nexport type KeepUrlState = Pick<\n KeepListQuery,\n \"search\" | \"tags\" | \"sort\" | \"pagination\" | \"archived\" | \"archiveScope\" | \"collectionId\" | \"pinnedFirst\" | \"activity\"\n>;\n\n/** Convert a list query to stable URLSearchParams without serializing functions or unsupported filters. */\nexport function encodeKeepListQuery<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta> = {},\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): URLSearchParams {\n const params: Required<KeepUrlParamNames> = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };\n const result = new URLSearchParams();\n const search = query.search?.query?.trim();\n if (search) result.set(params.search, search);\n for (const tag of query.tags ?? []) {\n const normalized = tag.trim();\n if (normalized) result.append(params.tags, normalized);\n }\n if (query.sort?.by) result.set(params.sort, `${query.sort.by}:${query.sort.direction ?? \"desc\"}`);\n const page = query.pagination?.page;\n if (page !== undefined && Number.isFinite(page) && page > 1) result.set(params.page, String(Math.floor(page)));\n if (query.archiveScope !== undefined) result.set(params.archiveScope, query.archiveScope);\n else if (query.archived !== undefined) result.set(params.archived, query.archived ? \"true\" : \"false\");\n if (query.collectionId) result.set(params.collection, query.collectionId);\n if (query.pinnedFirst) result.set(params.pinnedFirst, \"true\");\n if (query.activity?.opened) result.set(params.activityOpened, query.activity.opened);\n for (const [key, value] of [\n [params.lastOpenedBefore, query.activity?.lastOpenedBefore],\n [params.lastOpenedAfter, query.activity?.lastOpenedAfter],\n [params.inactiveForMs, query.activity?.inactiveForMs],\n ] as const) {\n if (value !== undefined && Number.isFinite(value)) result.set(key, String(value));\n }\n return result;\n}\n\n/** Parse a URL into the query fields supported by KeepCollection. Invalid values are ignored. */\nexport function decodeKeepListQuery(\n input: string | URL | URLSearchParams,\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): KeepUrlState {\n const params: Required<KeepUrlParamNames> = { ...DEFAULT_KEEP_URL_PARAMS, ...options.params };\n const searchParams = input instanceof URLSearchParams ? input : new URL(input, \"http://keepkit.invalid\").searchParams;\n const search = searchParams.get(params.search)?.trim();\n const tags = [\n ...new Set(\n searchParams\n .getAll(params.tags)\n .map((tag) => tag.trim())\n .filter(Boolean),\n ),\n ];\n const sortValue = searchParams.get(params.sort)?.split(\":\");\n const sort: KeepListQuery[\"sort\"] =\n sortValue?.[0] === \"savedAt\" || sortValue?.[0] === \"updatedAt\" || sortValue?.[0] === \"lastOpenedAt\"\n ? {\n by: sortValue[0],\n direction: sortValue[1] === \"asc\" ? (\"asc\" as const) : (\"desc\" as const),\n }\n : undefined;\n const rawPage = Number(searchParams.get(params.page));\n const page = Number.isInteger(rawPage) && rawPage > 0 ? rawPage : undefined;\n const archiveScopeValue = searchParams.get(params.archiveScope);\n const archiveScope =\n archiveScopeValue === \"active\" || archiveScopeValue === \"archived\" || archiveScopeValue === \"all\"\n ? archiveScopeValue\n : undefined;\n const archivedValue = searchParams.get(params.archived);\n const archived =\n archiveScope === \"archived\" || archivedValue === \"true\"\n ? true\n : archiveScope === \"active\" || archivedValue === \"false\"\n ? false\n : undefined;\n const collectionId = searchParams.get(params.collection)?.trim() || undefined;\n const pinnedFirst = searchParams.get(params.pinnedFirst) === \"true\" ? true : undefined;\n const activityOpenedValue = searchParams.get(params.activityOpened);\n const activityOpened: \"ever\" | \"never\" | undefined =\n activityOpenedValue === \"ever\" || activityOpenedValue === \"never\" ? activityOpenedValue : undefined;\n const parseActivityNumber = (name: string): number | undefined => {\n const rawValue = searchParams.get(name);\n if (rawValue === null || rawValue.trim() === \"\") return undefined;\n const value = Number(rawValue);\n return Number.isFinite(value) ? value : undefined;\n };\n const lastOpenedBefore = parseActivityNumber(params.lastOpenedBefore);\n const lastOpenedAfter = parseActivityNumber(params.lastOpenedAfter);\n const inactiveForMs = parseActivityNumber(params.inactiveForMs);\n const activity =\n activityOpened !== undefined ||\n lastOpenedBefore !== undefined ||\n lastOpenedAfter !== undefined ||\n inactiveForMs !== undefined\n ? {\n ...(activityOpened === undefined ? {} : { opened: activityOpened }),\n ...(lastOpenedBefore === undefined ? {} : { lastOpenedBefore }),\n ...(lastOpenedAfter === undefined ? {} : { lastOpenedAfter }),\n ...(inactiveForMs === undefined ? {} : { inactiveForMs }),\n }\n : undefined;\n return {\n ...(search ? { search: { query: search } } : {}),\n ...(tags.length > 0 ? { tags } : {}),\n ...(sort ? { sort } : {}),\n ...(page ? { pagination: { page } } : {}),\n ...(archived === undefined ? {} : { archived }),\n ...(archiveScope === undefined ? {} : { archiveScope }),\n ...(collectionId ? { collectionId } : {}),\n ...(pinnedFirst ? { pinnedFirst } : {}),\n ...(activity === undefined ? {} : { activity }),\n };\n}\n\nexport function serializeKeepListQuery<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta> = {},\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): string {\n const value = encodeKeepListQuery(query, options).toString();\n return value ? `?${value}` : \"\";\n}\n\nexport function mergeKeepListQueryFromUrl<TMeta = Record<string, unknown>>(\n query: KeepListQuery<TMeta>,\n input: string | URL | URLSearchParams,\n options: Pick<KeepUrlSyncOptions, \"params\"> = {},\n): KeepListQuery<TMeta> {\n const decoded = decodeKeepListQuery(input, options);\n return {\n ...query,\n ...decoded,\n search: decoded.search ?? query.search,\n tags: decoded.tags ?? query.tags,\n sort: decoded.sort ?? query.sort,\n pagination: decoded.pagination ? { ...query.pagination, ...decoded.pagination } : query.pagination,\n archived: decoded.archived ?? query.archived,\n archiveScope: decoded.archiveScope ?? query.archiveScope,\n activity: decoded.activity ?? query.activity,\n };\n}\n","import type { KeepPlugin, KeepPluginContext } from \"../items/types\";\n\nexport type KeepInvalidationPluginOptions<TMeta = Record<string, unknown>> = {\n /** Query keys to invalidate after a successful local KeepKit mutation. */\n queryKeys: readonly unknown[] | ((context: KeepPluginContext<TMeta>) => readonly (readonly unknown[])[]);\n /** Connect this callback to queryClient.invalidateQueries or SWR mutate. */\n invalidate: (queryKey: readonly unknown[], context: KeepPluginContext<TMeta>) => void | Promise<void>;\n name?: string;\n};\n\n/** Framework-neutral bridge for TanStack Query, SWR, and similar caches. */\nexport function createKeepInvalidationPlugin<TMeta = Record<string, unknown>>(\n options: KeepInvalidationPluginOptions<TMeta>,\n): KeepPlugin<TMeta> {\n return {\n name: options.name ?? \"keepkit-cache-invalidation\",\n after: async (context) => {\n const keys = typeof options.queryKeys === \"function\" ? options.queryKeys(context) : [options.queryKeys];\n await Promise.all(keys.map((queryKey) => options.invalidate(queryKey, context)));\n },\n };\n}\n","import { type BrowserStorageAdapterOptions, createBrowserStorageAdapter } from \"../../../storage\";\nimport { SyncStorageAdapter, type SyncStorageAdapterOptions } from \"../../../storage/sync\";\nimport type {\n KeepItem,\n KeepSyncAuthError,\n KeepSyncAuthStatus,\n KeepSyncState,\n RemoteSyncDriver,\n RemoteSyncResult,\n StorageAdapter,\n SyncCapableStorageAdapter,\n SyncOperation,\n SyncScope,\n} from \"../../items/types\";\nimport { KeepSyncAuthError as KeepSyncAuthErrorClass } from \"../../items/types\";\nimport { exportItems } from \"../../persistence/backup\";\nimport {\n createScopedStorageAdapter,\n getKeepScopeKey,\n isSameKeepScope,\n ScopedSyncQueueAdapter,\n} from \"../../persistence/scope\";\n\nexport type AuthenticatedSyncRequestContext<TMeta = Record<string, unknown>> = {\n token: string | null;\n scope?: SyncScope;\n operation?: SyncOperation<TMeta>;\n};\n\n/** Transport boundary for auth-aware requests; cookies and bearer tokens remain host concerns. */\nexport type AuthenticatedSyncTransport<TMeta = Record<string, unknown>> = {\n push: (\n operation: SyncOperation<TMeta>,\n context: AuthenticatedSyncRequestContext<TMeta>,\n ) => Promise<RemoteSyncResult<TMeta>>;\n pull?: (context: AuthenticatedSyncRequestContext<TMeta>) => Promise<KeepItem<TMeta>[]>;\n};\n\nexport type AuthenticatedSyncAuthContext<TMeta = Record<string, unknown>> = {\n operation?: SyncOperation<TMeta>;\n scope?: SyncScope;\n};\n\nexport type AuthenticatedSyncKitOptions<TMeta = Record<string, unknown>> = Omit<\n SyncStorageAdapterOptions<TMeta>,\n \"local\" | \"remote\" | \"scope\"\n> & {\n /** Optional custom local adapter. Browser storage is used when omitted. */\n local?: StorageAdapter<TMeta>;\n key?: BrowserStorageAdapterOptions[\"key\"];\n databaseName?: BrowserStorageAdapterOptions[\"databaseName\"];\n scope?: SyncScope;\n /** Resolve the active account or tenant before storage operations. */\n getScope?: () => SyncScope | undefined | Promise<SyncScope | undefined>;\n getAuthToken: () => Promise<string | null>;\n transport: AuthenticatedSyncTransport<TMeta>;\n onAuthError?: (error: KeepSyncAuthError<TMeta>, context: AuthenticatedSyncAuthContext<TMeta>) => void | Promise<void>;\n onReauthenticate?: (\n error: KeepSyncAuthError<TMeta>,\n context: AuthenticatedSyncAuthContext<TMeta>,\n ) => void | Promise<void>;\n onScopeChange?: (next: SyncScope | undefined, previous: SyncScope | undefined) => void | Promise<void>;\n};\n\nexport type AuthenticatedSyncKit<TMeta = Record<string, unknown>> = {\n readonly mode: \"sync\";\n readonly storage: SyncCapableStorageAdapter<TMeta>;\n readonly scope?: SyncScope;\n readonly scopeKey: string;\n getScope(): SyncScope | undefined;\n setScope(scope?: SyncScope): Promise<void>;\n subscribeScope(listener: () => void): () => void;\n exportBackup(): Promise<string>;\n dispose(): void;\n};\n\n/** Creates auth-independent sync wiring with per-request tokens and isolated account scopes. */\nexport function createAuthenticatedSyncKit<TMeta = Record<string, unknown>>(\n options: AuthenticatedSyncKitOptions<TMeta>,\n): AuthenticatedSyncKit<TMeta> {\n const controller = new AuthenticatedSyncStorageController(options);\n return {\n mode: \"sync\",\n storage: controller,\n get scope() {\n return controller.scope;\n },\n get scopeKey() {\n return controller.scopeKey;\n },\n getScope: () => controller.scope,\n setScope: (scope) => controller.setScope(scope),\n subscribeScope: (listener) => controller.subscribeScope(listener),\n exportBackup: () => controller.exportBackup(),\n dispose: () => controller.dispose(),\n };\n}\n\nclass AuthenticatedSyncStorageController<TMeta = Record<string, unknown>> implements SyncCapableStorageAdapter<TMeta> {\n private readonly options: AuthenticatedSyncKitOptions<TMeta>;\n private currentScope: SyncScope | undefined;\n private current: SyncStorageAdapter<TMeta>;\n private readonly scopeListeners = new Set<() => void>();\n private readonly dataListeners = new Set<() => void>();\n private readonly syncListeners = new Set<() => void>();\n private unsubscribeData: () => void = () => undefined;\n private unsubscribeSync: () => void = () => undefined;\n private transition = Promise.resolve();\n private disposed = false;\n\n constructor(options: AuthenticatedSyncKitOptions<TMeta>) {\n this.options = options;\n this.currentScope = options.scope;\n this.current = this.createAdapter(this.currentScope);\n this.attach(this.current);\n }\n\n get storageKey(): string | undefined {\n return this.current.storageKey;\n }\n\n get scope(): SyncScope | undefined {\n return this.currentScope;\n }\n\n get scopeKey(): string {\n return getKeepScopeKey(this.currentScope);\n }\n\n async getAll(): Promise<KeepItem<TMeta>[]> {\n await this.ensureScope();\n return this.current.getAll();\n }\n\n async set(item: KeepItem<TMeta>): Promise<void> {\n await this.ensureScope();\n return this.current.set(item);\n }\n\n async setMany(items: KeepItem<TMeta>[]): Promise<void> {\n await this.ensureScope();\n return this.current.setMany(items);\n }\n\n async remove(id: string): Promise<void> {\n await this.ensureScope();\n return this.current.remove(id);\n }\n\n async removeMany(ids: string[]): Promise<void> {\n await this.ensureScope();\n return this.current.removeMany(ids);\n }\n\n async clear(): Promise<void> {\n await this.ensureScope();\n return this.current.clear();\n }\n\n async merge(items: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]> {\n await this.ensureScope();\n return this.current.merge(items);\n }\n\n subscribe(listener: () => void): () => void {\n this.dataListeners.add(listener);\n return () => this.dataListeners.delete(listener);\n }\n\n getSyncState(): KeepSyncState<TMeta> {\n return this.current.getSyncState();\n }\n\n subscribeSync(listener: () => void): () => void {\n this.syncListeners.add(listener);\n return () => this.syncListeners.delete(listener);\n }\n\n async flushSync(): Promise<void> {\n await this.ensureScope();\n return this.current.flushSync();\n }\n\n async retrySync(): Promise<void> {\n await this.ensureScope();\n return this.current.retrySync?.() ?? this.current.flushSync();\n }\n\n async resolveSyncConflict(\n id: string,\n resolution: \"local\" | \"remote\" | \"manual\",\n item?: KeepItem<TMeta>,\n ): Promise<void> {\n await this.ensureScope();\n if (!this.current.resolveSyncConflict) {\n throw new Error(\"The authenticated sync adapter does not support conflict resolution.\");\n }\n return this.current.resolveSyncConflict(id, resolution, item);\n }\n\n async setScope(nextScope?: SyncScope): Promise<void> {\n const run = this.transition.then(async () => {\n if (isSameKeepScope(this.currentScope, nextScope)) return;\n if (this.disposed) throw new Error(\"AuthenticatedSyncKit has been disposed.\");\n const previousScope = this.currentScope;\n this.unsubscribeData();\n this.unsubscribeSync();\n this.current.dispose?.();\n this.currentScope = nextScope;\n this.current = this.createAdapter(nextScope);\n this.attach(this.current);\n await this.options.onScopeChange?.(nextScope, previousScope);\n this.notify(this.scopeListeners);\n this.notify(this.dataListeners);\n this.notify(this.syncListeners);\n });\n this.transition = run.catch(() => undefined);\n return run;\n }\n\n subscribeScope(listener: () => void): () => void {\n this.scopeListeners.add(listener);\n return () => this.scopeListeners.delete(listener);\n }\n\n async exportBackup(): Promise<string> {\n await this.ensureScope();\n return exportItems(this.current);\n }\n\n dispose(): void {\n this.disposed = true;\n this.unsubscribeData();\n this.unsubscribeSync();\n this.current.dispose?.();\n this.scopeListeners.clear();\n this.dataListeners.clear();\n this.syncListeners.clear();\n }\n\n private createAdapter(scope: SyncScope | undefined): SyncStorageAdapter<TMeta> {\n const local = this.options.local\n ? scope\n ? createScopedStorageAdapter(this.options.local, scope)\n : this.options.local\n : createBrowserStorageAdapter<TMeta>({ key: this.options.key, databaseName: this.options.databaseName, scope });\n const queue =\n this.options.queue && scope ? new ScopedSyncQueueAdapter(this.options.queue, scope) : this.options.queue;\n const remote = createAuthenticatedRemote(this.options, scope);\n return new SyncStorageAdapter<TMeta>({\n ...this.options,\n local,\n remote,\n queue,\n scope,\n });\n }\n\n private attach(adapter: SyncStorageAdapter<TMeta>): void {\n this.unsubscribeData = adapter.subscribe?.(() => this.notify(this.dataListeners)) ?? (() => undefined);\n this.unsubscribeSync = adapter.subscribeSync(() => this.notify(this.syncListeners));\n }\n\n private async ensureScope(): Promise<void> {\n if (!this.options.getScope) return;\n await this.setScope(await this.options.getScope());\n }\n\n private notify(listeners: Set<() => void>): void {\n for (const listener of listeners) listener();\n }\n}\n\nfunction createAuthenticatedRemote<TMeta>(\n options: AuthenticatedSyncKitOptions<TMeta>,\n scope: SyncScope | undefined,\n): RemoteSyncDriver<TMeta> {\n const pull = options.transport.pull;\n return {\n push: async (operation) => {\n try {\n const token = await options.getAuthToken();\n return await options.transport.push(operation, { token, scope, operation });\n } catch (cause) {\n return handleAuthFailure(cause, options, { operation, scope });\n }\n },\n pull: pull\n ? async () => {\n try {\n const token = await options.getAuthToken();\n return await pull({ token, scope });\n } catch (cause) {\n return handleAuthFailure(cause, options, { scope });\n }\n }\n : undefined,\n };\n}\n\nasync function handleAuthFailure<TMeta>(\n cause: unknown,\n options: AuthenticatedSyncKitOptions<TMeta>,\n context: AuthenticatedSyncAuthContext<TMeta>,\n): Promise<never> {\n const status = getAuthStatus(cause);\n if (!status) throw cause;\n const error =\n cause instanceof KeepSyncAuthErrorClass\n ? cause\n : new KeepSyncAuthErrorClass(status, { operation: context.operation, scope: context.scope, cause });\n await options.onAuthError?.(error, context);\n await options.onReauthenticate?.(error, context);\n throw error;\n}\n\nfunction getAuthStatus(error: unknown): KeepSyncAuthStatus | undefined {\n if (error instanceof KeepSyncAuthErrorClass) return error.status;\n if (!error || typeof error !== \"object\") return undefined;\n const candidate = error as { status?: unknown; response?: { status?: unknown }; cause?: unknown };\n if (candidate.status === 401 || candidate.status === 403) return candidate.status;\n if (candidate.response?.status === 401 || candidate.response?.status === 403) return candidate.response.status;\n return candidate.cause ? getAuthStatus(candidate.cause) : undefined;\n}\n"],"mappings":"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","names":[]}
|
package/dist/react.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { h as KeepItemMetadataRefresher, m as KeepItemRevalidator, i as KeepItemResolver, c as KeepAutoRevalidationOptions, g as KeepCollectionMeta, R as RevalidateKeepItemsOptions, l as KeepItemRevalidationSummary, I as ImportItemsOptions, a as ImportItemsResult,
|
|
2
|
-
export { k as KeepItemRevalidationResult,
|
|
3
|
-
import { r as KeepItemInput, K as KeepItem, p as KeepEventHandlers, a as StorageAdapter, e as KeepPlugin, t as KeepSchema, q as KeepInvalidItemPolicy, j as KeepChangeContext, D as KeepSyncState, F as KeepUndoState } from './types-
|
|
4
|
-
export { s as KeepItemStatus } from './types-
|
|
5
|
-
export { K as KeepScope, S as ScopedStorageAdapter } from './scope-
|
|
1
|
+
import { h as KeepItemMetadataRefresher, m as KeepItemRevalidator, i as KeepItemResolver, c as KeepAutoRevalidationOptions, g as KeepCollectionMeta, R as RevalidateKeepItemsOptions, l as KeepItemRevalidationSummary, I as ImportItemsOptions, a as ImportItemsResult, r as KeepStore, s as KeepStoreActions, n as KeepListQuery, o as KeepNavigationState, p as KeepRediscoveryOptions } from './store-DbAAC4yU.js';
|
|
2
|
+
export { k as KeepItemRevalidationResult, q as KeepRediscoveryStrategy, u as KeepUrlParamNames, v as KeepUrlState, w as KeepUrlSyncOptions, x as createRediscoveryQuery, F as isKeepItemMetadataStale } from './store-DbAAC4yU.js';
|
|
3
|
+
import { r as KeepItemInput, K as KeepItem, p as KeepEventHandlers, a as StorageAdapter, e as KeepPlugin, t as KeepSchema, q as KeepInvalidItemPolicy, j as KeepChangeContext, D as KeepSyncState, F as KeepUndoState } from './types-CJIbuqTO.js';
|
|
4
|
+
export { s as KeepItemStatus } from './types-CJIbuqTO.js';
|
|
5
|
+
export { K as KeepScope, S as ScopedStorageAdapter } from './scope-BsU6xvN9.js';
|
|
6
6
|
import * as react from 'react';
|
|
7
7
|
import { ReactNode, Ref, ButtonHTMLAttributes, MouseEvent, HTMLAttributes, ReactElement, ErrorInfo, Component, PropsWithChildren, ComponentType } from 'react';
|
|
8
8
|
|
|
@@ -13,6 +13,7 @@ type UseKeepItemResult<TMeta = Record<string, unknown>> = {
|
|
|
13
13
|
isMutating: boolean;
|
|
14
14
|
error: unknown | null;
|
|
15
15
|
save: () => Promise<void>;
|
|
16
|
+
recordOpen: (openedAt?: number) => Promise<void>;
|
|
16
17
|
remove: () => Promise<void>;
|
|
17
18
|
removeWithUndo: () => Promise<void>;
|
|
18
19
|
undo: () => Promise<void>;
|
|
@@ -99,6 +100,7 @@ type KeepContextValue<TMeta = Record<string, unknown>> = {
|
|
|
99
100
|
syncState: KeepSyncState<TMeta>;
|
|
100
101
|
undo: KeepUndoState;
|
|
101
102
|
saveItem: (item: KeepItem<TMeta>) => Promise<void>;
|
|
103
|
+
recordOpen: (id: string, openedAt?: number) => Promise<void>;
|
|
102
104
|
updateNote: (id: string, note?: string) => Promise<void>;
|
|
103
105
|
updateTags: (id: string, tags?: string[]) => Promise<void>;
|
|
104
106
|
toggleArchive: (id: string) => Promise<void>;
|
|
@@ -221,6 +223,15 @@ type UseKeepNavigatorResult<TMeta = Record<string, unknown>> = KeepNavigationSta
|
|
|
221
223
|
/** Derive a stable previous/current/next view and pointer actions from the provider store. */
|
|
222
224
|
declare function useKeepNavigator<TMeta = Record<string, unknown>>(options?: UseKeepNavigatorOptions<TMeta>): UseKeepNavigatorResult<TMeta>;
|
|
223
225
|
|
|
226
|
+
type UseKeepRediscoveryOptions = KeepRediscoveryOptions & {
|
|
227
|
+
limit?: number;
|
|
228
|
+
};
|
|
229
|
+
type UseKeepRediscoveryResult<TMeta = Record<string, unknown>> = UseKeepListResult<TMeta> & {
|
|
230
|
+
query: KeepListQuery<TMeta>;
|
|
231
|
+
};
|
|
232
|
+
/** Query and read a standard rediscovery view through the normal item list path. */
|
|
233
|
+
declare function useKeepRediscovery<TMeta = Record<string, unknown>>(options: UseKeepRediscoveryOptions): UseKeepRediscoveryResult<TMeta>;
|
|
234
|
+
|
|
224
235
|
type KeepShortcutModifier = "meta" | "ctrl" | "alt" | "shift";
|
|
225
236
|
type KeepShortcutOptions<TMeta = Record<string, unknown>> = {
|
|
226
237
|
key: string;
|
|
@@ -247,10 +258,11 @@ type KeepKit<TMeta> = {
|
|
|
247
258
|
orderBy?: "name" | "count";
|
|
248
259
|
}) => UseKeepCollectionsResult;
|
|
249
260
|
useList: (query?: KeepListQuery<TMeta>) => UseKeepListResult<TMeta>;
|
|
261
|
+
useRediscovery: (options: UseKeepRediscoveryOptions) => UseKeepRediscoveryResult<TMeta>;
|
|
250
262
|
useNavigator: (options?: UseKeepNavigatorOptions<TMeta>) => UseKeepNavigatorResult<TMeta>;
|
|
251
263
|
useShortcut: (options: KeepShortcutOptions<TMeta>) => void;
|
|
252
264
|
};
|
|
253
265
|
/** Create an app-specific, fully typed set of KeepKit components and hooks. */
|
|
254
266
|
declare function createKeepKit<TMeta = Record<string, unknown>>(options?: CreateKeepKitOptions<TMeta>): KeepKit<TMeta>;
|
|
255
267
|
|
|
256
|
-
export { type CreateKeepKitOptions, KeepAutoRevalidationOptions, KeepButton, type KeepButtonItem, type KeepButtonProps, type KeepButtonState, type KeepCollectionSummary, type KeepContextValue, KeepErrorBoundary, type KeepErrorBoundaryProps, KeepItemMetadataRefresher, KeepItemResolver, KeepItemRevalidationSummary, KeepItemRevalidator, type KeepKit, KeepListQuery, KeepProvider, type KeepProviderProps, type KeepShortcutModifier, type KeepShortcutOptions, KeepUndoState, RevalidateKeepItemsOptions, type UseKeepCollectionsOptions, type UseKeepCollectionsResult, type UseKeepItemResult, type UseKeepListResult, type UseKeepNavigatorOptions, type UseKeepNavigatorResult, createKeepKit, useKeepCollections, useKeepContext, useKeepItem, useKeepList, useKeepNavigator, useKeepShortcut, useKeepStore };
|
|
268
|
+
export { type CreateKeepKitOptions, KeepAutoRevalidationOptions, KeepButton, type KeepButtonItem, type KeepButtonProps, type KeepButtonState, type KeepCollectionSummary, type KeepContextValue, KeepErrorBoundary, type KeepErrorBoundaryProps, KeepItemMetadataRefresher, KeepItemResolver, KeepItemRevalidationSummary, KeepItemRevalidator, type KeepKit, KeepListQuery, KeepProvider, type KeepProviderProps, KeepRediscoveryOptions, type KeepShortcutModifier, type KeepShortcutOptions, KeepUndoState, RevalidateKeepItemsOptions, type UseKeepCollectionsOptions, type UseKeepCollectionsResult, type UseKeepItemResult, type UseKeepListResult, type UseKeepNavigatorOptions, type UseKeepNavigatorResult, type UseKeepRediscoveryOptions, type UseKeepRediscoveryResult, createKeepKit, useKeepCollections, useKeepContext, useKeepItem, useKeepList, useKeepNavigator, useKeepRediscovery, useKeepShortcut, useKeepStore };
|