From ec6b9c00503b1cfc9d48c502caf2a22136d96da9 Mon Sep 17 00:00:00 2001 From: Liam Tait Date: Fri, 5 Aug 2022 00:54:11 +1200 Subject: [PATCH] feat: add FastifyPluginAsyncJsonSchemaToTs and FastifyPluginCallbackJsonSchemaToTs plugin types (#15) * feat: add jstt plugin type * me, no I would never copy and paste code * elongate plugin type abbreviations * remove all abbreviations * remove abbreviations from readme * remove abbreviations from index doc comments --- README.md | 34 +++++++++++++ index.ts | 46 ++++++++++++++++-- types/plugin.test-d.ts | 108 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 types/plugin.test-d.ts diff --git a/README.md b/README.md index 22676e1..d9ba28a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,36 @@ # fastify-type-provider-json-schema-to-ts + A Type Provider for json-schema-to-ts + +## Plugin definition + +> **Note** +> When using plugin types, withTypeProvider is not required in order to register the plugin + +```ts +const plugin: FastifyPluginAsyncJsonSchemaToTs = async function ( + fastify, + _opts +) { + fastify.get( + "/", + { + schema: { + body: { + type: "object", + properties: { + x: { type: "string" }, + y: { type: "number" }, + z: { type: "boolean" }, + }, + required: ["x", "y", "z"], + } as const, + }, + }, + (req) => { + /// The `x`, `y`, and `z` types are automatically inferred + const { x, y, z } = req.body; + } + ); +}; +``` diff --git a/index.ts b/index.ts index a8fbeb2..cd81023 100644 --- a/index.ts +++ b/index.ts @@ -1,7 +1,47 @@ -import { FastifyTypeProvider } from 'fastify' +import { + FastifyTypeProvider, + FastifyPluginOptions, + RawServerBase, + RawServerDefault, + FastifyPluginCallback, + FastifyPluginAsync, +} from "fastify"; -import { JSONSchema7, FromSchema } from 'json-schema-to-ts' +import { JSONSchema7, FromSchema } from "json-schema-to-ts"; export interface JsonSchemaToTsProvider extends FastifyTypeProvider { - output: this['input'] extends JSONSchema7 ? FromSchema : never + output: this["input"] extends JSONSchema7 ? FromSchema : never; } + +/** + * FastifyPluginCallback with JSON Schema to Typescript automatic type inference + * + * @example + * ```typescript + * import { FastifyPluginCallbackJsonSchemaToTs } from "@fastify/type-provider-json-schema-to-ts" + * + * const plugin: FastifyPluginCallbackJsonSchemaToTs = (fastify, options, done) => { + * done() + * } + * ``` + */ +export type FastifyPluginCallbackJsonSchemaToTs< + Options extends FastifyPluginOptions = Record, + Server extends RawServerBase = RawServerDefault +> = FastifyPluginCallback; + +/** + * FastifyPluginAsync with JSON Schema to Typescript automatic type inference + * + * @example + * ```typescript + * import { FastifyPluginAsyncJsonSchemaToTs } fromg "@fastify/type-provider-json-schema-to-ts" + * + * const plugin: FastifyPluginAsyncJsonSchemaToTs = async (fastify, options) => { + * } + * ``` + */ +export type FastifyPluginAsyncJsonSchemaToTs< + Options extends FastifyPluginOptions = Record, + Server extends RawServerBase = RawServerDefault +> = FastifyPluginAsync; diff --git a/types/plugin.test-d.ts b/types/plugin.test-d.ts new file mode 100644 index 0000000..207f0de --- /dev/null +++ b/types/plugin.test-d.ts @@ -0,0 +1,108 @@ +import { + FastifyPluginAsyncJsonSchemaToTs, + FastifyPluginCallbackJsonSchemaToTs, +} from "../index"; +import { expectType } from "tsd"; +import Fastify, { FastifyPluginAsync, FastifyPluginCallback } from "fastify"; + +import { Http2Server } from "http2"; + +// Ensure the defaults of FastifyPluginAsyncJsonSchemaToTs are the same as FastifyPluginAsync +export const pluginAsyncDefaults: FastifyPluginAsync = async ( + fastify, + options +) => { + const pluginAsyncJSONSchemaToTsDefaults: FastifyPluginAsyncJsonSchemaToTs = + async (fastifyWithJSONSchemaToTs, optionsJSONSchemaToTs) => { + expectType(fastify.server); + expectType(options); + }; + fastify.register(pluginAsyncJSONSchemaToTsDefaults); +}; + +// Ensure the defaults of FastifyPluginCallbackJsonSchemaToTs are the same as FastifyPluginCallback +export const pluginCallbackDefaults: FastifyPluginCallback = async ( + fastify, + options, + done +) => { + const pluginCallbackJSONSchemaToTsDefaults: FastifyPluginCallbackJsonSchemaToTs = + async ( + fastifyWithJSONSchemaToTs, + optionsJSONSchemaToTs, + doneJSONSchemaToTs + ) => { + expectType(fastify.server); + expectType(options); + }; + + fastify.register(pluginCallbackJSONSchemaToTsDefaults); +}; + +const asyncPlugin: FastifyPluginAsyncJsonSchemaToTs< + { optionA: string }, + Http2Server +> = async (fastify, options) => { + expectType(fastify.server); + + expectType(options.optionA); + + fastify.get( + "/", + { + schema: { + body: { + type: "object", + properties: { + x: { type: "string" }, + y: { type: "number" }, + z: { type: "boolean" }, + }, + required: ["x", "y", "z"], + } as const, + }, + }, + (req) => { + expectType(req.body.z); + expectType(req.body.y); + expectType(req.body.x); + } + ); +}; + +const callbackPlugin: FastifyPluginCallbackJsonSchemaToTs< + { optionA: string }, + Http2Server +> = (fastify, options, done) => { + expectType(fastify.server); + + expectType(options.optionA); + + fastify.get( + "/", + { + schema: { + body: { + type: "object", + properties: { + x: { type: "string" }, + y: { type: "number" }, + z: { type: "boolean" }, + }, + required: ["x", "y", "z"], + } as const, + }, + }, + (req) => { + expectType(req.body.z); + expectType(req.body.y); + expectType(req.body.x); + } + ); + done(); +}; + +const fastify = Fastify(); + +fastify.register(asyncPlugin); +fastify.register(callbackPlugin);