Skip to content

Commit d92ef21

Browse files
committed
More lax types
1 parent 9944ab5 commit d92ef21

File tree

3 files changed

+34
-30
lines changed

3 files changed

+34
-30
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "openapi-backend",
33
"description": "Build, Validate, Route, Authenticate and Mock using OpenAPI definitions. Framework-agnostic",
4-
"version": "5.10.6",
4+
"version": "5.11.0",
55
"author": "Viljami Kuosmanen <[email protected]>",
66
"funding": "https://github.com/sponsors/anttiviljami",
77
"license": "MIT",

src/backend.ts

+30-25
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ export type Handler<
6262
D extends Document = Document,
6363
> = (context: Context<RequestBody, Params, Query, Headers, Cookies, D>, ...args: any[]) => any | Promise<any>;
6464

65+
/**
66+
* Map of operation handlers
67+
*/
68+
export type HandlerMap = { [operationId: string]: Handler | undefined };
69+
6570
export type BoolPredicate = (context: Context, ...args: any[]) => boolean;
6671

6772
/**
@@ -90,15 +95,13 @@ export interface Options<D extends Document = Document> {
9095
validate?: boolean | BoolPredicate;
9196
ajvOpts?: AjvOpts;
9297
customizeAjv?: AjvCustomizer;
93-
handlers?: {
98+
handlers?: HandlerMap & {
9499
notFound?: Handler;
95100
notImplemented?: Handler;
96101
validationFail?: Handler;
97-
[handler: string]: Handler | undefined;
98-
};
99-
securityHandlers?: {
100-
[handler: string]: Handler | undefined;
101102
};
103+
securityHandlers?: HandlerMap;
104+
ignoreTrailingSlashes?: boolean;
102105
}
103106

104107
/**
@@ -123,7 +126,7 @@ export class OpenAPIBackend<D extends Document = Document> {
123126
public ajvOpts: AjvOpts;
124127
public customizeAjv: AjvCustomizer | undefined;
125128

126-
public handlers: { [operationId: string]: Handler };
129+
public handlers: HandlerMap;
127130
public allowedHandlers = [
128131
'404',
129132
'notFound',
@@ -137,7 +140,7 @@ export class OpenAPIBackend<D extends Document = Document> {
137140
'postResponseHandler',
138141
];
139142

140-
public securityHandlers: { [name: string]: Handler };
143+
public securityHandlers: HandlerMap;
141144

142145
public router: OpenAPIRouter<D>;
143146
public validator: OpenAPIValidator<D>;
@@ -157,26 +160,25 @@ export class OpenAPIBackend<D extends Document = Document> {
157160
* @memberof OpenAPIBackend
158161
*/
159162
constructor(opts: Options<D>) {
160-
const optsWithDefaults = {
163+
const optsWithDefaults: Options<D> = {
161164
apiRoot: '/',
162165
validate: true,
163166
strict: false,
164167
quick: false,
165168
ignoreTrailingSlashes: true,
166-
ajvOpts: {},
167-
handlers: {},
168-
securityHandlers: {},
169+
handlers: {} as HandlerMap,
170+
securityHandlers: {} as HandlerMap,
169171
...opts,
170172
};
171-
this.apiRoot = optsWithDefaults.apiRoot;
173+
this.apiRoot = optsWithDefaults.apiRoot ?? '/';
172174
this.inputDocument = optsWithDefaults.definition;
173-
this.strict = optsWithDefaults.strict;
174-
this.quick = optsWithDefaults.quick;
175-
this.validate = optsWithDefaults.validate;
176-
this.ignoreTrailingSlashes = optsWithDefaults.ignoreTrailingSlashes;
177-
this.handlers = { ...optsWithDefaults.handlers }; // Copy to avoid mutating passed object
175+
this.strict = !!optsWithDefaults.strict;
176+
this.quick = !!optsWithDefaults.quick;
177+
this.validate = !!optsWithDefaults.validate;
178+
this.ignoreTrailingSlashes = !!optsWithDefaults.ignoreTrailingSlashes;
179+
this.handlers = { ...optsWithDefaults.handlers }; // Copy to avoid mutating passed object
178180
this.securityHandlers = { ...optsWithDefaults.securityHandlers }; // Copy to avoid mutating passed object
179-
this.ajvOpts = optsWithDefaults.ajvOpts;
181+
this.ajvOpts = optsWithDefaults.ajvOpts ?? {};
180182
this.customizeAjv = optsWithDefaults.customizeAjv;
181183
}
182184

@@ -257,7 +259,9 @@ export class OpenAPIBackend<D extends Document = Document> {
257259
// register all security handlers
258260
if (this.securityHandlers) {
259261
for (const [name, handler] of Object.entries(this.securityHandlers)) {
260-
this.registerSecurityHandler(name, handler);
262+
if (handler) {
263+
this.registerSecurityHandler(name, handler);
264+
}
261265
}
262266
}
263267

@@ -331,9 +335,10 @@ export class OpenAPIBackend<D extends Document = Document> {
331335
securitySchemes.map(async (name) => {
332336
securityHandlerResults[name] = undefined;
333337
if (this.securityHandlers[name]) {
338+
const securityHandler = this.securityHandlers[name];
334339
// return a promise that will set the security handler result
335340
return await Promise.resolve()
336-
.then(() => this.securityHandlers[name](context as Context<D>, ...handlerArgs))
341+
.then(() => securityHandler(context as Context<D>, ...handlerArgs))
337342
.then((result: unknown) => {
338343
securityHandlerResults[name] = result;
339344
})
@@ -389,7 +394,7 @@ export class OpenAPIBackend<D extends Document = Document> {
389394

390395
// call unauthorizedHandler handler if auth fails
391396
if (!authorized && securityRequirements.length > 0) {
392-
const unauthorizedHandler: Handler = this.handlers['unauthorizedHandler'];
397+
const unauthorizedHandler = this.handlers['unauthorizedHandler'];
393398
if (unauthorizedHandler) {
394399
return unauthorizedHandler(context as Context<D>, ...handlerArgs);
395400
}
@@ -402,7 +407,7 @@ export class OpenAPIBackend<D extends Document = Document> {
402407
: Boolean(this.validate);
403408

404409
// validate request
405-
const validationFailHandler: Handler = this.handlers['validationFail'];
410+
const validationFailHandler = this.handlers['validationFail'];
406411
if (validate) {
407412
context.validation = this.validator.validateRequest(req, context.operation);
408413
if (context.validation.errors) {
@@ -415,7 +420,7 @@ export class OpenAPIBackend<D extends Document = Document> {
415420
}
416421

417422
// get operation handler
418-
const routeHandler: Handler = this.handlers[operationId];
423+
const routeHandler = this.handlers[operationId];
419424
if (!routeHandler) {
420425
// 501 not implemented
421426
const notImplementedHandler = this.handlers['501'] || this.handlers['notImplemented'];
@@ -430,7 +435,7 @@ export class OpenAPIBackend<D extends Document = Document> {
430435
}).bind(this)();
431436

432437
// post response handler
433-
const postResponseHandler: Handler = this.handlers['postResponseHandler'];
438+
const postResponseHandler = this.handlers['postResponseHandler'];
434439
if (postResponseHandler) {
435440
// pass response to postResponseHandler
436441
context.response = response;
@@ -478,7 +483,7 @@ export class OpenAPIBackend<D extends Document = Document> {
478483
* @param {{ [operationId: string]: Handler }} handlers
479484
* @memberof OpenAPIBackend
480485
*/
481-
public register(handlers: { [operationId: string]: Handler }): void;
486+
public register<Handlers extends HandlerMap = HandlerMap>(handlers: Handlers): void;
482487

483488
/**
484489
* Registers a handler for an operation

src/router.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ export type Operation<D extends Document = Document> = PickVersionElement<
3030
method: string;
3131
};
3232

33-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
33+
/* eslint-disable @typescript-eslint/no-explicit-any */
3434
export type AnyRequestBody = any;
35+
export type UnknownParams = any;
36+
/* eslint-enable @typescript-eslint/no-explicit-any */
3537

3638
export interface Request {
3739
method: string;
@@ -47,9 +49,6 @@ export interface Request {
4749
body?: AnyRequestBody;
4850
}
4951

50-
export type UnknownParams = {
51-
[key: string]: string | string[];
52-
};
5352

5453
export interface ParsedRequest<
5554
RequestBody = AnyRequestBody,

0 commit comments

Comments
 (0)