@keepkit/core 0.28.2 → 0.28.4

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/react.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  queryKeepItems,
12
12
  reorderKeepItems,
13
13
  revalidateKeepItems
14
- } from "./chunk-JGGKIE3O.js";
14
+ } from "./chunk-Y4U5DEGG.js";
15
15
  import {
16
16
  parseKeepMeta
17
17
  } from "./chunk-5W4QSJHV.js";
@@ -21,7 +21,7 @@ import {
21
21
  normalizeKeepTags,
22
22
  persistKeepItems,
23
23
  removeKeepItems
24
- } from "./chunk-HDML3IDX.js";
24
+ } from "./chunk-2TENUU7B.js";
25
25
 
26
26
  // src/react/components/KeepButton.tsx
27
27
  import {
@@ -267,7 +267,13 @@ function KeepProviderContent({
267
267
  if (needsMigrationPersist) {
268
268
  await persistKeepItems(storage, next);
269
269
  }
270
+ const definitions = storage.getCollections ? await storage.getCollections() : void 0;
270
271
  setItems(next);
272
+ if (definitions) {
273
+ store.setState({
274
+ collections: Object.fromEntries(definitions.map(({ id, name }) => [id, { name }]))
275
+ });
276
+ }
271
277
  store.setState({ error: null });
272
278
  } catch (cause) {
273
279
  reportError(cause, { action: "refresh" });
@@ -292,7 +298,14 @@ function KeepProviderContent({
292
298
  undoRef.current?.timer && clearTimeout(undoRef.current.timer);
293
299
  undoRef.current = void 0;
294
300
  itemsRef.current = [];
295
- store.setState({ items: [], isHydrated: false, isLoading: true, error: null, undo: EMPTY_UNDO_STATE });
301
+ store.setState({
302
+ items: [],
303
+ collections: {},
304
+ isHydrated: false,
305
+ isLoading: true,
306
+ error: null,
307
+ undo: EMPTY_UNDO_STATE
308
+ });
296
309
  void refresh();
297
310
  });
298
311
  }, [refresh, storage, store]);
@@ -454,7 +467,7 @@ function KeepProviderContent({
454
467
  [updateItem]
455
468
  );
456
469
  const recordOpen = useCallback(
457
- (id, openedAt = Date.now()) => updateItem("open", id, (current) => ({ ...current, lastOpenedAt: openedAt, updatedAt: Date.now() })),
470
+ (id, openedAt = Date.now()) => updateItem("open", id, (current) => ({ ...current, lastOpenedAt: openedAt })),
458
471
  [updateItem]
459
472
  );
460
473
  const setArchive = useCallback(
@@ -496,47 +509,124 @@ function KeepProviderContent({
496
509
  },
497
510
  [updateItem]
498
511
  );
512
+ const updateItemsBatch = useCallback(
513
+ (action, ids, update) => {
514
+ const idSet = new Set(ids);
515
+ return runMutation(action, void 0, (previous) => {
516
+ const currentItems = previous.filter((item) => idSet.has(item.id));
517
+ const updatedItems = currentItems.map(update);
518
+ if (updatedItems.length === 0) return void 0;
519
+ const updatedById = new Map(updatedItems.map((item) => [item.id, item]));
520
+ return {
521
+ next: previous.map((item) => updatedById.get(item.id) ?? item),
522
+ persist: async () => {
523
+ try {
524
+ await persistKeepItems(storage, updatedItems);
525
+ } catch (cause) {
526
+ await restoreItems(storage, currentItems);
527
+ throw cause;
528
+ }
529
+ },
530
+ pluginContext: { action, items: updatedItems }
531
+ };
532
+ });
533
+ },
534
+ [runMutation, storage]
535
+ );
536
+ const archiveBatch = useCallback(
537
+ (ids) => updateItemsBatch("archive", ids, (item) => ({ ...item, archived: true, updatedAt: Date.now() })),
538
+ [updateItemsBatch]
539
+ );
540
+ const unarchiveBatch = useCallback(
541
+ (ids) => updateItemsBatch("archive", ids, (item) => ({ ...item, archived: false, updatedAt: Date.now() })),
542
+ [updateItemsBatch]
543
+ );
544
+ const pinBatch = useCallback(
545
+ (ids) => updateItemsBatch("pin", ids, (item) => ({ ...item, pinned: true, updatedAt: Date.now() })),
546
+ [updateItemsBatch]
547
+ );
548
+ const unpinBatch = useCallback(
549
+ (ids) => updateItemsBatch("pin", ids, (item) => ({ ...item, pinned: false, updatedAt: Date.now() })),
550
+ [updateItemsBatch]
551
+ );
552
+ const moveToCollectionBatch = useCallback(
553
+ (ids, collectionId) => {
554
+ const nextCollectionId = collectionId?.trim() || void 0;
555
+ return updateItemsBatch("collection", ids, (item) => {
556
+ const { collectionId: _oldCollectionId, ...withoutCollection } = item;
557
+ return {
558
+ ...withoutCollection,
559
+ ...nextCollectionId ? { collectionId: nextCollectionId } : {},
560
+ updatedAt: Date.now()
561
+ };
562
+ });
563
+ },
564
+ [updateItemsBatch]
565
+ );
499
566
  const createCollection = useCallback(
500
- async (id, name) => {
567
+ (id, name) => enqueueOperation(async () => {
501
568
  const trimmedId = id.trim();
502
569
  const trimmedName = name.trim();
503
570
  if (!trimmedId || !trimmedName) throw new Error("Collection id and name are required.");
504
571
  const current = store.getSnapshot().collections;
505
572
  if (current[trimmedId]) throw new Error(`Collection "${trimmedId}" already exists.`);
573
+ try {
574
+ await storage.setCollection?.({ id: trimmedId, name: trimmedName });
575
+ } catch (cause) {
576
+ reportError(cause, { action: "collection", id: trimmedId });
577
+ throw cause;
578
+ }
506
579
  store.setState({ collections: { ...current, [trimmedId]: { name: trimmedName } } });
507
- },
508
- [store]
580
+ }),
581
+ [enqueueOperation, reportError, storage, store]
509
582
  );
510
583
  const renameCollection = useCallback(
511
- async (id, name) => {
584
+ (id, name) => enqueueOperation(async () => {
512
585
  const trimmedName = name.trim();
513
586
  if (!trimmedName) throw new Error("Collection name is required.");
514
587
  const current = store.getSnapshot().collections;
515
588
  if (!current[id]) throw new Error(`Collection "${id}" does not exist.`);
589
+ try {
590
+ await storage.setCollection?.({ id, name: trimmedName });
591
+ } catch (cause) {
592
+ reportError(cause, { action: "collection", id });
593
+ throw cause;
594
+ }
516
595
  store.setState({ collections: { ...current, [id]: { name: trimmedName } } });
517
- },
518
- [store]
596
+ }),
597
+ [enqueueOperation, reportError, storage, store]
519
598
  );
520
599
  const removeCollection = useCallback(
521
- async (id) => {
600
+ (id) => enqueueOperation(async () => {
522
601
  const current = store.getSnapshot().collections;
523
602
  if (!current[id]) throw new Error(`Collection "${id}" does not exist.`);
524
603
  const { [id]: _removed, ...remaining } = current;
525
- store.setState({ collections: remaining });
526
604
  const affected = itemsRef.current.filter((item) => item.collectionId === id);
527
- if (affected.length > 0) {
528
- const nextItems = itemsRef.current.map(
529
- (item) => item.collectionId === id ? { ...item, collectionId: void 0, updatedAt: Date.now() } : item
530
- );
531
- itemsRef.current = nextItems;
532
- store.setState({ items: nextItems });
533
- for (const item of affected) {
534
- const { collectionId: _, ...withoutCollection } = item;
535
- await storage.set({ ...withoutCollection, collectionId: void 0, updatedAt: Date.now() });
605
+ const updated = affected.map((item) => {
606
+ const { collectionId: _collectionId, ...withoutCollection } = item;
607
+ return { ...withoutCollection, updatedAt: Date.now() };
608
+ });
609
+ try {
610
+ await persistKeepItems(storage, updated);
611
+ await storage.removeCollection?.(id);
612
+ } catch (cause) {
613
+ if (affected.length > 0) {
614
+ try {
615
+ await restoreItems(storage, affected);
616
+ } catch (rollbackError) {
617
+ reportError(rollbackError, { action: "collection", id });
618
+ }
536
619
  }
620
+ reportError(cause, { action: "collection", id });
621
+ throw cause;
537
622
  }
538
- },
539
- [storage, store]
623
+ if (affected.length > 0) {
624
+ const updatedById = new Map(updated.map((item) => [item.id, item]));
625
+ setItems(itemsRef.current.map((item) => updatedById.get(item.id) ?? item));
626
+ }
627
+ store.setState({ collections: remaining });
628
+ }),
629
+ [enqueueOperation, reportError, setItems, storage, store]
540
630
  );
541
631
  const updateTagsBatch = useCallback(
542
632
  async (ids, tags) => {
@@ -882,6 +972,11 @@ function KeepProviderContent({
882
972
  unarchiveItem,
883
973
  togglePin,
884
974
  moveToCollection,
975
+ archiveBatch,
976
+ unarchiveBatch,
977
+ pinBatch,
978
+ unpinBatch,
979
+ moveToCollectionBatch,
885
980
  createCollection,
886
981
  renameCollection,
887
982
  removeCollection,
@@ -931,6 +1026,11 @@ function KeepProviderContent({
931
1026
  unarchiveItem,
932
1027
  togglePin,
933
1028
  moveToCollection,
1029
+ archiveBatch,
1030
+ unarchiveBatch,
1031
+ pinBatch,
1032
+ unpinBatch,
1033
+ moveToCollectionBatch,
934
1034
  createCollection,
935
1035
  renameCollection,
936
1036
  removeCollection,
@@ -957,6 +1057,11 @@ function KeepProviderContent({
957
1057
  unarchiveItem,
958
1058
  togglePin,
959
1059
  moveToCollection,
1060
+ archiveBatch,
1061
+ unarchiveBatch,
1062
+ pinBatch,
1063
+ unpinBatch,
1064
+ moveToCollectionBatch,
960
1065
  createCollection,
961
1066
  renameCollection,
962
1067
  removeCollection,
@@ -994,6 +1099,11 @@ function KeepProviderContent({
994
1099
  unarchiveItem,
995
1100
  togglePin,
996
1101
  moveToCollection,
1102
+ archiveBatch,
1103
+ unarchiveBatch,
1104
+ pinBatch,
1105
+ unpinBatch,
1106
+ moveToCollectionBatch,
997
1107
  updateTagsBatch,
998
1108
  refreshItemMetadata,
999
1109
  revalidateItems,
@@ -1298,6 +1408,7 @@ function useKeepList(query = {}) {
1298
1408
  activity,
1299
1409
  archived,
1300
1410
  collectionId,
1411
+ organization,
1301
1412
  filter,
1302
1413
  pagination,
1303
1414
  pinnedFirst,
@@ -1313,6 +1424,7 @@ function useKeepList(query = {}) {
1313
1424
  activity,
1314
1425
  archived,
1315
1426
  collectionId,
1427
+ organization,
1316
1428
  filter,
1317
1429
  pagination,
1318
1430
  pinnedFirst,
@@ -1327,6 +1439,7 @@ function useKeepList(query = {}) {
1327
1439
  activity,
1328
1440
  archived,
1329
1441
  collectionId,
1442
+ organization,
1330
1443
  filter,
1331
1444
  pagination,
1332
1445
  pinnedFirst,
@@ -1397,6 +1510,14 @@ function useKeepList(query = {}) {
1397
1510
  (id, collectionId2) => actions.moveToCollection(id, collectionId2),
1398
1511
  [actions]
1399
1512
  );
1513
+ const archiveBatch = useCallback4((ids) => actions.archiveBatch(ids), [actions]);
1514
+ const unarchiveBatch = useCallback4((ids) => actions.unarchiveBatch(ids), [actions]);
1515
+ const pinBatch = useCallback4((ids) => actions.pinBatch(ids), [actions]);
1516
+ const unpinBatch = useCallback4((ids) => actions.unpinBatch(ids), [actions]);
1517
+ const moveToCollectionBatch = useCallback4(
1518
+ (ids, collectionId2) => actions.moveToCollectionBatch(ids, collectionId2),
1519
+ [actions]
1520
+ );
1400
1521
  return {
1401
1522
  items: result.items,
1402
1523
  totalCount: result.totalCount,
@@ -1424,6 +1545,11 @@ function useKeepList(query = {}) {
1424
1545
  unarchive,
1425
1546
  togglePin,
1426
1547
  moveToCollection,
1548
+ archiveBatch,
1549
+ unarchiveBatch,
1550
+ pinBatch,
1551
+ unpinBatch,
1552
+ moveToCollectionBatch,
1427
1553
  reorder: actions.reorderItems,
1428
1554
  move: actions.moveItem,
1429
1555
  clear: actions.clear,