@nwire/forge 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/__tests__/actor-methods.test.d.ts +9 -0
- package/dist/__tests__/actor-methods.test.d.ts.map +1 -0
- package/dist/__tests__/actor-methods.test.js +210 -0
- package/dist/__tests__/actor-methods.test.js.map +1 -0
- package/dist/__tests__/actor-schema-bound.test.d.ts +6 -0
- package/dist/__tests__/actor-schema-bound.test.d.ts.map +1 -0
- package/dist/__tests__/actor-schema-bound.test.js +112 -0
- package/dist/__tests__/actor-schema-bound.test.js.map +1 -0
- package/dist/__tests__/app-capabilities.test.d.ts +19 -0
- package/dist/__tests__/app-capabilities.test.d.ts.map +1 -0
- package/dist/__tests__/app-capabilities.test.js +57 -0
- package/dist/__tests__/app-capabilities.test.js.map +1 -0
- package/dist/__tests__/cli-runner.test.d.ts +6 -0
- package/dist/__tests__/cli-runner.test.d.ts.map +1 -0
- package/dist/__tests__/cli-runner.test.js +158 -0
- package/dist/__tests__/cli-runner.test.js.map +1 -0
- package/dist/__tests__/create-app.test.d.ts +18 -0
- package/dist/__tests__/create-app.test.d.ts.map +1 -0
- package/dist/__tests__/create-app.test.js +189 -0
- package/dist/__tests__/create-app.test.js.map +1 -0
- package/dist/__tests__/cross-service-bus.test.d.ts +8 -0
- package/dist/__tests__/cross-service-bus.test.d.ts.map +1 -0
- package/dist/__tests__/cross-service-bus.test.js +139 -0
- package/dist/__tests__/cross-service-bus.test.js.map +1 -0
- package/dist/__tests__/define-schema.test.d.ts +5 -0
- package/dist/__tests__/define-schema.test.d.ts.map +1 -0
- package/dist/__tests__/define-schema.test.js +83 -0
- package/dist/__tests__/define-schema.test.js.map +1 -0
- package/dist/__tests__/dev-logger.test.d.ts +9 -0
- package/dist/__tests__/dev-logger.test.d.ts.map +1 -0
- package/dist/__tests__/dev-logger.test.js +126 -0
- package/dist/__tests__/dev-logger.test.js.map +1 -0
- package/dist/__tests__/external-call.test.d.ts +14 -0
- package/dist/__tests__/external-call.test.d.ts.map +1 -0
- package/dist/__tests__/external-call.test.js +99 -0
- package/dist/__tests__/external-call.test.js.map +1 -0
- package/dist/__tests__/framework-events.test.d.ts +13 -0
- package/dist/__tests__/framework-events.test.d.ts.map +1 -0
- package/dist/__tests__/framework-events.test.js +204 -0
- package/dist/__tests__/framework-events.test.js.map +1 -0
- package/dist/__tests__/inline-handler.test.d.ts +8 -0
- package/dist/__tests__/inline-handler.test.d.ts.map +1 -0
- package/dist/__tests__/inline-handler.test.js +101 -0
- package/dist/__tests__/inline-handler.test.js.map +1 -0
- package/dist/__tests__/lifecycle-logging.test.d.ts +12 -0
- package/dist/__tests__/lifecycle-logging.test.d.ts.map +1 -0
- package/dist/__tests__/lifecycle-logging.test.js +112 -0
- package/dist/__tests__/lifecycle-logging.test.js.map +1 -0
- package/dist/__tests__/middleware.test.d.ts +7 -0
- package/dist/__tests__/middleware.test.d.ts.map +1 -0
- package/dist/__tests__/middleware.test.js +109 -0
- package/dist/__tests__/middleware.test.js.map +1 -0
- package/dist/__tests__/module-needs.test.d.ts +10 -0
- package/dist/__tests__/module-needs.test.d.ts.map +1 -0
- package/dist/__tests__/module-needs.test.js +77 -0
- package/dist/__tests__/module-needs.test.js.map +1 -0
- package/dist/__tests__/module-topo-sort.test.d.ts +15 -0
- package/dist/__tests__/module-topo-sort.test.d.ts.map +1 -0
- package/dist/__tests__/module-topo-sort.test.js +105 -0
- package/dist/__tests__/module-topo-sort.test.js.map +1 -0
- package/dist/__tests__/multi-tenancy.test.d.ts +10 -0
- package/dist/__tests__/multi-tenancy.test.d.ts.map +1 -0
- package/dist/__tests__/multi-tenancy.test.js +122 -0
- package/dist/__tests__/multi-tenancy.test.js.map +1 -0
- package/dist/__tests__/needs-topology.test.d.ts +11 -0
- package/dist/__tests__/needs-topology.test.d.ts.map +1 -0
- package/dist/__tests__/needs-topology.test.js +82 -0
- package/dist/__tests__/needs-topology.test.js.map +1 -0
- package/dist/__tests__/plugin-closure.test.d.ts +15 -0
- package/dist/__tests__/plugin-closure.test.d.ts.map +1 -0
- package/dist/__tests__/plugin-closure.test.js +140 -0
- package/dist/__tests__/plugin-closure.test.js.map +1 -0
- package/dist/__tests__/plugin.test.d.ts +10 -0
- package/dist/__tests__/plugin.test.d.ts.map +1 -0
- package/dist/__tests__/plugin.test.js +225 -0
- package/dist/__tests__/plugin.test.js.map +1 -0
- package/dist/__tests__/primitives.test.d.ts +9 -0
- package/dist/__tests__/primitives.test.d.ts.map +1 -0
- package/dist/__tests__/primitives.test.js +434 -0
- package/dist/__tests__/primitives.test.js.map +1 -0
- package/dist/__tests__/production-readiness.test.d.ts +22 -0
- package/dist/__tests__/production-readiness.test.d.ts.map +1 -0
- package/dist/__tests__/production-readiness.test.js +196 -0
- package/dist/__tests__/production-readiness.test.js.map +1 -0
- package/dist/__tests__/provider.test.d.ts +6 -0
- package/dist/__tests__/provider.test.d.ts.map +1 -0
- package/dist/__tests__/provider.test.js +122 -0
- package/dist/__tests__/provider.test.js.map +1 -0
- package/dist/__tests__/public-marker.test.d.ts +7 -0
- package/dist/__tests__/public-marker.test.d.ts.map +1 -0
- package/dist/__tests__/public-marker.test.js +54 -0
- package/dist/__tests__/public-marker.test.js.map +1 -0
- package/dist/__tests__/retry-dlq.test.d.ts +6 -0
- package/dist/__tests__/retry-dlq.test.d.ts.map +1 -0
- package/dist/__tests__/retry-dlq.test.js +68 -0
- package/dist/__tests__/retry-dlq.test.js.map +1 -0
- package/dist/__tests__/validate.test.d.ts +5 -0
- package/dist/__tests__/validate.test.d.ts.map +1 -0
- package/dist/__tests__/validate.test.js +53 -0
- package/dist/__tests__/validate.test.js.map +1 -0
- package/dist/__tests__/workflow-saga.test.d.ts +7 -0
- package/dist/__tests__/workflow-saga.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-saga.test.js +239 -0
- package/dist/__tests__/workflow-saga.test.js.map +1 -0
- package/dist/actor-store.d.ts +83 -0
- package/dist/actor-store.d.ts.map +1 -0
- package/dist/actor-store.js +85 -0
- package/dist/actor-store.js.map +1 -0
- package/dist/cli-runner.d.ts +46 -0
- package/dist/cli-runner.d.ts.map +1 -0
- package/dist/cli-runner.js +164 -0
- package/dist/cli-runner.js.map +1 -0
- package/dist/create-app.d.ts +131 -0
- package/dist/create-app.d.ts.map +1 -0
- package/dist/create-app.js +593 -0
- package/dist/create-app.js.map +1 -0
- package/dist/define-action.d.ts +148 -0
- package/dist/define-action.d.ts.map +1 -0
- package/dist/define-action.js +52 -0
- package/dist/define-action.js.map +1 -0
- package/dist/define-actor.d.ts +302 -0
- package/dist/define-actor.d.ts.map +1 -0
- package/dist/define-actor.js +294 -0
- package/dist/define-actor.js.map +1 -0
- package/dist/define-app.d.ts +104 -0
- package/dist/define-app.d.ts.map +1 -0
- package/dist/define-app.js +49 -0
- package/dist/define-app.js.map +1 -0
- package/dist/define-cron.d.ts +50 -0
- package/dist/define-cron.d.ts.map +1 -0
- package/dist/define-cron.js +34 -0
- package/dist/define-cron.js.map +1 -0
- package/dist/define-error.d.ts +10 -0
- package/dist/define-error.d.ts.map +1 -0
- package/dist/define-error.js +10 -0
- package/dist/define-error.js.map +1 -0
- package/dist/define-external-call.d.ts +85 -0
- package/dist/define-external-call.d.ts.map +1 -0
- package/dist/define-external-call.js +38 -0
- package/dist/define-external-call.js.map +1 -0
- package/dist/define-handler.d.ts +98 -0
- package/dist/define-handler.d.ts.map +1 -0
- package/dist/define-handler.js +29 -0
- package/dist/define-handler.js.map +1 -0
- package/dist/define-inbound-webhook.d.ts +82 -0
- package/dist/define-inbound-webhook.d.ts.map +1 -0
- package/dist/define-inbound-webhook.js +42 -0
- package/dist/define-inbound-webhook.js.map +1 -0
- package/dist/define-inbox.d.ts +40 -0
- package/dist/define-inbox.d.ts.map +1 -0
- package/dist/define-inbox.js +31 -0
- package/dist/define-inbox.js.map +1 -0
- package/dist/define-initializer.d.ts +54 -0
- package/dist/define-initializer.d.ts.map +1 -0
- package/dist/define-initializer.js +38 -0
- package/dist/define-initializer.js.map +1 -0
- package/dist/define-middleware.d.ts +8 -0
- package/dist/define-middleware.d.ts.map +1 -0
- package/dist/define-middleware.js +8 -0
- package/dist/define-middleware.js.map +1 -0
- package/dist/define-model.d.ts +10 -0
- package/dist/define-model.d.ts.map +1 -0
- package/dist/define-model.js +13 -0
- package/dist/define-model.js.map +1 -0
- package/dist/define-module.d.ts +157 -0
- package/dist/define-module.d.ts.map +1 -0
- package/dist/define-module.js +60 -0
- package/dist/define-module.js.map +1 -0
- package/dist/define-outbox.d.ts +47 -0
- package/dist/define-outbox.d.ts.map +1 -0
- package/dist/define-outbox.js +36 -0
- package/dist/define-outbox.js.map +1 -0
- package/dist/define-plugin.d.ts +171 -0
- package/dist/define-plugin.d.ts.map +1 -0
- package/dist/define-plugin.js +134 -0
- package/dist/define-plugin.js.map +1 -0
- package/dist/define-projection.d.ts +56 -0
- package/dist/define-projection.d.ts.map +1 -0
- package/dist/define-projection.js +44 -0
- package/dist/define-projection.js.map +1 -0
- package/dist/define-provider.d.ts +49 -0
- package/dist/define-provider.d.ts.map +1 -0
- package/dist/define-provider.js +45 -0
- package/dist/define-provider.js.map +1 -0
- package/dist/define-query.d.ts +50 -0
- package/dist/define-query.d.ts.map +1 -0
- package/dist/define-query.js +33 -0
- package/dist/define-query.js.map +1 -0
- package/dist/define-resolver.d.ts +111 -0
- package/dist/define-resolver.d.ts.map +1 -0
- package/dist/define-resolver.js +146 -0
- package/dist/define-resolver.js.map +1 -0
- package/dist/define-schema.d.ts +88 -0
- package/dist/define-schema.d.ts.map +1 -0
- package/dist/define-schema.js +72 -0
- package/dist/define-schema.js.map +1 -0
- package/dist/define-workflow.d.ts +193 -0
- package/dist/define-workflow.d.ts.map +1 -0
- package/dist/define-workflow.js +345 -0
- package/dist/define-workflow.js.map +1 -0
- package/dist/dev-logger.d.ts +41 -0
- package/dist/dev-logger.d.ts.map +1 -0
- package/dist/dev-logger.js +135 -0
- package/dist/dev-logger.js.map +1 -0
- package/dist/event-message.d.ts +37 -0
- package/dist/event-message.d.ts.map +1 -0
- package/dist/event-message.js +51 -0
- package/dist/event-message.js.map +1 -0
- package/dist/foundation.d.ts +14 -0
- package/dist/foundation.d.ts.map +1 -0
- package/dist/foundation.js +14 -0
- package/dist/foundation.js.map +1 -0
- package/dist/framework-event-bus.d.ts +13 -0
- package/dist/framework-event-bus.d.ts.map +1 -0
- package/dist/framework-event-bus.js +13 -0
- package/dist/framework-event-bus.js.map +1 -0
- package/dist/framework-events.d.ts +121 -0
- package/dist/framework-events.d.ts.map +1 -0
- package/dist/framework-events.js +67 -0
- package/dist/framework-events.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/module-surface.d.ts +47 -0
- package/dist/module-surface.d.ts.map +1 -0
- package/dist/module-surface.js +65 -0
- package/dist/module-surface.js.map +1 -0
- package/dist/projection-store.d.ts +26 -0
- package/dist/projection-store.d.ts.map +1 -0
- package/dist/projection-store.js +28 -0
- package/dist/projection-store.js.map +1 -0
- package/dist/public-marker.d.ts +35 -0
- package/dist/public-marker.d.ts.map +1 -0
- package/dist/public-marker.js +45 -0
- package/dist/public-marker.js.map +1 -0
- package/dist/response.d.ts +8 -0
- package/dist/response.d.ts.map +1 -0
- package/dist/response.js +8 -0
- package/dist/response.js.map +1 -0
- package/dist/runtime.d.ts +497 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1083 -0
- package/dist/runtime.js.map +1 -0
- package/dist/validate.d.ts +33 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +48 -0
- package/dist/validate.js.map +1 -0
- package/dist/when.d.ts +101 -0
- package/dist/when.d.ts.map +1 -0
- package/dist/when.js +57 -0
- package/dist/when.js.map +1 -0
- package/dist/workflow-timer-store.d.ts +78 -0
- package/dist/workflow-timer-store.d.ts.map +1 -0
- package/dist/workflow-timer-store.js +56 -0
- package/dist/workflow-timer-store.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineProjection` — first-class CQRS read models.
|
|
3
|
+
*
|
|
4
|
+
* export const SubmissionsByStudent = defineProjection('submissions-by-student', {
|
|
5
|
+
* listens: [AnswerSubmittedEvent, SubmissionAutoGradedEvent, ...],
|
|
6
|
+
* initial: () => ({}),
|
|
7
|
+
* on: {
|
|
8
|
+
* [AnswerSubmittedEvent.name]: (state, event) => ({
|
|
9
|
+
* ...state,
|
|
10
|
+
* [event.submissionId]: { ... }
|
|
11
|
+
* }),
|
|
12
|
+
* ...
|
|
13
|
+
* }
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* Projections are pure folds over event streams: `(state, event) => state`.
|
|
17
|
+
* The runtime registers a `when` listener for each event in `listens` and
|
|
18
|
+
* applies the corresponding `on` reducer to the projection's state.
|
|
19
|
+
*
|
|
20
|
+
* Queries (`defineQuery`) read from projections, not from actors. This
|
|
21
|
+
* preserves the CQRS separation: writes go through actors, reads through
|
|
22
|
+
* projections.
|
|
23
|
+
*
|
|
24
|
+
* Side effects (notifications, external sync) belong in `when` reactions, not
|
|
25
|
+
* in projections — projections are pure folds, like `assign`.
|
|
26
|
+
*/
|
|
27
|
+
import type { EventDefinition, EventPayload } from "@nwire/messages";
|
|
28
|
+
export type ProjectionReducer<TState, E extends EventDefinition = EventDefinition> = (state: TState, event: EventPayload<E>) => TState;
|
|
29
|
+
/** Studio-aware: declared read-model freshness target. */
|
|
30
|
+
export interface ProjectionFreshness {
|
|
31
|
+
/** Declared p95 milliseconds the projection lags behind the event stream. */
|
|
32
|
+
readonly p95MsBehindStream?: number;
|
|
33
|
+
}
|
|
34
|
+
export interface ProjectionOptions<TState> {
|
|
35
|
+
/** The events this projection folds over. Order matters for `on` lookup. */
|
|
36
|
+
readonly listens: readonly EventDefinition[];
|
|
37
|
+
/** Factory for the initial state when no events have been seen yet. */
|
|
38
|
+
readonly initial: () => TState;
|
|
39
|
+
/** Pure reducers, keyed by event name. */
|
|
40
|
+
readonly on: Readonly<Record<string, ProjectionReducer<TState>>>;
|
|
41
|
+
/** Free-form description (Studio-aware). */
|
|
42
|
+
readonly description?: string;
|
|
43
|
+
/** Declared freshness SLO (Studio-aware). */
|
|
44
|
+
readonly freshness?: ProjectionFreshness;
|
|
45
|
+
}
|
|
46
|
+
export interface ProjectionDefinition<TState = unknown> {
|
|
47
|
+
readonly $kind: "projection";
|
|
48
|
+
readonly name: string;
|
|
49
|
+
readonly listens: readonly EventDefinition[];
|
|
50
|
+
readonly initial: () => TState;
|
|
51
|
+
readonly on: Readonly<Record<string, ProjectionReducer<TState>>>;
|
|
52
|
+
readonly description?: string;
|
|
53
|
+
readonly freshness?: ProjectionFreshness;
|
|
54
|
+
}
|
|
55
|
+
export declare function defineProjection<TState>(name: string, options: ProjectionOptions<TState>): ProjectionDefinition<TState>;
|
|
56
|
+
//# sourceMappingURL=define-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-projection.d.ts","sourceRoot":"","sources":["../src/define-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAErE,MAAM,MAAM,iBAAiB,CAAC,MAAM,EAAE,CAAC,SAAS,eAAe,GAAG,eAAe,IAAI,CACnF,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,KACnB,MAAM,CAAC;AAEZ,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB,CAAC,MAAM;IACvC,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC;IAC/B,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACjE,4CAA4C;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB,CAAC,MAAM,GAAG,OAAO;IACpD,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC;IAC/B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,CAAC;CAC1C;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EACrC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,CAAC,MAAM,CAAC,GACjC,oBAAoB,CAAC,MAAM,CAAC,CAkB9B"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineProjection` — first-class CQRS read models.
|
|
3
|
+
*
|
|
4
|
+
* export const SubmissionsByStudent = defineProjection('submissions-by-student', {
|
|
5
|
+
* listens: [AnswerSubmittedEvent, SubmissionAutoGradedEvent, ...],
|
|
6
|
+
* initial: () => ({}),
|
|
7
|
+
* on: {
|
|
8
|
+
* [AnswerSubmittedEvent.name]: (state, event) => ({
|
|
9
|
+
* ...state,
|
|
10
|
+
* [event.submissionId]: { ... }
|
|
11
|
+
* }),
|
|
12
|
+
* ...
|
|
13
|
+
* }
|
|
14
|
+
* })
|
|
15
|
+
*
|
|
16
|
+
* Projections are pure folds over event streams: `(state, event) => state`.
|
|
17
|
+
* The runtime registers a `when` listener for each event in `listens` and
|
|
18
|
+
* applies the corresponding `on` reducer to the projection's state.
|
|
19
|
+
*
|
|
20
|
+
* Queries (`defineQuery`) read from projections, not from actors. This
|
|
21
|
+
* preserves the CQRS separation: writes go through actors, reads through
|
|
22
|
+
* projections.
|
|
23
|
+
*
|
|
24
|
+
* Side effects (notifications, external sync) belong in `when` reactions, not
|
|
25
|
+
* in projections — projections are pure folds, like `assign`.
|
|
26
|
+
*/
|
|
27
|
+
export function defineProjection(name, options) {
|
|
28
|
+
// Validate that every listened event has a reducer.
|
|
29
|
+
for (const event of options.listens) {
|
|
30
|
+
if (!options.on[event.name]) {
|
|
31
|
+
throw new Error(`defineProjection("${name}"): event "${event.name}" is in 'listens' but has no reducer in 'on'.`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
$kind: "projection",
|
|
36
|
+
name,
|
|
37
|
+
listens: options.listens,
|
|
38
|
+
initial: options.initial,
|
|
39
|
+
on: options.on,
|
|
40
|
+
description: options.description,
|
|
41
|
+
freshness: options.freshness,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=define-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-projection.js","sourceRoot":"","sources":["../src/define-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAsCH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,OAAkC;IAElC,oDAAoD;IACpD,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,qBAAqB,IAAI,cAAc,KAAK,CAAC,IAAI,+CAA+C,CACjG,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO;QACL,KAAK,EAAE,YAAY;QACnB,IAAI;QACJ,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,EAAE,EAAE,OAAO,CAAC,EAAE;QACd,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineProvider` — a bootable dependency.
|
|
3
|
+
*
|
|
4
|
+
* const database = defineProvider('database', {
|
|
5
|
+
* boot: async () => {
|
|
6
|
+
* const pool = createPool(config.database.url)
|
|
7
|
+
* await pool.connect()
|
|
8
|
+
* return pool
|
|
9
|
+
* },
|
|
10
|
+
* shutdown: async (pool) => { await pool.end() },
|
|
11
|
+
* healthCheck: async (pool) => { await pool.query('SELECT 1') }
|
|
12
|
+
* })
|
|
13
|
+
*
|
|
14
|
+
* createApp({
|
|
15
|
+
* modules: [...],
|
|
16
|
+
* providers: [database, redis, email]
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* Providers boot in declaration order during `app.start()`; shutdown runs in
|
|
20
|
+
* reverse during `app.stop()`. The booted value is registered on the runtime
|
|
21
|
+
* container under `provider.name`, so handlers resolve it via
|
|
22
|
+
* `ctx.resolve<Pool>('database')`.
|
|
23
|
+
*
|
|
24
|
+
* This is the right shape for things that have lifecycle (a connection that
|
|
25
|
+
* opens + closes; a pool you must drain; a worker process you must signal).
|
|
26
|
+
* For plain values, register them on the container directly — no provider
|
|
27
|
+
* needed.
|
|
28
|
+
*
|
|
29
|
+
* Providers vs plugins:
|
|
30
|
+
* - A provider produces a typed VALUE and manages its lifecycle.
|
|
31
|
+
* - A plugin hooks into the FRAMEWORK (middleware, lifecycle hooks, routes).
|
|
32
|
+
* Most things you import as "an integration" (Redis client, Stripe SDK,
|
|
33
|
+
* S3 client) are providers. Things like observability, auth, audit-log
|
|
34
|
+
* are plugins.
|
|
35
|
+
*/
|
|
36
|
+
export interface ProviderDefinition<T = unknown> {
|
|
37
|
+
readonly $kind: "provider";
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly boot: () => Promise<T> | T;
|
|
40
|
+
readonly shutdown?: (value: T) => Promise<void> | void;
|
|
41
|
+
readonly healthCheck?: (value: T) => Promise<void> | void;
|
|
42
|
+
}
|
|
43
|
+
export interface ProviderOptions<T> {
|
|
44
|
+
readonly boot: () => Promise<T> | T;
|
|
45
|
+
readonly shutdown?: (value: T) => Promise<void> | void;
|
|
46
|
+
readonly healthCheck?: (value: T) => Promise<void> | void;
|
|
47
|
+
}
|
|
48
|
+
export declare function defineProvider<T>(name: string, options: ProviderOptions<T>): ProviderDefinition<T>;
|
|
49
|
+
//# sourceMappingURL=define-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-provider.d.ts","sourceRoot":"","sources":["../src/define-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,OAAO;IAC7C,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC3D;AAED,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACvD,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC3D;AAED,wBAAgB,cAAc,CAAC,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,GAC1B,kBAAkB,CAAC,CAAC,CAAC,CAQvB"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineProvider` — a bootable dependency.
|
|
3
|
+
*
|
|
4
|
+
* const database = defineProvider('database', {
|
|
5
|
+
* boot: async () => {
|
|
6
|
+
* const pool = createPool(config.database.url)
|
|
7
|
+
* await pool.connect()
|
|
8
|
+
* return pool
|
|
9
|
+
* },
|
|
10
|
+
* shutdown: async (pool) => { await pool.end() },
|
|
11
|
+
* healthCheck: async (pool) => { await pool.query('SELECT 1') }
|
|
12
|
+
* })
|
|
13
|
+
*
|
|
14
|
+
* createApp({
|
|
15
|
+
* modules: [...],
|
|
16
|
+
* providers: [database, redis, email]
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* Providers boot in declaration order during `app.start()`; shutdown runs in
|
|
20
|
+
* reverse during `app.stop()`. The booted value is registered on the runtime
|
|
21
|
+
* container under `provider.name`, so handlers resolve it via
|
|
22
|
+
* `ctx.resolve<Pool>('database')`.
|
|
23
|
+
*
|
|
24
|
+
* This is the right shape for things that have lifecycle (a connection that
|
|
25
|
+
* opens + closes; a pool you must drain; a worker process you must signal).
|
|
26
|
+
* For plain values, register them on the container directly — no provider
|
|
27
|
+
* needed.
|
|
28
|
+
*
|
|
29
|
+
* Providers vs plugins:
|
|
30
|
+
* - A provider produces a typed VALUE and manages its lifecycle.
|
|
31
|
+
* - A plugin hooks into the FRAMEWORK (middleware, lifecycle hooks, routes).
|
|
32
|
+
* Most things you import as "an integration" (Redis client, Stripe SDK,
|
|
33
|
+
* S3 client) are providers. Things like observability, auth, audit-log
|
|
34
|
+
* are plugins.
|
|
35
|
+
*/
|
|
36
|
+
export function defineProvider(name, options) {
|
|
37
|
+
return {
|
|
38
|
+
$kind: "provider",
|
|
39
|
+
name,
|
|
40
|
+
boot: options.boot,
|
|
41
|
+
shutdown: options.shutdown,
|
|
42
|
+
healthCheck: options.healthCheck,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=define-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-provider.js","sourceRoot":"","sources":["../src/define-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAgBH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,OAA2B;IAE3B,OAAO;QACL,KAAK,EAAE,UAAU;QACjB,IAAI;QACJ,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineQuery` — read function over a projection.
|
|
3
|
+
*
|
|
4
|
+
* export const submissionsByStudent = defineQuery(SubmissionsByStudent, {
|
|
5
|
+
* name: 'submissions.by-student',
|
|
6
|
+
* schema: z.object({ studentId: StudentId, status: SubmissionStatus.optional() }),
|
|
7
|
+
* execute: (state, { studentId, status }) =>
|
|
8
|
+
* Object.values(state).filter(s => s.studentId === studentId &&
|
|
9
|
+
* (!status || s.status === status))
|
|
10
|
+
* })
|
|
11
|
+
*
|
|
12
|
+
* Queries read from projections, never from actors. They have no envelope, no
|
|
13
|
+
* bus, no commit semantics — direct calls. The runtime hands them the
|
|
14
|
+
* projection's current state and the validated input.
|
|
15
|
+
*
|
|
16
|
+
* Naming follows actions: `<domain>.<verb-noun>` so a query is addressable on
|
|
17
|
+
* the same routing keyspace as actions when transports need it (HTTP GET
|
|
18
|
+
* routes wire queries; HTTP POST routes wire actions).
|
|
19
|
+
*/
|
|
20
|
+
import type { z } from "zod";
|
|
21
|
+
import type { ZodTypeAny } from "@nwire/messages";
|
|
22
|
+
import type { ProjectionDefinition } from "./define-projection.js";
|
|
23
|
+
import { type PublicMarker } from "./public-marker.js";
|
|
24
|
+
/** Studio-aware: declared read-path SLO. */
|
|
25
|
+
export interface QuerySlo {
|
|
26
|
+
/** Declared p95 latency target in milliseconds. */
|
|
27
|
+
readonly p95LatencyMs?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface QueryOptions<TState, TSchema extends ZodTypeAny, TResult> {
|
|
30
|
+
readonly name: string;
|
|
31
|
+
readonly description?: string;
|
|
32
|
+
readonly schema: TSchema;
|
|
33
|
+
readonly execute: (state: TState, input: z.output<TSchema>) => TResult | Promise<TResult>;
|
|
34
|
+
/** Studio-aware: declared latency target. */
|
|
35
|
+
readonly slo?: QuerySlo;
|
|
36
|
+
/** Studio-aware: hint that this query is safe to cache. */
|
|
37
|
+
readonly cacheable?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface QueryDefinition<TState = unknown, TSchema extends ZodTypeAny = ZodTypeAny, TResult = unknown> extends PublicMarker {
|
|
40
|
+
readonly $kind: "query";
|
|
41
|
+
readonly name: string;
|
|
42
|
+
readonly description?: string;
|
|
43
|
+
readonly schema: TSchema;
|
|
44
|
+
readonly projection: ProjectionDefinition<TState>;
|
|
45
|
+
readonly execute: (state: TState, input: z.output<TSchema>) => TResult | Promise<TResult>;
|
|
46
|
+
readonly slo?: QuerySlo;
|
|
47
|
+
readonly cacheable?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export declare function defineQuery<TState, TSchema extends ZodTypeAny, TResult>(projection: ProjectionDefinition<TState>, options: QueryOptions<TState, TSchema, TResult>): QueryDefinition<TState, TSchema, TResult>;
|
|
50
|
+
//# sourceMappingURL=define-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-query.d.ts","sourceRoot":"","sources":["../src/define-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE9D,4CAA4C;AAC5C,MAAM,WAAW,QAAQ;IACvB,mDAAmD;IACnD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,YAAY,CAAC,MAAM,EAAE,OAAO,SAAS,UAAU,EAAE,OAAO;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1F,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe,CAC9B,MAAM,GAAG,OAAO,EAChB,OAAO,SAAS,UAAU,GAAG,UAAU,EACvC,OAAO,GAAG,OAAO,CACjB,SAAQ,YAAY;IACpB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1F,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,SAAS,UAAU,EAAE,OAAO,EACrE,UAAU,EAAE,oBAAoB,CAAC,MAAM,CAAC,EACxC,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,GAC9C,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAW3C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineQuery` — read function over a projection.
|
|
3
|
+
*
|
|
4
|
+
* export const submissionsByStudent = defineQuery(SubmissionsByStudent, {
|
|
5
|
+
* name: 'submissions.by-student',
|
|
6
|
+
* schema: z.object({ studentId: StudentId, status: SubmissionStatus.optional() }),
|
|
7
|
+
* execute: (state, { studentId, status }) =>
|
|
8
|
+
* Object.values(state).filter(s => s.studentId === studentId &&
|
|
9
|
+
* (!status || s.status === status))
|
|
10
|
+
* })
|
|
11
|
+
*
|
|
12
|
+
* Queries read from projections, never from actors. They have no envelope, no
|
|
13
|
+
* bus, no commit semantics — direct calls. The runtime hands them the
|
|
14
|
+
* projection's current state and the validated input.
|
|
15
|
+
*
|
|
16
|
+
* Naming follows actions: `<domain>.<verb-noun>` so a query is addressable on
|
|
17
|
+
* the same routing keyspace as actions when transports need it (HTTP GET
|
|
18
|
+
* routes wire queries; HTTP POST routes wire actions).
|
|
19
|
+
*/
|
|
20
|
+
import { markable } from "./public-marker.js";
|
|
21
|
+
export function defineQuery(projection, options) {
|
|
22
|
+
return markable({
|
|
23
|
+
$kind: "query",
|
|
24
|
+
name: options.name,
|
|
25
|
+
description: options.description,
|
|
26
|
+
schema: options.schema,
|
|
27
|
+
projection,
|
|
28
|
+
execute: options.execute,
|
|
29
|
+
slo: options.slo,
|
|
30
|
+
cacheable: options.cacheable,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=define-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-query.js","sourceRoot":"","sources":["../src/define-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EAAE,QAAQ,EAAqB,MAAM,iBAAiB,CAAC;AAkC9D,MAAM,UAAU,WAAW,CACzB,UAAwC,EACxC,OAA+C;IAE/C,OAAO,QAAQ,CAAC;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,UAAU;QACV,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineResolver` — the operation: a named, versioned, statused, typed
|
|
3
|
+
* capability the system exposes through one or more transports.
|
|
4
|
+
*
|
|
5
|
+
* const RecordWash = defineResolver({
|
|
6
|
+
* operation: "RecordWash",
|
|
7
|
+
* version: 1,
|
|
8
|
+
* status: "active",
|
|
9
|
+
* summary: "Record a wash at a station",
|
|
10
|
+
* description:"...",
|
|
11
|
+
* tags: ["Stations", "Washes"],
|
|
12
|
+
* params: z.object({ stationId: z.string().uuid() }),
|
|
13
|
+
* body: z.object({ subscriptionId: ..., plateNumber: ..., washType: ... }),
|
|
14
|
+
* returns: [washCreated, washAccepted],
|
|
15
|
+
* errors: [WashInProgress, QuotaExceeded, StationOffline],
|
|
16
|
+
* })
|
|
17
|
+
* .use(stationPipeline)
|
|
18
|
+
* .use(async ({ input, user, station, execute, send, useProjection }) => {
|
|
19
|
+
* // ...
|
|
20
|
+
* const wash = await execute(recordWash, { ... });
|
|
21
|
+
* return washCreated(wash);
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* Status lifecycle:
|
|
25
|
+
* draft — not mountable (build error if a transport tries)
|
|
26
|
+
* active — live, serves traffic
|
|
27
|
+
* deprecated — live + warns; must declare `successor`
|
|
28
|
+
* sunset — dead, returns 410/error/exit 1; must declare `sunsetDate`
|
|
29
|
+
*
|
|
30
|
+
* Transport-agnostic. Mounted onto REST/GraphQL/CLI via the transport
|
|
31
|
+
* namespace (rest.mount, graphql.mount, cli.mount).
|
|
32
|
+
*/
|
|
33
|
+
import type { z } from "zod";
|
|
34
|
+
import type { ZodTypeAny } from "@nwire/messages";
|
|
35
|
+
import type { NwireError } from "./define-error.js";
|
|
36
|
+
import { type MiddlewareDefinition, type HookDefinition, type PipeStep, type ResolverCtx } from "./define-middleware.js";
|
|
37
|
+
import type { ResponseSpecBase, ResponseInstance } from "./response.js";
|
|
38
|
+
export type ResolverStatus = "draft" | "active" | "deprecated" | "sunset";
|
|
39
|
+
export type AnyResolverDefinition = ResolverDefinition<any, any, any, any>;
|
|
40
|
+
export interface DefineResolverOptions<TParams extends ZodTypeAny | undefined, TQuery extends ZodTypeAny | undefined, TBody extends ZodTypeAny | undefined> {
|
|
41
|
+
readonly operation: string;
|
|
42
|
+
readonly version: number;
|
|
43
|
+
readonly status: ResolverStatus;
|
|
44
|
+
readonly summary?: string;
|
|
45
|
+
readonly description?: string;
|
|
46
|
+
readonly tags?: ReadonlyArray<string>;
|
|
47
|
+
readonly params?: TParams;
|
|
48
|
+
readonly query?: TQuery;
|
|
49
|
+
readonly body?: TBody;
|
|
50
|
+
readonly returns: ReadonlyArray<ResponseSpecBase>;
|
|
51
|
+
readonly errors?: ReadonlyArray<NwireError>;
|
|
52
|
+
/** Required when `status === "deprecated"` or `"sunset"`. */
|
|
53
|
+
readonly successor?: AnyResolverDefinition;
|
|
54
|
+
/** Required when `status === "sunset"`. ISO date the operation stopped serving. */
|
|
55
|
+
readonly sunsetDate?: string;
|
|
56
|
+
}
|
|
57
|
+
export interface ResolverHandlerContext<TInput = unknown> extends ResolverCtx {
|
|
58
|
+
readonly input: TInput;
|
|
59
|
+
}
|
|
60
|
+
export type ResolverHandler<TInput = any> = (ctx: ResolverHandlerContext<TInput>) => Promise<ResponseInstance | undefined> | ResponseInstance | undefined;
|
|
61
|
+
type ZodOutput<T> = T extends ZodTypeAny ? z.output<T> : never;
|
|
62
|
+
/**
|
|
63
|
+
* Flat-merge the params/query/body schemas. The handler sees one input
|
|
64
|
+
* object — `input.stationId`, not `input.params.stationId`. Collisions
|
|
65
|
+
* follow precedence: body > query > params (body is "the request", path/
|
|
66
|
+
* query are "the location"). Spec-level rationale: handlers shouldn't
|
|
67
|
+
* care where a value came from; they care what the operation needs.
|
|
68
|
+
*/
|
|
69
|
+
type MergeInput<TParams, TQuery, TBody> = (TParams extends ZodTypeAny ? ZodOutput<TParams> : unknown) & (TQuery extends ZodTypeAny ? ZodOutput<TQuery> : unknown) & (TBody extends ZodTypeAny ? ZodOutput<TBody> : unknown);
|
|
70
|
+
export interface ResolverDefinition<TParams extends ZodTypeAny | undefined = undefined, TQuery extends ZodTypeAny | undefined = undefined, TBody extends ZodTypeAny | undefined = undefined, TInput = MergeInput<TParams, TQuery, TBody>> {
|
|
71
|
+
readonly $kind: "resolver";
|
|
72
|
+
readonly operation: string;
|
|
73
|
+
readonly version: number;
|
|
74
|
+
readonly status: ResolverStatus;
|
|
75
|
+
readonly summary?: string;
|
|
76
|
+
readonly description?: string;
|
|
77
|
+
readonly tags?: ReadonlyArray<string>;
|
|
78
|
+
readonly params?: TParams;
|
|
79
|
+
readonly query?: TQuery;
|
|
80
|
+
readonly body?: TBody;
|
|
81
|
+
readonly returns: ReadonlyArray<ResponseSpecBase>;
|
|
82
|
+
readonly errors: ReadonlyArray<NwireError>;
|
|
83
|
+
readonly successor?: AnyResolverDefinition;
|
|
84
|
+
readonly sunsetDate?: string;
|
|
85
|
+
/** Composed middleware + hooks (built via successive `.use(...)` calls). */
|
|
86
|
+
readonly steps: ReadonlyArray<MiddlewareDefinition | HookDefinition>;
|
|
87
|
+
/** The terminal handler — last `.use(fn)` where fn has arity 1. */
|
|
88
|
+
readonly handler?: ResolverHandler<TInput>;
|
|
89
|
+
/**
|
|
90
|
+
* Append a middleware / pipe / hook to the chain. If the value is a
|
|
91
|
+
* function with arity 1, it's treated as the terminal handler — no further
|
|
92
|
+
* `.use()` after that.
|
|
93
|
+
*/
|
|
94
|
+
use(step: PipeStep): ResolverDefinition<TParams, TQuery, TBody, TInput>;
|
|
95
|
+
use(handler: ResolverHandler<TInput>): ResolverDefinition<TParams, TQuery, TBody, TInput>;
|
|
96
|
+
/**
|
|
97
|
+
* Call the resolver directly — for tests + harness. Runs middleware +
|
|
98
|
+
* handler in-process with the given input + ctx augmentations.
|
|
99
|
+
*/
|
|
100
|
+
call(opts: {
|
|
101
|
+
readonly input?: TInput;
|
|
102
|
+
readonly user?: any;
|
|
103
|
+
readonly container?: any;
|
|
104
|
+
readonly ctx?: Record<string, any>;
|
|
105
|
+
}): Promise<ResponseInstance | undefined>;
|
|
106
|
+
}
|
|
107
|
+
export declare function defineResolver<TParams extends ZodTypeAny | undefined = undefined, TQuery extends ZodTypeAny | undefined = undefined, TBody extends ZodTypeAny | undefined = undefined>(options: DefineResolverOptions<TParams, TQuery, TBody>): ResolverDefinition<TParams, TQuery, TBody>;
|
|
108
|
+
/** Type narrow. */
|
|
109
|
+
export declare const isResolver: (x: unknown) => x is AnyResolverDefinition;
|
|
110
|
+
export {};
|
|
111
|
+
//# sourceMappingURL=define-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-resolver.d.ts","sourceRoot":"","sources":["../src/define-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `defineResolver` — the operation: a named, versioned, statused, typed
|
|
3
|
+
* capability the system exposes through one or more transports.
|
|
4
|
+
*
|
|
5
|
+
* const RecordWash = defineResolver({
|
|
6
|
+
* operation: "RecordWash",
|
|
7
|
+
* version: 1,
|
|
8
|
+
* status: "active",
|
|
9
|
+
* summary: "Record a wash at a station",
|
|
10
|
+
* description:"...",
|
|
11
|
+
* tags: ["Stations", "Washes"],
|
|
12
|
+
* params: z.object({ stationId: z.string().uuid() }),
|
|
13
|
+
* body: z.object({ subscriptionId: ..., plateNumber: ..., washType: ... }),
|
|
14
|
+
* returns: [washCreated, washAccepted],
|
|
15
|
+
* errors: [WashInProgress, QuotaExceeded, StationOffline],
|
|
16
|
+
* })
|
|
17
|
+
* .use(stationPipeline)
|
|
18
|
+
* .use(async ({ input, user, station, execute, send, useProjection }) => {
|
|
19
|
+
* // ...
|
|
20
|
+
* const wash = await execute(recordWash, { ... });
|
|
21
|
+
* return washCreated(wash);
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* Status lifecycle:
|
|
25
|
+
* draft — not mountable (build error if a transport tries)
|
|
26
|
+
* active — live, serves traffic
|
|
27
|
+
* deprecated — live + warns; must declare `successor`
|
|
28
|
+
* sunset — dead, returns 410/error/exit 1; must declare `sunsetDate`
|
|
29
|
+
*
|
|
30
|
+
* Transport-agnostic. Mounted onto REST/GraphQL/CLI via the transport
|
|
31
|
+
* namespace (rest.mount, graphql.mount, cli.mount).
|
|
32
|
+
*/
|
|
33
|
+
import { unwindPipe, } from "./define-middleware.js";
|
|
34
|
+
function validateLifecycle(opts) {
|
|
35
|
+
const tag = `Resolver ${opts.operation} v${opts.version}`;
|
|
36
|
+
if (opts.status === "deprecated" && !opts.successor) {
|
|
37
|
+
throw new Error(`${tag}: status="deprecated" requires \`successor\` to point at the replacement resolver.`);
|
|
38
|
+
}
|
|
39
|
+
if (opts.status === "sunset") {
|
|
40
|
+
if (!opts.successor) {
|
|
41
|
+
throw new Error(`${tag}: status="sunset" requires \`successor\` to point at the replacement resolver.`);
|
|
42
|
+
}
|
|
43
|
+
if (!opts.sunsetDate) {
|
|
44
|
+
throw new Error(`${tag}: status="sunset" requires \`sunsetDate\` (ISO date when the operation stopped serving).`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function defineResolver(options) {
|
|
49
|
+
validateLifecycle(options);
|
|
50
|
+
const buildResolver = (steps, handler) => {
|
|
51
|
+
const def = {
|
|
52
|
+
$kind: "resolver",
|
|
53
|
+
operation: options.operation,
|
|
54
|
+
version: options.version,
|
|
55
|
+
status: options.status,
|
|
56
|
+
summary: options.summary,
|
|
57
|
+
description: options.description,
|
|
58
|
+
tags: options.tags,
|
|
59
|
+
params: options.params,
|
|
60
|
+
query: options.query,
|
|
61
|
+
body: options.body,
|
|
62
|
+
returns: options.returns,
|
|
63
|
+
errors: options.errors ?? [],
|
|
64
|
+
successor: options.successor,
|
|
65
|
+
sunsetDate: options.sunsetDate,
|
|
66
|
+
steps,
|
|
67
|
+
handler,
|
|
68
|
+
use(step) {
|
|
69
|
+
// Distinguish handler (single-arg fn) from middleware (two-arg fn).
|
|
70
|
+
if (typeof step === "function") {
|
|
71
|
+
// It's a handler — arity 1 (the destructured ctx).
|
|
72
|
+
return buildResolver(steps, step);
|
|
73
|
+
}
|
|
74
|
+
// Otherwise it's a middleware / hook / pipe.
|
|
75
|
+
const unwound = unwindPipe([step]);
|
|
76
|
+
const nextSteps = [
|
|
77
|
+
...steps,
|
|
78
|
+
...unwound.beforeHooks,
|
|
79
|
+
...unwound.middlewares,
|
|
80
|
+
...unwound.afterHooks,
|
|
81
|
+
];
|
|
82
|
+
return buildResolver(nextSteps, handler);
|
|
83
|
+
},
|
|
84
|
+
async call({ input, user, container, ctx: ctxExtra }) {
|
|
85
|
+
// Status gate.
|
|
86
|
+
if (options.status === "sunset") {
|
|
87
|
+
const { Gone } = await import("./define-error.js");
|
|
88
|
+
throw Gone.with({
|
|
89
|
+
operation: options.operation,
|
|
90
|
+
version: options.version,
|
|
91
|
+
successor: options.successor && { operation: options.successor.operation, version: options.successor.version },
|
|
92
|
+
sunsetDate: options.sunsetDate,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (options.status === "draft") {
|
|
96
|
+
throw new Error(`Resolver ${options.operation} v${options.version} is in status="draft" and cannot be called.`);
|
|
97
|
+
}
|
|
98
|
+
// Build the ctx. Adapters supply richer ctx; .call provides the
|
|
99
|
+
// minimum needed for unit tests + harness.
|
|
100
|
+
const ctx = {
|
|
101
|
+
input,
|
|
102
|
+
user,
|
|
103
|
+
container,
|
|
104
|
+
...(ctxExtra ?? {}),
|
|
105
|
+
};
|
|
106
|
+
if (!handler) {
|
|
107
|
+
throw new Error(`Resolver ${options.operation} v${options.version} has no handler. Call .use(async (ctx) => ...) before mounting.`);
|
|
108
|
+
}
|
|
109
|
+
// Compose middlewares (onion) around the handler.
|
|
110
|
+
let i = -1;
|
|
111
|
+
let result;
|
|
112
|
+
const dispatch = async (idx) => {
|
|
113
|
+
if (idx <= i)
|
|
114
|
+
throw new Error("next() called multiple times");
|
|
115
|
+
i = idx;
|
|
116
|
+
if (idx < steps.length) {
|
|
117
|
+
const step = steps[idx];
|
|
118
|
+
if (step.$kind === "middleware") {
|
|
119
|
+
await step.fn(ctx, () => dispatch(idx + 1));
|
|
120
|
+
}
|
|
121
|
+
else if (step.when === "before") {
|
|
122
|
+
await step.fn(ctx);
|
|
123
|
+
await dispatch(idx + 1);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
// after hooks run on the way back up — handled below.
|
|
127
|
+
await dispatch(idx + 1);
|
|
128
|
+
await step.fn(ctx, result);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
// Handler.
|
|
133
|
+
result = (await handler(ctx)) ?? undefined;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
await dispatch(0);
|
|
137
|
+
return result;
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
return def;
|
|
141
|
+
};
|
|
142
|
+
return buildResolver([], undefined);
|
|
143
|
+
}
|
|
144
|
+
/** Type narrow. */
|
|
145
|
+
export const isResolver = (x) => typeof x === "object" && x !== null && x.$kind === "resolver";
|
|
146
|
+
//# sourceMappingURL=define-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-resolver.js","sourceRoot":"","sources":["../src/define-resolver.ts"],"names":[],"mappings":"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"}
|