diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..99117d6c --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +[*.js] +indent_style = space +indent_size = 2 \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..c1a6f667 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/index.ts b/index.ts index e3040c65..cba65ebd 100644 --- a/index.ts +++ b/index.ts @@ -8,70 +8,75 @@ import OpenAPIFramework, { OpenAPIFrameworkConstructorArgs, } from './fw'; import OpenAPISchemaValidator from 'openapi-schema-validator'; -import OpenAPIRequestValidator, { OpenAPIRequestValidatorError } from 'openapi-request-validator'; +import OpenAPIRequestValidator, { + OpenAPIRequestValidatorError, +} from 'openapi-request-validator'; import OpenAPIRequestCoercer from 'openapi-request-coercer'; import { OpenAPIResponseValidatorError } from 'openapi-response-validator'; import { SecurityHandlers } from 'openapi-security-handler'; import { OpenAPI, OpenAPIV3 } from 'openapi-types'; -import { OpenAPIFrameworkVisitor, OpenAPIFrameworkAPIContext } from './fw/types'; +import { + OpenAPIFrameworkVisitor, + OpenAPIFrameworkAPIContext, +} from './fw/types'; // import BasePath from './fw/base.path'; export interface OpenApiMiddlewareOpts extends OpenAPIFrameworkArgs { + name: string; apiSpecPath: string; } export function OpenApiMiddleware(opts: OpenApiMiddlewareOpts) { if (!opts.apiSpecPath) throw new Error('apiSpecPath required'); - const apiDoc = handleYaml(handleFilePath(opts.apiSpecPath)); - console.log(opts) + const apiContents = loadSpecFile(opts.apiSpecPath); + if (!apiContents) + throw new Error(`spec could not be read at ${opts.apiSpecPath}`); + const apiDoc = handleYaml(apiContents); const framework = createFramework({ ...opts, apiDoc }); + this.opts = opts; + this.opts.name = this.opts.name || 'express-middleware-openapi'; + this.routeMap = buildRouteMap(framework); console.log(JSON.stringify(framework.apiDoc, null, 4), framework.basePaths); + console.log(opts); +} - this.opts = opts; - this.routeMap = buildRouteMap(framework) - console.log('----routeMap---', this.routeMap) -}; - - OpenApiMiddleware.prototype.middleware = function() { +OpenApiMiddleware.prototype.middleware = function() { return (req, res, next) => { const { path, method } = req; if (path && method) { - const schema = this.routeMap[path][method.toUpperCase()] - console.log('found schema', schema) + const schema = this.routeMap[path][method.toUpperCase()]; + console.log('found schema', schema); // Check if route is in map (throw error - option to ignore) if (this.opts.enableObjectCoercion) { // this modifies the request object with coerced types new OpenAPIRequestCoercer({ - loggingKey: 'my_logging_key', + loggingKey: this.opts.name, enableObjectCoercion: this.opts.enableObjectCoercion, - parameters: schema.parameters - }).coerce(req) + parameters: schema.parameters, + }).coerce(req); } const validationResult = new OpenAPIRequestValidator({ errorTransformer: this.errorTransformer, - ...schema - }).validate(req) - console.log(validationResult) + ...schema, + }).validate(req); + if (validationResult && validationResult.errors.length > 0) { - const { errors, status } = validationResult - console.log('----provide to custom error handler',errors, status) - return res.status(status).json(errors) + const { errors, status } = validationResult; + console.log('----provide to custom error handler', errors, status); + return res.status(status).json(errors); } - } next(); - } + }; }; - - function createFramework(args: OpenApiMiddlewareOpts): OpenAPIFramework { const frameworkArgs: OpenAPIFrameworkConstructorArgs = { featureType: 'middleware', - name: 'my_logging_prefix', + name: args.name, ...(args as OpenAPIFrameworkArgs), }; @@ -81,32 +86,32 @@ function createFramework(args: OpenApiMiddlewareOpts): OpenAPIFramework { } function buildRouteMap(framework) { - const routeMap = {} + const routeMap = {}; framework.initialize({ visitApi(ctx: OpenAPIFrameworkAPIContext) { - const apiDoc = ctx.getApiDoc() + const apiDoc = ctx.getApiDoc(); for (const bp of ctx.basePaths) { for (const path of Object.keys(apiDoc.paths)) { for (const [method, schema] of Object.entries(apiDoc.paths[path])) { - const pathKey = `${bp.path}${path}` - const methodKey = method.toUpperCase() - const routeMethod = routeMap[pathKey] + const pathKey = `${bp.path}${path}`; + const methodKey = method.toUpperCase(); + const routeMethod = routeMap[pathKey]; if (routeMethod) { // add a new method - routeMethod[methodKey] = schema + routeMethod[methodKey] = schema; } else { // create the path key and add first method - routeMap[pathKey] = { [methodKey]: schema } + routeMap[pathKey] = { [methodKey]: schema }; } } } } - } + }, }); - return routeMap + return routeMap; } -function handleFilePath(filePath) { +function loadSpecFile(filePath) { if (typeof filePath === 'string') { const absolutePath = path.resolve(process.cwd(), filePath); if (fs.existsSync(absolutePath)) { @@ -118,7 +123,7 @@ function handleFilePath(filePath) { } } } - return filePath; + return null; } function handleYaml(apiDoc) {