@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,38 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
import { untyped } from '@cqrs-ddd/untyped';
|
|
3
|
+
/**
|
|
4
|
+
* Optional static property on a behavior class that provides a stable,
|
|
5
|
+
* unique identity for deduplication when global and handler behaviors overlap.
|
|
6
|
+
*
|
|
7
|
+
* Use this to recognize one behavior across multiple loaded copies of its package:
|
|
8
|
+
*
|
|
9
|
+
* ```ts
|
|
10
|
+
* export class LoggingBehavior implements IPipelineBehavior {
|
|
11
|
+
* static readonly [PIPELINE_BEHAVIOR_ID] = 'my-package:LoggingBehavior';
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* When absent, the constructor reference is used as the fallback identity.
|
|
16
|
+
*/
|
|
17
|
+
export const PIPELINE_BEHAVIOR_ID = Symbol.for('@cqrs-ddd/pipeline:behavior-id');
|
|
18
|
+
/**
|
|
19
|
+
* Returns the identity used to deduplicate a behavior and resolve its options.
|
|
20
|
+
*
|
|
21
|
+
* By default the constructor reference is the identity. A behavior that must be
|
|
22
|
+
* recognized across multiple loaded copies of the same package can opt into a
|
|
23
|
+
* stable string identity through {@link PIPELINE_BEHAVIOR_ID}.
|
|
24
|
+
*
|
|
25
|
+
* @param cls - Behavior class whose identity should be resolved.
|
|
26
|
+
* @returns The constructor reference or the behavior's explicit stable id.
|
|
27
|
+
*
|
|
28
|
+
* @example Stable identity across duplicated package copies
|
|
29
|
+
* ```ts
|
|
30
|
+
* export class LoggingBehavior implements IPipelineBehavior {
|
|
31
|
+
* static readonly [PIPELINE_BEHAVIOR_ID] = 'my-package:LoggingBehavior';
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function getBehaviorId(cls) {
|
|
36
|
+
return untyped(cls)[PIPELINE_BEHAVIOR_ID] ?? cls;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=behavior-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behavior-id.js","sourceRoot":"","sources":["../../src/helpers/behavior-id.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAI5C;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,GAAG,CAC5C,gCAAgC,CACjC,CAAC;AAUF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAAC,GAAmC;IAC/D,OAAQ,OAAO,CAAC,GAAG,CAAC,CAAC,oBAAoB,CAAwB,IAAI,GAAG,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LoggingBehavior, type LoggingBehaviorOptions } from '../behaviors/logging.behavior.js';
|
|
2
|
+
import type { PipelineBehaviorTuple } from '../entries.js';
|
|
3
|
+
export type LoggingIntentOptions = LoggingBehaviorOptions;
|
|
4
|
+
/**
|
|
5
|
+
* Returns a logging behavior entry for `pipeline.wrap()` or `createPipeline({ globalBehaviors })`.
|
|
6
|
+
* @param options Per-handler logging options; omitted fields use behavior defaults.
|
|
7
|
+
* @returns The behavior class and options tuple.
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* export const getPrice = pipeline.wrap(
|
|
11
|
+
* { name: 'getPrice', kind: 'query' },
|
|
12
|
+
* logging({ requestResponseLogLevel: 'log' }),
|
|
13
|
+
* )(async (sku: string) => prices.find(sku));
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function logging(options?: LoggingIntentOptions): PipelineBehaviorTuple<LoggingBehavior, LoggingBehaviorOptions>;
|
|
17
|
+
//# sourceMappingURL=logging.intent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.intent.d.ts","sourceRoot":"","sources":["../../src/helpers/logging.intent.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC5B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CACrB,OAAO,GAAE,oBAAyB,GACjC,qBAAqB,CAAC,eAAe,EAAE,sBAAsB,CAAC,CAEhE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
import { LoggingBehavior, } from '../behaviors/logging.behavior.js';
|
|
3
|
+
/**
|
|
4
|
+
* Returns a logging behavior entry for `pipeline.wrap()` or `createPipeline({ globalBehaviors })`.
|
|
5
|
+
* @param options Per-handler logging options; omitted fields use behavior defaults.
|
|
6
|
+
* @returns The behavior class and options tuple.
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* export const getPrice = pipeline.wrap(
|
|
10
|
+
* { name: 'getPrice', kind: 'query' },
|
|
11
|
+
* logging({ requestResponseLogLevel: 'log' }),
|
|
12
|
+
* )(async (sku: string) => prices.find(sku));
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export function logging(options = {}) {
|
|
16
|
+
return [LoggingBehavior, options];
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=logging.intent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logging.intent.js","sourceRoot":"","sources":["../../src/helpers/logging.intent.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EACL,eAAe,GAEhB,MAAM,kCAAkC,CAAC;AAK1C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO,CACrB,OAAO,GAAyB,EAAE;IAElC,OAAO,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Makes JSON text acceptable to a PostgreSQL `jsonb` (or `json`) parameter.
|
|
3
|
+
*
|
|
4
|
+
* PostgreSQL rejects two things that `JSON.stringify` legitimately produces: a
|
|
5
|
+
* NUL character (`\u0000`, "unsupported Unicode escape sequence") and a lone
|
|
6
|
+
* UTF-16 surrogate (`\ud800`, "invalid input syntax for type json"). Either one
|
|
7
|
+
* fails the whole `INSERT`, so a single stray character in a payload or error
|
|
8
|
+
* message would lose the entire row. This replaces each with U+FFFD, the
|
|
9
|
+
* Unicode replacement character, in keys and values alike, and leaves every
|
|
10
|
+
* other character and every valid surrogate pair unchanged.
|
|
11
|
+
*
|
|
12
|
+
* The replacement is lossy by design: `jsonb` has no representation for these
|
|
13
|
+
* characters. Use it where keeping the record matters more than those
|
|
14
|
+
* characters, such as audit and dead-letter rows.
|
|
15
|
+
*
|
|
16
|
+
* @param json - JSON text, such as the output of `JSON.stringify`.
|
|
17
|
+
* @returns The same JSON text with the unsupported escapes replaced.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* toPostgresJson(JSON.stringify({ note: 'a\u0000b' })); // '{"note":"a\\ufffdb"}'
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function toPostgresJson(json: string): string;
|
|
25
|
+
//# sourceMappingURL=postgres-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-json.d.ts","sourceRoot":"","sources":["../../src/helpers/postgres-json.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAInD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
/** The replacement character that stands in for what `jsonb` cannot hold. */
|
|
3
|
+
const REPLACEMENT = '\\ufffd';
|
|
4
|
+
/**
|
|
5
|
+
* An escaped backslash (kept, so the scan stays aligned on escapes), a
|
|
6
|
+
* surrogate pair (kept), a `\u0000` escape or a lone surrogate escape.
|
|
7
|
+
*/
|
|
8
|
+
const JSONB_ESCAPES = /\\(?:\\|u(?:d[89ab][0-9a-f]{2}\\ud[c-f][0-9a-f]{2}|0000|d[89a-f][0-9a-f]{2}))/gi;
|
|
9
|
+
/**
|
|
10
|
+
* Makes JSON text acceptable to a PostgreSQL `jsonb` (or `json`) parameter.
|
|
11
|
+
*
|
|
12
|
+
* PostgreSQL rejects two things that `JSON.stringify` legitimately produces: a
|
|
13
|
+
* NUL character (`\u0000`, "unsupported Unicode escape sequence") and a lone
|
|
14
|
+
* UTF-16 surrogate (`\ud800`, "invalid input syntax for type json"). Either one
|
|
15
|
+
* fails the whole `INSERT`, so a single stray character in a payload or error
|
|
16
|
+
* message would lose the entire row. This replaces each with U+FFFD, the
|
|
17
|
+
* Unicode replacement character, in keys and values alike, and leaves every
|
|
18
|
+
* other character and every valid surrogate pair unchanged.
|
|
19
|
+
*
|
|
20
|
+
* The replacement is lossy by design: `jsonb` has no representation for these
|
|
21
|
+
* characters. Use it where keeping the record matters more than those
|
|
22
|
+
* characters, such as audit and dead-letter rows.
|
|
23
|
+
*
|
|
24
|
+
* @param json - JSON text, such as the output of `JSON.stringify`.
|
|
25
|
+
* @returns The same JSON text with the unsupported escapes replaced.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* toPostgresJson(JSON.stringify({ note: 'a\u0000b' })); // '{"note":"a\\ufffdb"}'
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export function toPostgresJson(json) {
|
|
33
|
+
return json.replace(JSONB_ESCAPES, (sequence) => sequence === '\\\\' || sequence.length === 12 ? sequence : REPLACEMENT);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=postgres-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-json.js","sourceRoot":"","sources":["../../src/helpers/postgres-json.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,6EAA6E;AAC7E,MAAM,WAAW,GAAG,SAAS,CAAC;AAE9B;;;GAGG;AACH,MAAM,aAAa,GACjB,iFAAiF,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,QAAQ,EAAE,EAAE,CAC9C,QAAQ,KAAK,MAAM,IAAI,QAAQ,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CACvE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IPipelineContext } from '../interfaces/pipeline.context.interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* Hands the handler `value` in place of its input, for a behavior that produces a new
|
|
4
|
+
* value instead of changing the caller's object, such as a validated, parsed copy. For a
|
|
5
|
+
* wrapped function that takes several arguments, `value` is the new argument array.
|
|
6
|
+
* Later behaviors see the replacement as `context.request`.
|
|
7
|
+
*
|
|
8
|
+
* @throws TypeError when the context does not support replacement, or when a
|
|
9
|
+
* multi-argument call receives a value that is not an array.
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* async handle(context: IPipelineContext, next: NextDelegate) {
|
|
13
|
+
* replaceRequest(context, schema.parse(context.request));
|
|
14
|
+
* return next();
|
|
15
|
+
* }
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function replaceRequest(context: IPipelineContext, value: unknown): void;
|
|
19
|
+
//# sourceMappingURL=replace-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-request.d.ts","sourceRoot":"","sources":["../../src/helpers/replace-request.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAC;AAEpF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,OAAO,GACb,IAAI,CAeN"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
import { SET_REQUEST } from '../constants/pipeline-context.constants.js';
|
|
3
|
+
/**
|
|
4
|
+
* Hands the handler `value` in place of its input, for a behavior that produces a new
|
|
5
|
+
* value instead of changing the caller's object, such as a validated, parsed copy. For a
|
|
6
|
+
* wrapped function that takes several arguments, `value` is the new argument array.
|
|
7
|
+
* Later behaviors see the replacement as `context.request`.
|
|
8
|
+
*
|
|
9
|
+
* @throws TypeError when the context does not support replacement, or when a
|
|
10
|
+
* multi-argument call receives a value that is not an array.
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* async handle(context: IPipelineContext, next: NextDelegate) {
|
|
14
|
+
* replaceRequest(context, schema.parse(context.request));
|
|
15
|
+
* return next();
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function replaceRequest(context, value) {
|
|
20
|
+
const setter = context[SET_REQUEST];
|
|
21
|
+
if (typeof setter !== 'function') {
|
|
22
|
+
throw new TypeError(`replaceRequest: the context of ${context.requestName} cannot replace its request.`);
|
|
23
|
+
}
|
|
24
|
+
if (Array.isArray(context.request) && !Array.isArray(value)) {
|
|
25
|
+
throw new TypeError(`replaceRequest: ${context.requestName} takes several arguments; pass the new argument array.`);
|
|
26
|
+
}
|
|
27
|
+
setter.call(context, value);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=replace-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"replace-request.js","sourceRoot":"","sources":["../../src/helpers/replace-request.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAGzE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAyB,EACzB,KAAc;IAEd,MAAM,MAAM,GACV,OACD,CAAC,WAAW,CAAC,CAAC;IACf,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,IAAI,SAAS,CACjB,kCAAkC,OAAO,CAAC,WAAW,8BAA8B,CACpF,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,SAAS,CACjB,mBAAmB,OAAO,CAAC,WAAW,wDAAwD,CAC/F,CAAC;IACJ,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IPipelineContext } from '../interfaces/pipeline.context.interface.js';
|
|
2
|
+
/** How a partitioned key treats the tenant, shared by every key factory. */
|
|
3
|
+
export interface TenantPartitionOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the key has a tenant segment, so equal identifiers in two tenants
|
|
6
|
+
* never share a key.
|
|
7
|
+
*
|
|
8
|
+
* @default true
|
|
9
|
+
*/
|
|
10
|
+
includeTenant?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Whether a missing tenant is an error rather than an absent segment.
|
|
13
|
+
* `includeTenant` answers "is the tenant part of the key"; this answers "may
|
|
14
|
+
* it be absent".
|
|
15
|
+
*
|
|
16
|
+
* @default the value of `includeTenant`
|
|
17
|
+
*/
|
|
18
|
+
requireTenant?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The tenant segment of a partitioned key: `[context.tenantId]`, or `[]` when
|
|
22
|
+
* `includeTenant` is `false`.
|
|
23
|
+
*
|
|
24
|
+
* @param missing - The package's partition error, raised with the dimension
|
|
25
|
+
* `'tenant'` when the tenant is required and absent.
|
|
26
|
+
* @throws What `missing` builds, when a required tenant is absent.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* joinKeySegments([
|
|
31
|
+
* ...tenantSegments(context, options, MissingRateLimitPartitionError),
|
|
32
|
+
* caller,
|
|
33
|
+
* context.requestName,
|
|
34
|
+
* ]);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function tenantSegments(context: IPipelineContext, options: TenantPartitionOptions, missing: new (requestName: string, dimension: 'tenant', remedy: string) => Error): (string | undefined)[];
|
|
38
|
+
//# sourceMappingURL=tenant-partition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-partition.d.ts","sourceRoot":"","sources":["../../src/helpers/tenant-partition.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6CAA6C,CAAC;AAEpF,4EAA4E;AAC5E,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,KACP,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,QAAQ,EACnB,MAAM,EAAE,MAAM,KACX,KAAK,GACT,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAWxB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
/**
|
|
3
|
+
* The tenant segment of a partitioned key: `[context.tenantId]`, or `[]` when
|
|
4
|
+
* `includeTenant` is `false`.
|
|
5
|
+
*
|
|
6
|
+
* @param missing - The package's partition error, raised with the dimension
|
|
7
|
+
* `'tenant'` when the tenant is required and absent.
|
|
8
|
+
* @throws What `missing` builds, when a required tenant is absent.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* joinKeySegments([
|
|
13
|
+
* ...tenantSegments(context, options, MissingRateLimitPartitionError),
|
|
14
|
+
* caller,
|
|
15
|
+
* context.requestName,
|
|
16
|
+
* ]);
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function tenantSegments(context, options, missing) {
|
|
20
|
+
const includeTenant = options.includeTenant ?? true;
|
|
21
|
+
if ((options.requireTenant ?? includeTenant) && !context.tenantId) {
|
|
22
|
+
throw new missing(context.requestName, 'tenant', 'Run the request inside a tenant scope (runWithTenant of @cqrs-ddd/pipeline-tenant), ' +
|
|
23
|
+
'or pass requireTenant: false for a single-tenant deployment.');
|
|
24
|
+
}
|
|
25
|
+
return includeTenant ? [context.tenantId] : [];
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=tenant-partition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-partition.js","sourceRoot":"","sources":["../../src/helpers/tenant-partition.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAwBtE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAyB,EACzB,OAA+B,EAC/B,OAIU;IAEV,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,IAAI,CAAC;IACpD,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QAClE,MAAM,IAAI,OAAO,CACf,OAAO,CAAC,WAAW,EACnB,QAAQ,EACR,sFAAsF;YACpF,8DAA8D,CACjE,CAAC;IACJ,CAAC;IACD,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACjD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export * from './behaviors/logging.behavior.js';
|
|
2
|
+
export { pipelineStore, SET_REQUEST, SET_TENANT_ID, } from './constants/pipeline-context.constants.js';
|
|
3
|
+
export { createPipeline, type DeclaredKind, type Pipeline, type PipelineOptions, REQUEST_KIND, type Wrap, type WrapOptions, } from './create-pipeline.js';
|
|
4
|
+
export type { PipelineBehaviorEntry, PipelineBehaviorTuple, } from './entries.js';
|
|
5
|
+
export { MissingPartitionError } from './errors/missing-partition.error.js';
|
|
6
|
+
export * from './errors/missing-pipeline-item.error.js';
|
|
7
|
+
export { type AnyClass, type DualClassDecorator, type HandlerPipeline, pipelineOf, SkipPipeline, UsePipeline, } from './handler-pipeline.js';
|
|
8
|
+
export { type BehaviorEntryAccumulators, behaviorEntryType, normalizeBehaviorEntries, } from './helpers/behavior-entries.js';
|
|
9
|
+
export { type BehaviorId, getBehaviorId, PIPELINE_BEHAVIOR_ID, } from './helpers/behavior-id.js';
|
|
10
|
+
export { type LoggingIntentOptions, logging, } from './helpers/logging.intent.js';
|
|
11
|
+
export { toPostgresJson } from './helpers/postgres-json.js';
|
|
12
|
+
export { replaceRequest } from './helpers/replace-request.js';
|
|
13
|
+
export { type TenantPartitionOptions, tenantSegments, } from './helpers/tenant-partition.js';
|
|
14
|
+
export type { ContextSource, ContextSources, CorrelationSource, } from './interfaces/context-source.interface.js';
|
|
15
|
+
export * from './interfaces/pipeline.behavior.interface.js';
|
|
16
|
+
export * from './interfaces/pipeline.context.interface.js';
|
|
17
|
+
export * from './interfaces/pipeline-behavior-contract.interface.js';
|
|
18
|
+
export * from './interfaces/pipeline-handler-meta.interface.js';
|
|
19
|
+
export { type LogLevel, type PinoLike, type PipelineLogger, pinoLogger, } from './logger.js';
|
|
20
|
+
export type { GlobalBehaviorScope, GlobalBehaviorsOptions, } from './options/global-behaviors.options.js';
|
|
21
|
+
export * from './pipeline.context.js';
|
|
22
|
+
export * from './pipeline-items.js';
|
|
23
|
+
export { validateBehaviorContracts } from './services/pipeline-contracts.js';
|
|
24
|
+
export { compilePipelinePlan, type PipelineDeclaration, type RequestKind, toGlobalConfigs, } from './services/pipeline-plan.js';
|
|
25
|
+
export { createPipelineRunner, type PipelineRunner, } from './services/pipeline-runner.js';
|
|
26
|
+
export type { Constructor } from './types.js';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,iCAAiC,CAAC;AAChD,OAAO,EACL,aAAa,EACb,WAAW,EACX,aAAa,GACd,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,QAAQ,EACb,KAAK,eAAe,EACpB,YAAY,EACZ,KAAK,IAAI,EACT,KAAK,WAAW,GACjB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,cAAc,yCAAyC,CAAC;AACxD,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,UAAU,EACV,YAAY,EACZ,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,yBAAyB,EAC9B,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,UAAU,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,KAAK,oBAAoB,EACzB,OAAO,GACR,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EACL,KAAK,sBAAsB,EAC3B,cAAc,GACf,MAAM,+BAA+B,CAAC;AACvC,YAAY,EACV,aAAa,EACb,cAAc,EACd,iBAAiB,GAClB,MAAM,0CAA0C,CAAC;AAClD,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,sDAAsD,CAAC;AACrE,cAAc,iDAAiD,CAAC;AAChE,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,UAAU,GACX,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,uCAAuC,CAAC;AAC/C,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EACL,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,EACpB,KAAK,cAAc,GACpB,MAAM,+BAA+B,CAAC;AACvC,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
export * from './behaviors/logging.behavior.js';
|
|
3
|
+
export { pipelineStore, SET_REQUEST, SET_TENANT_ID, } from './constants/pipeline-context.constants.js';
|
|
4
|
+
export { createPipeline, REQUEST_KIND, } from './create-pipeline.js';
|
|
5
|
+
export { MissingPartitionError } from './errors/missing-partition.error.js';
|
|
6
|
+
export * from './errors/missing-pipeline-item.error.js';
|
|
7
|
+
export { pipelineOf, SkipPipeline, UsePipeline, } from './handler-pipeline.js';
|
|
8
|
+
export { behaviorEntryType, normalizeBehaviorEntries, } from './helpers/behavior-entries.js';
|
|
9
|
+
export { getBehaviorId, PIPELINE_BEHAVIOR_ID, } from './helpers/behavior-id.js';
|
|
10
|
+
export { logging, } from './helpers/logging.intent.js';
|
|
11
|
+
export { toPostgresJson } from './helpers/postgres-json.js';
|
|
12
|
+
export { replaceRequest } from './helpers/replace-request.js';
|
|
13
|
+
export { tenantSegments, } from './helpers/tenant-partition.js';
|
|
14
|
+
export * from './interfaces/pipeline.behavior.interface.js';
|
|
15
|
+
export * from './interfaces/pipeline.context.interface.js';
|
|
16
|
+
export * from './interfaces/pipeline-behavior-contract.interface.js';
|
|
17
|
+
export * from './interfaces/pipeline-handler-meta.interface.js';
|
|
18
|
+
export { pinoLogger, } from './logger.js';
|
|
19
|
+
export * from './pipeline.context.js';
|
|
20
|
+
export * from './pipeline-items.js';
|
|
21
|
+
export { validateBehaviorContracts } from './services/pipeline-contracts.js';
|
|
22
|
+
export { compilePipelinePlan, toGlobalConfigs, } from './services/pipeline-plan.js';
|
|
23
|
+
export { createPipelineRunner, } from './services/pipeline-runner.js';
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,cAAc,iCAAiC,CAAC;AAChD,OAAO,EACL,aAAa,EACb,WAAW,EACX,aAAa,GACd,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,cAAc,EAId,YAAY,GAGb,MAAM,sBAAsB,CAAC;AAK9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,cAAc,yCAAyC,CAAC;AACxD,OAAO,EAIL,UAAU,EACV,YAAY,EACZ,WAAW,GACZ,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,aAAa,EACb,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAEL,OAAO,GACR,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAEL,cAAc,GACf,MAAM,+BAA+B,CAAC;AAMvC,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,sDAAsD,CAAC;AACrE,cAAc,iDAAiD,CAAC;AAChE,OAAO,EAIL,UAAU,GACX,MAAM,aAAa,CAAC;AAKrB,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAC7E,OAAO,EACL,mBAAmB,EAGnB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,oBAAoB,GAErB,MAAM,+BAA+B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A value kept for the current execution by the package that owns it, such as
|
|
3
|
+
* the tenant of `@cqrs-ddd/pipeline-tenant`. A pipeline reads it when it starts
|
|
4
|
+
* and runs its behaviors inside it, so nested dispatches inherit it.
|
|
5
|
+
*/
|
|
6
|
+
export interface ContextSource {
|
|
7
|
+
/** The value of the current execution, or `undefined` for none. */
|
|
8
|
+
current(): string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Runs `fn` with `value` as the current value (`undefined`: none) for
|
|
11
|
+
* everything it calls, synchronously or asynchronously.
|
|
12
|
+
*/
|
|
13
|
+
run<T>(value: string | undefined, fn: () => T): T;
|
|
14
|
+
}
|
|
15
|
+
/** A correlation id source, which also makes new ids. */
|
|
16
|
+
export interface CorrelationSource extends ContextSource {
|
|
17
|
+
/** A new correlation id, for a pipeline started without one. */
|
|
18
|
+
create(): string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Where pipelines take their tenant and correlation id from
|
|
22
|
+
* (`createPipeline({ sources })`).
|
|
23
|
+
*
|
|
24
|
+
* Without a source, a pipeline takes the value of the pipeline it is nested
|
|
25
|
+
* in, if any. A missing correlation id comes from the correlation source's
|
|
26
|
+
* `create()`, or, with no correlation source, from `uuidv7()`.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { correlationSource } from '@cqrs-ddd/pipeline-correlation';
|
|
31
|
+
* import { tenantSource } from '@cqrs-ddd/pipeline-tenant';
|
|
32
|
+
*
|
|
33
|
+
* const pipeline = createPipeline({
|
|
34
|
+
* sources: { tenantId: tenantSource, correlationId: correlationSource },
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export interface ContextSources {
|
|
39
|
+
readonly tenantId?: ContextSource;
|
|
40
|
+
readonly correlationId?: CorrelationSource;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=context-source.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-source.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/context-source.interface.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,OAAO,IAAI,MAAM,GAAG,SAAS,CAAC;IAC9B;;;OAGG;IACH,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CACnD;AAED,yDAAyD;AACzD,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,gEAAgE;IAChE,MAAM,IAAI,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;CAC5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-source.interface.js","sourceRoot":"","sources":["../../src/interfaces/context-source.interface.ts"],"names":[],"mappings":"AAAA,sEAAsE"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { Constructor } from '../types.js';
|
|
2
|
+
import type { IPipelineBehavior } from './pipeline.behavior.interface.js';
|
|
3
|
+
/**
|
|
4
|
+
* Well-known symbol for declaring an optional {@link IPipelineBehaviorContract}
|
|
5
|
+
* on a pipeline behavior class.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PIPELINE_BEHAVIOR_CONTRACT: unique symbol;
|
|
8
|
+
/**
|
|
9
|
+
* Inspection context provided to behavior contract validators before the first
|
|
10
|
+
* execution: when a function is wrapped, or when an adapter starts.
|
|
11
|
+
*/
|
|
12
|
+
export interface PipelineBehaviorValidationContext {
|
|
13
|
+
/** The CQRS handler class. */
|
|
14
|
+
handlerType: Constructor;
|
|
15
|
+
/** The name of the CQRS handler. */
|
|
16
|
+
handlerName: string;
|
|
17
|
+
/** The request kind of the handler ('command' | 'query' | 'event'). */
|
|
18
|
+
requestKind: 'command' | 'query' | 'event';
|
|
19
|
+
/**
|
|
20
|
+
* Source where this behavior was declared for the current handler:
|
|
21
|
+
* - `'handler'`: declared at the call site, such as `pipeline.wrap(options, ...entries)`.
|
|
22
|
+
* - `'global'`: declared globally, such as `createPipeline({ globalBehaviors })`.
|
|
23
|
+
* - `'both'`: declared globally and also customized at the call site.
|
|
24
|
+
*/
|
|
25
|
+
declarationSource: 'handler' | 'global' | 'both';
|
|
26
|
+
/** Effective options for resolved singletons; raw handler/global options for scoped behaviors. */
|
|
27
|
+
effectiveOptions: Record<string, unknown> | undefined;
|
|
28
|
+
/** Raw options declared on the handler, if any. */
|
|
29
|
+
handlerOptions: Record<string, unknown> | undefined;
|
|
30
|
+
/** Raw options declared globally, if any. */
|
|
31
|
+
globalOptions: Record<string, unknown> | undefined;
|
|
32
|
+
/** Complete ordered list of effective behavior classes active for this handler. */
|
|
33
|
+
effectiveBehaviorTypes: ReadonlyArray<Constructor<IPipelineBehavior>>;
|
|
34
|
+
/** The behavior instance, when one exists before the first execution. */
|
|
35
|
+
behaviorInstance?: IPipelineBehavior;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A diagnostic issue identified when a pipeline behavior contract is validated.
|
|
39
|
+
*/
|
|
40
|
+
export interface PipelineBehaviorDiagnostic {
|
|
41
|
+
/** The name of the handler where the issue occurred. */
|
|
42
|
+
handlerName: string;
|
|
43
|
+
/** The name of the behavior that emitted the diagnostic. */
|
|
44
|
+
behaviorName: string;
|
|
45
|
+
/** Actionable explanation of the invalid or missing configuration. */
|
|
46
|
+
message: string;
|
|
47
|
+
/** Concrete remediation recommendation to resolve the issue. */
|
|
48
|
+
fix: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Static ordering constraints relative to other pipeline behaviors.
|
|
52
|
+
*
|
|
53
|
+
* These are **relative-position** constraints, not dependency declarations. A
|
|
54
|
+
* target that is absent from the handler's effective chain produces no
|
|
55
|
+
* diagnostic, because there is no position to violate. `after: [CaslBehavior]`
|
|
56
|
+
* therefore means "must not run before `CaslBehavior` when it is present", not
|
|
57
|
+
* "`CaslBehavior` must be present".
|
|
58
|
+
*
|
|
59
|
+
* To require a peer, check {@link PipelineBehaviorValidationContext.effectiveBehaviorTypes}
|
|
60
|
+
* in {@link IPipelineBehaviorContract.validate} and return a diagnostic when it
|
|
61
|
+
* is missing. Ordering alone cannot express that.
|
|
62
|
+
*/
|
|
63
|
+
export interface PipelineBehaviorOrderRule {
|
|
64
|
+
/** This behavior must execute before the specified behaviors, when present. */
|
|
65
|
+
before?: Array<Constructor<IPipelineBehavior> | string>;
|
|
66
|
+
/** This behavior must execute after the specified behaviors, when present. */
|
|
67
|
+
after?: Array<Constructor<IPipelineBehavior> | string>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Ordering specification: either a static rule or a dynamic rule evaluated per handler context.
|
|
71
|
+
*/
|
|
72
|
+
export type PipelineBehaviorOrder = PipelineBehaviorOrderRule | ((context: PipelineBehaviorValidationContext) => PipelineBehaviorOrderRule | undefined);
|
|
73
|
+
/**
|
|
74
|
+
* Declarative contract exposed by a behavior class to define ordering constraints
|
|
75
|
+
* and validation rules checked before the first execution.
|
|
76
|
+
*/
|
|
77
|
+
export interface IPipelineBehaviorContract {
|
|
78
|
+
/**
|
|
79
|
+
* Relative ordering constraints against other behaviors in the pipeline.
|
|
80
|
+
* Targets can be behavior classes or behavior ID / class names (strings).
|
|
81
|
+
* Can be a static rule or a function evaluated with the handler context
|
|
82
|
+
* to restrict constraints to applicable request kinds or configurations.
|
|
83
|
+
*/
|
|
84
|
+
order?: PipelineBehaviorOrder;
|
|
85
|
+
/**
|
|
86
|
+
* Validates effective options and declaration sources before the first execution.
|
|
87
|
+
* Returns an array of diagnostics if deterministic misconfigurations are found.
|
|
88
|
+
*/
|
|
89
|
+
validate?: (context: PipelineBehaviorValidationContext) => PipelineBehaviorDiagnostic[] | undefined;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Thrown when a function is wrapped, or when an adapter starts, if deterministic
|
|
93
|
+
* pipeline policy misconfigurations or ordering violations are detected.
|
|
94
|
+
*/
|
|
95
|
+
export declare class PipelineConfigurationError extends Error {
|
|
96
|
+
readonly diagnostics: readonly PipelineBehaviorDiagnostic[];
|
|
97
|
+
constructor(diagnostics: readonly PipelineBehaviorDiagnostic[]);
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=pipeline-behavior-contract.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-behavior-contract.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/pipeline-behavior-contract.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,0BAA0B,eAEtC,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,iCAAiC;IAChD,8BAA8B;IAC9B,WAAW,EAAE,WAAW,CAAC;IACzB,oCAAoC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAC3C;;;;;OAKG;IACH,iBAAiB,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;IACjD,kGAAkG;IAClG,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtD,mDAAmD;IACnD,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACpD,6CAA6C;IAC7C,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACnD,mFAAmF;IACnF,sBAAsB,EAAE,aAAa,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACtE,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,iBAAiB,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,MAAM,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAAC,CAAC;IACxD,8EAA8E;IAC9E,KAAK,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,iBAAiB,CAAC,GAAG,MAAM,CAAC,CAAC;CACxD;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC7B,yBAAyB,GACzB,CAAC,CACC,OAAO,EAAE,iCAAiC,KACvC,yBAAyB,GAAG,SAAS,CAAC,CAAC;AAEhD;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,qBAAqB,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,EAAE,CACT,OAAO,EAAE,iCAAiC,KACvC,0BAA0B,EAAE,GAAG,SAAS,CAAC;CAC/C;AAED;;;GAGG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;aAEjC,WAAW,EAAE,SAAS,0BAA0B,EAAE;IADpE,YACkB,WAAW,EAAE,SAAS,0BAA0B,EAAE,EAYnE;CACF"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* Copyright (C) 2026-present Aristotelis — see repository license. */
|
|
2
|
+
/**
|
|
3
|
+
* Well-known symbol for declaring an optional {@link IPipelineBehaviorContract}
|
|
4
|
+
* on a pipeline behavior class.
|
|
5
|
+
*/
|
|
6
|
+
export const PIPELINE_BEHAVIOR_CONTRACT = Symbol.for('@cqrs-ddd/pipeline:behavior-contract');
|
|
7
|
+
/**
|
|
8
|
+
* Thrown when a function is wrapped, or when an adapter starts, if deterministic
|
|
9
|
+
* pipeline policy misconfigurations or ordering violations are detected.
|
|
10
|
+
*/
|
|
11
|
+
export class PipelineConfigurationError extends Error {
|
|
12
|
+
diagnostics;
|
|
13
|
+
constructor(diagnostics) {
|
|
14
|
+
const formatted = diagnostics
|
|
15
|
+
.map((d, idx) => ` ${idx + 1}. [${d.handlerName} -> ${d.behaviorName}] ${d.message}. Fix: ${d.fix}`)
|
|
16
|
+
.join('\n');
|
|
17
|
+
super(`Pipeline configuration invalid with ${diagnostics.length} error(s):\n${formatted}`);
|
|
18
|
+
this.diagnostics = diagnostics;
|
|
19
|
+
this.name = 'PipelineConfigurationError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=pipeline-behavior-contract.interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-behavior-contract.interface.js","sourceRoot":"","sources":["../../src/interfaces/pipeline-behavior-contract.interface.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAKtE;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,GAAG,CAClD,sCAAsC,CACvC,CAAC;AAgGF;;;GAGG;AACH,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IAEjC,WAAW;IAD7B,YACkB,WAAkD;QAElE,MAAM,SAAS,GAAG,WAAW;aAC1B,GAAG,CACF,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CACT,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,WAAW,OAAO,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,OAAO,UAAU,CAAC,CAAC,GAAG,EAAE,CACtF;aACA,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,KAAK,CACH,uCAAuC,WAAW,CAAC,MAAM,eAAe,SAAS,EAAE,CACpF,CAAC;2BAVc,WAAW;QAW3B,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BehaviorId } from '../helpers/behavior-id.js';
|
|
2
|
+
import type { Constructor } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Pre-computed handler metadata, resolved once, before the first execution.
|
|
5
|
+
* Avoids per-request reflection and string operations.
|
|
6
|
+
*/
|
|
7
|
+
export interface PipelineHandlerMeta {
|
|
8
|
+
readonly handlerType: Constructor;
|
|
9
|
+
readonly handlerName: string;
|
|
10
|
+
readonly requestKind: 'command' | 'query' | 'event' | 'unknown';
|
|
11
|
+
readonly behaviorOptions?: Map<BehaviorId, Record<string, unknown>>;
|
|
12
|
+
/** The operation name; absent, the request's class name. */
|
|
13
|
+
readonly requestName?: string;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=pipeline-handler-meta.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-handler-meta.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/pipeline-handler-meta.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IAChE,QAAQ,CAAC,eAAe,CAAC,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACpE,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline-handler-meta.interface.js","sourceRoot":"","sources":["../../src/interfaces/pipeline-handler-meta.interface.ts"],"names":[],"mappings":"AAAA,sEAAsE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { IPipelineContext } from './pipeline.context.interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* Delegate to call the next behavior in the chain, or the real handler.
|
|
4
|
+
*/
|
|
5
|
+
export type NextDelegate<TResponse = unknown> = () => Promise<TResponse>;
|
|
6
|
+
/**
|
|
7
|
+
* Interface every pipeline behavior must implement.
|
|
8
|
+
* Works for command handlers, query handlers, AND event handlers.
|
|
9
|
+
*
|
|
10
|
+
* Sagas don't need wrapping — they are reactive stream factories.
|
|
11
|
+
* Any commands a saga emits will flow through the CommandBus and
|
|
12
|
+
* hit the pipeline of the target command handler automatically.
|
|
13
|
+
*/
|
|
14
|
+
export interface IPipelineBehavior<TRequest = unknown, TResponse = unknown> {
|
|
15
|
+
handle(context: IPipelineContext<TRequest, TResponse>, next: NextDelegate<TResponse>): Promise<TResponse>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Optional instance contract for a behavior that merges its own defaults into
|
|
19
|
+
* the options declared at a call site or globally. Contract diagnostics call it on
|
|
20
|
+
* behavior instances so contract validators receive the options the behavior will
|
|
21
|
+
* apply; a behavior without an instance when the diagnostics run passes its
|
|
22
|
+
* validators the raw declared options.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* class CacheBehavior
|
|
27
|
+
* implements IPipelineBehavior, IPipelineBehaviorOptionsResolver<CacheOptions>
|
|
28
|
+
* {
|
|
29
|
+
* resolveEffectiveOptions(options?: CacheOptions): CacheOptions {
|
|
30
|
+
* return { ...this.defaults, ...options };
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export interface IPipelineBehaviorOptionsResolver<TOptions extends object = Record<string, unknown>> {
|
|
36
|
+
resolveEffectiveOptions(options?: TOptions): TOptions | undefined;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=pipeline.behavior.interface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.behavior.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/pipeline.behavior.interface.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE;;GAEG;AACH,MAAM,MAAM,YAAY,CAAC,SAAS,GAAG,OAAO,IAAI,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;AAEzE;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB,CAAC,QAAQ,GAAG,OAAO,EAAE,SAAS,GAAG,OAAO;IACxE,MAAM,CACJ,OAAO,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,EAC9C,IAAI,EAAE,YAAY,CAAC,SAAS,CAAC,GAC5B,OAAO,CAAC,SAAS,CAAC,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,gCAAgC,CAC/C,QAAQ,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAEjD,uBAAuB,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;CACnE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.behavior.interface.js","sourceRoot":"","sources":["../../src/interfaces/pipeline.behavior.interface.ts"],"names":[],"mappings":"AAAA,sEAAsE"}
|