@microphi/store 0.2.10 → 1.1.3

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 (63) hide show
  1. package/lib/index.d.ts +4 -0
  2. package/lib/index.js +8 -0
  3. package/lib/index.js.map +1 -0
  4. package/lib/lib/effect/effect.d.ts +61 -0
  5. package/lib/lib/effect/effect.js +75 -0
  6. package/lib/lib/effect/effect.js.map +1 -0
  7. package/lib/{list → lib/list}/list.d.ts +1 -1
  8. package/lib/lib/list/list.js +75 -0
  9. package/lib/lib/list/list.js.map +1 -0
  10. package/lib/lib/reduce/reduce.d.ts +11 -0
  11. package/lib/lib/reduce/reduce.js +26 -0
  12. package/lib/lib/reduce/reduce.js.map +1 -0
  13. package/lib/lib/store/store.d.ts +38 -0
  14. package/lib/lib/store/store.js +99 -0
  15. package/lib/lib/store/store.js.map +1 -0
  16. package/lib/lib/utilities/capitalise.d.ts +1 -0
  17. package/lib/lib/utilities/capitalise.js +7 -0
  18. package/lib/lib/utilities/capitalise.js.map +1 -0
  19. package/lib/lib/utilities/scan-instance.d.ts +2 -0
  20. package/lib/lib/utilities/scan-instance.js +19 -0
  21. package/lib/lib/utilities/scan-instance.js.map +1 -0
  22. package/package.json +18 -14
  23. package/bundles/microphi-store.umd.js +0 -996
  24. package/bundles/microphi-store.umd.js.map +0 -1
  25. package/bundles/microphi-store.umd.min.js +0 -16
  26. package/bundles/microphi-store.umd.min.js.map +0 -1
  27. package/esm2015/lib/actions.js +0 -105
  28. package/esm2015/lib/base-store.js +0 -156
  29. package/esm2015/lib/effect.js +0 -11
  30. package/esm2015/lib/http-status/http-status.interceptor.js +0 -31
  31. package/esm2015/lib/http-status/http-status.store.js +0 -63
  32. package/esm2015/lib/list/list.js +0 -80
  33. package/esm2015/lib/observable-list/observable-list.js +0 -119
  34. package/esm2015/lib/reduce.js +0 -15
  35. package/esm2015/lib/store.js +0 -13
  36. package/esm2015/microphi-store.js +0 -5
  37. package/esm2015/public-api.js +0 -13
  38. package/esm5/lib/actions.js +0 -110
  39. package/esm5/lib/base-store.js +0 -177
  40. package/esm5/lib/effect.js +0 -11
  41. package/esm5/lib/http-status/http-status.interceptor.js +0 -33
  42. package/esm5/lib/http-status/http-status.store.js +0 -66
  43. package/esm5/lib/list/list.js +0 -126
  44. package/esm5/lib/observable-list/observable-list.js +0 -250
  45. package/esm5/lib/reduce.js +0 -15
  46. package/esm5/lib/store.js +0 -13
  47. package/esm5/microphi-store.js +0 -5
  48. package/esm5/public-api.js +0 -13
  49. package/fesm2015/microphi-store.js +0 -586
  50. package/fesm2015/microphi-store.js.map +0 -1
  51. package/fesm5/microphi-store.js +0 -788
  52. package/fesm5/microphi-store.js.map +0 -1
  53. package/lib/actions.d.ts +0 -77
  54. package/lib/base-store.d.ts +0 -31
  55. package/lib/effect.d.ts +0 -2
  56. package/lib/http-status/http-status.interceptor.d.ts +0 -7
  57. package/lib/http-status/http-status.store.d.ts +0 -17
  58. package/lib/observable-list/observable-list.d.ts +0 -29
  59. package/lib/reduce.d.ts +0 -7
  60. package/lib/store.d.ts +0 -9
  61. package/microphi-store.d.ts +0 -4
  62. package/microphi-store.metadata.json +0 -1
  63. package/public-api.d.ts +0 -9
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './lib/store/store';
2
+ export * from './lib/effect/effect';
3
+ export * from './lib/reduce/reduce';
4
+ export * from './lib/list/list';
package/lib/index.js ADDED
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Public API Surface of store
3
+ */
4
+ export * from './lib/store/store';
5
+ export * from './lib/effect/effect';
6
+ export * from './lib/reduce/reduce';
7
+ export * from './lib/list/list';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC","sourcesContent":["/*\n * Public API Surface of store\n */\n\nexport * from './lib/store/store';\nexport * from './lib/effect/effect';\nexport * from './lib/reduce/reduce';\nexport * from './lib/list/list';\n"]}
@@ -0,0 +1,61 @@
1
+ export declare type EffectStrategy = 'switchMap' | 'mergeMap' | 'concatMap';
2
+ export interface Effect {
3
+ action: string;
4
+ strategy: EffectStrategy;
5
+ }
6
+ export declare const EffectSymbol: unique symbol;
7
+ /**
8
+ * Tags a method as an effect <br>
9
+ *
10
+ * Strategy is one of the following rxjs pipe-able operators:
11
+ * - `mergeMap`
12
+ * - `concatMap`
13
+ * - `switchMap`
14
+ *
15
+ * As an example consider the following:
16
+ * suppose there's an effect that takes 10 ms to return and then a reducer is called.<br>
17
+ * Suppose we dispatch its event, the following diagram demonstrate what happens<br>
18
+ * <code>
19
+ * `D -> E -> (10) -> R`<br>
20
+ * </code>
21
+ * Event is dispatched `D`, event is executed `E`, takes 10ms and finally reducer is called with result from `E`
22
+ *
23
+ * Now let's suppose we dispatch again the same while `E` is still pending (executing) and suppose we call it with a different argument.
24
+ *
25
+ *
26
+ * `D(a) -> E -> D(b)`
27
+ *
28
+ *
29
+ * what happens next depends on the strategy used.<br>
30
+ *
31
+ *
32
+ * If `switchMap` is used (default)
33
+ *
34
+ * `D(a) -> E(a) -> D(b) -> E(b) -> R(b)`
35
+ *
36
+ * the second dispatch cancels the first and so only `R(b)` is executed
37
+ *
38
+ *
39
+ * If `mergeMap` is used
40
+ *
41
+ * `D(a) -> E(a) -> D(b) -> E(b) -> R(a) -> R(b)
42
+ *
43
+ * effects are executed in parallel and the first to come is the first served
44
+ *
45
+ * i.e.: lets say E(a) takes longer to respond then
46
+ *
47
+ * `D(a) -> D(b) -> E(b) -> R(b) -> E(a) -> -> R(a)`
48
+ *
49
+ *
50
+ * If `concatMap` is used then the order of calls is respected.
51
+ *
52
+ * in the case above we'll have whatever the timings are on the effects
53
+ *
54
+ * `D(a) -> D(b) -> E(a) -> R(a) -> E(b) -> -> R(b)`
55
+ *
56
+ * @param strategy
57
+ * @constructor
58
+ */
59
+ export declare function Effect(strategy?: EffectStrategy): MethodDecorator;
60
+ export declare function getEffectMetadata(klass: object, key: string): any;
61
+ export declare function getEffects<T extends object>(instance: T): Effect[];
@@ -0,0 +1,75 @@
1
+ import { scanInstance } from '../utilities/scan-instance';
2
+ export const EffectSymbol = Symbol.for('@Effect');
3
+ /**
4
+ * Tags a method as an effect <br>
5
+ *
6
+ * Strategy is one of the following rxjs pipe-able operators:
7
+ * - `mergeMap`
8
+ * - `concatMap`
9
+ * - `switchMap`
10
+ *
11
+ * As an example consider the following:
12
+ * suppose there's an effect that takes 10 ms to return and then a reducer is called.<br>
13
+ * Suppose we dispatch its event, the following diagram demonstrate what happens<br>
14
+ * <code>
15
+ * `D -> E -> (10) -> R`<br>
16
+ * </code>
17
+ * Event is dispatched `D`, event is executed `E`, takes 10ms and finally reducer is called with result from `E`
18
+ *
19
+ * Now let's suppose we dispatch again the same while `E` is still pending (executing) and suppose we call it with a different argument.
20
+ *
21
+ *
22
+ * `D(a) -> E -> D(b)`
23
+ *
24
+ *
25
+ * what happens next depends on the strategy used.<br>
26
+ *
27
+ *
28
+ * If `switchMap` is used (default)
29
+ *
30
+ * `D(a) -> E(a) -> D(b) -> E(b) -> R(b)`
31
+ *
32
+ * the second dispatch cancels the first and so only `R(b)` is executed
33
+ *
34
+ *
35
+ * If `mergeMap` is used
36
+ *
37
+ * `D(a) -> E(a) -> D(b) -> E(b) -> R(a) -> R(b)
38
+ *
39
+ * effects are executed in parallel and the first to come is the first served
40
+ *
41
+ * i.e.: lets say E(a) takes longer to respond then
42
+ *
43
+ * `D(a) -> D(b) -> E(b) -> R(b) -> E(a) -> -> R(a)`
44
+ *
45
+ *
46
+ * If `concatMap` is used then the order of calls is respected.
47
+ *
48
+ * in the case above we'll have whatever the timings are on the effects
49
+ *
50
+ * `D(a) -> D(b) -> E(a) -> R(a) -> E(b) -> -> R(b)`
51
+ *
52
+ * @param strategy
53
+ * @constructor
54
+ */
55
+ export function Effect(strategy = 'switchMap') {
56
+ // return Reflect.metadata(EffectSymbol, strategy);
57
+ return (target, propertyKey) => {
58
+ // return Reflect.metadata(EffectSymbol, strategy)(target, propertyKey);
59
+ return Reflect.defineMetadata(EffectSymbol, strategy, target, propertyKey);
60
+ };
61
+ }
62
+ export function getEffectMetadata(klass, key) {
63
+ return Reflect.getMetadata(EffectSymbol, klass, key);
64
+ }
65
+ export function getEffects(instance) {
66
+ const effects = [];
67
+ scanInstance(instance, (proto, key) => {
68
+ const strategy = getEffectMetadata(proto, key);
69
+ if (strategy) {
70
+ effects.push({ action: key, strategy, });
71
+ }
72
+ });
73
+ return effects;
74
+ }
75
+ //# sourceMappingURL=effect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effect.js","sourceRoot":"","sources":["../../../src/lib/effect/effect.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAS1D,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,MAAM,UAAU,MAAM,CAAC,WAA2B,WAAW;IAC3D,mDAAmD;IACnD,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,wEAAwE;QACxE,OAAO,OAAO,CAAC,cAAc,CAAC,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAC7E,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,GAAW;IAC1D,OAAO,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,UAAU,CAAmB,QAAW;IAEtD,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,YAAY,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAEpC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,IAAI,QAAQ,EAAE;YACZ,OAAO,CAAC,IAAI,CAAC,EAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,GAAE,CAAC,CAAC;SACxC;IAEH,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import { Store } from '../store/store';\nimport { $Keys } from 'utility-types';\nimport { scanInstance } from '../utilities/scan-instance';\n\nexport type EffectStrategy = 'switchMap' | 'mergeMap' | 'concatMap';\n\nexport interface Effect {\n action: string;\n strategy: EffectStrategy;\n}\n\nexport const EffectSymbol = Symbol.for('@Effect');\n\n/**\n * Tags a method as an effect <br>\n *\n * Strategy is one of the following rxjs pipe-able operators:\n * - `mergeMap`\n * - `concatMap`\n * - `switchMap`\n *\n * As an example consider the following:\n * suppose there's an effect that takes 10 ms to return and then a reducer is called.<br>\n * Suppose we dispatch its event, the following diagram demonstrate what happens<br>\n * <code>\n * `D -> E -> (10) -> R`<br>\n * </code>\n * Event is dispatched `D`, event is executed `E`, takes 10ms and finally reducer is called with result from `E`\n *\n * Now let's suppose we dispatch again the same while `E` is still pending (executing) and suppose we call it with a different argument.\n *\n *\n * `D(a) -> E -> D(b)`\n *\n *\n * what happens next depends on the strategy used.<br>\n *\n *\n * If `switchMap` is used (default)\n *\n * `D(a) -> E(a) -> D(b) -> E(b) -> R(b)`\n *\n * the second dispatch cancels the first and so only `R(b)` is executed\n *\n *\n * If `mergeMap` is used\n *\n * `D(a) -> E(a) -> D(b) -> E(b) -> R(a) -> R(b)\n *\n * effects are executed in parallel and the first to come is the first served\n *\n * i.e.: lets say E(a) takes longer to respond then\n *\n * `D(a) -> D(b) -> E(b) -> R(b) -> E(a) -> -> R(a)`\n *\n *\n * If `concatMap` is used then the order of calls is respected.\n *\n * in the case above we'll have whatever the timings are on the effects\n *\n * `D(a) -> D(b) -> E(a) -> R(a) -> E(b) -> -> R(b)`\n *\n * @param strategy\n * @constructor\n */\nexport function Effect(strategy: EffectStrategy = 'switchMap'): MethodDecorator {\n // return Reflect.metadata(EffectSymbol, strategy);\n return (target, propertyKey) => {\n // return Reflect.metadata(EffectSymbol, strategy)(target, propertyKey);\n return Reflect.defineMetadata(EffectSymbol, strategy, target, propertyKey);\n };\n}\n\nexport function getEffectMetadata(klass: object, key: string) {\n return Reflect.getMetadata(EffectSymbol, klass, key);\n}\n\nexport function getEffects<T extends object>(instance: T): Effect[] {\n\n const effects: Effect[] = [];\n\n scanInstance(instance, (proto, key) => {\n\n const strategy = getEffectMetadata(proto, key);\n if (strategy) {\n effects.push({action: key, strategy,});\n }\n\n });\n\n return effects;\n}\n"]}
@@ -9,7 +9,7 @@ export declare class List<EntityType extends {}> implements Iterable<EntityType>
9
9
  get size(): number;
