kogosoftwarellc / open-api

A Monorepo of various packages to power OpenAPI in node
MIT License
892 stars 235 forks source link

openapi-framework: Allow injecting custom classes for features #785

Closed jsau- closed 2 years ago

jsau- commented 2 years ago

The current implementation does not allow defining custom classes to be used for:

This is absolutely fine for the general use case.

However, in very large projects this incurs a fairly large penalty on startup. For example, to perform an integration test on a single endpoint all of the classes must be instantiated for all paths/operations.

Allowing consumers to inject their own instances of these classes will support behavior like, within test environments, providing thin wrappers around the existing classes for this functionality which are lazy-initialized on any property being accessed. Lazy-initializing these classes sees fairly large improvements in integration test times for large API documents.

This may be useful for other reports of slow startup for large API documents, eg. Issue #372.

This could be seen as a resolution to pull requests #737 and #738 as well. Instead of having to pass AJV configuration to OpenAPIFrameworkArgs, consumers are able to write their own classes for request/response validation that instantiate AJV as they see fit.

honzapatCZ commented 2 years ago

Bump

Any docs to set it up? Would like to use the removeAdditional: "all" option

jsau- commented 2 years ago

@honzapatCZ I've not included any documentation on express-openapi or koa-openapi because the contrib guidelines say to keep things scoped to a single package; if this is approved I'll raise some extra ones to document in those packages after the fact.

In terms of how to use:

Let's say you're using express-openapi.

Currently you call the initialize function, eg.

initialize({
  app,
  apiDoc,
  ...
});

To use this you now have an extra parameter called features, where each property is a class which implements the same interface as the default package used by this library.

If you wanted to change the AJV behavior for request validation you would write a new class:

import {
  IOpenAPIRequestValidator,
  OpenAPIRequestValidatorArgs,
} from 'openapi-request-validator';

export default class CustomRequestValidator
  implements IOpenAPIRequestValidator {
  private args;

  constructor(args: OpenAPIRequestValidatorArgs) {
    this.args = args;
  }

  validateRequest(request: any) {
    return;
  }
}

EDIT: You can see examples of the required interfaces your classes must implement in the changeset. I've created a set of classes called Custom*.

(Except you'd probably copy the actual class code from packages/openapi-request-validator/index.ts, and make any changes desired.)

And then in initialize you'd change it to:

initialize({
  app,
  apiDoc,
  features: {
    requestValidator: CustomRequestValidator,
  },
  ...
});
jsdevel commented 2 years ago

solid PR @jsau- !