Skip to content

Commit 79b9563

Browse files
committed
chore: cleaning up
1 parent bd00a90 commit 79b9563

File tree

16 files changed

+181
-450
lines changed

16 files changed

+181
-450
lines changed

.vscode/settings.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
2-
"azureFunctions.deploySubpath": "example",
2+
"azureFunctions.deploySubpath": "packages/ajv-openapi-request-response-validator",
33
"azureFunctions.postDeployTask": "npm install (functions)",
44
"azureFunctions.projectLanguage": "TypeScript",
55
"azureFunctions.projectRuntime": "~4",
66
"debug.internalConsoleOptions": "neverOpen",
77
"azureFunctions.projectLanguageModel": 4,
8-
"azureFunctions.projectSubpath": "example",
8+
"azureFunctions.projectSubpath": "packages/ajv-openapi-request-response-validator",
99
"azureFunctions.preDeployTask": "npm prune (functions)",
1010

1111
// Place your settings in this file to overwrite default and user settings.
@@ -27,7 +27,7 @@
2727
"[json]": {
2828
"editor.formatOnSave": true
2929
},
30-
"eslint.workingDirectories": ["packages/*/"],
30+
"eslint.workingDirectories": [{ "mode": "auto" }],
3131
"eslint.options": {
3232
"resolvePluginsRelativeTo": "."
3333
},

.vscode/tasks.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
3838
"revealProblems": "onProblem",
3939
"close": true
4040
}
41+
},
42+
{
43+
"type": "shell",
44+
"label": "npm prune (functions)",
45+
"command": "npm prune --prodcution",
46+
"presentation": {
47+
"reveal": "silent",
48+
"revealProblems": "onProblem",
49+
"close": true
50+
}
4151
}
4252
]
4353
}

