@keepkit/core 0.28.4 → 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-Y4U5DEGG.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-2TENUU7B.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) {
@@ -411,6 +828,20 @@ var AuthenticatedSyncStorageController = class {
411
828
  await this.current.removeCollection?.(id);
412
829
  };
413
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
+ }
414
845
  }
415
846
  get storageKey() {
416
847
  return this.current.storageKey;
@@ -537,6 +968,7 @@ var AuthenticatedSyncStorageController = class {
537
968
  };
538
969
  function createAuthenticatedRemote(options, scope) {
539
970
  const pull = options.transport.pull;
971
+ const pullCollections = options.transport.pullCollections;
540
972
  return {
541
973
  push: async (operation) => {
542
974
  try {
@@ -553,6 +985,22 @@ function createAuthenticatedRemote(options, scope) {
553
985
  } catch (cause) {
554
986
  return handleAuthFailure(cause, options, { scope });
555
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
+ }
556
1004
  } : void 0
557
1005
  };
558
1006
  }
@@ -575,7 +1023,11 @@ function getAuthStatus(error) {
575
1023
  export {
576
1024
  DEFAULT_INDEXEDDB_DATABASE,
577
1025
  DEFAULT_INDEXEDDB_STORE,
1026
+ DEFAULT_KEEP_HISTORY_KEY,
1027
+ DEFAULT_KEEP_HISTORY_LIMIT,
1028
+ DEFAULT_KEEP_PROGRESS_KEY,
578
1029
  DEFAULT_KEEP_URL_PARAMS,
1030
+ DEFAULT_KEEP_VIEWING_RECORDS_KEY,
579
1031
  DEFAULT_SAVED_VIEWS_STORAGE_KEY,
580
1032
  DEFAULT_STORAGE_KEY,
581
1033
  DEFAULT_SYNC_QUEUE_DATABASE,
@@ -587,8 +1039,10 @@ export {
587
1039
  IndexedDBSyncQueueAdapter,
588
1040
  KEEP_BACKUP_FORMAT,
589
1041
  KEEP_BACKUP_VERSION,
1042
+ KeepActivityStorageError,
590
1043
  KeepBackupImportError,
591
1044
  KeepBackupParseError,
1045
+ KeepProgressStorageError,
592
1046
  KeepSchemaValidationError,
593
1047
  KeepStorageAccessError,
594
1048
  KeepStorageError,
@@ -597,11 +1051,15 @@ export {
597
1051
  KeepStore,
598
1052
  KeepSyncAuthError,
599
1053
  LocalStorageAdapter,
1054
+ LocalStorageKeepHistoryStorage,
1055
+ LocalStorageKeepProgressStorage,
600
1056
  LocalStorageKeepSavedViewStorage,
1057
+ LocalStorageKeepViewingRecordStorage,
601
1058
  LocalStorageSyncQueueAdapter,
602
1059
  ScopedStorageAdapter,
603
1060
  ScopedSyncQueueAdapter,
604
1061
  SyncStorageAdapter,
1062
+ addKeepItemToCollection,
605
1063
  createAuthenticatedSyncKit,
606
1064
  createBrowserStorageAdapter,
607
1065
  createInboxQuery,
@@ -614,12 +1072,14 @@ export {
614
1072
  decodeKeepListQuery,
615
1073
  encodeKeepListQuery,
616
1074
  exportItems,
1075
+ getKeepCollectionItems,
617
1076
  getKeepNavigationState,
618
1077
  getKeepScopeKey,
619
1078
  getTagCounts,
620
1079
  importItems,
621
1080
  isKeepItemMetadataStale,
622
1081
  isKeepSyncAuthError,
1082
+ isProgressCompatible,
623
1083
  isSameKeepScope,
624
1084
  mergeKeepItems,
625
1085
  mergeKeepListQueryFromUrl,
@@ -630,6 +1090,8 @@ export {
630
1090
  parseKeepMeta,
631
1091
  queryKeepItems,
632
1092
  reconcileKeepItems,
1093
+ removeKeepItemFromCollection,
1094
+ reorderKeepCollectionItems,
633
1095
  reorderKeepItems,
634
1096
  revalidateKeepItems,
635
1097
  serializeKeepListQuery,