@figliolia/galena 2.0.1 → 2.0.2
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/dist/Galena/Galena.d.ts +9 -8
- package/dist/Galena/Galena.js +7 -3
- package/dist/Galena/Guards.d.ts +36 -0
- package/dist/Galena/Guards.js +55 -0
- package/package.json +1 -1
- package/src/Galena/Galena.ts +14 -10
- package/src/Galena/Guards.ts +67 -0
package/dist/Galena/Galena.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Middleware } from "../Middleware/Middleware";
|
|
2
2
|
import { State } from "./State";
|
|
3
|
+
import { Guards } from "./Guards";
|
|
3
4
|
/**
|
|
4
5
|
* ## Galena
|
|
5
6
|
*
|
|
@@ -55,11 +56,11 @@ import { State } from "./State";
|
|
|
55
56
|
* });
|
|
56
57
|
* ```
|
|
57
58
|
*/
|
|
58
|
-
export declare class Galena<T extends Record<string, State<any>> = Record<string, State<any>>> {
|
|
59
|
+
export declare class Galena<T extends Record<string, State<any>> = Record<string, State<any>>> extends Guards {
|
|
59
60
|
readonly state: T;
|
|
61
|
+
private readonly subscriptions;
|
|
60
62
|
private readonly middleware;
|
|
61
63
|
private readonly IDs;
|
|
62
|
-
private readonly subscriptions;
|
|
63
64
|
constructor(middleware?: Middleware[]);
|
|
64
65
|
/**
|
|
65
66
|
* Compose State
|
|
@@ -76,7 +77,7 @@ export declare class Galena<T extends Record<string, State<any>> = Record<string
|
|
|
76
77
|
*
|
|
77
78
|
* Returns a unit of `State` by name
|
|
78
79
|
*/
|
|
79
|
-
get<K extends keyof T
|
|
80
|
+
get<K extends Extract<keyof T, string>>(name: K): T[K];
|
|
80
81
|
/**
|
|
81
82
|
* Mutable
|
|
82
83
|
*
|
|
@@ -88,21 +89,21 @@ export declare class Galena<T extends Record<string, State<any>> = Record<string
|
|
|
88
89
|
*
|
|
89
90
|
* Runs a mutation on the specified unit of state
|
|
90
91
|
*/
|
|
91
|
-
update<K extends keyof T
|
|
92
|
+
update<K extends Extract<keyof T, string>>(name: K, mutation: Parameters<T[K]["update"]>["0"]): any;
|
|
92
93
|
/**
|
|
93
94
|
* Background Update
|
|
94
95
|
*
|
|
95
96
|
* Runs a higher priority mutation on the specified unit of
|
|
96
97
|
* state
|
|
97
98
|
*/
|
|
98
|
-
backgroundUpdate<K extends keyof T
|
|
99
|
+
backgroundUpdate<K extends Extract<keyof T, string>>(name: K, mutation: Parameters<T[K]["backgroundUpdate"]>["0"]): any;
|
|
99
100
|
/**
|
|
100
101
|
* Priority Update
|
|
101
102
|
*
|
|
102
103
|
* Runs an immediate priority mutation on the specified unit
|
|
103
104
|
* of state
|
|
104
105
|
*/
|
|
105
|
-
priorityUpdate<K extends keyof T
|
|
106
|
+
priorityUpdate<K extends Extract<keyof T, string>>(name: K, mutation: Parameters<T[K]["priorityUpdate"]>["0"]): any;
|
|
106
107
|
/**
|
|
107
108
|
* Subscribe
|
|
108
109
|
*
|
|
@@ -113,14 +114,14 @@ export declare class Galena<T extends Record<string, State<any>> = Record<string
|
|
|
113
114
|
* subscription, call `Galena.unsubscribe()` with the ID returned
|
|
114
115
|
* by this method
|
|
115
116
|
*/
|
|
116
|
-
subscribe<K extends keyof T
|
|
117
|
+
subscribe<K extends Extract<keyof T, string>>(name: K, callback: Parameters<T[K]["subscribe"]>["0"]): string;
|
|
117
118
|
/**
|
|
118
119
|
* Unsubscribe
|
|
119
120
|
*
|
|
120
121
|
* Given a subscription ID returned from the `subscribe` method,
|
|
121
122
|
* this method removes and cleans up the corresponding subscription
|
|
122
123
|
*/
|
|
123
|
-
unsubscribe<K extends keyof T
|
|
124
|
+
unsubscribe<K extends Extract<keyof T, string>>(name: K, ID: string): boolean | undefined;
|
|
124
125
|
/**
|
|
125
126
|
* Subscribe All
|
|
126
127
|
*
|
package/dist/Galena/Galena.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Galena = void 0;
|
|
4
4
|
const event_emitter_1 = require("@figliolia/event-emitter");
|
|
5
5
|
const State_1 = require("./State");
|
|
6
|
+
const Guards_1 = require("./Guards");
|
|
6
7
|
/**
|
|
7
8
|
* ## Galena
|
|
8
9
|
*
|
|
@@ -58,12 +59,13 @@ const State_1 = require("./State");
|
|
|
58
59
|
* });
|
|
59
60
|
* ```
|
|
60
61
|
*/
|
|
61
|
-
class Galena {
|
|
62
|
+
class Galena extends Guards_1.Guards {
|
|
62
63
|
constructor(middleware = []) {
|
|
64
|
+
super();
|
|
63
65
|
this.state = {};
|
|
66
|
+
this.subscriptions = new Map();
|
|
64
67
|
this.middleware = [];
|
|
65
68
|
this.IDs = new event_emitter_1.AutoIncrementingID();
|
|
66
|
-
this.subscriptions = new Map();
|
|
67
69
|
this.middleware = middleware;
|
|
68
70
|
}
|
|
69
71
|
/**
|
|
@@ -78,6 +80,7 @@ class Galena {
|
|
|
78
80
|
composeState(name, initialState,
|
|
79
81
|
// @ts-ignore
|
|
80
82
|
Model = (State_1.State)) {
|
|
83
|
+
this.guardDuplicateStates(name, this.state);
|
|
81
84
|
const state = new Model(name, initialState);
|
|
82
85
|
state.registerMiddleware(...this.middleware);
|
|
83
86
|
this.mutable[name] = state;
|
|
@@ -90,6 +93,7 @@ class Galena {
|
|
|
90
93
|
* Returns a unit of `State` by name
|
|
91
94
|
*/
|
|
92
95
|
get(name) {
|
|
96
|
+
this.warnForUndefinedStates(name, this.state);
|
|
93
97
|
return this.state[name];
|
|
94
98
|
}
|
|
95
99
|
/**
|
|
@@ -160,7 +164,6 @@ class Galena {
|
|
|
160
164
|
* returned
|
|
161
165
|
*/
|
|
162
166
|
subscribeAll(callback) {
|
|
163
|
-
const subscriptionID = this.IDs.get();
|
|
164
167
|
const stateSubscriptions = [];
|
|
165
168
|
for (const key in this.state) {
|
|
166
169
|
stateSubscriptions.push([
|
|
@@ -170,6 +173,7 @@ class Galena {
|
|
|
170
173
|
}),
|
|
171
174
|
]);
|
|
172
175
|
}
|
|
176
|
+
const subscriptionID = this.IDs.get();
|
|
173
177
|
this.subscriptions.set(subscriptionID, stateSubscriptions);
|
|
174
178
|
return subscriptionID;
|
|
175
179
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
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: (name: string, state: Record<string, State<any>>) => 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: (name: string, state: Record<string, State<any>>) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Development Guard
|
|
31
|
+
*
|
|
32
|
+
* Wraps a provided function in a check for `process.env.NODE_ENV`
|
|
33
|
+
* equaling "development". Returns the callback
|
|
34
|
+
*/
|
|
35
|
+
private developmentGuard;
|
|
36
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
constructor() {
|
|
15
|
+
/**
|
|
16
|
+
* Warn For Undefined States
|
|
17
|
+
*
|
|
18
|
+
* In Galena, it's normal to lazy initialize a unit of state
|
|
19
|
+
* in attached to a `Galena` instance. This warning lets
|
|
20
|
+
* developers know that they are attempting to manipulate a
|
|
21
|
+
* unit of state that has not yet been initialized
|
|
22
|
+
*/
|
|
23
|
+
this.warnForUndefinedStates = this.developmentGuard((name, state) => {
|
|
24
|
+
if (!process.env.IGNORE_LAZY_STATE_WARNINGS && !(name in state)) {
|
|
25
|
+
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. To make these warnings go away, you can enable this process argument - "IGNORE_WARNINGS_FOR_LAZY_STATES=1"`);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Guard Duplicate States
|
|
30
|
+
*
|
|
31
|
+
* Throws an error if a developer attempts to create
|
|
32
|
+
* more than one state with the same name on a single
|
|
33
|
+
* `Galena` instance
|
|
34
|
+
*/
|
|
35
|
+
this.guardDuplicateStates = this.developmentGuard((name, state) => {
|
|
36
|
+
if (name in state) {
|
|
37
|
+
throw new Error(`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`);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Development Guard
|
|
43
|
+
*
|
|
44
|
+
* Wraps a provided function in a check for `process.env.NODE_ENV`
|
|
45
|
+
* equaling "development". Returns the callback
|
|
46
|
+
*/
|
|
47
|
+
developmentGuard(guard) {
|
|
48
|
+
return (...args) => {
|
|
49
|
+
if (process.env.NODE_ENV === "development") {
|
|
50
|
+
guard(...args);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.Guards = Guards;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@figliolia/galena",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "A performant state management library supporting mutable state, batched updates, middleware and a rich development API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/src/Galena/Galena.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { AutoIncrementingID } from "@figliolia/event-emitter";
|
|
|
3
3
|
import type { Middleware } from "Middleware/Middleware";
|
|
4
4
|
|
|
5
5
|
import { State } from "Galena/State";
|
|
6
|
+
import { Guards } from "./Guards";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* ## Galena
|
|
@@ -61,15 +62,16 @@ import { State } from "Galena/State";
|
|
|
61
62
|
*/
|
|
62
63
|
export class Galena<
|
|
63
64
|
T extends Record<string, State<any>> = Record<string, State<any>>
|
|
64
|
-
> {
|
|
65
|
+
> extends Guards {
|
|
65
66
|
public readonly state = {} as T;
|
|
66
|
-
private readonly middleware: Middleware[] = [];
|
|
67
|
-
private readonly IDs = new AutoIncrementingID();
|
|
68
67
|
private readonly subscriptions = new Map<
|
|
69
68
|
string,
|
|
70
69
|
[state: string, ID: string][]
|
|
71
70
|
>();
|
|
71
|
+
private readonly middleware: Middleware[] = [];
|
|
72
|
+
private readonly IDs = new AutoIncrementingID();
|
|
72
73
|
constructor(middleware: Middleware[] = []) {
|
|
74
|
+
super();
|
|
73
75
|
this.middleware = middleware;
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -91,6 +93,7 @@ export class Galena<
|
|
|
91
93
|
// @ts-ignore
|
|
92
94
|
Model: M = State<S>
|
|
93
95
|
) {
|
|
96
|
+
this.guardDuplicateStates(name, this.state);
|
|
94
97
|
const state = new Model(name, initialState);
|
|
95
98
|
state.registerMiddleware(...this.middleware);
|
|
96
99
|
this.mutable[name] = state;
|
|
@@ -103,7 +106,8 @@ export class Galena<
|
|
|
103
106
|
*
|
|
104
107
|
* Returns a unit of `State` by name
|
|
105
108
|
*/
|
|
106
|
-
public get<K extends keyof T
|
|
109
|
+
public get<K extends Extract<keyof T, string>>(name: K): T[K] {
|
|
110
|
+
this.warnForUndefinedStates(name, this.state);
|
|
107
111
|
return this.state[name];
|
|
108
112
|
}
|
|
109
113
|
|
|
@@ -121,7 +125,7 @@ export class Galena<
|
|
|
121
125
|
*
|
|
122
126
|
* Runs a mutation on the specified unit of state
|
|
123
127
|
*/
|
|
124
|
-
public update<K extends keyof T
|
|
128
|
+
public update<K extends Extract<keyof T, string>>(
|
|
125
129
|
name: K,
|
|
126
130
|
mutation: Parameters<T[K]["update"]>["0"]
|
|
127
131
|
) {
|
|
@@ -134,7 +138,7 @@ export class Galena<
|
|
|
134
138
|
* Runs a higher priority mutation on the specified unit of
|
|
135
139
|
* state
|
|
136
140
|
*/
|
|
137
|
-
public backgroundUpdate<K extends keyof T
|
|
141
|
+
public backgroundUpdate<K extends Extract<keyof T, string>>(
|
|
138
142
|
name: K,
|
|
139
143
|
mutation: Parameters<T[K]["backgroundUpdate"]>["0"]
|
|
140
144
|
) {
|
|
@@ -147,7 +151,7 @@ export class Galena<
|
|
|
147
151
|
* Runs an immediate priority mutation on the specified unit
|
|
148
152
|
* of state
|
|
149
153
|
*/
|
|
150
|
-
public priorityUpdate<K extends keyof T
|
|
154
|
+
public priorityUpdate<K extends Extract<keyof T, string>>(
|
|
151
155
|
name: K,
|
|
152
156
|
mutation: Parameters<T[K]["priorityUpdate"]>["0"]
|
|
153
157
|
) {
|
|
@@ -164,7 +168,7 @@ export class Galena<
|
|
|
164
168
|
* subscription, call `Galena.unsubscribe()` with the ID returned
|
|
165
169
|
* by this method
|
|
166
170
|
*/
|
|
167
|
-
public subscribe<K extends keyof T
|
|
171
|
+
public subscribe<K extends Extract<keyof T, string>>(
|
|
168
172
|
name: K,
|
|
169
173
|
callback: Parameters<T[K]["subscribe"]>["0"]
|
|
170
174
|
) {
|
|
@@ -177,7 +181,7 @@ export class Galena<
|
|
|
177
181
|
* Given a subscription ID returned from the `subscribe` method,
|
|
178
182
|
* this method removes and cleans up the corresponding subscription
|
|
179
183
|
*/
|
|
180
|
-
public unsubscribe<K extends keyof T
|
|
184
|
+
public unsubscribe<K extends Extract<keyof T, string>>(name: K, ID: string) {
|
|
181
185
|
return this.get(name).unsubscribe(ID);
|
|
182
186
|
}
|
|
183
187
|
|
|
@@ -193,7 +197,6 @@ export class Galena<
|
|
|
193
197
|
* returned
|
|
194
198
|
*/
|
|
195
199
|
public subscribeAll(callback: (nextState: T) => void) {
|
|
196
|
-
const subscriptionID = this.IDs.get();
|
|
197
200
|
const stateSubscriptions: [state: string, ID: string][] = [];
|
|
198
201
|
for (const key in this.state) {
|
|
199
202
|
stateSubscriptions.push([
|
|
@@ -203,6 +206,7 @@ export class Galena<
|
|
|
203
206
|
}),
|
|
204
207
|
]);
|
|
205
208
|
}
|
|
209
|
+
const subscriptionID = this.IDs.get();
|
|
206
210
|
this.subscriptions.set(subscriptionID, stateSubscriptions);
|
|
207
211
|
return subscriptionID;
|
|
208
212
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { State } from "./State";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Guards
|
|
5
|
+
*
|
|
6
|
+
* Development-only warnings and runtime errors designed to
|
|
7
|
+
* guard developers against possible pitfalls when using
|
|
8
|
+
* Galena. This interface provides composable error and
|
|
9
|
+
* warning methods that can be used to prevent invalid usage
|
|
10
|
+
* of the library
|
|
11
|
+
*/
|
|
12
|
+
export class Guards {
|
|
13
|
+
/**
|
|
14
|
+
* Warn For Undefined States
|
|
15
|
+
*
|
|
16
|
+
* In Galena, it's normal to lazy initialize a unit of state
|
|
17
|
+
* in attached to a `Galena` instance. This warning lets
|
|
18
|
+
* developers know that they are attempting to manipulate a
|
|
19
|
+
* unit of state that has not yet been initialized
|
|
20
|
+
*/
|
|
21
|
+
protected warnForUndefinedStates = this.developmentGuard(
|
|
22
|
+
<T extends Record<string, State<any>>, K extends Extract<keyof T, string>>(
|
|
23
|
+
name: K,
|
|
24
|
+
state: T
|
|
25
|
+
) => {
|
|
26
|
+
if (!process.env.IGNORE_LAZY_STATE_WARNINGS && !(name in state)) {
|
|
27
|
+
console.warn(
|
|
28
|
+
`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. To make these warnings go away, you can enable this process argument - "IGNORE_LAZY_STATE_WARNING=1"`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Guard Duplicate States
|
|
36
|
+
*
|
|
37
|
+
* Throws an error if a developer attempts to create
|
|
38
|
+
* more than one state with the same name on a single
|
|
39
|
+
* `Galena` instance
|
|
40
|
+
*/
|
|
41
|
+
protected guardDuplicateStates = this.developmentGuard(
|
|
42
|
+
<T extends Record<string, State<any>>, K extends Extract<keyof T, string>>(
|
|
43
|
+
name: K,
|
|
44
|
+
state: T
|
|
45
|
+
) => {
|
|
46
|
+
if (name in state) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`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`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Development Guard
|
|
56
|
+
*
|
|
57
|
+
* Wraps a provided function in a check for `process.env.NODE_ENV`
|
|
58
|
+
* equaling "development". Returns the callback
|
|
59
|
+
*/
|
|
60
|
+
private developmentGuard<F extends (...args: any[]) => void>(guard: F) {
|
|
61
|
+
return (...args: Parameters<F>) => {
|
|
62
|
+
if (process.env.NODE_ENV === "development") {
|
|
63
|
+
guard(...args);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|