@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.
- package/README.md +53 -0
- package/REFERENCE.md +146 -23
- package/dist/context/bounded-context.d.ts +131 -20
- package/dist/context/bounded-context.d.ts.map +1 -1
- package/dist/context/bounded-context.js +647 -48
- package/dist/context/bounded-context.js.map +1 -1
- package/dist/entity/entity-metadata.d.ts +12 -3
- package/dist/entity/entity-metadata.d.ts.map +1 -1
- package/dist/entity/entity-metadata.js +37 -1
- package/dist/entity/entity-metadata.js.map +1 -1
- package/dist/entity/entity-transaction.d.ts +46 -42
- package/dist/entity/entity-transaction.d.ts.map +1 -1
- package/dist/entity/entity-transaction.js +130 -35
- package/dist/entity/entity-transaction.js.map +1 -1
- package/dist/entity/entity.d.ts +138 -100
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +217 -227
- package/dist/entity/entity.js.map +1 -1
- package/dist/handler/event-registration-readiness.d.ts +13 -56
- package/dist/handler/event-registration-readiness.d.ts.map +1 -1
- package/dist/handler/event-registration-readiness.js +23 -43
- package/dist/handler/event-registration-readiness.js.map +1 -1
- package/dist/handler/generated-handler-registry.d.ts +8 -0
- package/dist/handler/generated-handler-registry.d.ts.map +1 -1
- package/dist/handler/generated-handler-registry.js +165 -3
- package/dist/handler/generated-handler-registry.js.map +1 -1
- package/dist/handler/handler-decorators.d.ts +70 -33
- package/dist/handler/handler-decorators.d.ts.map +1 -1
- package/dist/handler/handler-decorators.js +88 -31
- package/dist/handler/handler-decorators.js.map +1 -1
- package/dist/handler/handler-metadata.d.ts +53 -51
- package/dist/handler/handler-metadata.d.ts.map +1 -1
- package/dist/handler/handler-metadata.js +214 -42
- package/dist/handler/handler-metadata.js.map +1 -1
- package/dist/handler/registration-readiness-metadata.d.ts +4 -0
- package/dist/handler/registration-readiness-metadata.d.ts.map +1 -1
- package/dist/handler/registration-readiness-metadata.js +82 -1
- package/dist/handler/registration-readiness-metadata.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/repository/repository.d.ts +217 -70
- package/dist/repository/repository.d.ts.map +1 -1
- package/dist/repository/repository.js +2728 -354
- package/dist/repository/repository.js.map +1 -1
- package/dist/runtime/standalone-handler-runtime.d.ts +16 -0
- package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
- package/dist/runtime/standalone-handler-runtime.js +93 -18
- package/dist/runtime/standalone-handler-runtime.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- 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
|
|
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.
|
|
50
|
-
|
|
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
|
|
137
|
-
message-interface tokens. It selects exact
|
|
138
|
-
then replacement
|
|
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
|
|
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`,
|
|
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
|
|
537
|
-
`ManagedServerApplication.start()` starts the same
|
|
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](
|
|
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`
|
|
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
|
-
|
|
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,
|
|
664
|
-
|
|
665
|
-
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|