diff --git a/README.md b/README.md index d9ba28a..5e3d483 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,56 @@ const plugin: FastifyPluginAsyncJsonSchemaToTs = async function ( ); }; ``` + +## Using References from a Shared Schema + +JsonSchemaToTsProvider takes a generic that can be passed in the Shared Schema +as shown in the following example + +```ts +const userSchema = { + type: "object", + additionalProperties: false, + properties: { + givenName: { type: "string" }, + familyName: { type: "string" }, + }, + required: ["givenName", "familyName"], +} as const; + +const sharedSchema = { + $id: "shared-schema", + definitions: { + user: userSchema, + }, +} as const; + +// then when using JsonSchemaToTsProvider, the shared schema is passed through the generic +// references takes an array so can pass in multiple shared schema +const fastify = + Fastify().withTypeProvider< + JsonSchemaToTsProvider<{ references: [typeof sharedSchema] }> + >(); + +// now reference the shared schema like the following +fastify.get( + "/profile", + { + schema: { + body: { + type: "object", + properties: { + user: { + $ref: "shared-schema#/definitions/user", + }, + }, + required: ['user'], + }, + } as const, + }, + (req) => { + // givenName and familyName will be correctly typed as strings! + const { givenName, familyName } = req.body.user; + } +); +``` diff --git a/index.ts b/index.ts index cd4c190..2477e5f 100644 --- a/index.ts +++ b/index.ts @@ -7,10 +7,10 @@ import { FastifyPluginAsync } from 'fastify' -import { JSONSchema7, FromSchema } from 'json-schema-to-ts' +import { JSONSchema7, FromSchema, FromSchemaOptions, FromSchemaDefaultOptions } from 'json-schema-to-ts' -export interface JsonSchemaToTsProvider extends FastifyTypeProvider { - output: this['input'] extends JSONSchema7 ? FromSchema : never; +export interface JsonSchemaToTsProvider extends FastifyTypeProvider { + output: this['input'] extends JSONSchema7 ? FromSchema : never; } /** diff --git a/types/references.test-d.ts b/types/references.test-d.ts new file mode 100644 index 0000000..c9c99e0 --- /dev/null +++ b/types/references.test-d.ts @@ -0,0 +1,62 @@ +import { JsonSchemaToTsProvider } from '../index' +import { expectAssignable, expectType } from 'tsd' +import Fastify, { FastifyInstance, FastifyLoggerInstance, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from 'fastify' +import { FromSchema } from 'json-schema-to-ts' + +const addressSchema = { + type: 'object', + additionalProperties: false, + properties: { + line1: { type: 'string' }, + line2: { type: 'string' }, + city: { type: 'string' } + }, + required: ['line1', 'city'] +} as const +type Address = FromSchema; + +const userSchema = { + type: 'object', + additionalProperties: false, + properties: { + givenName: { type: 'string' }, + familyName: { type: 'string' } + }, + required: ['givenName', 'familyName'] +} as const +type User = FromSchema + +const sharedSchema = { + $id: 'shared-schema', + definitions: { + address: addressSchema, + user: userSchema + } +} as const + +type JsonSchemaToTsProviderWithSharedSchema = JsonSchemaToTsProvider<{ + references: [typeof sharedSchema]; +}>; +const fastify = Fastify().withTypeProvider() + +expectAssignable>(fastify) + +fastify.get('/profile', { + schema: { + body: { + type: 'object', + properties: { + user: { + $ref: 'shared-schema#/definitions/user' + }, + address: { + $ref: 'shared-schema#/definitions/address' + } + }, + required: ['user', 'address'] + } as const + } +}, (req) => { + expectType(req.body.user) + expectType
(req.body.address) +})