@figliolia/galena 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Galena.ts CHANGED
@@ -1,27 +1,30 @@
1
1
  import { EventEmitter } from "@figliolia/event-emitter";
2
2
  import type { Middleware } from "./Middleware";
3
3
  import type { State } from "./State";
4
- import type { AppSubscriber, GalenaSnapshot, StateTypes } from "./types";
4
+ import type {
5
+ AppSubscriber,
6
+ GalenaSnapshot,
7
+ Setter,
8
+ StateType,
9
+ StateTypes,
10
+ } from "./types";
5
11
 
6
12
  /**
7
- * Galena
13
+ * ### Galena
8
14
  *
9
- * Galena is designed to house one or more units of `State`
15
+ * Galena instances are designed to house one or more units of `State`
10
16
  * and exist as a pseudo global application state.
11
17
  *
12
18
  * By design, each of its `State` units have isolated reactivity
13
19
  * that prevents entire state trees from updating when a single
14
20
  * unit changes.
15
21
  *
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
22
  * ```typescript
22
23
  * import { Galena } from "@figliolia/galena";
23
24
  *
24
25
  * const AppState = new Galena({
26
+ * user: new State("<user-stuff>"),
27
+ * business: new State("<business-logic-stuff>")
25
28
  * // your reactive instances
26
29
  * }, ...middleware);
27
30
  *
@@ -29,8 +32,9 @@ import type { AppSubscriber, GalenaSnapshot, StateTypes } from "./types";
29
32
  * const myUnit = AppState.get("<key>"); // Returns State<T>
30
33
  *
31
34
  * // to run a callback anytime a unit of state changes
32
- * const unsubscribe = AppState.subscribe(({ updated }) => {
35
+ * const listener = AppState.subscribe(({ state, updated }) => {
33
36
  * // do something with the `State` instance that updated
37
+ * // the entirety of your state
34
38
  * });
35
39
  * ```
36
40
  */
@@ -43,10 +47,47 @@ export class Galena<T extends Record<string, State<any>>> {
43
47
  this.registerMiddleware(...middleware);
44
48
  }
45
49
 
50
+ /**
51
+ * Get
52
+ *
53
+ * Returns a connected State instance by key
54
+ */
46
55
  public get<K extends Extract<keyof T, string>>(key: K) {
47
56
  return this.state[key];
48
57
  }
49
58
 
59
+ /**
60
+ * Set
61
+ *
62
+ * Sets a connected State instance's state by key
63
+ */
64
+ public set<K extends Extract<keyof T, string>>(
65
+ key: K,
66
+ value: StateType<T[K]>,
67
+ ) {
68
+ return this.get(key).set(value);
69
+ }
70
+
71
+ /**
72
+ * Update
73
+ *
74
+ * Invokes a connected State instance's update method key
75
+ */
76
+ public update<K extends Extract<keyof T, string>>(
77
+ key: K,
78
+ updater: Setter<StateType<T[K]>>,
79
+ ) {
80
+ return this.get(key).update(updater);
81
+ }
82
+
83
+ /**
84
+ * Subscribe
85
+ *
86
+ * Listen for changes on your Galena instnace. Your provided
87
+ * callback will be invoked each time an attached state instance
88
+ * changes. To your callback will be provided the `updated` state
89
+ * instance, along with the entire `state` tree
90
+ */
50
91
  public subscribe = (subscriber: AppSubscriber<T>) => {
51
92
  const ID = this.Emitter.on("change", subscriber);
52
93
  const unsubscribers: (() => void)[] = [];
@@ -69,6 +110,12 @@ export class Galena<T extends Record<string, State<any>>> {
69
110
  };
70
111
  };
71
112
 
