@spine-event-engine/server 2.0.0-snapshot.12 → 2.0.0-snapshot.15

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.
Files changed (44) hide show
  1. package/README.md +18 -0
  2. package/REFERENCE.md +93 -7
  3. package/dist/entity/entity-transaction.d.ts +46 -42
  4. package/dist/entity/entity-transaction.d.ts.map +1 -1
  5. package/dist/entity/entity-transaction.js +130 -35
  6. package/dist/entity/entity-transaction.js.map +1 -1
  7. package/dist/entity/entity.d.ts +132 -84
  8. package/dist/entity/entity.d.ts.map +1 -1
  9. package/dist/entity/entity.js +213 -217
  10. package/dist/entity/entity.js.map +1 -1
  11. package/dist/handler/event-registration-readiness.d.ts +13 -56
  12. package/dist/handler/event-registration-readiness.d.ts.map +1 -1
  13. package/dist/handler/event-registration-readiness.js +23 -43
  14. package/dist/handler/event-registration-readiness.js.map +1 -1
  15. package/dist/handler/generated-handler-registry.d.ts +8 -0
  16. package/dist/handler/generated-handler-registry.d.ts.map +1 -1
  17. package/dist/handler/generated-handler-registry.js +165 -3
  18. package/dist/handler/generated-handler-registry.js.map +1 -1
  19. package/dist/handler/handler-decorators.d.ts +70 -33
  20. package/dist/handler/handler-decorators.d.ts.map +1 -1
  21. package/dist/handler/handler-decorators.js +88 -31
  22. package/dist/handler/handler-decorators.js.map +1 -1
  23. package/dist/handler/handler-metadata.d.ts +53 -51
  24. package/dist/handler/handler-metadata.d.ts.map +1 -1
  25. package/dist/handler/handler-metadata.js +214 -42
  26. package/dist/handler/handler-metadata.js.map +1 -1
  27. package/dist/handler/registration-readiness-metadata.d.ts +4 -0
  28. package/dist/handler/registration-readiness-metadata.d.ts.map +1 -1
  29. package/dist/handler/registration-readiness-metadata.js +82 -1
  30. package/dist/handler/registration-readiness-metadata.js.map +1 -1
  31. package/dist/index.d.ts +4 -4
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +1 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/repository/repository.d.ts +137 -20
  36. package/dist/repository/repository.d.ts.map +1 -1
  37. package/dist/repository/repository.js +2589 -282
  38. package/dist/repository/repository.js.map +1 -1
  39. package/dist/runtime/standalone-handler-runtime.d.ts +16 -0
  40. package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
  41. package/dist/runtime/standalone-handler-runtime.js +93 -18
  42. package/dist/runtime/standalone-handler-runtime.js.map +1 -1
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/package.json +12 -13
@@ -11,9 +11,9 @@
11
11
  * or implied. See the License for the specific language governing permissions and limitations under
12
12
  * the License.
13
13
  */
14
- import { clone, fromBinary, toBinary } from "@bufbuild/protobuf";
14
+ import { clone, create, fromBinary, toBinary, } from "@bufbuild/protobuf";
15
15
  import { EntityQuery, } from "@spine-event-engine/core";
16
- import { ActorContextSchema, ValidationErrorSchema, } from "@spine-event-engine/proto";
16
+ import { VersionSchema, ActorContextSchema, ValidationErrorSchema, } from "@spine-event-engine/proto";
17
17
  import { describeEntityMetadata, } from "./entity-metadata.js";
18
18
  import { EntityTransaction, } from "./entity-transaction.js";
19
19
  const processManagerQueries = new WeakMap();
@@ -23,6 +23,14 @@ const processManagerQueries = new WeakMap();
23
23
  * @internal
24
24
  */
