@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,114 @@
1
+ import { NonFunction, Setter, Subscriber } from "./types.mjs";
2
+ import { Middleware } from "./Middleware.mjs";
3
+
4
+ //#region src/State.d.ts
5
+ /**
6
+ * State
7
+ *
8
+ * The unit of reactivity for Galena. `State`'s can act
9
+ * as isolated instances or be part of your global app
10
+ * state (via `Galena` instances).
11
+ *
12
+ * There are three ways to create state instances
13
+ *
14
+ * ```typescript
15
+ * import { State, createState, useState, Profiler } from "@figliolia/galena";
16
+ * // for island states that can be shared between react components
17
+ * const myState = new State("<any value>", ...middleware);
18
+ * // or
19
+ * const myState = createState("<any value>", ...middleware);
20
+ *
21
+ * myState.set("<new-value>");
22
+ * myState.update(previousValue => "<new-value>");
23
+ * myState.subscribe(nextValue => {});
24
+ * myState.registerMiddleware(new Profiler());
25
+ *
26
+ * // Similarly if you wish to use your state inside a react component
27
+ * const MyComponent = () => {
28
+ * const [state, setState] = useState(myState);
29
+ * // or
30
+ * const [state, setState] = useMyState("<any-value>", ...middlware);
31
+ *
32
+ * return (
33
+ * // your jsx
34
+ * );
35
+ * }
36
+ * ```
37
+ */
38
+ declare class State<T> {
39
+ readonly initialState: NonFunction<T>;
40
+ private state;
41
+ readonly middleware: Middleware<T>[];
42
+ private readonly Emitter;
43
+ constructor(initialState: NonFunction<T>, ...middleware: Middleware<T>[]);
44
+ /**
45
+ * Set
46
+ *
47
+ * Updates the current value of state notifying
48
+ * all interested parties
49
+ */
50
+ readonly set: (state: NonFunction<T>) => void;
51
+ /**
52
+ * Update
53
+ *
54
+ * Updates the current value of state using a setter function
55
+ * receiving the previous state as a parameter. Notifies all
56
+ * interested parties
57
+ */
58
+ readonly update: (setter: Setter<T>) => void;
59
+ /**
60
+ * Reset
61
+ *
62
+ * Resets the current state back to the state which the instance
63
+ * was initialized with. Notifies all interested parties
64
+ */
65
+ readonly reset: () => void;
66
+ /**
67
+ * Get Snapshot
68
+ *
69
+ * Returns the current state. Designed for compatibility with
70
+ * `useSyncExternalStore`
71
+ */
72
+ readonly getSnapshot: () => NonFunction<T>;
73
+ /**
74
+ * Subscribe
75
+ *
76
+ * Registers a callback to be executed each time state
77
+ * changes. Returns an `unsubscribe` function
78
+ */
79
+ readonly subscribe: (fn: Subscriber<T>) => () => void;
80
+ /**
81
+ * Register Middleware
82
+ *
83
+ * Registers any number of `Middleware` instances on the
84
+ * current instance of `State`. Your middleware will begin
85
+ * executing at the next state transition
86
+ */
87
+ registerMiddleware(...middleware: Middleware<T>[]): void;
88
+ private withEmission;
89
+ private emit;
90
+ protected diffSetter(setter: Setter<T>): setter is NonFunction<T>;
91
+ private invokeMiddleware;
92
+ }
93
+ /**
94
+ * Create State
95
+ *
96
+ * Returns the unit of reactivity for Galena. `State`'s can act
97
+ * as isolated instances or be part of your global app
98
+ * state (via `Galena` instances);
99
+ *
100
+ * ```typescript
101
+ * import { createState, Profiler } from "@figliolia/galena";
102
+ *
103
+ * const myState = createState("<any value>", ...middleware);
104
+ *
105
+ * myState.set("<new-value>");
106
+ * myState.update(previousValue => "<new-value>");
107
+ * myState.subscribe(nextValue => {});
108
+ * myState.registerMiddleware(new Profiler());
109
+ * ```
110
+ */
111
+ declare function createState<T>(...args: ConstructorParameters<typeof State<T>>): State<T>;
112
+ //#endregion
113
+ export { State, createState };
114
+ //# sourceMappingURL=State.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"State.d.mts","names":[],"sources":["../src/State.ts"],"mappings":";;;;;;AAqCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,KAAA;EAAA,SAKO,YAAA,EAAc,WAAA,CAAY,CAAA;EAAA,QAJpC,KAAA;EAAA,SACQ,UAAA,EAAY,UAAA,CAAW,CAAA;EAAA,iBACtB,OAAA;cAEC,YAAA,EAAc,WAAA,CAAY,CAAA,MACvC,UAAA,EAAY,UAAA,CAAW,CAAA;EADI;;;;;;EAAA,SAahB,GAAA,GAAG,KAAA,EAAA,WAAA,CAAA,CAAA;EAAA;;;;;;;EAAA,SASH,MAAA,GAAM,MAAA,EAAA,MAAA,CAAA,CAAA;EAqBN;;;;;;EAAA,SARA,KAAA;EAgCT;;;;;;EAAA,SAxBS,WAAA,QAAW,WAAA,CAAA,CAAA;EAgDE;;;;;;EAAA,SAtCb,SAAA,GAAa,EAAA,EAAI,UAAA,CAAW,CAAA;EA0CpB;;AAyB1B;;;;;EArDS,kBAAA,CAAA,GAAsB,UAAA,EAAY,UAAA,CAAW,CAAA;EAAA,QAI5C,YAAA;EAAA,QAaA,IAAA;EAAA,UAOE,UAAA,CAAW,MAAA,EAAQ,MAAA,CAAO,CAAA,IAAK,MAAA,IAAU,WAAA,CAAY,CAAA;EAAA,QAIvD,gBAAA;AAAA;;;;;;;;;;;;;;;;;;;iBAyBM,WAAA,GAAA,CAAA,GACX,IAAA,EAAM,qBAAA,QAA6B,KAAA,CAAM,CAAA,KAAG,KAAA,CAAA,CAAA"}
package/dist/State.mjs ADDED
@@ -0,0 +1,148 @@
1
+ import { EventEmitter } from "@figliolia/event-emitter";
2
+ //#region src/State.ts
3
+ /**
4
+ * State
5
+ *
6
+ * The unit of reactivity for Galena. `State`'s can act
7
+ * as isolated instances or be part of your global app
8
+ * state (via `Galena` instances).
9
+ *
10
+ * There are three ways to create state instances
11
+ *
12
+ * ```typescript
13
+ * import { State, createState, useState, Profiler } from "@figliolia/galena";
14
+ * // for island states that can be shared between react components
15
+ * const myState = new State("<any value>", ...middleware);
16
+ * // or
17
+ * const myState = createState("<any value>", ...middleware);
18
+ *
19
+ * myState.set("<new-value>");
20
+ * myState.update(previousValue => "<new-value>");
21
+ * myState.subscribe(nextValue => {});
22
+ * 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
+ * }
34
+ * ```
35
+ */
36
+ var State = class {
37
+ state;
38
+ middleware = [];
39
+ Emitter = new EventEmitter();
40
+ constructor(initialState, ...middleware) {
41
+ this.initialState = initialState;
42
+ this.state = initialState;
43
+ this.registerMiddleware(...middleware);
44
+ }
45
+ /**
46
+ * Set
47
+ *
48
+ * Updates the current value of state notifying
49
+ * all interested parties
50
+ */
51
+ set = this.withEmission((state) => state);
52
+ /**
53
+ * Update
54
+ *
55
+ * Updates the current value of state using a setter function
56
+ * receiving the previous state as a parameter. Notifies all
57
+ * interested parties
58
+ */
59
+ update = this.withEmission((setter) => {
60
+ if (this.diffSetter(setter)) return setter;
61
+ return setter(this.state);
62
+ });
63
+ /**
64
+ * Reset
65
+ *
66
+ * Resets the current state back to the state which the instance
67
+ * was initialized with. Notifies all interested parties
68
+ */
69
+ reset = this.withEmission(() => this.initialState);
70
+ /**
71
+ * Get Snapshot
72
+ *
73
+ * Returns the current state. Designed for compatibility with
74
+ * `useSyncExternalStore`
75
+ */
76
+ getSnapshot = () => {
77
+ return this.state;
78
+ };
79
+ /**
80
+ * Subscribe
81
+ *
82
+ * Registers a callback to be executed each time state
83
+ * changes. Returns an `unsubscribe` function
84
+ */
85
+ subscribe = (fn) => {
86
+ const ID = this.Emitter.on("change", fn);
87
+ return () => {
88
+ this.Emitter.off("change", ID);
89
+ };
90
+ };
91
+ /**
92
+ * Register Middleware
93
+ *
94
+ * Registers any number of `Middleware` instances on the
95
+ * current instance of `State`. Your middleware will begin
96
+ * executing at the next state transition
97
+ */
98
+ registerMiddleware(...middleware) {
99
+ this.middleware.push(...middleware);
100
+ }
101
+ withEmission(fn) {
102
+ return (...args) => {
103
+ const result = fn(...args);
104
+ if (result instanceof Promise) {
105
+ result.then((resolved) => this.emit(resolved));
106
+ return;
107
+ }
108
+ return this.emit(result);
109
+ };
110
+ }
111
+ emit(nextState) {
112
+ this.invokeMiddleware("onBeforeUpdate");
113
+ this.state = nextState;
114
+ this.Emitter.emit("change", this.state);
115
+ this.invokeMiddleware("onUpdate");
116
+ }
117
+ diffSetter(setter) {
118
+ return typeof setter !== "function";
119
+ }
120
+ invokeMiddleware(fn) {
121
+ for (const middleware of this.middleware) middleware[fn](this);
122
+ }
123
+ };
124
+ /**
125
+ * Create State
126
+ *
127
+ * Returns the unit of reactivity for Galena. `State`'s can act
128
+ * as isolated instances or be part of your global app
129
+ * state (via `Galena` instances);
130
+ *
131
+ * ```typescript
132
+ * import { createState, Profiler } from "@figliolia/galena";
133
+ *
134
+ * const myState = createState("<any value>", ...middleware);
135
+ *
136
+ * myState.set("<new-value>");
137
+ * myState.update(previousValue => "<new-value>");
138
+ * myState.subscribe(nextValue => {});
139
+ * myState.registerMiddleware(new Profiler());
140
+ * ```
141
+ */
142
+ function createState(...args) {
143
+ return new State(...args);
144
+ }
145
+ //#endregion
146
+ export { State, createState };
147
+
148
+ //# sourceMappingURL=State.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"State.mjs","names":[],"sources":["../src/State.ts"],"sourcesContent":["import { EventEmitter } from \"@figliolia/event-emitter\";\nimport type { Middleware } from \"./Middleware\";\nimport type { NonFunction, Setter, Subscriber } from \"./types\";\n\n/**\n * State\n *\n * The unit of reactivity for Galena. `State`'s can act\n * as isolated instances or be part of your global app\n * state (via `Galena` instances).\n *\n * There are three ways to create state instances\n *\n * ```typescript\n * import { State, createState, useState, Profiler } from \"@figliolia/galena\";\n * // for island states that can be shared between react components\n * const myState = new State(\"<any value>\", ...middleware);\n * // or\n * const myState = createState(\"<any value>\", ...middleware);\n *\n * myState.set(\"<new-value>\");\n * myState.update(previousValue => \"<new-value>\");\n * myState.subscribe(nextValue => {});\n * myState.registerMiddleware(new Profiler());\n *\n * // Similarly if you wish to use your state inside a react component\n * const MyComponent = () => {\n * const [state, setState] = useState(myState);\n * // or\n * const [state, setState] = useMyState(\"<any-value>\", ...middlware);\n *\n * return (\n * // your jsx\n * );\n * }\n * ```\n */\nexport class State<T> {\n private state: NonFunction<T>;\n public readonly middleware: Middleware<T>[] = [];\n private readonly Emitter = new EventEmitter<{ change: NonFunction<T> }>();\n constructor(\n public readonly initialState: NonFunction<T>,\n ...middleware: Middleware<T>[]\n ) {\n this.state = initialState;\n this.registerMiddleware(...middleware);\n }\n\n /**\n * Set\n *\n * Updates the current value of state notifying\n * all interested parties\n */\n public readonly set = this.withEmission((state: NonFunction<T>) => state);\n\n /**\n * Update\n *\n * Updates the current value of state using a setter function\n * receiving the previous state as a parameter. Notifies all\n * interested parties\n */\n public readonly update = this.withEmission((setter: Setter<T>) => {\n if (this.diffSetter(setter)) {\n return setter;\n }\n return setter(this.state);\n });\n\n /**\n * Reset\n *\n * Resets the current state back to the state which the instance\n * was initialized with. Notifies all interested parties\n */\n public readonly reset = this.withEmission(() => this.initialState);\n\n /**\n * Get Snapshot\n *\n * Returns the current state. Designed for compatibility with\n * `useSyncExternalStore`\n */\n public readonly getSnapshot = () => {\n return this.state;\n };\n\n /**\n * Subscribe\n *\n * Registers a callback to be executed each time state\n * changes. Returns an `unsubscribe` function\n */\n public readonly subscribe = (fn: Subscriber<T>) => {\n const ID = this.Emitter.on(\"change\", fn);\n return () => {\n this.Emitter.off(\"change\", ID);\n };\n };\n\n /**\n * Register Middleware\n *\n * Registers any number of `Middleware` instances on the\n * current instance of `State`. Your middleware will begin\n * executing at the next state transition\n */\n public registerMiddleware(...middleware: Middleware<T>[]) {\n this.middleware.push(...middleware);\n }\n\n private withEmission<\n F extends (...args: any[]) => NonFunction<T> | Promise<NonFunction<T>>,\n >(fn: F) {\n return (...args: Parameters<F>) => {\n const result = fn(...args);\n if (result instanceof Promise) {\n void result.then(resolved => this.emit(resolved));\n return;\n }\n return this.emit(result);\n };\n }\n\n private emit(nextState: NonFunction<T>) {\n this.invokeMiddleware(\"onBeforeUpdate\");\n this.state = nextState;\n this.Emitter.emit(\"change\", this.state);\n this.invokeMiddleware(\"onUpdate\");\n }\n\n protected diffSetter(setter: Setter<T>): setter is NonFunction<T> {\n return typeof setter !== \"function\";\n }\n\n private invokeMiddleware<K extends keyof Middleware<T>>(fn: K) {\n for (const middleware of this.middleware) {\n middleware[fn](this);\n }\n }\n}\n\n/**\n * Create State\n *\n * Returns the unit of reactivity for Galena. `State`'s can act\n * as isolated instances or be part of your global app\n * state (via `Galena` instances);\n *\n * ```typescript\n * import { createState, Profiler } from \"@figliolia/galena\";\n *\n * const myState = createState(\"<any value>\", ...middleware);\n *\n * myState.set(\"<new-value>\");\n * myState.update(previousValue => \"<new-value>\");\n * myState.subscribe(nextValue => {});\n * myState.registerMiddleware(new Profiler());\n * ```\n */\nexport function createState<T>(\n ...args: ConstructorParameters<typeof State<T>>\n) {\n return new State<T>(...args);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,IAAa,QAAb,MAAsB;CACpB;CACA,aAA8C,EAAE;CAChD,UAA2B,IAAI,cAA0C;CACzE,YACE,cACA,GAAG,YACH;AAFgB,OAAA,eAAA;AAGhB,OAAK,QAAQ;AACb,OAAK,mBAAmB,GAAG,WAAW;;;;;;;;CASxC,MAAsB,KAAK,cAAc,UAA0B,MAAM;;;;;;;;CASzE,SAAyB,KAAK,cAAc,WAAsB;AAChE,MAAI,KAAK,WAAW,OAAO,CACzB,QAAO;AAET,SAAO,OAAO,KAAK,MAAM;GACzB;;;;;;;CAQF,QAAwB,KAAK,mBAAmB,KAAK,aAAa;;;;;;;CAQlE,oBAAoC;AAClC,SAAO,KAAK;;;;;;;;CASd,aAA6B,OAAsB;EACjD,MAAM,KAAK,KAAK,QAAQ,GAAG,UAAU,GAAG;AACxC,eAAa;AACX,QAAK,QAAQ,IAAI,UAAU,GAAG;;;;;;;;;;CAWlC,mBAA0B,GAAG,YAA6B;AACxD,OAAK,WAAW,KAAK,GAAG,WAAW;;CAGrC,aAEE,IAAO;AACP,UAAQ,GAAG,SAAwB;GACjC,MAAM,SAAS,GAAG,GAAG,KAAK;AAC1B,OAAI,kBAAkB,SAAS;AACxB,WAAO,MAAK,aAAY,KAAK,KAAK,SAAS,CAAC;AACjD;;AAEF,UAAO,KAAK,KAAK,OAAO;;;CAI5B,KAAa,WAA2B;AACtC,OAAK,iBAAiB,iBAAiB;AACvC,OAAK,QAAQ;AACb,OAAK,QAAQ,KAAK,UAAU,KAAK,MAAM;AACvC,OAAK,iBAAiB,WAAW;;CAGnC,WAAqB,QAA6C;AAChE,SAAO,OAAO,WAAW;;CAG3B,iBAAwD,IAAO;AAC7D,OAAK,MAAM,cAAc,KAAK,WAC5B,YAAW,IAAI,KAAK;;;;;;;;;;;;;;;;;;;;;AAuB1B,SAAgB,YACd,GAAG,MACH;AACA,QAAO,IAAI,MAAS,GAAG,KAAK"}
package/dist/index.cjs ADDED
@@ -0,0 +1,13 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_Galena = require("./Galena.cjs");
3
+ const require_Middleware = require("./Middleware.cjs");
4
+ const require_Logger = require("./Logger.cjs");
5
+ const require_Profiler = require("./Profiler.cjs");
6
+ const require_State = require("./State.cjs");
7
+ exports.Galena = require_Galena.Galena;
8
+ exports.Logger = require_Logger.Logger;
9
+ exports.Middleware = require_Middleware.Middleware;
10
+ exports.Profiler = require_Profiler.Profiler;
11
+ exports.State = require_State.State;
12
+ exports.createGalena = require_Galena.createGalena;
13
+ exports.createState = require_State.createState;
@@ -0,0 +1,7 @@
1
+ import { AppSubscriber, GalenaSnapshot, NonFunction, PartialSupport, Setter, StateTypes, Subscriber } from "./types.cjs";
2
+ import { State, createState } from "./State.cjs";
3
+ import { Middleware } from "./Middleware.cjs";
4
+ import { Galena, createGalena } from "./Galena.cjs";
5
+ import { Logger } from "./Logger.cjs";
6
+ import { Profiler } from "./Profiler.cjs";
7
+ export { AppSubscriber, Galena, GalenaSnapshot, Logger, Middleware, NonFunction, PartialSupport, Profiler, Setter, State, StateTypes, Subscriber, createGalena, createState };
@@ -0,0 +1,7 @@
1
+ import { AppSubscriber, GalenaSnapshot, NonFunction, PartialSupport, Setter, StateTypes, Subscriber } from "./types.mjs";
2
+ import { State, createState } from "./State.mjs";
3
+ import { Middleware } from "./Middleware.mjs";
4
+ import { Galena, createGalena } from "./Galena.mjs";
5
+ import { Logger } from "./Logger.mjs";
6
+ import { Profiler } from "./Profiler.mjs";
7
+ export { AppSubscriber, Galena, GalenaSnapshot, Logger, Middleware, NonFunction, PartialSupport, Profiler, Setter, State, StateTypes, Subscriber, createGalena, createState };
package/dist/index.mjs ADDED
@@ -0,0 +1,6 @@
1
+ import { Galena, createGalena } from "./Galena.mjs";
2
+ import { Middleware } from "./Middleware.mjs";
3
+ import { Logger } from "./Logger.mjs";
4
+ import { Profiler } from "./Profiler.mjs";
5
+ import { State, createState } from "./State.mjs";
6
+ export { Galena, Logger, Middleware, Profiler, State, createGalena, createState };
@@ -0,0 +1,16 @@
1
+ import { State } from "./State.cjs";
2
+
3
+ //#region src/types.d.ts
4
+ type NonFunction<T> = T extends ((...args: any[]) => any) ? never : T;
5
+ type PartialSupport<T> = T extends Record<string, any> ? Partial<T> : T;
6
+ type Setter<T> = NonFunction<T> | ((prevState: NonFunction<T>) => NonFunction<T> | Promise<NonFunction<T>>);
7
+ type Subscriber<T> = ((state: NonFunction<T>) => void) | (() => void);
8
+ interface GalenaSnapshot<T extends Record<string, State<any>>, K extends Extract<keyof T, string> = Extract<keyof T, string>> {
9
+ updated: T[K];
10
+ state: T;
11
+ }
12
+ type AppSubscriber<T extends Record<string, State<any>>, K extends Extract<keyof T, string> = Extract<keyof T, string>> = ((payload: GalenaSnapshot<T, K>) => void) | (() => void);
13
+ type StateTypes<T extends Record<string, State<any>>> = ReturnType<T[keyof T]["getSnapshot"]>;
14
+ //#endregion
15
+ export { AppSubscriber, GalenaSnapshot, NonFunction, PartialSupport, Setter, StateTypes, Subscriber };
16
+ //# sourceMappingURL=types.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.cts","names":[],"sources":["../src/types.ts"],"mappings":";;;KAEY,WAAA,MAAiB,CAAA,cAAc,IAAA,2BAA8B,CAAA;AAAA,KAE7D,cAAA,MAAoB,CAAA,SAAU,MAAA,gBAAsB,OAAA,CAAQ,CAAA,IAAK,CAAA;AAAA,KAEjE,MAAA,MACR,WAAA,CAAY,CAAA,MACV,SAAA,EAAW,WAAA,CAAY,CAAA,MAAO,WAAA,CAAY,CAAA,IAAK,OAAA,CAAQ,WAAA,CAAY,CAAA;AAAA,KAE7D,UAAA,QAAkB,KAAA,EAAO,WAAA,CAAY,CAAA;AAAA,UAEhC,cAAA,WACL,MAAA,SAAe,KAAA,kBACf,OAAA,OAAc,CAAA,YAAa,OAAA,OAAc,CAAA;EAEnD,OAAA,EAAS,CAAA,CAAE,CAAA;EACX,KAAA,EAAO,CAAA;AAAA;AAAA,KAGG,aAAA,WACA,MAAA,SAAe,KAAA,kBACf,OAAA,OAAc,CAAA,YAAa,OAAA,OAAc,CAAA,eAC/C,OAAA,EAAS,cAAA,CAAe,CAAA,EAAG,CAAA;AAAA,KAErB,UAAA,WAAqB,MAAA,SAAe,KAAA,UAAe,UAAA,CAC7D,CAAA,OAAQ,CAAA"}
@@ -0,0 +1,16 @@
1
+ import { State } from "./State.mjs";
2
+
3
+ //#region src/types.d.ts
4
+ type NonFunction<T> = T extends ((...args: any[]) => any) ? never : T;
5
+ type PartialSupport<T> = T extends Record<string, any> ? Partial<T> : T;
6
+ type Setter<T> = NonFunction<T> | ((prevState: NonFunction<T>) => NonFunction<T> | Promise<NonFunction<T>>);
7
+ type Subscriber<T> = ((state: NonFunction<T>) => void) | (() => void);
8
+ interface GalenaSnapshot<T extends Record<string, State<any>>, K extends Extract<keyof T, string> = Extract<keyof T, string>> {
9
+ updated: T[K];
10
+ state: T;
11
+ }
12
+ type AppSubscriber<T extends Record<string, State<any>>, K extends Extract<keyof T, string> = Extract<keyof T, string>> = ((payload: GalenaSnapshot<T, K>) => void) | (() => void);
13
+ type StateTypes<T extends Record<string, State<any>>> = ReturnType<T[keyof T]["getSnapshot"]>;
14
+ //#endregion
15
+ export { AppSubscriber, GalenaSnapshot, NonFunction, PartialSupport, Setter, StateTypes, Subscriber };
16
+ //# sourceMappingURL=types.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;KAEY,WAAA,MAAiB,CAAA,cAAc,IAAA,2BAA8B,CAAA;AAAA,KAE7D,cAAA,MAAoB,CAAA,SAAU,MAAA,gBAAsB,OAAA,CAAQ,CAAA,IAAK,CAAA;AAAA,KAEjE,MAAA,MACR,WAAA,CAAY,CAAA,MACV,SAAA,EAAW,WAAA,CAAY,CAAA,MAAO,WAAA,CAAY,CAAA,IAAK,OAAA,CAAQ,WAAA,CAAY,CAAA;AAAA,KAE7D,UAAA,QAAkB,KAAA,EAAO,WAAA,CAAY,CAAA;AAAA,UAEhC,cAAA,WACL,MAAA,SAAe,KAAA,kBACf,OAAA,OAAc,CAAA,YAAa,OAAA,OAAc,CAAA;EAEnD,OAAA,EAAS,CAAA,CAAE,CAAA;EACX,KAAA,EAAO,CAAA;AAAA;AAAA,KAGG,aAAA,WACA,MAAA,SAAe,KAAA,kBACf,OAAA,OAAc,CAAA,YAAa,OAAA,OAAc,CAAA,eAC/C,OAAA,EAAS,cAAA,CAAe,CAAA,EAAG,CAAA;AAAA,KAErB,UAAA,WAAqB,MAAA,SAAe,KAAA,UAAe,UAAA,CAC7D,CAAA,OAAQ,CAAA"}
Binary file
Binary file
package/package.json CHANGED
@@ -1,73 +1,52 @@
1
1
  {
2
2
  "name": "@figliolia/galena",
3
- "version": "2.3.5",
4
- "description": "A performant state management library supporting mutable state, batched updates, middleware and a rich development API",
5
- "main": "dist/cjs/index.js",
6
- "module": "dist/mjs/index.js",
7
- "types": "dist/types/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "import": "./dist/mjs/index.js",
11
- "require": "./dist/cjs/index.js",
12
- "types": "./dist/types/index.d.ts"
13
- }
14
- },
15
- "files": [
16
- "dist",
17
- "src/*"
18
- ],
19
- "author": "Alex Figliolia",
20
- "license": "MIT",
3
+ "version": "3.0.1",
4
+ "description": "A performant state management library supporting middleware and a rich developer API",
21
5
  "homepage": "https://github.com/alexfigliolia/galena#readme",