113
+ /**
114
+ * Register Middleware
115
+ *
116
+ * Adds middleware instances to each of the connected
117
+ * `State` instances
118
+ */
72
119
  public registerMiddleware(...middlewares: Middleware<StateTypes<T>>[]) {
73
120
  for (const key in this.state) {
74
121
  this.state[key]?.registerMiddleware?.(...middlewares);
@@ -83,24 +130,21 @@ export class Galena<T extends Record<string, State<any>>> {
83
130
  }
84
131
 
85
132
  /**
86
- * Create Galena
133
+ * ### createGalena
87
134
  *
88
- * Galena is designed to house one or more units of `State`
135
+ * Galena instances are designed to house one or more units of `State`
89
136
  * and exist as a pseudo global application state.
90
137
  *
91
138
  * By design, each of its `State` units have isolated reactivity
92
139
  * that prevents entire state trees from updating when a single
93
140
  * unit changes.
94
141
  *
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
142
  * ```typescript
101
- * import { createGalena } from "@figliolia/galena";
143
+ * import { Galena } from "@figliolia/galena";
102
144
  *
103
- * const AppState = createGalena({
145
+ * const AppState = new Galena({
146
+ * user: new State("<user-stuff>"),
147
+ * business: new State("<business-logic-stuff>")
104
148
  * // your reactive instances
105
149
  * }, ...middleware);
106
150
  *
@@ -108,8 +152,9 @@ export class Galena<T extends Record<string, State<any>>> {
108
152
  * const myUnit = AppState.get("<key>"); // Returns State<T>
109
153
  *
110
154
  * // to run a callback anytime a unit of state changes
111
- * const unsubscribe = AppState.subscribe(({ updated }) => {
155
+ * const listener = AppState.subscribe(({ state, updated }) => {
112
156
  * // do something with the `State` instance that updated
157
+ * // the entirety of your state
113
158
  * });
114
159
  * ```
115
160
  */
package/src/State.ts CHANGED
@@ -3,7 +3,7 @@ import type { Middleware } from "./Middleware";
3
3
  import type { NonFunction, Setter, Subscriber } from "./types";
4
4
 
5
5
  /**
6
- * State
6
+ * ### State
7
7
  *
8
8
  * The unit of reactivity for Galena. `State`'s can act
9
9
  * as isolated instances or be part of your global app
@@ -12,7 +12,7 @@ import type { NonFunction, Setter, Subscriber } from "./types";
12
12
  * There are three ways to create state instances
13
13
  *
14
14
  * ```typescript
15
- * import { State, createState, useState, Profiler } from "@figliolia/galena";
15
+ * import { State, createState, Profiler } from "@figliolia/galena";
16
16
  * // for island states that can be shared between react components
17
17
  * const myState = new State("<any value>", ...middleware);
18
18
  * // or
@@ -22,17 +22,7 @@ import type { NonFunction, Setter, Subscriber } from "./types";
22
22
  * myState.update(previousValue => "<new-value>");
23
23
  * myState.subscribe(nextValue => {});
24
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
- * }
25
+ * myState.reset(); // reset back to it's original value
36
26
  * ```
37
27
  */
38
28
  export class State<T> {
@@ -143,21 +133,26 @@ export class State<T> {
143
133
  }
144
134
 
145
135
  /**
146
- * Create State
136
+ * ### createState
147
137
  *
148
- * Returns the unit of reactivity for Galena. `State`'s can act
138
+ * The unit of reactivity for Galena. `State`'s can act
149
139
  * as isolated instances or be part of your global app
150
- * state (via `Galena` instances);
140
+ * state (via `Galena` instances).
151
141
  *
152
- * ```typescript
153
- * import { createState, Profiler } from "@figliolia/galena";
142
+ * There are three ways to create state instances
154
143
  *
144
+ * ```typescript
145
+ * import { State, createState, Profiler } from "@figliolia/galena";
146
+ * // for island states that can be shared between react components
147
+ * const myState = new State("<any value>", ...middleware);
148
+ * // or
155
149
  * const myState = createState("<any value>", ...middleware);
156
150
  *
157
151
  * myState.set("<new-value>");
158
152
  * myState.update(previousValue => "<new-value>");
159
153
  * myState.subscribe(nextValue => {});
160
154
  * myState.registerMiddleware(new Profiler());
155
+ * myState.reset(); // reset back to it's original value
161
156
  * ```
162
157
  */
163
158
  export function createState<T>(
package/src/types.ts CHANGED
@@ -24,5 +24,7 @@ export type AppSubscriber<
24
24
  > = ((payload: GalenaSnapshot<T, K>) => void) | (() => void);
25
25
 
26
26
  export type StateTypes<T extends Record<string, State<any>>> = ReturnType<
27
- T[keyof T]["getSnapshot"]
27
+ StateType<T[keyof T]>
28
28
  >;
29
+
30
+ export type StateType<T extends State<any>> = ReturnType<T["getSnapshot"]>;