@figliolia/galena 2.3.4 → 3.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 (144) 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/GalenaProvider.cjs +50 -0
  10. package/dist/GalenaProvider.d.cts +35 -0
  11. package/dist/GalenaProvider.d.cts.map +1 -0
  12. package/dist/GalenaProvider.d.mts +35 -0
  13. package/dist/GalenaProvider.d.mts.map +1 -0
  14. package/dist/GalenaProvider.mjs +52 -0
  15. package/dist/GalenaProvider.mjs.map +1 -0
  16. package/dist/Logger.cjs +46 -0
  17. package/dist/Logger.d.cts +35 -0
  18. package/dist/Logger.d.cts.map +1 -0
  19. package/dist/Logger.d.mts +35 -0
  20. package/dist/Logger.d.mts.map +1 -0
  21. package/dist/Logger.mjs +48 -0
  22. package/dist/Logger.mjs.map +1 -0
  23. package/dist/Middleware.cjs +62 -0
  24. package/dist/Middleware.d.cts +65 -0
  25. package/dist/Middleware.d.cts.map +1 -0
  26. package/dist/Middleware.d.mts +65 -0
  27. package/dist/Middleware.d.mts.map +1 -0
  28. package/dist/Middleware.mjs +64 -0
  29. package/dist/Middleware.mjs.map +1 -0
  30. package/dist/Profiler.cjs +41 -0
  31. package/dist/Profiler.d.cts +31 -0
  32. package/dist/Profiler.d.cts.map +1 -0
  33. package/dist/Profiler.d.mts +31 -0
  34. package/dist/Profiler.d.mts.map +1 -0
  35. package/dist/Profiler.mjs +43 -0
  36. package/dist/Profiler.mjs.map +1 -0
  37. package/dist/State.cjs +147 -0
  38. package/dist/State.d.cts +114 -0
  39. package/dist/State.d.cts.map +1 -0
  40. package/dist/State.d.mts +114 -0
  41. package/dist/State.d.mts.map +1 -0
  42. package/dist/State.mjs +148 -0
  43. package/dist/State.mjs.map +1 -0
  44. package/dist/commonHooks.cjs +17 -0
  45. package/dist/commonHooks.mjs +18 -0
  46. package/dist/commonHooks.mjs.map +1 -0
  47. package/dist/connect-multi.cjs +42 -0
  48. package/dist/connect-multi.d.cts +10 -0
  49. package/dist/connect-multi.d.cts.map +1 -0
  50. package/dist/connect-multi.d.mts +10 -0
  51. package/dist/connect-multi.d.mts.map +1 -0
  52. package/dist/connect-multi.mjs +44 -0
  53. package/dist/connect-multi.mjs.map +1 -0
  54. package/dist/connect.cjs +41 -0
  55. package/dist/connect.d.cts +9 -0
  56. package/dist/connect.d.cts.map +1 -0
  57. package/dist/connect.d.mts +9 -0
  58. package/dist/connect.d.mts.map +1 -0
  59. package/dist/connect.mjs +43 -0
  60. package/dist/connect.mjs.map +1 -0
  61. package/dist/createUseState.cjs +47 -0
  62. package/dist/createUseState.d.cts +46 -0
  63. package/dist/createUseState.d.cts.map +1 -0
  64. package/dist/createUseState.d.mts +46 -0
  65. package/dist/createUseState.d.mts.map +1 -0
  66. package/dist/createUseState.mjs +49 -0
  67. package/dist/createUseState.mjs.map +1 -0
  68. package/dist/index.cjs +23 -0
  69. package/dist/index.d.cts +12 -0
  70. package/dist/index.d.mts +12 -0
  71. package/dist/index.mjs +11 -0
  72. package/dist/types.d.cts +23 -0
  73. package/dist/types.d.cts.map +1 -0
  74. package/dist/types.d.mts +23 -0
  75. package/dist/types.d.mts.map +1 -0
  76. package/dist/useState.cjs +45 -0
  77. package/dist/useState.d.cts +43 -0
  78. package/dist/useState.d.cts.map +1 -0
  79. package/dist/useState.d.mts +43 -0
  80. package/dist/useState.d.mts.map +1 -0
  81. package/dist/useState.mjs +47 -0
  82. package/dist/useState.mjs.map +1 -0
  83. package/media/Logging.png +0 -0
  84. package/media/Profiling.png +0 -0
  85. package/package.json +38 -59
  86. package/src/Galena.ts +120 -0
  87. package/src/{Middlewares/Logger.ts → Logger.ts} +15 -14
  88. package/src/Middleware.ts +62 -0
  89. package/src/Profiler.ts +53 -0
  90. package/src/State.ts +167 -0
  91. package/src/index.ts +6 -3
  92. package/src/types.ts +28 -0
  93. package/dist/cjs/Galena/Galena.js +0 -223
  94. package/dist/cjs/Galena/Guards.js +0 -40
  95. package/dist/cjs/Galena/Scheduler.js +0 -84
  96. package/dist/cjs/Galena/State.js +0 -314
  97. package/dist/cjs/Galena/index.js +0 -22
  98. package/dist/cjs/Galena/types.js +0 -9
  99. package/dist/cjs/Middleware/Middleware.js +0 -46
  100. package/dist/cjs/Middleware/index.js +0 -20
  101. package/dist/cjs/Middleware/types.js +0 -8
  102. package/dist/cjs/Middlewares/Logger.js +0 -51
  103. package/dist/cjs/Middlewares/Profiler.js +0 -38
  104. package/dist/cjs/Middlewares/index.js +0 -7
  105. package/dist/cjs/index.js +0 -19
  106. package/dist/cjs/package.json +0 -3
  107. package/dist/mjs/Galena/Galena.js +0 -218
  108. package/dist/mjs/Galena/Guards.js +0 -36
  109. package/dist/mjs/Galena/Scheduler.js +0 -79
  110. package/dist/mjs/Galena/State.js +0 -313
  111. package/dist/mjs/Galena/index.js +0 -3
  112. package/dist/mjs/Galena/types.js +0 -6
  113. package/dist/mjs/Middleware/Middleware.js +0 -42
  114. package/dist/mjs/Middleware/index.js +0 -2
  115. package/dist/mjs/Middleware/types.js +0 -5
  116. package/dist/mjs/Middlewares/Logger.js +0 -44
  117. package/dist/mjs/Middlewares/Profiler.js +0 -35
  118. package/dist/mjs/Middlewares/index.js +0 -2
  119. package/dist/mjs/index.js +0 -3
  120. package/dist/mjs/package.json +0 -4
  121. package/dist/types/Galena/Galena.d.ts +0 -160
  122. package/dist/types/Galena/Guards.d.ts +0 -29
  123. package/dist/types/Galena/Scheduler.d.ts +0 -51
  124. package/dist/types/Galena/State.d.ts +0 -235
  125. package/dist/types/Galena/index.d.ts +0 -3
  126. package/dist/types/Galena/types.d.ts +0 -13
  127. package/dist/types/Middleware/Middleware.d.ts +0 -43
  128. package/dist/types/Middleware/index.d.ts +0 -2
  129. package/dist/types/Middleware/types.d.ts +0 -4
  130. package/dist/types/Middlewares/Logger.d.ts +0 -27
  131. package/dist/types/Middlewares/Profiler.d.ts +0 -22
  132. package/dist/types/Middlewares/index.d.ts +0 -2
  133. package/dist/types/index.d.ts +0 -3
  134. package/src/Galena/Galena.ts +0 -252
  135. package/src/Galena/Guards.ts +0 -49
  136. package/src/Galena/Scheduler.ts +0 -85
  137. package/src/Galena/State.ts +0 -344
  138. package/src/Galena/index.ts +0 -3
  139. package/src/Galena/types.ts +0 -18
  140. package/src/Middleware/Middleware.ts +0 -45
  141. package/src/Middleware/index.ts +0 -2
  142. package/src/Middleware/types.ts +0 -4
  143. package/src/Middlewares/Profiler.ts +0 -41
  144. package/src/Middlewares/index.ts +0 -2
