@rotorsoft/act 0.17.1 → 0.19.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.
@@ -1,102 +1,13 @@
1
1
  import { type ZodType } from "zod";
2
- import type { Patch, Schema } from "./types/index.js";
3
2
  /**
4
3
  * @module utils
5
4
  * @category Utilities
6
- * Utility functions for patching state, validation, extending objects, and async helpers.
5
+ * Utility functions for validation, extending objects, and async helpers.
7
6
  *
8
- * - Use `patch()` to immutably update state with patches.
9
7
  * - Use `validate()` to validate payloads against Zod schemas.
10
8
  * - Use `extend()` to merge and validate configuration objects.
11
9
  * - Use `sleep()` for async delays.
12
10
  */
13
- /**
14
- * Immutably applies patches to a state object, creating a new copy.
15
- *
16
- * This function performs deep merging for plain objects while preserving
17
- * immutability. Special types (Arrays, Dates, Maps, etc.) are replaced
18
- * entirely rather than merged. Setting a property to `undefined` or `null`
19
- * removes it from the resulting object.
20
- *
21
- * Used internally by the framework to apply event patches to state, but
22
- * can also be used directly for state transformations.
23
- *
24
- * **Merging rules:**
25
- * - Plain objects: Deep merge recursively
26
- * - Arrays, Dates, RegExp, Maps, Sets, TypedArrays: Replace entirely
27
- * - `undefined` or `null` values: Delete the property
28
- * - Primitives: Replace with patch value
29
- *
30
- * @param original - The original state object to patch
31
- * @param patches - The patches to apply (partial state)
32
- * @returns A new state object with patches applied
33
- *
34
- * @example Simple property update
35
- * ```typescript
36
- * import { patch } from "@rotorsoft/act";
37
- *
38
- * const state = { count: 0, name: "Alice" };
39
- * const updated = patch(state, { count: 5 });
40
- * // Result: { count: 5, name: "Alice" }
41
- * // Original unchanged: { count: 0, name: "Alice" }
42
- * ```
43
- *
44
- * @example Nested object patching
45
- * ```typescript
46
- * const state = {
47
- * user: { id: 1, name: "Alice", email: "alice@example.com" },
48
- * settings: { theme: "dark" }
49
- * };
50
- *
51
- * const updated = patch(state, {
52
- * user: { email: "newemail@example.com" }
53
- * });
54
- * // Result: {
55
- * // user: { id: 1, name: "Alice", email: "newemail@example.com" },
56
- * // settings: { theme: "dark" }
57
- * // }
58
- * ```
59
- *
60
- * @example Property deletion
61
- * ```typescript
62
- * const state = { count: 5, temp: "value", flag: true };
63
- *
64
- * const updated = patch(state, {
65
- * temp: undefined, // Delete temp
66
- * flag: null // Delete flag
67
- * });
68
- * // Result: { count: 5 }
69
- * ```
70
- *
71
- * @example Array replacement (not merged)
72
- * ```typescript
73
- * const state = { items: [1, 2, 3], meta: { count: 3 } };
74
- *
75
- * const updated = patch(state, {
76
- * items: [4, 5] // Arrays are replaced, not merged
77
- * });
78
- * // Result: { items: [4, 5], meta: { count: 3 } }
79
- * ```
80
- *
81
- * @example In event handlers
82
- * ```typescript
83
- * import { state } from "@rotorsoft/act";
84
- * import { z } from "zod";
85
- *
86
- * const Counter = state({ Counter: z.object({ count: z.number() }) })
87
- * .init(() => ({ count: 0 }))
88
- * .emits({ Incremented: z.object({ by: z.number() }) })
89
- * .patch({
90
- * Incremented: (event, state) => {
91
- * // patch() is called internally here
92
- * return { count: state.count + event.data.by };
93
- * }
94
- * });
95
- * ```
96
- *
97
- * @see {@link Patch} for the patch type definition
98
- */
99
- export declare const patch: <S extends Schema>(original: Readonly<S>, patches: Readonly<Patch<S>>) => Readonly<S>;
100
11
  /**
101
12
  * Validates a payload against a Zod schema.
102
13
  *
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,OAAO,EAAiB,MAAM,KAAK,CAAC;AAEjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA+BtD;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqFG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,SAAS,MAAM,EACpC,UAAU,QAAQ,CAAC,CAAC,CAAC,EACrB,SAAS,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAC1B,QAAQ,CAAC,CAAC,CAgBZ,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmGG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,EACxB,QAAQ,MAAM,EACd,SAAS,QAAQ,CAAC,CAAC,CAAC,EACpB,SAAS,OAAO,CAAC,CAAC,CAAC,KAClB,QAAQ,CAAC,CAAC,CAaZ,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwHG;AACH,eAAO,MAAM,MAAM,GACjB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjC,QAAQ,QAAQ,CAAC,CAAC,CAAC,EACnB,QAAQ,OAAO,CAAC,CAAC,CAAC,EAClB,SAAS,QAAQ,CAAC,CAAC,CAAC,KACnB,QAAQ,CAAC,CAAC,GAAG,CAAC,CAGhB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,wBAAsB,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,oBAEtC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,OAAO,EAAiB,MAAM,KAAK,CAAC;AAIjE;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmGG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,EACxB,QAAQ,MAAM,EACd,SAAS,QAAQ,CAAC,CAAC,CAAC,EACpB,SAAS,OAAO,CAAC,CAAC,CAAC,KAClB,QAAQ,CAAC,CAAC,CAaZ,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwHG;AACH,eAAO,MAAM,MAAM,GACjB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjC,QAAQ,QAAQ,CAAC,CAAC,CAAC,EACnB,QAAQ,OAAO,CAAC,CAAC,CAAC,EAClB,SAAS,QAAQ,CAAC,CAAC,CAAC,KACnB,QAAQ,CAAC,CAAC,GAAG,CAAC,CAGhB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,wBAAsB,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,oBAEtC"}
package/dist/index.cjs CHANGED
@@ -54,7 +54,6 @@ __export(index_exports, {
54
54
  disposeAndExit: () => disposeAndExit,
55
55
  extend: () => extend,
56
56
  logger: () => logger,
57
- patch: () => patch,
58
57
  port: () => port,
59
58
  projection: () => projection,
60
59
  sleep: () => sleep,
@@ -206,40 +205,6 @@ var config = () => {
206
205
  };
207
206
 
208
207
  // src/utils.ts
209
- var UNMERGEABLES = [
210
- RegExp,
211
- Date,
212
- Array,
213
- Map,
214
- Set,
215
- WeakMap,
216
- WeakSet,
217
- ArrayBuffer,
218
- SharedArrayBuffer,
219
- DataView,
220
- Int8Array,
221
- Uint8Array,
222
- Uint8ClampedArray,
223
- Int16Array,
224
- Uint16Array,
225
- Int32Array,
226
- Uint32Array,
227
- Float32Array,
228
- Float64Array
229
- ];
230
- var is_mergeable = (value) => !!value && typeof value === "object" && !UNMERGEABLES.some((t) => value instanceof t);
231
- var patch = (original, patches) => {
232
- const copy = {};
233
- Object.keys({ ...original, ...patches }).forEach((key) => {
234
- const patched_value = patches[key];
235
- const original_value = original[key];
236
- const patched = patches && key in patches;
237
- const deleted = patched && (typeof patched_value === "undefined" || patched_value === null);
238
- const value = patched && !deleted ? patched_value : original_value;
239
- !deleted && (copy[key] = is_mergeable(value) ? patch(original_value || {}, patched_value || {}) : value);
240
- });
241
- return copy;
242
- };
243
208
  var validate = (target, payload, schema) => {
244
209
  try {
245
210
  return schema ? schema.parse(payload) : payload;
@@ -636,6 +601,7 @@ var import_crypto2 = require("crypto");
636
601
  var import_events = __toESM(require("events"), 1);
637
602
 
638
603
  // src/event-sourcing.ts
604
+ var import_act_patch = require("@rotorsoft/act-patch");
639
605
  var import_crypto = require("crypto");
640
606
  async function snap(snapshot) {
641
607
  try {
@@ -668,7 +634,7 @@ async function load(me, stream, callback) {
668
634
  snaps++;
669
635
  patches = 0;
670
636
  } else if (me.patch[e.name]) {
671
- state2 = patch(state2, me.patch[e.name](event, state2));
637
+ state2 = (0, import_act_patch.patch)(state2, me.patch[e.name](event, state2));
672
638
  patches++;
673
639
  }
674
640
  callback && callback({ event, state: state2, patches, snaps });
@@ -740,9 +706,10 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
740
706
  );
741
707
  let { state: state2, patches } = snapshot;
742
708
  const snapshots = committed.map((event) => {
743
- state2 = patch(state2, me.patch[event.name](event, state2));
709
+ const p = me.patch[event.name](event, state2);
710
+ state2 = (0, import_act_patch.patch)(state2, p);
744
711
  patches++;
745
- return { event, state: state2, patches, snaps: snapshot.snaps };
712
+ return { event, state: state2, patches, snaps: snapshot.snaps, patch: p };
746
713
  });
747
714
  const last = snapshots.at(-1);
748
715
  me.snap && me.snap(last) && void snap(last);
@@ -1820,7 +1787,6 @@ function action_builder(state2) {
1820
1787
  disposeAndExit,
1821
1788
  extend,
1822
1789
  logger,
1823
- patch,
1824
1790
  port,
1825
1791
  projection,
1826
1792
  sleep,