@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/dist/core.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  reconcileKeepItems,
20
20
  reorderKeepItems,
21
21
  revalidateKeepItems
22
- } from "./chunk-IIGN4U7N.js";
22
+ } from "./chunk-AUNFZU3A.js";
23
23
  import {
24
24
  KeepSchemaValidationError,
25
25
  parseKeepMeta,
@@ -53,7 +53,273 @@ import {
53
53
  isKeepSyncAuthError,
54
54
  isSameKeepScope,
55
55
  normalizeKeepTags
56
- } from "./chunk-MZFZQIM5.js";
56
+ } from "./chunk-NZLAW4LY.js";
57
+
58
+ // src/features/items/activity.ts
59
+ var DEFAULT_KEEP_HISTORY_KEY = "keepkit:view-history";
60
+ var DEFAULT_KEEP_VIEWING_RECORDS_KEY = "keepkit:viewing-records";
61
+ var DEFAULT_KEEP_HISTORY_LIMIT = 100;
62
+ var LocalStorageKeepHistoryStorage = class {
63
+ constructor(options = {}) {
64
+ this.key = options.key ?? DEFAULT_KEEP_HISTORY_KEY;
65
+ this.limitKey = `${this.key}:limit`;
66
+ this.storage = options.storage ?? getBrowserStorage();
67
+ this.initialLimit = normalizeLimit(options.maxEntries ?? DEFAULT_KEEP_HISTORY_LIMIT);
68
+ this.now = options.now ?? Date.now;
69
+ }
70
+ async getAll() {
71
+ return (await this.read(this.key, isHistoryEntryArray, "history")).sort(
72
+ (left, right) => right.lastViewedAt - left.lastViewedAt
73
+ );
74
+ }
75
+ async getLimit() {
76
+ if (!this.storage) return this.initialLimit;
77
+ const raw = this.readRaw(this.limitKey, "history-limit");
78
+ if (raw === null) return this.initialLimit;
79
+ const parsed = parseJson(raw, this.limitKey, "history-limit");
80
+ if (typeof parsed !== "number" || !Number.isInteger(parsed) || parsed < 1) {
81
+ throw new KeepActivityStorageError("KeepKit history limit is invalid.", this.limitKey);
82
+ }
83
+ return parsed;
84
+ }
85
+ async setLimit(limit) {
86
+ const normalized = normalizeLimit(limit);
87
+ this.writeRaw(this.limitKey, JSON.stringify(normalized), "history-limit");
88
+ const entries = await this.getAll();
89
+ await this.writeEntries(entries.slice(0, normalized));
90
+ }
91
+ async record(itemId, viewedAt = this.now()) {
92
+ const normalizedId = normalizeId(itemId);
93
+ assertTimestamp(viewedAt);
94
+ const entries = await this.getAll();
95
+ const previous = entries.find((entry) => entry.itemId === normalizedId);
96
+ const next = [
97
+ { itemId: normalizedId, lastViewedAt: Math.max(previous?.lastViewedAt ?? 0, viewedAt) },
98
+ ...entries.filter((entry) => entry.itemId !== normalizedId)
99
+ ].sort((left, right) => right.lastViewedAt - left.lastViewedAt).slice(0, await this.getLimit());
100
+ await this.writeEntries(next);
101
+ return cloneHistoryEntries(next);
102
+ }
103
+ async remove(itemId) {
104
+ const normalizedId = normalizeId(itemId);
105
+ await this.writeEntries((await this.getAll()).filter((entry) => entry.itemId !== normalizedId));
106
+ }
107
+ async clear() {
108
+ this.writeRaw(this.key, "[]", "history");
109
+ }
110
+ async writeEntries(entries) {
111
+ this.writeRaw(this.key, JSON.stringify(entries), "history");
112
+ }
113
+ async read(key, validate, label) {
114
+ const raw = this.readRaw(key, label);
115
+ if (raw === null) return [];
116
+ const value = parseJson(raw, key, label);
117
+ if (!validate(value)) throw new KeepActivityStorageError(`KeepKit ${label} data is invalid.`, key);
118
+ return value;
119
+ }
120
+ readRaw(key, label) {
121
+ try {
122
+ return this.storage?.getItem(key) ?? null;
123
+ } catch (cause) {
124
+ throw new KeepActivityStorageError(`KeepKit could not read ${label} data.`, key, cause);
125
+ }
126
+ }
127
+ writeRaw(key, value, label) {
128
+ try {
129
+ this.storage?.setItem(key, value);
130
+ } catch (cause) {
131
+ throw new KeepActivityStorageError(`KeepKit could not write ${label} data.`, key, cause);
132
+ }
133
+ }
134
+ };
135
+ var LocalStorageKeepViewingRecordStorage = class {
136
+ constructor(options = {}) {
137
+ this.key = options.key ?? DEFAULT_KEEP_VIEWING_RECORDS_KEY;
138
+ this.storage = options.storage ?? getBrowserStorage();
139
+ this.now = options.now ?? Date.now;
140
+ this.createId = options.createId ?? createRecordId;
141
+ }
142
+ async getAll(itemId) {
143
+ const records = await this.readRecords();
144
+ const filtered = itemId === void 0 ? records : records.filter((record) => record.itemId === itemId);
145
+ return filtered.sort((left, right) => right.viewedAt - left.viewedAt).map((record) => ({ ...record }));
146
+ }
147
+ async set(record) {
148
+ const normalized = normalizeViewingRecord(record);
149
+ const records = await this.readRecords();
150
+ this.writeRecords([...records.filter((entry) => entry.id !== normalized.id), normalized]);
151
+ }
152
+ async add(itemId, options = {}) {
153
+ const record = {
154
+ id: this.createId(),
155
+ itemId: normalizeId(itemId),
156
+ viewedAt: options.viewedAt ?? this.now(),
157
+ ...options.note?.trim() ? { note: options.note.trim() } : {}
158
+ };
159
+ await this.set(record);
160
+ return { ...record };
161
+ }
162
+ async remove(id) {
163
+ this.writeRecords((await this.readRecords()).filter((record) => record.id !== id));
164
+ }
165
+ async removeForItem(itemId) {
166
+ const normalizedId = normalizeId(itemId);
167
+ this.writeRecords((await this.readRecords()).filter((record) => record.itemId !== normalizedId));
168
+ }
169
+ async clear() {
170
+ this.writeRecords([]);
171
+ }
172
+ async readRecords() {
173
+ const raw = this.readRaw();
174
+ if (raw === null) return [];
175
+ const value = parseJson(raw, this.key, "viewing records");
176
+ if (!isViewingRecordArray(value)) {
177
+ throw new KeepActivityStorageError("KeepKit viewing record data is invalid.", this.key);
178
+ }
179
+ return value;
180
+ }
181
+ readRaw() {
182
+ try {
183
+ return this.storage?.getItem(this.key) ?? null;
184
+ } catch (cause) {
185
+ throw new KeepActivityStorageError("KeepKit could not read viewing records.", this.key, cause);
186
+ }
187
+ }
188
+ writeRecords(records) {
189
+ try {
190
+ this.storage?.setItem(this.key, JSON.stringify(records));
191
+ } catch (cause) {
192
+ throw new KeepActivityStorageError("KeepKit could not write viewing records.", this.key, cause);
193
+ }
194
+ }
195
+ };
196
+ var KeepActivityStorageError = class extends Error {
197
+ constructor(message, storageKey, cause) {
198
+ super(message);
199
+ this.name = "KeepActivityStorageError";
200
+ this.storageKey = storageKey;
201
+ this.cause = cause;
202
+ }
203
+ };
204
+ function isHistoryEntryArray(value) {
205
+ return Array.isArray(value) && value.every(
206
+ (entry) => isRecord(entry) && typeof entry.itemId === "string" && entry.itemId.length > 0 && typeof entry.lastViewedAt === "number" && Number.isFinite(entry.lastViewedAt)
207
+ );
208
+ }
209
+ function isViewingRecordArray(value) {
210
+ return Array.isArray(value) && value.every(isViewingRecord);
211
+ }
212
+ function isViewingRecord(value) {
213
+ return isRecord(value) && typeof value.id === "string" && value.id.length > 0 && typeof value.itemId === "string" && value.itemId.length > 0 && typeof value.viewedAt === "number" && Number.isFinite(value.viewedAt) && value.viewedAt >= 0 && (value.note === void 0 || typeof value.note === "string");
214
+ }
215
+ function normalizeViewingRecord(record) {
216
+ const normalized = {
217
+ id: normalizeId(record.id),
218
+ itemId: normalizeId(record.itemId),
219
+ viewedAt: record.viewedAt,
220
+ ...record.note?.trim() ? { note: record.note.trim() } : {}
221
+ };
222
+ assertTimestamp(normalized.viewedAt);
223
+ return normalized;
224
+ }
225
+ function normalizeId(value) {
226
+ const normalized = value.trim();
227
+ if (!normalized) throw new TypeError("KeepKit item ids must not be empty.");
228
+ return normalized;
229
+ }
230
+ function normalizeLimit(value) {
231
+ if (!Number.isInteger(value) || value < 1) throw new RangeError("KeepKit history limit must be a positive integer.");
232
+ return value;
233
+ }
234
+ function assertTimestamp(value) {
235
+ if (!Number.isFinite(value) || value < 0) throw new TypeError("KeepKit timestamps must be non-negative numbers.");
236
+ }
237
+ function cloneHistoryEntries(entries) {
238
+ return entries.map((entry) => ({ ...entry }));
239
+ }
240
+ function parseJson(raw, key, label) {
241
+ try {
242
+ return JSON.parse(raw);
243
+ } catch (cause) {
244
+ throw new KeepActivityStorageError(`KeepKit ${label} data is not valid JSON.`, key, cause);
245
+ }
246
+ }
247
+ function isRecord(value) {
248
+ return typeof value === "object" && value !== null && !Array.isArray(value);
249
+ }
250
+ function getBrowserStorage() {
251
+ if (typeof window === "undefined") return void 0;
252
+ try {
253
+ return window.localStorage;
254
+ } catch {
255
+ return void 0;
256
+ }
257
+ }
258
+ function createRecordId() {
259
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
260
+ return `keepkit-view-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
261
+ }
262
+
263
+ // src/features/items/collections.ts
264
+ async function getKeepCollectionItems(storage, collectionId) {
265
+ const memberships = await requireMemberships(storage);
266
+ const items = await storage.getAll();
267
+ const itemsById = new Map(items.map((item) => [item.id, item]));
268
+ return memberships.filter((membership) => membership.collectionId === collectionId).sort((left, right) => left.order - right.order).flatMap((membership) => {
269
+ const item = itemsById.get(membership.itemId);
270
+ return item ? [item] : [];
271
+ });
272
+ }
273
+ async function addKeepItemToCollection(storage, collectionId, itemId, order) {
274
+ if (!(await storage.getAll()).some((item) => item.id === itemId)) {
275
+ throw new Error(`KeepKit cannot add missing item "${itemId}" to a collection.`);
276
+ }
277
+ const collectionMemberships = (await requireMemberships(storage)).filter((membership) => membership.collectionId === collectionId).filter((membership) => membership.itemId !== itemId).sort((left, right) => left.order - right.order);
278
+ const insertionIndex = order ?? collectionMemberships.length;
279
+ if (!Number.isInteger(insertionIndex) || insertionIndex < 0) {
280
+ throw new RangeError("Collection order must be a non-negative integer.");
281
+ }
282
+ collectionMemberships.splice(Math.min(insertionIndex, collectionMemberships.length), 0, {
283
+ collectionId,
284
+ itemId,
285
+ order: insertionIndex
286
+ });
287
+ const reordered = collectionMemberships.map((membership, index) => ({ ...membership, order: index }));
288
+ for (const membership of reordered) await storage.setCollectionMembership?.(membership);
289
+ const added = reordered.find((membership) => membership.itemId === itemId);
290
+ if (!added) throw new Error("KeepKit failed to add the collection membership.");
291
+ return added;
292
+ }
293
+ async function removeKeepItemFromCollection(storage, collectionId, itemId) {
294
+ const memberships = await requireMemberships(storage);
295
+ await storage.removeCollectionMembership?.(collectionId, itemId);
296
+ const remaining = memberships.filter((membership) => membership.collectionId === collectionId && membership.itemId !== itemId).sort((left, right) => left.order - right.order).map((membership, order) => ({ ...membership, order }));
297
+ for (const membership of remaining) await storage.setCollectionMembership?.(membership);
298
+ }
299
+ async function reorderKeepCollectionItems(storage, collectionId, itemIds) {
300
+ const allMemberships = await requireMemberships(storage);
301
+ const current = allMemberships.filter((membership) => membership.collectionId === collectionId).sort((left, right) => left.order - right.order);
302
+ const currentIds = new Set(current.map((membership) => membership.itemId));
303
+ const orderedIds = [...itemIds.filter((id, index) => currentIds.has(id) && itemIds.indexOf(id) === index)];
304
+ for (const membership of current) {
305
+ if (!orderedIds.includes(membership.itemId)) orderedIds.push(membership.itemId);
306
+ }
307
+ const currentByItemId = new Map(current.map((membership) => [membership.itemId, membership]));
308
+ const reordered = orderedIds.map((itemId, order) => ({
309
+ ...currentByItemId.get(itemId) ?? {},
310
+ collectionId,
311
+ itemId,
312
+ order
313
+ }));
314
+ for (const membership of reordered) await storage.setCollectionMembership?.(membership);
315
+ return reordered;
316
+ }
317
+ async function requireMemberships(storage) {
318
+ if (!storage.getCollectionMemberships || !storage.setCollectionMembership || !storage.removeCollectionMembership) {
319
+ throw new Error("KeepKit storage adapter does not support collection memberships.");
320
+ }
321
+ return storage.getCollectionMemberships();
322
+ }
57
323
 
58
324
  // src/features/items/presets.ts
59
325
  function createKeepKitPreset(options = {}) {
@@ -82,6 +348,157 @@ function createKeepKitPreset(options = {}) {
82
348
  }
83
349
  var createKeepKitSetup = createKeepKitPreset;
84
350
 
351
+ // src/features/items/progress.ts
352
+ var DEFAULT_KEEP_PROGRESS_KEY = "keepkit:progress";
353
+ var LocalStorageKeepProgressStorage = class {
354
+ constructor(options = {}) {
355
+ this.key = options.key ?? DEFAULT_KEEP_PROGRESS_KEY;
356
+ this.storage = options.storage ?? getBrowserStorage2();
357
+ this.now = options.now ?? Date.now;
358
+ }
359
+ async getAll() {
360
+ const raw = this.readRaw();
361
+ if (raw === null) return [];
362
+ let value;
363
+ try {
364
+ value = JSON.parse(raw);
365
+ } catch (cause) {
366
+ throw new KeepProgressStorageError("KeepKit progress data is not valid JSON.", this.key, cause);
367
+ }
368
+ if (!Array.isArray(value) || !value.every(isProgressRecord)) {
369
+ throw new KeepProgressStorageError("KeepKit progress data is invalid.", this.key);
370
+ }
371
+ return value.map((record) => ({ ...record }));
372
+ }
373
+ async getCourse(courseId) {
374
+ const id = normalizeId2(courseId, "course");
375
+ const record = (await this.getAll()).find((entry) => entry.kind === "course" && entry.courseId === id);
376
+ return record?.kind === "course" ? record : void 0;
377
+ }
378
+ async getItem(itemId, compatibility) {
379
+ const id = normalizeId2(itemId, "item");
380
+ const record = (await this.getAll()).find((entry) => entry.kind === "item" && entry.itemId === id);
381
+ if (record?.kind !== "item") return void 0;
382
+ if (!isProgressCompatible(record, compatibility)) return void 0;
383
+ return record;
384
+ }
385
+ async saveCourse(courseId, currentItemId) {
386
+ const record = {
387
+ kind: "course",
388
+ courseId: normalizeId2(courseId, "course"),
389
+ ...currentItemId?.trim() ? { currentItemId: currentItemId.trim() } : {},
390
+ updatedAt: this.now()
391
+ };
392
+ await this.set(record);
393
+ return record;
394
+ }
395
+ async saveItem(itemId, progress) {
396
+ const record = {
397
+ kind: "item",
398
+ itemId: normalizeId2(itemId, "item"),
399
+ ...progress,
400
+ updatedAt: this.now()
401
+ };
402
+ await this.set(record);
403
+ return record;
404
+ }
405
+ async set(record) {
406
+ const normalized = normalizeProgressRecord(record);
407
+ const records = await this.getAll();
408
+ const identity = getProgressIdentity(normalized);
409
+ this.writeRecords([...records.filter((entry) => getProgressIdentity(entry) !== identity), normalized]);
410
+ }
411
+ async resetCourse(courseId) {
412
+ const id = normalizeId2(courseId, "course");
413
+ this.writeRecords((await this.getAll()).filter((entry) => entry.kind !== "course" || entry.courseId !== id));
414
+ }
415
+ async resetItem(itemId) {
416
+ const id = normalizeId2(itemId, "item");
417
+ this.writeRecords((await this.getAll()).filter((entry) => entry.kind !== "item" || entry.itemId !== id));
418
+ }
419
+ async clear() {
420
+ this.writeRecords([]);
421
+ }
422
+ readRaw() {
423
+ try {
424
+ return this.storage?.getItem(this.key) ?? null;
425
+ } catch (cause) {
426
+ throw new KeepProgressStorageError("KeepKit could not read progress data.", this.key, cause);
427
+ }
428
+ }
429
+ writeRecords(records) {
430
+ try {
431
+ this.storage?.setItem(this.key, JSON.stringify(records));
432
+ } catch (cause) {
433
+ throw new KeepProgressStorageError("KeepKit could not write progress data.", this.key, cause);
434
+ }
435
+ }
436
+ };
437
+ function isProgressCompatible(record, compatibility) {
438
+ if (record.language !== void 0 && record.language !== compatibility?.language) return false;
439
+ if (record.contentVersion !== void 0 && record.contentVersion !== compatibility?.contentVersion) return false;
440
+ if (compatibility?.language !== void 0 && record.language !== compatibility.language) return false;
441
+ if (compatibility?.contentVersion !== void 0 && record.contentVersion !== compatibility.contentVersion)
442
+ return false;
443
+ return true;
444
+ }
445
+ var KeepProgressStorageError = class extends Error {
446
+ constructor(message, storageKey, cause) {
447
+ super(message);
448
+ this.name = "KeepProgressStorageError";
449
+ this.storageKey = storageKey;
450
+ this.cause = cause;
451
+ }
452
+ };
453
+ function isProgressRecord(value) {
454
+ if (!isRecord2(value) || typeof value.updatedAt !== "number" || !Number.isFinite(value.updatedAt) || value.updatedAt < 0)
455
+ return false;
456
+ if (value.kind === "course") {
457
+ return typeof value.courseId === "string" && value.courseId.length > 0 && (value.currentItemId === void 0 || typeof value.currentItemId === "string");
458
+ }
459
+ if (value.kind !== "item") return false;
460
+ return typeof value.itemId === "string" && value.itemId.length > 0 && (value.audioPositionMs === void 0 || typeof value.audioPositionMs === "number" && Number.isFinite(value.audioPositionMs) && value.audioPositionMs >= 0) && (value.readingPosition === void 0 || typeof value.readingPosition === "number" && Number.isFinite(value.readingPosition) && value.readingPosition >= 0) && (value.language === void 0 || typeof value.language === "string") && (value.contentVersion === void 0 || typeof value.contentVersion === "string");
461
+ }
462
+ function normalizeProgressRecord(record) {
463
+ if (!isProgressRecord(record)) throw new TypeError("KeepKit progress record is invalid.");
464
+ if (record.kind === "course") {
465
+ return {
466
+ kind: "course",
467
+ courseId: normalizeId2(record.courseId, "course"),
468
+ ...record.currentItemId?.trim() ? { currentItemId: record.currentItemId.trim() } : {},
469
+ updatedAt: record.updatedAt
470
+ };
471
+ }
472
+ return {
473
+ kind: "item",
474
+ itemId: normalizeId2(record.itemId, "item"),
475
+ ...record.audioPositionMs !== void 0 ? { audioPositionMs: record.audioPositionMs } : {},
476
+ ...record.readingPosition !== void 0 ? { readingPosition: record.readingPosition } : {},
477
+ ...record.language !== void 0 ? { language: record.language } : {},
478
+ ...record.contentVersion !== void 0 ? { contentVersion: record.contentVersion } : {},
479
+ updatedAt: record.updatedAt
480
+ };
481
+ }
482
+ function getProgressIdentity(record) {
483
+ return record.kind === "course" ? `course:${record.courseId}` : `item:${record.itemId}`;
484
+ }
485
+ function normalizeId2(value, kind) {
486
+ const normalized = value.trim();
487
+ if (!normalized) throw new TypeError(`KeepKit ${kind} ids must not be empty.`);
488
+ return normalized;
489
+ }
490
+ function isRecord2(value) {
491
+ return typeof value === "object" && value !== null && !Array.isArray(value);
492
+ }
493
+ function getBrowserStorage2() {
494
+ if (typeof window === "undefined") return void 0;
495
+ try {
496
+ return window.localStorage;
497
+ } catch {
498
+ return void 0;
499
+ }
500
+ }
501
+
85
502
  // src/features/items/saved-views.ts
86
503
  var DEFAULT_SAVED_VIEWS_STORAGE_KEY = "keepkit:saved-views";
87
504
  var LocalStorageKeepSavedViewStorage = class {
@@ -149,13 +566,13 @@ function isKeepListQuery(value) {
149
566
  }
150
567
  if (query.pinnedFirst !== void 0 && typeof query.pinnedFirst !== "boolean") return false;
151
568
  if (query.sort !== void 0) {
152
- if (!isRecord(query.sort) || !["savedAt", "updatedAt", "lastOpenedAt"].includes(String(query.sort.by)))
569
+ if (!isRecord3(query.sort) || !["savedAt", "updatedAt", "lastOpenedAt"].includes(String(query.sort.by)))
153
570
  return false;
154
571
  if (query.sort.direction !== void 0 && query.sort.direction !== "asc" && query.sort.direction !== "desc")
155
572
  return false;
156
573
  }
157
574
  if (query.search !== void 0) {
158
- if (!isRecord(query.search)) return false;
575
+ if (!isRecord3(query.search)) return false;
159
576
  if (query.search.query !== void 0 && typeof query.search.query !== "string") return false;
160
577
  if (query.search.mode !== void 0 && query.search.mode !== "and" && query.search.mode !== "or") return false;
161
578
  if (query.search.tokenize !== void 0 && typeof query.search.tokenize !== "boolean") return false;
@@ -164,7 +581,7 @@ function isKeepListQuery(value) {
164
581
  }
165
582
  }
166
583
  if (query.activity !== void 0) {
167
- if (!isRecord(query.activity)) return false;
584
+ if (!isRecord3(query.activity)) return false;
168
585
  if (query.activity.opened !== void 0 && query.activity.opened !== "ever" && query.activity.opened !== "never") {
169
586
  return false;
170
587
  }
@@ -178,7 +595,7 @@ function isKeepListQuery(value) {
178
595
  return false;
179
596
  }
180
597
  if (query.pagination !== void 0) {
181
- if (!isRecord(query.pagination) || [query.pagination.page, query.pagination.pageSize].some(isInvalidNumber))
598
+ if (!isRecord3(query.pagination) || [query.pagination.page, query.pagination.pageSize].some(isInvalidNumber))
182
599
  return false;
183
600
  }
184
601
  const organization = query.organization;
@@ -193,7 +610,7 @@ function isKeepListQuery(value) {
193
610
  }
194
611
  return true;
195
612
  }
196
- function isRecord(value) {
613
+ function isRecord3(value) {
197
614
  return typeof value === "object" && value !== null && !Array.isArray(value);
198
615
  }
199
616
  function isInvalidNumber(value) {
@@ -397,6 +814,34 @@ var AuthenticatedSyncStorageController = class {
397
814
  this.currentScope = options.scope;
398
815
  this.current = this.createAdapter(this.currentScope);
399
816
  this.attach(this.current);
817
+ if (this.current.getCollections && this.current.setCollection && this.current.removeCollection) {
818
+ this.getCollections = async () => {
819
+ await this.ensureScope();
820
+ return this.current.getCollections?.() ?? [];
821
+ };
822
+ this.setCollection = async (collection) => {
823
+ await this.ensureScope();
824
+ await this.current.setCollection?.(collection);
825
+ };
826
+ this.removeCollection = async (id) => {
827
+ await this.ensureScope();
828
+ await this.current.removeCollection?.(id);
829
+ };
830
+ }
831
+ if (this.current.getCollectionMemberships && this.current.setCollectionMembership && this.current.removeCollectionMembership) {
832
+ this.getCollectionMemberships = async () => {
833
+ await this.ensureScope();
834
+ return this.current.getCollectionMemberships?.() ?? [];
835
+ };
836
+ this.setCollectionMembership = async (membership) => {
837
+ await this.ensureScope();
838
+ await this.current.setCollectionMembership?.(membership);
839
+ };
840
+ this.removeCollectionMembership = async (collectionId, itemId) => {
841
+ await this.ensureScope();
842
+ await this.current.removeCollectionMembership?.(collectionId, itemId);
843
+ };
844
+ }
400
845
  }
401
846
  get storageKey() {
402
847
  return this.current.storageKey;
@@ -523,6 +968,7 @@ var AuthenticatedSyncStorageController = class {
523
968
  };
524
969
  function createAuthenticatedRemote(options, scope) {
525
970
  const pull = options.transport.pull;
971
+ const pullCollections = options.transport.pullCollections;
526
972
  return {
527
973
  push: async (operation) => {
528
974
  try {
@@ -539,6 +985,22 @@ function createAuthenticatedRemote(options, scope) {
539
985
  } catch (cause) {
540
986
  return handleAuthFailure(cause, options, { scope });
541
987
  }
988
+ } : void 0,
989
+ pushCollection: options.transport.pushCollection ? async (collectionOperation) => {
990
+ try {
991
+ const token = await options.getAuthToken();
992
+ await options.transport.pushCollection?.(collectionOperation, { token, scope, collectionOperation });
993
+ } catch (cause) {
994
+ return handleAuthFailure(cause, options, { collectionOperation, scope });
995
+ }
996
+ } : void 0,
997
+ pullCollections: pullCollections ? async () => {
998
+ try {
999
+ const token = await options.getAuthToken();
1000
+ return await pullCollections({ token, scope });
1001
+ } catch (cause) {
1002
+ return handleAuthFailure(cause, options, { scope });
1003
+ }
542
1004
  } : void 0
543
1005
  };
544
1006
  }
@@ -561,7 +1023,11 @@ function getAuthStatus(error) {
561
1023
  export {
562
1024
  DEFAULT_INDEXEDDB_DATABASE,
563
1025
  DEFAULT_INDEXEDDB_STORE,
1026
+ DEFAULT_KEEP_HISTORY_KEY,
1027
+ DEFAULT_KEEP_HISTORY_LIMIT,
1028
+ DEFAULT_KEEP_PROGRESS_KEY,
564
1029
  DEFAULT_KEEP_URL_PARAMS,
1030
+ DEFAULT_KEEP_VIEWING_RECORDS_KEY,
565
1031
  DEFAULT_SAVED_VIEWS_STORAGE_KEY,
566
1032
  DEFAULT_STORAGE_KEY,
567
1033
  DEFAULT_SYNC_QUEUE_DATABASE,
@@ -573,8 +1039,10 @@ export {
573
1039
  IndexedDBSyncQueueAdapter,
574
1040
  KEEP_BACKUP_FORMAT,
575
1041
  KEEP_BACKUP_VERSION,
1042
+ KeepActivityStorageError,
576
1043
  KeepBackupImportError,
577
1044
  KeepBackupParseError,
1045
+ KeepProgressStorageError,
578
1046
  KeepSchemaValidationError,
579
1047
  KeepStorageAccessError,
580
1048
  KeepStorageError,
@@ -583,11 +1051,15 @@ export {
583
1051
  KeepStore,
584
1052
  KeepSyncAuthError,
585
1053
  LocalStorageAdapter,
1054
+ LocalStorageKeepHistoryStorage,
1055
+ LocalStorageKeepProgressStorage,
586
1056
  LocalStorageKeepSavedViewStorage,
1057
+ LocalStorageKeepViewingRecordStorage,
587
1058
  LocalStorageSyncQueueAdapter,
588
1059
  ScopedStorageAdapter,
589
1060
  ScopedSyncQueueAdapter,
590
1061
  SyncStorageAdapter,
1062
+ addKeepItemToCollection,
591
1063
  createAuthenticatedSyncKit,
592
1064
  createBrowserStorageAdapter,
593
1065
  createInboxQuery,
@@ -600,12 +1072,14 @@ export {
600
1072
  decodeKeepListQuery,
601
1073
  encodeKeepListQuery,
602
1074
  exportItems,
1075
+ getKeepCollectionItems,
603
1076
  getKeepNavigationState,
604
1077
  getKeepScopeKey,
605
1078
  getTagCounts,
606
1079
  importItems,
607
1080
  isKeepItemMetadataStale,
608
1081
  isKeepSyncAuthError,
1082
+ isProgressCompatible,
609
1083
  isSameKeepScope,
610
1084
  mergeKeepItems,
611
1085
  mergeKeepListQueryFromUrl,
@@ -616,6 +1090,8 @@ export {
616
1090
  parseKeepMeta,
617
1091
  queryKeepItems,
618
1092
  reconcileKeepItems,
1093
+ removeKeepItemFromCollection,
1094
+ reorderKeepCollectionItems,
619
1095
  reorderKeepItems,
620
1096
  revalidateKeepItems,
621
1097
  serializeKeepListQuery,