@figliolia/galena 2.3.5 → 3.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.
Files changed (106) hide show
  1. package/README.md +172 -476
  2. package/dist/Galena.cjs +102 -0
  3. package/dist/Galena.d.cts +80 -0
  4. package/dist/Galena.d.cts.map +1 -0
  5. package/dist/Galena.d.mts +80 -0
  6. package/dist/Galena.d.mts.map +1 -0
  7. package/dist/Galena.mjs +103 -0
  8. package/dist/Galena.mjs.map +1 -0
  9. package/dist/Logger.cjs +46 -0
  10. package/dist/Logger.d.cts +35 -0
  11. package/dist/Logger.d.cts.map +1 -0
  12. package/dist/Logger.d.mts +35 -0
  13. package/dist/Logger.d.mts.map +1 -0
  14. package/dist/Logger.mjs +48 -0
  15. package/dist/Logger.mjs.map +1 -0
  16. package/dist/Middleware.cjs +62 -0
  17. package/dist/Middleware.d.cts +65 -0
  18. package/dist/Middleware.d.cts.map +1 -0
  19. package/dist/Middleware.d.mts +65 -0
  20. package/dist/Middleware.d.mts.map +1 -0
  21. package/dist/Middleware.mjs +64 -0
  22. package/dist/Middleware.mjs.map +1 -0
  23. package/dist/Profiler.cjs +41 -0
  24. package/dist/Profiler.d.cts +31 -0
  25. package/dist/Profiler.d.cts.map +1 -0
  26. package/dist/Profiler.d.mts +31 -0
  27. package/dist/Profiler.d.mts.map +1 -0
  28. package/dist/Profiler.mjs +43 -0
  29. package/dist/Profiler.mjs.map +1 -0
  30. package/dist/State.cjs +147 -0
  31. package/dist/State.d.cts +114 -0
  32. package/dist/State.d.cts.map +1 -0
  33. package/dist/State.d.mts +114 -0
  34. package/dist/State.d.mts.map +1 -0
  35. package/dist/State.mjs +148 -0
  36. package/dist/State.mjs.map +1 -0
  37. package/dist/index.cjs +13 -0
  38. package/dist/index.d.cts +7 -0
  39. package/dist/index.d.mts +7 -0
  40. package/dist/index.mjs +6 -0
  41. package/dist/types.d.cts +16 -0
  42. package/dist/types.d.cts.map +1 -0
  43. package/dist/types.d.mts +16 -0
  44. package/dist/types.d.mts.map +1 -0
  45. package/media/Logging.png +0 -0
  46. package/media/Profiling.png +0 -0
  47. package/package.json +38 -59
  48. package/src/Galena.ts +120 -0
  49. package/src/{Middlewares/Logger.ts → Logger.ts} +15 -14
  50. package/src/Middleware.ts +62 -0
  51. package/src/Profiler.ts +53 -0
  52. package/src/State.ts +167 -0
  53. package/src/index.ts +6 -3
  54. package/src/types.ts +28 -0
  55. package/dist/cjs/Galena/Galena.js +0 -223
  56. package/dist/cjs/Galena/Guards.js +0 -40
  57. package/dist/cjs/Galena/Scheduler.js +0 -84
  58. package/dist/cjs/Galena/State.js +0 -314
  59. package/dist/cjs/Galena/index.js +0 -22
  60. package/dist/cjs/Galena/types.js +0 -9
  61. package/dist/cjs/Middleware/Middleware.js +0 -46
  62. package/dist/cjs/Middleware/index.js +0 -20
  63. package/dist/cjs/Middleware/types.js +0 -8
  64. package/dist/cjs/Middlewares/Logger.js +0 -51
  65. package/dist/cjs/Middlewares/Profiler.js +0 -38
  66. package/dist/cjs/Middlewares/index.js +0 -7
  67. package/dist/cjs/index.js +0 -19
  68. package/dist/cjs/package.json +0 -3
  69. package/dist/mjs/Galena/Galena.js +0 -218
  70. package/dist/mjs/Galena/Guards.js +0 -36
  71. package/dist/mjs/Galena/Scheduler.js +0 -79
  72. package/dist/mjs/Galena/State.js +0 -313
  73. package/dist/mjs/Galena/index.js +0 -3
  74. package/dist/mjs/Galena/types.js +0 -6
  75. package/dist/mjs/Middleware/Middleware.js +0 -42
  76. package/dist/mjs/Middleware/index.js +0 -2
  77. package/dist/mjs/Middleware/types.js +0 -5
  78. package/dist/mjs/Middlewares/Logger.js +0 -44
  79. package/dist/mjs/Middlewares/Profiler.js +0 -35
  80. package/dist/mjs/Middlewares/index.js +0 -2
  81. package/dist/mjs/index.js +0 -3
  82. package/dist/mjs/package.json +0 -4
  83. package/dist/types/Galena/Galena.d.ts +0 -160
  84. package/dist/types/Galena/Guards.d.ts +0 -29
  85. package/dist/types/Galena/Scheduler.d.ts +0 -51
  86. package/dist/types/Galena/State.d.ts +0 -235
  87. package/dist/types/Galena/index.d.ts +0 -3
  88. package/dist/types/Galena/types.d.ts +0 -13
  89. package/dist/types/Middleware/Middleware.d.ts +0 -43
  90. package/dist/types/Middleware/index.d.ts +0 -2
  91. package/dist/types/Middleware/types.d.ts +0 -4
  92. package/dist/types/Middlewares/Logger.d.ts +0 -27
  93. package/dist/types/Middlewares/Profiler.d.ts +0 -22
  94. package/dist/types/Middlewares/index.d.ts +0 -2
  95. package/dist/types/index.d.ts +0 -3
  96. package/src/Galena/Galena.ts +0 -252
  97. package/src/Galena/Guards.ts +0 -49
  98. package/src/Galena/Scheduler.ts +0 -85
  99. package/src/Galena/State.ts +0 -344
  100. package/src/Galena/index.ts +0 -3
  101. package/src/Galena/types.ts +0 -18
  102. package/src/Middleware/Middleware.ts +0 -45
  103. package/src/Middleware/index.ts +0 -2
  104. package/src/Middleware/types.ts +0 -4
  105. package/src/Middlewares/Profiler.ts +0 -41
  106. package/src/Middlewares/index.ts +0 -2
