@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
package/README.md CHANGED
@@ -43,6 +43,41 @@ Add generated entities with `BoundedContext.add(...)` and use
43
43
  context is single-tenant or multitenant by construction; select that mode
44
44
  before registering application handlers and storage.
45
45
 
46
+ ## Give an Entity an application service
47
+
48
+ Spine normally constructs an Entity with its ID, state, version, and lifecycle
49
+ options. If your constructor also needs a service, supply `onCreate` when
50
+ registering the class. For example, the Projects application's Process Manager
51
+ uses an assignment-weight service:
52
+
53
+ <!-- docs-snippet-path: examples/projects/test/topology.test.ts -->
54
+
55
+ ```ts
56
+ import { BoundedContext } from "@spine-event-engine/server";
57
+ import { TaskAssignment, type AssignmentWeightService } from "../src/index.js";
58
+
59
+ // Create shared services before starting the context.
60
+ const weights: AssignmentWeightService = { weightFor: () => 2 };
61
+ const builder = BoundedContext.singleTenant("Assignments")
62
+ .withGeneratedRegistryRoot(new URL("..", import.meta.url))
63
+ .add(TaskAssignment, {
64
+ // Forward Spine's options and add the service required by the constructor.
65
+ onCreate: (options) => new TaskAssignment(options, weights),
66
+ });
67
+ ```
68
+
69
+ Call `builder.buildAsync()` to assemble the context. The callback runs for each
70
+ fresh or restored Entity object, not just once per ID. It also works for
71
+ Aggregates and Projections, including Projection rebuilds. Return a fresh
72
+ instance synchronously and pass the supplied options unchanged. Application
73
+ services are not persisted; the application manages their initialization and
74
+ shutdown. Constructors that need only `EntityOptions` require no callback.
75
+
76
+ Explicit repositories accept `onCreate` in their options too. See the
77
+ [guide](https://github.com/SpineEventEngine/spine-ts/blob/master/docs/USER_GUIDE.md#give-an-entity-an-application-service) for the
78
+ full story and the [reference](REFERENCE.md#entity-constructor-dependencies)
79
+ for the exact contract.
80
+
46
81
  ## Async handlers and Process Manager queries
47
82
 
48
83
  An `@Assign`, `@Command`, `@React`, or `@Subscribe` handler may return its
@@ -52,6 +87,24 @@ results and structural or imported thenable lookalikes are rejected during handl
52
87
  analysis. Rejection rolls back framework state and suppresses produced output; it
53
88
  cannot roll back an external HTTP request or other side effect.
54
89
 
90
+ Handler return declarations can use native unions for one of several results,
91
+ or fixed tuples for several ordered results. For example,
92
+ `CreateAccessGrant | ExtendAccessGrant` selects one Command, while
93
+ `readonly [AccessGrantCreated, AccessRequestCompleted?]` returns an Event and
94
+ possibly a second Event. Each actual result must be declared by that handler.
95
+ Arrays and local/imported aliases of these concrete message types are supported
96
+ too. `@Assign` returns Events, `@Command` returns Commands, `@React` returns
97
+ Events or `undefined`, and `@Subscribe` declares `void` or `Promise<void>`.
98
+ Event/rejection-input `@Command` also permits `undefined`, alone or alongside
99
+ concrete Command types. Only subscriptions accept `void`; required empty
100
+ results and unexpected returned values fail before Entity commit or publication.
101
+ See the [return-type guide](https://github.com/SpineEventEngine/spine-ts/blob/master/docs/USER_GUIDE.md#choose-what-a-handler-returns)
102
+ for examples, optional results, and the restrictions for each decorator.
103
+
104
+ Every Entity's `version` is the generated Spine `Version`; the framework
105
+ advances it once when a successful dispatch produces Events or changes state or
106
+ lifecycle, not for a no-op.
107
+
55
108
  Declare each domain rejection a command handler may throw. This registers the
56
109
  rejection before the server starts, so a client can subscribe even when no
57
110
  server handler consumes that rejection:
package/REFERENCE.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # @spine-event-engine/server reference
2
2
 
3
- This reference describes the public server contracts for coding agents.
3
+ This reference gives application developers and coding agents the detailed
4
+ server contracts. For an introduction and examples, start with the
5
+ [server README](README.md).
4
6
 
5
7
  ## Testing entry point
6
8
 
@@ -40,14 +42,49 @@ consume Events, rejections, or Entity states and produce no signal. State
40
42
  subscribers use the System Event Bus. Produced signals are published in-process
41
43
  on a best-effort basis; this is not an exactly-once contract.
42
44
 
45
+ ## Entity constructor dependencies
46
+
47
+ Supply `onCreate` when an Entity constructor needs an application service:
48
+ `new Repository({ entityType, schema, onCreate })` for an explicit repository,
49
+ or `.add(EntityClass, { onCreate })` when Spine creates the repository. The
50
+ callback receives `EntityOptions` with the registered class's exact identifier
51
+ and state-schema types. Its result must be an instance of that class.
52
+
53
+ `onCreate` is required when the class cannot be constructed with framework
54
+ options alone. It is optional for constructors that need only `EntityOptions`, or
55
+ constructors whose additional parameters are optional or have defaults.
56
+
57
+ For each new object, the callback must synchronously return a fresh instance
58
+ and pass the supplied options unchanged to its constructor. Those options
59
+ contain the ID, schema, state, Spine `Version`, and lifecycle flags. The same
60
+ callback runs when restoring a stored Aggregate, Projection, or Process Manager,
61
+ and when creating a Projection during a rebuild. It is not a once-per-ID hook.
62
+ Queries that read stored state without constructing an Entity do not call it.
63
+
64
+ Construct and initialize shared services before building the context. Keep
65
+ network calls and other business work in handlers, not in `onCreate`. A thrown
66
+ construction error fails that dispatch before its handler runs; it is not a
67
+ domain rejection. An asynchronous callback or a result of the wrong class is
68
+ rejected. Services are neither serialized nor closed by Spine; close them in
69
+ application shutdown after closing the context.
70
+
71
+ Spine still connects Entity history and Process Manager queries. A constructor
72
+ callback does not receive the current actor or tenant. Pass these to a service
73
+ from the handler when needed. Queries made through the Process Manager still
74
+ use the handler's context. Services are passed directly; no dependency container
75
+ is required, and the storage format is unchanged.
76
+
77
+ See the [Entity dependency guide](https://github.com/SpineEventEngine/spine-ts/blob/master/docs/USER_GUIDE.md#give-an-entity-an-application-service)
78
+ and the [Projects example](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/projects/README.md).
79
+
43
80
  ## Integration broker and event origin
44
81
 
45
82
  Each `BoundedContext` creates and closes exactly one private integration broker.
46
83
  The broker has distinct status, configuration, and event exchanges. Event
47
84
  export is requested-only: a context installs a domestic publisher only for
48
85
  event types requested by another context, and withdrawal removes only that
49
- requester's interest. The broker does not enforce ownership; the supported
50
- shape is many consumers and one domain producer per event type at a time.
86
+ requester's interest. Each event type should have one producing domain and may
87
+ have many consumers; the broker does not enforce that producer restriction.
51
88
 
52
89
  The status exchange announces `BoundedContextOnline`; observing a foreign
53
90
  announcement resends the local complete wanted-event document. The
@@ -133,9 +170,9 @@ To override the default channel factory, add
133
170
 
134
171
  ## Routing lifecycle
135
172
 
136
- Event, command, and state-update routing accepts exact schemas and nominal
137
- message-interface tokens. It selects exact, first registered matching token,
138
- then replacement/default. The route runs once at accepted admission; its
173
+ Event, command, and state-update routing accepts exact schemas and generated
174
+ message-interface tokens. It selects an exact schema first, then the first
175
+ matching token, then the replacement or default route. The route runs when the message is accepted; its
139
176
  validated typed targets are stored and reused for retries. The legacy-named
140
177
  local `catchUpReadSide()` helper is unrelated to retry: it resets and replays
141
178
  the whole local read side, and is not Projection catch-up.
@@ -253,6 +290,92 @@ rejection-input command reactions during generated metadata ingestion and
253
290
  repository construction.
254
291
  Event- and rejection-input `@Command` methods remain Event- or
255
292
  rejection-to-command reactions on Event Bus.
293
+
294
+ ### Handler return types
295
+
296
+ Use a TypeScript union such as `CreateAccessGrant | ExtendAccessGrant` to return
297
+ one of several Commands. A tuple such as
298
+ `readonly [AccessGrantCreated, AccessRequestCompleted?]` returns multiple Events
299
+ in order, with the second optional. Either declaration may have one outer
300
+ `Promise` layer. Generated metadata lists every possible schema; runtime checks
301
+ each result against the invoked handler's list. A whole result may be absent
302
+ for `@React` and Event/rejection-input `@Command`, using a generated signal type
303
+ unioned with `undefined`. A reaction that never emits can declare `undefined`
304
+ alone or `Promise<undefined>`. Either reaction kind may also return an empty
305
+ typed array. Command-input `@Command` and `@Assign` require nonempty results.
306
+ `@Subscribe` declares `void` or `Promise<void>` and produces no signals.
307
+ `@Throws` declares thrown rejections separately from normal results.
308
+
309
+ Only subscriptions accept `void`. An absent reaction result or optional tuple
310
+ entry uses `undefined`, never `null`. The framework validates all returned
311
+ values before committing Entity changes or publishing outputs. An invalid
312
+ subscription result fails even if it is an empty array. A valid no-output
313
+ reaction still saves its Entity state changes.
314
+
315
+ Other supported forms are `T[]`, `readonly T[]`, `Array<T>`, `ReadonlyArray<T>`,
316
+ named tuple entries, union alternatives inside tuple entries, and local or
317
+ imported aliases resolving to concrete generated messages. Only one flat
318
+ collection level is supported. Rest tuples, nested collections, nested promises,
319
+ custom thenables, framework envelopes, and unresolved/`any`/`unknown` result
320
+ branches are rejected. TypeScript enforces tuple structure; the runtime checks
321
+ declared message types, required nonempty results, and result order, not tuple
322
+ arity or positional schema constraints. See the
323
+ [user guide](https://github.com/SpineEventEngine/spine-ts/blob/master/docs/USER_GUIDE.md#choose-what-a-handler-returns) for a compact
324
+ return-type table and examples.
325
+
326
+ These independent examples use generated review-workflow messages. The Commander
327
+ chooses whether to start or schedule a review. The reactor example shows a
328
+ different workflow: record a started review and optionally schedule a follow-up.
329
+ They illustrate return declarations, not two handlers to register together.
330
+
331
+ <!-- docs-snippet-path: packages/server/test/runtime/standalone-handler-runtime.test.ts -->
332
+
333
+ ```ts
334
+ import { create } from "@bufbuild/protobuf";
335
+ import {
336
+ AbstractCommander,
337
+ AbstractEventReactor,
338
+ Command,
339
+ React,
340
+ } from "@spine-event-engine/server";
341
+ import {
342
+ StartReviewSchema,
343
+ ScheduleReviewSchema,
344
+ type StartReview,
345
+ type ScheduleReview,
346
+ } from "../../test-fixtures/generated/handler-registry/commands_pb.js";
347
+ import {
348
+ ReviewStartedSchema,
349
+ ReviewFollowUpScheduledSchema,
350
+ type ReviewStarted,
351
+ type ReviewFollowUpScheduled,
352
+ type ReviewTaskAssigned,
353
+ } from "../../test-fixtures/generated/handler-registry/events_pb.js";
354
+
355
+ export class ReviewCommander extends AbstractCommander {
356
+ @Command
357
+ planReview(event: ReviewTaskAssigned): StartReview | ScheduleReview {
358
+ // Return one Command, choosing its type using the application's rules.
359
+ return event.name === "Security review"
360
+ ? create(ScheduleReviewSchema, { id: event.id })
361
+ : create(StartReviewSchema, { id: event.id });
362
+ }
363
+ }
364
+
365
+ export class ReviewReactor extends AbstractEventReactor {
366
+ @React
367
+ recordReview(event: ReviewTaskAssigned): readonly [ReviewStarted, ReviewFollowUpScheduled?] {
368
+ const started = create(ReviewStartedSchema, { id: event.id });
369
+ // A tuple returns ordered Events. Its optional second value may be absent.
370
+ if (event.name !== "Security review") return [started];
371
+ return [
372
+ started,
373
+ create(ReviewFollowUpScheduledSchema, { id: event.id, name: "Security follow-up" }),
374
+ ];
375
+ }
376
+ }
377
+ ```
378
+
256
379
  Produced commands retain the source actor, tenant, origin, and causal lineage.
257
380
  The enqueue is post-commit best effort, not an atomic outbox or exactly-once
258
381
  delivery: a process crash between commit and enqueue can lose a child. Accepted
@@ -299,11 +422,7 @@ import {
299
422
  type ProjectId,
300
423
  } from "../generated/spine/server/testing/project_workflow_pb.js";
301
424
 
302
- class ApprovalCoordinator extends ProcessManager<
303
- ProjectId,
304
- typeof CoordinationStateSchema,
305
- number
306
- > {
425
+ class ApprovalCoordinator extends ProcessManager<ProjectId, typeof CoordinationStateSchema> {
307
426
  @Command
308
427
  approve(command: ApproveProject, context: CommandContext): ScheduleProject {
309
428
  this.update((draft) => Object.assign(draft, { id: this.id, projectName: command.status }));
@@ -335,7 +454,7 @@ const registry: GeneratedHandlerRegistry = {
335
454
  };
336
455
  const [handlers] = new HandlerRegistryIngestor().ingest(registry);
337
456
  if (handlers === undefined) throw new Error("Generated Process Manager metadata is missing.");
338
- const repository = new Repository({
457
+ const repository = new Repository<typeof ApprovalCoordinator>({
339
458
  entityType: ApprovalCoordinator,
340
459
  schema: CoordinationStateSchema,
341
460
  handlers: handlers as EntityHandlersMetadata<ApprovalCoordinator, typeof CoordinationStateSchema>,
@@ -395,7 +514,7 @@ the builder on the first build attempt.
395
514
 
396
515
  `SubscriptionService` streams are live best-effort notifications, not replay,
397
516
  ordering, or completeness contracts. A standalone Server defaults to the
398
- persistent registry. In a managed complete-replica cohort, the framework starts
517
+ persistent registry. In a group of managed server replicas, the framework starts
399
518
  and closes each child Server and accepts only every context's actual
400
519
  `InMemorySubscriptionRegistry`; a persistent or custom registry is rejected
401
520
  and the assembled child is closed before READY. Durable logical bindings remain
@@ -453,7 +572,7 @@ record-storage handle, while the context closes the registry.
453
572
 
454
573
  `Entity` is the state base class. `Aggregate`, `Projection`, and
455
574
  `ProcessManager` identify the three entity families. Handler decorators are
456
- `@Assign`, `@Command`, `@React`, `@Subscribe`, and `@Apply`. A command-accepting
575
+ `@Assign`, `@Command`, `@React`, and `@Subscribe`. A command-accepting
457
576
  handler uses `@Throws(GeneratedRejection)` to declare its possible domain
458
577
  rejections. Write the primary handler decorator first and `@Throws` immediately
459
578
  below it; declaration order does not affect behavior. Generated metadata records
@@ -464,6 +583,10 @@ handler, `update(mutator)` changes the active draft and returns the draft;
464
583
  `tryUpdate(mutator)` validates a scratch draft and returns violations without
465
584
  applying an invalid change. Entity lifecycle and version changes are committed
466
585
  only after the transaction accepts.
586
+ Every Entity exposes the generated Spine `Version` message, starting at number
587
+ zero. A dispatch that produces Events or changes state or lifecycle advances it
588
+ once; no-op and rejected dispatches do not. Repositories restore and persist the
589
+ full Version, including its timestamp, across current state, history, and Stand.
467
590
 
468
591
  ## Signals, validation, and rejection behavior
469
592
 
@@ -533,8 +656,8 @@ signal or explicit-close retry, and sets `process.exitCode` to `1` after a
533
656
  signal-driven failure.
534
657
 
535
658
  `ManagedServerApplication.run()` is the Node-only deployment entrypoint for a
536
- complete-replica process cohort when the framework handles process shutdown.
537
- `ManagedServerApplication.start()` starts the same cohort for an embedding host
659
+ group of complete server replicas when the framework handles process shutdown.
660
+ `ManagedServerApplication.start()` starts the same group for an embedding host
538
661
  and installs no process signal handlers; that host closes the returned handle.
539
662
  Both require a positive safe-integer
540
663
  `processCount` and an ESM `moduleUrl`; it never derives a process count from
@@ -566,7 +689,7 @@ admission.
566
689
  `ServerOptions` is native-only: it configures contexts, resources, services,
567
690
  and the native listener. It has no `browser` option and the root package does
568
691
  not load `@spine-event-engine/auth`. Browser hosting belongs to the explicit
569
- `@spine-event-engine/server/browser` entry point; see the [browser/auth guide](../../docs/BROWSER_CLIENT_AUTH_EXTENSION_GUIDE.md).
692
+ `@spine-event-engine/server/browser` entry point; see the [browser/auth guide](https://github.com/SpineEventEngine/spine-ts/blob/master/docs/BROWSER_CLIENT_AUTH_EXTENSION_GUIDE.md).
570
693
 
571
694
  Browser unary gateway admission has a fixed 1 MiB (1,048,576-byte) request
572
695
  limit. A larger unary gateway request is rejected with `ResourceExhausted`.
@@ -622,7 +745,7 @@ native backend. Concurrent calls share an attempt; a failed unfinished phase
622
745
  can be retried without repeating completed native cleanup.
623
746
 
624
747
  Browser subscription bindings are separate from service subscription records.
625
- `BrowserAdmission` selects their ownership. Authenticated mode supplies
748
+ `BrowserAdmission` determines who configures and manages them. Authenticated mode supplies
626
749
  `sessions` and may supply `BrowserServerOptions.bindings`; production then
627
750
  requires `DurableSubscriptionBindings` from `@spine-event-engine/server/browser` and rejects a
628
751
  missing or in-memory binding store before listener open. Public mode supplies
@@ -641,7 +764,7 @@ inside the stored Topic and are checked for Activate and Cancel. Create assigns
641
764
  the public ID directly; no quota, reservation, fingerprint, or lease is
642
765
  persisted. Cleanup remains bounded and restart-safe at the record level. It
643
766
  cleans the backend definition before deleting its record. It is not a cleaner
644
- lease or fence: this direct store supports one Gateway process. Active streams do not resume,
767
+ lock between Gateway processes: this store supports one Gateway process. Active streams do not resume,
645
768
  updates are not replayed, and the registry provides neither exactly-once
646
769
  delivery, global update ordering, nor cluster-complete notification delivery.
647
770
 
@@ -660,10 +783,10 @@ rows are direct records; a delivered row is the deduplication fact. A handler
660
783
  effect and the exact pending-to-delivered compare-and-set are not one
661
784
  transaction, so a lost acknowledgement can redeliver after restart. Downstream
662
785
  signal handling must be idempotent. A customized `DeliveryWorkRegistry`
663
- implements `validateOwnership()` so delivery can validate before dispatch, at
664
- repository commit time, and before acknowledgement. Validation is a fence
665
- against an observed takeover, not a distributed transaction with handler
666
- storage.
786
+ implements `validateOwnership()` so delivery can validate before dispatch, before
787
+ the Entity transaction commit, and before acknowledgement. These checks stop a worker
788
+ after it detects that another worker has taken the shard. They do not make
789
+ delivery and handler storage part of one distributed transaction.
667
790
 
668
791
  `keepUntil` is the optional deduplication-protection deadline, not a second
669
792
  retention setting. A delivered row is cleanup-eligible when that deadline is
@@ -118,10 +118,10 @@ export interface ContextDeliveryDescriptor {
118
118
  */
119
119
  onReady(onReady: OnDeliveryReady): () => void;
120
120
  /**
121
- * Updates readiness ownership to use configured delivery routes.
121
+ * Routes readiness notifications through the configured delivery routes.
122
122
  *
123
123
  * @param scopes Lists routes that may receive buffered readiness.
124
- * @param onReady Observes readiness after routed ownership begins.
124
+ * @param onReady Observes readiness after routing changes.
125
125
  * @param options Allows an empty route set when `allowEmpty` is true.
126
126
  * @returns A promise that resolves after the readiness transition completes.
127
127
  */
@@ -141,7 +141,7 @@ export interface CommandEndpoint {
141
141
  */
142
142
  acceptedCommandTypes(): readonly string[];
143
143
  /**
144
- * Posts a command into the context-owned command bus.
144
+ * Posts a command to this context's command bus.
145
145
  *
146
146
  * @param command Contains the command to dispatch.
147
147
  * @returns A promise that settles after queued command dispatch completes and may reject.
@@ -159,7 +159,7 @@ export interface EventEndpoint {
159
159
  */
160
160
  acceptedEventTypes(): readonly string[];
161
161
  /**
162
- * Posts an event into the context-owned event bus.
162
+ * Posts an event to this context's event bus.
163
163
  *
164
164
  * @param event Contains the event to dispatch.
165
165
  * @returns A promise that settles after persistence and dispatch complete and may reject.
@@ -218,24 +218,116 @@ interface FrameworkConstructionToken {
218
218
  readonly frameworkConstructionToken: true;
219
219
  }
220
220
  interface BoundedContextAccess {
221
+ /**
222
+ * Checks whether a value is a builder created by this module.
223
+ *
224
+ * @param value Value to check.
225
+ * @returns True for a registered builder.
226
+ */
221
227
  isBuilder(value: unknown): value is BoundedContextBuilder;
228
+ /**
229
+ * Builds a registered context builder with supplied default storage.
230
+ *
231
+ * @param builder Registered builder to build.
232
+ * @param defaultStorageFactory Storage used when the builder has none.
233
+ * @returns Promise resolving to a bounded context.
234
+ */
222
235
  build(builder: BoundedContextBuilder, defaultStorageFactory: StorageFactory): Promise<BoundedContext>;
236
+ /**
237
+ * Subscribes to a public event type on a built context.
238
+ *
239
+ * @param context Built context to observe.
240
+ * @param typeUrl Public event type URL.
241
+ * @param subscriber Event subscriber to register.
242
+ * @returns Cancellable event subscription.
243
+ */
223
244
  subscribeToEvent(context: BoundedContext, typeUrl: string, subscriber: EventSubscriber): EventSubscription;
245
+ /**
246
+ * Posts a framework System event through the context publisher.
247
+ *
248
+ * @param context Target bounded context.
249
+ * @param event System event to post.
250
+ * @returns Promise settling after publication.
251
+ */
224
252
  postSystemEvent(context: BoundedContext, event: Event): Promise<void>;
253
+ /**
254
+ * Marks a copied event as external and posts it through the context endpoint.
255
+ *
256
+ * @param context Target bounded context.
257
+ * @param event External event to post.
258
+ * @returns Event dispatch promise.
259
+ */
225
260
  postExternalEvent(context: BoundedContext, event: Event): Promise<void>;
261
+ /**
262
+ * Observes commands and events published by the context.
263
+ *
264
+ * @param context Context whose signals are observed.
265
+ * @param observer Callbacks for produced commands and events.
266
+ * @returns Handle whose close operation removes the observer.
267
+ */
226
268
  observeProducedSignals(context: BoundedContext, observer: {
227
269
  readonly onCommand?: (command: Readonly<Command>) => void;
228
270
  readonly onEvent?: (event: Readonly<Event>) => void;
229
271
  }): {
230
272
  readonly close: () => void;
231
273
  };
274
+ /**
275
+ * Returns a copy-safe snapshot of paired domain and System specifications.
276
+ *
277
+ * @param context Context whose pairing is read.
278
+ * @returns Paired specification snapshot.
279
+ */
232
280
  systemPairing(context: BoundedContext): SystemPairingSnapshot;
281
+ /**
282
+ * Returns the context tenant index.
283
+ *
284
+ * @param context Context whose index is read.
285
+ * @returns Tenant index for the built context.
286
+ */
233
287
  tenantIndex(context: BoundedContext): TenantIndex;
288
+ /**
289
+ * Returns the storage factory configured for a built context.
290
+ *
291
+ * @param context Context whose storage factory is read.
292
+ * @returns Configured storage factory.
293
+ */
234
294
  storageFactory(context: BoundedContext): StorageFactory;
295
+ /**
296
+ * Returns the context's Stand subscription registry.
297
+ *
298
+ * @param context Context whose registry is read.
299
+ * @returns Stand subscription registry.
300
+ */
235
301
  subscriptionRegistry(context: BoundedContext): StandSubscriptionRegistry;
302
+ /**
303
+ * Processes a registered Stand subscription and forwards each update.
304
+ *
305
+ * @param context Context containing the subscription.
306
+ * @param id Registered subscription ID.
307
+ * @param onUpdate Callback receiving updates.
308
+ * @returns Promise resolving to the subscription handle.
309
+ */
236
310
  consumeSubscription(context: BoundedContext, id: string, onUpdate: (update: import("@spine-event-engine/proto/client").SubscriptionUpdate) => void): Promise<import("../stand/stand.js").StandSubscription>;
311
+ /**
312
+ * Sets a logger on context buses and subscription runtime.
313
+ *
314
+ * @param context Context receiving the logger.
315
+ * @param logger Logging layer to install.
316
+ */
237
317
  installLogger(context: BoundedContext, logger: ILogLayer): void;
318
+ /**
319
+ * Returns the logger installed on a built context.
320
+ *
321
+ * @param context Context whose logger is read.
322
+ * @returns Installed logging layer.
323
+ */
238
324
  loggerFor(context: BoundedContext): ILogLayer;
325
+ /**
326
+ * Returns the delivery descriptor for a built context.
327
+ *
328
+ * @param context Context whose descriptor is read.
329
+ * @returns Delivery descriptor.
330
+ */
239
331
  delivery(context: BoundedContext): ContextDeliveryDescriptor;
240
332
  }
241
333
  /**
@@ -244,7 +336,7 @@ interface BoundedContextAccess {
244
336
  export declare class BoundedContext {
245
337
  #private;
246
338
  /**
247
- * Creates a framework-owned bounded context.
339
+ * Creates a Bounded Context from its prepared framework services.
248
340
  *
249
341
  * @param snapshot Contains the immutable context metadata.
250
342
  * @param commandBus Dispatches commands accepted by this context.
@@ -253,7 +345,7 @@ export declare class BoundedContext {
253
345
  * @param publisher Publishes signals produced by context handlers.
254
346
  * @param stand Stores read-side state for this context.
255
347
  * @param systemStand Stores read-side state for the paired System Context.
256
- * @param subscriptionRuntime Coordinates pair-owned subscription delivery.
348
+ * @param subscriptionRuntime Coordinates subscriptions for the paired contexts.
257
349
  * @param systemSpec Contains paired System Context metadata.
258
350
  * @param storageFactory Creates context storage.
259
351
  * @param repositories Lists repositories to register.
@@ -306,19 +398,19 @@ export declare class BoundedContext {
306
398
  */
307
399
  get snapshot(): BoundedContextSnapshot;
308
400
  /**
309
- * Returns the command endpoint owned by this context.
401
+ * Returns this context's command endpoint.
310
402
  *
311
403
  * @returns Returns the context command endpoint.
312
404
  */
313
405
  commandBus(): CommandEndpoint;
314
406
  /**
315
- * Returns the event endpoint owned by this context.
407
+ * Returns this context's event endpoint.
316
408
  *
317
409
  * @returns Returns the context event endpoint.
318
410
  */
319
411
  eventBus(): EventEndpoint;
320
412
  /**
321
- * Returns the context-owned read-side Stand.
413
+ * Returns the Stand that stores this context's read-side state.
322
414
  *
323
415
  * @returns Returns the read-side state store.
324
416
  */
@@ -356,14 +448,14 @@ export declare class BoundedContext {
356
448
  */
357
449
  catchUpReadSide(options?: ReadCatchUpOptions): Promise<ReadCatchUpResult>;
358
450
  /**
359
- * Closes context-owned buses, Stand, and repository storage/runtime bindings.
451
+ * Closes this context's buses, Stand, and repository storage and runtime bindings.
360
452
  *
361
453
  * Close is idempotent and returns the same close outcome on repeated calls.
362
- * The context attempts every owned close hook; when any hook fails, the
454
+ * The context attempts every close hook; when any hook fails, the
363
455
  * returned promise rejects with an `AggregateError` after the remaining hooks
364
456
  * have also been attempted.
365
457
  *
366
- * @returns A promise that settles after all owned resources close.
458
+ * @returns A promise that settles after all resources close.
367
459
  */
368
460
  close(): Promise<void>;
369
461
  }
@@ -372,18 +464,25 @@ export declare class BoundedContext {
372
464
  */
373
465
  export declare const boundedContextAccess: BoundedContextAccess;
374
466
  /**
375
- * Customizes a repository assembled from an Entity class and generated handlers.
467
+ * Configures routing and Entity construction for a generated repository.
468
+ *
469
+ * `onCreate` passes the framework's Entity options to an application constructor callback.
470
+ * It is required when the Entity class has additional required constructor arguments.
376
471
  *
377
- * @typeParam EntityType - The Entity class added to a Bounded Context builder.
472
+ * @typeParam EntityType The Entity class added to a Bounded Context builder.
378
473
  */
379
- export type GeneratedRepositoryOptions<EntityType extends RepositoryEntityType & ConcreteRepositoryEntityType<EntityType>> = Readonly<Pick<RepositoryOptions<EntityType>, "commandRouting" | "eventRouting" | "stateUpdateRouting" | "stringifierRegistry">>;
474
+ export type GeneratedRepositoryOptions<EntityType extends RepositoryEntityType & ConcreteRepositoryEntityType<EntityType>> = Readonly<Pick<RepositoryOptions<EntityType>, "commandRouting" | "eventRouting" | "stateUpdateRouting" | "stringifierRegistry">> & (RepositoryOptions<EntityType> extends {
475
+ readonly onCreate: infer Callback;
476
+ } ? {
477
+ readonly onCreate: Callback;
478
+ } : Pick<RepositoryOptions<EntityType>, "onCreate">);
380
479
  /**
381
480
  * Assembles a {@link BoundedContext} from repositories and dispatchers.
382
481
  */
383
482
  export declare class BoundedContextBuilder {
384
483
  #private;
385
484
  /**
386
- * Creates a framework-owned context builder.
485
+ * Creates a builder from a prepared context specification.
387
486
  *
388
487
  * @param specSnapshot Contains the initial context specification.
389
488
  * @param token Proves framework-controlled construction.
@@ -416,6 +515,7 @@ export declare class BoundedContextBuilder {
416
515
  /**
417
516
  * Adds an explicitly assembled repository.
418
517
  *
518
+ * @typeParam EntityType Concrete Entity class represented by the repository.
419
519
  * @param entry The repository to register.
420
520
  * @returns This builder for further configuration.
421
521
  */
@@ -423,14 +523,19 @@ export declare class BoundedContextBuilder {
423
523
  /**
424
524
  * Adds an Entity class whose repository is assembled from generated handlers.
425
525
  *
526
+ * @typeParam EntityType Concrete Entity class represented by this entry.
426
527
  * @param entry The Entity class to register.
427
- * @param options Optional custom routing and field mappings for its generated repository.
528
+ * @param options Routing and constructor callback for its generated repository. The callback
529
+ * is required when the Entity constructor needs additional application arguments.
428
530
  * @returns This builder for further configuration.
429
531
  */
430
- add<EntityType extends RepositoryEntityType & ConcreteRepositoryEntityType<EntityType>>(entry: EntityType, options?: GeneratedRepositoryOptions<EntityType>): this;
532
+ add<EntityType extends RepositoryEntityType & ConcreteRepositoryEntityType<EntityType>>(entry: EntityType, ...options: GeneratedRepositoryOptions<EntityType> extends {
533
+ readonly onCreate: object;
534
+ } ? [options: GeneratedRepositoryOptions<EntityType>] : [options?: GeneratedRepositoryOptions<EntityType>]): this;
431
535
  /**
432
536
  * Removes a repository from the context registration list.
433
537
  *
538
+ * @typeParam EntityType Concrete Entity class represented by the repository.
434
539
  * @param repository Identifies the repository to remove.
435
540
  * @returns Returns this builder for further configuration.
436
541
  */
@@ -504,7 +609,7 @@ export declare class BoundedContextBuilder {
504
609
  */
505
610
  withSubscriptionRegistry(registry: StandSubscriptionRegistry): this;
506
611
  /**
507
- * Sets the target-to-shard strategy for the context-owned Entity Inbox.
612
+ * Sets how Entity Inbox targets are assigned to shards.
508
613
  *
509
614
  * @param strategy Selects the durable shard for Aggregate and Process Manager targets.
510
615
  * @returns Returns this builder for further configuration.
@@ -534,6 +639,12 @@ export declare class BoundedContextBuilder {
534
639
  * @returns Resolves to the built context.
535
640
  */
536
641
  buildAsync(): Promise<BoundedContext>;
642
+ /**
643
+ * Creates the domain EventStore using this context's storage mode.
644
+ *
645
+ * @param storageFactory Storage provider for event records.
646
+ * @returns Domain EventStore.
647
+ */
537
648
  private createEventStore;
538
649
  }
539
650
  /**
@@ -542,7 +653,7 @@ export declare class BoundedContextBuilder {
542
653
  export declare class ContextSpec {
543
654
  #private;
544
655
  /**
545
- * Creates a framework-owned context specification.
656
+ * Creates a context specification from prepared values.
546
657
  *
547
658
  * @param snapshot Contains immutable specification values.
548
659
  * @param token Proves framework-controlled construction.