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.
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 enablejson-schema-to-ts
to resolve$ref
schema typesschemas
: an array containing all$ref
schemas and user-picked schemas (viaschemaFilter
option) to be registered withfastify.addSchema
so that@fastify/swagger
can re-export them ascomponents.schemas
OpenAPI definitions
Property | Type | Description | Default |
---|---|---|---|
schemaFilter | ({id}: {id:string, isRef: boolean}) => boolean |
Pick the schemas to register with fastify.addSchema . |
All components.schemas definitions |
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.
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
'srefResolver
option to preserve components names) - All schemas registered via
.addSchema
being exposed under OpenAPi'scomponents.schemas
no matter their$ref
value 🔗 - Fastify seems not to be always able to resolve
#
-leading$ref
s (#/components/schemas/Name
) but only/components/schemas/Name
. For this reason the plugin rewrites$id
and$ref
values as the latter
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.