@@ -0,0 +1,102 @@
1
+ let _figliolia_event_emitter = require("@figliolia/event-emitter");
2
+ //#region src/Galena.ts
3
+ /**
4
+ * Galena
5
+ *
6
+ * Galena is designed to house one or more units of `State`
7
+ * and exist as a pseudo global application state.
8
+ *
9
+ * By design, each of its `State` units have isolated reactivity
10
+ * that prevents entire state trees from updating when a single
11
+ * unit changes.
12
+ *
13
+ * This is dissimilar to redux-like models where downstream reconciliations
14
+ * will propagate everwhere a given store is read from. In galena, downstream
15
+ * reconciliations occur only for consumers of the slice of state that
16
+ * changed - making it safer to use with more frequent state changes.
17
+ *
18
+ * ```typescript
19
+ * import { Galena } from "@figliolia/galena";
20
+ *
21
+ * const AppState = new Galena({
22
+ * // your reactive instances
23
+ * }, ...middleware);
24
+ *
25
+ * // to retreive and work with an individual unit
26
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
27
+ *
28
+ * // to run a callback anytime a unit of state changes
29
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
30
+ * // do something with the `State` instance that updated
31
+ * });
32
+ * ```
33
+ */
34
+ var Galena = class {
35
+ Emitter = new _figliolia_event_emitter.EventEmitter();
36
+ constructor(state, ...middleware) {
37
+ this.state = state;
38
+ this.registerMiddleware(...middleware);
39
+ }
40
+ get(key) {
41
+ return this.state[key];
42
+ }
43
+ subscribe = (subscriber) => {
44
+ const ID = this.Emitter.on("change", subscriber);
45
+ const unsubscribers = [];
46
+ for (const key in this.state) {
47
+ const instance = this.state[key];
48
+ if (!instance) continue;
49
+ unsubscribers.push(instance.subscribe(() => this.emit({
50
+ state: this.state,
51
+ updated: instance
52
+ })));
53
+ }
54
+ return () => {
55
+ this.Emitter.off("change", ID);
56
+ while (unsubscribers.length) unsubscribers.pop?.()?.();
57
+ };
58
+ };
59
+ registerMiddleware(...middlewares) {
60
+ for (const key in this.state) this.state[key]?.registerMiddleware?.(...middlewares);
61
+ }
62
+ emit(event) {
63
+ this.Emitter.emit("change", event);
64
+ }
65
+ };
66
+ /**
67
+ * Create Galena
68
+ *
69
+ * Galena is designed to house one or more units of `State`
70
+ * and exist as a pseudo global application state.
71
+ *
72
+ * By design, each of its `State` units have isolated reactivity
73
+ * that prevents entire state trees from updating when a single
74
+ * unit changes.
75
+ *
76
+ * This is dissimilar to redux-like models where downstream reconciliations
77
+ * will propagate everwhere a given store is read from. In galena, downstream
78
+ * reconciliations occur only for consumers of the slice of state that
79
+ * changed - making it safer to use with more frequent state changes.
80
+ *
81
+ * ```typescript
82
+ * import { createGalena } from "@figliolia/galena";
83
+ *
84
+ * const AppState = createGalena({
85
+ * // your reactive instances
86
+ * }, ...middleware);
87
+ *
88
+ * // to retreive and work with an individual unit
89
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
90
+ *
91
+ * // to run a callback anytime a unit of state changes
92
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
93
+ * // do something with the `State` instance that updated
94
+ * });
95
+ * ```
96
+ */
97
+ const createGalena = (...args) => {
98
+ return new Galena(...args);
99
+ };
100
+ //#endregion
101
+ exports.Galena = Galena;
102
+ exports.createGalena = createGalena;
@@ -0,0 +1,80 @@
1
+ import { AppSubscriber, StateTypes } from "./types.cjs";
2
+ import { State } from "./State.cjs";
3
+ import { Middleware } from "./Middleware.cjs";
4
+
5
+ //#region src/Galena.d.ts
6
+ /**
7
+ * Galena
8
+ *
9
+ * Galena is designed to house one or more units of `State`
10
+ * and exist as a pseudo global application state.
11
+ *
12
+ * By design, each of its `State` units have isolated reactivity
13
+ * that prevents entire state trees from updating when a single
14
+ * unit changes.
15
+ *
16
+ * This is dissimilar to redux-like models where downstream reconciliations
17
+ * will propagate everwhere a given store is read from. In galena, downstream
18
+ * reconciliations occur only for consumers of the slice of state that
19
+ * changed - making it safer to use with more frequent state changes.
20
+ *
21
+ * ```typescript
22
+ * import { Galena } from "@figliolia/galena";
23
+ *
24
+ * const AppState = new Galena({
25
+ * // your reactive instances
26
+ * }, ...middleware);
27
+ *
28
+ * // to retreive and work with an individual unit
29
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
30
+ *
31
+ * // to run a callback anytime a unit of state changes
32
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
33
+ * // do something with the `State` instance that updated
34
+ * });
35
+ * ```
36
+ */
37
+ declare class Galena<T extends Record<string, State<any>>> {
38
+ readonly state: T;
39
+ private Emitter;
40
+ constructor(state: T, ...middleware: Middleware<StateTypes<T>>[]);
41
+ get<K extends Extract<keyof T, string>>(key: K): T[K];
42
+ subscribe: (subscriber: AppSubscriber<T>) => () => void;
43
+ registerMiddleware(...middlewares: Middleware<StateTypes<T>>[]): void;
44
+ private emit;
45
+ }
46
+ /**
47
+ * Create Galena
48
+ *
49
+ * Galena is designed to house one or more units of `State`
50
+ * and exist as a pseudo global application state.
51
+ *
52
+ * By design, each of its `State` units have isolated reactivity
53
+ * that prevents entire state trees from updating when a single
54
+ * unit changes.
55
+ *
56
+ * This is dissimilar to redux-like models where downstream reconciliations
57
+ * will propagate everwhere a given store is read from. In galena, downstream
58
+ * reconciliations occur only for consumers of the slice of state that
59
+ * changed - making it safer to use with more frequent state changes.
60
+ *
61
+ * ```typescript
62
+ * import { createGalena } from "@figliolia/galena";
63
+ *
64
+ * const AppState = createGalena({
65
+ * // your reactive instances
66
+ * }, ...middleware);
67
+ *
68
+ * // to retreive and work with an individual unit
69
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
70
+ *
71
+ * // to run a callback anytime a unit of state changes
72
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
73
+ * // do something with the `State` instance that updated
74
+ * });
75
+ * ```
76
+ */
77
+ declare const createGalena: <T extends Record<string, State<any>>>(...args: ConstructorParameters<typeof Galena<T>>) => Galena<T>;
78
+ //#endregion
79
+ export { Galena, createGalena };
80
+ //# sourceMappingURL=Galena.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Galena.d.cts","names":[],"sources":["../src/Galena.ts"],"mappings":";;;;;;;AAoCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,MAAA,WAAiB,MAAA,SAAe,KAAA;EAAA,SAGzB,KAAA,EAAO,CAAA;EAAA,QAFjB,OAAA;cAEU,KAAA,EAAO,CAAA,KACpB,UAAA,EAAY,UAAA,CAAW,UAAA,CAAW,CAAA;EAKhC,GAAA,WAAc,OAAA,OAAc,CAAA,UAAA,CAAY,GAAA,EAAK,CAAA,GAAC,CAAA,CAAA,CAAA;EAI9C,SAAA,GAAa,UAAA,EAAY,aAAA,CAAc,CAAA;EAsBvC,kBAAA,CAAA,GAAsB,WAAA,EAAa,UAAA,CAAW,UAAA,CAAW,CAAA;EAAA,QAMxD,IAAA;AAAA;;;;;;;;;;;;;;;;;;AAsCV;;;;;;;;;;;;;;cAAa,YAAA,aAA0B,MAAA,SAAe,KAAA,WACjD,IAAA,EAAM,qBAAA,QAA6B,MAAA,CAAO,CAAA,OAAG,MAAA,CAAA,CAAA"}
@@ -0,0 +1,80 @@
1
+ import { AppSubscriber, StateTypes } from "./types.mjs";
2
+ import { State } from "./State.mjs";
3
+ import { Middleware } from "./Middleware.mjs";
4
+
5
+ //#region src/Galena.d.ts
6
+ /**
7
+ * Galena
8
+ *
9
+ * Galena is designed to house one or more units of `State`
10
+ * and exist as a pseudo global application state.
11
+ *
12
+ * By design, each of its `State` units have isolated reactivity
13
+ * that prevents entire state trees from updating when a single
14
+ * unit changes.
15
+ *
16
+ * This is dissimilar to redux-like models where downstream reconciliations
17
+ * will propagate everwhere a given store is read from. In galena, downstream
18
+ * reconciliations occur only for consumers of the slice of state that
19
+ * changed - making it safer to use with more frequent state changes.
20
+ *
21
+ * ```typescript
22
+ * import { Galena } from "@figliolia/galena";
23
+ *
24
+ * const AppState = new Galena({
25
+ * // your reactive instances
26
+ * }, ...middleware);
27
+ *
28
+ * // to retreive and work with an individual unit
29
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
30
+ *
31
+ * // to run a callback anytime a unit of state changes
32
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
33
+ * // do something with the `State` instance that updated
34
+ * });
35
+ * ```
36
+ */
37
+ declare class Galena<T extends Record<string, State<any>>> {
38
+ readonly state: T;
39
+ private Emitter;
40
+ constructor(state: T, ...middleware: Middleware<StateTypes<T>>[]);
41
+ get<K extends Extract<keyof T, string>>(key: K): T[K];
42
+ subscribe: (subscriber: AppSubscriber<T>) => () => void;
43
+ registerMiddleware(...middlewares: Middleware<StateTypes<T>>[]): void;
44
+ private emit;
45
+ }
46
+ /**
47
+ * Create Galena
48
+ *
49
+ * Galena is designed to house one or more units of `State`
50
+ * and exist as a pseudo global application state.
51
+ *
52
+ * By design, each of its `State` units have isolated reactivity
53
+ * that prevents entire state trees from updating when a single
54
+ * unit changes.
55
+ *
56
+ * This is dissimilar to redux-like models where downstream reconciliations
57
+ * will propagate everwhere a given store is read from. In galena, downstream
58
+ * reconciliations occur only for consumers of the slice of state that
59
+ * changed - making it safer to use with more frequent state changes.
60
+ *
61
+ * ```typescript
62
+ * import { createGalena } from "@figliolia/galena";
63
+ *
64
+ * const AppState = createGalena({
65
+ * // your reactive instances
66
+ * }, ...middleware);
67
+ *
68
+ * // to retreive and work with an individual unit
69
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
70
+ *
71
+ * // to run a callback anytime a unit of state changes
72
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
73
+ * // do something with the `State` instance that updated
74
+ * });
75
+ * ```
76
+ */
77
+ declare const createGalena: <T extends Record<string, State<any>>>(...args: ConstructorParameters<typeof Galena<T>>) => Galena<T>;
78
+ //#endregion
79
+ export { Galena, createGalena };
80
+ //# sourceMappingURL=Galena.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Galena.d.mts","names":[],"sources":["../src/Galena.ts"],"mappings":";;;;;;;AAoCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,MAAA,WAAiB,MAAA,SAAe,KAAA;EAAA,SAGzB,KAAA,EAAO,CAAA;EAAA,QAFjB,OAAA;cAEU,KAAA,EAAO,CAAA,KACpB,UAAA,EAAY,UAAA,CAAW,UAAA,CAAW,CAAA;EAKhC,GAAA,WAAc,OAAA,OAAc,CAAA,UAAA,CAAY,GAAA,EAAK,CAAA,GAAC,CAAA,CAAA,CAAA;EAI9C,SAAA,GAAa,UAAA,EAAY,aAAA,CAAc,CAAA;EAsBvC,kBAAA,CAAA,GAAsB,WAAA,EAAa,UAAA,CAAW,UAAA,CAAW,CAAA;EAAA,QAMxD,IAAA;AAAA;;;;;;;;;;;;;;;;;;AAsCV;;;;;;;;;;;;;;cAAa,YAAA,aAA0B,MAAA,SAAe,KAAA,WACjD,IAAA,EAAM,qBAAA,QAA6B,MAAA,CAAO,CAAA,OAAG,MAAA,CAAA,CAAA"}
@@ -0,0 +1,103 @@
1
+ import { EventEmitter } from "@figliolia/event-emitter";
2
+ //#region src/Galena.ts
3
+ /**
4
+ * Galena
5
+ *
6
+ * Galena is designed to house one or more units of `State`
7
+ * and exist as a pseudo global application state.
8
+ *
9
+ * By design, each of its `State` units have isolated reactivity
10
+ * that prevents entire state trees from updating when a single
11
+ * unit changes.
12
+ *
13
+ * This is dissimilar to redux-like models where downstream reconciliations
14
+ * will propagate everwhere a given store is read from. In galena, downstream
15
+ * reconciliations occur only for consumers of the slice of state that
16
+ * changed - making it safer to use with more frequent state changes.
17
+ *
18
+ * ```typescript
19
+ * import { Galena } from "@figliolia/galena";
20
+ *
21
+ * const AppState = new Galena({
22
+ * // your reactive instances
23
+ * }, ...middleware);
24
+ *
25
+ * // to retreive and work with an individual unit
26
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
27
+ *
28
+ * // to run a callback anytime a unit of state changes
29
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
30
+ * // do something with the `State` instance that updated
31
+ * });
32
+ * ```
33
+ */
34
+ var Galena = class {
35
+ Emitter = new EventEmitter();
36
+ constructor(state, ...middleware) {
37
+ this.state = state;
38
+ this.registerMiddleware(...middleware);
39
+ }
40
+ get(key) {
41
+ return this.state[key];
42
+ }
43
+ subscribe = (subscriber) => {
44
+ const ID = this.Emitter.on("change", subscriber);
45
+ const unsubscribers = [];
46
+ for (const key in this.state) {
47
+ const instance = this.state[key];
48
+ if (!instance) continue;
49
+ unsubscribers.push(instance.subscribe(() => this.emit({
50
+ state: this.state,
51
+ updated: instance
52
+ })));
53
+ }
54
+ return () => {
55
+ this.Emitter.off("change", ID);
56
+ while (unsubscribers.length) unsubscribers.pop?.()?.();
57
+ };
58
+ };
59
+ registerMiddleware(...middlewares) {
60
+ for (const key in this.state) this.state[key]?.registerMiddleware?.(...middlewares);
61
+ }
62
+ emit(event) {
63
+ this.Emitter.emit("change", event);
64
+ }
65
+ };
66
+ /**
67
+ * Create Galena
68
+ *
69
+ * Galena is designed to house one or more units of `State`
70
+ * and exist as a pseudo global application state.
71
+ *
72
+ * By design, each of its `State` units have isolated reactivity
73
+ * that prevents entire state trees from updating when a single
74
+ * unit changes.
75
+ *
76
+ * This is dissimilar to redux-like models where downstream reconciliations
77
+ * will propagate everwhere a given store is read from. In galena, downstream
78
+ * reconciliations occur only for consumers of the slice of state that
79
+ * changed - making it safer to use with more frequent state changes.
80
+ *
81
+ * ```typescript
82
+ * import { createGalena } from "@figliolia/galena";
83
+ *
84
+ * const AppState = createGalena({
85
+ * // your reactive instances
86
+ * }, ...middleware);
87
+ *
88
+ * // to retreive and work with an individual unit
89
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
90
+ *
91
+ * // to run a callback anytime a unit of state changes
92
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
93
+ * // do something with the `State` instance that updated
94
+ * });
95
+ * ```
96
+ */
97
+ const createGalena = (...args) => {
98
+ return new Galena(...args);
99
+ };
100
+ //#endregion
101
+ export { Galena, createGalena };
102
+
103
+ //# sourceMappingURL=Galena.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Galena.mjs","names":[],"sources":["../src/Galena.ts"],"sourcesContent":["import { EventEmitter } from \"@figliolia/event-emitter\";\nimport type { Middleware } from \"./Middleware\";\nimport type { State } from \"./State\";\nimport type { AppSubscriber, GalenaSnapshot, StateTypes } from \"./types\";\n\n/**\n * Galena\n *\n * Galena is designed to house one or more units of `State`\n * and exist as a pseudo global application state.\n *\n * By design, each of its `State` units have isolated reactivity\n * that prevents entire state trees from updating when a single\n * unit changes.\n *\n * This is dissimilar to redux-like models where downstream reconciliations\n * will propagate everwhere a given store is read from. In galena, downstream\n * reconciliations occur only for consumers of the slice of state that\n * changed - making it safer to use with more frequent state changes.\n *\n * ```typescript\n * import { Galena } from \"@figliolia/galena\";\n *\n * const AppState = new Galena({\n * // your reactive instances\n * }, ...middleware);\n *\n * // to retreive and work with an individual unit\n * const myUnit = AppState.get(\"<key>\"); // Returns State<T>\n *\n * // to run a callback anytime a unit of state changes\n * const unsubscribe = AppState.subscribe(({ updated }) => {\n * // do something with the `State` instance that updated\n * });\n * ```\n */\nexport class Galena<T extends Record<string, State<any>>> {\n private Emitter = new EventEmitter<{ change: GalenaSnapshot<T> }>();\n constructor(\n public readonly state: T,\n ...middleware: Middleware<StateTypes<T>>[]\n ) {\n this.registerMiddleware(...middleware);\n }\n\n public get<K extends Extract<keyof T, string>>(key: K) {\n return this.state[key];\n }\n\n public subscribe = (subscriber: AppSubscriber<T>) => {\n const ID = this.Emitter.on(\"change\", subscriber);\n const unsubscribers: (() => void)[] = [];\n for (const key in this.state) {\n const instance = this.state[key];\n if (!instance) {\n continue;\n }\n unsubscribers.push(\n instance.subscribe(() =>\n this.emit({ state: this.state, updated: instance }),\n ),\n );\n }\n return () => {\n this.Emitter.off(\"change\", ID);\n while (unsubscribers.length) {\n unsubscribers.pop?.()?.();\n }\n };\n };\n\n public registerMiddleware(...middlewares: Middleware<StateTypes<T>>[]) {\n for (const key in this.state) {\n this.state[key]?.registerMiddleware?.(...middlewares);\n }\n }\n\n private emit<K extends Extract<keyof T, string>>(\n event: GalenaSnapshot<T, K>,\n ) {\n this.Emitter.emit(\"change\", event);\n }\n}\n\n/**\n * Create Galena\n *\n * Galena is designed to house one or more units of `State`\n * and exist as a pseudo global application state.\n *\n * By design, each of its `State` units have isolated reactivity\n * that prevents entire state trees from updating when a single\n * unit changes.\n *\n * This is dissimilar to redux-like models where downstream reconciliations\n * will propagate everwhere a given store is read from. In galena, downstream\n * reconciliations occur only for consumers of the slice of state that\n * changed - making it safer to use with more frequent state changes.\n *\n * ```typescript\n * import { createGalena } from \"@figliolia/galena\";\n *\n * const AppState = createGalena({\n * // your reactive instances\n * }, ...middleware);\n *\n * // to retreive and work with an individual unit\n * const myUnit = AppState.get(\"<key>\"); // Returns State<T>\n *\n * // to run a callback anytime a unit of state changes\n * const unsubscribe = AppState.subscribe(({ updated }) => {\n * // do something with the `State` instance that updated\n * });\n * ```\n */\nexport const createGalena = <T extends Record<string, State<any>>>(\n ...args: ConstructorParameters<typeof Galena<T>>\n) => {\n return new Galena(...args);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,IAAa,SAAb,MAA0D;CACxD,UAAkB,IAAI,cAA6C;CACnE,YACE,OACA,GAAG,YACH;AAFgB,OAAA,QAAA;AAGhB,OAAK,mBAAmB,GAAG,WAAW;;CAGxC,IAA+C,KAAQ;AACrD,SAAO,KAAK,MAAM;;CAGpB,aAAoB,eAAiC;EACnD,MAAM,KAAK,KAAK,QAAQ,GAAG,UAAU,WAAW;EAChD,MAAM,gBAAgC,EAAE;AACxC,OAAK,MAAM,OAAO,KAAK,OAAO;GAC5B,MAAM,WAAW,KAAK,MAAM;AAC5B,OAAI,CAAC,SACH;AAEF,iBAAc,KACZ,SAAS,gBACP,KAAK,KAAK;IAAE,OAAO,KAAK;IAAO,SAAS;IAAU,CAAC,CACpD,CACF;;AAEH,eAAa;AACX,QAAK,QAAQ,IAAI,UAAU,GAAG;AAC9B,UAAO,cAAc,OACnB,eAAc,OAAO,IAAI;;;CAK/B,mBAA0B,GAAG,aAA0C;AACrE,OAAK,MAAM,OAAO,KAAK,MACrB,MAAK,MAAM,MAAM,qBAAqB,GAAG,YAAY;;CAIzD,KACE,OACA;AACA,OAAK,QAAQ,KAAK,UAAU,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCtC,MAAa,gBACX,GAAG,SACA;AACH,QAAO,IAAI,OAAO,GAAG,KAAK"}
@@ -0,0 +1,46 @@
1
+ const require_Middleware = require("./Middleware.cjs");
2
+ //#region src/Logger.ts
3
+ /**
4
+ * Logger
5
+ *
6
+ * A middleware for Redux-style logging! Each state transition
7
+ * will log to the console the `State` instance that changed
8
+ * along with a before and after snapshot of the current state:
9
+ *
10
+ * ```typescript
11
+ * const AppState = new Galena({}, new Logger());
12
+ * // or
13
+ * AppState.registerMiddlerware(new Logger());
14
+ * // or
15
+ * const MyState = new State(4, new Logger());
16
+ * // or
17
+ * MyState.registerMiddleware(new Logger());
18
+ * ```
19
+ */
20
+ var Logger = class extends require_Middleware.Middleware {
21
+ previousState = null;
22
+ onBeforeUpdate(state) {
23
+ this.previousState = state.getSnapshot();
24
+ }
25
+ onUpdate(state) {
26
+ console.log("%cMutation:", "color: rgb(187, 186, 186); font-weight: bold", "@", this.time);
27
+ console.log(" %cPrevious State", "color: #26ad65; font-weight: bold", this.previousState);
28
+ console.log(" %cNext State ", "color: rgb(17, 118, 249); font-weight: bold", state.getSnapshot());
29
+ }
30
+ /**
31
+ * Time
32
+ *
33
+ * Returns the time in which a given state transition completed
34
+ */
35
+ get time() {
36
+ const date = /* @__PURE__ */ new Date();
37
+ const mHours = date.getHours();
38
+ const hours = mHours > 12 ? mHours - 12 : mHours;
39
+ const mins = date.getMinutes();
40
+ const minutes = mins.toString().length === 1 ? `0${mins}` : mins;
41
+ const secs = date.getSeconds();
42
+ return `${hours}:${minutes}:${secs.toString().length === 1 ? `0${secs}` : secs}:${date.getMilliseconds()}`;
43
+ }
44
+ };
45
+ //#endregion
46
+ exports.Logger = Logger;
@@ -0,0 +1,35 @@
1
+ import { State } from "./State.cjs";
2
+ import { Middleware } from "./Middleware.cjs";
3
+
4
+ //#region src/Logger.d.ts
5
+ /**
6
+ * Logger
7
+ *
8
+ * A middleware for Redux-style logging! Each state transition
9
+ * will log to the console the `State` instance that changed
10
+ * along with a before and after snapshot of the current state:
11
+ *
12
+ * ```typescript
13
+ * const AppState = new Galena({}, new Logger());
14
+ * // or
15
+ * AppState.registerMiddlerware(new Logger());
16
+ * // or
17
+ * const MyState = new State(4, new Logger());
18
+ * // or
19
+ * MyState.registerMiddleware(new Logger());
20
+ * ```
21
+ */
22
+ declare class Logger<T = any> extends Middleware {
23
+ private previousState;
24
+ onBeforeUpdate(state: State<T>): void;
25
+ onUpdate(state: State<T>): void;
26
+ /**
27
+ * Time
28
+ *
29
+ * Returns the time in which a given state transition completed
30
+ */
31
+ private get time();
32
+ }
33
+ //#endregion
34
+ export { Logger };
35
+ //# sourceMappingURL=Logger.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.d.cts","names":[],"sources":["../src/Logger.ts"],"mappings":";;;;;;AAoBA;;;;;;;;;;;;;;;cAAa,MAAA,kBAAwB,UAAA;EAAA,QAC3B,aAAA;EAEC,cAAA,CAAe,KAAA,EAAO,KAAA,CAAM,CAAA;EAI5B,QAAA,CAAS,KAAA,EAAO,KAAA,CAAM,CAAA;EAAA;;;;;EAAA,YAwBnB,IAAA,CAAA;AAAA"}
@@ -0,0 +1,35 @@
1
+ import { State } from "./State.mjs";
2
+ import { Middleware } from "./Middleware.mjs";
3
+
4
+ //#region src/Logger.d.ts
5
+ /**
6
+ * Logger
7
+ *
8
+ * A middleware for Redux-style logging! Each state transition
9
+ * will log to the console the `State` instance that changed
10
+ * along with a before and after snapshot of the current state:
11
+ *
12
+ * ```typescript
13
+ * const AppState = new Galena({}, new Logger());
14
+ * // or
15
+ * AppState.registerMiddlerware(new Logger());
16
+ * // or
17
+ * const MyState = new State(4, new Logger());
18
+ * // or
19
+ * MyState.registerMiddleware(new Logger());
20
+ * ```
21
+ */
22
+ declare class Logger<T = any> extends Middleware {
23
+ private previousState;
24
+ onBeforeUpdate(state: State<T>): void;
25
+ onUpdate(state: State<T>): void;
26
+ /**
27
+ * Time
28
+ *
29
+ * Returns the time in which a given state transition completed
30
+ */
31
+ private get time();
32
+ }
33
+ //#endregion
34
+ export { Logger };
35
+ //# sourceMappingURL=Logger.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.d.mts","names":[],"sources":["../src/Logger.ts"],"mappings":";;;;;;AAoBA;;;;;;;;;;;;;;;cAAa,MAAA,kBAAwB,UAAA;EAAA,QAC3B,aAAA;EAEC,cAAA,CAAe,KAAA,EAAO,KAAA,CAAM,CAAA;EAI5B,QAAA,CAAS,KAAA,EAAO,KAAA,CAAM,CAAA;EAAA;;;;;EAAA,YAwBnB,IAAA,CAAA;AAAA"}
@@ -0,0 +1,48 @@
1
+ import { Middleware } from "./Middleware.mjs";
2
+ //#region src/Logger.ts
3
+ /**
4
+ * Logger
5
+ *
6
+ * A middleware for Redux-style logging! Each state transition
7
+ * will log to the console the `State` instance that changed
8
+ * along with a before and after snapshot of the current state:
9
+ *
10
+ * ```typescript
11
+ * const AppState = new Galena({}, new Logger());
12
+ * // or
13
+ * AppState.registerMiddlerware(new Logger());
14
+ * // or
15
+ * const MyState = new State(4, new Logger());
16
+ * // or
17
+ * MyState.registerMiddleware(new Logger());
18
+ * ```
19
+ */
20
+ var Logger = class extends Middleware {
21
+ previousState = null;
22
+ onBeforeUpdate(state) {
23
+ this.previousState = state.getSnapshot();
24
+ }
25
+ onUpdate(state) {
26
+ console.log("%cMutation:", "color: rgb(187, 186, 186); font-weight: bold", "@", this.time);
27
+ console.log(" %cPrevious State", "color: #26ad65; font-weight: bold", this.previousState);
28
+ console.log(" %cNext State ", "color: rgb(17, 118, 249); font-weight: bold", state.getSnapshot());
29
+ }
30
+ /**
31
+ * Time
32
+ *
33
+ * Returns the time in which a given state transition completed
34
+ */
35
+ get time() {
36
+ const date = /* @__PURE__ */ new Date();
37
+ const mHours = date.getHours();
38
+ const hours = mHours > 12 ? mHours - 12 : mHours;
39
+ const mins = date.getMinutes();
40
+ const minutes = mins.toString().length === 1 ? `0${mins}` : mins;
41
+ const secs = date.getSeconds();
42
+ return `${hours}:${minutes}:${secs.toString().length === 1 ? `0${secs}` : secs}:${date.getMilliseconds()}`;
43
+ }
44
+ };
45
+ //#endregion
46
+ export { Logger };
47
+
48
+ //# sourceMappingURL=Logger.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.mjs","names":[],"sources":["../src/Logger.ts"],"sourcesContent":["import { Middleware } from \"./Middleware\";\nimport type { State } from \"./State\";\n\n/**\n * Logger\n *\n * A middleware for Redux-style logging! Each state transition\n * will log to the console the `State` instance that changed\n * along with a before and after snapshot of the current state:\n *\n * ```typescript\n * const AppState = new Galena({}, new Logger());\n * // or\n * AppState.registerMiddlerware(new Logger());\n * // or\n * const MyState = new State(4, new Logger());\n * // or\n * MyState.registerMiddleware(new Logger());\n * ```\n */\nexport class Logger<T = any> extends Middleware {\n private previousState: T | null = null;\n\n override onBeforeUpdate(state: State<T>) {\n this.previousState = state.getSnapshot();\n }\n\n override onUpdate(state: State<T>) {\n console.log(\n \"%cMutation:\",\n \"color: rgb(187, 186, 186); font-weight: bold\",\n \"@\",\n this.time,\n );\n console.log(\n \" %cPrevious State\",\n \"color: #26ad65; font-weight: bold\",\n this.previousState,\n );\n console.log(\n \" %cNext State \",\n \"color: rgb(17, 118, 249); font-weight: bold\",\n state.getSnapshot(),\n );\n }\n\n /**\n * Time\n *\n * Returns the time in which a given state transition completed\n */\n private get time() {\n const date = new Date();\n const mHours = date.getHours();\n const hours = mHours > 12 ? mHours - 12 : mHours;\n const mins = date.getMinutes();\n const minutes = mins.toString().length === 1 ? `0${mins}` : mins;\n const secs = date.getSeconds();\n const seconds = secs.toString().length === 1 ? `0${secs}` : secs;\n const milliseconds = date.getMilliseconds();\n return `${hours}:${minutes}:${seconds}:${milliseconds}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoBA,IAAa,SAAb,cAAqC,WAAW;CAC9C,gBAAkC;CAElC,eAAwB,OAAiB;AACvC,OAAK,gBAAgB,MAAM,aAAa;;CAG1C,SAAkB,OAAiB;AACjC,UAAQ,IACN,eACA,gDACA,KACA,KAAK,KACN;AACD,UAAQ,IACN,uBACA,qCACA,KAAK,cACN;AACD,UAAQ,IACN,uBACA,+CACA,MAAM,aAAa,CACpB;;;;;;;CAQH,IAAY,OAAO;EACjB,MAAM,uBAAO,IAAI,MAAM;EACvB,MAAM,SAAS,KAAK,UAAU;EAC9B,MAAM,QAAQ,SAAS,KAAK,SAAS,KAAK;EAC1C,MAAM,OAAO,KAAK,YAAY;EAC9B,MAAM,UAAU,KAAK,UAAU,CAAC,WAAW,IAAI,IAAI,SAAS;EAC5D,MAAM,OAAO,KAAK,YAAY;AAG9B,SAAO,GAAG,MAAM,GAAG,QAAQ,GAFX,KAAK,UAAU,CAAC,WAAW,IAAI,IAAI,SAAS,KAEtB,GADjB,KAAK,iBAAiB"}
@@ -0,0 +1,62 @@
1
+ //#region src/Middleware.ts
2
+ /**
3
+ * Middleware
4
+ *
5
+ * Galena's middleware API is designed to provide hooks
6
+ * for state changes that you can tap into to run your
7
+ * own logic.
8
+ *
9
+ * Middleware is great for logging, analytics, and profiling:
10
+ *
11
+ * ```typescript
12
+ * export class Profiler<T = any> extends Middleware<T> {
13
+ * private previousState: T | null = null;
14
+ * private startTime: null | number = null;
15
+ * constructor(public readonly threshold: number = 16) {
16
+ * super();
17
+ * }
18
+ *
19
+ * public override onBeforeUpdate(state: State<T>) {
20
+ * this.startTime = performance.now();
21
+ * this.previousState = state.getSnapshot();
22
+ * }
23
+ *
24
+ * public override onUpdate(state: T) {
25
+ * const diff = performance.now() - this.startTime;
26
+ * if(diff >= this.threshold) {
27
+ * console.warn(`A slow state transition was detected when transitioning the following piece of state`);
28
+ * console.log('Previous state', this.previousState);
29
+ * console.log('Current state', state.getSnapshot());
30
+ * }
31
+ * }
32
+ * }
33
+ * ```
34
+ *
35
+ * To register your middleware, simply add it when constructing
36
+ * a `State` or `Galena` instance.
37
+ *
38
+ * ```typescript
39
+ * import { State } from "@figliolia/galena";
40
+ * import { Profiler } from './myProfiler';
41
+ *
42
+ * const myState = new State(5, new Profiler());
43
+ * ```
44
+ */
45
+ var Middleware = class {
46
+ /**
47
+ * On Before Update
48
+ *
49
+ * Executes prior to a `State` instance being updated.
50
+ * Receives the state prior to its update as a parameter
51
+ */
52
+ onBeforeUpdate(_state) {}
53
+ /**
54
+ * On Update
55
+ *
56
+ * Executes after a `State` instance has been update.
57
+ * Receives the most recent state as a parameter
58
+ */
59
+ onUpdate(_state) {}
60
+ };
61
+ //#endregion
62
+ exports.Middleware = Middleware;