@flurryx/store 0.8.4 → 1.0.0
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 +1044 -326
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +558 -18
- package/dist/index.d.ts +558 -18
- package/dist/index.js +1038 -331
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,32 +1,898 @@
|
|
|
1
1
|
// src/base-store.ts
|
|
2
2
|
import { signal } from "@angular/core";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
|
|
4
|
+
// src/store-clone.ts
|
|
5
|
+
function cloneValue(value) {
|
|
6
|
+
if (value !== null && typeof value === "object") {
|
|
7
|
+
const existingClone = cloneReference(value, /* @__PURE__ */ new WeakMap());
|
|
8
|
+
return existingClone;
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
function cloneReference(value, seen) {
|
|
13
|
+
const seenClone = seen.get(value);
|
|
14
|
+
if (seenClone) {
|
|
15
|
+
return seenClone;
|
|
16
|
+
}
|
|
17
|
+
if (value instanceof Date) {
|
|
18
|
+
return new Date(value.getTime());
|
|
19
|
+
}
|
|
20
|
+
if (value instanceof Map) {
|
|
21
|
+
const clonedMap = /* @__PURE__ */ new Map();
|
|
22
|
+
seen.set(value, clonedMap);
|
|
23
|
+
value.forEach((entryValue, key) => {
|
|
24
|
+
clonedMap.set(
|
|
25
|
+
cloneValueWithSeen(key, seen),
|
|
26
|
+
cloneValueWithSeen(entryValue, seen)
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
return clonedMap;
|
|
30
|
+
}
|
|
31
|
+
if (value instanceof Set) {
|
|
32
|
+
const clonedSet = /* @__PURE__ */ new Set();
|
|
33
|
+
seen.set(value, clonedSet);
|
|
34
|
+
value.forEach((entryValue) => {
|
|
35
|
+
clonedSet.add(cloneValueWithSeen(entryValue, seen));
|
|
36
|
+
});
|
|
37
|
+
return clonedSet;
|
|
38
|
+
}
|
|
39
|
+
if (Array.isArray(value)) {
|
|
40
|
+
const clonedArray = [];
|
|
41
|
+
seen.set(value, clonedArray);
|
|
42
|
+
value.forEach((item, index) => {
|
|
43
|
+
clonedArray[index] = cloneValueWithSeen(item, seen);
|
|
44
|
+
});
|
|
45
|
+
return clonedArray;
|
|
46
|
+
}
|
|
47
|
+
const clonedObject = Object.create(Object.getPrototypeOf(value));
|
|
48
|
+
seen.set(value, clonedObject);
|
|
49
|
+
Reflect.ownKeys(value).forEach((key) => {
|
|
50
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
51
|
+
if (!descriptor) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if ("value" in descriptor) {
|
|
55
|
+
descriptor.value = cloneValueWithSeen(descriptor.value, seen);
|
|
56
|
+
}
|
|
57
|
+
Object.defineProperty(clonedObject, key, descriptor);
|
|
58
|
+
});
|
|
59
|
+
return clonedObject;
|
|
60
|
+
}
|
|
61
|
+
function cloneValueWithSeen(value, seen) {
|
|
62
|
+
if (value !== null && typeof value === "object") {
|
|
63
|
+
return cloneReference(value, seen);
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
function createSnapshotRestorePatch(currentState, snapshotState) {
|
|
68
|
+
const patch = {};
|
|
69
|
+
const keys = /* @__PURE__ */ new Set([
|
|
70
|
+
...Reflect.ownKeys(currentState),
|
|
71
|
+
...Reflect.ownKeys(snapshotState)
|
|
72
|
+
]);
|
|
73
|
+
keys.forEach((key) => {
|
|
74
|
+
if (Object.prototype.hasOwnProperty.call(snapshotState, key)) {
|
|
75
|
+
patch[key] = cloneValue(
|
|
76
|
+
snapshotState[key]
|
|
77
|
+
);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
patch[key] = void 0;
|
|
81
|
+
});
|
|
82
|
+
return patch;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/store-messages.ts
|
|
86
|
+
var INVALID_HISTORY_INDEX_ERROR = "History index is out of range";
|
|
87
|
+
var INVALID_HISTORY_MESSAGE_ID_ERROR = "History message id is out of range";
|
|
88
|
+
var MESSAGE_NOT_ACKNOWLEDGED_ERROR = "Message was not acknowledged";
|
|
89
|
+
|
|
90
|
+
// src/store-channels.ts
|
|
91
|
+
function serializeStoreMessageChannelValue(value) {
|
|
92
|
+
if (value === void 0) {
|
|
93
|
+
return { __flurryxType: "undefined" };
|
|
94
|
+
}
|
|
95
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
if (value instanceof Date) {
|
|
99
|
+
return {
|
|
100
|
+
__flurryxType: "date",
|
|
101
|
+
value: value.toISOString()
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (value instanceof Map) {
|
|
105
|
+
return {
|
|
106
|
+
__flurryxType: "map",
|
|
107
|
+
entries: Array.from(value.entries(), ([key, entryValue]) => [
|
|
108
|
+
serializeStoreMessageChannelValue(key),
|
|
109
|
+
serializeStoreMessageChannelValue(entryValue)
|
|
110
|
+
])
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (value instanceof Set) {
|
|
114
|
+
return {
|
|
115
|
+
__flurryxType: "set",
|
|
116
|
+
values: Array.from(
|
|
117
|
+
value.values(),
|
|
118
|
+
(entryValue) => serializeStoreMessageChannelValue(entryValue)
|
|
119
|
+
)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (Array.isArray(value)) {
|
|
123
|
+
return {
|
|
124
|
+
__flurryxType: "array",
|
|
125
|
+
values: value.map(
|
|
126
|
+
(entryValue) => serializeStoreMessageChannelValue(entryValue)
|
|
127
|
+
)
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (typeof value === "object") {
|
|
131
|
+
return {
|
|
132
|
+
__flurryxType: "object",
|
|
133
|
+
entries: Object.entries(value).map(
|
|
134
|
+
([key, entryValue]) => [
|
|
135
|
+
key,
|
|
136
|
+
serializeStoreMessageChannelValue(entryValue)
|
|
137
|
+
]
|
|
138
|
+
)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
throw new Error("Store message channel cannot serialize this value");
|
|
142
|
+
}
|
|
143
|
+
function deserializeStoreMessageChannelValue(value) {
|
|
144
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
145
|
+
return value;
|
|
146
|
+
}
|
|
147
|
+
switch (value.__flurryxType) {
|
|
148
|
+
case "undefined":
|
|
149
|
+
return void 0;
|
|
150
|
+
case "date":
|
|
151
|
+
return new Date(value.value);
|
|
152
|
+
case "array":
|
|
153
|
+
return value.values.map(
|
|
154
|
+
(entryValue) => deserializeStoreMessageChannelValue(entryValue)
|
|
155
|
+
);
|
|
156
|
+
case "set":
|
|
157
|
+
return new Set(
|
|
158
|
+
value.values.map(
|
|
159
|
+
(entryValue) => deserializeStoreMessageChannelValue(entryValue)
|
|
160
|
+
)
|
|
161
|
+
);
|
|
162
|
+
case "map":
|
|
163
|
+
return new Map(
|
|
164
|
+
value.entries.map(([key, entryValue]) => [
|
|
165
|
+
deserializeStoreMessageChannelValue(key),
|
|
166
|
+
deserializeStoreMessageChannelValue(entryValue)
|
|
167
|
+
])
|
|
168
|
+
);
|
|
169
|
+
case "object": {
|
|
170
|
+
const result = {};
|
|
171
|
+
value.entries.forEach(([key, entryValue]) => {
|
|
172
|
+
result[key] = deserializeStoreMessageChannelValue(entryValue);
|
|
173
|
+
});
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function defaultSerializeStoreMessageChannelState(state) {
|
|
179
|
+
return JSON.stringify(serializeStoreMessageChannelValue(state));
|
|
180
|
+
}
|
|
181
|
+
function defaultDeserializeStoreMessageChannelState(value) {
|
|
182
|
+
return deserializeStoreMessageChannelValue(
|
|
183
|
+
JSON.parse(value)
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
function normalizeStoreMessageChannelState(state) {
|
|
187
|
+
const maxId = state.messages.reduce(
|
|
188
|
+
(currentMax, entry) => Math.max(currentMax, entry.id),
|
|
189
|
+
0
|
|
190
|
+
);
|
|
191
|
+
return {
|
|
192
|
+
nextId: Math.max(state.nextId, maxId + 1),
|
|
193
|
+
messages: state.messages.map((entry) => cloneValue(entry))
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function createInitialStoreMessageRecord(id, message, clock = Date.now) {
|
|
197
|
+
return {
|
|
198
|
+
id,
|
|
199
|
+
message: cloneValue(message),
|
|
200
|
+
status: "pending",
|
|
201
|
+
attempts: 0,
|
|
202
|
+
createdAt: clock(),
|
|
203
|
+
lastAttemptedAt: null,
|
|
204
|
+
acknowledgedAt: null,
|
|
205
|
+
error: null
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function isQuotaExceededError(error) {
|
|
209
|
+
return error instanceof DOMException && (error.code === 22 || error.code === 1014 || error.name === "QuotaExceededError" || error.name === "NS_ERROR_DOM_QUOTA_REACHED");
|
|
210
|
+
}
|
|
211
|
+
function resolveGlobalStorage(name) {
|
|
212
|
+
const storage = globalThis[name];
|
|
213
|
+
if (!storage) {
|
|
214
|
+
throw new Error(`${name} is not available in this environment`);
|
|
215
|
+
}
|
|
216
|
+
return storage;
|
|
217
|
+
}
|
|
218
|
+
function createInMemoryStoreMessageChannel() {
|
|
219
|
+
let messages = [];
|
|
220
|
+
let nextId = 1;
|
|
221
|
+
return {
|
|
222
|
+
publish(message) {
|
|
223
|
+
const record = createInitialStoreMessageRecord(nextId++, message);
|
|
224
|
+
messages = [...messages, record];
|
|
225
|
+
return cloneValue(record);
|
|
226
|
+
},
|
|
227
|
+
getMessage(id) {
|
|
228
|
+
const record = messages.find((entry) => entry.id === id);
|
|
229
|
+
return record ? cloneValue(record) : void 0;
|
|
230
|
+
},
|
|
231
|
+
getMessages() {
|
|
232
|
+
return messages.map((entry) => cloneValue(entry));
|
|
233
|
+
},
|
|
234
|
+
saveMessage(entry) {
|
|
235
|
+
const record = cloneValue(entry);
|
|
236
|
+
const existingIndex = messages.findIndex(
|
|
237
|
+
(candidate) => candidate.id === record.id
|
|
238
|
+
);
|
|
239
|
+
if (existingIndex === -1) {
|
|
240
|
+
messages = [...messages, record];
|
|
241
|
+
} else {
|
|
242
|
+
messages = messages.map((c, i) => i === existingIndex ? record : c);
|
|
243
|
+
}
|
|
244
|
+
nextId = Math.max(nextId, record.id + 1);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function createStorageStoreMessageChannel(options) {
|
|
249
|
+
const serialize = options.serialize ?? defaultSerializeStoreMessageChannelState;
|
|
250
|
+
const deserialize = options.deserialize ?? defaultDeserializeStoreMessageChannelState;
|
|
251
|
+
function readState() {
|
|
252
|
+
const rawState = options.storage.getItem(options.storageKey);
|
|
253
|
+
if (rawState === null) {
|
|
254
|
+
return { nextId: 1, messages: [] };
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
return normalizeStoreMessageChannelState(deserialize(rawState));
|
|
258
|
+
} catch {
|
|
259
|
+
return { nextId: 1, messages: [] };
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function writeState(state) {
|
|
263
|
+
const normalized = normalizeStoreMessageChannelState(state);
|
|
264
|
+
try {
|
|
265
|
+
options.storage.setItem(options.storageKey, serialize(normalized));
|
|
266
|
+
} catch (error) {
|
|
267
|
+
if (!isQuotaExceededError(error) || normalized.messages.length === 0) {
|
|
268
|
+
throw error;
|
|
269
|
+
}
|
|
270
|
+
let remaining = [...normalized.messages];
|
|
271
|
+
while (remaining.length > 0) {
|
|
272
|
+
remaining = remaining.slice(1);
|
|
273
|
+
try {
|
|
274
|
+
options.storage.setItem(
|
|
275
|
+
options.storageKey,
|
|
276
|
+
serialize({ nextId: normalized.nextId, messages: remaining })
|
|
277
|
+
);
|
|
278
|
+
return;
|
|
279
|
+
} catch (retryError) {
|
|
280
|
+
if (!isQuotaExceededError(retryError)) {
|
|
281
|
+
throw retryError;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
options.storage.setItem(
|
|
286
|
+
options.storageKey,
|
|
287
|
+
serialize({ nextId: normalized.nextId, messages: [] })
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
publish(message) {
|
|
293
|
+
const state = readState();
|
|
294
|
+
const record = createInitialStoreMessageRecord(state.nextId, message);
|
|
295
|
+
writeState({
|
|
296
|
+
nextId: state.nextId + 1,
|
|
297
|
+
messages: [...state.messages, record]
|
|
298
|
+
});
|
|
299
|
+
return cloneValue(record);
|
|
300
|
+
},
|
|
301
|
+
getMessage(id) {
|
|
302
|
+
const record = readState().messages.find((entry) => entry.id === id);
|
|
303
|
+
return record ? cloneValue(record) : void 0;
|
|
304
|
+
},
|
|
305
|
+
getMessages() {
|
|
306
|
+
return readState().messages.map((entry) => cloneValue(entry));
|
|
307
|
+
},
|
|
308
|
+
saveMessage(entry) {
|
|
309
|
+
const state = readState();
|
|
310
|
+
const record = cloneValue(entry);
|
|
311
|
+
const existingIndex = state.messages.findIndex(
|
|
312
|
+
(candidate) => candidate.id === record.id
|
|
313
|
+
);
|
|
314
|
+
if (existingIndex === -1) {
|
|
315
|
+
writeState({
|
|
316
|
+
nextId: Math.max(state.nextId, record.id + 1),
|
|
317
|
+
messages: [...state.messages, record]
|
|
318
|
+
});
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const nextMessages = state.messages.map(
|
|
322
|
+
(c, i) => i === existingIndex ? record : c
|
|
323
|
+
);
|
|
324
|
+
writeState({
|
|
325
|
+
nextId: Math.max(state.nextId, record.id + 1),
|
|
326
|
+
messages: nextMessages
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function createLocalStorageStoreMessageChannel(options) {
|
|
332
|
+
return createStorageStoreMessageChannel({
|
|
333
|
+
...options,
|
|
334
|
+
storage: options.storage ?? resolveGlobalStorage("localStorage")
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
function createSessionStorageStoreMessageChannel(options) {
|
|
338
|
+
return createStorageStoreMessageChannel({
|
|
339
|
+
...options,
|
|
340
|
+
storage: options.storage ?? resolveGlobalStorage("sessionStorage")
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
function createCompositeStoreMessageChannel(options) {
|
|
344
|
+
if (options.channels.length === 0) {
|
|
345
|
+
throw new Error(
|
|
346
|
+
"createCompositeStoreMessageChannel: 'channels' option must contain at least one channel"
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
const primaryChannel = options.channels[0];
|
|
350
|
+
const replicaChannels = options.channels.slice(1);
|
|
351
|
+
return {
|
|
352
|
+
publish(message) {
|
|
353
|
+
const record = primaryChannel.publish(message);
|
|
354
|
+
replicaChannels.forEach((channel) => {
|
|
355
|
+
channel.saveMessage(record);
|
|
356
|
+
});
|
|
357
|
+
return cloneValue(record);
|
|
358
|
+
},
|
|
359
|
+
getMessage(id) {
|
|
360
|
+
const record = primaryChannel.getMessage(id);
|
|
361
|
+
return record ? cloneValue(record) : void 0;
|
|
362
|
+
},
|
|
363
|
+
getMessages() {
|
|
364
|
+
return primaryChannel.getMessages().map((record) => cloneValue(record));
|
|
365
|
+
},
|
|
366
|
+
saveMessage(entry) {
|
|
367
|
+
primaryChannel.saveMessage(entry);
|
|
368
|
+
replicaChannels.forEach((channel) => {
|
|
369
|
+
channel.saveMessage(entry);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/store-replay.ts
|
|
376
|
+
function messageAffectsKey(message, key) {
|
|
377
|
+
if (message.type === "clearAll") {
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
return "key" in message && message.key === key;
|
|
381
|
+
}
|
|
382
|
+
function toDeadLetterEntry(record) {
|
|
383
|
+
return {
|
|
384
|
+
id: record.id,
|
|
385
|
+
message: cloneValue(record.message),
|
|
386
|
+
attempts: record.attempts,
|
|
387
|
+
error: record.error ?? MESSAGE_NOT_ACKNOWLEDGED_ERROR,
|
|
388
|
+
failedAt: record.lastAttemptedAt ?? record.createdAt
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
function createStoreHistory(config) {
|
|
392
|
+
const messageChannel = config.channel ?? createInMemoryStoreMessageChannel();
|
|
393
|
+
const clock = config.clock ?? Date.now;
|
|
394
|
+
let history = [
|
|
395
|
+
{
|
|
396
|
+
id: null,
|
|
397
|
+
index: 0,
|
|
398
|
+
message: null,
|
|
399
|
+
snapshot: config.captureSnapshot(),
|
|
400
|
+
acknowledgedAt: null
|
|
401
|
+
}
|
|
402
|
+
];
|
|
403
|
+
let currentIndex = 0;
|
|
404
|
+
function recordSnapshot(record) {
|
|
405
|
+
const nextIndex = history.length;
|
|
406
|
+
history = [
|
|
407
|
+
...history,
|
|
408
|
+
{
|
|
409
|
+
id: record.id,
|
|
410
|
+
index: nextIndex,
|
|
411
|
+
message: cloneValue(record.message),
|
|
412
|
+
snapshot: config.captureSnapshot(),
|
|
413
|
+
acknowledgedAt: record.acknowledgedAt
|
|
414
|
+
}
|
|
415
|
+
];
|
|
416
|
+
currentIndex = nextIndex;
|
|
417
|
+
}
|
|
418
|
+
function truncateFutureHistory() {
|
|
419
|
+
if (currentIndex === history.length - 1) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
history = history.slice(0, currentIndex + 1);
|
|
423
|
+
}
|
|
424
|
+
function ensureIndexInRange(index) {
|
|
425
|
+
if (!Number.isInteger(index) || index < 0 || index >= history.length) {
|
|
426
|
+
throw new Error(INVALID_HISTORY_INDEX_ERROR);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
function travelTo(index) {
|
|
430
|
+
ensureIndexInRange(index);
|
|
431
|
+
config.applySnapshot(history[index].snapshot);
|
|
432
|
+
currentIndex = index;
|
|
433
|
+
}
|
|
434
|
+
function undo() {
|
|
435
|
+
if (currentIndex === 0) {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
travelTo(currentIndex - 1);
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
function redo() {
|
|
442
|
+
if (currentIndex >= history.length - 1) {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
travelTo(currentIndex + 1);
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
function getErrorMessage(error) {
|
|
449
|
+
if (error instanceof Error && error.message) {
|
|
450
|
+
return error.message;
|
|
451
|
+
}
|
|
452
|
+
return MESSAGE_NOT_ACKNOWLEDGED_ERROR;
|
|
453
|
+
}
|
|
454
|
+
function persistMessageAttempt(record, status, error, attemptedAt) {
|
|
455
|
+
const nextRecord = {
|
|
456
|
+
...record,
|
|
457
|
+
message: cloneValue(record.message),
|
|
458
|
+
status,
|
|
459
|
+
attempts: record.attempts + 1,
|
|
460
|
+
lastAttemptedAt: attemptedAt,
|
|
461
|
+
acknowledgedAt: status === "acknowledged" ? attemptedAt : record.acknowledgedAt,
|
|
462
|
+
error
|
|
463
|
+
};
|
|
464
|
+
messageChannel.saveMessage(nextRecord);
|
|
465
|
+
return nextRecord;
|
|
466
|
+
}
|
|
467
|
+
function consumeRecord(record, options) {
|
|
468
|
+
const clonedMessage = cloneValue(record.message);
|
|
469
|
+
const attemptedAt = clock();
|
|
470
|
+
try {
|
|
471
|
+
const acknowledged = config.applyMessage(clonedMessage);
|
|
472
|
+
if (!acknowledged) {
|
|
473
|
+
throw new Error(MESSAGE_NOT_ACKNOWLEDGED_ERROR);
|
|
474
|
+
}
|
|
475
|
+
const acknowledgedRecord = persistMessageAttempt(
|
|
476
|
+
{
|
|
477
|
+
...record,
|
|
478
|
+
message: clonedMessage
|
|
479
|
+
},
|
|
480
|
+
"acknowledged",
|
|
481
|
+
null,
|
|
482
|
+
attemptedAt
|
|
483
|
+
);
|
|
484
|
+
if (options?.recordHistory !== false) {
|
|
485
|
+
truncateFutureHistory();
|
|
486
|
+
recordSnapshot(acknowledgedRecord);
|
|
487
|
+
}
|
|
488
|
+
return true;
|
|
489
|
+
} catch (error) {
|
|
490
|
+
persistMessageAttempt(
|
|
491
|
+
{
|
|
492
|
+
...record,
|
|
493
|
+
message: clonedMessage
|
|
494
|
+
},
|
|
495
|
+
"dead-letter",
|
|
496
|
+
getErrorMessage(error),
|
|
497
|
+
attemptedAt
|
|
498
|
+
);
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
function resolveReplayRecords(ids) {
|
|
503
|
+
return ids.map((id) => {
|
|
504
|
+
if (!Number.isInteger(id) || id < 1) {
|
|
505
|
+
throw new Error(INVALID_HISTORY_MESSAGE_ID_ERROR);
|
|
506
|
+
}
|
|
507
|
+
const record = messageChannel.getMessage(id);
|
|
508
|
+
if (!record) {
|
|
509
|
+
throw new Error(INVALID_HISTORY_MESSAGE_ID_ERROR);
|
|
510
|
+
}
|
|
511
|
+
return cloneValue(record);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
function replayByIds(input) {
|
|
515
|
+
const ids = Array.isArray(input) ? input : [input];
|
|
516
|
+
const records = resolveReplayRecords(ids);
|
|
517
|
+
let acknowledgedCount = 0;
|
|
518
|
+
records.forEach((record) => {
|
|
519
|
+
if (consumeRecord(record)) {
|
|
520
|
+
acknowledgedCount += 1;
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
return acknowledgedCount;
|
|
524
|
+
}
|
|
525
|
+
function replayDeadLetter(id) {
|
|
526
|
+
const record = messageChannel.getMessage(id);
|
|
527
|
+
if (!record || record.status !== "dead-letter") {
|
|
528
|
+
return false;
|
|
529
|
+
}
|
|
530
|
+
return consumeRecord(record);
|
|
531
|
+
}
|
|
532
|
+
function replayDeadLetters() {
|
|
533
|
+
const ids = messageChannel.getMessages().filter((record) => record.status === "dead-letter").map((record) => record.id);
|
|
534
|
+
let acknowledgedCount = 0;
|
|
535
|
+
ids.forEach((id) => {
|
|
536
|
+
if (replayDeadLetter(id)) {
|
|
537
|
+
acknowledgedCount += 1;
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
return acknowledgedCount;
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
publish(message) {
|
|
544
|
+
const record = messageChannel.publish(message);
|
|
545
|
+
return consumeRecord(record);
|
|
546
|
+
},
|
|
547
|
+
replay(input) {
|
|
548
|
+
return replayByIds(input);
|
|
549
|
+
},
|
|
550
|
+
travelTo,
|
|
551
|
+
undo,
|
|
552
|
+
redo,
|
|
553
|
+
getHistory(key) {
|
|
554
|
+
if (key === void 0) {
|
|
555
|
+
return history.map((entry) => cloneValue(entry));
|
|
556
|
+
}
|
|
557
|
+
return history.filter((entry) => {
|
|
558
|
+
if (entry.message === null) {
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
return messageAffectsKey(entry.message, key);
|
|
562
|
+
}).map((entry) => cloneValue(entry));
|
|
563
|
+
},
|
|
564
|
+
getMessages(key) {
|
|
565
|
+
const records = messageChannel.getMessages();
|
|
566
|
+
if (key === void 0) {
|
|
567
|
+
return records.map((record) => cloneValue(record));
|
|
568
|
+
}
|
|
569
|
+
return records.filter((record) => messageAffectsKey(record.message, key)).map((record) => cloneValue(record));
|
|
570
|
+
},
|
|
571
|
+
getDeadLetters() {
|
|
572
|
+
return messageChannel.getMessages().filter((record) => record.status === "dead-letter").map((record) => toDeadLetterEntry(record));
|
|
573
|
+
},
|
|
574
|
+
replayDeadLetter,
|
|
575
|
+
replayDeadLetters,
|
|
576
|
+
getCurrentIndex() {
|
|
577
|
+
return currentIndex;
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
}
|
|
8
581
|
|
|
9
582
|
// src/store-registry.ts
|
|
10
583
|
var trackedStores = /* @__PURE__ */ new Set();
|
|
11
584
|
function trackStore(store) {
|
|
12
585
|
trackedStores.add(store);
|
|
13
586
|
}
|
|
14
|
-
function clearAllStores() {
|
|
15
|
-
for (const store of [...trackedStores]) {
|
|
16
|
-
store.clearAll();
|
|
17
|
-
}
|
|
587
|
+
function clearAllStores() {
|
|
588
|
+
for (const store of [...trackedStores]) {
|
|
589
|
+
store.clearAll();
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// src/store-message-consumer.ts
|
|
594
|
+
import {
|
|
595
|
+
isKeyedResourceData,
|
|
596
|
+
createKeyedResourceData,
|
|
597
|
+
isAnyKeyLoading
|
|
598
|
+
} from "@flurryx/core";
|
|
599
|
+
function createDefaultState() {
|
|
600
|
+
return {
|
|
601
|
+
data: void 0,
|
|
602
|
+
isLoading: false,
|
|
603
|
+
status: void 0,
|
|
604
|
+
errors: void 0
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
function createStoreMessageConsumer(signals, notifier) {
|
|
608
|
+
function applyUpdate(key, newState, notify = true) {
|
|
609
|
+
const sig = signals.getOrCreate(key);
|
|
610
|
+
const previousState = sig();
|
|
611
|
+
sig.update((state) => ({ ...state, ...newState }));
|
|
612
|
+
if (notify) {
|
|
613
|
+
const updatedState = sig();
|
|
614
|
+
notifier.notify(key, updatedState, previousState);
|
|
615
|
+
}
|
|
616
|
+
return true;
|
|
617
|
+
}
|
|
618
|
+
function applyClear(key) {
|
|
619
|
+
const sig = signals.getOrCreate(key);
|
|
620
|
+
const previousState = sig();
|
|
621
|
+
sig.set(createDefaultState());
|
|
622
|
+
const nextState = sig();
|
|
623
|
+
notifier.notify(key, nextState, previousState);
|
|
624
|
+
return true;
|
|
625
|
+
}
|
|
626
|
+
function applyClearAll() {
|
|
627
|
+
const keys = Array.from(signals.getAllKeys());
|
|
628
|
+
if (keys.length === 0) {
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
keys.forEach((key) => {
|
|
632
|
+
applyClear(key);
|
|
633
|
+
});
|
|
634
|
+
return true;
|
|
635
|
+
}
|
|
636
|
+
function applyStartLoading(key) {
|
|
637
|
+
const sig = signals.getOrCreate(key);
|
|
638
|
+
sig.update(
|
|
639
|
+
(state) => ({
|
|
640
|
+
...state,
|
|
641
|
+
status: void 0,
|
|
642
|
+
isLoading: true,
|
|
643
|
+
errors: void 0
|
|
644
|
+
})
|
|
645
|
+
);
|
|
646
|
+
return true;
|
|
647
|
+
}
|
|
648
|
+
function applyStopLoading(key) {
|
|
649
|
+
const sig = signals.getOrCreate(key);
|
|
650
|
+
sig.update(
|
|
651
|
+
(state) => ({
|
|
652
|
+
...state,
|
|
653
|
+
isLoading: false
|
|
654
|
+
})
|
|
655
|
+
);
|
|
656
|
+
return true;
|
|
657
|
+
}
|
|
658
|
+
function applyUpdateKeyedOne(key, resourceKey, entity) {
|
|
659
|
+
const sig = signals.getOrCreate(key);
|
|
660
|
+
const state = sig();
|
|
661
|
+
const data = isKeyedResourceData(state.data) ? state.data : createKeyedResourceData();
|
|
662
|
+
const nextErrors = { ...data.errors };
|
|
663
|
+
delete nextErrors[resourceKey];
|
|
664
|
+
const nextData = {
|
|
665
|
+
...data,
|
|
666
|
+
entities: { ...data.entities, [resourceKey]: entity },
|
|
667
|
+
isLoading: { ...data.isLoading, [resourceKey]: false },
|
|
668
|
+
status: { ...data.status, [resourceKey]: "Success" },
|
|
669
|
+
errors: nextErrors
|
|
670
|
+
};
|
|
671
|
+
return applyUpdate(key, {
|
|
672
|
+
data: nextData,
|
|
673
|
+
isLoading: isAnyKeyLoading(nextData.isLoading),
|
|
674
|
+
status: void 0,
|
|
675
|
+
errors: void 0
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
function applyClearKeyedOne(key, resourceKey) {
|
|
679
|
+
const sig = signals.getOrCreate(key);
|
|
680
|
+
const previousState = sig();
|
|
681
|
+
const state = previousState;
|
|
682
|
+
if (!isKeyedResourceData(state.data)) {
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
const data = state.data;
|
|
686
|
+
const nextEntities = { ...data.entities };
|
|
687
|
+
delete nextEntities[resourceKey];
|
|
688
|
+
const nextIsLoading = { ...data.isLoading };
|
|
689
|
+
delete nextIsLoading[resourceKey];
|
|
690
|
+
const nextStatus = { ...data.status };
|
|
691
|
+
delete nextStatus[resourceKey];
|
|
692
|
+
const nextErrors = { ...data.errors };
|
|
693
|
+
delete nextErrors[resourceKey];
|
|
694
|
+
const nextData = {
|
|
695
|
+
...data,
|
|
696
|
+
entities: nextEntities,
|
|
697
|
+
isLoading: nextIsLoading,
|
|
698
|
+
status: nextStatus,
|
|
699
|
+
errors: nextErrors
|
|
700
|
+
};
|
|
701
|
+
sig.update(
|
|
702
|
+
(prev) => ({
|
|
703
|
+
...prev,
|
|
704
|
+
data: nextData,
|
|
705
|
+
status: void 0,
|
|
706
|
+
isLoading: isAnyKeyLoading(nextIsLoading),
|
|
707
|
+
errors: void 0
|
|
708
|
+
})
|
|
709
|
+
);
|
|
710
|
+
const updatedState = sig();
|
|
711
|
+
notifier.notify(key, updatedState, previousState);
|
|
712
|
+
return true;
|
|
713
|
+
}
|
|
714
|
+
function applyStartKeyedLoading(key, resourceKey) {
|
|
715
|
+
const sig = signals.getOrCreate(key);
|
|
716
|
+
const state = sig();
|
|
717
|
+
if (!isKeyedResourceData(state.data)) {
|
|
718
|
+
return applyStartLoading(key);
|
|
719
|
+
}
|
|
720
|
+
const previousState = state;
|
|
721
|
+
const data = state.data;
|
|
722
|
+
const nextIsLoading = {
|
|
723
|
+
...data.isLoading,
|
|
724
|
+
[resourceKey]: true
|
|
725
|
+
};
|
|
726
|
+
const nextStatus = { ...data.status };
|
|
727
|
+
delete nextStatus[resourceKey];
|
|
728
|
+
const nextErrors = { ...data.errors };
|
|
729
|
+
delete nextErrors[resourceKey];
|
|
730
|
+
const nextData = {
|
|
731
|
+
...data,
|
|
732
|
+
isLoading: nextIsLoading,
|
|
733
|
+
status: nextStatus,
|
|
734
|
+
errors: nextErrors
|
|
735
|
+
};
|
|
736
|
+
sig.update(
|
|
737
|
+
(previous) => ({
|
|
738
|
+
...previous,
|
|
739
|
+
data: nextData,
|
|
740
|
+
status: void 0,
|
|
741
|
+
isLoading: isAnyKeyLoading(nextIsLoading),
|
|
742
|
+
errors: void 0
|
|
743
|
+
})
|
|
744
|
+
);
|
|
745
|
+
const updatedState = sig();
|
|
746
|
+
notifier.notify(key, updatedState, previousState);
|
|
747
|
+
return true;
|
|
748
|
+
}
|
|
749
|
+
function applyMessage(message) {
|
|
750
|
+
switch (message.type) {
|
|
751
|
+
case "update":
|
|
752
|
+
return applyUpdate(message.key, cloneValue(message.state));
|
|
753
|
+
case "clear":
|
|
754
|
+
return applyClear(message.key);
|
|
755
|
+
case "clearAll":
|
|
756
|
+
return applyClearAll();
|
|
757
|
+
case "startLoading":
|
|
758
|
+
return applyStartLoading(message.key);
|
|
759
|
+
case "stopLoading":
|
|
760
|
+
return applyStopLoading(message.key);
|
|
761
|
+
case "updateKeyedOne":
|
|
762
|
+
return applyUpdateKeyedOne(
|
|
763
|
+
message.key,
|
|
764
|
+
message.resourceKey,
|
|
765
|
+
cloneValue(message.entity)
|
|
766
|
+
);
|
|
767
|
+
case "clearKeyedOne":
|
|
768
|
+
return applyClearKeyedOne(message.key, message.resourceKey);
|
|
769
|
+
case "startKeyedLoading":
|
|
770
|
+
return applyStartKeyedLoading(message.key, message.resourceKey);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
function applySnapshot(snapshot) {
|
|
774
|
+
const keys = /* @__PURE__ */ new Set([
|
|
775
|
+
...Array.from(signals.getAllKeys()),
|
|
776
|
+
...Object.keys(snapshot)
|
|
777
|
+
]);
|
|
778
|
+
keys.forEach((rawKey) => {
|
|
779
|
+
const key = rawKey;
|
|
780
|
+
const sig = signals.getOrCreate(key);
|
|
781
|
+
const snapshotState = snapshot[key] ?? createDefaultState();
|
|
782
|
+
applyUpdate(key, createSnapshotRestorePatch(sig(), snapshotState), true);
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
function captureSnapshot() {
|
|
786
|
+
const entries = Array.from(signals.getAllKeys()).map((key) => [
|
|
787
|
+
key,
|
|
788
|
+
cloneValue(signals.getOrCreate(key)())
|
|
789
|
+
]);
|
|
790
|
+
return Object.fromEntries(entries);
|
|
791
|
+
}
|
|
792
|
+
return {
|
|
793
|
+
applyMessage,
|
|
794
|
+
applySnapshot,
|
|
795
|
+
createSnapshot: captureSnapshot
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
function createUpdateMessage(key, state) {
|
|
799
|
+
return { type: "update", key, state };
|
|
800
|
+
}
|
|
801
|
+
function createClearMessage(key) {
|
|
802
|
+
return { type: "clear", key };
|
|
803
|
+
}
|
|
804
|
+
function createClearAllMessage() {
|
|
805
|
+
return { type: "clearAll" };
|
|
806
|
+
}
|
|
807
|
+
function createStartLoadingMessage(key) {
|
|
808
|
+
return { type: "startLoading", key };
|
|
809
|
+
}
|
|
810
|
+
function createStopLoadingMessage(key) {
|
|
811
|
+
return { type: "stopLoading", key };
|
|
812
|
+
}
|
|
813
|
+
function createUpdateKeyedOneMessage(key, resourceKey, entity) {
|
|
814
|
+
return {
|
|
815
|
+
type: "updateKeyedOne",
|
|
816
|
+
key,
|
|
817
|
+
resourceKey,
|
|
818
|
+
entity
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
function createClearKeyedOneMessage(key, resourceKey) {
|
|
822
|
+
return {
|
|
823
|
+
type: "clearKeyedOne",
|
|
824
|
+
key,
|
|
825
|
+
resourceKey
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
function createStartKeyedLoadingMessage(key, resourceKey) {
|
|
829
|
+
return {
|
|
830
|
+
type: "startKeyedLoading",
|
|
831
|
+
key,
|
|
832
|
+
resourceKey
|
|
833
|
+
};
|
|
18
834
|
}
|
|
19
835
|
|
|
20
836
|
// src/base-store.ts
|
|
21
837
|
var updateHooksMap = /* @__PURE__ */ new WeakMap();
|
|
22
838
|
var BaseStore = class {
|
|
23
|
-
constructor(storeEnum) {
|
|
839
|
+
constructor(storeEnum, options) {
|
|
24
840
|
this.storeEnum = storeEnum;
|
|
841
|
+
this.storeKeys = Object.keys(storeEnum);
|
|
25
842
|
this.initializeState();
|
|
26
843
|
updateHooksMap.set(this, /* @__PURE__ */ new Map());
|
|
844
|
+
const consumer = createStoreMessageConsumer(
|
|
845
|
+
{
|
|
846
|
+
getOrCreate: (key) => this.signalsState.get(key),
|
|
847
|
+
getAllKeys: () => this.storeKeys
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
notify: (key, next, prev) => this.notifyUpdateHooks(key, next, prev)
|
|
851
|
+
}
|
|
852
|
+
);
|
|
853
|
+
this.history = createStoreHistory({
|
|
854
|
+
captureSnapshot: () => consumer.createSnapshot(),
|
|
855
|
+
applySnapshot: (snapshot) => consumer.applySnapshot(snapshot),
|
|
856
|
+
applyMessage: (message) => consumer.applyMessage(message),
|
|
857
|
+
channel: options?.channel
|
|
858
|
+
});
|
|
27
859
|
trackStore(this);
|
|
28
860
|
}
|
|
29
861
|
signalsState = /* @__PURE__ */ new Map();
|
|
862
|
+
storeKeys;
|
|
863
|
+
history;
|
|
864
|
+
/** @inheritDoc */
|
|
865
|
+
travelTo = (index) => this.history.travelTo(index);
|
|
866
|
+
/** @inheritDoc */
|
|
867
|
+
undo = () => this.history.undo();
|
|
868
|
+
/** @inheritDoc */
|
|
869
|
+
redo = () => this.history.redo();
|
|
870
|
+
/** @inheritDoc */
|
|
871
|
+
getDeadLetters = () => this.history.getDeadLetters();
|
|
872
|
+
/** @inheritDoc */
|
|
873
|
+
replayDeadLetter = (id) => this.history.replayDeadLetter(id);
|
|
874
|
+
/** @inheritDoc */
|
|
875
|
+
replayDeadLetters = () => this.history.replayDeadLetters();
|
|
876
|
+
/** @inheritDoc */
|
|
877
|
+
getCurrentIndex = () => this.history.getCurrentIndex();
|
|
878
|
+
replay(idOrIds) {
|
|
879
|
+
if (Array.isArray(idOrIds)) {
|
|
880
|
+
return this.history.replay(idOrIds);
|
|
881
|
+
}
|
|
882
|
+
return this.history.replay(idOrIds);
|
|
883
|
+
}
|
|
884
|
+
getHistory(key) {
|
|
885
|
+
if (key === void 0) {
|
|
886
|
+
return this.history.getHistory();
|
|
887
|
+
}
|
|
888
|
+
return this.history.getHistory(key);
|
|
889
|
+
}
|
|
890
|
+
getMessages(key) {
|
|
891
|
+
if (key === void 0) {
|
|
892
|
+
return this.history.getMessages();
|
|
893
|
+
}
|
|
894
|
+
return this.history.getMessages(key);
|
|
895
|
+
}
|
|
30
896
|
/**
|
|
31
897
|
* Returns a **read-only** `Signal` for the given store slot.
|
|
32
898
|
*
|
|
@@ -71,23 +937,13 @@ var BaseStore = class {
|
|
|
71
937
|
* @param newState - Partial state to merge (e.g. `{ data: newData, status: 'Success' }`).
|
|
72
938
|
*/
|
|
73
939
|
update(key, newState) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
const previousState = currentState();
|
|
79
|
-
currentState.update((state) => ({
|
|
80
|
-
...state,
|
|
81
|
-
...newState
|
|
82
|
-
}));
|
|
83
|
-
const updatedState = currentState();
|
|
84
|
-
this.notifyUpdateHooks(key, updatedState, previousState);
|
|
940
|
+
this.history.publish(
|
|
941
|
+
createUpdateMessage(key, cloneValue(newState))
|
|
942
|
+
);
|
|
85
943
|
}
|
|
86
944
|
/** Resets every slot in this store to its initial idle state. */
|
|
87
945
|
clearAll() {
|
|
88
|
-
|
|
89
|
-
this.clear(key);
|
|
90
|
-
});
|
|
946
|
+
this.history.publish(createClearAllMessage());
|
|
91
947
|
}
|
|
92
948
|
/**
|
|
93
949
|
* Resets a single slot to `{ data: undefined, isLoading: false, status: undefined, errors: undefined }`.
|
|
@@ -95,20 +951,7 @@ var BaseStore = class {
|
|
|
95
951
|
* @param key - The slot to clear.
|
|
96
952
|
*/
|
|
97
953
|
clear(key) {
|
|
98
|
-
|
|
99
|
-
if (!currentState) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
const previousState = currentState();
|
|
103
|
-
const _typedKey = key;
|
|
104
|
-
currentState.set({
|
|
105
|
-
data: void 0,
|
|
106
|
-
isLoading: false,
|
|
107
|
-
status: void 0,
|
|
108
|
-
errors: void 0
|
|
109
|
-
});
|
|
110
|
-
const nextState = currentState();
|
|
111
|
-
this.notifyUpdateHooks(key, nextState, previousState);
|
|
954
|
+
this.history.publish(createClearMessage(key));
|
|
112
955
|
}
|
|
113
956
|
/**
|
|
114
957
|
* Marks a slot as loading: sets `isLoading: true` and clears `status` and `errors`.
|
|
@@ -116,19 +959,7 @@ var BaseStore = class {
|
|
|
116
959
|
* @param key - The slot to mark as loading.
|
|
117
960
|
*/
|
|
118
961
|
startLoading(key) {
|
|
119
|
-
|
|
120
|
-
if (!currentState) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const _typedKey = key;
|
|
124
|
-
currentState.update(
|
|
125
|
-
(state) => ({
|
|
126
|
-
...state,
|
|
127
|
-
status: void 0,
|
|
128
|
-
isLoading: true,
|
|
129
|
-
errors: void 0
|
|
130
|
-
})
|
|
131
|
-
);
|
|
962
|
+
this.history.publish(createStartLoadingMessage(key));
|
|
132
963
|
}
|
|
133
964
|
/**
|
|
134
965
|
* Marks a slot as no longer loading: sets `isLoading: false`.
|
|
@@ -137,17 +968,7 @@ var BaseStore = class {
|
|
|
137
968
|
* @param key - The slot to stop loading.
|
|
138
969
|
*/
|
|
139
970
|
stopLoading(key) {
|
|
140
|
-
|
|
141
|
-
if (!currentState) {
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
const _typedKey = key;
|
|
145
|
-
currentState.update(
|
|
146
|
-
(state) => ({
|
|
147
|
-
...state,
|
|
148
|
-
isLoading: false
|
|
149
|
-
})
|
|
150
|
-
);
|
|
971
|
+
this.history.publish(createStopLoadingMessage(key));
|
|
151
972
|
}
|
|
152
973
|
/**
|
|
153
974
|
* Merges a single entity into a {@link KeyedResourceData} slot.
|
|
@@ -159,36 +980,13 @@ var BaseStore = class {
|
|
|
159
980
|
* @param entity - The entity value to store.
|
|
160
981
|
*/
|
|
161
982
|
updateKeyedOne(key, resourceKey, entity) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
delete nextErrors[resourceKey];
|
|
170
|
-
const nextData = {
|
|
171
|
-
...data,
|
|
172
|
-
entities: {
|
|
173
|
-
...data.entities,
|
|
174
|
-
[resourceKey]: entity
|
|
175
|
-
},
|
|
176
|
-
isLoading: {
|
|
177
|
-
...data.isLoading,
|
|
178
|
-
[resourceKey]: false
|
|
179
|
-
},
|
|
180
|
-
status: {
|
|
181
|
-
...data.status,
|
|
182
|
-
[resourceKey]: "Success"
|
|
183
|
-
},
|
|
184
|
-
errors: nextErrors
|
|
185
|
-
};
|
|
186
|
-
this.update(key, {
|
|
187
|
-
data: nextData,
|
|
188
|
-
isLoading: isAnyKeyLoading(nextData.isLoading),
|
|
189
|
-
status: void 0,
|
|
190
|
-
errors: void 0
|
|
191
|
-
});
|
|
983
|
+
this.history.publish(
|
|
984
|
+
createUpdateKeyedOneMessage(
|
|
985
|
+
key,
|
|
986
|
+
resourceKey,
|
|
987
|
+
cloneValue(entity)
|
|
988
|
+
)
|
|
989
|
+
);
|
|
192
990
|
}
|
|
193
991
|
/**
|
|
194
992
|
* Removes a single entity from a {@link KeyedResourceData} slot,
|
|
@@ -199,43 +997,9 @@ var BaseStore = class {
|
|
|
199
997
|
* @param resourceKey - The entity identifier to remove.
|
|
200
998
|
*/
|
|
201
999
|
clearKeyedOne(key, resourceKey) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
const previousState = currentState();
|
|
207
|
-
const state = previousState;
|
|
208
|
-
if (!isKeyedResourceData(state.data)) {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
const data = state.data;
|
|
212
|
-
const nextEntities = { ...data.entities };
|
|
213
|
-
delete nextEntities[resourceKey];
|
|
214
|
-
const nextIsLoading = { ...data.isLoading };
|
|
215
|
-
delete nextIsLoading[resourceKey];
|
|
216
|
-
const nextStatus = { ...data.status };
|
|
217
|
-
delete nextStatus[resourceKey];
|
|
218
|
-
const nextErrors = { ...data.errors };
|
|
219
|
-
delete nextErrors[resourceKey];
|
|
220
|
-
const nextData = {
|
|
221
|
-
...data,
|
|
222
|
-
entities: nextEntities,
|
|
223
|
-
isLoading: nextIsLoading,
|
|
224
|
-
status: nextStatus,
|
|
225
|
-
errors: nextErrors
|
|
226
|
-
};
|
|
227
|
-
const _typedKey = key;
|
|
228
|
-
currentState.update(
|
|
229
|
-
(prev) => ({
|
|
230
|
-
...prev,
|
|
231
|
-
data: nextData,
|
|
232
|
-
status: void 0,
|
|
233
|
-
isLoading: isAnyKeyLoading(nextIsLoading),
|
|
234
|
-
errors: void 0
|
|
235
|
-
})
|
|
1000
|
+
this.history.publish(
|
|
1001
|
+
createClearKeyedOneMessage(key, resourceKey)
|
|
236
1002
|
);
|
|
237
|
-
const updatedState = currentState();
|
|
238
|
-
this.notifyUpdateHooks(key, updatedState, previousState);
|
|
239
1003
|
}
|
|
240
1004
|
/**
|
|
241
1005
|
* Marks a single entity within a keyed slot as loading.
|
|
@@ -246,47 +1010,9 @@ var BaseStore = class {
|
|
|
246
1010
|
* @param resourceKey - The entity identifier to mark as loading.
|
|
247
1011
|
*/
|
|
248
1012
|
startKeyedLoading(key, resourceKey) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
const _typedKey = key;
|
|
254
|
-
const state = currentState();
|
|
255
|
-
if (!isKeyedResourceData(state.data)) {
|
|
256
|
-
this.startLoading(key);
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
const previousState = state;
|
|
260
|
-
const data = state.data;
|
|
261
|
-
const nextIsLoading = {
|
|
262
|
-
...data.isLoading,
|
|
263
|
-
[resourceKey]: true
|
|
264
|
-
};
|
|
265
|
-
const nextStatus = {
|
|
266
|
-
...data.status
|
|
267
|
-
};
|
|
268
|
-
delete nextStatus[resourceKey];
|
|
269
|
-
const nextErrors = {
|
|
270
|
-
...data.errors
|
|
271
|
-
};
|
|
272
|
-
delete nextErrors[resourceKey];
|
|
273
|
-
const nextData = {
|
|
274
|
-
...data,
|
|
275
|
-
isLoading: nextIsLoading,
|
|
276
|
-
status: nextStatus,
|
|
277
|
-
errors: nextErrors
|
|
278
|
-
};
|
|
279
|
-
currentState.update(
|
|
280
|
-
(previous) => ({
|
|
281
|
-
...previous,
|
|
282
|
-
data: nextData,
|
|
283
|
-
status: void 0,
|
|
284
|
-
isLoading: isAnyKeyLoading(nextIsLoading),
|
|
285
|
-
errors: void 0
|
|
286
|
-
})
|
|
1013
|
+
this.history.publish(
|
|
1014
|
+
createStartKeyedLoadingMessage(key, resourceKey)
|
|
287
1015
|
);
|
|
288
|
-
const updatedState = currentState();
|
|
289
|
-
this.notifyUpdateHooks(key, updatedState, previousState);
|
|
290
1016
|
}
|
|
291
1017
|
notifyUpdateHooks(key, nextState, previousState) {
|
|
292
1018
|
const hooks = updateHooksMap.get(this);
|
|
@@ -294,25 +1020,34 @@ var BaseStore = class {
|
|
|
294
1020
|
if (!keyHooks) {
|
|
295
1021
|
return;
|
|
296
1022
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
1023
|
+
const errors = [];
|
|
1024
|
+
keyHooks.forEach((hook) => {
|
|
1025
|
+
try {
|
|
1026
|
+
hook(
|
|
1027
|
+
nextState,
|
|
1028
|
+
previousState
|
|
1029
|
+
);
|
|
1030
|
+
} catch (error) {
|
|
1031
|
+
errors.push(error);
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
if (errors.length > 0) {
|
|
1035
|
+
queueMicrotask(() => {
|
|
1036
|
+
if (errors.length === 1) {
|
|
1037
|
+
throw errors[0];
|
|
1038
|
+
}
|
|
1039
|
+
throw new AggregateError(
|
|
1040
|
+
errors,
|
|
1041
|
+
`${errors.length} onUpdate hooks threw for key "${String(key)}"`
|
|
1042
|
+
);
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
303
1045
|
}
|
|
304
1046
|
initializeState() {
|
|
305
|
-
|
|
306
|
-
const _typedKey = key;
|
|
307
|
-
const initialState = {
|
|
308
|
-
data: void 0,
|
|
309
|
-
isLoading: false,
|
|
310
|
-
status: void 0,
|
|
311
|
-
errors: void 0
|
|
312
|
-
};
|
|
1047
|
+
this.storeKeys.forEach((key) => {
|
|
313
1048
|
this.signalsState.set(
|
|
314
|
-
|
|
315
|
-
signal(
|
|
1049
|
+
key,
|
|
1050
|
+
signal(createDefaultState())
|
|
316
1051
|
);
|
|
317
1052
|
});
|
|
318
1053
|
}
|
|
@@ -320,23 +1055,58 @@ var BaseStore = class {
|
|
|
320
1055
|
|
|
321
1056
|
// src/lazy-store.ts
|
|
322
1057
|
import { signal as signal2 } from "@angular/core";
|
|
323
|
-
import {
|
|
324
|
-
isAnyKeyLoading as isAnyKeyLoading2,
|
|
325
|
-
isKeyedResourceData as isKeyedResourceData2,
|
|
326
|
-
createKeyedResourceData as createKeyedResourceData2
|
|
327
|
-
} from "@flurryx/core";
|
|
328
|
-
function createDefaultState() {
|
|
329
|
-
return {
|
|
330
|
-
data: void 0,
|
|
331
|
-
isLoading: false,
|
|
332
|
-
status: void 0,
|
|
333
|
-
errors: void 0
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
1058
|
var LazyStore = class {
|
|
337
1059
|
signals = /* @__PURE__ */ new Map();
|
|
338
1060
|
hooks = /* @__PURE__ */ new Map();
|
|
339
|
-
|
|
1061
|
+
history;
|
|
1062
|
+
/** @inheritDoc */
|
|
1063
|
+
travelTo = (index) => this.history.travelTo(index);
|
|
1064
|
+
/** @inheritDoc */
|
|
1065
|
+
undo = () => this.history.undo();
|
|
1066
|
+
/** @inheritDoc */
|
|
1067
|
+
redo = () => this.history.redo();
|
|
1068
|
+
getMessages(key) {
|
|
1069
|
+
if (key === void 0) {
|
|
1070
|
+
return this.history.getMessages();
|
|
1071
|
+
}
|
|
1072
|
+
return this.history.getMessages(key);
|
|
1073
|
+
}
|
|
1074
|
+
/** @inheritDoc */
|
|
1075
|
+
getDeadLetters = () => this.history.getDeadLetters();
|
|
1076
|
+
/** @inheritDoc */
|
|
1077
|
+
replayDeadLetter = (id) => this.history.replayDeadLetter(id);
|
|
1078
|
+
/** @inheritDoc */
|
|
1079
|
+
replayDeadLetters = () => this.history.replayDeadLetters();
|
|
1080
|
+
/** @inheritDoc */
|
|
1081
|
+
getCurrentIndex = () => this.history.getCurrentIndex();
|
|
1082
|
+
replay(idOrIds) {
|
|
1083
|
+
if (Array.isArray(idOrIds)) {
|
|
1084
|
+
return this.history.replay(idOrIds);
|
|
1085
|
+
}
|
|
1086
|
+
return this.history.replay(idOrIds);
|
|
1087
|
+
}
|
|
1088
|
+
getHistory(key) {
|
|
1089
|
+
if (key === void 0) {
|
|
1090
|
+
return this.history.getHistory();
|
|
1091
|
+
}
|
|
1092
|
+
return this.history.getHistory(key);
|
|
1093
|
+
}
|
|
1094
|
+
constructor(options) {
|
|
1095
|
+
const consumer = createStoreMessageConsumer(
|
|
1096
|
+
{
|
|
1097
|
+
getOrCreate: (key) => this.getOrCreate(key),
|
|
1098
|
+
getAllKeys: () => this.signals.keys()
|
|
1099
|
+
},
|
|
1100
|
+
{
|
|
1101
|
+
notify: (key, next, prev) => this.notifyHooks(key, next, prev)
|
|
1102
|
+
}
|
|
1103
|
+
);
|
|
1104
|
+
this.history = createStoreHistory({
|
|
1105
|
+
captureSnapshot: () => consumer.createSnapshot(),
|
|
1106
|
+
applySnapshot: (snapshot) => consumer.applySnapshot(snapshot),
|
|
1107
|
+
applyMessage: (message) => consumer.applyMessage(message),
|
|
1108
|
+
channel: options?.channel
|
|
1109
|
+
});
|
|
340
1110
|
trackStore(this);
|
|
341
1111
|
}
|
|
342
1112
|
getOrCreate(key) {
|
|
@@ -347,138 +1117,55 @@ var LazyStore = class {
|
|
|
347
1117
|
}
|
|
348
1118
|
return sig;
|
|
349
1119
|
}
|
|
1120
|
+
/** @inheritDoc */
|
|
350
1121
|
get(key) {
|
|
351
1122
|
return this.getOrCreate(key);
|
|
352
1123
|
}
|
|
1124
|
+
/** @inheritDoc */
|
|
353
1125
|
update(key, newState) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
const nextState = sig();
|
|
358
|
-
this.notifyHooks(key, nextState, previousState);
|
|
1126
|
+
this.history.publish(
|
|
1127
|
+
createUpdateMessage(key, cloneValue(newState))
|
|
1128
|
+
);
|
|
359
1129
|
}
|
|
1130
|
+
/** @inheritDoc */
|
|
360
1131
|
clear(key) {
|
|
361
|
-
|
|
362
|
-
const previousState = sig();
|
|
363
|
-
sig.set(createDefaultState());
|
|
364
|
-
const nextState = sig();
|
|
365
|
-
this.notifyHooks(key, nextState, previousState);
|
|
1132
|
+
this.history.publish(createClearMessage(key));
|
|
366
1133
|
}
|
|
1134
|
+
/** @inheritDoc */
|
|
367
1135
|
clearAll() {
|
|
368
|
-
|
|
369
|
-
this.clear(key);
|
|
370
|
-
}
|
|
1136
|
+
this.history.publish(createClearAllMessage());
|
|
371
1137
|
}
|
|
1138
|
+
/** @inheritDoc */
|
|
372
1139
|
startLoading(key) {
|
|
373
|
-
|
|
374
|
-
sig.update(
|
|
375
|
-
(state) => ({
|
|
376
|
-
...state,
|
|
377
|
-
status: void 0,
|
|
378
|
-
isLoading: true,
|
|
379
|
-
errors: void 0
|
|
380
|
-
})
|
|
381
|
-
);
|
|
1140
|
+
this.history.publish(createStartLoadingMessage(key));
|
|
382
1141
|
}
|
|
1142
|
+
/** @inheritDoc */
|
|
383
1143
|
stopLoading(key) {
|
|
384
|
-
|
|
385
|
-
sig.update(
|
|
386
|
-
(state) => ({
|
|
387
|
-
...state,
|
|
388
|
-
isLoading: false
|
|
389
|
-
})
|
|
390
|
-
);
|
|
1144
|
+
this.history.publish(createStopLoadingMessage(key));
|
|
391
1145
|
}
|
|
1146
|
+
/** @inheritDoc */
|
|
392
1147
|
updateKeyedOne(key, resourceKey, entity) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
entities: { ...data.entities, [resourceKey]: entity },
|
|
401
|
-
isLoading: { ...data.isLoading, [resourceKey]: false },
|
|
402
|
-
status: { ...data.status, [resourceKey]: "Success" },
|
|
403
|
-
errors: nextErrors
|
|
404
|
-
};
|
|
405
|
-
this.update(key, {
|
|
406
|
-
data: nextData,
|
|
407
|
-
isLoading: isAnyKeyLoading2(nextData.isLoading),
|
|
408
|
-
status: void 0,
|
|
409
|
-
errors: void 0
|
|
410
|
-
});
|
|
1148
|
+
this.history.publish(
|
|
1149
|
+
createUpdateKeyedOneMessage(
|
|
1150
|
+
key,
|
|
1151
|
+
resourceKey,
|
|
1152
|
+
cloneValue(entity)
|
|
1153
|
+
)
|
|
1154
|
+
);
|
|
411
1155
|
}
|
|
1156
|
+
/** @inheritDoc */
|
|
412
1157
|
clearKeyedOne(key, resourceKey) {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
if (!isKeyedResourceData2(state.data)) {
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
const data = state.data;
|
|
419
|
-
const previousState = state;
|
|
420
|
-
const nextEntities = { ...data.entities };
|
|
421
|
-
delete nextEntities[resourceKey];
|
|
422
|
-
const nextIsLoading = { ...data.isLoading };
|
|
423
|
-
delete nextIsLoading[resourceKey];
|
|
424
|
-
const nextStatus = { ...data.status };
|
|
425
|
-
delete nextStatus[resourceKey];
|
|
426
|
-
const nextErrors = { ...data.errors };
|
|
427
|
-
delete nextErrors[resourceKey];
|
|
428
|
-
const nextData = {
|
|
429
|
-
...data,
|
|
430
|
-
entities: nextEntities,
|
|
431
|
-
isLoading: nextIsLoading,
|
|
432
|
-
status: nextStatus,
|
|
433
|
-
errors: nextErrors
|
|
434
|
-
};
|
|
435
|
-
sig.update(
|
|
436
|
-
(prev) => ({
|
|
437
|
-
...prev,
|
|
438
|
-
data: nextData,
|
|
439
|
-
status: void 0,
|
|
440
|
-
isLoading: isAnyKeyLoading2(nextIsLoading),
|
|
441
|
-
errors: void 0
|
|
442
|
-
})
|
|
1158
|
+
this.history.publish(
|
|
1159
|
+
createClearKeyedOneMessage(key, resourceKey)
|
|
443
1160
|
);
|
|
444
|
-
const updatedState = sig();
|
|
445
|
-
this.notifyHooks(key, updatedState, previousState);
|
|
446
1161
|
}
|
|
1162
|
+
/** @inheritDoc */
|
|
447
1163
|
startKeyedLoading(key, resourceKey) {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
if (!isKeyedResourceData2(state.data)) {
|
|
451
|
-
this.startLoading(key);
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
const previousState = state;
|
|
455
|
-
const data = state.data;
|
|
456
|
-
const nextIsLoading = {
|
|
457
|
-
...data.isLoading,
|
|
458
|
-
[resourceKey]: true
|
|
459
|
-
};
|
|
460
|
-
const nextStatus = { ...data.status };
|
|
461
|
-
delete nextStatus[resourceKey];
|
|
462
|
-
const nextErrors = { ...data.errors };
|
|
463
|
-
delete nextErrors[resourceKey];
|
|
464
|
-
const nextData = {
|
|
465
|
-
...data,
|
|
466
|
-
isLoading: nextIsLoading,
|
|
467
|
-
status: nextStatus,
|
|
468
|
-
errors: nextErrors
|
|
469
|
-
};
|
|
470
|
-
sig.update(
|
|
471
|
-
(previous) => ({
|
|
472
|
-
...previous,
|
|
473
|
-
data: nextData,
|
|
474
|
-
status: void 0,
|
|
475
|
-
isLoading: isAnyKeyLoading2(nextIsLoading),
|
|
476
|
-
errors: void 0
|
|
477
|
-
})
|
|
1164
|
+
this.history.publish(
|
|
1165
|
+
createStartKeyedLoadingMessage(key, resourceKey)
|
|
478
1166
|
);
|
|
479
|
-
const updatedState = sig();
|
|
480
|
-
this.notifyHooks(key, updatedState, previousState);
|
|
481
1167
|
}
|
|
1168
|
+
/** @inheritDoc */
|
|
482
1169
|
onUpdate(key, callback) {
|
|
483
1170
|
if (!this.hooks.has(key)) {
|
|
484
1171
|
this.hooks.set(key, []);
|
|
@@ -501,12 +1188,28 @@ var LazyStore = class {
|
|
|
501
1188
|
if (!keyHooks) {
|
|
502
1189
|
return;
|
|
503
1190
|
}
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
1191
|
+
const errors = [];
|
|
1192
|
+
keyHooks.forEach((hook) => {
|
|
1193
|
+
try {
|
|
1194
|
+
hook(
|
|
1195
|
+
nextState,
|
|
1196
|
+
previousState
|
|
1197
|
+
);
|
|
1198
|
+
} catch (error) {
|
|
1199
|
+
errors.push(error);
|
|
1200
|
+
}
|
|
1201
|
+
});
|
|
1202
|
+
if (errors.length > 0) {
|
|
1203
|
+
queueMicrotask(() => {
|
|
1204
|
+
if (errors.length === 1) {
|
|
1205
|
+
throw errors[0];
|
|
1206
|
+
}
|
|
1207
|
+
throw new AggregateError(
|
|
1208
|
+
errors,
|
|
1209
|
+
`${errors.length} onUpdate hooks threw for key "${String(key)}"`
|
|
1210
|
+
);
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
510
1213
|
}
|
|
511
1214
|
};
|
|
512
1215
|
|
|
@@ -515,12 +1218,12 @@ import { InjectionToken, inject } from "@angular/core";
|
|
|
515
1218
|
|
|
516
1219
|
// src/dynamic-store.ts
|
|
517
1220
|
var DynamicStore = class extends BaseStore {
|
|
518
|
-
constructor(config) {
|
|
1221
|
+
constructor(config, options) {
|
|
519
1222
|
const identityEnum = Object.keys(config).reduce(
|
|
520
1223
|
(acc, key) => ({ ...acc, [key]: key }),
|
|
521
1224
|
{}
|
|
522
1225
|
);
|
|
523
|
-
super(identityEnum);
|
|
1226
|
+
super(identityEnum, options);
|
|
524
1227
|
}
|
|
525
1228
|
};
|
|
526
1229
|
|
|
@@ -541,12 +1244,12 @@ function mirrorKey(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
|
541
1244
|
}
|
|
542
1245
|
|
|
543
1246
|
// src/collect-keyed.ts
|
|
544
|
-
import { createKeyedResourceData as
|
|
1247
|
+
import { createKeyedResourceData as createKeyedResourceData2, isAnyKeyLoading as isAnyKeyLoading2 } from "@flurryx/core";
|
|
545
1248
|
function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
546
1249
|
const resolvedTargetKey = typeof targetKeyOrOptions === "string" ? targetKeyOrOptions : sourceKey;
|
|
547
1250
|
const resolvedOptions = typeof targetKeyOrOptions === "object" ? targetKeyOrOptions : options;
|
|
548
1251
|
target.update(resolvedTargetKey, {
|
|
549
|
-
data:
|
|
1252
|
+
data: createKeyedResourceData2()
|
|
550
1253
|
});
|
|
551
1254
|
let previousId;
|
|
552
1255
|
const cleanup = source.onUpdate(sourceKey, (state) => {
|
|
@@ -577,7 +1280,7 @@ function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
|
577
1280
|
};
|
|
578
1281
|
target.update(resolvedTargetKey, {
|
|
579
1282
|
data: updatedKeyed,
|
|
580
|
-
isLoading:
|
|
1283
|
+
isLoading: isAnyKeyLoading2(newIsLoading),
|
|
581
1284
|
status: "Success"
|
|
582
1285
|
});
|
|
583
1286
|
previousId = currentId;
|
|
@@ -599,7 +1302,7 @@ function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
|
599
1302
|
};
|
|
600
1303
|
target.update(resolvedTargetKey, {
|
|
601
1304
|
data: updatedKeyed,
|
|
602
|
-
isLoading:
|
|
1305
|
+
isLoading: isAnyKeyLoading2(newIsLoading)
|
|
603
1306
|
});
|
|
604
1307
|
previousId = currentId;
|
|
605
1308
|
} else if (resourceState.data === void 0 && previousId !== void 0) {
|
|
@@ -615,7 +1318,7 @@ function collectKeyed(source, sourceKey, target, targetKeyOrOptions, options) {
|
|
|
615
1318
|
};
|
|
616
1319
|
target.update(resolvedTargetKey, {
|
|
617
1320
|
data: updatedKeyed,
|
|
618
|
-
isLoading:
|
|
1321
|
+
isLoading: isAnyKeyLoading2(remainingLoading)
|
|
619
1322
|
});
|
|
620
1323
|
previousId = void 0;
|
|
621
1324
|
} else if (resourceState.isLoading && currentId !== void 0) {
|
|
@@ -655,7 +1358,6 @@ function wireMirrors(store, mirrors) {
|
|
|
655
1358
|
def.targetKey
|
|
656
1359
|
);
|
|
657
1360
|
}
|
|
658
|
-
return store;
|
|
659
1361
|
}
|
|
660
1362
|
function wireMirrorKeyed(store, defs) {
|
|
661
1363
|
for (const def of defs) {
|
|
@@ -670,7 +1372,6 @@ function wireMirrorKeyed(store, defs) {
|
|
|
670
1372
|
}
|
|
671
1373
|
);
|
|
672
1374
|
}
|
|
673
|
-
return store;
|
|
674
1375
|
}
|
|
675
1376
|
var MIRROR_SELF_SAME_KEY_ERROR = "mirrorSelf source and target keys must be different";
|
|
676
1377
|
function wireSelfMirrors(store, defs) {
|
|
@@ -685,7 +1386,6 @@ function wireSelfMirrors(store, defs) {
|
|
|
685
1386
|
def.targetKey
|
|
686
1387
|
);
|
|
687
1388
|
}
|
|
688
|
-
return store;
|
|
689
1389
|
}
|
|
690
1390
|
function createBuilder(accum, mirrors = [], mirrorKeyedDefs = [], selfMirrors = []) {
|
|
691
1391
|
return {
|
|
@@ -742,11 +1442,11 @@ function createBuilder(accum, mirrors = [], mirrorKeyedDefs = [], selfMirrors =
|
|
|
742
1442
|
selfMirrors
|
|
743
1443
|
);
|
|
744
1444
|
},
|
|
745
|
-
build() {
|
|
1445
|
+
build(options) {
|
|
746
1446
|
return new InjectionToken("FlurryxStore", {
|
|
747
1447
|
providedIn: "root",
|
|
748
1448
|
factory: () => {
|
|
749
|
-
const store = new DynamicStore(accum);
|
|
1449
|
+
const store = new DynamicStore(accum, options);
|
|
750
1450
|
wireMirrors(store, mirrors);
|
|
751
1451
|
wireMirrorKeyed(store, mirrorKeyedDefs);
|
|
752
1452
|
wireSelfMirrors(store, selfMirrors);
|
|
@@ -817,11 +1517,11 @@ function createConstrainedBuilder(_enumObj, accum, mirrors = [], mirrorKeyedDefs
|
|
|
817
1517
|
selfMirrors
|
|
818
1518
|
);
|
|
819
1519
|
},
|
|
820
|
-
build() {
|
|
1520
|
+
build(options) {
|
|
821
1521
|
return new InjectionToken("FlurryxStore", {
|
|
822
1522
|
providedIn: "root",
|
|
823
1523
|
factory: () => {
|
|
824
|
-
const store = new DynamicStore(accum);
|
|
1524
|
+
const store = new DynamicStore(accum, options);
|
|
825
1525
|
wireMirrors(store, mirrors);
|
|
826
1526
|
wireMirrorKeyed(store, mirrorKeyedDefs);
|
|
827
1527
|
wireSelfMirrors(store, selfMirrors);
|
|
@@ -868,11 +1568,11 @@ function createInterfaceBuilder(mirrors = [], mirrorKeyedDefs = [], selfMirrors
|
|
|
868
1568
|
selfMirrors
|
|
869
1569
|
);
|
|
870
1570
|
},
|
|
871
|
-
build() {
|
|
1571
|
+
build(options) {
|
|
872
1572
|
return new InjectionToken("FlurryxStore", {
|
|
873
1573
|
providedIn: "root",
|
|
874
1574
|
factory: () => {
|
|
875
|
-
const store = new LazyStore();
|
|
1575
|
+
const store = new LazyStore(options);
|
|
876
1576
|
wireMirrors(store, mirrors);
|
|
877
1577
|
wireMirrorKeyed(store, mirrorKeyedDefs);
|
|
878
1578
|
wireSelfMirrors(store, selfMirrors);
|
|
@@ -897,7 +1597,14 @@ export {
|
|
|
897
1597
|
LazyStore,
|
|
898
1598
|
Store,
|
|
899
1599
|
clearAllStores,
|
|
1600
|
+
cloneValue,
|
|
900
1601
|
collectKeyed,
|
|
1602
|
+
createCompositeStoreMessageChannel,
|
|
1603
|
+
createInMemoryStoreMessageChannel,
|
|
1604
|
+
createLocalStorageStoreMessageChannel,
|
|
1605
|
+
createSessionStorageStoreMessageChannel,
|
|
1606
|
+
createSnapshotRestorePatch,
|
|
1607
|
+
createStorageStoreMessageChannel,
|
|
901
1608
|
mirrorKey
|
|
902
1609
|
};
|
|
903
1610
|
//# sourceMappingURL=index.js.map
|