@nestjs-pipeline/job-context 0.2.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.
Files changed (68) hide show
  1. package/COMMERCIAL_LICENSE.txt +34 -0
  2. package/LICENSE +661 -0
  3. package/README.md +210 -0
  4. package/dist/constants/job-context.constants.d.ts +7 -0
  5. package/dist/constants/job-context.constants.d.ts.map +1 -0
  6. package/dist/constants/job-context.constants.js +11 -0
  7. package/dist/constants/job-context.constants.js.map +1 -0
  8. package/dist/decorators/as-system.decorator.d.ts +32 -0
  9. package/dist/decorators/as-system.decorator.d.ts.map +1 -0
  10. package/dist/decorators/as-system.decorator.js +58 -0
  11. package/dist/decorators/as-system.decorator.js.map +1 -0
  12. package/dist/decorators/in-job-context.decorator.d.ts +32 -0
  13. package/dist/decorators/in-job-context.decorator.d.ts.map +1 -0
  14. package/dist/decorators/in-job-context.decorator.js +53 -0
  15. package/dist/decorators/in-job-context.decorator.js.map +1 -0
  16. package/dist/errors/invalid-job-context.error.d.ts +15 -0
  17. package/dist/errors/invalid-job-context.error.d.ts.map +1 -0
  18. package/dist/errors/invalid-job-context.error.js +24 -0
  19. package/dist/errors/invalid-job-context.error.js.map +1 -0
  20. package/dist/errors/missing-job-context.error.d.ts +14 -0
  21. package/dist/errors/missing-job-context.error.d.ts.map +1 -0
  22. package/dist/errors/missing-job-context.error.js +23 -0
  23. package/dist/errors/missing-job-context.error.js.map +1 -0
  24. package/dist/helpers/parse-job-context.d.ts +20 -0
  25. package/dist/helpers/parse-job-context.d.ts.map +1 -0
  26. package/dist/helpers/parse-job-context.js +71 -0
  27. package/dist/helpers/parse-job-context.js.map +1 -0
  28. package/dist/helpers/principal-reference.d.ts +12 -0
  29. package/dist/helpers/principal-reference.d.ts.map +1 -0
  30. package/dist/helpers/principal-reference.js +18 -0
  31. package/dist/helpers/principal-reference.js.map +1 -0
  32. package/dist/helpers/registration.d.ts +39 -0
  33. package/dist/helpers/registration.d.ts.map +1 -0
  34. package/dist/helpers/registration.js +49 -0
  35. package/dist/helpers/registration.js.map +1 -0
  36. package/dist/helpers/with-job-context.d.ts +21 -0
  37. package/dist/helpers/with-job-context.d.ts.map +1 -0
  38. package/dist/helpers/with-job-context.js +49 -0
  39. package/dist/helpers/with-job-context.js.map +1 -0
  40. package/dist/index.d.ts +12 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +17 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/interfaces/context-source.interface.d.ts +23 -0
  45. package/dist/interfaces/context-source.interface.d.ts.map +1 -0
  46. package/dist/interfaces/context-source.interface.js +4 -0
  47. package/dist/interfaces/context-source.interface.js.map +1 -0
  48. package/dist/interfaces/job-context-options.interface.d.ts +22 -0
  49. package/dist/interfaces/job-context-options.interface.d.ts.map +1 -0
  50. package/dist/interfaces/job-context-options.interface.js +4 -0
  51. package/dist/interfaces/job-context-options.interface.js.map +1 -0
  52. package/dist/interfaces/job-context.interface.d.ts +12 -0
  53. package/dist/interfaces/job-context.interface.d.ts.map +1 -0
  54. package/dist/interfaces/job-context.interface.js +4 -0
  55. package/dist/interfaces/job-context.interface.js.map +1 -0
  56. package/dist/interfaces/job-principal.interface.d.ts +28 -0
  57. package/dist/interfaces/job-principal.interface.d.ts.map +1 -0
  58. package/dist/interfaces/job-principal.interface.js +4 -0
  59. package/dist/interfaces/job-principal.interface.js.map +1 -0
  60. package/dist/interfaces/principal-reference.interface.d.ts +12 -0
  61. package/dist/interfaces/principal-reference.interface.d.ts.map +1 -0
  62. package/dist/interfaces/principal-reference.interface.js +4 -0
  63. package/dist/interfaces/principal-reference.interface.js.map +1 -0
  64. package/dist/job-context.module.d.ts +42 -0
  65. package/dist/job-context.module.d.ts.map +1 -0
  66. package/dist/job-context.module.js +99 -0
  67. package/dist/job-context.module.js.map +1 -0
  68. package/package.json +57 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principal-reference.d.ts","sourceRoot":"","sources":["../../src/helpers/principal-reference.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAEtF;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,kBAAkB,GAAG,kBAAkB,CAG7E"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.toReference = toReference;