25
25
  export const processManagerQueryAccess = Object.freeze({
26
+ /**
27
+ * Enables read-side queries for the duration of one handler invocation.
28
+ *
29
+ * @param entity Process Manager receiving the query capability.
30
+ * @param execute Repository operation that runs queries.
31
+ * @param actorContext Actor and tenant of the incoming signal.
32
+ * @returns A function that disables and removes this capability.
33
+ */
26
34
  bind(entity, execute, actorContext) {
27
35
  const capability = {
28
36
  execute,
@@ -35,6 +43,12 @@ export const processManagerQueryAccess = Object.freeze({
35
43
  processManagerQueries.delete(entity);
36
44
  };
37
45
  },
46
+ /**
47
+ * Gets the query capability of a currently executing Process Manager.
48
+ *
49
+ * @param entity Process Manager attempting a query.
50
+ * @returns The active repository query capability.
51
+ */
38
52
  require(entity) {
39
53
  const capability = processManagerQueries.get(entity);
40
54
  if (capability?.active !== true) {
@@ -57,7 +71,7 @@ export class ProcessManagerQuery {
57
71
  * Creates the repository-scoped query facade.
58
72
  *
59
73
  * @internal
60
- * @param entity Process Manager that owns this query capability.
74
+ * @param entity Process Manager using this query capability.
61
75
  * @param schema State schema read by this query.
62
76
  * @param builder Typed query builder used to create the wire query.
63
77
  */
@@ -79,6 +93,7 @@ export class ProcessManagerQuery {
79
93
  /**
80
94
  * Adds a typed state predicate to the query.
81
95
  *
96
+ * @typeParam Predicate Comparison supported by the registered columns.
82
97
  * @param predicate Predicate evaluated against registered state columns.
83
98
  * @returns This query for fluent configuration.
84
99
  */
@@ -99,6 +114,7 @@ export class ProcessManagerQuery {
99
114
  /**
100
115
  * Sets the ordering for matching states by one registered column.
101
116
  *
117
+ * @typeParam Column Registered column supplying the ordered values.
102
118
  * @param column Registered orderable column used for sorting.
103
119
  * @param direction Optional sort direction, ascending by default.
104
120
  * @returns This query for fluent configuration.
@@ -182,15 +198,17 @@ export class TransactionalEntityScopeError extends Error {
182
198
  Object.setPrototypeOf(this, new.target.prototype);
183
199
  }
184
200
  }
185
- const isProxy = process.getBuiltinModule("node:util").types.isProxy;
186
201
  /**
187
- * Common in-memory OOP shell for one server-side entity state.
202
+ * Identity, state, version, and lifecycle of one server-side Entity.
188
203
  *
189
204
  * The shell exposes identity, descriptor-derived metadata, cloned state
190
- * snapshots, caller-owned plain version metadata snapshots, and lifecycle flags. It does not
205
+ * snapshots, Spine Version snapshots, and lifecycle flags. It does not
191
206
  * invoke handlers, create transactions, write repositories or storage, dispatch
192
207
  * messages, increment versions, route IDs, query read models, start buses, or
193
208
  * mutate process-wide runtime state.
209
+ *
210
+ * @typeParam Id Domain identifier type.
211
+ * @typeParam Schema Generated schema describing the Entity state.
194
212
  */
195
213
  export class Entity {
196
214
  #id;
@@ -210,7 +228,7 @@ export class Entity {
210
228
  this.#schema = options.schema;
211
229
  this.#metadata = describeEntityMetadata(options.schema);
212
230
  this.#state = EntitySnapshots.clone(options.schema, options.state);
213
- this.#version = EntityVersions.clone(options.version);
231
+ this.#version = clone(VersionSchema, options.version ?? create(VersionSchema));
214
232
  this.#lifecycle = {
215
233
  archived: options.lifecycle?.archived ?? false,
216
234
  deleted: options.lifecycle?.deleted ?? false,
@@ -219,7 +237,7 @@ export class Entity {
219
237
  /**
220
238
  * Gets the stable entity identifier.
221
239
  *
222
- * @returns The caller-owned entity identifier.
240
+ * @returns The domain identifier supplied during construction.
223
241
  */
224
242
  get id() {
225
243
  return this.#id;
@@ -249,12 +267,12 @@ export class Entity {
249
267
  return EntitySnapshots.clone(this.#schema, this.#state);
250
268
  }
251
269
  /**
252
- * Gets the caller-owned plain version metadata snapshot.
270
+ * Gets the current Spine Version without exposing the stored message.
253
271
  *
254
- * @returns A validated clone of the version metadata.
272
+ * @returns A copy of the version number and timestamp.
255
273
  */
256
274
  get version() {
257
- return EntityVersions.clone(this.#version);
275
+ return clone(VersionSchema, this.#version);
258
276
  }
259
277
  /**
260
278
  * Gets the current lifecycle flag snapshot.
@@ -300,7 +318,7 @@ export class Entity {
300
318
  return this.#lifecycleFlagsChanged;
301
319
  }
302
320
  /**
303
- * Replaces stored state from framework-owned subclass or runtime code.
321
+ * Replaces stored state when framework transaction code accepts a draft.
304
322
  *
305
323
  * @param state Next entity state snapshot.
306
324
  */
@@ -308,15 +326,15 @@ export class Entity {
308
326
  this.#state = EntitySnapshots.clone(this.#schema, state);
309
327
  }
310
328
  /**
311
- * Replaces caller-owned version metadata from framework-owned subclass or runtime code.
329
+ * Applies the Version calculated by a framework transaction.
312
330
  *
313
- * @param version Next caller-owned version metadata.
331
+ * @param version Accepted version number and timestamp.
314
332
  */
315
- replaceVersionMetadata(version) {
316
- this.#version = EntityVersions.clone(version);
333
+ replaceVersion(version) {
334
+ this.#version = clone(VersionSchema, version);
317
335
  }
318
336
  /**
319
- * Replaces lifecycle flags from framework-owned subclass or runtime code.
337
+ * Applies lifecycle flags accepted by framework transaction code.
320
338
  *
321
339
  * @param lifecycle Lifecycle flag changes to apply.
322
340
  */
@@ -366,21 +384,60 @@ const boundEntityHistories = new WeakMap();
366
384
  * @internal
367
385
  */
368
386
  export const entityHistoryAccess = Object.freeze({
387
+ /**
388
+ * Associates an Entity instance with its repository history operations.
389
+ *
390
+ * @param entity Entity instance loaded by the repository.
391
+ * @param binding Operations bound to that Entity's history.
392
+ */
369
393
  bind(entity, binding) {
370
394
  boundEntityHistories.set(entity, binding);
371
395
  },
396
+ /**
397
+ * Reads the most recent retained state no later than the requested time.
398
+ *
399
+ * @param entity Entity whose state is requested.
400
+ * @param time Latest allowed state timestamp.
401
+ * @returns The retained state, or undefined when none matches.
402
+ */
372
403
  stateAt(entity, time) {
373
404
  return EntityHistory.require(entity).stateAt(time);
374
405
  },
406
+ /**
407
+ * Reads retained states after checking the history read limit.
408
+ *
409
+ * @param entity Entity whose history is requested.
410
+ * @param depth Maximum number of states to return.
411
+ * @returns Retained states in descending version order.
412
+ */
375
413
  states(entity, depth) {
376
414
  return EntityHistory.require(entity).states(EntityHistory.depth(depth));
377
415
  },
416
+ /**
417
+ * Reads diagnostic Events after checking the history read limit.
418
+ *
419
+ * @param entity Entity that produced the Events.
420
+ * @param depth Maximum number of Events to return.
421
+ * @returns Retained Events in descending producer-version order.
422
+ */
378
423
  events(entity, depth) {
379
424
  return EntityHistory.require(entity).events(EntityHistory.depth(depth));
380
425
  },
426
+ /**
427
+ * Gets the state-history storage attached by the repository.
428
+ *
429
+ * @param entity Entity whose retained states are maintained.
430
+ * @returns Its state-history storage.
431
+ */
381
432
  stateMaintenance(entity) {
382
433
  return EntityHistory.require(entity).stateMaintenance;
383
434
  },
435
+ /**
436
+ * Gets diagnostic Event storage attached by the repository.
437
+ *
438
+ * @param entity Entity whose retained Events are maintained.
439
+ * @returns Its diagnostic Event storage.
440
+ */
384
441
  eventMaintenance(entity) {
385
442
  return EntityHistory.require(entity).eventMaintenance;
386
443
  },
@@ -389,6 +446,12 @@ export const entityHistoryAccess = Object.freeze({
389
446
  * Validates repository-bound history lookups.
390
447
  */
391
448
  const EntityHistory = Object.freeze({
449
+ /**
450
+ * Gets history operations installed during repository execution.
451
+ *
452
+ * @param entity Entity instance whose binding is required.
453
+ * @returns Its repository history operations.
454
+ */
392
455
  require(entity) {
393
456
  const binding = boundEntityHistories.get(entity);
394
457
  if (binding === undefined) {
@@ -396,6 +459,12 @@ const EntityHistory = Object.freeze({
396
459
  }
397
460
  return binding;
398
461
  },
462
+ /**
463
+ * Rejects history read limits that are not positive safe integers.
464
+ *
465
+ * @param depth Requested history read limit.
466
+ * @returns The validated limit.
467
+ */
399
468
  depth(depth) {
400
469
  if (!Number.isSafeInteger(depth) || depth <= 0) {
401
470
  throw new RangeError("Entity history depth must be a positive safe integer.");
@@ -404,16 +473,19 @@ const EntityHistory = Object.freeze({
404
473
  },
405
474
  });
406
475
  /**
407
- * Common in-memory entity shell with a protected scoped transaction draft.
476
+ * Entity base with one active transaction draft.
408
477
  *
409
478
  * The transaction scope is backed by {@link EntityTransaction}. Subclasses can
410
- * start one active draft, mutate draft state/version/lifecycle through protected
479
+ * start one active draft, mutate draft state and lifecycle through protected
411
480
  * helpers, and then commit or roll back the scope. Accepted commits replace this
412
- * entity's in-memory state, explicit version metadata, and lifecycle flags.
481
+ * Entity's state, framework-calculated Spine Version, and lifecycle flags.
413
482
  * Rejected commits leave the transaction active so subclass code can correct the
414
483
  * draft or roll it back explicitly. This base does not write repositories,
415
- * emit events, dispatch handlers, increment versions, or manage global
484
+ * emit events, dispatch handlers, or manage global
416
485
  * transaction state.
486
+ *
487
+ * @typeParam Id Domain identifier type.
488
+ * @typeParam Schema Generated schema describing the Entity state.
417
489
  */
418
490
  export class TransactionalEntity extends Entity {
419
491
  #transaction;
@@ -449,7 +521,7 @@ export class TransactionalEntity extends Entity {
449
521
  previous: this.state,
450
522
  version: {
451
523
  previous: previousVersion,
452
- draft: EntityVersions.clone(previousVersion),
524
+ draft: clone(VersionSchema, previousVersion),
453
525
  },
454
526
  lifecycle: this.lifecycle,
455
527
  });
@@ -463,19 +535,6 @@ export class TransactionalEntity extends Entity {
463
535
  currentDraft() {
464
536
  return this.#requireTransaction("currentDraft").currentDraft;
465
537
  }
466
- /**
467
- * Gets the current draft version metadata snapshot.
468
- *
469
- * @returns Cloned previous and draft version metadata.
470
- * @throws {@link TransactionalEntityScopeError} when no transaction is active.
471
- */
472
- draftVersionMetadata() {
473
- const version = this.#requireTransaction("draftVersionMetadata").version;
474
- return {
475
- previous: EntityVersions.clone(version.previous),
476
- draft: EntityVersions.clone(version.draft),
477
- };
478
- }
479
538
  /**
480
539
  * Gets the current draft lifecycle flag snapshot.
481
540
  *
@@ -508,17 +567,6 @@ export class TransactionalEntity extends Entity {
508
567
  tryUpdate(mutator) {
509
568
  return this.#requireTransaction("tryUpdate").tryUpdate(mutator);
510
569
  }
511
- /**
512
- * Updates the buffered draft version metadata without computing version increments.
513
- *
514
- * @param draft Caller-owned version metadata for the active draft.
515
- * @returns Cloned previous and draft version metadata.
516
- * @throws {@link TransactionalEntityScopeError} when no transaction is active.
517
- */
518
- updateDraftVersionMetadata(draft) {
519
- this.#requireTransaction("updateDraftVersionMetadata").updateVersionMetadata(EntityVersions.clone(draft));
520
- return this.draftVersionMetadata();
521
- }
522
570
  /**
523
571
  * Marks the buffered draft lifecycle as archived.
524
572
  *
@@ -558,23 +606,24 @@ export class TransactionalEntity extends Entity {
558
606
  /**
559
607
  * Commits the active draft transaction.
560
608
  *
561
- * Accepted commits apply state, version metadata, and lifecycle flags to this
609
+ * Accepted commits apply state, Spine Version, and lifecycle flags to this
562
610
  * entity and close the transaction. Rejected commits do not apply anything and
563
611
  * keep the transaction active for correction or explicit rollback.
564
612
  *
613
+ * @param producedEvents Whether handling returned Events, requiring a version advance.
565
614
  * @returns A cloned accepted or rejected transaction result.
566
615
  * @throws {@link TransactionalEntityScopeError} when no transaction is active.
567
616
  */
568
- commitTransaction() {
617
+ commitTransaction(producedEvents = false) {
569
618
  const transaction = this.#requireTransaction("commitTransaction");
570
- const result = transaction.commit();
619
+ const result = transaction.commit(producedEvents);
571
620
  if (result.status === "accepted") {
572
621
  if (result.previous === undefined ||
573
622
  !EntitySnapshots.equal(this.schema, result.previous, result.next)) {
574
623
  this.#stateChanged = true;
575
624
  }
576
625
  this.replaceState(result.next);
577
- this.replaceVersionMetadata(result.version.committed);
626
+ this.replaceVersion(result.version.committed);
578
627
  this.replaceLifecycleFlags(result.lifecycle);
579
628
  this.#transaction = undefined;
580
629
  rejectedCommits.delete(this);
@@ -595,6 +644,12 @@ export class TransactionalEntity extends Entity {
595
644
  this.#transaction = undefined;
596
645
  return result;
597
646
  }
647
+ /**
648
+ * Gets the active transaction or rejects an out-of-scope operation.
649
+ *
650
+ * @param operation Draft operation being attempted.
651
+ * @returns The currently active transaction.
652
+ */
598
653
  #requireTransaction(operation) {
599
654
  const transaction = this.#transaction;
600
655
  if (transaction?.status !== "active") {
@@ -609,12 +664,29 @@ export class TransactionalEntity extends Entity {
609
664
  * @internal
610
665
  */
611
666
  export const transactionalEntityAccess = Object.freeze({
667
+ /**
668
+ * Starts the Entity's protected transaction before invoking its handler.
669
+ *
670
+ * @param entity Entity about to handle a signal.
671
+ */
612
672
  start(entity) {
613
673
  TransactionAccess.call(entity, "startTransaction");
614
674
  },
615
- commit(entity) {
616
- return TransactionAccess.call(entity, "commitTransaction");
675
+ /**
676
+ * Commits the handler's draft and records whether it returned Events.
677
+ *
678
+ * @param entity Entity whose handler has completed.
679
+ * @param producedEvents Whether handling returned domain Events.
680
+ * @returns The accepted or validation-rejected transaction result.
681
+ */
682
+ commit(entity, producedEvents = false) {
683
+ return TransactionAccess.call(entity, "commitTransaction", producedEvents);
617
684
  },
685
+ /**
686
+ * Rolls back an active draft, ignoring a transaction that has already closed.
687
+ *
688
+ * @param entity Entity whose handling failed or was rejected.
689
+ */
618
690
  rollback(entity) {
619
691
  try {
620
692
  TransactionAccess.call(entity, "rollbackTransaction");
@@ -625,6 +697,12 @@ export const transactionalEntityAccess = Object.freeze({
625
697
  }
626
698
  }
627
699
  },
700
+ /**
701
+ * Reads the validation failure retained for the Entity's latest rejected commit.
702
+ *
703
+ * @param entity Entity whose rejected result is requested.
704
+ * @returns A copy of the rejected result, or undefined when none is retained.
705
+ */
628
706
  rejectedCommit(entity) {
629
707
  const rejected = rejectedCommits.get(entity);
630
708
  return rejected === undefined
@@ -636,28 +714,44 @@ export const transactionalEntityAccess = Object.freeze({
636
714
  * Bridges repository code to protected transactional entity methods.
637
715
  */
638
716
  const TransactionAccess = Object.freeze({
639
- call(entity, methodName) {
717
+ /**
718
+ * Invokes a protected transaction method from repository code.
719
+ *
720
+ * @param entity Instance receiving the method call.
721
+ * @param methodName Transaction method to invoke.
722
+ * @param args Arguments passed to the transaction method.
723
+ * @returns The method's result.
724
+ */
725
+ call(entity, methodName, ...args) {
640
726
  const method = entity[methodName];
641
727
  if (typeof method !== "function") {
642
728
  throw new TypeError(`Transactional entity access requires "${methodName}".`);
643
729
  }
644
- return Reflect.apply(method, entity, []);
730
+ return Reflect.apply(method, entity, args);
645
731
  },
732
+ /**
733
+ * Tests whether an operation failed because no transaction was active.
734
+ *
735
+ * @param error Failure returned by a transaction operation.
736
+ * @returns True only for a missing transaction scope.
737
+ */
646
738
  isMissing(error) {
647
739
  return error instanceof TransactionalEntityScopeError && error.reason === "missing";
648
740
  },
649
741
  });
650
742
  /**
651
- * Abstract aggregate family marker over the common transactional entity shell.
743
+ * Base class for Aggregates with transactional state and Event-history access.
744
+ *
745
+ * Provides Aggregate family identity and protected repository-backed history
746
+ * methods. Repositories and bounded contexts handle dispatch, persistence, and
747
+ * Event publication; application handlers change state through draft helpers.
652
748
  *
653
- * This class intentionally adds only stable family identity. It does not add
654
- * command dispatch, snapshots, repositories, idempotency guards, or handler
655
- * invocation. Repository-bound diagnostic event-history reads are declared
656
- * below for the Aggregate family.
749
+ * @typeParam Id Domain identifier type.
750
+ * @typeParam Schema Generated schema describing the Aggregate state.
657
751
  */
658
752
  export class Aggregate extends TransactionalEntity {
659
753
  /**
660
- * Creates an aggregate family shell from caller-provided state and metadata inputs.
754
+ * Creates an Aggregate from its identity, state, and metadata.
661
755
  *
662
756
  * @param options Identity, schema, state, version, and lifecycle inputs.
663
757
  */
@@ -694,15 +788,18 @@ export class Aggregate extends TransactionalEntity {
694
788
  }
695
789
  }
696
790
  /**
697
- * Abstract projection family marker over the common transactional entity shell.
791
+ * Base class for Projections with transactional state.
698
792
  *
699
- * This class intentionally adds only stable family identity. It does not add
700
- * event subscriptions, event playing, repositories, version columns, query
701
- * clients, or handler invocation.
793
+ * Provides Projection family identity. Repositories and bounded contexts invoke
794
+ * Event handlers and persist their state changes with the Projection's Version.
795
+ * Projections do not expose the diagnostic history methods of other families.
796
+ *
797
+ * @typeParam Id Domain identifier type.
798
+ * @typeParam Schema Generated schema describing the Projection state.
702
799
  */
703
800
  export class Projection extends TransactionalEntity {
704
801
  /**
705
- * Creates a projection family shell from caller-provided state and metadata inputs.
802
+ * Creates a Projection from its identity, state, and metadata.
706
803
  *
707
804
  * @param options Identity, schema, state, version, and lifecycle inputs.
708
805
  */
@@ -712,15 +809,18 @@ export class Projection extends TransactionalEntity {
712
809
  }
713
810
  }
714
811
  /**
715
- * Abstract process manager family marker over the common transactional entity shell.
812
+ * Base class for Process Managers coordinating a workflow through signals.
813
+ *
814
+ * Provides transactional state, protected Event-history access, and
815
+ * handler-scoped Projection reads through `select()`. Repositories and bounded
816
+ * contexts invoke handlers, persist changes, and deliver returned signals.
716
817
  *
717
- * This class adds a protected, handler-scoped, read-only Projection query
718
- * capability. It does not add command posting, repositories, bounded-context
719
- * injection, or handler invocation.
818
+ * @typeParam Id Domain identifier type.
819
+ * @typeParam Schema Generated schema describing the Process Manager state.
720
820
  */
721
821
  export class ProcessManager extends TransactionalEntity {
722
822
  /**
723
- * Creates a process manager family shell from caller-provided state and metadata inputs.
823
+ * Creates a Process Manager from its identity, state, and metadata.
724
824
  *
725
825
  * @param options Identity, schema, state, version, and lifecycle inputs.
726
826
  */
@@ -762,6 +862,8 @@ export class ProcessManager extends TransactionalEntity {
762
862
  * handler. Reads use that signal's actor and tenant; they cannot mutate state
763
863
  * or select a different tenant.
764
864
  *
865
+ * @typeParam QuerySchema Generated Projection state schema to query.
866
+ * @typeParam Columns Descriptor-backed columns available for that schema.
765
867
  * @param schema Projection state schema to query.
766
868
  * @param columns Generated descriptor-backed columns for `schema`.
767
869
  * @returns A read-only Entity query.
@@ -775,6 +877,12 @@ export class ProcessManager extends TransactionalEntity {
775
877
  * Marks immutable entity families.
776
878
  */
777
879
  const EntityFamilies = Object.freeze({
880
+ /**
881
+ * Sets an immutable family marker on an Entity instance.
882
+ *
883
+ * @param entity Instance being constructed.
884
+ * @param family Aggregate, Projection, or Process Manager family marker.
885
+ */
778
886
  mark(entity, family) {
779
887
  Object.defineProperty(entity, "entityFamily", {
780
888
  configurable: false,
@@ -788,9 +896,26 @@ const EntityFamilies = Object.freeze({
788
896
  * Creates entity-state snapshots and compares state bytes.
789
897
  */
790
898
  const EntitySnapshots = Object.freeze({
899
+ /**
900
+ * Copies state through its schema, discarding unknown wire fields.
901
+ *
902
+ * @typeParam Schema Generated schema describing the state.
903
+ * @param schema Schema used for encoding and decoding.
904
+ * @param state State snapshot to copy.
905
+ * @returns An independent state message containing known fields.
906
+ */
791
907
  clone(schema, state) {
792
908
  return fromBinary(schema, toBinary(schema, state, { writeUnknownFields: false }));
793
909
  },
910
+ /**
911
+ * Compares the encoded known fields of two state snapshots.
912
+ *
913
+ * @typeParam Schema Generated schema shared by both snapshots.
914
+ * @param schema Schema used to encode the states.
915
+ * @param previous State before handling.
916
+ * @param next State after handling.
917
+ * @returns True when their encoded known fields are identical.
918
+ */
794
919
  equal(schema, previous, next) {
795
920
  const previousBinary = toBinary(schema, previous, { writeUnknownFields: false });
796
921
  const nextBinary = toBinary(schema, next, { writeUnknownFields: false });
@@ -799,16 +924,23 @@ const EntitySnapshots = Object.freeze({
799
924
  },
800
925
  });
801
926
  /**
802
- * Creates immutable transaction-result snapshots.
927
+ * Copies transaction version, lifecycle, and validation snapshots.
803
928
  */
804
929
  const EntityCommits = Object.freeze({
930
+ /**
931
+ * Copies version, lifecycle, and validation messages in a transaction result.
932
+ *
933
+ * @typeParam Schema Generated schema describing the transaction's state.
934
+ * @param result Accepted or rejected transaction result.
935
+ * @returns A result with independent version and validation metadata.
936
+ */
805
937
  clone(result) {
806
938
  if (result.status === "accepted") {
807
939
  return {
808
940
  ...result,
809
941
  version: {
810
- previous: EntityVersions.clone(result.version.previous),
811
- committed: EntityVersions.clone(result.version.committed),
942
+ previous: clone(VersionSchema, result.version.previous),
943
+ committed: clone(VersionSchema, result.version.committed),
812
944
  },
813
945
  lifecycle: { archived: result.lifecycle.archived, deleted: result.lifecycle.deleted },
814
946
  validation: this.validation(result.validation),
@@ -817,13 +949,19 @@ const EntityCommits = Object.freeze({
817
949
  return {
818
950
  ...result,
819
951
  version: {
820
- previous: EntityVersions.clone(result.version.previous),
821
- draft: EntityVersions.clone(result.version.draft),
952
+ previous: clone(VersionSchema, result.version.previous),
953
+ draft: clone(VersionSchema, result.version.draft),
822
954
  },
823
955
  lifecycle: { archived: result.lifecycle.archived, deleted: result.lifecycle.deleted },
824
956
  validation: this.validation(result.validation),
825
957
  };
826
958
  },
959
+ /**
960
+ * Copies validation errors without exposing the stored violation messages.
961
+ *
962
+ * @param validation State-transition validation result.
963
+ * @returns An independent valid result or cloned validation error.
964
+ */
827
965
  validation(validation) {
828
966
  if (validation.valid) {
829
967
  return { valid: true, violations: [], error: undefined };
@@ -836,146 +974,4 @@ const EntityCommits = Object.freeze({
836
974
  };
837
975
  },
838
976
  });
839
- const maxVersionMetadataDepth = 1_000;
840
- /**
841
- * Validates and clones caller-provided plain version metadata.
842
- */
843
- const EntityVersions = Object.freeze({
844
- clone(version) {
845
- return this.value(version, "$", new WeakSet(), 0);
846
- },
847
- value(value, path, stack, depth) {
848
- if (depth > maxVersionMetadataDepth) {
849
- throw this.error(path, "excessive nesting depth");
850
- }
851
- if (value === null) {
852
- return value;
853
- }
854
- switch (typeof value) {
855
- case "string":
856
- case "number":
857
- case "boolean":
858
- case "bigint":
859
- case "symbol":
860
- case "undefined":
861
- return value;
862
- case "function":
863
- throw this.error(path, "function");
864
- case "object":
865
- return this.object(value, path, stack, depth);
866
- }
867
- },
868
- object(value, path, stack, depth) {
869
- if (isProxy(value))
870
- throw this.error(path, "Proxy");
871
- if (ArrayBuffer.isView(value))
872
- throw this.error(path, this.kind(value));
873
- if (value instanceof ArrayBuffer || this.isSharedBuffer(value)) {
874
- throw this.error(path, this.kind(value));
875
- }
876
- if (stack.has(value))
877
- throw this.error(path, "cyclic object");
878
- stack.add(value);
879
- try {
880
- if (Array.isArray(value))
881
- return this.array(value, path, stack, depth);
882
- if (!this.isPlainObject(value))
883
- throw this.error(path, this.kind(value));
884
- const clone = Object.create(this.prototype(value));
885
- const descriptors = Object.getOwnPropertyDescriptors(value);
886
- const [symbolKey] = Object.getOwnPropertySymbols(descriptors);
887
- if (symbolKey !== undefined) {
888
- throw this.error(`${path}[${String(symbolKey)}]`, "symbol-keyed property");
889
- }
890
- for (const [key, descriptor] of Object.entries(descriptors)) {
891
- const childPath = `${path}.${key}`;
892
- if (!descriptor.enumerable)
893
- throw this.error(childPath, "non-enumerable property");
894
- if (!("value" in descriptor))
895
- throw this.error(childPath, "accessor property");
896
- Object.defineProperty(clone, key, {
897
- configurable: true,
898
- enumerable: true,
899
- value: this.value(descriptor.value, childPath, stack, depth + 1),
900
- writable: true,
901
- });
902
- }
903
- return clone;
904
- }
905
- finally {
906
- stack.delete(value);
907
- }
908
- },
909
- array(value, path, stack, depth) {
910
- if (this.prototype(value) !== Array.prototype)
911
- throw this.error(path, "Array");
912
- const descriptors = Object.getOwnPropertyDescriptors(value);
913
- const [symbolKey] = Object.getOwnPropertySymbols(descriptors);
914
- if (symbolKey !== undefined) {
915
- throw this.error(`${path}[${String(symbolKey)}]`, "symbol-keyed property");
916
- }
917
- const lengthDescriptor = descriptors.length;
918
- if (lengthDescriptor === undefined || !("value" in lengthDescriptor)) {
919
- throw this.error(path, "array without data length");
920
- }
921
- const length = lengthDescriptor.value;
922
- const clone = new Array(length);
923
- for (const [key, descriptor] of Object.entries(descriptors)) {
924
- if (key === "length")
925
- continue;
926
- if (!this.isArrayKey(key, length))
927
- throw this.error(`${path}.${key}`, "custom array property");
928
- if (!descriptor.enumerable)
929
- throw this.error(`${path}[${key}]`, "non-enumerable property");
930
- if (!("value" in descriptor))
931
- throw this.error(`${path}[${key}]`, "accessor property");
932
- }
933
- for (let index = 0; index < length; index += 1) {
934
- const key = String(index);
935
- const descriptor = descriptors[key];
936
- if (descriptor === undefined || !("value" in descriptor)) {
937
- throw this.error(`${path}[${key}]`, "sparse array element");
938
- }
939
- Object.defineProperty(clone, index, {
940
- configurable: true,
941
- enumerable: true,
942
- value: this.value(descriptor.value, `${path}[${key}]`, stack, depth + 1),
943
- writable: true,
944
- });
945
- }
946
- return clone;
947
- },
948
- isArrayKey(key, length) {
949
- const index = Number(key);
950
- return Number.isInteger(index) && index >= 0 && index < length && String(index) === key;
951
- },
952
- isPlainObject(value) {
953
- const prototype = this.prototype(value);
954
- return prototype === Object.prototype || prototype === null;
955
- },
956
- prototype(value) {
957
- return Object.getPrototypeOf(value);
958
- },
959
- kind(value) {
960
- if (value instanceof Date)
961
- return "Date";
962
- if (value instanceof Map)
963
- return "Map";
964
- if (value instanceof Set)
965
- return "Set";
966
- if (ArrayBuffer.isView(value))
967
- return "typed array";
968
- if (value instanceof ArrayBuffer)
969
- return "ArrayBuffer";
970
- if (this.isSharedBuffer(value))
971
- return "SharedArrayBuffer";
972
- return "object";
973
- },
974
- isSharedBuffer(value) {
975
- return typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
976
- },
977
- error(path, kind) {
978
- return new TypeError(`Entity version metadata must be plain snapshot data; ${path} contains ${kind}.`);
979
- },
980
- });
981
977
  //# sourceMappingURL=entity.js.map