@geekmidas/constructs 0.0.21 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/dist/{AWSLambdaFunction-qWpalqfr.d.mts → AWSLambdaFunction-DCh1tOhB.d.mts} +3 -3
- package/dist/{AWSLambdaSubscriberAdaptor-CWbBNRz3.d.mts → AWSLambdaSubscriberAdaptor-DtNZPMoV.d.mts} +2 -2
- package/dist/{AmazonApiGatewayEndpointAdaptor-BQ0IJdaI.d.mts → AmazonApiGatewayEndpointAdaptor-BaTM2TNu.d.mts} +3 -3
- package/dist/{AmazonApiGatewayEndpointAdaptor-DXssXsJi.cjs → AmazonApiGatewayEndpointAdaptor-CPqlw2Rx.cjs} +3 -3
- package/dist/{AmazonApiGatewayEndpointAdaptor-DXssXsJi.cjs.map → AmazonApiGatewayEndpointAdaptor-CPqlw2Rx.cjs.map} +1 -1
- package/dist/{AmazonApiGatewayEndpointAdaptor-CacGag6F.mjs → AmazonApiGatewayEndpointAdaptor-Cm4iD199.mjs} +3 -3
- package/dist/{AmazonApiGatewayEndpointAdaptor-CacGag6F.mjs.map → AmazonApiGatewayEndpointAdaptor-Cm4iD199.mjs.map} +1 -1
- package/dist/{AmazonApiGatewayEndpointAdaptor-Da9BR5On.d.cts → AmazonApiGatewayEndpointAdaptor-TP_hLNAa.d.cts} +2 -2
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-C4_AZ1ek.d.mts → AmazonApiGatewayV1EndpointAdaptor-B2ZpUFiC.d.mts} +4 -4
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-CSm3NsWz.d.cts → AmazonApiGatewayV1EndpointAdaptor-CConfCqz.d.cts} +3 -3
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-BpnG55R7.mjs → AmazonApiGatewayV1EndpointAdaptor-D38HuQa9.mjs} +2 -2
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-BpnG55R7.mjs.map → AmazonApiGatewayV1EndpointAdaptor-D38HuQa9.mjs.map} +1 -1
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-Df4kszio.cjs → AmazonApiGatewayV1EndpointAdaptor-tjpvLBRb.cjs} +2 -2
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-Df4kszio.cjs.map → AmazonApiGatewayV1EndpointAdaptor-tjpvLBRb.cjs.map} +1 -1
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-DdM8Tr1X.d.mts → AmazonApiGatewayV2EndpointAdaptor-BwMQInBi.d.mts} +4 -4
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-ZORzMEET.mjs → AmazonApiGatewayV2EndpointAdaptor-ByYtiJtN.mjs} +2 -2
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-ZORzMEET.mjs.map → AmazonApiGatewayV2EndpointAdaptor-ByYtiJtN.mjs.map} +1 -1
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-5SIvqPby.cjs → AmazonApiGatewayV2EndpointAdaptor-DcJ_w3ro.cjs} +2 -2
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-5SIvqPby.cjs.map → AmazonApiGatewayV2EndpointAdaptor-DcJ_w3ro.cjs.map} +1 -1
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-6hsBFVLf.d.cts → AmazonApiGatewayV2EndpointAdaptor-DurJvFwa.d.cts} +3 -3
- package/dist/Authorizer-C0ge_tc8.cjs +92 -0
- package/dist/Authorizer-C0ge_tc8.cjs.map +1 -0
- package/dist/Authorizer-CpSUMTIs.d.cts +125 -0
- package/dist/Authorizer-D1w7MpK6.d.mts +125 -0
- package/dist/Authorizer-r9U3y_ms.mjs +68 -0
- package/dist/Authorizer-r9U3y_ms.mjs.map +1 -0
- package/dist/{BaseFunctionBuilder-Ct6zY6Jq.d.mts → BaseFunctionBuilder-Oc2xmxmg.d.mts} +2 -2
- package/dist/{Construct-DDR0295I.d.mts → Construct-DCPATqec.d.mts} +1 -1
- package/dist/Construct.d.mts +1 -1
- package/dist/{Cron-DnMRWPFR.d.mts → Cron-DPEcDCDW.d.mts} +2 -2
- package/dist/{CronBuilder-RLDitFmP.d.mts → CronBuilder-CxKTiepV.d.mts} +4 -4
- package/dist/{Endpoint-D2Imgihs.d.cts → Endpoint-BJPJTGjV.d.cts} +2 -2
- package/dist/{Endpoint-PtQ-wLIS.d.mts → Endpoint-DoY1Owv2.d.mts} +4 -4
- package/dist/{EndpointBuilder-B5QPf5Wd.mjs → EndpointBuilder-69uVrKZL.mjs} +15 -2
- package/dist/EndpointBuilder-69uVrKZL.mjs.map +1 -0
- package/dist/{EndpointBuilder-BPHpUekp.d.mts → EndpointBuilder-BJRkivxQ.d.mts} +6 -5
- package/dist/{EndpointBuilder-DrJbIf3Z.cjs → EndpointBuilder-Bhyft7WY.cjs} +15 -2
- package/dist/EndpointBuilder-Bhyft7WY.cjs.map +1 -0
- package/dist/{EndpointBuilder-TApJQhtG.d.cts → EndpointBuilder-CQ-jOXsD.d.cts} +4 -3
- package/dist/{EndpointFactory-DNwMexc7.mjs → EndpointFactory-ARUlRlyM.mjs} +94 -13
- package/dist/EndpointFactory-ARUlRlyM.mjs.map +1 -0
- package/dist/{EndpointFactory-TJ6gtM0W.d.mts → EndpointFactory-BKEPcQgE.d.mts} +50 -19
- package/dist/{EndpointFactory-CSeDcWYn.cjs → EndpointFactory-BcVbkrxf.cjs} +94 -13
- package/dist/EndpointFactory-BcVbkrxf.cjs.map +1 -0
- package/dist/{EndpointFactory-D94AFjIc.d.cts → EndpointFactory-DgwmAR_8.d.cts} +50 -19
- package/dist/{Function-CD3rXWfa.d.mts → Function-Dthlh2Fb.d.mts} +2 -2
- package/dist/{FunctionBuilder-j2VkwuGf.d.mts → FunctionBuilder-CZFBLfdV.d.mts} +4 -4
- package/dist/{FunctionExecutionWrapper-B0WP-Vec.d.mts → FunctionExecutionWrapper-CfuajSB5.d.mts} +2 -2
- package/dist/{HonoEndpointAdaptor-Bg_vTyA5.mjs → HonoEndpointAdaptor-BmB4Sc7L.mjs} +3 -3
- package/dist/{HonoEndpointAdaptor-Bg_vTyA5.mjs.map → HonoEndpointAdaptor-BmB4Sc7L.mjs.map} +1 -1
- package/dist/{HonoEndpointAdaptor-B_gJPWGD.cjs → HonoEndpointAdaptor-CnqR6PSB.cjs} +3 -3
- package/dist/{HonoEndpointAdaptor-B_gJPWGD.cjs.map → HonoEndpointAdaptor-CnqR6PSB.cjs.map} +1 -1
- package/dist/{HonoEndpointAdaptor-DB_DdiJr.d.cts → HonoEndpointAdaptor-DBjipl6Q.d.mts} +8 -8
- package/dist/{HonoEndpointAdaptor-D99d4b-Z.d.mts → HonoEndpointAdaptor-sSG85VER.d.cts} +6 -6
- package/dist/{Subscriber-itwm7ugy.d.mts → Subscriber-BfxLwZpX.d.mts} +2 -2
- package/dist/{Subscriber-D-FPWts6.cjs → Subscriber-DvOtIyWq.cjs} +1 -1
- package/dist/{Subscriber-D-FPWts6.cjs.map → Subscriber-DvOtIyWq.cjs.map} +1 -1
- package/dist/{Subscriber-CGb8LjZa.mjs → Subscriber-JzcFFi4p.mjs} +1 -1
- package/dist/{Subscriber-CGb8LjZa.mjs.map → Subscriber-JzcFFi4p.mjs.map} +1 -1
- package/dist/{SubscriberBuilder-BfE2cL1q.cjs → SubscriberBuilder-DUuV207i.cjs} +2 -2
- package/dist/{SubscriberBuilder-BfE2cL1q.cjs.map → SubscriberBuilder-DUuV207i.cjs.map} +1 -1
- package/dist/{SubscriberBuilder-9j3JCu8-.d.mts → SubscriberBuilder-lTiTUS1o.d.mts} +2 -2
- package/dist/{SubscriberBuilder-BcAspHv9.mjs → SubscriberBuilder-tm4oVOt3.mjs} +2 -2
- package/dist/{SubscriberBuilder-BcAspHv9.mjs.map → SubscriberBuilder-tm4oVOt3.mjs.map} +1 -1
- package/dist/{TestEndpointAdaptor-Bew9lWsx.cjs → TestEndpointAdaptor-BtLcw4JW.cjs} +3 -3
- package/dist/{TestEndpointAdaptor-Bew9lWsx.cjs.map → TestEndpointAdaptor-BtLcw4JW.cjs.map} +1 -1
- package/dist/{TestEndpointAdaptor-C-c8v7VI.d.mts → TestEndpointAdaptor-CGQVysE0.d.mts} +3 -3
- package/dist/{TestEndpointAdaptor-BYCwwiYk.d.cts → TestEndpointAdaptor-CJO-og9U.d.cts} +2 -2
- package/dist/{TestEndpointAdaptor-JONQJeXc.mjs → TestEndpointAdaptor-o7JbNcL-.mjs} +3 -3
- package/dist/{TestEndpointAdaptor-JONQJeXc.mjs.map → TestEndpointAdaptor-o7JbNcL-.mjs.map} +1 -1
- package/dist/adaptors/aws.cjs +4 -4
- package/dist/adaptors/aws.d.cts +6 -6
- package/dist/adaptors/aws.d.mts +15 -15
- package/dist/adaptors/aws.mjs +4 -4
- package/dist/adaptors/hono.cjs +2 -2
- package/dist/adaptors/hono.d.cts +4 -4
- package/dist/adaptors/hono.d.mts +9 -9
- package/dist/adaptors/hono.mjs +2 -2
- package/dist/adaptors/testing.cjs +2 -2
- package/dist/adaptors/testing.d.cts +4 -4
- package/dist/adaptors/testing.d.mts +9 -9
- package/dist/adaptors/testing.mjs +2 -2
- package/dist/crons/Cron.d.cts +1 -1
- package/dist/crons/Cron.d.mts +6 -6
- package/dist/crons/CronBuilder.d.cts +1 -1
- package/dist/crons/CronBuilder.d.mts +7 -7
- package/dist/crons/index.d.cts +5 -5
- package/dist/crons/index.d.mts +11 -11
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.cjs +2 -2
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.cts +4 -4
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.mts +9 -9
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.mjs +2 -2
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.cjs +3 -3
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.cts +5 -5
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.mts +10 -10
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.mjs +3 -3
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.cjs +3 -3
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.cts +5 -5
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.mts +10 -10
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.mjs +3 -3
- package/dist/endpoints/Authorizer.cjs +5 -14
- package/dist/endpoints/Authorizer.d.cts +2 -2
- package/dist/endpoints/Authorizer.d.mts +2 -2
- package/dist/endpoints/Authorizer.mjs +2 -13
- package/dist/endpoints/Endpoint.d.cts +3 -3
- package/dist/endpoints/Endpoint.d.mts +8 -8
- package/dist/endpoints/EndpointBuilder.cjs +2 -1
- package/dist/endpoints/EndpointBuilder.d.cts +4 -4
- package/dist/endpoints/EndpointBuilder.d.mts +9 -9
- package/dist/endpoints/EndpointBuilder.mjs +2 -1
- package/dist/endpoints/EndpointFactory.cjs +3 -2
- package/dist/endpoints/EndpointFactory.d.cts +5 -5
- package/dist/endpoints/EndpointFactory.d.mts +10 -10
- package/dist/endpoints/EndpointFactory.mjs +3 -2
- package/dist/endpoints/HonoEndpointAdaptor.cjs +2 -2
- package/dist/endpoints/HonoEndpointAdaptor.d.cts +4 -4
- package/dist/endpoints/HonoEndpointAdaptor.d.mts +9 -9
- package/dist/endpoints/HonoEndpointAdaptor.mjs +2 -2
- package/dist/endpoints/TestEndpointAdaptor.cjs +2 -2
- package/dist/endpoints/TestEndpointAdaptor.d.cts +4 -4
- package/dist/endpoints/TestEndpointAdaptor.d.mts +9 -9
- package/dist/endpoints/TestEndpointAdaptor.mjs +2 -2
- package/dist/endpoints/audit.d.cts +3 -3
- package/dist/endpoints/audit.d.mts +8 -8
- package/dist/endpoints/helpers.d.cts +3 -3
- package/dist/endpoints/helpers.d.mts +8 -8
- package/dist/endpoints/index.cjs +3 -2
- package/dist/endpoints/index.cjs.map +1 -1
- package/dist/endpoints/index.d.cts +7 -7
- package/dist/endpoints/index.d.mts +12 -12
- package/dist/endpoints/index.mjs +3 -2
- package/dist/endpoints/index.mjs.map +1 -1
- package/dist/endpoints/processAudits.cjs +1 -1
- package/dist/endpoints/processAudits.d.cts +25 -6
- package/dist/endpoints/processAudits.d.mts +30 -11
- package/dist/endpoints/processAudits.mjs +1 -1
- package/dist/functions/AWSLambdaFunction.d.mts +4 -4
- package/dist/functions/BaseFunctionBuilder.d.mts +2 -2
- package/dist/functions/Function.d.mts +2 -2
- package/dist/functions/FunctionBuilder.d.mts +4 -4
- package/dist/functions/FunctionExecutionWrapper.d.mts +3 -3
- package/dist/functions/TestFunctionAdaptor.d.mts +2 -2
- package/dist/functions/index.d.cts +1 -1
- package/dist/functions/index.d.mts +5 -5
- package/dist/{index-IoTEI3As.d.mts → index-9gJrM7Rw.d.mts} +2 -2
- package/dist/index-Ceo-GuhJ.d.cts +10 -0
- package/dist/index.d.mts +2 -2
- package/dist/{processAudits-BFokHhCO.cjs → processAudits-CzHkPokQ.cjs} +13 -7
- package/dist/processAudits-CzHkPokQ.cjs.map +1 -0
- package/dist/{processAudits-DfcB-X-4.mjs → processAudits-Dj8UGqcW.mjs} +13 -7
- package/dist/processAudits-Dj8UGqcW.mjs.map +1 -0
- package/dist/publisher.d.mts +1 -1
- package/dist/subscribers/AWSLambdaSubscriberAdaptor.d.mts +3 -3
- package/dist/subscribers/Subscriber.cjs +1 -1
- package/dist/subscribers/Subscriber.d.mts +2 -2
- package/dist/subscribers/Subscriber.mjs +1 -1
- package/dist/subscribers/SubscriberBuilder.cjs +2 -2
- package/dist/subscribers/SubscriberBuilder.d.mts +3 -3
- package/dist/subscribers/SubscriberBuilder.mjs +2 -2
- package/dist/subscribers/index.cjs +2 -2
- package/dist/subscribers/index.d.cts +2 -2
- package/dist/subscribers/index.d.mts +5 -5
- package/dist/subscribers/index.mjs +2 -2
- package/dist/{types-DKf0juBf.d.mts → types-Cy1IhmUB.d.mts} +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +6 -6
- package/src/endpoints/AmazonApiGatewayEndpointAdaptor.ts +2 -0
- package/src/endpoints/Authorizer.ts +119 -1
- package/src/endpoints/EndpointBuilder.ts +24 -4
- package/src/endpoints/EndpointFactory.ts +215 -22
- package/src/endpoints/HonoEndpointAdaptor.ts +2 -0
- package/src/endpoints/TestEndpointAdaptor.ts +2 -0
- package/src/endpoints/__tests__/EndpointFactory.authorizers.spec.ts +141 -0
- package/src/endpoints/processAudits.ts +39 -16
- package/dist/Authorizer-BTmly8ps.d.cts +0 -29
- package/dist/Authorizer-pmPvIVgv.d.mts +0 -29
- package/dist/EndpointBuilder-B5QPf5Wd.mjs.map +0 -1
- package/dist/EndpointBuilder-DrJbIf3Z.cjs.map +0 -1
- package/dist/EndpointFactory-CSeDcWYn.cjs.map +0 -1
- package/dist/EndpointFactory-DNwMexc7.mjs.map +0 -1
- package/dist/endpoints/Authorizer.cjs.map +0 -1
- package/dist/endpoints/Authorizer.mjs.map +0 -1
- package/dist/index-C6vCFivC.d.cts +0 -10
- package/dist/processAudits-BFokHhCO.cjs.map +0 -1
- package/dist/processAudits-DfcB-X-4.mjs.map +0 -1
|
@@ -12,7 +12,8 @@ import uniqBy from 'lodash.uniqby';
|
|
|
12
12
|
import { ConstructType } from '../Construct';
|
|
13
13
|
import { BaseFunctionBuilder } from '../functions';
|
|
14
14
|
import type { HttpMethod } from '../types';
|
|
15
|
-
import type { Authorizer } from './Authorizer';
|
|
15
|
+
import type { Authorizer, SecurityScheme } from './Authorizer';
|
|
16
|
+
import { getSecurityScheme } from './Authorizer';
|
|
16
17
|
import { Endpoint, type EndpointSchemas } from './Endpoint';
|
|
17
18
|
import type {
|
|
18
19
|
AuthorizeFn,
|
|
@@ -66,6 +67,7 @@ export class EndpointBuilder<
|
|
|
66
67
|
_authorizerName?: TAuthorizers[number];
|
|
67
68
|
_actorExtractor?: ActorExtractor<TServices, TSession, TLogger>;
|
|
68
69
|
_audits: MappedAudit<TAuditAction, OutSchema>[] = [];
|
|
70
|
+
_customSecuritySchemes: Record<string, SecurityScheme> = {};
|
|
69
71
|
|
|
70
72
|
constructor(
|
|
71
73
|
readonly route: TRoute,
|
|
@@ -616,9 +618,27 @@ export class EndpointBuilder<
|
|
|
616
618
|
TDatabaseServiceName
|
|
617
619
|
> {
|
|
618
620
|
// Find authorizer metadata if name is set
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
621
|
+
// If the authorizer name is set but not in availableAuthorizers, create a simple authorizer object
|
|
622
|
+
let authorizer: Authorizer | undefined;
|
|
623
|
+
if (this._authorizerName) {
|
|
624
|
+
const existingAuthorizer = this._availableAuthorizers.find(
|
|
625
|
+
(a) => a.name === this._authorizerName,
|
|
626
|
+
);
|
|
627
|
+
|
|
628
|
+
if (existingAuthorizer) {
|
|
629
|
+
authorizer = existingAuthorizer;
|
|
630
|
+
} else {
|
|
631
|
+
// Create authorizer with security scheme if available (built-in or custom)
|
|
632
|
+
const securityScheme = getSecurityScheme(
|
|
633
|
+
this._authorizerName as string,
|
|
634
|
+
this._customSecuritySchemes,
|
|
635
|
+
);
|
|
636
|
+
authorizer = {
|
|
637
|
+
name: this._authorizerName as string,
|
|
638
|
+
securityScheme,
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
}
|
|
622
642
|
|
|
623
643
|
return new Endpoint({
|
|
624
644
|
fn,
|
|
@@ -9,7 +9,11 @@ import { ConsoleLogger } from '@geekmidas/logger/console';
|
|
|
9
9
|
import type { Service } from '@geekmidas/services';
|
|
10
10
|
import uniqBy from 'lodash.uniqby';
|
|
11
11
|
import type { HttpMethod } from '../types';
|
|
12
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
Authorizer,
|
|
14
|
+
BuiltInSecuritySchemeId,
|
|
15
|
+
SecurityScheme,
|
|
16
|
+
} from './Authorizer';
|
|
13
17
|
import type { AuthorizeFn, SessionFn } from './Endpoint';
|
|
14
18
|
import { EndpointBuilder } from './EndpointBuilder';
|
|
15
19
|
import type { ActorExtractor } from './audit';
|
|
@@ -32,6 +36,10 @@ export class EndpointFactory<
|
|
|
32
36
|
> = ExtractStorageAuditAction<NonNullable<TAuditStorage>>,
|
|
33
37
|
TDatabase = undefined,
|
|
34
38
|
TDatabaseServiceName extends string = string,
|
|
39
|
+
TSecuritySchemes extends Record<string, SecurityScheme> = Record<
|
|
40
|
+
string,
|
|
41
|
+
SecurityScheme
|
|
42
|
+
>,
|
|
35
43
|
> {
|
|
36
44
|
// @ts-ignore
|
|
37
45
|
private defaultServices: TServices;
|
|
@@ -56,6 +64,7 @@ export class EndpointFactory<
|
|
|
56
64
|
| Service<TDatabaseServiceName, TDatabase>
|
|
57
65
|
| undefined;
|
|
58
66
|
private defaultActorExtractor?: ActorExtractor<TServices, TSession, TLogger>;
|
|
67
|
+
private customSecuritySchemes: TSecuritySchemes = {} as TSecuritySchemes;
|
|
59
68
|
|
|
60
69
|
constructor({
|
|
61
70
|
basePath,
|
|
@@ -70,6 +79,7 @@ export class EndpointFactory<
|
|
|
70
79
|
defaultAuditorStorage,
|
|
71
80
|
defaultDatabaseService,
|
|
72
81
|
defaultActorExtractor,
|
|
82
|
+
customSecuritySchemes = {} as TSecuritySchemes,
|
|
73
83
|
}: EndpointFactoryOptions<
|
|
74
84
|
TServices,
|
|
75
85
|
TBasePath,
|
|
@@ -81,7 +91,8 @@ export class EndpointFactory<
|
|
|
81
91
|
TAuditStorage,
|
|
82
92
|
TAuditStorageServiceName,
|
|
83
93
|
TDatabase,
|
|
84
|
-
TDatabaseServiceName
|
|
94
|
+
TDatabaseServiceName,
|
|
95
|
+
TSecuritySchemes
|
|
85
96
|
> = {}) {
|
|
86
97
|
// Initialize default services
|
|
87
98
|
this.defaultServices = uniqBy(
|
|
@@ -99,6 +110,7 @@ export class EndpointFactory<
|
|
|
99
110
|
this.defaultAuditorStorage = defaultAuditorStorage;
|
|
100
111
|
this.defaultDatabaseService = defaultDatabaseService;
|
|
101
112
|
this.defaultActorExtractor = defaultActorExtractor;
|
|
113
|
+
this.customSecuritySchemes = customSecuritySchemes;
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
static joinPaths<TBasePath extends string, P extends string>(
|
|
@@ -153,7 +165,8 @@ export class EndpointFactory<
|
|
|
153
165
|
TAuditStorageServiceName,
|
|
154
166
|
TAuditAction,
|
|
155
167
|
TDatabase,
|
|
156
|
-
TDatabaseServiceName
|
|
168
|
+
TDatabaseServiceName,
|
|
169
|
+
TSecuritySchemes
|
|
157
170
|
> {
|
|
158
171
|
const authorizerConfigs = authorizers.map((name) => ({
|
|
159
172
|
name,
|
|
@@ -170,7 +183,8 @@ export class EndpointFactory<
|
|
|
170
183
|
TAuditStorageServiceName,
|
|
171
184
|
TAuditAction,
|
|
172
185
|
TDatabase,
|
|
173
|
-
TDatabaseServiceName
|
|
186
|
+
TDatabaseServiceName,
|
|
187
|
+
TSecuritySchemes
|
|
174
188
|
>({
|
|
175
189
|
defaultServices: this.defaultServices,
|
|
176
190
|
basePath: this.basePath,
|
|
@@ -183,6 +197,150 @@ export class EndpointFactory<
|
|
|
183
197
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
184
198
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
185
199
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
200
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Define custom security schemes for this factory.
|
|
206
|
+
* These extend the built-in schemes (jwt, bearer, apiKey, oauth2, oidc).
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```typescript
|
|
210
|
+
* const router = e.securitySchemes({
|
|
211
|
+
* awsIamSigV4: {
|
|
212
|
+
* type: 'apiKey',
|
|
213
|
+
* in: 'header',
|
|
214
|
+
* name: 'Authorization',
|
|
215
|
+
* 'x-amazon-apigateway-authtype': 'awsSigv4',
|
|
216
|
+
* },
|
|
217
|
+
* });
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
securitySchemes<T extends Record<string, SecurityScheme>>(
|
|
221
|
+
schemes: T,
|
|
222
|
+
): EndpointFactory<
|
|
223
|
+
TServices,
|
|
224
|
+
TBasePath,
|
|
225
|
+
TLogger,
|
|
226
|
+
TSession,
|
|
227
|
+
TEventPublisher,
|
|
228
|
+
TEventPublisherServiceName,
|
|
229
|
+
TAuthorizers,
|
|
230
|
+
TAuditStorage,
|
|
231
|
+
TAuditStorageServiceName,
|
|
232
|
+
TAuditAction,
|
|
233
|
+
TDatabase,
|
|
234
|
+
TDatabaseServiceName,
|
|
235
|
+
TSecuritySchemes & T
|
|
236
|
+
> {
|
|
237
|
+
return new EndpointFactory<
|
|
238
|
+
TServices,
|
|
239
|
+
TBasePath,
|
|
240
|
+
TLogger,
|
|
241
|
+
TSession,
|
|
242
|
+
TEventPublisher,
|
|
243
|
+
TEventPublisherServiceName,
|
|
244
|
+
TAuthorizers,
|
|
245
|
+
TAuditStorage,
|
|
246
|
+
TAuditStorageServiceName,
|
|
247
|
+
TAuditAction,
|
|
248
|
+
TDatabase,
|
|
249
|
+
TDatabaseServiceName,
|
|
250
|
+
TSecuritySchemes & T
|
|
251
|
+
>({
|
|
252
|
+
defaultServices: this.defaultServices,
|
|
253
|
+
basePath: this.basePath,
|
|
254
|
+
defaultAuthorizeFn: this.defaultAuthorizeFn,
|
|
255
|
+
defaultLogger: this.defaultLogger,
|
|
256
|
+
defaultSessionExtractor: this.defaultSessionExtractor,
|
|
257
|
+
defaultEventPublisher: this.defaultEventPublisher,
|
|
258
|
+
availableAuthorizers: this.availableAuthorizers,
|
|
259
|
+
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
260
|
+
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
261
|
+
defaultDatabaseService: this.defaultDatabaseService,
|
|
262
|
+
defaultActorExtractor: this.defaultActorExtractor,
|
|
263
|
+
customSecuritySchemes: {
|
|
264
|
+
...this.customSecuritySchemes,
|
|
265
|
+
...schemes,
|
|
266
|
+
} as TSecuritySchemes & T,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Set the default authorizer for all endpoints created from this factory.
|
|
272
|
+
* Individual endpoints can override this by calling `.authorizer()` on the builder.
|
|
273
|
+
* Use `'none'` to explicitly disable authorization for all endpoints.
|
|
274
|
+
*
|
|
275
|
+
* Accepts:
|
|
276
|
+
* - Built-in security scheme names: 'jwt', 'bearer', 'apiKey', 'oauth2', 'oidc'
|
|
277
|
+
* - Custom security scheme names defined via `.securitySchemes()`
|
|
278
|
+
* - 'none' to disable authorization
|
|
279
|
+
*/
|
|
280
|
+
authorizer(
|
|
281
|
+
name:
|
|
282
|
+
| BuiltInSecuritySchemeId
|
|
283
|
+
| keyof TSecuritySchemes
|
|
284
|
+
| TAuthorizers[number]
|
|
285
|
+
| 'none',
|
|
286
|
+
): EndpointFactory<
|
|
287
|
+
TServices,
|
|
288
|
+
TBasePath,
|
|
289
|
+
TLogger,
|
|
290
|
+
TSession,
|
|
291
|
+
TEventPublisher,
|
|
292
|
+
TEventPublisherServiceName,
|
|
293
|
+
TAuthorizers,
|
|
294
|
+
TAuditStorage,
|
|
295
|
+
TAuditStorageServiceName,
|
|
296
|
+
TAuditAction,
|
|
297
|
+
TDatabase,
|
|
298
|
+
TDatabaseServiceName,
|
|
299
|
+
TSecuritySchemes
|
|
300
|
+
> {
|
|
301
|
+
// Validate that the authorizer exists in available authorizers (if authorizers() was called)
|
|
302
|
+
if (name !== 'none' && this.availableAuthorizers.length > 0) {
|
|
303
|
+
const authorizerExists = this.availableAuthorizers.some(
|
|
304
|
+
(a) => a.name === name,
|
|
305
|
+
);
|
|
306
|
+
if (!authorizerExists) {
|
|
307
|
+
const available = this.availableAuthorizers
|
|
308
|
+
.map((a) => a.name)
|
|
309
|
+
.join(', ');
|
|
310
|
+
throw new Error(
|
|
311
|
+
`Authorizer "${name as string}" not found in available authorizers: ${available}`,
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return new EndpointFactory<
|
|
317
|
+
TServices,
|
|
318
|
+
TBasePath,
|
|
319
|
+
TLogger,
|
|
320
|
+
TSession,
|
|
321
|
+
TEventPublisher,
|
|
322
|
+
TEventPublisherServiceName,
|
|
323
|
+
TAuthorizers,
|
|
324
|
+
TAuditStorage,
|
|
325
|
+
TAuditStorageServiceName,
|
|
326
|
+
TAuditAction,
|
|
327
|
+
TDatabase,
|
|
328
|
+
TDatabaseServiceName,
|
|
329
|
+
TSecuritySchemes
|
|
330
|
+
>({
|
|
331
|
+
defaultServices: this.defaultServices,
|
|
332
|
+
basePath: this.basePath,
|
|
333
|
+
defaultAuthorizeFn: this.defaultAuthorizeFn,
|
|
334
|
+
defaultLogger: this.defaultLogger,
|
|
335
|
+
defaultSessionExtractor: this.defaultSessionExtractor,
|
|
336
|
+
defaultEventPublisher: this.defaultEventPublisher,
|
|
337
|
+
availableAuthorizers: this.availableAuthorizers,
|
|
338
|
+
defaultAuthorizerName:
|
|
339
|
+
name === 'none' ? undefined : (name as TAuthorizers[number]),
|
|
340
|
+
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
341
|
+
defaultDatabaseService: this.defaultDatabaseService,
|
|
342
|
+
defaultActorExtractor: this.defaultActorExtractor,
|
|
343
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
186
344
|
});
|
|
187
345
|
}
|
|
188
346
|
|
|
@@ -201,7 +359,8 @@ export class EndpointFactory<
|
|
|
201
359
|
TAuditStorageServiceName,
|
|
202
360
|
TAuditAction,
|
|
203
361
|
TDatabase,
|
|
204
|
-
TDatabaseServiceName
|
|
362
|
+
TDatabaseServiceName,
|
|
363
|
+
TSecuritySchemes
|
|
205
364
|
> {
|
|
206
365
|
const newBasePath = EndpointFactory.joinPaths(path, this.basePath);
|
|
207
366
|
return new EndpointFactory<
|
|
@@ -216,7 +375,8 @@ export class EndpointFactory<
|
|
|
216
375
|
TAuditStorageServiceName,
|
|
217
376
|
TAuditAction,
|
|
218
377
|
TDatabase,
|
|
219
|
-
TDatabaseServiceName
|
|
378
|
+
TDatabaseServiceName,
|
|
379
|
+
TSecuritySchemes
|
|
220
380
|
>({
|
|
221
381
|
defaultServices: this.defaultServices,
|
|
222
382
|
basePath: newBasePath,
|
|
@@ -229,6 +389,7 @@ export class EndpointFactory<
|
|
|
229
389
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
230
390
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
231
391
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
392
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
232
393
|
});
|
|
233
394
|
}
|
|
234
395
|
|
|
@@ -247,7 +408,8 @@ export class EndpointFactory<
|
|
|
247
408
|
TAuditStorageServiceName,
|
|
248
409
|
TAuditAction,
|
|
249
410
|
TDatabase,
|
|
250
|
-
TDatabaseServiceName
|
|
411
|
+
TDatabaseServiceName,
|
|
412
|
+
TSecuritySchemes
|
|
251
413
|
> {
|
|
252
414
|
return new EndpointFactory<
|
|
253
415
|
TServices,
|
|
@@ -261,7 +423,8 @@ export class EndpointFactory<
|
|
|
261
423
|
TAuditStorageServiceName,
|
|
262
424
|
TAuditAction,
|
|
263
425
|
TDatabase,
|
|
264
|
-
TDatabaseServiceName
|
|
426
|
+
TDatabaseServiceName,
|
|
427
|
+
TSecuritySchemes
|
|
265
428
|
>({
|
|
266
429
|
defaultServices: this.defaultServices,
|
|
267
430
|
basePath: this.basePath,
|
|
@@ -274,6 +437,7 @@ export class EndpointFactory<
|
|
|
274
437
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
275
438
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
276
439
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
440
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
277
441
|
});
|
|
278
442
|
}
|
|
279
443
|
|
|
@@ -292,7 +456,8 @@ export class EndpointFactory<
|
|
|
292
456
|
TAuditStorageServiceName,
|
|
293
457
|
TAuditAction,
|
|
294
458
|
TDatabase,
|
|
295
|
-
TDatabaseServiceName
|
|
459
|
+
TDatabaseServiceName,
|
|
460
|
+
TSecuritySchemes
|
|
296
461
|
> {
|
|
297
462
|
return new EndpointFactory<
|
|
298
463
|
[...S, ...TServices],
|
|
@@ -306,7 +471,8 @@ export class EndpointFactory<
|
|
|
306
471
|
TAuditStorageServiceName,
|
|
307
472
|
TAuditAction,
|
|
308
473
|
TDatabase,
|
|
309
|
-
TDatabaseServiceName
|
|
474
|
+
TDatabaseServiceName,
|
|
475
|
+
TSecuritySchemes
|
|
310
476
|
>({
|
|
311
477
|
defaultServices: [...services, ...this.defaultServices],
|
|
312
478
|
basePath: this.basePath,
|
|
@@ -319,6 +485,7 @@ export class EndpointFactory<
|
|
|
319
485
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
320
486
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
321
487
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
488
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
322
489
|
});
|
|
323
490
|
}
|
|
324
491
|
|
|
@@ -336,7 +503,8 @@ export class EndpointFactory<
|
|
|
336
503
|
TAuditStorageServiceName,
|
|
337
504
|
TAuditAction,
|
|
338
505
|
TDatabase,
|
|
339
|
-
TDatabaseServiceName
|
|
506
|
+
TDatabaseServiceName,
|
|
507
|
+
TSecuritySchemes
|
|
340
508
|
> {
|
|
341
509
|
return new EndpointFactory<
|
|
342
510
|
TServices,
|
|
@@ -350,7 +518,8 @@ export class EndpointFactory<
|
|
|
350
518
|
TAuditStorageServiceName,
|
|
351
519
|
TAuditAction,
|
|
352
520
|
TDatabase,
|
|
353
|
-
TDatabaseServiceName
|
|
521
|
+
TDatabaseServiceName,
|
|
522
|
+
TSecuritySchemes
|
|
354
523
|
>({
|
|
355
524
|
defaultServices: this.defaultServices,
|
|
356
525
|
basePath: this.basePath,
|
|
@@ -377,6 +546,7 @@ export class EndpointFactory<
|
|
|
377
546
|
TSession,
|
|
378
547
|
L
|
|
379
548
|
>,
|
|
549
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
380
550
|
});
|
|
381
551
|
}
|
|
382
552
|
|
|
@@ -397,7 +567,8 @@ export class EndpointFactory<
|
|
|
397
567
|
TAuditStorageServiceName,
|
|
398
568
|
TAuditAction,
|
|
399
569
|
TDatabase,
|
|
400
|
-
TDatabaseServiceName
|
|
570
|
+
TDatabaseServiceName,
|
|
571
|
+
TSecuritySchemes
|
|
401
572
|
> {
|
|
402
573
|
return new EndpointFactory<
|
|
403
574
|
TServices,
|
|
@@ -411,7 +582,8 @@ export class EndpointFactory<
|
|
|
411
582
|
TAuditStorageServiceName,
|
|
412
583
|
TAuditAction,
|
|
413
584
|
TDatabase,
|
|
414
|
-
TDatabaseServiceName
|
|
585
|
+
TDatabaseServiceName,
|
|
586
|
+
TSecuritySchemes
|
|
415
587
|
>({
|
|
416
588
|
defaultServices: this.defaultServices,
|
|
417
589
|
basePath: this.basePath,
|
|
@@ -424,6 +596,7 @@ export class EndpointFactory<
|
|
|
424
596
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
425
597
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
426
598
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
599
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
427
600
|
});
|
|
428
601
|
}
|
|
429
602
|
|
|
@@ -441,7 +614,8 @@ export class EndpointFactory<
|
|
|
441
614
|
TAuditStorageServiceName,
|
|
442
615
|
TAuditAction,
|
|
443
616
|
TDatabase,
|
|
444
|
-
TDatabaseServiceName
|
|
617
|
+
TDatabaseServiceName,
|
|
618
|
+
TSecuritySchemes
|
|
445
619
|
> {
|
|
446
620
|
return new EndpointFactory<
|
|
447
621
|
TServices,
|
|
@@ -455,7 +629,8 @@ export class EndpointFactory<
|
|
|
455
629
|
TAuditStorageServiceName,
|
|
456
630
|
TAuditAction,
|
|
457
631
|
TDatabase,
|
|
458
|
-
TDatabaseServiceName
|
|
632
|
+
TDatabaseServiceName,
|
|
633
|
+
TSecuritySchemes
|
|
459
634
|
>({
|
|
460
635
|
defaultServices: this.defaultServices,
|
|
461
636
|
basePath: this.basePath,
|
|
@@ -477,6 +652,7 @@ export class EndpointFactory<
|
|
|
477
652
|
T,
|
|
478
653
|
TLogger
|
|
479
654
|
>,
|
|
655
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
480
656
|
});
|
|
481
657
|
}
|
|
482
658
|
|
|
@@ -498,7 +674,8 @@ export class EndpointFactory<
|
|
|
498
674
|
TAuditStorageServiceName,
|
|
499
675
|
TAuditAction,
|
|
500
676
|
T,
|
|
501
|
-
TName
|
|
677
|
+
TName,
|
|
678
|
+
TSecuritySchemes
|
|
502
679
|
> {
|
|
503
680
|
return new EndpointFactory<
|
|
504
681
|
TServices,
|
|
@@ -512,7 +689,8 @@ export class EndpointFactory<
|
|
|
512
689
|
TAuditStorageServiceName,
|
|
513
690
|
TAuditAction,
|
|
514
691
|
T,
|
|
515
|
-
TName
|
|
692
|
+
TName,
|
|
693
|
+
TSecuritySchemes
|
|
516
694
|
>({
|
|
517
695
|
defaultServices: this.defaultServices,
|
|
518
696
|
basePath: this.basePath,
|
|
@@ -528,6 +706,7 @@ export class EndpointFactory<
|
|
|
528
706
|
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
529
707
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
530
708
|
defaultDatabaseService: service,
|
|
709
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
531
710
|
});
|
|
532
711
|
}
|
|
533
712
|
|
|
@@ -550,7 +729,8 @@ export class EndpointFactory<
|
|
|
550
729
|
TName,
|
|
551
730
|
ExtractStorageAuditAction<T>,
|
|
552
731
|
TDatabase,
|
|
553
|
-
TDatabaseServiceName
|
|
732
|
+
TDatabaseServiceName,
|
|
733
|
+
TSecuritySchemes
|
|
554
734
|
> {
|
|
555
735
|
return new EndpointFactory<
|
|
556
736
|
TServices,
|
|
@@ -564,7 +744,8 @@ export class EndpointFactory<
|
|
|
564
744
|
TName,
|
|
565
745
|
ExtractStorageAuditAction<T>,
|
|
566
746
|
TDatabase,
|
|
567
|
-
TDatabaseServiceName
|
|
747
|
+
TDatabaseServiceName,
|
|
748
|
+
TSecuritySchemes
|
|
568
749
|
>({
|
|
569
750
|
defaultServices: this.defaultServices,
|
|
570
751
|
basePath: this.basePath,
|
|
@@ -582,6 +763,7 @@ export class EndpointFactory<
|
|
|
582
763
|
TSession,
|
|
583
764
|
TLogger
|
|
584
765
|
>,
|
|
766
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
585
767
|
});
|
|
586
768
|
}
|
|
587
769
|
|
|
@@ -603,7 +785,8 @@ export class EndpointFactory<
|
|
|
603
785
|
TAuditStorageServiceName,
|
|
604
786
|
TAuditAction,
|
|
605
787
|
TDatabase,
|
|
606
|
-
TDatabaseServiceName
|
|
788
|
+
TDatabaseServiceName,
|
|
789
|
+
TSecuritySchemes
|
|
607
790
|
> {
|
|
608
791
|
return new EndpointFactory<
|
|
609
792
|
TServices,
|
|
@@ -617,7 +800,8 @@ export class EndpointFactory<
|
|
|
617
800
|
TAuditStorageServiceName,
|
|
618
801
|
TAuditAction,
|
|
619
802
|
TDatabase,
|
|
620
|
-
TDatabaseServiceName
|
|
803
|
+
TDatabaseServiceName,
|
|
804
|
+
TSecuritySchemes
|
|
621
805
|
>({
|
|
622
806
|
defaultServices: this.defaultServices,
|
|
623
807
|
basePath: this.basePath,
|
|
@@ -630,6 +814,7 @@ export class EndpointFactory<
|
|
|
630
814
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
631
815
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
632
816
|
defaultActorExtractor: extractor,
|
|
817
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
633
818
|
});
|
|
634
819
|
}
|
|
635
820
|
|
|
@@ -718,6 +903,9 @@ export class EndpointFactory<
|
|
|
718
903
|
builder._actorExtractor = this.defaultActorExtractor;
|
|
719
904
|
}
|
|
720
905
|
|
|
906
|
+
// Set custom security schemes
|
|
907
|
+
builder._customSecuritySchemes = this.customSecuritySchemes;
|
|
908
|
+
|
|
721
909
|
return builder;
|
|
722
910
|
}
|
|
723
911
|
|
|
@@ -785,6 +973,10 @@ export interface EndpointFactoryOptions<
|
|
|
785
973
|
TAuditStorageServiceName extends string = string,
|
|
786
974
|
TDatabase = undefined,
|
|
787
975
|
TDatabaseServiceName extends string = string,
|
|
976
|
+
TSecuritySchemes extends Record<string, SecurityScheme> = Record<
|
|
977
|
+
string,
|
|
978
|
+
SecurityScheme
|
|
979
|
+
>,
|
|
788
980
|
> {
|
|
789
981
|
defaultServices?: TServices;
|
|
790
982
|
basePath?: TBasePath;
|
|
@@ -798,6 +990,7 @@ export interface EndpointFactoryOptions<
|
|
|
798
990
|
defaultAuditorStorage?: Service<TAuditStorageServiceName, TAuditStorage>;
|
|
799
991
|
defaultDatabaseService?: Service<TDatabaseServiceName, TDatabase>;
|
|
800
992
|
defaultActorExtractor?: ActorExtractor<TServices, TSession, TLogger>;
|
|
993
|
+
customSecuritySchemes?: TSecuritySchemes;
|
|
801
994
|
}
|
|
802
995
|
|
|
803
996
|
export const e = new EndpointFactory();
|
|
@@ -294,3 +294,144 @@ describe('EndpointFactory.authorizers', () => {
|
|
|
294
294
|
expect(endpoint.tags).toEqual(['public', 'contact']);
|
|
295
295
|
});
|
|
296
296
|
});
|
|
297
|
+
|
|
298
|
+
describe('EndpointFactory.authorizer (default)', () => {
|
|
299
|
+
it('should set default authorizer for all endpoints', () => {
|
|
300
|
+
const factory = new EndpointFactory()
|
|
301
|
+
.authorizers(['iam', 'jwt'] as const)
|
|
302
|
+
.authorizer('jwt');
|
|
303
|
+
|
|
304
|
+
const endpoint1 = factory.get('/users').handle(async () => ({ users: [] }));
|
|
305
|
+
const endpoint2 = factory
|
|
306
|
+
.post('/users')
|
|
307
|
+
.body(z.object({ name: z.string() }))
|
|
308
|
+
.handle(async () => ({ id: '1' }));
|
|
309
|
+
|
|
310
|
+
expect(endpoint1.authorizer).toEqual({ name: 'jwt' });
|
|
311
|
+
expect(endpoint2.authorizer).toEqual({ name: 'jwt' });
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('should allow endpoint to override factory default authorizer', () => {
|
|
315
|
+
const factory = new EndpointFactory()
|
|
316
|
+
.authorizers(['iam', 'jwt'] as const)
|
|
317
|
+
.authorizer('jwt');
|
|
318
|
+
|
|
319
|
+
const endpoint = factory
|
|
320
|
+
.get('/admin')
|
|
321
|
+
.authorizer('iam')
|
|
322
|
+
.handle(async () => ({ admin: true }));
|
|
323
|
+
|
|
324
|
+
expect(endpoint.authorizer).toEqual({ name: 'iam' });
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('should allow endpoint to disable authorizer with none', () => {
|
|
328
|
+
const factory = new EndpointFactory()
|
|
329
|
+
.authorizers(['iam', 'jwt'] as const)
|
|
330
|
+
.authorizer('jwt');
|
|
331
|
+
|
|
332
|
+
const endpoint = factory
|
|
333
|
+
.get('/public')
|
|
334
|
+
.authorizer('none')
|
|
335
|
+
.handle(async () => ({ public: true }));
|
|
336
|
+
|
|
337
|
+
expect(endpoint.authorizer).toBeUndefined();
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it('should throw error when setting non-existent default authorizer', () => {
|
|
341
|
+
const factory = new EndpointFactory().authorizers(['iam', 'jwt'] as const);
|
|
342
|
+
|
|
343
|
+
expect(() => {
|
|
344
|
+
// @ts-expect-error - testing invalid authorizer
|
|
345
|
+
factory.authorizer('invalid');
|
|
346
|
+
}).toThrow(
|
|
347
|
+
'Authorizer "invalid" not found in available authorizers: iam, jwt',
|
|
348
|
+
);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
it('should preserve default authorizer when chaining factory methods', () => {
|
|
352
|
+
const factory = new EndpointFactory()
|
|
353
|
+
.authorizers(['iam', 'jwt'] as const)
|
|
354
|
+
.authorizer('jwt')
|
|
355
|
+
.route('/api/v1');
|
|
356
|
+
|
|
357
|
+
const endpoint = factory.get('/users').handle(async () => ({ users: [] }));
|
|
358
|
+
|
|
359
|
+
expect(endpoint.authorizer).toEqual({ name: 'jwt' });
|
|
360
|
+
expect(endpoint.route).toBe('/api/v1/users');
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it('should preserve default authorizer with services', () => {
|
|
364
|
+
const dbService = {
|
|
365
|
+
serviceName: 'database' as const,
|
|
366
|
+
register: async () => ({ query: async () => [] }),
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
const factory = new EndpointFactory()
|
|
370
|
+
.authorizers(['jwt'] as const)
|
|
371
|
+
.authorizer('jwt')
|
|
372
|
+
.services([dbService]);
|
|
373
|
+
|
|
374
|
+
const endpoint = factory.get('/users').handle(async ({ services }) => {
|
|
375
|
+
await services.database.query();
|
|
376
|
+
return { users: [] };
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
expect(endpoint.authorizer).toEqual({ name: 'jwt' });
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it('should allow factory.authorizer("none") to clear default', () => {
|
|
383
|
+
const factory = new EndpointFactory()
|
|
384
|
+
.authorizers(['iam', 'jwt'] as const)
|
|
385
|
+
.authorizer('jwt')
|
|
386
|
+
.authorizer('none');
|
|
387
|
+
|
|
388
|
+
const endpoint = factory.get('/test').handle(async () => ({ test: true }));
|
|
389
|
+
|
|
390
|
+
expect(endpoint.authorizer).toBeUndefined();
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it('should allow setting default authorizer without calling authorizers() first', () => {
|
|
394
|
+
// When no authorizers are defined, validation is skipped
|
|
395
|
+
const factory = new EndpointFactory().authorizer('custom');
|
|
396
|
+
|
|
397
|
+
const endpoint = factory.get('/test').handle(async () => ({ test: true }));
|
|
398
|
+
|
|
399
|
+
expect(endpoint.authorizer).toEqual({ name: 'custom' });
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('should work with nested route factories', () => {
|
|
403
|
+
const rootFactory = new EndpointFactory()
|
|
404
|
+
.authorizers(['iam', 'jwt', 'api-key'] as const)
|
|
405
|
+
.authorizer('jwt');
|
|
406
|
+
|
|
407
|
+
const apiFactory = rootFactory.route('/api');
|
|
408
|
+
const adminFactory = apiFactory.route('/admin');
|
|
409
|
+
|
|
410
|
+
const endpoint = adminFactory
|
|
411
|
+
.delete('/users/:id')
|
|
412
|
+
.params(z.object({ id: z.string() }))
|
|
413
|
+
.handle(async () => ({ deleted: true }));
|
|
414
|
+
|
|
415
|
+
expect(endpoint.route).toBe('/api/admin/users/:id');
|
|
416
|
+
expect(endpoint.authorizer).toEqual({ name: 'jwt' });
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it('should allow sub-factory to override parent default authorizer', () => {
|
|
420
|
+
const rootFactory = new EndpointFactory()
|
|
421
|
+
.authorizers(['iam', 'jwt'] as const)
|
|
422
|
+
.authorizer('jwt');
|
|
423
|
+
|
|
424
|
+
const adminFactory = rootFactory.route('/admin').authorizer('iam');
|
|
425
|
+
|
|
426
|
+
const publicEndpoint = rootFactory
|
|
427
|
+
.get('/public')
|
|
428
|
+
.handle(async () => ({ public: true }));
|
|
429
|
+
|
|
430
|
+
const adminEndpoint = adminFactory
|
|
431
|
+
.get('/dashboard')
|
|
432
|
+
.handle(async () => ({ admin: true }));
|
|
433
|
+
|
|
434
|
+
expect(publicEndpoint.authorizer).toEqual({ name: 'jwt' });
|
|
435
|
+
expect(adminEndpoint.authorizer).toEqual({ name: 'iam' });
|
|
436
|
+
});
|
|
437
|
+
});
|