@flurryx/rx 0.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.
@@ -0,0 +1,6 @@
1
+ import { ResourceErrors } from '@flurryx/core';
2
+
3
+ type ErrorNormalizer = (error: unknown) => ResourceErrors;
4
+ declare function defaultErrorNormalizer(error: unknown): ResourceErrors;
5
+
6
+ export { type ErrorNormalizer as E, defaultErrorNormalizer as d };
@@ -0,0 +1,6 @@
1
+ import { ResourceErrors } from '@flurryx/core';
2
+
3
+ type ErrorNormalizer = (error: unknown) => ResourceErrors;
4
+ declare function defaultErrorNormalizer(error: unknown): ResourceErrors;
5
+
6
+ export { type ErrorNormalizer as E, defaultErrorNormalizer as d };
package/dist/http.cjs ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/http.ts
21
+ var http_exports = {};
22
+ __export(http_exports, {
23
+ httpErrorNormalizer: () => httpErrorNormalizer
24
+ });
25
+ module.exports = __toCommonJS(http_exports);
26
+
27
+ // src/error/http-error-normalizer.ts
28
+ var import_http = require("@angular/common/http");
29
+ var httpErrorNormalizer = (error) => {
30
+ if (!(error instanceof import_http.HttpErrorResponse)) {
31
+ return [
32
+ {
33
+ code: "UNKNOWN",
34
+ message: String(error)
35
+ }
36
+ ];
37
+ }
38
+ const errors = error.error?.errors;
39
+ if (Array.isArray(errors)) {
40
+ return errors;
41
+ }
42
+ return [
43
+ {
44
+ code: error.status.toString(),
45
+ message: error.message
46
+ }
47
+ ];
48
+ };
49
+ // Annotate the CommonJS export names for ESM import in node:
50
+ 0 && (module.exports = {
51
+ httpErrorNormalizer
52
+ });
53
+ //# sourceMappingURL=http.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/http.ts","../src/error/http-error-normalizer.ts"],"sourcesContent":["export { httpErrorNormalizer } from './error/http-error-normalizer';\n","import { HttpErrorResponse } from '@angular/common/http';\nimport type { ResourceErrors } from '@flurryx/core';\nimport type { ErrorNormalizer } from './error-normalizer';\n\nexport const httpErrorNormalizer: ErrorNormalizer = (\n error: unknown\n): ResourceErrors => {\n if (!(error instanceof HttpErrorResponse)) {\n return [\n {\n code: 'UNKNOWN',\n message: String(error),\n },\n ];\n }\n\n const errors = error.error?.errors as unknown;\n if (Array.isArray(errors)) {\n return errors as ResourceErrors;\n }\n\n return [\n {\n code: error.status.toString(),\n message: error.message,\n },\n ];\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAAkC;AAI3B,IAAM,sBAAuC,CAClD,UACmB;AACnB,MAAI,EAAE,iBAAiB,gCAAoB;AACzC,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,SAAS,OAAO,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,OAAO;AAC5B,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,MACE,MAAM,MAAM,OAAO,SAAS;AAAA,MAC5B,SAAS,MAAM;AAAA,IACjB;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,6 @@
1
+ import { E as ErrorNormalizer } from './error-normalizer-DZz8HS0o.cjs';
2
+ import '@flurryx/core';
3
+
4
+ declare const httpErrorNormalizer: ErrorNormalizer;
5
+
6
+ export { httpErrorNormalizer };
package/dist/http.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { E as ErrorNormalizer } from './error-normalizer-DZz8HS0o.js';
2
+ import '@flurryx/core';
3
+
4
+ declare const httpErrorNormalizer: ErrorNormalizer;
5
+
6
+ export { httpErrorNormalizer };
package/dist/http.js ADDED
@@ -0,0 +1,26 @@
1
+ // src/error/http-error-normalizer.ts
2
+ import { HttpErrorResponse } from "@angular/common/http";
3
+ var httpErrorNormalizer = (error) => {
4
+ if (!(error instanceof HttpErrorResponse)) {
5
+ return [
6
+ {
7
+ code: "UNKNOWN",
8
+ message: String(error)
9
+ }
10
+ ];
11
+ }
12
+ const errors = error.error?.errors;
13
+ if (Array.isArray(errors)) {
14
+ return errors;
15
+ }
16
+ return [
17
+ {
18
+ code: error.status.toString(),
19
+ message: error.message
20
+ }
21
+ ];
22
+ };
23
+ export {
24
+ httpErrorNormalizer
25
+ };
26
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/error/http-error-normalizer.ts"],"sourcesContent":["import { HttpErrorResponse } from '@angular/common/http';\nimport type { ResourceErrors } from '@flurryx/core';\nimport type { ErrorNormalizer } from './error-normalizer';\n\nexport const httpErrorNormalizer: ErrorNormalizer = (\n error: unknown\n): ResourceErrors => {\n if (!(error instanceof HttpErrorResponse)) {\n return [\n {\n code: 'UNKNOWN',\n message: String(error),\n },\n ];\n }\n\n const errors = error.error?.errors as unknown;\n if (Array.isArray(errors)) {\n return errors as ResourceErrors;\n }\n\n return [\n {\n code: error.status.toString(),\n message: error.message,\n },\n ];\n};\n"],"mappings":";AAAA,SAAS,yBAAyB;AAI3B,IAAM,sBAAuC,CAClD,UACmB;AACnB,MAAI,EAAE,iBAAiB,oBAAoB;AACzC,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,SAAS,OAAO,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,OAAO;AAC5B,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,MACE,MAAM,MAAM,OAAO,SAAS;AAAA,MAC5B,SAAS,MAAM;AAAA,IACjB;AAAA,EACF;AACF;","names":[]}
package/dist/index.cjs ADDED
@@ -0,0 +1,445 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ Loading: () => Loading,
24
+ SkipIfCached: () => SkipIfCached,
25
+ defaultErrorNormalizer: () => defaultErrorNormalizer,
26
+ syncToKeyedStore: () => syncToKeyedStore,
27
+ syncToStore: () => syncToStore
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/operators/sync-to-store.ts
32
+ var import_rxjs = require("rxjs");
33
+
34
+ // src/error/error-normalizer.ts
35
+ function defaultErrorNormalizer(error) {
36
+ if (typeof error === "object" && error !== null && "error" in error && typeof error.error === "object") {
37
+ const inner = error.error;
38
+ if (inner && Array.isArray(inner.errors)) {
39
+ return inner.errors;
40
+ }
41
+ }
42
+ if (typeof error === "object" && error !== null && "status" in error && "message" in error) {
43
+ const typed = error;
44
+ return [
45
+ {
46
+ code: String(typed.status),
47
+ message: typed.message
48
+ }
49
+ ];
50
+ }
51
+ if (error instanceof Error) {
52
+ return [
53
+ {
54
+ code: "UNKNOWN",
55
+ message: error.message
56
+ }
57
+ ];
58
+ }
59
+ return [
60
+ {
61
+ code: "UNKNOWN",
62
+ message: String(error)
63
+ }
64
+ ];
65
+ }
66
+
67
+ // src/operators/sync-to-store.ts
68
+ function syncToStore(store, key, options = { completeOnFirstEmission: true }) {
69
+ const normalizeError = options.errorNormalizer ?? defaultErrorNormalizer;
70
+ return (source) => {
71
+ let pipeline = source.pipe(
72
+ (0, import_rxjs.tap)({
73
+ next: (data) => {
74
+ store.update(key, {
75
+ data,
76
+ isLoading: false,
77
+ status: "Success",
78
+ errors: void 0
79
+ });
80
+ },
81
+ error: (error) => {
82
+ store.update(key, {
83
+ data: void 0,
84
+ isLoading: false,
85
+ status: "Error",
86
+ errors: normalizeError(error)
87
+ });
88
+ }
89
+ })
90
+ );
91
+ if (options.completeOnFirstEmission) {
92
+ pipeline = pipeline.pipe((0, import_rxjs.take)(1));
93
+ }
94
+ if (options.callbackAfterComplete) {
95
+ pipeline = pipeline.pipe((0, import_rxjs.finalize)(options.callbackAfterComplete));
96
+ }
97
+ return pipeline;
98
+ };
99
+ }
100
+
101
+ // src/operators/sync-to-keyed-store.ts
102
+ var import_rxjs2 = require("rxjs");
103
+ var import_core = require("@flurryx/core");
104
+ function withoutKey(record, key) {
105
+ const next = {
106
+ ...record
107
+ };
108
+ delete next[key];
109
+ return next;
110
+ }
111
+ function syncToKeyedStore(store, storeKey, resourceKey, options = {
112
+ completeOnFirstEmission: true
113
+ }) {
114
+ const { completeOnFirstEmission, callbackAfterComplete, mapResponse } = options;
115
+ const normalizeError = options.errorNormalizer ?? defaultErrorNormalizer;
116
+ return (source) => {
117
+ let pipeline = source.pipe(
118
+ (0, import_rxjs2.tap)({
119
+ next: (response) => {
120
+ const value = mapResponse ? mapResponse(response) : response;
121
+ const storeSignal = store.get(storeKey);
122
+ const state = storeSignal();
123
+ const data = state.data ?? (0, import_core.createKeyedResourceData)();
124
+ const nextIsLoading = {
125
+ ...data.isLoading,
126
+ [resourceKey]: false
127
+ };
128
+ const nextStatus = {
129
+ ...data.status,
130
+ [resourceKey]: "Success"
131
+ };
132
+ const nextData = {
133
+ ...data,
134
+ entities: {
135
+ ...data.entities,
136
+ [resourceKey]: value
137
+ },
138
+ isLoading: nextIsLoading,
139
+ status: nextStatus,
140
+ errors: withoutKey(data.errors, resourceKey)
141
+ };
142
+ store.update(storeKey, {
143
+ data: nextData,
144
+ isLoading: (0, import_core.isAnyKeyLoading)(nextIsLoading),
145
+ status: void 0,
146
+ errors: void 0
147
+ });
148
+ },
149
+ error: (error) => {
150
+ const storeSignal = store.get(storeKey);
151
+ const state = storeSignal();
152
+ const data = state.data ?? (0, import_core.createKeyedResourceData)();
153
+ const nextIsLoading = {
154
+ ...data.isLoading,
155
+ [resourceKey]: false
156
+ };
157
+ const nextStatus = {
158
+ ...data.status,
159
+ [resourceKey]: "Error"
160
+ };
161
+ const nextErrors = {
162
+ ...data.errors,
163
+ [resourceKey]: normalizeError(error)
164
+ };
165
+ const nextData = {
166
+ ...data,
167
+ isLoading: nextIsLoading,
168
+ status: nextStatus,
169
+ errors: nextErrors
170
+ };
171
+ store.update(storeKey, {
172
+ data: nextData,
173
+ isLoading: (0, import_core.isAnyKeyLoading)(nextIsLoading),
174
+ status: void 0,
175
+ errors: void 0
176
+ });
177
+ }
178
+ })
179
+ );
180
+ if (completeOnFirstEmission) {
181
+ pipeline = pipeline.pipe((0, import_rxjs2.take)(1));
182
+ }
183
+ if (callbackAfterComplete) {
184
+ pipeline = pipeline.pipe((0, import_rxjs2.finalize)(callbackAfterComplete));
185
+ }
186
+ return pipeline;
187
+ };
188
+ }
189
+
190
+ // src/decorators/skip-if-cached.ts
191
+ var import_rxjs3 = require("rxjs");
192
+ var import_core2 = require("@flurryx/core");
193
+ var import_core3 = require("@flurryx/core");
194
+ var cacheState = /* @__PURE__ */ new WeakMap();
195
+ function getStoreKeyMap(store, key) {
196
+ let storeMap = cacheState.get(store);
197
+ if (!storeMap) {
198
+ storeMap = /* @__PURE__ */ new Map();
199
+ cacheState.set(store, storeMap);
200
+ }
201
+ let keyMap = storeMap.get(key);
202
+ if (!keyMap) {
203
+ keyMap = /* @__PURE__ */ new Map();
204
+ storeMap.set(key, keyMap);
205
+ }
206
+ return keyMap;
207
+ }
208
+ function getCacheEntry(store, key, cacheKey) {
209
+ return getStoreKeyMap(store, key).get(cacheKey);
210
+ }
211
+ function setCacheEntry(store, key, cacheKey, entry) {
212
+ getStoreKeyMap(store, key).set(cacheKey, entry);
213
+ }
214
+ function clearCacheEntry(store, key, cacheKey) {
215
+ getStoreKeyMap(store, key).delete(cacheKey);
216
+ }
217
+ function deriveResourceKey(args) {
218
+ const key = args[0];
219
+ if (typeof key === "string" || typeof key === "number") {
220
+ return key;
221
+ }
222
+ return void 0;
223
+ }
224
+ function isExpired(timestamp, timeoutMs, now) {
225
+ if (timeoutMs === import_core3.CACHE_NO_TIMEOUT) {
226
+ return false;
227
+ }
228
+ if (timestamp === void 0) {
229
+ return false;
230
+ }
231
+ return now - timestamp >= timeoutMs;
232
+ }
233
+ function getStoreContext(instance, storeKey, getStore) {
234
+ const store = getStore(instance);
235
+ if (!store) {
236
+ return void 0;
237
+ }
238
+ const storeSignal = store.get(storeKey);
239
+ if (!storeSignal) {
240
+ return void 0;
241
+ }
242
+ const currentState = storeSignal();
243
+ if (currentState === null || currentState === void 0) {
244
+ return void 0;
245
+ }
246
+ return { store, storeSignal, currentState };
247
+ }
248
+ function getCacheContext(store, storeKey, args, argsString, currentState) {
249
+ const keyedData = (0, import_core2.isKeyedResourceData)(currentState.data) ? currentState.data : void 0;
250
+ const resourceKey = keyedData ? deriveResourceKey(args) : void 0;
251
+ const isKeyedCall = keyedData !== void 0 && resourceKey !== void 0;
252
+ const keyedCacheKey = argsString;
253
+ const nonKeyedCacheKey = "__single__";
254
+ const runtimeCacheKey = isKeyedCall ? keyedCacheKey : nonKeyedCacheKey;
255
+ const keyedCacheEntry = getCacheEntry(store, storeKey, keyedCacheKey);
256
+ const nonKeyedCacheEntry = getCacheEntry(store, storeKey, nonKeyedCacheKey);
257
+ return {
258
+ isKeyedCall,
259
+ resourceKey,
260
+ keyedData,
261
+ runtimeCacheKey,
262
+ keyedCacheEntry,
263
+ nonKeyedCacheEntry
264
+ };
265
+ }
266
+ function handleCacheErrors(store, storeKey, context, currentState) {
267
+ if (!context.keyedData && currentState.status === "Error") {
268
+ clearCacheEntry(store, storeKey, "__single__");
269
+ }
270
+ if (context.keyedData && context.resourceKey !== void 0) {
271
+ const status = context.keyedData.status[context.resourceKey];
272
+ if (status === "Error") {
273
+ clearCacheEntry(store, storeKey, context.runtimeCacheKey);
274
+ }
275
+ }
276
+ }
277
+ function handleKeyedCache(store, storeKey, context, timeoutMs, now, returnObservable) {
278
+ const { keyedData, resourceKey, keyedCacheEntry, runtimeCacheKey } = context;
279
+ if (!keyedData || resourceKey === void 0) {
280
+ return { hit: false };
281
+ }
282
+ const typed = keyedData;
283
+ const status = typed.status[resourceKey];
284
+ const entity = typed.entities[resourceKey];
285
+ const loading = typed.isLoading[resourceKey] === true;
286
+ const expired = isExpired(keyedCacheEntry?.timestamp, timeoutMs, now);
287
+ if (expired) {
288
+ clearCacheEntry(store, storeKey, runtimeCacheKey);
289
+ }
290
+ if (!expired && status === "Success" && entity !== void 0) {
291
+ if (returnObservable) {
292
+ return { hit: true, value: (0, import_rxjs3.of)(entity) };
293
+ }
294
+ return { hit: true };
295
+ }
296
+ if (returnObservable) {
297
+ if (keyedCacheEntry?.inflight$) {
298
+ return { hit: true, value: keyedCacheEntry.inflight$ };
299
+ }
300
+ } else if (loading) {
301
+ return { hit: true };
302
+ }
303
+ return { hit: false };
304
+ }
305
+ function handleNonKeyedCache(store, storeKey, context, timeoutMs, now, returnObservable, currentState, argsString, storeSignal) {
306
+ const { nonKeyedCacheEntry, runtimeCacheKey } = context;
307
+ if (returnObservable && nonKeyedCacheEntry?.args === argsString && nonKeyedCacheEntry.inflight$) {
308
+ return { hit: true, value: nonKeyedCacheEntry.inflight$ };
309
+ }
310
+ const hasValidCacheState = currentState?.status === "Success" || currentState?.isLoading === true;
311
+ if (nonKeyedCacheEntry && isExpired(nonKeyedCacheEntry.timestamp, timeoutMs, now)) {
312
+ clearCacheEntry(store, storeKey, runtimeCacheKey);
313
+ } else if (nonKeyedCacheEntry?.args === argsString && hasValidCacheState) {
314
+ if (returnObservable) {
315
+ if (nonKeyedCacheEntry.inflight$) {
316
+ return { hit: true, value: nonKeyedCacheEntry.inflight$ };
317
+ }
318
+ return { hit: true, value: (0, import_rxjs3.of)(storeSignal().data) };
319
+ }
320
+ return { hit: true };
321
+ }
322
+ return { hit: false };
323
+ }
324
+ function createCachedObservable(result, store, storeKey, runtimeCacheKey, argsString) {
325
+ return result.pipe(
326
+ (0, import_rxjs3.tap)({
327
+ next: () => {
328
+ setCacheEntry(store, storeKey, runtimeCacheKey, {
329
+ timestamp: Date.now(),
330
+ args: argsString
331
+ });
332
+ },
333
+ error: () => {
334
+ clearCacheEntry(store, storeKey, runtimeCacheKey);
335
+ }
336
+ }),
337
+ (0, import_rxjs3.finalize)(() => {
338
+ const entry = getCacheEntry(store, storeKey, runtimeCacheKey);
339
+ if (entry?.inflight$) {
340
+ const { inflight$: _inflight$, ...rest } = entry;
341
+ setCacheEntry(store, storeKey, runtimeCacheKey, rest);
342
+ }
343
+ }),
344
+ (0, import_rxjs3.shareReplay)({ bufferSize: 1, refCount: true })
345
+ );
346
+ }
347
+ function SkipIfCached(storeKey, storeGetter, returnObservable = false, timeoutMs = import_core3.DEFAULT_CACHE_TTL_MS) {
348
+ return function(_target, _propertyKey, descriptor) {
349
+ const originalMethod = descriptor.value;
350
+ descriptor.value = function(...args) {
351
+ const storeContext = getStoreContext(this, storeKey, storeGetter);
352
+ if (!storeContext) {
353
+ return originalMethod.apply(this, args);
354
+ }
355
+ const { store, storeSignal, currentState } = storeContext;
356
+ const argsString = JSON.stringify(args);
357
+ const now = Date.now();
358
+ const cacheContext = getCacheContext(
359
+ store,
360
+ storeKey,
361
+ args,
362
+ argsString,
363
+ currentState
364
+ );
365
+ handleCacheErrors(store, storeKey, cacheContext, currentState);
366
+ let cacheHit;
367
+ if (cacheContext.isKeyedCall) {
368
+ cacheHit = handleKeyedCache(
369
+ store,
370
+ storeKey,
371
+ cacheContext,
372
+ timeoutMs,
373
+ now,
374
+ returnObservable
375
+ );
376
+ } else {
377
+ cacheHit = handleNonKeyedCache(
378
+ store,
379
+ storeKey,
380
+ cacheContext,
381
+ timeoutMs,
382
+ now,
383
+ returnObservable,
384
+ currentState,
385
+ argsString,
386
+ storeSignal
387
+ );
388
+ }
389
+ if (cacheHit.hit) {
390
+ return cacheHit.value;
391
+ }
392
+ const result = originalMethod.apply(this, args);
393
+ if (!returnObservable) {
394
+ setCacheEntry(store, storeKey, cacheContext.runtimeCacheKey, {
395
+ timestamp: now,
396
+ args: argsString
397
+ });
398
+ return result;
399
+ }
400
+ const inflight$ = createCachedObservable(
401
+ result,
402
+ store,
403
+ storeKey,
404
+ cacheContext.runtimeCacheKey,
405
+ argsString
406
+ );
407
+ setCacheEntry(store, storeKey, cacheContext.runtimeCacheKey, {
408
+ timestamp: now,
409
+ args: argsString,
410
+ inflight$
411
+ });
412
+ return inflight$;
413
+ };
414
+ return descriptor;
415
+ };
416
+ }
417
+
418
+ // src/decorators/loading.ts
419
+ function Loading(storeKey, storeGetter) {
420
+ return function(_target, _propertyKey, descriptor) {
421
+ const originalMethod = descriptor.value;
422
+ descriptor.value = function(...args) {
423
+ const store = storeGetter(this);
424
+ const resourceKey = args[0];
425
+ const canKey = typeof resourceKey === "string" || typeof resourceKey === "number";
426
+ const hasKeyed = typeof store === "object" && store !== null && "startKeyedLoading" in store && typeof store.startKeyedLoading === "function";
427
+ if (canKey && hasKeyed) {
428
+ store.startKeyedLoading(storeKey, resourceKey);
429
+ } else {
430
+ store?.startLoading(storeKey);
431
+ }
432
+ return originalMethod.apply(this, args);
433
+ };
434
+ return descriptor;
435
+ };
436
+ }
437
+ // Annotate the CommonJS export names for ESM import in node:
438
+ 0 && (module.exports = {
439
+ Loading,
440
+ SkipIfCached,
441
+ defaultErrorNormalizer,
442
+ syncToKeyedStore,
443
+ syncToStore
444
+ });
445
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/operators/sync-to-store.ts","../src/error/error-normalizer.ts","../src/operators/sync-to-keyed-store.ts","../src/decorators/skip-if-cached.ts","../src/decorators/loading.ts"],"sourcesContent":["export {\n syncToStore,\n type SyncToStoreOptions,\n} from './operators/sync-to-store';\nexport {\n syncToKeyedStore,\n type SyncToKeyedStoreOptions,\n} from './operators/sync-to-keyed-store';\nexport { SkipIfCached } from './decorators/skip-if-cached';\nexport { Loading } from './decorators/loading';\nexport {\n defaultErrorNormalizer,\n type ErrorNormalizer,\n} from './error/error-normalizer';\n","import { finalize, Observable, take, tap } from \"rxjs\";\nimport { BaseStore } from \"@flurryx/store\";\nimport type { ResourceState } from \"@flurryx/core\";\nimport {\n defaultErrorNormalizer,\n type ErrorNormalizer,\n} from \"../error/error-normalizer\";\n\nexport interface SyncToStoreOptions {\n completeOnFirstEmission?: boolean;\n callbackAfterComplete?: () => void;\n errorNormalizer?: ErrorNormalizer;\n}\n\nexport function syncToStore<\n TEnum extends Record<string, string | number>,\n TData extends { [K in keyof TEnum]: ResourceState<unknown> }\n>(\n store: BaseStore<TEnum, TData>,\n key: keyof TEnum,\n options: SyncToStoreOptions = { completeOnFirstEmission: true }\n) {\n const normalizeError = options.errorNormalizer ?? defaultErrorNormalizer;\n\n return <R>(source: Observable<R>) => {\n let pipeline = source.pipe(\n tap({\n next: (data: R) => {\n store.update(key, {\n data,\n isLoading: false,\n status: \"Success\",\n errors: undefined,\n } as Partial<TData[typeof key]>);\n },\n error: (error: unknown) => {\n store.update(key, {\n data: undefined,\n isLoading: false,\n status: \"Error\",\n errors: normalizeError(error),\n } as Partial<TData[typeof key]>);\n },\n })\n );\n\n if (options.completeOnFirstEmission) {\n pipeline = pipeline.pipe(take(1));\n }\n\n if (options.callbackAfterComplete) {\n pipeline = pipeline.pipe(finalize(options.callbackAfterComplete));\n }\n\n return pipeline;\n };\n}\n","import type { ResourceErrors } from '@flurryx/core';\n\nexport type ErrorNormalizer = (error: unknown) => ResourceErrors;\n\nexport function defaultErrorNormalizer(error: unknown): ResourceErrors {\n if (\n typeof error === 'object' &&\n error !== null &&\n 'error' in error &&\n typeof (error as Record<string, unknown>).error === 'object'\n ) {\n const inner = (error as { error: Record<string, unknown> }).error;\n if (inner && Array.isArray(inner.errors)) {\n return inner.errors as ResourceErrors;\n }\n }\n\n if (\n typeof error === 'object' &&\n error !== null &&\n 'status' in error &&\n 'message' in error\n ) {\n const typed = error as { status: number; message: string };\n return [\n {\n code: String(typed.status),\n message: typed.message,\n },\n ];\n }\n\n if (error instanceof Error) {\n return [\n {\n code: 'UNKNOWN',\n message: error.message,\n },\n ];\n }\n\n return [\n {\n code: 'UNKNOWN',\n message: String(error),\n },\n ];\n}\n","import { finalize, Observable, take, tap } from \"rxjs\";\nimport { BaseStore } from \"@flurryx/store\";\nimport {\n createKeyedResourceData,\n isAnyKeyLoading,\n type KeyedResourceData,\n type KeyedResourceKey,\n type ResourceErrors,\n type ResourceState,\n type ResourceStatus,\n} from \"@flurryx/core\";\nimport {\n defaultErrorNormalizer,\n type ErrorNormalizer,\n} from \"../error/error-normalizer\";\nimport type { SyncToStoreOptions } from \"./sync-to-store\";\n\nexport interface SyncToKeyedStoreOptions<R, TValue> extends SyncToStoreOptions {\n mapResponse?: (response: R) => TValue;\n errorNormalizer?: ErrorNormalizer;\n}\n\nfunction withoutKey<TKey extends KeyedResourceKey, TValue>(\n record: Partial<Record<TKey, TValue>>,\n key: TKey\n): Partial<Record<TKey, TValue>> {\n const next: Partial<Record<TKey, TValue>> = {\n ...record,\n };\n delete next[key];\n return next;\n}\n\nexport function syncToKeyedStore<\n TEnum extends Record<string, string | number>,\n TStoreKey extends keyof TEnum,\n TKey extends KeyedResourceKey,\n TValue,\n R = TValue,\n TState extends ResourceState<KeyedResourceData<TKey, TValue>> = ResourceState<\n KeyedResourceData<TKey, TValue>\n >,\n TData extends {\n [K in keyof TEnum]: ResourceState<unknown>;\n } & { [K in TStoreKey]: TState } = {\n [K in keyof TEnum]: ResourceState<unknown>;\n } & { [K in TStoreKey]: TState }\n>(\n store: BaseStore<TEnum, TData>,\n storeKey: TStoreKey,\n resourceKey: TKey,\n options: SyncToKeyedStoreOptions<R, TValue> = {\n completeOnFirstEmission: true,\n }\n) {\n const { completeOnFirstEmission, callbackAfterComplete, mapResponse } =\n options;\n const normalizeError = options.errorNormalizer ?? defaultErrorNormalizer;\n\n return (source: Observable<R>) => {\n let pipeline = source.pipe(\n tap({\n next: (response: R) => {\n const value = mapResponse\n ? mapResponse(response)\n : (response as unknown as TValue);\n\n const storeSignal = store.get(storeKey);\n const state = storeSignal();\n const data = state.data ?? createKeyedResourceData<TKey, TValue>();\n\n const nextIsLoading = {\n ...data.isLoading,\n [resourceKey]: false,\n } as Partial<Record<TKey, boolean>>;\n\n const nextStatus: Partial<Record<TKey, ResourceStatus>> = {\n ...data.status,\n [resourceKey]: \"Success\",\n };\n\n const nextData: KeyedResourceData<TKey, TValue> = {\n ...data,\n entities: {\n ...data.entities,\n [resourceKey]: value,\n } as Partial<Record<TKey, TValue>>,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: withoutKey(data.errors, resourceKey),\n };\n\n store.update(storeKey, {\n data: nextData,\n isLoading: isAnyKeyLoading(nextIsLoading),\n status: undefined,\n errors: undefined,\n } as Partial<TData[typeof storeKey]>);\n },\n error: (error: unknown) => {\n const storeSignal = store.get(storeKey);\n const state = storeSignal();\n const data = state.data ?? createKeyedResourceData<TKey, TValue>();\n\n const nextIsLoading = {\n ...data.isLoading,\n [resourceKey]: false,\n } as Partial<Record<TKey, boolean>>;\n\n const nextStatus: Partial<Record<TKey, ResourceStatus>> = {\n ...data.status,\n [resourceKey]: \"Error\",\n };\n\n const nextErrors: Partial<Record<TKey, ResourceErrors>> = {\n ...data.errors,\n [resourceKey]: normalizeError(error),\n };\n\n const nextData: KeyedResourceData<TKey, TValue> = {\n ...data,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n store.update(storeKey, {\n data: nextData,\n isLoading: isAnyKeyLoading(nextIsLoading),\n status: undefined,\n errors: undefined,\n } as Partial<TData[typeof storeKey]>);\n },\n })\n );\n\n if (completeOnFirstEmission) {\n pipeline = pipeline.pipe(take(1));\n }\n\n if (callbackAfterComplete) {\n pipeline = pipeline.pipe(finalize(callbackAfterComplete));\n }\n\n return pipeline;\n };\n}\n","import { WritableSignal } from '@angular/core';\nimport { finalize, Observable, of, shareReplay, tap } from 'rxjs';\nimport type { ResourceState, StoreEnum, KeyedResourceKey } from '@flurryx/core';\nimport { isKeyedResourceData } from '@flurryx/core';\nimport { CACHE_NO_TIMEOUT, DEFAULT_CACHE_TTL_MS } from '@flurryx/core';\n\ntype StoreWithSignal<TKey extends StoreEnum> = {\n get: (key: TKey) => WritableSignal<ResourceState<unknown>> | undefined;\n};\n\ninterface CacheEntry {\n timestamp: number;\n args: string;\n inflight$?: Observable<unknown>;\n}\n\nconst cacheState = new WeakMap<\n object,\n Map<StoreEnum, Map<string, CacheEntry>>\n>();\n\nfunction getStoreKeyMap(\n store: object,\n key: StoreEnum\n): Map<string, CacheEntry> {\n let storeMap = cacheState.get(store);\n if (!storeMap) {\n storeMap = new Map();\n cacheState.set(store, storeMap);\n }\n\n let keyMap = storeMap.get(key);\n if (!keyMap) {\n keyMap = new Map();\n storeMap.set(key, keyMap);\n }\n\n return keyMap;\n}\n\nfunction getCacheEntry(\n store: object,\n key: StoreEnum,\n cacheKey: string\n): CacheEntry | undefined {\n return getStoreKeyMap(store, key).get(cacheKey);\n}\n\nfunction setCacheEntry(\n store: object,\n key: StoreEnum,\n cacheKey: string,\n entry: CacheEntry\n): void {\n getStoreKeyMap(store, key).set(cacheKey, entry);\n}\n\nfunction clearCacheEntry(\n store: object,\n key: StoreEnum,\n cacheKey: string\n): void {\n getStoreKeyMap(store, key).delete(cacheKey);\n}\n\nfunction deriveResourceKey(args: unknown[]): KeyedResourceKey | undefined {\n const key = args[0];\n if (typeof key === 'string' || typeof key === 'number') {\n return key;\n }\n return undefined;\n}\n\nfunction isExpired(\n timestamp: number | undefined,\n timeoutMs: number,\n now: number\n): boolean {\n if (timeoutMs === CACHE_NO_TIMEOUT) {\n return false;\n }\n if (timestamp === undefined) {\n return false;\n }\n return now - timestamp >= timeoutMs;\n}\n\ninterface StoreContext {\n store: object;\n storeSignal: WritableSignal<ResourceState<unknown>>;\n currentState: ResourceState<unknown>;\n}\n\nfunction getStoreContext<TTarget, TKey extends StoreEnum>(\n instance: TTarget,\n storeKey: TKey,\n getStore: (i: TTarget) => StoreWithSignal<TKey> | undefined\n): StoreContext | undefined {\n const store = getStore(instance);\n if (!store) {\n return undefined;\n }\n\n const storeSignal = store.get(storeKey);\n if (!storeSignal) {\n return undefined;\n }\n\n const currentState = storeSignal();\n if (currentState === null || currentState === undefined) {\n return undefined;\n }\n\n return { store, storeSignal, currentState };\n}\n\ninterface CacheContext {\n isKeyedCall: boolean;\n resourceKey: KeyedResourceKey | undefined;\n keyedData: ReturnType<typeof isKeyedResourceData> extends true\n ? { entities: object; isLoading: object; status: object; errors: object }\n : undefined;\n runtimeCacheKey: string;\n keyedCacheEntry: CacheEntry | undefined;\n nonKeyedCacheEntry: CacheEntry | undefined;\n}\n\nfunction getCacheContext(\n store: object,\n storeKey: StoreEnum,\n args: unknown[],\n argsString: string,\n currentState: ResourceState<unknown>\n): CacheContext {\n const keyedData = isKeyedResourceData(currentState.data)\n ? currentState.data\n : undefined;\n const resourceKey = keyedData ? deriveResourceKey(args) : undefined;\n const isKeyedCall = keyedData !== undefined && resourceKey !== undefined;\n\n const keyedCacheKey = argsString;\n const nonKeyedCacheKey = '__single__';\n const runtimeCacheKey = isKeyedCall ? keyedCacheKey : nonKeyedCacheKey;\n\n const keyedCacheEntry = getCacheEntry(store, storeKey, keyedCacheKey);\n const nonKeyedCacheEntry = getCacheEntry(store, storeKey, nonKeyedCacheKey);\n\n return {\n isKeyedCall,\n resourceKey,\n keyedData: keyedData as CacheContext['keyedData'],\n runtimeCacheKey,\n keyedCacheEntry,\n nonKeyedCacheEntry,\n };\n}\n\nfunction handleCacheErrors(\n store: object,\n storeKey: StoreEnum,\n context: CacheContext,\n currentState: ResourceState<unknown>\n): void {\n if (!context.keyedData && currentState.status === 'Error') {\n clearCacheEntry(store, storeKey, '__single__');\n }\n if (context.keyedData && context.resourceKey !== undefined) {\n const status = (\n context.keyedData as {\n status: Partial<Record<KeyedResourceKey, string>>;\n }\n ).status[context.resourceKey];\n if (status === 'Error') {\n clearCacheEntry(store, storeKey, context.runtimeCacheKey);\n }\n }\n}\n\ninterface CacheHitResult {\n hit: boolean;\n value?: Observable<unknown>;\n}\n\nfunction handleKeyedCache(\n store: object,\n storeKey: StoreEnum,\n context: CacheContext,\n timeoutMs: number,\n now: number,\n returnObservable: boolean\n): CacheHitResult {\n const { keyedData, resourceKey, keyedCacheEntry, runtimeCacheKey } = context;\n\n if (!keyedData || resourceKey === undefined) {\n return { hit: false };\n }\n\n const typed = keyedData as {\n status: Partial<Record<KeyedResourceKey, string>>;\n entities: Partial<Record<KeyedResourceKey, unknown>>;\n isLoading: Partial<Record<KeyedResourceKey, boolean>>;\n };\n\n const status = typed.status[resourceKey];\n const entity = typed.entities[resourceKey];\n const loading = typed.isLoading[resourceKey] === true;\n\n const expired = isExpired(keyedCacheEntry?.timestamp, timeoutMs, now);\n if (expired) {\n clearCacheEntry(store, storeKey, runtimeCacheKey);\n }\n\n if (!expired && status === 'Success' && entity !== undefined) {\n if (returnObservable) {\n return { hit: true, value: of(entity) };\n }\n return { hit: true };\n }\n\n if (returnObservable) {\n if (keyedCacheEntry?.inflight$) {\n return { hit: true, value: keyedCacheEntry.inflight$ };\n }\n } else if (loading) {\n return { hit: true };\n }\n\n return { hit: false };\n}\n\nfunction handleNonKeyedCache(\n store: object,\n storeKey: StoreEnum,\n context: CacheContext,\n timeoutMs: number,\n now: number,\n returnObservable: boolean,\n currentState: ResourceState<unknown>,\n argsString: string,\n storeSignal: WritableSignal<ResourceState<unknown>>\n): CacheHitResult {\n const { nonKeyedCacheEntry, runtimeCacheKey } = context;\n\n if (\n returnObservable &&\n nonKeyedCacheEntry?.args === argsString &&\n nonKeyedCacheEntry.inflight$\n ) {\n return { hit: true, value: nonKeyedCacheEntry.inflight$ };\n }\n\n const hasValidCacheState =\n currentState?.status === 'Success' || currentState?.isLoading === true;\n\n if (\n nonKeyedCacheEntry &&\n isExpired(nonKeyedCacheEntry.timestamp, timeoutMs, now)\n ) {\n clearCacheEntry(store, storeKey, runtimeCacheKey);\n } else if (nonKeyedCacheEntry?.args === argsString && hasValidCacheState) {\n if (returnObservable) {\n if (nonKeyedCacheEntry.inflight$) {\n return { hit: true, value: nonKeyedCacheEntry.inflight$ };\n }\n return { hit: true, value: of(storeSignal().data) };\n }\n return { hit: true };\n }\n\n return { hit: false };\n}\n\nfunction createCachedObservable(\n result: Observable<unknown>,\n store: object,\n storeKey: StoreEnum,\n runtimeCacheKey: string,\n argsString: string\n): Observable<unknown> {\n return result.pipe(\n tap({\n next: () => {\n setCacheEntry(store, storeKey, runtimeCacheKey, {\n timestamp: Date.now(),\n args: argsString,\n });\n },\n error: () => {\n clearCacheEntry(store, storeKey, runtimeCacheKey);\n },\n }),\n finalize(() => {\n const entry = getCacheEntry(store, storeKey, runtimeCacheKey);\n if (entry?.inflight$) {\n const { inflight$: _inflight$, ...rest } = entry;\n setCacheEntry(store, storeKey, runtimeCacheKey, rest);\n }\n }),\n shareReplay({ bufferSize: 1, refCount: true })\n );\n}\n\nexport function SkipIfCached<TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: {\n store: StoreWithSignal<TKey>;\n }) => StoreWithSignal<TKey> | undefined,\n returnObservable?: boolean,\n timeoutMs?: number\n): MethodDecorator;\nexport function SkipIfCached<TTarget, TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: TTarget) => StoreWithSignal<TKey> | undefined,\n returnObservable?: boolean,\n timeoutMs?: number\n): MethodDecorator;\nexport function SkipIfCached<TTarget, TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: TTarget) => StoreWithSignal<TKey> | undefined,\n returnObservable = false,\n timeoutMs = DEFAULT_CACHE_TTL_MS\n): MethodDecorator {\n return function (\n _target: unknown,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ) {\n const originalMethod = descriptor.value as (\n this: TTarget,\n ...args: unknown[]\n ) => unknown;\n\n descriptor.value = function (this: TTarget, ...args: unknown[]) {\n const storeContext = getStoreContext(this, storeKey, storeGetter);\n if (!storeContext) {\n return originalMethod.apply(this, args);\n }\n const { store, storeSignal, currentState } = storeContext;\n\n const argsString = JSON.stringify(args);\n const now = Date.now();\n const cacheContext = getCacheContext(\n store,\n storeKey,\n args,\n argsString,\n currentState\n );\n\n handleCacheErrors(store, storeKey, cacheContext, currentState);\n\n let cacheHit: CacheHitResult;\n\n if (cacheContext.isKeyedCall) {\n cacheHit = handleKeyedCache(\n store,\n storeKey,\n cacheContext,\n timeoutMs,\n now,\n returnObservable\n );\n } else {\n cacheHit = handleNonKeyedCache(\n store,\n storeKey,\n cacheContext,\n timeoutMs,\n now,\n returnObservable,\n currentState,\n argsString,\n storeSignal\n );\n }\n\n if (cacheHit.hit) {\n return cacheHit.value;\n }\n\n const result = originalMethod.apply(this, args);\n\n if (!returnObservable) {\n setCacheEntry(store, storeKey, cacheContext.runtimeCacheKey, {\n timestamp: now,\n args: argsString,\n });\n return result;\n }\n\n const inflight$ = createCachedObservable(\n result as Observable<unknown>,\n store,\n storeKey,\n cacheContext.runtimeCacheKey,\n argsString\n );\n\n setCacheEntry(store, storeKey, cacheContext.runtimeCacheKey, {\n timestamp: now,\n args: argsString,\n inflight$,\n });\n\n return inflight$;\n };\n\n return descriptor;\n };\n}\n","import type { StoreEnum, KeyedResourceKey } from '@flurryx/core';\n\ntype StoreWithLoading<TKey extends StoreEnum> = {\n startLoading: (key: TKey) => void;\n};\n\nexport function Loading<TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: {\n store: StoreWithLoading<TKey>;\n }) => StoreWithLoading<TKey>\n): MethodDecorator;\nexport function Loading<TTarget, TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: TTarget) => StoreWithLoading<TKey>\n): MethodDecorator;\nexport function Loading<TTarget, TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: TTarget) => StoreWithLoading<TKey>\n) {\n return function (\n _target: unknown,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ) {\n const originalMethod = descriptor.value as (\n this: unknown,\n ...args: unknown[]\n ) => unknown;\n\n descriptor.value = function (this: TTarget, ...args: unknown[]) {\n const store = storeGetter(this);\n\n const resourceKey = args[0];\n const canKey =\n typeof resourceKey === 'string' || typeof resourceKey === 'number';\n const hasKeyed =\n typeof store === 'object' &&\n store !== null &&\n 'startKeyedLoading' in store &&\n typeof (store as { startKeyedLoading?: unknown }).startKeyedLoading ===\n 'function';\n\n if (canKey && hasKeyed) {\n (\n store as unknown as {\n startKeyedLoading: (\n key: TKey,\n resourceKey: KeyedResourceKey\n ) => void;\n }\n ).startKeyedLoading(storeKey, resourceKey as KeyedResourceKey);\n } else {\n store?.startLoading(storeKey);\n }\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n };\n}\n"],"mappings":"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","names":["import_rxjs","import_rxjs","import_core"]}
@@ -0,0 +1,47 @@
1
+ import { Observable } from 'rxjs';
2
+ import { BaseStore } from '@flurryx/store';
3
+ import { ResourceState, KeyedResourceKey, KeyedResourceData, StoreEnum } from '@flurryx/core';
4
+ import { E as ErrorNormalizer } from './error-normalizer-DZz8HS0o.cjs';
5
+ export { d as defaultErrorNormalizer } from './error-normalizer-DZz8HS0o.cjs';
6
+ import { WritableSignal } from '@angular/core';
7
+
8
+ interface SyncToStoreOptions {
9
+ completeOnFirstEmission?: boolean;
10
+ callbackAfterComplete?: () => void;
11
+ errorNormalizer?: ErrorNormalizer;
12
+ }
13
+ declare function syncToStore<TEnum extends Record<string, string | number>, TData extends {
14
+ [K in keyof TEnum]: ResourceState<unknown>;
15
+ }>(store: BaseStore<TEnum, TData>, key: keyof TEnum, options?: SyncToStoreOptions): <R>(source: Observable<R>) => Observable<R>;
16
+
17
+ interface SyncToKeyedStoreOptions<R, TValue> extends SyncToStoreOptions {
18
+ mapResponse?: (response: R) => TValue;
19
+ errorNormalizer?: ErrorNormalizer;
20
+ }
21
+ declare function syncToKeyedStore<TEnum extends Record<string, string | number>, TStoreKey extends keyof TEnum, TKey extends KeyedResourceKey, TValue, R = TValue, TState extends ResourceState<KeyedResourceData<TKey, TValue>> = ResourceState<KeyedResourceData<TKey, TValue>>, TData extends {
22
+ [K in keyof TEnum]: ResourceState<unknown>;
23
+ } & {
24
+ [K in TStoreKey]: TState;
25
+ } = {
26
+ [K in keyof TEnum]: ResourceState<unknown>;
27
+ } & {
28
+ [K in TStoreKey]: TState;
29
+ }>(store: BaseStore<TEnum, TData>, storeKey: TStoreKey, resourceKey: TKey, options?: SyncToKeyedStoreOptions<R, TValue>): (source: Observable<R>) => Observable<R>;
30
+
31
+ type StoreWithSignal<TKey extends StoreEnum> = {
32
+ get: (key: TKey) => WritableSignal<ResourceState<unknown>> | undefined;
33
+ };
34
+ declare function SkipIfCached<TKey extends StoreEnum>(storeKey: TKey, storeGetter: (instance: {
35
+ store: StoreWithSignal<TKey>;
36
+ }) => StoreWithSignal<TKey> | undefined, returnObservable?: boolean, timeoutMs?: number): MethodDecorator;
37
+ declare function SkipIfCached<TTarget, TKey extends StoreEnum>(storeKey: TKey, storeGetter: (instance: TTarget) => StoreWithSignal<TKey> | undefined, returnObservable?: boolean, timeoutMs?: number): MethodDecorator;
38
+
39
+ type StoreWithLoading<TKey extends StoreEnum> = {
40
+ startLoading: (key: TKey) => void;
41
+ };
42
+ declare function Loading<TKey extends StoreEnum>(storeKey: TKey, storeGetter: (instance: {
43
+ store: StoreWithLoading<TKey>;
44
+ }) => StoreWithLoading<TKey>): MethodDecorator;
45
+ declare function Loading<TTarget, TKey extends StoreEnum>(storeKey: TKey, storeGetter: (instance: TTarget) => StoreWithLoading<TKey>): MethodDecorator;
46
+
47
+ export { ErrorNormalizer, Loading, SkipIfCached, type SyncToKeyedStoreOptions, type SyncToStoreOptions, syncToKeyedStore, syncToStore };
@@ -0,0 +1,47 @@
1
+ import { Observable } from 'rxjs';
2
+ import { BaseStore } from '@flurryx/store';
3
+ import { ResourceState, KeyedResourceKey, KeyedResourceData, StoreEnum } from '@flurryx/core';
4
+ import { E as ErrorNormalizer } from './error-normalizer-DZz8HS0o.js';
5
+ export { d as defaultErrorNormalizer } from './error-normalizer-DZz8HS0o.js';
6
+ import { WritableSignal } from '@angular/core';
7
+
8
+ interface SyncToStoreOptions {
9
+ completeOnFirstEmission?: boolean;
10
+ callbackAfterComplete?: () => void;
11
+ errorNormalizer?: ErrorNormalizer;
12
+ }
13
+ declare function syncToStore<TEnum extends Record<string, string | number>, TData extends {
14
+ [K in keyof TEnum]: ResourceState<unknown>;
15
+ }>(store: BaseStore<TEnum, TData>, key: keyof TEnum, options?: SyncToStoreOptions): <R>(source: Observable<R>) => Observable<R>;
16
+
17
+ interface SyncToKeyedStoreOptions<R, TValue> extends SyncToStoreOptions {
18
+ mapResponse?: (response: R) => TValue;
19
+ errorNormalizer?: ErrorNormalizer;
20
+ }
21
+ declare function syncToKeyedStore<TEnum extends Record<string, string | number>, TStoreKey extends keyof TEnum, TKey extends KeyedResourceKey, TValue, R = TValue, TState extends ResourceState<KeyedResourceData<TKey, TValue>> = ResourceState<KeyedResourceData<TKey, TValue>>, TData extends {
22
+ [K in keyof TEnum]: ResourceState<unknown>;
23
+ } & {
24
+ [K in TStoreKey]: TState;
25
+ } = {
26
+ [K in keyof TEnum]: ResourceState<unknown>;
27
+ } & {
28
+ [K in TStoreKey]: TState;
29
+ }>(store: BaseStore<TEnum, TData>, storeKey: TStoreKey, resourceKey: TKey, options?: SyncToKeyedStoreOptions<R, TValue>): (source: Observable<R>) => Observable<R>;
30
+
31
+ type StoreWithSignal<TKey extends StoreEnum> = {
32
+ get: (key: TKey) => WritableSignal<ResourceState<unknown>> | undefined;
33
+ };
34
+ declare function SkipIfCached<TKey extends StoreEnum>(storeKey: TKey, storeGetter: (instance: {
35
+ store: StoreWithSignal<TKey>;
36
+ }) => StoreWithSignal<TKey> | undefined, returnObservable?: boolean, timeoutMs?: number): MethodDecorator;
37
+ declare function SkipIfCached<TTarget, TKey extends StoreEnum>(storeKey: TKey, storeGetter: (instance: TTarget) => StoreWithSignal<TKey> | undefined, returnObservable?: boolean, timeoutMs?: number): MethodDecorator;
38
+
39
+ type StoreWithLoading<TKey extends StoreEnum> = {
40
+ startLoading: (key: TKey) => void;
41
+ };
42
+ declare function Loading<TKey extends StoreEnum>(storeKey: TKey, storeGetter: (instance: {
43
+ store: StoreWithLoading<TKey>;
44
+ }) => StoreWithLoading<TKey>): MethodDecorator;
45
+ declare function Loading<TTarget, TKey extends StoreEnum>(storeKey: TKey, storeGetter: (instance: TTarget) => StoreWithLoading<TKey>): MethodDecorator;
46
+
47
+ export { ErrorNormalizer, Loading, SkipIfCached, type SyncToKeyedStoreOptions, type SyncToStoreOptions, syncToKeyedStore, syncToStore };
package/dist/index.js ADDED
@@ -0,0 +1,417 @@
1
+ // src/operators/sync-to-store.ts
2
+ import { finalize, take, tap } from "rxjs";
3
+
4
+ // src/error/error-normalizer.ts
5
+ function defaultErrorNormalizer(error) {
6
+ if (typeof error === "object" && error !== null && "error" in error && typeof error.error === "object") {
7
+ const inner = error.error;
8
+ if (inner && Array.isArray(inner.errors)) {
9
+ return inner.errors;
10
+ }
11
+ }
12
+ if (typeof error === "object" && error !== null && "status" in error && "message" in error) {
13
+ const typed = error;
14
+ return [
15
+ {
16
+ code: String(typed.status),
17
+ message: typed.message
18
+ }
19
+ ];
20
+ }
21
+ if (error instanceof Error) {
22
+ return [
23
+ {
24
+ code: "UNKNOWN",
25
+ message: error.message
26
+ }
27
+ ];
28
+ }
29
+ return [
30
+ {
31
+ code: "UNKNOWN",
32
+ message: String(error)
33
+ }
34
+ ];
35
+ }
36
+
37
+ // src/operators/sync-to-store.ts
38
+ function syncToStore(store, key, options = { completeOnFirstEmission: true }) {
39
+ const normalizeError = options.errorNormalizer ?? defaultErrorNormalizer;
40
+ return (source) => {
41
+ let pipeline = source.pipe(
42
+ tap({
43
+ next: (data) => {
44
+ store.update(key, {
45
+ data,
46
+ isLoading: false,
47
+ status: "Success",
48
+ errors: void 0
49
+ });
50
+ },
51
+ error: (error) => {
52
+ store.update(key, {
53
+ data: void 0,
54
+ isLoading: false,
55
+ status: "Error",
56
+ errors: normalizeError(error)
57
+ });
58
+ }
59
+ })
60
+ );
61
+ if (options.completeOnFirstEmission) {
62
+ pipeline = pipeline.pipe(take(1));
63
+ }
64
+ if (options.callbackAfterComplete) {
65
+ pipeline = pipeline.pipe(finalize(options.callbackAfterComplete));
66
+ }
67
+ return pipeline;
68
+ };
69
+ }
70
+
71
+ // src/operators/sync-to-keyed-store.ts
72
+ import { finalize as finalize2, take as take2, tap as tap2 } from "rxjs";
73
+ import {
74
+ createKeyedResourceData,
75
+ isAnyKeyLoading
76
+ } from "@flurryx/core";
77
+ function withoutKey(record, key) {
78
+ const next = {
79
+ ...record
80
+ };
81
+ delete next[key];
82
+ return next;
83
+ }
84
+ function syncToKeyedStore(store, storeKey, resourceKey, options = {
85
+ completeOnFirstEmission: true
86
+ }) {
87
+ const { completeOnFirstEmission, callbackAfterComplete, mapResponse } = options;
88
+ const normalizeError = options.errorNormalizer ?? defaultErrorNormalizer;
89
+ return (source) => {
90
+ let pipeline = source.pipe(
91
+ tap2({
92
+ next: (response) => {
93
+ const value = mapResponse ? mapResponse(response) : response;
94
+ const storeSignal = store.get(storeKey);
95
+ const state = storeSignal();
96
+ const data = state.data ?? createKeyedResourceData();
97
+ const nextIsLoading = {
98
+ ...data.isLoading,
99
+ [resourceKey]: false
100
+ };
101
+ const nextStatus = {
102
+ ...data.status,
103
+ [resourceKey]: "Success"
104
+ };
105
+ const nextData = {
106
+ ...data,
107
+ entities: {
108
+ ...data.entities,
109
+ [resourceKey]: value
110
+ },
111
+ isLoading: nextIsLoading,
112
+ status: nextStatus,
113
+ errors: withoutKey(data.errors, resourceKey)
114
+ };
115
+ store.update(storeKey, {
116
+ data: nextData,
117
+ isLoading: isAnyKeyLoading(nextIsLoading),
118
+ status: void 0,
119
+ errors: void 0
120
+ });
121
+ },
122
+ error: (error) => {
123
+ const storeSignal = store.get(storeKey);
124
+ const state = storeSignal();
125
+ const data = state.data ?? createKeyedResourceData();
126
+ const nextIsLoading = {
127
+ ...data.isLoading,
128
+ [resourceKey]: false
129
+ };
130
+ const nextStatus = {
131
+ ...data.status,
132
+ [resourceKey]: "Error"
133
+ };
134
+ const nextErrors = {
135
+ ...data.errors,
136
+ [resourceKey]: normalizeError(error)
137
+ };
138
+ const nextData = {
139
+ ...data,
140
+ isLoading: nextIsLoading,
141
+ status: nextStatus,
142
+ errors: nextErrors
143
+ };
144
+ store.update(storeKey, {
145
+ data: nextData,
146
+ isLoading: isAnyKeyLoading(nextIsLoading),
147
+ status: void 0,
148
+ errors: void 0
149
+ });
150
+ }
151
+ })
152
+ );
153
+ if (completeOnFirstEmission) {
154
+ pipeline = pipeline.pipe(take2(1));
155
+ }
156
+ if (callbackAfterComplete) {
157
+ pipeline = pipeline.pipe(finalize2(callbackAfterComplete));
158
+ }
159
+ return pipeline;
160
+ };
161
+ }
162
+
163
+ // src/decorators/skip-if-cached.ts
164
+ import { finalize as finalize3, of, shareReplay, tap as tap3 } from "rxjs";
165
+ import { isKeyedResourceData } from "@flurryx/core";
166
+ import { CACHE_NO_TIMEOUT, DEFAULT_CACHE_TTL_MS } from "@flurryx/core";
167
+ var cacheState = /* @__PURE__ */ new WeakMap();
168
+ function getStoreKeyMap(store, key) {
169
+ let storeMap = cacheState.get(store);
170
+ if (!storeMap) {
171
+ storeMap = /* @__PURE__ */ new Map();
172
+ cacheState.set(store, storeMap);
173
+ }
174
+ let keyMap = storeMap.get(key);
175
+ if (!keyMap) {
176
+ keyMap = /* @__PURE__ */ new Map();
177
+ storeMap.set(key, keyMap);
178
+ }
179
+ return keyMap;
180
+ }
181
+ function getCacheEntry(store, key, cacheKey) {
182
+ return getStoreKeyMap(store, key).get(cacheKey);
183
+ }
184
+ function setCacheEntry(store, key, cacheKey, entry) {
185
+ getStoreKeyMap(store, key).set(cacheKey, entry);
186
+ }
187
+ function clearCacheEntry(store, key, cacheKey) {
188
+ getStoreKeyMap(store, key).delete(cacheKey);
189
+ }
190
+ function deriveResourceKey(args) {
191
+ const key = args[0];
192
+ if (typeof key === "string" || typeof key === "number") {
193
+ return key;
194
+ }
195
+ return void 0;
196
+ }
197
+ function isExpired(timestamp, timeoutMs, now) {
198
+ if (timeoutMs === CACHE_NO_TIMEOUT) {
199
+ return false;
200
+ }
201
+ if (timestamp === void 0) {
202
+ return false;
203
+ }
204
+ return now - timestamp >= timeoutMs;
205
+ }
206
+ function getStoreContext(instance, storeKey, getStore) {
207
+ const store = getStore(instance);
208
+ if (!store) {
209
+ return void 0;
210
+ }
211
+ const storeSignal = store.get(storeKey);
212
+ if (!storeSignal) {
213
+ return void 0;
214
+ }
215
+ const currentState = storeSignal();
216
+ if (currentState === null || currentState === void 0) {
217
+ return void 0;
218
+ }
219
+ return { store, storeSignal, currentState };
220
+ }
221
+ function getCacheContext(store, storeKey, args, argsString, currentState) {
222
+ const keyedData = isKeyedResourceData(currentState.data) ? currentState.data : void 0;
223
+ const resourceKey = keyedData ? deriveResourceKey(args) : void 0;
224
+ const isKeyedCall = keyedData !== void 0 && resourceKey !== void 0;
225
+ const keyedCacheKey = argsString;
226
+ const nonKeyedCacheKey = "__single__";
227
+ const runtimeCacheKey = isKeyedCall ? keyedCacheKey : nonKeyedCacheKey;
228
+ const keyedCacheEntry = getCacheEntry(store, storeKey, keyedCacheKey);
229
+ const nonKeyedCacheEntry = getCacheEntry(store, storeKey, nonKeyedCacheKey);
230
+ return {
231
+ isKeyedCall,
232
+ resourceKey,
233
+ keyedData,
234
+ runtimeCacheKey,
235
+ keyedCacheEntry,
236
+ nonKeyedCacheEntry
237
+ };
238
+ }
239
+ function handleCacheErrors(store, storeKey, context, currentState) {
240
+ if (!context.keyedData && currentState.status === "Error") {
241
+ clearCacheEntry(store, storeKey, "__single__");
242
+ }
243
+ if (context.keyedData && context.resourceKey !== void 0) {
244
+ const status = context.keyedData.status[context.resourceKey];
245
+ if (status === "Error") {
246
+ clearCacheEntry(store, storeKey, context.runtimeCacheKey);
247
+ }
248
+ }
249
+ }
250
+ function handleKeyedCache(store, storeKey, context, timeoutMs, now, returnObservable) {
251
+ const { keyedData, resourceKey, keyedCacheEntry, runtimeCacheKey } = context;
252
+ if (!keyedData || resourceKey === void 0) {
253
+ return { hit: false };
254
+ }
255
+ const typed = keyedData;
256
+ const status = typed.status[resourceKey];
257
+ const entity = typed.entities[resourceKey];
258
+ const loading = typed.isLoading[resourceKey] === true;
259
+ const expired = isExpired(keyedCacheEntry?.timestamp, timeoutMs, now);
260
+ if (expired) {
261
+ clearCacheEntry(store, storeKey, runtimeCacheKey);
262
+ }
263
+ if (!expired && status === "Success" && entity !== void 0) {
264
+ if (returnObservable) {
265
+ return { hit: true, value: of(entity) };
266
+ }
267
+ return { hit: true };
268
+ }
269
+ if (returnObservable) {
270
+ if (keyedCacheEntry?.inflight$) {
271
+ return { hit: true, value: keyedCacheEntry.inflight$ };
272
+ }
273
+ } else if (loading) {
274
+ return { hit: true };
275
+ }
276
+ return { hit: false };
277
+ }
278
+ function handleNonKeyedCache(store, storeKey, context, timeoutMs, now, returnObservable, currentState, argsString, storeSignal) {
279
+ const { nonKeyedCacheEntry, runtimeCacheKey } = context;
280
+ if (returnObservable && nonKeyedCacheEntry?.args === argsString && nonKeyedCacheEntry.inflight$) {
281
+ return { hit: true, value: nonKeyedCacheEntry.inflight$ };
282
+ }
283
+ const hasValidCacheState = currentState?.status === "Success" || currentState?.isLoading === true;
284
+ if (nonKeyedCacheEntry && isExpired(nonKeyedCacheEntry.timestamp, timeoutMs, now)) {
285
+ clearCacheEntry(store, storeKey, runtimeCacheKey);
286
+ } else if (nonKeyedCacheEntry?.args === argsString && hasValidCacheState) {
287
+ if (returnObservable) {
288
+ if (nonKeyedCacheEntry.inflight$) {
289
+ return { hit: true, value: nonKeyedCacheEntry.inflight$ };
290
+ }
291
+ return { hit: true, value: of(storeSignal().data) };
292
+ }
293
+ return { hit: true };
294
+ }
295
+ return { hit: false };
296
+ }
297
+ function createCachedObservable(result, store, storeKey, runtimeCacheKey, argsString) {
298
+ return result.pipe(
299
+ tap3({
300
+ next: () => {
301
+ setCacheEntry(store, storeKey, runtimeCacheKey, {
302
+ timestamp: Date.now(),
303
+ args: argsString
304
+ });
305
+ },
306
+ error: () => {
307
+ clearCacheEntry(store, storeKey, runtimeCacheKey);
308
+ }
309
+ }),
310
+ finalize3(() => {
311
+ const entry = getCacheEntry(store, storeKey, runtimeCacheKey);
312
+ if (entry?.inflight$) {
313
+ const { inflight$: _inflight$, ...rest } = entry;
314
+ setCacheEntry(store, storeKey, runtimeCacheKey, rest);
315
+ }
316
+ }),
317
+ shareReplay({ bufferSize: 1, refCount: true })
318
+ );
319
+ }
320
+ function SkipIfCached(storeKey, storeGetter, returnObservable = false, timeoutMs = DEFAULT_CACHE_TTL_MS) {
321
+ return function(_target, _propertyKey, descriptor) {
322
+ const originalMethod = descriptor.value;
323
+ descriptor.value = function(...args) {
324
+ const storeContext = getStoreContext(this, storeKey, storeGetter);
325
+ if (!storeContext) {
326
+ return originalMethod.apply(this, args);
327
+ }
328
+ const { store, storeSignal, currentState } = storeContext;
329
+ const argsString = JSON.stringify(args);
330
+ const now = Date.now();
331
+ const cacheContext = getCacheContext(
332
+ store,
333
+ storeKey,
334
+ args,
335
+ argsString,
336
+ currentState
337
+ );
338
+ handleCacheErrors(store, storeKey, cacheContext, currentState);
339
+ let cacheHit;
340
+ if (cacheContext.isKeyedCall) {
341
+ cacheHit = handleKeyedCache(
342
+ store,
343
+ storeKey,
344
+ cacheContext,
345
+ timeoutMs,
346
+ now,
347
+ returnObservable
348
+ );
349
+ } else {
350
+ cacheHit = handleNonKeyedCache(
351
+ store,
352
+ storeKey,
353
+ cacheContext,
354
+ timeoutMs,
355
+ now,
356
+ returnObservable,
357
+ currentState,
358
+ argsString,
359
+ storeSignal
360
+ );
361
+ }
362
+ if (cacheHit.hit) {
363
+ return cacheHit.value;
364
+ }
365
+ const result = originalMethod.apply(this, args);
366
+ if (!returnObservable) {
367
+ setCacheEntry(store, storeKey, cacheContext.runtimeCacheKey, {
368
+ timestamp: now,
369
+ args: argsString
370
+ });
371
+ return result;
372
+ }
373
+ const inflight$ = createCachedObservable(
374
+ result,
375
+ store,
376
+ storeKey,
377
+ cacheContext.runtimeCacheKey,
378
+ argsString
379
+ );
380
+ setCacheEntry(store, storeKey, cacheContext.runtimeCacheKey, {
381
+ timestamp: now,
382
+ args: argsString,
383
+ inflight$
384
+ });
385
+ return inflight$;
386
+ };
387
+ return descriptor;
388
+ };
389
+ }
390
+
391
+ // src/decorators/loading.ts
392
+ function Loading(storeKey, storeGetter) {
393
+ return function(_target, _propertyKey, descriptor) {
394
+ const originalMethod = descriptor.value;
395
+ descriptor.value = function(...args) {
396
+ const store = storeGetter(this);
397
+ const resourceKey = args[0];
398
+ const canKey = typeof resourceKey === "string" || typeof resourceKey === "number";
399
+ const hasKeyed = typeof store === "object" && store !== null && "startKeyedLoading" in store && typeof store.startKeyedLoading === "function";
400
+ if (canKey && hasKeyed) {
401
+ store.startKeyedLoading(storeKey, resourceKey);
402
+ } else {
403
+ store?.startLoading(storeKey);
404
+ }
405
+ return originalMethod.apply(this, args);
406
+ };
407
+ return descriptor;
408
+ };
409
+ }
410
+ export {
411
+ Loading,
412
+ SkipIfCached,
413
+ defaultErrorNormalizer,
414
+ syncToKeyedStore,
415
+ syncToStore
416
+ };
417
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/operators/sync-to-store.ts","../src/error/error-normalizer.ts","../src/operators/sync-to-keyed-store.ts","../src/decorators/skip-if-cached.ts","../src/decorators/loading.ts"],"sourcesContent":["import { finalize, Observable, take, tap } from \"rxjs\";\nimport { BaseStore } from \"@flurryx/store\";\nimport type { ResourceState } from \"@flurryx/core\";\nimport {\n defaultErrorNormalizer,\n type ErrorNormalizer,\n} from \"../error/error-normalizer\";\n\nexport interface SyncToStoreOptions {\n completeOnFirstEmission?: boolean;\n callbackAfterComplete?: () => void;\n errorNormalizer?: ErrorNormalizer;\n}\n\nexport function syncToStore<\n TEnum extends Record<string, string | number>,\n TData extends { [K in keyof TEnum]: ResourceState<unknown> }\n>(\n store: BaseStore<TEnum, TData>,\n key: keyof TEnum,\n options: SyncToStoreOptions = { completeOnFirstEmission: true }\n) {\n const normalizeError = options.errorNormalizer ?? defaultErrorNormalizer;\n\n return <R>(source: Observable<R>) => {\n let pipeline = source.pipe(\n tap({\n next: (data: R) => {\n store.update(key, {\n data,\n isLoading: false,\n status: \"Success\",\n errors: undefined,\n } as Partial<TData[typeof key]>);\n },\n error: (error: unknown) => {\n store.update(key, {\n data: undefined,\n isLoading: false,\n status: \"Error\",\n errors: normalizeError(error),\n } as Partial<TData[typeof key]>);\n },\n })\n );\n\n if (options.completeOnFirstEmission) {\n pipeline = pipeline.pipe(take(1));\n }\n\n if (options.callbackAfterComplete) {\n pipeline = pipeline.pipe(finalize(options.callbackAfterComplete));\n }\n\n return pipeline;\n };\n}\n","import type { ResourceErrors } from '@flurryx/core';\n\nexport type ErrorNormalizer = (error: unknown) => ResourceErrors;\n\nexport function defaultErrorNormalizer(error: unknown): ResourceErrors {\n if (\n typeof error === 'object' &&\n error !== null &&\n 'error' in error &&\n typeof (error as Record<string, unknown>).error === 'object'\n ) {\n const inner = (error as { error: Record<string, unknown> }).error;\n if (inner && Array.isArray(inner.errors)) {\n return inner.errors as ResourceErrors;\n }\n }\n\n if (\n typeof error === 'object' &&\n error !== null &&\n 'status' in error &&\n 'message' in error\n ) {\n const typed = error as { status: number; message: string };\n return [\n {\n code: String(typed.status),\n message: typed.message,\n },\n ];\n }\n\n if (error instanceof Error) {\n return [\n {\n code: 'UNKNOWN',\n message: error.message,\n },\n ];\n }\n\n return [\n {\n code: 'UNKNOWN',\n message: String(error),\n },\n ];\n}\n","import { finalize, Observable, take, tap } from \"rxjs\";\nimport { BaseStore } from \"@flurryx/store\";\nimport {\n createKeyedResourceData,\n isAnyKeyLoading,\n type KeyedResourceData,\n type KeyedResourceKey,\n type ResourceErrors,\n type ResourceState,\n type ResourceStatus,\n} from \"@flurryx/core\";\nimport {\n defaultErrorNormalizer,\n type ErrorNormalizer,\n} from \"../error/error-normalizer\";\nimport type { SyncToStoreOptions } from \"./sync-to-store\";\n\nexport interface SyncToKeyedStoreOptions<R, TValue> extends SyncToStoreOptions {\n mapResponse?: (response: R) => TValue;\n errorNormalizer?: ErrorNormalizer;\n}\n\nfunction withoutKey<TKey extends KeyedResourceKey, TValue>(\n record: Partial<Record<TKey, TValue>>,\n key: TKey\n): Partial<Record<TKey, TValue>> {\n const next: Partial<Record<TKey, TValue>> = {\n ...record,\n };\n delete next[key];\n return next;\n}\n\nexport function syncToKeyedStore<\n TEnum extends Record<string, string | number>,\n TStoreKey extends keyof TEnum,\n TKey extends KeyedResourceKey,\n TValue,\n R = TValue,\n TState extends ResourceState<KeyedResourceData<TKey, TValue>> = ResourceState<\n KeyedResourceData<TKey, TValue>\n >,\n TData extends {\n [K in keyof TEnum]: ResourceState<unknown>;\n } & { [K in TStoreKey]: TState } = {\n [K in keyof TEnum]: ResourceState<unknown>;\n } & { [K in TStoreKey]: TState }\n>(\n store: BaseStore<TEnum, TData>,\n storeKey: TStoreKey,\n resourceKey: TKey,\n options: SyncToKeyedStoreOptions<R, TValue> = {\n completeOnFirstEmission: true,\n }\n) {\n const { completeOnFirstEmission, callbackAfterComplete, mapResponse } =\n options;\n const normalizeError = options.errorNormalizer ?? defaultErrorNormalizer;\n\n return (source: Observable<R>) => {\n let pipeline = source.pipe(\n tap({\n next: (response: R) => {\n const value = mapResponse\n ? mapResponse(response)\n : (response as unknown as TValue);\n\n const storeSignal = store.get(storeKey);\n const state = storeSignal();\n const data = state.data ?? createKeyedResourceData<TKey, TValue>();\n\n const nextIsLoading = {\n ...data.isLoading,\n [resourceKey]: false,\n } as Partial<Record<TKey, boolean>>;\n\n const nextStatus: Partial<Record<TKey, ResourceStatus>> = {\n ...data.status,\n [resourceKey]: \"Success\",\n };\n\n const nextData: KeyedResourceData<TKey, TValue> = {\n ...data,\n entities: {\n ...data.entities,\n [resourceKey]: value,\n } as Partial<Record<TKey, TValue>>,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: withoutKey(data.errors, resourceKey),\n };\n\n store.update(storeKey, {\n data: nextData,\n isLoading: isAnyKeyLoading(nextIsLoading),\n status: undefined,\n errors: undefined,\n } as Partial<TData[typeof storeKey]>);\n },\n error: (error: unknown) => {\n const storeSignal = store.get(storeKey);\n const state = storeSignal();\n const data = state.data ?? createKeyedResourceData<TKey, TValue>();\n\n const nextIsLoading = {\n ...data.isLoading,\n [resourceKey]: false,\n } as Partial<Record<TKey, boolean>>;\n\n const nextStatus: Partial<Record<TKey, ResourceStatus>> = {\n ...data.status,\n [resourceKey]: \"Error\",\n };\n\n const nextErrors: Partial<Record<TKey, ResourceErrors>> = {\n ...data.errors,\n [resourceKey]: normalizeError(error),\n };\n\n const nextData: KeyedResourceData<TKey, TValue> = {\n ...data,\n isLoading: nextIsLoading,\n status: nextStatus,\n errors: nextErrors,\n };\n\n store.update(storeKey, {\n data: nextData,\n isLoading: isAnyKeyLoading(nextIsLoading),\n status: undefined,\n errors: undefined,\n } as Partial<TData[typeof storeKey]>);\n },\n })\n );\n\n if (completeOnFirstEmission) {\n pipeline = pipeline.pipe(take(1));\n }\n\n if (callbackAfterComplete) {\n pipeline = pipeline.pipe(finalize(callbackAfterComplete));\n }\n\n return pipeline;\n };\n}\n","import { WritableSignal } from '@angular/core';\nimport { finalize, Observable, of, shareReplay, tap } from 'rxjs';\nimport type { ResourceState, StoreEnum, KeyedResourceKey } from '@flurryx/core';\nimport { isKeyedResourceData } from '@flurryx/core';\nimport { CACHE_NO_TIMEOUT, DEFAULT_CACHE_TTL_MS } from '@flurryx/core';\n\ntype StoreWithSignal<TKey extends StoreEnum> = {\n get: (key: TKey) => WritableSignal<ResourceState<unknown>> | undefined;\n};\n\ninterface CacheEntry {\n timestamp: number;\n args: string;\n inflight$?: Observable<unknown>;\n}\n\nconst cacheState = new WeakMap<\n object,\n Map<StoreEnum, Map<string, CacheEntry>>\n>();\n\nfunction getStoreKeyMap(\n store: object,\n key: StoreEnum\n): Map<string, CacheEntry> {\n let storeMap = cacheState.get(store);\n if (!storeMap) {\n storeMap = new Map();\n cacheState.set(store, storeMap);\n }\n\n let keyMap = storeMap.get(key);\n if (!keyMap) {\n keyMap = new Map();\n storeMap.set(key, keyMap);\n }\n\n return keyMap;\n}\n\nfunction getCacheEntry(\n store: object,\n key: StoreEnum,\n cacheKey: string\n): CacheEntry | undefined {\n return getStoreKeyMap(store, key).get(cacheKey);\n}\n\nfunction setCacheEntry(\n store: object,\n key: StoreEnum,\n cacheKey: string,\n entry: CacheEntry\n): void {\n getStoreKeyMap(store, key).set(cacheKey, entry);\n}\n\nfunction clearCacheEntry(\n store: object,\n key: StoreEnum,\n cacheKey: string\n): void {\n getStoreKeyMap(store, key).delete(cacheKey);\n}\n\nfunction deriveResourceKey(args: unknown[]): KeyedResourceKey | undefined {\n const key = args[0];\n if (typeof key === 'string' || typeof key === 'number') {\n return key;\n }\n return undefined;\n}\n\nfunction isExpired(\n timestamp: number | undefined,\n timeoutMs: number,\n now: number\n): boolean {\n if (timeoutMs === CACHE_NO_TIMEOUT) {\n return false;\n }\n if (timestamp === undefined) {\n return false;\n }\n return now - timestamp >= timeoutMs;\n}\n\ninterface StoreContext {\n store: object;\n storeSignal: WritableSignal<ResourceState<unknown>>;\n currentState: ResourceState<unknown>;\n}\n\nfunction getStoreContext<TTarget, TKey extends StoreEnum>(\n instance: TTarget,\n storeKey: TKey,\n getStore: (i: TTarget) => StoreWithSignal<TKey> | undefined\n): StoreContext | undefined {\n const store = getStore(instance);\n if (!store) {\n return undefined;\n }\n\n const storeSignal = store.get(storeKey);\n if (!storeSignal) {\n return undefined;\n }\n\n const currentState = storeSignal();\n if (currentState === null || currentState === undefined) {\n return undefined;\n }\n\n return { store, storeSignal, currentState };\n}\n\ninterface CacheContext {\n isKeyedCall: boolean;\n resourceKey: KeyedResourceKey | undefined;\n keyedData: ReturnType<typeof isKeyedResourceData> extends true\n ? { entities: object; isLoading: object; status: object; errors: object }\n : undefined;\n runtimeCacheKey: string;\n keyedCacheEntry: CacheEntry | undefined;\n nonKeyedCacheEntry: CacheEntry | undefined;\n}\n\nfunction getCacheContext(\n store: object,\n storeKey: StoreEnum,\n args: unknown[],\n argsString: string,\n currentState: ResourceState<unknown>\n): CacheContext {\n const keyedData = isKeyedResourceData(currentState.data)\n ? currentState.data\n : undefined;\n const resourceKey = keyedData ? deriveResourceKey(args) : undefined;\n const isKeyedCall = keyedData !== undefined && resourceKey !== undefined;\n\n const keyedCacheKey = argsString;\n const nonKeyedCacheKey = '__single__';\n const runtimeCacheKey = isKeyedCall ? keyedCacheKey : nonKeyedCacheKey;\n\n const keyedCacheEntry = getCacheEntry(store, storeKey, keyedCacheKey);\n const nonKeyedCacheEntry = getCacheEntry(store, storeKey, nonKeyedCacheKey);\n\n return {\n isKeyedCall,\n resourceKey,\n keyedData: keyedData as CacheContext['keyedData'],\n runtimeCacheKey,\n keyedCacheEntry,\n nonKeyedCacheEntry,\n };\n}\n\nfunction handleCacheErrors(\n store: object,\n storeKey: StoreEnum,\n context: CacheContext,\n currentState: ResourceState<unknown>\n): void {\n if (!context.keyedData && currentState.status === 'Error') {\n clearCacheEntry(store, storeKey, '__single__');\n }\n if (context.keyedData && context.resourceKey !== undefined) {\n const status = (\n context.keyedData as {\n status: Partial<Record<KeyedResourceKey, string>>;\n }\n ).status[context.resourceKey];\n if (status === 'Error') {\n clearCacheEntry(store, storeKey, context.runtimeCacheKey);\n }\n }\n}\n\ninterface CacheHitResult {\n hit: boolean;\n value?: Observable<unknown>;\n}\n\nfunction handleKeyedCache(\n store: object,\n storeKey: StoreEnum,\n context: CacheContext,\n timeoutMs: number,\n now: number,\n returnObservable: boolean\n): CacheHitResult {\n const { keyedData, resourceKey, keyedCacheEntry, runtimeCacheKey } = context;\n\n if (!keyedData || resourceKey === undefined) {\n return { hit: false };\n }\n\n const typed = keyedData as {\n status: Partial<Record<KeyedResourceKey, string>>;\n entities: Partial<Record<KeyedResourceKey, unknown>>;\n isLoading: Partial<Record<KeyedResourceKey, boolean>>;\n };\n\n const status = typed.status[resourceKey];\n const entity = typed.entities[resourceKey];\n const loading = typed.isLoading[resourceKey] === true;\n\n const expired = isExpired(keyedCacheEntry?.timestamp, timeoutMs, now);\n if (expired) {\n clearCacheEntry(store, storeKey, runtimeCacheKey);\n }\n\n if (!expired && status === 'Success' && entity !== undefined) {\n if (returnObservable) {\n return { hit: true, value: of(entity) };\n }\n return { hit: true };\n }\n\n if (returnObservable) {\n if (keyedCacheEntry?.inflight$) {\n return { hit: true, value: keyedCacheEntry.inflight$ };\n }\n } else if (loading) {\n return { hit: true };\n }\n\n return { hit: false };\n}\n\nfunction handleNonKeyedCache(\n store: object,\n storeKey: StoreEnum,\n context: CacheContext,\n timeoutMs: number,\n now: number,\n returnObservable: boolean,\n currentState: ResourceState<unknown>,\n argsString: string,\n storeSignal: WritableSignal<ResourceState<unknown>>\n): CacheHitResult {\n const { nonKeyedCacheEntry, runtimeCacheKey } = context;\n\n if (\n returnObservable &&\n nonKeyedCacheEntry?.args === argsString &&\n nonKeyedCacheEntry.inflight$\n ) {\n return { hit: true, value: nonKeyedCacheEntry.inflight$ };\n }\n\n const hasValidCacheState =\n currentState?.status === 'Success' || currentState?.isLoading === true;\n\n if (\n nonKeyedCacheEntry &&\n isExpired(nonKeyedCacheEntry.timestamp, timeoutMs, now)\n ) {\n clearCacheEntry(store, storeKey, runtimeCacheKey);\n } else if (nonKeyedCacheEntry?.args === argsString && hasValidCacheState) {\n if (returnObservable) {\n if (nonKeyedCacheEntry.inflight$) {\n return { hit: true, value: nonKeyedCacheEntry.inflight$ };\n }\n return { hit: true, value: of(storeSignal().data) };\n }\n return { hit: true };\n }\n\n return { hit: false };\n}\n\nfunction createCachedObservable(\n result: Observable<unknown>,\n store: object,\n storeKey: StoreEnum,\n runtimeCacheKey: string,\n argsString: string\n): Observable<unknown> {\n return result.pipe(\n tap({\n next: () => {\n setCacheEntry(store, storeKey, runtimeCacheKey, {\n timestamp: Date.now(),\n args: argsString,\n });\n },\n error: () => {\n clearCacheEntry(store, storeKey, runtimeCacheKey);\n },\n }),\n finalize(() => {\n const entry = getCacheEntry(store, storeKey, runtimeCacheKey);\n if (entry?.inflight$) {\n const { inflight$: _inflight$, ...rest } = entry;\n setCacheEntry(store, storeKey, runtimeCacheKey, rest);\n }\n }),\n shareReplay({ bufferSize: 1, refCount: true })\n );\n}\n\nexport function SkipIfCached<TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: {\n store: StoreWithSignal<TKey>;\n }) => StoreWithSignal<TKey> | undefined,\n returnObservable?: boolean,\n timeoutMs?: number\n): MethodDecorator;\nexport function SkipIfCached<TTarget, TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: TTarget) => StoreWithSignal<TKey> | undefined,\n returnObservable?: boolean,\n timeoutMs?: number\n): MethodDecorator;\nexport function SkipIfCached<TTarget, TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: TTarget) => StoreWithSignal<TKey> | undefined,\n returnObservable = false,\n timeoutMs = DEFAULT_CACHE_TTL_MS\n): MethodDecorator {\n return function (\n _target: unknown,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ) {\n const originalMethod = descriptor.value as (\n this: TTarget,\n ...args: unknown[]\n ) => unknown;\n\n descriptor.value = function (this: TTarget, ...args: unknown[]) {\n const storeContext = getStoreContext(this, storeKey, storeGetter);\n if (!storeContext) {\n return originalMethod.apply(this, args);\n }\n const { store, storeSignal, currentState } = storeContext;\n\n const argsString = JSON.stringify(args);\n const now = Date.now();\n const cacheContext = getCacheContext(\n store,\n storeKey,\n args,\n argsString,\n currentState\n );\n\n handleCacheErrors(store, storeKey, cacheContext, currentState);\n\n let cacheHit: CacheHitResult;\n\n if (cacheContext.isKeyedCall) {\n cacheHit = handleKeyedCache(\n store,\n storeKey,\n cacheContext,\n timeoutMs,\n now,\n returnObservable\n );\n } else {\n cacheHit = handleNonKeyedCache(\n store,\n storeKey,\n cacheContext,\n timeoutMs,\n now,\n returnObservable,\n currentState,\n argsString,\n storeSignal\n );\n }\n\n if (cacheHit.hit) {\n return cacheHit.value;\n }\n\n const result = originalMethod.apply(this, args);\n\n if (!returnObservable) {\n setCacheEntry(store, storeKey, cacheContext.runtimeCacheKey, {\n timestamp: now,\n args: argsString,\n });\n return result;\n }\n\n const inflight$ = createCachedObservable(\n result as Observable<unknown>,\n store,\n storeKey,\n cacheContext.runtimeCacheKey,\n argsString\n );\n\n setCacheEntry(store, storeKey, cacheContext.runtimeCacheKey, {\n timestamp: now,\n args: argsString,\n inflight$,\n });\n\n return inflight$;\n };\n\n return descriptor;\n };\n}\n","import type { StoreEnum, KeyedResourceKey } from '@flurryx/core';\n\ntype StoreWithLoading<TKey extends StoreEnum> = {\n startLoading: (key: TKey) => void;\n};\n\nexport function Loading<TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: {\n store: StoreWithLoading<TKey>;\n }) => StoreWithLoading<TKey>\n): MethodDecorator;\nexport function Loading<TTarget, TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: TTarget) => StoreWithLoading<TKey>\n): MethodDecorator;\nexport function Loading<TTarget, TKey extends StoreEnum>(\n storeKey: TKey,\n storeGetter: (instance: TTarget) => StoreWithLoading<TKey>\n) {\n return function (\n _target: unknown,\n _propertyKey: string | symbol,\n descriptor: PropertyDescriptor\n ) {\n const originalMethod = descriptor.value as (\n this: unknown,\n ...args: unknown[]\n ) => unknown;\n\n descriptor.value = function (this: TTarget, ...args: unknown[]) {\n const store = storeGetter(this);\n\n const resourceKey = args[0];\n const canKey =\n typeof resourceKey === 'string' || typeof resourceKey === 'number';\n const hasKeyed =\n typeof store === 'object' &&\n store !== null &&\n 'startKeyedLoading' in store &&\n typeof (store as { startKeyedLoading?: unknown }).startKeyedLoading ===\n 'function';\n\n if (canKey && hasKeyed) {\n (\n store as unknown as {\n startKeyedLoading: (\n key: TKey,\n resourceKey: KeyedResourceKey\n ) => void;\n }\n ).startKeyedLoading(storeKey, resourceKey as KeyedResourceKey);\n } else {\n store?.startLoading(storeKey);\n }\n return originalMethod.apply(this, args);\n };\n\n return descriptor;\n };\n}\n"],"mappings":"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","names":["finalize","take","tap","tap","take","finalize","finalize","tap"]}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@flurryx/rx",
3
+ "version": "0.0.1",
4
+ "description": "RxJS operators and decorators for flurryx stores",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "require": {
17
+ "types": "./dist/index.d.cts",
18
+ "default": "./dist/index.cjs"
19
+ }
20
+ },
21
+ "./http": {
22
+ "import": {
23
+ "types": "./dist/http.d.ts",
24
+ "default": "./dist/http.js"
25
+ },
26
+ "require": {
27
+ "types": "./dist/http.d.cts",
28
+ "default": "./dist/http.cjs"
29
+ }
30
+ }
31
+ },
32
+ "files": ["dist"],
33
+ "scripts": {
34
+ "build": "tsup",
35
+ "typecheck": "tsc --noEmit"
36
+ },
37
+ "sideEffects": false,
38
+ "dependencies": {
39
+ "@flurryx/core": "0.0.1",
40
+ "@flurryx/store": "0.0.1"
41
+ },
42
+ "peerDependencies": {
43
+ "@angular/core": ">=17.0.0",
44
+ "rxjs": ">=7.0.0"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "@angular/common": {
48
+ "optional": true
49
+ }
50
+ }
51
+ }