diff --git a/package.json b/package.json index 3d40f6f..3dae837 100644 --- a/package.json +++ b/package.json @@ -36,13 +36,13 @@ "@fastify/swagger-ui": "^5.2.5", "@fastify/type-provider-typebox": "^6.1.0", "@scalar/fastify-api-reference": "^1.44.15", - "@sinclair/typebox": "^0.34.48", "fastify": "^5.7.4", "fastify-cli": "^7.4.1", "fastify-plugin": "^5.1.0", "jsonwebtoken": "^9.0.3", "jwks-rsa": "^3.2.2", - "openid-client": "^6.8.2" + "openid-client": "^6.8.2", + "typebox": "^1.0.81" }, "devDependencies": { "@commitlint/cli": "^20.4.1", diff --git a/src/plugins/auth.ts b/src/plugins/auth.ts index 0426607..4a3f129 100644 --- a/src/plugins/auth.ts +++ b/src/plugins/auth.ts @@ -1,12 +1,12 @@ import { ResponseSchema } from "../utils/schema.js"; import { UnionOneOf } from "../utils/typebox/union-oneof.js"; -import { Type } from "@sinclair/typebox"; import { FastifyReply, FastifyRequest } from "fastify"; import fp from "fastify-plugin"; import jwt, { JwtHeader, SigningKeyCallback } from "jsonwebtoken"; import { JwksClient } from "jwks-rsa"; import * as client from "openid-client"; import { skipSubjectCheck, WWWAuthenticateChallengeError } from "openid-client"; +import { Type } from "typebox"; export interface AuthPluginOptions { /** The discovery URL of the OpenID Connect provider. */ diff --git a/src/plugins/sensible.ts b/src/plugins/sensible.ts index 7a56c0b..d93c0fa 100644 --- a/src/plugins/sensible.ts +++ b/src/plugins/sensible.ts @@ -1,6 +1,6 @@ import sensible from "@fastify/sensible"; -import { Type } from "@sinclair/typebox"; import fp from "fastify-plugin"; +import { Type } from "typebox"; export const HttpError = Type.Ref("HttpError"); diff --git a/src/routes/auth-example/index.ts b/src/routes/auth-example/index.ts index 40ea073..2dc6144 100644 --- a/src/routes/auth-example/index.ts +++ b/src/routes/auth-example/index.ts @@ -1,8 +1,8 @@ import { FastifyTypebox } from "../../app.js"; import { AuthResponseSchema } from "../../plugins/auth.js"; import { mergeResponse } from "../../utils/schema.js"; -import { Type } from "@sinclair/typebox"; import { FastifyPluginAsync } from "fastify"; +import { Type } from "typebox"; const authExample: FastifyPluginAsync = async ( fastify: FastifyTypebox, diff --git a/src/routes/example/index.ts b/src/routes/example/index.ts index 712857d..3fd4d48 100644 --- a/src/routes/example/index.ts +++ b/src/routes/example/index.ts @@ -1,7 +1,7 @@ import { FastifyTypebox } from "../../app.js"; import { HttpError } from "../../plugins/sensible.js"; -import { Type } from "@sinclair/typebox"; import { FastifyPluginAsync } from "fastify"; +import { Type } from "typebox"; const example: FastifyPluginAsync = async ( fastify: FastifyTypebox, diff --git a/src/routes/root.ts b/src/routes/root.ts index ede5840..68dc6f3 100644 --- a/src/routes/root.ts +++ b/src/routes/root.ts @@ -1,6 +1,6 @@ import { FastifyTypebox } from "../app.js"; -import { Type } from "@sinclair/typebox"; import { FastifyPluginAsync } from "fastify"; +import { Type } from "typebox"; const root: FastifyPluginAsync = async ( fastify: FastifyTypebox, diff --git a/src/utils/schema.ts b/src/utils/schema.ts index 1356a19..4e1df39 100644 --- a/src/utils/schema.ts +++ b/src/utils/schema.ts @@ -1,5 +1,5 @@ import { UnionOneOf } from "./typebox/union-oneof.js"; -import { TSchema } from "@sinclair/typebox"; +import { TSchema } from "typebox"; export type ResponseSchema = Record; diff --git a/src/utils/typebox/union-oneof.ts b/src/utils/typebox/union-oneof.ts index ebf9ba0..5c0fce0 100644 --- a/src/utils/typebox/union-oneof.ts +++ b/src/utils/typebox/union-oneof.ts @@ -2,7 +2,7 @@ /*-------------------------------------------------------------------------- -@sinclair/typebox/prototypes +typebox/prototypes The MIT License (MIT) @@ -28,25 +28,27 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ -import { TypeRegistry, Kind, Static, TSchema, SchemaOptions } from '@sinclair/typebox' -import { Value } from '@sinclair/typebox/value' +import { TSchema, TSchemaOptions, Static } from 'typebox' // ------------------------------------------------------------------------------------- // TUnionOneOf // ------------------------------------------------------------------------------------- export interface TUnionOneOf extends TSchema { - [Kind]: 'UnionOneOf' + '~kind': 'UnionOneOf' static: { [K in keyof T]: Static }[number] oneOf: T } // ------------------------------------------------------------------------------------- // UnionOneOf // ------------------------------------------------------------------------------------- -/** `[Experimental]` Creates a Union type with a `oneOf` schema representation */ -export function UnionOneOf(oneOf: [...T], options: SchemaOptions = {}) { - function UnionOneOfCheck(schema: TUnionOneOf, value: unknown) { - return 1 === schema.oneOf.reduce((acc: number, schema: any) => (Value.Check(schema, value) ? acc + 1 : acc), 0) - } - if (!TypeRegistry.Has('UnionOneOf')) TypeRegistry.Set('UnionOneOf', UnionOneOfCheck) - return { ...options, [Kind]: 'UnionOneOf', oneOf } as TUnionOneOf +/** + * `[Experimental]` Creates a Union type with a `oneOf` schema representation + * + * Note: Runtime validation of oneOf is handled by the JSON Schema validator (e.g., Ajv) + * which is used by Fastify. The oneOf keyword is a standard JSON Schema keyword that + * ensures exactly one of the schemas matches. This implementation doesn't need custom + * validation logic as the standard validator handles it. + */ +export function UnionOneOf(oneOf: [...T], options: TSchemaOptions = {}) { + return { ...options, '~kind': 'UnionOneOf', oneOf } as TUnionOneOf } diff --git a/yarn.lock b/yarn.lock index b4a4479..11640fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -789,13 +789,6 @@ __metadata: languageName: node linkType: hard -"@sinclair/typebox@npm:^0.34.48": - version: 0.34.48 - resolution: "@sinclair/typebox@npm:0.34.48" - checksum: 10c0/e09f26d8ad471a07ee64004eea7c4ec185349a1f61c03e87e71ea33cbe98e97959940076c2e52968a955ffd4c215bf5ba7035e77079511aac7935f25e989e29d - languageName: node - linkType: hard - "@trivago/prettier-plugin-sort-imports@npm:^6.0.2": version: 6.0.2 resolution: "@trivago/prettier-plugin-sort-imports@npm:6.0.2" @@ -3830,7 +3823,6 @@ __metadata: "@fastify/swagger-ui": "npm:^5.2.5" "@fastify/type-provider-typebox": "npm:^6.1.0" "@scalar/fastify-api-reference": "npm:^1.44.15" - "@sinclair/typebox": "npm:^0.34.48" "@trivago/prettier-plugin-sort-imports": "npm:^6.0.2" "@types/jsonwebtoken": "npm:^9.0.10" "@types/node": "npm:^25.2.2" @@ -3849,6 +3841,7 @@ __metadata: openid-client: "npm:^6.8.2" prettier: "npm:^3.8.1" prettier-plugin-jsdoc: "npm:^1.8.0" + typebox: "npm:^1.0.81" typescript: "npm:^5.9.3" typescript-eslint: "npm:^8.54.0" languageName: unknown @@ -3964,6 +3957,13 @@ __metadata: languageName: node linkType: hard +"typebox@npm:^1.0.81": + version: 1.0.81 + resolution: "typebox@npm:1.0.81" + checksum: 10c0/0944c5a5214a8c218d345dbba30de8384fd00fc6ab6c948e67661e8647c42f04530401f8e6238a556860bb1dbcdf1b300407219c66aac237c6ccaeed22d2460c + languageName: node + linkType: hard + "typescript-eslint@npm:^8.54.0": version: 8.54.0 resolution: "typescript-eslint@npm:8.54.0"