@flurryx/store 1.0.1 → 1.1.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
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  BaseStore: () => BaseStore,
24
+ INVALID_STORE_KEY_ERROR: () => INVALID_STORE_KEY_ERROR,
24
25
  LazyStore: () => LazyStore,
25
26
  Store: () => Store,
26
27
  clearAllStores: () => clearAllStores,
@@ -121,12 +122,259 @@ function createSnapshotRestorePatch(currentState, snapshotState) {
121
122
  }
122
123
 
123
124
  // src/store-replay.ts
124
- var import_core = require("@angular/core");
125
+ var import_core2 = require("@angular/core");
125
126
 
126
127
  // src/store-messages.ts
127
128
  var INVALID_HISTORY_INDEX_ERROR = "History index is out of range";
128
129
  var INVALID_HISTORY_MESSAGE_ID_ERROR = "History message id is out of range";
129
130
  var MESSAGE_NOT_ACKNOWLEDGED_ERROR = "Message was not acknowledged";
131
+ var INVALID_STORE_KEY_ERROR = "Invalid store key";
132
+
133
+ // src/store-message-consumer.ts
134
+ var import_core = require("@flurryx/core");
135
+ function createDefaultState() {
136
+ return {
137
+ data: void 0,
138
+ isLoading: false,
139
+ status: void 0,
140
+ errors: void 0
141
+ };
142
+ }
143
+ function createStoreMessageConsumer(signals, notifier) {
144
+ function applyUpdate(key, newState, notify = true) {
145
+ const sig = signals.getOrCreate(key);
146
+ const previousState = sig();
147
+ sig.update((state) => ({ ...state, ...newState }));
148
+ if (notify) {
149
+ const updatedState = sig();
150
+ notifier.notify(key, updatedState, previousState);
151
+ }
152
+ return true;
153
+ }
154
+ function applyClear(key) {
155
+ const sig = signals.getOrCreate(key);
156
+ const previousState = sig();
157
+ sig.set(createDefaultState());
158
+ const nextState = sig();
159
+ notifier.notify(key, nextState, previousState);
160
+ return true;
161
+ }
162
+ function applyClearAll() {
163
+ const keys = Array.from(signals.getAllKeys());
164
+ if (keys.length === 0) {
165
+ return false;
166
+ }
167
+ keys.forEach((key) => {
168
+ applyClear(key);
169
+ });
170
+ return true;
171
+ }
172
+ function applyStartLoading(key) {
173
+ const sig = signals.getOrCreate(key);
174
+ sig.update(
175
+ (state) => ({
176
+ ...state,
177
+ status: void 0,
178
+ isLoading: true,
179
+ errors: void 0
180
+ })
181
+ );
182
+ return true;
183
+ }
184
+ function applyStopLoading(key) {
185
+ const sig = signals.getOrCreate(key);
186
+ sig.update(
187
+ (state) => ({
188
+ ...state,
189
+ isLoading: false
190
+ })
191
+ );
192
+ return true;
193
+ }
194
+ function applyUpdateKeyedOne(key, resourceKey, entity) {
195
+ const sig = signals.getOrCreate(key);
196
+ const state = sig();
197
+ const data = (0, import_core.isKeyedResourceData)(state.data) ? state.data : (0, import_core.createKeyedResourceData)();
198
+ const nextErrors = { ...data.errors };
199
+ delete nextErrors[resourceKey];
200
+ const nextData = {
201
+ ...data,
202
+ entities: { ...data.entities, [resourceKey]: entity },
203
+ isLoading: { ...data.isLoading, [resourceKey]: false },
204
+ status: { ...data.status, [resourceKey]: "Success" },
205
+ errors: nextErrors
206
+ };
207
+ return applyUpdate(key, {
208
+ data: nextData,
209
+ isLoading: (0, import_core.isAnyKeyLoading)(nextData.isLoading),
210
+ status: void 0,
211
+ errors: void 0
212
+ });
213
+ }
214
+ function applyClearKeyedOne(key, resourceKey) {
215
+ const sig = signals.getOrCreate(key);
216
+ const previousState = sig();
217
+ const state = previousState;
218
+ if (!(0, import_core.isKeyedResourceData)(state.data)) {
219
+ return true;
220
+ }
221
+ const data = state.data;
222
+ const nextEntities = { ...data.entities };
223
+ delete nextEntities[resourceKey];
224
+ const nextIsLoading = { ...data.isLoading };
225
+ delete nextIsLoading[resourceKey];
226
+ const nextStatus = { ...data.status };
227
+ delete nextStatus[resourceKey];
228
+ const nextErrors = { ...data.errors };
229
+ delete nextErrors[resourceKey];
230
+ const nextData = {
231
+ ...data,
232
+ entities: nextEntities,
233
+ isLoading: nextIsLoading,
234
+ status: nextStatus,
235
+ errors: nextErrors
236
+ };
237
+ sig.update(
238
+ (prev) => ({
239
+ ...prev,
240
+ data: nextData,
241
+ status: void 0,
242
+ isLoading: (0, import_core.isAnyKeyLoading)(nextIsLoading),
243
+ errors: void 0
244
+ })
245
+ );
246
+ const updatedState = sig();
247
+ notifier.notify(key, updatedState, previousState);
248
+ return true;
249
+ }
250
+ function applyStartKeyedLoading(key, resourceKey) {
251
+ const sig = signals.getOrCreate(key);
252
+ const state = sig();
253
+ if (!(0, import_core.isKeyedResourceData)(state.data)) {
254
+ return applyStartLoading(key);
255
+ }
256
+ const previousState = state;
257
+ const data = state.data;
258
+ const nextIsLoading = {
259
+ ...data.isLoading,
260
+ [resourceKey]: true
261
+ };
262
+ const nextStatus = { ...data.status };
263
+ delete nextStatus[resourceKey];
264
+ const nextErrors = { ...data.errors };
265
+ delete nextErrors[resourceKey];
266
+ const nextData = {
267
+ ...data,
268
+ isLoading: nextIsLoading,
269
+ status: nextStatus,
270
+ errors: nextErrors
271
+ };
272
+ sig.update(
273
+ (previous) => ({
274
+ ...previous,
275
+ data: nextData,
276
+ status: void 0,
277
+ isLoading: (0, import_core.isAnyKeyLoading)(nextIsLoading),
278
+ errors: void 0
279
+ })
280
+ );
281
+ const updatedState = sig();
282
+ notifier.notify(key, updatedState, previousState);
283
+ return true;
284
+ }
285
+ function applyMessage(message) {
286
+ switch (message.type) {
287
+ case "update":
288
+ return applyUpdate(message.key, cloneValue(message.state));
289
+ case "clear":
290
+ return applyClear(message.key);
291
+ case "clearAll":
292
+ return applyClearAll();
293
+ case "startLoading":
294
+ return applyStartLoading(message.key);
295
+ case "stopLoading":
296
+ return applyStopLoading(message.key);
297
+ case "updateKeyedOne":
298
+ return applyUpdateKeyedOne(
299
+ message.key,
300
+ message.resourceKey,
301
+ cloneValue(message.entity)
302
+ );
303
+ case "clearKeyedOne":
304
+ return applyClearKeyedOne(message.key, message.resourceKey);
305
+ case "startKeyedLoading":
306
+ return applyStartKeyedLoading(message.key, message.resourceKey);
307
+ }
308
+ }
309
+ function applySnapshot(snapshot) {
310
+ const keys = /* @__PURE__ */ new Set([
311
+ ...Array.from(signals.getAllKeys()),
312
+ ...Object.keys(snapshot)
313
+ ]);
314
+ keys.forEach((rawKey) => {
315
+ const key = rawKey;
316
+ const sig = signals.getOrCreate(key);
317
+ const snapshotState = snapshot[key] ?? createDefaultState();
318
+ applyUpdate(key, createSnapshotRestorePatch(sig(), snapshotState), true);
319
+ });
320
+ }
321
+ function captureSnapshot() {
322
+ const entries = Array.from(signals.getAllKeys()).map((key) => [
323
+ key,
324
+ cloneValue(signals.getOrCreate(key)())
325
+ ]);
326
+ return Object.fromEntries(entries);
327
+ }
328
+ function applyKeyUpdate(key, snapshotState) {
329
+ const sig = signals.getOrCreate(key);
330
+ const currentState = sig();
331
+ const patch = createSnapshotRestorePatch(currentState, snapshotState);
332
+ applyUpdate(key, patch, true);
333
+ }
334
+ return {
335
+ applyMessage,
336
+ applySnapshot,
337
+ applyKeyUpdate,
338
+ createSnapshot: captureSnapshot
339
+ };
340
+ }
341
+ function createUpdateMessage(key, state) {
342
+ return { type: "update", key, state };
343
+ }
344
+ function createClearMessage(key) {
345
+ return { type: "clear", key };
346
+ }
347
+ function createClearAllMessage() {
348
+ return { type: "clearAll" };
349
+ }
350
+ function createStartLoadingMessage(key) {
351
+ return { type: "startLoading", key };
352
+ }
353
+ function createStopLoadingMessage(key) {
354
+ return { type: "stopLoading", key };
355
+ }
356
+ function createUpdateKeyedOneMessage(key, resourceKey, entity) {
357
+ return {
358
+ type: "updateKeyedOne",
359
+ key,
360
+ resourceKey,
361
+ entity
362
+ };
363
+ }
364
+ function createClearKeyedOneMessage(key, resourceKey) {
365
+ return {
366
+ type: "clearKeyedOne",
367
+ key,
368
+ resourceKey
369
+ };
370
+ }
371
+ function createStartKeyedLoadingMessage(key, resourceKey) {
372
+ return {
373
+ type: "startKeyedLoading",
374
+ key,
375
+ resourceKey
376
+ };
377
+ }
130
378
 
