@geekmidas/constructs 0.0.15 → 0.0.17
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/dist/{Cron-Bi3QOge_.cjs → Cron-3bP5rwXs.cjs} +1 -1
- package/dist/{Cron-Bi3QOge_.cjs.map → Cron-3bP5rwXs.cjs.map} +1 -1
- package/dist/{Cron-Dy_HW2Vv.mjs → Cron-gISh3p1m.mjs} +1 -1
- package/dist/{Cron-Dy_HW2Vv.mjs.map → Cron-gISh3p1m.mjs.map} +1 -1
- package/dist/{CronBuilder-Dv_w7Yri.cjs → CronBuilder-2zUMc0WT.cjs} +2 -2
- package/dist/{CronBuilder-Dv_w7Yri.cjs.map → CronBuilder-2zUMc0WT.cjs.map} +1 -1
- package/dist/{CronBuilder-Bl3A2Zp4.mjs → CronBuilder-BCYftl8v.mjs} +2 -2
- package/dist/{CronBuilder-Bl3A2Zp4.mjs.map → CronBuilder-BCYftl8v.mjs.map} +1 -1
- package/dist/{EndpointBuilder-DLoHiV83.d.mts → EndpointBuilder-D02Qo4Ha.d.mts} +9 -8
- package/dist/{EndpointBuilder-C3cdFvpS.d.cts → EndpointBuilder-DHPOWw0B.d.cts} +9 -8
- package/dist/{EndpointBuilder-I--56szz.mjs → EndpointBuilder-DN0NQp1W.mjs} +2 -1
- package/dist/EndpointBuilder-DN0NQp1W.mjs.map +1 -0
- package/dist/{EndpointBuilder-B8vyK_Fy.cjs → EndpointBuilder-bMiowRHY.cjs} +2 -1
- package/dist/EndpointBuilder-bMiowRHY.cjs.map +1 -0
- package/dist/{EndpointFactory-D_FfajK9.mjs → EndpointFactory-B0ldqkHz.mjs} +42 -11
- package/dist/EndpointFactory-B0ldqkHz.mjs.map +1 -0
- package/dist/{EndpointFactory-D6wQfk6Q.d.cts → EndpointFactory-DFFXRU-l.d.cts} +31 -22
- package/dist/{EndpointFactory-BJ71jEqM.cjs → EndpointFactory-DqvIVjOy.cjs} +42 -11
- package/dist/EndpointFactory-DqvIVjOy.cjs.map +1 -0
- package/dist/{EndpointFactory-2wSubmux.d.mts → EndpointFactory-g84YJjGf.d.mts} +31 -22
- package/dist/{HonoEndpointAdaptor-7hIKI32d.d.mts → HonoEndpointAdaptor-Br1vuQ3A.d.mts} +3 -3
- package/dist/{HonoEndpointAdaptor-C9wC10-w.d.cts → HonoEndpointAdaptor-Dc8XsOxw.d.cts} +3 -3
- package/dist/adaptors/aws.d.cts +1 -1
- package/dist/adaptors/aws.d.mts +1 -1
- package/dist/adaptors/hono.d.cts +2 -2
- package/dist/adaptors/hono.d.mts +2 -2
- package/dist/adaptors/testing.d.cts +1 -1
- package/dist/adaptors/testing.d.mts +1 -1
- package/dist/crons/Cron.cjs +1 -1
- package/dist/crons/Cron.d.cts +1 -1
- package/dist/crons/Cron.d.mts +1 -1
- package/dist/crons/Cron.mjs +1 -1
- package/dist/crons/CronBuilder.cjs +2 -2
- package/dist/crons/CronBuilder.d.cts +1 -1
- package/dist/crons/CronBuilder.d.mts +1 -1
- package/dist/crons/CronBuilder.mjs +2 -2
- package/dist/crons/index.cjs +2 -2
- package/dist/crons/index.d.cts +5 -5
- package/dist/crons/index.d.mts +1 -1
- package/dist/crons/index.mjs +2 -2
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.cts +1 -1
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.mts +1 -1
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.cts +1 -1
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.mts +1 -1
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.cts +1 -1
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.mts +1 -1
- package/dist/endpoints/Endpoint.d.cts +1 -1
- package/dist/endpoints/Endpoint.d.mts +1 -1
- package/dist/endpoints/EndpointBuilder.cjs +1 -1
- package/dist/endpoints/EndpointBuilder.d.cts +2 -2
- package/dist/endpoints/EndpointBuilder.d.mts +2 -2
- package/dist/endpoints/EndpointBuilder.mjs +1 -1
- package/dist/endpoints/EndpointFactory.cjs +2 -2
- package/dist/endpoints/EndpointFactory.d.cts +3 -3
- package/dist/endpoints/EndpointFactory.d.mts +3 -3
- package/dist/endpoints/EndpointFactory.mjs +2 -2
- package/dist/endpoints/HonoEndpointAdaptor.d.cts +2 -2
- package/dist/endpoints/HonoEndpointAdaptor.d.mts +2 -2
- package/dist/endpoints/TestEndpointAdaptor.d.cts +1 -1
- package/dist/endpoints/TestEndpointAdaptor.d.mts +1 -1
- package/dist/endpoints/audit.d.cts +1 -1
- package/dist/endpoints/audit.d.mts +1 -1
- package/dist/endpoints/helpers.d.cts +1 -1
- package/dist/endpoints/helpers.d.mts +1 -1
- package/dist/endpoints/index.cjs +2 -2
- package/dist/endpoints/index.d.cts +5 -5
- package/dist/endpoints/index.d.mts +5 -5
- package/dist/endpoints/index.mjs +2 -2
- package/dist/endpoints/processAudits.d.cts +1 -1
- package/dist/endpoints/processAudits.d.mts +1 -1
- package/dist/functions/index.d.cts +1 -1
- package/dist/functions/index.d.mts +1 -1
- package/dist/index-C1dy81Sw.d.cts +10 -0
- package/dist/{index-Doa8YPmH.d.cts → index-TxufD5Xp.d.mts} +2 -2
- package/dist/subscribers/index.d.cts +2 -2
- package/dist/subscribers/index.d.mts +2 -2
- package/package.json +7 -7
- package/src/endpoints/EndpointBuilder.ts +28 -45
- package/src/endpoints/EndpointFactory.ts +103 -5
- package/src/endpoints/__tests__/EndpointFactory.database-auditor.spec.ts +96 -0
- package/dist/EndpointBuilder-B8vyK_Fy.cjs.map +0 -1
- package/dist/EndpointBuilder-I--56szz.mjs.map +0 -1
- package/dist/EndpointFactory-BJ71jEqM.cjs.map +0 -1
- package/dist/EndpointFactory-D_FfajK9.mjs.map +0 -1
- package/dist/index-DRf5AP3P.d.mts +0 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/constructs",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -66,14 +66,14 @@
|
|
|
66
66
|
"lodash.set": "~4.3.2",
|
|
67
67
|
"lodash.uniqby": "~4.7.0",
|
|
68
68
|
"openapi-types": "~12.1.3",
|
|
69
|
-
"@geekmidas/audit": "0.0.
|
|
70
|
-
"@geekmidas/logger": "0.0.1",
|
|
71
|
-
"@geekmidas/schema": "0.0.2",
|
|
72
|
-
"@geekmidas/services": "0.0.1",
|
|
73
|
-
"@geekmidas/errors": "0.0.1",
|
|
69
|
+
"@geekmidas/audit": "0.0.5",
|
|
74
70
|
"@geekmidas/cache": "0.0.7",
|
|
75
71
|
"@geekmidas/events": "0.0.2",
|
|
76
|
-
"@geekmidas/
|
|
72
|
+
"@geekmidas/logger": "0.0.1",
|
|
73
|
+
"@geekmidas/services": "0.0.1",
|
|
74
|
+
"@geekmidas/rate-limit": "0.1.0",
|
|
75
|
+
"@geekmidas/schema": "0.0.2",
|
|
76
|
+
"@geekmidas/errors": "0.0.1"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@types/lodash.compact": "~3.0.9",
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AuditStorage,
|
|
3
|
+
AuditableAction,
|
|
4
|
+
ExtractStorageAuditAction,
|
|
5
|
+
} from '@geekmidas/audit';
|
|
2
6
|
import type { EventPublisher, MappedEvent } from '@geekmidas/events';
|
|
3
7
|
import type { Logger } from '@geekmidas/logger';
|
|
4
8
|
import type { RateLimitConfig } from '@geekmidas/rate-limit';
|
|
@@ -172,7 +176,10 @@ export class EndpointBuilder<
|
|
|
172
176
|
TEventPublisherServiceName,
|
|
173
177
|
TAuthorizers,
|
|
174
178
|
TAuditStorage,
|
|
175
|
-
TAuditStorageServiceName
|
|
179
|
+
TAuditStorageServiceName,
|
|
180
|
+
TAuditAction,
|
|
181
|
+
TDatabase,
|
|
182
|
+
TDatabaseServiceName
|
|
176
183
|
> {
|
|
177
184
|
this.schemas.body = schema as unknown as T;
|
|
178
185
|
// @ts-ignore
|
|
@@ -193,7 +200,10 @@ export class EndpointBuilder<
|
|
|
193
200
|
TEventPublisherServiceName,
|
|
194
201
|
TAuthorizers,
|
|
195
202
|
TAuditStorage,
|
|
196
|
-
TAuditStorageServiceName
|
|
203
|
+
TAuditStorageServiceName,
|
|
204
|
+
TAuditAction,
|
|
205
|
+
TDatabase,
|
|
206
|
+
TDatabaseServiceName
|
|
197
207
|
> {
|
|
198
208
|
this.schemas.query = schema as unknown as T;
|
|
199
209
|
// @ts-ignore
|
|
@@ -214,7 +224,10 @@ export class EndpointBuilder<
|
|
|
214
224
|
TEventPublisherServiceName,
|
|
215
225
|
TAuthorizers,
|
|
216
226
|
TAuditStorage,
|
|
217
|
-
TAuditStorageServiceName
|
|
227
|
+
TAuditStorageServiceName,
|
|
228
|
+
TAuditAction,
|
|
229
|
+
TDatabase,
|
|
230
|
+
TDatabaseServiceName
|
|
218
231
|
> {
|
|
219
232
|
return this.search(schema);
|
|
220
233
|
}
|
|
@@ -233,7 +246,10 @@ export class EndpointBuilder<
|
|
|
233
246
|
TEventPublisherServiceName,
|
|
234
247
|
TAuthorizers,
|
|
235
248
|
TAuditStorage,
|
|
236
|
-
TAuditStorageServiceName
|
|
249
|
+
TAuditStorageServiceName,
|
|
250
|
+
TAuditAction,
|
|
251
|
+
TDatabase,
|
|
252
|
+
TDatabaseServiceName
|
|
237
253
|
> {
|
|
238
254
|
this.schemas.params = schema as unknown as T;
|
|
239
255
|
// @ts-ignore
|
|
@@ -412,8 +428,9 @@ export class EndpointBuilder<
|
|
|
412
428
|
/**
|
|
413
429
|
* Set the auditor storage service for this endpoint.
|
|
414
430
|
* This enables audit functionality and makes `auditor` available in the handler context.
|
|
431
|
+
* The audit action type is automatically inferred from the storage's generic parameter.
|
|
415
432
|
*/
|
|
416
|
-
auditor<T extends AuditStorage
|
|
433
|
+
auditor<T extends AuditStorage<any>, TName extends string>(
|
|
417
434
|
storage: Service<TName, T>,
|
|
418
435
|
): EndpointBuilder<
|
|
419
436
|
TRoute,
|
|
@@ -428,7 +445,7 @@ export class EndpointBuilder<
|
|
|
428
445
|
TAuthorizers,
|
|
429
446
|
T,
|
|
430
447
|
TName,
|
|
431
|
-
|
|
448
|
+
ExtractStorageAuditAction<T>,
|
|
432
449
|
TDatabase,
|
|
433
450
|
TDatabaseServiceName
|
|
434
451
|
> {
|
|
@@ -450,7 +467,7 @@ export class EndpointBuilder<
|
|
|
450
467
|
TAuthorizers,
|
|
451
468
|
T,
|
|
452
469
|
TName,
|
|
453
|
-
|
|
470
|
+
ExtractStorageAuditAction<T>,
|
|
454
471
|
TDatabase,
|
|
455
472
|
TDatabaseServiceName
|
|
456
473
|
>;
|
|
@@ -500,43 +517,9 @@ export class EndpointBuilder<
|
|
|
500
517
|
* ])
|
|
501
518
|
* ```
|
|
502
519
|
*/
|
|
503
|
-
audit
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
TRoute,
|
|
507
|
-
TMethod,
|
|
508
|
-
TInput,
|
|
509
|
-
TServices,
|
|
510
|
-
TLogger,
|
|
511
|
-
OutSchema,
|
|
512
|
-
TSession,
|
|
513
|
-
TEventPublisher,
|
|
514
|
-
TEventPublisherServiceName,
|
|
515
|
-
TAuthorizers,
|
|
516
|
-
TAuditStorage,
|
|
517
|
-
TAuditStorageServiceName,
|
|
518
|
-
T,
|
|
519
|
-
TDatabase,
|
|
520
|
-
TDatabaseServiceName
|
|
521
|
-
> {
|
|
522
|
-
this._audits = audits as unknown as MappedAudit<TAuditAction, OutSchema>[];
|
|
523
|
-
return this as unknown as EndpointBuilder<
|
|
524
|
-
TRoute,
|
|
525
|
-
TMethod,
|
|
526
|
-
TInput,
|
|
527
|
-
TServices,
|
|
528
|
-
TLogger,
|
|
529
|
-
OutSchema,
|
|
530
|
-
TSession,
|
|
531
|
-
TEventPublisher,
|
|
532
|
-
TEventPublisherServiceName,
|
|
533
|
-
TAuthorizers,
|
|
534
|
-
TAuditStorage,
|
|
535
|
-
TAuditStorageServiceName,
|
|
536
|
-
T,
|
|
537
|
-
TDatabase,
|
|
538
|
-
TDatabaseServiceName
|
|
539
|
-
>;
|
|
520
|
+
audit(audits: MappedAudit<TAuditAction, OutSchema>[]): this {
|
|
521
|
+
this._audits = audits;
|
|
522
|
+
return this;
|
|
540
523
|
}
|
|
541
524
|
|
|
542
525
|
/**
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AuditStorage,
|
|
3
|
+
AuditableAction,
|
|
4
|
+
ExtractStorageAuditAction,
|
|
5
|
+
} from '@geekmidas/audit';
|
|
2
6
|
import type { EventPublisher, MappedEvent } from '@geekmidas/events';
|
|
3
7
|
import type { Logger } from '@geekmidas/logger';
|
|
4
8
|
import { ConsoleLogger } from '@geekmidas/logger/console';
|
|
5
9
|
import type { Service } from '@geekmidas/services';
|
|
6
10
|
import uniqBy from 'lodash.uniqby';
|
|
7
11
|
import type { HttpMethod } from '../types';
|
|
12
|
+
import type { ActorExtractor } from './audit';
|
|
8
13
|
import type { Authorizer } from './Authorizer';
|
|
9
14
|
import type { AuthorizeFn, SessionFn } from './Endpoint';
|
|
10
15
|
import { EndpointBuilder } from './EndpointBuilder';
|
|
@@ -19,8 +24,11 @@ export class EndpointFactory<
|
|
|
19
24
|
TEventPublisher extends EventPublisher<any> | undefined = undefined,
|
|
20
25
|
TEventPublisherServiceName extends string = string,
|
|
21
26
|
TAuthorizers extends readonly string[] = readonly string[],
|
|
22
|
-
TAuditStorage extends AuditStorage | undefined = undefined,
|
|
27
|
+
TAuditStorage extends AuditStorage<any> | undefined = undefined,
|
|
23
28
|
TAuditStorageServiceName extends string = string,
|
|
29
|
+
TAuditAction extends AuditableAction<string, unknown> = ExtractStorageAuditAction<
|
|
30
|
+
NonNullable<TAuditStorage>
|
|
31
|
+
>,
|
|
24
32
|
TDatabase = undefined,
|
|
25
33
|
TDatabaseServiceName extends string = string,
|
|
26
34
|
> {
|
|
@@ -41,6 +49,7 @@ export class EndpointFactory<
|
|
|
41
49
|
private defaultDatabaseService:
|
|
42
50
|
| Service<TDatabaseServiceName, TDatabase>
|
|
43
51
|
| undefined;
|
|
52
|
+
private defaultActorExtractor?: ActorExtractor<TServices, TSession, TLogger>;
|
|
44
53
|
|
|
45
54
|
constructor({
|
|
46
55
|
basePath,
|
|
@@ -54,6 +63,7 @@ export class EndpointFactory<
|
|
|
54
63
|
defaultAuthorizerName,
|
|
55
64
|
defaultAuditorStorage,
|
|
56
65
|
defaultDatabaseService,
|
|
66
|
+
defaultActorExtractor,
|
|
57
67
|
}: EndpointFactoryOptions<
|
|
58
68
|
TServices,
|
|
59
69
|
TBasePath,
|
|
@@ -82,6 +92,7 @@ export class EndpointFactory<
|
|
|
82
92
|
this.defaultAuthorizerName = defaultAuthorizerName;
|
|
83
93
|
this.defaultAuditorStorage = defaultAuditorStorage;
|
|
84
94
|
this.defaultDatabaseService = defaultDatabaseService;
|
|
95
|
+
this.defaultActorExtractor = defaultActorExtractor;
|
|
85
96
|
}
|
|
86
97
|
|
|
87
98
|
static joinPaths<TBasePath extends string, P extends string>(
|
|
@@ -134,6 +145,7 @@ export class EndpointFactory<
|
|
|
134
145
|
T,
|
|
135
146
|
TAuditStorage,
|
|
136
147
|
TAuditStorageServiceName,
|
|
148
|
+
TAuditAction,
|
|
137
149
|
TDatabase,
|
|
138
150
|
TDatabaseServiceName
|
|
139
151
|
> {
|
|
@@ -150,6 +162,7 @@ export class EndpointFactory<
|
|
|
150
162
|
T,
|
|
151
163
|
TAuditStorage,
|
|
152
164
|
TAuditStorageServiceName,
|
|
165
|
+
TAuditAction,
|
|
153
166
|
TDatabase,
|
|
154
167
|
TDatabaseServiceName
|
|
155
168
|
>({
|
|
@@ -163,6 +176,7 @@ export class EndpointFactory<
|
|
|
163
176
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
164
177
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
165
178
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
179
|
+
defaultActorExtractor: this.defaultActorExtractor,
|
|
166
180
|
});
|
|
167
181
|
}
|
|
168
182
|
|
|
@@ -179,6 +193,7 @@ export class EndpointFactory<
|
|
|
179
193
|
TAuthorizers,
|
|
180
194
|
TAuditStorage,
|
|
181
195
|
TAuditStorageServiceName,
|
|
196
|
+
TAuditAction,
|
|
182
197
|
TDatabase,
|
|
183
198
|
TDatabaseServiceName
|
|
184
199
|
> {
|
|
@@ -193,6 +208,7 @@ export class EndpointFactory<
|
|
|
193
208
|
TAuthorizers,
|
|
194
209
|
TAuditStorage,
|
|
195
210
|
TAuditStorageServiceName,
|
|
211
|
+
TAuditAction,
|
|
196
212
|
TDatabase,
|
|
197
213
|
TDatabaseServiceName
|
|
198
214
|
>({
|
|
@@ -206,6 +222,7 @@ export class EndpointFactory<
|
|
|
206
222
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
207
223
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
208
224
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
225
|
+
defaultActorExtractor: this.defaultActorExtractor,
|
|
209
226
|
});
|
|
210
227
|
}
|
|
211
228
|
|
|
@@ -222,6 +239,7 @@ export class EndpointFactory<
|
|
|
222
239
|
TAuthorizers,
|
|
223
240
|
TAuditStorage,
|
|
224
241
|
TAuditStorageServiceName,
|
|
242
|
+
TAuditAction,
|
|
225
243
|
TDatabase,
|
|
226
244
|
TDatabaseServiceName
|
|
227
245
|
> {
|
|
@@ -235,6 +253,7 @@ export class EndpointFactory<
|
|
|
235
253
|
TAuthorizers,
|
|
236
254
|
TAuditStorage,
|
|
237
255
|
TAuditStorageServiceName,
|
|
256
|
+
TAuditAction,
|
|
238
257
|
TDatabase,
|
|
239
258
|
TDatabaseServiceName
|
|
240
259
|
>({
|
|
@@ -248,6 +267,7 @@ export class EndpointFactory<
|
|
|
248
267
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
249
268
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
250
269
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
270
|
+
defaultActorExtractor: this.defaultActorExtractor,
|
|
251
271
|
});
|
|
252
272
|
}
|
|
253
273
|
|
|
@@ -264,6 +284,7 @@ export class EndpointFactory<
|
|
|
264
284
|
TAuthorizers,
|
|
265
285
|
TAuditStorage,
|
|
266
286
|
TAuditStorageServiceName,
|
|
287
|
+
TAuditAction,
|
|
267
288
|
TDatabase,
|
|
268
289
|
TDatabaseServiceName
|
|
269
290
|
> {
|
|
@@ -277,6 +298,7 @@ export class EndpointFactory<
|
|
|
277
298
|
TAuthorizers,
|
|
278
299
|
TAuditStorage,
|
|
279
300
|
TAuditStorageServiceName,
|
|
301
|
+
TAuditAction,
|
|
280
302
|
TDatabase,
|
|
281
303
|
TDatabaseServiceName
|
|
282
304
|
>({
|
|
@@ -290,6 +312,7 @@ export class EndpointFactory<
|
|
|
290
312
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
291
313
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
292
314
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
315
|
+
defaultActorExtractor: this.defaultActorExtractor,
|
|
293
316
|
});
|
|
294
317
|
}
|
|
295
318
|
|
|
@@ -305,6 +328,7 @@ export class EndpointFactory<
|
|
|
305
328
|
TAuthorizers,
|
|
306
329
|
TAuditStorage,
|
|
307
330
|
TAuditStorageServiceName,
|
|
331
|
+
TAuditAction,
|
|
308
332
|
TDatabase,
|
|
309
333
|
TDatabaseServiceName
|
|
310
334
|
> {
|
|
@@ -318,6 +342,7 @@ export class EndpointFactory<
|
|
|
318
342
|
TAuthorizers,
|
|
319
343
|
TAuditStorage,
|
|
320
344
|
TAuditStorageServiceName,
|
|
345
|
+
TAuditAction,
|
|
321
346
|
TDatabase,
|
|
322
347
|
TDatabaseServiceName
|
|
323
348
|
>({
|
|
@@ -340,6 +365,8 @@ export class EndpointFactory<
|
|
|
340
365
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
341
366
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
342
367
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
368
|
+
defaultActorExtractor: this
|
|
369
|
+
.defaultActorExtractor as unknown as ActorExtractor<TServices, TSession, L>,
|
|
343
370
|
});
|
|
344
371
|
}
|
|
345
372
|
|
|
@@ -358,6 +385,7 @@ export class EndpointFactory<
|
|
|
358
385
|
TAuthorizers,
|
|
359
386
|
TAuditStorage,
|
|
360
387
|
TAuditStorageServiceName,
|
|
388
|
+
TAuditAction,
|
|
361
389
|
TDatabase,
|
|
362
390
|
TDatabaseServiceName
|
|
363
391
|
> {
|
|
@@ -371,6 +399,7 @@ export class EndpointFactory<
|
|
|
371
399
|
TAuthorizers,
|
|
372
400
|
TAuditStorage,
|
|
373
401
|
TAuditStorageServiceName,
|
|
402
|
+
TAuditAction,
|
|
374
403
|
TDatabase,
|
|
375
404
|
TDatabaseServiceName
|
|
376
405
|
>({
|
|
@@ -384,6 +413,7 @@ export class EndpointFactory<
|
|
|
384
413
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
385
414
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
386
415
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
416
|
+
defaultActorExtractor: this.defaultActorExtractor,
|
|
387
417
|
});
|
|
388
418
|
}
|
|
389
419
|
|
|
@@ -399,6 +429,7 @@ export class EndpointFactory<
|
|
|
399
429
|
TAuthorizers,
|
|
400
430
|
TAuditStorage,
|
|
401
431
|
TAuditStorageServiceName,
|
|
432
|
+
TAuditAction,
|
|
402
433
|
TDatabase,
|
|
403
434
|
TDatabaseServiceName
|
|
404
435
|
> {
|
|
@@ -412,6 +443,7 @@ export class EndpointFactory<
|
|
|
412
443
|
TAuthorizers,
|
|
413
444
|
TAuditStorage,
|
|
414
445
|
TAuditStorageServiceName,
|
|
446
|
+
TAuditAction,
|
|
415
447
|
TDatabase,
|
|
416
448
|
TDatabaseServiceName
|
|
417
449
|
>({
|
|
@@ -429,6 +461,8 @@ export class EndpointFactory<
|
|
|
429
461
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
430
462
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
431
463
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
464
|
+
defaultActorExtractor: this
|
|
465
|
+
.defaultActorExtractor as unknown as ActorExtractor<TServices, T, TLogger>,
|
|
432
466
|
});
|
|
433
467
|
}
|
|
434
468
|
|
|
@@ -448,6 +482,7 @@ export class EndpointFactory<
|
|
|
448
482
|
TAuthorizers,
|
|
449
483
|
TAuditStorage,
|
|
450
484
|
TAuditStorageServiceName,
|
|
485
|
+
TAuditAction,
|
|
451
486
|
T,
|
|
452
487
|
TName
|
|
453
488
|
> {
|
|
@@ -461,6 +496,7 @@ export class EndpointFactory<
|
|
|
461
496
|
TAuthorizers,
|
|
462
497
|
TAuditStorage,
|
|
463
498
|
TAuditStorageServiceName,
|
|
499
|
+
TAuditAction,
|
|
464
500
|
T,
|
|
465
501
|
TName
|
|
466
502
|
>({
|
|
@@ -480,8 +516,9 @@ export class EndpointFactory<
|
|
|
480
516
|
/**
|
|
481
517
|
* Set the auditor storage service for endpoints created from this factory.
|
|
482
518
|
* This enables audit functionality and makes `auditor` available in handler context.
|
|
519
|
+
* The audit action type is automatically inferred from the storage's generic parameter.
|
|
483
520
|
*/
|
|
484
|
-
auditor<T extends AuditStorage
|
|
521
|
+
auditor<T extends AuditStorage<any>, TName extends string>(
|
|
485
522
|
storage: Service<TName, T>,
|
|
486
523
|
): EndpointFactory<
|
|
487
524
|
TServices,
|
|
@@ -493,6 +530,7 @@ export class EndpointFactory<
|
|
|
493
530
|
TAuthorizers,
|
|
494
531
|
T,
|
|
495
532
|
TName,
|
|
533
|
+
ExtractStorageAuditAction<T>,
|
|
496
534
|
TDatabase,
|
|
497
535
|
TDatabaseServiceName
|
|
498
536
|
> {
|
|
@@ -506,6 +544,7 @@ export class EndpointFactory<
|
|
|
506
544
|
TAuthorizers,
|
|
507
545
|
T,
|
|
508
546
|
TName,
|
|
547
|
+
ExtractStorageAuditAction<T>,
|
|
509
548
|
TDatabase,
|
|
510
549
|
TDatabaseServiceName
|
|
511
550
|
>({
|
|
@@ -519,6 +558,59 @@ export class EndpointFactory<
|
|
|
519
558
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
520
559
|
defaultAuditorStorage: storage,
|
|
521
560
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
561
|
+
defaultActorExtractor: this.defaultActorExtractor as unknown as ActorExtractor<
|
|
562
|
+
TServices,
|
|
563
|
+
TSession,
|
|
564
|
+
TLogger
|
|
565
|
+
>,
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Set the actor extractor function for endpoints created from this factory.
|
|
571
|
+
* The actor is extracted from the request context and attached to all audits.
|
|
572
|
+
*/
|
|
573
|
+
actor(
|
|
574
|
+
extractor: ActorExtractor<TServices, TSession, TLogger>,
|
|
575
|
+
): EndpointFactory<
|
|
576
|
+
TServices,
|
|
577
|
+
TBasePath,
|
|
578
|
+
TLogger,
|
|
579
|
+
TSession,
|
|
580
|
+
TEventPublisher,
|
|
581
|
+
TEventPublisherServiceName,
|
|
582
|
+
TAuthorizers,
|
|
583
|
+
TAuditStorage,
|
|
584
|
+
TAuditStorageServiceName,
|
|
585
|
+
TAuditAction,
|
|
586
|
+
TDatabase,
|
|
587
|
+
TDatabaseServiceName
|
|
588
|
+
> {
|
|
589
|
+
return new EndpointFactory<
|
|
590
|
+
TServices,
|
|
591
|
+
TBasePath,
|
|
592
|
+
TLogger,
|
|
593
|
+
TSession,
|
|
594
|
+
TEventPublisher,
|
|
595
|
+
TEventPublisherServiceName,
|
|
596
|
+
TAuthorizers,
|
|
597
|
+
TAuditStorage,
|
|
598
|
+
TAuditStorageServiceName,
|
|
599
|
+
TAuditAction,
|
|
600
|
+
TDatabase,
|
|
601
|
+
TDatabaseServiceName
|
|
602
|
+
>({
|
|
603
|
+
defaultServices: this.defaultServices,
|
|
604
|
+
basePath: this.basePath,
|
|
605
|
+
defaultAuthorizeFn: this.defaultAuthorizeFn,
|
|
606
|
+
defaultLogger: this.defaultLogger,
|
|
607
|
+
defaultSessionExtractor: this.defaultSessionExtractor,
|
|
608
|
+
defaultEventPublisher: this.defaultEventPublisher,
|
|
609
|
+
availableAuthorizers: this.availableAuthorizers,
|
|
610
|
+
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
611
|
+
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
612
|
+
defaultDatabaseService: this.defaultDatabaseService,
|
|
613
|
+
defaultActorExtractor: extractor,
|
|
522
614
|
});
|
|
523
615
|
}
|
|
524
616
|
|
|
@@ -538,7 +630,7 @@ export class EndpointFactory<
|
|
|
538
630
|
TAuthorizers,
|
|
539
631
|
TAuditStorage,
|
|
540
632
|
TAuditStorageServiceName,
|
|
541
|
-
|
|
633
|
+
TAuditAction,
|
|
542
634
|
TDatabase,
|
|
543
635
|
TDatabaseServiceName
|
|
544
636
|
> {
|
|
@@ -556,7 +648,7 @@ export class EndpointFactory<
|
|
|
556
648
|
TAuthorizers,
|
|
557
649
|
TAuditStorage,
|
|
558
650
|
TAuditStorageServiceName,
|
|
559
|
-
|
|
651
|
+
TAuditAction,
|
|
560
652
|
TDatabase,
|
|
561
653
|
TDatabaseServiceName
|
|
562
654
|
>(fullPath, method);
|
|
@@ -602,6 +694,11 @@ export class EndpointFactory<
|
|
|
602
694
|
builder._setDatabaseService(this.defaultDatabaseService as any);
|
|
603
695
|
}
|
|
604
696
|
|
|
697
|
+
// Set actor extractor if configured
|
|
698
|
+
if (this.defaultActorExtractor) {
|
|
699
|
+
builder._actorExtractor = this.defaultActorExtractor;
|
|
700
|
+
}
|
|
701
|
+
|
|
605
702
|
return builder;
|
|
606
703
|
}
|
|
607
704
|
|
|
@@ -681,6 +778,7 @@ export interface EndpointFactoryOptions<
|
|
|
681
778
|
defaultAuthorizerName?: TAuthorizers[number];
|
|
682
779
|
defaultAuditorStorage?: Service<TAuditStorageServiceName, TAuditStorage>;
|
|
683
780
|
defaultDatabaseService?: Service<TDatabaseServiceName, TDatabase>;
|
|
781
|
+
defaultActorExtractor?: ActorExtractor<TServices, TSession, TLogger>;
|
|
684
782
|
}
|
|
685
783
|
|
|
686
784
|
export const e = new EndpointFactory();
|
|
@@ -351,6 +351,102 @@ describe('EndpointFactory', () => {
|
|
|
351
351
|
});
|
|
352
352
|
});
|
|
353
353
|
|
|
354
|
+
describe('actor', () => {
|
|
355
|
+
it('should create a factory with actor extractor', () => {
|
|
356
|
+
const actorExtractor = () => ({ id: '123', type: 'user' as const });
|
|
357
|
+
const factory = new EndpointFactory();
|
|
358
|
+
const factoryWithActor = factory.actor(actorExtractor);
|
|
359
|
+
|
|
360
|
+
expect(factoryWithActor).toBeInstanceOf(EndpointFactory);
|
|
361
|
+
expect(factoryWithActor).not.toBe(factory);
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
it('should pass actor extractor to created endpoints', () => {
|
|
365
|
+
const actorExtractor = () => ({ id: '123', type: 'user' as const });
|
|
366
|
+
const factory = new EndpointFactory()
|
|
367
|
+
.logger(mockLogger)
|
|
368
|
+
.actor(actorExtractor);
|
|
369
|
+
|
|
370
|
+
const endpoint = factory
|
|
371
|
+
.get('/test')
|
|
372
|
+
.handle(async () => ({ success: true }));
|
|
373
|
+
|
|
374
|
+
expect(endpoint.actorExtractor).toBe(actorExtractor);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
it('should preserve actor extractor through factory chains', () => {
|
|
378
|
+
const actorExtractor = () => ({ id: '123', type: 'user' as const });
|
|
379
|
+
const factory = new EndpointFactory()
|
|
380
|
+
.actor(actorExtractor)
|
|
381
|
+
.logger(mockLogger)
|
|
382
|
+
.route('/api');
|
|
383
|
+
|
|
384
|
+
const endpoint = factory
|
|
385
|
+
.get('/users')
|
|
386
|
+
.handle(async () => ({ users: [] }));
|
|
387
|
+
|
|
388
|
+
expect(endpoint.actorExtractor).toBe(actorExtractor);
|
|
389
|
+
expect(endpoint.route).toBe('/api/users');
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
it('should allow endpoints to override actor extractor', () => {
|
|
393
|
+
const factoryActor = () => ({ id: 'factory', type: 'system' as const });
|
|
394
|
+
const endpointActor = () => ({ id: 'endpoint', type: 'user' as const });
|
|
395
|
+
|
|
396
|
+
const factory = new EndpointFactory()
|
|
397
|
+
.logger(mockLogger)
|
|
398
|
+
.actor(factoryActor);
|
|
399
|
+
|
|
400
|
+
const endpoint = factory
|
|
401
|
+
.get('/test')
|
|
402
|
+
.actor(endpointActor)
|
|
403
|
+
.handle(async () => ({ success: true }));
|
|
404
|
+
|
|
405
|
+
expect(endpoint.actorExtractor).toBe(endpointActor);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('should work with auditor and database', () => {
|
|
409
|
+
const actorExtractor = ({ session }: any) => ({
|
|
410
|
+
id: session.userId,
|
|
411
|
+
type: 'user' as const,
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
const mockAuditStorage: AuditStorage = {
|
|
415
|
+
write: vi.fn().mockResolvedValue(undefined),
|
|
416
|
+
query: vi.fn().mockResolvedValue([]),
|
|
417
|
+
count: vi.fn().mockResolvedValue(0),
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
const AuditStorageService = {
|
|
421
|
+
serviceName: 'auditStorage' as const,
|
|
422
|
+
async register() {
|
|
423
|
+
return mockAuditStorage;
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
const DatabaseService = {
|
|
428
|
+
serviceName: 'database' as const,
|
|
429
|
+
async register() {
|
|
430
|
+
return { query: vi.fn() };
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
const factory = new EndpointFactory()
|
|
435
|
+
.logger(mockLogger)
|
|
436
|
+
.database(DatabaseService)
|
|
437
|
+
.auditor(AuditStorageService)
|
|
438
|
+
.actor(actorExtractor);
|
|
439
|
+
|
|
440
|
+
const endpoint = factory
|
|
441
|
+
.get('/test')
|
|
442
|
+
.handle(async () => ({ success: true }));
|
|
443
|
+
|
|
444
|
+
expect(endpoint.actorExtractor).toBe(actorExtractor);
|
|
445
|
+
expect(endpoint.databaseService).toBe(DatabaseService);
|
|
446
|
+
expect(endpoint.auditorStorageService).toBe(AuditStorageService);
|
|
447
|
+
});
|
|
448
|
+
});
|
|
449
|
+
|
|
354
450
|
describe('constructor options with database and auditor', () => {
|
|
355
451
|
const DatabaseService = {
|
|
356
452
|
serviceName: 'database' as const,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"EndpointBuilder-B8vyK_Fy.cjs","names":["BaseFunctionBuilder","route: TRoute","method: TMethod","ConstructType","publisher: Service<TEventPublisherServiceName, TEventPublisher>","storage: Service<TAuditStorageServiceName, TAuditStorage>","service: Service<TDatabaseServiceName, TDatabase>","description: string","status: SuccessStatus","event: TEvent","tags: string[]","memorySize: number","publisher: Service<TName, T>","schema: T","config: RateLimitConfig","name: TAuthorizers[number] | 'none'","services: T","logger: T","storage: Service<TName, T>","extractor: ActorExtractor<TServices, TSession, TLogger>","audits: MappedAudit<T, OutSchema>[]","service: Service<TName, T>","_schema: any","fn: EndpointHandler<\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TDatabase,\n TAuditStorage,\n TAuditAction\n >","Endpoint"],"sources":["../src/endpoints/EndpointBuilder.ts"],"sourcesContent":["import type { AuditStorage, AuditableAction } from '@geekmidas/audit';\nimport type { EventPublisher, MappedEvent } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { RateLimitConfig } from '@geekmidas/rate-limit';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport uniqBy from 'lodash.uniqby';\nimport { ConstructType } from '../Construct';\nimport { BaseFunctionBuilder } from '../functions';\nimport type { HttpMethod } from '../types';\nimport type { Authorizer } from './Authorizer';\nimport { Endpoint, type EndpointSchemas } from './Endpoint';\nimport type {\n AuthorizeFn,\n EndpointHandler,\n SessionFn,\n SuccessStatus,\n} from './Endpoint';\nimport type { ActorExtractor, MappedAudit } from './audit';\n\nexport class EndpointBuilder<\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n OutSchema extends StandardSchemaV1 | undefined = undefined,\n TSession = unknown,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuthorizers extends readonly string[] = readonly string[],\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n TDatabase = undefined,\n TDatabaseServiceName extends string = string,\n> extends BaseFunctionBuilder<\n TInput,\n OutSchema,\n TServices,\n TLogger,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TDatabase,\n TDatabaseServiceName\n> {\n protected schemas: TInput = {} as TInput;\n protected _description?: string;\n protected _status?: SuccessStatus;\n protected _tags?: string[];\n protected _memorySize?: number;\n _getSession: SessionFn<TServices, TLogger, TSession> = () => ({}) as TSession;\n _authorize: AuthorizeFn<TServices, TLogger, TSession> = () => true;\n _rateLimit?: RateLimitConfig;\n _availableAuthorizers: Authorizer[] = [];\n _authorizerName?: TAuthorizers[number];\n _actorExtractor?: ActorExtractor<TServices, TSession, TLogger>;\n _audits: MappedAudit<TAuditAction, OutSchema>[] = [];\n\n constructor(\n readonly route: TRoute,\n readonly method: TMethod,\n ) {\n super(ConstructType.Endpoint);\n }\n\n // Internal setter for EndpointFactory to set default publisher\n _setPublisher(\n publisher: Service<TEventPublisherServiceName, TEventPublisher>,\n ) {\n this._publisher = publisher;\n }\n\n // Internal setter for EndpointFactory to set default auditor storage\n _setAuditorStorage(\n storage: Service<TAuditStorageServiceName, TAuditStorage>,\n ) {\n this._auditorStorage = storage;\n }\n\n // Internal setter for EndpointFactory to set default database service\n _setDatabaseService(service: Service<TDatabaseServiceName, TDatabase>) {\n this._databaseService = service;\n }\n\n description(description: string): this {\n this._description = description;\n return this;\n }\n\n status(status: SuccessStatus): this {\n this._status = status;\n return this;\n }\n\n event<TEvent extends MappedEvent<TEventPublisher, OutSchema>>(\n event: TEvent,\n ): this {\n this._events.push(event);\n return this;\n }\n\n tags(tags: string[]): this {\n this._tags = tags;\n return this;\n }\n\n memorySize(memorySize: number): this {\n this._memorySize = memorySize;\n return this;\n }\n\n publisher<T extends EventPublisher<any>, TName extends string>(\n publisher: Service<TName, T>,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n T,\n TName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n > {\n this._publisher = publisher as unknown as Service<\n TEventPublisherServiceName,\n TEventPublisher\n >;\n\n return this as unknown as EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n T,\n TName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n >;\n }\n\n body<T extends StandardSchemaV1>(\n schema: T,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n Omit<TInput, 'body'> & { body: T },\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName\n > {\n this.schemas.body = schema as unknown as T;\n // @ts-ignore\n return this;\n }\n\n search<T extends StandardSchemaV1>(\n schema: T,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n Omit<TInput, 'query'> & { query: T },\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName\n > {\n this.schemas.query = schema as unknown as T;\n // @ts-ignore\n return this;\n }\n\n query<T extends StandardSchemaV1>(\n schema: T,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n Omit<TInput, 'query'> & { query: T },\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName\n > {\n return this.search(schema);\n }\n\n params<T extends StandardSchemaV1>(\n schema: T,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n Omit<TInput, 'params'> & { params: T },\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName\n > {\n this.schemas.params = schema as unknown as T;\n // @ts-ignore\n return this;\n }\n\n rateLimit(config: RateLimitConfig): this {\n this._rateLimit = config;\n return this;\n }\n\n authorizer(\n name: TAuthorizers[number] | 'none',\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n > {\n // Special case: 'none' explicitly marks endpoint as having no authorizer\n if (name === 'none') {\n this._authorizerName = undefined;\n return this;\n }\n\n // Validate that the authorizer exists in available authorizers\n const authorizerExists = this._availableAuthorizers.some(\n (a) => a.name === name,\n );\n if (!authorizerExists && this._availableAuthorizers.length > 0) {\n const available = this._availableAuthorizers\n .map((a) => a.name)\n .join(', ');\n throw new Error(\n `Authorizer \"${name as string}\" not found in available authorizers: ${available}`,\n );\n }\n this._authorizerName = name;\n return this;\n }\n\n services<T extends Service[]>(\n services: T,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n [...TServices, ...T],\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n > {\n this._services = uniqBy(\n [...this._services, ...services],\n (s) => s.serviceName,\n ) as TServices;\n\n return this as unknown as EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n [...TServices, ...T],\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n >;\n }\n\n logger<T extends Logger>(\n logger: T,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n T,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n > {\n this._logger = logger as unknown as TLogger;\n\n return this as unknown as EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n T,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n >;\n }\n\n output<T extends StandardSchemaV1>(\n schema: T,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n T,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n > {\n this.outputSchema = schema as unknown as OutSchema;\n\n return this as unknown as EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n T,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n >;\n }\n\n /**\n * Set the auditor storage service for this endpoint.\n * This enables audit functionality and makes `auditor` available in the handler context.\n */\n auditor<T extends AuditStorage, TName extends string>(\n storage: Service<TName, T>,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n T,\n TName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n > {\n this._auditorStorage = storage as unknown as Service<\n TAuditStorageServiceName,\n TAuditStorage\n >;\n\n return this as unknown as EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n T,\n TName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n >;\n }\n\n /**\n * Set the actor extractor function for audit records.\n * The actor is extracted from the request context and attached to all audits.\n */\n actor(\n extractor: ActorExtractor<TServices, TSession, TLogger>,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n > {\n this._actorExtractor = extractor;\n return this;\n }\n\n /**\n * Add declarative audit definitions that are processed after the handler executes.\n * Similar to `.event()` for events, but for audits.\n *\n * @example\n * ```typescript\n * .audit<AppAuditAction>([\n * {\n * type: 'user.created',\n * payload: (response) => ({ userId: response.id, email: response.email }),\n * when: (response) => response.active,\n * entityId: (response) => response.id,\n * table: 'users',\n * },\n * ])\n * ```\n */\n audit<T extends AuditableAction<string, unknown>>(\n audits: MappedAudit<T, OutSchema>[],\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n T,\n TDatabase,\n TDatabaseServiceName\n > {\n this._audits = audits as unknown as MappedAudit<TAuditAction, OutSchema>[];\n return this as unknown as EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n T,\n TDatabase,\n TDatabaseServiceName\n >;\n }\n\n /**\n * Set the database service for this endpoint.\n * The database will be available in the handler context as `db`.\n * When audit storage is configured and uses the same database,\n * `db` will automatically be the transaction for ACID compliance.\n *\n * @example\n * ```typescript\n * .database(databaseService)\n * .handle(async ({ db }) => {\n * // db is the raw database or transaction (when auditor uses same db)\n * return await db.selectFrom('users').selectAll().execute();\n * })\n * ```\n */\n database<T, TName extends string>(\n service: Service<TName, T>,\n ): EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n T,\n TName\n > {\n this._databaseService = service as unknown as Service<\n TDatabaseServiceName,\n TDatabase\n >;\n\n return this as unknown as EndpointBuilder<\n TRoute,\n TMethod,\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuthorizers,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n T,\n TName\n >;\n }\n\n // EndpointBuilder doesn't have a generic input method - it uses body, query, params instead\n input(_schema: any): any {\n throw new Error(\n 'EndpointBuilder does not support generic input. Use body(), query(), or params() instead.',\n );\n }\n\n handle(\n fn: EndpointHandler<\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TDatabase,\n TAuditStorage,\n TAuditAction\n >,\n ): Endpoint<\n TRoute,\n TMethod,\n TInput,\n OutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n > {\n // Find authorizer metadata if name is set\n const authorizer = this._authorizerName\n ? this._availableAuthorizers.find((a) => a.name === this._authorizerName)\n : undefined;\n\n return new Endpoint({\n fn,\n method: this.method,\n route: this.route,\n description: this._description,\n tags: this._tags,\n input: this.schemas,\n output: this.outputSchema,\n services: this._services,\n logger: this._logger,\n timeout: this._timeout,\n memorySize: this._memorySize,\n authorize: this._authorize,\n status: this._status,\n getSession: this._getSession,\n rateLimit: this._rateLimit,\n publisherService: this._publisher,\n events: this._events,\n authorizer,\n auditorStorageService: this._auditorStorage,\n actorExtractor: this._actorExtractor,\n audits: this._audits,\n databaseService: this._databaseService,\n });\n }\n}\n"],"mappings":"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"}
|