@figliolia/galena 2.3.5 → 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.
- package/README.md +172 -476
- package/dist/Galena.cjs +102 -0
- package/dist/Galena.d.cts +80 -0
- package/dist/Galena.d.cts.map +1 -0
- package/dist/Galena.d.mts +80 -0
- package/dist/Galena.d.mts.map +1 -0
- package/dist/Galena.mjs +103 -0
- package/dist/Galena.mjs.map +1 -0
- package/dist/GalenaProvider.cjs +50 -0
- package/dist/GalenaProvider.d.cts +35 -0
- package/dist/GalenaProvider.d.cts.map +1 -0
- package/dist/GalenaProvider.d.mts +35 -0
- package/dist/GalenaProvider.d.mts.map +1 -0
- package/dist/GalenaProvider.mjs +52 -0
- package/dist/GalenaProvider.mjs.map +1 -0
- package/dist/Logger.cjs +46 -0
- package/dist/Logger.d.cts +35 -0
- package/dist/Logger.d.cts.map +1 -0
- package/dist/Logger.d.mts +35 -0
- package/dist/Logger.d.mts.map +1 -0
- package/dist/Logger.mjs +48 -0
- package/dist/Logger.mjs.map +1 -0
- package/dist/Middleware.cjs +62 -0
- package/dist/Middleware.d.cts +65 -0
- package/dist/Middleware.d.cts.map +1 -0
- package/dist/Middleware.d.mts +65 -0
- package/dist/Middleware.d.mts.map +1 -0
- package/dist/Middleware.mjs +64 -0
- package/dist/Middleware.mjs.map +1 -0
- package/dist/Profiler.cjs +41 -0
- package/dist/Profiler.d.cts +31 -0
- package/dist/Profiler.d.cts.map +1 -0
- package/dist/Profiler.d.mts +31 -0
- package/dist/Profiler.d.mts.map +1 -0
- package/dist/Profiler.mjs +43 -0
- package/dist/Profiler.mjs.map +1 -0
- package/dist/State.cjs +147 -0
- package/dist/State.d.cts +114 -0
- package/dist/State.d.cts.map +1 -0
- package/dist/State.d.mts +114 -0
- package/dist/State.d.mts.map +1 -0
- package/dist/State.mjs +148 -0
- package/dist/State.mjs.map +1 -0
- package/dist/commonHooks.cjs +17 -0
- package/dist/commonHooks.mjs +18 -0
- package/dist/commonHooks.mjs.map +1 -0
- package/dist/connect-multi.cjs +42 -0
- package/dist/connect-multi.d.cts +10 -0
- package/dist/connect-multi.d.cts.map +1 -0
- package/dist/connect-multi.d.mts +10 -0
- package/dist/connect-multi.d.mts.map +1 -0
- package/dist/connect-multi.mjs +44 -0
- package/dist/connect-multi.mjs.map +1 -0
- package/dist/connect.cjs +41 -0
- package/dist/connect.d.cts +9 -0
- package/dist/connect.d.cts.map +1 -0
- package/dist/connect.d.mts +9 -0
- package/dist/connect.d.mts.map +1 -0
- package/dist/connect.mjs +43 -0
- package/dist/connect.mjs.map +1 -0
- package/dist/createUseState.cjs +47 -0
- package/dist/createUseState.d.cts +46 -0
- package/dist/createUseState.d.cts.map +1 -0
- package/dist/createUseState.d.mts +46 -0
- package/dist/createUseState.d.mts.map +1 -0
- package/dist/createUseState.mjs +49 -0
- package/dist/createUseState.mjs.map +1 -0
- package/dist/index.cjs +23 -0
- package/dist/index.d.cts +12 -0
- package/dist/index.d.mts +12 -0
- package/dist/index.mjs +11 -0
- package/dist/types.d.cts +23 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +23 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/useState.cjs +45 -0
- package/dist/useState.d.cts +43 -0
- package/dist/useState.d.cts.map +1 -0
- package/dist/useState.d.mts +43 -0
- package/dist/useState.d.mts.map +1 -0
- package/dist/useState.mjs +47 -0
- package/dist/useState.mjs.map +1 -0
- package/media/Logging.png +0 -0
- package/media/Profiling.png +0 -0
- package/package.json +38 -59
- package/src/Galena.ts +120 -0
- package/src/{Middlewares/Logger.ts → Logger.ts} +15 -14
- package/src/Middleware.ts +62 -0
- package/src/Profiler.ts +53 -0
- package/src/State.ts +167 -0
- package/src/index.ts +6 -3
- package/src/types.ts +28 -0
- package/dist/cjs/Galena/Galena.js +0 -223
- package/dist/cjs/Galena/Guards.js +0 -40
- package/dist/cjs/Galena/Scheduler.js +0 -84
- package/dist/cjs/Galena/State.js +0 -314
- package/dist/cjs/Galena/index.js +0 -22
- package/dist/cjs/Galena/types.js +0 -9
- package/dist/cjs/Middleware/Middleware.js +0 -46
- package/dist/cjs/Middleware/index.js +0 -20
- package/dist/cjs/Middleware/types.js +0 -8
- package/dist/cjs/Middlewares/Logger.js +0 -51
- package/dist/cjs/Middlewares/Profiler.js +0 -38
- package/dist/cjs/Middlewares/index.js +0 -7
- package/dist/cjs/index.js +0 -19
- package/dist/cjs/package.json +0 -3
- package/dist/mjs/Galena/Galena.js +0 -218
- package/dist/mjs/Galena/Guards.js +0 -36
- package/dist/mjs/Galena/Scheduler.js +0 -79
- package/dist/mjs/Galena/State.js +0 -313
- package/dist/mjs/Galena/index.js +0 -3
- package/dist/mjs/Galena/types.js +0 -6
- package/dist/mjs/Middleware/Middleware.js +0 -42
- package/dist/mjs/Middleware/index.js +0 -2
- package/dist/mjs/Middleware/types.js +0 -5
- package/dist/mjs/Middlewares/Logger.js +0 -44
- package/dist/mjs/Middlewares/Profiler.js +0 -35
- package/dist/mjs/Middlewares/index.js +0 -2
- package/dist/mjs/index.js +0 -3
- package/dist/mjs/package.json +0 -4
- package/dist/types/Galena/Galena.d.ts +0 -160
- package/dist/types/Galena/Guards.d.ts +0 -29
- package/dist/types/Galena/Scheduler.d.ts +0 -51
- package/dist/types/Galena/State.d.ts +0 -235
- package/dist/types/Galena/index.d.ts +0 -3
- package/dist/types/Galena/types.d.ts +0 -13
- package/dist/types/Middleware/Middleware.d.ts +0 -43
- package/dist/types/Middleware/index.d.ts +0 -2
- package/dist/types/Middleware/types.d.ts +0 -4
- package/dist/types/Middlewares/Logger.d.ts +0 -27
- package/dist/types/Middlewares/Profiler.d.ts +0 -22
- package/dist/types/Middlewares/index.d.ts +0 -2
- package/dist/types/index.d.ts +0 -3
- package/src/Galena/Galena.ts +0 -252
- package/src/Galena/Guards.ts +0 -49
- package/src/Galena/Scheduler.ts +0 -85
- package/src/Galena/State.ts +0 -344
- package/src/Galena/index.ts +0 -3
- package/src/Galena/types.ts +0 -18
- package/src/Middleware/Middleware.ts +0 -45
- package/src/Middleware/index.ts +0 -2
- package/src/Middleware/types.ts +0 -4
- package/src/Middlewares/Profiler.ts +0 -41
- package/src/Middlewares/index.ts +0 -2
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Galena = void 0;
|
|
4
|
-
const event_emitter_1 = require("@figliolia/event-emitter");
|
|
5
|
-
const State_1 = require("./State");
|
|
6
|
-
const Guards_1 = require("./Guards");
|
|
7
|
-
/**
|
|
8
|
-
* ## Galena
|
|
9
|
-
*
|
|
10
|
-
* A performant global state solution that scales
|
|
11
|
-
*
|
|
12
|
-
* ### Creating State
|
|
13
|
-
*
|
|
14
|
-
* ```typescript
|
|
15
|
-
* // AppState.ts
|
|
16
|
-
* import { Galena } from "@figliolia/galena";
|
|
17
|
-
*
|
|
18
|
-
* const AppState = new Galena([...middleware]);
|
|
19
|
-
*
|
|
20
|
-
* const NavigationState = AppState.composeState("navigation", {
|
|
21
|
-
* currentRoute: "/",
|
|
22
|
-
* userID: "12345",
|
|
23
|
-
* permittedRoutes: ["/*"]
|
|
24
|
-
* });
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* ### Subscribing to State Changes
|
|
28
|
-
* #### Using the Galena Instance
|
|
29
|
-
* ```typescript
|
|
30
|
-
* import { AppState } from "./AppState";
|
|
31
|
-
*
|
|
32
|
-
* AppState.subscribe(appState => {
|
|
33
|
-
* const navState = appState.get("navigation");
|
|
34
|
-
* const { currentRoute } = navState.state;
|
|
35
|
-
* // do something with state changes!
|
|
36
|
-
* });
|
|
37
|
-
* ```
|
|
38
|
-
* #### Using the State Instance
|
|
39
|
-
* ```typescript
|
|
40
|
-
* NavigationState.subscribe(navigation => {
|
|
41
|
-
* const { currentRoute } = navigation
|
|
42
|
-
* // do something with state changes!
|
|
43
|
-
* });
|
|
44
|
-
* ```
|
|
45
|
-
*
|
|
46
|
-
* #### Using Global Subscriptions
|
|
47
|
-
* ```typescript
|
|
48
|
-
* NavigationState.subscribeAll(nextState => {
|
|
49
|
-
* const { currentRoute } = nextState.navigation
|
|
50
|
-
* // do something with state changes!
|
|
51
|
-
* });
|
|
52
|
-
* ```
|
|
53
|
-
*
|
|
54
|
-
* ### Mutating State
|
|
55
|
-
* ```typescript
|
|
56
|
-
* NavigationState.update(state => {
|
|
57
|
-
* state.currentRoute = "/profile";
|
|
58
|
-
* // You can mutate state without creating new objects!
|
|
59
|
-
* });
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
class Galena extends Guards_1.Guards {
|
|
63
|
-
constructor(middleware = []) {
|
|
64
|
-
super();
|
|
65
|
-
this.state = {};
|
|
66
|
-
this.middleware = [];
|
|
67
|
-
this.IDs = new event_emitter_1.AutoIncrementingID();
|
|
68
|
-
this.subscriptions = new Map();
|
|
69
|
-
this.middleware = middleware;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Compose State
|
|
73
|
-
*
|
|
74
|
-
* Creates a new `State` instance and returns it. Your new state
|
|
75
|
-
* becomes immediately available on your `Galena` instance and
|
|
76
|
-
* is wired into your middleware. All existing subscriptions to
|
|
77
|
-
* state will automatically receive updates when your new unit of
|
|
78
|
-
* state updates
|
|
79
|
-
*/
|
|
80
|
-
composeState(name, initialState, Model) {
|
|
81
|
-
this.guardDuplicateStates(name, this.state);
|
|
82
|
-
const StateModel = Model || (State_1.State);
|
|
83
|
-
const state = new StateModel(name, initialState);
|
|
84
|
-
state.registerMiddleware(...this.middleware);
|
|
85
|
-
this.mutable[name] = state;
|
|
86
|
-
this.reIndexSubscriptions(name);
|
|
87
|
-
return state;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Get State
|
|
91
|
-
*
|
|
92
|
-
* Returns a mutable state instance
|
|
93
|
-
*/
|
|
94
|
-
getState() {
|
|
95
|
-
return this.state;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Get
|
|
99
|
-
*
|
|
100
|
-
* Returns a unit of `State` by name
|
|
101
|
-
*/
|
|
102
|
-
get(name) {
|
|
103
|
-
this.warnForUndefinedStates(name, this.state);
|
|
104
|
-
return this.state[name];
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Mutable
|
|
108
|
-
*
|
|
109
|
-
* Returns a mutable state instance
|
|
110
|
-
*/
|
|
111
|
-
get mutable() {
|
|
112
|
-
return this.state;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Update
|
|
116
|
-
*
|
|
117
|
-
* Runs a mutation on the specified unit of state
|
|
118
|
-
*/
|
|
119
|
-
update(name, mutation) {
|
|
120
|
-
return this.get(name).update(mutation);
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Background Update
|
|
124
|
-
*
|
|
125
|
-
* Runs a higher priority mutation on the specified unit of
|
|
126
|
-
* state
|
|
127
|
-
*/
|
|
128
|
-
backgroundUpdate(name, mutation) {
|
|
129
|
-
return this.get(name).backgroundUpdate(mutation);
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Priority Update
|
|
133
|
-
*
|
|
134
|
-
* Runs an immediate priority mutation on the specified unit
|
|
135
|
-
* of state
|
|
136
|
-
*/
|
|
137
|
-
priorityUpdate(name, mutation) {
|
|
138
|
-
return this.get(name).priorityUpdate(mutation);
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Subscribe
|
|
142
|
-
*
|
|
143
|
-
* Given the name of a unit of state, this method registers
|
|
144
|
-
* a subscription on the target state instance. The callback
|
|
145
|
-
* you provide will execute each time state changes. Returns
|
|
146
|
-
* a unique identifier for your subscription. To clean up your
|
|
147
|
-
* subscription, call `Galena.unsubscribe()` with the ID returned
|
|
148
|
-
* by this method
|
|
149
|
-
*/
|
|
150
|
-
subscribe(name, callback) {
|
|
151
|
-
return this.get(name).subscribe(callback);
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* Unsubscribe
|
|
155
|
-
*
|
|
156
|
-
* Given a subscription ID returned from the `subscribe` method,
|
|
157
|
-
* this method removes and cleans up the corresponding subscription
|
|
158
|
-
*/
|
|
159
|
-
unsubscribe(name, ID) {
|
|
160
|
-
return this.get(name).unsubscribe(ID);
|
|
161
|
-
}
|
|
162
|
-
/**
|
|
163
|
-
* Subscribe All
|
|
164
|
-
*
|
|
165
|
-
* Registers a callback on each registered `State` instance and
|
|
166
|
-
* is invoked each time your state changes. Using `Galena`'s
|
|
167
|
-
* `subscribeAll` method, although performant, can be less
|
|
168
|
-
* performant than subscribing directly to a target `State`
|
|
169
|
-
* instance using `Galena.subscribe()`. To clean up your
|
|
170
|
-
* subscription, call `Galena.unsubscribeAll()` with the ID
|
|
171
|
-
* returned
|
|
172
|
-
*/
|
|
173
|
-
subscribeAll(callback) {
|
|
174
|
-
const stateSubscriptions = [];
|
|
175
|
-
for (const key in this.state) {
|
|
176
|
-
stateSubscriptions.push([
|
|
177
|
-
key,
|
|
178
|
-
this.state[key].subscribe(() => {
|
|
179
|
-
void callback(this.state);
|
|
180
|
-
}),
|
|
181
|
-
]);
|
|
182
|
-
}
|
|
183
|
-
const subscriptionID = this.IDs.get();
|
|
184
|
-
this.subscriptions.set(subscriptionID, stateSubscriptions);
|
|
185
|
-
return subscriptionID;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Unsubscribe
|
|
189
|
-
*
|
|
190
|
-
* Given a subscription ID returned from the `subscribeAll()` method,
|
|
191
|
-
* this method removes and cleans up the corresponding subscription
|
|
192
|
-
*/
|
|
193
|
-
unsubscribeAll(ID) {
|
|
194
|
-
const IDs = this.subscriptions.get(ID);
|
|
195
|
-
if (IDs) {
|
|
196
|
-
for (const [state, ID] of IDs) {
|
|
197
|
-
this.state[state].unsubscribe(ID);
|
|
198
|
-
}
|
|
199
|
-
this.subscriptions.delete(ID);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* ReIndex Subscriptions
|
|
204
|
-
*
|
|
205
|
-
* When units of state are created lazily, this method updates
|
|
206
|
-
* each existing subscription to receive mutations occurring on
|
|
207
|
-
* recently created `State` instances that post-date prior
|
|
208
|
-
* subscriptions
|
|
209
|
-
*/
|
|
210
|
-
reIndexSubscriptions(name) {
|
|
211
|
-
var _a, _b;
|
|
212
|
-
for (const [ID, unitSubscriptions] of this.subscriptions) {
|
|
213
|
-
const [stateName, listenerID] = unitSubscriptions[0];
|
|
214
|
-
const subscriptions = this.state[stateName]["emitter"].storage.get(stateName);
|
|
215
|
-
const listener = (_b = (_a = subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.storage) === null || _a === void 0 ? void 0 : _a.get) === null || _b === void 0 ? void 0 : _b.call(_a, listenerID);
|
|
216
|
-
if (listener) {
|
|
217
|
-
unitSubscriptions.push([name, this.state[name].subscribe(listener)]);
|
|
218
|
-
this.subscriptions.set(ID, unitSubscriptions);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
exports.Galena = Galena;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Guards = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Guards
|
|
6
|
-
*
|
|
7
|
-
* Development-only warnings and runtime errors designed to
|
|
8
|
-
* guard developers against possible pitfalls when using
|
|
9
|
-
* Galena. This interface provides composable error and
|
|
10
|
-
* warning methods that can be used to prevent invalid usage
|
|
11
|
-
* of the library
|
|
12
|
-
*/
|
|
13
|
-
class Guards {
|
|
14
|
-
/**
|
|
15
|
-
* Warn For Undefined States
|
|
16
|
-
*
|
|
17
|
-
* In Galena, it's normal to lazy initialize a unit of state
|
|
18
|
-
* in attached to a `Galena` instance. This warning lets
|
|
19
|
-
* developers know that they are attempting to manipulate a
|
|
20
|
-
* unit of state that has not yet been initialized
|
|
21
|
-
*/
|
|
22
|
-
warnForUndefinedStates(name, state) {
|
|
23
|
-
if (!(name in state)) {
|
|
24
|
-
console.warn(`A unit of state with the name "${name}" does not yet exist on this Galena instance. If this is expected, you can ignore this warning`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Guard Duplicate States
|
|
29
|
-
*
|
|
30
|
-
* Throws an error if a developer attempts to create
|
|
31
|
-
* more than one state with the same name on a single
|
|
32
|
-
* `Galena` instance
|
|
33
|
-
*/
|
|
34
|
-
guardDuplicateStates(name, state) {
|
|
35
|
-
if (name in state) {
|
|
36
|
-
console.warn(`A unit of state with the name "${name}" already exists on this Galena instance. Please re-name this new unit of state to something unique`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
exports.Guards = Guards;
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Scheduler = void 0;
|
|
4
|
-
const types_1 = require("./types");
|
|
5
|
-
/**
|
|
6
|
-
* Scheduler
|
|
7
|
-
*
|
|
8
|
-
* Scheduling dispatched events to state consumers is how Galena
|
|
9
|
-
* out-performs just about every state management library out there.
|
|
10
|
-
* The scheduler offers the ability to dispatch state updates on 3
|
|
11
|
-
* priorities:
|
|
12
|
-
*
|
|
13
|
-
* 1. Immediate - Immediate synchronous task execution and propagation of
|
|
14
|
-
* changes to consumers
|
|
15
|
-
* 2. Microtask - Immediate task execution and scheduled propagation of
|
|
16
|
-
* changes to consumers
|
|
17
|
-
* 3. Batched - Immediate task execution and batched propagation of
|
|
18
|
-
* changes to consumers
|
|
19
|
-
*
|
|
20
|
-
* This module manages the propagation of changes to State consumers
|
|
21
|
-
* by implementing the three priorities outlined above
|
|
22
|
-
*/
|
|
23
|
-
class Scheduler {
|
|
24
|
-
constructor() {
|
|
25
|
-
this.task = null;
|
|
26
|
-
this.schedule = null;
|
|
27
|
-
this.executeTasks = this.executeTasks.bind(this);
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Schedule Task
|
|
31
|
-
*
|
|
32
|
-
* Given a task (the emission of state changes to consumers)
|
|
33
|
-
* and a priority, this method executes the task on the priority
|
|
34
|
-
* level specified
|
|
35
|
-
*/
|
|
36
|
-
scheduleTask(task, priority) {
|
|
37
|
-
this.task = task;
|
|
38
|
-
switch (priority) {
|
|
39
|
-
case types_1.Priority.IMMEDIATE:
|
|
40
|
-
return this.executeTasks();
|
|
41
|
-
case types_1.Priority.MICROTASK:
|
|
42
|
-
return Promise.resolve().then(() => {
|
|
43
|
-
return this.executeTasks();
|
|
44
|
-
});
|
|
45
|
-
case types_1.Priority.BATCHED:
|
|
46
|
-
default:
|
|
47
|
-
if (!this.schedule) {
|
|
48
|
-
this.createSchedule();
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Create Schedule
|
|
54
|
-
*
|
|
55
|
-
* Schedules the execution of the current task after 5 milliseconds
|
|
56
|
-
*/
|
|
57
|
-
createSchedule() {
|
|
58
|
-
this.clearSchedule();
|
|
59
|
-
this.schedule = setTimeout(this.executeTasks, 5);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Clear Schedule
|
|
63
|
-
*
|
|
64
|
-
* Clears the schedule if it exists
|
|
65
|
-
*/
|
|
66
|
-
clearSchedule() {
|
|
67
|
-
if (this.schedule !== null) {
|
|
68
|
-
clearTimeout(this.schedule);
|
|
69
|
-
this.schedule = null;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Execute Tasks
|
|
74
|
-
*
|
|
75
|
-
* Clears the schedule if it exists and executes the current task
|
|
76
|
-
*/
|
|
77
|
-
executeTasks() {
|
|
78
|
-
var _a;
|
|
79
|
-
this.clearSchedule();
|
|
80
|
-
(_a = this.task) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
81
|
-
this.task = null;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
exports.Scheduler = Scheduler;
|
package/dist/cjs/Galena/State.js
DELETED
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.State = void 0;
|
|
4
|
-
const event_emitter_1 = require("@figliolia/event-emitter");
|
|
5
|
-
const types_1 = require("../Middleware/types");
|
|
6
|
-
const Scheduler_1 = require("./Scheduler");
|
|
7
|
-
const types_2 = require("./types");
|
|
8
|
-
/**
|
|
9
|
-
* ### State
|
|
10
|
-
*
|
|
11
|
-
* The root of all reactivity in Galena. State instances can
|
|
12
|
-
* operate in isolation by calling `new State(...args)` or as
|
|
13
|
-
* part of your application's larger global state by using
|
|
14
|
-
* `new Galena().composeState()`.
|
|
15
|
-
*
|
|
16
|
-
* `State` instances operate on the premise of pub-sub and mutability.
|
|
17
|
-
* This provides significant performance improvement over more traditional
|
|
18
|
-
* state management tools because
|
|
19
|
-
*
|
|
20
|
-
* 1. Mutations can occur in O(1) space
|
|
21
|
-
* 2. Mutations can be batched when dispatching updates to subscribers
|
|
22
|
-
*
|
|
23
|
-
* When deciding how many `State` instances are required for your
|
|
24
|
-
* applications needs, we suggest creating and organizing state in
|
|
25
|
-
* accordance with your application logic. Meaning, you might have a
|
|
26
|
-
* `State` instance for navigation/routing, another `State` instance
|
|
27
|
-
* for storing user information, and so on. Performance can improve
|
|
28
|
-
* significantly when state is dispersed amongst multiple instances
|
|
29
|
-
*
|
|
30
|
-
* #### Creating State Instances
|
|
31
|
-
*
|
|
32
|
-
* ```typescript
|
|
33
|
-
* const MyState = new State("MyState", {
|
|
34
|
-
* someData: true,
|
|
35
|
-
* listItems: [1, 2, 3, 4];
|
|
36
|
-
* // ...etc
|
|
37
|
-
* });
|
|
38
|
-
* ```
|
|
39
|
-
*
|
|
40
|
-
* #### Updating State
|
|
41
|
-
* ##### Synchronous updates
|
|
42
|
-
* ```typescript
|
|
43
|
-
* MyState.update((state) => {
|
|
44
|
-
* state.listItems.push(5);
|
|
45
|
-
* });
|
|
46
|
-
* ```
|
|
47
|
-
* ##### Asynchronous updates
|
|
48
|
-
* ```typescript
|
|
49
|
-
* MyState.update(async (state) => {
|
|
50
|
-
* const listItems = await fetch("/list-items");
|
|
51
|
-
* state.listItems = listItems;
|
|
52
|
-
* });
|
|
53
|
-
* ```
|
|
54
|
-
*
|
|
55
|
-
* #### Subscribing to State Changes
|
|
56
|
-
* ```typescript
|
|
57
|
-
* MyState.subscribe((state) => {
|
|
58
|
-
* const { listItems } = state
|
|
59
|
-
* // Do something with your list items!
|
|
60
|
-
* });
|
|
61
|
-
* ```
|
|
62
|
-
*/
|
|
63
|
-
class State extends Scheduler_1.Scheduler {
|
|
64
|
-
constructor(name, initialState) {
|
|
65
|
-
super();
|
|
66
|
-
this.middleware = [];
|
|
67
|
-
this.emitter = new event_emitter_1.EventEmitter();
|
|
68
|
-
/**
|
|
69
|
-
* Update
|
|
70
|
-
*
|
|
71
|
-
* Mutates state and notifies any open subscriptions. This method
|
|
72
|
-
* by default uses task batching for optimized performance. In almost
|
|
73
|
-
* every use-case, this method is the correct way to mutate state. If
|
|
74
|
-
* you need to bypass batching for higher-priority state updates, you
|
|
75
|
-
* can use `State.priorityUpdate()` or `State.backgroundUpdate()`
|
|
76
|
-
*
|
|
77
|
-
* ##### Synchronous updates
|
|
78
|
-
* ```typescript
|
|
79
|
-
* MyState.update((state, initialState) => {
|
|
80
|
-
* state.listItems.push(5);
|
|
81
|
-
* });
|
|
82
|
-
* ```
|
|
83
|
-
* ##### Asynchronous updates
|
|
84
|
-
* ```typescript
|
|
85
|
-
* MyState.update(async (state, initialState) => {
|
|
86
|
-
* const listItems = await fetch("/list-items");
|
|
87
|
-
* state.listItems = listItems;
|
|
88
|
-
* });
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
this.update = this.mutation((func) => {
|
|
92
|
-
return func(this.state, this.initialState);
|
|
93
|
-
}, types_2.Priority.BATCHED);
|
|
94
|
-
/**
|
|
95
|
-
* Background Update
|
|
96
|
-
*
|
|
97
|
-
* Mutates state and notifies any open subscriptions. This method
|
|
98
|
-
* bypasses Galena's internal task batching for a more immediate
|
|
99
|
-
* state update and propagation of state to consumers. It utilizes
|
|
100
|
-
* a micro-task that allows for the current call stack to clear
|
|
101
|
-
* ahead of propagating state updates to consumers
|
|
102
|
-
*
|
|
103
|
-
* ##### Synchronous updates
|
|
104
|
-
* ```typescript
|
|
105
|
-
* MyState.backgroundUpdate((state, initialState) => {
|
|
106
|
-
* state.listItems.push(5);
|
|
107
|
-
* });
|
|
108
|
-
* ```
|
|
109
|
-
* ##### Asynchronous updates
|
|
110
|
-
* ```typescript
|
|
111
|
-
* MyState.backgroundUpdate(async (state, initialState) => {
|
|
112
|
-
* const listItems = await fetch("/list-items");
|
|
113
|
-
* state.listItems = listItems;
|
|
114
|
-
* });
|
|
115
|
-
* ```
|
|
116
|
-
*/
|
|
117
|
-
this.backgroundUpdate = this.mutation((func) => {
|
|
118
|
-
return func(this.state, this.initialState);
|
|
119
|
-
}, types_2.Priority.MICROTASK);
|
|
120
|
-
/**
|
|
121
|
-
* Priority Update
|
|
122
|
-
*
|
|
123
|
-
* Mutates state and notifies any open subscriptions. This method
|
|
124
|
-
* bypasses optimizations for task batching and scheduling. This means
|
|
125
|
-
* that state updates made with this method propagate to subscriptions
|
|
126
|
-
* as immediately as possible. Overusing this method can cause your
|
|
127
|
-
* state updates to perform slower in certain cases. The usage of this
|
|
128
|
-
* method should be conserved for state mutations that need to occur
|
|
129
|
-
* at a certain frame rate
|
|
130
|
-
*
|
|
131
|
-
* ##### Synchronous updates
|
|
132
|
-
* ```typescript
|
|
133
|
-
* MyState.priorityUpdate((state, initialState) => {
|
|
134
|
-
* state.listItems.push(5);
|
|
135
|
-
* });
|
|
136
|
-
* ```
|
|
137
|
-
* ##### Asynchronous updates
|
|
138
|
-
* ```typescript
|
|
139
|
-
* MyState.priorityUpdate(async (state, initialState) => {
|
|
140
|
-
* const listItems = await fetch("/list-items");
|
|
141
|
-
* state.listItems = listItems;
|
|
142
|
-
* });
|
|
143
|
-
* ```
|
|
144
|
-
*/
|
|
145
|
-
this.priorityUpdate = this.mutation((func) => {
|
|
146
|
-
return func(this.state, this.initialState);
|
|
147
|
-
}, types_2.Priority.IMMEDIATE);
|
|
148
|
-
/**
|
|
149
|
-
* Reset
|
|
150
|
-
*
|
|
151
|
-
* Resets the current state to its initial state
|
|
152
|
-
*/
|
|
153
|
-
this.reset = this.mutation(() => {
|
|
154
|
-
this.state = State.clone(this.initialState);
|
|
155
|
-
});
|
|
156
|
-
this.name = name;
|
|
157
|
-
this.state = initialState;
|
|
158
|
-
this.initialState = State.clone(initialState);
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Get State
|
|
162
|
-
*
|
|
163
|
-
* Returns a readonly snapshot of the current state
|
|
164
|
-
*/
|
|
165
|
-
getState() {
|
|
166
|
-
return this.state;
|
|
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 = types_2.Priority.BATCHED) {
|
|
198
|
-
return (...args) => {
|
|
199
|
-
this.lifeCycleEvent(types_1.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(types_1.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 Object.assign({}, state);
|
|
309
|
-
}
|
|
310
|
-
return state;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
exports.State = State;
|
package/dist/cjs/Galena/index.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.State = exports.Galena = void 0;
|
|
18
|
-
var Galena_1 = require("./Galena");
|
|
19
|
-
Object.defineProperty(exports, "Galena", { enumerable: true, get: function () { return Galena_1.Galena; } });
|
|
20
|
-
var State_1 = require("./State");
|
|
21
|
-
Object.defineProperty(exports, "State", { enumerable: true, get: function () { return State_1.State; } });
|
|
22
|
-
__exportStar(require("./types"), exports);
|
package/dist/cjs/Galena/types.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Priority = void 0;
|
|
4
|
-
var Priority;
|
|
5
|
-
(function (Priority) {
|
|
6
|
-
Priority[Priority["IMMEDIATE"] = 1] = "IMMEDIATE";
|
|
7
|
-
Priority[Priority["MICROTASK"] = 2] = "MICROTASK";
|
|
8
|
-
Priority[Priority["BATCHED"] = 3] = "BATCHED";
|
|
9
|
-
})(Priority || (exports.Priority = Priority = {}));
|