Revision 0.8.0 (#9)

- Rename to TypeMap
This commit is contained in:
sinclairzx81
2025-01-26 03:27:38 +09:00
committed by GitHub
parent d24876b2ac
commit 5ce19b2f4f
52 changed files with 3769 additions and 1228 deletions

120
src/compile/compile.ts Normal file
View File

@@ -0,0 +1,120 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TypeCompiler, TypeCheck, ValueErrorIterator } from '@sinclair/typebox/compiler'
import { Value } from '@sinclair/typebox/value'
import { TypeBox, TTypeBox } from '../typebox/typebox'
import { StandardSchemaV1 } from './standard'
import { IsEvalSupported } from './environment'
import * as t from '@sinclair/typebox'
// ------------------------------------------------------------------
// StandardSchemaProps
// ------------------------------------------------------------------
export class StandardSchemaProps<Type extends t.TSchema> implements StandardSchemaV1.Props<Type, t.Static<Type>> {
readonly #check: TypeCheck<Type>
constructor(check: TypeCheck<Type>) {
this.#check = check
}
// ----------------------------------------------------------------
// StandardSchemaV1.Props<Type, t.Static<Type>>
// ----------------------------------------------------------------
public get vendor(): '@sinclair/typemap' {
return '@sinclair/typemap'
}
public get version(): 1 {
return 1
}
public get types(): { input: Type; output: t.Static<Type> } {
return { input: this.#check.Schema(), output: null }
}
public validate(value: unknown): StandardSchemaV1.Result<t.Static<Type>> {
return this.#check.Check(value) ? this.#createValue(value) : this.#createIssues(value)
}
// ----------------------------------------------------------------
// Internal
// ----------------------------------------------------------------
#createIssues(value: unknown) {
const errors = [...Value.Errors(this.#check.Schema(), value)]
const issues: StandardSchemaV1.Issue[] = errors.map((error) => ({ ...error, path: [error.path] }))
return { issues }
}
#createValue(value: unknown) {
return { value }
}
}
// ------------------------------------------------------------------
// Validator<TSchema>
// ------------------------------------------------------------------
export class Validator<Type extends t.TSchema> implements StandardSchemaV1<Type, t.Static<Type>> {
readonly #standard: StandardSchemaProps<Type>
readonly #check: TypeCheck<Type>
constructor(check: TypeCheck<Type>) {
this.#standard = new StandardSchemaProps<Type>(check)
this.#check = check
}
/** Standard Schema Interface */
public get ['~standard'](): StandardSchemaProps<Type> {
return this.#standard
}
/** Parses this value. Do not use this function for high throughput validation */
public Parse(value: unknown): t.StaticDecode<Type> {
return Value.Parse(this.#check.Schema(), value)
}
/** Checks if this value matches the type */
public Check(value: unknown): value is t.Static<Type> {
return this.#check.Check(value)
}
/** Returns errors for this value */
public Errors(value: unknown): ValueErrorIterator {
return this.#check.Errors(value)
}
}
// ------------------------------------------------------------------
// CompileDynamic
// ------------------------------------------------------------------
// prettier-ignore
function CompileDynamic<Type extends t.TSchema>(type: Type, references: t.TSchema[] = []): TypeCheck<Type> {
return new TypeCheck(type, references, value => Value.Check(type, references, value), TypeCompiler.Code(type, references))
}
// ------------------------------------------------------------------
// Compile
// ------------------------------------------------------------------
/** Compiles a type for high performance validation */
// prettier-ignore
type TCompile<Type extends object | string,
Schema extends t.TSchema = TTypeBox<Type>,
Result extends Validator<Schema> = Validator<Schema>
> = Result
/** Compiles a type for high performance validation */
// prettier-ignore
export function Compile<Type extends object | string>(type: Type): TCompile<Type> {
const schema = TypeBox(type)
const check = IsEvalSupported() ? TypeCompiler.Compile(schema) : CompileDynamic(schema)
return new Validator(check)
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typebox-adapter
@sinclair/typemap
The MIT License (MIT)
@@ -26,4 +26,18 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
export * from './box'
/** Cached: flag to indicate if the environment supports runtime evaluation */
let isEvalSupported: boolean | undefined = undefined
// prettier-ignore
function TryEval(): boolean {
try { new Function('null')(); return true } catch { return false }
}
/** Tests if the environment supports eval */
// prettier-ignore
export function IsEvalSupported(): boolean {
if(isEvalSupported === undefined) {
isEvalSupported = TryEval()
}
return isEvalSupported
}

82
src/compile/standard.ts Normal file
View File

@@ -0,0 +1,82 @@
/*--------------------------------------------------------------------------
MIT License
Copyright (c) 2024 Colin McDonnell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------------------------*/
/** The Standard Schema interface. */
export interface StandardSchemaV1<Input = unknown, Output = Input> {
/** The Standard Schema properties. */
readonly '~standard': StandardSchemaV1.Props<Input, Output>
}
export declare namespace StandardSchemaV1 {
/** The Standard Schema properties interface. */
export interface Props<Input = unknown, Output = Input> {
/** The version number of the standard. */
readonly version: 1
/** The vendor name of the schema library. */
readonly vendor: string
/** Validates unknown input values. */
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>
/** Inferred types associated with the schema. */
readonly types?: Types<Input, Output> | undefined
}
/** The result interface of the validate function. */
export type Result<Output> = SuccessResult<Output> | FailureResult
/** The result interface if validation succeeds. */
export interface SuccessResult<Output> {
/** The typed output value. */
readonly value: Output
/** The non-existent issues. */
readonly issues?: undefined
}
/** The result interface if validation fails. */
export interface FailureResult {
/** The issues of failed validation. */
readonly issues: ReadonlyArray<Issue>
}
/** The issue interface of the failure output. */
export interface Issue {
/** The error message of the issue. */
readonly message: string
/** The path of the issue, if any. */
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined
}
/** The path segment interface of the issue. */
export interface PathSegment {
/** The key representing a path segment. */
readonly key: PropertyKey
}
/** The Standard Schema types interface. */
export interface Types<Input = unknown, Output = Input> {
/** The input type of the schema. */
readonly input: Input
/** The output type of the schema. */
readonly output: Output
}
/** Infers the input type of a Standard Schema. */
export type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['input']
/** Infers the output type of a Standard Schema. */
export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema['~standard']['types']>['output']
}

85
src/guard.ts Normal file
View File

@@ -0,0 +1,85 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as v from 'valibot'
import * as z from 'zod'
// ------------------------------------------------------------------
// Syntax
// ------------------------------------------------------------------
/** Returns true if the given value is a Syntax type */
export type TIsSyntax<Type extends unknown> = Type extends string ? true : false
/** Returns true if the given value is a Syntax type */
export function IsSyntax(type: unknown): type is string {
return t.ValueGuard.IsString(type)
}
// ------------------------------------------------------------------
// TypeBox
// ------------------------------------------------------------------
/** Returns true if the given value is a TypeBox type */
export type TIsTypeBox<Type extends unknown> = Type extends t.TSchema ? true : false
/** Returns true if the given value is a TypeBox type */
export function IsTypeBox(type: unknown): type is t.TSchema {
return t.KindGuard.IsSchema(type)
}
// ------------------------------------------------------------------
// Valibot
// ------------------------------------------------------------------
/** Returns true if the given value is a Valibot type */
// prettier-ignore
export type TIsValibot<Type extends unknown> = (
Type extends v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>
? Type extends { '~standard': { vendor: 'valibot' } }
? true
: false
: false
)
/** Returns true if the given value is a Valibot type */
// prettier-ignore
export function IsValibot(type: unknown): type is v.AnySchema {
return (
t.ValueGuard.IsObject(type) &&
t.ValueGuard.HasPropertyKey(type, '~standard') &&
t.ValueGuard.IsObject(type['~standard']) &&
t.ValueGuard.HasPropertyKey(type['~standard'], 'vendor') &&
type['~standard'].vendor === 'valibot'
)
}
// ------------------------------------------------------------------
// Zod
// ------------------------------------------------------------------
// prettier-ignore
/** Returns true if the given value is a Zod type */
export type TIsZod<Type extends unknown> = (
Type extends z.ZodTypeAny ? true : false
)
/** Returns true if the given value is a Zod type */
export function IsZod(type: unknown): type is z.ZodTypeAny {
return t.ValueGuard.IsObject(type) && t.ValueGuard.HasPropertyKey(type, '~standard') && t.ValueGuard.IsObject(type['~standard']) && t.ValueGuard.HasPropertyKey(type['~standard'], 'vendor') && type['~standard'].vendor === 'zod'
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typebox-adapter
@sinclair/typemap
The MIT License (MIT)
@@ -26,4 +26,8 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
export * from './box'
export { type Static } from './static'
export * from './compile/compile'
export * from './typebox/typebox'
export * from './valibot/valibot'
export * from './zod/zod'

44
src/static.ts Normal file
View File

@@ -0,0 +1,44 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as s from '@sinclair/typebox/syntax'
import * as t from '@sinclair/typebox'
import * as v from 'valibot'
import * as z from 'zod'
type BaseSchema = v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>
/** Statically infers a type */
// prettier-ignore
export type Static<Type extends object | string> = (
Type extends string ? s.StaticParseAsType<{}, Type> :
Type extends t.TSchema ? t.Static<Type> :
Type extends BaseSchema ? v.InferInput<Type> :
Type extends z.ZodTypeAny ? z.infer<Type> :
never
)

View File

@@ -0,0 +1,44 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { StaticParseAsSchema, Parse } from '@sinclair/typebox/syntax'
import * as t from '@sinclair/typebox'
// prettier-ignore
export type TTypeBoxFromSyntax<
Type extends string | object,
Parsed = Type extends string ? StaticParseAsSchema<{}, Type> : t.TNever,
Result extends t.TSchema = Parsed extends t.TSchema ? Parsed : t.TNever
> = Result
// prettier-ignore
export function TypeBoxFromSyntax<Type extends string | object>(type: Type): TTypeBoxFromSyntax<Type> {
const parsed = t.ValueGuard.IsString(type) ? Parse(type) : t.Never()
const result = t.KindGuard.IsSchema(parsed) ? parsed : t.Never()
return result as never
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typebox-adapter
@sinclair/typemap
The MIT License (MIT)
@@ -26,4 +26,13 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
export * from './box'
import * as t from '@sinclair/typebox'
// prettier-ignore
export type TTypeBoxFromTypeBox<Type extends unknown> = (
Type extends t.TSchema ? Type : t.TNever
)
// prettier-ignore
export function TypeBoxFromTypeBox<Type extends unknown, Result extends TTypeBoxFromTypeBox<Type> = TTypeBoxFromTypeBox<Type>>(type: Type): Result {
return (t.KindGuard.IsSchema(type) ? type : t.Never()) as never
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typebox-adapter
@sinclair/typemap
The MIT License (MIT)
@@ -26,14 +26,15 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as tb from '@sinclair/typebox'
import * as t from '@sinclair/typebox'
import * as v from 'valibot'
import * as Guard from '../guard'
// ------------------------------------------------------------------
// Options
// ------------------------------------------------------------------
function IsSchemaWithPipe(type: BaseSchema): type is v.SchemaWithPipe<[BaseSchema, ...BaseValidation[]]> {
return tb.ValueGuard.IsObject(type) && tb.ValueGuard.HasPropertyKey(type, 'pipe') && tb.ValueGuard.IsArray(type.pipe)
return t.ValueGuard.IsObject(type) && t.ValueGuard.HasPropertyKey(type, 'pipe') && t.ValueGuard.IsArray(type.pipe)
}
// prettier-ignore
function Options(type: BaseSchema) {
@@ -42,19 +43,19 @@ function Options(type: BaseSchema) {
return {
...options, ...(
action.type === 'args' ? {} :
action.type === 'base64' ? { format: 'valibot:base64' } :
action.type === 'bic' ? { format: 'valibot:bic' } :
action.type === 'base64' ? { format: 'base64' } :
action.type === 'bic' ? { format: 'bic' } :
action.type === 'brand' ? {} :
action.type === 'bytes' ? {} :
action.type === 'check' ? {} :
action.type === 'check_items' ? {} :
action.type === 'credit_card' ? { format: 'valibot:credit_card' } :
action.type === 'cuid2' ? { format: 'valibot:cuid2' } :
action.type === 'decimal' ? { format: 'valibot:decimal' } :
action.type === 'credit_card' ? { format: 'credit_card' } :
action.type === 'cuid2' ? { format: 'cuid2' } :
action.type === 'decimal' ? { format: 'decimal' } :
action.type === 'description' ? { description: action.description } :
action.type === 'digits' ? { format: 'valibot:digits' } :
action.type === 'email' ? { format: 'valibot:email' } :
action.type === 'emoji' ? { format: 'valibot:emoji' } :
action.type === 'digits' ? { format: 'digits' } :
action.type === 'email' ? { format: 'email' } :
action.type === 'emoji' ? { format: 'emoji' } :
action.type === 'empty' ? (
type.type === 'array' ? { maxItems: 0 } :
type.type === 'string' ? { maxLength: 0 } :
@@ -71,26 +72,26 @@ function Options(type: BaseSchema) {
action.type === 'hex_color' ? {} :
action.type === 'imei' ? {} :
action.type === 'includes' ? (
type.type === 'array' ? { contains: tb.Literal(action.requirement) } :
type.type === 'array' ? { contains: t.Literal(action.requirement) } :
type.type === 'string' ? { pattern: action.requirement } :
{}) :
action.type === 'integer' ? { multipleOf: 1 } :
action.type === 'ip' ? { format: 'valibot:ip' } :
action.type === 'ipv4' ? { format: 'valibot:ipv4' } :
action.type === 'ipv6' ? { format: 'valibot:ipv6' } :
action.type === 'iso_date' ? { format: 'valibot:iso_date' } :
action.type === 'iso_date_time' ? { format: 'valibot:iso_date_time' } :
action.type === 'iso_time' ? { format: 'valibot:iso_time' } :
action.type === 'iso_time_second' ? { format: 'valibot:iso_time_second' } :
action.type === 'iso_timestamp' ? { format: 'valibot:iso_timestamp' } :
action.type === 'iso_week' ? { format: 'valibot:iso_week' } :
action.type === 'ip' ? { format: 'ip' } :
action.type === 'ipv4' ? { format: 'ipv4' } :
action.type === 'ipv6' ? { format: 'ipv6' } :
action.type === 'iso_date' ? { format: 'iso_date' } :
action.type === 'iso_date_time' ? { format: 'iso_date_time' } :
action.type === 'iso_time' ? { format: 'iso_time' } :
action.type === 'iso_time_second' ? { format: 'iso_time_second' } :
action.type === 'iso_timestamp' ? { format: 'iso_timestamp' } :
action.type === 'iso_week' ? { format: 'iso_week' } :
action.type === 'length' ? (
type.type === 'string' ? { minLength: action.requirement, maxLength: action.requirement } :
type.type === 'array' ? { minItems: action.requirement, maxItems: action.requirement } :
{}) :
action.type === 'mac' ? { format: 'valibot:mac' } :
action.type === 'mac48' ? { format: 'valibot:mac48' } :
action.type === 'mac64' ? { format: 'valibot:mac64' } :
action.type === 'mac' ? { format: 'mac' } :
action.type === 'mac48' ? { format: 'mac48' } :
action.type === 'mac64' ? { format: 'mac64' } :
action.type === 'map_items' ? {} :
action.type === 'max_bytes' ? {} :
action.type === 'max_graphemes' ? {} :
@@ -101,7 +102,7 @@ function Options(type: BaseSchema) {
action.type === 'max_size' ? {} :
action.type === 'max_value' ? { maximum: action.requirement } :
action.type === 'max_words' ? {} :
action.type === 'metadata' ? { ...action.metadata } :
action.type === 'metadata' ? { metadata: action.metadata } :
action.type === 'mime_type' ? {} :
action.type === 'min_bytes' ? {} :
action.type === 'min_graphemes' ? {} :
@@ -113,7 +114,7 @@ function Options(type: BaseSchema) {
action.type === 'min_value' ? { minimum: action.requirement } :
action.type === 'min_words' ? {} :
action.type === 'multiple_of' ? { multipleOf: action.requirement } :
action.type === 'nanoid' ? { format: 'valibot:nanoid' } :
action.type === 'nanoid' ? { format: 'nanoid' } :
action.type === 'non_empty' ? {} :
action.type === 'normalize' ? {} :
action.type === 'not_bytes' ? {} :
@@ -122,7 +123,7 @@ function Options(type: BaseSchema) {
action.type === 'not_size' ? {} :
action.type === 'not_value' ? {} :
action.type === 'not_words' ? {} :
action.type === 'octal' ? { format: 'valibot:octal' } :
action.type === 'octal' ? { format: 'octal' } :
action.type === 'partial_check' ? {} :
action.type === 'raw_check' ? {} :
action.type === 'raw_transform' ? {} :
@@ -144,9 +145,9 @@ function Options(type: BaseSchema) {
action.type === 'trim' ? {} :
action.type === 'trim_end' ? {} :
action.type === 'trim_start' ? {} :
action.type === 'ulid' ? { format: 'valibot:ulid' } :
action.type === 'url' ? { format: 'valibot:url' } :
action.type === 'uuid' ? { format: 'valibot:uuid' } :
action.type === 'ulid' ? { format: 'ulid' } :
action.type === 'url' ? { format: 'url' } :
action.type === 'uuid' ? { format: 'uuid' } :
action.type === 'value' ? {} :
action.type === 'words' ? {} :
{})
@@ -156,31 +157,31 @@ function Options(type: BaseSchema) {
// ------------------------------------------------------------------
// Formats
// ------------------------------------------------------------------
tb.FormatRegistry.Set('valibot:base64', (value) => v.safeParse(v.pipe(v.string(), v.base64()), value).success)
tb.FormatRegistry.Set('valibot:bic', (value) => v.safeParse(v.pipe(v.string(), v.bic()), value).success)
tb.FormatRegistry.Set('valibot:credit_card', (value) => v.safeParse(v.pipe(v.string(), v.creditCard()), value).success)
tb.FormatRegistry.Set('valibot:cuid2', (value) => v.safeParse(v.pipe(v.string(), v.cuid2()), value).success)
tb.FormatRegistry.Set('valibot:decimal', (value) => v.safeParse(v.pipe(v.string(), v.decimal()), value).success)
tb.FormatRegistry.Set('valibot:digits', (value) => v.safeParse(v.pipe(v.string(), v.digits()), value).success)
tb.FormatRegistry.Set('valibot:email', (value) => v.safeParse(v.pipe(v.string(), v.email()), value).success)
tb.FormatRegistry.Set('valibot:emoji', (value) => v.safeParse(v.pipe(v.string(), v.emoji()), value).success)
tb.FormatRegistry.Set('valibot:ip', (value) => v.safeParse(v.pipe(v.string(), v.ip()), value).success)
tb.FormatRegistry.Set('valibot:ipv4', (value) => v.safeParse(v.pipe(v.string(), v.ipv4()), value).success)
tb.FormatRegistry.Set('valibot:ipv6', (value) => v.safeParse(v.pipe(v.string(), v.ipv6()), value).success)
tb.FormatRegistry.Set('valibot:iso_date', (value) => v.safeParse(v.pipe(v.string(), v.isoDate()), value).success)
tb.FormatRegistry.Set('valibot:iso_date_time', (value) => v.safeParse(v.pipe(v.string(), v.isoDateTime()), value).success)
tb.FormatRegistry.Set('valibot:iso_time', (value) => v.safeParse(v.pipe(v.string(), v.isoTime()), value).success)
tb.FormatRegistry.Set('valibot:iso_time_second', (value) => v.safeParse(v.pipe(v.string(), v.isoTimeSecond()), value).success)
tb.FormatRegistry.Set('valibot:iso_timestamp', (value) => v.safeParse(v.pipe(v.string(), v.isoTimestamp()), value).success)
tb.FormatRegistry.Set('valibot:iso_week', (value) => v.safeParse(v.pipe(v.string(), v.isoWeek()), value).success)
tb.FormatRegistry.Set('valibot:mac', (value) => v.safeParse(v.pipe(v.string(), v.mac()), value).success)
tb.FormatRegistry.Set('valibot:mac48', (value) => v.safeParse(v.pipe(v.string(), v.mac48()), value).success)
tb.FormatRegistry.Set('valibot:mac64', (value) => v.safeParse(v.pipe(v.string(), v.mac64()), value).success)
tb.FormatRegistry.Set('valibot:nanoid', (value) => v.safeParse(v.pipe(v.string(), v.nanoid()), value).success)
tb.FormatRegistry.Set('valibot:octal', (value) => v.safeParse(v.pipe(v.string(), v.octal()), value).success)
tb.FormatRegistry.Set('valibot:ulid', (value) => v.safeParse(v.pipe(v.string(), v.ulid()), value).success)
tb.FormatRegistry.Set('valibot:url', (value) => v.safeParse(v.pipe(v.string(), v.url()), value).success)
tb.FormatRegistry.Set('valibot:uuid', (value) => v.safeParse(v.pipe(v.string(), v.uuid()), value).success)
t.FormatRegistry.Set('base64', (value) => v.safeParse(v.pipe(v.string(), v.base64()), value).success)
t.FormatRegistry.Set('bic', (value) => v.safeParse(v.pipe(v.string(), v.bic()), value).success)
t.FormatRegistry.Set('credit_card', (value) => v.safeParse(v.pipe(v.string(), v.creditCard()), value).success)
t.FormatRegistry.Set('cuid2', (value) => v.safeParse(v.pipe(v.string(), v.cuid2()), value).success)
t.FormatRegistry.Set('decimal', (value) => v.safeParse(v.pipe(v.string(), v.decimal()), value).success)
t.FormatRegistry.Set('digits', (value) => v.safeParse(v.pipe(v.string(), v.digits()), value).success)
t.FormatRegistry.Set('email', (value) => v.safeParse(v.pipe(v.string(), v.email()), value).success)
t.FormatRegistry.Set('emoji', (value) => v.safeParse(v.pipe(v.string(), v.emoji()), value).success)
t.FormatRegistry.Set('ip', (value) => v.safeParse(v.pipe(v.string(), v.ip()), value).success)
t.FormatRegistry.Set('ipv4', (value) => v.safeParse(v.pipe(v.string(), v.ipv4()), value).success)
t.FormatRegistry.Set('ipv6', (value) => v.safeParse(v.pipe(v.string(), v.ipv6()), value).success)
t.FormatRegistry.Set('iso_date', (value) => v.safeParse(v.pipe(v.string(), v.isoDate()), value).success)
t.FormatRegistry.Set('iso_date_time', (value) => v.safeParse(v.pipe(v.string(), v.isoDateTime()), value).success)
t.FormatRegistry.Set('iso_time', (value) => v.safeParse(v.pipe(v.string(), v.isoTime()), value).success)
t.FormatRegistry.Set('iso_time_second', (value) => v.safeParse(v.pipe(v.string(), v.isoTimeSecond()), value).success)
t.FormatRegistry.Set('iso_timestamp', (value) => v.safeParse(v.pipe(v.string(), v.isoTimestamp()), value).success)
t.FormatRegistry.Set('iso_week', (value) => v.safeParse(v.pipe(v.string(), v.isoWeek()), value).success)
t.FormatRegistry.Set('mac', (value) => v.safeParse(v.pipe(v.string(), v.mac()), value).success)
t.FormatRegistry.Set('mac48', (value) => v.safeParse(v.pipe(v.string(), v.mac48()), value).success)
t.FormatRegistry.Set('mac64', (value) => v.safeParse(v.pipe(v.string(), v.mac64()), value).success)
t.FormatRegistry.Set('nanoid', (value) => v.safeParse(v.pipe(v.string(), v.nanoid()), value).success)
t.FormatRegistry.Set('octal', (value) => v.safeParse(v.pipe(v.string(), v.octal()), value).success)
t.FormatRegistry.Set('ulid', (value) => v.safeParse(v.pipe(v.string(), v.ulid()), value).success)
t.FormatRegistry.Set('url', (value) => v.safeParse(v.pipe(v.string(), v.url()), value).success)
t.FormatRegistry.Set('uuid', (value) => v.safeParse(v.pipe(v.string(), v.uuid()), value).success)
// ------------------------------------------------------------------
// Schema
@@ -191,156 +192,156 @@ type BaseRecordKey = v.BaseSchema<string, string | number | symbol, v.BaseIssue<
// ------------------------------------------------------------------
// Any
// ------------------------------------------------------------------
type TFromAny<_Type extends v.AnySchema> = tb.Ensure<tb.TAny>
function FromAny(type: BaseSchema): tb.TSchema {
return tb.Any(Options(type))
type TFromAny<_Type extends v.AnySchema> = t.Ensure<t.TAny>
function FromAny(type: BaseSchema): t.TSchema {
return t.Any(Options(type))
}
// ------------------------------------------------------------------
// Array
// ------------------------------------------------------------------
type TFromArray<Type extends BaseSchema> = tb.Ensure<tb.TArray<TFromType<Type>>>
function FromArray(type: BaseSchema): tb.TSchema {
return tb.Array(FromType((type as v.ArraySchema<any, any>).item), Options(type))
type TFromArray<Type extends BaseSchema> = t.Ensure<t.TArray<TFromType<Type>>>
function FromArray(type: BaseSchema): t.TSchema {
return t.Array(FromType((type as v.ArraySchema<any, any>).item), Options(type))
}
// ------------------------------------------------------------------
// BigInt
// ------------------------------------------------------------------
type TFromBigInt<_Type extends v.BigintSchema<any>> = tb.Ensure<tb.TBigInt>
function FromBigInt(type: BaseSchema): tb.TSchema {
return tb.BigInt(Options(type))
type TFromBigInt<_Type extends v.BigintSchema<any>> = t.Ensure<t.TBigInt>
function FromBigInt(type: BaseSchema): t.TSchema {
return t.BigInt(Options(type))
}
// ------------------------------------------------------------------
// Blob
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TBlob>('ValibotBlob', (schema, value) => {
t.TypeRegistry.Set<TBlob>('ValibotBlob', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
interface TBlob<Type extends v.BlobSchema<any> = v.BlobSchema<any>> extends tb.TSchema {
[tb.Kind]: 'ValibotBlob'
interface TBlob<Type extends v.BlobSchema<any> = v.BlobSchema<any>> extends t.TSchema {
[t.Kind]: 'ValibotBlob'
static: v.InferOutput<this['type']>
type: Type
}
function _Blob(type: v.BlobSchema<any>, options?: tb.SchemaOptions): TBlob {
return tb.CreateType({ [tb.Kind]: 'ValibotBlob', type }, options) as never
function _Blob(type: v.BlobSchema<any>, options?: t.SchemaOptions): TBlob {
return t.CreateType({ [t.Kind]: 'ValibotBlob', type }, options) as never
}
type TFromBlob<Type extends v.BlobSchema<any>> = tb.Ensure<TBlob<Type>>
function FromBlob(type: BaseSchema): tb.TSchema {
type TFromBlob<Type extends v.BlobSchema<any>> = t.Ensure<TBlob<Type>>
function FromBlob(type: BaseSchema): t.TSchema {
return _Blob(type as v.BlobSchema<any>, Options(type))
}
// ------------------------------------------------------------------
// Boolean
// ------------------------------------------------------------------
type TFromBoolean<_Type extends v.BooleanSchema<any>> = tb.TBoolean
function FromBoolean(type: BaseSchema): tb.TSchema {
return tb.Boolean(Options(type))
type TFromBoolean<_Type extends v.BooleanSchema<any>> = t.TBoolean
function FromBoolean(type: BaseSchema): t.TSchema {
return t.Boolean(Options(type))
}
// ------------------------------------------------------------------
// Custom
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TCustom>('ValibotCustom', (schema, value) => v.safeParse(schema.schema, value).success)
export interface TCustom<Type extends v.CustomSchema<any, any> = v.CustomSchema<any, any>> extends tb.TSchema {
[tb.Kind]: 'ValibotCustom'
t.TypeRegistry.Set<TCustom>('ValibotCustom', (schema, value) => v.safeParse(schema.schema, value).success)
export interface TCustom<Type extends v.CustomSchema<any, any> = v.CustomSchema<any, any>> extends t.TSchema {
[t.Kind]: 'ValibotCustom'
static: v.InferOutput<this['type']>
type: Type
}
function Custom<Type extends v.CustomSchema<any, any>>(type: Type, options?: tb.SchemaOptions): TCustom<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotCustom', type }, options) as never
function Custom<Type extends v.CustomSchema<any, any>>(type: Type, options?: t.SchemaOptions): TCustom<Type> {
return t.CreateType({ [t.Kind]: 'ValibotCustom', type }, options) as never
}
type TFromCustom<Type extends v.CustomSchema<any, any>> = tb.Ensure<TCustom<Type>>
function FromCustom(type: BaseSchema): tb.TSchema {
type TFromCustom<Type extends v.CustomSchema<any, any>> = t.Ensure<TCustom<Type>>
function FromCustom(type: BaseSchema): t.TSchema {
return Custom(type as v.CustomSchema<any, any>, Options(type))
}
// ------------------------------------------------------------------
// Date
// ------------------------------------------------------------------
type TFromDate<_Type extends v.DateSchema<any>> = tb.TDate
function FromDate(type: BaseSchema): tb.TSchema {
return tb.Date(Options(type))
type TFromDate<_Type extends v.DateSchema<any>> = t.TDate
function FromDate(type: BaseSchema): t.TSchema {
return t.Date(Options(type))
}
// ------------------------------------------------------------------
// Enum
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TValibotEnum>('ValibotEnum', (schema, value) => {
t.TypeRegistry.Set<TValibotEnum>('ValibotEnum', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TValibotEnum<Type extends v.EnumSchema<v.Enum, any> = v.EnumSchema<v.Enum, any>> extends tb.TSchema {
[tb.Kind]: 'ValibotEnum'
export interface TValibotEnum<Type extends v.EnumSchema<v.Enum, any> = v.EnumSchema<v.Enum, any>> extends t.TSchema {
[t.Kind]: 'ValibotEnum'
static: v.InferOutput<this['type']>
type: Type
}
function ValibotEnum<Type extends v.EnumSchema<v.Enum, any>>(type: Type, options?: tb.SchemaOptions): TValibotEnum<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotEnum', type }, options) as never
function ValibotEnum<Type extends v.EnumSchema<v.Enum, any>>(type: Type, options?: t.SchemaOptions): TValibotEnum<Type> {
return t.CreateType({ [t.Kind]: 'ValibotEnum', type }, options) as never
}
type TFromEnum<Enum extends v.EnumSchema<v.Enum, any>> = TValibotEnum<Enum>
function FromEnum<Type extends BaseSchema>(type: Type): tb.TSchema {
function FromEnum<Type extends BaseSchema>(type: Type): t.TSchema {
return ValibotEnum(type as never as v.EnumSchema<v.Enum, any>, Options(type))
}
// ------------------------------------------------------------------
// File
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TFile>('ValibotFile', (schema, value) => {
t.TypeRegistry.Set<TFile>('ValibotFile', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TFile<Type extends v.FileSchema<any> = v.FileSchema<any>> extends tb.TSchema {
[tb.Kind]: 'ValibotFile'
export interface TFile<Type extends v.FileSchema<any> = v.FileSchema<any>> extends t.TSchema {
[t.Kind]: 'ValibotFile'
static: v.InferOutput<this['type']>
type: Type
}
function _File(type: v.FileSchema<any>, options?: tb.SchemaOptions): TFile {
return tb.CreateType({ [tb.Kind]: 'ValibotFile', type }, options) as never
function _File(type: v.FileSchema<any>, options?: t.SchemaOptions): TFile {
return t.CreateType({ [t.Kind]: 'ValibotFile', type }, options) as never
}
type TFromFile<Type extends v.FileSchema<any>> = tb.Ensure<TFile<Type>>
function FromFile(type: BaseSchema): tb.TSchema {
type TFromFile<Type extends v.FileSchema<any>> = t.Ensure<TFile<Type>>
function FromFile(type: BaseSchema): t.TSchema {
return _File(type as v.FileSchema<any>, Options(type))
}
// ------------------------------------------------------------------
// Function
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TFunction>('ValibotFunction', (schema, value) => {
t.TypeRegistry.Set<TFunction>('ValibotFunction', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TFunction<Type extends v.FunctionSchema<any> = v.FunctionSchema<any>> extends tb.TSchema {
[tb.Kind]: 'ValibotFunction'
export interface TFunction<Type extends v.FunctionSchema<any> = v.FunctionSchema<any>> extends t.TSchema {
[t.Kind]: 'ValibotFunction'
static: v.InferOutput<this['type']>
type: Type
}
function _Function<Type extends v.FunctionSchema<any>>(type: Type, options?: tb.SchemaOptions): TFunction<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotFunction', type }, options) as never
function _Function<Type extends v.FunctionSchema<any>>(type: Type, options?: t.SchemaOptions): TFunction<Type> {
return t.CreateType({ [t.Kind]: 'ValibotFunction', type }, options) as never
}
type TFromFunction<Type extends v.FunctionSchema<any>> = tb.Ensure<TFunction<Type>>
function FromFunction(type: BaseSchema): tb.TSchema {
type TFromFunction<Type extends v.FunctionSchema<any>> = t.Ensure<TFunction<Type>>
function FromFunction(type: BaseSchema): t.TSchema {
return _Function(type as v.FunctionSchema<any>, Options(type))
}
// ------------------------------------------------------------------
// Instance
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TInstance>('ValibotInstance', (schema, value) => {
t.TypeRegistry.Set<TInstance>('ValibotInstance', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TInstance<Type extends v.InstanceSchema<v.Class, any> = v.InstanceSchema<v.Class, any>> extends tb.TSchema {
[tb.Kind]: 'ValibotInstance'
export interface TInstance<Type extends v.InstanceSchema<v.Class, any> = v.InstanceSchema<v.Class, any>> extends t.TSchema {
[t.Kind]: 'ValibotInstance'
static: v.InferOutput<this['type']>
type: Type
}
function Instance<Type extends v.InstanceSchema<v.Class, any>>(type: Type, options?: tb.SchemaOptions): TInstance<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotInstance', type }, options) as never
function Instance<Type extends v.InstanceSchema<v.Class, any>>(type: Type, options?: t.SchemaOptions): TInstance<Type> {
return t.CreateType({ [t.Kind]: 'ValibotInstance', type }, options) as never
}
type TFromInstance<Type extends v.InstanceSchema<v.Class, any>> = tb.Ensure<TInstance<Type>>
function FromInstance(type: BaseSchema): tb.TSchema {
type TFromInstance<Type extends v.InstanceSchema<v.Class, any>> = t.Ensure<TInstance<Type>>
function FromInstance(type: BaseSchema): t.TSchema {
return Instance(type as v.InstanceSchema<v.Class, any>, Options(type))
}
// ------------------------------------------------------------------
// Intersect
// ------------------------------------------------------------------
// prettier-ignore
type TFromIntersect<Type extends BaseSchema[], Result extends tb.TSchema[] = []> = (
type TFromIntersect<Type extends BaseSchema[], Result extends t.TSchema[] = []> = (
Type extends [infer Left extends BaseSchema, ...infer Right extends BaseSchema[]]
? TFromIntersect<Right, [...Result, TFromType<Left>]>
: tb.TIntersect<Result>
: t.TIntersect<Result>
)
function FromIntersect(type: BaseSchema): tb.TSchema {
function FromIntersect(type: BaseSchema): t.TSchema {
const intersect = type as v.IntersectSchema<BaseSchema[], any>
return tb.Intersect(
return t.Intersect(
intersect.options.map((option) => FromType(option)),
Options(type),
)
@@ -348,268 +349,268 @@ function FromIntersect(type: BaseSchema): tb.TSchema {
// ------------------------------------------------------------------
// Literal
// ------------------------------------------------------------------
type TFromLiteral<Value extends tb.TLiteralValue> = tb.Ensure<tb.TLiteral<Value>>
function FromLiteral(type: BaseSchema): tb.TSchema {
const literal = type as v.LiteralSchema<tb.TLiteralValue, any>
return tb.Literal(literal.literal, Options(type))
type TFromLiteral<Value extends t.TLiteralValue> = t.Ensure<t.TLiteral<Value>>
function FromLiteral(type: BaseSchema): t.TSchema {
const literal = type as v.LiteralSchema<t.TLiteralValue, any>
return t.Literal(literal.literal, Options(type))
}
// ------------------------------------------------------------------
// LooseObject
// ------------------------------------------------------------------
type TFromLooseObject<Properties extends v.ObjectEntries> = tb.Ensure<
tb.TObject<{
type TFromLooseObject<Properties extends v.ObjectEntries> = t.Ensure<
t.TObject<{
-readonly [Key in keyof Properties]: TFromType<Properties[Key]>
}>
>
function FromLooseObject(type: BaseSchema): tb.TSchema {
function FromLooseObject(type: BaseSchema): t.TSchema {
const object = type as v.LooseObjectSchema<v.ObjectEntries, any>
const keys = globalThis.Object.getOwnPropertyNames(object.entries)
return tb.Object(
return t.Object(
keys.reduce((properties, key) => {
return { ...properties, [key]: FromType(object.entries[key]) }
}, {} as tb.TProperties),
}, {} as t.TProperties),
Options(type),
)
}
// ------------------------------------------------------------------
// LooseTuple
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TLooseTuple>('ValibotLooseTuple', (schema, value) => {
t.TypeRegistry.Set<TLooseTuple>('ValibotLooseTuple', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TLooseTuple<Type extends v.LooseTupleSchema<BaseSchema[], any> = v.LooseTupleSchema<BaseSchema[], any>> extends tb.TSchema {
[tb.Kind]: 'ValibotLooseTuple'
export interface TLooseTuple<Type extends v.LooseTupleSchema<BaseSchema[], any> = v.LooseTupleSchema<BaseSchema[], any>> extends t.TSchema {
[t.Kind]: 'ValibotLooseTuple'
static: v.InferOutput<this['type']>
type: Type
}
function LooseTuple<Type extends v.LooseTupleSchema<BaseSchema[], any>>(type: Type, schema?: tb.SchemaOptions): TLooseTuple<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotLooseTuple', type }) as never
function LooseTuple<Type extends v.LooseTupleSchema<BaseSchema[], any>>(type: Type, schema?: t.SchemaOptions): TLooseTuple<Type> {
return t.CreateType({ [t.Kind]: 'ValibotLooseTuple', type }) as never
}
type TFromLooseTuple<Type extends v.LooseTupleSchema<BaseSchema[], any>> = tb.Ensure<TLooseTuple<Type>>
function FromLooseTuple(type: BaseSchema): tb.TSchema {
type TFromLooseTuple<Type extends v.LooseTupleSchema<BaseSchema[], any>> = t.Ensure<TLooseTuple<Type>>
function FromLooseTuple(type: BaseSchema): t.TSchema {
return LooseTuple(type as v.LooseTupleSchema<BaseSchema[], any>, Options(type))
}
// ------------------------------------------------------------------
// Map
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TMap>('ValibotMap', (schema, value) => {
t.TypeRegistry.Set<TMap>('ValibotMap', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TMap<Type extends v.MapSchema<BaseSchema, BaseSchema, any> = v.MapSchema<BaseSchema, BaseSchema, any>> extends tb.TSchema {
[tb.Kind]: 'ValibotMap'
export interface TMap<Type extends v.MapSchema<BaseSchema, BaseSchema, any> = v.MapSchema<BaseSchema, BaseSchema, any>> extends t.TSchema {
[t.Kind]: 'ValibotMap'
static: v.InferOutput<this['type']>
type: Type
}
function _Map<Type extends v.MapSchema<BaseSchema, BaseSchema, any>>(type: Type, options?: tb.SchemaOptions): TMap<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotMap', type }) as never
function _Map<Type extends v.MapSchema<BaseSchema, BaseSchema, any>>(type: Type, options?: t.SchemaOptions): TMap<Type> {
return t.CreateType({ [t.Kind]: 'ValibotMap', type }) as never
}
type TFromMap<Type extends v.MapSchema<BaseSchema, BaseSchema, any>> = tb.Ensure<TMap<Type>>
function FromMap(type: BaseSchema): tb.TSchema {
type TFromMap<Type extends v.MapSchema<BaseSchema, BaseSchema, any>> = t.Ensure<TMap<Type>>
function FromMap(type: BaseSchema): t.TSchema {
return _Map(type as v.MapSchema<BaseSchema, BaseSchema, any>, Options(type))
}
// ------------------------------------------------------------------
// NaN
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TNaN>('ValibotNaN', (schema, value) => {
t.TypeRegistry.Set<TNaN>('ValibotNaN', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TNaN<Type extends v.NanSchema<any> = v.NanSchema<any>> extends tb.TSchema {
[tb.Kind]: 'ValibotNaN'
export interface TNaN<Type extends v.NanSchema<any> = v.NanSchema<any>> extends t.TSchema {
[t.Kind]: 'ValibotNaN'
static: v.InferOutput<this['type']>
type: Type
}
function _NaN<Type extends v.NanSchema<any>>(type: Type, options?: tb.SchemaOptions): TNaN<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotNaN', type }, options) as never
function _NaN<Type extends v.NanSchema<any>>(type: Type, options?: t.SchemaOptions): TNaN<Type> {
return t.CreateType({ [t.Kind]: 'ValibotNaN', type }, options) as never
}
type TFromNaN<Type extends v.NanSchema<any>> = tb.Ensure<TNaN<Type>>
function FromNaN(type: BaseSchema): tb.TSchema {
type TFromNaN<Type extends v.NanSchema<any>> = t.Ensure<TNaN<Type>>
function FromNaN(type: BaseSchema): t.TSchema {
return _NaN(type as v.NanSchema<any>, Options(type))
}
// ------------------------------------------------------------------
// Never
// ------------------------------------------------------------------
type TFromNever<_Type extends v.NeverSchema<any>> = tb.TNever
function FromNever(type: BaseSchema): tb.TSchema {
return tb.Never(Options(type))
type TFromNever<_Type extends v.NeverSchema<any>> = t.TNever
function FromNever(type: BaseSchema): t.TSchema {
return t.Never(Options(type))
}
// ------------------------------------------------------------------
// NonNullable
// ------------------------------------------------------------------
type TFromNonNullable<Type extends BaseSchema> = tb.TExclude<TFromType<Type>, tb.TNull>
function FromNonNullable(type: BaseSchema): tb.TSchema {
type TFromNonNullable<Type extends BaseSchema> = t.TExclude<TFromType<Type>, t.TNull>
function FromNonNullable(type: BaseSchema): t.TSchema {
const non_nullable = type as v.NonNullableSchema<BaseSchema, any>
return tb.Exclude(FromType(non_nullable.wrapped), tb.Null(), Options(type))
return t.Exclude(FromType(non_nullable.wrapped), t.Null(), Options(type))
}
// ------------------------------------------------------------------
// NonNullish
// ------------------------------------------------------------------
type TFromNonNullish<Type extends BaseSchema> = tb.TExclude<TFromType<Type>, tb.TUnion<[tb.TNull, tb.TUndefined]>>
function FromNonNullish(type: BaseSchema): tb.TSchema {
type TFromNonNullish<Type extends BaseSchema> = t.TExclude<TFromType<Type>, t.TUnion<[t.TNull, t.TUndefined]>>
function FromNonNullish(type: BaseSchema): t.TSchema {
const non_nullish = type as v.NonNullishSchema<BaseSchema, any>
return tb.Exclude(FromType(non_nullish.wrapped), tb.Union([tb.Null(), tb.Undefined()]), Options(type))
return t.Exclude(FromType(non_nullish.wrapped), t.Union([t.Null(), t.Undefined()]), Options(type))
}
// ------------------------------------------------------------------
// NonOptional
// ------------------------------------------------------------------
type TFromNonOptional<Type extends BaseSchema, Result extends TFromType<Type> = TFromType<Type>> = tb.TOptionalWithFlag<Result, false>
function FromNonOptional(type: BaseSchema): tb.TSchema {
type TFromNonOptional<Type extends BaseSchema, Result extends TFromType<Type> = TFromType<Type>> = t.TOptionalWithFlag<Result, false>
function FromNonOptional(type: BaseSchema): t.TSchema {
const non_optional = type as v.NonOptionalSchema<BaseSchema, any>
return tb.Optional(FromType(non_optional.wrapped), false)
return t.Optional(FromType(non_optional.wrapped), false)
}
// ------------------------------------------------------------------
// Null
// ------------------------------------------------------------------
type TFromNull<_Type extends v.NullSchema<any>> = tb.TNull
type TFromNull<_Type extends v.NullSchema<any>> = t.TNull
function FromNull(type: BaseSchema) {
return tb.Null(Options(type))
return t.Null(Options(type))
}
// ------------------------------------------------------------------
// Nullable
// ------------------------------------------------------------------
type TFromNullable<Type extends BaseSchema> = tb.TUnion<[TFromType<Type>, tb.TNull]>
type TFromNullable<Type extends BaseSchema> = t.TUnion<[TFromType<Type>, t.TNull]>
function FromNullable(type: BaseSchema) {
const nullable = type as v.NullableSchema<BaseSchema, any>
return tb.Union([tb.Null(), FromType(nullable.wrapped)], Options(type))
return t.Union([t.Null(), FromType(nullable.wrapped)], Options(type))
}
// ------------------------------------------------------------------
// Nullish
// ------------------------------------------------------------------
type TFromNullish<Type extends BaseSchema> = tb.TUnion<[TFromType<Type>, tb.TNull, tb.TUndefined]>
type TFromNullish<Type extends BaseSchema> = t.TUnion<[TFromType<Type>, t.TNull, t.TUndefined]>
function FromNullish(type: BaseSchema) {
const nullish = type as v.NullishSchema<BaseSchema, any>
return tb.Union([FromType(nullish.wrapped), tb.Null(), tb.Undefined()], Options(type))
return t.Union([FromType(nullish.wrapped), t.Null(), t.Undefined()], Options(type))
}
// ------------------------------------------------------------------
// Number
// ------------------------------------------------------------------
type TFromNumber<_Type extends v.NumberSchema<any>> = tb.TNumber
function FromNumber(type: BaseSchema): tb.TSchema {
return tb.Number(Options(type))
type TFromNumber<_Type extends v.NumberSchema<any>> = t.TNumber
function FromNumber(type: BaseSchema): t.TSchema {
return t.Number(Options(type))
}
// ------------------------------------------------------------------
// Object
// ------------------------------------------------------------------
type TFromObject<Properties extends v.ObjectEntries> = tb.Ensure<
tb.TObject<{
type TFromObject<Properties extends v.ObjectEntries> = t.Ensure<
t.TObject<{
-readonly [Key in keyof Properties]: TFromType<Properties[Key]>
}>
>
function FromObject(type: BaseSchema): tb.TSchema {
function FromObject(type: BaseSchema): t.TSchema {
const object = type as v.ObjectSchema<v.ObjectEntries, any>
const keys = globalThis.Object.getOwnPropertyNames(object.entries)
return tb.Object(
return t.Object(
keys.reduce((properties, key) => {
return { ...properties, [key]: FromType(object.entries[key]) }
}, {} as tb.TProperties),
}, {} as t.TProperties),
Options(type),
)
}
// ------------------------------------------------------------------
// ObjectWithRest
// ------------------------------------------------------------------
type TFromObjectWithRest<Properties extends v.ObjectEntries, _Rest extends BaseSchema> = tb.Ensure<
tb.TObject<{
type TFromObjectWithRest<Properties extends v.ObjectEntries, _Rest extends BaseSchema> = t.Ensure<
t.TObject<{
-readonly [Key in keyof Properties]: TFromType<Properties[Key]>
}>
>
function FromObjectWithRest(type: BaseSchema): tb.TSchema {
function FromObjectWithRest(type: BaseSchema): t.TSchema {
const object = type as v.ObjectWithRestSchema<v.ObjectEntries, BaseSchema, any>
const keys = globalThis.Object.getOwnPropertyNames(object.entries)
return tb.Object(
return t.Object(
keys.reduce((properties, key) => {
return { ...properties, [key]: FromType(object.entries[key]) }
}, {} as tb.TProperties),
}, {} as t.TProperties),
{ ...Options(type), additionalProperties: FromType(object.rest) },
)
}
// ------------------------------------------------------------------
// Optional
// ------------------------------------------------------------------
type TFromOptional<Type extends BaseSchema, Result extends TFromType<Type> = TFromType<Type>> = tb.TOptionalWithFlag<Result, true>
function FromOptional(type: BaseSchema): tb.TSchema {
type TFromOptional<Type extends BaseSchema, Result extends TFromType<Type> = TFromType<Type>> = t.TOptionalWithFlag<Result, true>
function FromOptional(type: BaseSchema): t.TSchema {
const optional = type as v.OptionalSchema<BaseSchema, any>
return tb.Optional(FromType(optional.wrapped))
return t.Optional(FromType(optional.wrapped))
}
// ------------------------------------------------------------------
// PickList
// ------------------------------------------------------------------
type PickListOption = string | number | bigint
// prettier-ignore
type TFromPickList<Options extends PickListOption[], Result extends tb.TSchema[] = []> = (
type TFromPickList<Options extends PickListOption[], Result extends t.TSchema[] = []> = (
Options extends [infer Left extends PickListOption, ...infer Right extends PickListOption[]]
? (
Left extends tb.TLiteralValue
? TFromPickList<Right, [...Result, tb.TLiteral<Left>]>
Left extends t.TLiteralValue
? TFromPickList<Right, [...Result, t.TLiteral<Left>]>
: TFromPickList<Right, [...Result]>
)
: tb.TUnion<Result>
: t.TUnion<Result>
)
function FromPickList(type: BaseSchema): tb.TSchema {
function FromPickList(type: BaseSchema): t.TSchema {
const picklist = type as v.PicklistSchema<v.PicklistOptions, any>
return tb.Union(
picklist.options.map((option) => tb.Literal(option as tb.TLiteralValue)),
return t.Union(
picklist.options.map((option) => t.Literal(option as t.TLiteralValue)),
Options(type),
)
}
// ------------------------------------------------------------------
// Promise
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TPromise>('ValibotPromise', (schema, value) => {
t.TypeRegistry.Set<TPromise>('ValibotPromise', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TPromise<Type extends v.PromiseSchema<any> = v.PromiseSchema<any>> extends tb.TSchema {
[tb.Kind]: 'ValibotPromise'
export interface TPromise<Type extends v.PromiseSchema<any> = v.PromiseSchema<any>> extends t.TSchema {
[t.Kind]: 'ValibotPromise'
static: v.InferOutput<this['type']>
type: Type
}
function _Promise<Type extends v.PromiseSchema<any>>(type: Type, options?: tb.SchemaOptions): TPromise<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotPromise', type }, options) as never
function _Promise<Type extends v.PromiseSchema<any>>(type: Type, options?: t.SchemaOptions): TPromise<Type> {
return t.CreateType({ [t.Kind]: 'ValibotPromise', type }, options) as never
}
type TFromPromise<Type extends v.PromiseSchema<any>> = tb.Ensure<TPromise<Type>>
function FromPromise(type: BaseSchema): tb.TSchema {
type TFromPromise<Type extends v.PromiseSchema<any>> = t.Ensure<TPromise<Type>>
function FromPromise(type: BaseSchema): t.TSchema {
return _Promise(type as v.PromiseSchema<any>, Options(type))
}
// ------------------------------------------------------------------
// Record
// ------------------------------------------------------------------
type TFromRecord<Key extends BaseRecordKey, Value extends BaseSchema> = tb.Ensure<tb.TRecordOrObject<TFromType<Key>, TFromType<Value>>>
type TFromRecord<Key extends BaseRecordKey, Value extends BaseSchema> = t.Ensure<t.TRecordOrObject<TFromType<Key>, TFromType<Value>>>
function FromRecord(type: BaseSchema) {
const record = type as v.RecordSchema<BaseRecordKey, BaseSchema, any>
return tb.Record(FromType(record.key), FromType(record.value), Options(type))
return t.Record(FromType(record.key), FromType(record.value), Options(type))
}
// ------------------------------------------------------------------
// Set
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TInstance>('ValibotSet', (schema, value) => {
t.TypeRegistry.Set<TInstance>('ValibotSet', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
export interface TSet<Type extends v.SetSchema<BaseSchema, any> = v.SetSchema<BaseSchema, any>> extends tb.TSchema {
[tb.Kind]: 'ValibotSet'
export interface TSet<Type extends v.SetSchema<BaseSchema, any> = v.SetSchema<BaseSchema, any>> extends t.TSchema {
[t.Kind]: 'ValibotSet'
static: v.InferOutput<this['type']> extends infer Result ? Result : never
type: Type
}
function Set<Type extends v.SetSchema<BaseSchema, any>>(type: Type, options?: tb.SchemaOptions): TSet<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotSet', type }, options) as never
function Set<Type extends v.SetSchema<BaseSchema, any>>(type: Type, options?: t.SchemaOptions): TSet<Type> {
return t.CreateType({ [t.Kind]: 'ValibotSet', type }, options) as never
}
type TFromSet<Type extends v.SetSchema<BaseSchema, any>> = tb.Ensure<TSet<Type>>
function FromSet(type: BaseSchema): tb.TSchema {
type TFromSet<Type extends v.SetSchema<BaseSchema, any>> = t.Ensure<TSet<Type>>
function FromSet(type: BaseSchema): t.TSchema {
return Set(type as v.SetSchema<BaseSchema, any>)
}
// ------------------------------------------------------------------
// StrictObject
// ------------------------------------------------------------------
type TFromStrictObject<Properties extends v.ObjectEntries> = tb.Ensure<
tb.TObject<{
type TFromStrictObject<Properties extends v.ObjectEntries> = t.Ensure<
t.TObject<{
-readonly [Key in keyof Properties]: TFromType<Properties[Key]>
}>
>
function FromStrictObject(type: BaseSchema): tb.TSchema {
function FromStrictObject(type: BaseSchema): t.TSchema {
const object = type as v.StrictObjectSchema<v.ObjectEntries, any>
const keys = globalThis.Object.getOwnPropertyNames(object.entries)
return tb.Object(
return t.Object(
keys.reduce((properties, key) => {
return { ...properties, [key]: FromType(object.entries[key]) }
}, {} as tb.TProperties),
}, {} as t.TProperties),
{ ...Options(type), additionalProperties: false },
)
}
@@ -617,121 +618,121 @@ function FromStrictObject(type: BaseSchema): tb.TSchema {
// StrictTuple
// ------------------------------------------------------------------
// prettier-ignore
type TFromStrictTuple<Type extends BaseSchema[], Result extends tb.TSchema[] = []> = (
type TFromStrictTuple<Type extends BaseSchema[], Result extends t.TSchema[] = []> = (
Type extends [infer Left extends BaseSchema, ...infer Right extends BaseSchema[]]
? TFromTuple<Right, [...Result, TFromType<Left>]>
: tb.TTuple<Result>
: t.TTuple<Result>
)
function FromStrictTuple(type: BaseSchema): tb.TSchema {
function FromStrictTuple(type: BaseSchema): t.TSchema {
const tuple = type as v.StrictTupleSchema<any, any>
const items = globalThis.Array.isArray(tuple.items) ? tuple.items.map((item) => FromType(item)) : []
return tb.Tuple(items, Options(type))
return t.Tuple(items, Options(type))
}
// ------------------------------------------------------------------
// String
// ------------------------------------------------------------------
type TFromString<_Type extends v.StringSchema<any>> = tb.TString
function FromString(type: BaseSchema): tb.TSchema {
return tb.String(Options(type))
type TFromString<_Type extends v.StringSchema<any>> = t.TString
function FromString(type: BaseSchema): t.TSchema {
return t.String(Options(type))
}
// ------------------------------------------------------------------
// Symbol
// ------------------------------------------------------------------
type TFromSymbol<_Type extends v.SymbolSchema<any>> = tb.TSymbol
function FromSymbol(type: BaseSchema): tb.TSchema {
return tb.Symbol(Options(type))
type TFromSymbol<_Type extends v.SymbolSchema<any>> = t.TSymbol
function FromSymbol(type: BaseSchema): t.TSchema {
return t.Symbol(Options(type))
}
// ------------------------------------------------------------------
// Tuple
// ------------------------------------------------------------------
// prettier-ignore
type TFromTuple<Type extends BaseSchema[], Result extends tb.TSchema[] = []> = (
type TFromTuple<Type extends BaseSchema[], Result extends t.TSchema[] = []> = (
Type extends [infer Left extends BaseSchema, ...infer Right extends BaseSchema[]]
? TFromTuple<Right, [...Result, TFromType<Left>]>
: tb.TTuple<Result>
: t.TTuple<Result>
)
function FromTuple(type: BaseSchema): tb.TSchema {
function FromTuple(type: BaseSchema): t.TSchema {
const tuple = type as v.TupleSchema<any, any>
const items = globalThis.Array.isArray(tuple.items) ? tuple.items.map((item) => FromType(item)) : []
return tb.Tuple(items, Options(type))
return t.Tuple(items, Options(type))
}
// ------------------------------------------------------------------
// TupleWithRest
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TTupleWithRest>('ValibotTupleWithRest', (schema, value) => {
t.TypeRegistry.Set<TTupleWithRest>('ValibotTupleWithRest', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
interface TTupleWithRest<Type extends v.TupleWithRestSchema<BaseSchema[], BaseSchema, any> = v.TupleWithRestSchema<BaseSchema[], BaseSchema, any>> extends tb.TSchema {
[tb.Kind]: 'ValibotTupleWithRest'
interface TTupleWithRest<Type extends v.TupleWithRestSchema<BaseSchema[], BaseSchema, any> = v.TupleWithRestSchema<BaseSchema[], BaseSchema, any>> extends t.TSchema {
[t.Kind]: 'ValibotTupleWithRest'
static: v.InferOutput<this['type']>
type: Type
}
function TupleWithRest<Type extends v.TupleWithRestSchema<BaseSchema[], BaseSchema, any>>(type: Type, options?: tb.SchemaOptions): TTupleWithRest<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotTupleWithRest', type }, Options(type)) as never
function TupleWithRest<Type extends v.TupleWithRestSchema<BaseSchema[], BaseSchema, any>>(type: Type, options?: t.SchemaOptions): TTupleWithRest<Type> {
return t.CreateType({ [t.Kind]: 'ValibotTupleWithRest', type }, Options(type)) as never
}
type TFromTupleWithRest<Type extends v.TupleWithRestSchema<BaseSchema[], BaseSchema, any>> = tb.Ensure<TTupleWithRest<Type>>
function FromTupleWithRest(type: BaseSchema): tb.TSchema {
type TFromTupleWithRest<Type extends v.TupleWithRestSchema<BaseSchema[], BaseSchema, any>> = t.Ensure<TTupleWithRest<Type>>
function FromTupleWithRest(type: BaseSchema): t.TSchema {
return TupleWithRest(type as v.TupleWithRestSchema<BaseSchema[], BaseSchema, any>, Options(type))
}
// ------------------------------------------------------------------
// Undefined
// ------------------------------------------------------------------
type TFromUndefined<_Type extends v.UndefinedSchema<any>> = tb.TUndefined
function FromUndefined(type: BaseSchema): tb.TSchema {
return tb.Undefined(Options(type))
type TFromUndefined<_Type extends v.UndefinedSchema<any>> = t.TUndefined
function FromUndefined(type: BaseSchema): t.TSchema {
return t.Undefined(Options(type))
}
// ------------------------------------------------------------------
// Undefinable
// ------------------------------------------------------------------
type TFromUndefinedable<Type extends BaseSchema> = tb.TUnion<[TFromType<Type>, tb.TUndefined]>
function FromUndefinedable(type: BaseSchema): tb.TSchema {
type TFromUndefinedable<Type extends BaseSchema> = t.TUnion<[TFromType<Type>, t.TUndefined]>
function FromUndefinedable(type: BaseSchema): t.TSchema {
const undefinedable = type as v.UndefinedableSchema<BaseSchema, any>
return tb.Union([FromType(undefinedable.wrapped), tb.Undefined()], Options(type))
return t.Union([FromType(undefinedable.wrapped), t.Undefined()], Options(type))
}
// ------------------------------------------------------------------
// Union
// ------------------------------------------------------------------
// prettier-ignore
type TFromUnion<Type extends BaseSchema[], Result extends tb.TSchema[] = []> = (
type TFromUnion<Type extends BaseSchema[], Result extends t.TSchema[] = []> = (
Type extends [infer Left extends BaseSchema, ...infer Right extends BaseSchema[]]
? TFromUnion<Right, [...Result, TFromType<Left>]>
: tb.TUnion<Result>
: t.TUnion<Result>
)
function FromUnion(type: BaseSchema): tb.TSchema {
function FromUnion(type: BaseSchema): t.TSchema {
const variants = (type as v.UnionSchema<BaseSchema[], any>).options.map((option) => FromType(option))
return tb.Union(variants, Options(type))
return t.Union(variants, Options(type))
}
// ------------------------------------------------------------------
// Unknown
// ------------------------------------------------------------------
type TFromUnknown<_Type extends v.UnknownSchema> = tb.TUnknown
function FromUnknown(type: BaseSchema): tb.TSchema {
return tb.Unknown(Options(type))
type TFromUnknown<_Type extends v.UnknownSchema> = t.TUnknown
function FromUnknown(type: BaseSchema): t.TSchema {
return t.Unknown(Options(type))
}
// ------------------------------------------------------------------
// Variant
// ------------------------------------------------------------------
tb.TypeRegistry.Set<TVariant>('ValibotVariant', (schema, value) => {
t.TypeRegistry.Set<TVariant>('ValibotVariant', (schema, value) => {
return v.safeParse(schema.schema, value).success
})
interface TVariant<Type extends v.VariantSchema<string, v.VariantOptions<string>, any> = v.VariantSchema<string, v.VariantOptions<string>, any>> extends tb.TSchema {
[tb.Kind]: 'ValibotVariant'
interface TVariant<Type extends v.VariantSchema<string, v.VariantOptions<string>, any> = v.VariantSchema<string, v.VariantOptions<string>, any>> extends t.TSchema {
[t.Kind]: 'ValibotVariant'
static: v.InferOutput<this['type']>
type: Type
}
function Variant<Type extends v.VariantSchema<string, v.VariantOptions<string>, any>>(type: Type): TVariant<Type> {
return tb.CreateType({ [tb.Kind]: 'ValibotVariant', type }, Options(type)) as never
return t.CreateType({ [t.Kind]: 'ValibotVariant', type }, Options(type)) as never
}
type TFromVariant<Type extends v.VariantSchema<string, v.VariantOptions<string>, any>> = tb.Ensure<TVariant<Type>>
function FromVariant(type: BaseSchema): tb.TSchema {
type TFromVariant<Type extends v.VariantSchema<string, v.VariantOptions<string>, any>> = t.Ensure<TVariant<Type>>
function FromVariant(type: BaseSchema): t.TSchema {
return Variant(type as v.VariantSchema<string, v.VariantOptions<string>, any>)
}
// ------------------------------------------------------------------
// Void
// ------------------------------------------------------------------
type TFromVoid<_Type extends v.VoidSchema<any>> = tb.TVoid
function FromVoid(type: BaseSchema): tb.TSchema {
return tb.Void(Options(type))
type TFromVoid<_Type extends v.VoidSchema<any>> = t.TVoid
function FromVoid(type: BaseSchema): t.TSchema {
return t.Void(Options(type))
}
// ------------------------------------------------------------------
// Type
@@ -753,7 +754,7 @@ export type TFromType<Type extends BaseSchema> = (
Type extends v.FunctionSchema<any> ? TFromFunction<Type> :
Type extends v.InstanceSchema<v.Class, any> ? TFromInstance<Type> :
Type extends v.IntersectSchema<infer Types extends BaseSchema[], any> ? TFromIntersect<Types> :
Type extends v.LiteralSchema<infer Value extends tb.TLiteralValue, any> ? TFromLiteral<Value> :
Type extends v.LiteralSchema<infer Value extends t.TLiteralValue, any> ? TFromLiteral<Value> :
Type extends v.LooseObjectSchema<infer Properties extends v.ObjectEntries, any> ? TFromLooseObject<Properties> :
Type extends v.LooseTupleSchema<BaseSchema[], any> ? TFromLooseTuple<Type> :
Type extends v.MapSchema<BaseSchema, BaseSchema, any> ? TFromMap<Type> :
@@ -785,7 +786,7 @@ export type TFromType<Type extends BaseSchema> = (
Type extends v.UnknownSchema ? TFromUnknown<Type> :
Type extends v.VariantSchema<string, v.VariantOptions<string>, any> ? TFromVariant<Type> :
Type extends v.VoidSchema<any> ? TFromVoid<Type> :
tb.TNever
t.TNever
)
// prettier-ignore
export function FromType<Type extends BaseSchema>(type: Type): TFromType<Type> {
@@ -834,35 +835,18 @@ export function FromType<Type extends BaseSchema>(type: Type): TFromType<Type> {
type.type === 'union' ? FromUnion(type) :
type.type === 'variant' ? FromVariant(type) :
type.type === 'void' ? FromVoid(type) :
tb.Never()
t.Never()
) as never
}
// ------------------------------------------------------------------
// IsValibot
// TypeBoxFromValibot
// ------------------------------------------------------------------
// prettier-ignore
export function IsValibot(type: unknown): type is BaseSchema {
return (
tb.ValueGuard.IsObject(type) &&
tb.ValueGuard.HasPropertyKey(type, '~standard') &&
tb.ValueGuard.IsObject(type['~standard']) &&
tb.ValueGuard.HasPropertyKey(type['~standard'], 'vendor') &&
type['~standard'].vendor === 'valibot'
)
}
// ------------------------------------------------------------------
// Box
// ------------------------------------------------------------------
/** Converts a Valibot Type to a TypeBox Type */
// prettier-ignore
export type TBox<Type extends unknown> = (
Type extends BaseSchema
? Type extends { '~standard': { vendor: 'valibot' } }
? TFromType<Type>
: undefined
: undefined
export type TTypeBoxFromValibot<Type extends unknown> = (
Type extends BaseSchema ? TFromType<Type> : t.TNever
)
/** Converts a Valibot Type to a TypeBox Type */
export function Box<Type extends unknown, Result extends TBox<Type> = TBox<Type>>(type: Type): Result {
return (IsValibot(type) ? FromType(type) : undefined) as never
// prettier-ignore
export function TypeBoxFromValibot<Type extends unknown, Result extends TTypeBoxFromValibot<Type> = TTypeBoxFromValibot<Type>>(type: Type): Result {
return (Guard.IsValibot(type) ? FromType(type) : t.Never()) as never
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typebox-adapter
@sinclair/typemap
The MIT License (MIT)
@@ -26,106 +26,106 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as tb from '@sinclair/typebox'
import * as t from '@sinclair/typebox'
import * as z from 'zod'
import * as Guard from '../guard'
// ------------------------------------------------------------------
// Options
// ------------------------------------------------------------------
function Options(type: z.ZodTypeAny): tb.SchemaOptions {
const description = tb.ValueGuard.IsUndefined(type.description) ? {} : { description: type.description }
function Options(type: z.ZodTypeAny): t.SchemaOptions {
const description = t.ValueGuard.IsUndefined(type.description) ? {} : { description: type.description }
return { ...description }
}
// ------------------------------------------------------------------
// Formats
// ------------------------------------------------------------------
const check = (type: z.ZodTypeAny, value: unknown) => type.safeParse(value).success
tb.FormatRegistry.Set('zod:base64', (value) => check(z.string().base64(), value))
tb.FormatRegistry.Set('zod:base64url', (value) => check(z.string().base64url(), value))
tb.FormatRegistry.Set('zod:cidrv4', (value) => check(z.string().cidr({ version: 'v4' }), value))
tb.FormatRegistry.Set('zod:cidrv6', (value) => check(z.string().cidr({ version: 'v6' }), value))
tb.FormatRegistry.Set('zod:cidr', (value) => check(z.string().cidr(), value))
tb.FormatRegistry.Set('zod:cuid', (value) => check(z.string().cuid(), value))
tb.FormatRegistry.Set('zod:cuid2', (value) => check(z.string().cuid2(), value))
tb.FormatRegistry.Set('zod:ulid', (value) => check(z.string().ulid(), value))
tb.FormatRegistry.Set('zod:email', (value) => check(z.string().email(), value))
tb.FormatRegistry.Set('zod:emoji', (value) => check(z.string().emoji(), value))
tb.FormatRegistry.Set('zod:ipv4', (value) => check(z.string().ip({ version: 'v4' }), value))
tb.FormatRegistry.Set('zod:ipv6', (value) => check(z.string().ip({ version: 'v6' }), value))
tb.FormatRegistry.Set('zod:ip', (value) => check(z.string().ip(), value))
tb.FormatRegistry.Set('zod:ipv6Cidr', (value) => check(z.string().cidr({ version: 'v6' }), value))
tb.FormatRegistry.Set('zod:nanoid', (value) => check(z.string().nanoid(), value))
tb.FormatRegistry.Set('zod:jwt', (value) => check(z.string().jwt(), value))
tb.FormatRegistry.Set('zod:date', (value) => check(z.string().date(), value))
tb.FormatRegistry.Set('zod:datetime', (value) => check(z.string().datetime(), value))
tb.FormatRegistry.Set('zod:duration', (value) => check(z.string().duration(), value))
tb.FormatRegistry.Set('zod:time', (value) => check(z.string().time(), value))
tb.FormatRegistry.Set('zod:url', (value) => check(z.string().url(), value))
tb.FormatRegistry.Set('zod:uuid', (value) => check(z.string().uuid(), value))
t.FormatRegistry.Set('base64', (value) => check(z.string().base64(), value))
t.FormatRegistry.Set('base64url', (value) => check(z.string().base64url(), value))
t.FormatRegistry.Set('cidrv4', (value) => check(z.string().cidr({ version: 'v4' }), value))
t.FormatRegistry.Set('cidrv6', (value) => check(z.string().cidr({ version: 'v6' }), value))
t.FormatRegistry.Set('cidr', (value) => check(z.string().cidr(), value))
t.FormatRegistry.Set('cuid', (value) => check(z.string().cuid(), value))
t.FormatRegistry.Set('cuid2', (value) => check(z.string().cuid2(), value))
t.FormatRegistry.Set('date', (value) => check(z.string().date(), value))
t.FormatRegistry.Set('datetime', (value) => check(z.string().datetime(), value))
t.FormatRegistry.Set('duration', (value) => check(z.string().duration(), value))
t.FormatRegistry.Set('email', (value) => check(z.string().email(), value))
t.FormatRegistry.Set('emoji', (value) => check(z.string().emoji(), value))
t.FormatRegistry.Set('ipv4', (value) => check(z.string().ip({ version: 'v4' }), value))
t.FormatRegistry.Set('ipv6', (value) => check(z.string().ip({ version: 'v6' }), value))
t.FormatRegistry.Set('ip', (value) => check(z.string().ip(), value))
t.FormatRegistry.Set('jwt', (value) => check(z.string().jwt(), value))
t.FormatRegistry.Set('nanoid', (value) => check(z.string().nanoid(), value))
t.FormatRegistry.Set('time', (value) => check(z.string().time(), value))
t.FormatRegistry.Set('ulid', (value) => check(z.string().ulid(), value))
t.FormatRegistry.Set('url', (value) => check(z.string().url(), value))
t.FormatRegistry.Set('uuid', (value) => check(z.string().uuid(), value))
// ------------------------------------------------------------------
// Any
// ------------------------------------------------------------------
type TFromAny = tb.TAny
function FromAny<Def extends z.ZodAnyDef>(_def: Def) {
return tb.Any()
type TFromAny = t.TAny
function FromAny<Def extends z.ZodAnyDef>(_def: Def): t.TSchema {
return t.Any()
}
// ------------------------------------------------------------------
// Array
// ------------------------------------------------------------------
type TFromArray<Type extends z.ZodTypeAny> = tb.Ensure<tb.TArray<TFromType<Type>>>
function FromArray<Def extends z.ZodArrayDef>(def: Def): tb.TSchema {
type TFromArray<Type extends z.ZodTypeAny> = t.Ensure<t.TArray<TFromType<Type>>>
function FromArray<Def extends z.ZodArrayDef>(def: Def): t.TSchema {
const minItems = def.minLength === null ? {} : { minItems: def.minLength.value }
const maxItems = def.maxLength === null ? {} : { minItems: def.maxLength.value }
const options = { ...minItems, ...maxItems }
return tb.Array(FromType(def.type), options)
return t.Array(FromType(def.type), options)
}
// ------------------------------------------------------------------
// BigInt
// ------------------------------------------------------------------
type TFromBigInt = tb.TBigInt
function FromBigInt<Def extends z.ZodBigIntDef>(def: Def) {
return tb.BigInt()
type TFromBigInt = t.TBigInt
function FromBigInt<Def extends z.ZodBigIntDef>(def: Def): t.TSchema {
return t.BigInt()
}
// ------------------------------------------------------------------
// Boolean
// ------------------------------------------------------------------
type TFromBoolean = tb.TBoolean
function FromBoolean<Def extends z.ZodBooleanDef>(def: Def) {
return tb.Boolean()
type TFromBoolean = t.TBoolean
function FromBoolean<Def extends z.ZodBooleanDef>(def: Def): t.TSchema {
return t.Boolean()
}
// ------------------------------------------------------------------
// Date
// ------------------------------------------------------------------
type TFromDate = tb.TDate
function FromDate<Def extends z.ZodDateDef>(def: Def) {
return tb.Date()
type TFromDate = t.TDate
function FromDate<Def extends z.ZodDateDef>(def: Def): t.TSchema {
return t.Date()
}
// ------------------------------------------------------------------
// Default
// ------------------------------------------------------------------
type TFromDefault<Type extends z.ZodType> = TFromType<Type>
function FromDefault<Def extends z.ZodDefaultDef>(def: Def): tb.TSchema {
return tb.CloneType(FromType(def.innerType), { default: def.defaultValue() })
function FromDefault<Def extends z.ZodDefaultDef>(def: Def): t.TSchema {
return t.CloneType(FromType(def.innerType), { default: def.defaultValue() })
}
// ------------------------------------------------------------------
// DiscriminatedUnion
// ------------------------------------------------------------------
// prettier-ignore
type TFromDiscriminatedUnion<Discriminator extends string, Types extends readonly z.ZodObject<any>[], Result extends tb.TSchema[] = []> = (
type TFromDiscriminatedUnion<Discriminator extends string, Types extends readonly z.ZodObject<any>[], Result extends t.TSchema[] = []> = (
Types extends [infer Left extends z.ZodObject<any>, ...infer Right extends z.ZodObject<any>[]]
? TFromDiscriminatedUnion<Discriminator, Right, [...Result, TFromType<Left>]>
: tb.TUnion<Result>
: t.TUnion<Result>
)
function FromDiscriminatedUnion<Def extends z.ZodDiscriminatedUnionDef<string, z.ZodDiscriminatedUnionOption<string>[]>>(def: Def): tb.TSchema {
function FromDiscriminatedUnion<Def extends z.ZodDiscriminatedUnionDef<string, z.ZodDiscriminatedUnionOption<string>[]>>(def: Def): t.TSchema {
const types = def.options.map((type) => FromType(type))
return tb.Union(types, { discriminator: def.discriminator })
return t.Union(types, { discriminator: def.discriminator })
}
// ------------------------------------------------------------------
// Effects
// ------------------------------------------------------------------
type TFromEffects<Input extends z.ZodTypeAny, Output extends unknown> = tb.Ensure<tb.TTransform<TFromType<Input>, Output>>
function FromEffects<Type extends z.ZodEffects<z.ZodTypeAny, unknown>>(type: Type): tb.TSchema {
return tb
type TFromEffects<Input extends z.ZodTypeAny, Output extends unknown> = t.Ensure<t.TTransform<TFromType<Input>, Output>>
function FromEffects<Type extends z.ZodEffects<z.ZodTypeAny, unknown>>(type: Type): t.TSchema {
return t
.Transform(FromType(type._def.schema))
.Decode((value) => type.parse(value))
.Encode((_) => {
@@ -133,69 +133,77 @@ function FromEffects<Type extends z.ZodEffects<z.ZodTypeAny, unknown>>(type: Typ
})
}
// ------------------------------------------------------------------
// Enum
// ------------------------------------------------------------------
type TFromEnum<Variants extends string[], Result extends t.TLiteral[] = []> = Variants extends [infer Left extends string, ...infer Right extends string[]] ? TFromEnum<Right, [...Result, t.TLiteral<Left>]> : t.TUnion<Result>
function FromEnum<Def extends z.ZodEnumDef>(def: Def): t.TSchema {
const variants = def.values.map((value) => t.Literal(value))
return t.Union(variants)
}
// ------------------------------------------------------------------
// Literal
// ------------------------------------------------------------------
type TFromLiteral<Value extends unknown> = tb.Ensure<Value extends tb.TLiteralValue ? tb.TLiteral<Value> : tb.TNever>
function FromLiteral<Def extends z.ZodLiteralDef>(def: Def) {
return tb.Literal(def.value as tb.TLiteralValue)
type TFromLiteral<Value extends unknown> = t.Ensure<Value extends t.TLiteralValue ? t.TLiteral<Value> : t.TNever>
function FromLiteral<Def extends z.ZodLiteralDef>(def: Def): t.TSchema {
return t.Literal(def.value as t.TLiteralValue)
}
// ------------------------------------------------------------------
// Intersect
// ------------------------------------------------------------------
// prettier-ignore
type TFromIntersect<Types extends z.ZodTypeAny[], Result extends tb.TSchema[] = []> = (
type TFromIntersect<Types extends z.ZodTypeAny[], Result extends t.TSchema[] = []> = (
Types extends [infer Left extends z.ZodTypeAny, ...infer Right extends z.ZodTypeAny[]]
? TFromIntersect<Right, [...Result, TFromType<Left>]>
: tb.Ensure<tb.TIntersect<Result>>
: t.Ensure<t.TIntersect<Result>>
)
function FromIntersect<Type extends z.ZodIntersectionDef>(type: Type): tb.TSchema {
return tb.Intersect([FromType(type.left), FromType(type.right)])
function FromIntersect<Type extends z.ZodIntersectionDef>(type: Type): t.TSchema {
return t.Intersect([FromType(type.left), FromType(type.right)])
}
// ------------------------------------------------------------------
// Object
// ------------------------------------------------------------------
type TFromObject<Properties extends z.ZodRawShape> = tb.Ensure<
tb.TObject<{
type TFromObject<Properties extends z.ZodRawShape> = t.Ensure<
t.TObject<{
[Key in keyof Properties]: TFromType<Properties[Key]>
}>
>
function FromObject<Def extends z.ZodObjectDef<z.ZodRawShape>, Shape extends z.ZodRawShape>(def: Def, shape: Shape): tb.TSchema {
function FromObject<Def extends z.ZodObjectDef<z.ZodRawShape>, Shape extends z.ZodRawShape>(def: Def, shape: Shape): t.TSchema {
const additionalProperties = def.unknownKeys === 'strict' ? { additionalProperties: false } : {}
const options = { ...additionalProperties }
return tb.Object(
return t.Object(
globalThis.Object.keys(shape).reduce((properties: any, key: any) => {
return { ...properties, [key]: FromType(shape[key]) }
}, {} as tb.TProperties) as never,
}, {} as t.TProperties) as never,
options,
)
}
// ------------------------------------------------------------------
// Optional
// ------------------------------------------------------------------
type TFromOptional<Type extends z.ZodTypeAny, Result extends tb.TSchema = tb.TOptional<TFromType<Type>>> = Result
function FromOptional<Def extends z.ZodOptionalDef>(def: Def): tb.TSchema {
return tb.Optional(FromType(def.innerType))
type TFromOptional<Type extends z.ZodTypeAny, Result extends t.TSchema = t.TOptional<TFromType<Type>>> = Result
function FromOptional<Def extends z.ZodOptionalDef>(def: Def): t.TSchema {
return t.Optional(FromType(def.innerType))
}
// ------------------------------------------------------------------
// Promise
// ------------------------------------------------------------------
type TFromPromise<Type extends z.ZodTypeAny> = tb.Ensure<tb.TPromise<TFromType<Type>>>
function FromPromise<Def extends z.ZodPromiseDef>(def: Def): tb.TSchema {
return tb.Promise(FromType(def.type))
type TFromPromise<Type extends z.ZodTypeAny> = t.Ensure<t.TPromise<TFromType<Type>>>
function FromPromise<Def extends z.ZodPromiseDef>(def: Def): t.TSchema {
return t.Promise(FromType(def.type))
}
// ------------------------------------------------------------------
// Nullable
// ------------------------------------------------------------------
type TFromNullable<Type extends z.ZodTypeAny> = tb.Ensure<tb.TUnion<[tb.TNull, TFromType<Type>]>>
function FromNullable<Def extends z.ZodNullableDef>(def: Def): tb.TSchema {
return tb.Union([tb.Null(), FromType(def.innerType)])
type TFromNullable<Type extends z.ZodTypeAny> = t.Ensure<t.TUnion<[t.TNull, TFromType<Type>]>>
function FromNullable<Def extends z.ZodNullableDef>(def: Def): t.TSchema {
return t.Union([t.Null(), FromType(def.innerType)])
}
// ------------------------------------------------------------------
// Number
// ------------------------------------------------------------------
type TFromNumber = tb.TNumber
type TFromNumber = t.TNumber
// prettier-ignore
function FromNumber<Def extends z.ZodNumberDef>(def: Def) {
function FromNumber<Def extends z.ZodNumberDef>(def: Def): t.TSchema {
const options = def.checks.reduce((options, check) => {
return { ...options, ... (
check.kind === 'int' ? { multipleOf: 1 } :
@@ -205,124 +213,124 @@ function FromNumber<Def extends z.ZodNumberDef>(def: Def) {
{}
)}
}, {})
return tb.Number(options)
return t.Number(options)
}
// ------------------------------------------------------------------
// Never
// ------------------------------------------------------------------
type TFromNever = tb.TNever
function FromNever<Def extends z.ZodNeverDef>(def: Def) {
return tb.Never()
type TFromNever = t.TNever
function FromNever<Def extends z.ZodNeverDef>(def: Def): t.TSchema {
return t.Never()
}
// ------------------------------------------------------------------
// Null
// ------------------------------------------------------------------
type TFromNull = tb.TNull
function FromNull<Def extends z.ZodNullDef>(def: Def) {
return tb.Null()
type TFromNull = t.TNull
function FromNull<Def extends z.ZodNullDef>(def: Def): t.TSchema {
return t.Null()
}
// ------------------------------------------------------------------
// Readonly
// ------------------------------------------------------------------
type TFromReadonly<Type extends z.ZodTypeAny, Result extends tb.TSchema = tb.TReadonly<TFromType<Type>>> = Result
function FromReadonly<Def extends z.ZodReadonlyDef>(def: Def): tb.TSchema {
return tb.Readonly(FromType(def.innerType))
type TFromReadonly<Type extends z.ZodTypeAny, Result extends t.TSchema = t.TReadonly<TFromType<Type>>> = Result
function FromReadonly<Def extends z.ZodReadonlyDef>(def: Def): t.TSchema {
return t.Readonly(FromType(def.innerType))
}
// ------------------------------------------------------------------
// Record
// ------------------------------------------------------------------
type TFromRecord<Key extends z.ZodTypeAny, Value extends z.ZodTypeAny> = tb.Ensure<tb.TRecordOrObject<TFromType<Key>, TFromType<Value>>>
function FromRecord<Def extends z.ZodRecordDef>(def: Def): tb.TSchema {
return tb.Record(FromType(def.keyType), FromType(def.valueType))
type TFromRecord<Key extends z.ZodTypeAny, Value extends z.ZodTypeAny> = t.Ensure<t.TRecordOrObject<TFromType<Key>, TFromType<Value>>>
function FromRecord<Def extends z.ZodRecordDef>(def: Def): t.TSchema {
return t.Record(FromType(def.keyType), FromType(def.valueType))
}
// ------------------------------------------------------------------
// String
// ------------------------------------------------------------------
type TFromString = tb.TString
type TFromString = t.TString
// prettier-ignore
function FromString<Def extends z.ZodStringDef>(def: Def) {
function FromString<Def extends z.ZodStringDef>(def: Def): t.TSchema {
const options = def.checks.reduce((options, check) => {
return { ...options, ...(
check.kind === 'base64' ? { format: 'zod:base64' } :
check.kind === 'base64url' ? { format: 'zod:base64url' } :
check.kind === 'cidr' ? { format: check.version === 'v4' ? 'zod:cidrv4' : check.version === 'v6' ? 'zod:cidrv6' : 'zod:cidr' } :
check.kind === 'cuid' ? { format: 'zod:cuid' } :
check.kind === 'cuid2' ? { format: 'zod:cuid2' } :
check.kind === 'date' ? { format: 'zod:date' } :
check.kind === 'datetime' ? { format: 'zod:datetime' } :
check.kind === 'duration' ? { format: 'zod:duration' } :
check.kind === 'email' ? { format: 'zod:email' } :
check.kind === 'emoji' ? { format: 'zod:emoji' } :
check.kind === 'base64' ? { format: 'base64' } :
check.kind === 'base64url' ? { format: 'base64url' } :
check.kind === 'cidr' ? { format: check.version === 'v4' ? 'cidrv4' : check.version === 'v6' ? 'cidrv6' : 'cidr' } :
check.kind === 'cuid' ? { format: 'cuid' } :
check.kind === 'cuid2' ? { format: 'cuid2' } :
check.kind === 'date' ? { format: 'date' } :
check.kind === 'datetime' ? { format: 'datetime' } :
check.kind === 'duration' ? { format: 'duration' } :
check.kind === 'email' ? { format: 'email' } :
check.kind === 'emoji' ? { format: 'emoji' } :
check.kind === 'endsWith' ? { pattern: `${check.value}$` } :
check.kind === 'includes' ? { pattern: check.value } :
check.kind === 'ip' ? { format: check.version === 'v4' ? 'zod:ipv4' : check.version === 'v6' ? 'zod:ipv6' : 'zod:ip' } :
check.kind === 'jwt' ? { format: 'zod:jwt' } :
check.kind === 'ip' ? { format: check.version === 'v4' ? 'ipv4' : check.version === 'v6' ? 'ipv6' : 'ip' } :
check.kind === 'jwt' ? { format: 'jwt' } :
check.kind === 'length' ? { minLength: check.value, maxLength: check.value } :
check.kind === 'min' ? { minLength: check.value } :
check.kind === 'max' ? { maxLength: check.value } :
check.kind === 'nanoid' ? { format: 'zod:nanoid' } :
check.kind === 'nanoid' ? { format: 'nanoid' } :
check.kind === 'regex' ? { pattern: check.regex.source } :
check.kind === 'startsWith' ? { pattern: `^${check.value}` } :
check.kind === 'time' ? { format: 'zod:time' } :
check.kind === 'ulid' ? { format: 'zod:ulid' } :
check.kind === 'url' ? { format: 'zod:url' } :
check.kind === 'uuid' ? { format: 'zod:uuid' } :
check.kind === 'time' ? { format: 'time' } :
check.kind === 'ulid' ? { format: 'ulid' } :
check.kind === 'url' ? { format: 'url' } :
check.kind === 'uuid' ? { format: 'uuid' } :
{}
)}
}, {})
return tb.String(options)
return t.String(options)
}
// ------------------------------------------------------------------
// Symbol
// ------------------------------------------------------------------
type TFromSymbol = tb.TSymbol
function FromSymbol<Def extends z.ZodSymbolDef>(def: Def) {
return tb.Symbol()
type TFromSymbol = t.TSymbol
function FromSymbol<Def extends z.ZodSymbolDef>(def: Def): t.TSchema {
return t.Symbol()
}
// ------------------------------------------------------------------
// Tuple
// ------------------------------------------------------------------
// prettier-ignore
type TFromTuple<Types extends z.ZodTypeAny[], Result extends tb.TSchema[] = []> = (
type TFromTuple<Types extends z.ZodTypeAny[], Result extends t.TSchema[] = []> = (
Types extends [infer Left extends z.ZodTypeAny, ...infer Right extends z.ZodTypeAny[]]
? TFromTuple<Right, [...Result, TFromType<Left>]>
: tb.TTuple<Result>
: t.TTuple<Result>
)
function FromTuple<Def extends z.ZodTupleDef>(def: Def): tb.TSchema {
return tb.Tuple(def.items.map((item) => FromType(item)))
function FromTuple<Def extends z.ZodTupleDef>(def: Def): t.TSchema {
return t.Tuple(def.items.map((item) => FromType(item)))
}
// ------------------------------------------------------------------
// Undefined
// ------------------------------------------------------------------
type TFromUndefined = tb.TUndefined
function FromUndefined<Def extends z.ZodUndefinedDef>(def: Def) {
return tb.Undefined()
type TFromUndefined = t.TUndefined
function FromUndefined<Def extends z.ZodUndefinedDef>(def: Def): t.TSchema {
return t.Undefined()
}
// ------------------------------------------------------------------
// Union
// ------------------------------------------------------------------
// prettier-ignore
type TFromUnion<Types extends z.ZodTypeAny[], Result extends tb.TSchema[] = []> = (
type TFromUnion<Types extends z.ZodTypeAny[], Result extends t.TSchema[] = []> = (
Types extends [infer Left extends z.ZodTypeAny, ...infer Right extends z.ZodTypeAny[]]
? TFromUnion<Right, [...Result, TFromType<Left>]>
: tb.TUnion<Result>
: t.TUnion<Result>
)
function FromUnion<Def extends z.ZodUnionDef>(def: Def): tb.TSchema {
return tb.Union(def.options.map((item) => FromType(item)))
function FromUnion<Def extends z.ZodUnionDef>(def: Def): t.TSchema {
return t.Union(def.options.map((item) => FromType(item)))
}
// ------------------------------------------------------------------
// Unknown
// ------------------------------------------------------------------
type TFromUnknown = tb.TUnknown
function FromUnknown<Def extends z.ZodUnknownDef>(def: Def) {
return tb.Unknown()
type TFromUnknown = t.TUnknown
function FromUnknown<Def extends z.ZodUnknownDef>(def: Def): t.TSchema {
return t.Unknown()
}
// ------------------------------------------------------------------
// Void
// ------------------------------------------------------------------
type TFromVoid = tb.TVoid
function FromVoid<Def extends z.ZodVoidDef>(def: Def) {
return tb.Void()
type TFromVoid = t.TVoid
function FromVoid<Def extends z.ZodVoidDef>(def: Def): t.TSchema {
return t.Void()
}
// ------------------------------------------------------------------
// Type
@@ -337,6 +345,7 @@ type TFromType<Type extends z.ZodType> = (
Type extends z.ZodDefault<infer Type> ? TFromDefault<Type> :
Type extends z.ZodDiscriminatedUnion<infer Discriminator, infer Types> ? TFromDiscriminatedUnion<Discriminator, Types> :
Type extends z.ZodEffects<infer Input, infer Output> ? TFromEffects<Input, Output> :
Type extends z.ZodEnum<infer Variants> ? TFromEnum<Variants> :
Type extends z.ZodLiteral<infer Value> ? TFromLiteral<Value> :
Type extends z.ZodNullable<infer Type> ? TFromNullable<Type> :
Type extends z.ZodObject<infer Properties> ? TFromObject<Properties> :
@@ -349,17 +358,17 @@ type TFromType<Type extends z.ZodType> = (
Type extends z.ZodNull ? TFromNull :
Type extends z.ZodString ? TFromString :
Type extends z.ZodSymbol ? TFromSymbol :
Type extends z.ZodTuple<infer Types> ? TFromTuple<tb.Assert<Types, z.ZodTypeAny[]>> :
Type extends z.ZodTuple<infer Types> ? TFromTuple<t.Assert<Types, z.ZodTypeAny[]>> :
Type extends z.ZodUndefined ? TFromUndefined :
Type extends z.ZodUnion<infer Types> ? TFromUnion<tb.Assert<Types, z.ZodTypeAny[]>> :
Type extends z.ZodUnion<infer Types> ? TFromUnion<t.Assert<Types, z.ZodTypeAny[]>> :
Type extends z.ZodUnknown ? TFromUnknown :
Type extends z.ZodVoid ? TFromVoid :
// Intersection (Ensure Last Due to Zod Differentiation Issue)
Type extends z.ZodIntersection<infer Left, infer Right> ? TFromIntersect<[Left, Right]> :
tb.TNever
t.TNever
)
// prettier-ignore
function FromType<Type extends z.ZodType>(type: Type): tb.TSchema {
function FromType<Type extends z.ZodType>(type: Type): t.TSchema {
const schema = (
type instanceof z.ZodAny ? FromAny(type._def) :
type instanceof z.ZodArray ? FromArray(type._def) :
@@ -369,6 +378,7 @@ function FromType<Type extends z.ZodType>(type: Type): tb.TSchema {
type instanceof z.ZodDefault ? FromDefault(type._def) :
type instanceof z.ZodDiscriminatedUnion ? FromDiscriminatedUnion(type._def) :
type instanceof z.ZodEffects ? FromEffects(type) :
type instanceof z.ZodEnum ? FromEnum(type._def) :
type instanceof z.ZodLiteral ? FromLiteral(type._def) :
type instanceof z.ZodNullable ? FromNullable(type._def) :
type instanceof z.ZodObject ? FromObject(type._def, type.shape) :
@@ -388,16 +398,19 @@ function FromType<Type extends z.ZodType>(type: Type): tb.TSchema {
type instanceof z.ZodVoid ? FromVoid(type._def) :
// Intersection (Ensure Last Due to Zod Differentiation Issue)
type instanceof z.ZodIntersection ? FromIntersect(type._def) :
tb.Never()
) as tb.TSchema
return tb.CreateType(schema, Options(type)) as tb.TSchema
t.Never()
) as t.TSchema
return t.CreateType(schema, Options(type)) as t.TSchema
}
// ------------------------------------------------------------------
// Box
// TypeBoxFromZod
// ------------------------------------------------------------------
/** Converts a Zod Type to a TypeBox Type */
export type TBox<Type extends unknown> = Type extends z.ZodType ? TFromType<Type> : undefined
/** Converts a Zod Type to a TypeBox Type */
export function Box<Type extends unknown, Result extends TBox<Type> = TBox<Type>>(type: Type): Result {
return (type instanceof z.ZodType ? FromType(type) : undefined) as never
// prettier-ignore
export type TTypeBoxFromZod<Type extends unknown> = (
Type extends z.ZodType ? TFromType<Type> : t.TNever
)
// prettier-ignore
export function TypeBoxFromZod<Type extends unknown, Result extends TTypeBoxFromZod<Type> = TTypeBoxFromZod<Type>>(type: Type): Result {
return (type instanceof z.ZodType ? FromType(type) : t.Never()) as never
}

63
src/typebox/typebox.ts Normal file
View File

@@ -0,0 +1,63 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TTypeBoxFromSyntax, TypeBoxFromSyntax } from './typebox-from-syntax'
import { TTypeBoxFromTypeBox, TypeBoxFromTypeBox } from './typebox-from-typebox'
import { TTypeBoxFromValibot, TypeBoxFromValibot } from './typebox-from-valibot'
import { TTypeBoxFromZod, TypeBoxFromZod } from './typebox-from-zod'
import * as Guard from '../guard'
import * as t from '@sinclair/typebox'
/** Creates a TypeBox type from Syntax or another Type */
// prettier-ignore
export type TTypeBox<Type extends object | string> = (
Guard.TIsSyntax<Type> extends true ? TTypeBoxFromSyntax<Type> :
Guard.TIsTypeBox<Type> extends true ? TTypeBoxFromTypeBox<Type> :
Guard.TIsValibot<Type> extends true ? TTypeBoxFromValibot<Type> :
Guard.TIsZod<Type> extends true ? TTypeBoxFromZod<Type> :
t.TNever
)
/** Creates a TypeBox type from Syntax or another Type */
// prettier-ignore
export function TypeBox<Type extends object | string>(type: Type): TTypeBox<Type> {
return (
Guard.IsSyntax(type) ? TypeBoxFromSyntax(type) :
Guard.IsTypeBox(type) ? TypeBoxFromTypeBox(type) :
Guard.IsValibot(type) ? TypeBoxFromValibot(type) :
Guard.IsZod(type) ? TypeBoxFromZod(type) :
t.Never()
) as never
}
/**
* Creates a TypeBox type from Syntax or another Type
* @deprecated Use TypeBox() export instead
*/
export function Box<Type extends object | string>(type: Type): TTypeBox<Type> {
return TypeBox(type)
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typebox-adapter
@sinclair/typemap
The MIT License (MIT)
@@ -26,4 +26,10 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
export * from './box'
import * as v from 'valibot'
// Valibot really should consider providing default generic type parameters
export type BaseConstraint = v.BaseValidation<any, unknown, v.BaseIssue<unknown>> | v.BaseMetadata<any> | v.RegexAction<any, any>
export type BaseRecordKey = v.BaseSchema<string, string | number | symbol, v.BaseIssue<unknown>>
export type BaseSchema = v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>
export type BaseError = v.ErrorMessage<any>

View File

@@ -0,0 +1,46 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TTypeBoxFromSyntax, TypeBoxFromSyntax } from '../typebox/typebox-from-syntax'
import { ValibotFromTypeBox, TValibotFromTypeBox } from './valibot-from-typebox'
import * as t from '@sinclair/typebox'
import * as c from './common'
// prettier-ignore
export type TValibotFromSyntax<Type extends object | string,
Schema extends t.TSchema = TTypeBoxFromSyntax<Type>,
Result extends c.BaseSchema = TValibotFromTypeBox<Schema>
> = Result
// prettier-ignore
export function ValibotFromSyntax<Type extends object | string>(type: Type): TValibotFromSyntax<Type> {
const schema = TypeBoxFromSyntax(type)
const result = ValibotFromTypeBox(schema)
return result
}

View File

@@ -0,0 +1,394 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as v from 'valibot'
import * as c from './common'
// ------------------------------------------------------------------
// Constraints
// ------------------------------------------------------------------
function CreateConstraints(type: t.TSchema, initial: c.BaseConstraint[] = []): c.BaseConstraint[] {
const constraints: c.BaseConstraint[] = []
if (t.ValueGuard.IsString(type.description)) constraints.push(v.description(type.description!))
if (t.ValueGuard.IsString(type.title)) constraints.push(v.title(type.title!))
if (t.ValueGuard.IsObject(type.metadata)) constraints.push(v.metadata(type.metadata!))
return [...initial, ...constraints]
}
function CreateType(type: c.BaseSchema, constraints: c.BaseConstraint[] = []) {
return constraints.length === 0 ? type : v.pipe(type, ...constraints)
}
// ------------------------------------------------------------------
// Any
// ------------------------------------------------------------------
type TFromAny<Result = v.AnySchema> = Result
function FromAny(type: t.TAny): c.BaseSchema {
return CreateType(v.any(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Array
// ------------------------------------------------------------------
type TFromArray<Type extends t.TSchema, Result = v.ArraySchema<TFromType<Type>, c.BaseError>> = Result
function FromArray(type: t.TArray): c.BaseSchema {
const { minItems, maxItems /* minContains, maxContains, contains */ } = type
const constraints = CreateConstraints(type)
if (t.ValueGuard.IsNumber(minItems)) constraints.push(v.minLength(minItems))
if (t.ValueGuard.IsNumber(maxItems)) constraints.push(v.maxLength(maxItems))
const mapped = v.array(FromType(type.items))
return CreateType(mapped, constraints)
}
// ------------------------------------------------------------------
// BigInt
// ------------------------------------------------------------------
type TFromBigInt<Result = v.BigintSchema<c.BaseError>> = Result
function FromBigInt(type: t.TBigInt): c.BaseSchema {
return CreateType(v.bigint(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Boolean
// ------------------------------------------------------------------
type TFromBoolean<Result = v.BooleanSchema<c.BaseError>> = Result
function FromBoolean(type: t.TBoolean): c.BaseSchema {
return CreateType(v.boolean(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Date
// ------------------------------------------------------------------
type TFromDate<Result = v.DateSchema<c.BaseError>> = Result
function FromDate(type: t.TDate): c.BaseSchema {
return CreateType(v.date(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Function
// ------------------------------------------------------------------
// prettier-ignore
type TFromFunction<Parameters extends t.TSchema[], ReturnType extends t.TSchema> = (
v.FunctionSchema<any>
)
function FromFunction(type: t.TFunction): c.BaseSchema {
return CreateType(v.function(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Integer
// ------------------------------------------------------------------
type TFromInteger = v.NumberSchema<c.BaseError>
function FromInteger(type: t.TInteger): c.BaseSchema {
const { exclusiveMaximum, exclusiveMinimum, minimum, maximum, multipleOf } = type
const constraints = CreateConstraints(type, [v.integer()])
if (t.ValueGuard.IsNumber(exclusiveMinimum)) constraints.push(v.minValue(exclusiveMinimum + 1))
if (t.ValueGuard.IsNumber(exclusiveMaximum)) constraints.push(v.minValue(exclusiveMaximum - 1))
if (t.ValueGuard.IsNumber(maximum)) constraints.push(v.maxValue(maximum))
if (t.ValueGuard.IsNumber(minimum)) constraints.push(v.minValue(minimum))
if (t.ValueGuard.IsNumber(multipleOf)) constraints.push(v.multipleOf(multipleOf))
return CreateType(v.number(), constraints)
}
// ------------------------------------------------------------------
// Intersect
// ------------------------------------------------------------------
type TFromIntersect<Types extends t.TSchema[], Result extends c.BaseSchema[] = []> = Types extends [infer Left extends t.TSchema, ...infer Right extends t.TSchema[]]
? TFromIntersect<Right, [...Result, TFromType<Left>]>
: v.IntersectSchema<Result, any>
function FromIntersect(type: t.TIntersect): c.BaseSchema {
const schemas = type.allOf.map((schema) => FromType(schema))
return CreateType(v.intersect(schemas), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Literal
// ------------------------------------------------------------------
type TFromLiteral<Value extends t.TLiteralValue> = v.LiteralSchema<Value, any>
function FromLiteral(type: t.TLiteral): c.BaseSchema {
return CreateType(v.literal(type.const), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Object
// ------------------------------------------------------------------
// prettier-ignore
type TFromObject<Properties extends t.TProperties,
Result = v.ObjectSchema<{
[Key in keyof Properties]: TFromType<Properties[Key]>
}, c.BaseError>
> = Result
function FromObject(type: t.TObject): c.BaseSchema {
const { additionalProperties } = type
const constraints = CreateConstraints(type)
const properties = globalThis.Object.getOwnPropertyNames(type.properties).reduce((result, key) => ({ ...result, [key]: FromType(type.properties[key]) }), {})
return additionalProperties === false
? CreateType(v.strictObject(properties), constraints) // facade
: CreateType(v.object(properties), constraints)
}
// ------------------------------------------------------------------
// Promise
// ------------------------------------------------------------------
type TFromPromise<_Type extends t.TSchema, Result = v.PromiseSchema<c.BaseError>> = Result
function FromPromise(type: t.TPromise): c.BaseSchema {
return CreateType(v.promise(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Record
// ------------------------------------------------------------------
type TFromRegExp<Result = v.StringSchema<c.BaseError>> = Result
function FromRegExp(type: t.TRegExp): c.BaseSchema {
const { minLength, maxLength } = type
const constraints = CreateConstraints(type, [v.regex(new RegExp(type.source, type.flags))])
if (t.ValueGuard.IsNumber(maxLength)) constraints.push(v.maxLength(maxLength))
if (t.ValueGuard.IsNumber(minLength)) constraints.push(v.minLength(minLength))
return CreateType(v.string(), constraints)
}
// ------------------------------------------------------------------
// Record
// ------------------------------------------------------------------
// prettier-ignore
type TFromRecord<Key extends t.TSchema, Value extends t.TSchema> = (
TFromType<Key> extends infer MappedKey extends c.BaseRecordKey
? v.RecordSchema<MappedKey, TFromType<Value>, c.BaseError>
: v.RecordSchema<v.StringSchema<c.BaseError>, TFromType<Value>, c.BaseError>
)
// prettier-ignore
function FromRecord(type: t.TRecord): c.BaseSchema {
const constraints = CreateConstraints(type)
const pattern = globalThis.Object.getOwnPropertyNames(type.patternProperties)[0]
const value = FromType(type.patternProperties[pattern])
return (
pattern === t.PatternStringExact
? CreateType(v.record(v.string(), value), constraints)
: CreateType(v.record(v.pipe(v.string(), v.regex(new RegExp(pattern))), value), constraints)
)
}
// ------------------------------------------------------------------
// Optional
// ------------------------------------------------------------------
type TFromOptional<Type extends t.TSchema, Result = v.OptionalSchema<TFromType<Type>, c.BaseError>> = Result
function FromOptional(type: t.TOptional<t.TSchema>): c.BaseSchema {
return v.optional(FromType(t.Optional(type, false)))
}
// ------------------------------------------------------------------
// Readonly
// ------------------------------------------------------------------
type TFromReadonly<Type extends t.TSchema, Result = TFromType<Type>> = Result
function FromReadonly(type: t.TReadonly<t.TSchema>): c.BaseSchema {
return FromType(t.Readonly(type, false))
}
// ------------------------------------------------------------------
// Never
// ------------------------------------------------------------------
type TFromNever<Result = v.NeverSchema<c.BaseError>> = Result
function FromNever(type: t.TNever): c.BaseSchema {
return CreateType(v.never(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Null
// ------------------------------------------------------------------
type TFromNull<Result = v.NullSchema<c.BaseError>> = Result
function FromNull(type: t.TNull): c.BaseSchema {
return CreateType(v.null(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Number
// ------------------------------------------------------------------
type TFromNumber<Result = v.NumberSchema<c.BaseError>> = Result
function FromNumber(type: t.TNumber): c.BaseSchema {
const { exclusiveMaximum, exclusiveMinimum, minimum, maximum, multipleOf } = type
const constraints = CreateConstraints(type)
if (t.ValueGuard.IsNumber(exclusiveMinimum)) constraints.push(v.minValue(exclusiveMinimum + 1))
if (t.ValueGuard.IsNumber(exclusiveMaximum)) constraints.push(v.minValue(exclusiveMaximum - 1))
if (t.ValueGuard.IsNumber(maximum)) constraints.push(v.maxValue(maximum))
if (t.ValueGuard.IsNumber(minimum)) constraints.push(v.minValue(minimum))
if (t.ValueGuard.IsNumber(multipleOf)) constraints.push(v.multipleOf(multipleOf))
return CreateType(v.number(), constraints)
}
// ------------------------------------------------------------------
// String
// ------------------------------------------------------------------
type TFromString<Result = v.StringSchema<c.BaseError>> = Result
// prettier-ignore
function FromString(type: t.TString): c.BaseSchema {
const { minLength, maxLength, pattern, format } = type
const constraints = CreateConstraints(type)
if (t.ValueGuard.IsNumber(maxLength)) constraints.push(v.maxLength(maxLength))
if (t.ValueGuard.IsNumber(minLength)) constraints.push(v.minLength(minLength))
if (t.ValueGuard.IsString(pattern)) constraints.push(v.regex(new RegExp(pattern)))
if (t.ValueGuard.IsString(format)) constraints.push(...(
format === 'base64' ? [v.base64()] :
format === 'bic' ? [v.bic()] :
format === 'credit_card' ? [v.creditCard()] :
format === 'cuid2' ? [v.cuid2()] :
format === 'decimal' ? [v.decimal()] :
format === 'digits' ? [v.digits()] :
format === 'email' ? [v.email()] :
format === 'emoji' ? [v.emoji()] :
format === 'ip' ? [v.ip()] :
format === 'ipv4' ? [v.ipv4()] :
format === 'ipv6' ? [v.ipv6()] :
format === 'iso_date' ? [v.isoDate()] :
format === 'iso_date_time' ? [v.isoDateTime()] :
format === 'iso_time' ? [v.isoTime()] :
format === 'iso_time_second' ? [v.isoTimeSecond()] :
format === 'iso_timestamp' ? [v.isoTimestamp()] :
format === 'iso_week' ? [v.isoWeek()] :
format === 'mac' ? [v.mac()] :
format === 'mac48' ? [v.mac48()] :
format === 'mac64' ? [v.mac64()] :
format === 'nanoid' ? [v.nanoid()] :
format === 'octal' ? [v.octal()] :
format === 'ulid' ? [v.ulid()] :
format === 'url' ? [v.url()] :
format === 'uuid' ? [v.uuid()] :
[]))
return CreateType(v.string(), constraints)
}
// ------------------------------------------------------------------
// Symbol
// ------------------------------------------------------------------
type TFromSymbol<Result = v.SymbolSchema<c.BaseError>> = Result
function FromSymbol(type: t.TSymbol): c.BaseSchema {
return CreateType(v.symbol(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Tuple
// ------------------------------------------------------------------
// prettier-ignore
type TFromTuple<Types extends t.TSchema[], Mapped extends c.BaseSchema[] = TFromTypes<Types>> = (
v.TupleSchema<Mapped, c.BaseError>
)
function FromTuple(type: t.TTuple): c.BaseSchema {
const mapped = FromTypes(type.items || []) as [] | [c.BaseSchema, ...c.BaseSchema[]]
return CreateType(v.tuple(mapped), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Undefined
// ------------------------------------------------------------------
type TFromUndefined<Result = v.UndefinedSchema<c.BaseError>> = Result
function FromUndefined(type: t.TUndefined): c.BaseSchema {
return CreateType(v.undefined(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Union
// ------------------------------------------------------------------
// prettier-ignore
type TFromUnion<Types extends t.TSchema[], Mapped extends c.BaseSchema[] = TFromTypes<Types>, Result = v.UnionSchema<Mapped, c.BaseError>> = (
Result
)
function FromUnion(type: t.TUnion): c.BaseSchema {
const mapped = FromTypes(type.anyOf) as [c.BaseSchema, c.BaseSchema, ...c.BaseSchema[]]
return CreateType(v.union(mapped), CreateConstraints(type))
}
// ------------------------------------------------------------------
// TUnknown
// ------------------------------------------------------------------
type TFromUnknown<Result = v.UnknownSchema> = Result
function FromUnknown(type: t.TUnknown): c.BaseSchema {
return CreateType(v.unknown(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Void
// ------------------------------------------------------------------
type TFromVoid<Result = v.VoidSchema<c.BaseError>> = Result
function FromVoid(type: t.TVoid): c.BaseSchema {
return CreateType(v.void(), CreateConstraints(type))
}
// ------------------------------------------------------------------
// Types
// ------------------------------------------------------------------
type TFromTypes<Types extends t.TSchema[], Result extends c.BaseSchema[] = []> = Types extends [infer Left extends t.TSchema, ...infer Right extends t.TSchema[]] ? TFromTypes<Right, [...Result, TFromType<Left>]> : Result
function FromTypes(types: t.TSchema[]): c.BaseSchema[] {
return types.map((type) => FromType(type))
}
// ------------------------------------------------------------------
// Type
// ------------------------------------------------------------------
// prettier-ignore
type TFromType<Type extends t.TSchema> = (
Type extends t.TReadonly<infer Type extends t.TSchema> ? TFromReadonly<Type> :
Type extends t.TOptional<infer Type extends t.TSchema> ? TFromOptional<Type> :
Type extends t.TAny ? TFromAny :
Type extends t.TArray<infer Type extends t.TSchema> ? TFromArray<Type> :
Type extends t.TBigInt ? TFromBigInt :
Type extends t.TBoolean ? TFromBoolean :
Type extends t.TDate ? TFromDate :
Type extends t.TFunction<infer Parameters extends t.TSchema[], infer ReturnType extends t.TSchema> ? TFromFunction<Parameters, ReturnType> :
Type extends t.TInteger ? TFromInteger :
Type extends t.TIntersect<infer Types extends t.TSchema[]> ? TFromIntersect<Types> :
Type extends t.TLiteral<infer Value extends t.TLiteralValue> ? TFromLiteral<Value> :
Type extends t.TNull ? TFromNull :
Type extends t.TNever ? TFromNever :
Type extends t.TNumber ? TFromNumber :
Type extends t.TObject<infer Properties extends t.TProperties> ? TFromObject<Properties> :
Type extends t.TPromise<infer Type extends t.TSchema> ? TFromPromise<Type> :
Type extends t.TRecord<infer Key extends t.TSchema, infer Value extends t.TSchema> ? TFromRecord<Key, Value> :
Type extends t.TRegExp ? TFromRegExp :
Type extends t.TString ? TFromString :
Type extends t.TSymbol ? TFromSymbol :
Type extends t.TTuple<infer Types extends t.TSchema[]> ? TFromTuple<Types> :
Type extends t.TUndefined ? TFromUndefined :
Type extends t.TUnion<infer Types extends t.TSchema[]> ? TFromUnion<Types> :
Type extends t.TUnknown ? TFromUnknown :
Type extends t.TVoid ? TFromVoid :
v.NeverSchema<c.BaseError>
)
// prettier-ignore
function FromType(type: t.TSchema): c.BaseSchema {
return (
t.KindGuard.IsReadonly(type) ? FromReadonly(type) :
t.KindGuard.IsOptional(type) ? FromOptional(type) :
t.KindGuard.IsAny(type) ? FromAny(type) :
t.KindGuard.IsArray(type) ? FromArray(type) :
t.KindGuard.IsBigInt(type) ? FromBigInt(type) :
t.KindGuard.IsBoolean(type) ? FromBoolean(type) :
t.KindGuard.IsDate(type) ? FromDate(type) :
t.KindGuard.IsFunction(type) ? FromFunction(type) :
t.KindGuard.IsInteger(type) ? FromInteger(type) :
t.KindGuard.IsIntersect(type) ? FromIntersect(type) :
t.KindGuard.IsLiteral(type) ? FromLiteral(type) :
t.KindGuard.IsNever(type) ? FromNever(type) :
t.KindGuard.IsNull(type) ? FromNull(type) :
t.KindGuard.IsNumber(type) ? FromNumber(type) :
t.KindGuard.IsObject(type) ? FromObject(type) :
t.KindGuard.IsPromise(type) ? FromPromise(type) :
t.KindGuard.IsRegExp(type) ? FromRegExp(type) :
t.KindGuard.IsRecord(type) ? FromRecord(type) :
t.KindGuard.IsString(type) ? FromString(type) :
t.KindGuard.IsSymbol(type) ? FromSymbol(type) :
t.KindGuard.IsTuple(type) ? FromTuple(type) :
t.KindGuard.IsUndefined(type) ? FromUndefined(type) :
t.KindGuard.IsUnion(type) ? FromUnion(type) :
t.KindGuard.IsUnknown(type) ? FromUnknown(type) :
t.KindGuard.IsVoid(type) ? FromVoid(type) :
v.never()
)
}
// ------------------------------------------------------------------
// ValibotFromTypeBox
// ------------------------------------------------------------------
// prettier-ignore
export type TValibotFromTypeBox<Type extends object | string> = (
Type extends t.TSchema ? TFromType<Type> : v.NeverSchema<c.BaseError>
)
// prettier-ignore
export function ValibotFromTypeBox<Type extends object | string>(type: Type): TValibotFromTypeBox<Type> {
return (t.KindGuard.IsSchema(type) ? FromType(type) : v.never()) as never
}

View File

@@ -0,0 +1,40 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as Guard from '../guard'
import * as v from 'valibot'
import * as c from './common'
// prettier-ignore
export type TValibotFromValibot<Type extends object | string,
Result extends c.BaseSchema = Type extends c.BaseSchema ? Type : v.NeverSchema<c.BaseError>
> = Result
// prettier-ignore
export function ValibotFromValibot<Type extends object | string>(type: Type): TValibotFromValibot<Type> {
return (Guard.IsValibot(type) ? type : undefined) as never
}

View File

@@ -0,0 +1,46 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { type TTypeBoxFromZod, TypeBoxFromZod } from '../typebox/typebox-from-zod'
import { type TValibotFromTypeBox, ValibotFromTypeBox } from './valibot-from-typebox'
import * as t from '@sinclair/typebox'
import * as v from 'valibot'
// prettier-ignore
export type TValibotFromZod<
Type extends object | string,
Schema extends t.TSchema = TTypeBoxFromZod<Type>,
Result extends v.BaseSchema<any, any, any> = TValibotFromTypeBox<Schema>
> = Result
// prettier-ignore
export function ValibotFromZod<Type extends object | string>(type: Type): TValibotFromZod<Type> {
const schema = TypeBoxFromZod(type)
const result = ValibotFromTypeBox(schema)
return result
}

56
src/valibot/valibot.ts Normal file
View File

@@ -0,0 +1,56 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { type TValibotFromSyntax, ValibotFromSyntax } from './valibot-from-syntax'
import { type TValibotFromTypeBox, ValibotFromTypeBox } from './valibot-from-typebox'
import { type TValibotFromValibot, ValibotFromValibot } from './valibot-from-valibot'
import { type TValibotFromZod, ValibotFromZod } from './valibot-from-zod'
import * as Guard from '../guard'
import * as v from 'valibot'
import * as c from './common'
/** Creates a Valibot type from Syntax or another Type */
// prettier-ignore
export type TValibot<Type extends object | string> = (
Guard.TIsSyntax<Type> extends true ? TValibotFromSyntax<Type> :
Guard.TIsTypeBox<Type> extends true ? TValibotFromTypeBox<Type> :
Guard.TIsValibot<Type> extends true ? TValibotFromValibot<Type> :
Guard.TIsZod<Type> extends true ? TValibotFromZod<Type> :
v.NeverSchema<c.BaseError>
)
/** Creates a Valibot type from Syntax or another Type */
// prettier-ignore
export function Valibot<Type extends object | string, Result = TValibot<Type>>(type: Type): Result {
return (
Guard.IsSyntax(type) ? ValibotFromSyntax(type) :
Guard.IsTypeBox(type) ? ValibotFromTypeBox(type) :
Guard.IsValibot(type) ? ValibotFromValibot(type) :
Guard.IsZod(type) ? ValibotFromZod(type as any) :
v.never()
) as never
}

View File

@@ -0,0 +1,45 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TTypeBoxFromSyntax, TypeBoxFromSyntax } from '../typebox/typebox-from-syntax'
import { ZodFromTypeBox, TZodFromTypeBox } from './zod-from-typebox'
import * as t from '@sinclair/typebox'
import * as z from 'zod'
// prettier-ignore
export type TZodFromSyntax<Type extends object | string,
Schema extends t.TSchema = TTypeBoxFromSyntax<Type>,
Result extends z.ZodTypeAny | z.ZodEffects<any> = TZodFromTypeBox<Schema>
> = Result
// prettier-ignore
export function ZodFromSyntax<Type extends string>(type: Type): TZodFromSyntax<Type> {
const schema = TypeBoxFromSyntax(type)
const result = ZodFromTypeBox(schema)
return result
}

389
src/zod/zod-from-typebox.ts Normal file
View File

@@ -0,0 +1,389 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import * as t from '@sinclair/typebox'
import * as z from 'zod'
// ------------------------------------------------------------------
// Constraint
// ------------------------------------------------------------------
type TConstraint<Input extends z.ZodTypeAny = z.ZodTypeAny, Output extends z.ZodTypeAny = Input> = (input: Input) => Output
// ------------------------------------------------------------------
// Any
// ------------------------------------------------------------------
type TFromAny<Result = z.ZodAny> = Result
function FromAny(_type: t.TAny): z.ZodTypeAny {
return z.any()
}
// ------------------------------------------------------------------
// Array
// ------------------------------------------------------------------
type TFromArray<Type extends t.TSchema, Result = z.ZodArray<TFromType<Type>>> = Result
function FromArray(type: t.TArray): z.ZodTypeAny {
const constraints: TConstraint<z.ZodArray<z.ZodTypeAny, any>>[] = []
const { minItems, maxItems /* minContains, maxContains, contains */ } = type
if (t.ValueGuard.IsNumber(minItems)) constraints.push((input) => input.min(minItems))
if (t.ValueGuard.IsNumber(maxItems)) constraints.push((input) => input.max(maxItems))
const mapped = z.array(FromType(type.items))
return constraints.reduce((type, constraint) => constraint(type), mapped)
}
// ------------------------------------------------------------------
// BigInt
// ------------------------------------------------------------------
type TFromBigInt<Result = z.ZodBigInt> = Result
function FromBigInt(_type: t.TBigInt): z.ZodTypeAny {
return z.bigint()
}
// ------------------------------------------------------------------
// Boolean
// ------------------------------------------------------------------
type TFromBoolean<Result = z.ZodBoolean> = Result
function FromBoolean(_type: t.TBoolean): z.ZodTypeAny {
return z.boolean()
}
// ------------------------------------------------------------------
// Date
// ------------------------------------------------------------------
type TFromDate<Result = z.ZodDate> = Result
function FromDate(_type: t.TDate): z.ZodTypeAny {
return z.date()
}
// ------------------------------------------------------------------
// Function
// ------------------------------------------------------------------
// prettier-ignore
type TFromFunction<Parameters extends t.TSchema[], ReturnType extends t.TSchema,
MappedParameters extends z.ZodTypeAny[] = TFromTypes<Parameters>
> = (
MappedParameters extends [z.ZodTypeAny, ...z.ZodTypeAny[]] | []
? z.ZodFunction<z.ZodTuple<MappedParameters>, TFromType<ReturnType>>
: z.ZodNever
)
function FromFunction(type: t.TFunction): z.ZodTypeAny {
const mappedParameters = FromTypes(type.parameters) as [] | [z.ZodTypeAny, ...z.ZodTypeAny[]]
return z.function(z.tuple(mappedParameters), FromType(type.returns))
}
// ------------------------------------------------------------------
// Integer
// ------------------------------------------------------------------
type TFromInteger<Result = z.ZodNumber> = Result
function FromInteger(type: t.TInteger): z.ZodTypeAny {
const { exclusiveMaximum, exclusiveMinimum, minimum, maximum, multipleOf } = type
const constraints: TConstraint<z.ZodNumber>[] = [(value) => value.int()]
if (t.ValueGuard.IsNumber(exclusiveMinimum)) constraints.push((input) => input.min(exclusiveMinimum + 1))
if (t.ValueGuard.IsNumber(exclusiveMaximum)) constraints.push((input) => input.min(exclusiveMaximum - 1))
if (t.ValueGuard.IsNumber(maximum)) constraints.push((input) => input.max(maximum))
if (t.ValueGuard.IsNumber(minimum)) constraints.push((input) => input.min(minimum))
if (t.ValueGuard.IsNumber(multipleOf)) constraints.push((input) => input.multipleOf(multipleOf))
return constraints.reduce((input, constraint) => constraint(input), z.number())
}
// ------------------------------------------------------------------
// Intersect
// ------------------------------------------------------------------
type TFromIntersect<Types extends t.TSchema[], Result extends z.ZodTypeAny = z.ZodUnknown> = Types extends [infer Left extends t.TSchema, ...infer Right extends t.TSchema[]]
? TFromIntersect<Right, z.ZodIntersection<TFromType<Left>, Result>>
: Result
function FromIntersect(type: t.TIntersect): z.ZodTypeAny {
return type.allOf.reduce((result, left) => {
return z.intersection(FromType(left), result) as never
}, z.unknown()) as never
}
// ------------------------------------------------------------------
// Literal
// ------------------------------------------------------------------
type TFromLiteral<Value extends t.TLiteralValue, Result = z.ZodLiteral<Value>> = Result
function FromLiteral(type: t.TLiteral): z.ZodTypeAny {
return z.literal(type.const)
}
// ------------------------------------------------------------------
// Object
// ------------------------------------------------------------------
type TFromObject<
Properties extends t.TProperties,
Result = z.ZodObject<{
[Key in keyof Properties]: TFromType<Properties[Key]>
}>,
> = Result
// prettier-ignore
function FromObject(type: t.TObject): z.ZodTypeAny {
const constraints: TConstraint<z.ZodObject<any, any, any>>[] = []
const { additionalProperties } = type
if (additionalProperties === false) constraints.push((input) => input.strict())
if (t.KindGuard.IsSchema(additionalProperties)) constraints.push((input) => input.catchall(FromType(additionalProperties)))
const properties = globalThis.Object.getOwnPropertyNames(type.properties).reduce((result, key) => ({ ...result, [key]: FromType(type.properties[key]) }), {})
return constraints.reduce((type, constraint) => constraint(type), z.object(properties))
}
// ------------------------------------------------------------------
// Promise
// ------------------------------------------------------------------
type TFromPromise<Type extends t.TSchema, Result = z.ZodPromise<TFromType<Type>>> = Result
function FromPromise(type: t.TPromise): z.ZodTypeAny {
return z.promise(FromType(type.item))
}
// ------------------------------------------------------------------
// Record
// ------------------------------------------------------------------
type TFromRegExp<Result = z.ZodString> = Result
function FromRegExp(type: t.TRegExp): z.ZodTypeAny {
const constraints: TConstraint<z.ZodString>[] = [(input) => input.regex(new RegExp(type.source), type.flags)]
const { minLength, maxLength } = type
if (t.ValueGuard.IsNumber(maxLength)) constraints.push((input) => input.max(maxLength))
if (t.ValueGuard.IsNumber(minLength)) constraints.push((input) => input.min(minLength))
return constraints.reduce((type, constraint) => constraint(type), z.string())
}
// ------------------------------------------------------------------
// Record
// ------------------------------------------------------------------
type TFromRecord<Key extends t.TSchema, Value extends t.TSchema> = TFromType<Key> extends infer ZodKey extends z.KeySchema ? z.ZodRecord<ZodKey, TFromType<Value>> : z.ZodNever
// prettier-ignore
function FromRecord(type: t.TRecord): z.ZodTypeAny {
const pattern = globalThis.Object.getOwnPropertyNames(type.patternProperties)[0]
const value = FromType(type.patternProperties[pattern])
return (
pattern === t.PatternBooleanExact ? z.record(z.boolean(), value) :
pattern === t.PatternNumberExact ? z.record(z.number(), value) :
pattern === t.PatternStringExact ? z.record(z.string(), value) :
z.record(z.string().regex(new RegExp(pattern)), value)
)
}
// ------------------------------------------------------------------
// Optional
// ------------------------------------------------------------------
type TFromOptional<Type extends t.TSchema, Result = z.ZodOptional<TFromType<Type>>> = Result
function FromOptional(type: t.TOptional<t.TSchema>): z.ZodTypeAny {
return z.optional(FromType(t.Optional(type, false)))
}
// ------------------------------------------------------------------
// Readonly
// ------------------------------------------------------------------
type TFromReadonly<Type extends t.TSchema, Result = z.ZodReadonly<TFromType<Type>>> = Result
function FromReadonly(type: t.TReadonly<t.TSchema>): z.ZodTypeAny {
return FromType(t.Readonly(type, false))
}
// ------------------------------------------------------------------
// Never
// ------------------------------------------------------------------
type TFromNever<Result = z.ZodNever> = Result
function FromNever(type: t.TNever): z.ZodTypeAny {
return z.never()
}
// ------------------------------------------------------------------
// Never
// ------------------------------------------------------------------
type TFromNull<Result = z.ZodNull> = Result
function FromNull(_type: t.TNull): z.ZodTypeAny {
return z.null()
}
// ------------------------------------------------------------------
// Number
// ------------------------------------------------------------------
type TFromNumber<Result = z.ZodNumber> = Result
function FromNumber(type: t.TNumber): z.ZodTypeAny {
const { exclusiveMaximum, exclusiveMinimum, minimum, maximum, multipleOf } = type
const constraints: TConstraint<z.ZodNumber>[] = []
if (t.ValueGuard.IsNumber(exclusiveMinimum)) constraints.push((input) => input.min(exclusiveMinimum + 1))
if (t.ValueGuard.IsNumber(exclusiveMaximum)) constraints.push((input) => input.min(exclusiveMaximum - 1))
if (t.ValueGuard.IsNumber(maximum)) constraints.push((input) => input.max(maximum))
if (t.ValueGuard.IsNumber(minimum)) constraints.push((input) => input.min(minimum))
if (t.ValueGuard.IsNumber(multipleOf)) constraints.push((input) => input.multipleOf(multipleOf))
return constraints.reduce((input, constraint) => constraint(input), z.number())
}
// ------------------------------------------------------------------
// String
// ------------------------------------------------------------------
type TFromString<Result = z.ZodString> = Result
// prettier-ignore
function FromString(type: t.TString): z.ZodTypeAny {
const constraints: TConstraint<z.ZodString>[] = []
const { minLength, maxLength, pattern, format } = type
if (t.ValueGuard.IsNumber(maxLength)) constraints.push((input) => input.max(maxLength))
if (t.ValueGuard.IsNumber(minLength)) constraints.push((input) => input.min(minLength))
if (t.ValueGuard.IsString(pattern)) constraints.push((input) => input.regex(new RegExp(pattern)))
if (t.ValueGuard.IsString(format))
constraints.push((input) =>
format === 'base64' ? input.base64() :
format === 'base64url' ? input.base64url() :
format === 'cidrv4' ? input.cidr({ version: 'v4' }) :
format === 'cidrv6' ? input.cidr({ version: 'v6' }) :
format === 'cidr' ? input.cidr() :
format === 'cuid' ? input.cuid() :
format === 'cuid2' ? input.cuid2() :
format === 'date' ? input.date() :
format === 'datetime' ? input.datetime() :
format === 'duration' ? input.duration() :
format === 'email' ? input.email() :
format === 'emoji' ? input.emoji() :
format === 'ipv4' ? input.ip({ version: 'v4' }) :
format === 'ipv6' ? input.ip({ version: 'v6' }) :
format === 'ip' ? input.ip() :
format === 'jwt' ? input.jwt() :
format === 'nanoid' ? input.nanoid() :
format === 'time' ? input.time() :
format === 'ulid' ? input.ulid() :
format === 'url' ? input.url() :
format === 'uuid' ? input.uuid() :
input,
)
return constraints.reduce((type, constraint) => constraint(type), z.string())
}
// ------------------------------------------------------------------
// Symbol
// ------------------------------------------------------------------
type TFromSymbol<Result = z.ZodSymbol> = Result
function FromSymbol(_type: t.TSymbol): z.ZodTypeAny {
return z.symbol()
}
// ------------------------------------------------------------------
// Tuple
// ------------------------------------------------------------------
// prettier-ignore
type TFromTuple<Types extends t.TSchema[], Mapped extends z.ZodTypeAny[] = TFromTypes<Types>> = (
Mapped extends [z.ZodTypeAny, ...z.ZodTypeAny[]] | []
? z.ZodTuple<Mapped>
: z.ZodNever
)
function FromTuple(type: t.TTuple): z.ZodTypeAny {
const mapped = FromTypes(type.items || []) as [] | [z.ZodTypeAny, ...z.ZodTypeAny[]]
return z.tuple(mapped)
}
// ------------------------------------------------------------------
// Undefined
// ------------------------------------------------------------------
type TFromUndefined<Result = z.ZodUndefined> = Result
function FromUndefined(_type: t.TUndefined): z.ZodTypeAny {
return z.undefined()
}
// ------------------------------------------------------------------
// Union
// ------------------------------------------------------------------
// prettier-ignore
type TFromUnion<Types extends t.TSchema[], Mapped extends z.ZodTypeAny[] = TFromTypes<Types>> = (
Mapped extends z.ZodUnionOptions ? z.ZodUnion<Mapped> : z.ZodNever
)
function FromUnion(_type: t.TUnion): z.ZodTypeAny {
const mapped = FromTypes(_type.anyOf) as [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]
return mapped.length >= 1 ? z.union(mapped) : z.never()
}
// ------------------------------------------------------------------
// TUnknown
// ------------------------------------------------------------------
type TFromUnknown<Result = z.ZodUnknown> = Result
function FromUnknown(_type: t.TUnknown): z.ZodTypeAny {
return z.unknown()
}
// ------------------------------------------------------------------
// Void
// ------------------------------------------------------------------
type TFromVoid<Result = z.ZodVoid> = Result
function FromVoid(_type: t.TVoid): z.ZodTypeAny {
return z.void()
}
// ------------------------------------------------------------------
// Types
// ------------------------------------------------------------------
type TFromTypes<Types extends t.TSchema[], Result extends z.ZodTypeAny[] = []> = Types extends [infer Left extends t.TSchema, ...infer Right extends t.TSchema[]] ? TFromTypes<Right, [...Result, TFromType<Left>]> : Result
function FromTypes(types: t.TSchema[]): z.ZodTypeAny[] {
return types.map((type) => FromType(type))
}
// ------------------------------------------------------------------
// Type
// ------------------------------------------------------------------
// prettier-ignore
type TFromType<Type extends t.TSchema> = (
Type extends t.TReadonly<infer Type extends t.TSchema> ? TFromReadonly<Type> :
Type extends t.TOptional<infer Type extends t.TSchema> ? TFromOptional<Type> :
Type extends t.TAny ? TFromAny :
Type extends t.TArray<infer Type extends t.TSchema> ? TFromArray<Type> :
Type extends t.TBigInt ? TFromBigInt :
Type extends t.TBoolean ? TFromBoolean :
Type extends t.TDate ? TFromDate :
Type extends t.TFunction<infer Parameters extends t.TSchema[], infer ReturnType extends t.TSchema> ? TFromFunction<Parameters, ReturnType> :
Type extends t.TInteger ? TFromInteger :
Type extends t.TIntersect<infer Types extends t.TSchema[]> ? TFromIntersect<Types> :
Type extends t.TLiteral<infer Value extends t.TLiteralValue> ? TFromLiteral<Value> :
Type extends t.TNever ? TFromNever :
Type extends t.TNull ? TFromNull :
Type extends t.TNumber ? TFromNumber :
Type extends t.TObject<infer Properties extends t.TProperties> ? TFromObject<Properties> :
Type extends t.TPromise<infer Type extends t.TSchema> ? TFromPromise<Type> :
Type extends t.TRecord<infer Key extends t.TSchema, infer Value extends t.TSchema> ? TFromRecord<Key, Value> :
Type extends t.TRegExp ? TFromRegExp :
Type extends t.TString ? TFromString :
Type extends t.TSymbol ? TFromSymbol :
Type extends t.TTuple<infer Types extends t.TSchema[]> ? TFromTuple<Types> :
Type extends t.TUndefined ? TFromUndefined :
Type extends t.TUnion<infer Types extends t.TSchema[]> ? TFromUnion<Types> :
Type extends t.TUnknown ? TFromUnknown :
Type extends t.TVoid ? TFromVoid :
z.ZodNever
)
// prettier-ignore
function FromType(type: t.TSchema): z.ZodTypeAny {
const constraints: TConstraint<z.ZodTypeAny>[] = []
if(!t.ValueGuard.IsUndefined(type.description)) constraints.push(input => input.describe(type.description!))
if(!t.ValueGuard.IsUndefined(type.default)) constraints.push(input => input.default(type.default))
return constraints.reduce((type, constraint) => constraint(type), (
t.KindGuard.IsReadonly(type) ? FromReadonly(type) :
t.KindGuard.IsOptional(type) ? FromOptional(type) :
t.KindGuard.IsAny(type) ? FromAny(type) :
t.KindGuard.IsArray(type) ? FromArray(type) :
t.KindGuard.IsBigInt(type) ? FromBigInt(type) :
t.KindGuard.IsBoolean(type) ? FromBoolean(type) :
t.KindGuard.IsDate(type) ? FromDate(type) :
t.KindGuard.IsFunction(type) ? FromFunction(type) :
t.KindGuard.IsInteger(type) ? FromInteger(type) :
t.KindGuard.IsIntersect(type) ? FromIntersect(type) :
t.KindGuard.IsLiteral(type) ? FromLiteral(type) :
t.KindGuard.IsNever(type) ? FromNever(type) :
t.KindGuard.IsNull(type) ? FromNull(type) :
t.KindGuard.IsNumber(type) ? FromNumber(type) :
t.KindGuard.IsObject(type) ? FromObject(type) :
t.KindGuard.IsPromise(type) ? FromPromise(type) :
t.KindGuard.IsRegExp(type) ? FromRegExp(type) :
t.KindGuard.IsRecord(type) ? FromRecord(type) :
t.KindGuard.IsString(type) ? FromString(type) :
t.KindGuard.IsSymbol(type) ? FromSymbol(type) :
t.KindGuard.IsTuple(type) ? FromTuple(type) :
t.KindGuard.IsUndefined(type) ? FromUndefined(type) :
t.KindGuard.IsUnion(type) ? FromUnion(type) :
t.KindGuard.IsUnknown(type) ? FromUnknown(type) :
t.KindGuard.IsVoid(type) ? FromVoid(type) :
z.never()
))
}
// ------------------------------------------------------------------
// ZodFromTypeBox
// ------------------------------------------------------------------
// prettier-ignore
export type TZodFromTypeBox<Type extends object | string> = (
Type extends t.TSchema ? TFromType<Type> : z.ZodNever
)
export function ZodFromTypeBox<Type extends object | string>(type: Type): TZodFromTypeBox<Type> {
return (t.KindGuard.IsSchema(type) ? FromType(type) : z.never()) as never
}

View File

@@ -0,0 +1,45 @@
/*--------------------------------------------------------------------------
@sinclair/typemap
The MIT License (MIT)
Copyright (c) 2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
---------------------------------------------------------------------------*/
import { type TTypeBoxFromValibot, TypeBoxFromValibot } from '../typebox/typebox-from-valibot'
import { type TZodFromTypeBox, ZodFromTypeBox } from './zod-from-typebox'
import * as t from '@sinclair/typebox'
import * as z from 'zod'
// prettier-ignore
export type TZodFromValibot<Type extends object | string,
Schema extends t.TSchema = TTypeBoxFromValibot<Type>,
Result extends z.ZodTypeAny | z.ZodEffects<any> = TZodFromTypeBox<Schema>
> = Result
// prettier-ignore
export function ZodFromValibot<Type extends object | string>(type: Type): TZodFromValibot<Type> {
const schema = TypeBoxFromValibot(type)
const result = ZodFromTypeBox(schema)
return result
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typebox-adapter
@sinclair/typemap
The MIT License (MIT)
@@ -26,11 +26,21 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TSchema, KindGuard } from '@sinclair/typebox'
import * as Guard from '../guard'
import * as z from 'zod'
/** Converts a TypeBox Type to a TypeBox Type */
export type TBox<Type extends unknown> = Type extends TSchema ? Type : undefined
/** Converts a TypeBox Type to a TypeBox Type */
export function Box<Type extends unknown, Result extends TBox<Type> = TBox<Type>>(type: Type): Result {
return (KindGuard.IsSchema(type) ? type : undefined) as never
type BaseType = z.ZodTypeAny | z.ZodEffects<any>
// prettier-ignore
export type TZodFromZod<Type extends object | string,
Result extends BaseType = (
Type extends BaseType
? Type
: z.ZodNever
)
> = Result
// prettier-ignore
export function ZodFromZod<Type extends object | string>(type: Type): TZodFromZod<Type> {
return (Guard.IsZod(type) ? type : z.never()) as never
}

View File

@@ -1,6 +1,6 @@
/*--------------------------------------------------------------------------
@sinclair/typebox-adapter
@sinclair/typemap
The MIT License (MIT)
@@ -26,33 +26,31 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/
import { TSchema, KindGuard, Unknown, type TUnknown } from '@sinclair/typebox'
import * as TypeBox from './typebox/index'
import * as Valibot from './valibot/index'
import * as Zod from './zod/index'
import { type TZodFromSyntax, ZodFromSyntax } from './zod-from-syntax'
import { type TZodFromTypeBox, ZodFromTypeBox } from './zod-from-typebox'
import { type TZodFromValibot, ZodFromValibot } from './zod-from-valibot'
import { type TZodFromZod, ZodFromZod } from './zod-from-zod'
import * as Guard from '../guard'
import * as z from 'zod'
/** Converts a Zod, Valibot or TypeBox Type to a TypeBox Type */
/** Creates a Zod type from Syntax or another Type */
// prettier-ignore
export type TBox<Type extends unknown> = (
TypeBox.TBox<Type> extends infer Schema extends TSchema ? Schema :
Valibot.TBox<Type> extends infer Schema extends TSchema ? Schema :
Zod.TBox<Type> extends infer Schema extends TSchema ? Schema :
TUnknown
export type TZod<Type extends object | string> = (
Guard.TIsSyntax<Type> extends true ? TZodFromSyntax<Type> :
Guard.TIsTypeBox<Type> extends true ? TZodFromTypeBox<Type> :
Guard.TIsValibot<Type> extends true ? TZodFromValibot<Type> :
Guard.TIsZod<Type> extends true ? TZodFromZod<Type> :
z.ZodNever
)
/** Converts a Zod, Valibot or TypeBox Type to a TypeBox Type */
/** Creates a Zod type from Syntax or another Type */
// prettier-ignore
export function Box<Type extends unknown>(type: Type): TBox<Type> {
{
const result = TypeBox.Box(type)
if(KindGuard.IsSchema(result)) return result as never
}
{
const result = Valibot.Box(type)
if(KindGuard.IsSchema(result)) return result as never
}
{
const result = Zod.Box(type)
if(KindGuard.IsSchema(result)) return result as never
}
return Unknown() as never
export function Zod<Type extends object | string, Result = TZod<Type>>(type: Type): Result {
return (
Guard.IsSyntax(type) ? ZodFromSyntax(type) :
Guard.IsTypeBox(type) ? ZodFromTypeBox(type) :
Guard.IsValibot(type) ? ZodFromValibot(type) :
Guard.IsZod(type) ? ZodFromZod(type) :
z.never()
) as never
}