5
+ /**
6
+ * Copies only the identity fields of `principal`, so grants or session data an
7
+ * application object also holds never reach a payload or a restore call.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * toReference({ id: 'u-1', type: 'user', sid: 's-1', grants: [] }); // { id: 'u-1', type: 'user' }
12
+ * ```
13
+ */
14
+ function toReference(principal) {
15
+ const { id, type, sessionId } = principal;
16
+ return sessionId === undefined ? { id, type } : { id, type, sessionId };
17
+ }
18
+ //# sourceMappingURL=principal-reference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principal-reference.js","sourceRoot":"","sources":["../../src/helpers/principal-reference.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAatE,kCAGC;AAZD;;;;;;;;GAQG;AACH,SAAgB,WAAW,CAAC,SAA6B;IACvD,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC;IAC1C,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,39 @@
1
+ import type { JobContextSources } from '../interfaces/context-source.interface';
2
+ import type { IJobPrincipal } from '../interfaces/job-principal.interface';
3
+ /** What `JobContextModule` registers for the decorators, which run outside DI. */
4
+ export interface Registration {
5
+ readonly principal: IJobPrincipal;
6
+ readonly tenants: readonly string[];
7
+ readonly sources: JobContextSources;
8
+ }
9
+ /**
10
+ * Makes `registration` the one the decorators and `withJobContext` use.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * register({ principal, tenants: ['tenant_a'], sources });
15
+ * ```
16
+ */
17
+ export declare function register(registration: Registration): void;
18
+ /**
19
+ * Removes `registration` if it is still the active one, so closing one
20
+ * application does not remove another's.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * unregister(registration);
25
+ * ```
26
+ */
27
+ export declare function unregister(registration: Registration): void;
28
+ /**
29
+ * The active registration.
30
+ *
31
+ * @throws {MissingJobContextError} When no `JobContextModule` is running.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const { principal, tenants, sources } = activeRegistration();
36
+ * ```
37
+ */
38
+ export declare function activeRegistration(): Registration;
39
+ //# sourceMappingURL=registration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registration.d.ts","sourceRoot":"","sources":["../../src/helpers/registration.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAE3E,kFAAkF;AAClF,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;CACrC;AAID;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAEzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,YAAY,GAAG,IAAI,CAE3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAKjD"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.register = register;
5
+ exports.unregister = unregister;
6
+ exports.activeRegistration = activeRegistration;
7
+ const missing_job_context_error_1 = require("../errors/missing-job-context.error");
8
+ let active;
9
+ /**
10
+ * Makes `registration` the one the decorators and `withJobContext` use.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * register({ principal, tenants: ['tenant_a'], sources });
15
+ * ```
16
+ */
17
+ function register(registration) {
18
+ active = registration;
19
+ }
20
+ /**
21
+ * Removes `registration` if it is still the active one, so closing one
22
+ * application does not remove another's.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * unregister(registration);
27
+ * ```
28
+ */
29
+ function unregister(registration) {
30
+ if (active === registration)
31
+ active = undefined;
32
+ }
33
+ /**
34
+ * The active registration.
35
+ *
36
+ * @throws {MissingJobContextError} When no `JobContextModule` is running.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * const { principal, tenants, sources } = activeRegistration();
41
+ * ```
42
+ */
43
+ function activeRegistration() {
44
+ if (active === undefined) {
45
+ throw new missing_job_context_error_1.MissingJobContextError('a running JobContextModule');
46
+ }
47
+ return active;
48
+ }
49
+ //# sourceMappingURL=registration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registration.js","sourceRoot":"","sources":["../../src/helpers/registration.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAuBtE,4BAEC;AAWD,gCAEC;AAYD,gDAKC;AArDD,mFAA6E;AAW7E,IAAI,MAAgC,CAAC;AAErC;;;;;;;GAOG;AACH,SAAgB,QAAQ,CAAC,YAA0B;IACjD,MAAM,GAAG,YAAY,CAAC;AACxB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,UAAU,CAAC,YAA0B;IACnD,IAAI,MAAM,KAAK,YAAY;QAAE,MAAM,GAAG,SAAS,CAAC;AAClD,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,kBAAkB;IAChC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,kDAAsB,CAAC,4BAA4B,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { WithJobContext } from '../interfaces/job-context.interface';
2
+ /**
3
+ * Stamps the current execution context onto a job payload: the tenant and
4
+ * correlation id of the registered sources (a new one from the correlation
5
+ * source's `create()` when none is active), and the principal the registered `IJobPrincipal`
6
+ * captures, reduced to its identity. The processor restores it with
7
+ * `@InJobContext`.
8
+ *
9
+ * @param data - The payload. Must be a plain object; a shallow copy is returned.
10
+ * @returns A copy of `data` with `jobContext` added.
11
+ * @throws {TypeError} When `data` is not a plain object.
12
+ * @throws {MissingJobContextError} Without a running `JobContextModule`, a
13
+ * current tenant, or a current principal.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * await queue.add('send', withJobContext({ userId, email }));
18
+ * ```
19
+ */
20
+ export declare function withJobContext<T extends Record<string, unknown>>(data: T): WithJobContext<T>;
21
+ //# sourceMappingURL=with-job-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-job-context.d.ts","sourceRoot":"","sources":["../../src/helpers/with-job-context.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAI1E;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9D,IAAI,EAAE,CAAC,GACN,cAAc,CAAC,CAAC,CAAC,CAwBnB"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.withJobContext = withJobContext;
5
+ const missing_job_context_error_1 = require("../errors/missing-job-context.error");
6
+ const principal_reference_1 = require("./principal-reference");
7
+ const registration_1 = require("./registration");
8
+ /**
9
+ * Stamps the current execution context onto a job payload: the tenant and
10
+ * correlation id of the registered sources (a new one from the correlation
11
+ * source's `create()` when none is active), and the principal the registered `IJobPrincipal`
12
+ * captures, reduced to its identity. The processor restores it with
13
+ * `@InJobContext`.
14
+ *
15
+ * @param data - The payload. Must be a plain object; a shallow copy is returned.
16
+ * @returns A copy of `data` with `jobContext` added.
17
+ * @throws {TypeError} When `data` is not a plain object.
18
+ * @throws {MissingJobContextError} Without a running `JobContextModule`, a
19
+ * current tenant, or a current principal.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * await queue.add('send', withJobContext({ userId, email }));
24
+ * ```
25
+ */
26
+ function withJobContext(data) {
27
+ const prototype = data !== null && typeof data === 'object'
28
+ ? Object.getPrototypeOf(data)
29
+ : undefined;
30
+ if (prototype !== Object.prototype && prototype !== null) {
31
+ throw new TypeError('withJobContext(data) requires a plain object payload. Wrap arrays and class instances in a plain object first.');
32
+ }
33
+ const { principal, sources } = (0, registration_1.activeRegistration)();
34
+ const tenantId = sources.tenantId.current();
35
+ if (tenantId === undefined)
36
+ throw new missing_job_context_error_1.MissingJobContextError('tenant');
37
+ const captured = principal.capture();
38
+ if (captured === undefined)
39
+ throw new missing_job_context_error_1.MissingJobContextError('principal');
40
+ return {
41
+ ...data,
42
+ jobContext: {
43
+ tenantId,
44
+ correlationId: sources.correlationId.current() ?? sources.correlationId.create(),
45
+ principal: (0, principal_reference_1.toReference)(captured),
46
+ },
47
+ };
48
+ }
49
+ //# sourceMappingURL=with-job-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"with-job-context.js","sourceRoot":"","sources":["../../src/helpers/with-job-context.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAyBtE,wCA0BC;AAjDD,mFAA6E;AAE7E,+DAAoD;AACpD,iDAAoD;AAEpD;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,cAAc,CAC5B,IAAO;IAEP,MAAM,SAAS,GACb,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QACvC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC;QAC7B,CAAC,CAAC,SAAS,CAAC;IAChB,IAAI,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACzD,MAAM,IAAI,SAAS,CACjB,gHAAgH,CACjH,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,IAAA,iCAAkB,GAAE,CAAC;IACpD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IAC5C,IAAI,QAAQ,KAAK,SAAS;QAAE,MAAM,IAAI,kDAAsB,CAAC,QAAQ,CAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;IACrC,IAAI,QAAQ,KAAK,SAAS;QAAE,MAAM,IAAI,kDAAsB,CAAC,WAAW,CAAC,CAAC;IAC1E,OAAO;QACL,GAAG,IAAI;QACP,UAAU,EAAE;YACV,QAAQ;YACR,aAAa,EACX,OAAO,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE;YACnE,SAAS,EAAE,IAAA,iCAAW,EAAC,QAAQ,CAAC;SACjC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { AsSystem, type AsSystemOptions, } from './decorators/as-system.decorator';
2
+ export { InJobContext, type InJobContextOptions, } from './decorators/in-job-context.decorator';
3
+ export { InvalidJobContextError } from './errors/invalid-job-context.error';
4
+ export { MissingJobContextError } from './errors/missing-job-context.error';
5
+ export { withJobContext } from './helpers/with-job-context';
6
+ export type { ContextSource, CorrelationSource, JobContextSources, } from './interfaces/context-source.interface';
7
+ export type { JobContext, WithJobContext, } from './interfaces/job-context.interface';
8
+ export type { JobContextOptions } from './interfaces/job-context-options.interface';
9
+ export type { IJobPrincipal } from './interfaces/job-principal.interface';
10
+ export type { PrincipalReference } from './interfaces/principal-reference.interface';
11
+ export { JobContextModule } from './job-context.module';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,QAAQ,EACR,KAAK,eAAe,GACrB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,YAAY,EACZ,KAAK,mBAAmB,GACzB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,UAAU,EACV,cAAc,GACf,MAAM,oCAAoC,CAAC;AAC5C,YAAY,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AACpF,YAAY,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAC1E,YAAY,EAAE,kBAAkB,EAAE,MAAM,4CAA4C,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.JobContextModule = exports.withJobContext = exports.MissingJobContextError = exports.InvalidJobContextError = exports.InJobContext = exports.AsSystem = void 0;
5
+ var as_system_decorator_1 = require("./decorators/as-system.decorator");
6
+ Object.defineProperty(exports, "AsSystem", { enumerable: true, get: function () { return as_system_decorator_1.AsSystem; } });
7
+ var in_job_context_decorator_1 = require("./decorators/in-job-context.decorator");
8
+ Object.defineProperty(exports, "InJobContext", { enumerable: true, get: function () { return in_job_context_decorator_1.InJobContext; } });
9
+ var invalid_job_context_error_1 = require("./errors/invalid-job-context.error");
10
+ Object.defineProperty(exports, "InvalidJobContextError", { enumerable: true, get: function () { return invalid_job_context_error_1.InvalidJobContextError; } });
11
+ var missing_job_context_error_1 = require("./errors/missing-job-context.error");
12
+ Object.defineProperty(exports, "MissingJobContextError", { enumerable: true, get: function () { return missing_job_context_error_1.MissingJobContextError; } });
13
+ var with_job_context_1 = require("./helpers/with-job-context");
14
+ Object.defineProperty(exports, "withJobContext", { enumerable: true, get: function () { return with_job_context_1.withJobContext; } });
15
+ var job_context_module_1 = require("./job-context.module");
16
+ Object.defineProperty(exports, "JobContextModule", { enumerable: true, get: function () { return job_context_module_1.JobContextModule; } });
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;AAEtE,wEAG0C;AAFxC,+GAAA,QAAQ,OAAA;AAGV,kFAG+C;AAF7C,wHAAA,YAAY,OAAA;AAGd,gFAA4E;AAAnE,mIAAA,sBAAsB,OAAA;AAC/B,gFAA4E;AAAnE,mIAAA,sBAAsB,OAAA;AAC/B,+DAA4D;AAAnD,kHAAA,cAAc,OAAA;AAavB,2DAAwD;AAA/C,sHAAA,gBAAgB,OAAA"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A value kept for the current execution by the package that owns it, such as
3
+ * `tenantSource` of `@nestjs-pipeline/tenant`.
4
+ */
5
+ export interface ContextSource {
6
+ /** The value of the current execution, or `undefined` for none. */
7
+ current(): string | undefined;
8
+ /** Runs `fn` with `value` as the current value for everything it calls. */
9
+ run<T>(value: string | undefined, fn: () => T): T;
10
+ }
11
+ /** A correlation id source that also makes new ids and judges ids received from outside. */
12
+ export interface CorrelationSource extends ContextSource {
13
+ /** A new correlation id. */
14
+ create(): string;
15
+ /** Whether `id`, read from a job payload, is a well-formed correlation id. */
16
+ accepts(id: string): boolean;
17
+ }
18
+ /** The tenant and correlation id a job carries and restores. */
19
+ export interface JobContextSources {
20
+ readonly tenantId: ContextSource;
21
+ readonly correlationId: CorrelationSource;
22
+ }
23
+ //# 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;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,OAAO,IAAI,MAAM,GAAG,SAAS,CAAC;IAC9B,2EAA2E;IAC3E,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CACnD;AAED,4FAA4F;AAC5F,MAAM,WAAW,iBAAkB,SAAQ,aAAa;IACtD,4BAA4B;IAC5B,MAAM,IAAI,MAAM,CAAC;IACjB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;CAC9B;AAED,gEAAgE;AAChE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,CAAC;CAC3C"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=context-source.interface.js.map
@@ -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,22 @@
1
+ import type { ModuleMetadata, Type } from '@nestjs/common';
2
+ import type { JobContextSources } from './context-source.interface';
3
+ import type { IJobPrincipal } from './job-principal.interface';
4
+ /** Options of `JobContextModule.forRoot`. */
5
+ export interface JobContextOptions {
6
+ /** The application's principal port, instantiated through dependency injection. */
7
+ principal: Type<IJobPrincipal>;
8
+ /**
9
+ * Tenants a job may run in. A payload naming another tenant is refused, and
10
+ * `@AsSystem` work runs once per tenant, in this order. Must not be empty.
11
+ */
12
+ tenants: readonly string[];
13
+ /**
14
+ * Where the tenant and correlation id are read when a job is enqueued and
15
+ * restored when it runs, such as `tenantSource` of `@nestjs-pipeline/tenant`
16
+ * and `correlationSource` of `@nestjs-pipeline/correlation`.
17
+ */
18
+ sources: JobContextSources;
19
+ /** Modules that export the dependencies of `principal`. */
20
+ imports?: ModuleMetadata['imports'];
21
+ }
22
+ //# sourceMappingURL=job-context-options.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-context-options.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/job-context-options.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,mFAAmF;IACnF,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAC/B;;;OAGG;IACH,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;;OAIG;IACH,OAAO,EAAE,iBAAiB,CAAC;IAC3B,2DAA2D;IAC3D,OAAO,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;CACrC"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=job-context-options.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-context-options.interface.js","sourceRoot":"","sources":["../../src/interfaces/job-context-options.interface.ts"],"names":[],"mappings":";AAAA,sEAAsE"}
@@ -0,0 +1,12 @@
1
+ import type { PrincipalReference } from './principal-reference.interface';
2
+ /** Execution context a job payload carries from the request that enqueued it. */
3
+ export interface JobContext {
4
+ readonly tenantId: string;
5
+ readonly correlationId: string;
6
+ readonly principal: PrincipalReference;
7
+ }
8
+ /** A job payload stamped by `withJobContext`. */
9
+ export type WithJobContext<T extends Record<string, unknown>> = T & {
10
+ jobContext: JobContext;
11
+ };
12
+ //# sourceMappingURL=job-context.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-context.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/job-context.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,iFAAiF;AACjF,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;CACxC;AAED,iDAAiD;AACjD,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG;IAClE,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=job-context.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-context.interface.js","sourceRoot":"","sources":["../../src/interfaces/job-context.interface.ts"],"names":[],"mappings":";AAAA,sEAAsE"}
@@ -0,0 +1,28 @@
1
+ import type { PrincipalReference } from './principal-reference.interface';
2
+ /**
3
+ * Application port that reads the current principal when a job is enqueued and
4
+ * binds it again when the job runs. The application implements it over its own
5
+ * authentication state; register the implementation with
6
+ * `JobContextModule.forRoot`.
7
+ *
8
+ * @typeParam TGrant - The application's grant type, as declared in `@AsSystem`.
9
+ */
10
+ export interface IJobPrincipal<TGrant = unknown> {
11
+ /**
12
+ * The principal of the current execution, or `undefined` when there is none.
13
+ * Only `id`, `type` and `sessionId` of the result are kept.
14
+ */
15
+ capture(): PrincipalReference | undefined;
16
+ /**
17
+ * Re-checks `principal` against current state and runs `work` with it as the
18
+ * current principal. It runs inside the job's tenant and correlation id.
19
+ * Throw to refuse the job, for example for a revoked session or a deleted
20
+ * principal; the job then fails without running.
21
+ *
22
+ * @param grants - Set only for `@AsSystem` work: the complete grants its code
23
+ * declares. For a job payload it is `undefined`, and the principal's
24
+ * authorization must be resolved from current state.
25
+ */
26
+ restore<T>(principal: PrincipalReference, work: () => Promise<T>, grants?: readonly TGrant[]): Promise<T>;
27
+ }
28
+ //# sourceMappingURL=job-principal.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-principal.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/job-principal.interface.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa,CAAC,MAAM,GAAG,OAAO;IAC7C;;;OAGG;IACH,OAAO,IAAI,kBAAkB,GAAG,SAAS,CAAC;IAE1C;;;;;;;;;OASG;IACH,OAAO,CAAC,CAAC,EACP,SAAS,EAAE,kBAAkB,EAC7B,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACtB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAAC,CAAC,CAAC,CAAC;CACf"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=job-principal.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-principal.interface.js","sourceRoot":"","sources":["../../src/interfaces/job-principal.interface.ts"],"names":[],"mappings":";AAAA,sEAAsE"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Identity of the principal a job acts for. It carries no grants: what the
3
+ * principal may do is resolved again when the job runs.
4
+ */
5
+ export interface PrincipalReference {
6
+ readonly id: string;
7
+ /** Application-defined classification, such as `'user'` or `'service'`. */
8
+ readonly type: string;
9
+ /** Login session the principal authenticated with; absent when it has none. */
10
+ readonly sessionId?: string;
11
+ }
12
+ //# sourceMappingURL=principal-reference.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principal-reference.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/principal-reference.interface.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B"}
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ //# sourceMappingURL=principal-reference.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principal-reference.interface.js","sourceRoot":"","sources":["../../src/interfaces/principal-reference.interface.ts"],"names":[],"mappings":";AAAA,sEAAsE"}
@@ -0,0 +1,42 @@
1
+ import { type DynamicModule } from '@nestjs/common';
2
+ import type { JobContextOptions } from './interfaces/job-context-options.interface';
3
+ /**
4
+ * Connects `withJobContext`, `@InJobContext` and `@AsSystem` to the
5
+ * application's principal port, tenant list, and tenant and correlation id
6
+ * sources. The decorators wrap methods
7
+ * outside dependency injection, so they read the registration of the running
8
+ * module; with none they fail closed. One application registers it once.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * @Module({
13
+ * imports: [
14
+ * JobContextModule.forRoot({
15
+ * principal: SessionJobPrincipal,
16
+ * tenants: ['tenant_a', 'tenant_b'],
17
+ * sources: { tenantId: tenantSource, correlationId: correlationSource },
18
+ * imports: [AuthsModule],
19
+ * }),
20
+ * ],
21
+ * })
22
+ * export class JobsModule {}
23
+ * ```
24
+ */
25
+ export declare class JobContextModule {
26
+ /**
27
+ * Builds the module for `options`.
28
+ *
29
+ * @throws {TypeError} When `options.tenants` is empty.
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * JobContextModule.forRoot({
34
+ * principal: SessionJobPrincipal,
35
+ * tenants: ['tenant_a'],
36
+ * sources: { tenantId: tenantSource, correlationId: correlationSource },
37
+ * });
38
+ * ```
39
+ */
40
+ static forRoot(options: JobContextOptions): DynamicModule;
41
+ }
42
+ //# sourceMappingURL=job-context.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-context.module.d.ts","sourceRoot":"","sources":["../src/job-context.module.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,gBAAgB,CAAC;AAYxB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAyBpF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,gBAAgB;IAC3B;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,aAAa;CAe1D"}
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
4
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
5
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
6
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
7
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
8
+ };
9
+ var __metadata = (this && this.__metadata) || function (k, v) {
10
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
11
+ };
12
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
+ return function (target, key) { decorator(target, key, paramIndex); }
14
+ };
15
+ var JobContextModule_1;
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.JobContextModule = void 0;
18
+ const common_1 = require("@nestjs/common");
19
+ const job_context_constants_1 = require("./constants/job-context.constants");
20
+ const registration_1 = require("./helpers/registration");
21
+ /**
22
+ * Registers the principal port, tenants and sources when it is constructed, before any
23
+ * lifecycle hook can start a worker, and removes them at shutdown.
24
+ */
25
+ let JobContextRegistration = class JobContextRegistration {
26
+ registration;
27
+ constructor(principal, tenants, sources) {
28
+ this.registration = { principal, tenants, sources };
29
+ (0, registration_1.register)(this.registration);
30
+ }
31
+ onApplicationShutdown() {
32
+ (0, registration_1.unregister)(this.registration);
33
+ }
34
+ };
35
+ JobContextRegistration = __decorate([
36
+ (0, common_1.Injectable)(),
37
+ __param(0, (0, common_1.Inject)(job_context_constants_1.JOB_PRINCIPAL)),
38
+ __param(1, (0, common_1.Inject)(job_context_constants_1.JOB_TENANTS)),
39
+ __param(2, (0, common_1.Inject)(job_context_constants_1.JOB_SOURCES)),
40
+ __metadata("design:paramtypes", [Object, Array, Object])
41
+ ], JobContextRegistration);
42
+ /**
43
+ * Connects `withJobContext`, `@InJobContext` and `@AsSystem` to the
44
+ * application's principal port, tenant list, and tenant and correlation id
45
+ * sources. The decorators wrap methods
46
+ * outside dependency injection, so they read the registration of the running
47
+ * module; with none they fail closed. One application registers it once.
48
+ *
49
+ * @example
50
+ * ```ts
51
+ * @Module({
52
+ * imports: [
53
+ * JobContextModule.forRoot({
54
+ * principal: SessionJobPrincipal,
55
+ * tenants: ['tenant_a', 'tenant_b'],
56
+ * sources: { tenantId: tenantSource, correlationId: correlationSource },
57
+ * imports: [AuthsModule],
58
+ * }),
59
+ * ],
60
+ * })
61
+ * export class JobsModule {}
62
+ * ```
63
+ */
64
+ let JobContextModule = JobContextModule_1 = class JobContextModule {
65
+ /**
66
+ * Builds the module for `options`.
67
+ *
68
+ * @throws {TypeError} When `options.tenants` is empty.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * JobContextModule.forRoot({
73
+ * principal: SessionJobPrincipal,
74
+ * tenants: ['tenant_a'],
75
+ * sources: { tenantId: tenantSource, correlationId: correlationSource },
76
+ * });
77
+ * ```
78
+ */
79
+ static forRoot(options) {
80
+ if (options.tenants.length === 0) {
81
+ throw new TypeError('JobContextModule needs at least one tenant.');
82
+ }
83
+ return {
84
+ module: JobContextModule_1,
85
+ imports: options.imports ?? [],
86
+ providers: [
87
+ { provide: job_context_constants_1.JOB_PRINCIPAL, useClass: options.principal },
88
+ { provide: job_context_constants_1.JOB_TENANTS, useValue: [...options.tenants] },
89
+ { provide: job_context_constants_1.JOB_SOURCES, useValue: options.sources },
90
+ JobContextRegistration,
91
+ ],
92
+ };
93
+ }
94
+ };
95
+ exports.JobContextModule = JobContextModule;
96
+ exports.JobContextModule = JobContextModule = JobContextModule_1 = __decorate([
97
+ (0, common_1.Module)({})
98
+ ], JobContextModule);
99
+ //# sourceMappingURL=job-context.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-context.module.js","sourceRoot":"","sources":["../src/job-context.module.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;;;;;;;;;;;;;;AAEtE,2CAMwB;AACxB,6EAI2C;AAC3C,yDAIgC;AAKhC;;;GAGG;AACH,IACM,sBAAsB,GAD5B,MACM,sBAAsB;IACT,YAAY,CAAe;IAE5C,YACyB,SAAwB,EAC1B,OAA0B,EAC1B,OAA0B;QAE/C,IAAI,CAAC,YAAY,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;QACpD,IAAA,uBAAQ,EAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9B,CAAC;IAED,qBAAqB;QACnB,IAAA,yBAAU,EAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;CACF,CAAA;AAfK,sBAAsB;IAD3B,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,eAAM,EAAC,qCAAa,CAAC,CAAA;IACrB,WAAA,IAAA,eAAM,EAAC,mCAAW,CAAC,CAAA;IACnB,WAAA,IAAA,eAAM,EAAC,mCAAW,CAAC,CAAA;;GANlB,sBAAsB,CAe3B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEI,IAAM,gBAAgB,wBAAtB,MAAM,gBAAgB;IAC3B;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,OAAO,CAAC,OAA0B;QACvC,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC;QACrE,CAAC;QACD,OAAO;YACL,MAAM,EAAE,kBAAgB;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,SAAS,EAAE;gBACT,EAAE,OAAO,EAAE,qCAAa,EAAE,QAAQ,EAAE,OAAO,CAAC,SAAS,EAAE;gBACvD,EAAE,OAAO,EAAE,mCAAW,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE;gBACxD,EAAE,OAAO,EAAE,mCAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE;gBACnD,sBAAsB;aACvB;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AA9BY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,gBAAgB,CA8B5B"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@nestjs-pipeline/job-context",
3
+ "version": "0.2.0",
4
+ "description": "Carries the tenant, correlation id and principal of a request into the queue jobs it enqueues, and gives system-started work an explicit context",
5
+ "author": "Aristotelis",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "engines": {
8
+ "node": ">=22.0.0"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/aristoteliss/nestjs-pipeline.git",
13
+ "directory": "packages/pipeline-job-context"
14
+ },
15
+ "homepage": "https://github.com/aristoteliss/nestjs-pipeline/tree/master/packages/pipeline-job-context#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/aristoteliss/nestjs-pipeline/issues"
18
+ },
19
+ "keywords": [
20
+ "nestjs",
21
+ "cqrs",
22
+ "pipeline",
23
+ "multi-tenancy",
24
+ "queue",
25
+ "jobs",
26
+ "authorization",
27
+ "correlation-id"
28
+ ],
29
+ "main": "dist/index.js",
30
+ "types": "dist/index.d.ts",
31
+ "files": [
32
+ "dist",
33
+ "LICENSE",
34
+ "COMMERCIAL_LICENSE.txt"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "peerDependencies": {
40
+ "@nestjs/common": "^11.0.0"
41
+ },
42
+ "devDependencies": {
43
+ "@nestjs/common": "^11.2.6",
44
+ "@vitest/coverage-v8": "^4.1.11",
45
+ "reflect-metadata": "^0.2.2",
46
+ "vitest": "^4.1.11"
47
+ },
48
+ "scripts": {
49
+ "build": "tsc -p tsconfig.build.json",
50
+ "build:watch": "tsc -p tsconfig.build.json --watch",
51
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
52
+ "rebuild": "pnpm run clean && pnpm run build",
53
+ "lint": "tsc --noEmit",
54
+ "test": "vitest run",
55
+ "test:watch": "vitest"
56
+ }
57
+ }