Skip to content

Latest commit

 

History

History
158 lines (123 loc) · 5.69 KB

plugins.md

File metadata and controls

158 lines (123 loc) · 5.69 KB

Plugins

openapi-ts-json-schema plugins are intended as a way to generate extra artifacts based on the same internal metadata created to generate the JSON schema output.

Fastify integration plugin

This plugin is an attempt to better integrate Fastify and its json-schema-to-ts type provider to register schemas with fastify.addSchema and let @fastify/swagger generate a better OpenAPI definition.

The plugin generates a <outputPath>/fastify-integration.ts TS file exposing:

  • RefSchemas TS type specifically built to enable json-schema-to-ts to resolve $ref schema types
  • schemas: an array containing all $ref schemas and user-picked schemas (via schemaFilter option) to be registered with fastify.addSchema so that @fastify/swagger can re-export them as components.schemas OpenAPI definitions

Options

Property Type Description Default
schemaFilter ({id}: {id:string, isRef: boolean}) => boolean Pick the schemas to register with fastify.addSchema. All components.schemas definitions

Example

Generate TypeScript JSON schemas:

import {
  openapiToTsJsonSchema,
  fastifyIntegrationPlugin,
} from 'openapi-ts-json-schema';

await openapiToTsJsonSchema({
  openApiSchema: path.resolve(fixtures, 'path/to/open-api-specs.yaml'),
  outputPath: 'path/to/generated/schemas',
  definitionPathsToGenerateFrom: ['components.schemas', 'paths'],
  plugins: [
    fastifyIntegrationPlugin({
      // Optional
      schemaFilter: ({ id }) => id.startsWith('/components/schemas'),
    }),
  ],
});

Register generated schemas:

import { JsonSchemaToTsProvider } from '@fastify/type-provider-json-schema-to-ts';
import {
  RefSchemas,
  schemas,
} from '.path/to/generated/schemas/fastify-integration';

// Configure json-schema-to-ts type provider to hydrate "$ref"s schema types
const server =
  fastify.withTypeProvider<
    JsonSchemaToTsProvider<{ references: RefSchemas }>
  >();

// Register exposed JSON schemas
schemas.forEach((schema) => {
  server.addSchema(schema);
});

Configure @fastify/swagger's refResolver option to re-export registered schemas under OpenAPI components.schema prop:

await server.register(fastifySwagger, {
  openapi: {
    /*...*/
  },
  refResolver: {
    buildLocalReference: (json, baseUri, fragment, i) => {
      const OPEN_API_COMPONENTS_SCHEMAS_PATH = '/components/schemas/';
      if (
        typeof json.$id === 'string' &&
        json.$id.startsWith(OPEN_API_COMPONENTS_SCHEMAS_PATH)
      ) {
        return json.$id.replace(OPEN_API_COMPONENTS_SCHEMAS_PATH, '');
      }

      return `def-${i}`;
    },
  },
});

Reference registered schemas as:

server.get('/pet', {
  schema: {
    response: {
      200: { $ref: '/components/schemas/Pets' },
    },
  } as const,
  handler: (req) => {
    return [
      {
        id,
        name: 'Pet name',
        tag: '3',
      },
    ];
  },
});

Check out the Fastify integration plugin example to see how to setup Fastify and json-schema-to-ts type provider.

Notes

This plugin should be considered bleeding edge. I'm still figuring out the best way to integrate open-ts-json-schema output with Fastify.

Please consider that @fastify/swagger currently comes with some limitations:

  • OpenApi components being renamed as def-${counter} by default 🔗 (you need to configure @fastify/swagger's refResolver option to preserve components names)
  • All schemas registered via .addSchema being exposed under OpenAPi's components.schemas no matter their $ref value 🔗
  • Fastify seems not to be always able to resolve #-leading $refs (#/components/schemas/Name) but only /components/schemas/Name. For this reason the plugin rewrites $id and $ref values as the latter

Write your own plugin

openapi-ts-json-schema exposes a TS type to support custom plugins implementation:

import type { Plugin } from 'openapi-ts-json-schema';

// An `openapi-ts-json-schema` consists of a factory function returning an async function
const myPlugin: Plugin<{ optionOne: string; optionTwo: string }> =
  // Factory function with optional options
  ({ optionOne, optionTwo }) => ({
    onInit: async ({ options }) => {
      // Validate/mutate option values here
    };
    onBeforeGeneration: async ({ outputPath, metaData, options, utils }) => {
      // Generate plugin-specific artifacts
    };
  })

export myPlugin;

...import and instantiate your plugin:

import { openapiToTsJsonSchema } from 'openapi-ts-json-schema';
import { myPlugin } from '../myPlugin';

await openapiToTsJsonSchema({
  openApiSchema: 'path/to/open-api-specs.yaml',
  definitionPathsToGenerateFrom: ['components.schemas'],
  plugins: [myPlugin({ optionOne: 'foo', optionTwo: 'bar' })],
});

Take a look at fastifyIntegrationPlugin to get an idea.