@spine-event-engine/server 2.0.0-snapshot.14 → 2.0.0-snapshot.16

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 (52) hide show
  1. package/README.md +53 -0
  2. package/REFERENCE.md +146 -23
  3. package/dist/context/bounded-context.d.ts +131 -20
  4. package/dist/context/bounded-context.d.ts.map +1 -1
  5. package/dist/context/bounded-context.js +647 -48
  6. package/dist/context/bounded-context.js.map +1 -1
  7. package/dist/entity/entity-metadata.d.ts +12 -3
  8. package/dist/entity/entity-metadata.d.ts.map +1 -1
  9. package/dist/entity/entity-metadata.js +37 -1
  10. package/dist/entity/entity-metadata.js.map +1 -1
  11. package/dist/entity/entity-transaction.d.ts +46 -42
  12. package/dist/entity/entity-transaction.d.ts.map +1 -1
  13. package/dist/entity/entity-transaction.js +130 -35
  14. package/dist/entity/entity-transaction.js.map +1 -1
  15. package/dist/entity/entity.d.ts +138 -100
  16. package/dist/entity/entity.d.ts.map +1 -1
  17. package/dist/entity/entity.js +217 -227
  18. package/dist/entity/entity.js.map +1 -1
  19. package/dist/handler/event-registration-readiness.d.ts +13 -56
  20. package/dist/handler/event-registration-readiness.d.ts.map +1 -1
  21. package/dist/handler/event-registration-readiness.js +23 -43
  22. package/dist/handler/event-registration-readiness.js.map +1 -1
  23. package/dist/handler/generated-handler-registry.d.ts +8 -0
  24. package/dist/handler/generated-handler-registry.d.ts.map +1 -1
  25. package/dist/handler/generated-handler-registry.js +165 -3
  26. package/dist/handler/generated-handler-registry.js.map +1 -1
  27. package/dist/handler/handler-decorators.d.ts +70 -33
  28. package/dist/handler/handler-decorators.d.ts.map +1 -1
  29. package/dist/handler/handler-decorators.js +88 -31
  30. package/dist/handler/handler-decorators.js.map +1 -1
  31. package/dist/handler/handler-metadata.d.ts +53 -51
  32. package/dist/handler/handler-metadata.d.ts.map +1 -1
  33. package/dist/handler/handler-metadata.js +214 -42
  34. package/dist/handler/handler-metadata.js.map +1 -1
  35. package/dist/handler/registration-readiness-metadata.d.ts +4 -0
  36. package/dist/handler/registration-readiness-metadata.d.ts.map +1 -1
  37. package/dist/handler/registration-readiness-metadata.js +82 -1
  38. package/dist/handler/registration-readiness-metadata.js.map +1 -1
  39. package/dist/index.d.ts +4 -4
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +1 -1
  42. package/dist/index.js.map +1 -1
  43. package/dist/repository/repository.d.ts +217 -70
  44. package/dist/repository/repository.d.ts.map +1 -1
  45. package/dist/repository/repository.js +2728 -354
  46. package/dist/repository/repository.js.map +1 -1
  47. package/dist/runtime/standalone-handler-runtime.d.ts +16 -0
  48. package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
  49. package/dist/runtime/standalone-handler-runtime.js +93 -18
  50. package/dist/runtime/standalone-handler-runtime.js.map +1 -1
  51. package/dist/tsconfig.tsbuildinfo +1 -1
  52. package/package.json +12 -12
@@ -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,15 @@ 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.
203
+ *
204
+ * Keeps the Entity ID, state schema, state, Spine Version, and lifecycle flags.
205
+ * State and Version accessors return copies, and lifecycle access returns a
206
+ * separate flag object. Repositories run handlers and manage storage.
188
207
  *
189
- * The shell exposes identity, descriptor-derived metadata, cloned state
190
- * snapshots, caller-owned plain version metadata snapshots, and lifecycle flags. It does not
191
- * invoke handlers, create transactions, write repositories or storage, dispatch
192
- * messages, increment versions, route IDs, query read models, start buses, or
193
- * mutate process-wide runtime state.
208
+ * @typeParam Id Domain identifier type.
209
+ * @typeParam Schema Generated schema describing the Entity state.
194
210
  */
