diff --git a/.changeset/nice-walls-train.md b/.changeset/nice-walls-train.md new file mode 100644 index 0000000..d525475 --- /dev/null +++ b/.changeset/nice-walls-train.md @@ -0,0 +1,5 @@ +--- +"koa-oas3": minor +--- + +update validatePaths type to accept string array or regex array diff --git a/__tests__/index.spec.ts b/__tests__/index.spec.ts index 1cafd8c..9c27aa3 100644 --- a/__tests__/index.spec.ts +++ b/__tests__/index.spec.ts @@ -424,3 +424,67 @@ describe('Koa Oas3 with ChowOptions', () => { }); }) + +describe('Pass Regex Array as a validatePaths option', () => { + let mw: koa.Middleware; + const pathParam = 345; + + beforeEach(async () => { + mw = await oas({ + file: path.resolve('./__tests__/fixtures/pet-store.json'), + endpoint: '/openapi', + uiEndpoint: '/openapi.html', + validatePaths: [new RegExp(`pets(?!/${pathParam})`)], + validationOptions: { requestBodyAjvOptions: { allErrors: true } } as ChowOptions + }); + }) + + test('should NOT validate paths specified that do not validate against the RegExp pattern', async () => { + const ctx = createContext({ + url: `/pets/${pathParam}`, + headers: { + 'accept': 'application/json' + }, + method: 'GET' + }); + + mw = await oas({ + file: path.resolve('./__tests__/fixtures/pet-store.json'), + endpoint: '/openapi', + uiEndpoint: '/openapi.html', + validatePaths: [new RegExp(`pets(?!/${pathParam})`)], + validationOptions: { requestBodyAjvOptions: { allErrors: true } } as ChowOptions + }); + + const next = jest.fn(); + await mw(ctx, next); + + expect(next).toHaveBeenCalledTimes(1); + expect(next).toHaveBeenCalledWith(); + }) + + test('should validate paths specified in RegExp pattern', async () => { + const ctx = createContext({ + url: `/pets/`, + headers: { + 'accept': 'application/json' + }, + method: 'GET' + }); + + mw = await oas({ + file: path.resolve('./__tests__/fixtures/pet-store.json'), + endpoint: '/openapi', + uiEndpoint: '/openapi.html', + validatePaths: [new RegExp(`pets(?!/${pathParam})`)], + validationOptions: { requestBodyAjvOptions: { allErrors: true } } as ChowOptions + }); + + const next = jest.fn(); + await mw(ctx, next); + + expect(next).toHaveBeenCalledTimes(1); + expect(next).not.toHaveBeenCalledWith(); + }) + +}) diff --git a/src/config.ts b/src/config.ts index 984b7e4..deb2bee 100644 --- a/src/config.ts +++ b/src/config.ts @@ -34,7 +34,7 @@ export interface Config { * Whitelist paths for request validation * default: ['/'] */ - validatePaths: string[]; + validatePaths: Array | Array; /** * Optional base path to swagger ui bundle */ diff --git a/src/index.ts b/src/index.ts index 3647b65..6fd6c84 100644 --- a/src/index.ts +++ b/src/index.ts @@ -93,7 +93,7 @@ export async function oas(cfg: Partial): Promise { return; } - if (!config.validatePaths.some(path => ctx.path.startsWith(path))) { + if (skipValidation(config.validatePaths, ctx)) { // Skip validation if no path matches return next(); } @@ -151,3 +151,14 @@ async function compileOas(config: Config) { doc: openApiObject, }; } + +function skipValidation(validatePaths: Array | Array, ctx: koa.Context) { + let dontValidate = !validatePaths.some((path: string | RegExp) => { + if (path instanceof RegExp) { + return path.test(ctx.path); + } else { + return ctx.path.startsWith(path as string); + } + }); + return dontValidate; +} \ No newline at end of file