@cqrs-ddd/pipeline 0.5.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/COMMERCIAL_LICENSE.txt +34 -0
- package/LICENSE +661 -0
- package/README.md +42 -0
- package/dist/behaviors/logging.behavior.d.ts +195 -0
- package/dist/behaviors/logging.behavior.d.ts.map +1 -0
- package/dist/behaviors/logging.behavior.js +206 -0
- package/dist/behaviors/logging.behavior.js.map +1 -0
- package/dist/constants/pipeline-context.constants.d.ts +34 -0
- package/dist/constants/pipeline-context.constants.d.ts.map +1 -0
- package/dist/constants/pipeline-context.constants.js +34 -0
- package/dist/constants/pipeline-context.constants.js.map +1 -0
- package/dist/create-pipeline.d.ts +122 -0
- package/dist/create-pipeline.d.ts.map +1 -0
- package/dist/create-pipeline.js +193 -0
- package/dist/create-pipeline.js.map +1 -0
- package/dist/entries.d.ts +13 -0
- package/dist/entries.d.ts.map +1 -0
- package/dist/entries.js +3 -0
- package/dist/entries.js.map +1 -0
- package/dist/errors/missing-partition.error.d.ts +27 -0
- package/dist/errors/missing-partition.error.d.ts.map +1 -0
- package/dist/errors/missing-partition.error.js +33 -0
- package/dist/errors/missing-partition.error.js.map +1 -0
- package/dist/errors/missing-pipeline-item.error.d.ts +8 -0
- package/dist/errors/missing-pipeline-item.error.d.ts.map +1 -0
- package/dist/errors/missing-pipeline-item.error.js +16 -0
- package/dist/errors/missing-pipeline-item.error.js.map +1 -0
- package/dist/handler-pipeline.d.ts +62 -0
- package/dist/handler-pipeline.d.ts.map +1 -0
- package/dist/handler-pipeline.js +74 -0
- package/dist/handler-pipeline.js.map +1 -0
- package/dist/helpers/behavior-entries.d.ts +34 -0
- package/dist/helpers/behavior-entries.d.ts.map +1 -0
- package/dist/helpers/behavior-entries.js +50 -0
- package/dist/helpers/behavior-entries.js.map +1 -0
- package/dist/helpers/behavior-id.d.ts +43 -0
- package/dist/helpers/behavior-id.d.ts.map +1 -0
- package/dist/helpers/behavior-id.js +38 -0
- package/dist/helpers/behavior-id.js.map +1 -0
- package/dist/helpers/logging.intent.d.ts +17 -0
- package/dist/helpers/logging.intent.d.ts.map +1 -0
- package/dist/helpers/logging.intent.js +18 -0
- package/dist/helpers/logging.intent.js.map +1 -0
- package/dist/helpers/postgres-json.d.ts +25 -0
- package/dist/helpers/postgres-json.d.ts.map +1 -0
- package/dist/helpers/postgres-json.js +35 -0
- package/dist/helpers/postgres-json.js.map +1 -0
- package/dist/helpers/replace-request.d.ts +19 -0
- package/dist/helpers/replace-request.d.ts.map +1 -0
- package/dist/helpers/replace-request.js +29 -0
- package/dist/helpers/replace-request.js.map +1 -0
- package/dist/helpers/tenant-partition.d.ts +38 -0
- package/dist/helpers/tenant-partition.d.ts.map +1 -0
- package/dist/helpers/tenant-partition.js +27 -0
- package/dist/helpers/tenant-partition.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/context-source.interface.d.ts +42 -0
- package/dist/interfaces/context-source.interface.d.ts.map +1 -0
- package/dist/interfaces/context-source.interface.js +3 -0
- package/dist/interfaces/context-source.interface.js.map +1 -0
- package/dist/interfaces/pipeline-behavior-contract.interface.d.ts +99 -0
- package/dist/interfaces/pipeline-behavior-contract.interface.d.ts.map +1 -0
- package/dist/interfaces/pipeline-behavior-contract.interface.js +22 -0
- package/dist/interfaces/pipeline-behavior-contract.interface.js.map +1 -0
- package/dist/interfaces/pipeline-handler-meta.interface.d.ts +15 -0
- package/dist/interfaces/pipeline-handler-meta.interface.d.ts.map +1 -0
- package/dist/interfaces/pipeline-handler-meta.interface.js +3 -0
- package/dist/interfaces/pipeline-handler-meta.interface.js.map +1 -0
- package/dist/interfaces/pipeline.behavior.interface.d.ts +38 -0
- package/dist/interfaces/pipeline.behavior.interface.d.ts.map +1 -0
- package/dist/interfaces/pipeline.behavior.interface.js +3 -0
- package/dist/interfaces/pipeline.behavior.interface.js.map +1 -0
- package/dist/interfaces/pipeline.context.interface.d.ts +69 -0
- package/dist/interfaces/pipeline.context.interface.d.ts.map +1 -0
- package/dist/interfaces/pipeline.context.interface.js +3 -0
- package/dist/interfaces/pipeline.context.interface.js.map +1 -0
- package/dist/logger.d.ts +45 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +64 -0
- package/dist/logger.js.map +1 -0
- package/dist/options/global-behaviors.options.d.ts +57 -0
- package/dist/options/global-behaviors.options.d.ts.map +1 -0
- package/dist/options/global-behaviors.options.js +3 -0
- package/dist/options/global-behaviors.options.js.map +1 -0
- package/dist/pipeline-items.d.ts +22 -0
- package/dist/pipeline-items.d.ts.map +1 -0
- package/dist/pipeline-items.js +34 -0
- package/dist/pipeline-items.js.map +1 -0
- package/dist/pipeline.context.d.ts +86 -0
- package/dist/pipeline.context.d.ts.map +1 -0
- package/dist/pipeline.context.js +109 -0
- package/dist/pipeline.context.js.map +1 -0
- package/dist/services/pipeline-contracts.d.ts +29 -0
- package/dist/services/pipeline-contracts.d.ts.map +1 -0
- package/dist/services/pipeline-contracts.js +102 -0
- package/dist/services/pipeline-contracts.js.map +1 -0
- package/dist/services/pipeline-plan.d.ts +49 -0
- package/dist/services/pipeline-plan.d.ts.map +1 -0
- package/dist/services/pipeline-plan.js +111 -0
- package/dist/services/pipeline-plan.js.map +1 -0
- package/dist/services/pipeline-runner.d.ts +26 -0
- package/dist/services/pipeline-runner.d.ts.map +1 -0
- package/dist/services/pipeline-runner.js +68 -0
- package/dist/services/pipeline-runner.js.map +1 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Constructor } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Rich context available to every pipeline behavior during execution.
|
|
4
|
+
*
|
|
5
|
+
* Behaviors should type-hint against this **interface** to stay decoupled.
|
|
6
|
+
* The concrete implementation ({@link BasePipelineContext}) provides shared
|
|
7
|
+
* logic; extend it only when you need a custom context variant.
|
|
8
|
+
*/
|
|
9
|
+
export interface IPipelineContext<TRequest = unknown, TResponse = unknown> {
|
|
10
|
+
/**
|
|
11
|
+
* Immutable correlation ID for distributed tracing: the current correlation
|
|
12
|
+
* id when the pipeline starts (from `@cqrs-ddd/pipeline-correlation`, or the
|
|
13
|
+
* enclosing pipeline), otherwise a new one from the correlation source's
|
|
14
|
+
* `create()` (`uuidv7()` without one). Nested dispatches
|
|
15
|
+
* inherit it.
|
|
16
|
+
*/
|
|
17
|
+
readonly correlationId: string;
|
|
18
|
+
/**
|
|
19
|
+
* Tenant of this execution: the current tenant when the pipeline starts
|
|
20
|
+
* (from `@cqrs-ddd/pipeline-tenant`, or the enclosing pipeline), which nested
|
|
21
|
+
* dispatches inherit. Absent when there is none; tenant-scoped behaviors
|
|
22
|
+
* then fail closed.
|
|
23
|
+
*/
|
|
24
|
+
readonly tenantId?: string;
|
|
25
|
+
/** The command/query/event instance with all its property values. */
|
|
26
|
+
readonly request: TRequest;
|
|
27
|
+
/** The class (constructor) of the command/query/event. */
|
|
28
|
+
readonly requestType: Constructor<TRequest>;
|
|
29
|
+
/** The class name string, e.g. "CreateUserCommand". */
|
|
30
|
+
readonly requestName: string;
|
|
31
|
+
/** The handler class (constructor) that will process this request. */
|
|
32
|
+
readonly handlerType: Constructor;
|
|
33
|
+
/** The handler class name string, e.g. "CreateUserHandler". */
|
|
34
|
+
readonly handlerName: string;
|
|
35
|
+
/** 'command', 'query', or 'event': declared when wrapping, or read from the request's brand. */
|
|
36
|
+
readonly requestKind: 'command' | 'query' | 'event' | 'unknown';
|
|
37
|
+
/** UTC timestamp when the pipeline execution started. */
|
|
38
|
+
readonly startedAt: Date;
|
|
39
|
+
/**
|
|
40
|
+
* The handler's return value, set automatically after the real handler executes.
|
|
41
|
+
* Available to behaviors in their post-`next()` code path.
|
|
42
|
+
* `undefined` before the handler runs or for event handlers that return void.
|
|
43
|
+
*/
|
|
44
|
+
readonly response: TResponse | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Bag for sharing arbitrary data between behaviors in the same execution.
|
|
47
|
+
* Use createPipelineItem and the typed item accessors for compile-time value checks.
|
|
48
|
+
* Raw map access remains supported and bypasses those checks.
|
|
49
|
+
*
|
|
50
|
+
* Keys can be strings or exported `unique symbol` constants. Exported symbols
|
|
51
|
+
* are strongly recommended to prevent collision between behaviors or third-party packages.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* export const MY_ITEM = Symbol('MY_ITEM');
|
|
56
|
+
* context.items.set(MY_ITEM, customData);
|
|
57
|
+
* const val = context.items.get(MY_ITEM);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
readonly items: Map<string | symbol, unknown>;
|
|
61
|
+
/**
|
|
62
|
+
* Returns the options for a behavior on this handler: the options from a
|
|
63
|
+
* global `[Behavior, opts]` tuple, shallowly overridden by the options of the
|
|
64
|
+
* call site's `[Behavior, opts]` entry. Returns undefined when
|
|
65
|
+
* neither supplies options for that behavior.
|
|
66
|
+
*/
|
|
67
|
+
getBehaviorOptions<T = Record<string, unknown>>(behaviorType: Constructor): T | undefined;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=pipeline.context.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.context.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/pipeline.context.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB,CAAC,QAAQ,GAAG,OAAO,EAAE,SAAS,GAAG,OAAO;IACvE;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAE3B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAE3B,0DAA0D;IAC1D,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAE5C,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAElC,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,gGAAgG;IAChG,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IAEhE,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IAEzB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAC;IAEzC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,CAAC;IAE9C;;;;;OAKG;IACH,kBAAkB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5C,YAAY,EAAE,WAAW,GACxB,CAAC,GAAG,SAAS,CAAC;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.context.interface.js","sourceRoot":"","sources":["../../src/interfaces/pipeline.context.interface.ts"],"names":[],"mappings":"AAAA,sEAAsE"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** The levels behaviors log at, named as NestJS names them. */
|
|
2
|
+
export type LogLevel = 'log' | 'error' | 'warn' | 'debug' | 'verbose' | 'fatal';
|
|
3
|
+
/**
|
|
4
|
+
* The logger a behavior writes through. `console` satisfies it, and so does a NestJS
|
|
5
|
+
* `LoggerService`; a pino logger does through {@link pinoLogger}. A missing optional
|
|
6
|
+
* method makes that level silent.
|
|
7
|
+
*/
|
|
8
|
+
export interface PipelineLogger {
|
|
9
|
+
log(message: unknown, ...optionalParams: unknown[]): unknown;
|
|
10
|
+
error(message: unknown, ...optionalParams: unknown[]): unknown;
|
|
11
|
+
warn(message: unknown, ...optionalParams: unknown[]): unknown;
|
|
12
|
+
debug?(message: unknown, ...optionalParams: unknown[]): unknown;
|
|
13
|
+
verbose?(message: unknown, ...optionalParams: unknown[]): unknown;
|
|
14
|
+
fatal?(message: unknown, ...optionalParams: unknown[]): unknown;
|
|
15
|
+
}
|
|
16
|
+
/** The methods of a pino logger that {@link pinoLogger} calls. */
|
|
17
|
+
export interface PinoLike {
|
|
18
|
+
trace(fields: object, message?: string): unknown;
|
|
19
|
+
debug(fields: object, message?: string): unknown;
|
|
20
|
+
info(fields: object, message?: string): unknown;
|
|
21
|
+
warn(fields: object, message?: string): unknown;
|
|
22
|
+
error(fields: object, message?: string): unknown;
|
|
23
|
+
fatal(fields: object, message?: string): unknown;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Adapts a pino logger to {@link PipelineLogger}, so behaviors write structured records:
|
|
27
|
+
* `log` writes at pino's `info` and `verbose` at `trace`; the last string argument of a
|
|
28
|
+
* call with more than one is the `context` field, as NestJS passes it; on `error`, a string
|
|
29
|
+
* before it is the `stack` field; an `Error` message becomes `err`; an object message, such
|
|
30
|
+
* as `LoggingBehavior`'s `logFormat: 'structured'` records, becomes the record's fields;
|
|
31
|
+
* other arguments go to `params`.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* import pino from 'pino';
|
|
36
|
+
*
|
|
37
|
+
* const logger = pinoLogger(pino());
|
|
38
|
+
* const pipeline = createPipeline({
|
|
39
|
+
* logger,
|
|
40
|
+
* globalBehaviors: { before: [logging({ logFormat: 'structured' })] },
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function pinoLogger(pino: PinoLike): Required<PipelineLogger>;
|
|
45
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAEA,+DAA+D;AAC/D,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AAEhF;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC/D,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAC9D,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAChE,OAAO,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IAClE,KAAK,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;CACjE;AAED,kEAAkE;AAClE,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAClD;AAWD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,CAiCnE"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
const PINO_LEVEL = {
|
|
3
|
+
log: 'info',
|
|
4
|
+
error: 'error',
|
|
5
|
+
warn: 'warn',
|
|
6
|
+
debug: 'debug',
|
|
7
|
+
verbose: 'trace',
|
|
8
|
+
fatal: 'fatal',
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Adapts a pino logger to {@link PipelineLogger}, so behaviors write structured records:
|
|
12
|
+
* `log` writes at pino's `info` and `verbose` at `trace`; the last string argument of a
|
|
13
|
+
* call with more than one is the `context` field, as NestJS passes it; on `error`, a string
|
|
14
|
+
* before it is the `stack` field; an `Error` message becomes `err`; an object message, such
|
|
15
|
+
* as `LoggingBehavior`'s `logFormat: 'structured'` records, becomes the record's fields;
|
|
16
|
+
* other arguments go to `params`.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import pino from 'pino';
|
|
21
|
+
*
|
|
22
|
+
* const logger = pinoLogger(pino());
|
|
23
|
+
* const pipeline = createPipeline({
|
|
24
|
+
* logger,
|
|
25
|
+
* globalBehaviors: { before: [logging({ logFormat: 'structured' })] },
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function pinoLogger(pino) {
|
|
30
|
+
const write = (level) => (message, ...params) => {
|
|
31
|
+
const last = params.at(-1);
|
|
32
|
+
const context = params.length > 0 && typeof last === 'string' ? last : undefined;
|
|
33
|
+
const rest = context === undefined ? params : params.slice(0, -1);
|
|
34
|
+
const stack = level === 'error' && typeof rest[0] === 'string'
|
|
35
|
+
? rest.shift()
|
|
36
|
+
: undefined;
|
|
37
|
+
const fields = {};
|
|
38
|
+
if (context !== undefined)
|
|
39
|
+
fields.context = context;
|
|
40
|
+
if (stack !== undefined)
|
|
41
|
+
fields.stack = stack;
|
|
42
|
+
if (rest.length > 0)
|
|
43
|
+
fields.params = rest;
|
|
44
|
+
const target = PINO_LEVEL[level];
|
|
45
|
+
if (message instanceof Error) {
|
|
46
|
+
pino[target]({ ...fields, err: message }, message.message);
|
|
47
|
+
}
|
|
48
|
+
else if (typeof message === 'object' && message !== null) {
|
|
49
|
+
pino[target]({ ...fields, ...message });
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
pino[target](fields, String(message));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
log: write('log'),
|
|
57
|
+
error: write('error'),
|
|
58
|
+
warn: write('warn'),
|
|
59
|
+
debug: write('debug'),
|
|
60
|
+
verbose: write('verbose'),
|
|
61
|
+
fatal: write('fatal'),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,sEAAsE;AA6BtE,MAAM,UAAU,GAAG;IACjB,GAAG,EAAE,MAAM;IACX,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,OAAO;IAChB,KAAK,EAAE,OAAO;CACN,CAAC;AAEX;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,UAAU,CAAC,IAAc;IACvC,MAAM,KAAK,GACT,CAAC,KAAe,EAAE,EAAE,CACpB,CAAC,OAAgB,EAAE,GAAG,MAAiB,EAAQ,EAAE;QAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,OAAO,GACX,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,MAAM,IAAI,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,KAAK,GACT,KAAK,KAAK,OAAO,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;YAC9C,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE;YACd,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QACpD,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QAC9C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QAC1C,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7D,CAAC;aAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YAC3D,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QACxC,CAAC;IACH,CAAC,CAAC;IACJ,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC;QACjB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;QACrB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;QACrB,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;QACzB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;KACtB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { PipelineBehaviorEntry } from '../entries.js';
|
|
2
|
+
/** Determines which handler kinds global behaviors apply to. */
|
|
3
|
+
export type GlobalBehaviorScope = 'commands' | 'queries' | 'events' | 'all';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for behaviors that are automatically applied to all
|
|
6
|
+
* Commands, Queries, and/or Events, regardless of the entries declared at a call site.
|
|
7
|
+
*
|
|
8
|
+
* Execution order:
|
|
9
|
+
* `[before] → [call-site behaviors] → [after] → handler`. If the same
|
|
10
|
+
* behavior class is declared globally and at a call site, it runs once at its
|
|
11
|
+
* global position with the call-site options merged over the global ones.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* // Single object
|
|
16
|
+
* createPipeline({
|
|
17
|
+
* globalBehaviors: {
|
|
18
|
+
* scope: 'all',
|
|
19
|
+
* before: [LoggingBehavior, [MetricsBehavior, { meterName: 'api' }]],
|
|
20
|
+
* after: [AuditBehavior],
|
|
21
|
+
* },
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // Array — different scopes for different request kinds
|
|
25
|
+
* createPipeline({
|
|
26
|
+
* globalBehaviors: [
|
|
27
|
+
* { scope: 'commands', before: [AuditBehavior] },
|
|
28
|
+
* { scope: 'queries', before: [CacheBehavior] },
|
|
29
|
+
* { scope: 'all', after: [LoggingBehavior] },
|
|
30
|
+
* ],
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export interface GlobalBehaviorsOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Which handler kinds these behaviors apply to.
|
|
37
|
+
* - `'commands'` — only command handlers
|
|
38
|
+
* - `'queries'` — only query handlers
|
|
39
|
+
* - `'events'` — only event handlers
|
|
40
|
+
* - `'all'` — commands, queries, and events
|
|
41
|
+
*
|
|
42
|
+
* @default 'all'
|
|
43
|
+
*/
|
|
44
|
+
scope?: GlobalBehaviorScope;
|
|
45
|
+
/**
|
|
46
|
+
* Behaviors prepended BEFORE the behaviors declared at the call site.
|
|
47
|
+
* These run first (outermost) in the pipeline chain.
|
|
48
|
+
*/
|
|
49
|
+
before?: PipelineBehaviorEntry[];
|
|
50
|
+
/**
|
|
51
|
+
* Behaviors appended AFTER the behaviors declared at the call site
|
|
52
|
+
* (still before the actual handler execution).
|
|
53
|
+
* These run closest to the handler, after all other behaviors.
|
|
54
|
+
*/
|
|
55
|
+
after?: PipelineBehaviorEntry[];
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=global-behaviors.options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-behaviors.options.d.ts","sourceRoot":"","sources":["../../src/options/global-behaviors.options.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,gEAAgE;AAChE,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAE5B;;;OAGG;IACH,MAAM,CAAC,EAAE,qBAAqB,EAAE,CAAC;IAEjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,qBAAqB,EAAE,CAAC;CACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-behaviors.options.js","sourceRoot":"","sources":["../../src/options/global-behaviors.options.ts"],"names":[],"mappings":"AAAA,sEAAsE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IPipelineContext } from './interfaces/pipeline.context.interface.js';
|
|
2
|
+
/** Associates a context map key with its compile-time value type. */
|
|
3
|
+
export interface PipelineItemToken<T> {
|
|
4
|
+
readonly key: string | symbol;
|
|
5
|
+
readonly name: string;
|
|
6
|
+
readonly __itemType?: T;
|
|
7
|
+
}
|
|
8
|
+
/** Creates a unique symbol-backed token, or wraps an existing interoperability key. */
|
|
9
|
+
export declare function createPipelineItem<T>(name: string, key?: string | symbol): PipelineItemToken<T>;
|
|
10
|
+
/** Reads an item without runtime type validation. Raw keys require a caller-supplied type. */
|
|
11
|
+
export declare function getPipelineItem<T>(context: IPipelineContext, token: PipelineItemToken<T> | string | symbol): T | undefined;
|
|
12
|
+
/** Writes an item using the token's value type; raw keys remain unchecked. */
|
|
13
|
+
export declare function setPipelineItem<T>(context: IPipelineContext, token: PipelineItemToken<T> | string | symbol, value: NoInfer<T>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Reads a required item, throwing MissingPipelineItemError for absent or undefined values.
|
|
16
|
+
* Null and other falsy values are returned unchanged. No runtime type validation occurs.
|
|
17
|
+
* The optional custom message supplements the item, request and handler diagnostic.
|
|
18
|
+
*/
|
|
19
|
+
export declare function requirePipelineItem<T>(context: IPipelineContext, token: PipelineItemToken<T> | string | symbol, customMessage?: string): T;
|
|
20
|
+
/** Checks key presence, including entries explicitly set to undefined. */
|
|
21
|
+
export declare function hasPipelineItem<T>(context: IPipelineContext, token: PipelineItemToken<T> | string | symbol): boolean;
|
|
22
|
+
//# sourceMappingURL=pipeline-items.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-items.d.ts","sourceRoot":"","sources":["../src/pipeline-items.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAC;AAEnF,qEAAqE;AACrE,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;CACzB;AAED,uFAAuF;AACvF,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAM,GAAG,MAAqB,GAClC,iBAAiB,CAAC,CAAC,CAAC,CAEtB;AAQD,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,GAC5C,CAAC,GAAG,SAAS,CAEf;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,EAC7C,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAChB,IAAI,CAEN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,EAC7C,aAAa,CAAC,EAAE,MAAM,GACrB,CAAC,CAWH;AAED,0EAA0E;AAC1E,wBAAgB,eAAe,CAAC,CAAC,EAC/B,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,MAAM,GAC5C,OAAO,CAET"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
import { MissingPipelineItemError } from './errors/missing-pipeline-item.error.js';
|
|
3
|
+
/** Creates a unique symbol-backed token, or wraps an existing interoperability key. */
|
|
4
|
+
export function createPipelineItem(name, key = Symbol(name)) {
|
|
5
|
+
return { key, name };
|
|
6
|
+
}
|
|
7
|
+
function itemKey(token) {
|
|
8
|
+
return typeof token === 'object' ? token.key : token;
|
|
9
|
+
}
|
|
10
|
+
/** Reads an item without runtime type validation. Raw keys require a caller-supplied type. */
|
|
11
|
+
export function getPipelineItem(context, token) {
|
|
12
|
+
return context.items.get(itemKey(token));
|
|
13
|
+
}
|
|
14
|
+
/** Writes an item using the token's value type; raw keys remain unchecked. */
|
|
15
|
+
export function setPipelineItem(context, token, value) {
|
|
16
|
+
context.items.set(itemKey(token), value);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Reads a required item, throwing MissingPipelineItemError for absent or undefined values.
|
|
20
|
+
* Null and other falsy values are returned unchanged. No runtime type validation occurs.
|
|
21
|
+
* The optional custom message supplements the item, request and handler diagnostic.
|
|
22
|
+
*/
|
|
23
|
+
export function requirePipelineItem(context, token, customMessage) {
|
|
24
|
+
const value = getPipelineItem(context, token);
|
|
25
|
+
if (value === undefined) {
|
|
26
|
+
throw new MissingPipelineItemError(typeof token === 'object' ? token.name : String(token), context.requestName, context.handlerName, customMessage);
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
/** Checks key presence, including entries explicitly set to undefined. */
|
|
31
|
+
export function hasPipelineItem(context, token) {
|
|
32
|
+
return context.items.has(itemKey(token));
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=pipeline-items.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-items.js","sourceRoot":"","sources":["../src/pipeline-items.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AAUnF,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAChC,IAAY,EACZ,GAAG,GAAoB,MAAM,CAAC,IAAI,CAAC;IAEnC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACvB,CAAC;AAED,SAAS,OAAO,CACd,KAA6C;IAE7C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AACvD,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,eAAe,CAC7B,OAAyB,EACzB,KAA6C;IAE7C,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAkB,CAAC;AAC5D,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,eAAe,CAC7B,OAAyB,EACzB,KAA6C,EAC7C,KAAiB;IAEjB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAyB,EACzB,KAA6C,EAC7C,aAAsB;IAEtB,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,wBAAwB,CAChC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACtD,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,WAAW,EACnB,aAAa,CACd,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAC7B,OAAyB,EACzB,KAA6C;IAE7C,OAAO,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { SET_CORRELATION_ID, SET_REQUEST, SET_RESPONSE, SET_TENANT_ID } from './constants/pipeline-context.constants.js';
|
|
2
|
+
import { type BehaviorId } from './helpers/behavior-id.js';
|
|
3
|
+
import { IPipelineContext } from './interfaces/pipeline.context.interface.js';
|
|
4
|
+
import { PipelineHandlerMeta } from './interfaces/pipeline-handler-meta.interface.js';
|
|
5
|
+
import type { Constructor } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Abstract base class with shared implementation for all pipeline contexts.
|
|
8
|
+
*
|
|
9
|
+
* Provides default implementations for:
|
|
10
|
+
* - `getBehaviorOptions()` — reads from the pre-computed options map
|
|
11
|
+
* - `response` — readonly holder for the handler's return value (set via Symbol)
|
|
12
|
+
* - Common fields (correlationId, startedAt, items)
|
|
13
|
+
*
|
|
14
|
+
* Extend this class to create custom context variants for specialized pipelines.
|
|
15
|
+
* Behaviors should still type-hint against {@link IPipelineContext} (the interface).
|
|
16
|
+
*/
|
|
17
|
+
export declare abstract class BasePipelineContext<TRequest = unknown, TResponse = unknown> implements IPipelineContext<TRequest, TResponse> {
|
|
18
|
+
private _correlationId;
|
|
19
|
+
get correlationId(): string;
|
|
20
|
+
/** @internal Assigns the ID before the behavior chain starts. */
|
|
21
|
+
[SET_CORRELATION_ID](value: string): void;
|
|
22
|
+
private _tenantId;
|
|
23
|
+
/**
|
|
24
|
+
* Active tenant identifier for multi-tenant pipeline executions.
|
|
25
|
+
*/
|
|
26
|
+
get tenantId(): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Assigns the tenant once per execution. A different value after one is set
|
|
29
|
+
* (by the runner, from the tenant source or the enclosing pipeline)
|
|
30
|
+
* throws, so a behavior cannot move an execution to another tenant after an
|
|
31
|
+
* earlier behavior has used it.
|
|
32
|
+
*/
|
|
33
|
+
[SET_TENANT_ID](value: string | undefined): void;
|
|
34
|
+
abstract readonly request: TRequest;
|
|
35
|
+
abstract readonly requestType: Constructor<TRequest>;
|
|
36
|
+
abstract readonly requestName: string;
|
|
37
|
+
abstract readonly handlerType: Constructor;
|
|
38
|
+
abstract readonly handlerName: string;
|
|
39
|
+
abstract readonly requestKind: 'command' | 'query' | 'event' | 'unknown';
|
|
40
|
+
readonly startedAt: Date;
|
|
41
|
+
/**
|
|
42
|
+
* Bag for sharing arbitrary data between behaviors in the same execution.
|
|
43
|
+
* Supports string and unique symbol keys.
|
|
44
|
+
*/
|
|
45
|
+
readonly items: Map<string | symbol, unknown>;
|
|
46
|
+
/** Backing field for `response` — only writable via `[SET_RESPONSE]()`. */
|
|
47
|
+
private _response;
|
|
48
|
+
/** The handler's return value. Read-only for behaviors. */
|
|
49
|
+
get response(): TResponse | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Symbol-keyed setter — only callable by code that imports `SET_RESPONSE`.
|
|
52
|
+
* This keeps `response` effectively readonly for behaviors.
|
|
53
|
+
*/
|
|
54
|
+
[SET_RESPONSE](value: TResponse | undefined): void;
|
|
55
|
+
/**
|
|
56
|
+
* Options per behavior for this handler: global `[Behavior, opts]` tuple
|
|
57
|
+
* options, shallowly overridden by the call site's options.
|
|
58
|
+
*/
|
|
59
|
+
protected abstract readonly behaviorOptionsMap: Map<BehaviorId, Record<string, unknown>> | undefined;
|
|
60
|
+
constructor();
|
|
61
|
+
/**
|
|
62
|
+
* Returns the options for a behavior on this handler: the options from a
|
|
63
|
+
* global `[Behavior, opts]` tuple, shallowly overridden by the options of the
|
|
64
|
+
* call site's `[Behavior, opts]` entry.
|
|
65
|
+
*/
|
|
66
|
+
getBehaviorOptions<T = Record<string, unknown>>(behaviorType: Constructor): T | undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Concrete pipeline context created per request.
|
|
70
|
+
* Pre-computed handler metadata is injected via {@link PipelineHandlerMeta}.
|
|
71
|
+
*/
|
|
72
|
+
export declare class PipelineContext<TRequest = unknown, TResponse = unknown> extends BasePipelineContext<TRequest, TResponse> {
|
|
73
|
+
readonly requestType: Constructor<TRequest>;
|
|
74
|
+
readonly requestName: string;
|
|
75
|
+
readonly handlerType: Constructor;
|
|
76
|
+
readonly handlerName: string;
|
|
77
|
+
readonly requestKind: 'command' | 'query' | 'event' | 'unknown';
|
|
78
|
+
protected readonly behaviorOptionsMap: Map<BehaviorId, Record<string, unknown>> | undefined;
|
|
79
|
+
private _request;
|
|
80
|
+
/** The input of this execution, or the replacement a behavior handed in. */
|
|
81
|
+
get request(): TRequest;
|
|
82
|
+
/** Replaces the input the handler receives; see `replaceRequest`. */
|
|
83
|
+
[SET_REQUEST](value: TRequest): void;
|
|
84
|
+
constructor(request: TRequest, meta: PipelineHandlerMeta);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=pipeline.context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.context.d.ts","sourceRoot":"","sources":["../src/pipeline.context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
import { untyped } from '@cqrs-ddd/untyped';
|
|
3
|
+
import { SET_CORRELATION_ID, SET_REQUEST, SET_RESPONSE, SET_TENANT_ID, } from './constants/pipeline-context.constants.js';
|
|
4
|
+
import { getBehaviorId } from './helpers/behavior-id.js';
|
|
5
|
+
/**
|
|
6
|
+
* Abstract base class with shared implementation for all pipeline contexts.
|
|
7
|
+
*
|
|
8
|
+
* Provides default implementations for:
|
|
9
|
+
* - `getBehaviorOptions()` — reads from the pre-computed options map
|
|
10
|
+
* - `response` — readonly holder for the handler's return value (set via Symbol)
|
|
11
|
+
* - Common fields (correlationId, startedAt, items)
|
|
12
|
+
*
|
|
13
|
+
* Extend this class to create custom context variants for specialized pipelines.
|
|
14
|
+
* Behaviors should still type-hint against {@link IPipelineContext} (the interface).
|
|
15
|
+
*/
|
|
16
|
+
export class BasePipelineContext {
|
|
17
|
+
_correlationId = '';
|
|
18
|
+
get correlationId() {
|
|
19
|
+
return this._correlationId;
|
|
20
|
+
}
|
|
21
|
+
/** @internal Assigns the ID before the behavior chain starts. */
|
|
22
|
+
[SET_CORRELATION_ID](value) {
|
|
23
|
+
this._correlationId = value;
|
|
24
|
+
}
|
|
25
|
+
_tenantId = undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Active tenant identifier for multi-tenant pipeline executions.
|
|
28
|
+
*/
|
|
29
|
+
get tenantId() {
|
|
30
|
+
return this._tenantId;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Assigns the tenant once per execution. A different value after one is set
|
|
34
|
+
* (by the runner, from the tenant source or the enclosing pipeline)
|
|
35
|
+
* throws, so a behavior cannot move an execution to another tenant after an
|
|
36
|
+
* earlier behavior has used it.
|
|
37
|
+
*/
|
|
38
|
+
[SET_TENANT_ID](value) {
|
|
39
|
+
if (this._tenantId !== undefined && this._tenantId !== value) {
|
|
40
|
+
throw new Error('PipelineContext tenantId is already assigned and cannot be changed');
|
|
41
|
+
}
|
|
42
|
+
this._tenantId = value;
|
|
43
|
+
}
|
|
44
|
+
startedAt;
|
|
45
|
+
/**
|
|
46
|
+
* Bag for sharing arbitrary data between behaviors in the same execution.
|
|
47
|
+
* Supports string and unique symbol keys.
|
|
48
|
+
*/
|
|
49
|
+
items;
|
|
50
|
+
/** Backing field for `response` — only writable via `[SET_RESPONSE]()`. */
|
|
51
|
+
_response = undefined;
|
|
52
|
+
/** The handler's return value. Read-only for behaviors. */
|
|
53
|
+
get response() {
|
|
54
|
+
return this._response;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Symbol-keyed setter — only callable by code that imports `SET_RESPONSE`.
|
|
58
|
+
* This keeps `response` effectively readonly for behaviors.
|
|
59
|
+
*/
|
|
60
|
+
[SET_RESPONSE](value) {
|
|
61
|
+
this._response = value;
|
|
62
|
+
}
|
|
63
|
+
constructor() {
|
|
64
|
+
this.startedAt = new Date();
|
|
65
|
+
this.items = new Map();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns the options for a behavior on this handler: the options from a
|
|
69
|
+
* global `[Behavior, opts]` tuple, shallowly overridden by the options of the
|
|
70
|
+
* call site's `[Behavior, opts]` entry.
|
|
71
|
+
*/
|
|
72
|
+
getBehaviorOptions(behaviorType) {
|
|
73
|
+
return this.behaviorOptionsMap?.get(getBehaviorId(behaviorType));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Concrete pipeline context created per request.
|
|
78
|
+
* Pre-computed handler metadata is injected via {@link PipelineHandlerMeta}.
|
|
79
|
+
*/
|
|
80
|
+
export class PipelineContext extends BasePipelineContext {
|
|
81
|
+
requestType;
|
|
82
|
+
requestName;
|
|
83
|
+
handlerType;
|
|
84
|
+
handlerName;
|
|
85
|
+
requestKind;
|
|
86
|
+
behaviorOptionsMap;
|
|
87
|
+
_request;
|
|
88
|
+
/** The input of this execution, or the replacement a behavior handed in. */
|
|
89
|
+
get request() {
|
|
90
|
+
return this._request;
|
|
91
|
+
}
|
|
92
|
+
/** Replaces the input the handler receives; see `replaceRequest`. */
|
|
93
|
+
[SET_REQUEST](value) {
|
|
94
|
+
this._request = value;
|
|
95
|
+
}
|
|
96
|
+
constructor(request, meta) {
|
|
97
|
+
super();
|
|
98
|
+
this._request = request;
|
|
99
|
+
this.requestType = (request === null || request === undefined
|
|
100
|
+
? Object
|
|
101
|
+
: untyped(request).constructor);
|
|
102
|
+
this.requestName = meta.requestName ?? this.requestType.name;
|
|
103
|
+
this.handlerType = meta.handlerType;
|
|
104
|
+
this.handlerName = meta.handlerName;
|
|
105
|
+
this.requestKind = meta.requestKind;
|
|
106
|
+
this.behaviorOptionsMap = meta.behaviorOptions;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=pipeline.context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.context.js","sourceRoot":"","sources":["../src/pipeline.context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type BehaviorId } from '../helpers/behavior-id.js';
|
|
2
|
+
import type { IPipelineBehavior } from '../interfaces/pipeline.behavior.interface.js';
|
|
3
|
+
import { type PipelineBehaviorDiagnostic } from '../interfaces/pipeline-behavior-contract.interface.js';
|
|
4
|
+
import type { Constructor } from '../types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Validates the ordering rules and option contracts that behavior classes declare
|
|
7
|
+
* through `PIPELINE_BEHAVIOR_CONTRACT`, appending a diagnostic per violation. Framework
|
|
8
|
+
* adapters call it at bootstrap; `createPipeline()` calls it when a function is wrapped.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const diagnostics: PipelineBehaviorDiagnostic[] = [];
|
|
13
|
+
* validateBehaviorContracts({ ...plan, handlerType, handlerName, requestKind, resolvedBehaviors, diagnostics });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateBehaviorContracts(params: {
|
|
17
|
+
handlerType: Constructor;
|
|
18
|
+
handlerName: string;
|
|
19
|
+
requestKind: 'command' | 'query' | 'event';
|
|
20
|
+
behaviorTypes: Constructor<IPipelineBehavior>[];
|
|
21
|
+
resolvedBehaviors: Map<number, IPipelineBehavior>;
|
|
22
|
+
mergedOptions: Map<BehaviorId, Record<string, unknown>>;
|
|
23
|
+
handlerOptions?: Map<BehaviorId, Record<string, unknown>>;
|
|
24
|
+
globalOptions: Map<BehaviorId, Record<string, unknown>>;
|
|
25
|
+
handlerBehaviorTypes?: Constructor<IPipelineBehavior>[];
|
|
26
|
+
globalBehaviorIds: Set<BehaviorId>;
|
|
27
|
+
diagnostics: PipelineBehaviorDiagnostic[];
|
|
28
|
+
}): void;
|
|
29
|
+
//# sourceMappingURL=pipeline-contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-contracts.d.ts","sourceRoot":"","sources":["../../src/services/pipeline-contracts.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,UAAU,EAAiB,MAAM,2BAA2B,CAAC;AAC3E,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,uDAAuD,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE;IAChD,WAAW,EAAE,WAAW,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAC3C,aAAa,EAAE,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC;IAChD,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAClD,aAAa,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,cAAc,CAAC,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D,aAAa,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACxD,oBAAoB,CAAC,EAAE,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC;IACxD,iBAAiB,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACnC,WAAW,EAAE,0BAA0B,EAAE,CAAC;CAC3C,GAAG,IAAI,CAyHP"}
|