@keepkit/core 0.28.3 → 0.28.5
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 +26 -2
- package/dist/{chunk-IIGN4U7N.js → chunk-AUNFZU3A.js} +61 -6
- package/dist/chunk-AUNFZU3A.js.map +1 -0
- package/dist/{chunk-MZFZQIM5.js → chunk-NZLAW4LY.js} +467 -27
- package/dist/chunk-NZLAW4LY.js.map +1 -0
- package/dist/core.d.ts +164 -7
- package/dist/core.js +483 -7
- package/dist/core.js.map +1 -1
- package/dist/react.d.ts +5 -5
- package/dist/react.js +58 -22
- package/dist/react.js.map +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/{scope-BsU6xvN9.d.ts → scope-BteyH-b9.d.ts} +9 -3
- package/dist/storage.d.ts +47 -9
- package/dist/storage.js +1 -1
- package/dist/{store-C7pEDMLm.d.ts → store-DVP3QyVp.d.ts} +13 -4
- package/dist/{types-CJIbuqTO.d.ts → types-SKIL2p2c.d.ts} +43 -3
- package/package.json +1 -1
- package/dist/chunk-IIGN4U7N.js.map +0 -1
- package/dist/chunk-MZFZQIM5.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SyncScope, a as StorageAdapter, K as
|
|
1
|
+
import { S as SyncScope, a as StorageAdapter, K as KeepCollectionDefinition, b as KeepCollectionMembership, c as KeepItem, d as SyncQueueAdapter, e as KeepSyncQueueOperation } from './types-SKIL2p2c.js';
|
|
2
2
|
|
|
3
3
|
type KeepScope = SyncScope;
|
|
4
4
|
/** Return a stable, human-readable namespace for browser storage and queues. */
|
|
@@ -11,6 +11,12 @@ declare function isSameKeepScope(left: KeepScope | undefined, right: KeepScope |
|
|
|
11
11
|
*/
|
|
12
12
|
declare class ScopedStorageAdapter<TMeta = Record<string, unknown>> implements StorageAdapter<TMeta> {
|
|
13
13
|
readonly storageKey?: string;
|
|
14
|
+
readonly getCollections?: () => Promise<KeepCollectionDefinition[]>;
|
|
15
|
+
readonly setCollection?: (collection: KeepCollectionDefinition) => Promise<void>;
|
|
16
|
+
readonly removeCollection?: (id: string, scope?: SyncScope) => Promise<void>;
|
|
17
|
+
readonly getCollectionMemberships?: () => Promise<KeepCollectionMembership[]>;
|
|
18
|
+
readonly setCollectionMembership?: (membership: KeepCollectionMembership) => Promise<void>;
|
|
19
|
+
readonly removeCollectionMembership?: (collectionId: string, itemId: string, scope?: SyncScope) => Promise<void>;
|
|
14
20
|
private readonly base;
|
|
15
21
|
private readonly scope?;
|
|
16
22
|
constructor(base: StorageAdapter<TMeta>, scope?: KeepScope);
|
|
@@ -29,8 +35,8 @@ declare class ScopedSyncQueueAdapter<TMeta = Record<string, unknown>> implements
|
|
|
29
35
|
private readonly base;
|
|
30
36
|
private readonly scope?;
|
|
31
37
|
constructor(base: SyncQueueAdapter<TMeta>, scope?: KeepScope);
|
|
32
|
-
getAll(): Promise<
|
|
33
|
-
setMany(operations:
|
|
38
|
+
getAll(): Promise<KeepSyncQueueOperation<TMeta>[]>;
|
|
39
|
+
setMany(operations: KeepSyncQueueOperation<TMeta>[]): Promise<void>;
|
|
34
40
|
remove(operationIds: string[]): Promise<void>;
|
|
35
41
|
clear(): Promise<void>;
|
|
36
42
|
}
|
package/dist/storage.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as StorageAdapter, R as RemoteSyncDriver,
|
|
2
|
-
import { K as KeepScope } from './scope-
|
|
3
|
-
export { S as ScopedStorageAdapter, a as ScopedSyncQueueAdapter, c as createScopedStorageAdapter } from './scope-
|
|
1
|
+
import { a as StorageAdapter, R as RemoteSyncDriver, d as SyncQueueAdapter, u as KeepConflictResolver, S as SyncScope, e as KeepSyncQueueOperation, o as SyncCapableStorageAdapter, K as KeepCollectionDefinition, b as KeepCollectionMembership, I as KeepSyncState, c as KeepItem, H as KeepSyncResolution } from './types-SKIL2p2c.js';
|
|
2
|
+
import { K as KeepScope } from './scope-BteyH-b9.js';
|
|
3
|
+
export { S as ScopedStorageAdapter, a as ScopedSyncQueueAdapter, c as createScopedStorageAdapter } from './scope-BteyH-b9.js';
|
|
4
4
|
|
|
5
5
|
type LocalStorageSyncQueueOptions = {
|
|
6
6
|
key?: string;
|
|
@@ -40,8 +40,8 @@ declare class LocalStorageSyncQueueAdapter<TMeta = Record<string, unknown>> impl
|
|
|
40
40
|
private readonly key;
|
|
41
41
|
private readonly storage;
|
|
42
42
|
constructor(options?: LocalStorageSyncQueueOptions);
|
|
43
|
-
getAll(): Promise<
|
|
44
|
-
setMany(operations:
|
|
43
|
+
getAll(): Promise<KeepSyncQueueOperation<TMeta>[]>;
|
|
44
|
+
setMany(operations: KeepSyncQueueOperation<TMeta>[]): Promise<void>;
|
|
45
45
|
remove(operationIds: string[]): Promise<void>;
|
|
46
46
|
clear(): Promise<void>;
|
|
47
47
|
}
|
|
@@ -52,8 +52,8 @@ declare class IndexedDBSyncQueueAdapter<TMeta = Record<string, unknown>> impleme
|
|
|
52
52
|
private readonly indexedDB;
|
|
53
53
|
private databasePromise;
|
|
54
54
|
constructor(options?: IndexedDBSyncQueueOptions);
|
|
55
|
-
getAll(): Promise<
|
|
56
|
-
setMany(operations:
|
|
55
|
+
getAll(): Promise<KeepSyncQueueOperation<TMeta>[]>;
|
|
56
|
+
setMany(operations: KeepSyncQueueOperation<TMeta>[]): Promise<void>;
|
|
57
57
|
remove(operationIds: string[]): Promise<void>;
|
|
58
58
|
clear(): Promise<void>;
|
|
59
59
|
private open;
|
|
@@ -66,8 +66,8 @@ declare class FallbackSyncQueueAdapter<TMeta = Record<string, unknown>> implemen
|
|
|
66
66
|
private active;
|
|
67
67
|
constructor(options: FallbackSyncQueueAdapterOptions<TMeta>);
|
|
68
68
|
get isUsingFallback(): boolean;
|
|
69
|
-
getAll(): Promise<
|
|
70
|
-
setMany(operations:
|
|
69
|
+
getAll(): Promise<KeepSyncQueueOperation<TMeta>[]>;
|
|
70
|
+
setMany(operations: KeepSyncQueueOperation<TMeta>[]): Promise<void>;
|
|
71
71
|
remove(operationIds: string[]): Promise<void>;
|
|
72
72
|
clear(): Promise<void>;
|
|
73
73
|
private execute;
|
|
@@ -75,6 +75,12 @@ declare class FallbackSyncQueueAdapter<TMeta = Record<string, unknown>> implemen
|
|
|
75
75
|
/** A local-first adapter that persists remote operations until they are acknowledged. */
|
|
76
76
|
declare class SyncStorageAdapter<TMeta = Record<string, unknown>> implements SyncCapableStorageAdapter<TMeta> {
|
|
77
77
|
readonly storageKey?: string;
|
|
78
|
+
readonly getCollections?: () => Promise<KeepCollectionDefinition[]>;
|
|
79
|
+
readonly setCollection?: (collection: KeepCollectionDefinition) => Promise<void>;
|
|
80
|
+
readonly removeCollection?: (id: string, scope?: SyncScope) => Promise<void>;
|
|
81
|
+
readonly getCollectionMemberships?: () => Promise<KeepCollectionMembership[]>;
|
|
82
|
+
readonly setCollectionMembership?: (membership: KeepCollectionMembership) => Promise<void>;
|
|
83
|
+
readonly removeCollectionMembership?: (collectionId: string, itemId: string, scope?: SyncScope) => Promise<void>;
|
|
78
84
|
private readonly local;
|
|
79
85
|
private readonly remote;
|
|
80
86
|
private readonly queue;
|
|
@@ -112,8 +118,10 @@ declare class SyncStorageAdapter<TMeta = Record<string, unknown>> implements Syn
|
|
|
112
118
|
dispose(): void;
|
|
113
119
|
private runFlush;
|
|
114
120
|
private createOperation;
|
|
121
|
+
private createCollectionOperation;
|
|
115
122
|
private applyScope;
|
|
116
123
|
private pushWithRetry;
|
|
124
|
+
private pushCollectionWithRetry;
|
|
117
125
|
private enqueueBeforeLocalWrite;
|
|
118
126
|
private enqueueManyBeforeLocalWrite;
|
|
119
127
|
private loadQueue;
|
|
@@ -145,6 +153,12 @@ declare const DEFAULT_INDEXEDDB_DATABASE = "keepkit";
|
|
|
145
153
|
declare const DEFAULT_INDEXEDDB_STORE = "items";
|
|
146
154
|
type StorageAdapterFactoryOptions<TMeta = Record<string, unknown>> = {
|
|
147
155
|
getAll: () => KeepItem<TMeta>[] | Promise<KeepItem<TMeta>[]>;
|
|
156
|
+
getCollections?: () => KeepCollectionDefinition[] | Promise<KeepCollectionDefinition[]>;
|
|
157
|
+
setCollection?: (collection: KeepCollectionDefinition) => void | Promise<void>;
|
|
158
|
+
removeCollection?: (id: string, scope?: KeepScope) => void | Promise<void>;
|
|
159
|
+
getCollectionMemberships?: () => KeepCollectionMembership[] | Promise<KeepCollectionMembership[]>;
|
|
160
|
+
setCollectionMembership?: (membership: KeepCollectionMembership) => void | Promise<void>;
|
|
161
|
+
removeCollectionMembership?: (collectionId: string, itemId: string, scope?: KeepScope) => void | Promise<void>;
|
|
148
162
|
set: (item: KeepItem<TMeta>) => void | Promise<void>;
|
|
149
163
|
setMany?: (items: KeepItem<TMeta>[]) => void | Promise<void>;
|
|
150
164
|
remove: (id: string) => void | Promise<void>;
|
|
@@ -171,6 +185,12 @@ type FallbackStorageAdapterOptions<TMeta = Record<string, unknown>> = {
|
|
|
171
185
|
*/
|
|
172
186
|
declare class FallbackStorageAdapter<TMeta = Record<string, unknown>> implements StorageAdapter<TMeta> {
|
|
173
187
|
readonly storageKey: string | undefined;
|
|
188
|
+
readonly getCollections?: () => Promise<KeepCollectionDefinition[]>;
|
|
189
|
+
readonly setCollection?: (collection: KeepCollectionDefinition) => Promise<void>;
|
|
190
|
+
readonly removeCollection?: (id: string, scope?: KeepScope) => Promise<void>;
|
|
191
|
+
readonly getCollectionMemberships?: () => Promise<KeepCollectionMembership[]>;
|
|
192
|
+
readonly setCollectionMembership?: (membership: KeepCollectionMembership) => Promise<void>;
|
|
193
|
+
readonly removeCollectionMembership?: (collectionId: string, itemId: string, scope?: KeepScope) => Promise<void>;
|
|
174
194
|
private readonly primary;
|
|
175
195
|
private readonly fallback;
|
|
176
196
|
private readonly shouldFallback;
|
|
@@ -214,6 +234,12 @@ declare class LocalStorageAdapter<TMeta = Record<string, unknown>> implements St
|
|
|
214
234
|
private readonly storage;
|
|
215
235
|
constructor(options?: LocalStorageAdapterOptions);
|
|
216
236
|
getAll(): Promise<KeepItem<TMeta>[]>;
|
|
237
|
+
getCollections(): Promise<KeepCollectionDefinition[]>;
|
|
238
|
+
setCollection(collection: KeepCollectionDefinition): Promise<void>;
|
|
239
|
+
removeCollection(id: string, scope?: KeepScope): Promise<void>;
|
|
240
|
+
getCollectionMemberships(): Promise<KeepCollectionMembership[]>;
|
|
241
|
+
setCollectionMembership(membership: KeepCollectionMembership): Promise<void>;
|
|
242
|
+
removeCollectionMembership(collectionId: string, itemId: string, scope?: KeepScope): Promise<void>;
|
|
217
243
|
set(item: KeepItem<TMeta>): Promise<void>;
|
|
218
244
|
setMany(items: KeepItem<TMeta>[]): Promise<void>;
|
|
219
245
|
remove(id: string): Promise<void>;
|
|
@@ -222,6 +248,8 @@ declare class LocalStorageAdapter<TMeta = Record<string, unknown>> implements St
|
|
|
222
248
|
merge(localItems: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]>;
|
|
223
249
|
subscribe(listener: () => void): () => void;
|
|
224
250
|
private write;
|
|
251
|
+
private writeCollections;
|
|
252
|
+
private writeMemberships;
|
|
225
253
|
}
|
|
226
254
|
/** An async StorageAdapter backed by IndexedDB, with one object store per adapter. */
|
|
227
255
|
declare class IndexedDBAdapter<TMeta = Record<string, unknown>> implements StorageAdapter<TMeta> {
|
|
@@ -231,8 +259,15 @@ declare class IndexedDBAdapter<TMeta = Record<string, unknown>> implements Stora
|
|
|
231
259
|
private readonly version;
|
|
232
260
|
private readonly indexedDB;
|
|
233
261
|
private databasePromise;
|
|
262
|
+
private collectionDatabasePromise;
|
|
234
263
|
constructor(options?: IndexedDBAdapterOptions);
|
|
235
264
|
getAll(): Promise<KeepItem<TMeta>[]>;
|
|
265
|
+
getCollections(): Promise<KeepCollectionDefinition[]>;
|
|
266
|
+
setCollection(collection: KeepCollectionDefinition): Promise<void>;
|
|
267
|
+
removeCollection(id: string, scope?: KeepScope): Promise<void>;
|
|
268
|
+
getCollectionMemberships(): Promise<KeepCollectionMembership[]>;
|
|
269
|
+
setCollectionMembership(membership: KeepCollectionMembership): Promise<void>;
|
|
270
|
+
removeCollectionMembership(collectionId: string, itemId: string, scope?: KeepScope): Promise<void>;
|
|
236
271
|
set(item: KeepItem<TMeta>): Promise<void>;
|
|
237
272
|
setMany(items: KeepItem<TMeta>[]): Promise<void>;
|
|
238
273
|
remove(id: string): Promise<void>;
|
|
@@ -241,6 +276,9 @@ declare class IndexedDBAdapter<TMeta = Record<string, unknown>> implements Stora
|
|
|
241
276
|
merge(localItems: KeepItem<TMeta>[]): Promise<KeepItem<TMeta>[]>;
|
|
242
277
|
subscribe(listener: () => void): () => void;
|
|
243
278
|
private notifySubscribers;
|
|
279
|
+
private writeCollection;
|
|
280
|
+
private writeCollectionMembership;
|
|
281
|
+
private openCollections;
|
|
244
282
|
private open;
|
|
245
283
|
}
|
|
246
284
|
|
package/dist/storage.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as KeepItem, f as KeepItemStatus, a as StorageAdapter, g as KeepSchema, h as KeepInvalidItemPolicy, K as KeepCollectionDefinition, b as KeepCollectionMembership, i as KeepChangeContext, j as KeepUndoState } from './types-SKIL2p2c.js';
|
|
2
2
|
|
|
3
3
|
type KeepNavigationState<TMeta = Record<string, unknown>> = {
|
|
4
4
|
items: KeepItem<TMeta>[];
|
|
@@ -165,13 +165,22 @@ declare function serializeKeepListQuery<TMeta = Record<string, unknown>>(query?:
|
|
|
165
165
|
declare function mergeKeepListQueryFromUrl<TMeta = Record<string, unknown>>(query: KeepListQuery<TMeta>, input: string | URL | URLSearchParams, options?: Pick<KeepUrlSyncOptions, "params">): KeepListQuery<TMeta>;
|
|
166
166
|
|
|
167
167
|
declare const KEEP_BACKUP_FORMAT = "keepkit";
|
|
168
|
-
declare const KEEP_BACKUP_VERSION =
|
|
169
|
-
type
|
|
168
|
+
declare const KEEP_BACKUP_VERSION = 2;
|
|
169
|
+
type KeepBackupV1<TMeta = Record<string, unknown>> = {
|
|
170
|
+
format: typeof KEEP_BACKUP_FORMAT;
|
|
171
|
+
version: 1;
|
|
172
|
+
exportedAt: number;
|
|
173
|
+
items: KeepItem<TMeta>[];
|
|
174
|
+
};
|
|
175
|
+
type KeepBackupV2<TMeta = Record<string, unknown>> = {
|
|
170
176
|
format: typeof KEEP_BACKUP_FORMAT;
|
|
171
177
|
version: typeof KEEP_BACKUP_VERSION;
|
|
172
178
|
exportedAt: number;
|
|
173
179
|
items: KeepItem<TMeta>[];
|
|
180
|
+
collections: KeepCollectionDefinition[];
|
|
181
|
+
memberships: KeepCollectionMembership[];
|
|
174
182
|
};
|
|
183
|
+
type KeepBackup<TMeta = Record<string, unknown>> = KeepBackupV1<TMeta> | KeepBackupV2<TMeta>;
|
|
175
184
|
type ImportItemsOptions<TMeta = unknown> = {
|
|
176
185
|
mode?: "replace" | "merge";
|
|
177
186
|
schema?: KeepSchema<TMeta>;
|
|
@@ -263,4 +272,4 @@ declare class KeepStore<TMeta = Record<string, unknown>> {
|
|
|
263
272
|
setState(next: Partial<KeepStoreState<TMeta>>): void;
|
|
264
273
|
}
|
|
265
274
|
|
|
266
|
-
export {
|
|
275
|
+
export { createRediscoveryQuery as A, decodeKeepListQuery as B, encodeKeepListQuery as C, DEFAULT_KEEP_URL_PARAMS as D, exportItems as E, getKeepNavigationState as F, getTagCounts as G, importItems as H, type ImportItemsOptions as I, isKeepItemMetadataStale as J, type KeepListQuery as K, mergeKeepListQueryFromUrl as L, moveKeepItem as M, orderKeepItems as N, queryKeepItems as O, reconcileKeepItems as P, type QueryKeepItemsResult as Q, type RevalidateKeepItemsOptions as R, reorderKeepItems as S, revalidateKeepItems as T, serializeKeepListQuery as U, type ImportItemsResult as a, KEEP_BACKUP_FORMAT as b, KEEP_BACKUP_VERSION as c, type KeepAutoRevalidationOptions as d, type KeepBackup as e, KeepBackupImportError as f, KeepBackupParseError as g, type KeepBackupV1 as h, type KeepBackupV2 as i, type KeepCollectionMeta as j, type KeepItemMetadataRefresher as k, type KeepItemResolver as l, type KeepItemRevalidationRecord as m, type KeepItemRevalidationResult as n, type KeepItemRevalidationSummary as o, type KeepItemRevalidator as p, type KeepNavigationState as q, type KeepRediscoveryOptions as r, type KeepRediscoveryStrategy as s, KeepStore as t, type KeepStoreActions as u, type KeepStoreState as v, type KeepUrlParamNames as w, type KeepUrlState as x, type KeepUrlSyncOptions as y, createInboxQuery as z };
|
|
@@ -3,6 +3,19 @@ type SyncScope = {
|
|
|
3
3
|
userId?: string;
|
|
4
4
|
tenantId?: string;
|
|
5
5
|
};
|
|
6
|
+
type KeepCollectionDefinition = {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
scope?: SyncScope;
|
|
10
|
+
};
|
|
11
|
+
/** A course-specific membership; the same item may have memberships in several collections. */
|
|
12
|
+
type KeepCollectionMembership = {
|
|
13
|
+
collectionId: string;
|
|
14
|
+
itemId: string;
|
|
15
|
+
/** Zero-based order within this collection. */
|
|
16
|
+
order: number;
|
|
17
|
+
scope?: SyncScope;
|
|
18
|
+
};
|
|
6
19
|
type KeepItem<TMeta = Record<string, unknown>> = {
|
|
7
20
|
id: string;
|
|
8
21
|
savedAt: number;
|
|
@@ -47,6 +60,15 @@ type KeepItemInput<TMeta = Record<string, unknown>> = {
|
|
|
47
60
|
};
|
|
48
61
|
interface StorageAdapter<TMeta = Record<string, unknown>> {
|
|
49
62
|
getAll(): Promise<KeepItem<TMeta>[]>;
|
|
63
|
+
/** Optional local collection metadata; independent of saved items and item backups. */
|
|
64
|
+
getCollections?(): Promise<KeepCollectionDefinition[]>;
|
|
65
|
+
/** Upsert by collection ID within the provided scope. */
|
|
66
|
+
setCollection?(collection: KeepCollectionDefinition): Promise<void>;
|
|
67
|
+
removeCollection?(id: string, scope?: SyncScope): Promise<void>;
|
|
68
|
+
getCollectionMemberships?(): Promise<KeepCollectionMembership[]>;
|
|
69
|
+
/** Upsert by collection ID and item ID within the provided scope. */
|
|
70
|
+
setCollectionMembership?(membership: KeepCollectionMembership): Promise<void>;
|
|
71
|
+
removeCollectionMembership?(collectionId: string, itemId: string, scope?: SyncScope): Promise<void>;
|
|
50
72
|
set(item: KeepItem<TMeta>): Promise<void>;
|
|
51
73
|
setMany?(items: KeepItem<TMeta>[]): Promise<void>;
|
|
52
74
|
remove(id: string): Promise<void>;
|
|
@@ -120,13 +142,27 @@ type KeepSyncState<TMeta = Record<string, unknown>> = {
|
|
|
120
142
|
type SyncOperation<TMeta = Record<string, unknown>> = {
|
|
121
143
|
operationId: string;
|
|
122
144
|
type: "upsert" | "remove";
|
|
145
|
+
/** Collection operations use a separate driver hook while sharing the durable queue format. */
|
|
146
|
+
entity?: "item" | "collection";
|
|
123
147
|
id: string;
|
|
124
148
|
item?: KeepItem<TMeta>;
|
|
149
|
+
collection?: KeepCollectionDefinition;
|
|
125
150
|
createdAt: number;
|
|
126
151
|
baseRevision?: string;
|
|
127
152
|
attempts?: number;
|
|
128
153
|
scope?: SyncScope;
|
|
129
154
|
};
|
|
155
|
+
type KeepCollectionSyncOperation = {
|
|
156
|
+
operationId: string;
|
|
157
|
+
type: "upsert" | "remove";
|
|
158
|
+
entity: "collection";
|
|
159
|
+
id: string;
|
|
160
|
+
collection?: KeepCollectionDefinition;
|
|
161
|
+
createdAt: number;
|
|
162
|
+
attempts?: number;
|
|
163
|
+
scope?: SyncScope;
|
|
164
|
+
};
|
|
165
|
+
type KeepSyncQueueOperation<TMeta = Record<string, unknown>> = SyncOperation<TMeta>;
|
|
130
166
|
type KeepSyncAuthStatus = 401 | 403;
|
|
131
167
|
/** Indicates that a sync request needs the host application to re-authenticate. */
|
|
132
168
|
declare class KeepSyncAuthError<TMeta = Record<string, unknown>> extends Error {
|
|
@@ -158,10 +194,14 @@ type KeepConflictResolver<TMeta = Record<string, unknown>> = (local: KeepItem<TM
|
|
|
158
194
|
interface RemoteSyncDriver<TMeta = Record<string, unknown>> {
|
|
159
195
|
push(operation: SyncOperation<TMeta>): Promise<RemoteSyncResult<TMeta>>;
|
|
160
196
|
pull?: () => Promise<KeepItem<TMeta>[]>;
|
|
197
|
+
/** Push collection operations through the same scoped, durable queue as item operations. */
|
|
198
|
+
pushCollection?(operation: KeepCollectionSyncOperation): Promise<void>;
|
|
199
|
+
/** Return the complete collection snapshot for the active authenticated scope. */
|
|
200
|
+
pullCollections?: () => Promise<KeepCollectionDefinition[]>;
|
|
161
201
|
}
|
|
162
202
|
interface SyncQueueAdapter<TMeta = Record<string, unknown>> {
|
|
163
|
-
getAll(): Promise<
|
|
164
|
-
setMany(operations:
|
|
203
|
+
getAll(): Promise<KeepSyncQueueOperation<TMeta>[]>;
|
|
204
|
+
setMany(operations: KeepSyncQueueOperation<TMeta>[]): Promise<void>;
|
|
165
205
|
remove(operationIds: string[]): Promise<void>;
|
|
166
206
|
clear(): Promise<void>;
|
|
167
207
|
}
|
|
@@ -228,4 +268,4 @@ type KeepUndoState = {
|
|
|
228
268
|
};
|
|
229
269
|
declare function normalizeKeepTags(tags?: string[]): string[] | undefined;
|
|
230
270
|
|
|
231
|
-
export {
|
|
271
|
+
export { KeepStorageAccessError as A, KeepStorageError as B, type KeepStorageOperation as C, KeepStorageParseError as D, KeepStorageQuotaError as E, type KeepSyncAuthStatus as F, type KeepSyncConflict as G, type KeepSyncResolution as H, type KeepSyncState as I, type KeepSyncStatus as J, type KeepCollectionDefinition as K, isKeepSyncAuthError as L, normalizeKeepTags as M, type RemoteSyncDriver as R, type SyncScope as S, type StorageAdapter as a, type KeepCollectionMembership as b, type KeepItem as c, type SyncQueueAdapter as d, type KeepSyncQueueOperation as e, type KeepItemStatus as f, type KeepSchema as g, type KeepInvalidItemPolicy as h, type KeepChangeContext as i, type KeepUndoState as j, type KeepPluginContext as k, type KeepPlugin as l, type SyncOperation as m, type KeepCollectionSyncOperation as n, type SyncCapableStorageAdapter as o, type RemoteSyncResult as p, KeepSyncAuthError as q, type KeepAction as r, type KeepChangePhase as s, type KeepConflictContext as t, type KeepConflictResolver as u, type KeepErrorContext as v, type KeepErrorHandler as w, type KeepEventHandlers as x, type KeepItemInput as y, type KeepSchemaParseResult as z };
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
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 organization?: {\n collection?: \"assigned\" | \"unassigned\";\n tags?: \"assigned\" | \"unassigned\";\n note?: \"assigned\" | \"unassigned\";\n };\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\n/** Build the default Inbox query: active items without a collection. */\nexport function createInboxQuery<TMeta = Record<string, unknown>>(\n options: { organization?: KeepListQuery<TMeta>[\"organization\"] } = {},\n): KeepListQuery<TMeta> {\n return { organization: { collection: \"unassigned\", ...options.organization } };\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 matchesOrganization(item, query.organization) &&\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 matchesOrganization<TMeta>(\n item: KeepItem<TMeta>,\n organization: KeepListQuery<TMeta>[\"organization\"],\n): boolean {\n if (organization?.collection === \"assigned\" && !item.collectionId?.trim()) return false;\n if (organization?.collection === \"unassigned\" && item.collectionId?.trim()) return false;\n if (organization?.tags === \"assigned\" && !item.tags?.some((tag) => tag.trim())) return false;\n if (organization?.tags === \"unassigned\" && item.tags?.some((tag) => tag.trim())) return false;\n if (organization?.note === \"assigned\" && !item.note?.trim()) return false;\n if (organization?.note === \"unassigned\" && item.note?.trim()) return false;\n return true;\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 const lastActivityAt = item.lastOpenedAt ?? item.savedAt;\n if (lastActivityAt > 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 archiveBatch: (ids: string[]) => Promise<void>;\n unarchiveBatch: (ids: string[]) => Promise<void>;\n pinBatch: (ids: string[]) => Promise<void>;\n unpinBatch: (ids: string[]) => Promise<void>;\n moveToCollectionBatch: (ids: 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;;;AClGO,SAAS,iBACd,UAAmE,CAAC,GAC9C;AACtB,SAAO,EAAE,cAAc,EAAE,YAAY,cAAc,GAAG,QAAQ,aAAa,EAAE;AAC/E;AAEA,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,oBAAoB,MAAM,MAAM,YAAY,KAC5C,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,oBACP,MACA,cACS;AACT,MAAI,cAAc,eAAe,cAAc,CAAC,KAAK,cAAc,KAAK,EAAG,QAAO;AAClF,MAAI,cAAc,eAAe,gBAAgB,KAAK,cAAc,KAAK,EAAG,QAAO;AACnF,MAAI,cAAc,SAAS,cAAc,CAAC,KAAK,MAAM,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAG,QAAO;AACvF,MAAI,cAAc,SAAS,gBAAgB,KAAK,MAAM,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAG,QAAO;AACxF,MAAI,cAAc,SAAS,cAAc,CAAC,KAAK,MAAM,KAAK,EAAG,QAAO;AACpE,MAAI,cAAc,SAAS,gBAAgB,KAAK,MAAM,KAAK,EAAG,QAAO;AACrE,SAAO;AACT;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,UAAM,iBAAiB,KAAK,gBAAgB,KAAK;AACjD,QAAI,iBAAiB,OAAQ,QAAO;AAAA,EACtC;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;;;AChLO,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;;;AC5FO,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"]}
|