packages/ajv-openapi-request-response-validator/package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@
2626
"prebuild": "npm run clean",
2727
"build": "tsc -b",
2828
"build:fast": "tsc -b --incremental",
29+
"watch": "tsc -w",
2930
"test": "tsc -b test/tsconfig.json && rm -rf coverage && jest",
30-
"lint": "npm run lint:lib && npm run lint:test",
31-
"lint:lib": "eslint -c 'src/.eslintrc.js' './src/**/*.ts'",
31+
"lint": "npm run lint:src && npm run lint:test",
32+
"lint:src": "eslint -c 'src/.eslintrc.js' './src/**/*.ts'",
3233
"lint:test": "eslint -c 'test/.eslintrc.js' './test/**/*.ts'",
33-
"updateVersion": "ts-node ./scripts/updateVersion.ts",
34-
"validateRelease": "ts-node ./scripts/validateRelease.ts",
35-
"watch": "webpack --watch --mode development"
34+
"lint:fix": "npm run lint:fix:src && npm run lint:fix:test",
35+
"lint:fix:src": "eslint --fix -c 'src/.eslintrc.js' './src/**/*.ts'",
36+
"lint:fix:test": "eslint --fix -c 'test/.eslintrc.js' './test/**/*.ts'"
3637
},
3738
"files": [
3839
"dist"

packages/ajv-openapi-request-response-validator/src/ajv-factory.ts

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,21 @@ import addFormats from 'ajv-formats'
44
import { AjvExtras, DEFAULT_AJV_EXTRAS, DEFAULT_AJV_SETTINGS } from './ajv-opts'
55

66
/**
7-
* @param spec - Parsed OpenAPI V3 specification
8-
* @param ajvOpts - Optional Ajv options
9-
* @param validatorOpts - Optional additional validator options
10-
* @param ajvExtras - Optional additional Ajv features
11-
*/
12-
export function createAjvInstance(
13-
ajvOpts: Options = DEFAULT_AJV_SETTINGS,
14-
ajvExtras: AjvExtras = DEFAULT_AJV_EXTRAS
15-
) {
16-
const ajv = new AjvDraft4({ ...DEFAULT_AJV_SETTINGS, ...ajvOpts })
17-
if (ajvExtras?.addStandardFormats === true) {
18-
addFormats(ajv)
19-
}
20-
if (ajvExtras?.customKeywords) {
21-
ajvExtras.customKeywords.forEach((kwd) => {
22-
ajv.addKeyword(kwd)
23-
})
24-
}
7+
* @param spec - Parsed OpenAPI V3 specification
8+
* @param ajvOpts - Optional Ajv options
9+
* @param validatorOpts - Optional additional validator options
10+
* @param ajvExtras - Optional additional Ajv features
11+
*/
12+
export function createAjvInstance(ajvOpts: Options = DEFAULT_AJV_SETTINGS, ajvExtras: AjvExtras = DEFAULT_AJV_EXTRAS) {
13+
const ajv = new AjvDraft4({ ...DEFAULT_AJV_SETTINGS, ...ajvOpts })
14+
if (ajvExtras?.addStandardFormats === true) {
15+
addFormats(ajv)
16+
}
17+
if (ajvExtras?.customKeywords) {
18+
ajvExtras.customKeywords.forEach((kwd) => {
19+
ajv.addKeyword(kwd)
20+
})
21+
}
2522

26-
return ajv
27-
}
23+
return ajv
24+
}

packages/ajv-openapi-request-response-validator/src/ajv-openapi-request-response-validator.ts

Lines changed: 85 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
/* eslint-disable @typescript-eslint/naming-convention */
22
/* eslint-disable no-invalid-this */
33
import Ajv, { ErrorObject, ValidateFunction } from 'ajv'
4-
import OpenapiRequestCoercer from './request-coercer'
5-
import { dummyLogger } from 'ts-log';
4+
import OpenapiRequestCoercer from 'openapi-request-coercer'
5+
import { dummyLogger } from 'ts-log'
66
import { OpenAPIV3 } from 'openapi-types'
77
import {
88
convertDatesToISOString,
@@ -15,7 +15,7 @@ import {
1515
hasComponentSchemas,
1616
isValidReferenceObject,
1717
Primitive,
18-
isURLSearchParams
18+
isURLSearchParams,
1919
} from './openapi-validator'
2020
import { merge, openApiMergeRules } from 'allof-merge'
2121

@@ -88,7 +88,7 @@ export class AjvOpenApiValidator {
8888
constructor(
8989
spec: OpenAPIV3.Document,
9090
private ajv: Ajv,
91-
validatorOpts?: ValidatorOpts,
91+
validatorOpts?: ValidatorOpts
9292
) {
9393
this.validatorOpts = validatorOpts ? { ...DEFAULT_VALIDATOR_OPTS, ...validatorOpts } : DEFAULT_VALIDATOR_OPTS
9494
if (this.validatorOpts.logger == undefined) {
@@ -98,16 +98,25 @@ export class AjvOpenApiValidator {
9898
this.initialize(spec, this.validatorOpts.coerceTypes)
9999
}
100100

101-
102-
validateQueryParams(path: string, method: string, origParams: Record<string, Primitive> | URLSearchParams, strict = true): ErrorObj[] | undefined {
101+
validateQueryParams(
102+
path: string,
103+
method: string,
104+
origParams: Record<string, Primitive> | URLSearchParams,
105+
strict = true
106+
): ErrorObj[] | undefined {
103107
const parameterDefinitions = this.paramsValidators.filter((p) => p.path === path?.toLowerCase() && p.method === method?.toLowerCase())
104108

105109
let errResponse: ErrorObj[] = []
106110

107-
let params = isURLSearchParams(origParams) ? Array.from(origParams.entries()).reduce((acc, [key, value]) => {
108-
acc[key] = value
109-
return acc
110-
}, {} as Record<string, Primitive> ) : origParams
111+
let params = isURLSearchParams(origParams)
112+
? Array.from(origParams.entries()).reduce(
113+
(acc, [key, value]) => {
114+
acc[key] = value
115+
return acc
116+
},
117+
{} as Record<string, Primitive>
118+
)
119+
: origParams
111120

112121
if (this.requestCoercer) {
113122
params = this.unserializeParameters(params)
@@ -235,8 +244,6 @@ export class AjvOpenApiValidator {
235244
return undefined
236245
}
237246

238-
239-
240247
private initialize(origSpec: OpenAPIV3.Document, coerceTypes: boolean): void {
241248
const schemaCompileFailures: string[] = []
242249
const spec: OpenAPIV3.Document = merge(origSpec, { rules: openApiMergeRules() })
@@ -364,7 +371,9 @@ export class AjvOpenApiValidator {
364371

365372
if (schema) {
366373
const schemaName = `#/paths${path.replace(/[{}]/g, '')}/${method}/response/${key}`
367-
this.validatorOpts.logger.info(`Adding response body validator '${path}', '${method}', '${key}' with schema '${schemaName}'`)
374+
this.validatorOpts.logger.info(
375+
`Adding response body validator '${path}', '${method}', '${key}' with schema '${schemaName}'`
376+
)
368377
this.ajv.addSchema(schema, schemaName)
369378
const validator = this.ajv.compile({ $ref: schemaName })
370379
this.responseBodyValidators.push({
@@ -427,8 +436,8 @@ export class AjvOpenApiValidator {
427436
},
428437
validator,
429438
})
430-
431-
if (isValidReferenceObject(resolvedParam.schema)) {
439+
440+
if (coerceTypes && isValidReferenceObject(resolvedParam.schema)) {
432441
const fullyResolved = this.fullyResolveParameter(spec, resolvedParam)
433442
if (fullyResolved) {
434443
resolvedParams.push(fullyResolved)
@@ -438,13 +447,12 @@ export class AjvOpenApiValidator {
438447
}
439448
}
440449
})
441-
450+
442451
if (this.validatorOpts.coerceTypes == true && resolvedParams.length > 0) {
443452
this.requestCoercer = new OpenapiRequestCoercer({
444453
logger: this.validatorOpts.logger,
445454
enableObjectCoercion: true,
446455
parameters: resolvedParams,
447-
448456
})
449457
}
450458
}
@@ -470,18 +478,21 @@ export class AjvOpenApiValidator {
470478
}
471479
}
472480

473-
474-
475-
private resolveRef(document: OpenAPIV3.Document, ref: string): any {
476-
const pathParts = ref.split('/');
477-
478-
return pathParts.reduce((current: any, part) => {
479-
if (part === '#' || part === '') return current;
480-
return current ? current[part] : undefined;
481-
}, document);
482-
}
483-
484-
private fullyResolveSchemaRefs(document: OpenAPIV3.Document, schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject, visited: Map<string, OpenAPIV3.SchemaObject> = new Map<string, OpenAPIV3.SchemaObject>()): OpenAPIV3.SchemaObject | undefined {
481+
private resolveRef(document: OpenAPIV3.Document, ref: string): OpenAPIV3.SchemaObject {
482+
const pathParts = ref.split('/')
483+
484+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
485+
return pathParts.reduce((current: any, part) => {
486+
if (part === '#' || part === '') return current
487+
return current ? current[part] : undefined
488+
}, document)
489+
}
490+
491+
private fullyResolveSchemaRefs(
492+
document: OpenAPIV3.Document,
493+
schema: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject,
494+
visited: Map<string, OpenAPIV3.SchemaObject> = new Map<string, OpenAPIV3.SchemaObject>()
495+
): OpenAPIV3.SchemaObject | undefined {
485496
if (typeof schema !== 'object') {
486497
return undefined
487498
}
@@ -492,53 +503,58 @@ export class AjvOpenApiValidator {
492503
return resolved
493504
}
494505
}
495-
506+
496507
let resolvedSchema
497-
if (isValidReferenceObject(schema)) {
498-
resolvedSchema = this.resolveRef(document, schema.$ref) as OpenAPIV3.SchemaObject;
499-
visited.set(schema.$ref, resolvedSchema);
508+
if (isValidReferenceObject(schema)) {
509+
resolvedSchema = this.resolveRef(document, schema.$ref) as OpenAPIV3.SchemaObject
510+
visited.set(schema.$ref, resolvedSchema)
500511
} else {
501512
resolvedSchema = schema
502513
}
503-
504-
for (const key in resolvedSchema) {
514+
515+
for (const key in resolvedSchema) {
505516
if (typeof resolvedSchema[key as keyof OpenAPIV3.SchemaObject] === 'object') {
506-
resolvedSchema[key as keyof OpenAPIV3.SchemaObject] = this.fullyResolveSchemaRefs(document, resolvedSchema[key as keyof OpenAPIV3.SchemaObject], visited);
507-
}
517+
resolvedSchema[key as keyof OpenAPIV3.SchemaObject] = this.fullyResolveSchemaRefs(
518+
document,
519+
resolvedSchema[key as keyof OpenAPIV3.SchemaObject],
520+
visited
521+
)
522+
}
508523
}
509-
510-
return resolvedSchema;
524+
525+
return resolvedSchema
511526
}
512-
513-
private fullyResolveParameter(document: OpenAPIV3.Document, parameter: OpenAPIV3.ParameterObject): OpenAPIV3.ParameterObject | undefined {
514-
if (!parameter.schema || typeof parameter.schema !== 'object' || !isValidReferenceObject(parameter.schema)) {
515-
return parameter;
516-
}
517-
518-
return { ...parameter, schema: this.fullyResolveSchemaRefs(document, parameter.schema) };
519-
}
520-
521-
private unserializeParameters(parameters: Record<string, Primitive>): Record<string, any> {
522-
const result: Record<string, any> = {};
527+
528+
private fullyResolveParameter(document: OpenAPIV3.Document, parameter: OpenAPIV3.ParameterObject): OpenAPIV3.ParameterObject | undefined {
529+
if (!parameter.schema || typeof parameter.schema !== 'object' || !isValidReferenceObject(parameter.schema)) {
530+
return parameter
531+
}
532+
533+
return { ...parameter, schema: this.fullyResolveSchemaRefs(document, parameter.schema) }
534+
}
535+
536+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
537+
private unserializeParameters(parameters: Record<string, Primitive>): Record<string, any> {
538+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
539+
const result: Record<string, any> = {}
523540
for (const key in parameters) {
524-
const value = parameters[key];
525-
let target = result;
526-
const splitKey = key.split('[');
527-
const lastKeyIndex = splitKey.length - 1;
528-
529-
splitKey.forEach((part, index) => {
530-
const cleanPart = part.replace(']', '');
531-
532-
if (index === lastKeyIndex) {
533-
target[cleanPart] = typeof value === 'string' ? decodeURIComponent(value) : value // TODO is the decode necesary?
534-
} else {
535-
if (!target[cleanPart]) target[cleanPart] = {};
536-
target = target[cleanPart];
537-
}
538-
});
541+
const value = parameters[key]
542+
let target = result
543+
const splitKey = key.split('[')
544+
const lastKeyIndex = splitKey.length - 1
545+
546+
splitKey.forEach((part, index) => {
547+
const cleanPart = part.replace(']', '')
548+
549+
if (index === lastKeyIndex) {
550+
target[cleanPart] = value
551+
} else {
552+
if (!target[cleanPart]) target[cleanPart] = {}
553+
target = target[cleanPart]
554+
}
555+
})
539556
}
540-
541-
return result;
557+
558+
return result
542559
}
543-
544-
}
560+
}

packages/ajv-openapi-request-response-validator/src/openapi-validator.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { OpenAPIV3 } from 'openapi-types'
2-
import { Logger } from 'ts-log';
2+
import { Logger } from 'ts-log'
33
export const STATUS_BAD_REQUEST = 400
44
export const EC_VALIDATION = 'Validation'
55
export const ET_VALIDATION = 'Validation failed'
@@ -64,7 +64,11 @@ export function hasComponentRequestBodies(doc: OpenAPIV3.Document): doc is DocWi
6464
export function isValidReferenceObject(
6565
parameter: OpenAPIV3.ParameterObject | OpenAPIV3.SchemaObject | OpenAPIV3.RequestBodyObject | OpenAPIV3.ReferenceObject
6666
): parameter is OpenAPIV3.ReferenceObject {
67-
return (parameter as OpenAPIV3.ReferenceObject).$ref !== undefined && (parameter as OpenAPIV3.ReferenceObject).$ref !== null && (parameter as OpenAPIV3.ReferenceObject).$ref.includes('/')
67+
return (
68+
(parameter as OpenAPIV3.ReferenceObject).$ref !== undefined &&
69+
(parameter as OpenAPIV3.ReferenceObject).$ref !== null &&
70+
(parameter as OpenAPIV3.ReferenceObject).$ref.includes('/')
71+
)
6872
}
6973

7074
export function isURLSearchParams(params: Record<string, Primitive> | URLSearchParams): params is URLSearchParams {

0 commit comments

Comments
 (0)