@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
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # @nestjs-pipeline/job-context
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@nestjs-pipeline/job-context.svg)](https://www.npmjs.com/package/@nestjs-pipeline/job-context)
4
+ [![License](https://img.shields.io/npm/l/@nestjs-pipeline/job-context.svg)](https://www.npmjs.com/package/@nestjs-pipeline/job-context)
5
+
6
+ The execution context of a request, carried into the queue jobs it enqueues: the tenant,
7
+ the correlation id and the principal. A job then makes the decisions the request would
8
+ have made. System-started work, such as a cron job, declares its context explicitly
9
+ instead. Nothing falls back to a default tenant or an anonymous principal.
10
+
11
+ It depends on no other pipeline package. It reads and restores the tenant and the
12
+ correlation id through the sources it is given, usually `tenantSource` of
13
+ [`@nestjs-pipeline/tenant`](https://github.com/aristoteliss/nestjs-pipeline/tree/master/packages/pipeline-tenant#readme)
14
+ and `correlationSource` of
15
+ [`@nestjs-pipeline/correlation`](https://github.com/aristoteliss/nestjs-pipeline/tree/master/packages/pipeline-correlation#readme),
16
+ so pipelines a job dispatches get the same tenant and correlation id.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pnpm add @nestjs-pipeline/job-context @nestjs/common
22
+ ```
23
+
24
+ Requires Node.js 22 or later.
25
+
26
+ ## Setup
27
+
28
+ Implement `IJobPrincipal` over the application's authentication state, and register it
29
+ with the tenants jobs may run in and the tenant and correlation id sources:
30
+
31
+ `Capability`, `SessionRepository`, `SessionsModule`, `currentPrincipal`,
32
+ `runAsPrincipal` and `SessionRevokedError` stand for the application's own authentication
33
+ code.
34
+
35
+ ```typescript
36
+ import { Injectable, Module } from '@nestjs/common';
37
+ import { correlationSource } from '@nestjs-pipeline/correlation';
38
+ import {
39
+ type IJobPrincipal,
40
+ JobContextModule,
41
+ type PrincipalReference,
42
+ } from '@nestjs-pipeline/job-context';
43
+ import { tenantSource } from '@nestjs-pipeline/tenant';
44
+
45
+ @Injectable()
46
+ export class SessionJobPrincipal implements IJobPrincipal<Capability> {
47
+ constructor(private readonly sessions: SessionRepository) {}
48
+
49
+ capture(): PrincipalReference | undefined {
50
+ const principal = currentPrincipal();
51
+ return principal && { id: principal.id, type: principal.type, sessionId: principal.sid };
52
+ }
53
+
54
+ async restore<T>(
55
+ principal: PrincipalReference,
56
+ work: () => Promise<T>,
57
+ grants?: readonly Capability[],
58
+ ): Promise<T> {
59
+ if (grants) return runAsPrincipal({ ...principal, grants }, work);
60
+ const session = await this.sessions.findActive(principal.sessionId, principal.id);
61
+ if (!session) throw new SessionRevokedError();
62
+ return runAsPrincipal(principal, work);
63
+ }
64
+ }
65
+
66
+ @Module({
67
+ imports: [
68
+ JobContextModule.forRoot({
69
+ principal: SessionJobPrincipal,
70
+ tenants: ['tenant_a', 'tenant_b'],
71
+ sources: { tenantId: tenantSource, correlationId: correlationSource },
72
+ imports: [SessionsModule],
73
+ }),
74
+ ],
75
+ })
76
+ export class JobsModule {}
77
+ ```
78
+
79
+ `capture` reads the current principal when a job is enqueued; only its `id`, `type` and
80
+ `sessionId` are kept. `restore` runs when the job does, inside the job's tenant and
81
+ correlation id: it must re-check the principal against current state, bind it the way a
82
+ request would, and throw to refuse the job.
83
+
84
+ ## Usage
85
+
86
+ Stamp the payload when enqueuing, from inside the request or handler, so the tenant,
87
+ correlation id and principal are current:
88
+
89
+ ```typescript
90
+ import { InjectQueue } from '@nestjs/bullmq';
91
+ import { EventsHandler, type IEventHandler } from '@nestjs/cqrs';
92
+ import { withJobContext, type WithJobContext } from '@nestjs-pipeline/job-context';
93
+ import type { Queue } from 'bullmq';
94
+
95
+ type WelcomeEmail = { userId: string; email: string };
96
+
97
+ @EventsHandler(UserRegisteredEvent)
98
+ export class EnqueueWelcomeEmail implements IEventHandler<UserRegisteredEvent> {
99
+ constructor(
100
+ @InjectQueue(WELCOME_EMAIL_QUEUE)
101
+ private readonly queue: Queue<WithJobContext<WelcomeEmail>>,
102
+ ) {}
103
+
104
+ async handle({ userId, email }: UserRegisteredEvent) {
105
+ await this.queue.add('send', withJobContext({ userId, email }));
106
+ }
107
+ }
108
+ ```
109
+
110
+ Restore it in the processor. Place the decorator under the transport decorator:
111
+
112
+ ```typescript
113
+ import { Processor, WorkerHost } from '@nestjs/bullmq';
114
+ import { CommandBus } from '@nestjs/cqrs';
115
+ import { InJobContext, type WithJobContext } from '@nestjs-pipeline/job-context';
116
+ import type { Job } from 'bullmq';
117
+
118
+ @Processor(WELCOME_EMAIL_QUEUE)
119
+ export class SendWelcomeEmailProcessor extends WorkerHost {
120
+ constructor(private readonly commandBus: CommandBus) {
121
+ super();
122
+ }
123
+
124
+ @InJobContext()
125
+ async process(job: Job<WithJobContext<WelcomeEmail>>) {
126
+ await this.commandBus.execute(new SendWelcomeEmailCommand(job.data));
127
+ }
128
+ }
129
+ ```
130
+
131
+ `@InJobContext()` reads `data.jobContext` from the first argument (a BullMQ `Job`); pass
132
+ `{ path: 'jobContext' }` for a transport that hands the payload itself.
133
+
134
+ ```typescript
135
+ @EventPattern('user.registered')
136
+ @InJobContext({ path: 'jobContext' })
137
+ async onRegistered(@Payload() data: WithJobContext<WelcomeEmail>) {
138
+ await this.commandBus.execute(new SendWelcomeEmailCommand(data));
139
+ }
140
+ ```
141
+
142
+ A refused job throws `MissingJobContextError` or `InvalidJobContextError` before the method
143
+ runs; let the queue mark it failed rather than retrying it, since the payload will not change.
144
+
145
+ Declare system-started work:
146
+
147
+ ```typescript
148
+ import { AsSystem } from '@nestjs-pipeline/job-context';
149
+ import { Cron } from '@nestjs/schedule';
150
+
151
+ @Cron('0 3 * * *')
152
+ @AsSystem({
153
+ principal: { id: 'session-cleanup', type: 'service' },
154
+ grants: [{ action: 'delete', subject: 'Auth' }],
155
+ })
156
+ async purgeSessions() {
157
+ await this.commandBus.execute(new PurgeExpiredSessionsCommand());
158
+ }
159
+ ```
160
+
161
+ ## Behavior
162
+
163
+ - **`withJobContext(data)`** returns a copy of `data` with `jobContext`: the tenant and
164
+ the correlation id of the configured sources (a new one from the correlation source's
165
+ `create()` when none is active), and the captured principal. It throws `MissingJobContextError` without a
166
+ running `JobContextModule`, a tenant, or a principal, and `TypeError` for a payload that
167
+ is not a plain object.
168
+ - **`@InJobContext()`** validates the payload's context before the method runs. It refuses
169
+ a missing context (`MissingJobContextError`), and a malformed one, an unconfigured
170
+ tenant, a correlation id the correlation source's `accepts` refuses
171
+ (`correlationSource` accepts at most 128 characters of `A-Z a-z 0-9 . _ ~ : / + = @ -`), or a
172
+ principal carrying any field beyond `id`, `type` and `sessionId`, such as grants
173
+ (`InvalidJobContextError`). It then runs the method inside the tenant, the correlation
174
+ id, and `restore(principal, work)`. The method becomes async.
175
+ - **`@AsSystem({ principal, grants })`** runs the method once per configured tenant, one
176
+ after another, each with a new correlation id from `create()` and `restore(principal, work, grants)`. A
177
+ failing tenant does not stop the others; the method then rejects with an
178
+ `AggregateError` of the failures. Return values are discarded.
179
+ - **`JobContextModule.forRoot`** registers the principal port, tenants and sources when the module
180
+ is instantiated and removes them at application shutdown. The decorators wrap methods
181
+ outside dependency injection, so they use the registration of the running application;
182
+ without one they fail closed. Register it once per application.
183
+
184
+ ## Security
185
+
186
+ A payload is data: anyone who can write to the queue can write it. The package therefore
187
+ carries an identity reference only, never grants, and `restore` decides what that
188
+ identity may do now. Re-check a user's session and account in `restore`, so a revoked
189
+ session or a deleted user refuses the job. Grants come only from `@AsSystem`, in code.
190
+ The tenant must be one of the configured tenants.
191
+
192
+ ## API
193
+
194
+ | Export | Kind | Description |
195
+ | --- | --- | --- |
196
+ | `withJobContext(data)` | function | Copies `data` and adds the current `jobContext` |
197
+ | `InJobContext(options?)` | decorator | Runs a job method in its payload's context; `path` defaults to `'data.jobContext'` |
198
+ | `AsSystem(options)` | decorator | Runs system work once per tenant as the declared principal and grants |
199
+ | `JobContextModule.forRoot(options)` | module | Registers `principal` (a class), `tenants`, `sources` and optional `imports` |
200
+ | `ContextSource`, `CorrelationSource`, `JobContextSources` | type | `{ current, run }`; the correlation source adds `create()` and `accepts(id)`; and the `{ tenantId, correlationId }` pair `sources` takes |
201
+ | `IJobPrincipal<TGrant>` | interface | Application port: `capture()` and `restore(principal, work, grants?)` |
202
+ | `PrincipalReference` | type | `{ id, type, sessionId? }` |
203
+ | `JobContext`, `WithJobContext<T>` | type | The carried context, and a payload with it |
204
+ | `MissingJobContextError`, `InvalidJobContextError` | error | Framework-neutral; map them in the consumer if needed |
205
+
206
+ ## License
207
+
208
+ Dual-licensed under **AGPL-3.0-or-later** or a **Commercial License**. See
209
+ [`LICENSE`](https://github.com/aristoteliss/nestjs-pipeline/blob/master/LICENSE) and [`COMMERCIAL_LICENSE.txt`](https://github.com/aristoteliss/nestjs-pipeline/blob/master/COMMERCIAL_LICENSE.txt)
210
+ at the repository root.
@@ -0,0 +1,7 @@
1
+ /** Injection token of the application's `IJobPrincipal`. */
2
+ export declare const JOB_PRINCIPAL: unique symbol;
3
+ /** Injection token of the configured tenant list. */
4
+ export declare const JOB_TENANTS: unique symbol;
5
+ /** Injection token of the tenant and correlation id sources. */
6
+ export declare const JOB_SOURCES: unique symbol;
7
+ //# sourceMappingURL=job-context.constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-context.constants.d.ts","sourceRoot":"","sources":["../../src/constants/job-context.constants.ts"],"names":[],"mappings":"AAEA,4DAA4D;AAC5D,eAAO,MAAM,aAAa,eAA0B,CAAC;AAErD,qDAAqD;AACrD,eAAO,MAAM,WAAW,eAAwB,CAAC;AAEjD,gEAAgE;AAChE,eAAO,MAAM,WAAW,eAAwB,CAAC"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.JOB_SOURCES = exports.JOB_TENANTS = exports.JOB_PRINCIPAL = void 0;
5
+ /** Injection token of the application's `IJobPrincipal`. */
6
+ exports.JOB_PRINCIPAL = Symbol('JOB_PRINCIPAL');
7
+ /** Injection token of the configured tenant list. */
8
+ exports.JOB_TENANTS = Symbol('JOB_TENANTS');
9
+ /** Injection token of the tenant and correlation id sources. */
10
+ exports.JOB_SOURCES = Symbol('JOB_SOURCES');
11
+ //# sourceMappingURL=job-context.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-context.constants.js","sourceRoot":"","sources":["../../src/constants/job-context.constants.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;AAEtE,4DAA4D;AAC/C,QAAA,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;AAErD,qDAAqD;AACxC,QAAA,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AAEjD,gEAAgE;AACnD,QAAA,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { PrincipalReference } from '../interfaces/principal-reference.interface';
2
+ /** Options of {@link AsSystem}. */
3
+ export interface AsSystemOptions<TGrant = unknown> {
4
+ /** The service principal the work acts as. */
5
+ principal: PrincipalReference;
6
+ /** The principal's complete authorization; nothing else grants it anything. */
7
+ grants: readonly TGrant[];
8
+ }
9
+ /**
10
+ * Runs system-started work, such as a cron job, once per configured tenant.
11
+ * Each run has its own tenant, a new correlation id, and the declared service
12
+ * principal and grants, bound through the registered `IJobPrincipal`. Grants
13
+ * come only from this declaration, never from data.
14
+ *
15
+ * Tenants run one after another. A failing tenant does not stop the others;
16
+ * the method then rejects with an `AggregateError` of the failures. Its return
17
+ * values are discarded. Place it under the scheduling decorator.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * @Cron('0 3 * * *')
22
+ * @AsSystem({
23
+ * principal: { id: 'session-cleanup', type: 'service' },
24
+ * grants: [{ action: 'delete', subject: 'Auth' }],
25
+ * })
26
+ * async purgeSessions() {
27
+ * await this.commandBus.execute(new PurgeExpiredSessionsCommand());
28
+ * }
29
+ * ```
30
+ */
31
+ export declare function AsSystem<TGrant>(options: AsSystemOptions<TGrant>): MethodDecorator;
32
+ //# sourceMappingURL=as-system.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"as-system.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/as-system.decorator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAEtF,mCAAmC;AACnC,MAAM,WAAW,eAAe,CAAC,MAAM,GAAG,OAAO;IAC/C,8CAA8C;IAC9C,SAAS,EAAE,kBAAkB,CAAC;IAC9B,+EAA+E;IAC/E,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAC7B,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,GAC/B,eAAe,CA2CjB"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AsSystem = AsSystem;
5
+ const principal_reference_1 = require("../helpers/principal-reference");
6
+ const registration_1 = require("../helpers/registration");
7
+ /**
8
+ * Runs system-started work, such as a cron job, once per configured tenant.
9
+ * Each run has its own tenant, a new correlation id, and the declared service
10
+ * principal and grants, bound through the registered `IJobPrincipal`. Grants
11
+ * come only from this declaration, never from data.
12
+ *
13
+ * Tenants run one after another. A failing tenant does not stop the others;
14
+ * the method then rejects with an `AggregateError` of the failures. Its return
15
+ * values are discarded. Place it under the scheduling decorator.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * @Cron('0 3 * * *')
20
+ * @AsSystem({
21
+ * principal: { id: 'session-cleanup', type: 'service' },
22
+ * grants: [{ action: 'delete', subject: 'Auth' }],
23
+ * })
24
+ * async purgeSessions() {
25
+ * await this.commandBus.execute(new PurgeExpiredSessionsCommand());
26
+ * }
27
+ * ```
28
+ */
29
+ function AsSystem(options) {
30
+ const reference = (0, principal_reference_1.toReference)(options.principal);
31
+ const grants = [...options.grants];
32
+ return (_target, _propertyKey, descriptor) => {
33
+ const original = descriptor.value;
34
+ descriptor.value = async function (...args) {
35
+ const { principal, tenants, sources } = (0, registration_1.activeRegistration)();
36
+ const failures = [];
37
+ const failed = [];
38
+ for (const tenant of tenants) {
39
+ try {
40
+ await sources.tenantId.run(tenant, () => sources.correlationId.run(sources.correlationId.create(), () => principal.restore(reference, async () => original.apply(this, args), grants)));
41
+ }
42
+ catch (error) {
43
+ failures.push(error);
44
+ failed.push(tenant);
45
+ }
46
+ }
47
+ if (failures.length > 0) {
48
+ throw new AggregateError(failures, `System work failed in tenants: ${failed.join(', ')}`);
49
+ }
50
+ };
51
+ Object.defineProperty(descriptor.value, 'name', {
52
+ value: original.name,
53
+ configurable: true,
54
+ });
55
+ return descriptor;
56
+ };
57
+ }
58
+ //# sourceMappingURL=as-system.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"as-system.decorator.js","sourceRoot":"","sources":["../../src/decorators/as-system.decorator.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AAoCtE,4BA6CC;AA/ED,wEAA6D;AAC7D,0DAA6D;AAW7D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,QAAQ,CACtB,OAAgC;IAEhC,MAAM,SAAS,GAAG,IAAA,iCAAW,EAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnC,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,UAA8B,EAAE,EAAE;QAC/D,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAwC,CAAC;QAErE,UAAU,CAAC,KAAK,GAAG,KAAK,WAEtB,GAAG,IAAe;YAElB,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAA,iCAAkB,GAAE,CAAC;YAC7D,MAAM,QAAQ,GAAc,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;YAC5B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,CAAC;oBACH,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,CACtC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAC7D,SAAS,CAAC,OAAO,CACf,SAAS,EACT,KAAK,IAAI,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,EACtC,MAAM,CACP,CACF,CACF,CAAC;gBACJ,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACrB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,MAAM,IAAI,cAAc,CACtB,QAAQ,EACR,kCAAkC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACtD,CAAC;YACJ,CAAC;QACH,CAAC,CAAC;QACF,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE;YAC9C,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,32 @@
1
+ /** Options of {@link InJobContext}. */
2
+ export interface InJobContextOptions {
3
+ /**
4
+ * Dot path to the job context in the method's first argument.
5
+ *
6
+ * @default 'data.jobContext' (a BullMQ `Job`)
7
+ */
8
+ path?: string;
9
+ }
10
+ /**
11
+ * Runs a job-processing method inside the context `withJobContext` stamped on
12
+ * its payload: the tenant, the correlation id, and the principal the registered
13
+ * `IJobPrincipal` re-checks and binds. The method becomes async.
14
+ *
15
+ * It fails closed before the method runs: a payload without a context, with a
16
+ * malformed one, with an unconfigured tenant, or with a principal carrying
17
+ * anything beyond `id`, `type` and `sessionId` is refused, and so is a
18
+ * principal `restore` rejects. Place it under the transport decorator.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * @Processor(WELCOME_EMAIL_QUEUE)
23
+ * export class SendWelcomeEmailProcessor extends WorkerHost {
24
+ * @InJobContext()
25
+ * async process(job: Job<WithJobContext<WelcomeEmail>>) {
26
+ * await this.commandBus.execute(new SendWelcomeEmailCommand(job.data));
27
+ * }
28
+ * }
29
+ * ```
30
+ */
31
+ export declare function InJobContext(options?: InJobContextOptions): MethodDecorator;
32
+ //# sourceMappingURL=in-job-context.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-job-context.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/in-job-context.decorator.ts"],"names":[],"mappings":"AAKA,uCAAuC;AACvC,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAWD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAC1B,OAAO,GAAE,mBAAwB,GAChC,eAAe,CA2BjB"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.InJobContext = InJobContext;
5
+ const parse_job_context_1 = require("../helpers/parse-job-context");
6
+ const registration_1 = require("../helpers/registration");
7
+ function readPath(value, segments) {
8
+ let current = value;
9
+ for (const segment of segments) {
10
+ if (typeof current !== 'object' || current === null)
11
+ return undefined;
12
+ current = current[segment];
13
+ }
14
+ return current;
15
+ }
16
+ /**
17
+ * Runs a job-processing method inside the context `withJobContext` stamped on
18
+ * its payload: the tenant, the correlation id, and the principal the registered
19
+ * `IJobPrincipal` re-checks and binds. The method becomes async.
20
+ *
21
+ * It fails closed before the method runs: a payload without a context, with a
22
+ * malformed one, with an unconfigured tenant, or with a principal carrying
23
+ * anything beyond `id`, `type` and `sessionId` is refused, and so is a
24
+ * principal `restore` rejects. Place it under the transport decorator.
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * @Processor(WELCOME_EMAIL_QUEUE)
29
+ * export class SendWelcomeEmailProcessor extends WorkerHost {
30
+ * @InJobContext()
31
+ * async process(job: Job<WithJobContext<WelcomeEmail>>) {
32
+ * await this.commandBus.execute(new SendWelcomeEmailCommand(job.data));
33
+ * }
34
+ * }
35
+ * ```
36
+ */
37
+ function InJobContext(options = {}) {
38
+ const segments = (options.path ?? 'data.jobContext').split('.');
39
+ return (_target, _propertyKey, descriptor) => {
40
+ const original = descriptor.value;
41
+ descriptor.value = async function (...args) {
42
+ const { principal, tenants, sources } = (0, registration_1.activeRegistration)();
43
+ const context = (0, parse_job_context_1.parseJobContext)(readPath(args[0], segments), tenants, sources.correlationId.accepts);
44
+ return sources.tenantId.run(context.tenantId, () => sources.correlationId.run(context.correlationId, () => principal.restore(context.principal, async () => original.apply(this, args))));
45
+ };
46
+ Object.defineProperty(descriptor.value, 'name', {
47
+ value: original.name,
48
+ configurable: true,
49
+ });
50
+ return descriptor;
51
+ };
52
+ }
53
+ //# sourceMappingURL=in-job-context.decorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-job-context.decorator.js","sourceRoot":"","sources":["../../src/decorators/in-job-context.decorator.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AA6CtE,oCA6BC;AAxED,oEAA+D;AAC/D,0DAA6D;AAY7D,SAAS,QAAQ,CAAC,KAAc,EAAE,QAA2B;IAC3D,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,SAAS,CAAC;QACtE,OAAO,GAAI,OAAmC,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,YAAY,CAC1B,UAA+B,EAAE;IAEjC,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,iBAAiB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEhE,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,UAA8B,EAAE,EAAE;QAC/D,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAwC,CAAC;QAErE,UAAU,CAAC,KAAK,GAAG,KAAK,WAA0B,GAAG,IAAe;YAClE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,IAAA,iCAAkB,GAAE,CAAC;YAC7D,MAAM,OAAO,GAAG,IAAA,mCAAe,EAC7B,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAC3B,OAAO,EACP,OAAO,CAAC,aAAa,CAAC,OAAO,CAC9B,CAAC;YACF,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,EAAE,CACjD,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,EAAE,CACpD,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE,CAC9C,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAC3B,CACF,CACF,CAAC;QACJ,CAAC,CAAC;QACF,MAAM,CAAC,cAAc,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE;YAC9C,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Raised when a job payload's context is malformed, names an unconfigured
3
+ * tenant, or carries fields a principal reference must not have, such as
4
+ * grants. A payload is data written by whoever can write to the queue.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * throw new InvalidJobContextError('tenantId is not a configured tenant');
9
+ * ```
10
+ */
11
+ export declare class InvalidJobContextError extends Error {
12
+ readonly reason: string;
13
+ constructor(reason: string);
14
+ }
15
+ //# sourceMappingURL=invalid-job-context.error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalid-job-context.error.d.ts","sourceRoot":"","sources":["../../src/errors/invalid-job-context.error.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAIpC"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.InvalidJobContextError = void 0;
5
+ /**
6
+ * Raised when a job payload's context is malformed, names an unconfigured
7
+ * tenant, or carries fields a principal reference must not have, such as
8
+ * grants. A payload is data written by whoever can write to the queue.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * throw new InvalidJobContextError('tenantId is not a configured tenant');
13
+ * ```
14
+ */
15
+ class InvalidJobContextError extends Error {
16
+ reason;
17
+ constructor(reason) {
18
+ super(`Invalid job context: ${reason}.`);
19
+ this.reason = reason;
20
+ this.name = InvalidJobContextError.name;
21
+ }
22
+ }
23
+ exports.InvalidJobContextError = InvalidJobContextError;
24
+ //# sourceMappingURL=invalid-job-context.error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invalid-job-context.error.js","sourceRoot":"","sources":["../../src/errors/invalid-job-context.error.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;AAEtE;;;;;;;;;GASG;AACH,MAAa,sBAAuB,SAAQ,KAAK;IAC1B;IAArB,YAAqB,MAAc;QACjC,KAAK,CAAC,wBAAwB,MAAM,GAAG,CAAC,CAAC;QADtB,WAAM,GAAN,MAAM,CAAQ;QAEjC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC;IAC1C,CAAC;CACF;AALD,wDAKC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Raised when a job would run, or be enqueued, without part of its execution
3
+ * context. A job never falls back to a default tenant or an anonymous principal.
4
+ *
5
+ * @example
6
+ * ```ts
7
+ * throw new MissingJobContextError('principal');
8
+ * ```
9
+ */
10
+ export declare class MissingJobContextError extends Error {
11
+ readonly missing: string;
12
+ constructor(missing: string);
13
+ }
14
+ //# sourceMappingURL=missing-job-context.error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-job-context.error.d.ts","sourceRoot":"","sources":["../../src/errors/missing-job-context.error.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM;gBAAf,OAAO,EAAE,MAAM;CAMrC"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.MissingJobContextError = void 0;
5
+ /**
6
+ * Raised when a job would run, or be enqueued, without part of its execution
7
+ * context. A job never falls back to a default tenant or an anonymous principal.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * throw new MissingJobContextError('principal');
12
+ * ```
13
+ */
14
+ class MissingJobContextError extends Error {
15
+ missing;
16
+ constructor(missing) {
17
+ super(`Missing job context: ${missing}. A job never runs without it and never falls back to a default.`);
18
+ this.missing = missing;
19
+ this.name = MissingJobContextError.name;
20
+ }
21
+ }
22
+ exports.MissingJobContextError = MissingJobContextError;
23
+ //# sourceMappingURL=missing-job-context.error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-job-context.error.js","sourceRoot":"","sources":["../../src/errors/missing-job-context.error.ts"],"names":[],"mappings":";AAAA,sEAAsE;;;AAEtE;;;;;;;;GAQG;AACH,MAAa,sBAAuB,SAAQ,KAAK;IAC1B;IAArB,YAAqB,OAAe;QAClC,KAAK,CACH,wBAAwB,OAAO,kEAAkE,CAClG,CAAC;QAHiB,YAAO,GAAP,OAAO,CAAQ;QAIlC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC;IAC1C,CAAC;CACF;AAPD,wDAOC"}
@@ -0,0 +1,20 @@
1
+ import type { JobContext } from '../interfaces/job-context.interface';
2
+ /**
3
+ * Validates a job payload's context before anything runs with it. Every field
4
+ * is checked, unknown fields are refused, the tenant must be configured, and
5
+ * the correlation id must be one `acceptsCorrelationId` accepts.
6
+ *
7
+ * @param value - The payload's `jobContext` value, as read from the queue.
8
+ * @param tenants - The configured tenants.
9
+ * @param acceptsCorrelationId - The correlation source's `accepts`.
10
+ * @returns A context holding only the validated fields.
11
+ * @throws {MissingJobContextError} When `value` is `undefined`.
12
+ * @throws {InvalidJobContextError} For any other value that is not a valid context.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const context = parseJobContext(job.data.jobContext, ['tenant_a'], sources.correlationId.accepts);
17
+ * ```
18
+ */
19
+ export declare function parseJobContext(value: unknown, tenants: readonly string[], acceptsCorrelationId: (id: string) => boolean): JobContext;
20
+ //# sourceMappingURL=parse-job-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-job-context.d.ts","sourceRoot":"","sources":["../../src/helpers/parse-job-context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAyBtE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,oBAAoB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,GAC5C,UAAU,CAmCZ"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /* Copyright (C) 2026-present Aristotelis — see repository license. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.parseJobContext = parseJobContext;
5
+ const invalid_job_context_error_1 = require("../errors/invalid-job-context.error");
6
+ const missing_job_context_error_1 = require("../errors/missing-job-context.error");
7
+ const principal_reference_1 = require("./principal-reference");
8
+ const CONTEXT_FIELDS = new Set(['tenantId', 'correlationId', 'principal']);
9
+ const PRINCIPAL_FIELDS = new Set(['id', 'type', 'sessionId']);
10
+ function isRecord(value) {
11
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
12
+ }
13
+ function isText(value) {
14
+ return typeof value === 'string' && value.trim() !== '';
15
+ }
16
+ function assertFields(value, allowed, name) {
17
+ const extra = Object.keys(value).find((key) => !allowed.has(key));
18
+ if (extra !== undefined) {
19
+ throw new invalid_job_context_error_1.InvalidJobContextError(`${name} carries the field "${extra}"`);
20
+ }
21
+ }
22
+ /**
23
+ * Validates a job payload's context before anything runs with it. Every field
24
+ * is checked, unknown fields are refused, the tenant must be configured, and
25
+ * the correlation id must be one `acceptsCorrelationId` accepts.
26
+ *
27
+ * @param value - The payload's `jobContext` value, as read from the queue.
28
+ * @param tenants - The configured tenants.
29
+ * @param acceptsCorrelationId - The correlation source's `accepts`.
30
+ * @returns A context holding only the validated fields.
31
+ * @throws {MissingJobContextError} When `value` is `undefined`.
32
+ * @throws {InvalidJobContextError} For any other value that is not a valid context.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const context = parseJobContext(job.data.jobContext, ['tenant_a'], sources.correlationId.accepts);
37
+ * ```
38
+ */
39
+ function parseJobContext(value, tenants, acceptsCorrelationId) {
40
+ if (value === undefined) {
41
+ throw new missing_job_context_error_1.MissingJobContextError('the payload has no jobContext');
42
+ }
43
+ if (!isRecord(value)) {
44
+ throw new invalid_job_context_error_1.InvalidJobContextError('jobContext is not an object');
45
+ }
46
+ assertFields(value, CONTEXT_FIELDS, 'jobContext');
47
+ const { tenantId, correlationId, principal } = value;
48
+ if (typeof tenantId !== 'string' || !tenants.includes(tenantId)) {
49
+ throw new invalid_job_context_error_1.InvalidJobContextError('tenantId is not a configured tenant');
50
+ }
51
+ if (typeof correlationId !== 'string' ||
52
+ !acceptsCorrelationId(correlationId)) {
53
+ throw new invalid_job_context_error_1.InvalidJobContextError('correlationId is malformed');
54
+ }
55
+ if (!isRecord(principal)) {
56
+ throw new invalid_job_context_error_1.InvalidJobContextError('principal is not an object');
57
+ }
58
+ assertFields(principal, PRINCIPAL_FIELDS, 'principal');
59
+ const { id, type, sessionId } = principal;
60
+ if (!isText(id) ||
61
+ !isText(type) ||
62
+ (sessionId !== undefined && !isText(sessionId))) {
63
+ throw new invalid_job_context_error_1.InvalidJobContextError('principal is malformed');
64
+ }
65
+ return {
66
+ tenantId,
67
+ correlationId,
68
+ principal: (0, principal_reference_1.toReference)({ id, type, sessionId }),
69
+ };
70
+ }
71
+ //# sourceMappingURL=parse-job-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-job-context.js","sourceRoot":"","sources":["../../src/helpers/parse-job-context.ts"],"names":[],"mappings":";AAAA,sEAAsE;;AA8CtE,0CAuCC;AAnFD,mFAA6E;AAC7E,mFAA6E;AAE7E,+DAAoD;AAEpD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC,CAAC;AAC3E,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;AAE9D,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,MAAM,CAAC,KAAc;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CACnB,KAA8B,EAC9B,OAA4B,EAC5B,IAAY;IAEZ,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAClE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,kDAAsB,CAAC,GAAG,IAAI,uBAAuB,KAAK,GAAG,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,eAAe,CAC7B,KAAc,EACd,OAA0B,EAC1B,oBAA6C;IAE7C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,kDAAsB,CAAC,+BAA+B,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,kDAAsB,CAAC,6BAA6B,CAAC,CAAC;IAClE,CAAC;IACD,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;IAClD,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACrD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,kDAAsB,CAAC,qCAAqC,CAAC,CAAC;IAC1E,CAAC;IACD,IACE,OAAO,aAAa,KAAK,QAAQ;QACjC,CAAC,oBAAoB,CAAC,aAAa,CAAC,EACpC,CAAC;QACD,MAAM,IAAI,kDAAsB,CAAC,4BAA4B,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,kDAAsB,CAAC,4BAA4B,CAAC,CAAC;IACjE,CAAC;IACD,YAAY,CAAC,SAAS,EAAE,gBAAgB,EAAE,WAAW,CAAC,CAAC;IACvD,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC;IAC1C,IACE,CAAC,MAAM,CAAC,EAAE,CAAC;QACX,CAAC,MAAM,CAAC,IAAI,CAAC;QACb,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAC/C,CAAC;QACD,MAAM,IAAI,kDAAsB,CAAC,wBAAwB,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO;QACL,QAAQ;QACR,aAAa;QACb,SAAS,EAAE,IAAA,iCAAW,EAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;KAChD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { PrincipalReference } from '../interfaces/principal-reference.interface';
2
+ /**
3
+ * Copies only the identity fields of `principal`, so grants or session data an
4
+ * application object also holds never reach a payload or a restore call.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * toReference({ id: 'u-1', type: 'user', sid: 's-1', grants: [] }); // { id: 'u-1', type: 'user' }
9
+ * ```
10
+ */
11
+ export declare function toReference(principal: PrincipalReference): PrincipalReference;
12
+ //# sourceMappingURL=principal-reference.d.ts.map