@fastify/type-provider-typebox
Advanced tools
Comparing version 2.0.1 to 2.1.0
@@ -1,5 +0,11 @@ | ||
import { FastifyTypeProvider } from 'fastify'; | ||
import { FastifySchemaCompiler, FastifyTypeProvider } from "fastify"; | ||
import { ValueError } from '@sinclair/typebox/compiler'; | ||
import { Static, TSchema } from '@sinclair/typebox'; | ||
export declare class TypeBoxValidationError extends Error { | ||
readonly errors: ValueError[]; | ||
constructor(errors: ValueError[]); | ||
} | ||
export declare const TypeBoxValidatorCompiler: FastifySchemaCompiler<TSchema>; | ||
export interface TypeBoxTypeProvider extends FastifyTypeProvider { | ||
output: this['input'] extends TSchema ? Static<this['input']> : never; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TypeBoxValidatorCompiler = exports.TypeBoxValidationError = void 0; | ||
const compiler_1 = require("@sinclair/typebox/compiler"); | ||
class TypeBoxValidationError extends Error { | ||
constructor(errors) { | ||
super('[' + errors.map(({ path, message }) => `['${path}', '${message}']`).join(', ') + ']'); | ||
Object.defineProperty(this, "errors", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: errors | ||
}); | ||
} | ||
} | ||
exports.TypeBoxValidationError = TypeBoxValidationError; | ||
const TypeBoxValidatorCompiler = ({ schema }) => { | ||
const typeCheck = compiler_1.TypeCompiler.Compile(schema); | ||
return (value) => { | ||
if (typeCheck.Check(value)) | ||
return; | ||
throw new TypeBoxValidationError([...typeCheck.Errors(value)]); | ||
}; | ||
}; | ||
exports.TypeBoxValidatorCompiler = TypeBoxValidatorCompiler; |
41
index.ts
@@ -1,7 +0,44 @@ | ||
import { FastifyTypeProvider } from 'fastify' | ||
import { FastifySchemaCompiler, FastifyTypeProvider } from "fastify" | ||
import { TypeCompiler, ValueError } from '@sinclair/typebox/compiler' | ||
import { Static, TSchema } from '@sinclair/typebox' | ||
export class TypeBoxValidationError extends Error { | ||
constructor(public readonly errors: ValueError[]) { | ||
super('[' + errors.map(({ path, message }) => `['${path}', '${message}']`).join(', ') + ']') | ||
} | ||
} | ||
/** | ||
* Enables TypeBox schema validation | ||
* | ||
* @example | ||
* ```typescript | ||
* import Fastify from 'fastify' | ||
* | ||
* const server = Fastify().setValidatorCompiler(TypeBoxValidatorCompiler) | ||
* ``` | ||
*/ | ||
export const TypeBoxValidatorCompiler: FastifySchemaCompiler<TSchema> = ({ schema }) => { | ||
const typeCheck = TypeCompiler.Compile(schema) | ||
return (value): any => { | ||
if (typeCheck.Check(value)) return | ||
// Future: Consider returning FastifySchemaValidationError[] structure instead of throw. The TypeBoxValidationError | ||
// does generates human readable (and parsable) error messages, however the FastifySchemaValidationError may be a | ||
// better fit as it would allow Fastify to standardize on error reporting. For consideration. | ||
throw new TypeBoxValidationError([...typeCheck.Errors(value)]) | ||
} | ||
} | ||
/** | ||
* Enables automatic type inference on a Fastify instance. | ||
* | ||
* @example | ||
* ```typescript | ||
* import Fastify from 'fastify' | ||
* | ||
* const server = Fastify().withTypeProvider<TypeBoxTypeProvider>() | ||
* ``` | ||
*/ | ||
export interface TypeBoxTypeProvider extends FastifyTypeProvider { | ||
output: this['input'] extends TSchema ? Static<this['input']> : never | ||
} |
{ | ||
"name": "@fastify/type-provider-typebox", | ||
"version": "2.0.1", | ||
"version": "2.1.0", | ||
"description": "A Type Provider for Typebox over Fastify", | ||
@@ -37,3 +37,3 @@ "main": "dist/index.js", | ||
"tap": "^16.3.0", | ||
"tsd": "^0.21.0" | ||
"tsd": "^0.22.0" | ||
}, | ||
@@ -40,0 +40,0 @@ "tsd": { |
@@ -77,1 +77,27 @@ # fastify-type-provider-typebox | ||
``` | ||
## 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. | ||
```ts | ||
import { TypeBoxTypeProvider, TypeBoxValidatorCompiler } from '@fastify/type-provider-typebox' | ||
import { Type } from '@sinclair/typebox' | ||
import Fastify from 'fastify' | ||
const fastify = Fastify().setValidatorCompiler(TypeBoxValidatorCompiler) | ||
fastify.withTypeProvider<TypeBoxTypeProvider>().get('/', { | ||
schema: { | ||
querystring: Type.Object({ | ||
x: Type.String(), | ||
y: Type.String(), | ||
z: Type.String() | ||
}) | ||
} | ||
}, (req) => { | ||
const { x, y, z } = req.query | ||
}) | ||
``` | ||
For additional information on this compiler, please refer to the TypeBox documentation located [here](https://github.com/sinclairzx81/typebox#Compiler) |
const tap = require('tap') | ||
const Fastify = require('fastify') | ||
const { Type } = require('@sinclair/typebox') | ||
const { TypeBoxValidatorCompiler } = require('../dist/index') | ||
// Tests that Fastify accepts TypeBox schemas without explicit configuration | ||
// This test ensures AJV ignores the TypeBox [Kind] symbol property in strict | ||
tap.test('should compile typebox schema without configuration', async t => { | ||
@@ -17,8 +18,7 @@ t.plan(1) | ||
}, (_req, _res) => { }) | ||
await fastify.listen({ port: 5000 }) | ||
await fastify.close() | ||
await fastify.ready() | ||
t.pass() | ||
}) | ||
// Tests that Fastify rejects unknown properties on the schema. | ||
// This test ensures AJV internally throws for unknown schema properties in strict | ||
tap.test('should not compile schema with unknown keywords', async t => { | ||
@@ -32,12 +32,45 @@ t.plan(1) | ||
z: Type.Number() | ||
}, { kind: 'Object' }) // unknown | ||
}, { kind: 'Object' }) // unknown keyword | ||
} | ||
}, (_req, _res) => { }) | ||
try { | ||
await fastify.listen({ port: 5000 }) // expect throw | ||
await fastify.ready() // expect throw | ||
t.fail() | ||
} catch { | ||
await fastify.close() | ||
t.pass() | ||
} | ||
}) | ||
}) | ||
tap.test('should validate querystring parameters', async t => { | ||
t.plan(1) | ||
const fastify = Fastify().setValidatorCompiler(TypeBoxValidatorCompiler).get('/', { | ||
schema: { | ||
querystring: Type.Object({ | ||
a: Type.String(), | ||
b: Type.String(), | ||
c: Type.String() | ||
}) | ||
} | ||
}, (req, res) => res.send(req.query)) | ||
const { a, b, c } = await fastify.inject().get('/').query({ a: '1', b: '2', c: '3' }).then(res => res.json()) | ||
if (a === '1' && b === '2' & c === '3') { | ||
t.pass() | ||
} else { | ||
t.fail() | ||
} | ||
}) | ||
tap.test('should not validate querystring parameters', async t => { | ||
t.plan(1) | ||
const fastify = Fastify().setValidatorCompiler(TypeBoxValidatorCompiler).get('/', { | ||
schema: { | ||
querystring: Type.Object({ | ||
a: Type.String(), | ||
b: Type.String(), | ||
c: Type.String() | ||
}) | ||
} | ||
}, (req, res) => res.send(req.query)) | ||
const statusCode = await fastify.inject().get('/').query({ a: '1', b: '2' }).then(res => res.statusCode) | ||
t.equal(statusCode, 500) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
12091
171
102
11