Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add typebox plugin types #27

Merged
merged 1 commit into from
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,32 @@ export const CreateProductHandler = (
};
```


## Plugin definition

> **Note**
> When using plugin types, withTypeProvider is not required in order to register the plugin

```ts
import { Type } from '@sinclair/typebox';
import { FastifyPluginAsyncTypebox } from '@fastify/type-provider-typebox'

const plugin: FastifyPluginAsyncTypebox = async function(fastify, _opts) {
fastify.get('/', {
schema: {
body: Type.Object({
x: Type.String(),
y: Type.Number(),
z: Type.Boolean()
})
}
}, (req) => {
/// The `x`, `y`, and `z` types are automatically inferred
const { x, y, z } = req.body
});
}
```

## Type Compiler

TypeBox provides an optional type compiler that perform very fast runtime type checking for data received on routes. Note this compiler is limited to types expressable through the TypeBox `Type.*` namespace only. To enable this compiler, you can call `.setValidatorCompiler(...)` with the `TypeBoxValidatorCompiler` export provided by this package.
Expand Down
46 changes: 45 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { FastifySchemaCompiler, FastifyTypeProvider } from "fastify"
import {
FastifyPluginAsync,
FastifyPluginCallback,
FastifyPluginOptions,
FastifySchemaCompiler,
FastifyTypeProvider,
RawServerBase,
RawServerDefault
} from "fastify"
import { TypeCompiler, ValueError } from '@sinclair/typebox/compiler'
import { Static, TSchema } from '@sinclair/typebox'

Expand Down Expand Up @@ -42,3 +50,39 @@ export class TypeBoxValidationError extends Error {
export interface TypeBoxTypeProvider extends FastifyTypeProvider {
output: this['input'] extends TSchema ? Static<this['input']> : never
}



/**
* FastifyPluginCallback with Typebox automatic type inference
*
* @example
* ```typescript
* import { FastifyPluginCallbackTypebox } fromg "@fastify/type-provider-typebox"
*
* const plugin: FastifyPluginCallbackTypebox = (fastify, options, done) => {
* done()
* }
* ```
*/
export type FastifyPluginCallbackTypebox<
Options extends FastifyPluginOptions = Record<never, never>,
Server extends RawServerBase = RawServerDefault,
> = FastifyPluginCallback<Options, Server, TypeBoxTypeProvider>


/**
* FastifyPluginAsync with Typebox automatic type inference
*
* @example
* ```typescript
* import { FastifyPluginAsyncTypebox } fromg "@fastify/type-provider-typebox"
*
* const plugin: FastifyPluginAsyncTypebox = async (fastify, options) => {
* }
* ```
*/
export type FastifyPluginAsyncTypebox<
Options extends FastifyPluginOptions = Record<never, never>,
Server extends RawServerBase = RawServerDefault
> = FastifyPluginAsync<Options, Server, TypeBoxTypeProvider>
78 changes: 78 additions & 0 deletions types/plugin.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { FastifyPluginAsyncTypebox, FastifyPluginCallbackTypebox } from '../index'
import { expectType } from 'tsd'
import Fastify, { FastifyPluginAsync, FastifyPluginCallback } from 'fastify'
import { Type } from '@sinclair/typebox'
import { Http2Server } from 'http2'


// Ensure the defaults of FastifyPluginAsyncTypebox are the same as FastifyPluginAsync
export const pluginAsyncDefaults: FastifyPluginAsync = async (fastify, options) => {
const pluginAsyncTypeboxDefaults: FastifyPluginAsyncTypebox = async (fastifyWithTypebox, optionsTypebox) => {
expectType<typeof fastifyWithTypebox['server']>(fastify.server);
expectType<typeof optionsTypebox>(options);
}
fastify.register(pluginAsyncTypeboxDefaults)

}


// Ensure the defaults of FastifyPluginCallbackTypebox are the same as FastifyPluginCallback
export const pluginCallbackDefaults: FastifyPluginCallback = async (fastify, options, done) => {
const pluginCallbackTypeboxDefaults: FastifyPluginCallbackTypebox = async (fastifyWithTypebox, optionsTypebox, doneTypebox) => {
expectType<typeof fastifyWithTypebox['server']>(fastify.server);
expectType<typeof optionsTypebox>(options);
}

fastify.register(pluginCallbackTypeboxDefaults)
}


const asyncPlugin: FastifyPluginAsyncTypebox<{ optionA: string }, Http2Server> = async (fastify, options) => {

expectType<Http2Server>(fastify.server)

expectType<string>(options.optionA)

fastify.get('/', {
schema: {
body: Type.Object({
x: Type.String(),
y: Type.Number(),
z: Type.Boolean(),
})
}
}, (req) => {
expectType<boolean>(req.body.z)
expectType<number>(req.body.y)
expectType<string>(req.body.x)
})
}


const callbackPlugin: FastifyPluginCallbackTypebox<{ optionA: string }, Http2Server> = (fastify, options, done) => {

expectType<Http2Server>(fastify.server)

expectType<string>(options.optionA)

fastify.get('/', {
schema: {
body: Type.Object({
x: Type.String(),
y: Type.Number(),
z: Type.Boolean(),
})
}
}, (req) => {
expectType<boolean>(req.body.z)
expectType<number>(req.body.y)
expectType<string>(req.body.x)
})
done()
}


const fastify = Fastify()

fastify.register(asyncPlugin)
fastify.register(callbackPlugin)