@ngrx-traits/core 15.0.0 → 16.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.
Files changed (28) hide show
  1. package/{esm2020 → esm2022}/cache/cache.module.mjs +5 -5
  2. package/{esm2020 → esm2022}/local-store/traits-local-store.mjs +4 -4
  3. package/{esm2020 → esm2022}/trait-effect.mjs +4 -4
  4. package/{fesm2020 → fesm2022}/ngrx-traits-core.mjs +10 -10
  5. package/{fesm2020 → fesm2022}/ngrx-traits-core.mjs.map +1 -1
  6. package/package.json +8 -16
  7. package/fesm2015/ngrx-traits-core-testing.mjs +0 -46
  8. package/fesm2015/ngrx-traits-core-testing.mjs.map +0 -1
  9. package/fesm2015/ngrx-traits-core.mjs +0 -945
  10. package/fesm2015/ngrx-traits-core.mjs.map +0 -1
  11. /package/{esm2020 → esm2022}/cache/cache.actions.mjs +0 -0
  12. /package/{esm2020 → esm2022}/cache/cache.models.mjs +0 -0
  13. /package/{esm2020 → esm2022}/cache/cache.reducer.mjs +0 -0
  14. /package/{esm2020 → esm2022}/cache/cache.selectors.mjs +0 -0
  15. /package/{esm2020 → esm2022}/cache/cache.service.mjs +0 -0
  16. /package/{esm2020 → esm2022}/cache/index.mjs +0 -0
  17. /package/{esm2020 → esm2022}/create-entity-feature.mjs +0 -0
  18. /package/{esm2020 → esm2022}/index.mjs +0 -0
  19. /package/{esm2020 → esm2022}/local-store/disable-local-trait-effects.token.mjs +0 -0
  20. /package/{esm2020 → esm2022}/local-store/index.mjs +0 -0
  21. /package/{esm2020 → esm2022}/model.mjs +0 -0
  22. /package/{esm2020 → esm2022}/ngrx-traits-core.mjs +0 -0
  23. /package/{esm2020 → esm2022}/testing/index.mjs +0 -0
  24. /package/{esm2020 → esm2022}/testing/ngrx-traits-core-testing.mjs +0 -0
  25. /package/{esm2020 → esm2022}/testing/provide-mock-local-traits.mjs +0 -0
  26. /package/{esm2020 → esm2022}/util.mjs +0 -0
  27. /package/{fesm2020 → fesm2022}/ngrx-traits-core-testing.mjs +0 -0
  28. /package/{fesm2020 → fesm2022}/ngrx-traits-core-testing.mjs.map +0 -0
