@flurryx/store 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -37,7 +37,7 @@ __export(index_exports, {
37
37
  module.exports = __toCommonJS(index_exports);
38
38
 
39
39
  // src/base-store.ts
40
- var import_core2 = require("@angular/core");
40
+ var import_core3 = require("@angular/core");
41
41
 
42
42
  // src/store-clone.ts
43
43
  function cloneValue(value) {
@@ -120,6 +120,9 @@ function createSnapshotRestorePatch(currentState, snapshotState) {
120
120
  return patch;
121
121
  }
122
122
 
123
+ // src/store-replay.ts
124
+ var import_core = require("@angular/core");
125
+
123
126
  // src/store-messages.ts
124
127
  var INVALID_HISTORY_INDEX_ERROR = "History index is out of range";
125
128
  var INVALID_HISTORY_MESSAGE_ID_ERROR = "History message id is out of range";
@@ -426,6 +429,125 @@ function toDeadLetterEntry(record) {
426
429
  failedAt: record.lastAttemptedAt ?? record.createdAt
427
430
  };
428
431
  }
432
+ function areValuesEquivalent(left, right, seen = /* @__PURE__ */ new WeakMap()) {
433
+ if (Object.is(left, right)) {
434
+ return true;
435
+ }
436
+ if (typeof left !== typeof right || left === null || right === null) {
437
+ return false;
438
+ }
439
+ if (typeof left !== "object" || typeof right !== "object") {
440
+ return false;
441
+ }
442
+ let seenRights = seen.get(left);
443
+ if (seenRights?.has(right)) {
444
+ return true;
445
+ }
446
+ if (!seenRights) {
447
+ seenRights = /* @__PURE__ */ new WeakSet();
448
+ seen.set(left, seenRights);
449
+ }
450
+ seenRights.add(right);
451
+ if (left instanceof Date || right instanceof Date) {
452
+ return left instanceof Date && right instanceof Date && left.getTime() === right.getTime();
453
+ }
454
+ if (left instanceof Map || right instanceof Map) {
455
+ if (!(left instanceof Map) || !(right instanceof Map)) {
456
+ return false;
457
+ }
458
+ const leftEntries = Array.from(left.entries());
459
+ const rightEntries = Array.from(right.entries());
460
+ if (leftEntries.length !== rightEntries.length) {
461
+ return false;
462
+ }
463
+ return leftEntries.every(([leftKey, leftValue], index) => {
464
+ const rightEntry = rightEntries[index];
465
+ if (!rightEntry) {
466
+ return false;
467
+ }
468
+ return areValuesEquivalent(leftKey, rightEntry[0], seen) && areValuesEquivalent(leftValue, rightEntry[1], seen);
469
+ });
470
+ }
471
+ if (left instanceof Set || right instanceof Set) {
472
+ if (!(left instanceof Set) || !(right instanceof Set)) {
473
+ return false;
474
+ }
475
+ const leftValues = Array.from(left.values());
476
+ const rightValues = Array.from(right.values());
477
+ if (leftValues.length !== rightValues.length) {
478
+ return false;
479
+ }
480
+ return leftValues.every(
481
+ (leftValue, index) => areValuesEquivalent(leftValue, rightValues[index], seen)
482
+ );
483
+ }
484
+ if (Array.isArray(left) || Array.isArray(right)) {
485
+ if (!Array.isArray(left) || !Array.isArray(right)) {
486
+ return false;
487
+ }
488
+ if (left.length !== right.length) {
489
+ return false;
490
+ }
491
+ return left.every(
492
+ (leftValue, index) => areValuesEquivalent(leftValue, right[index], seen)
493
+ );
494
+ }
495
+ if (Object.getPrototypeOf(left) !== Object.getPrototypeOf(right)) {
496
+ return false;
497
+ }
498
+ const leftRecord = left;
499
+ const rightRecord = right;
500
+ const leftKeys = Reflect.ownKeys(leftRecord);
501
+ const rightKeys = Reflect.ownKeys(rightRecord);
502
+ if (leftKeys.length !== rightKeys.length) {
503
+ return false;
504
+ }
505
+ return leftKeys.every((key) => {
506
+ if (!Object.prototype.hasOwnProperty.call(rightRecord, key)) {
507
+ return false;
508
+ }
509
+ return areValuesEquivalent(leftRecord[key], rightRecord[key], seen);
510
+ });
511
+ }
512
+ function areStoreMessageRecordsEquivalent(sourceRecord, cachedRecord) {
513
+ return sourceRecord.id === cachedRecord.id && sourceRecord.status === cachedRecord.status && sourceRecord.attempts === cachedRecord.attempts && sourceRecord.createdAt === cachedRecord.createdAt && sourceRecord.lastAttemptedAt === cachedRecord.lastAttemptedAt && sourceRecord.acknowledgedAt === cachedRecord.acknowledgedAt && sourceRecord.error === cachedRecord.error && areValuesEquivalent(sourceRecord.message, cachedRecord.message);
514
+ }
515
+ function createStableReadonlyCollection(items) {
516
+ return Object.freeze([...items]);
517
+ }
518
+ function appendStableReadonlyCollectionItem(input) {
519
+ return createStableReadonlyCollection([...input.items, input.item]);
520
+ }
521
+ function upsertStableReadonlyCollectionItem(input) {
522
+ const existingIndex = input.items.findIndex(
523
+ (candidate) => candidate.id === input.item.id
524
+ );
525
+ if (existingIndex === -1) {
526
+ return appendStableReadonlyCollectionItem(input);
527
+ }
528
+ if (Object.is(input.items[existingIndex], input.item)) {
529
+ return input.items;
530
+ }
531
+ const nextItems = [...input.items];
532
+ nextItems[existingIndex] = input.item;
533
+ return createStableReadonlyCollection(nextItems);
534
+ }
535
+ function syncStableReadonlyCollectionById(input) {
536
+ const cachedItemsById = /* @__PURE__ */ new Map();
537
+ input.items.forEach((item) => {
538
+ cachedItemsById.set(item.id, item);
539
+ });
540
+ let didChange = input.items.length !== input.sourceItems.length;
541
+ const nextItems = input.sourceItems.map((sourceItem, index) => {
542
+ const cachedItem = cachedItemsById.get(input.getSourceId(sourceItem));
543
+ const nextItem = cachedItem && input.areEquivalent(sourceItem, cachedItem) ? cachedItem : input.createItem(sourceItem);
544
+ if (!didChange && input.items[index] !== nextItem) {
545
+ didChange = true;
546
+ }
547
+ return nextItem;
548
+ });
549
+ return didChange ? createStableReadonlyCollection(nextItems) : input.items;
550
+ }
429
551
  function createStoreHistory(config) {
430
552
  const messageChannel = config.channel ?? createInMemoryStoreMessageChannel();
431
553
  const clock = config.clock ?? Date.now;
@@ -439,18 +561,30 @@ function createStoreHistory(config) {
439
561
  }
440
562
  ];
441
563
  let currentIndex = 0;
564
+ let historyCollection = createStableReadonlyCollection(
565
+ history.map((entry) => cloneValue(entry))
566
+ );
567
+ let messageCollection = createStableReadonlyCollection(
568
+ messageChannel.getMessages().map((record) => cloneValue(record))
569
+ );
570
+ const version = (0, import_core.signal)(0);
571
+ function notifyVersion() {
572
+ version.update((v) => v + 1);
573
+ }
442
574
  function recordSnapshot(record) {
443
575
  const nextIndex = history.length;
444
- history = [
445
- ...history,
446
- {
447
- id: record.id,
448
- index: nextIndex,
449
- message: cloneValue(record.message),
450
- snapshot: config.captureSnapshot(),
451
- acknowledgedAt: record.acknowledgedAt
452
- }
453
- ];
576
+ const nextHistoryEntry = {
577
+ id: record.id,
578
+ index: nextIndex,
579
+ message: cloneValue(record.message),
580
+ snapshot: config.captureSnapshot(),
581
+ acknowledgedAt: record.acknowledgedAt
582
+ };
583
+ history = [...history, nextHistoryEntry];
584
+ historyCollection = appendStableReadonlyCollectionItem({
585
+ items: historyCollection,
586
+ item: cloneValue(nextHistoryEntry)
587
+ });
454
588
  currentIndex = nextIndex;
455
589
  }
456
590
  function truncateFutureHistory() {
@@ -458,6 +592,9 @@ function createStoreHistory(config) {
458
592
  return;
459
593
  }
460
594
  history = history.slice(0, currentIndex + 1);
595
+ historyCollection = createStableReadonlyCollection(
596
+ historyCollection.slice(0, currentIndex + 1)
597
+ );
461
598
  }
462
599
  function ensureIndexInRange(index) {
463
600
  if (!Number.isInteger(index) || index < 0 || index >= history.length) {
@@ -468,6 +605,7 @@ function createStoreHistory(config) {
468
605
  ensureIndexInRange(index);
469
606
  config.applySnapshot(history[index].snapshot);
470
607
  currentIndex = index;
608
+ notifyVersion();
471
609
  }
472
610
  function undo() {
473
611
  if (currentIndex === 0) {
@@ -500,6 +638,10 @@ function createStoreHistory(config) {
500
638
  error
501
639
  };
502
640
  messageChannel.saveMessage(nextRecord);
641
+ messageCollection = upsertStableReadonlyCollectionItem({
642
+ items: messageCollection,
643
+ item: cloneValue(nextRecord)
644
+ });
503
645
  return nextRecord;
504
646
  }
505
647
  function consumeRecord(record, options) {
@@ -523,6 +665,7 @@ function createStoreHistory(config) {
523
665
  truncateFutureHistory();
524
666
  recordSnapshot(acknowledgedRecord);
525
667
  }
668
+ notifyVersion();
526
669
  return true;
527
670
  } catch (error) {
528
671
  persistMessageAttempt(
@@ -534,6 +677,7 @@ function createStoreHistory(config) {
534
677
  getErrorMessage(error),
535
678
  attemptedAt
536
679
  );
680
+ notifyVersion();
537
681
  return false;
538
682
  }
539
683
  }
@@ -577,9 +721,35 @@ function createStoreHistory(config) {
577
721
  });
578
722
  return acknowledgedCount;
579
723
  }
724
+ const historySignal = (0, import_core.computed)(() => {
725
+ version();
726
+ return historyCollection;
727
+ });
728
+ const messagesSignal = (0, import_core.computed)(() => {
729
+ version();
730
+ messageCollection = syncStableReadonlyCollectionById({
731
+ items: messageCollection,
732
+ sourceItems: messageChannel.getMessages(),
733
+ getSourceId: (record) => record.id,
734
+ createItem: (record) => cloneValue(record),
735
+ areEquivalent: areStoreMessageRecordsEquivalent
736
+ });
737
+ return messageCollection;
738
+ });
739
+ const currentIndexSignal = (0, import_core.computed)(() => {
740
+ version();
741
+ return currentIndex;
742
+ });
580
743
  return {
744
+ historySignal,
745
+ messagesSignal,
746
+ currentIndexSignal,
581
747
  publish(message) {
582
748
  const record = messageChannel.publish(message);
749
+ messageCollection = appendStableReadonlyCollectionItem({
750
+ items: messageCollection,
751
+ item: cloneValue(record)
752
+ });
583
753
  return consumeRecord(record);
584
754
  },
585
755
  replay(input) {
@@ -629,7 +799,7 @@ function clearAllStores() {
629
799
  }
630
800
 
631
801
  // src/store-message-consumer.ts
632
- var import_core = require("@flurryx/core");
802
+ var import_core2 = require("@flurryx/core");
633
803
  function createDefaultState() {
634
804
  return {
635
805
  data: void 0,
@@ -692,7 +862,7 @@ function createStoreMessageConsumer(signals, notifier) {
692
862
  function applyUpdateKeyedOne(key, resourceKey, entity) {
693
863
  const sig = signals.getOrCreate(key);
694
864
  const state = sig();
695
- const data = (0, import_core.isKeyedResourceData)(state.data) ? state.data : (0, import_core.createKeyedResourceData)();
865
+ const data = (0, import_core2.isKeyedResourceData)(state.data) ? state.data : (0, import_core2.createKeyedResourceData)();
696
866
  const nextErrors = { ...data.errors };
697
867
  delete nextErrors[resourceKey];
698
868
  const nextData = {
@@ -704,7 +874,7 @@ function createStoreMessageConsumer(signals, notifier) {
704
874
  };
705
875
  return applyUpdate(key, {
706
876
  data: nextData,
707
- isLoading: (0, import_core.isAnyKeyLoading)(nextData.isLoading),
877
+ isLoading: (0, import_core2.isAnyKeyLoading)(nextData.isLoading),
708
878
  status: void 0,
709
879
  errors: void 0
710
880
  });
@@ -713,7 +883,7 @@ function createStoreMessageConsumer(signals, notifier) {
713
883
  const sig = signals.getOrCreate(key);
714
884
  const previousState = sig();
715
885
  const state = previousState;
716
- if (!(0, import_core.isKeyedResourceData)(state.data)) {
886
+ if (!(0, import_core2.isKeyedResourceData)(state.data)) {
717
887
  return true;
718
888
  }
719
889
  const data = state.data;
@@ -737,7 +907,7 @@ function createStoreMessageConsumer(signals, notifier) {
737
907
  ...prev,
738
908
  data: nextData,
739
909
  status: void 0,
740
- isLoading: (0, import_core.isAnyKeyLoading)(nextIsLoading),
910
+ isLoading: (0, import_core2.isAnyKeyLoading)(nextIsLoading),
741
911
  errors: void 0
742
912
  })
743
913
  );
@@ -748,7 +918,7 @@ function createStoreMessageConsumer(signals, notifier) {
748
918
  function applyStartKeyedLoading(key, resourceKey) {
749
919
  const sig = signals.getOrCreate(key);
750
920
  const state = sig();
751
- if (!(0, import_core.isKeyedResourceData)(state.data)) {
921
+ if (!(0, import_core2.isKeyedResourceData)(state.data)) {
752
922
  return applyStartLoading(key);
753
923
  }
754
924
  const previousState = state;
@@ -772,7 +942,7 @@ function createStoreMessageConsumer(signals, notifier) {
772
942
  ...previous,
773
943
  data: nextData,
774
944
  status: void 0,
775
- isLoading: (0, import_core.isAnyKeyLoading)(nextIsLoading),
945
+ isLoading: (0, import_core2.isAnyKeyLoading)(nextIsLoading),
776
946
  errors: void 0
777
947
  })
778
948
  );
@@ -884,48 +1054,60 @@ var BaseStore = class {
884
1054
  notify: (key, next, prev) => this.notifyUpdateHooks(key, next, prev)
885
1055
  }
886
1056
  );
887
- this.history = createStoreHistory({
1057
+ this.historyDriver = createStoreHistory({
888
1058
  captureSnapshot: () => consumer.createSnapshot(),
889
1059
  applySnapshot: (snapshot) => consumer.applySnapshot(snapshot),
890
1060
  applyMessage: (message) => consumer.applyMessage(message),
891
1061
  channel: options?.channel
892
1062
  });
1063
+ this.history = this.historyDriver.historySignal;
1064
+ this.messages = this.historyDriver.messagesSignal;
1065
+ this.currentIndex = this.historyDriver.currentIndexSignal;
1066
+ this.keys = (0, import_core3.signal)([...this.storeKeys]).asReadonly();
893
1067
  trackStore(this);
894
1068
  }
895
1069
  signalsState = /* @__PURE__ */ new Map();
896
1070
  storeKeys;
897
- history;
1071
+ historyDriver;
1072
+ /** @inheritDoc */
1073
+ travelTo = (index) => this.historyDriver.travelTo(index);
1074
+ /** @inheritDoc */
1075
+ undo = () => this.historyDriver.undo();
898
1076
  /** @inheritDoc */
899
- travelTo = (index) => this.history.travelTo(index);
1077
+ redo = () => this.historyDriver.redo();
900
1078
  /** @inheritDoc */
901
- undo = () => this.history.undo();
1079
+ getDeadLetters = () => this.historyDriver.getDeadLetters();
902
1080
  /** @inheritDoc */
903
- redo = () => this.history.redo();
1081
+ replayDeadLetter = (id) => this.historyDriver.replayDeadLetter(id);
904
1082
  /** @inheritDoc */
905
- getDeadLetters = () => this.history.getDeadLetters();
1083
+ replayDeadLetters = () => this.historyDriver.replayDeadLetters();
906
1084
  /** @inheritDoc */
907
- replayDeadLetter = (id) => this.history.replayDeadLetter(id);
1085
+ getCurrentIndex = () => this.historyDriver.getCurrentIndex();
908
1086
  /** @inheritDoc */
909
- replayDeadLetters = () => this.history.replayDeadLetters();
1087
+ history;
1088
+ /** @inheritDoc */
1089
+ messages;
1090
+ /** @inheritDoc */
1091
+ currentIndex;
910
1092
  /** @inheritDoc */
911
- getCurrentIndex = () => this.history.getCurrentIndex();
1093
+ keys;
912
1094
  replay(idOrIds) {
913
1095
  if (Array.isArray(idOrIds)) {
914
- return this.history.replay(idOrIds);
1096
+ return this.historyDriver.replay(idOrIds);
915
1097
  }
916
- return this.history.replay(idOrIds);
1098
+ return this.historyDriver.replay(idOrIds);
917
1099
  }
918
1100
  getHistory(key) {
919
1101
  if (key === void 0) {
920
- return this.history.getHistory();
1102
+ return this.historyDriver.getHistory();
921
1103
  }
922
- return this.history.getHistory(key);
1104
+ return this.historyDriver.getHistory(key);
923
1105
  }
924
1106
  getMessages(key) {
925
1107
  if (key === void 0) {
926
- return this.history.getMessages();
1108
+ return this.historyDriver.getMessages();
927
1109
  }
928
- return this.history.getMessages(key);
1110
+ return this.historyDriver.getMessages(key);
929
1111
  }
930
1112
  /**
931
1113
  * Returns a **read-only** `Signal` for the given store slot.
@@ -971,13 +1153,13 @@ var BaseStore = class {
971
1153
  * @param newState - Partial state to merge (e.g. `{ data: newData, status: 'Success' }`).
972
1154
  */
973
1155
  update(key, newState) {
974
- this.history.publish(
1156
+ this.historyDriver.publish(
975
1157
  createUpdateMessage(key, cloneValue(newState))
976
1158
  );
977
1159
  }
978
1160
  /** Resets every slot in this store to its initial idle state. */
979
1161
  clearAll() {
980
- this.history.publish(createClearAllMessage());
1162
+ this.historyDriver.publish(createClearAllMessage());
981
1163
  }
982
1164
  /**
983
1165
  * Resets a single slot to `{ data: undefined, isLoading: false, status: undefined, errors: undefined }`.
@@ -985,7 +1167,7 @@ var BaseStore = class {
985
1167
  * @param key - The slot to clear.
986
1168
  */
987
1169
  clear(key) {
988
- this.history.publish(createClearMessage(key));
1170
+ this.historyDriver.publish(createClearMessage(key));
989
1171
  }
990
1172
  /**
991
1173
  * Marks a slot as loading: sets `isLoading: true` and clears `status` and `errors`.
@@ -993,7 +1175,7 @@ var BaseStore = class {
993
1175
  * @param key - The slot to mark as loading.
994
1176
  */
995
1177
  startLoading(key) {
996
- this.history.publish(createStartLoadingMessage(key));
1178
+ this.historyDriver.publish(createStartLoadingMessage(key));
997
1179
  }
998
1180
  /**
999
1181
  * Marks a slot as no longer loading: sets `isLoading: false`.
@@ -1002,7 +1184,7 @@ var BaseStore = class {
1002
1184
  * @param key - The slot to stop loading.
1003
1185
  */
1004
1186
  stopLoading(key) {
1005
- this.history.publish(createStopLoadingMessage(key));
1187
+ this.historyDriver.publish(createStopLoadingMessage(key));
1006
1188
  }
1007
1189
  /**
1008
1190
  * Merges a single entity into a {@link KeyedResourceData} slot.
@@ -1014,7 +1196,7 @@ var BaseStore = class {
1014
1196
  * @param entity - The entity value to store.
1015
1197
  */
1016
1198
  updateKeyedOne(key, resourceKey, entity) {
1017
- this.history.publish(
1199
+ this.historyDriver.publish(
1018
1200
  createUpdateKeyedOneMessage(
1019
1201
  key,
1020
1202
  resourceKey,
@@ -1031,7 +1213,7 @@ var BaseStore = class {
1031
1213
  * @param resourceKey - The entity identifier to remove.
1032
1214
  */
1033
1215
  clearKeyedOne(key, resourceKey) {
1034
- this.history.publish(
1216
+ this.historyDriver.publish(
1035
1217
  createClearKeyedOneMessage(key, resourceKey)
1036
1218
  );
1037
1219
  }
@@ -1044,7 +1226,7 @@ var BaseStore = class {
1044
1226
  * @param resourceKey - The entity identifier to mark as loading.
1045
1227
  */
1046
1228
  startKeyedLoading(key, resourceKey) {
1047
- this.history.publish(
1229
+ this.historyDriver.publish(
1048
1230
  createStartKeyedLoadingMessage(key, resourceKey)
1049
1231
  );
1050
1232
  }
@@ -1081,49 +1263,57 @@ var BaseStore = class {
1081
1263
  this.storeKeys.forEach((key) => {
1082
1264
  this.signalsState.set(
1083
1265
  key,
1084
- (0, import_core2.signal)(createDefaultState())
1266
+ (0, import_core3.signal)(createDefaultState())
1085
1267
  );
1086
1268
  });
1087
1269
  }
1088
1270
  };
1089
1271
 
1090
1272
  // src/lazy-store.ts
1091
- var import_core3 = require("@angular/core");
1273
+ var import_core4 = require("@angular/core");
1092
1274
  var LazyStore = class {
1093
1275
  signals = /* @__PURE__ */ new Map();
1094
1276
  hooks = /* @__PURE__ */ new Map();
1095
- history;
1277
+ historyDriver;
1096
1278
  /** @inheritDoc */
1097
- travelTo = (index) => this.history.travelTo(index);
1279
+ travelTo = (index) => this.historyDriver.travelTo(index);
1098
1280
  /** @inheritDoc */
1099
- undo = () => this.history.undo();
1281
+ undo = () => this.historyDriver.undo();
1100
1282
  /** @inheritDoc */
1101
- redo = () => this.history.redo();
1283
+ redo = () => this.historyDriver.redo();
1102
1284
  getMessages(key) {
1103
1285
  if (key === void 0) {
1104
- return this.history.getMessages();
1286
+ return this.historyDriver.getMessages();
1105
1287
  }
1106
- return this.history.getMessages(key);
1288
+ return this.historyDriver.getMessages(key);
1107
1289
  }
1290
+ getDeadLetters = () => this.historyDriver.getDeadLetters();
1108
1291
  /** @inheritDoc */
1109
- getDeadLetters = () => this.history.getDeadLetters();
1292
+ replayDeadLetter = (id) => this.historyDriver.replayDeadLetter(id);
1293
+ /** @inheritDoc */
1294
+ replayDeadLetters = () => this.historyDriver.replayDeadLetters();
1295
+ /** @inheritDoc */
1296
+ getCurrentIndex = () => this.historyDriver.getCurrentIndex();
1297
+ /** @inheritDoc */
1298
+ history;
1110
1299
  /** @inheritDoc */
1111
- replayDeadLetter = (id) => this.history.replayDeadLetter(id);
1300
+ messages;
1112
1301
  /** @inheritDoc */
1113
- replayDeadLetters = () => this.history.replayDeadLetters();
1302
+ currentIndex;
1114
1303
  /** @inheritDoc */
1115
- getCurrentIndex = () => this.history.getCurrentIndex();
1304
+ keys;
1305
+ keysSignal = (0, import_core4.signal)([]);
1116
1306
  replay(idOrIds) {
1117
1307
  if (Array.isArray(idOrIds)) {
1118
- return this.history.replay(idOrIds);
1308
+ return this.historyDriver.replay(idOrIds);
1119
1309
  }
1120
- return this.history.replay(idOrIds);
1310
+ return this.historyDriver.replay(idOrIds);
1121
1311
  }
1122
1312
  getHistory(key) {
1123
1313
  if (key === void 0) {
1124
- return this.history.getHistory();
1314
+ return this.historyDriver.getHistory();
1125
1315
  }
1126
- return this.history.getHistory(key);
1316
+ return this.historyDriver.getHistory(key);
1127
1317
  }
1128
1318
  constructor(options) {
1129
1319
  const consumer = createStoreMessageConsumer(
@@ -1135,19 +1325,24 @@ var LazyStore = class {
1135
1325
  notify: (key, next, prev) => this.notifyHooks(key, next, prev)
1136
1326
  }
1137
1327
  );
1138
- this.history = createStoreHistory({
1328
+ this.historyDriver = createStoreHistory({
1139
1329
  captureSnapshot: () => consumer.createSnapshot(),
1140
1330
  applySnapshot: (snapshot) => consumer.applySnapshot(snapshot),
1141
1331
  applyMessage: (message) => consumer.applyMessage(message),
1142
1332
  channel: options?.channel
1143
1333
  });
1334
+ this.history = this.historyDriver.historySignal;
1335
+ this.messages = this.historyDriver.messagesSignal;
1336
+ this.currentIndex = this.historyDriver.currentIndexSignal;
1337
+ this.keys = this.keysSignal.asReadonly();
1144
1338
  trackStore(this);
1145
1339
  }
1146
1340
  getOrCreate(key) {
1147
1341
  let sig = this.signals.get(key);
1148
1342
  if (!sig) {
1149
- sig = (0, import_core3.signal)(createDefaultState());
1343
+ sig = (0, import_core4.signal)(createDefaultState());
1150
1344
  this.signals.set(key, sig);
1345
+ this.keysSignal.update((prev) => [...prev, key]);
1151
1346
  }
1152
1347
  return sig;
1153
1348
  }
@@ -1157,29 +1352,29 @@ var LazyStore = class {
1157
1352
  }
1158
1353
  /** @inheritDoc */
1159
1354
  update(key, newState) {
1160
- this.history.publish(
1355
+ this.historyDriver.publish(
1161
1356
  createUpdateMessage(key, cloneValue(newState))
1162
1357
  );
1163
1358
  }
1164
1359
  /** @inheritDoc */
1165
1360
  clear(key) {
1166
- this.history.publish(createClearMessage(key));
1361
+ this.historyDriver.publish(createClearMessage(key));
1167
1362
  }
1168
1363
  /** @inheritDoc */
1169
1364
  clearAll() {
1170
- this.history.publish(createClearAllMessage());
1365
+ this.historyDriver.publish(createClearAllMessage());
1171
1366
  }
1172
1367
  /** @inheritDoc */
1173
1368
  startLoading(key) {
1174
- this.history.publish(createStartLoadingMessage(key));
1369
+ this.historyDriver.publish(createStartLoadingMessage(key));
1175
1370
  }
1176
1371
  /** @inheritDoc */
1177
1372
  stopLoading(key) {
1178
- this.history.publish(createStopLoadingMessage(key));
1373
+ this.historyDriver.publish(createStopLoadingMessage(key));
1179
1374
  }
1180
1375
  /** @inheritDoc */
1181
1376
  updateKeyedOne(key, resourceKey, entity) {
1182
- this.history.publish(
1377
+ this.historyDriver.publish(
1183
1378
  createUpdateKeyedOneMessage(
1184
1379
  key,
1185
1380
  resourceKey,
@@ -1189,13 +1384,13 @@ var LazyStore = class {
1189
1384
  }
1190
1385
  /** @inheritDoc */
1191
1386
  clearKeyedOne(key, resourceKey) {
1192
- this.history.publish(
1387
+ this.historyDriver.publish(
1193
1388
  createClearKeyedOneMessage(key, resourceKey)
1194
1389
  );
1195
1390
  }
1196
1391
  /** @inheritDoc */
1197
1392
  startKeyedLoading(key, resourceKey) {
1198
- this.history.publish(
1393
+ this.historyDriver.publish(
1199
1394
  createStartKeyedLoadingMessage(key, resourceKey)
1200
1395
  );
1201
1396
  }
@@ -1248,7 +1443,7 @@ var LazyStore = class {
1248
1443
  };
1249
1444
 
1250
1445
  // src/store-builder.ts
1251
- var import_core5 = require("@angular/core");
1446
+ var import_core6 = require("@angular/core");
1252
1447
 
1253
1448
  // src/dynamic-store.ts
1254
1449
  var DynamicStore = class extends BaseStore {
@@ -1278,12 +1473,12 @@ function mirrorKey(source, sourceKey, target, targetKeyOrOptions, options) {
1278
1473
  }
1279
1474
 
1280
1475
  // src/collect-keyed.ts
1281
- var import_core4 = require("@flurryx/core");
1476
+ var import_core5 = require("@flurryx/core");
1282
1477
  function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
1283
1478
  const resolvedTargetKey = typeof targetKeyOrOptions === "string" ? targetKeyOrOptions : sourceKey;
1284
1479
  const resolvedOptions = typeof targetKeyOrOptions === "object" ? targetKeyOrOptions : options;
1285
1480
  target.update(resolvedTargetKey, {
1286
- data: (0, import_core4.createKeyedResourceData)()
1481
+ data: (0, import_core5.createKeyedResourceData)()
1287
1482
  });
1288
1483
  let previousId;
1289
1484
  const cleanup = source.onUpdate(sourceKey, (state) => {
@@ -1314,7 +1509,7 @@ function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
1314
1509
  };
1315
1510
  target.update(resolvedTargetKey, {
1316
1511
  data: updatedKeyed,
1317
- isLoading: (0, import_core4.isAnyKeyLoading)(newIsLoading),
1512
+ isLoading: (0, import_core5.isAnyKeyLoading)(newIsLoading),
1318
1513
  status: "Success"
1319
1514
  });
1320
1515
  previousId = currentId;
@@ -1336,7 +1531,7 @@ function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
1336
1531
  };
1337
1532
  target.update(resolvedTargetKey, {
1338
1533
  data: updatedKeyed,
1339
- isLoading: (0, import_core4.isAnyKeyLoading)(newIsLoading)
1534
+ isLoading: (0, import_core5.isAnyKeyLoading)(newIsLoading)
1340
1535
  });
1341
1536
  previousId = currentId;
1342
1537
  } else if (resourceState.data === void 0 && previousId !== void 0) {
@@ -1352,7 +1547,7 @@ function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
1352
1547
  };
1353
1548
  target.update(resolvedTargetKey, {
1354
1549
  data: updatedKeyed,
1355
- isLoading: (0, import_core4.isAnyKeyLoading)(remainingLoading)
1550
+ isLoading: (0, import_core5.isAnyKeyLoading)(remainingLoading)
1356
1551
  });
1357
1552
  previousId = void 0;
1358
1553
  } else if (resourceState.isLoading && currentId !== void 0) {
@@ -1384,7 +1579,7 @@ function resource() {
1384
1579
  // src/store-builder.ts
1385
1580
  function wireMirrors(store, mirrors) {
1386
1581
  for (const def of mirrors) {
1387
- const sourceStore = (0, import_core5.inject)(def.sourceToken);
1582
+ const sourceStore = (0, import_core6.inject)(def.sourceToken);
1388
1583
  mirrorKey(
1389
1584
  sourceStore,
1390
1585
  def.sourceKey,
@@ -1395,7 +1590,7 @@ function wireMirrors(store, mirrors) {
1395
1590
  }
1396
1591
  function wireMirrorKeyed(store, defs) {
1397
1592
  for (const def of defs) {
1398
- const sourceStore = (0, import_core5.inject)(def.sourceToken);
1593
+ const sourceStore = (0, import_core6.inject)(def.sourceToken);
1399
1594
  collectKeyed(
1400
1595
  sourceStore,
1401
1596
  def.sourceKey,
@@ -1477,7 +1672,7 @@ function createBuilder(accum, mirrors = [], mirrorKeyedDefs = [], selfMirrors =
1477
1672
  );
1478
1673
  },
1479
1674
  build(options) {
1480
- return new import_core5.InjectionToken("FlurryxStore", {
1675
+ return new import_core6.InjectionToken("FlurryxStore", {
1481
1676
  providedIn: "root",
1482
1677
  factory: () => {
1483
1678
  const store = new DynamicStore(accum, options);
@@ -1552,7 +1747,7 @@ function createConstrainedBuilder(_enumObj, accum, mirrors = [], mirrorKeyedDefs
1552
1747
  );
1553
1748
  },
1554
1749
  build(options) {
1555
- return new import_core5.InjectionToken("FlurryxStore", {
1750
+ return new import_core6.InjectionToken("FlurryxStore", {
1556
1751
  providedIn: "root",
1557
1752
  factory: () => {
1558
1753
  const store = new DynamicStore(accum, options);
@@ -1603,7 +1798,7 @@ function createInterfaceBuilder(mirrors = [], mirrorKeyedDefs = [], selfMirrors
1603
1798
  );
1604
1799
  },
1605
1800
  build(options) {
1606
- return new import_core5.InjectionToken("FlurryxStore", {
1801
+ return new import_core6.InjectionToken("FlurryxStore", {
1607
1802
  providedIn: "root",
1608
1803
  factory: () => {
1609
1804
  const store = new LazyStore(options);