From 03a372bb7b6287453965d559367cc6e82b34025e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Felipe=20Schulle?= Date: Fri, 5 Dec 2025 10:34:02 -0300 Subject: [PATCH 1/4] add deprecated version from typebox, compatible from elysia --- .changeset/upset-emus-sort.md | 5 + clean-package.config.json | 5 + package.json | 1 + pnpm-lock.yaml | 8 + src/resolvers/typebox-deprecated.spec.ts | 41 +++++ src/resolvers/typebox-deprecated.ts | 205 +++++++++++++++++++++++ tsup.config.ts | 2 +- 7 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 .changeset/upset-emus-sort.md create mode 100644 src/resolvers/typebox-deprecated.spec.ts create mode 100644 src/resolvers/typebox-deprecated.ts diff --git a/.changeset/upset-emus-sort.md b/.changeset/upset-emus-sort.md new file mode 100644 index 0000000..a553edd --- /dev/null +++ b/.changeset/upset-emus-sort.md @@ -0,0 +1,5 @@ +--- +"@brainylab/resolver-validators": patch +--- + +add deprecated version from typebox, compatible from elysia diff --git a/clean-package.config.json b/clean-package.config.json index 097e4e8..098b5ed 100755 --- a/clean-package.config.json +++ b/clean-package.config.json @@ -15,6 +15,11 @@ "import": "./dist/resolvers/typebox.js", "default": "./dist/resolvers/typebox.js" }, + "./typebox-deprecated": { + "types": "./dist/resolvers/typebox-deprecated.d.ts", + "import": "./dist/resolvers/typebox-deprecated.js", + "default": "./dist/resolvers/typebox-deprecated.js" + }, "./zod": { "types": "./dist/resolvers/zod.d.ts", "import": "./dist/resolvers/zod.js", diff --git a/package.json b/package.json index 545165d..17a9f50 100755 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@changesets/cli": "2.29.8", "@changesets/get-release-plan": "4.0.14", "@changesets/types": "6.1.0", + "@sinclair/typebox": "0.34.41", "@types/node": "^22.7.4", "@vitest/coverage-v8": "2.1.2", "@vitest/ui": "2.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1e0f31..bf00447 100755 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@changesets/types': specifier: 6.1.0 version: 6.1.0 + '@sinclair/typebox': + specifier: 0.34.41 + version: 0.34.41 '@types/node': specifier: ^22.7.4 version: 22.7.4 @@ -833,6 +836,9 @@ packages: cpu: [x64] os: [win32] + '@sinclair/typebox@0.34.41': + resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} + '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} @@ -2390,6 +2396,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true + '@sinclair/typebox@0.34.41': {} + '@standard-schema/spec@1.0.0': {} '@types/chai@5.2.3': diff --git a/src/resolvers/typebox-deprecated.spec.ts b/src/resolvers/typebox-deprecated.spec.ts new file mode 100644 index 0000000..1308253 --- /dev/null +++ b/src/resolvers/typebox-deprecated.spec.ts @@ -0,0 +1,41 @@ +import { Type } from "@sinclair/typebox"; +import { describe, expect, it } from "vitest"; + +import { rv } from "../index"; +import { resolver } from "./typebox-deprecated"; + +describe("TypeBox Deprecated Resolver", () => { + it("resolver core schema to typebox validator", () => { + const coreSchema = rv.object({ + name: rv.string({ description: "description test" }), + age: rv.optional(rv.number()), + isActive: rv.boolean(), + description: rv.nullable(rv.string()), + other: rv.object({ + name: rv.string(), + age: rv.number(), + }), + hobbies: rv.array(rv.string()), + cities: rv.tuple([rv.string(), rv.number()]), + date: rv.or(rv.date(), rv.string()), + }); + + const typeBoxSchema = Type.Object({ + name: Type.String({ description: "description test" }), + age: Type.Optional(Type.Number()), + isActive: Type.Boolean(), + description: Type.Null(Type.String()), + other: Type.Object({ + name: Type.String(), + age: Type.Number(), + }), + hobbies: Type.Array(Type.String()), + cities: Type.Tuple([Type.String(), Type.Number()]), + date: Type.Union([Type.Date(), Type.String()]), + }); + + const resolvedTypeBox = resolver(coreSchema); + + expect(resolvedTypeBox).toEqual(typeBoxSchema); + }); +}); diff --git a/src/resolvers/typebox-deprecated.ts b/src/resolvers/typebox-deprecated.ts new file mode 100644 index 0000000..dc96e85 --- /dev/null +++ b/src/resolvers/typebox-deprecated.ts @@ -0,0 +1,205 @@ +import { + type NumberOptions, + type StringOptions, + type TArray, + type TBoolean, + type TDate, + type TNull, + type TNumber, + type TObject, + type TSchema, + type TString, + type TTuple, + type TUnion, + Type, +} from "@sinclair/typebox"; + +import { isObject } from "@/utils"; + +import type { + RVNumberParams, + RVParams, + RVSchema, + RVStringParams, + RVTypes, +} from "@/types"; + +// import { TBOptional } from "./optional"; +// import { TBRequired } from "./required"; + +function TBString(params?: RVStringParams): TString { + const typeBoxParams: StringOptions = {}; + + const keys: { [key in keyof RVStringParams]: string } = { + min: "minLength", + max: "maxLength", + format: "format", + pattern: "pattern", + description: "description", + }; + + if (params) { + for (const key in keys) { + const mappedKey = keys[key as keyof typeof keys] as keyof RVStringParams; + if (params[key as keyof RVStringParams] !== undefined) { + typeBoxParams[mappedKey] = params[key as keyof RVStringParams]; + } + } + } + + return Type.String(typeBoxParams); +} + +function TBTuple(schemas: TSchema[]): TTuple { + return Type.Tuple(schemas); +} + +function TBUnion(schemas: TSchema[]): TUnion { + return Type.Union(schemas); +} + +function TBArray(schema: TArray): TArray { + return Type.Array(schema); +} + +function TBBoolean(): TBoolean { + return Type.Boolean(); +} + +function TBDate(): TDate { + return Type.Date(); +} + +function TBNullable(schema: TSchema): TNull { + return Type.Null(schema); +} + +function TBOptional(schema: TSchema): TSchema { + return Type.Optional(schema as unknown as TSchema); +} + +function TBNumber(params?: RVNumberParams): TNumber { + const typeBoxParams: NumberOptions = {}; + + const keys: { [key in keyof RVNumberParams]: string } = { + min: "minLength", + max: "maxLength", + description: "description", + }; + + if (params) { + for (const key in keys) { + const mappedKey = keys[key as keyof typeof keys] as keyof RVNumberParams; + if (params[key as keyof RVNumberParams] !== undefined) { + typeBoxParams[mappedKey] = params[key as keyof RVNumberParams]; + } + } + } + + return Type.Number(typeBoxParams); +} + +function TBObject(schema: TObject): TObject { + return Type.Object(schema); +} + +type PrimitiveSchema = { + type: RVTypes; + schema?: RVSchema; + schemas?: RVSchema[]; + params?: RVParams; + optional?: boolean; +}; + +type ResolverObjectSchema = { + type: "object"; + schema: { [key: string]: PrimitiveSchema }; +}; + +function resolverPrimitiveSchema( + options: PrimitiveSchema, +): TSchema | undefined { + if (options.type === "string") { + return TBString(options.params); + } + + if (options.type === "number") { + return TBNumber(options.params); + } + + if (options.type === "boolean") { + return TBBoolean(); + } + + if (options.type === "date") { + return TBDate(); + } + + if (options.type === "array") { + return TBArray( + resolverPrimitiveSchema(options.schema as PrimitiveSchema) as TArray, + ); + } + + if (options.type === "tuple") { + const tuplePrimitiveResolved = options.schemas?.map((schema) => + resolverPrimitiveSchema(schema as PrimitiveSchema), + ); + return TBTuple(tuplePrimitiveResolved as TSchema[]); + } + + if (options.type === "object") { + return resolverObjectSchema( + options as unknown as ResolverObjectSchema, + ) as TObject; + } + + if (options.type === "optional") { + return TBOptional( + resolverPrimitiveSchema(options.schema as PrimitiveSchema) as TSchema, + ); + } + + if (options.type === "nullable") { + return TBNullable( + resolverPrimitiveSchema(options.schema as PrimitiveSchema) as TSchema, + ); + } + + if (options.type === "or") { + return TBUnion( + options.schemas?.map( + (item) => resolverPrimitiveSchema(item as PrimitiveSchema) as TSchema, + ) as TSchema[], + ); + } +} + +function resolverObjectSchema(schema: ResolverObjectSchema) { + if (schema.type === "object") { + const resolvedTypeBox = {} as TObject; + + const primitiveSchema = schema.schema; + + for (const key in primitiveSchema) { + const value = primitiveSchema[key]; + + if (value.type === "optional") { + resolvedTypeBox[key] = resolverPrimitiveSchema(value); + continue; + } + + resolvedTypeBox[key] = resolverPrimitiveSchema(value); + } + + return TBObject(resolvedTypeBox); + } +} + +export function resolver(schema: RVSchema) { + if (isObject(schema)) { + return resolverObjectSchema(schema as ResolverObjectSchema); + } + + return resolverPrimitiveSchema(schema as PrimitiveSchema); +} diff --git a/tsup.config.ts b/tsup.config.ts index d4f187d..fc74495 100755 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -7,5 +7,5 @@ export default defineConfig({ splitting: false, bundle: true, dts: true, - external: ["typebox", "zod"], + external: ["typebox", "zod", "@sinclair/typebox"], }); From 6f7b8322dbe0ebc63068dfa416749f74998bb728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Felipe=20Schulle?= Date: Fri, 5 Dec 2025 13:34:39 +0000 Subject: [PATCH 2/4] ci(changesets): version packages --- .changeset/upset-emus-sort.md | 5 ----- CHANGELOG.md | 6 ++++++ package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) delete mode 100644 .changeset/upset-emus-sort.md diff --git a/.changeset/upset-emus-sort.md b/.changeset/upset-emus-sort.md deleted file mode 100644 index a553edd..0000000 --- a/.changeset/upset-emus-sort.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@brainylab/resolver-validators": patch ---- - -add deprecated version from typebox, compatible from elysia diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e22d27..a4a4924 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # @brainylab/resolver-validators +## 0.8.4 + +### Patch Changes + +- [`03a372b`](https://github.com/brainylab/resolver-validators/commit/03a372bb7b6287453965d559367cc6e82b34025e) Thanks [@andrefelipeschulle](https://github.com/andrefelipeschulle)! - add deprecated version from typebox, compatible from elysia + ## 0.8.3 ### Patch Changes diff --git a/package.json b/package.json index 2940c91..9e2e31b 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@brainylab/resolver-validators", - "version": "0.8.3", + "version": "0.8.4", "description": "", "keywords": [], "bugs": { From f9d86616340db6dc776d837b40a7e78dc65f22f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Felipe=20Schulle?= Date: Fri, 5 Dec 2025 10:52:43 -0300 Subject: [PATCH 3/4] fix: fix build typebox-deprecated --- .changeset/thin-days-burn.md | 5 +++++ package.json | 5 +---- tsup.config.ts | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 .changeset/thin-days-burn.md diff --git a/.changeset/thin-days-burn.md b/.changeset/thin-days-burn.md new file mode 100644 index 0000000..9d84ce1 --- /dev/null +++ b/.changeset/thin-days-burn.md @@ -0,0 +1,5 @@ +--- +"@brainylab/resolver-validators": patch +--- + +fix build typebox-deprecated diff --git a/package.json b/package.json index 9e2e31b..d1c26fa 100755 --- a/package.json +++ b/package.json @@ -20,10 +20,7 @@ ], "type": "module", "scripts": { - "build": "pnpm build:core && pnpm build:resolvers:typebox && pnpm build:resolvers:zod", - "build:core": "pnpm tsup ./src/index.ts --clean", - "build:resolvers:typebox": "pnpm tsup ./src/resolvers/typebox.ts --out-dir dist/resolvers --clean", - "build:resolvers:zod": "pnpm tsup ./src/resolvers/zod.ts --out-dir dist/resolvers", + "build": "pnpm tsup --clean", "commit": "pnpm commit:add && pnpm commit:detail && pnpm commit:push", "commit:add": "git add .", "commit:detail": "cz", diff --git a/tsup.config.ts b/tsup.config.ts index fc74495..5c9876f 100755 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,11 +1,11 @@ import { defineConfig } from "tsup"; export default defineConfig({ - entry: ["!./src/**/*.spec.ts"], + entry: ["src", "!./src/**/*.spec.ts"], target: "es2022", format: ["esm"], splitting: false, - bundle: true, + bundle: false, dts: true, external: ["typebox", "zod", "@sinclair/typebox"], }); From 9c47f41b4d50a40477c45537c5d253cfb27e9466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Felipe=20Schulle?= Date: Fri, 5 Dec 2025 13:53:13 +0000 Subject: [PATCH 4/4] ci(changesets): version packages --- .changeset/thin-days-burn.md | 5 ----- CHANGELOG.md | 6 ++++++ package.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) delete mode 100644 .changeset/thin-days-burn.md diff --git a/.changeset/thin-days-burn.md b/.changeset/thin-days-burn.md deleted file mode 100644 index 9d84ce1..0000000 --- a/.changeset/thin-days-burn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@brainylab/resolver-validators": patch ---- - -fix build typebox-deprecated diff --git a/CHANGELOG.md b/CHANGELOG.md index a4a4924..d2516c3 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # @brainylab/resolver-validators +## 0.8.5 + +### Patch Changes + +- [`f9d8661`](https://github.com/brainylab/resolver-validators/commit/f9d86616340db6dc776d837b40a7e78dc65f22f4) Thanks [@andrefelipeschulle](https://github.com/andrefelipeschulle)! - fix build typebox-deprecated + ## 0.8.4 ### Patch Changes diff --git a/package.json b/package.json index d1c26fa..1b25556 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@brainylab/resolver-validators", - "version": "0.8.4", + "version": "0.8.5", "description": "", "keywords": [], "bugs": {