@figliolia/galena 3.0.2 → 4.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 (47) hide show
  1. package/README.md +42 -54
  2. package/dist/API.cjs +9 -0
  3. package/dist/API.d.cts +13 -0
  4. package/dist/API.d.cts.map +1 -0
  5. package/dist/API.d.mts +13 -0
  6. package/dist/API.d.mts.map +1 -0
  7. package/dist/API.mjs +11 -0
  8. package/dist/API.mjs.map +1 -0
  9. package/dist/Galena.cjs +80 -22
  10. package/dist/Galena.d.cts +69 -22
  11. package/dist/Galena.d.cts.map +1 -1
  12. package/dist/Galena.d.mts +69 -22
  13. package/dist/Galena.d.mts.map +1 -1
  14. package/dist/Galena.mjs +80 -22
  15. package/dist/Galena.mjs.map +1 -1
  16. package/dist/Logger.cjs +2 -2
  17. package/dist/Logger.mjs +2 -2
  18. package/dist/Logger.mjs.map +1 -1
  19. package/dist/Middleware.cjs +2 -2
  20. package/dist/Middleware.d.cts +2 -2
  21. package/dist/Middleware.d.mts +2 -2
  22. package/dist/Middleware.mjs +2 -2
  23. package/dist/Middleware.mjs.map +1 -1
  24. package/dist/Profiler.cjs +2 -2
  25. package/dist/Profiler.mjs +2 -2
  26. package/dist/Profiler.mjs.map +1 -1
  27. package/dist/State.cjs +23 -24
  28. package/dist/State.d.cts +22 -23
  29. package/dist/State.d.cts.map +1 -1
  30. package/dist/State.d.mts +22 -23
  31. package/dist/State.d.mts.map +1 -1
  32. package/dist/State.mjs +23 -24
  33. package/dist/State.mjs.map +1 -1
  34. package/dist/index.d.cts +2 -2
  35. package/dist/index.d.mts +2 -2
  36. package/dist/types.d.cts +4 -2
  37. package/dist/types.d.cts.map +1 -1
  38. package/dist/types.d.mts +4 -2
  39. package/dist/types.d.mts.map +1 -1
  40. package/package.json +8 -8
  41. package/src/API.ts +12 -0
  42. package/src/Galena.ts +101 -23
  43. package/src/Logger.ts +2 -2
  44. package/src/Middleware.ts +2 -2
  45. package/src/Profiler.ts +2 -2
  46. package/src/State.ts +23 -24
  47. package/src/types.ts +7 -1
package/dist/Galena.d.mts CHANGED
@@ -1,77 +1,124 @@
1
- import { AppSubscriber, StateTypes } from "./types.mjs";
1
+ import { AppSubscriber, GalenaSnapshot, GalenaState, Setter, StateType, StateTypes } from "./types.mjs";
2
2
  import { State } from "./State.mjs";
3
3
  import { Middleware } from "./Middleware.mjs";
4
+ import { API } from "./API.mjs";
4
5
 
5
6
  //#region src/Galena.d.ts
6
7
  /**
7
- * Galena
8
+ * ### Galena
8
9
  *
9
- * Galena is designed to house one or more units of `State`
10
+ * Galena instances are designed to house one or more units of `State`
10
11
  * and exist as a pseudo global application state.
11
12
  *
12
13
  * By design, each of its `State` units have isolated reactivity
13
14
  * that prevents entire state trees from updating when a single
14
15
  * unit changes.
15
16
  *
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
17
  * ```typescript
22
18
  * import { Galena } from "@figliolia/galena";
23
19
  *
24
20
  * const AppState = new Galena({
21
+ * user: new State("<user-stuff>"),
22
+ * business: new State("<business-logic-stuff>")
25
23
  * // your reactive instances
26
24
  * }, ...middleware);
27
25
  *
28
26
  * // to retreive and work with an individual unit
29
- * const myUnit = AppState.get("<key>"); // Returns State<T>
27
+ * const userState = AppState.get("user"); // Returns State<T>
30
28
  *
31
29
  * // to run a callback anytime a unit of state changes
32
- * const unsubscribe = AppState.subscribe(({ updated }) => {
30
+ * const listener = AppState.subscribe(({ state, updated }) => {
33
31
  * // do something with the `State` instance that updated
32
+ * // the entirety of your state
34
33
  * });
34
+ *
35
+ * // get the current application state
36
+ * const currentState = AppState.getState();
37
+ *
38
+ * // operate on an instance of state
39
+ * AppState.update("user", userState => ({
40
+ * ...userState,
41
+ * // your updates
42
+ * }));
35
43
  * ```
36
44
  */
