Skip to content

Commit

Permalink
feat: expose FromSchema options (#22)
Browse files Browse the repository at this point in the history
* feat: expose FromSchema options

* test: add tests for external references

* docs: update to add an example of how to use external references

* Update README.md

* Update README.md
  • Loading branch information
kalvenschraut authored Dec 13, 2022
1 parent 25cd92a commit 357ff54
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 3 deletions.
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
);
```
6 changes: 3 additions & 3 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<this['input']> : never;
export interface JsonSchemaToTsProvider<Options extends FromSchemaOptions = FromSchemaDefaultOptions> extends FastifyTypeProvider {
output: this['input'] extends JSONSchema7 ? FromSchema<this['input'], Options> : never;
}

/**
Expand Down
62 changes: 62 additions & 0 deletions types/references.test-d.ts
Original file line number Diff line number Diff line change
@@ -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<typeof addressSchema>;

const userSchema = {
type: 'object',
additionalProperties: false,
properties: {
givenName: { type: 'string' },
familyName: { type: 'string' }
},
required: ['givenName', 'familyName']
} as const
type User = FromSchema<typeof userSchema>

const sharedSchema = {
$id: 'shared-schema',
definitions: {
address: addressSchema,
user: userSchema
}
} as const

type JsonSchemaToTsProviderWithSharedSchema = JsonSchemaToTsProvider<{
references: [typeof sharedSchema];
}>;
const fastify = Fastify().withTypeProvider<JsonSchemaToTsProviderWithSharedSchema>()

expectAssignable<FastifyInstance<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, FastifyLoggerInstance, JsonSchemaToTsProviderWithSharedSchema>>(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<User>(req.body.user)
expectType<Address>(req.body.address)
})

0 comments on commit 357ff54

Please sign in to comment.