6
+ "license": "MIT",
7
+ "author": "Alex Figliolia",
22
8
  "repository": {
23
9
  "type": "git",
24
10
  "url": "git+https://github.com/alexfigliolia/galena.git"
25
11
  },
26
- "keywords": [
27
- "state",
28
- "state management",
29
- "mutable",
30
- "extendable",
31
- "event",
32
- "emitter",
33
- "flux",
34
- "island",
35
- "batch",
36
- "performance"
12
+ "files": [
13
+ "dist",
14
+ "src",
15
+ "media"
37
16
  ],
38
- "scripts": {
39
- "build": "ts-packager -e src",
40
- "lint": "tsx ci/commands/Lint.ts",
41
- "test": "tsx ci/commands/Test.ts"
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.mjs",
19
+ "types": "./dist/index.d.cts",
20
+ "exports": {
21
+ ".": {
22
+ "import": "./dist/index.mjs",
23
+ "require": "./dist/index.cjs"
24
+ },
25
+ "./package.json": "./package.json"
42
26
  },
43
- "dependencies": {
44
- "@figliolia/event-emitter": "^1.1.5"
27
+ "publishConfig": {
28
+ "access": "public"
45
29
  },
46
- "peerDependencies": {
47
- "@figliolia/event-emitter": "^1.1.5"
30
+ "scripts": {
31
+ "build": "tsdown",
32
+ "lint": "oxlint --type-aware --type-check --report-unused-disable-directives --fix && oxfmt"
48
33
  },
49
34
  "devDependencies": {
50
- "@figliolia/child-process": "^1.0.1",
51
- "@figliolia/ts-packager": "^1.1.0",
52
- "@types/node": "^20.11.19",
53
- "@typescript-eslint/eslint-plugin": "^5.59.1",
54
- "@typescript-eslint/parser": "^5.59.1",
55
- "eslint": "^8.39.0",
56
- "eslint-config-airbnb": "^19.0.4",
57
- "eslint-config-airbnb-typescript": "^17.0.0",
58
- "eslint-config-prettier": "^8.8.0",
59
- "eslint-import-resolver-typescript": "^3.6.1",
60
- "eslint-plugin-import": "^2.27.5",
61
- "eslint-plugin-json-format": "^2.0.1",
62
- "eslint-plugin-prettier": "^5.1.3",
63
- "eslint-plugin-simple-import-sort": "^10.0.0",
64
- "eslint-plugin-unused-imports": "3",
65
- "prettier": "^3.2.4",
66
- "tsc-alias": "^1.8.8",
67
- "tsx": "^4.7.1",
68
- "typescript": "^5.3.3"
35
+ "@figliolia/event-emitter": "^1.2.0",
36
+ "@typescript-eslint/eslint-plugin": "^8.57.0",
37
+ "@typescript-eslint/parser": "^8.57.0",
38
+ "eslint": "^10.0.3",
39
+ "eslint-import-resolver-typescript": "^4.4.4",
40
+ "eslint-plugin-import": "^2.32.0",
41
+ "eslint-plugin-simple-import-sort": "^12.1.1",
42
+ "eslint-plugin-unused-imports": "^4.4.1",
43
+ "oxfmt": "^0.42.0",
44
+ "oxlint": "^1.36.0",
45
+ "oxlint-tsgolint": "^0.17.0",
46
+ "tsdown": "^0.21.1",
47
+ "typescript": "^5.9.3"
69
48
  },
70
- "publishConfig": {
71
- "access": "public"
49
+ "peerDependencies": {
50
+ "@figliolia/event-emitter": ">=1.2.0"
72
51
  }
73
- }
52
+ }
package/src/Galena.ts ADDED
@@ -0,0 +1,120 @@
1
+ import { EventEmitter } from "@figliolia/event-emitter";
2
+ import type { Middleware } from "./Middleware";
3
+ import type { State } from "./State";
4
+ import type { AppSubscriber, GalenaSnapshot, StateTypes } from "./types";
5
+
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
+ export class Galena<T extends Record<string, State<any>>> {
38
+ private Emitter = new EventEmitter<{ change: GalenaSnapshot<T> }>();
39
+ constructor(
40
+ public readonly state: T,
41
+ ...middleware: Middleware<StateTypes<T>>[]
42
+ ) {
43
+ this.registerMiddleware(...middleware);
44
+ }
45
+
46
+ public get<K extends Extract<keyof T, string>>(key: K) {
47
+ return this.state[key];
48
+ }
49
+
50
+ public subscribe = (subscriber: AppSubscriber<T>) => {
51
+ const ID = this.Emitter.on("change", subscriber);
52
+ const unsubscribers: (() => void)[] = [];
53
+ for (const key in this.state) {
54
+ const instance = this.state[key];
55
+ if (!instance) {
56
+ continue;
57
+ }
58
+ unsubscribers.push(
59
+ instance.subscribe(() =>
60
+ this.emit({ state: this.state, updated: instance }),
61
+ ),
62
+ );
63
+ }
64
+ return () => {
65
+ this.Emitter.off("change", ID);
66
+ while (unsubscribers.length) {
67
+ unsubscribers.pop?.()?.();
68
+ }
69
+ };
70
+ };
71
+
72
+ public registerMiddleware(...middlewares: Middleware<StateTypes<T>>[]) {
73
+ for (const key in this.state) {
74
+ this.state[key]?.registerMiddleware?.(...middlewares);
75
+ }
76
+ }
77
+
78
+ private emit<K extends Extract<keyof T, string>>(
79
+ event: GalenaSnapshot<T, K>,
80
+ ) {
81
+ this.Emitter.emit("change", event);
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Create Galena
87
+ *
88
+ * Galena is designed to house one or more units of `State`
89
+ * and exist as a pseudo global application state.
90
+ *
91
+ * By design, each of its `State` units have isolated reactivity
92
+ * that prevents entire state trees from updating when a single
93
+ * unit changes.
94
+ *
95
+ * This is dissimilar to redux-like models where downstream reconciliations
96
+ * will propagate everwhere a given store is read from. In galena, downstream
97
+ * reconciliations occur only for consumers of the slice of state that
98
+ * changed - making it safer to use with more frequent state changes.
99
+ *
100
+ * ```typescript
101
+ * import { createGalena } from "@figliolia/galena";
102
+ *
103
+ * const AppState = createGalena({
104
+ * // your reactive instances
105
+ * }, ...middleware);
106
+ *
107
+ * // to retreive and work with an individual unit
108
+ * const myUnit = AppState.get("<key>"); // Returns State<T>
109
+ *
110
+ * // to run a callback anytime a unit of state changes
111
+ * const unsubscribe = AppState.subscribe(({ updated }) => {
112
+ * // do something with the `State` instance that updated
113
+ * });
114
+ * ```
115
+ */
116
+ export const createGalena = <T extends Record<string, State<any>>>(
117
+ ...args: ConstructorParameters<typeof Galena<T>>
118
+ ) => {
119
+ return new Galena(...args);
120
+ };
@@ -1,5 +1,5 @@
1
- import { State } from "Galena/State";
2
- import { Middleware } from "Middleware/Middleware";
1
+ import { Middleware } from "./Middleware";
2
+ import type { State } from "./State";
3
3
 
4
4
  /**
5
5
  * Logger
@@ -9,24 +9,26 @@ import { Middleware } from "Middleware/Middleware";
9
9
  * along with a before and after snapshot of the current state:
10
10
  *
11
11
  * ```typescript
12
- * const State = new Galena([new Logger()]);
13
- * // if using isolated state instances:
14
- * const MyState = new State(...args);
15
- * MyState.registerMiddleware(new Logger())
12
+ * const AppState = new Galena({}, new Logger());
13
+ * // or
14
+ * AppState.registerMiddlerware(new Logger());
15
+ * // or
16
+ * const MyState = new State(4, new Logger());
17
+ * // or
18
+ * MyState.registerMiddleware(new Logger());
16
19
  * ```
17
20
  */
18
- export class Logger extends Middleware {
19
- private previousState: Record<string, any> | null = null;
21
+ export class Logger<T = any> extends Middleware {
22
+ private previousState: T | null = null;
20
23
 
21
- override onBeforeUpdate(state: State) {
22
- this.previousState = State.clone(state.state);
24
+ override onBeforeUpdate(state: State<T>) {
25
+ this.previousState = state.getSnapshot();
23
26
  }
24
27
 
25
- override onUpdate(state: State) {
28
+ override onUpdate(state: State<T>) {
26
29
  console.log(
27
30
  "%cMutation:",
28
31
  "color: rgb(187, 186, 186); font-weight: bold",
29
- state.name,
30
32
  "@",
31
33
  this.time,
32
34
  );
@@ -38,9 +40,8 @@ export class Logger extends Middleware {
38
40
  console.log(
39
41
  " %cNext State ",
40
42
  "color: rgb(17, 118, 249); font-weight: bold",
41
- state.getState(),
43
+ state.getSnapshot(),
42
44
  );
43
- this.previousState = null;
44
45
  }
45
46
 
46
47
  /**