37
- declare class Galena<T extends Record<string, State<any>>> {
45
+ declare class Galena<T extends Record<string, State<any>>> extends API<GalenaState<T>, GalenaSnapshot<T>, StateTypes<T>> {
38
46
  readonly state: T;
39
47
  private Emitter;
40
48
  constructor(state: T, ...middleware: Middleware<StateTypes<T>>[]);
49
+ getState(): GalenaState<T>;
50
+ /**
51
+ * Get
52
+ *
53
+ * Returns a connected State instance by key
54
+ */
41
55
  get<K extends Extract<keyof T, string>>(key: K): T[K];
56
+ /**
57
+ * Set
58
+ *
59
+ * Sets a connected State instance's state by key
60
+ */
61
+ set<K extends Extract<keyof T, string>>(key: K, value: StateType<T[K]>): void;
62
+ /**
63
+ * Update
64
+ *
65
+ * Invokes a connected State instance's update method key
66
+ */
67
+ update<K extends Extract<keyof T, string>>(key: K, updater: Setter<StateType<T[K]>>): void;
68
+ /**
69
+ * Subscribe
70
+ *
71
+ * Listen for changes on your Galena instnace. Your provided
72
+ * callback will be invoked each time an attached state instance
73
+ * changes. To your callback will be provided the `updated` state
74
+ * instance, along with the entire `state` tree
75
+ */
42
76
  subscribe: (subscriber: AppSubscriber<T>) => () => void;
77
+ /**
78
+ * Register Middleware
79
+ *
80
+ * Adds middleware instances to each of the connected
81
+ * `State` instances
82
+ */
43
83
  registerMiddleware(...middlewares: Middleware<StateTypes<T>>[]): void;
44
84
  private emit;
45
85
  }
46
86
  /**
47
- * Create Galena
87
+ * ### createGalena
48
88
  *
49
- * Galena is designed to house one or more units of `State`
89
+ * Galena instances are designed to house one or more units of `State`
50
90
  * and exist as a pseudo global application state.
51
91
  *
52
92
  * By design, each of its `State` units have isolated reactivity
53
93
  * that prevents entire state trees from updating when a single
54
94
  * unit changes.
55
95
  *
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
96
  * ```typescript
62
- * import { createGalena } from "@figliolia/galena";
97
+ * import { Galena } from "@figliolia/galena";
63
98
  *
64
- * const AppState = createGalena({
99
+ * const AppState = new Galena({
100
+ * user: new State("<user-stuff>"),
101
+ * business: new State("<business-logic-stuff>")
65
102
  * // your reactive instances
66
103
  * }, ...middleware);
67
104
  *
68
105
  * // to retreive and work with an individual unit
69
- * const myUnit = AppState.get("<key>"); // Returns State<T>
106
+ * const userState = AppState.get("user"); // Returns State<T>
70
107
  *
71
108
  * // to run a callback anytime a unit of state changes
72
- * const unsubscribe = AppState.subscribe(({ updated }) => {
109
+ * const listener = AppState.subscribe(({ state, updated }) => {
73
110
  * // do something with the `State` instance that updated
111
+ * // the entirety of your state
74
112
  * });
113
+ *
114
+ * // get the current application state
115
+ * const currentState = AppState.getState();
116
+ *
117
+ * // operate on an instance of state
118
+ * AppState.update("user", userState => ({
119
+ * ...userState,
120
+ * // your updates
121
+ * }));
75
122
  * ```
76
123
  */
77
124
  declare const createGalena: <T extends Record<string, State<any>>>(...args: ConstructorParameters<typeof Galena<T>>) => Galena<T>;
@@ -1 +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"}
1
+ {"version":3,"file":"Galena.d.mts","names":[],"sources":["../src/Galena.ts"],"mappings":";;;;;;;;AAmDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,MAAA,WAAiB,MAAA,SAAe,KAAA,gBAAqB,GAAA,CAChE,WAAA,CAAY,CAAA,GACZ,cAAA,CAAe,CAAA,GACf,UAAA,CAAW,CAAA;EAAA,SAIO,KAAA,EAAO,CAAA;EAAA,QAFjB,OAAA;cAEU,KAAA,EAAO,CAAA,KACpB,UAAA,EAAY,UAAA,CAAW,UAAA,CAAW,CAAA;EAKhC,QAAA,CAAA,GAAQ,WAAA,CAAA,CAAA;EAbiD;;;;;EA2BzD,GAAA,WAAc,OAAA,OAAc,CAAA,UAAA,CAAY,GAAA,EAAK,CAAA,GAAC,CAAA,CAAA,CAAA;EA3BW;;;;;EAoCzD,GAAA,WAAc,OAAA,OAAc,CAAA,UAAA,CACjC,GAAA,EAAK,CAAA,EACL,KAAA,EAAO,SAAA,CAAU,CAAA,CAAE,CAAA;EAnCV;;;;;EA6CJ,MAAA,WAAiB,OAAA,OAAc,CAAA,UAAA,CACpC,GAAA,EAAK,CAAA,EACL,OAAA,EAAS,MAAA,CAAO,SAAA,CAAU,CAAA,CAAE,CAAA;EA3CZ;;;;;;;;EAwDX,SAAA,GAAa,UAAA,EAAY,aAAA,CAAc,CAAA;EApCnC;;;;;;EAgEJ,kBAAA,CAAA,GAAsB,WAAA,EAAa,UAAA,CAAW,UAAA,CAAW,CAAA;EAAA,QAMxD,IAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CV;;;;;;;cAAa,YAAA,aAA0B,MAAA,SAAe,KAAA,WACjD,IAAA,EAAM,qBAAA,QAA6B,MAAA,CAAO,CAAA,OAAG,MAAA,CAAA,CAAA"}
package/dist/Galena.mjs CHANGED
@@ -1,45 +1,90 @@
1
+ import { API } from "./API.mjs";
1
2
  import { EventEmitter } from "@figliolia/event-emitter";
2
3
  //#region src/Galena.ts
3
4
  /**
4
- * Galena
5
+ * ### Galena
5
6
  *
6
- * Galena is designed to house one or more units of `State`
7
+ * Galena instances are designed to house one or more units of `State`
7
8
  * and exist as a pseudo global application state.
8
9
  *
9
10
  * By design, each of its `State` units have isolated reactivity
10
11
  * that prevents entire state trees from updating when a single
11
12
  * unit changes.
12
13
  *
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
14
  * ```typescript
19
15
  * import { Galena } from "@figliolia/galena";
20
16
  *
21
17
  * const AppState = new Galena({
18
+ * user: new State("<user-stuff>"),
19
+ * business: new State("<business-logic-stuff>")
22
20
  * // your reactive instances
23
21
  * }, ...middleware);
24
22
  *
25
23
  * // to retreive and work with an individual unit
26
- * const myUnit = AppState.get("<key>"); // Returns State<T>
24
+ * const userState = AppState.get("user"); // Returns State<T>
27
25
  *
28
26
  * // to run a callback anytime a unit of state changes
29
- * const unsubscribe = AppState.subscribe(({ updated }) => {
27
+ * const listener = AppState.subscribe(({ state, updated }) => {
30
28
  * // do something with the `State` instance that updated
29
+ * // the entirety of your state
31
30
  * });
31
+ *
32
+ * // get the current application state
33
+ * const currentState = AppState.getState();
34
+ *
35
+ * // operate on an instance of state
36
+ * AppState.update("user", userState => ({
37
+ * ...userState,
38
+ * // your updates
39
+ * }));
32
40
  * ```
33
41
  */
34
- var Galena = class {
42
+ var Galena = class extends API {
35
43
  Emitter = new EventEmitter();
36
44
  constructor(state, ...middleware) {
45
+ super(...middleware);
37
46
  this.state = state;
38
- this.registerMiddleware(...middleware);
39
47
  }
48
+ getState() {
49
+ const result = {};
50
+ for (const key in this.state) {
51
+ const state = key;
52
+ result[state] = this.state[key].getState();
53
+ }
54
+ return result;
55
+ }
56
+ /**
57
+ * Get
58
+ *
59
+ * Returns a connected State instance by key
60
+ */
40
61
  get(key) {
41
62
  return this.state[key];
42
63
  }
64
+ /**
65
+ * Set
66
+ *
67
+ * Sets a connected State instance's state by key
68
+ */
69
+ set(key, value) {
70
+ return this.get(key).set(value);
71
+ }
72
+ /**
73
+ * Update
74
+ *
75
+ * Invokes a connected State instance's update method key
76
+ */
77
+ update(key, updater) {
78
+ return this.get(key).update(updater);
79
+ }
80
+ /**
81
+ * Subscribe
82
+ *
83
+ * Listen for changes on your Galena instnace. Your provided
84
+ * callback will be invoked each time an attached state instance
85
+ * changes. To your callback will be provided the `updated` state
86
+ * instance, along with the entire `state` tree
87
+ */
43
88
  subscribe = (subscriber) => {
44
89
  const ID = this.Emitter.on("change", subscriber);
45
90
  const unsubscribers = [];
@@ -56,6 +101,12 @@ var Galena = class {
56
101
  while (unsubscribers.length) unsubscribers.pop?.()?.();
57
102
  };
58
103
  };
104
+ /**
105
+ * Register Middleware
106
+ *
107
+ * Adds middleware instances to each of the connected
108
+ * `State` instances
109
+ */
59
110
  registerMiddleware(...middlewares) {
60
111
  for (const key in this.state) this.state[key]?.registerMiddleware?.(...middlewares);
61
112
  }
@@ -64,34 +115,41 @@ var Galena = class {
64
115
  }
65
116
  };
66
117
  /**
67
- * Create Galena
118
+ * ### createGalena
68
119
  *
69
- * Galena is designed to house one or more units of `State`
120
+ * Galena instances are designed to house one or more units of `State`
70
121
  * and exist as a pseudo global application state.
71
122
  *
72
123
  * By design, each of its `State` units have isolated reactivity
73
124
  * that prevents entire state trees from updating when a single
74
125
  * unit changes.
75
126
  *
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
127
  * ```typescript
82
- * import { createGalena } from "@figliolia/galena";
128
+ * import { Galena } from "@figliolia/galena";
83
129
  *
84
- * const AppState = createGalena({
130
+ * const AppState = new Galena({
131
+ * user: new State("<user-stuff>"),
132
+ * business: new State("<business-logic-stuff>")
85
133
  * // your reactive instances
86
134
  * }, ...middleware);
87
135
  *
88
136
  * // to retreive and work with an individual unit
89
- * const myUnit = AppState.get("<key>"); // Returns State<T>
137
+ * const userState = AppState.get("user"); // Returns State<T>
90
138
  *
91
139
  * // to run a callback anytime a unit of state changes
92
- * const unsubscribe = AppState.subscribe(({ updated }) => {
140
+ * const listener = AppState.subscribe(({ state, updated }) => {
93
141
  * // do something with the `State` instance that updated
142
+ * // the entirety of your state
94
143
  * });
144
+ *
145
+ * // get the current application state
146
+ * const currentState = AppState.getState();
147
+ *
148
+ * // operate on an instance of state
149
+ * AppState.update("user", userState => ({
150
+ * ...userState,
151
+ * // your updates
152
+ * }));
95
153
  * ```
96
154
  */
97
155
  const createGalena = (...args) => {
@@ -1 +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"}
1
+ {"version":3,"file":"Galena.mjs","names":[],"sources":["../src/Galena.ts"],"sourcesContent":["import { EventEmitter } from \"@figliolia/event-emitter\";\nimport { API } from \"./API\";\nimport type { Middleware } from \"./Middleware\";\nimport type { State } from \"./State\";\nimport type {\n AppSubscriber,\n GalenaSnapshot,\n GalenaState,\n Setter,\n StateType,\n StateTypes,\n} from \"./types\";\n\n/**\n * ### Galena\n *\n * Galena instances are 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 * ```typescript\n * import { Galena } from \"@figliolia/galena\";\n *\n * const AppState = new Galena({\n * user: new State(\"<user-stuff>\"),\n * business: new State(\"<business-logic-stuff>\")\n * // your reactive instances\n * }, ...middleware);\n *\n * // to retreive and work with an individual unit\n * const userState = AppState.get(\"user\"); // Returns State<T>\n *\n * // to run a callback anytime a unit of state changes\n * const listener = AppState.subscribe(({ state, updated }) => {\n * // do something with the `State` instance that updated\n * // the entirety of your state\n * });\n *\n * // get the current application state\n * const currentState = AppState.getState();\n *\n * // operate on an instance of state\n * AppState.update(\"user\", userState => ({\n * ...userState,\n * // your updates\n * }));\n * ```\n */\nexport class Galena<T extends Record<string, State<any>>> extends API<\n GalenaState<T>,\n GalenaSnapshot<T>,\n StateTypes<T>\n> {\n private Emitter = new EventEmitter<{ change: GalenaSnapshot<T> }>();\n constructor(\n public readonly state: T,\n ...middleware: Middleware<StateTypes<T>>[]\n ) {\n super(...middleware);\n }\n\n public getState() {\n const result = {} as GalenaState<T>;\n for (const key in this.state) {\n const state = key as keyof T;\n result[state] = this.state[key].getState();\n }\n return result;\n }\n\n /**\n * Get\n *\n * Returns a connected State instance by key\n */\n public get<K extends Extract<keyof T, string>>(key: K) {\n return this.state[key];\n }\n\n /**\n * Set\n *\n * Sets a connected State instance's state by key\n */\n public set<K extends Extract<keyof T, string>>(\n key: K,\n value: StateType<T[K]>,\n ) {\n return this.get(key).set(value);\n }\n\n /**\n * Update\n *\n * Invokes a connected State instance's update method key\n */\n public update<K extends Extract<keyof T, string>>(\n key: K,\n updater: Setter<StateType<T[K]>>,\n ) {\n return this.get(key).update(updater);\n }\n\n /**\n * Subscribe\n *\n * Listen for changes on your Galena instnace. Your provided\n * callback will be invoked each time an attached state instance\n * changes. To your callback will be provided the `updated` state\n * instance, along with the entire `state` tree\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 /**\n * Register Middleware\n *\n * Adds middleware instances to each of the connected\n * `State` instances\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 * ### createGalena\n *\n * Galena instances are 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 * ```typescript\n * import { Galena } from \"@figliolia/galena\";\n *\n * const AppState = new Galena({\n * user: new State(\"<user-stuff>\"),\n * business: new State(\"<business-logic-stuff>\")\n * // your reactive instances\n * }, ...middleware);\n *\n * // to retreive and work with an individual unit\n * const userState = AppState.get(\"user\"); // Returns State<T>\n *\n * // to run a callback anytime a unit of state changes\n * const listener = AppState.subscribe(({ state, updated }) => {\n * // do something with the `State` instance that updated\n * // the entirety of your state\n * });\n *\n * // get the current application state\n * const currentState = AppState.getState();\n *\n * // operate on an instance of state\n * AppState.update(\"user\", userState => ({\n * ...userState,\n * // your updates\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,IAAa,SAAb,cAAkE,IAIhE;CACA,UAAkB,IAAI,cAA6C;CACnE,YACE,OACA,GAAG,YACH;AACA,QAAM,GAAG,WAAW;AAHJ,OAAA,QAAA;;CAMlB,WAAkB;EAChB,MAAM,SAAS,EAAE;AACjB,OAAK,MAAM,OAAO,KAAK,OAAO;GAC5B,MAAM,QAAQ;AACd,UAAO,SAAS,KAAK,MAAM,KAAK,UAAU;;AAE5C,SAAO;;;;;;;CAQT,IAA+C,KAAQ;AACrD,SAAO,KAAK,MAAM;;;;;;;CAQpB,IACE,KACA,OACA;AACA,SAAO,KAAK,IAAI,IAAI,CAAC,IAAI,MAAM;;;;;;;CAQjC,OACE,KACA,SACA;AACA,SAAO,KAAK,IAAI,IAAI,CAAC,OAAO,QAAQ;;;;;;;;;;CAWtC,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;;;;;;;;;CAW/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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CtC,MAAa,gBACX,GAAG,SACA;AACH,QAAO,IAAI,OAAO,GAAG,KAAK"}
package/dist/Logger.cjs CHANGED
@@ -20,12 +20,12 @@ const require_Middleware = require("./Middleware.cjs");
20
20
  var Logger = class extends require_Middleware.Middleware {
21
21
  previousState = null;
22
22
  onBeforeUpdate(state) {
23
- this.previousState = state.getSnapshot();
23
+ this.previousState = state.getState();
24
24
  }
25
25
  onUpdate(state) {
26
26
  console.log("%cMutation:", "color: rgb(187, 186, 186); font-weight: bold", "@", this.time);
27
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());
28
+ console.log(" %cNext State ", "color: rgb(17, 118, 249); font-weight: bold", state.getState());
29
29
  }
30
30
  /**
31
31
  * Time
package/dist/Logger.mjs CHANGED
@@ -20,12 +20,12 @@ import { Middleware } from "./Middleware.mjs";
20
20
  var Logger = class extends Middleware {
21
21
  previousState = null;
22
22
  onBeforeUpdate(state) {
23
- this.previousState = state.getSnapshot();
23
+ this.previousState = state.getState();
24
24
  }
25
25
  onUpdate(state) {
26
26
  console.log("%cMutation:", "color: rgb(187, 186, 186); font-weight: bold", "@", this.time);
27
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());
28
+ console.log(" %cNext State ", "color: rgb(17, 118, 249); font-weight: bold", state.getState());
29
29
  }
30
30
  /**
31
31
  * Time
@@ -1 +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"}
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.getState();\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.getState(),\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,UAAU;;CAGvC,SAAkB,OAAiB;AACjC,UAAQ,IACN,eACA,gDACA,KACA,KAAK,KACN;AACD,UAAQ,IACN,uBACA,qCACA,KAAK,cACN;AACD,UAAQ,IACN,uBACA,+CACA,MAAM,UAAU,CACjB;;;;;;;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"}
@@ -18,7 +18,7 @@
18
18
  *
19
19
  * public override onBeforeUpdate(state: State<T>) {
20
20
  * this.startTime = performance.now();
21
- * this.previousState = state.getSnapshot();
21
+ * this.previousState = state.getState();
22
22
  * }
23
23
  *
24
24
  * public override onUpdate(state: T) {
@@ -26,7 +26,7 @@
26
26
  * if(diff >= this.threshold) {
27
27
  * console.warn(`A slow state transition was detected when transitioning the following piece of state`);
28
28
  * console.log('Previous state', this.previousState);
29
- * console.log('Current state', state.getSnapshot());
29
+ * console.log('Current state', state.getState());
30
30
  * }
31
31
  * }
32
32
  * }
@@ -20,7 +20,7 @@ import { State } from "./State.cjs";
20
20
  *
21
21
  * public override onBeforeUpdate(state: State<T>) {
22
22
  * this.startTime = performance.now();
23
- * this.previousState = state.getSnapshot();
23
+ * this.previousState = state.getState();
24
24
  * }
25
25
  *
26
26
  * public override onUpdate(state: T) {
@@ -28,7 +28,7 @@ import { State } from "./State.cjs";
28
28
  * if(diff >= this.threshold) {
29
29
  * console.warn(`A slow state transition was detected when transitioning the following piece of state`);
30
30
  * console.log('Previous state', this.previousState);
31
- * console.log('Current state', state.getSnapshot());
31
+ * console.log('Current state', state.getState());
32
32
  * }
33
33
  * }
34
34
  * }
@@ -20,7 +20,7 @@ import { State } from "./State.mjs";
20
20
  *
21
21
  * public override onBeforeUpdate(state: State<T>) {
22
22
  * this.startTime = performance.now();
23
- * this.previousState = state.getSnapshot();
23
+ * this.previousState = state.getState();
24
24
  * }
25
25
  *
26
26
  * public override onUpdate(state: T) {
@@ -28,7 +28,7 @@ import { State } from "./State.mjs";
28
28
  * if(diff >= this.threshold) {
29
29
  * console.warn(`A slow state transition was detected when transitioning the following piece of state`);
30
30
  * console.log('Previous state', this.previousState);
31
- * console.log('Current state', state.getSnapshot());
31
+ * console.log('Current state', state.getState());
32
32
  * }
33
33
  * }
34
34
  * }
@@ -18,7 +18,7 @@
18
18
  *
19
19
  * public override onBeforeUpdate(state: State<T>) {
20
20
  * this.startTime = performance.now();
21
- * this.previousState = state.getSnapshot();
21
+ * this.previousState = state.getState();
22
22
  * }
23
23
  *
24
24
  * public override onUpdate(state: T) {
@@ -26,7 +26,7 @@
26
26
  * if(diff >= this.threshold) {
27
27
  * console.warn(`A slow state transition was detected when transitioning the following piece of state`);
28
28
  * console.log('Previous state', this.previousState);
29
- * console.log('Current state', state.getSnapshot());
29
+ * console.log('Current state', state.getState());
30
30
  * }
31
31
  * }
32
32
  * }
@@ -1 +1 @@
1
- {"version":3,"file":"Middleware.mjs","names":[],"sources":["../src/Middleware.ts"],"sourcesContent":["import type { State } from \"./State\";\n\n/**\n * Middleware\n *\n * Galena's middleware API is designed to provide hooks\n * for state changes that you can tap into to run your\n * own logic.\n *\n * Middleware is great for logging, analytics, and profiling:\n *\n * ```typescript\n * export class Profiler<T = any> extends Middleware<T> {\n * private previousState: T | null = null;\n * private startTime: null | number = null;\n * constructor(public readonly threshold: number = 16) {\n * super();\n * }\n *\n * public override onBeforeUpdate(state: State<T>) {\n * this.startTime = performance.now();\n * this.previousState = state.getSnapshot();\n * }\n *\n * public override onUpdate(state: T) {\n * const diff = performance.now() - this.startTime;\n * if(diff >= this.threshold) {\n * console.warn(`A slow state transition was detected when transitioning the following piece of state`);\n * console.log('Previous state', this.previousState);\n * console.log('Current state', state.getSnapshot());\n * }\n * }\n * }\n * ```\n *\n * To register your middleware, simply add it when constructing\n * a `State` or `Galena` instance.\n *\n * ```typescript\n * import { State } from \"@figliolia/galena\";\n * import { Profiler } from './myProfiler';\n *\n * const myState = new State(5, new Profiler());\n * ```\n */\nexport class Middleware<T = any> {\n /**\n * On Before Update\n *\n * Executes prior to a `State` instance being updated.\n * Receives the state prior to its update as a parameter\n */\n public onBeforeUpdate(_state: State<T>) {}\n\n /**\n * On Update\n *\n * Executes after a `State` instance has been update.\n * Receives the most recent state as a parameter\n */\n public onUpdate(_state: State<T>) {}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,IAAa,aAAb,MAAiC;;;;;;;CAO/B,eAAsB,QAAkB;;;;;;;CAQxC,SAAgB,QAAkB"}
1
+ {"version":3,"file":"Middleware.mjs","names":[],"sources":["../src/Middleware.ts"],"sourcesContent":["import type { State } from \"./State\";\n\n/**\n * Middleware\n *\n * Galena's middleware API is designed to provide hooks\n * for state changes that you can tap into to run your\n * own logic.\n *\n * Middleware is great for logging, analytics, and profiling:\n *\n * ```typescript\n * export class Profiler<T = any> extends Middleware<T> {\n * private previousState: T | null = null;\n * private startTime: null | number = null;\n * constructor(public readonly threshold: number = 16) {\n * super();\n * }\n *\n * public override onBeforeUpdate(state: State<T>) {\n * this.startTime = performance.now();\n * this.previousState = state.getState();\n * }\n *\n * public override onUpdate(state: T) {\n * const diff = performance.now() - this.startTime;\n * if(diff >= this.threshold) {\n * console.warn(`A slow state transition was detected when transitioning the following piece of state`);\n * console.log('Previous state', this.previousState);\n * console.log('Current state', state.getState());\n * }\n * }\n * }\n * ```\n *\n * To register your middleware, simply add it when constructing\n * a `State` or `Galena` instance.\n *\n * ```typescript\n * import { State } from \"@figliolia/galena\";\n * import { Profiler } from './myProfiler';\n *\n * const myState = new State(5, new Profiler());\n * ```\n */\nexport class Middleware<T = any> {\n /**\n * On Before Update\n *\n * Executes prior to a `State` instance being updated.\n * Receives the state prior to its update as a parameter\n */\n public onBeforeUpdate(_state: State<T>) {}\n\n /**\n * On Update\n *\n * Executes after a `State` instance has been update.\n * Receives the most recent state as a parameter\n */\n public onUpdate(_state: State<T>) {}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,IAAa,aAAb,MAAiC;;;;;;;CAO/B,eAAsB,QAAkB;;;;;;;CAQxC,SAAgB,QAAkB"}
package/dist/Profiler.cjs CHANGED
@@ -25,7 +25,7 @@ var Profiler = class extends require_Middleware.Middleware {
25
25
  }
26
26
  onBeforeUpdate(state) {
27
27
  this.startTime = performance.now();
28
- this.previousState = state.getSnapshot();
28
+ this.previousState = state.getState();
29
29
  }
30
30
  onUpdate(state) {
31
31
  if (this.startTime === null) return;
@@ -33,7 +33,7 @@ var Profiler = class extends require_Middleware.Middleware {
33
33
  if (diff >= this.threshold) {
34
34
  console.warn(`A slow state transition of ${diff.toFixed(1)}ms was detected when transitioning the following piece of state`);
35
35
  console.log(" %cPrevious State", "color: #26ad65; font-weight: bold", this.previousState);
36
- console.log(" %cCurrent State ", "color: rgb(17, 118, 249); font-weight: bold", state.getSnapshot());
36
+ console.log(" %cCurrent State ", "color: rgb(17, 118, 249); font-weight: bold", state.getState());
37
37
  }
38
38
  }
39
39
  };
package/dist/Profiler.mjs CHANGED
@@ -25,7 +25,7 @@ var Profiler = class extends Middleware {
25
25
  }
26
26
  onBeforeUpdate(state) {
27
27
  this.startTime = performance.now();
28
- this.previousState = state.getSnapshot();
28
+ this.previousState = state.getState();
29
29
  }
30
30
  onUpdate(state) {
31
31
  if (this.startTime === null) return;
@@ -33,7 +33,7 @@ var Profiler = class extends Middleware {
33
33
  if (diff >= this.threshold) {
34
34
  console.warn(`A slow state transition of ${diff.toFixed(1)}ms was detected when transitioning the following piece of state`);
35
35
  console.log(" %cPrevious State", "color: #26ad65; font-weight: bold", this.previousState);
36
- console.log(" %cCurrent State ", "color: rgb(17, 118, 249); font-weight: bold", state.getSnapshot());
36
+ console.log(" %cCurrent State ", "color: rgb(17, 118, 249); font-weight: bold", state.getState());
37
37
  }
38
38
  }
39
39
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Profiler.mjs","names":[],"sources":["../src/Profiler.ts"],"sourcesContent":["import { Middleware } from \"./Middleware\";\nimport type { State } from \"./State\";\n\n/**\n * Profiler\n *\n * A logger for state transitions exceeding a given\n * millisecond threshold\n *\n * ```typescript\n * const AppState = new Galena({}, new Profiler());\n * // or\n * AppState.registerMiddlerware(new Profiler());\n * // or\n * const MyState = new State(4, new Profiler());\n * // or\n * MyState.registerMiddleware(new Profiler());\n * ```\n */\nexport class Profiler<T = any> extends Middleware<T> {\n private previousState: T | null = null;\n private startTime: null | number = null;\n constructor(public readonly threshold = 16) {\n super();\n }\n\n public override onBeforeUpdate(state: State<T>) {\n this.startTime = performance.now();\n this.previousState = state.getSnapshot();\n }\n\n public override onUpdate(state: State<T>) {\n if (this.startTime === null) {\n return;\n }\n const diff = performance.now() - this.startTime;\n if (diff >= this.threshold) {\n console.warn(\n `A slow state transition of ${diff.toFixed(1)}ms was detected when transitioning the following piece of state`,\n );\n console.log(\n \" %cPrevious State\",\n \"color: #26ad65; font-weight: bold\",\n this.previousState,\n );\n console.log(\n \" %cCurrent State \",\n \"color: rgb(17, 118, 249); font-weight: bold\",\n state.getSnapshot(),\n );\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,IAAa,WAAb,cAAuC,WAAc;CACnD,gBAAkC;CAClC,YAAmC;CACnC,YAAY,YAA4B,IAAI;AAC1C,SAAO;AADmB,OAAA,YAAA;;CAI5B,eAA+B,OAAiB;AAC9C,OAAK,YAAY,YAAY,KAAK;AAClC,OAAK,gBAAgB,MAAM,aAAa;;CAG1C,SAAyB,OAAiB;AACxC,MAAI,KAAK,cAAc,KACrB;EAEF,MAAM,OAAO,YAAY,KAAK,GAAG,KAAK;AACtC,MAAI,QAAQ,KAAK,WAAW;AAC1B,WAAQ,KACN,8BAA8B,KAAK,QAAQ,EAAE,CAAC,iEAC/C;AACD,WAAQ,IACN,uBACA,qCACA,KAAK,cACN;AACD,WAAQ,IACN,0BACA,+CACA,MAAM,aAAa,CACpB"}
1
+ {"version":3,"file":"Profiler.mjs","names":[],"sources":["../src/Profiler.ts"],"sourcesContent":["import { Middleware } from \"./Middleware\";\nimport type { State } from \"./State\";\n\n/**\n * Profiler\n *\n * A logger for state transitions exceeding a given\n * millisecond threshold\n *\n * ```typescript\n * const AppState = new Galena({}, new Profiler());\n * // or\n * AppState.registerMiddlerware(new Profiler());\n * // or\n * const MyState = new State(4, new Profiler());\n * // or\n * MyState.registerMiddleware(new Profiler());\n * ```\n */\nexport class Profiler<T = any> extends Middleware<T> {\n private previousState: T | null = null;\n private startTime: null | number = null;\n constructor(public readonly threshold = 16) {\n super();\n }\n\n public override onBeforeUpdate(state: State<T>) {\n this.startTime = performance.now();\n this.previousState = state.getState();\n }\n\n public override onUpdate(state: State<T>) {\n if (this.startTime === null) {\n return;\n }\n const diff = performance.now() - this.startTime;\n if (diff >= this.threshold) {\n console.warn(\n `A slow state transition of ${diff.toFixed(1)}ms was detected when transitioning the following piece of state`,\n );\n console.log(\n \" %cPrevious State\",\n \"color: #26ad65; font-weight: bold\",\n this.previousState,\n );\n console.log(\n \" %cCurrent State \",\n \"color: rgb(17, 118, 249); font-weight: bold\",\n state.getState(),\n );\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,IAAa,WAAb,cAAuC,WAAc;CACnD,gBAAkC;CAClC,YAAmC;CACnC,YAAY,YAA4B,IAAI;AAC1C,SAAO;AADmB,OAAA,YAAA;;CAI5B,eAA+B,OAAiB;AAC9C,OAAK,YAAY,YAAY,KAAK;AAClC,OAAK,gBAAgB,MAAM,UAAU;;CAGvC,SAAyB,OAAiB;AACxC,MAAI,KAAK,cAAc,KACrB;EAEF,MAAM,OAAO,YAAY,KAAK,GAAG,KAAK;AACtC,MAAI,QAAQ,KAAK,WAAW;AAC1B,WAAQ,KACN,8BAA8B,KAAK,QAAQ,EAAE,CAAC,iEAC/C;AACD,WAAQ,IACN,uBACA,qCACA,KAAK,cACN;AACD,WAAQ,IACN,0BACA,+CACA,MAAM,UAAU,CACjB"}
package/dist/State.cjs CHANGED
@@ -1,17 +1,18 @@
1
+ const require_API = require("./API.cjs");
1
2
  let _figliolia_event_emitter = require("@figliolia/event-emitter");
2
3
  //#region src/State.ts
3
4
  /**
4
- * State
5
+ * ### State
5
6
  *
6
7
  * The unit of reactivity for Galena. `State`'s can act
7
8
  * as isolated instances or be part of your global app
8
9
  * state (via `Galena` instances).
9
10
  *
10
- * There are three ways to create state instances
11
+ * There are two ways to create state instances
11
12
  *
12
13
  * ```typescript
13
- * import { State, createState, useState, Profiler } from "@figliolia/galena";
14
- * // for island states that can be shared between react components
14
+ * import { State, createState, Profiler } from "@figliolia/galena";
15
+
15
16
  * const myState = new State("<any value>", ...middleware);
16
17
  * // or
17
18
  * const myState = createState("<any value>", ...middleware);
@@ -20,27 +21,18 @@ let _figliolia_event_emitter = require("@figliolia/event-emitter");
20
21
  * myState.update(previousValue => "<new-value>");
21
22
  * myState.subscribe(nextValue => {});
22
23
  * myState.registerMiddleware(new Profiler());
23
- *
24
- * // Similarly if you wish to use your state inside a react component
25
- * const MyComponent = () => {
26
- * const [state, setState] = useState(myState);
27
- * // or
28
- * const [state, setState] = useMyState("<any-value>", ...middlware);
29
- *
30
- * return (
31
- * // your jsx
32
- * );
33
- * }
24
+ * myState.reset(); // reset back to it's original value
25
+ * // to get the current value at any point in time
26
+ * const currentValue = myState.getState();
34
27
  * ```
35
28
  */
36
- var State = class {
29
+ var State = class extends require_API.API {
37
30
  state;
38
- middleware = [];
39
31
  Emitter = new _figliolia_event_emitter.EventEmitter();
40
32
  constructor(initialState, ...middleware) {
33
+ super(...middleware);
41
34
  this.initialState = initialState;
42
35
  this.state = initialState;
43
- this.registerMiddleware(...middleware);
44
36
  }
45
37
  /**
46
38
  * Set
@@ -73,7 +65,7 @@ var State = class {
73
65
  * Returns the current state. Designed for compatibility with
74
66
  * `useSyncExternalStore`
75
67
  */
76
- getSnapshot = () => {
68
+ getState = () => {
77
69
  return this.state;
78
70
  };
79
71
  /**
@@ -122,21 +114,28 @@ var State = class {
122
114
  }
123
115
  };
124
116
  /**
125
- * Create State
117
+ * ### createState
126
118
  *
127
- * Returns the unit of reactivity for Galena. `State`'s can act
119
+ * The unit of reactivity for Galena. `State`'s can act
128
120
  * as isolated instances or be part of your global app
129
- * state (via `Galena` instances);
121
+ * state (via `Galena` instances).
130
122
  *
131
- * ```typescript
132
- * import { createState, Profiler } from "@figliolia/galena";
123
+ * There are two ways to create state instances
133
124
  *
125
+ * ```typescript
126
+ * import { State, createState, Profiler } from "@figliolia/galena";
127
+
128
+ * const myState = new State("<any value>", ...middleware);
129
+ * // or
134
130
  * const myState = createState("<any value>", ...middleware);
135
131
  *
136
132
  * myState.set("<new-value>");
137
133
  * myState.update(previousValue => "<new-value>");
138
134
  * myState.subscribe(nextValue => {});
139
135
  * myState.registerMiddleware(new Profiler());
136
+ * myState.reset(); // reset back to it's original value
137
+ * // to get the current value at any point in time
138
+ * const currentValue = myState.getState();
140
139
  * ```
141
140
  */
142
141
  function createState(...args) {