@inglorious/store 5.4.1 → 5.5.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
@@ -424,6 +424,52 @@ const cartItemType = [
424
424
  ]
425
425
  ```
426
426
 
427
+ ### Behavior Composition with Functions
428
+
429
+ Behaviors can also be functions that wrap and extend other behaviors. This enables decorator-like patterns and middleware:
430
+
431
+ ```javascript
432
+ // Base behaviors
433
+ const baseHandlers = {
434
+ formSubmit(entity, value) {
435
+ entity.value = value
436
+ },
437
+ }
438
+
439
+ // Function that adds validation
440
+ const validated = (behavior) => ({
441
+ formSubmit(entity, value, api) {
442
+ if (!value.trim()) return // Validate first
443
+ behavior.formSubmit?.(entity, value, api)
444
+ },
445
+ })
446
+
447
+ // Function that adds loading state to async handlers
448
+ const withLoading = (behavior) => ({
449
+ async fetchData(entity, payload, api) {
450
+ entity.loading = true
451
+ try {
452
+ await behavior.fetchData?.(entity, payload, api)
453
+ } finally {
454
+ entity.loading = false
455
+ }
456
+ },
457
+ })
458
+
459
+ // Compose behaviors
460
+ const types = {
461
+ form: [baseHandlers, validated(baseHandlers), withLoading(baseHandlers)],
462
+ }
463
+ ```
464
+
465
+ **Why function composition for behaviors:**
466
+
467
+ - ✅ Add cross-cutting concerns (validation, logging, error handling)
468
+ - ✅ Reuse behavior logic across entities
469
+ - ✅ Create middleware-like wrappers
470
+ - ✅ Cleaner than deep inheritance hierarchies
471
+ - ✅ Works for both apps and games
472
+
427
473
  ### Events
428
474
 
429
475
  Events are broadcast to all relevant handlers in a pub/sub pattern.
@@ -580,7 +626,6 @@ Creates a convenience wrapper with utility methods.
580
626
 
581
627
  **Returns:**
582
628
 
583
- - `createSelector(inputSelectors, resultFunc)`: Memoized selectors
584
629
  - `getTypes()`, `getEntities()`, `getEntity(id)`: State accessors
585
630
  - `notify(type, payload)`: Dispatch events
586
631
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inglorious/store",
3
- "version": "5.4.1",
3
+ "version": "5.5.0",
4
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",
package/src/api.js CHANGED
@@ -1,11 +1,4 @@
1
- import { createSelector as _createSelector } from "./select.js"
2
-
3
1
  export function createApi(store, extras) {
4
- const createSelector = (inputSelectors, resultFunc) => {
5
- const selector = _createSelector(inputSelectors, resultFunc)
6
- return () => selector(store.getState())
7
- }
8
-
9
2
  const getTypes = () => store.getTypes()
10
3
 
11
4
  const getEntities = () => store.getState()
@@ -13,7 +6,6 @@ export function createApi(store, extras) {
13
6
  const getEntity = (id) => getEntities()[id]
14
7
 
15
8
  return {
16
- createSelector,
17
9
  getTypes,
18
10
  getEntities,
19
11
  getEntity,
package/src/types.js CHANGED
@@ -12,8 +12,9 @@ import { pipe } from "@inglorious/utils/functions/functions.js"
12
12
  * @returns {Type} The fully composed and augmented type object.
13
13
  */
14
14
  export function augmentType(type) {
15
- const behaviors = ensureArray(type).map((fn) =>
16
- typeof fn !== "function" ? (type) => extend(type, fn) : fn,
15
+ const behaviors = ensureArray(type).map(
16
+ (behavior) => (type) =>
17
+ extend(type, typeof behavior === "function" ? behavior(type) : behavior),
17
18
  )
18
19
 
19
20
  return pipe(...behaviors)({})