@inglorious/store 5.1.0 → 5.2.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 +17 -16
- package/package.json +12 -7
- package/src/api.js +1 -1
- package/src/client/dev-tools.js +2 -4
- package/src/store.js +11 -11
- package/src/store.test.js +18 -29
package/README.md
CHANGED
|
@@ -128,8 +128,8 @@ const types = {
|
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
const entities = {
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
counter1: { type: "counter", value: 0 },
|
|
132
|
+
counter2: { type: "counter", value: 10 },
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
const store = createStore({ types, entities })
|
|
@@ -138,8 +138,8 @@ const store = createStore({ types, entities })
|
|
|
138
138
|
store.notify("increment")
|
|
139
139
|
store.update()
|
|
140
140
|
|
|
141
|
-
console.log(store.getState().
|
|
142
|
-
console.log(store.getState().
|
|
141
|
+
console.log(store.getState().counter1.value) // => 1
|
|
142
|
+
console.log(store.getState().counter2.value) // => 11
|
|
143
143
|
|
|
144
144
|
// To update just one counter, add filtering logic in the handler
|
|
145
145
|
```
|
|
@@ -233,7 +233,7 @@ store.subscribe(() => {
|
|
|
233
233
|
|
|
234
234
|
// 6. Dispatch events (use notify or dispatch - both work!)
|
|
235
235
|
store.notify("inputChange", "Buy milk")
|
|
236
|
-
store.notify("formSubmit", store.getState().
|
|
236
|
+
store.notify("formSubmit", store.getState().form.value)
|
|
237
237
|
store.notify("toggleClick", 1) // Only todo with id=1 will respond
|
|
238
238
|
store.notify("filterClick", "active")
|
|
239
239
|
|
|
@@ -302,8 +302,8 @@ Your state is a collection of **entities** (instances) organized by **type** (li
|
|
|
302
302
|
|
|
303
303
|
```javascript
|
|
304
304
|
const entities = {
|
|
305
|
-
|
|
306
|
-
|
|
305
|
+
item1: { type: "cartItem", name: "Shoes", quantity: 1, price: 99 },
|
|
306
|
+
item2: { type: "cartItem", name: "Shirt", quantity: 2, price: 29 },
|
|
307
307
|
}
|
|
308
308
|
```
|
|
309
309
|
|
|
@@ -346,13 +346,13 @@ Events are broadcast to all relevant handlers in a pub/sub pattern.
|
|
|
346
346
|
|
|
347
347
|
```javascript
|
|
348
348
|
// Simplest form - just the entity ID
|
|
349
|
-
store.notify("increment", "
|
|
349
|
+
store.notify("increment", "counter1")
|
|
350
350
|
|
|
351
351
|
// With additional data
|
|
352
|
-
store.notify("applyDiscount", { id: "
|
|
352
|
+
store.notify("applyDiscount", { id: "item1", percent: 10 })
|
|
353
353
|
|
|
354
354
|
// Also supports dispatch() for Redux compatibility
|
|
355
|
-
store.dispatch({ type: "increment", payload: "
|
|
355
|
+
store.dispatch({ type: "increment", payload: "counter1" })
|
|
356
356
|
|
|
357
357
|
// Process the queue - this is when handlers actually run
|
|
358
358
|
store.update()
|
|
@@ -367,8 +367,8 @@ For global state logic that doesn't belong to a specific entity type.
|
|
|
367
367
|
```javascript
|
|
368
368
|
const systems = [
|
|
369
369
|
{
|
|
370
|
-
calculateTotal(
|
|
371
|
-
state.cartTotal = Object.values(
|
|
370
|
+
calculateTotal(entities) {
|
|
371
|
+
state.cartTotal = Object.values(entities)
|
|
372
372
|
.filter((e) => e.type === "cartItem")
|
|
373
373
|
.reduce((sum, item) => sum + item.price * item.quantity, 0)
|
|
374
374
|
},
|
|
@@ -415,9 +415,8 @@ Creates a convenience wrapper with utility methods.
|
|
|
415
415
|
Create memoized, performant selectors.
|
|
416
416
|
|
|
417
417
|
```javascript
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
(entities) => Object.values(entities).filter((e) => e.completed),
|
|
418
|
+
const selectCompletedTasks = createSelector([(state) => state.tasks], (tasks) =>
|
|
419
|
+
tasks.filter((task) => task.completed),
|
|
421
420
|
)
|
|
422
421
|
```
|
|
423
422
|
|
|
@@ -572,7 +571,9 @@ This store powers the [Inglorious Engine](https://github.com/IngloriousCoderz/in
|
|
|
572
571
|
|
|
573
572
|
## License
|
|
574
573
|
|
|
575
|
-
MIT © [Matteo Antony Mistretta]
|
|
574
|
+
MIT © [Matteo Antony Mistretta](https://github.com/IngloriousCoderz)
|
|
575
|
+
|
|
576
|
+
This is free and open-source software. Use it however you want!
|
|
576
577
|
|
|
577
578
|
---
|
|
578
579
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inglorious/store",
|
|
3
|
-
"version": "5.
|
|
4
|
-
"description": "A state manager
|
|
3
|
+
"version": "5.2.0",
|
|
4
|
+
"description": "A state manager for real-time, collaborative apps, inspired by game development patterns and compatible with Redux.",
|
|
5
5
|
"author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -13,12 +13,17 @@
|
|
|
13
13
|
"url": "https://github.com/IngloriousCoderz/inglorious-engine/issues"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [
|
|
16
|
+
"state",
|
|
17
|
+
"state-management",
|
|
18
|
+
"store",
|
|
19
|
+
"redux",
|
|
20
|
+
"redux-alternative",
|
|
21
|
+
"mutative",
|
|
22
|
+
"immer",
|
|
16
23
|
"collaborative",
|
|
17
24
|
"multiplayer",
|
|
18
25
|
"realtime",
|
|
19
|
-
"
|
|
20
|
-
"state-manager",
|
|
21
|
-
"store"
|
|
26
|
+
"event-batching"
|
|
22
27
|
],
|
|
23
28
|
"type": "module",
|
|
24
29
|
"exports": {
|
|
@@ -37,10 +42,10 @@
|
|
|
37
42
|
},
|
|
38
43
|
"dependencies": {
|
|
39
44
|
"mutative": "^1.3.0",
|
|
40
|
-
"@inglorious/utils": "3.6.
|
|
45
|
+
"@inglorious/utils": "3.6.1"
|
|
41
46
|
},
|
|
42
47
|
"peerDependencies": {
|
|
43
|
-
"@inglorious/utils": "3.6.
|
|
48
|
+
"@inglorious/utils": "3.6.1"
|
|
44
49
|
},
|
|
45
50
|
"devDependencies": {
|
|
46
51
|
"prettier": "^3.6.2",
|
package/src/api.js
CHANGED
package/src/client/dev-tools.js
CHANGED
|
@@ -13,14 +13,12 @@ export function connectDevTools(store, config = {}) {
|
|
|
13
13
|
return
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
const name = config.name ?? document.title
|
|
16
17
|
const skippedEvents = config.skippedEvents ?? []
|
|
17
18
|
|
|
18
19
|
devToolsInstance = window.__REDUX_DEVTOOLS_EXTENSION__.connect({
|
|
19
|
-
name
|
|
20
|
+
name,
|
|
20
21
|
predicate: (state, action) => !skippedEvents.includes(action.type),
|
|
21
|
-
actionCreators: {
|
|
22
|
-
jump: () => ({ type: "jump", payload: { inputId: "input0" } }),
|
|
23
|
-
},
|
|
24
22
|
// @see https://github.com/reduxjs/redux-devtools/blob/main/extension/docs/API/Arguments.md#features
|
|
25
23
|
features: {
|
|
26
24
|
pause: true, // start/pause recording of dispatched actions
|
package/src/store.js
CHANGED
|
@@ -68,7 +68,7 @@ export function createStore({
|
|
|
68
68
|
const processedEvents = []
|
|
69
69
|
|
|
70
70
|
state = create(state, patcher, {
|
|
71
|
-
enableAutoFreeze: state.
|
|
71
|
+
enableAutoFreeze: state.game?.devMode,
|
|
72
72
|
})
|
|
73
73
|
|
|
74
74
|
listeners.forEach((onUpdate) => onUpdate())
|
|
@@ -83,7 +83,7 @@ export function createStore({
|
|
|
83
83
|
if (event.type === "morph") {
|
|
84
84
|
const { id, type } = event.payload
|
|
85
85
|
|
|
86
|
-
const entity = draft
|
|
86
|
+
const entity = draft[id]
|
|
87
87
|
const oldType = types[entity.type]
|
|
88
88
|
|
|
89
89
|
originalTypes[id] = type
|
|
@@ -96,7 +96,7 @@ export function createStore({
|
|
|
96
96
|
|
|
97
97
|
if (event.type === "add") {
|
|
98
98
|
const { id, ...entity } = event.payload
|
|
99
|
-
draft
|
|
99
|
+
draft[id] = augmentEntity(id, entity)
|
|
100
100
|
const type = types[entity.type]
|
|
101
101
|
|
|
102
102
|
eventMap.addEntity(id, type)
|
|
@@ -105,9 +105,9 @@ export function createStore({
|
|
|
105
105
|
|
|
106
106
|
if (event.type === "remove") {
|
|
107
107
|
const id = event.payload
|
|
108
|
-
const entity = draft
|
|
108
|
+
const entity = draft[id]
|
|
109
109
|
const type = types[entity.type]
|
|
110
|
-
delete draft
|
|
110
|
+
delete draft[id]
|
|
111
111
|
|
|
112
112
|
eventMap.removeEntity(id, type)
|
|
113
113
|
incomingEvents.unshift({ type: "destroy", payload: id })
|
|
@@ -115,7 +115,7 @@ export function createStore({
|
|
|
115
115
|
|
|
116
116
|
const entityIds = eventMap.getEntitiesForEvent(event.type)
|
|
117
117
|
for (const id of entityIds) {
|
|
118
|
-
const entity = draft
|
|
118
|
+
const entity = draft[id]
|
|
119
119
|
const type = types[entity.type]
|
|
120
120
|
const handle = type[event.type]
|
|
121
121
|
handle(entity, event.payload, api)
|
|
@@ -187,11 +187,11 @@ export function createStore({
|
|
|
187
187
|
* @param {Object} nextState - The new state to set.
|
|
188
188
|
*/
|
|
189
189
|
function setState(nextState) {
|
|
190
|
-
const oldEntities = state
|
|
191
|
-
const newEntities = augmentEntities(nextState
|
|
190
|
+
const oldEntities = state ?? {}
|
|
191
|
+
const newEntities = augmentEntities(nextState)
|
|
192
192
|
|
|
193
|
-
state =
|
|
194
|
-
eventMap = new EventMap(types, nextState
|
|
193
|
+
state = newEntities
|
|
194
|
+
eventMap = new EventMap(types, nextState)
|
|
195
195
|
incomingEvents = []
|
|
196
196
|
|
|
197
197
|
const oldEntityIds = new Set(Object.keys(oldEntities))
|
|
@@ -217,6 +217,6 @@ export function createStore({
|
|
|
217
217
|
* Resets the store to its initial state.
|
|
218
218
|
*/
|
|
219
219
|
function reset() {
|
|
220
|
-
setState(
|
|
220
|
+
setState(originalEntities)
|
|
221
221
|
}
|
|
222
222
|
}
|
package/src/store.test.js
CHANGED
|
@@ -16,12 +16,10 @@ test("it should process events by mutating state inside handlers", () => {
|
|
|
16
16
|
},
|
|
17
17
|
}
|
|
18
18
|
const afterState = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
isFed: true,
|
|
24
|
-
},
|
|
19
|
+
kitty1: {
|
|
20
|
+
id: "kitty1",
|
|
21
|
+
type: "kitty",
|
|
22
|
+
isFed: true,
|
|
25
23
|
},
|
|
26
24
|
}
|
|
27
25
|
|
|
@@ -50,13 +48,11 @@ test("it should process an event queue in the same update cycle", () => {
|
|
|
50
48
|
},
|
|
51
49
|
}
|
|
52
50
|
const afterState = {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
isMeowing: true,
|
|
59
|
-
},
|
|
51
|
+
kitty1: {
|
|
52
|
+
id: "kitty1",
|
|
53
|
+
type: "kitty",
|
|
54
|
+
isFed: true,
|
|
55
|
+
isMeowing: true,
|
|
60
56
|
},
|
|
61
57
|
}
|
|
62
58
|
|
|
@@ -89,10 +85,8 @@ test("it should send an event from an entity and process it in the same update c
|
|
|
89
85
|
},
|
|
90
86
|
}
|
|
91
87
|
const afterState = {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
kitty1: { id: "kitty1", type: "kitty", position: "far" },
|
|
95
|
-
},
|
|
88
|
+
doggo1: { id: "doggo1", type: "doggo" },
|
|
89
|
+
kitty1: { id: "kitty1", type: "kitty", position: "far" },
|
|
96
90
|
}
|
|
97
91
|
|
|
98
92
|
const store = createStore(config)
|
|
@@ -112,17 +106,16 @@ test("it should add an entity via an 'add' event", () => {
|
|
|
112
106
|
entities: {},
|
|
113
107
|
}
|
|
114
108
|
const newEntity = { id: "kitty1", type: "kitty" }
|
|
109
|
+
const afterState = {
|
|
110
|
+
kitty1: { id: "kitty1", type: "kitty" },
|
|
111
|
+
}
|
|
115
112
|
|
|
116
113
|
const store = createStore(config)
|
|
117
114
|
store.notify("add", newEntity)
|
|
118
115
|
store.update()
|
|
119
116
|
|
|
120
117
|
const state = store.getState()
|
|
121
|
-
expect(state).toStrictEqual(
|
|
122
|
-
entities: {
|
|
123
|
-
kitty1: { id: "kitty1", type: "kitty" },
|
|
124
|
-
},
|
|
125
|
-
})
|
|
118
|
+
expect(state).toStrictEqual(afterState)
|
|
126
119
|
})
|
|
127
120
|
|
|
128
121
|
test("it should remove an entity via a 'remove' event", () => {
|
|
@@ -138,7 +131,7 @@ test("it should remove an entity via a 'remove' event", () => {
|
|
|
138
131
|
store.update()
|
|
139
132
|
|
|
140
133
|
const state = store.getState()
|
|
141
|
-
expect(state.
|
|
134
|
+
expect(state.kitty1).toBeUndefined()
|
|
142
135
|
})
|
|
143
136
|
|
|
144
137
|
test("it should change an entity's behavior via a 'morph' event", () => {
|
|
@@ -169,17 +162,13 @@ test("it should change an entity's behavior via a 'morph' event", () => {
|
|
|
169
162
|
store.update()
|
|
170
163
|
|
|
171
164
|
expect(store.getState()).toStrictEqual({
|
|
172
|
-
|
|
173
|
-
bug: { id: "bug", type: "bug", isFull: true },
|
|
174
|
-
},
|
|
165
|
+
bug: { id: "bug", type: "bug", isFull: true },
|
|
175
166
|
})
|
|
176
167
|
|
|
177
168
|
store.notify("morph", { id: "bug", type: [Caterpillar, Butterfly] })
|
|
178
169
|
store.notify("fly")
|
|
179
170
|
store.update()
|
|
180
171
|
expect(store.getState()).toStrictEqual({
|
|
181
|
-
|
|
182
|
-
bug: { id: "bug", type: "bug", isFull: true, hasFlown: true },
|
|
183
|
-
},
|
|
172
|
+
bug: { id: "bug", type: "bug", isFull: true, hasFlown: true },
|
|
184
173
|
})
|
|
185
174
|
})
|