@inglorious/store 1.1.0 → 1.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 CHANGED
@@ -90,7 +90,7 @@ Creates a convenient API object that encapsulates the store's methods and provid
90
90
 
91
91
  - An `api` object with methods for interacting with the store and state, including:
92
92
  - `createSelector(inputSelectors, resultFunc)`: A helper function that automatically binds the store's state to a new selector.
93
- - `getTypes()`, `getEntities()`, `getEntity(id)`, `getType(id)`: Utility functions for accessing state.
93
+ - `getTypes()`, `getEntities()`, `getEntity(id)`: Utility functions for accessing state.
94
94
  - `notify(type, payload)`, `dispatch(action)`: Aliases to the store's event dispatching methods.
95
95
 
96
96
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inglorious/store",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "A state manager inspired by Redux, but tailored for the specific needs of game development.",
5
5
  "author": "IceOnFire <antony.mistretta@gmail.com> (https://ingloriouscoderz.it)",
6
6
  "license": "MIT",
package/src/api.js CHANGED
@@ -12,23 +12,12 @@ export function createApi(store) {
12
12
 
13
13
  const getEntity = (id) => getEntities()[id]
14
14
 
15
- const notify = (type, payload) => {
16
- store.notify(type, payload)
17
- }
18
-
19
- const dispatch = (action) => {
20
- store.dispatch(action)
21
- }
22
-
23
- const getType = (id) => store.getOriginalTypes()?.[id]
24
-
25
15
  return {
26
16
  createSelector,
27
17
  getTypes,
28
18
  getEntities,
29
19
  getEntity,
30
- getType,
31
- notify,
32
- dispatch,
20
+ dispatch: store.dispatch,
21
+ notify: store.notify,
33
22
  }
34
23
  }
package/src/store.js CHANGED
@@ -6,6 +6,7 @@ import { augmentType, augmentTypes } from "./types.js"
6
6
 
7
7
  /**
8
8
  * Creates a store to manage state and events.
9
+ *
9
10
  * @param {Object} config - Configuration options for the store.
10
11
  * @param {Object} [config.types] - The initial types configuration.
11
12
  * @param {Object} [config.entities] - The initial entities configuration.
@@ -17,14 +18,11 @@ export function createStore({
17
18
  systems = [],
18
19
  }) {
19
20
  const listeners = new Set()
20
- let incomingEvents = []
21
21
 
22
22
  const types = augmentTypes(originalTypes)
23
- const eventMap = new EventMap(types, originalEntities)
24
23
 
25
- const entities = augmentEntities(originalEntities)
26
- const initialState = { entities }
27
- let state = initialState
24
+ let state, eventMap, incomingEvents
25
+ reset()
28
26
 
29
27
  return {
30
28
  subscribe,
@@ -40,6 +38,7 @@ export function createStore({
40
38
 
41
39
  /**
42
40
  * Subscribes a listener to state updates.
41
+ *
43
42
  * @param {Function} listener - The listener function to call on updates.
44
43
  * @returns {Function} A function to unsubscribe the listener.
45
44
  */
@@ -53,6 +52,7 @@ export function createStore({
53
52
 
54
53
  /**
55
54
  * Updates the state based on elapsed time and processes events.
55
+ *
56
56
  * @param {number} dt - The delta time since the last update in milliseconds.
57
57
  * @param {Object} api - The engine's public API.
58
58
  */
@@ -86,6 +86,7 @@ export function createStore({
86
86
  const type = types[entity.type]
87
87
 
88
88
  eventMap.addEntity(id, type)
89
+ incomingEvents.unshift({ type: "create", payload: id })
89
90
  }
90
91
 
91
92
  if (event.type === "remove") {
@@ -95,6 +96,7 @@ export function createStore({
95
96
  delete state.entities[id]
96
97
 
97
98
  eventMap.removeEntity(id, type)
99
+ incomingEvents.unshift({ type: "destroy", payload: id })
98
100
  }
99
101
 
100
102
  const entityIds = eventMap.getEntitiesForEvent(event.type)
@@ -102,7 +104,7 @@ export function createStore({
102
104
  const entity = state.entities[id]
103
105
  const type = types[entity.type]
104
106
  const handle = type[event.type]
105
- handle?.(entity, event.payload, api)
107
+ handle(entity, event.payload, api)
106
108
  }
107
109
 
108
110
  systems.forEach((system) => {
@@ -119,6 +121,7 @@ export function createStore({
119
121
 
120
122
  /**
121
123
  * Notifies the store of a new event.
124
+ *
122
125
  * @param {string} type - The event object type to notify.
123
126
  * @param {any} payload - The event object payload to notify.
124
127
  */
@@ -128,6 +131,7 @@ export function createStore({
128
131
 
129
132
  /**
130
133
  * Dispatches an event to be processed in the next update cycle.
134
+ *
131
135
  * @param {Object} event - The event object.
132
136
  * @param {string} event.type - The type of the event.
133
137
  * @param {any} [event.payload] - The payload of the event.
@@ -139,6 +143,7 @@ export function createStore({
139
143
  /**
140
144
  * Retrieves the augmented types configuration.
141
145
  * This includes composed behaviors and event handlers wrapped for immutability.
146
+ *
142
147
  * @returns {Object} The augmented types configuration.
143
148
  */
144
149
  function getTypes() {
@@ -147,6 +152,7 @@ export function createStore({
147
152
 
148
153
  /**
149
154
  * Retrieves the original, un-augmented types configuration.
155
+ *
150
156
  * @returns {Object} The original types configuration.
151
157
  */
152
158
  function getOriginalTypes() {
@@ -155,17 +161,50 @@ export function createStore({
155
161
 
156
162
  /**
157
163
  * Retrieves the current state.
164
+ *
158
165
  * @returns {Object} The current state.
159
166
  */
160
167
  function getState() {
161
168
  return state
162
169
  }
163
170
 
164
- function setState(newState) {
165
- state = newState
171
+ /**
172
+ * Sets the entire state of the store.
173
+ * This is useful for importing state or setting initial state from a server.
174
+ *
175
+ * @param {Object} nextState - The new state to set.
176
+ */
177
+ function setState(nextState) {
178
+ const oldEntities = state?.entities ?? {}
179
+ const newEntities = augmentEntities(nextState.entities)
180
+
181
+ state = { entities: newEntities }
182
+ eventMap = new EventMap(types, nextState.entities)
183
+ incomingEvents = []
184
+
185
+ const oldEntityIds = new Set(Object.keys(oldEntities))
186
+ const newEntityIds = new Set(Object.keys(newEntities))
187
+
188
+ const entitiesToCreate = [...newEntityIds].filter(
189
+ (id) => !oldEntityIds.has(id),
190
+ )
191
+ const entitiesToDestroy = [...oldEntityIds].filter(
192
+ (id) => !newEntityIds.has(id),
193
+ )
194
+
195
+ entitiesToCreate.forEach((id) => {
196
+ incomingEvents.push({ type: "create", payload: id })
197
+ })
198
+
199
+ entitiesToDestroy.forEach((id) => {
200
+ incomingEvents.push({ type: "destroy", payload: id })
201
+ })
166
202
  }
167
203
 
204
+ /**
205
+ * Resets the store to its initial state.
206
+ */
168
207
  function reset() {
169
- state = initialState
208
+ setState({ entities: originalEntities })
170
209
  }
171
210
  }