@@ -1,945 +0,0 @@
1
- import * as i1 from '@ngrx/store';
2
- import { createFeatureSelector, createReducer, createSelector, combineReducers, Store, ReducerManager, createAction, props, on, StoreModule } from '@ngrx/store';
3
- import * as i0 from '@angular/core';
4
- import { inject, Injectable, InjectionToken, Injector, NgModule } from '@angular/core';
5
- import { Actions, ofType, EffectSources } from '@ngrx/effects';
6
- import { takeUntil, first, concatMap, tap } from 'rxjs/operators';
7
- import { of } from 'rxjs';
8
-
9
- function insertIf(condition, getElement) {
10
- return condition ? [getElement()] : [];
11
- }
12
- function toMap(a) {
13
- return a.reduce((acum, value) => {
14
- acum[value] = true;
15
- return acum;
16
- }, {});
17
- }
18
- function capitalize(name) {
19
- return name.charAt(0).toUpperCase() + name.slice(1);
20
- }
21
- function camelCaseToSentence(text) {
22
- const result = text.replace(/([A-Z])/g, ' $1');
23
- return result.charAt(0).toUpperCase() + result.slice(1);
24
- }
25
- /**
26
- * Set propertyReducer in sourceReducer in a property of the source state,
27
- * @param sourceReducer
28
- * @param property
29
- * @param propertyReducer
30
- *
31
- * @example
32
- *
33
- * const newReducer = setPropertyReducer(productsReducer, 'selectedProduct', selectedProductReducer)
34
- */
35
- function setPropertyReducer(sourceReducer, property, propertyReducer) {
36
- return function reducer(state, action) {
37
- const sourceState = sourceReducer(state, action);
38
- return Object.assign(Object.assign({}, sourceState), { [property]: propertyReducer(sourceState[property], action) });
39
- };
40
- }
41
- /**
42
- * Set propertyReducers in sourceReducer each in a property of the source state,
43
- * @param sourceReducer
44
- * @param property
45
- * @param propertyReducer
46
- *
47
- * @example
48
- *
49
- * const newReducer = setPropertyReducer(productsReducer,
50
- * {
51
- * selectedProduct: selectedProductReducer
52
- * favoriteProduct: favoriteProductReducer
53
- * })
54
- */
55
- function setPropertiesReducer(sourceReducer, propertiesReducers) {
56
- return function reducer(state, action) {
57
- const newState = Object.assign({}, sourceReducer(state, action));
58
- for (const property in propertiesReducers) {
59
- newState[property] = propertiesReducers[property](newState[property], action);
60
- }
61
- return newState;
62
- };
63
- }
64
- /**
65
- * joins two reducers so the work in the same state
66
- * @param firstReducer
67
- * @param secondReducer
68
- */
69
- function joinReducers(firstReducer, secondReducer) {
70
- return function reducer(state, action) {
71
- const sourceState = firstReducer(state, action);
72
- return secondReducer(sourceState, action);
73
- };
74
- }
75
-
76
- /**
77
- * Creates a function that when execute will combine all the traits, and return a EntityFeatureFactory
78
- * which combines all the traits actions, selectors , reducers and effects,
79
- * the names param will replace any action and selector with the word Entity or Entities,
80
- * with the corresponding entityName and entitiesName param (entityName+'s' if entitiesName is omitted).
81
- * @param namesConfig - Optional Names for entities
82
- * @param namesConfig.entityName - singular name for entity
83
- * @param [namesConfig.entitiesName] - plural name for entities, defaults to entityName + 's'
84
- * @param traits set of traits to be combined
85
- *
86
- * @example
87
- *
88
- * const featureFactory = createEntityFeatureFactory(
89
- * { entityName: 'product' },
90
- * addLoadEntitiesTrait<Product>(),
91
- * addSelectEntityTrait<Product>(),
92
- * addAsyncActionTrait({
93
- * name: 'checkout',
94
- * actionSuccessProps: props<{ orderId: string }>(),
95
- * })
96
- * );
97
- *
98
- * export const productsFeature = featureFactory({
99
- * actionsGroupKey: '[Products]',
100
- * featureSelector: 'products',
101
- * });
102
- */
103
- function createEntityFeatureFactory(namesOrFactory, ...traits) {
104
- return ((config) => {
105
- const { entityName, entitiesName } = 'entityName' in namesOrFactory
106
- ? namesOrFactory
107
- : { entityName: 'Entity', entitiesName: 'Entities' };
108
- const singular = capitalize(entityName);
109
- const plural = entitiesName
110
- ? capitalize(entitiesName)
111
- : capitalize(entityName + 's');
112
- const sortedTraits = sortTraits('entityName' in namesOrFactory ? [...traits] : [namesOrFactory, ...traits]);
113
- const allConfigs = buildAllConfigs(sortedTraits);
114
- const allActions = buildAllActions(sortedTraits, config.actionsGroupKey, singular, plural, allConfigs);
115
- const allSelectors = buildAllSelectors(sortedTraits, allConfigs);
116
- const allMutators = buildAllMutators(sortedTraits, allSelectors, allConfigs);
117
- const initialState = buildInitialState(sortedTraits, allConfigs);
118
- const reducer = buildReducer(sortedTraits, initialState, allActions, allSelectors, allMutators, allConfigs);
119
- const featureSelector = typeof config.featureSelector === 'string'
120
- ? createFeatureSelector(config.featureSelector)
121
- : config.featureSelector;
122
- const allFeatureSelectors = allSelectors && getSelectorsForFeature(featureSelector, allSelectors);
123
- const allEffects = buildAllEffects(sortedTraits, allActions, allFeatureSelectors, allConfigs);
124
- return {
125
- actions: entityName
126
- ? renameProps(allActions, singular, plural)
127
- : allActions,
128
- selectors: entityName
129
- ? renameProps(allFeatureSelectors, singular, plural)
130
- : allSelectors,
131
- initialState,
132
- reducer: reducer !== null && reducer !== void 0 ? reducer : createReducer(initialState),
133
- effects: allEffects,
134
- };
135
- });
136
- }
137
- function renameProps(target, entityName, entitiesName) {
138
- const result = {};
139
- for (const [key, value] of Object.entries(target)) {
140
- const newKey = key
141
- .replace('Entities', entitiesName)
142
- .replace('Entity', entityName);
143
- result[newKey] = value;
144
- }
145
- return result;
146
- }
147
- function sortTraits(traits) {
148
- var _a;
149
- const sortedTraits = [];
150
- for (let i = 0; i < traits.length; i++) {
151
- const trait = traits[i];
152
- if (!((_a = trait.depends) === null || _a === void 0 ? void 0 : _a.length)) {
153
- sortedTraits.push(trait);
154
- continue;
155
- }
156
- if (trait.depends.length > 1)
157
- for (const d of trait.depends) {
158
- const isTraitPresent = traits.some((tr) => tr.key === d);
159
- if (isTraitPresent) {
160
- trait.depends = [d];
161
- break;
162
- }
163
- }
164
- if (trait.depends.length > 1)
165
- throw Error('could not find dependencies ' + trait.depends.join(' '));
166
- const isDependencyAlreadyAdded = sortedTraits.some((tr) => { var _a; return tr.key === ((_a = trait === null || trait === void 0 ? void 0 : trait.depends) === null || _a === void 0 ? void 0 : _a[0]); });
167
- if (isDependencyAlreadyAdded)
168
- sortedTraits.push(trait);
169
- else {
170
- // move trait to the end
171
- delete traits[i];
172
- traits.push(trait);
173
- }
174
- }
175
- return sortedTraits;
176
- }
177
- function buildAllConfigs(sortedTraits) {
178
- return sortedTraits.reduce((acc, factory) => {
179
- acc[factory.key] = factory.config;
180
- return acc;
181
- }, {});
182
- }
183
- function buildAllActions(sortedTraits, actionsGroupKey, entityName, entitiesName, allConfigs) {
184
- return sortedTraits.reduce((previousResult, factory) => {
185
- var _a, _b;
186
- let result = (_b = (_a = factory === null || factory === void 0 ? void 0 : factory.actions) === null || _a === void 0 ? void 0 : _a.call(factory, {
187
- actionsGroupKey: actionsGroupKey,
188
- entityName,
189
- entitiesName,
190
- allConfigs,
191
- })) !== null && _b !== void 0 ? _b : {};
192
- result = previousResult ? Object.assign(Object.assign({}, previousResult), result) : result;
193
- return result;
194
- }, {});
195
- }
196
- function buildAllSelectors(sortedTraits, allConfigs) {
197
- return sortedTraits.reduce((previousResult, factory) => {
198
- var _a, _b;
199
- let result = (_b = (_a = factory === null || factory === void 0 ? void 0 : factory.selectors) === null || _a === void 0 ? void 0 : _a.call(factory, {
200
- previousSelectors: previousResult,
201
- allConfigs,
202
- })) !== null && _b !== void 0 ? _b : {};
203
- result = previousResult ? Object.assign(Object.assign({}, previousResult), result) : result;
204
- return result;
205
- }, {});
206
- }
207
- function buildAllMutators(sortedTraits, allSelectors, allConfigs) {
208
- return (sortedTraits.reduce((previousResult, factory) => {
209
- var _a, _b;
210
- let result = (_b = (_a = factory === null || factory === void 0 ? void 0 : factory.mutators) === null || _a === void 0 ? void 0 : _a.call(factory, {
211
- allSelectors: allSelectors,
212
- previousMutators: previousResult,
213
- allConfigs,
214
- })) !== null && _b !== void 0 ? _b : {};
215
- result = previousResult ? Object.assign(Object.assign({}, previousResult), result) : result;
216
- return result;
217
- }, {}) || {});
218
- }
219
- function buildInitialState(sortedTraits, allConfigs) {
220
- return sortedTraits.reduce((previousResult, factory) => {
221
- var _a, _b, _c;
222
- const result = (_c = (_b = (_a = factory === null || factory === void 0 ? void 0 : factory.initialState) === null || _a === void 0 ? void 0 : _a.call(factory, {
223
- previousInitialState: previousResult,
224
- allConfigs,
225
- })) !== null && _b !== void 0 ? _b : previousResult) !== null && _c !== void 0 ? _c : {};
226
- return result;
227
- }, {});
228
- }
229
- function buildReducer(sortedTraits, initialState, allActions, allSelectors, allMutators, allConfigs) {
230
- return sortedTraits.reduce((previousResult, factory) => {
231
- var _a;
232
- const result = (_a = factory === null || factory === void 0 ? void 0 : factory.reducer) === null || _a === void 0 ? void 0 : _a.call(factory, {
233
- initialState,
234
- allActions,
235
- allSelectors,
236
- allMutators,
237
- allConfigs,
238
- });
239
- return result && previousResult
240
- ? (state = initialState, action) => {
241
- const aState = previousResult(state, action);
242
- return result(aState, action);
243
- }
244
- : result !== null && result !== void 0 ? result : previousResult;
245
- }, undefined);
246
- }
247
- function buildAllEffects(sortedTraits, allActions, allFeatureSelectors, allConfigs) {
248
- return sortedTraits.reduce((previousResult, factory) => {
249
- var _a, _b;
250
- let result = (_b = (_a = factory === null || factory === void 0 ? void 0 : factory.effects) === null || _a === void 0 ? void 0 : _a.call(factory, {
251
- allActions,
252
- allSelectors: allFeatureSelectors,
253
- allConfigs,
254
- })) !== null && _b !== void 0 ? _b : [];
255
- result = previousResult ? [...previousResult, ...result] : result;
256
- return result;
257
- }, []);
258
- }
259
- function getSelectorsForFeature(featureSelect, selectors) {
260
- const ss = {};
261
- for (const prop in selectors) {
262
- ss[prop] = createSelector(featureSelect, selectors[prop]);
263
- }
264
- return ss;
265
- }
266
- /**
267
- * Combine a map entityFeatureFactories into one,
268
- * grouping the actions and selectors by the key of the respective entityFeatureFactory
269
- * @param traitFactoriesMap
270
- *
271
- * @example
272
- *
273
- * const clientsFeatureFactory = createEntityFeatureFactory(
274
- * { entityName: 'client', entitiesName: 'clients' },
275
- * addLoadEntitiesTrait<Client>(),
276
- * addCrudEntitiesTrait<Client>()
277
- * );
278
- *
279
- * const productOrderFeatureFactory = createEntityFeatureFactory(
280
- * { entityName: 'productOrder' },
281
- * addLoadEntitiesTrait<ProductOrder>(),
282
- * addSelectEntitiesTrait<ProductOrder>()
283
- * );
284
- *
285
- * const productFeatureFactory = createEntityFeatureFactory(
286
- * { entityName: 'product' },
287
- * addLoadEntitiesTrait<Product>(),
288
- * addSelectEntitiesTrait<Product>()
289
- * );
290
- *
291
- * const productCombinedFactory = combineEntityFeatures({
292
- * products: productFeatureFactory,
293
- * productOrders: productOrderFeatureFactory,
294
- * clients: clientsFeatureFactory,
295
- * });
296
- *
297
- * const combinedFeature = productCombinedFactory({
298
- * actionsGroupKey: '[Combined]',
299
- * featureSelector: 'combined',
300
- * });
301
- *
302
- * combinedFeature.actions.client.loadClients();
303
- * combinedFeature.actions.product.loadProducts();
304
- */
305
- function combineEntityFeatures(traitFactoriesMap) {
306
- return ((config) => {
307
- const featureSelector = typeof config.featureSelector === 'string'
308
- ? createFeatureSelector(config.featureSelector)
309
- : config.featureSelector;
310
- const actions = {};
311
- const selectors = {};
312
- const reducers = {};
313
- let effects = [];
314
- for (const [key, entityFeatureFactory] of Object.entries(traitFactoriesMap)) {
315
- const selector = createSelector(featureSelector, (state) => state[key]);
316
- const featureTraits = entityFeatureFactory({
317
- actionsGroupKey: config.actionsGroupKey,
318
- featureSelector: selector,
319
- });
320
- actions[key] = featureTraits.actions;
321
- selectors[key] = featureTraits.selectors;
322
- reducers[key] = featureTraits.reducer;
323
- effects = [...effects, ...featureTraits.effects];
324
- }
325
- return {
326
- actions,
327
- selectors,
328
- reducer: combineReducers(reducers),
329
- effects,
330
- };
331
- });
332
- }
333
- /**
334
- * Mix a map entityFeatureFactories into one, different from combine the actions and selectors a mix, not group by key like in combine, the keys are still use
335
- * internal in the reducers and selector to separate the state
336
- * @param traitFactoriesMap
337
- *
338
- * @example
339
- *
340
- * const clientsFeatureFactory = createEntityFeatureFactory(
341
- * { entityName: 'client', entitiesName: 'clients' },
342
- * addLoadEntitiesTrait<Client>(),
343
- * addCrudEntitiesTrait<Client>()
344
- * );
345
- *
346
- * const productOrderFeatureFactory = createEntityFeatureFactory(
347
- * { entityName: 'productOrder' },
348
- * addLoadEntitiesTrait<ProductOrder>(),
349
- * addSelectEntitiesTrait<ProductOrder>()
350
- * );
351
- *
352
- * const productFeatureFactory = createEntityFeatureFactory(
353
- * { entityName: 'product' },
354
- * addLoadEntitiesTrait<Product>(),
355
- * addSelectEntitiesTrait<Product>()
356
- * );
357
- *
358
- * const productMixedFactory = mixEntityFeatures({
359
- * products: productFeatureFactory,
360
- * productOrders: productOrderFeatureFactory,
361
- * clients: clientsFeatureFactory,
362
- * });
363
- *
364
- * const mixedFeature = productMixedFactory({
365
- * actionsGroupKey: '[Mixed]',
366
- * featureSelector: 'mixed',
367
- * });
368
- * mixedFeature.actions.loadClients();
369
- * mixedFeature.actions.loadProducts();
370
- *
371
- */
372
- function mixEntityFeatures(traitFactoriesMap) {
373
- return ((config) => {
374
- const featureSelector = typeof config.featureSelector === 'string'
375
- ? createFeatureSelector(config.featureSelector)
376
- : config.featureSelector;
377
- let actions = {};
378
- let selectors = {};
379
- const reducers = {};
380
- let effects = [];
381
- for (const [key, entityFeatureFactory] of Object.entries(traitFactoriesMap)) {
382
- const selector = createSelector(featureSelector, (state) => state[key]);
383
- const featureTraits = entityFeatureFactory({
384
- actionsGroupKey: config.actionsGroupKey,
385
- featureSelector: selector,
386
- });
387
- actions = Object.assign(Object.assign({}, actions), featureTraits.actions);
388
- selectors = Object.assign(Object.assign({}, selectors), featureTraits.selectors);
389
- reducers[key] = featureTraits.reducer;
390
- effects = [...effects, ...featureTraits.effects];
391
- }
392
- return {
393
- actions,
394
- selectors,
395
- reducer: combineReducers(reducers),
396
- effects,
397
- };
398
- });
399
- }
400
- /**
401
- * Combines targetTraitFactory with the traitFactoriesMap using the keys as props for the targetTraitFactory state,
402
- * and grouping the combined actions by key
403
- * @param targetTraitFactory
404
- * @param traitFactoriesMap
405
- *
406
- * @example
407
- *
408
- * const clientsFeatureFactory = createEntityFeatureFactory(
409
- * { entityName: 'client', entitiesName: 'clients' },
410
- * addLoadEntitiesTrait<Client>(),
411
- * addCrudEntitiesTrait<Client>()
412
- * );
413
- *
414
- * const productOrderFeatureFactory = createEntityFeatureFactory(
415
- * { entityName: 'productOrder' },
416
- * addLoadEntitiesTrait<ProductOrder>(),
417
- * addSelectEntitiesTrait<ProductOrder>()
418
- * );
419
- *
420
- * const productFeatureFactory = createEntityFeatureFactory(
421
- * { entityName: 'product' },
422
- * addLoadEntitiesTrait<Product>(),
423
- * addSelectEntitiesTrait<Product>()
424
- * );
425
- *
426
- * const productAddEntityPropertiesFactory = addEntityFeaturesProperties(
427
- * productFeatureFactory,
428
- * {
429
- * productOrders: productOrderFeatureFactory,
430
- * clients: clientsFeatureFactory,
431
- * }
432
- * );
433
- *
434
- * const combinedFeature = productAddEntityPropertiesFactory({
435
- * actionsGroupKey: '[addEntityFeatures]',
436
- * featureSelector: 'addEntityFeatures',
437
- * });
438
- *
439
- * combinedFeature.actions.loadProducts();
440
- * combinedFeature.actions.clients.loadClients();
441
- * combinedFeature.actions.productOrders.loadProductOrders();
442
- */
443
- function addEntityFeaturesProperties(targetTraitFactory, traitFactoriesMap) {
444
- return ((config) => {
445
- const featureSelector = typeof config.featureSelector === 'string'
446
- ? createFeatureSelector(config.featureSelector)
447
- : config.featureSelector;
448
- const targetFeatureTraits = targetTraitFactory({
449
- actionsGroupKey: config.actionsGroupKey,
450
- featureSelector: featureSelector,
451
- });
452
- const actions = Object.assign({}, targetFeatureTraits.actions);
453
- const selectors = Object.assign({}, targetFeatureTraits.selectors);
454
- const reducers = {};
455
- let effects = [...targetFeatureTraits.effects];
456
- for (const [key, entityFeatureFactory] of Object.entries(traitFactoriesMap)) {
457
- const selector = createSelector(featureSelector, (state) => state[key]);
458
- const featureTraits = entityFeatureFactory({
459
- actionsGroupKey: config.actionsGroupKey,
460
- featureSelector: selector,
461
- });
462
- actions[key] = featureTraits.actions;
463
- selectors[key] = featureTraits.selectors;
464
- reducers[key] = featureTraits.reducer;
465
- effects = [...effects, ...featureTraits.effects];
466
- }
467
- return {
468
- actions,
469
- selectors,
470
- reducer: setPropertiesReducer(targetFeatureTraits.reducer, reducers),
471
- effects,
472
- };
473
- });
474
- }
475
- /**
476
- * Helper function to create an implementation a TraitFactory
477
- * @param f TraitFactory implementation
478
- */
479
- function createTraitFactory(f) {
480
- return f;
481
- }
482
- /**
483
- * Helper function to combine selectors in components as map
484
- *
485
- * @example
486
- *
487
- * view = combineSelectors({
488
- * products: ProductSelectors.selectProductsCurrentPage,
489
- * isLoading: ProductSelectors.isLoadingProductsCurrentPage,
490
- * selectedProduct: ProductSelectors.selectProductSelected,
491
- * isLoadingCheckout: ProductSelectors.isLoadingCheckout,
492
- * selectedSort: ProductSelectors.selectProductsSort,
493
- * filters: ProductSelectors.selectProductsFilter,
494
- * });
495
- * @param t
496
- */
497
- function combineSelectors(t) {
498
- const selectors = Object.values(t);
499
- const keys = Object.keys(t);
500
- const projector = (...args) => keys.reduce((acc, key, index) => {
501
- acc[key] = args[index];
502
- return acc;
503
- }, {});
504
- return createSelector.apply(null, [...selectors, projector]);
505
- }
506
-
507
- class TraitEffect {
508
- constructor() {
509
- this.name = this.constructor.name;
510
- this.componentId = '';
511
- this.actions$ = inject(Actions);
512
- this.store = inject((Store));
513
- }
514
- ngrxOnIdentifyEffects() {
515
- return this.componentId ? this.name + this.componentId : '';
516
- }
517
- ngrxOnRunEffects(resolvedEffects$) {
518
- return this.componentId
519
- ? resolvedEffects$.pipe(takeUntil(this.actions$.pipe(ofType(getDestroyActionName(this.componentId)))))
520
- : resolvedEffects$;
521
- }
522
- }
523
- TraitEffect.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TraitEffect, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
524
- TraitEffect.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TraitEffect });
525
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TraitEffect, decorators: [{
526
- type: Injectable
527
- }] });
528
- function getDestroyActionName(id) {
529
- return `[${id}] Destroyed`;
530
- }
531
-
532
- /**
533
- * @ignore
534
- * @internal
535
- */
536
- const DISABLE_LOCAL_TRAIT_EFFECTS = new InjectionToken('disableLocalTraitEffects');
537
-
538
- let id = 0;
539
- function uniqueComponentId() {
540
- return id++;
541
- }
542
- /**
543
- * Builds traitFactory and registers effects and reducers with
544
- * a generated component id, returns build actions and selectors
545
- * and a destroy method that will unergister the effects and reducers
546
- * when called, and a addEffect which can be use to register extra effects
547
- *
548
- * Used inside TraitsLocalStore, can be used to create your
549
- * own Component Service without extending TraitsLocalStore
550
- * @param injector
551
- * @param componentName
552
- * @param traitFactory
553
- */
554
- function buildLocalTraits(injector, componentName, traitFactory) {
555
- var _a;
556
- const reducers = injector.get(ReducerManager);
557
- const effects = injector.get(EffectSources);
558
- const store = injector.get(Store);
559
- const componentId = `${componentName}_${uniqueComponentId()}`;
560
- const traits = traitFactory({
561
- featureSelector: createFeatureSelector(componentId),
562
- actionsGroupKey: `[${componentId}]`,
563
- });
564
- traits.reducer && reducers.addReducer(componentId, traits.reducer);
565
- const providers = (traits.effects && [...traits.effects.map((e) => ({ provide: e }))]) || [];
566
- const disableLocalTraitsEffects = injector.get(DISABLE_LOCAL_TRAIT_EFFECTS, false);
567
- if (!disableLocalTraitsEffects) {
568
- const i = Injector.create({
569
- providers: providers,
570
- parent: injector,
571
- });
572
- (_a = traits.effects) === null || _a === void 0 ? void 0 : _a.forEach((e) => {
573
- const effect = i.get(e);
574
- effect.componentId = componentId;
575
- effects.addEffects(effect);
576
- });
577
- }
578
- function destroy() {
579
- store.dispatch({ type: getDestroyActionName(componentId) });
580
- /**
581
- * A service that extends TraitsLocalStore and other component service are destroyed
582
- * before the component that depends on them, this causes that any subscriptions
583
- * to selectors of the TraitsLocalStore could fail because the store state is removed before
584
- * they are unsubscribe by the onDestroy of the component. Executing reducers.removeReducer
585
- * inside setTimeout ensures the state is remove after the component onDestroy was called,
586
- * avoiding the before mentioned possible issues.
587
- */
588
- setTimeout(() => reducers.removeReducer(componentId));
589
- }
590
- return {
591
- destroy,
592
- actions: traits.actions,
593
- selectors: traits.selectors,
594
- addEffects(localEffect) {
595
- localEffect.componentId = componentId;
596
- effects.addEffects(localEffect);
597
- },
598
- };
599
- }
600
- /**
601
- * Class used to create local traits service, receives a trait factory, which will be
602
- * built and its reducers and effect register using a dynamic id when the service is built
603
- * and get destroyed when the onDestroy lifecycle method of the service is called, if the service
604
- * has effects this.traits.addEffects(this) should be call in the constructor
605
- *
606
- * @example
607
- * const productFeatureFactory = createEntityFeatureFactory(
608
- * { entityName: 'product' },
609
- * addLoadEntitiesTrait<Product>(),
610
- * addSelectEntityTrait<Product>(),
611
- * );
612
- *
613
- * Injectable()
614
- * export class ProductsLocalTraits extends TraitsLocalStore<
615
- * typeof productFeatureFactory
616
- * > {
617
- * loadProducts$ = createEffect(() =>
618
- * this.actions$.pipe(
619
- * ofType(this.localActions.loadProducts),
620
- * switchMap(() =>
621
- * //call your service to get the products data
622
- * this.productService.getProducts().pipe(
623
- * map((res) =>
624
- * this.localActions.loadProductsSuccess({ entities: res.resultList })
625
- * ),
626
- * catchError(() => of(this.localActions.loadProductsFail()))
627
- * )
628
- * )
629
- * )
630
- * );
631
- *
632
- * constructor(injector: Injector, private productService: ProductService) {
633
- * super(injector);
634
- * this.traits.addEffects(this); // IMPORTANT! add this line if the service has effects
635
- * }
636
- *
637
- * setup(): LocalTraitsConfig<typeof productFeatureFactory> {
638
- * return {
639
- * componentName: 'ProductsPickerComponent',
640
- * traitsFactory: productFeatureFactory,
641
- * };
642
- * }
643
- * }
644
- *
645
- * // use in component later
646
- *
647
- * Component({
648
- * selector: 'some-component',
649
- * template: `<div> some content</div> `,
650
- * providers: [ProductsLocalTraits],
651
- * changeDetection: ChangeDetectionStrategy.OnPush,
652
- * })
653
- * export class ProductSelectDialogComponent implements OnInit {
654
- * constructor(private store: Store, private traits: ProductsLocalTraits) {}
655
- *
656
- * ngOnInit() {
657
- * this.store.dispatch(this.traits.localActions.loadProducts());
658
- * }
659
- * }
660
- */
661
- class TraitsLocalStore extends TraitEffect {
662
- constructor() {
663
- super();
664
- this.injector = inject(Injector);
665
- const config = this.setup();
666
- this.traits = buildLocalTraits(this.injector, config.componentName, config.traitsFactory);
667
- this.localActions = this.traits.actions;
668
- this.localSelectors = this.traits.selectors;
669
- }
670
- ngOnDestroy() {
671
- this.traits.destroy();
672
- }
673
- }
674
- TraitsLocalStore.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TraitsLocalStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
675
- TraitsLocalStore.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TraitsLocalStore });
676
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TraitsLocalStore, decorators: [{
677
- type: Injectable
678
- }], ctorParameters: function () { return []; } });
679
-
680
- function hash(key) {
681
- return JSON.stringify(key, (_, val) => typeof val == 'object'
682
- ? Object.keys(val)
683
- .sort()
684
- .reduce((result, k) => {
685
- result[k] = val[k];
686
- return result;
687
- }, {})
688
- : val);
689
- }
690
- function hashKey(key) {
691
- return typeof key === 'string'
692
- ? [key]
693
- : key.map((k) => {
694
- return typeof k === 'string' ? k : hash(k);
695
- });
696
- }
697
- function getCacheValue(keys, state) {
698
- var _a;
699
- let parent = state;
700
- for (const key of keys) {
701
- parent = (_a = parent === null || parent === void 0 ? void 0 : parent.keys) === null || _a === void 0 ? void 0 : _a[key];
702
- if (!parent)
703
- return undefined;
704
- }
705
- return parent === null || parent === void 0 ? void 0 : parent.data;
706
- }
707
- function isCacheValid(cache, exp) {
708
- return !cache.invalid && Date.now() <= cache.date + exp;
709
- }
710
-
711
- const cacheStateSelector = createFeatureSelector('cache');
712
- const selectCache = (key) => createSelector(cacheStateSelector, (state) => getCacheValue(hashKey(key), state));
713
-
714
- const cache$1 = createAction('[Cache] Cache', props());
715
- const hitCache = createAction('[Cache] Hit Cache', props());
716
- const invalidateCache$1 = createAction('[Cache] Invalidate Cache', props());
717
- const deleteCache = createAction('[Cache] Delete Cache', props());
718
-
719
- /**
720
- * Cache the result of source parameter using the provided key, when call
721
- * again if the cache is valid (exist and is not expired or invalidated)
722
- * it will return the cache value without calling again source
723
- * @example
724
- * // cache for 3 min
725
- * loadStores$ = createEffect(() => {
726
- * return this.actions$.pipe(
727
- * ofType(ProductStoreActions.loadStores),
728
- * exhaustMap(() =>
729
- * cache({
730
- * key: ['stores'],
731
- * store: this.store,
732
- * source: this.storeService.getStores(),
733
- * expire: 1000 * 60 * 3 // optional param , cache forever if not present
734
- * }).pipe(
735
- * map((res) => ProductStoreActions.loadStoresSuccess({ entities: res })),
736
- * catchError(() => of(ProductStoreActions.loadStoresFail()))
737
- * )
738
- * )
739
- * );
740
- * });
741
- * // cache top 10, for 3 mins
742
- * loadDepartments$ = createEffect(() => {
743
- * return this.actions$.pipe(
744
- * ofType(this.localActions.loadDepartments),
745
- * concatLatestFrom(() =>
746
- * this.store.select(this.localSelectors.selectDepartmentsFilter)
747
- * ),
748
- * exhaustMap(([_, filters]) =>
749
- * cache({
750
- * key: ['stores','departments',{ storeId: filters!.storeId },
751
- * store: this.store,
752
- * source: this.storeService.getStoreDepartments(filters!.storeId),
753
- * expires: 1000 * 60 * 3,
754
- * maxCacheSize: 10,
755
- * }).pipe(
756
- * map((res) =>
757
- * this.localActions.loadDepartmentsSuccess({
758
- * entities: res,
759
- * })
760
- * ),
761
- * catchError(() => of(this.localActions.loadDepartmentsFail()))
762
- * )
763
- * )
764
- * );
765
- * });
766
- *
767
- * @param options - configuration
768
- * @param options.store - required ngrx store
769
- * @param options.key - key can be string, array of string or array of string with plain objects
770
- * @param options.source - called when cache is invalid
771
- * @param options.expires - time to expire the cache valued, if not present is infinite
772
- * @param options.maxCacheSize - max number of keys to store , only works if last key is variable
773
- */
774
- function cache({ store, key, source, expires, maxCacheSize, skip, }) {
775
- const exp = expires !== null && expires !== void 0 ? expires : Infinity;
776
- return store.select(selectCache(key)).pipe(first(), concatMap((cache) => cache && !skip && isCacheValid(cache, exp)
777
- ? of(cache.value).pipe(tap(() => store.dispatch(hitCache({ key }))))
778
- : source.pipe(tap((value) => store.dispatch(cache$1({
779
- key,
780
- date: Date.now(),
781
- value,
782
- maxCacheSize,
783
- }))))));
784
- }
785
-
786
- const initialState = {
787
- keys: {},
788
- };
789
- const cacheReducer = createReducer(initialState, on(cache$1, (state, { key, value, date, maxCacheSize }) => setCacheValue(hashKey(key), { value, date, invalid: false }, state, maxCacheSize)), on(invalidateCache$1, (state, { key }) => {
790
- const k = hashKey(key);
791
- return invalidateCache(k, state);
792
- }), on(deleteCache, (state, { key }) => {
793
- const k = hashKey(key);
794
- return deleteCacheValue(k, state);
795
- }), on(hitCache, (state, { key }) => {
796
- const k = hashKey(key);
797
- return increaseCacheHitCount(k, state);
798
- }));
799
- function setCacheValue(keys, value, state, maxCacheSize, expires) {
800
- const newState = Object.assign({}, state);
801
- let cache = newState;
802
- let lastCache = undefined;
803
- for (let i = 0; i < keys.length; i++) {
804
- const key = keys[i];
805
- cache.keys = (cache === null || cache === void 0 ? void 0 : cache.keys) ? Object.assign({}, cache === null || cache === void 0 ? void 0 : cache.keys) : {};
806
- let v = cache.keys[key];
807
- v = v ? Object.assign({}, v) : {};
808
- cache.keys[key] = v;
809
- lastCache = cache;
810
- cache = v;
811
- }
812
- cache.data = cache.data
813
- ? Object.assign(Object.assign({}, value), { hitCount: cache.data.hitCount + 1 }) : Object.assign(Object.assign({}, value), { hitCount: 1 });
814
- if (maxCacheSize &&
815
- (lastCache === null || lastCache === void 0 ? void 0 : lastCache.keys) &&
816
- Object.keys(lastCache.keys).length > maxCacheSize) {
817
- const entries = findLessHitOrOldestCacheEntries(lastCache, expires !== null && expires !== void 0 ? expires : Infinity, maxCacheSize);
818
- if (entries && entries.length) {
819
- for (const [key] of entries) {
820
- delete lastCache.keys[key];
821
- }
822
- }
823
- }
824
- return newState;
825
- }
826
- function findLessHitOrOldestCacheEntries(state, expires, maxCacheSize) {
827
- if (!state.keys)
828
- return undefined;
829
- const entries = Object.entries(state.keys);
830
- // find the newest key;
831
- const [newestKey] = entries.reduce((a, b) => {
832
- var _a, _b, _c, _d;
833
- const aDate = (_b = (_a = a[1].data) === null || _a === void 0 ? void 0 : _a.date) !== null && _b !== void 0 ? _b : 0;
834
- const bDate = (_d = (_c = b[1].data) === null || _c === void 0 ? void 0 : _c.date) !== null && _d !== void 0 ? _d : 0;
835
- return aDate > bDate ? a : b;
836
- });
837
- const sorted = entries.sort(([aKey, aValue], [bKey, bValue]) => {
838
- var _a, _b, _c, _d, _e, _f, _g, _h;
839
- // ensures the newest key always wins
840
- if (aKey === newestKey)
841
- return -1;
842
- if (bKey === newestKey)
843
- return 1;
844
- const aValid = aValue.data && isCacheValid(aValue.data, expires) ? 1 : 0;
845
- const bValid = bValue.data && isCacheValid(bValue.data, expires) ? 1 : 0;
846
- const diffValid = aValid - bValid;
847
- const diffHit = ((_b = (_a = aValue.data) === null || _a === void 0 ? void 0 : _a.hitCount) !== null && _b !== void 0 ? _b : 0) - ((_d = (_c = bValue.data) === null || _c === void 0 ? void 0 : _c.hitCount) !== null && _d !== void 0 ? _d : 0);
848
- const diffDate = ((_f = (_e = aValue.data) === null || _e === void 0 ? void 0 : _e.date) !== null && _f !== void 0 ? _f : 0) - ((_h = (_g = bValue.data) === null || _g === void 0 ? void 0 : _g.date) !== null && _h !== void 0 ? _h : 0);
849
- return (-1 * (diffValid === 0 ? (diffHit === 0 ? diffDate : diffHit) : diffValid));
850
- });
851
- return sorted.slice(maxCacheSize);
852
- }
853
- function deleteCacheValue(keys, state) {
854
- const newState = Object.assign({}, state);
855
- let cache = newState;
856
- for (const key of keys) {
857
- if (!cache.keys)
858
- return state;
859
- cache.keys = Object.assign({}, cache === null || cache === void 0 ? void 0 : cache.keys);
860
- let v = cache.keys[key];
861
- if (!v)
862
- return state;
863
- v = Object.assign({}, v);
864
- cache.keys[key] = v;
865
- cache = v;
866
- }
867
- if (cache.data)
868
- delete cache.data;
869
- else if (cache.keys)
870
- delete cache.keys;
871
- return newState;
872
- }
873
- function invalidateCache(keys, state) {
874
- var _a;
875
- const newState = Object.assign({}, state);
876
- let cache = newState;
877
- for (const key of keys) {
878
- if (!(cache === null || cache === void 0 ? void 0 : cache.keys))
879
- return state;
880
- cache.keys = Object.assign({}, cache === null || cache === void 0 ? void 0 : cache.keys);
881
- let v = (_a = cache === null || cache === void 0 ? void 0 : cache.keys) === null || _a === void 0 ? void 0 : _a[key];
882
- if (!v)
883
- return state;
884
- v = Object.assign({}, v);
885
- cache.keys[key] = v;
886
- cache = v;
887
- }
888
- cache && invalidaSubKeys(cache);
889
- return newState;
890
- }
891
- function increaseCacheHitCount(keys, state) {
892
- var _a;
893
- const newState = Object.assign({}, state);
894
- let cache = newState;
895
- for (const key of keys) {
896
- if (!(cache === null || cache === void 0 ? void 0 : cache.keys))
897
- return state;
898
- cache.keys = Object.assign({}, cache === null || cache === void 0 ? void 0 : cache.keys);
899
- let v = (_a = cache === null || cache === void 0 ? void 0 : cache.keys) === null || _a === void 0 ? void 0 : _a[key];
900
- if (!v)
901
- return state;
902
- v = Object.assign({}, v);
903
- cache.keys[key] = v;
904
- cache = v;
905
- }
906
- if (!cache.data)
907
- return state;
908
- cache.data = Object.assign(Object.assign({}, cache.data), { hitCount: cache.data.hitCount + 1 });
909
- return newState;
910
- }
911
- function invalidaSubKeys(state) {
912
- if (state.data) {
913
- state.data = Object.assign(Object.assign({}, state.data), { invalid: true });
914
- }
915
- if (state.keys) {
916
- state.keys = Object.assign({}, state.keys);
917
- for (const key in state.keys) {
918
- state.keys[key] = invalidaSubKeys(Object.assign({}, state.keys[key]));
919
- }
920
- }
921
- return state;
922
- }
923
-
924
- class CacheModule {
925
- }
926
- CacheModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CacheModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
927
- CacheModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: CacheModule, imports: [i1.StoreFeatureModule] });
928
- CacheModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CacheModule, imports: [StoreModule.forFeature('cache', cacheReducer)] });
929
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: CacheModule, decorators: [{
930
- type: NgModule,
931
- args: [{
932
- imports: [StoreModule.forFeature('cache', cacheReducer)],
933
- providers: [],
934
- }]
935
- }] });
936
-
937
- const CacheActions = { invalidateCache: invalidateCache$1, deleteCache };
938
- const CacheSelectors = { getCache: selectCache };
939
-
940
- /**
941
- * Generated bundle index. Do not edit.
942
- */
943
-
944
- export { CacheActions, CacheModule, CacheSelectors, DISABLE_LOCAL_TRAIT_EFFECTS, TraitEffect, TraitsLocalStore, addEntityFeaturesProperties, buildLocalTraits, cache, camelCaseToSentence, capitalize, combineEntityFeatures, combineSelectors, createEntityFeatureFactory, createTraitFactory, getDestroyActionName, insertIf, joinReducers, mixEntityFeatures, setPropertiesReducer, setPropertyReducer, toMap };
945
- //# sourceMappingURL=ngrx-traits-core.mjs.map