@@ -1,313 +0,0 @@
1
- import { EventEmitter } from "@figliolia/event-emitter";
2
- import { MiddlewareEvents } from "../Middleware/types.js";
3
- import { Scheduler } from "./Scheduler.js";
4
- import { Priority } from "./types.js";
5
- /**
6
- * ### State
7
- *
8
- * The root of all reactivity in Galena. State instances can
9
- * operate in isolation by calling `new State(...args)` or as
10
- * part of your application's larger global state by using
11
- * `new Galena().composeState()`.
12
- *
13
- * `State` instances operate on the premise of pub-sub and mutability.
14
- * This provides significant performance improvement over more traditional
15
- * state management tools because
16
- *
17
- * 1. Mutations can occur in O(1) space
18
- * 2. Mutations can be batched when dispatching updates to subscribers
19
- *
20
- * When deciding how many `State` instances are required for your
21
- * applications needs, we suggest creating and organizing state in
22
- * accordance with your application logic. Meaning, you might have a
23
- * `State` instance for navigation/routing, another `State` instance
24
- * for storing user information, and so on. Performance can improve
25
- * significantly when state is dispersed amongst multiple instances
26
- *
27
- * #### Creating State Instances
28
- *
29
- * ```typescript
30
- * const MyState = new State("MyState", {
31
- * someData: true,
32
- * listItems: [1, 2, 3, 4];
33
- * // ...etc
34
- * });
35
- * ```
36
- *
37
- * #### Updating State
38
- * ##### Synchronous updates
39
- * ```typescript
40
- * MyState.update((state) => {
41
- * state.listItems.push(5);
42
- * });
43
- * ```
44
- * ##### Asynchronous updates
45
- * ```typescript
46
- * MyState.update(async (state) => {
47
- * const listItems = await fetch("/list-items");
48
- * state.listItems = listItems;
49
- * });
50
- * ```
51
- *
52
- * #### Subscribing to State Changes
53
- * ```typescript
54
- * MyState.subscribe((state) => {
55
- * const { listItems } = state
56
- * // Do something with your list items!
57
- * });
58
- * ```
59
- */
60
- export class State extends Scheduler {
61
- state;
62
- name;
63
- initialState;
64
- middleware = [];
65
- emitter = new EventEmitter();
66
- constructor(name, initialState) {
67
- super();
68
- this.name = name;
69
- this.state = initialState;
70
- this.initialState = State.clone(initialState);
71
- }
72
- /**
73
- * Get State
74
- *
75
- * Returns a readonly snapshot of the current state
76
- */
77
- getState() {
78
- return this.state;
79
- }
80
- /**
81
- * Update
82
- *
83
- * Mutates state and notifies any open subscriptions. This method
84
- * by default uses task batching for optimized performance. In almost
85
- * every use-case, this method is the correct way to mutate state. If
86
- * you need to bypass batching for higher-priority state updates, you
87
- * can use `State.priorityUpdate()` or `State.backgroundUpdate()`
88
- *
89
- * ##### Synchronous updates
90
- * ```typescript
91
- * MyState.update((state, initialState) => {
92
- * state.listItems.push(5);
93
- * });
94
- * ```
95
- * ##### Asynchronous updates
96
- * ```typescript
97
- * MyState.update(async (state, initialState) => {
98
- * const listItems = await fetch("/list-items");
99
- * state.listItems = listItems;
100
- * });
101
- * ```
102
- */
103
- update = this.mutation((func) => {
104
- return func(this.state, this.initialState);
105
- }, Priority.BATCHED);
106
- /**
107
- * Background Update
108
- *
109
- * Mutates state and notifies any open subscriptions. This method
110
- * bypasses Galena's internal task batching for a more immediate
111
- * state update and propagation of state to consumers. It utilizes
112
- * a micro-task that allows for the current call stack to clear
113
- * ahead of propagating state updates to consumers
114
- *
115
- * ##### Synchronous updates
116
- * ```typescript
117
- * MyState.backgroundUpdate((state, initialState) => {
118
- * state.listItems.push(5);
119
- * });
120
- * ```
121
- * ##### Asynchronous updates
122
- * ```typescript
123
- * MyState.backgroundUpdate(async (state, initialState) => {
124
- * const listItems = await fetch("/list-items");
125
- * state.listItems = listItems;
126
- * });
127
- * ```
128
- */
129
- backgroundUpdate = this.mutation((func) => {
130
- return func(this.state, this.initialState);
131
- }, Priority.MICROTASK);
132
- /**
133
- * Priority Update
134
- *
135
- * Mutates state and notifies any open subscriptions. This method
136
- * bypasses optimizations for task batching and scheduling. This means
137
- * that state updates made with this method propagate to subscriptions
138
- * as immediately as possible. Overusing this method can cause your
139
- * state updates to perform slower in certain cases. The usage of this
140
- * method should be conserved for state mutations that need to occur
141
- * at a certain frame rate
142
- *
143
- * ##### Synchronous updates
144
- * ```typescript
145
- * MyState.priorityUpdate((state, initialState) => {
146
- * state.listItems.push(5);
147
- * });
148
- * ```
149
- * ##### Asynchronous updates
150
- * ```typescript
151
- * MyState.priorityUpdate(async (state, initialState) => {
152
- * const listItems = await fetch("/list-items");
153
- * state.listItems = listItems;
154
- * });
155
- * ```
156
- */
157
- priorityUpdate = this.mutation((func) => {
158
- return func(this.state, this.initialState);
159
- }, Priority.IMMEDIATE);
160
- /**
161
- * Reset
162
- *
163
- * Resets the current state to its initial state
164
- */
165
- reset = this.mutation(() => {
166
- this.state = State.clone(this.initialState);
167
- });
168
- /**
169
- * Mutation
170
- *
171
- * This method can be used to wrap arbitrary functions that when invoked
172
- * will:
173
- * 1. Notify your subscriptions with the latest state
174
- * 2. Execute any registered middleware (such as loggers or profiling tools)
175
- *
176
- * Using this method, developers can compose and extend `Galena`'s internal
177
- * infrastructure for state mutations to create proprietary models for your
178
- * state
179
- *
180
- * ```typescript
181
- * import { State } from "@figliolia/galena";
182
- *
183
- * // Extend of Galena State
184
- * class MyState extends State {
185
- * addListItem = mutation((newListItem) => {
186
- * this.state.list.push(newListItem);
187
- * });
188
- * }
189
- *
190
- * // Create an instance
191
- * const myState = new MyState("myState", { list: [] });
192
- *
193
- * // Invoke your custom mutation method
194
- * myState.addListItem("new-item");
195
- * ```
196
- */
197
- mutation(func, priority = Priority.BATCHED) {
198
- return (...args) => {
199
- this.lifeCycleEvent(MiddlewareEvents.onBeforeUpdate);
200
- const returnValue = func(...args);
201
- if (returnValue instanceof Promise) {
202
- return returnValue.then(v => {
203
- this.scheduleUpdate(priority);
204
- return v;
205
- });
206
- }
207
- this.scheduleUpdate(priority);
208
- return returnValue;
209
- };
210
- }
211
- /**
212
- * Schedule Update
213
- *
214
- * Schedules an update to State subscribers and emits the
215
- * `onUpdate` lifecycle hook
216
- */
217
- scheduleUpdate(priority) {
218
- this.lifeCycleEvent(MiddlewareEvents.onUpdate);
219
- void this.scheduleTask(() => this.emitter.emit(this.name, this.state), priority);
220
- }
221
- /**
222
- * Register Middleware
223
- *
224
- * Caches a `Middleware` instance and invokes its
225
- * lifecycle subscriptions on all state transitions
226
- */
227
- registerMiddleware(...middleware) {
228
- this.middleware.push(...middleware);
229
- }
230
- /**
231
- * Subscribe
232
- *
233
- * Registers a subscription on the state instance. The
234
- * callback you provide will execute each time state changes.
235
- * Returns a unique identifier for your subscription
236
- */
237
- subscribe(callback) {
238
- return this.emitter.on(this.name, callback);
239
- }
240
- /**
241
- * Unsubscribe
242
- *
243
- * Given a subscription ID, removes a registered subscription
244
- * from the `State` instance
245
- */
246
- unsubscribe(ID) {
247
- return this.emitter.off(this.name, ID);
248
- }
249
- /**
250
- * Clear All Subscriptions
251
- *
252
- * Removes all open subscriptions to the `State` instance
253
- */
254
- clearAllSubscriptions() {
255
- return this.emitter.storage.clear();
256
- }
257
- /**
258
- * Life Cycle Event
259
- *
260
- * Triggers a life cycle event for each registered middleware
261
- */
262
- lifeCycleEvent(event) {
263
- const maxIndex = this.middleware.length - 1;
264
- for (let i = maxIndex; i > -1; i--) {
265
- this.middleware[i][event](this);
266
- }
267
- }
268
- /**
269
- * Clone
270
- *
271
- * `State` instances accept any value as a form of reactive
272
- * state. In order to maintain the initial state past any state
273
- * transitions, this method clones the initial values provided
274
- * to the `State` constructor and caches them to allow for
275
- * developers to easily reset their current state back to its
276
- * initial value
277
- */
278
- static clone(state) {
279
- switch (typeof state) {
280
- case "string":
281
- return String(state);
282
- case "bigint":
283
- return BigInt(state);
284
- case "boolean":
285
- return Boolean(state);
286
- case "number":
287
- return Number(state);
288
- case "symbol":
289
- case "function":
290
- return state;
291
- case "undefined":
292
- return undefined;
293
- case "object":
294
- default:
295
- if (!state) {
296
- return null;
297
- }
298
- if (Array.isArray(state)) {
299
- return [...state];
300
- }
301
- if (state instanceof Set) {
302
- return new Set(state);
303
- }
304
- if (state instanceof Map) {
305
- return new Map(state);
306
- }
307
- if (state && typeof state === "object") {
308
- return { ...state };
309
- }
310
- return state;
311
- }
312
- }
313
- }
@@ -1,3 +0,0 @@
1
- export { Galena } from "./Galena.js";
2
- export { State } from "./State.js";
3
- export * from "./types.js";
@@ -1,6 +0,0 @@
1
- export var Priority;
2
- (function (Priority) {
3
- Priority[Priority["IMMEDIATE"] = 1] = "IMMEDIATE";
4
- Priority[Priority["MICROTASK"] = 2] = "MICROTASK";
5
- Priority[Priority["BATCHED"] = 3] = "BATCHED";
6
- })(Priority || (Priority = {}));
@@ -1,42 +0,0 @@
1
- /**
2
- * # Middleware
3
- *
4
- * A root interface for all `Galena` Middleware. When creating
5
- * a middleware for your `Galena` state, simply extend this
6
- * class any override any of its public lifecycle methods.
7
- *
8
- * ### Creating a Profiling Middleware
9
- *
10
- * ```typescript
11
- * export class ProfilerMiddleware extends Middleware {
12
- * updateState: number | null = null;
13
- *
14
- * override onBeforeUpdate(state: State) {
15
- * this.updateStart = performance.now();
16
- * }
17
- *
18
- * override onUpdate(state: State) {
19
- * if(this.updateStart) {
20
- * const timeToUpdate = performance.now() - this.updateStart;
21
- * if(timeToUpdate > 16) {
22
- * console.warn("A state transition took more than 16 milliseconds!", State);
23
- * }
24
- * }
25
- * }
26
- * }
27
- * ```
28
- */
29
- export class Middleware {
30
- /**
31
- * On Before Update
32
- *
33
- * An event emitted each time a `State` mutation is enqueued
34
- */
35
- onBeforeUpdate(_state) { }
36
- /**
37
- * On Update
38
- *
39
- * An event emitted each time a `State` instance is mutated
40
- */
41
- onUpdate(_state) { }
42
- }
@@ -1,2 +0,0 @@
1
- export { Middleware } from "./Middleware.js";
2
- export * from "./types.js";
@@ -1,5 +0,0 @@
1
- export var MiddlewareEvents;
2
- (function (MiddlewareEvents) {
3
- MiddlewareEvents["onUpdate"] = "onUpdate";
4
- MiddlewareEvents["onBeforeUpdate"] = "onBeforeUpdate";
5
- })(MiddlewareEvents || (MiddlewareEvents = {}));
@@ -1,44 +0,0 @@
1
- import { State } from "../Galena/State.js";
2
- import { Middleware } from "../Middleware/Middleware.js";
3
- /**
4
- * Logger
5
- *
6
- * A middleware for Redux-style logging! Each state transition
7
- * will log to the console the `State` instance that changed
8
- * along with a before and after snapshot of the current state:
9
- *
10
- * ```typescript
11
- * const State = new Galena([new Logger()]);
12
- * // if using isolated state instances:
13
- * const MyState = new State(...args);
14
- * MyState.registerMiddleware(new Logger())
15
- * ```
16
- */
17
- export class Logger extends Middleware {
18
- previousState = null;
19
- onBeforeUpdate(state) {
20
- this.previousState = State.clone(state.state);
21
- }
22
- onUpdate(state) {
23
- console.log("%cMutation:", "color: rgb(187, 186, 186); font-weight: bold", state.name, "@", this.time);
24
- console.log(" %cPrevious State", "color: #26ad65; font-weight: bold", this.previousState);
25
- console.log(" %cNext State ", "color: rgb(17, 118, 249); font-weight: bold", state.getState());
26
- this.previousState = null;
27
- }
28
- /**
29
- * Time
30
- *
31
- * Returns the time in which a given state transition completed
32
- */
33
- get time() {
34
- const date = new Date();
35
- const mHours = date.getHours();
36
- const hours = mHours > 12 ? mHours - 12 : mHours;
37
- const mins = date.getMinutes();
38
- const minutes = mins.toString().length === 1 ? `0${mins}` : mins;
39
- const secs = date.getSeconds();
40
- const seconds = secs.toString().length === 1 ? `0${secs}` : secs;
41
- const milliseconds = date.getMilliseconds();
42
- return `${hours}:${minutes}:${seconds}:${milliseconds}`;
43
- }
44
- }
@@ -1,35 +0,0 @@
1
- import { Middleware } from "../Middleware/Middleware.js";
2
- /**
3
- * Profiler
4
- *
5
- * A logger for state transitions exceeding a given threshold
6
- * for duration:
7
- *
8
- * ```typescript
9
- * const State = new Galena([new Profiler()]);
10
- * // if using isolated state instances:
11
- * const MyState = new State(...args);
12
- * MyState.registerMiddleware(new Profiler())
13
- * ```
14
- */
15
- export class Profiler extends Middleware {
16
- threshold;
17
- startTime = null;
18
- constructor(threshold = 16) {
19
- super();
20
- this.threshold = threshold;
21
- }
22
- onBeforeUpdate(_) {
23
- this.startTime = performance.now();
24
- }
25
- onUpdate(nextState) {
26
- if (this.startTime) {
27
- const endTime = performance.now();
28
- const diff = endTime - this.startTime;
29
- if (diff > this.threshold) {
30
- console.warn(`A slow state transition was detected on ${nextState.name}`, nextState.getState());
31
- console.warn(`The last transition took ${diff}ms`);
32
- }
33
- }
34
- }
35
- }
@@ -1,2 +0,0 @@
1
- export { Logger } from "./Logger.js";
2
- export { Profiler } from "./Profiler.js";
package/dist/mjs/index.js DELETED
@@ -1,3 +0,0 @@
1
- export * from "./Galena/index.js";
2
- export * from "./Middleware/index.js";
3
- export * from "./Middlewares/index.js";
@@ -1,4 +0,0 @@
1
- {
2
- "type": "module",
3
- "exports": "./index.js"
4
- }
@@ -1,160 +0,0 @@
1
- import { State } from "./State";
2
- import type { Middleware } from "../Middleware/Middleware";
3
- import { Guards } from "./Guards";
4
- import type { Subscription } from "./types";
5
- /**
6
- * ## Galena
7
- *
8
- * A performant global state solution that scales
9
- *
10
- * ### Creating State
11
- *
12
- * ```typescript
13
- * // AppState.ts
14
- * import { Galena } from "@figliolia/galena";
15
- *
16
- * const AppState = new Galena([...middleware]);
17
- *
18
- * const NavigationState = AppState.composeState("navigation", {
19
- * currentRoute: "/",
20
- * userID: "12345",
21
- * permittedRoutes: ["/*"]
22
- * });
23
- * ```
24
- *
25
- * ### Subscribing to State Changes
26
- * #### Using the Galena Instance
27
- * ```typescript
28
- * import { AppState } from "./AppState";
29
- *
30
- * AppState.subscribe(appState => {
31
- * const navState = appState.get("navigation");
32
- * const { currentRoute } = navState.state;
33
- * // do something with state changes!
34
- * });
35
- * ```
36
- * #### Using the State Instance
37
- * ```typescript
38
- * NavigationState.subscribe(navigation => {
39
- * const { currentRoute } = navigation
40
- * // do something with state changes!
41
- * });
42
- * ```
43
- *
44
- * #### Using Global Subscriptions
45
- * ```typescript
46
- * NavigationState.subscribeAll(nextState => {
47
- * const { currentRoute } = nextState.navigation
48
- * // do something with state changes!
49
- * });
50
- * ```
51
- *
52
- * ### Mutating State
53
- * ```typescript
54
- * NavigationState.update(state => {
55
- * state.currentRoute = "/profile";
56
- * // You can mutate state without creating new objects!
57
- * });
58
- * ```
59
- */
60
- export declare class Galena<T extends Record<string, State<any>> = Record<string, State<any>>> extends Guards {
61
- readonly state: T;
62
- private readonly middleware;
63
- private readonly IDs;
64
- private readonly subscriptions;
65
- constructor(middleware?: Middleware[]);
66
- /**
67
- * Compose State
68
- *
69
- * Creates a new `State` instance and returns it. Your new state
70
- * becomes immediately available on your `Galena` instance and
71
- * is wired into your middleware. All existing subscriptions to
72
- * state will automatically receive updates when your new unit of
73
- * state updates
74
- */
75
- composeState<S extends Record<string, any>, M extends typeof State<S>>(name: string, initialState: S, Model?: M): InstanceType<M>;
76
- /**
77
- * Get State
78
- *
79
- * Returns a mutable state instance
80
- */
81
- getState(): Readonly<T>;
82
- /**
83
- * Get
84
- *
85
- * Returns a unit of `State` by name
86
- */
87
- get<K extends Extract<keyof T, string>>(name: K): T[K];
88
- /**
89
- * Mutable
90
- *
91
- * Returns a mutable state instance
92
- */
93
- private get mutable();
94
- /**
95
- * Update
96
- *
97
- * Runs a mutation on the specified unit of state
98
- */
99
- update<K extends Extract<keyof T, string>>(name: K, mutation: Parameters<T[K]["update"]>["0"]): any;
100
- /**
101
- * Background Update
102
- *
103
- * Runs a higher priority mutation on the specified unit of
104
- * state
105
- */
106
- backgroundUpdate<K extends Extract<keyof T, string>>(name: K, mutation: Parameters<T[K]["backgroundUpdate"]>["0"]): any;
107
- /**
108
- * Priority Update
109
- *
110
- * Runs an immediate priority mutation on the specified unit
111
- * of state
112
- */
113
- priorityUpdate<K extends Extract<keyof T, string>>(name: K, mutation: Parameters<T[K]["priorityUpdate"]>["0"]): any;
114
- /**
115
- * Subscribe
116
- *
117
- * Given the name of a unit of state, this method registers
118
- * a subscription on the target state instance. The callback
119
- * you provide will execute each time state changes. Returns
120
- * a unique identifier for your subscription. To clean up your
121
- * subscription, call `Galena.unsubscribe()` with the ID returned
122
- * by this method
123
- */
124
- subscribe<K extends Extract<keyof T, string>>(name: K, callback: Parameters<T[K]["subscribe"]>["0"]): string;
125
- /**
126
- * Unsubscribe
127
- *
128
- * Given a subscription ID returned from the `subscribe` method,
129
- * this method removes and cleans up the corresponding subscription
130
- */
131
- unsubscribe<K extends Extract<keyof T, string>>(name: K, ID: string): boolean | undefined;
132
- /**
133
- * Subscribe All
134
- *
135
- * Registers a callback on each registered `State` instance and
136
- * is invoked each time your state changes. Using `Galena`'s
137
- * `subscribeAll` method, although performant, can be less
138
- * performant than subscribing directly to a target `State`
139
- * instance using `Galena.subscribe()`. To clean up your
140
- * subscription, call `Galena.unsubscribeAll()` with the ID
141
- * returned
142
- */
143
- subscribeAll(callback: Subscription<T>): string;
144
- /**
145
- * Unsubscribe
146
- *
147
- * Given a subscription ID returned from the `subscribeAll()` method,
148
- * this method removes and cleans up the corresponding subscription
149
- */
150
- unsubscribeAll(ID: string): void;
151
- /**
152
- * ReIndex Subscriptions
153
- *
154
- * When units of state are created lazily, this method updates
155
- * each existing subscription to receive mutations occurring on
156
- * recently created `State` instances that post-date prior
157
- * subscriptions
158
- */
159
- private reIndexSubscriptions;
160
- }
@@ -1,29 +0,0 @@
1
- import type { State } from "./State";
2
- /**
3
- * Guards
4
- *
5
- * Development-only warnings and runtime errors designed to
6
- * guard developers against possible pitfalls when using
7
- * Galena. This interface provides composable error and
8
- * warning methods that can be used to prevent invalid usage
9
- * of the library
10
- */
11
- export declare class Guards {
12
- /**
13
- * Warn For Undefined States
14
- *
15
- * In Galena, it's normal to lazy initialize a unit of state
16
- * in attached to a `Galena` instance. This warning lets
17
- * developers know that they are attempting to manipulate a
18
- * unit of state that has not yet been initialized
19
- */
20
- protected warnForUndefinedStates<T extends Record<string, State<any>>>(name: string, state: T): void;
21
- /**
22
- * Guard Duplicate States
23
- *
24
- * Throws an error if a developer attempts to create
25
- * more than one state with the same name on a single
26
- * `Galena` instance
27
- */
28
- protected guardDuplicateStates<T extends Record<string, State<any>>>(name: string, state: T): void;
29
- }