131
379
  // src/store-channels.ts
132
380
  function serializeStoreMessageChannelValue(value) {
@@ -567,7 +815,7 @@ function createStoreHistory(config) {
567
815
  let messageCollection = createStableReadonlyCollection(
568
816
  messageChannel.getMessages().map((record) => cloneValue(record))
569
817
  );
570
- const version = (0, import_core.signal)(0);
818
+ const version = (0, import_core2.signal)(0);
571
819
  function notifyVersion() {
572
820
  version.update((v) => v + 1);
573
821
  }
@@ -601,24 +849,36 @@ function createStoreHistory(config) {
601
849
  throw new Error(INVALID_HISTORY_INDEX_ERROR);
602
850
  }
603
851
  }
604
- function travelTo(index) {
852
+ function restoreStoreAt(index) {
605
853
  ensureIndexInRange(index);
606
854
  config.applySnapshot(history[index].snapshot);
607
855
  currentIndex = index;
608
856
  notifyVersion();
609
857
  }
858
+ function restoreResource(key, index) {
859
+ const targetIndex = index !== void 0 ? index : currentIndex;
860
+ ensureIndexInRange(targetIndex);
861
+ const allKeys = new Set(Array.from(config.getAllKeys()));
862
+ if (!allKeys.has(key)) {
863
+ throw new Error(INVALID_STORE_KEY_ERROR);
864
+ }
865
+ const snapshot = history[targetIndex].snapshot;
866
+ const snapshotState = snapshot[key];
867
+ config.applyKeyUpdate(key, snapshotState ?? createDefaultState());
868
+ notifyVersion();
869
+ }
610
870
  function undo() {
611
871
  if (currentIndex === 0) {
612
872
  return false;
613
873
  }
614
- travelTo(currentIndex - 1);
874
+ restoreStoreAt(currentIndex - 1);
615
875
  return true;
616
876
  }
617
877
  function redo() {
618
878
  if (currentIndex >= history.length - 1) {
619
879
  return false;
620
880
  }
621
- travelTo(currentIndex + 1);
881
+ restoreStoreAt(currentIndex + 1);
622
882
  return true;
623
883
  }
624
884
  function getErrorMessage(error) {
@@ -721,11 +981,11 @@ function createStoreHistory(config) {
721
981
  });
722
982
  return acknowledgedCount;
723
983
  }
724
- const historySignal = (0, import_core.computed)(() => {
984
+ const historySignal = (0, import_core2.computed)(() => {
725
985
  version();
726
986
  return historyCollection;
727
987
  });
728
- const messagesSignal = (0, import_core.computed)(() => {
988
+ const messagesSignal = (0, import_core2.computed)(() => {
729
989
  version();
730
990
  messageCollection = syncStableReadonlyCollectionById({
731
991
  items: messageCollection,
@@ -736,7 +996,7 @@ function createStoreHistory(config) {
736
996
  });
737
997
  return messageCollection;
738
998
  });
739
- const currentIndexSignal = (0, import_core.computed)(() => {
999
+ const currentIndexSignal = (0, import_core2.computed)(() => {
740
1000
  version();
741
1001
  return currentIndex;
742
1002
  });
@@ -755,7 +1015,8 @@ function createStoreHistory(config) {
755
1015
  replay(input) {
756
1016
  return replayByIds(input);
757
1017
  },
758
- travelTo,
1018
+ restoreStoreAt,
1019
+ restoreResource,
759
1020
  undo,
760
1021
  redo,
761
1022
  getHistory(key) {
@@ -798,245 +1059,6 @@ function clearAllStores() {
798
1059
  }
799
1060
  }
800
1061
 
801
- // src/store-message-consumer.ts
802
- var import_core2 = require("@flurryx/core");
803
- function createDefaultState() {
804
- return {
805
- data: void 0,
806
- isLoading: false,
807
- status: void 0,
808
- errors: void 0
809
- };
810
- }
811
- function createStoreMessageConsumer(signals, notifier) {
812
- function applyUpdate(key, newState, notify = true) {
813
- const sig = signals.getOrCreate(key);
814
- const previousState = sig();
815
- sig.update((state) => ({ ...state, ...newState }));
816
- if (notify) {
817
- const updatedState = sig();
818
- notifier.notify(key, updatedState, previousState);
819
- }
820
- return true;
821
- }
822
- function applyClear(key) {
823
- const sig = signals.getOrCreate(key);
824
- const previousState = sig();
825
- sig.set(createDefaultState());
826
- const nextState = sig();
827
- notifier.notify(key, nextState, previousState);
828
- return true;
829
- }
830
- function applyClearAll() {
831
- const keys = Array.from(signals.getAllKeys());
832
- if (keys.length === 0) {
833
- return false;
834
- }
835
- keys.forEach((key) => {
836
- applyClear(key);
837
- });
838
- return true;
839
- }
840
- function applyStartLoading(key) {
841
- const sig = signals.getOrCreate(key);
842
- sig.update(
843
- (state) => ({
844
- ...state,
845
- status: void 0,
846
- isLoading: true,
847
- errors: void 0
848
- })
849
- );
850
- return true;
851
- }
852
- function applyStopLoading(key) {
853
- const sig = signals.getOrCreate(key);
854
- sig.update(
855
- (state) => ({
856
- ...state,
857
- isLoading: false
858
- })
859
- );
860
- return true;
861
- }
862
- function applyUpdateKeyedOne(key, resourceKey, entity) {
863
- const sig = signals.getOrCreate(key);
864
- const state = sig();
865
- const data = (0, import_core2.isKeyedResourceData)(state.data) ? state.data : (0, import_core2.createKeyedResourceData)();
866
- const nextErrors = { ...data.errors };
867
- delete nextErrors[resourceKey];
868
- const nextData = {
869
- ...data,
870
- entities: { ...data.entities, [resourceKey]: entity },
871
- isLoading: { ...data.isLoading, [resourceKey]: false },
872
- status: { ...data.status, [resourceKey]: "Success" },
873
- errors: nextErrors
874
- };
875
- return applyUpdate(key, {
876
- data: nextData,
877
- isLoading: (0, import_core2.isAnyKeyLoading)(nextData.isLoading),
878
- status: void 0,
879
- errors: void 0
880
- });
881
- }
882
- function applyClearKeyedOne(key, resourceKey) {
883
- const sig = signals.getOrCreate(key);
884
- const previousState = sig();
885
- const state = previousState;
886
- if (!(0, import_core2.isKeyedResourceData)(state.data)) {
887
- return true;
888
- }
889
- const data = state.data;
890
- const nextEntities = { ...data.entities };
891
- delete nextEntities[resourceKey];
892
- const nextIsLoading = { ...data.isLoading };
893
- delete nextIsLoading[resourceKey];
894
- const nextStatus = { ...data.status };
895
- delete nextStatus[resourceKey];
896
- const nextErrors = { ...data.errors };
897
- delete nextErrors[resourceKey];
898
- const nextData = {
899
- ...data,
900
- entities: nextEntities,
901
- isLoading: nextIsLoading,
902
- status: nextStatus,
903
- errors: nextErrors
904
- };
905
- sig.update(
906
- (prev) => ({
907
- ...prev,
908
- data: nextData,
909
- status: void 0,
910
- isLoading: (0, import_core2.isAnyKeyLoading)(nextIsLoading),
911
- errors: void 0
912
- })
913
- );
914
- const updatedState = sig();
915
- notifier.notify(key, updatedState, previousState);
916
- return true;
917
- }
918
- function applyStartKeyedLoading(key, resourceKey) {
919
- const sig = signals.getOrCreate(key);
920
- const state = sig();
921
- if (!(0, import_core2.isKeyedResourceData)(state.data)) {
922
- return applyStartLoading(key);
923
- }
924
- const previousState = state;
925
- const data = state.data;
926
- const nextIsLoading = {
927
- ...data.isLoading,
928
- [resourceKey]: true
929
- };
930
- const nextStatus = { ...data.status };
931
- delete nextStatus[resourceKey];
932
- const nextErrors = { ...data.errors };
933
- delete nextErrors[resourceKey];
934
- const nextData = {
935
- ...data,
936
- isLoading: nextIsLoading,
937
- status: nextStatus,
938
- errors: nextErrors
939
- };
940
- sig.update(
941
- (previous) => ({
942
- ...previous,
943
- data: nextData,
944
- status: void 0,
945
- isLoading: (0, import_core2.isAnyKeyLoading)(nextIsLoading),
946
- errors: void 0
947
- })
948
- );
949
- const updatedState = sig();
950
- notifier.notify(key, updatedState, previousState);
951
- return true;
952
- }
953
- function applyMessage(message) {
954
- switch (message.type) {
955
- case "update":
956
- return applyUpdate(message.key, cloneValue(message.state));
957
- case "clear":
958
- return applyClear(message.key);
959
- case "clearAll":
960
- return applyClearAll();
961
- case "startLoading":
962
- return applyStartLoading(message.key);
963
- case "stopLoading":
964
- return applyStopLoading(message.key);
965
- case "updateKeyedOne":
966
- return applyUpdateKeyedOne(
967
- message.key,
968
- message.resourceKey,
969
- cloneValue(message.entity)
970
- );
971
- case "clearKeyedOne":
972
- return applyClearKeyedOne(message.key, message.resourceKey);
973
- case "startKeyedLoading":
974
- return applyStartKeyedLoading(message.key, message.resourceKey);
975
- }
976
- }
977
- function applySnapshot(snapshot) {
978
- const keys = /* @__PURE__ */ new Set([
979
- ...Array.from(signals.getAllKeys()),
980
- ...Object.keys(snapshot)
981
- ]);
982
- keys.forEach((rawKey) => {
983
- const key = rawKey;
984
- const sig = signals.getOrCreate(key);
985
- const snapshotState = snapshot[key] ?? createDefaultState();
986
- applyUpdate(key, createSnapshotRestorePatch(sig(), snapshotState), true);
987
- });
988
- }
989
- function captureSnapshot() {
990
- const entries = Array.from(signals.getAllKeys()).map((key) => [
991
- key,
992
- cloneValue(signals.getOrCreate(key)())
993
- ]);
994
- return Object.fromEntries(entries);
995
- }
996
- return {
997
- applyMessage,
998
- applySnapshot,
999
- createSnapshot: captureSnapshot
1000
- };
1001
- }
1002
- function createUpdateMessage(key, state) {
1003
- return { type: "update", key, state };
1004
- }
1005
- function createClearMessage(key) {
1006
- return { type: "clear", key };
1007
- }
1008
- function createClearAllMessage() {
1009
- return { type: "clearAll" };
1010
- }
1011
- function createStartLoadingMessage(key) {
1012
- return { type: "startLoading", key };
1013
- }
1014
- function createStopLoadingMessage(key) {
1015
- return { type: "stopLoading", key };
1016
- }
1017
- function createUpdateKeyedOneMessage(key, resourceKey, entity) {
1018
- return {
1019
- type: "updateKeyedOne",
1020
- key,
1021
- resourceKey,
1022
- entity
1023
- };
1024
- }
1025
- function createClearKeyedOneMessage(key, resourceKey) {
1026
- return {
1027
- type: "clearKeyedOne",
1028
- key,
1029
- resourceKey
1030
- };
1031
- }
1032
- function createStartKeyedLoadingMessage(key, resourceKey) {
1033
- return {
1034
- type: "startKeyedLoading",
1035
- key,
1036
- resourceKey
1037
- };
1038
- }
1039
-
1040
1062
  // src/base-store.ts
1041
1063
  var updateHooksMap = /* @__PURE__ */ new WeakMap();
1042
1064
  var BaseStore = class {
@@ -1057,6 +1079,8 @@ var BaseStore = class {
1057
1079
  this.historyDriver = createStoreHistory({
1058
1080
  captureSnapshot: () => consumer.createSnapshot(),
1059
1081
  applySnapshot: (snapshot) => consumer.applySnapshot(snapshot),
1082
+ applyKeyUpdate: (key, snapshotState) => consumer.applyKeyUpdate(key, snapshotState),
1083
+ getAllKeys: () => this.storeKeys,
1060
1084
  applyMessage: (message) => consumer.applyMessage(message),
1061
1085
  channel: options?.channel
1062
1086
  });
@@ -1070,7 +1094,9 @@ var BaseStore = class {
1070
1094
  storeKeys;
1071
1095
  historyDriver;
1072
1096
  /** @inheritDoc */
1073
- travelTo = (index) => this.historyDriver.travelTo(index);
1097
+ restoreStoreAt = (index) => this.historyDriver.restoreStoreAt(index);
1098
+ /** @inheritDoc */
1099
+ restoreResource = (key, index) => this.historyDriver.restoreResource(key, index);
1074
1100
  /** @inheritDoc */
1075
1101
  undo = () => this.historyDriver.undo();
1076
1102
  /** @inheritDoc */
@@ -1276,7 +1302,9 @@ var LazyStore = class {
1276
1302
  hooks = /* @__PURE__ */ new Map();
1277
1303
  historyDriver;
1278
1304
  /** @inheritDoc */
1279
- travelTo = (index) => this.historyDriver.travelTo(index);
1305
+ restoreStoreAt = (index) => this.historyDriver.restoreStoreAt(index);
1306
+ /** @inheritDoc */
1307
+ restoreResource = (key, index) => this.historyDriver.restoreResource(key, index);
1280
1308
  /** @inheritDoc */
1281
1309
  undo = () => this.historyDriver.undo();
1282
1310
  /** @inheritDoc */
@@ -1328,6 +1356,8 @@ var LazyStore = class {
1328
1356
  this.historyDriver = createStoreHistory({
1329
1357
  captureSnapshot: () => consumer.createSnapshot(),
1330
1358
  applySnapshot: (snapshot) => consumer.applySnapshot(snapshot),
1359
+ applyKeyUpdate: (key, snapshotState) => consumer.applyKeyUpdate(key, snapshotState),
1360
+ getAllKeys: () => this.signals.keys(),
1331
1361
  applyMessage: (message) => consumer.applyMessage(message),
1332
1362
  channel: options?.channel
1333
1363
  });
@@ -1824,6 +1854,7 @@ function createStoreFor(enumObj) {
1824
1854
  // Annotate the CommonJS export names for ESM import in node:
1825
1855
  0 && (module.exports = {
1826
1856
  BaseStore,
1857
+ INVALID_STORE_KEY_ERROR,
1827
1858
  LazyStore,
1828
1859
  Store,
1829
1860
  clearAllStores,