10
10
  get(id: any): EntityType;
11
11
  private getId;
12
- constructor(entities: EntityType[], IDField: $Keys<EntityType>);
12
+ constructor(IDField: $Keys<EntityType>, entities?: EntityType[]);
13
13
  [Symbol.iterator](): IterableIterator<EntityType>;
14
14
  upsert(...entities: EntityType[]): void;
15
15
  prepend(...entities: EntityType[]): void;
@@ -0,0 +1,75 @@
1
+ export class List {
2
+ constructor(IDField, entities = []) {
3
+ this.IDField = IDField;
4
+ this.entities = new Map();
5
+ /**
6
+ * maps entities position from the original array to their ids
7
+ */
8
+ this.ids = [];
9
+ this.ids = entities.map((e) => this.getId(e));
10
+ entities
11
+ .forEach((item, idx) => {
12
+ const id = item[IDField];
13
+ this.entities.set(id, item);
14
+ });
15
+ }
16
+ get size() {
17
+ if (this.ids.length !== this.entities.size) {
18
+ throw new Error(`Size Mismatch ${this.ids.length} !== ${this.entities.size}`);
19
+ }
20
+ return this.entities.size;
21
+ }
22
+ get(id) {
23
+ return this.entities.get(id);
24
+ }
25
+ getId(entity) {
26
+ return entity[this.IDField];
27
+ }
28
+ *[Symbol.iterator]() {
29
+ // tslint:disable-next-line:forin
30
+ for (const idx in this.ids) {
31
+ const id = this.ids[idx];
32
+ yield this.entities.get(id);
33
+ }
34
+ }
35
+ upsert(...entities) {
36
+ entities.forEach((e) => {
37
+ const id = this.getId(e);
38
+ if (!this.entities.has(id)) {
39
+ this.ids.push(id);
40
+ }
41
+ this.entities.set(id, e);
42
+ });
43
+ }
44
+ prepend(...entities) {
45
+ entities.reverse().forEach((e) => {
46
+ const id = this.getId(e);
47
+ if (this.entities.has(id)) {
48
+ this.delete(e);
49
+ }
50
+ this.ids.unshift(id);
51
+ this.entities.set(id, e);
52
+ });
53
+ }
54
+ delete(...entities) {
55
+ entities.forEach((e) => {
56
+ const id = this.getId(e);
57
+ const indexOfId = this.ids.findIndex((_id) => _id === id);
58
+ if (indexOfId >= 0) {
59
+ this.ids.splice(indexOfId, 1);
60
+ this.entities.delete(id);
61
+ }
62
+ });
63
+ }
64
+ append(...entities) {
65
+ entities.forEach((e) => {
66
+ const id = this.getId(e);
67
+ if (this.entities.has(id)) {
68
+ this.delete(e);
69
+ }
70
+ this.ids.push(id);
71
+ this.entities.set(id, e);
72
+ });
73
+ }
74
+ }
75
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/lib/list/list.ts"],"names":[],"mappings":"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","sourcesContent":["import { $Keys } from 'utility-types';\n\nexport class List<EntityType extends {}> implements Iterable<EntityType> {\n\n public readonly entities = new Map<any, EntityType>();\n\n /**\n * maps entities position from the original array to their ids\n */\n private readonly ids: any[] = [];\n\n public get size() {\n if (this.ids.length !== this.entities.size) {\n\n throw new Error(`Size Mismatch ${this.ids.length} !== ${this.entities.size}`);\n }\n\n return this.entities.size;\n }\n\n public get(id) {\n return this.entities.get(id);\n }\n private getId(entity: EntityType) {\n return entity[this.IDField];\n }\n\n constructor(private IDField: $Keys<EntityType>, entities: EntityType[] = []) {\n\n this.ids = entities.map((e) => this.getId(e));\n\n entities\n .forEach((item, idx) => {\n const id = item[IDField];\n this.entities.set(id, item);\n });\n }\n\n *[Symbol.iterator](): IterableIterator<EntityType> {\n // tslint:disable-next-line:forin\n for (const idx in this.ids) {\n const id = this.ids[idx];\n yield this.entities.get(id);\n }\n }\n\n public upsert(...entities: EntityType[]) {\n entities.forEach((e) => {\n const id = this.getId(e);\n\n if (!this.entities.has(id)) {\n this.ids.push(id);\n }\n\n this.entities.set(id, e);\n });\n }\n\n public prepend(...entities: EntityType[]) {\n entities.reverse().forEach((e) => {\n const id = this.getId(e);\n\n if (this.entities.has(id)) {\n this.delete(e);\n }\n\n this.ids.unshift(id);\n\n this.entities.set(id, e);\n\n });\n }\n\n public delete(...entities: EntityType[]) {\n entities.forEach((e) => {\n const id = this.getId(e);\n const indexOfId = this.ids.findIndex((_id) => _id === id);\n\n if (indexOfId >= 0) {\n this.ids.splice(indexOfId, 1);\n this.entities.delete(id);\n }\n });\n }\n\n public append(...entities: EntityType[]) {\n entities.forEach((e) => {\n const id = this.getId(e);\n\n if (this.entities.has(id)) {\n this.delete(e);\n }\n\n this.ids.push(id);\n this.entities.set(id, e);\n });\n }\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import 'reflect-metadata';
2
+ import { Class } from 'utility-types';
3
+ export declare const ReduceSymbol: unique symbol;
4
+ export interface Reducer {
5
+ action: string;
6
+ }
7
+ export declare function Reduce(): MethodDecorator;
8
+ export declare function getReduceMetadata(klass: Class<any>, key: string): any;
9
+ export declare function getReducers(instance: object): {
10
+ action: string;
11
+ }[];
@@ -0,0 +1,26 @@
1
+ import 'reflect-metadata';
2
+ import { scanInstance } from '../utilities/scan-instance';
3
+ export const ReduceSymbol = Symbol('@Reduce');
4
+ export function Reduce() {
5
+ return (target, propertyKey) => {
6
+ // by convention a reducer have name such as onFindAll
7
+ // where findAll is the associated action
8
+ // with the following we extract the action's name
9
+ const action = propertyKey.slice(2, 3).toLowerCase() + propertyKey.slice(3);
10
+ return Reflect.defineMetadata(ReduceSymbol, action, target, propertyKey);
11
+ };
12
+ }
13
+ export function getReduceMetadata(klass, key) {
14
+ return Reflect.getMetadata(ReduceSymbol, klass, key);
15
+ }
16
+ export function getReducers(instance) {
17
+ const reducers = [];
18
+ scanInstance(instance, (proto, key) => {
19
+ const metadata = getReduceMetadata(proto, key);
20
+ if (metadata) {
21
+ reducers.push({ action: metadata });
22
+ }
23
+ });
24
+ return reducers;
25
+ }
26
+ //# sourceMappingURL=reduce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reduce.js","sourceRoot":"","sources":["../../../src/lib/reduce/reduce.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG1D,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;AAM9C,MAAM,UAAU,MAAM;IACpB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE;QAC7B,sDAAsD;QACtD,yCAAyC;QACzC,kDAAkD;QAClD,MAAM,MAAM,GAAI,WAAsB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,GAAI,WAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAEpG,OAAO,OAAO,CAAC,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IAC3E,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAiB,EAAE,GAAW;IAC9D,OAAO,OAAO,CAAC,WAAW,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAgB;IAE1C,MAAM,QAAQ,GAAwB,EAAE,CAAC;IAEzC,YAAY,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAEpC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,IAAI,QAAQ,EAAE;YACZ,QAAQ,CAAC,IAAI,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAC,CAAC,CAAC;SACnC;IAEH,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["import 'reflect-metadata';\nimport { scanInstance } from '../utilities/scan-instance';\nimport { Class } from 'utility-types';\n\nexport const ReduceSymbol = Symbol('@Reduce');\n\nexport interface Reducer {\n action: string;\n}\n\nexport function Reduce(): MethodDecorator {\n return (target, propertyKey) => {\n // by convention a reducer have name such as onFindAll\n // where findAll is the associated action\n // with the following we extract the action's name\n const action = (propertyKey as string).slice(2, 3).toLowerCase() + (propertyKey as string).slice(3);\n\n return Reflect.defineMetadata(ReduceSymbol, action, target, propertyKey);\n };\n}\n\nexport function getReduceMetadata(klass: Class<any>, key: string) {\n return Reflect.getMetadata(ReduceSymbol, klass, key);\n}\n\nexport function getReducers(instance: object): {action: string;}[] {\n\n const reducers: {action: string;}[] = [];\n\n scanInstance(instance, (proto, key) => {\n\n const metadata = getReduceMetadata(proto, key);\n if (metadata) {\n reducers.push({action: metadata});\n }\n\n });\n\n return reducers;\n}\n"]}
@@ -0,0 +1,38 @@
1
+ import { BehaviorSubject, Observable } from 'rxjs';
2
+ import { Reducer } from '../reduce/reduce';
3
+ import { Effect } from '../effect/effect';
4
+ import { Brand, Primitive } from 'utility-types';
5
+ export declare type getPayloadFromActionType<A, C extends keyof A> = A[C] extends Function ? A[C] extends () => any ? never[] : A[C] extends (...args: infer T) => any ? T : never[] : A[C][];
6
+ export declare type PureReducer<T extends Primitive> = Brand<T, 'reducer'>;
7
+ export declare type makeEffects<Actions> = {
8
+ [k in keyof Actions]: Actions[k] extends PureReducer<Primitive> ? never : Actions[k];
9
+ };
10
+ export declare type makeStore<State, Actions> = {
11
+ [k in keyof makeEffects<Actions>]: makeEffects<Actions>[k];
12
+ } & {
13
+ [k in keyof Actions as `on${Capitalize<string & k>}`]: Actions[k] extends (...args: any) => Observable<infer O> ? (state: State, payload: O) => State : Actions[k] extends PureReducer<infer O> ? (state?: State, payload?: O) => State : (state?: State) => State;
14
+ };
15
+ export interface LoadingState<A> {
16
+ code: keyof A;
17
+ payload?: any;
18
+ response?: any;
19
+ error?: any;
20
+ status: boolean;
21
+ }
22
+ export declare abstract class Store<State, A> {
23
+ private initialState;
24
+ private readonly actions;
25
+ readonly effects: Effect[];
26
+ readonly reducers: Reducer[];
27
+ private _loading$;
28
+ get loading$(): Observable<LoadingState<A>>;
29
+ protected readonly _store$: BehaviorSubject<State>;
30
+ get state$(): Observable<State>;
31
+ constructor(initialState: State);
32
+ select<R>(projection: (s: State) => R): Observable<R>;
33
+ getLoadingFor<C extends keyof A>(action: C): Observable<boolean>;
34
+ dispatch<C extends keyof A>(action: C, ...payload: getPayloadFromActionType<A, C>): void;
35
+ private static noopEffect;
36
+ private static getOperator;
37
+ private swallowError;
38
+ }
@@ -0,0 +1,99 @@
1
+ import { BehaviorSubject, EMPTY, of, Subject } from 'rxjs';
2
+ import { getReducers } from '../reduce/reduce';
3
+ import { catchError, concatMap, filter, map, mergeMap, switchMap, tap, withLatestFrom } from 'rxjs/operators';
4
+ import { getEffects } from '../effect/effect';
5
+ export class Store {
6
+ constructor(initialState) {
7
+ this.initialState = initialState;
8
+ this.actions = new Map();
9
+ this._loading$ = new Subject();
10
+ this._store$ = new BehaviorSubject(
11
+ // we need this in order to decouple initial state between instances
12
+ JSON.parse(JSON.stringify(this.initialState)));
13
+ this.effects = getEffects(this);
14
+ this.reducers = getReducers(this);
15
+ const actions = [].concat(this.effects, this.reducers);
16
+ const actionsSet = new Set();
17
+ actions.forEach(({ action }) => actionsSet.add(action));
18
+ actionsSet.forEach((key) => {
19
+ this.actions.set(key, new Subject());
20
+ const effect = this.effects.find((e) => e.action === key);
21
+ const operator = Store.getOperator(effect?.strategy);
22
+ this.actions.get(key).pipe(withLatestFrom(this._store$), tap(([{ payload }]) => {
23
+ this._loading$.next({
24
+ payload: payload,
25
+ status: true,
26
+ code: key,
27
+ });
28
+ }), operator(([{ name, payload }]) => {
29
+ return this[name](...payload).pipe(tap((response) => {
30
+ this._loading$.next({
31
+ payload,
32
+ response,
33
+ status: false,
34
+ // here the action is done. The action is the only async call
35
+ // we can assume the loading is done as the effect is not async
36
+ code: key,
37
+ });
38
+ }),
39
+ // the above is
40
+ map((response) => {
41
+ // by convention reducer name must be
42
+ // on + Action
43
+ const reducerName = `on${(name[0]).toUpperCase()}${name.slice(1)}`;
44
+ // @ts-ignore
45
+ return this[reducerName](this._store$.getValue(), response);
46
+ }),
47
+ // error need to be swallowed here too otherwise the observable chain will be broken
48
+ // meaning that once an action goes into an error it cannot be dispatched again
49
+ catchError((error) => this.swallowError(key, error, payload)));
50
+ })).subscribe(this._store$);
51
+ });
52
+ }
53
+ get loading$() {
54
+ return this._loading$.asObservable();
55
+ }
56
+ get state$() {
57
+ return this._store$.asObservable();
58
+ }
59
+ select(projection) {
60
+ return this.state$.pipe(map(projection));
61
+ }
62
+ getLoadingFor(action) {
63
+ return this.loading$.pipe(filter(({ code }) => code === action), map(({ status }) => status));
64
+ }
65
+ dispatch(action, ...payload) {
66
+ if (!this.actions.has(action)) {
67
+ throw new Error(`Cannot find action ${String(action)}`);
68
+ }
69
+ const name = (typeof this[action] === 'function' ? action : 'noopEffect');
70
+ this.actions.get(action)?.next({ name, payload });
71
+ }
72
+ // eslint-disable-next-line @typescript-eslint/member-ordering
73
+ static noopEffect(payload) {
74
+ return of(payload);
75
+ }
76
+ // eslint-disable-next-line @typescript-eslint/member-ordering
77
+ static getOperator(strategyFn) {
78
+ if (strategyFn === 'mergeMap') {
79
+ return mergeMap;
80
+ }
81
+ else if (strategyFn === 'concatMap') {
82
+ return concatMap;
83
+ }
84
+ else {
85
+ return switchMap;
86
+ }
87
+ }
88
+ swallowError(key, error, payload) {
89
+ console.log(`Error handling action "${key}"`, error);
90
+ this._loading$.next({
91
+ payload,
92
+ error: error,
93
+ status: false,
94
+ code: key,
95
+ });
96
+ return EMPTY;
97
+ }
98
+ }
99
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/lib/store/store.ts"],"names":[],"mappings":"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","sourcesContent":["import { BehaviorSubject, EMPTY, Observable, of, Subject } from 'rxjs';\nimport { getReducers, Reducer } from '../reduce/reduce';\nimport { catchError, concatMap, filter, map, mergeMap, switchMap, tap, withLatestFrom } from 'rxjs/operators';\nimport { Effect, EffectStrategy, getEffects } from '../effect/effect';\nimport { Brand, Primitive } from 'utility-types';\n\nexport type getPayloadFromActionType<A, C extends keyof A> =\n A[C] extends Function ? A[C] extends () => any\n ? never[] : A[C] extends (...args: infer T) => any\n ? T : never[] : A[C][];\n\nexport type PureReducer<T extends Primitive> = Brand<T, 'reducer'>;\n\nexport type makeEffects<Actions> = {\n // Effects\n [k in keyof Actions]: Actions[k] extends PureReducer<Primitive>\n ? never\n : Actions[k]\n}\n\nexport type makeStore<State, Actions> =\n {\n [k in keyof makeEffects<Actions>]: makeEffects<Actions>[k]\n }\n // &\n // Actions\n &\n {\n // Reducers\n [k in keyof Actions as `on${Capitalize<string & k>}`]: Actions[k] extends (...args: any) => Observable<infer O>\n ? (state: State, payload: O) => State\n : Actions[k] extends PureReducer<infer O>\n ? (state?: State, payload?: O) => State\n : (state?: State) => State\n\n };\n\nexport interface LoadingState<A> {\n code: keyof A;\n payload?: any;\n response?: any;\n error?: any;\n status: boolean;\n}\n\nexport abstract class Store<State, A> {\n\n private readonly actions: Map<string, Subject<{ name: string, payload?: any }>> = new Map();\n\n readonly effects: Effect[];\n\n readonly reducers: Reducer[];\n\n\n private _loading$ = new Subject<LoadingState<A>>();\n\n public get loading$(): Observable<LoadingState<A>> {\n return this._loading$.asObservable();\n }\n\n protected readonly _store$: BehaviorSubject<State> = new BehaviorSubject<State>(\n // we need this in order to decouple initial state between instances\n JSON.parse(JSON.stringify(this.initialState))\n );\n\n public get state$(): Observable<State> {\n return this._store$.asObservable();\n }\n\n constructor(private initialState: State) {\n\n this.effects = getEffects(this);\n this.reducers = getReducers(this);\n\n const actions = [].concat(this.effects, this.reducers);\n\n const actionsSet = new Set<string>();\n\n actions.forEach(({action}) => actionsSet.add(action));\n\n actionsSet.forEach((key) => {\n\n this.actions.set(key, new Subject());\n\n const effect = this.effects.find((e) => e.action === key);\n\n const operator = Store.getOperator(effect?.strategy);\n\n this.actions.get(key).pipe(\n withLatestFrom(this._store$),\n tap(([{payload}]) => {\n this._loading$.next({\n payload: payload,\n status: true,\n code: key as keyof A,\n });\n }),\n operator(([{name, payload}]) => {\n\n return this[name](...payload).pipe(\n tap((response) => {\n this._loading$.next({\n payload,\n response,\n status: false,\n // here the action is done. The action is the only async call\n // we can assume the loading is done as the effect is not async\n code: key as keyof A,\n });\n }),\n // the above is\n map((response) => {\n // by convention reducer name must be\n // on + Action\n const reducerName = `on${(name[0]).toUpperCase()}${(name as string).slice(1)}`;\n\n // @ts-ignore\n return this[reducerName](this._store$.getValue(), response);\n }),\n // error need to be swallowed here too otherwise the observable chain will be broken\n // meaning that once an action goes into an error it cannot be dispatched again\n catchError((error) => this.swallowError(key, error, payload)),\n );\n }),\n // @ts-ignore\n ).subscribe(this._store$);\n });\n }\n\n select<R>(projection: (s: State) => R) {\n return this.state$.pipe(\n map(projection)\n );\n }\n\n getLoadingFor<C extends keyof A>(action: C): Observable<boolean> {\n return this.loading$.pipe(\n filter(({code}) => code === action),\n map(({status}) => status),\n );\n }\n\n dispatch<C extends keyof A>(\n action: C,\n ...payload: getPayloadFromActionType<A, C>\n ) {\n\n if (!this.actions.has(action as string)) {\n throw new Error(`Cannot find action ${String(action)}`);\n }\n\n const name: string = (typeof (this as unknown as A)[action] === 'function' ? action : 'noopEffect') as string;\n\n\n this.actions.get(action as string)?.next({name, payload});\n }\n\n // eslint-disable-next-line @typescript-eslint/member-ordering\n private static noopEffect(payload: any) {\n return of(payload);\n }\n\n // eslint-disable-next-line @typescript-eslint/member-ordering\n private static getOperator(strategyFn: EffectStrategy) {\n if (strategyFn === 'mergeMap') {\n return mergeMap;\n } else if (strategyFn === 'concatMap') {\n return concatMap;\n } else {\n return switchMap;\n }\n }\n\n private swallowError(key: string, error: Error, payload: any) {\n console.log(`Error handling action \"${key}\"`, error);\n\n this._loading$.next({\n payload,\n error: error,\n status: false,\n code: key as keyof A,\n });\n\n return EMPTY;\n }\n\n}\n"]}
@@ -0,0 +1 @@
1
+ export declare function capitalise(s: string): string;
@@ -0,0 +1,7 @@
1
+ export function capitalise(s) {
2
+ if (!s) {
3
+ return '';
4
+ }
5
+ return s[0].toUpperCase() + s.slice(1);
6
+ }
7
+ //# sourceMappingURL=capitalise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalise.js","sourceRoot":"","sources":["../../../src/lib/utilities/capitalise.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,IAAI,CAAC,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC;KAAE;IAEtB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC","sourcesContent":["export function capitalise(s: string) {\n if (!s) { return ''; }\n\n return s[0].toUpperCase() + s.slice(1);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { Class } from 'utility-types';
2
+ export declare function scanInstance<T extends object>(instance: T, cb: (proto: Class<T>, key: string) => void): void;
@@ -0,0 +1,19 @@
1
+ const builtInMethods = Object.keys(Object.getOwnPropertyDescriptors(Object.getPrototypeOf({})));
2
+ export function scanInstance(instance, cb) {
3
+ let proto = Object.getPrototypeOf(instance);
4
+ while (proto) {
5
+ const descriptors = Object.getOwnPropertyDescriptors(proto);
6
+ Object.keys(descriptors)
7
+ .filter((k) => {
8
+ return !builtInMethods.includes(k);
9
+ })
10
+ .forEach((key) => cb(proto, key));
11
+ try {
12
+ proto = Object.getPrototypeOf(proto);
13
+ }
14
+ catch (e) {
15
+ proto = null;
16
+ }
17
+ }
18
+ }
19
+ //# sourceMappingURL=scan-instance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan-instance.js","sourceRoot":"","sources":["../../../src/lib/utilities/scan-instance.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,yBAAyB,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAEhG,MAAM,UAAU,YAAY,CAAmB,QAAW,EAAE,EAA0C;IAEpG,IAAI,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;IAE5C,OAAO,KAAK,EAAE;QAEZ,MAAM,WAAW,GAAG,MAAM,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC;QAE5D,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;aACrB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YACZ,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC;aACD,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAEpC,IAAI;YACF,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;SACtC;QAAC,OAAO,CAAC,EAAE;YACV,KAAK,GAAG,IAAI,CAAC;SACd;KACF;AAEH,CAAC","sourcesContent":["import { Class } from 'utility-types';\n\nconst builtInMethods = Object.keys(Object.getOwnPropertyDescriptors(Object.getPrototypeOf({})));\n\nexport function scanInstance<T extends object>(instance: T, cb: (proto: Class<T>, key: string) => void) {\n\n let proto = Object.getPrototypeOf(instance);\n\n while (proto) {\n\n const descriptors = Object.getOwnPropertyDescriptors(proto);\n\n Object.keys(descriptors)\n .filter((k) => {\n return !builtInMethods.includes(k);\n })\n .forEach((key) => cb(proto, key));\n\n try {\n proto = Object.getPrototypeOf(proto);\n } catch (e) {\n proto = null;\n }\n }\n\n}\n"]}
package/package.json CHANGED
@@ -13,24 +13,28 @@
13
13
  "flux",
14
14
  "elm"
15
15
  ],
16
- "version": "0.2.10",
16
+ "main": "lib/index.js",
17
+ "typings": "lib/index.d.ts",
18
+ "module": "lib/index.js",
19
+ "directories": {
20
+ "lib": "lib"
21
+ },
22
+ "files": [
23
+ "lib"
24
+ ],
25
+ "version": "1.1.3",
17
26
  "dependencies": {
18
- "@microgamma/loggator": "^1.10.18",
19
27
  "reflect-metadata": "^0.1.13",
28
+ "tslib": "^2.5.0"
29
+ },
30
+ "devDependencies": {
31
+ "@microphi/test": "^1.1.0",
20
32
  "utility-types": "^3.10.0"
21
33
  },
22
- "schematics": "./schematics/collection.json",
23
- "main": "bundles/microphi-store.umd.js",
24
- "module": "fesm5/microphi-store.js",
25
- "es2015": "fesm2015/microphi-store.js",
26
- "esm5": "esm5/microphi-store.js",
27
- "esm2015": "esm2015/microphi-store.js",
28
- "fesm5": "fesm5/microphi-store.js",
29
- "fesm2015": "fesm2015/microphi-store.js",
30
- "typings": "microphi-store.d.ts",
31
- "metadata": "microphi-store.metadata.json",
32
- "sideEffects": false,
33
34
  "peerDependencies": {
34
- "tslib": "^1.10.0"
35
+ "rxjs": "^7.8.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsc -p tsconfig.lib.prod.json"
35
39
  }
36
40
  }