195
211
  export class Entity {
196
212
  #id;
@@ -201,7 +217,7 @@ export class Entity {
201
217
  #lifecycle;
202
218
  #lifecycleFlagsChanged = false;
203
219
  /**
204
- * Creates an entity shell from caller-provided state and metadata inputs.
220
+ * Initializes an Entity from its ID, schema, state, Version, and lifecycle flags.
205
221
  *
206
222
  * @param options Identity, schema, state, version, and lifecycle inputs.
207
223
  */
@@ -210,7 +226,7 @@ export class Entity {
210
226
  this.#schema = options.schema;
211
227
  this.#metadata = describeEntityMetadata(options.schema);
212
228
  this.#state = EntitySnapshots.clone(options.schema, options.state);
213
- this.#version = EntityVersions.clone(options.version);
229
+ this.#version = clone(VersionSchema, options.version ?? create(VersionSchema));
214
230
  this.#lifecycle = {
215
231
  archived: options.lifecycle?.archived ?? false,
216
232
  deleted: options.lifecycle?.deleted ?? false,
@@ -219,7 +235,7 @@ export class Entity {
219
235
  /**
220
236
  * Gets the stable entity identifier.
221
237
  *
222
- * @returns The caller-owned entity identifier.
238
+ * @returns The domain identifier supplied during construction.
223
239
  */
224
240
  get id() {
225
241
  return this.#id;
@@ -249,12 +265,12 @@ export class Entity {
249
265
  return EntitySnapshots.clone(this.#schema, this.#state);
250
266
  }
251
267
  /**
252
- * Gets the caller-owned plain version metadata snapshot.
268
+ * Gets the current Spine Version without exposing the stored message.
253
269
  *
254
- * @returns A validated clone of the version metadata.
270
+ * @returns A copy of the version number and timestamp.
255
271
  */
256
272
  get version() {
257
- return EntityVersions.clone(this.#version);
273
+ return clone(VersionSchema, this.#version);
258
274
  }
259
275
  /**
260
276
  * Gets the current lifecycle flag snapshot.
@@ -300,7 +316,7 @@ export class Entity {
300
316
  return this.#lifecycleFlagsChanged;
301
317
  }
302
318
  /**
303
- * Replaces stored state from framework-owned subclass or runtime code.
319
+ * Replaces stored state when framework transaction code accepts a draft.
304
320
  *
305
321
  * @param state Next entity state snapshot.
306
322
  */
@@ -308,15 +324,15 @@ export class Entity {
308
324
  this.#state = EntitySnapshots.clone(this.#schema, state);
309
325
  }
310
326
  /**
311
- * Replaces caller-owned version metadata from framework-owned subclass or runtime code.
327
+ * Applies the Version calculated by a framework transaction.
312
328
  *
313
- * @param version Next caller-owned version metadata.
329
+ * @param version Accepted version number and timestamp.
314
330
  */
315
- replaceVersionMetadata(version) {
316
- this.#version = EntityVersions.clone(version);
331
+ replaceVersion(version) {
332
+ this.#version = clone(VersionSchema, version);
317
333
  }
318
334
  /**
319
- * Replaces lifecycle flags from framework-owned subclass or runtime code.
335
+ * Applies lifecycle flags accepted by framework transaction code.
320
336
  *
321
337
  * @param lifecycle Lifecycle flag changes to apply.
322
338
  */
@@ -366,21 +382,60 @@ const boundEntityHistories = new WeakMap();
366
382
  * @internal
367
383
  */
368
384
  export const entityHistoryAccess = Object.freeze({
385
+ /**
386
+ * Associates an Entity instance with its repository history operations.
387
+ *
388
+ * @param entity Entity instance loaded by the repository.
389
+ * @param binding Operations bound to that Entity's history.
390
+ */
369
391
  bind(entity, binding) {
370
392
  boundEntityHistories.set(entity, binding);
371
393
  },
394
+ /**
395
+ * Reads the most recent retained state no later than the requested time.
396
+ *
397
+ * @param entity Entity whose state is requested.
398
+ * @param time Latest allowed state timestamp.
399
+ * @returns The retained state, or undefined when none matches.
400
+ */
372
401
  stateAt(entity, time) {
373
402
  return EntityHistory.require(entity).stateAt(time);
374
403
  },
404
+ /**
405
+ * Reads retained states after checking the history read limit.
406
+ *
407
+ * @param entity Entity whose history is requested.
408
+ * @param depth Maximum number of states to return.
409
+ * @returns Retained states in descending version order.
410
+ */
375
411
  states(entity, depth) {
376
412
  return EntityHistory.require(entity).states(EntityHistory.depth(depth));
377
413
  },
414
+ /**
415
+ * Reads diagnostic Events after checking the history read limit.
416
+ *
417
+ * @param entity Entity that produced the Events.
418
+ * @param depth Maximum number of Events to return.
419
+ * @returns Retained Events in descending producer-version order.
420
+ */
378
421
  events(entity, depth) {
379
422
  return EntityHistory.require(entity).events(EntityHistory.depth(depth));
380
423
  },
424
+ /**
425
+ * Gets the state-history storage attached by the repository.
426
+ *
427
+ * @param entity Entity whose retained states are maintained.
428
+ * @returns Its state-history storage.
429
+ */
381
430
  stateMaintenance(entity) {
382
431
  return EntityHistory.require(entity).stateMaintenance;
383
432
  },
433
+ /**
434
+ * Gets diagnostic Event storage attached by the repository.
435
+ *
436
+ * @param entity Entity whose retained Events are maintained.
437
+ * @returns Its diagnostic Event storage.
438
+ */
384
439
  eventMaintenance(entity) {
385
440
  return EntityHistory.require(entity).eventMaintenance;
386
441
  },
@@ -389,6 +444,12 @@ export const entityHistoryAccess = Object.freeze({
389
444
  * Validates repository-bound history lookups.
390
445
  */
391
446
  const EntityHistory = Object.freeze({
447
+ /**
448
+ * Gets history operations installed during repository execution.
449
+ *
450
+ * @param entity Entity instance whose binding is required.
451
+ * @returns Its repository history operations.
452
+ */
392
453
  require(entity) {
393
454
  const binding = boundEntityHistories.get(entity);
394
455
  if (binding === undefined) {
@@ -396,6 +457,12 @@ const EntityHistory = Object.freeze({
396
457
  }
397
458
  return binding;
398
459
  },
460
+ /**
461
+ * Rejects history read limits that are not positive safe integers.
462
+ *
463
+ * @param depth Requested history read limit.
464
+ * @returns The validated limit.
465
+ */
399
466
  depth(depth) {
400
467
  if (!Number.isSafeInteger(depth) || depth <= 0) {
401
468
  throw new RangeError("Entity history depth must be a positive safe integer.");
@@ -404,16 +471,15 @@ const EntityHistory = Object.freeze({
404
471
  },
405
472
  });
406
473
  /**
407
- * Common in-memory entity shell with a protected scoped transaction draft.
474
+ * Entity base with one active transaction draft.
475
+ *
476
+ * Repository dispatch starts and finishes each transaction. Entity handlers
477
+ * change the draft state or lifecycle through protected helpers. A successful
478
+ * commit updates state, Spine Version, and lifecycle flags. A rejected commit
479
+ * leaves the draft active until the framework rolls it back.
408
480
  *
409
- * The transaction scope is backed by {@link EntityTransaction}. Subclasses can
410
- * start one active draft, mutate draft state/version/lifecycle through protected
411
- * 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.
413
- * Rejected commits leave the transaction active so subclass code can correct the
414
- * draft or roll it back explicitly. This base does not write repositories,
415
- * emit events, dispatch handlers, increment versions, or manage global
416
- * transaction state.
481
+ * @typeParam Id Domain identifier type.
482
+ * @typeParam Schema Generated schema describing the Entity state.
417
483
  */
418
484
  export class TransactionalEntity extends Entity {
419
485
  #transaction;
@@ -449,7 +515,7 @@ export class TransactionalEntity extends Entity {
449
515
  previous: this.state,
450
516
  version: {
451
517
  previous: previousVersion,
452
- draft: EntityVersions.clone(previousVersion),
518
+ draft: clone(VersionSchema, previousVersion),
453
519
  },
454
520
  lifecycle: this.lifecycle,
455
521
  });
@@ -463,19 +529,6 @@ export class TransactionalEntity extends Entity {
463
529
  currentDraft() {
464
530
  return this.#requireTransaction("currentDraft").currentDraft;
465
531
  }
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
532
  /**
480
533
  * Gets the current draft lifecycle flag snapshot.
481
534
  *
@@ -508,17 +561,6 @@ export class TransactionalEntity extends Entity {
508
561
  tryUpdate(mutator) {
509
562
  return this.#requireTransaction("tryUpdate").tryUpdate(mutator);
510
563
  }
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
564
  /**
523
565
  * Marks the buffered draft lifecycle as archived.
524
566
  *
@@ -558,23 +600,24 @@ export class TransactionalEntity extends Entity {
558
600
  /**
559
601
  * Commits the active draft transaction.
560
602
  *
561
- * Accepted commits apply state, version metadata, and lifecycle flags to this
603
+ * Accepted commits apply state, Spine Version, and lifecycle flags to this
562
604
  * entity and close the transaction. Rejected commits do not apply anything and
563
605
  * keep the transaction active for correction or explicit rollback.
564
606
  *
607
+ * @param producedEvents Whether handling returned Events, requiring a version advance.
565
608
  * @returns A cloned accepted or rejected transaction result.
566
609
  * @throws {@link TransactionalEntityScopeError} when no transaction is active.
567
610
  */
568
- commitTransaction() {
611
+ commitTransaction(producedEvents = false) {
569
612
  const transaction = this.#requireTransaction("commitTransaction");
570
- const result = transaction.commit();
613
+ const result = transaction.commit(producedEvents);
571
614
  if (result.status === "accepted") {
572
615
  if (result.previous === undefined ||
573
616
  !EntitySnapshots.equal(this.schema, result.previous, result.next)) {
574
617
  this.#stateChanged = true;
575
618
  }
576
619
  this.replaceState(result.next);
577
- this.replaceVersionMetadata(result.version.committed);
620
+ this.replaceVersion(result.version.committed);
578
621
  this.replaceLifecycleFlags(result.lifecycle);
579
622
  this.#transaction = undefined;
580
623
  rejectedCommits.delete(this);
@@ -595,6 +638,12 @@ export class TransactionalEntity extends Entity {
595
638
  this.#transaction = undefined;
596
639
  return result;
597
640
  }
641
+ /**
642
+ * Gets the active transaction or rejects an out-of-scope operation.
643
+ *
644
+ * @param operation Draft operation being attempted.
645
+ * @returns The currently active transaction.
646
+ */
598
647
  #requireTransaction(operation) {
599
648
  const transaction = this.#transaction;
600
649
  if (transaction?.status !== "active") {
@@ -609,12 +658,29 @@ export class TransactionalEntity extends Entity {
609
658
  * @internal
610
659
  */
611
660
  export const transactionalEntityAccess = Object.freeze({
661
+ /**
662
+ * Starts the Entity's protected transaction before invoking its handler.
663
+ *
664
+ * @param entity Entity about to handle a signal.
665
+ */
612
666
  start(entity) {
613
667
  TransactionAccess.call(entity, "startTransaction");
614
668
  },
615
- commit(entity) {
616
- return TransactionAccess.call(entity, "commitTransaction");
669
+ /**
670
+ * Commits the handler's draft and records whether it returned Events.
671
+ *
672
+ * @param entity Entity whose handler has completed.
673
+ * @param producedEvents Whether handling returned domain Events.
674
+ * @returns The accepted or validation-rejected transaction result.
675
+ */
676
+ commit(entity, producedEvents = false) {
677
+ return TransactionAccess.call(entity, "commitTransaction", producedEvents);
617
678
  },
679
+ /**
680
+ * Rolls back an active draft, ignoring a transaction that has already closed.
681
+ *
682
+ * @param entity Entity whose handling failed or was rejected.
683
+ */
618
684
  rollback(entity) {
619
685
  try {
620
686
  TransactionAccess.call(entity, "rollbackTransaction");
@@ -625,6 +691,12 @@ export const transactionalEntityAccess = Object.freeze({
625
691
  }
626
692
  }
627
693
  },
694
+ /**
695
+ * Reads the validation failure retained for the Entity's latest rejected commit.
696
+ *
697
+ * @param entity Entity whose rejected result is requested.
698
+ * @returns A copy of the rejected result, or undefined when none is retained.
699
+ */
628
700
  rejectedCommit(entity) {
629
701
  const rejected = rejectedCommits.get(entity);
630
702
  return rejected === undefined
@@ -636,28 +708,44 @@ export const transactionalEntityAccess = Object.freeze({
636
708
  * Bridges repository code to protected transactional entity methods.
637
709
  */
638
710
  const TransactionAccess = Object.freeze({
639
- call(entity, methodName) {
711
+ /**
712
+ * Invokes a protected transaction method from repository code.
713
+ *
714
+ * @param entity Instance receiving the method call.
715
+ * @param methodName Transaction method to invoke.
716
+ * @param args Arguments passed to the transaction method.
717
+ * @returns The method's result.
718
+ */
719
+ call(entity, methodName, ...args) {
640
720
  const method = entity[methodName];
641
721
  if (typeof method !== "function") {
642
722
  throw new TypeError(`Transactional entity access requires "${methodName}".`);
643
723
  }
644
- return Reflect.apply(method, entity, []);
724
+ return Reflect.apply(method, entity, args);
645
725
  },
726
+ /**
727
+ * Tests whether an operation failed because no transaction was active.
728
+ *
729
+ * @param error Failure returned by a transaction operation.
730
+ * @returns True only for a missing transaction scope.
731
+ */
646
732
  isMissing(error) {
647
733
  return error instanceof TransactionalEntityScopeError && error.reason === "missing";
648
734
  },
649
735
  });
650
736
  /**
651
- * Abstract aggregate family marker over the common transactional entity shell.
737
+ * Base class for Aggregates with transactional state and Event-history access.
738
+ *
739
+ * Provides Aggregate family identity and protected repository-backed history
740
+ * methods. Repositories and bounded contexts handle dispatch, persistence, and
741
+ * Event publication; application handlers change state through draft helpers.
652
742
  *
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.
743
+ * @typeParam Id Domain identifier type.
744
+ * @typeParam Schema Generated schema describing the Aggregate state.
657
745
  */
658
746
  export class Aggregate extends TransactionalEntity {
659
747
  /**
660
- * Creates an aggregate family shell from caller-provided state and metadata inputs.
748
+ * Creates an Aggregate from its identity, state, and metadata.
661
749
  *
662
750
  * @param options Identity, schema, state, version, and lifecycle inputs.
663
751
  */
@@ -694,15 +782,18 @@ export class Aggregate extends TransactionalEntity {
694
782
  }
695
783
  }
696
784
  /**
697
- * Abstract projection family marker over the common transactional entity shell.
785
+ * Base class for Projections with transactional state.
698
786
  *
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.
787
+ * Repositories and Bounded Contexts invoke Event handlers and persist state
788
+ * changes with the Projection's Version.
789
+ * Projections do not expose the diagnostic history methods of other families.
790
+ *
791
+ * @typeParam Id Domain identifier type.
792
+ * @typeParam Schema Generated schema describing the Projection state.
702
793
  */
703
794
  export class Projection extends TransactionalEntity {
704
795
  /**
705
- * Creates a projection family shell from caller-provided state and metadata inputs.
796
+ * Creates a Projection from its identity, state, and metadata.
706
797
  *
707
798
  * @param options Identity, schema, state, version, and lifecycle inputs.
708
799
  */
@@ -712,15 +803,18 @@ export class Projection extends TransactionalEntity {
712
803
  }
713
804
  }
714
805
  /**
715
- * Abstract process manager family marker over the common transactional entity shell.
806
+ * Base class for Process Managers coordinating a workflow through signals.
807
+ *
808
+ * Provides transactional state, protected Event-history access, and
809
+ * handler-scoped Projection reads through `select()`. Repositories and bounded
810
+ * contexts invoke handlers, persist changes, and deliver returned signals.
716
811
  *
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.
812
+ * @typeParam Id Domain identifier type.
813
+ * @typeParam Schema Generated schema describing the Process Manager state.
720
814
  */
721
815
  export class ProcessManager extends TransactionalEntity {
722
816
  /**
723
- * Creates a process manager family shell from caller-provided state and metadata inputs.
817
+ * Creates a Process Manager from its identity, state, and metadata.
724
818
  *
725
819
  * @param options Identity, schema, state, version, and lifecycle inputs.
726
820
  */
@@ -762,6 +856,8 @@ export class ProcessManager extends TransactionalEntity {
762
856
  * handler. Reads use that signal's actor and tenant; they cannot mutate state
763
857
  * or select a different tenant.
764
858
  *
859
+ * @typeParam QuerySchema Generated Projection state schema to query.
860
+ * @typeParam Columns Descriptor-backed columns available for that schema.
765
861
  * @param schema Projection state schema to query.
766
862
  * @param columns Generated descriptor-backed columns for `schema`.
767
863
  * @returns A read-only Entity query.
@@ -775,6 +871,12 @@ export class ProcessManager extends TransactionalEntity {
775
871
  * Marks immutable entity families.
776
872
  */
777
873
  const EntityFamilies = Object.freeze({
874
+ /**
875
+ * Records whether an Entity is an Aggregate, Projection, or Process Manager.
876
+ *
877
+ * @param entity Instance being constructed.
878
+ * @param family Kind of Entity being constructed.
879
+ */
778
880
  mark(entity, family) {
779
881
  Object.defineProperty(entity, "entityFamily", {
780
882
  configurable: false,
@@ -788,9 +890,26 @@ const EntityFamilies = Object.freeze({
788
890
  * Creates entity-state snapshots and compares state bytes.
789
891
  */
790
892
  const EntitySnapshots = Object.freeze({
893
+ /**
894
+ * Copies state through its schema, discarding unknown wire fields.
895
+ *
896
+ * @typeParam Schema Generated schema describing the state.
897
+ * @param schema Schema used for encoding and decoding.
898
+ * @param state State snapshot to copy.
899
+ * @returns An independent state message containing known fields.
900
+ */
791
901
  clone(schema, state) {
792
902
  return fromBinary(schema, toBinary(schema, state, { writeUnknownFields: false }));
793
903
  },
904
+ /**
905
+ * Compares the encoded known fields of two state snapshots.
906
+ *
907
+ * @typeParam Schema Generated schema shared by both snapshots.
908
+ * @param schema Schema used to encode the states.
909
+ * @param previous State before handling.
910
+ * @param next State after handling.
911
+ * @returns True when their encoded known fields are identical.
912
+ */
794
913
  equal(schema, previous, next) {
795
914
  const previousBinary = toBinary(schema, previous, { writeUnknownFields: false });
796
915
  const nextBinary = toBinary(schema, next, { writeUnknownFields: false });
@@ -799,16 +918,23 @@ const EntitySnapshots = Object.freeze({
799
918
  },
800
919
  });
801
920
  /**
802
- * Creates immutable transaction-result snapshots.
921
+ * Copies transaction version, lifecycle, and validation snapshots.
803
922
  */
804
923
  const EntityCommits = Object.freeze({
924
+ /**
925
+ * Copies version, lifecycle, and validation messages in a transaction result.
926
+ *
927
+ * @typeParam Schema Generated schema describing the transaction's state.
928
+ * @param result Accepted or rejected transaction result.
929
+ * @returns A result with independent version and validation metadata.
930
+ */
805
931
  clone(result) {
806
932
  if (result.status === "accepted") {
807
933
  return {
808
934
  ...result,
809
935
  version: {
810
- previous: EntityVersions.clone(result.version.previous),
811
- committed: EntityVersions.clone(result.version.committed),
936
+ previous: clone(VersionSchema, result.version.previous),
937
+ committed: clone(VersionSchema, result.version.committed),
812
938
  },
813
939
  lifecycle: { archived: result.lifecycle.archived, deleted: result.lifecycle.deleted },
814
940
  validation: this.validation(result.validation),
@@ -817,13 +943,19 @@ const EntityCommits = Object.freeze({
817
943
  return {
818
944
  ...result,
819
945
  version: {
820
- previous: EntityVersions.clone(result.version.previous),
821
- draft: EntityVersions.clone(result.version.draft),
946
+ previous: clone(VersionSchema, result.version.previous),
947
+ draft: clone(VersionSchema, result.version.draft),
822
948
  },
823
949
  lifecycle: { archived: result.lifecycle.archived, deleted: result.lifecycle.deleted },
824
950
  validation: this.validation(result.validation),
825
951
  };
826
952
  },
953
+ /**
954
+ * Copies validation errors without exposing the stored violation messages.
955
+ *
956
+ * @param validation State-transition validation result.
957
+ * @returns An independent valid result or cloned validation error.
958
+ */
827
959
  validation(validation) {
828
960
  if (validation.valid) {
829
961
  return { valid: true, violations: [], error: undefined };
@@ -836,146 +968,4 @@ const EntityCommits = Object.freeze({
836
968
  };
837
969
  },
838
970
  });
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
971
  //# sourceMappingURL=entity.js.map