mirror of
https://github.com/zoriya/typebox.git
synced 2025-12-05 22:36:12 +00:00
Revision 0.32.0 (#689)
This commit is contained in:
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
node: [16.x, 18.x, 20.x]
|
||||
os: [ubuntu-latest, windows-latest, macOS-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
|
||||
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
node: [20.x]
|
||||
os: [ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import { shell } from '@sinclair/hammer'
|
||||
|
||||
export async function measurement() {
|
||||
await shell(`hammer run benchmark/measurement/module/index.ts --dist target/benchmark/measurement`)
|
||||
}
|
||||
@@ -13,7 +13,7 @@ const T: any = {} // T is any
|
||||
|
||||
const { type } = T // unsafe: type is any
|
||||
|
||||
if(TypeGuard.TString(T)) {
|
||||
if(TypeGuard.IsString(T)) {
|
||||
|
||||
const { type } = T // safe: type is 'string'
|
||||
}
|
||||
|
||||
473
changelog/0.32.0.md
Normal file
473
changelog/0.32.0.md
Normal file
@@ -0,0 +1,473 @@
|
||||
## [0.32.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.32.0)
|
||||
|
||||
## Overview
|
||||
|
||||
Revision 0.32.0 adds support for ESM and carries out the work necessary to fully modularize the TypeBox type system to enable selective type imports. This revision also adds three new types (Mapped, Const, and Deref), along with two new Value functions (Clean and Default) as well as many enhancements to existing types (Index, KeyOf, RegExp, Optional and Readonly). This revision also carries out many internal optimizations to enhance type inference across all types.
|
||||
|
||||
This revision is a milestone revision for the TypeBox project. It has several breaking changes and requires a minor revision.
|
||||
|
||||
## Contents
|
||||
|
||||
- [Type Imports](#Type-Imports)
|
||||
- [Value Function Import](#Value-Function-Imports)
|
||||
- [CommonJS and ESM](#CommonJS-and-ESM)
|
||||
- [Types](#Types)
|
||||
- [Mapped Type](#Types-Mapped-Type)
|
||||
- [Const Type](#Types-Const-Type)
|
||||
- [Deref Type](#Types-Deref-Type)
|
||||
- [RegExp Type](#Types-RegExp-Type)
|
||||
- [Subtract Modifiers](#Types-Subtract-Modifiers)
|
||||
- [Values](#Values)
|
||||
- [Clean Function](#Values-Clean-Function)
|
||||
- [Default Function](#Values-Default-Function)
|
||||
- [Errors](#Errors)
|
||||
- [Error Parameter](#Errors-Error-Parameter)
|
||||
- [Optimizations](#Optimizations)
|
||||
- [Bundle Size](#Optimizations-Bundle-Size)
|
||||
- [Breaking](#Breaking)
|
||||
- [Renamed Symbols](#Breaking-Renamed-Symbols)
|
||||
- [TypeGuard Interface Change](#Breaking-TypeGuard-Interface-Change)
|
||||
- [Value Submodule Imports](#Breaking-Value-Submodule-Imports)
|
||||
- [Error Function](#Breaking-Error-Function)
|
||||
- [RegEx](#Breaking-RegEx)
|
||||
|
||||
<a name="Type-Imports"></a>
|
||||
|
||||
### Type Imports
|
||||
|
||||
Revision 0.32.0 adds the ability to import types individually.
|
||||
|
||||
```typescript
|
||||
import { Type, type Static } from '@sinclair/typebox' // classic - 37.0 kb minified
|
||||
|
||||
import { Object, String, Number, type Static } from '@sinclair/typebox' // selective - 6.5 kb minified
|
||||
```
|
||||
|
||||
<a name="Value-Function-Imports"></a>
|
||||
|
||||
### Value Function Imports
|
||||
|
||||
Revision 0.32.0 adds the ability to import value functions from the `/value` module path.
|
||||
|
||||
```typescript
|
||||
import { Value } from '@sinclair/typebox/value' // classic - 61.5 kb minified
|
||||
|
||||
import { Check } from '@sinclair/typebox/value' // selective - 18.2 kb minified
|
||||
```
|
||||
|
||||
### CommonJS and ESM
|
||||
|
||||
<a name="CommonJS-and-ESM"></a>
|
||||
|
||||
Revision 0.32.0 now publishes both CommonJS and ESM builds of TypeBox. Existing CommonJS users should not be impacted by the addition of ESM. For ESM users however, particularily those using bundlers, it's now possible to benefit from deep tree shake optimizations provided by modern bundler tooling.
|
||||
|
||||
<a name="Types"></a>
|
||||
|
||||
## Types
|
||||
|
||||
Revision 0.32.0 adds three new types to the type system and makes enhancements to Readonly and Optional modifiers.
|
||||
|
||||
<a name="Types-Mapped-Type"></a>
|
||||
|
||||
### Mapped Type
|
||||
|
||||
Revision 0.32.0 adds the Mapped type which replicates TS [Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html) at runtime. The following shows the syntax comparison between TypeScript and TypeBox.
|
||||
|
||||
#### TypeScript
|
||||
|
||||
```typescript
|
||||
type T = {
|
||||
x: number,
|
||||
y: number,
|
||||
z: number
|
||||
}
|
||||
|
||||
type M = { [K in keyof T]: T[K] } // a mapped type
|
||||
```
|
||||
#### TypeBox
|
||||
```typescript
|
||||
const T = Type.Object({
|
||||
x: Type.Number(),
|
||||
y: Type.Number(),
|
||||
z: Type.Number()
|
||||
})
|
||||
|
||||
const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K)) // a mapped type
|
||||
```
|
||||
Mapped types use a functional design to replicate the TypeScript feature. For users interested in this type, it may be helpful to use the [TypeBox Workbench](https://sinclairzx81.github.io/typebox-workbench/) which can generate runtime Mapped types from TypeScript syntax.
|
||||
|
||||
<a name="Types-Const-Type"></a>
|
||||
|
||||
### Const Type
|
||||
|
||||
Revision 0.32.0 adds a new Const type that creates `readonly` types from object, array and primitive literal values. This type analogs the TypeScript `as const` syntax. The following shows general usage.
|
||||
|
||||
```typescript
|
||||
const A = Type.Const(1 as const) // const A: TLiteral<1>
|
||||
|
||||
const B = Type.Const([1, 2, 3] as const) // const B: TReadonly<TTuple<[
|
||||
// TLiteral<1>,
|
||||
// TLiteral<2>,
|
||||
// TLiteral<3>
|
||||
// ]>>
|
||||
|
||||
const C = Type.Const({ // const C: TObject<{
|
||||
x: 1, // x: TReadonly<TLiteral<1>>,
|
||||
y: 2, // y: TReadonly<TLiteral<2>>,
|
||||
z: 3 // z: TReadonly<TLiteral<3>>,
|
||||
} as const) // }>
|
||||
```
|
||||
Revision 0.32.0 continues support for TypeScript 4.0, and because of this, the `as const` syntax must be appended to each literal value passed to the Const type. When TypeBox ends support for 4.0, updates will be made to this type to make use of [Const Type Parameters](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#const-type-parameters). This update will enable TypeBox to correctly infer the readonly literal type without the need for `as const`.
|
||||
|
||||
|
||||
<a name="Types-Deref-Type"></a>
|
||||
|
||||
### Deref Type
|
||||
|
||||
Revision 0.32.0 adds a new Type.Deref type which can be used to dereference type schematics.
|
||||
|
||||
```typescript
|
||||
const Vector = Type.Object({ // const Vector = {
|
||||
x: Type.Number(), // type: 'object',
|
||||
y: Type.Number(), // required: ['x', 'y', 'z'],
|
||||
}, { $id: 'Vector' }) // properties: {
|
||||
// x: { type: 'number' },
|
||||
// y: { type: 'number' }
|
||||
// },
|
||||
// $id: 'Vector'
|
||||
// }
|
||||
|
||||
const VectorRef = Type.Ref(Vector) // const VectorRef = {
|
||||
// $ref: 'Vector'
|
||||
// }
|
||||
// ... Embedded Reference Type
|
||||
|
||||
const Vertex = Type.Object({ // const Vertex = {
|
||||
position: VectorRef, // type: 'object',
|
||||
texcoord: VectorRef, // required: ['position', 'texcoord'],
|
||||
}) // properties: {
|
||||
// position: { $ref: 'Vector' },
|
||||
// texcoord: { $ref: 'Vector' }
|
||||
// }
|
||||
// }
|
||||
|
||||
// ... Dereferenced Embedded Reference Type
|
||||
|
||||
const VertexDeref = Type.Deref(Vertex, [Vector]) // const VertexDeref = {
|
||||
// type: 'object',
|
||||
// required: ['position', 'texcoord'],
|
||||
// properties: {
|
||||
// position: {
|
||||
// type: 'object',
|
||||
// required: ['x', 'y', 'z'],
|
||||
// properties: {
|
||||
// x: { type: 'number' },
|
||||
// y: { type: 'number' }
|
||||
// }
|
||||
// },
|
||||
// texcoord: {
|
||||
// type: 'object',
|
||||
// required: ['x', 'y', 'z'],
|
||||
// properties: {
|
||||
// x: { type: 'number' },
|
||||
// y: { type: 'number' }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
```
|
||||
The addition of Deref was prompted by issues composing reference types with mapping types (such as Partial, Required, Pick and Omit) which is generally not supported. Prior to Revision 0.32.0, there was some expectation for users to maintain and dereference types manually. In 0.32.0, users will still need to maintain references, but Deref will offer a more convenient mechanism to normalize reference types prior to composition.
|
||||
|
||||
|
||||
<a name="Types-RegExp-Type"></a>
|
||||
|
||||
### RegExp Type
|
||||
|
||||
Revision 0.32.0 updates RegExp to support the full ECMA 262 regular expression syntax. In previous revisions, this type had been expressed as an alias for `TString` with a `pattern` to try ensure compliance with the [regular expression](https://json-schema.org/understanding-json-schema/reference/regular_expressions) subset supported by Json Schema. In Revision 0.32.0, RegExp is given a new type representation unto itself (named `TRegExp`) which houses both `source` and `flags` properties used to reconstruct a JavaScript regular expression object, making it properly distinct from `TString` and fully supportive of UTF-16.
|
||||
|
||||
```typescript
|
||||
// Case Insensitive
|
||||
|
||||
const T = Type.RegExp(/abc/i) // const T = {
|
||||
// type: 'RegExp',
|
||||
// source: 'abc',
|
||||
// flags: 'i'
|
||||
// }
|
||||
|
||||
type T = Static<typeof T> // type T = string
|
||||
|
||||
Value.Check(T, 'abc') // ok
|
||||
Value.Check(T, 'ABC') // ok
|
||||
|
||||
// Extended Syntax
|
||||
|
||||
const E = Type.RegExp(/<a?:.+?:\d{18}>|\p{Extended_Pictographic}/gu)
|
||||
|
||||
Value.Check(E, '♥️♦️♠️♣️') // ok - emoji supported
|
||||
```
|
||||
|
||||
The RegExp type can be thought of as a more capable TemplateLiteral that can only reasonably infer as `string`. Additionally, the RegExp inference type of `string` is unique to the other `[JavaScript]` types in that it does not infer as it's named type. The updates to RegExp were prompted by the limitations with Json Schema expressions, and to provide better options for users requiring general Unicode validation support. For Json Schema compliance, the recommendation moving forward will be to use either String with pattern or TemplateLiteral.
|
||||
|
||||
```typescript
|
||||
const T = Type.String({ pattern: '^(a|b|c)$' }) // Json Schema compliant
|
||||
|
||||
const T = Type.TemplateLiteral('${a|b|c}') // Json Schema compliant
|
||||
|
||||
const T = Type.RegExp(/$(a|b|c)$/) // Non Json Schema compliant
|
||||
```
|
||||
|
||||
<a name="Types-Subtractive-Modifiers"></a>
|
||||
|
||||
### Subtract Modifier
|
||||
|
||||
Revision 0.32.0 adds new overloads for Readonly and Optional modifiers that enable them to subtract (or remove) that modifier from a type. Both Readonly and Optional now accept an optional secondary boolean argument that if `false`, will remove the modifier.
|
||||
|
||||
#### TypeScript
|
||||
```typescript
|
||||
type T = {
|
||||
x?: number,
|
||||
y?: number
|
||||
}
|
||||
type M = { [K in keyof T]-?: T[K] } // -? - subtract optional modifier
|
||||
```
|
||||
#### TypeBox
|
||||
```typescript
|
||||
const T = Type.Object({
|
||||
x: Type.Optional(Type.Number()),
|
||||
y: Type.Optional(Type.Number())
|
||||
})
|
||||
const M = Type.Mapped(Type.KeyOf(T), K => {
|
||||
return Type.Optional(Type.Index(T, K), false) // false - subtract optional modifier
|
||||
})
|
||||
```
|
||||
Subtractive modifiers are provided in support of the new Mapped type feature.
|
||||
|
||||
<a name="Values"></a>
|
||||
|
||||
## Values
|
||||
|
||||
Revision 0.32.0 adds two new functions to the Value module.
|
||||
|
||||
<a name="Values-Clean-Function"></a>
|
||||
|
||||
### Clean Function
|
||||
|
||||
Revision 0.32.0 adds a new Clean function that can be used to omit any values unknown to the type. This function will work irrespective of if `additionalProperties` is specified on the type. The Clean function is intended to replicate the functionality of Ajv's `removeAdditional` configuration.
|
||||
|
||||
```typescript
|
||||
const T = Type.Object({
|
||||
x: Type.Number(),
|
||||
y: Type.Number()
|
||||
})
|
||||
|
||||
const X = Value.Clean(T, null) // const 'X = null
|
||||
|
||||
const Y = Value.Clean(T, { x: 1 }) // const 'Y = { x: 1 }
|
||||
|
||||
const Z = Value.Clean(T, { x: 1, y: 2, z: 3 }) // const 'Z = { x: 1, y: 2 }
|
||||
```
|
||||
|
||||
Note: the Clean function does not check the validity of the value being cleaned, and does not provide assurances that the result will be valid. Its return value is `unknown` and should be checked before use.
|
||||
|
||||
<a name="Values-Default-Function"></a>
|
||||
|
||||
### Default Function
|
||||
|
||||
Revision 0.32.0 adds a new Default function that can be used to add missing values if the type specifies a `default` annotation. This function is intended to replicate Ajv's `useDefaults` functionality.
|
||||
|
||||
```typescript
|
||||
const T = Type.Object({
|
||||
x: Type.Number({ default: 0 }),
|
||||
y: Type.Number({ default: 0 })
|
||||
})
|
||||
|
||||
const X = Value.Default(T, null) // const 'X = null - non-enumerable
|
||||
|
||||
const Y = Value.Default(T, { }) // const 'Y = { x: 0, y: 0 }
|
||||
|
||||
const Z = Value.Default(T, { x: 1 }) // const 'Z = { x: 1, y: 0 }
|
||||
```
|
||||
|
||||
The Default function does not check the validity of the value being defaulted, and does not provide assurances that the result will be valid. Its return value is `unknown` and should be checked before use.
|
||||
|
||||
<a name="Optimizations"></a>
|
||||
|
||||
## Optimizations
|
||||
|
||||
Following the work to modularize TypeBox's type system, additional optimizations were carried out across each submodule to only import dependent type infrastructure. This has led to some fairly significant reductions in output sizes across each submodule. The main TypeBox import has increased in size due in part to the new Mapped types feature and other associative types, however selective imports supported on this revision should offer options for users concerned about output bundle size. There will be contined work to optimize the new type system throughout 0.32.0 and subsequent revisions.
|
||||
|
||||
The following shows the comparisons between 0.31.0 and 0.32.0.
|
||||
|
||||
<a name="Optimizations-Bundle-Size"></a>
|
||||
|
||||
```typescript
|
||||
// Revision 0.31.0
|
||||
|
||||
┌──────────────────────┬────────────┬────────────┬─────────────┐
|
||||
│ (index) │ Compiled │ Minified │ Compression │
|
||||
├──────────────────────┼────────────┼────────────┼─────────────┤
|
||||
│ typebox/compiler │ '163.6 kb' │ ' 71.6 kb' │ '2.28 x' │
|
||||
│ typebox/errors │ '113.3 kb' │ ' 50.1 kb' │ '2.26 x' │
|
||||
│ typebox/system │ ' 83.9 kb' │ ' 37.5 kb' │ '2.24 x' │
|
||||
│ typebox/value │ '191.1 kb' │ ' 82.3 kb' │ '2.32 x' │
|
||||
│ typebox │ ' 73.8 kb' │ ' 32.3 kb' │ '2.29 x' │
|
||||
└──────────────────────┴────────────┴────────────┴─────────────┘
|
||||
|
||||
// Revision 0.32.0
|
||||
|
||||
┌──────────────────────┬────────────┬────────────┬─────────────┐
|
||||
│ (index) │ Compiled │ Minified │ Compression │
|
||||
├──────────────────────┼────────────┼────────────┼─────────────┤
|
||||
│ typebox/compiler │ '120.6 kb' │ ' 52.9 kb' │ '2.28 x' │
|
||||
│ typebox/errors │ ' 55.7 kb' │ ' 25.5 kb' │ '2.19 x' │
|
||||
│ typebox/system │ ' 4.7 kb' │ ' 2.0 kb' │ '2.33 x' │
|
||||
│ typebox/value │ '146.2 kb' │ ' 62.0 kb' │ '2.36 x' │
|
||||
│ typebox │ ' 91.4 kb' │ ' 37.8 kb' │ '2.42 x' │
|
||||
└──────────────────────┴────────────┴────────────┴─────────────┘
|
||||
```
|
||||
<a name="Errors"></a>
|
||||
|
||||
## Errors
|
||||
|
||||
Revision 0.32.0 makes some enhancements to errors.
|
||||
|
||||
<a name="Errors-Error-Parameter"></a>
|
||||
|
||||
### Error Parameter
|
||||
|
||||
Revision 0.32.0 updates TypeBox's ErrorFunction to accept an ErrorParameter that contains additional information regarding the cause of a validation error. In Revision 0.31.0, only `errorType` and `schema` were passed through to this function. In 0.32.0 the additional properties `value` and `path` are also passed through. This update was prompted by some users needing to be able to generate specific error messages derived from specific values or other associated information.
|
||||
|
||||
The following shows the changes from 0.31.0 to 0.32.0.
|
||||
|
||||
```typescript
|
||||
// Revision 0.31.0
|
||||
|
||||
import { TypeSystemErrorFunction } from '@sinclair/typebox/system'
|
||||
|
||||
TypeSystemErrorFunction.Set((schema, errorType) => {
|
||||
|
||||
return 'oh no, an error!'
|
||||
})
|
||||
|
||||
// Revision 0.32.0
|
||||
|
||||
import { SetErrorFunction } from '@sinclair/typebox/errors'
|
||||
|
||||
SetErrorFunction(({ schema, errorType, path, value }) => { // as destructured object
|
||||
|
||||
return 'oh no, an error!'
|
||||
})
|
||||
```
|
||||
Note that Revision 0.32.0 does make a breaking interface change by moving the ErrorFunction from `/system` to `/errors`. See breaking changes for more information.
|
||||
|
||||
<a name="Breaking"></a>
|
||||
|
||||
## Breaking
|
||||
|
||||
The following list the breaking changes in Revision 0.32.0.
|
||||
|
||||
|
||||
<a name="Breaking-Renamed-Symbols"></a>
|
||||
|
||||
### Renamed Symbols
|
||||
|
||||
Revision 0.32.0 renames the `Optional`, `Required` and `Transform` symbols to `OptionalKind`, `RequiredKind` and `TransformKind`. This change was necessary to avoid conflicts with exported type functions.
|
||||
|
||||
```typescript
|
||||
// Revision 0.31.0
|
||||
import { Kind, Hint, Optional, Required, Transform } from '@sinclair/typebox' // these are symbols
|
||||
|
||||
// Revision 0.32.0
|
||||
import {
|
||||
Kind, Hint, OptionalKind, RequiredKind, TransformKind, // these are symbols
|
||||
Optional, Required, Transform // these are type imports
|
||||
} from '@sinclair/typebox'
|
||||
```
|
||||
|
||||
<a name="Breaking-TypeGuard-Interface-Change"></a>
|
||||
|
||||
### TypeGuard Interface Change
|
||||
|
||||
Revision 0.32.0 has a breaking interface change on the TypeGuard utility where the `T` prefixed guard functions have been updated to use the `Is` prefix. This naming change is perhaps somewhat more sensible than the previous naming, however the update was largely prompted by TypeScript compiler issues where interface types (i.e. `TString`) where conflicting with the `TString` functions leading to breakage in CommonJS.
|
||||
|
||||
```typescript
|
||||
// Revision 0.31.0
|
||||
|
||||
import { TypeGuard, Kind } from '@sinclair/typebox'
|
||||
|
||||
const R = TypeGuard.TString({ ... })
|
||||
|
||||
// Revision 0.32.0
|
||||
|
||||
import { TypeGuard } from '@sinclair/typebox'
|
||||
|
||||
const R = TypeGuard.IsString({ ... })
|
||||
```
|
||||
|
||||
<a name="Breaking-Value-Submodule-Imports"></a>
|
||||
|
||||
### Value Submodule Imports
|
||||
|
||||
The value submodule function import paths are unfortunately no longer supported. Instead, these can be imported directly on the `/value` path. The need to break the submodule paths was mostly due to complexities configuring dual ESM and CommonJS publishing for the package, as well as retaining support for pre and post node16 module resolution (of which many complexities reside, both for Node as well as for TypeScript type module resolution)
|
||||
|
||||
```typescript
|
||||
// Revision 0.31.0
|
||||
|
||||
import { Check } from '@sinclair/typebox/value/check'
|
||||
|
||||
// Revision 0.32.0
|
||||
|
||||
import { Check } from '@sinclair/typebox/value'
|
||||
```
|
||||
|
||||
<a name="Breaking-Error-Function"></a>
|
||||
|
||||
### Error Function
|
||||
|
||||
The TypeSystemErrorFunction has been replaced with SetErrorFunction which can be imported on the `/errors` submodule. This change is generally a tidy up, and to reserve the `/system` submodule for type system policy configuration, as well as future Json Schema generation options (draft 2020-12)
|
||||
|
||||
```typescript
|
||||
// Revision 0.31.0
|
||||
|
||||
import { TypeSystemErrorFunction, ValueErrorType, DefaultErrorFunction } from '@sinclair/typebox/system'
|
||||
|
||||
TypeSystemErrorFunction.Set((schema, errorType) => { // i18n override
|
||||
switch(errorType) {
|
||||
/* en-US */ case ValueErrorType.String: return 'Expected string'
|
||||
/* fr-FR */ case ValueErrorType.Number: return 'Nombre attendu'
|
||||
/* ko-KR */ case ValueErrorType.Boolean: return '예상 부울'
|
||||
/* en-US */ default: return DefaultErrorFunction(schema, errorType)
|
||||
}
|
||||
})
|
||||
|
||||
// Revision 0.32.0
|
||||
|
||||
import { SetErrorFunction, ValueErrorType, DefaultErrorFunction } from '@sinclair/typebox/errors'
|
||||
|
||||
SetErrorFunction((error) => { // i18n override
|
||||
switch(error.errorType) {
|
||||
/* en-US */ case ValueErrorType.String: return 'Expected string'
|
||||
/* fr-FR */ case ValueErrorType.Number: return 'Nombre attendu'
|
||||
/* ko-KR */ case ValueErrorType.Boolean: return '예상 부울'
|
||||
/* en-US */ default: return DefaultErrorFunction(error)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
<a name="Breaking-RegEx"></a>
|
||||
|
||||
### RegEx
|
||||
|
||||
This RegEx function was flagged for deprecation on 0.30.0. It has been removed on Revision 0.32.0. Use the Type.RegExp type, or Type.String with a pattern to remain compatible with the Json Schema specification.
|
||||
|
||||
```typescript
|
||||
// Revision 0.31.0
|
||||
|
||||
const T = Type.RegEx(/abc/) // deprecation warning
|
||||
|
||||
// Revision 0.32.0
|
||||
|
||||
const A = Type.RegExp(/abc/) // JavaScript Type
|
||||
|
||||
const B = Type.String({ pattern: /abc/.source }) // Json Type
|
||||
```
|
||||
148
example/annotation/annotation.ts
Normal file
148
example/annotation/annotation.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 Types from '@sinclair/typebox'
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Annotation
|
||||
//
|
||||
// Generates TypeScript Type Annotations from TypeBox types
|
||||
// -------------------------------------------------------------------
|
||||
/** Generates TypeScript Type Annotations from TypeBox types */
|
||||
export namespace Annotation {
|
||||
// -----------------------------------------------------------------
|
||||
// Escape
|
||||
// -----------------------------------------------------------------
|
||||
function Escape(content: string) {
|
||||
return content.replace(/'/g, "\\'")
|
||||
}
|
||||
// -----------------------------------------------------------------
|
||||
// Types
|
||||
// -----------------------------------------------------------------
|
||||
function Intersect(schema: Types.TSchema[], references: Types.TSchema[]): string {
|
||||
const [L, ...R] = schema
|
||||
// prettier-ignore
|
||||
return R.length === 0
|
||||
? `${Visit(L, references)}`
|
||||
: `${Visit(L, references)} & ${Intersect(R, references)}`
|
||||
}
|
||||
function Union(schema: Types.TSchema[], references: Types.TSchema[]): string {
|
||||
const [L, ...R] = schema
|
||||
// prettier-ignore
|
||||
return R.length === 0
|
||||
? `${Visit(L, references)}`
|
||||
: `${Visit(L, references)} | ${Union(R, references)}`
|
||||
}
|
||||
function Tuple(schema: Types.TSchema[], references: Types.TSchema[]): string {
|
||||
const [L, ...R] = schema
|
||||
// prettier-ignore
|
||||
return R.length > 0
|
||||
? `${Visit(L, references)}, ${Tuple(R, references)}`
|
||||
: ``
|
||||
}
|
||||
function Property(schema: Types.TProperties, K: string, references: Types.TSchema[]): string {
|
||||
const TK = schema[K]
|
||||
// prettier-ignore
|
||||
return (
|
||||
Types.TypeGuard.IsOptional(TK) && Types.TypeGuard.IsReadonly(TK) ? `readonly ${K}?: ${Visit(TK, references)}` :
|
||||
Types.TypeGuard.IsReadonly(TK) ? `readonly ${K}: ${Visit(TK, references)}` :
|
||||
Types.TypeGuard.IsOptional(TK) ? `${K}?: ${Visit(TK, references)}` :
|
||||
`${K}: ${Visit(TK, references)}`
|
||||
)
|
||||
}
|
||||
function Properties(schema: Types.TProperties, K: string[], references: Types.TSchema[]): string {
|
||||
const [L, ...R] = K
|
||||
// prettier-ignore
|
||||
return R.length === 0
|
||||
? `${Property(schema, L, references)}`
|
||||
: `${Property(schema, L, references)}; ${Properties(schema, R, references)}`
|
||||
}
|
||||
function Parameters(schema: Types.TSchema[], I: number, references: Types.TSchema[]): string {
|
||||
const [L, ...R] = schema
|
||||
// prettier-ignore
|
||||
return R.length === 0
|
||||
? `param_${I}: ${Visit(L, references)}`
|
||||
: `param_${I}: ${Visit(L, references)}, ${Parameters(R, I + 1, references)}`
|
||||
}
|
||||
function Literal(schema: Types.TLiteral, references: Types.TSchema[]): string {
|
||||
return typeof schema.const === 'string' ? `'${Escape(schema.const)}'` : schema.const.toString()
|
||||
}
|
||||
function Record(schema: Types.TRecord, references: Types.TSchema[]): string {
|
||||
// prettier-ignore
|
||||
return (
|
||||
Types.PatternBooleanExact in schema.patternProperties ? `Record<boolean, ${Visit(schema.patternProperties[Types.PatternBooleanExact], references)}>` :
|
||||
Types.PatternNumberExact in schema.patternProperties ? `Record<number, ${Visit(schema.patternProperties[Types.PatternNumberExact], references)}>` :
|
||||
Types.PatternStringExact in schema.patternProperties ? `Record<string, ${Visit(schema.patternProperties[Types.PatternStringExact], references)}>` :
|
||||
`{}`
|
||||
)
|
||||
}
|
||||
function TemplateLiteral(schema: Types.TTemplateLiteral, references: Types.TSchema[]) {
|
||||
const E = Types.TemplateLiteralParseExact(schema.pattern)
|
||||
if (!Types.IsTemplateLiteralExpressionFinite(E)) return 'string'
|
||||
return [...Types.TemplateLiteralExpressionGenerate(E)].map((literal) => `'${Escape(literal)}'`).join(' | ')
|
||||
}
|
||||
function Visit(schema: Types.TSchema, references: Types.TSchema[]): string {
|
||||
// prettier-ignore
|
||||
return (
|
||||
Types.TypeGuard.IsAny(schema) ? 'any' :
|
||||
Types.TypeGuard.IsArray(schema) ? `${Visit(schema.items, references)}[]` :
|
||||
Types.TypeGuard.IsAsyncIterator(schema) ? `AsyncIterableIterator<${Visit(schema.items, references)}>` :
|
||||
Types.TypeGuard.IsBigInt(schema) ? `bigint` :
|
||||
Types.TypeGuard.IsBoolean(schema) ? `boolean` :
|
||||
Types.TypeGuard.IsConstructor(schema) ? `new (${Parameters(schema.parameter, 0, references)}) => ${Visit(schema.returns, references)}` :
|
||||
Types.TypeGuard.IsDate(schema) ? 'Date' :
|
||||
Types.TypeGuard.IsFunction(schema) ? `(${Parameters(schema.parameters, 0, references)}) => ${Visit(schema.returns, references)}` :
|
||||
Types.TypeGuard.IsInteger(schema) ? 'number' :
|
||||
Types.TypeGuard.IsIntersect(schema) ? `(${Intersect(schema.allOf, references)})` :
|
||||
Types.TypeGuard.IsIterator(schema) ? `IterableIterator<${Visit(schema.items, references)}>` :
|
||||
Types.TypeGuard.IsLiteral(schema) ? `${Literal(schema, references)}` :
|
||||
Types.TypeGuard.IsNever(schema) ? `never` :
|
||||
Types.TypeGuard.IsNull(schema) ? `null` :
|
||||
Types.TypeGuard.IsNot(schema) ? 'unknown' :
|
||||
Types.TypeGuard.IsNumber(schema) ? 'number' :
|
||||
Types.TypeGuard.IsObject(schema) ? `{ ${Properties(schema.properties, Object.getOwnPropertyNames(schema.properties), references)} }` :
|
||||
Types.TypeGuard.IsPromise(schema) ? `Promise<${Visit(schema.item, references)}>` :
|
||||
Types.TypeGuard.IsRecord(schema) ? `${Record(schema, references)}` :
|
||||
Types.TypeGuard.IsRef(schema) ? `${Visit(Types.Type.Deref(schema, references), references)}` :
|
||||
Types.TypeGuard.IsString(schema) ? 'string' :
|
||||
Types.TypeGuard.IsSymbol(schema) ? 'symbol' :
|
||||
Types.TypeGuard.IsTemplateLiteral(schema) ? `${TemplateLiteral(schema, references)}` :
|
||||
Types.TypeGuard.IsThis(schema) ? 'unknown' : // requires named interface
|
||||
Types.TypeGuard.IsTuple(schema) ? `[${Tuple(schema.items || [], references)}]` :
|
||||
Types.TypeGuard.IsUint8Array(schema) ? `Uint8Array` :
|
||||
Types.TypeGuard.IsUndefined(schema) ? 'undefined' :
|
||||
Types.TypeGuard.IsUnion(schema) ? `${Union(schema.anyOf, references)}` :
|
||||
Types.TypeGuard.IsVoid(schema) ? `void` :
|
||||
'unknown'
|
||||
)
|
||||
}
|
||||
/** Generates a TypeScript annotation for the given schema */
|
||||
export function Code(schema: Types.TSchema, references: Types.TSchema[] = []): string {
|
||||
return Visit(schema, references)
|
||||
}
|
||||
}
|
||||
1
example/annotation/index.ts
Normal file
1
example/annotation/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './annotation'
|
||||
@@ -44,7 +44,6 @@ import {
|
||||
TTuple,
|
||||
TProperties,
|
||||
TIntersect,
|
||||
IntersectType,
|
||||
TUnion,
|
||||
TNever
|
||||
} from '@sinclair/typebox'
|
||||
@@ -75,7 +74,7 @@ export type TEvaluateArray<T extends TSchema[]> = T extends [infer L, ...infer
|
||||
[]
|
||||
// prettier-ignore
|
||||
export type TEvaluate<T extends TSchema> =
|
||||
T extends TIntersect<infer S> ? IntersectType<TEvaluateIntersectRest<S>> :
|
||||
T extends TIntersect<infer S> ? TIntersect<TEvaluateIntersectRest<S>> :
|
||||
T extends TUnion<infer S> ? TUnion<TEvaluateArray<S>> :
|
||||
T extends TConstructor<infer P, infer R> ? TConstructor<TEvaluateArray<P>, TEvaluate<R>> :
|
||||
T extends TFunction<infer P, infer R> ? TFunction<TEvaluateArray<P>, TEvaluate<R>> :
|
||||
@@ -119,16 +118,16 @@ export function EvaluateArray<T extends TSchema[] | undefined>(rest: T) {
|
||||
// prettier-ignore
|
||||
export function Evaluate<T extends TSchema>(schema: T): TEvaluate<T> {
|
||||
return (
|
||||
TypeGuard.TIntersect(schema) ? Type.Intersect(EvaluateIntersectRest(schema.allOf)) :
|
||||
TypeGuard.TUnion(schema) ? Type.Union(EvaluateArray(schema.anyOf)) :
|
||||
TypeGuard.TAsyncIterator(schema) ? Type.AsyncIterator(Evaluate(schema.items)) :
|
||||
TypeGuard.TIterator(schema) ? Type.Iterator(Evaluate(schema.items)) :
|
||||
TypeGuard.TObject(schema) ? Type.Object(EvaluateProperties(schema.properties)) :
|
||||
TypeGuard.TConstructor(schema) ? Type.Constructor(EvaluateArray(schema.parameters), Evaluate(schema.returns)) :
|
||||
TypeGuard.TFunction(schema) ? Type.Function(EvaluateArray(schema.parameters), Evaluate(schema.returns)) :
|
||||
TypeGuard.TTuple(schema) ? Type.Tuple(EvaluateArray(schema.items)) :
|
||||
TypeGuard.TArray(schema) ? Type.Promise(Evaluate(schema.items)) :
|
||||
TypeGuard.TPromise(schema) ? Type.Promise(Evaluate(schema.item)) :
|
||||
TypeGuard.IsIntersect(schema) ? Type.Intersect(EvaluateIntersectRest(schema.allOf)) :
|
||||
TypeGuard.IsUnion(schema) ? Type.Union(EvaluateArray(schema.anyOf)) :
|
||||
TypeGuard.IsAsyncIterator(schema) ? Type.AsyncIterator(Evaluate(schema.items)) :
|
||||
TypeGuard.IsIterator(schema) ? Type.Iterator(Evaluate(schema.items)) :
|
||||
TypeGuard.IsObject(schema) ? Type.Object(EvaluateProperties(schema.properties)) :
|
||||
TypeGuard.IsConstructor(schema) ? Type.Constructor(EvaluateArray(schema.parameters), Evaluate(schema.returns)) :
|
||||
TypeGuard.IsFunction(schema) ? Type.Function(EvaluateArray(schema.parameters), Evaluate(schema.returns)) :
|
||||
TypeGuard.IsTuple(schema) ? Type.Tuple(EvaluateArray(schema.items)) :
|
||||
TypeGuard.IsArray(schema) ? Type.Promise(Evaluate(schema.items)) :
|
||||
TypeGuard.IsPromise(schema) ? Type.Promise(Evaluate(schema.item)) :
|
||||
schema
|
||||
) as TEvaluate<T>
|
||||
}
|
||||
@@ -26,7 +26,6 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './const'
|
||||
export * from './evaluate'
|
||||
export * from './partial-deep'
|
||||
export * from './union-enum'
|
||||
@@ -26,7 +26,7 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TypeGuard, Type, TSchema, TIntersect, TUnion, TObject, TPartial, TProperties, AssertRest, AssertType, Evaluate } from '@sinclair/typebox'
|
||||
import { TypeGuard, Type, TSchema, TIntersect, TUnion, TObject, TPartial, TProperties, Evaluate } from '@sinclair/typebox'
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
// TDeepPartial
|
||||
@@ -34,9 +34,10 @@ import { TypeGuard, Type, TSchema, TIntersect, TUnion, TObject, TPartial, TPrope
|
||||
export type TPartialDeepProperties<T extends TProperties> = {
|
||||
[K in keyof T]: TPartial<T[K]>
|
||||
}
|
||||
export type TPartialDeepRest<T extends TSchema[]> = T extends [infer L, ...infer R]
|
||||
? [TPartial<AssertType<L>>, ...TPartialDeepRest<AssertRest<R>>]
|
||||
: []
|
||||
export type TPartialDeepRest<T extends TSchema[]> =
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? [TPartial<L>, ...TPartialDeepRest<R>]
|
||||
: []
|
||||
export type TPartialDeep<T extends TSchema> =
|
||||
T extends TIntersect<infer S> ? TIntersect<TPartialDeepRest<S>> :
|
||||
T extends TUnion<infer S> ? TUnion<TPartialDeepRest<S>> :
|
||||
@@ -57,9 +58,9 @@ function PartialDeepRest<T extends TSchema[]>(rest: [...T]): TPartialDeepRest<T>
|
||||
/** Maps the given schema as deep partial, making all properties and sub properties optional */
|
||||
export function PartialDeep<T extends TSchema>(type: T): TPartialDeep<T> {
|
||||
return (
|
||||
TypeGuard.TIntersect(type) ? Type.Intersect(PartialDeepRest(type.allOf)) :
|
||||
TypeGuard.TUnion(type) ? Type.Union(PartialDeepRest(type.anyOf)) :
|
||||
TypeGuard.TObject(type) ? Type.Partial(Type.Object(PartialDeepProperties(type.properties))) :
|
||||
TypeGuard.IsIntersect(type) ? Type.Intersect(PartialDeepRest(type.allOf)) :
|
||||
TypeGuard.IsUnion(type) ? Type.Union(PartialDeepRest(type.anyOf)) :
|
||||
TypeGuard.IsObject(type) ? Type.Partial(Type.Object(PartialDeepProperties(type.properties))) :
|
||||
type
|
||||
) as any
|
||||
}
|
||||
@@ -26,22 +26,11 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { TypeSystemErrorFunction, DefaultErrorFunction } from '@sinclair/typebox/system'
|
||||
import * as Types from '@sinclair/typebox'
|
||||
import { SetErrorFunction, DefaultErrorFunction } from '@sinclair/typebox/errors'
|
||||
import * as Types from '@sinclair/typebox/type'
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Utility Types
|
||||
// --------------------------------------------------------------------------
|
||||
export type Assert<T, U> = T extends U ? T : never
|
||||
export type Base = { m: string, t: string }
|
||||
export type Base16 = { m: 'F', t: '01', '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9', '9': 'A', 'A': 'B', 'B': 'C', 'C': 'D', 'D': 'E', 'E': 'F', 'F': '0' }
|
||||
export type Base10 = { m: '9', t: '01', '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9', '9': '0' }
|
||||
export type Reverse<T extends string> = T extends `${infer L}${infer R}` ? `${Reverse<R>}${L}` : T
|
||||
export type Tick<T extends string, B extends Base> = T extends keyof B ? B[T] : never
|
||||
export type Next<T extends string, B extends Base> = T extends Assert<B, Base>['m'] ? Assert<B, Base>['t'] : T extends `${infer L}${infer R}` ? L extends Assert<B, Base>['m'] ? `${Assert<Tick<L, B>, string>}${Next<R, B>}` : `${Assert<Tick<L, B>, string>}${R}` : never
|
||||
export type Increment<T extends string, B extends Base = Base10> = Reverse<Next<Reverse<T>, B>>
|
||||
// --------------------------------------------------------------------------
|
||||
// SchemaOptions
|
||||
// Metadata
|
||||
// --------------------------------------------------------------------------
|
||||
export interface Metadata {
|
||||
[name: string]: any
|
||||
@@ -65,9 +54,10 @@ export interface TBoolean extends Types.TSchema {
|
||||
// --------------------------------------------------------------------------
|
||||
// TUnion
|
||||
// --------------------------------------------------------------------------
|
||||
type InferUnion<T extends TStruct[], D extends string, Index = string> = T extends [infer L, ...infer R]
|
||||
? Types.Evaluate<{ [_ in D]: Index } & Types.Static<Types.AssertType<L>>> | InferUnion<Types.AssertRest<R>, D, Increment<Types.Assert<Index, string>>>
|
||||
: never
|
||||
export type InferUnion<T extends TStruct[], D extends string, Index = string> =
|
||||
T extends [infer L extends TStruct, ...infer R extends TStruct[]]
|
||||
? Types.Evaluate<{ [_ in D]: Index } & Types.Static<L>> | InferUnion<R, D, Types.Increment<Types.Assert<Index, string>>>
|
||||
: never
|
||||
|
||||
export interface TUnion<T extends TStruct[] = TStruct[], D extends string = string> extends Types.TSchema {
|
||||
[Types.Kind]: 'TypeDef:Union'
|
||||
@@ -170,14 +160,31 @@ export interface TString extends Types.TSchema {
|
||||
// --------------------------------------------------------------------------
|
||||
// TStruct
|
||||
// --------------------------------------------------------------------------
|
||||
// used for structural type inference
|
||||
type OptionalKeys<T extends TFields> = { [K in keyof T]: T[K] extends (Types.TOptional<T[K]>) ? T[K] : never }
|
||||
type RequiredKeys<T extends TFields> = { [K in keyof T]: T[K] extends (Types.TOptional<T[K]>) ? never : T[K] }
|
||||
// static inference
|
||||
type ReadonlyOptionalPropertyKeys<T extends TFields> = { [K in keyof T]: T[K] extends Types.TReadonly<Types.TSchema> ? (T[K] extends Types.TOptional<T[K]> ? K : never) : never }[keyof T]
|
||||
type ReadonlyPropertyKeys<T extends TFields> = { [K in keyof T]: T[K] extends Types.TReadonly<Types.TSchema> ? (T[K] extends Types.TOptional<T[K]> ? never : K) : never }[keyof T]
|
||||
type OptionalPropertyKeys<T extends TFields> = { [K in keyof T]: T[K] extends Types.TOptional<Types.TSchema> ? (T[K] extends Types.TReadonly<T[K]> ? never : K) : never }[keyof T]
|
||||
type RequiredPropertyKeys<T extends TFields> = keyof Omit<T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>
|
||||
// prettier-ignore
|
||||
type StructStaticProperties<T extends TFields, R extends Record<keyof any, unknown>> = Types.Evaluate<(
|
||||
Readonly<Partial<Pick<R, ReadonlyOptionalPropertyKeys<T>>>> &
|
||||
Readonly<Pick<R, ReadonlyPropertyKeys<T>>> &
|
||||
Partial<Pick<R, OptionalPropertyKeys<T>>> &
|
||||
Required<Pick<R, RequiredPropertyKeys<T>>>
|
||||
)>
|
||||
// prettier-ignore
|
||||
export type StructStatic<T extends TFields, P extends unknown[]> = StructStaticProperties<T, {
|
||||
[K in keyof T]: Static<T[K], P>
|
||||
}>
|
||||
export interface StructMetadata extends Metadata {
|
||||
additionalProperties?: boolean
|
||||
}
|
||||
export interface TStruct<T extends TFields = TFields> extends Types.TSchema, StructMetadata {
|
||||
[Types.Kind]: 'TypeDef:Struct'
|
||||
static: Types.PropertiesReduce<T, this['params']>
|
||||
static: StructStatic<T, this['params']>
|
||||
optionalProperties: { [K in Types.Assert<OptionalKeys<T>, keyof T>]: T[K] }
|
||||
properties: { [K in Types.Assert<RequiredKeys<T>, keyof T>]: T[K] }
|
||||
}
|
||||
@@ -487,8 +494,8 @@ Types.TypeRegistry.Set<TTimestamp>('TypeDef:Timestamp', (schema, value) => Value
|
||||
// --------------------------------------------------------------------------
|
||||
// TypeSystemErrorFunction
|
||||
// --------------------------------------------------------------------------
|
||||
TypeSystemErrorFunction.Set((schema, type) => {
|
||||
switch(schema[Types.Kind]) {
|
||||
SetErrorFunction((error) => {
|
||||
switch(error.schema[Types.Kind]) {
|
||||
case 'TypeDef:Array': return 'Expected Array'
|
||||
case 'TypeDef:Boolean': return 'Expected Boolean'
|
||||
case 'TypeDef:Union': return 'Expected Union'
|
||||
@@ -503,7 +510,7 @@ TypeSystemErrorFunction.Set((schema, type) => {
|
||||
case 'TypeDef:Struct': return 'Expected Struct'
|
||||
case 'TypeDef:Timestamp': return 'Expected Timestamp'
|
||||
}
|
||||
return DefaultErrorFunction(schema, type)
|
||||
return DefaultErrorFunction(error)
|
||||
})
|
||||
// --------------------------------------------------------------------------
|
||||
// TypeDefBuilder
|
||||
@@ -588,8 +595,8 @@ export class TypeDefBuilder {
|
||||
}
|
||||
/** [Standard] Creates a Struct type */
|
||||
public Struct<T extends TFields>(fields: T, metadata: StructMetadata = {}): TStruct<T> {
|
||||
const optionalProperties = globalThis.Object.getOwnPropertyNames(fields).reduce((acc, key) => (Types.TypeGuard.TOptional(fields[key]) ? { ...acc, [key]: fields[key] } : { ...acc }), {} as TFields)
|
||||
const properties = globalThis.Object.getOwnPropertyNames(fields).reduce((acc, key) => (Types.TypeGuard.TOptional(fields[key]) ? { ...acc } : { ...acc, [key]: fields[key] }), {} as TFields)
|
||||
const optionalProperties = globalThis.Object.getOwnPropertyNames(fields).reduce((acc, key) => (Types.TypeGuard.IsOptional(fields[key]) ? { ...acc, [key]: fields[key] } : { ...acc }), {} as TFields)
|
||||
const properties = globalThis.Object.getOwnPropertyNames(fields).reduce((acc, key) => (Types.TypeGuard.IsOptional(fields[key]) ? { ...acc } : { ...acc, [key]: fields[key] }), {} as TFields)
|
||||
const optionalObject = globalThis.Object.getOwnPropertyNames(optionalProperties).length > 0 ? { optionalProperties: optionalProperties } : {}
|
||||
const requiredObject = globalThis.Object.getOwnPropertyNames(properties).length === 0 ? {} : { properties: properties }
|
||||
return this.Create({ [Types.Kind]: 'TypeDef:Struct', ...requiredObject, ...optionalObject }, metadata)
|
||||
@@ -1,46 +0,0 @@
|
||||
# Using TypeBox with TRPC
|
||||
|
||||
To use TypeBox with TRPC, you will need to wrap types in a TRPC compatible validation function. The following shows wrapping a type using the TypeCompiler.
|
||||
|
||||
<a name="Example"></a>
|
||||
|
||||
## Example
|
||||
|
||||
[TypeScript Link Here](https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzsAdsGAVASgBQMIA0c2+AolFNHAL5wBmlIcA5AAIxRgDGA9AM4BTKADchzALAAoUJFiJiATzAC8EcMAA2QmvUYtWfVFw0BDYFB4wlAgEYQAHjy5qwmsVJnR4SDNaIYAZS4ACwEQEx0GNX1DFGMzCytlO3sJSSkeHjgAWly8-ILCouKS0rLyvIys1XUtPjgI32UGlAATOCgBGABXKBR6iOMIPl6BeioSPCqcitm5+YWCqQF7WXg6briYYAgUOCxuJoEAHgw4FZgBNvrAkLCTAD4ACj478IAuYiJOuiErrgEfE+t1C4QA2gBdOAAXjgkIAlIgpHA4M5+vA7lwANYwxTKGquLRQAB0BLcLzeJm+Al+nTigPhyI6XV6eyewhMGm6Ak+myxKAgAHcUIjoQ8kZIUSjgHQ4E9MVjSaFsezOdz4YjOj0+nAOVyBEyUWi+N44GATDBgkQQIC+CYAOZjWiwhXE8iUKB8VX6+HEgBi5hNT3hAEJDXBLZRBXAUAJo5N3dAnkgbXw7Y7PgADAAkCFT6YEtDoVFz5st1EzRGcrR5LAAQgBBAAiAH0sKQAIoAVVIAQwzBojMlNCk1Gmiwnk6nlUkmTgXYL4+ny5XZSkxvg8FhqHQk2JXE6FoEwfXuxNDVa7VhMGJYEoANaoyZxNQYG6MCeBy4Rye4aOxIAeRsAArAQuA-BBwxRExgWsYkADluhAGwhGDAgoLgGxYOUBCkJQqA0PDaghxRDVnwgd83w-L8fz-ODEOQ1CSNI5jiQAR25KAFCeZNkBQKjBxhcVX3fYkIgAaj4qjiRsRE5ySARsjtX4pGWVYvFRM94BMMAwCwCjLigXEb0od9UKQJkTEvOBR3hIA)
|
||||
|
||||
```typescript
|
||||
import { initTRPC, TRPCError } from '@trpc/server'
|
||||
import { TypeCompiler } from '@sinclair/typebox/compiler'
|
||||
import { Type, TSchema } from '@sinclair/typebox'
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// Compiles a Type and returns a closure for TRPC
|
||||
// ---------------------------------------------------------------------------------
|
||||
export function RpcType<T extends TSchema>(schema: T, references: TSchema[] = []) {
|
||||
const check = TypeCompiler.Compile(schema, references)
|
||||
return (value: unknown) => {
|
||||
if (check.Check(value)) return value
|
||||
const { path, message } = check.Errors(value).First()!
|
||||
throw new TRPCError({ message: `${message} for ${path}`, code: 'BAD_REQUEST' })
|
||||
}
|
||||
}
|
||||
// ---------------------------------------------------------------------------------
|
||||
// Usage
|
||||
// ---------------------------------------------------------------------------------
|
||||
const t = initTRPC.create()
|
||||
const add = t.procedure
|
||||
.input(RpcType(
|
||||
Type.Object({
|
||||
a: Type.Number(),
|
||||
b: Type.Number(),
|
||||
})
|
||||
))
|
||||
.output(RpcType(
|
||||
Type.Number()
|
||||
))
|
||||
.query(({ input }) => input.a + input.b) // type-safe
|
||||
|
||||
export const appRouter = t.router({
|
||||
add
|
||||
})
|
||||
```
|
||||
46
hammer.mjs
46
hammer.mjs
@@ -1,36 +1,32 @@
|
||||
import { compression, measurement } from './benchmark'
|
||||
import { readFileSync } from 'fs'
|
||||
import * as Benchmark from './task/benchmark'
|
||||
import * as Build from './task/build'
|
||||
import * as Fs from 'fs'
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// Clean
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function clean() {
|
||||
await folder('node_modules/typebox').delete()
|
||||
await folder('target').delete()
|
||||
}
|
||||
// -------------------------------------------------------------------------------
|
||||
// Format
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function format() {
|
||||
await shell('prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write src test examples/index.ts benchmark')
|
||||
await shell('prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write src test task example/index.ts')
|
||||
}
|
||||
// -------------------------------------------------------------------------------
|
||||
// Start
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function start() {
|
||||
await shell(`hammer run examples/index.ts --dist target/examples`)
|
||||
await shell(`hammer run example/index.ts --dist target/example`)
|
||||
}
|
||||
// -------------------------------------------------------------------------------
|
||||
// Benchmark
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function benchmark_compression() {
|
||||
await compression()
|
||||
}
|
||||
export async function benchmark_measurement() {
|
||||
await measurement()
|
||||
}
|
||||
export async function benchmark() {
|
||||
await benchmark_compression()
|
||||
await benchmark_measurement()
|
||||
await Benchmark.compression()
|
||||
await Benchmark.measurement()
|
||||
}
|
||||
// -------------------------------------------------------------------------------
|
||||
// Test
|
||||
@@ -56,20 +52,36 @@ export async function test(filter = '') {
|
||||
// -------------------------------------------------------------------------------
|
||||
// Build
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function build_check(target = 'target/build') {
|
||||
const { version } = JSON.parse(Fs.readFileSync('package.json', 'utf8'))
|
||||
await shell(`cd ${target} && attw sinclair-typebox-${version}.tgz`)
|
||||
}
|
||||
export async function build(target = 'target/build') {
|
||||
await test()
|
||||
await folder(target).delete()
|
||||
await shell(`tsc -p ./src/tsconfig.json --outDir ${target}`)
|
||||
await folder(target).add('package.json')
|
||||
await clean()
|
||||
await Promise.all([
|
||||
Build.Import.build(target),
|
||||
Build.Require.build(target),
|
||||
Build.Redirect.build(target)
|
||||
])
|
||||
await folder(target).add('readme.md')
|
||||
await folder(target).add('license')
|
||||
await shell(`cd ${target} && npm pack`)
|
||||
await build_check(target)
|
||||
}
|
||||
// -------------------------------------------------------------------------------
|
||||
// Install
|
||||
// -------------------------------------------------------------------------------
|
||||
export async function install_local() {
|
||||
await clean()
|
||||
await build('target/typebox')
|
||||
await folder('node_modules').add('target/typebox')
|
||||
}
|
||||
// -------------------------------------------------------------
|
||||
// Publish
|
||||
// -------------------------------------------------------------
|
||||
export async function publish(otp, target = 'target/build') {
|
||||
const { version } = JSON.parse(readFileSync('package.json', 'utf8'))
|
||||
const { version } = JSON.parse(Fs.readFileSync('package.json', 'utf8'))
|
||||
if(version.includes('-dev')) throw Error(`package version should not include -dev specifier`)
|
||||
await shell(`cd ${target} && npm publish sinclair-typebox-${version}.tgz --access=public --otp ${otp}`)
|
||||
await shell(`git tag ${version}`)
|
||||
@@ -79,7 +91,7 @@ export async function publish(otp, target = 'target/build') {
|
||||
// Publish-Dev
|
||||
// -------------------------------------------------------------
|
||||
export async function publish_dev(otp, target = 'target/build') {
|
||||
const { version } = JSON.parse(readFileSync(`${target}/package.json`, 'utf8'))
|
||||
const { version } = JSON.parse(Fs.readFileSync(`${target}/package.json`, 'utf8'))
|
||||
if(!version.includes('-dev')) throw Error(`development package version should include -dev specifier`)
|
||||
await shell(`cd ${target} && npm publish sinclair-typebox-${version}.tgz --access=public --otp ${otp} --tag dev`)
|
||||
}
|
||||
4
license
4
license
@@ -1,4 +1,6 @@
|
||||
TypeBox: JSON Schema Type Builder with Static Type Resolution for TypeScript
|
||||
TypeBox
|
||||
|
||||
Json Schema Type Builder with Static Type Resolution for TypeScript
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
623
package-lock.json
generated
623
package-lock.json
generated
@@ -1,17 +1,18 @@
|
||||
{
|
||||
"name": "@sinclair/typebox",
|
||||
"version": "0.31.28",
|
||||
"version": "0.32.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@sinclair/typebox",
|
||||
"version": "0.31.28",
|
||||
"version": "0.32.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@arethetypeswrong/cli": "^0.13.2",
|
||||
"@sinclair/hammer": "^0.18.0",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/node": "^20.10.1",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"mocha": "^9.2.2",
|
||||
@@ -19,6 +20,59 @@
|
||||
"typescript": "^5.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@andrewbranch/untar.js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz",
|
||||
"integrity": "sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@arethetypeswrong/cli": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@arethetypeswrong/cli/-/cli-0.13.2.tgz",
|
||||
"integrity": "sha512-eqRWeFFiI58xwsiUfZSdZsmNCaqqtxmSPP9554ajiCDrB/aNzq5VktVK7dNiT9PamunNeoej4KbDBnkNwVacvg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@arethetypeswrong/core": "0.13.2",
|
||||
"chalk": "^4.1.2",
|
||||
"cli-table3": "^0.6.3",
|
||||
"commander": "^10.0.1",
|
||||
"marked": "^9.1.2",
|
||||
"marked-terminal": "^6.0.0",
|
||||
"semver": "^7.5.4"
|
||||
},
|
||||
"bin": {
|
||||
"attw": "dist/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@arethetypeswrong/core": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@arethetypeswrong/core/-/core-0.13.2.tgz",
|
||||
"integrity": "sha512-1l6ygar+6TH4o1JipWWGCEZlOhAwEShm1yKx+CgIByNjCzufbu6k9DNbDmBjdouusNRhBIOYQe1UHnJig+GtAw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@andrewbranch/untar.js": "^1.0.3",
|
||||
"fflate": "^0.7.4",
|
||||
"semver": "^7.5.4",
|
||||
"typescript": "5.3.2",
|
||||
"validate-npm-package-name": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@colors/colors": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
|
||||
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.15.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz",
|
||||
@@ -47,6 +101,18 @@
|
||||
"hammer": "hammer"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
||||
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/mocha": {
|
||||
"version": "9.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz",
|
||||
@@ -54,10 +120,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.2.tgz",
|
||||
"integrity": "sha512-wBo3KqP/PBqje5TI9UTiuL3yWfP6sdPtjtygSOqcYZWT232dfDeDOnkDps5wqZBP9NgGgYrNejinl0faAuE+HQ==",
|
||||
"dev": true
|
||||
"version": "20.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.1.tgz",
|
||||
"integrity": "sha512-T2qwhjWwGH81vUEx4EXmBKsTJRXFXNZTL4v0gi01+zyBmCwzE6TyHszqX01m+QHTEq+EZNo13NeJIdEqf+Myrg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@ungap/promise-all-settled": {
|
||||
"version": "1.1.2",
|
||||
@@ -107,6 +176,21 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escapes": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz",
|
||||
"integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"type-fest": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
@@ -131,6 +215,12 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansicolors": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
|
||||
"integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
@@ -193,6 +283,15 @@
|
||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/builtins": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
|
||||
"integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"semver": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||
@@ -205,6 +304,19 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/cardinal": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
|
||||
"integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansicolors": "~0.3.2",
|
||||
"redeyed": "~2.1.0"
|
||||
},
|
||||
"bin": {
|
||||
"cdl": "bin/cdl.js"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -233,6 +345,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/char-regex": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
@@ -260,6 +381,21 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-table3": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
|
||||
"integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "10.* || >= 12.*"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@colors/colors": "1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
@@ -289,6 +425,15 @@
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -345,6 +490,12 @@
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/emojilib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz",
|
||||
"integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.15.7",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz",
|
||||
@@ -722,12 +873,31 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"esparse": "bin/esparse.js",
|
||||
"esvalidate": "bin/esvalidate.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fflate": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz",
|
||||
"integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
@@ -1008,6 +1178,62 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "9.1.6",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz",
|
||||
"integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
}
|
||||
},
|
||||
"node_modules/marked-terminal": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.1.0.tgz",
|
||||
"integrity": "sha512-QaCSF6NV82oo6K0szEnmc65ooDeW0T/Adcyf0fcW+Hto2GT1VADFg8dn1zaeHqzj65fqDH1hMNChGNRaC/lbkA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-escapes": "^6.2.0",
|
||||
"cardinal": "^2.1.1",
|
||||
"chalk": "^5.3.0",
|
||||
"cli-table3": "^0.6.3",
|
||||
"node-emoji": "^2.1.0",
|
||||
"supports-hyperlinks": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"marked": ">=1 <11"
|
||||
}
|
||||
},
|
||||
"node_modules/marked-terminal/node_modules/chalk": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
|
||||
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz",
|
||||
@@ -1081,6 +1307,21 @@
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/node-emoji": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz",
|
||||
"integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.6.0",
|
||||
"char-regex": "^1.0.2",
|
||||
"emojilib": "^2.4.0",
|
||||
"skin-tone": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@@ -1204,6 +1445,15 @@
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/redeyed": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
|
||||
"integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esprima": "~4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
@@ -1242,6 +1492,21 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
|
||||
@@ -1251,6 +1516,18 @@
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/skin-tone": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz",
|
||||
"integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"unicode-emoji-modifier-base": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
@@ -1304,6 +1581,31 @@
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-hyperlinks": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz",
|
||||
"integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0",
|
||||
"supports-color": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.18"
|
||||
}
|
||||
},
|
||||
"node_modules/supports-hyperlinks/node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
@@ -1316,6 +1618,18 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
|
||||
"integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz",
|
||||
@@ -1329,6 +1643,21 @@
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/unicode-emoji-modifier-base": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz",
|
||||
"integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
@@ -1338,6 +1667,18 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/validate-npm-package-name": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz",
|
||||
"integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"builtins": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@@ -1391,6 +1732,12 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
@@ -1447,6 +1794,47 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@andrewbranch/untar.js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz",
|
||||
"integrity": "sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==",
|
||||
"dev": true
|
||||
},
|
||||
"@arethetypeswrong/cli": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@arethetypeswrong/cli/-/cli-0.13.2.tgz",
|
||||
"integrity": "sha512-eqRWeFFiI58xwsiUfZSdZsmNCaqqtxmSPP9554ajiCDrB/aNzq5VktVK7dNiT9PamunNeoej4KbDBnkNwVacvg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@arethetypeswrong/core": "0.13.2",
|
||||
"chalk": "^4.1.2",
|
||||
"cli-table3": "^0.6.3",
|
||||
"commander": "^10.0.1",
|
||||
"marked": "^9.1.2",
|
||||
"marked-terminal": "^6.0.0",
|
||||
"semver": "^7.5.4"
|
||||
}
|
||||
},
|
||||
"@arethetypeswrong/core": {
|
||||
"version": "0.13.2",
|
||||
"resolved": "https://registry.npmjs.org/@arethetypeswrong/core/-/core-0.13.2.tgz",
|
||||
"integrity": "sha512-1l6ygar+6TH4o1JipWWGCEZlOhAwEShm1yKx+CgIByNjCzufbu6k9DNbDmBjdouusNRhBIOYQe1UHnJig+GtAw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@andrewbranch/untar.js": "^1.0.3",
|
||||
"fflate": "^0.7.4",
|
||||
"semver": "^7.5.4",
|
||||
"typescript": "5.3.2",
|
||||
"validate-npm-package-name": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"@colors/colors": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
|
||||
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@esbuild/linux-loong64": {
|
||||
"version": "0.15.7",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz",
|
||||
@@ -1463,6 +1851,12 @@
|
||||
"esbuild": "0.15.7"
|
||||
}
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
|
||||
"integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/mocha": {
|
||||
"version": "9.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz",
|
||||
@@ -1470,10 +1864,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.2.tgz",
|
||||
"integrity": "sha512-wBo3KqP/PBqje5TI9UTiuL3yWfP6sdPtjtygSOqcYZWT232dfDeDOnkDps5wqZBP9NgGgYrNejinl0faAuE+HQ==",
|
||||
"dev": true
|
||||
"version": "20.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.1.tgz",
|
||||
"integrity": "sha512-T2qwhjWwGH81vUEx4EXmBKsTJRXFXNZTL4v0gi01+zyBmCwzE6TyHszqX01m+QHTEq+EZNo13NeJIdEqf+Myrg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
},
|
||||
"@ungap/promise-all-settled": {
|
||||
"version": "1.1.2",
|
||||
@@ -1508,6 +1905,15 @@
|
||||
"integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-escapes": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz",
|
||||
"integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"type-fest": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
@@ -1523,6 +1929,12 @@
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"ansicolors": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
|
||||
"integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
|
||||
"dev": true
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
@@ -1576,12 +1988,31 @@
|
||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
|
||||
"dev": true
|
||||
},
|
||||
"builtins": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
|
||||
"integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
|
||||
"dev": true
|
||||
},
|
||||
"cardinal": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz",
|
||||
"integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansicolors": "~0.3.2",
|
||||
"redeyed": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
||||
@@ -1603,6 +2034,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"char-regex": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
|
||||
"dev": true
|
||||
},
|
||||
"chokidar": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
@@ -1619,6 +2056,16 @@
|
||||
"readdirp": "~3.6.0"
|
||||
}
|
||||
},
|
||||
"cli-table3": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
|
||||
"integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"string-width": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||
@@ -1645,6 +2092,12 @@
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true
|
||||
},
|
||||
"commander": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
|
||||
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -1686,6 +2139,12 @@
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"emojilib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz",
|
||||
"integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==",
|
||||
"dev": true
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.15.7",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.7.tgz",
|
||||
@@ -1867,12 +2326,24 @@
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fflate": {
|
||||
"version": "0.7.4",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz",
|
||||
"integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==",
|
||||
"dev": true
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
@@ -2073,6 +2544,43 @@
|
||||
"is-unicode-supported": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"yallist": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"marked": {
|
||||
"version": "9.1.6",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz",
|
||||
"integrity": "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==",
|
||||
"dev": true
|
||||
},
|
||||
"marked-terminal": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-6.1.0.tgz",
|
||||
"integrity": "sha512-QaCSF6NV82oo6K0szEnmc65ooDeW0T/Adcyf0fcW+Hto2GT1VADFg8dn1zaeHqzj65fqDH1hMNChGNRaC/lbkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "^6.2.0",
|
||||
"cardinal": "^2.1.1",
|
||||
"chalk": "^5.3.0",
|
||||
"cli-table3": "^0.6.3",
|
||||
"node-emoji": "^2.1.0",
|
||||
"supports-hyperlinks": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
|
||||
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz",
|
||||
@@ -2126,6 +2634,18 @@
|
||||
"integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
|
||||
"dev": true
|
||||
},
|
||||
"node-emoji": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz",
|
||||
"integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@sindresorhus/is": "^4.6.0",
|
||||
"char-regex": "^1.0.2",
|
||||
"emojilib": "^2.4.0",
|
||||
"skin-tone": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@@ -2207,6 +2727,15 @@
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"redeyed": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz",
|
||||
"integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esprima": "~4.0.0"
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
@@ -2225,6 +2754,15 @@
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||
"dev": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"serialize-javascript": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
|
||||
@@ -2234,6 +2772,15 @@
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"skin-tone": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz",
|
||||
"integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"unicode-emoji-modifier-base": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
@@ -2269,6 +2816,27 @@
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"supports-hyperlinks": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz",
|
||||
"integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0",
|
||||
"supports-color": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
@@ -2278,12 +2846,30 @@
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
|
||||
"integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz",
|
||||
"integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==",
|
||||
"dev": true
|
||||
},
|
||||
"undici-types": {
|
||||
"version": "5.26.5",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"dev": true
|
||||
},
|
||||
"unicode-emoji-modifier-base": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz",
|
||||
"integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==",
|
||||
"dev": true
|
||||
},
|
||||
"uri-js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||
@@ -2293,6 +2879,15 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"validate-npm-package-name": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz",
|
||||
"integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"builtins": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@@ -2331,6 +2926,12 @@
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "16.2.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
|
||||
|
||||
36
package.json
36
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@sinclair/typebox",
|
||||
"version": "0.31.28",
|
||||
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
|
||||
"version": "0.32.0",
|
||||
"description": "Json Schema Type Builder with Static Type Resolution for TypeScript",
|
||||
"keywords": [
|
||||
"typescript",
|
||||
"json-schema",
|
||||
@@ -10,28 +10,6 @@
|
||||
],
|
||||
"author": "sinclairzx81",
|
||||
"license": "MIT",
|
||||
"main": "./typebox.js",
|
||||
"types": "./typebox.d.ts",
|
||||
"exports": {
|
||||
"./compiler": "./compiler/index.js",
|
||||
"./errors": "./errors/index.js",
|
||||
"./system": "./system/index.js",
|
||||
"./value/cast": "./value/cast.js",
|
||||
"./value/check": "./value/check.js",
|
||||
"./value/clone": "./value/clone.js",
|
||||
"./value/convert": "./value/convert.js",
|
||||
"./value/create": "./value/create.js",
|
||||
"./value/delta": "./value/delta.js",
|
||||
"./value/deref": "./value/deref.js",
|
||||
"./value/equal": "./value/equal.js",
|
||||
"./value/guard": "./value/guard.js",
|
||||
"./value/hash": "./value/hash.js",
|
||||
"./value/mutate": "./value/mutate.js",
|
||||
"./value/pointer": "./value/pointer.js",
|
||||
"./value/transform": "./value/transform.js",
|
||||
"./value": "./value/index.js",
|
||||
".": "./typebox.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sinclairzx81/typebox"
|
||||
@@ -40,21 +18,21 @@
|
||||
"test:typescript": "hammer task test_typescript",
|
||||
"test:static": "hammer task test_static",
|
||||
"test:runtime": "hammer task test_runtime",
|
||||
"install:local": "hammer task install_local",
|
||||
"benchmark": "hammer task benchmark",
|
||||
"build": "hammer task build",
|
||||
"test": "hammer task test",
|
||||
"clean": "hammer task clean",
|
||||
"format": "hammer task format",
|
||||
"start": "hammer task start",
|
||||
"benchmark:compression": "hammer task benchmark_compression",
|
||||
"benchmark:measurement": "hammer task benchmark_measurement",
|
||||
"benchmark": "hammer task benchmark",
|
||||
"build": "hammer task build",
|
||||
"publish": "hammer task publish",
|
||||
"publish:dev": "hammer task publish_dev"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arethetypeswrong/cli": "^0.13.2",
|
||||
"@sinclair/hammer": "^0.18.0",
|
||||
"@types/mocha": "^9.1.1",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/node": "^20.10.1",
|
||||
"ajv": "^8.12.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"mocha": "^9.2.2",
|
||||
|
||||
@@ -26,25 +26,70 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { EncodeTransform, DecodeTransform, HasTransform, TransformDecodeCheckError, TransformEncodeCheckError } from '../value/transform'
|
||||
import { IsArray, IsString, IsNumber, IsBigInt } from '../value/guard'
|
||||
import { Errors, ValueErrorIterator } from '../errors/errors'
|
||||
import { TransformEncode, TransformDecode, HasTransform, TransformDecodeCheckError, TransformEncodeCheckError } from '../value/transform/index'
|
||||
import { Errors, ValueErrorIterator } from '../errors/index'
|
||||
import { TypeSystemPolicy } from '../system/index'
|
||||
import { Deref } from '../value/deref'
|
||||
import { Hash } from '../value/hash'
|
||||
import * as Types from '../typebox'
|
||||
import { TypeBoxError } from '../type/error/index'
|
||||
import { Deref } from '../value/deref/index'
|
||||
import { Hash } from '../value/hash/index'
|
||||
import { Kind } from '../type/symbols/index'
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
import { TypeRegistry, FormatRegistry } from '../type/registry/index'
|
||||
import { KeyOfPattern } from '../type/keyof/index'
|
||||
import { ExtendsUndefinedCheck } from '../type/extends/extends-undefined'
|
||||
|
||||
import type { TSchema } from '../type/schema/index'
|
||||
import type { TAsyncIterator } from '../type/async-iterator/index'
|
||||
import type { TAny } from '../type/any/index'
|
||||
import type { TArray } from '../type/array/index'
|
||||
import type { TBigInt } from '../type/bigint/index'
|
||||
import type { TBoolean } from '../type/boolean/index'
|
||||
import type { TDate } from '../type/date/index'
|
||||
import type { TConstructor } from '../type/constructor/index'
|
||||
import type { TFunction } from '../type/function/index'
|
||||
import type { TInteger } from '../type/integer/index'
|
||||
import type { TIntersect } from '../type/intersect/index'
|
||||
import type { TIterator } from '../type/iterator/index'
|
||||
import type { TLiteral } from '../type/literal/index'
|
||||
import { Never, type TNever } from '../type/never/index'
|
||||
import type { TNot } from '../type/not/index'
|
||||
import type { TNull } from '../type/null/index'
|
||||
import type { TNumber } from '../type/number/index'
|
||||
import type { TObject } from '../type/object/index'
|
||||
import type { TPromise } from '../type/promise/index'
|
||||
import type { TRecord } from '../type/record/index'
|
||||
import type { TRef } from '../type/ref/index'
|
||||
import type { TRegExp } from '../type/regexp/index'
|
||||
import type { TTemplateLiteral } from '../type/template-literal/index'
|
||||
import type { TThis } from '../type/recursive/index'
|
||||
import type { TTuple } from '../type/tuple/index'
|
||||
import type { TUnion } from '../type/union/index'
|
||||
import type { TUnknown } from '../type/unknown/index'
|
||||
import type { Static, StaticDecode, StaticEncode } from '../type/static/index'
|
||||
import type { TString } from '../type/string/index'
|
||||
import type { TSymbol } from '../type/symbol/index'
|
||||
import type { TUndefined } from '../type/undefined/index'
|
||||
import type { TUint8Array } from '../type/uint8array/index'
|
||||
import type { TVoid } from '../type/void/index'
|
||||
// ------------------------------------------------------------------
|
||||
// ValueGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsArray, IsString, IsNumber, IsBigInt } from '../value/guard/index'
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsSchema } from '../type/guard/type'
|
||||
// ------------------------------------------------------------------
|
||||
// CheckFunction
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
export type CheckFunction = (value: unknown) => boolean
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// TypeCheck
|
||||
// -------------------------------------------------------------------
|
||||
export class TypeCheck<T extends Types.TSchema> {
|
||||
// ------------------------------------------------------------------
|
||||
export class TypeCheck<T extends TSchema> {
|
||||
private readonly hasTransform: boolean
|
||||
constructor(private readonly schema: T, private readonly references: Types.TSchema[], private readonly checkFunc: CheckFunction, private readonly code: string) {
|
||||
this.hasTransform = HasTransform.Has(schema, references)
|
||||
constructor(private readonly schema: T, private readonly references: TSchema[], private readonly checkFunc: CheckFunction, private readonly code: string) {
|
||||
this.hasTransform = HasTransform(schema, references)
|
||||
}
|
||||
/** Returns the generated assertion code used to validate this type. */
|
||||
public Code(): string {
|
||||
@@ -55,24 +100,24 @@ export class TypeCheck<T extends Types.TSchema> {
|
||||
return Errors(this.schema, this.references, value)
|
||||
}
|
||||
/** Returns true if the value matches the compiled type. */
|
||||
public Check(value: unknown): value is Types.Static<T> {
|
||||
public Check(value: unknown): value is Static<T> {
|
||||
return this.checkFunc(value)
|
||||
}
|
||||
/** Decodes a value or throws if error */
|
||||
public Decode(value: unknown): Types.StaticDecode<T> {
|
||||
public Decode(value: unknown): StaticDecode<T> {
|
||||
if (!this.checkFunc(value)) throw new TransformDecodeCheckError(this.schema, value, this.Errors(value).First()!)
|
||||
return this.hasTransform ? DecodeTransform.Decode(this.schema, this.references, value) : value
|
||||
return this.hasTransform ? TransformDecode(this.schema, this.references, value) : value
|
||||
}
|
||||
/** Encodes a value or throws if error */
|
||||
public Encode(value: unknown): Types.StaticEncode<T> {
|
||||
const encoded = this.hasTransform ? EncodeTransform.Encode(this.schema, this.references, value) : value
|
||||
public Encode(value: unknown): StaticEncode<T> {
|
||||
const encoded = this.hasTransform ? TransformEncode(this.schema, this.references, value) : value
|
||||
if (!this.checkFunc(encoded)) throw new TransformEncodeCheckError(this.schema, value, this.Errors(value).First()!)
|
||||
return encoded
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// Character
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
namespace Character {
|
||||
export function DollarSign(code: number) {
|
||||
return code === 36
|
||||
@@ -87,9 +132,9 @@ namespace Character {
|
||||
return code >= 48 && code <= 57
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// MemberExpression
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
namespace MemberExpression {
|
||||
function IsFirstCharacterNumeric(value: string) {
|
||||
if (value.length === 0) return false
|
||||
@@ -111,9 +156,9 @@ namespace MemberExpression {
|
||||
return IsAccessor(key) ? `${object}.${key}` : `${object}['${EscapeHyphen(key)}']`
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// Identifier
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
namespace Identifier {
|
||||
export function Encode($id: string) {
|
||||
const buffer: string[] = []
|
||||
@@ -128,30 +173,30 @@ namespace Identifier {
|
||||
return buffer.join('').replace(/__/g, '_')
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// LiteralString
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
namespace LiteralString {
|
||||
export function Escape(content: string) {
|
||||
return content.replace(/'/g, "\\'")
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// Errors
|
||||
// -------------------------------------------------------------------
|
||||
export class TypeCompilerUnknownTypeError extends Types.TypeBoxError {
|
||||
constructor(public readonly schema: Types.TSchema) {
|
||||
// ------------------------------------------------------------------
|
||||
export class TypeCompilerUnknownTypeError extends TypeBoxError {
|
||||
constructor(public readonly schema: TSchema) {
|
||||
super('Unknown type')
|
||||
}
|
||||
}
|
||||
export class TypeCompilerTypeGuardError extends Types.TypeBoxError {
|
||||
constructor(public readonly schema: Types.TSchema) {
|
||||
export class TypeCompilerTypeGuardError extends TypeBoxError {
|
||||
constructor(public readonly schema: TSchema) {
|
||||
super('Preflight validation check failed to guard for the given schema')
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// Policy
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
export namespace Policy {
|
||||
export function IsExactOptionalProperty(value: string, key: string, expression: string) {
|
||||
return TypeSystemPolicy.ExactOptionalPropertyTypes ? `('${key}' in ${value} ? ${expression} : true)` : `(${MemberExpression.Encode(value, key)} !== undefined ? ${expression} : true)`
|
||||
@@ -171,36 +216,36 @@ export namespace Policy {
|
||||
return TypeSystemPolicy.AllowNullVoid ? `(${value} === undefined || ${value} === null)` : `${value} === undefined`
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// TypeCompiler
|
||||
// -------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
export type TypeCompilerLanguageOption = 'typescript' | 'javascript'
|
||||
export interface TypeCompilerCodegenOptions {
|
||||
language?: TypeCompilerLanguageOption
|
||||
}
|
||||
/** Compiles Types for Runtime Type Checking */
|
||||
export namespace TypeCompiler {
|
||||
// ----------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------
|
||||
// Guards
|
||||
// ----------------------------------------------------------------------
|
||||
function IsAnyOrUnknown(schema: Types.TSchema) {
|
||||
return schema[Types.Kind] === 'Any' || schema[Types.Kind] === 'Unknown'
|
||||
// ----------------------------------------------------------------
|
||||
function IsAnyOrUnknown(schema: TSchema) {
|
||||
return schema[Kind] === 'Any' || schema[Kind] === 'Unknown'
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------
|
||||
// Types
|
||||
// -------------------------------------------------------------------
|
||||
function* TAny(schema: Types.TAny, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
// ----------------------------------------------------------------
|
||||
function* FromAny(schema: TAny, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield 'true'
|
||||
}
|
||||
function* TArray(schema: Types.TArray, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromArray(schema: TArray, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `Array.isArray(${value})`
|
||||
const [parameter, accumulator] = [CreateParameter('value', 'any'), CreateParameter('acc', 'number')]
|
||||
if (IsNumber(schema.maxItems)) yield `${value}.length <= ${schema.maxItems}`
|
||||
if (IsNumber(schema.minItems)) yield `${value}.length >= ${schema.minItems}`
|
||||
const elementExpression = CreateExpression(schema.items, references, 'value')
|
||||
yield `${value}.every((${parameter}) => ${elementExpression})`
|
||||
if (Types.TypeGuard.TSchema(schema.contains) || IsNumber(schema.minContains) || IsNumber(schema.maxContains)) {
|
||||
const containsSchema = Types.TypeGuard.TSchema(schema.contains) ? schema.contains : Types.Type.Never()
|
||||
if (IsSchema(schema.contains) || IsNumber(schema.minContains) || IsNumber(schema.maxContains)) {
|
||||
const containsSchema = IsSchema(schema.contains) ? schema.contains : Never()
|
||||
const checkExpression = CreateExpression(containsSchema, references, 'value')
|
||||
const checkMinContains = IsNumber(schema.minContains) ? [`(count >= ${schema.minContains})`] : []
|
||||
const checkMaxContains = IsNumber(schema.maxContains) ? [`(count <= ${schema.maxContains})`] : []
|
||||
@@ -214,10 +259,10 @@ export namespace TypeCompiler {
|
||||
yield `((${parameter}) => { ${block} )(${value})`
|
||||
}
|
||||
}
|
||||
function* TAsyncIterator(schema: Types.TAsyncIterator, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromAsyncIterator(schema: TAsyncIterator, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof value === 'object' && Symbol.asyncIterator in ${value})`
|
||||
}
|
||||
function* TBigInt(schema: Types.TBigInt, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromBigInt(schema: TBigInt, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'bigint')`
|
||||
if (IsBigInt(schema.exclusiveMaximum)) yield `${value} < BigInt(${schema.exclusiveMaximum})`
|
||||
if (IsBigInt(schema.exclusiveMinimum)) yield `${value} > BigInt(${schema.exclusiveMinimum})`
|
||||
@@ -225,13 +270,13 @@ export namespace TypeCompiler {
|
||||
if (IsBigInt(schema.minimum)) yield `${value} >= BigInt(${schema.minimum})`
|
||||
if (IsBigInt(schema.multipleOf)) yield `(${value} % BigInt(${schema.multipleOf})) === 0`
|
||||
}
|
||||
function* TBoolean(schema: Types.TBoolean, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromBoolean(schema: TBoolean, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'boolean')`
|
||||
}
|
||||
function* TConstructor(schema: Types.TConstructor, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromConstructor(schema: TConstructor, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield* Visit(schema.returns, references, `${value}.prototype`)
|
||||
}
|
||||
function* TDate(schema: Types.TDate, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromDate(schema: TDate, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(${value} instanceof Date) && Number.isFinite(${value}.getTime())`
|
||||
if (IsNumber(schema.exclusiveMaximumTimestamp)) yield `${value}.getTime() < ${schema.exclusiveMaximumTimestamp}`
|
||||
if (IsNumber(schema.exclusiveMinimumTimestamp)) yield `${value}.getTime() > ${schema.exclusiveMinimumTimestamp}`
|
||||
@@ -239,10 +284,10 @@ export namespace TypeCompiler {
|
||||
if (IsNumber(schema.minimumTimestamp)) yield `${value}.getTime() >= ${schema.minimumTimestamp}`
|
||||
if (IsNumber(schema.multipleOfTimestamp)) yield `(${value}.getTime() % ${schema.multipleOfTimestamp}) === 0`
|
||||
}
|
||||
function* TFunction(schema: Types.TFunction, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromFunction(schema: TFunction, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'function')`
|
||||
}
|
||||
function* TInteger(schema: Types.TInteger, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromInteger(schema: TInteger, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'number' && Number.isInteger(${value}))`
|
||||
if (IsNumber(schema.exclusiveMaximum)) yield `${value} < ${schema.exclusiveMaximum}`
|
||||
if (IsNumber(schema.exclusiveMinimum)) yield `${value} > ${schema.exclusiveMinimum}`
|
||||
@@ -250,41 +295,41 @@ export namespace TypeCompiler {
|
||||
if (IsNumber(schema.minimum)) yield `${value} >= ${schema.minimum}`
|
||||
if (IsNumber(schema.multipleOf)) yield `(${value} % ${schema.multipleOf}) === 0`
|
||||
}
|
||||
function* TIntersect(schema: Types.TIntersect, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
const check1 = schema.allOf.map((schema: Types.TSchema) => CreateExpression(schema, references, value)).join(' && ')
|
||||
function* FromIntersect(schema: TIntersect, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const check1 = schema.allOf.map((schema: TSchema) => CreateExpression(schema, references, value)).join(' && ')
|
||||
if (schema.unevaluatedProperties === false) {
|
||||
const keyCheck = CreateVariable(`${new RegExp(Types.KeyResolver.ResolvePattern(schema))};`)
|
||||
const keyCheck = CreateVariable(`${new RegExp(KeyOfPattern(schema))};`)
|
||||
const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key))`
|
||||
yield `(${check1} && ${check2})`
|
||||
} else if (Types.TypeGuard.TSchema(schema.unevaluatedProperties)) {
|
||||
const keyCheck = CreateVariable(`${new RegExp(Types.KeyResolver.ResolvePattern(schema))};`)
|
||||
} else if (IsSchema(schema.unevaluatedProperties)) {
|
||||
const keyCheck = CreateVariable(`${new RegExp(KeyOfPattern(schema))};`)
|
||||
const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key) || ${CreateExpression(schema.unevaluatedProperties, references, `${value}[key]`)})`
|
||||
yield `(${check1} && ${check2})`
|
||||
} else {
|
||||
yield `(${check1})`
|
||||
}
|
||||
}
|
||||
function* TIterator(schema: Types.TIterator, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromIterator(schema: TIterator, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof value === 'object' && Symbol.iterator in ${value})`
|
||||
}
|
||||
function* TLiteral(schema: Types.TLiteral, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromLiteral(schema: TLiteral, references: TSchema[], value: string): IterableIterator<string> {
|
||||
if (typeof schema.const === 'number' || typeof schema.const === 'boolean') {
|
||||
yield `(${value} === ${schema.const})`
|
||||
} else {
|
||||
yield `(${value} === '${LiteralString.Escape(schema.const)}')`
|
||||
}
|
||||
}
|
||||
function* TNever(schema: Types.TNever, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromNever(schema: TNever, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `false`
|
||||
}
|
||||
function* TNot(schema: Types.TNot, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromNot(schema: TNot, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const expression = CreateExpression(schema.not, references, value)
|
||||
yield `(!${expression})`
|
||||
}
|
||||
function* TNull(schema: Types.TNull, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromNull(schema: TNull, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(${value} === null)`
|
||||
}
|
||||
function* TNumber(schema: Types.TNumber, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromNumber(schema: TNumber, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield Policy.IsNumberLike(value)
|
||||
if (IsNumber(schema.exclusiveMaximum)) yield `${value} < ${schema.exclusiveMaximum}`
|
||||
if (IsNumber(schema.exclusiveMinimum)) yield `${value} > ${schema.exclusiveMinimum}`
|
||||
@@ -292,7 +337,7 @@ export namespace TypeCompiler {
|
||||
if (IsNumber(schema.minimum)) yield `${value} >= ${schema.minimum}`
|
||||
if (IsNumber(schema.multipleOf)) yield `(${value} % ${schema.multipleOf}) === 0`
|
||||
}
|
||||
function* TObject(schema: Types.TObject, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromObject(schema: TObject, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield Policy.IsObjectLike(value)
|
||||
if (IsNumber(schema.minProperties)) yield `Object.getOwnPropertyNames(${value}).length >= ${schema.minProperties}`
|
||||
if (IsNumber(schema.maxProperties)) yield `Object.getOwnPropertyNames(${value}).length <= ${schema.maxProperties}`
|
||||
@@ -302,7 +347,7 @@ export namespace TypeCompiler {
|
||||
const property = schema.properties[knownKey]
|
||||
if (schema.required && schema.required.includes(knownKey)) {
|
||||
yield* Visit(property, references, memberExpression)
|
||||
if (Types.ExtendsUndefined.Check(property) || IsAnyOrUnknown(property)) yield `('${knownKey}' in ${value})`
|
||||
if (ExtendsUndefinedCheck(property) || IsAnyOrUnknown(property)) yield `('${knownKey}' in ${value})`
|
||||
} else {
|
||||
const expression = CreateExpression(property, references, memberExpression)
|
||||
yield Policy.IsExactOptionalProperty(value, knownKey, expression)
|
||||
@@ -322,28 +367,33 @@ export namespace TypeCompiler {
|
||||
yield `(Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key) || ${expression}))`
|
||||
}
|
||||
}
|
||||
function* TPromise(schema: Types.TPromise<any>, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromPromise(schema: TPromise, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof value === 'object' && typeof ${value}.then === 'function')`
|
||||
}
|
||||
function* TRecord(schema: Types.TRecord<any, any>, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromRecord(schema: TRecord, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield Policy.IsRecordLike(value)
|
||||
if (IsNumber(schema.minProperties)) yield `Object.getOwnPropertyNames(${value}).length >= ${schema.minProperties}`
|
||||
if (IsNumber(schema.maxProperties)) yield `Object.getOwnPropertyNames(${value}).length <= ${schema.maxProperties}`
|
||||
const [patternKey, patternSchema] = Object.entries(schema.patternProperties)[0]
|
||||
const variable = CreateVariable(`${new RegExp(patternKey)}`)
|
||||
const check1 = CreateExpression(patternSchema, references, 'value')
|
||||
const check2 = Types.TypeGuard.TSchema(schema.additionalProperties) ? CreateExpression(schema.additionalProperties, references, value) : schema.additionalProperties === false ? 'false' : 'true'
|
||||
const check2 = IsSchema(schema.additionalProperties) ? CreateExpression(schema.additionalProperties, references, value) : schema.additionalProperties === false ? 'false' : 'true'
|
||||
const expression = `(${variable}.test(key) ? ${check1} : ${check2})`
|
||||
yield `(Object.entries(${value}).every(([key, value]) => ${expression}))`
|
||||
}
|
||||
function* TRef(schema: Types.TRef<any>, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromRef(schema: TRef, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const target = Deref(schema, references)
|
||||
// Reference: If we have seen this reference before we can just yield and return the function call.
|
||||
// If this isn't the case we defer to visit to generate and set the function for subsequent passes.
|
||||
if (state.functions.has(schema.$ref)) return yield `${CreateFunctionName(schema.$ref)}(${value})`
|
||||
yield* Visit(target, references, value)
|
||||
}
|
||||
function* TString(schema: Types.TString, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromRegExp(schema: TRegExp, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const variable = CreateVariable(`${new RegExp(schema.source, schema.flags)};`)
|
||||
yield `(typeof ${value} === 'string')`
|
||||
yield `${variable}.test(${value})`
|
||||
}
|
||||
function* FromString(schema: TString, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'string')`
|
||||
if (IsNumber(schema.maxLength)) yield `${value}.length <= ${schema.maxLength}`
|
||||
if (IsNumber(schema.minLength)) yield `${value}.length >= ${schema.minLength}`
|
||||
@@ -355,19 +405,19 @@ export namespace TypeCompiler {
|
||||
yield `format('${schema.format}', ${value})`
|
||||
}
|
||||
}
|
||||
function* TSymbol(schema: Types.TSymbol, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromSymbol(schema: TSymbol, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'symbol')`
|
||||
}
|
||||
function* TTemplateLiteral(schema: Types.TTemplateLiteral, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromTemplateLiteral(schema: TTemplateLiteral, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `(typeof ${value} === 'string')`
|
||||
const variable = CreateVariable(`${new RegExp(schema.pattern)};`)
|
||||
yield `${variable}.test(${value})`
|
||||
}
|
||||
function* TThis(schema: Types.TThis, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromThis(schema: TThis, references: TSchema[], value: string): IterableIterator<string> {
|
||||
// Note: This types are assured to be hoisted prior to this call. Just yield the function.
|
||||
yield `${CreateFunctionName(schema.$ref)}(${value})`
|
||||
}
|
||||
function* TTuple(schema: Types.TTuple<any[]>, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromTuple(schema: TTuple, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `Array.isArray(${value})`
|
||||
if (schema.items === undefined) return yield `${value}.length === 0`
|
||||
yield `(${value}.length === ${schema.maxItems})`
|
||||
@@ -376,35 +426,35 @@ export namespace TypeCompiler {
|
||||
yield `${expression}`
|
||||
}
|
||||
}
|
||||
function* TUndefined(schema: Types.TUndefined, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromUndefined(schema: TUndefined, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `${value} === undefined`
|
||||
}
|
||||
function* TUnion(schema: Types.TUnion<any[]>, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
const expressions = schema.anyOf.map((schema: Types.TSchema) => CreateExpression(schema, references, value))
|
||||
function* FromUnion(schema: TUnion, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const expressions = schema.anyOf.map((schema: TSchema) => CreateExpression(schema, references, value))
|
||||
yield `(${expressions.join(' || ')})`
|
||||
}
|
||||
function* TUint8Array(schema: Types.TUint8Array, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromUint8Array(schema: TUint8Array, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield `${value} instanceof Uint8Array`
|
||||
if (IsNumber(schema.maxByteLength)) yield `(${value}.length <= ${schema.maxByteLength})`
|
||||
if (IsNumber(schema.minByteLength)) yield `(${value}.length >= ${schema.minByteLength})`
|
||||
}
|
||||
function* TUnknown(schema: Types.TUnknown, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromUnknown(schema: TUnknown, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield 'true'
|
||||
}
|
||||
function* TVoid(schema: Types.TVoid, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromVoid(schema: TVoid, references: TSchema[], value: string): IterableIterator<string> {
|
||||
yield Policy.IsVoidLike(value)
|
||||
}
|
||||
function* TKind(schema: Types.TSchema, references: Types.TSchema[], value: string): IterableIterator<string> {
|
||||
function* FromKind(schema: TSchema, references: TSchema[], value: string): IterableIterator<string> {
|
||||
const instance = state.instances.size
|
||||
state.instances.set(instance, schema)
|
||||
yield `kind('${schema[Types.Kind]}', ${instance}, ${value})`
|
||||
yield `kind('${schema[Kind]}', ${instance}, ${value})`
|
||||
}
|
||||
function* Visit<T extends Types.TSchema>(schema: T, references: Types.TSchema[], value: string, useHoisting: boolean = true): IterableIterator<string> {
|
||||
function* Visit(schema: TSchema, references: TSchema[], value: string, useHoisting: boolean = true): IterableIterator<string> {
|
||||
const references_ = IsString(schema.$id) ? [...references, schema] : references
|
||||
const schema_ = schema as any
|
||||
// ----------------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------
|
||||
// Hoisting
|
||||
// ----------------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------
|
||||
if (useHoisting && IsString(schema.$id)) {
|
||||
const functionName = CreateFunctionName(schema.$id)
|
||||
if (state.functions.has(functionName)) {
|
||||
@@ -415,86 +465,88 @@ export namespace TypeCompiler {
|
||||
return yield `${functionName}(${value})`
|
||||
}
|
||||
}
|
||||
switch (schema_[Types.Kind]) {
|
||||
switch (schema_[Kind]) {
|
||||
case 'Any':
|
||||
return yield* TAny(schema_, references_, value)
|
||||
return yield* FromAny(schema_, references_, value)
|
||||
case 'Array':
|
||||
return yield* TArray(schema_, references_, value)
|
||||
return yield* FromArray(schema_, references_, value)
|
||||
case 'AsyncIterator':
|
||||
return yield* TAsyncIterator(schema_, references_, value)
|
||||
return yield* FromAsyncIterator(schema_, references_, value)
|
||||
case 'BigInt':
|
||||
return yield* TBigInt(schema_, references_, value)
|
||||
return yield* FromBigInt(schema_, references_, value)
|
||||
case 'Boolean':
|
||||
return yield* TBoolean(schema_, references_, value)
|
||||
return yield* FromBoolean(schema_, references_, value)
|
||||
case 'Constructor':
|
||||
return yield* TConstructor(schema_, references_, value)
|
||||
return yield* FromConstructor(schema_, references_, value)
|
||||
case 'Date':
|
||||
return yield* TDate(schema_, references_, value)
|
||||
return yield* FromDate(schema_, references_, value)
|
||||
case 'Function':
|
||||
return yield* TFunction(schema_, references_, value)
|
||||
return yield* FromFunction(schema_, references_, value)
|
||||
case 'Integer':
|
||||
return yield* TInteger(schema_, references_, value)
|
||||
return yield* FromInteger(schema_, references_, value)
|
||||
case 'Intersect':
|
||||
return yield* TIntersect(schema_, references_, value)
|
||||
return yield* FromIntersect(schema_, references_, value)
|
||||
case 'Iterator':
|
||||
return yield* TIterator(schema_, references_, value)
|
||||
return yield* FromIterator(schema_, references_, value)
|
||||
case 'Literal':
|
||||
return yield* TLiteral(schema_, references_, value)
|
||||
return yield* FromLiteral(schema_, references_, value)
|
||||
case 'Never':
|
||||
return yield* TNever(schema_, references_, value)
|
||||
return yield* FromNever(schema_, references_, value)
|
||||
case 'Not':
|
||||
return yield* TNot(schema_, references_, value)
|
||||
return yield* FromNot(schema_, references_, value)
|
||||
case 'Null':
|
||||
return yield* TNull(schema_, references_, value)
|
||||
return yield* FromNull(schema_, references_, value)
|
||||
case 'Number':
|
||||
return yield* TNumber(schema_, references_, value)
|
||||
return yield* FromNumber(schema_, references_, value)
|
||||
case 'Object':
|
||||
return yield* TObject(schema_, references_, value)
|
||||
return yield* FromObject(schema_, references_, value)
|
||||
case 'Promise':
|
||||
return yield* TPromise(schema_, references_, value)
|
||||
return yield* FromPromise(schema_, references_, value)
|
||||
case 'Record':
|
||||
return yield* TRecord(schema_, references_, value)
|
||||
return yield* FromRecord(schema_, references_, value)
|
||||
case 'Ref':
|
||||
return yield* TRef(schema_, references_, value)
|
||||
return yield* FromRef(schema_, references_, value)
|
||||
case 'RegExp':
|
||||
return yield* FromRegExp(schema_, references_, value)
|
||||
case 'String':
|
||||
return yield* TString(schema_, references_, value)
|
||||
return yield* FromString(schema_, references_, value)
|
||||
case 'Symbol':
|
||||
return yield* TSymbol(schema_, references_, value)
|
||||
return yield* FromSymbol(schema_, references_, value)
|
||||
case 'TemplateLiteral':
|
||||
return yield* TTemplateLiteral(schema_, references_, value)
|
||||
return yield* FromTemplateLiteral(schema_, references_, value)
|
||||
case 'This':
|
||||
return yield* TThis(schema_, references_, value)
|
||||
return yield* FromThis(schema_, references_, value)
|
||||
case 'Tuple':
|
||||
return yield* TTuple(schema_, references_, value)
|
||||
return yield* FromTuple(schema_, references_, value)
|
||||
case 'Undefined':
|
||||
return yield* TUndefined(schema_, references_, value)
|
||||
return yield* FromUndefined(schema_, references_, value)
|
||||
case 'Union':
|
||||
return yield* TUnion(schema_, references_, value)
|
||||
return yield* FromUnion(schema_, references_, value)
|
||||
case 'Uint8Array':
|
||||
return yield* TUint8Array(schema_, references_, value)
|
||||
return yield* FromUint8Array(schema_, references_, value)
|
||||
case 'Unknown':
|
||||
return yield* TUnknown(schema_, references_, value)
|
||||
return yield* FromUnknown(schema_, references_, value)
|
||||
case 'Void':
|
||||
return yield* TVoid(schema_, references_, value)
|
||||
return yield* FromVoid(schema_, references_, value)
|
||||
default:
|
||||
if (!Types.TypeRegistry.Has(schema_[Types.Kind])) throw new TypeCompilerUnknownTypeError(schema)
|
||||
return yield* TKind(schema_, references_, value)
|
||||
if (!TypeRegistry.Has(schema_[Kind])) throw new TypeCompilerUnknownTypeError(schema)
|
||||
return yield* FromKind(schema_, references_, value)
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------
|
||||
// Compiler State
|
||||
// -------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
const state = {
|
||||
language: 'javascript', // target language
|
||||
functions: new Map<string, string>(), // local functions
|
||||
variables: new Map<string, string>(), // local variables
|
||||
instances: new Map<number, Types.TKind>() // exterior kind instances
|
||||
language: 'javascript', // target language
|
||||
functions: new Map<string, string>(), // local functions
|
||||
variables: new Map<string, string>(), // local variables
|
||||
instances: new Map<number, TSchema>() // exterior kind instances
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------
|
||||
// Compiler Factory
|
||||
// -------------------------------------------------------------------
|
||||
function CreateExpression(schema: Types.TSchema, references: Types.TSchema[], value: string, useHoisting: boolean = true): string {
|
||||
// ----------------------------------------------------------------
|
||||
function CreateExpression(schema: TSchema, references: TSchema[], value: string, useHoisting: boolean = true): string {
|
||||
return `(${[...Visit(schema, references, value, useHoisting)].join(' && ')})`
|
||||
}
|
||||
function CreateFunctionName($id: string) {
|
||||
@@ -505,7 +557,7 @@ export namespace TypeCompiler {
|
||||
state.variables.set(variableName, `const ${variableName} = ${expression}`)
|
||||
return variableName
|
||||
}
|
||||
function CreateFunction(name: string, schema: Types.TSchema, references: Types.TSchema[], value: string, useHoisting: boolean = true): string {
|
||||
function CreateFunction(name: string, schema: TSchema, references: TSchema[], value: string, useHoisting: boolean = true): string {
|
||||
const [newline, pad] = ['\n', (length: number) => ''.padStart(length, ' ')]
|
||||
const parameter = CreateParameter('value', 'any')
|
||||
const returns = CreateReturns('boolean')
|
||||
@@ -519,10 +571,10 @@ export namespace TypeCompiler {
|
||||
function CreateReturns(type: string) {
|
||||
return state.language === 'typescript' ? `: ${type}` : ''
|
||||
}
|
||||
// -------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------
|
||||
// Compile
|
||||
// -------------------------------------------------------------------
|
||||
function Build<T extends Types.TSchema>(schema: T, references: Types.TSchema[], options: TypeCompilerCodegenOptions): string {
|
||||
// ----------------------------------------------------------------
|
||||
function Build<T extends TSchema>(schema: T, references: TSchema[], options: TypeCompilerCodegenOptions): string {
|
||||
const functionCode = CreateFunction('check', schema, references, 'value') // will populate functions and variables
|
||||
const parameter = CreateParameter('value', 'any')
|
||||
const returns = CreateReturns('boolean')
|
||||
@@ -535,9 +587,9 @@ export namespace TypeCompiler {
|
||||
return [...variables, ...functions, checkFunction].join('\n')
|
||||
}
|
||||
/** Generates the code used to assert this type and returns it as a string */
|
||||
export function Code<T extends Types.TSchema>(schema: T, references: Types.TSchema[], options?: TypeCompilerCodegenOptions): string
|
||||
export function Code<T extends TSchema>(schema: T, references: TSchema[], options?: TypeCompilerCodegenOptions): string
|
||||
/** Generates the code used to assert this type and returns it as a string */
|
||||
export function Code<T extends Types.TSchema>(schema: T, options?: TypeCompilerCodegenOptions): string
|
||||
export function Code<T extends TSchema>(schema: T, options?: TypeCompilerCodegenOptions): string
|
||||
/** Generates the code used to assert this type and returns it as a string */
|
||||
export function Code(...args: any[]) {
|
||||
const defaults = { language: 'javascript' }
|
||||
@@ -554,24 +606,24 @@ export namespace TypeCompiler {
|
||||
state.variables.clear()
|
||||
state.functions.clear()
|
||||
state.instances.clear()
|
||||
if (!Types.TypeGuard.TSchema(schema)) throw new TypeCompilerTypeGuardError(schema)
|
||||
for (const schema of references) if (!Types.TypeGuard.TSchema(schema)) throw new TypeCompilerTypeGuardError(schema)
|
||||
if (!IsSchema(schema)) throw new TypeCompilerTypeGuardError(schema)
|
||||
for (const schema of references) if (!IsSchema(schema)) throw new TypeCompilerTypeGuardError(schema)
|
||||
return Build(schema, references, options)
|
||||
}
|
||||
/** Compiles a TypeBox type for optimal runtime type checking. Types must be valid TypeBox types of TSchema */
|
||||
export function Compile<T extends Types.TSchema>(schema: T, references: Types.TSchema[] = []): TypeCheck<T> {
|
||||
export function Compile<T extends TSchema>(schema: T, references: TSchema[] = []): TypeCheck<T> {
|
||||
const generatedCode = Code(schema, references, { language: 'javascript' })
|
||||
const compiledFunction = globalThis.Function('kind', 'format', 'hash', generatedCode)
|
||||
const instances = new Map(state.instances)
|
||||
function typeRegistryFunction(kind: string, instance: number, value: unknown) {
|
||||
if (!Types.TypeRegistry.Has(kind) || !instances.has(instance)) return false
|
||||
const checkFunc = Types.TypeRegistry.Get(kind)!
|
||||
if (!TypeRegistry.Has(kind) || !instances.has(instance)) return false
|
||||
const checkFunc = TypeRegistry.Get(kind)!
|
||||
const schema = instances.get(instance)!
|
||||
return checkFunc(schema, value)
|
||||
}
|
||||
function formatRegistryFunction(format: string, value: string) {
|
||||
if (!Types.FormatRegistry.Has(format)) return false
|
||||
const checkFunc = Types.FormatRegistry.Get(format)!
|
||||
if (!FormatRegistry.Has(format)) return false
|
||||
const checkFunc = FormatRegistry.Get(format)!
|
||||
return checkFunc(value)
|
||||
}
|
||||
function hashFunction(value: unknown) {
|
||||
|
||||
@@ -27,4 +27,4 @@ THE SOFTWARE.
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export { ValueError, ValueErrorType, ValueErrorIterator } from '../errors/index'
|
||||
export * from './compiler'
|
||||
export { TypeCompiler, TypeCheck, type TypeCompilerCodegenOptions, type TypeCompilerLanguageOption, TypeCompilerTypeGuardError, TypeCompilerUnknownTypeError } from './compiler'
|
||||
|
||||
@@ -26,15 +26,72 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { IsArray, IsUint8Array, IsDate, IsPromise, IsFunction, IsAsyncIterator, IsIterator, IsBoolean, IsNumber, IsBigInt, IsString, IsSymbol, IsInteger, IsNull, IsUndefined } from '../value/guard'
|
||||
import { TypeSystemPolicy, TypeSystemErrorFunction } from '../system/system'
|
||||
import { Deref } from '../value/deref'
|
||||
import { Hash } from '../value/hash'
|
||||
import * as Types from '../typebox'
|
||||
import { TypeSystemPolicy } from '../system/index'
|
||||
import { KeyOfPattern } from '../type/keyof/index'
|
||||
import { TypeRegistry, FormatRegistry } from '../type/registry/index'
|
||||
import { ExtendsUndefinedCheck } from '../type/extends/extends-undefined'
|
||||
import { GetErrorFunction } from './function'
|
||||
import { TypeBoxError } from '../type/error/index'
|
||||
import { Deref } from '../value/deref/index'
|
||||
import { Hash } from '../value/hash/index'
|
||||
import { Kind } from '../type/symbols/index'
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
import type { TSchema } from '../type/schema/index'
|
||||
import type { TAsyncIterator } from '../type/async-iterator/index'
|
||||
import type { TAny } from '../type/any/index'
|
||||
import type { TArray } from '../type/array/index'
|
||||
import type { TBigInt } from '../type/bigint/index'
|
||||
import type { TBoolean } from '../type/boolean/index'
|
||||
import type { TDate } from '../type/date/index'
|
||||
import type { TConstructor } from '../type/constructor/index'
|
||||
import type { TFunction } from '../type/function/index'
|
||||
import type { TInteger } from '../type/integer/index'
|
||||
import type { TIntersect } from '../type/intersect/index'
|
||||
import type { TIterator } from '../type/iterator/index'
|
||||
import type { TLiteral } from '../type/literal/index'
|
||||
import { Never, type TNever } from '../type/never/index'
|
||||
import type { TNot } from '../type/not/index'
|
||||
import type { TNull } from '../type/null/index'
|
||||
import type { TNumber } from '../type/number/index'
|
||||
import type { TObject } from '../type/object/index'
|
||||
import type { TPromise } from '../type/promise/index'
|
||||
import type { TRecord } from '../type/record/index'
|
||||
import type { TRef } from '../type/ref/index'
|
||||
import type { TRegExp } from '../type/regexp/index'
|
||||
import type { TTemplateLiteral } from '../type/template-literal/index'
|
||||
import type { TThis } from '../type/recursive/index'
|
||||
import type { TTuple } from '../type/tuple/index'
|
||||
import type { TUnion } from '../type/union/index'
|
||||
import type { TUnknown } from '../type/unknown/index'
|
||||
import type { TString } from '../type/string/index'
|
||||
import type { TSymbol } from '../type/symbol/index'
|
||||
import type { TUndefined } from '../type/undefined/index'
|
||||
import type { TUint8Array } from '../type/uint8array/index'
|
||||
import type { TVoid } from '../type/void/index'
|
||||
// ------------------------------------------------------------------
|
||||
// ValueGuard
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
import {
|
||||
IsArray,
|
||||
IsUint8Array,
|
||||
IsDate,
|
||||
IsPromise,
|
||||
IsFunction,
|
||||
IsAsyncIterator,
|
||||
IsIterator,
|
||||
IsBoolean,
|
||||
IsNumber,
|
||||
IsBigInt,
|
||||
IsString,
|
||||
IsSymbol,
|
||||
IsInteger,
|
||||
IsNull,
|
||||
IsUndefined
|
||||
} from '../value/guard/index'
|
||||
// ------------------------------------------------------------------
|
||||
// ValueErrorType
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
export enum ValueErrorType {
|
||||
ArrayContains,
|
||||
ArrayMaxContains,
|
||||
@@ -84,6 +141,7 @@ export enum ValueErrorType {
|
||||
ObjectRequiredProperty,
|
||||
Object,
|
||||
Promise,
|
||||
RegExp,
|
||||
StringFormatUnknown,
|
||||
StringFormat,
|
||||
StringMaxLength,
|
||||
@@ -100,39 +158,39 @@ export enum ValueErrorType {
|
||||
Union,
|
||||
Void,
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// ValueError
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
export interface ValueError {
|
||||
type: ValueErrorType
|
||||
schema: Types.TSchema
|
||||
schema: TSchema
|
||||
path: string
|
||||
value: unknown
|
||||
message: string
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// ValueErrors
|
||||
// --------------------------------------------------------------------------
|
||||
export class ValueErrorsUnknownTypeError extends Types.TypeBoxError {
|
||||
constructor(public readonly schema: Types.TSchema) {
|
||||
// ------------------------------------------------------------------
|
||||
export class ValueErrorsUnknownTypeError extends TypeBoxError {
|
||||
constructor(public readonly schema: TSchema) {
|
||||
super('Unknown type')
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// EscapeKey
|
||||
// --------------------------------------------------------------------------
|
||||
export function EscapeKey(key: string): string {
|
||||
// ------------------------------------------------------------------
|
||||
function EscapeKey(key: string): string {
|
||||
return key.replace(/~/g, '~0').replace(/\//g, '~1') // RFC6901 Path
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// Guards
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
function IsDefined<T>(value: unknown): value is T {
|
||||
return value !== undefined
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// ValueErrorIterator
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
export class ValueErrorIterator {
|
||||
constructor(private readonly iterator: IterableIterator<ValueError>) {}
|
||||
public [Symbol.iterator]() {
|
||||
@@ -147,14 +205,14 @@ export class ValueErrorIterator {
|
||||
// --------------------------------------------------------------------------
|
||||
// Create
|
||||
// --------------------------------------------------------------------------
|
||||
function Create(type: ValueErrorType, schema: Types.TSchema, path: string, value: unknown): ValueError {
|
||||
return { type, schema, path, value, message: TypeSystemErrorFunction.Get()(schema, type) }
|
||||
function Create(errorType: ValueErrorType, schema: TSchema, path: string, value: unknown): ValueError {
|
||||
return { type: errorType, schema, path, value, message: GetErrorFunction()({ errorType, path, schema, value }) }
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// Types
|
||||
// --------------------------------------------------------------------------
|
||||
function* TAny(schema: Types.TAny, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {}
|
||||
function* TArray(schema: Types.TArray, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromAny(schema: TAny, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {}
|
||||
function* FromArray(schema: TArray, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsArray(value)) {
|
||||
return yield Create(ValueErrorType.Array, schema, path, value)
|
||||
}
|
||||
@@ -175,7 +233,7 @@ function* TArray(schema: Types.TArray, references: Types.TSchema[], path: string
|
||||
if (!(IsDefined(schema.contains) || IsDefined(schema.minContains) || IsDefined(schema.maxContains))) {
|
||||
return
|
||||
}
|
||||
const containsSchema = IsDefined<Types.TSchema>(schema.contains) ? schema.contains : Types.Type.Never()
|
||||
const containsSchema = IsDefined<TSchema>(schema.contains) ? schema.contains : Never()
|
||||
const containsCount = value.reduce((acc: number, value, index) => (Visit(containsSchema, references, `${path}${index}`, value).next().done === true ? acc + 1 : acc), 0)
|
||||
if (containsCount === 0) {
|
||||
yield Create(ValueErrorType.ArrayContains, schema, path, value)
|
||||
@@ -187,10 +245,10 @@ function* TArray(schema: Types.TArray, references: Types.TSchema[], path: string
|
||||
yield Create(ValueErrorType.ArrayMaxContains, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* TAsyncIterator(schema: Types.TAsyncIterator, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromAsyncIterator(schema: TAsyncIterator, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsAsyncIterator(value)) yield Create(ValueErrorType.AsyncIterator, schema, path, value)
|
||||
}
|
||||
function* TBigInt(schema: Types.TBigInt, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromBigInt(schema: TBigInt, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsBigInt(value)) return yield Create(ValueErrorType.BigInt, schema, path, value)
|
||||
if (IsDefined<bigint>(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) {
|
||||
yield Create(ValueErrorType.BigIntExclusiveMaximum, schema, path, value)
|
||||
@@ -208,13 +266,13 @@ function* TBigInt(schema: Types.TBigInt, references: Types.TSchema[], path: stri
|
||||
yield Create(ValueErrorType.BigIntMultipleOf, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* TBoolean(schema: Types.TBoolean, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromBoolean(schema: TBoolean, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsBoolean(value)) yield Create(ValueErrorType.Boolean, schema, path, value)
|
||||
}
|
||||
function* TConstructor(schema: Types.TConstructor, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromConstructor(schema: TConstructor, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
yield* Visit(schema.returns, references, path, value.prototype)
|
||||
}
|
||||
function* TDate(schema: Types.TDate, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromDate(schema: TDate, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsDate(value)) return yield Create(ValueErrorType.Date, schema, path, value)
|
||||
if (IsDefined<number>(schema.exclusiveMaximumTimestamp) && !(value.getTime() < schema.exclusiveMaximumTimestamp)) {
|
||||
yield Create(ValueErrorType.DateExclusiveMaximumTimestamp, schema, path, value)
|
||||
@@ -232,10 +290,10 @@ function* TDate(schema: Types.TDate, references: Types.TSchema[], path: string,
|
||||
yield Create(ValueErrorType.DateMultipleOfTimestamp, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* TFunction(schema: Types.TFunction, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromFunction(schema: TFunction, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsFunction(value)) yield Create(ValueErrorType.Function, schema, path, value)
|
||||
}
|
||||
function* TInteger(schema: Types.TInteger, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromInteger(schema: TInteger, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsInteger(value)) return yield Create(ValueErrorType.Integer, schema, path, value)
|
||||
if (IsDefined<number>(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) {
|
||||
yield Create(ValueErrorType.IntegerExclusiveMaximum, schema, path, value)
|
||||
@@ -253,7 +311,7 @@ function* TInteger(schema: Types.TInteger, references: Types.TSchema[], path: st
|
||||
yield Create(ValueErrorType.IntegerMultipleOf, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* TIntersect(schema: Types.TIntersect, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromIntersect(schema: TIntersect, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
for (const inner of schema.allOf) {
|
||||
const next = Visit(inner, references, path, value).next()
|
||||
if (!next.done) {
|
||||
@@ -262,7 +320,7 @@ function* TIntersect(schema: Types.TIntersect, references: Types.TSchema[], path
|
||||
}
|
||||
}
|
||||
if (schema.unevaluatedProperties === false) {
|
||||
const keyCheck = new RegExp(Types.KeyResolver.ResolvePattern(schema))
|
||||
const keyCheck = new RegExp(KeyOfPattern(schema))
|
||||
for (const valueKey of Object.getOwnPropertyNames(value)) {
|
||||
if (!keyCheck.test(valueKey)) {
|
||||
yield Create(ValueErrorType.IntersectUnevaluatedProperties, schema, `${path}/${valueKey}`, value)
|
||||
@@ -270,7 +328,7 @@ function* TIntersect(schema: Types.TIntersect, references: Types.TSchema[], path
|
||||
}
|
||||
}
|
||||
if (typeof schema.unevaluatedProperties === 'object') {
|
||||
const keyCheck = new RegExp(Types.KeyResolver.ResolvePattern(schema))
|
||||
const keyCheck = new RegExp(KeyOfPattern(schema))
|
||||
for (const valueKey of Object.getOwnPropertyNames(value)) {
|
||||
if (!keyCheck.test(valueKey)) {
|
||||
const next = Visit(schema.unevaluatedProperties, references, `${path}/${valueKey}`, value[valueKey]).next()
|
||||
@@ -279,22 +337,22 @@ function* TIntersect(schema: Types.TIntersect, references: Types.TSchema[], path
|
||||
}
|
||||
}
|
||||
}
|
||||
function* TIterator(schema: Types.TIterator, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromIterator(schema: TIterator, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsIterator(value)) yield Create(ValueErrorType.Iterator, schema, path, value)
|
||||
}
|
||||
function* TLiteral(schema: Types.TLiteral, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromLiteral(schema: TLiteral, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!(value === schema.const)) yield Create(ValueErrorType.Literal, schema, path, value)
|
||||
}
|
||||
function* TNever(schema: Types.TNever, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromNever(schema: TNever, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
yield Create(ValueErrorType.Never, schema, path, value)
|
||||
}
|
||||
function* TNot(schema: Types.TNot, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromNot(schema: TNot, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (Visit(schema.not, references, path, value).next().done === true) yield Create(ValueErrorType.Not, schema, path, value)
|
||||
}
|
||||
function* TNull(schema: Types.TNull, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromNull(schema: TNull, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsNull(value)) yield Create(ValueErrorType.Null, schema, path, value)
|
||||
}
|
||||
function* TNumber(schema: Types.TNumber, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromNumber(schema: TNumber, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!TypeSystemPolicy.IsNumberLike(value)) return yield Create(ValueErrorType.Number, schema, path, value)
|
||||
if (IsDefined<number>(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) {
|
||||
yield Create(ValueErrorType.NumberExclusiveMaximum, schema, path, value)
|
||||
@@ -312,7 +370,7 @@ function* TNumber(schema: Types.TNumber, references: Types.TSchema[], path: stri
|
||||
yield Create(ValueErrorType.NumberMultipleOf, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* TObject(schema: Types.TObject, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromObject(schema: TObject, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!TypeSystemPolicy.IsObjectLike(value)) return yield Create(ValueErrorType.Object, schema, path, value)
|
||||
if (IsDefined<number>(schema.minProperties) && !(Object.getOwnPropertyNames(value).length >= schema.minProperties)) {
|
||||
yield Create(ValueErrorType.ObjectMinProperties, schema, path, value)
|
||||
@@ -337,14 +395,14 @@ function* TObject(schema: Types.TObject, references: Types.TSchema[], path: stri
|
||||
if (typeof schema.additionalProperties === 'object') {
|
||||
for (const valueKey of unknownKeys) {
|
||||
if (knownKeys.includes(valueKey)) continue
|
||||
yield* Visit(schema.additionalProperties as Types.TSchema, references, `${path}/${EscapeKey(valueKey)}`, value[valueKey])
|
||||
yield* Visit(schema.additionalProperties as TSchema, references, `${path}/${EscapeKey(valueKey)}`, value[valueKey])
|
||||
}
|
||||
}
|
||||
for (const knownKey of knownKeys) {
|
||||
const property = schema.properties[knownKey]
|
||||
if (schema.required && schema.required.includes(knownKey)) {
|
||||
yield* Visit(property, references, `${path}/${EscapeKey(knownKey)}`, value[knownKey])
|
||||
if (Types.ExtendsUndefined.Check(schema) && !(knownKey in value)) {
|
||||
if (ExtendsUndefinedCheck(schema) && !(knownKey in value)) {
|
||||
yield Create(ValueErrorType.ObjectRequiredProperty, property, `${path}/${EscapeKey(knownKey)}`, undefined)
|
||||
}
|
||||
} else {
|
||||
@@ -354,10 +412,10 @@ function* TObject(schema: Types.TObject, references: Types.TSchema[], path: stri
|
||||
}
|
||||
}
|
||||
}
|
||||
function* TPromise(schema: Types.TPromise, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromPromise(schema: TPromise, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsPromise(value)) yield Create(ValueErrorType.Promise, schema, path, value)
|
||||
}
|
||||
function* TRecord(schema: Types.TRecord, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromRecord(schema: TRecord, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!TypeSystemPolicy.IsRecordLike(value)) return yield Create(ValueErrorType.Object, schema, path, value)
|
||||
if (IsDefined<number>(schema.minProperties) && !(Object.getOwnPropertyNames(value).length >= schema.minProperties)) {
|
||||
yield Create(ValueErrorType.ObjectMinProperties, schema, path, value)
|
||||
@@ -372,7 +430,7 @@ function* TRecord(schema: Types.TRecord, references: Types.TSchema[], path: stri
|
||||
}
|
||||
if (typeof schema.additionalProperties === 'object') {
|
||||
for (const [propertyKey, propertyValue] of Object.entries(value)) {
|
||||
if (!regex.test(propertyKey)) yield* Visit(schema.additionalProperties as Types.TSchema, references, `${path}/${EscapeKey(propertyKey)}`, propertyValue)
|
||||
if (!regex.test(propertyKey)) yield* Visit(schema.additionalProperties as TSchema, references, `${path}/${EscapeKey(propertyKey)}`, propertyValue)
|
||||
}
|
||||
}
|
||||
if (schema.additionalProperties === false) {
|
||||
@@ -382,10 +440,16 @@ function* TRecord(schema: Types.TRecord, references: Types.TSchema[], path: stri
|
||||
}
|
||||
}
|
||||
}
|
||||
function* TRef(schema: Types.TRef<any>, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromRef(schema: TRef, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
yield* Visit(Deref(schema, references), references, path, value)
|
||||
}
|
||||
function* TString(schema: Types.TString, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromRegExp(schema: TRegExp, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
const regex = new RegExp(schema.source, schema.flags)
|
||||
if (!regex.test(value)) {
|
||||
return yield Create(ValueErrorType.RegExp, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* FromString(schema: TString, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsString(value)) return yield Create(ValueErrorType.String, schema, path, value)
|
||||
if (IsDefined<number>(schema.minLength) && !(value.length >= schema.minLength)) {
|
||||
yield Create(ValueErrorType.StringMinLength, schema, path, value)
|
||||
@@ -400,30 +464,30 @@ function* TString(schema: Types.TString, references: Types.TSchema[], path: stri
|
||||
}
|
||||
}
|
||||
if (IsString(schema.format)) {
|
||||
if (!Types.FormatRegistry.Has(schema.format)) {
|
||||
if (!FormatRegistry.Has(schema.format)) {
|
||||
yield Create(ValueErrorType.StringFormatUnknown, schema, path, value)
|
||||
} else {
|
||||
const format = Types.FormatRegistry.Get(schema.format)!
|
||||
const format = FormatRegistry.Get(schema.format)!
|
||||
if (!format(value)) {
|
||||
yield Create(ValueErrorType.StringFormat, schema, path, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function* TSymbol(schema: Types.TSymbol, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromSymbol(schema: TSymbol, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsSymbol(value)) yield Create(ValueErrorType.Symbol, schema, path, value)
|
||||
}
|
||||
function* TTemplateLiteral(schema: Types.TTemplateLiteral, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromTemplateLiteral(schema: TTemplateLiteral, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsString(value)) return yield Create(ValueErrorType.String, schema, path, value)
|
||||
const regex = new RegExp(schema.pattern)
|
||||
if (!regex.test(value)) {
|
||||
yield Create(ValueErrorType.StringPattern, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* TThis(schema: Types.TThis, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromThis(schema: TThis, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
yield* Visit(Deref(schema, references), references, path, value)
|
||||
}
|
||||
function* TTuple(schema: Types.TTuple<any[]>, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromTuple(schema: TTuple<any[]>, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsArray(value)) return yield Create(ValueErrorType.Tuple, schema, path, value)
|
||||
if (schema.items === undefined && !(value.length === 0)) {
|
||||
return yield Create(ValueErrorType.TupleLength, schema, path, value)
|
||||
@@ -438,10 +502,10 @@ function* TTuple(schema: Types.TTuple<any[]>, references: Types.TSchema[], path:
|
||||
yield* Visit(schema.items[i], references, `${path}/${i}`, value[i])
|
||||
}
|
||||
}
|
||||
function* TUndefined(schema: Types.TUndefined, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromUndefined(schema: TUndefined, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsUndefined(value)) yield Create(ValueErrorType.Undefined, schema, path, value)
|
||||
}
|
||||
function* TUnion(schema: Types.TUnion, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromUnion(schema: TUnion, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
let count = 0
|
||||
for (const subschema of schema.anyOf) {
|
||||
const errors = [...Visit(subschema, references, path, value)]
|
||||
@@ -452,7 +516,7 @@ function* TUnion(schema: Types.TUnion, references: Types.TSchema[], path: string
|
||||
yield Create(ValueErrorType.Union, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* TUint8Array(schema: Types.TUint8Array, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromUint8Array(schema: TUint8Array, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!IsUint8Array(value)) return yield Create(ValueErrorType.Uint8Array, schema, path, value)
|
||||
if (IsDefined<number>(schema.maxByteLength) && !(value.length <= schema.maxByteLength)) {
|
||||
yield Create(ValueErrorType.Uint8ArrayMaxByteLength, schema, path, value)
|
||||
@@ -461,87 +525,89 @@ function* TUint8Array(schema: Types.TUint8Array, references: Types.TSchema[], pa
|
||||
yield Create(ValueErrorType.Uint8ArrayMinByteLength, schema, path, value)
|
||||
}
|
||||
}
|
||||
function* TUnknown(schema: Types.TUnknown, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {}
|
||||
function* TVoid(schema: Types.TVoid, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* FromUnknown(schema: TUnknown, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {}
|
||||
function* FromVoid(schema: TVoid, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
if (!TypeSystemPolicy.IsVoidLike(value)) yield Create(ValueErrorType.Void, schema, path, value)
|
||||
}
|
||||
function* TKind(schema: Types.TSchema, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
const check = Types.TypeRegistry.Get(schema[Types.Kind])!
|
||||
function* FromKind(schema: TSchema, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
const check = TypeRegistry.Get(schema[Kind])!
|
||||
if (!check(schema, value)) yield Create(ValueErrorType.Kind, schema, path, value)
|
||||
}
|
||||
function* Visit<T extends Types.TSchema>(schema: T, references: Types.TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
function* Visit<T extends TSchema>(schema: T, references: TSchema[], path: string, value: any): IterableIterator<ValueError> {
|
||||
const references_ = IsDefined<string>(schema.$id) ? [...references, schema] : references
|
||||
const schema_ = schema as any
|
||||
switch (schema_[Types.Kind]) {
|
||||
switch (schema_[Kind]) {
|
||||
case 'Any':
|
||||
return yield* TAny(schema_, references_, path, value)
|
||||
return yield* FromAny(schema_, references_, path, value)
|
||||
case 'Array':
|
||||
return yield* TArray(schema_, references_, path, value)
|
||||
return yield* FromArray(schema_, references_, path, value)
|
||||
case 'AsyncIterator':
|
||||
return yield* TAsyncIterator(schema_, references_, path, value)
|
||||
return yield* FromAsyncIterator(schema_, references_, path, value)
|
||||
case 'BigInt':
|
||||
return yield* TBigInt(schema_, references_, path, value)
|
||||
return yield* FromBigInt(schema_, references_, path, value)
|
||||
case 'Boolean':
|
||||
return yield* TBoolean(schema_, references_, path, value)
|
||||
return yield* FromBoolean(schema_, references_, path, value)
|
||||
case 'Constructor':
|
||||
return yield* TConstructor(schema_, references_, path, value)
|
||||
return yield* FromConstructor(schema_, references_, path, value)
|
||||
case 'Date':
|
||||
return yield* TDate(schema_, references_, path, value)
|
||||
return yield* FromDate(schema_, references_, path, value)
|
||||
case 'Function':
|
||||
return yield* TFunction(schema_, references_, path, value)
|
||||
return yield* FromFunction(schema_, references_, path, value)
|
||||
case 'Integer':
|
||||
return yield* TInteger(schema_, references_, path, value)
|
||||
return yield* FromInteger(schema_, references_, path, value)
|
||||
case 'Intersect':
|
||||
return yield* TIntersect(schema_, references_, path, value)
|
||||
return yield* FromIntersect(schema_, references_, path, value)
|
||||
case 'Iterator':
|
||||
return yield* TIterator(schema_, references_, path, value)
|
||||
return yield* FromIterator(schema_, references_, path, value)
|
||||
case 'Literal':
|
||||
return yield* TLiteral(schema_, references_, path, value)
|
||||
return yield* FromLiteral(schema_, references_, path, value)
|
||||
case 'Never':
|
||||
return yield* TNever(schema_, references_, path, value)
|
||||
return yield* FromNever(schema_, references_, path, value)
|
||||
case 'Not':
|
||||
return yield* TNot(schema_, references_, path, value)
|
||||
return yield* FromNot(schema_, references_, path, value)
|
||||
case 'Null':
|
||||
return yield* TNull(schema_, references_, path, value)
|
||||
return yield* FromNull(schema_, references_, path, value)
|
||||
case 'Number':
|
||||
return yield* TNumber(schema_, references_, path, value)
|
||||
return yield* FromNumber(schema_, references_, path, value)
|
||||
case 'Object':
|
||||
return yield* TObject(schema_, references_, path, value)
|
||||
return yield* FromObject(schema_, references_, path, value)
|
||||
case 'Promise':
|
||||
return yield* TPromise(schema_, references_, path, value)
|
||||
return yield* FromPromise(schema_, references_, path, value)
|
||||
case 'Record':
|
||||
return yield* TRecord(schema_, references_, path, value)
|
||||
return yield* FromRecord(schema_, references_, path, value)
|
||||
case 'Ref':
|
||||
return yield* TRef(schema_, references_, path, value)
|
||||
return yield* FromRef(schema_, references_, path, value)
|
||||
case 'RegExp':
|
||||
return yield* FromRegExp(schema_, references_, path, value)
|
||||
case 'String':
|
||||
return yield* TString(schema_, references_, path, value)
|
||||
return yield* FromString(schema_, references_, path, value)
|
||||
case 'Symbol':
|
||||
return yield* TSymbol(schema_, references_, path, value)
|
||||
return yield* FromSymbol(schema_, references_, path, value)
|
||||
case 'TemplateLiteral':
|
||||
return yield* TTemplateLiteral(schema_, references_, path, value)
|
||||
return yield* FromTemplateLiteral(schema_, references_, path, value)
|
||||
case 'This':
|
||||
return yield* TThis(schema_, references_, path, value)
|
||||
return yield* FromThis(schema_, references_, path, value)
|
||||
case 'Tuple':
|
||||
return yield* TTuple(schema_, references_, path, value)
|
||||
return yield* FromTuple(schema_, references_, path, value)
|
||||
case 'Undefined':
|
||||
return yield* TUndefined(schema_, references_, path, value)
|
||||
return yield* FromUndefined(schema_, references_, path, value)
|
||||
case 'Union':
|
||||
return yield* TUnion(schema_, references_, path, value)
|
||||
return yield* FromUnion(schema_, references_, path, value)
|
||||
case 'Uint8Array':
|
||||
return yield* TUint8Array(schema_, references_, path, value)
|
||||
return yield* FromUint8Array(schema_, references_, path, value)
|
||||
case 'Unknown':
|
||||
return yield* TUnknown(schema_, references_, path, value)
|
||||
return yield* FromUnknown(schema_, references_, path, value)
|
||||
case 'Void':
|
||||
return yield* TVoid(schema_, references_, path, value)
|
||||
return yield* FromVoid(schema_, references_, path, value)
|
||||
default:
|
||||
if (!Types.TypeRegistry.Has(schema_[Types.Kind])) throw new ValueErrorsUnknownTypeError(schema)
|
||||
return yield* TKind(schema_, references_, path, value)
|
||||
if (!TypeRegistry.Has(schema_[Kind])) throw new ValueErrorsUnknownTypeError(schema)
|
||||
return yield* FromKind(schema_, references_, path, value)
|
||||
}
|
||||
}
|
||||
/** Returns an iterator for each error in this value. */
|
||||
export function Errors<T extends Types.TSchema>(schema: T, references: Types.TSchema[], value: unknown): ValueErrorIterator
|
||||
export function Errors<T extends TSchema>(schema: T, references: TSchema[], value: unknown): ValueErrorIterator
|
||||
/** Returns an iterator for each error in this value. */
|
||||
export function Errors<T extends Types.TSchema>(schema: T, value: unknown): ValueErrorIterator
|
||||
export function Errors<T extends TSchema>(schema: T, value: unknown): ValueErrorIterator
|
||||
/** Returns an iterator for each error in this value. */
|
||||
export function Errors(...args: any[]) {
|
||||
const iterator = args.length === 3 ? Visit(args[0], args[1], '', args[2]) : Visit(args[0], [], '', args[1])
|
||||
|
||||
193
src/errors/function.ts
Normal file
193
src/errors/function.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/system
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema } from '../type/schema/index'
|
||||
import { Kind } from '../type/symbols/index'
|
||||
import { ValueErrorType } from './errors'
|
||||
|
||||
/** Creates an error message using en-US as the default locale */
|
||||
export function DefaultErrorFunction(error: ErrorFunctionParameter) {
|
||||
switch (error.errorType) {
|
||||
case ValueErrorType.ArrayContains:
|
||||
return 'Expected array to contain at least one matching value'
|
||||
case ValueErrorType.ArrayMaxContains:
|
||||
return `Expected array to contain no more than ${error.schema.maxContains} matching values`
|
||||
case ValueErrorType.ArrayMinContains:
|
||||
return `Expected array to contain at least ${error.schema.minContains} matching values`
|
||||
case ValueErrorType.ArrayMaxItems:
|
||||
return `Expected array length to be less or equal to ${error.schema.maxItems}`
|
||||
case ValueErrorType.ArrayMinItems:
|
||||
return `Expected array length to be greater or equal to ${error.schema.minItems}`
|
||||
case ValueErrorType.ArrayUniqueItems:
|
||||
return 'Expected array elements to be unique'
|
||||
case ValueErrorType.Array:
|
||||
return 'Expected array'
|
||||
case ValueErrorType.AsyncIterator:
|
||||
return 'Expected AsyncIterator'
|
||||
case ValueErrorType.BigIntExclusiveMaximum:
|
||||
return `Expected bigint to be less than ${error.schema.exclusiveMaximum}`
|
||||
case ValueErrorType.BigIntExclusiveMinimum:
|
||||
return `Expected bigint to be greater than ${error.schema.exclusiveMinimum}`
|
||||
case ValueErrorType.BigIntMaximum:
|
||||
return `Expected bigint to be less or equal to ${error.schema.maximum}`
|
||||
case ValueErrorType.BigIntMinimum:
|
||||
return `Expected bigint to be greater or equal to ${error.schema.minimum}`
|
||||
case ValueErrorType.BigIntMultipleOf:
|
||||
return `Expected bigint to be a multiple of ${error.schema.multipleOf}`
|
||||
case ValueErrorType.BigInt:
|
||||
return 'Expected bigint'
|
||||
case ValueErrorType.Boolean:
|
||||
return 'Expected boolean'
|
||||
case ValueErrorType.DateExclusiveMinimumTimestamp:
|
||||
return `Expected Date timestamp to be greater than ${error.schema.exclusiveMinimumTimestamp}`
|
||||
case ValueErrorType.DateExclusiveMaximumTimestamp:
|
||||
return `Expected Date timestamp to be less than ${error.schema.exclusiveMaximumTimestamp}`
|
||||
case ValueErrorType.DateMinimumTimestamp:
|
||||
return `Expected Date timestamp to be greater or equal to ${error.schema.minimumTimestamp}`
|
||||
case ValueErrorType.DateMaximumTimestamp:
|
||||
return `Expected Date timestamp to be less or equal to ${error.schema.maximumTimestamp}`
|
||||
case ValueErrorType.DateMultipleOfTimestamp:
|
||||
return `Expected Date timestamp to be a multiple of ${error.schema.multipleOfTimestamp}`
|
||||
case ValueErrorType.Date:
|
||||
return 'Expected Date'
|
||||
case ValueErrorType.Function:
|
||||
return 'Expected function'
|
||||
case ValueErrorType.IntegerExclusiveMaximum:
|
||||
return `Expected integer to be less than ${error.schema.exclusiveMaximum}`
|
||||
case ValueErrorType.IntegerExclusiveMinimum:
|
||||
return `Expected integer to be greater than ${error.schema.exclusiveMinimum}`
|
||||
case ValueErrorType.IntegerMaximum:
|
||||
return `Expected integer to be less or equal to ${error.schema.maximum}`
|
||||
case ValueErrorType.IntegerMinimum:
|
||||
return `Expected integer to be greater or equal to ${error.schema.minimum}`
|
||||
case ValueErrorType.IntegerMultipleOf:
|
||||
return `Expected integer to be a multiple of ${error.schema.multipleOf}`
|
||||
case ValueErrorType.Integer:
|
||||
return 'Expected integer'
|
||||
case ValueErrorType.IntersectUnevaluatedProperties:
|
||||
return 'Unexpected property'
|
||||
case ValueErrorType.Intersect:
|
||||
return 'Expected all values to match'
|
||||
case ValueErrorType.Iterator:
|
||||
return 'Expected Iterator'
|
||||
case ValueErrorType.Literal:
|
||||
return `Expected ${typeof error.schema.const === 'string' ? `'${error.schema.const}'` : error.schema.const}`
|
||||
case ValueErrorType.Never:
|
||||
return 'Never'
|
||||
case ValueErrorType.Not:
|
||||
return 'Value should not match'
|
||||
case ValueErrorType.Null:
|
||||
return 'Expected null'
|
||||
case ValueErrorType.NumberExclusiveMaximum:
|
||||
return `Expected number to be less than ${error.schema.exclusiveMaximum}`
|
||||
case ValueErrorType.NumberExclusiveMinimum:
|
||||
return `Expected number to be greater than ${error.schema.exclusiveMinimum}`
|
||||
case ValueErrorType.NumberMaximum:
|
||||
return `Expected number to be less or equal to ${error.schema.maximum}`
|
||||
case ValueErrorType.NumberMinimum:
|
||||
return `Expected number to be greater or equal to ${error.schema.minimum}`
|
||||
case ValueErrorType.NumberMultipleOf:
|
||||
return `Expected number to be a multiple of ${error.schema.multipleOf}`
|
||||
case ValueErrorType.Number:
|
||||
return 'Expected number'
|
||||
case ValueErrorType.Object:
|
||||
return 'Expected object'
|
||||
case ValueErrorType.ObjectAdditionalProperties:
|
||||
return 'Unexpected property'
|
||||
case ValueErrorType.ObjectMaxProperties:
|
||||
return `Expected object to have no more than ${error.schema.maxProperties} properties`
|
||||
case ValueErrorType.ObjectMinProperties:
|
||||
return `Expected object to have at least ${error.schema.minProperties} properties`
|
||||
case ValueErrorType.ObjectRequiredProperty:
|
||||
return 'Required property'
|
||||
case ValueErrorType.Promise:
|
||||
return 'Expected Promise'
|
||||
case ValueErrorType.RegExp:
|
||||
return 'Expected string to match regular expression'
|
||||
case ValueErrorType.StringFormatUnknown:
|
||||
return `Unknown format '${error.schema.format}'`
|
||||
case ValueErrorType.StringFormat:
|
||||
return `Expected string to match '${error.schema.format}' format`
|
||||
case ValueErrorType.StringMaxLength:
|
||||
return `Expected string length less or equal to ${error.schema.maxLength}`
|
||||
case ValueErrorType.StringMinLength:
|
||||
return `Expected string length greater or equal to ${error.schema.minLength}`
|
||||
case ValueErrorType.StringPattern:
|
||||
return `Expected string to match '${error.schema.pattern}'`
|
||||
case ValueErrorType.String:
|
||||
return 'Expected string'
|
||||
case ValueErrorType.Symbol:
|
||||
return 'Expected symbol'
|
||||
case ValueErrorType.TupleLength:
|
||||
return `Expected tuple to have ${error.schema.maxItems || 0} elements`
|
||||
case ValueErrorType.Tuple:
|
||||
return 'Expected tuple'
|
||||
case ValueErrorType.Uint8ArrayMaxByteLength:
|
||||
return `Expected byte length less or equal to ${error.schema.maxByteLength}`
|
||||
case ValueErrorType.Uint8ArrayMinByteLength:
|
||||
return `Expected byte length greater or equal to ${error.schema.minByteLength}`
|
||||
case ValueErrorType.Uint8Array:
|
||||
return 'Expected Uint8Array'
|
||||
case ValueErrorType.Undefined:
|
||||
return 'Expected undefined'
|
||||
case ValueErrorType.Union:
|
||||
return 'Expected union value'
|
||||
case ValueErrorType.Void:
|
||||
return 'Expected void'
|
||||
case ValueErrorType.Kind:
|
||||
return `Expected kind '${error.schema[Kind]}'`
|
||||
default:
|
||||
return 'Unknown error type'
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ErrorFunction
|
||||
// ------------------------------------------------------------------
|
||||
export type ErrorFunctionParameter = {
|
||||
/** The type of validation error */
|
||||
errorType: ValueErrorType
|
||||
/** The path of the error */
|
||||
path: string
|
||||
/** The schema associated with the error */
|
||||
schema: TSchema
|
||||
/** The value associated with the error */
|
||||
value: unknown
|
||||
}
|
||||
export type ErrorFunction = (parameter: ErrorFunctionParameter) => string
|
||||
/** Manages error message providers */
|
||||
let errorFunction: ErrorFunction = DefaultErrorFunction
|
||||
|
||||
/** Sets the error function used to generate error messages. */
|
||||
export function SetErrorFunction(callback: ErrorFunction) {
|
||||
errorFunction = callback
|
||||
}
|
||||
/** Gets the error function used to generate error messages */
|
||||
export function GetErrorFunction(): ErrorFunction {
|
||||
return errorFunction
|
||||
}
|
||||
@@ -26,4 +26,5 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './errors'
|
||||
export { Errors, ValueError, ValueErrorIterator, ValueErrorType, ValueErrorsUnknownTypeError } from './errors'
|
||||
export { DefaultErrorFunction, GetErrorFunction, SetErrorFunction, type ErrorFunction } from './function'
|
||||
|
||||
117
src/index.ts
Normal file
117
src/index.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Infrastructure
|
||||
// ------------------------------------------------------------------
|
||||
export { Kind, Hint, ReadonlyKind, OptionalKind, TransformKind } from './type/symbols/index'
|
||||
export { PatternBoolean, PatternBooleanExact, PatternNumber, PatternNumberExact, PatternString, PatternStringExact } from './type/patterns/index'
|
||||
export { TypeRegistry, FormatRegistry } from './type/registry/index'
|
||||
export { TypeGuard, ValueGuard } from './type/guard/index'
|
||||
export { CloneType, CloneRest } from './type/clone/type'
|
||||
export { TypeBoxError } from './type/error/index'
|
||||
// ------------------------------------------------------------------
|
||||
// Type
|
||||
// ------------------------------------------------------------------
|
||||
export { Any, type TAny } from './type/any/index'
|
||||
export { Array, type TArray, type ArrayOptions } from './type/array/index'
|
||||
export { AsyncIterator, type TAsyncIterator } from './type/async-iterator/index'
|
||||
export { Awaited, type TAwaited } from './type/awaited/index'
|
||||
export { BigInt, type TBigInt, type BigIntOptions } from './type/bigint/index'
|
||||
export { Boolean, type TBoolean } from './type/boolean/index'
|
||||
export { Composite, type TComposite } from './type/composite/index'
|
||||
export { Const, type TConst } from './type/const/index'
|
||||
export { Constructor, type TConstructor } from './type/constructor/index'
|
||||
export { ConstructorParameters, type TConstructorParameters } from './type/constructor-parameters/index'
|
||||
export { Date, type TDate, type DateOptions } from './type/date/index'
|
||||
export { Deref, type TDeref } from './type/deref/index'
|
||||
export { Enum, type TEnum } from './type/enum/index'
|
||||
export { Exclude, type TExclude, type TExcludeFromMappedResult } from './type/exclude/index'
|
||||
export { Extends, type TExtends, type ExtendsFromMappedResult, type ExtendsFromMappedKey, ExtendsCheck, ExtendsResult, ExtendsUndefinedCheck } from './type/extends/index'
|
||||
export { Extract, type TExtract, type TExtractFromMappedResult } from './type/extract/index'
|
||||
export { Function, type TFunction } from './type/function/index'
|
||||
export { Increment, type Assert, type AssertType, type AssertRest, type AssertProperties, type Ensure, type Evaluate, type TupleToIntersect, type TupleToUnion, type UnionToTuple } from './type/helpers/index'
|
||||
export { Index, IndexPropertyKeys, IndexFromMappedKey, IndexFromMappedResult, type TIndex, type TIndexPropertyKeys, type TIndexFromMappedKey, type TIndexFromMappedResult } from './type/indexed/index'
|
||||
export { InstanceType, type TInstanceType } from './type/instance-type/index'
|
||||
export { Integer, type TInteger, type IntegerOptions } from './type/integer/index'
|
||||
export { Intersect, IntersectEvaluated, type TIntersect, type TIntersectEvaluated, type IntersectOptions } from './type/intersect/index'
|
||||
export { Iterator, type TIterator } from './type/iterator/index'
|
||||
export { Intrinsic, IntrinsicFromMappedKey, type TIntrinsic, Capitalize, type TCapitalize, Lowercase, type TLowercase, Uncapitalize, type TUncapitalize, Uppercase, type TUppercase } from './type/intrinsic/index'
|
||||
export { KeyOf, type TKeyOf, type KeyOfFromMappedResult, KeyOfPropertyKeys, KeyOfPattern } from './type/keyof/index'
|
||||
export { Literal, type TLiteral } from './type/literal/index'
|
||||
export { Mapped, MappedKey, MappedResult, type TMapped, type TMappedKey, type TMappedResult, type TMappedFunction } from './type/mapped/index'
|
||||
export { Never, type TNever } from './type/never/index'
|
||||
export { Not, type TNot } from './type/not/index'
|
||||
export { Null, type TNull } from './type/null/index'
|
||||
export { Number, type TNumber, type NumberOptions } from './type/number/index'
|
||||
export { Object, type TObject, type TProperties, type ObjectOptions } from './type/object/index'
|
||||
export { Omit, type TOmit, type TOmitFromMappedKey, type TOmitFromMappedResult } from './type/omit/index'
|
||||
export { Optional, OptionalFromMappedResult, type TOptional, type TOptionalWithFlag, type TOptionalFromMappedResult } from './type/optional/index'
|
||||
export { Parameters, type TParameters } from './type/parameters/index'
|
||||
export { Partial, PartialFromMappedResult, type TPartial, type TPartialFromMappedResult } from './type/partial/index'
|
||||
export { Pick, type TPick, type TPickFromMappedKey, type TPickFromMappedResult } from './type/pick/index'
|
||||
export { Promise, type TPromise } from './type/promise/index'
|
||||
export { Readonly, ReadonlyFromMappedResult, type TReadonly, type TReadonlyWithFlag, type TReadonlyFromMappedResult } from './type/readonly/index'
|
||||
export { ReadonlyOptional, type TReadonlyOptional } from './type/readonly-optional/index'
|
||||
export { Record, type TRecord } from './type/record/index'
|
||||
export { Recursive, type TRecursive, type TThis } from './type/recursive/index'
|
||||
export { Ref, type TRef } from './type/ref/index'
|
||||
export { RegExp, type TRegExp } from './type/regexp/index'
|
||||
export { Required, type TRequired, type TRequiredFromMappedResult } from './type/required/index'
|
||||
export { Rest, type TRest } from './type/rest/index'
|
||||
export { ReturnType, type TReturnType } from './type/return-type/index'
|
||||
export { type TSchema, type TKind, type SchemaOptions, type TAnySchema } from './type/schema/index'
|
||||
export { type Static, type StaticDecode, type StaticEncode } from './type/static/index'
|
||||
export { Strict } from './type/strict/index'
|
||||
export { String, type TString, type StringOptions, type StringFormatOption, type StringContentEncodingOption } from './type/string/index'
|
||||
export { Symbol, type TSymbol, type TSymbolValue as SymbolValue } from './type/symbol/index'
|
||||
export {
|
||||
TemplateLiteral,
|
||||
IsTemplateLiteralFinite,
|
||||
IsTemplateLiteralExpressionFinite,
|
||||
TemplateLiteralParse,
|
||||
TemplateLiteralParseExact,
|
||||
TemplateLiteralGenerate,
|
||||
TemplateLiteralExpressionGenerate,
|
||||
type TTemplateLiteral,
|
||||
type TIsTemplateLiteralFinite,
|
||||
type TTemplateLiteralGenerate,
|
||||
type TTemplateLiteralKind,
|
||||
} from './type/template-literal/index'
|
||||
export { Transform, TransformDecodeBuilder, TransformEncodeBuilder, type TTransform, type TransformOptions, type TransformFunction } from './type/transform/index'
|
||||
export { Tuple, type TTuple } from './type/tuple/index'
|
||||
export { Uint8Array, type TUint8Array, type Uint8ArrayOptions } from './type/uint8array/index'
|
||||
export { Undefined, type TUndefined } from './type/undefined/index'
|
||||
export { Union, UnionEvaluated, type TUnion, type TUnionEvaluated } from './type/union/index'
|
||||
export { Unknown, type TUnknown } from './type/unknown/index'
|
||||
export { Unsafe, type TUnsafe } from './type/unsafe/index'
|
||||
export { Void, type TVoid } from './type/void/index'
|
||||
// ------------------------------------------------------------------
|
||||
// Namespace
|
||||
// ------------------------------------------------------------------
|
||||
export { Type, JsonTypeBuilder, JavaScriptTypeBuilder } from './type/type/index'
|
||||
@@ -26,5 +26,5 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export { ValueErrorType } from '../errors/errors'
|
||||
export * from './system'
|
||||
export { TypeSystemPolicy } from './policy'
|
||||
export { TypeSystem, TypeSystemDuplicateFormat, TypeSystemDuplicateTypeKind } from './system'
|
||||
|
||||
67
src/system/policy.ts
Normal file
67
src/system/policy.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/system
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { IsObject, IsArray, IsNumber, IsUndefined } from '../value/guard/index'
|
||||
|
||||
export namespace TypeSystemPolicy {
|
||||
// ------------------------------------------------------------------
|
||||
// TypeSystemPolicy
|
||||
// ------------------------------------------------------------------
|
||||
/** Shared assertion routines used by the value and errors modules */
|
||||
/** Sets whether TypeBox should assert optional properties using the TypeScript `exactOptionalPropertyTypes` assertion policy. The default is `false` */
|
||||
export let ExactOptionalPropertyTypes: boolean = false
|
||||
/** Sets whether arrays should be treated as a kind of objects. The default is `false` */
|
||||
export let AllowArrayObject: boolean = false
|
||||
/** Sets whether `NaN` or `Infinity` should be treated as valid numeric values. The default is `false` */
|
||||
export let AllowNaN: boolean = false
|
||||
/** Sets whether `null` should validate for void types. The default is `false` */
|
||||
export let AllowNullVoid: boolean = false
|
||||
/** Asserts this value using the ExactOptionalPropertyTypes policy */
|
||||
export function IsExactOptionalProperty(value: Record<keyof any, unknown>, key: string) {
|
||||
return ExactOptionalPropertyTypes ? key in value : value[key] !== undefined
|
||||
}
|
||||
/** Asserts this value using the AllowArrayObjects policy */
|
||||
export function IsObjectLike(value: unknown): value is Record<keyof any, unknown> {
|
||||
const isObject = IsObject(value)
|
||||
return AllowArrayObject ? isObject : isObject && !IsArray(value)
|
||||
}
|
||||
/** Asserts this value as a record using the AllowArrayObjects policy */
|
||||
export function IsRecordLike(value: unknown): value is Record<keyof any, unknown> {
|
||||
return IsObjectLike(value) && !(value instanceof Date) && !(value instanceof Uint8Array)
|
||||
}
|
||||
/** Asserts this value using the AllowNaN policy */
|
||||
export function IsNumberLike(value: unknown): value is number {
|
||||
const isNumber = IsNumber(value)
|
||||
return AllowNaN ? isNumber : isNumber && Number.isFinite(value)
|
||||
}
|
||||
/** Asserts this value using the AllowVoidNull policy */
|
||||
export function IsVoidLike(value: unknown): value is void {
|
||||
const isUndefined = IsUndefined(value)
|
||||
return AllowNullVoid ? isUndefined || value === null : isUndefined
|
||||
}
|
||||
}
|
||||
@@ -26,234 +26,39 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { IsObject, IsArray, IsNumber, IsUndefined } from '../value/guard'
|
||||
import { ValueErrorType } from '../errors/errors'
|
||||
import * as Types from '../typebox'
|
||||
import { TypeRegistry, FormatRegistry } from '../type/registry/index'
|
||||
import { Unsafe } from '../type/unsafe/index'
|
||||
import { Kind } from '../type/symbols/index'
|
||||
import { TypeBoxError } from '../type/error/index'
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// Errors
|
||||
// --------------------------------------------------------------------------
|
||||
export class TypeSystemDuplicateTypeKind extends Types.TypeBoxError {
|
||||
// ------------------------------------------------------------------
|
||||
export class TypeSystemDuplicateTypeKind extends TypeBoxError {
|
||||
constructor(kind: string) {
|
||||
super(`Duplicate type kind '${kind}' detected`)
|
||||
}
|
||||
}
|
||||
export class TypeSystemDuplicateFormat extends Types.TypeBoxError {
|
||||
export class TypeSystemDuplicateFormat extends TypeBoxError {
|
||||
constructor(kind: string) {
|
||||
super(`Duplicate string format '${kind}' detected`)
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
// TypeSystem
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------
|
||||
/** Creates user defined types and formats and provides overrides for value checking behaviours */
|
||||
export namespace TypeSystem {
|
||||
/** Creates a new type */
|
||||
export function Type<Type, Options = Record<PropertyKey, unknown>>(kind: string, check: (options: Options, value: unknown) => boolean) {
|
||||
if (Types.TypeRegistry.Has(kind)) throw new TypeSystemDuplicateTypeKind(kind)
|
||||
Types.TypeRegistry.Set(kind, check)
|
||||
return (options: Partial<Options> = {}) => Types.Type.Unsafe<Type>({ ...options, [Types.Kind]: kind })
|
||||
if (TypeRegistry.Has(kind)) throw new TypeSystemDuplicateTypeKind(kind)
|
||||
TypeRegistry.Set(kind, check)
|
||||
return (options: Partial<Options> = {}) => Unsafe<Type>({ ...options, [Kind]: kind })
|
||||
}
|
||||
/** Creates a new string format */
|
||||
export function Format<F extends string>(format: F, check: (value: string) => boolean): F {
|
||||
if (Types.FormatRegistry.Has(format)) throw new TypeSystemDuplicateFormat(format)
|
||||
Types.FormatRegistry.Set(format, check)
|
||||
if (FormatRegistry.Has(format)) throw new TypeSystemDuplicateFormat(format)
|
||||
FormatRegistry.Set(format, check)
|
||||
return format
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// TypeSystemErrorFunction
|
||||
// --------------------------------------------------------------------------
|
||||
/** Manages error message providers */
|
||||
export namespace TypeSystemErrorFunction {
|
||||
let errorMessageFunction: ErrorFunction = DefaultErrorFunction
|
||||
/** Resets the error message function to en-us */
|
||||
export function Reset() {
|
||||
errorMessageFunction = DefaultErrorFunction
|
||||
}
|
||||
/** Sets the error message function used to generate error messages */
|
||||
export function Set(callback: ErrorFunction) {
|
||||
errorMessageFunction = callback
|
||||
}
|
||||
/** Gets the error message function */
|
||||
export function Get(): ErrorFunction {
|
||||
return errorMessageFunction
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// TypeSystemPolicy
|
||||
// --------------------------------------------------------------------------
|
||||
/** Shared assertion routines used by the value and errors modules */
|
||||
export namespace TypeSystemPolicy {
|
||||
/** Sets whether TypeBox should assert optional properties using the TypeScript `exactOptionalPropertyTypes` assertion policy. The default is `false` */
|
||||
export let ExactOptionalPropertyTypes: boolean = false
|
||||
/** Sets whether arrays should be treated as a kind of objects. The default is `false` */
|
||||
export let AllowArrayObject: boolean = false
|
||||
/** Sets whether `NaN` or `Infinity` should be treated as valid numeric values. The default is `false` */
|
||||
export let AllowNaN: boolean = false
|
||||
/** Sets whether `null` should validate for void types. The default is `false` */
|
||||
export let AllowNullVoid: boolean = false
|
||||
/** Asserts this value using the ExactOptionalPropertyTypes policy */
|
||||
export function IsExactOptionalProperty(value: Record<keyof any, unknown>, key: string) {
|
||||
return ExactOptionalPropertyTypes ? key in value : value[key] !== undefined
|
||||
}
|
||||
/** Asserts this value using the AllowArrayObjects policy */
|
||||
export function IsObjectLike(value: unknown): value is Record<keyof any, unknown> {
|
||||
const isObject = IsObject(value)
|
||||
return AllowArrayObject ? isObject : isObject && !IsArray(value)
|
||||
}
|
||||
/** Asserts this value as a record using the AllowArrayObjects policy */
|
||||
export function IsRecordLike(value: unknown): value is Record<keyof any, unknown> {
|
||||
return IsObjectLike(value) && !(value instanceof Date) && !(value instanceof Uint8Array)
|
||||
}
|
||||
/** Asserts this value using the AllowNaN policy */
|
||||
export function IsNumberLike(value: unknown): value is number {
|
||||
const isNumber = IsNumber(value)
|
||||
return AllowNaN ? isNumber : isNumber && Number.isFinite(value)
|
||||
}
|
||||
/** Asserts this value using the AllowVoidNull policy */
|
||||
export function IsVoidLike(value: unknown): value is void {
|
||||
const isUndefined = IsUndefined(value)
|
||||
return AllowNullVoid ? isUndefined || value === null : isUndefined
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------------------------
|
||||
// ErrorFunction
|
||||
// --------------------------------------------------------------------------
|
||||
export type ErrorFunction = (schema: Types.TSchema, type: ValueErrorType) => string
|
||||
// --------------------------------------------------------------------------
|
||||
// DefaultErrorFunction
|
||||
// --------------------------------------------------------------------------
|
||||
/** Creates an error message using en-US as the default locale */
|
||||
export function DefaultErrorFunction(schema: Types.TSchema, errorType: ValueErrorType) {
|
||||
switch (errorType) {
|
||||
case ValueErrorType.ArrayContains:
|
||||
return 'Expected array to contain at least one matching value'
|
||||
case ValueErrorType.ArrayMaxContains:
|
||||
return `Expected array to contain no more than ${schema.maxContains} matching values`
|
||||
case ValueErrorType.ArrayMinContains:
|
||||
return `Expected array to contain at least ${schema.minContains} matching values`
|
||||
case ValueErrorType.ArrayMaxItems:
|
||||
return `Expected array length to be less or equal to ${schema.maxItems}`
|
||||
case ValueErrorType.ArrayMinItems:
|
||||
return `Expected array length to be greater or equal to ${schema.minItems}`
|
||||
case ValueErrorType.ArrayUniqueItems:
|
||||
return 'Expected array elements to be unique'
|
||||
case ValueErrorType.Array:
|
||||
return 'Expected array'
|
||||
case ValueErrorType.AsyncIterator:
|
||||
return 'Expected AsyncIterator'
|
||||
case ValueErrorType.BigIntExclusiveMaximum:
|
||||
return `Expected bigint to be less than ${schema.exclusiveMaximum}`
|
||||
case ValueErrorType.BigIntExclusiveMinimum:
|
||||
return `Expected bigint to be greater than ${schema.exclusiveMinimum}`
|
||||
case ValueErrorType.BigIntMaximum:
|
||||
return `Expected bigint to be less or equal to ${schema.maximum}`
|
||||
case ValueErrorType.BigIntMinimum:
|
||||
return `Expected bigint to be greater or equal to ${schema.minimum}`
|
||||
case ValueErrorType.BigIntMultipleOf:
|
||||
return `Expected bigint to be a multiple of ${schema.multipleOf}`
|
||||
case ValueErrorType.BigInt:
|
||||
return 'Expected bigint'
|
||||
case ValueErrorType.Boolean:
|
||||
return 'Expected boolean'
|
||||
case ValueErrorType.DateExclusiveMinimumTimestamp:
|
||||
return `Expected Date timestamp to be greater than ${schema.exclusiveMinimumTimestamp}`
|
||||
case ValueErrorType.DateExclusiveMaximumTimestamp:
|
||||
return `Expected Date timestamp to be less than ${schema.exclusiveMaximumTimestamp}`
|
||||
case ValueErrorType.DateMinimumTimestamp:
|
||||
return `Expected Date timestamp to be greater or equal to ${schema.minimumTimestamp}`
|
||||
case ValueErrorType.DateMaximumTimestamp:
|
||||
return `Expected Date timestamp to be less or equal to ${schema.maximumTimestamp}`
|
||||
case ValueErrorType.DateMultipleOfTimestamp:
|
||||
return `Expected Date timestamp to be a multiple of ${schema.multipleOfTimestamp}`
|
||||
case ValueErrorType.Date:
|
||||
return 'Expected Date'
|
||||
case ValueErrorType.Function:
|
||||
return 'Expected function'
|
||||
case ValueErrorType.IntegerExclusiveMaximum:
|
||||
return `Expected integer to be less than ${schema.exclusiveMaximum}`
|
||||
case ValueErrorType.IntegerExclusiveMinimum:
|
||||
return `Expected integer to be greater than ${schema.exclusiveMinimum}`
|
||||
case ValueErrorType.IntegerMaximum:
|
||||
return `Expected integer to be less or equal to ${schema.maximum}`
|
||||
case ValueErrorType.IntegerMinimum:
|
||||
return `Expected integer to be greater or equal to ${schema.minimum}`
|
||||
case ValueErrorType.IntegerMultipleOf:
|
||||
return `Expected integer to be a multiple of ${schema.multipleOf}`
|
||||
case ValueErrorType.Integer:
|
||||
return 'Expected integer'
|
||||
case ValueErrorType.IntersectUnevaluatedProperties:
|
||||
return 'Unexpected property'
|
||||
case ValueErrorType.Intersect:
|
||||
return 'Expected all values to match'
|
||||
case ValueErrorType.Iterator:
|
||||
return 'Expected Iterator'
|
||||
case ValueErrorType.Literal:
|
||||
return `Expected ${typeof schema.const === 'string' ? `'${schema.const}'` : schema.const}`
|
||||
case ValueErrorType.Never:
|
||||
return 'Never'
|
||||
case ValueErrorType.Not:
|
||||
return 'Value should not match'
|
||||
case ValueErrorType.Null:
|
||||
return 'Expected null'
|
||||
case ValueErrorType.NumberExclusiveMaximum:
|
||||
return `Expected number to be less than ${schema.exclusiveMaximum}`
|
||||
case ValueErrorType.NumberExclusiveMinimum:
|
||||
return `Expected number to be greater than ${schema.exclusiveMinimum}`
|
||||
case ValueErrorType.NumberMaximum:
|
||||
return `Expected number to be less or equal to ${schema.maximum}`
|
||||
case ValueErrorType.NumberMinimum:
|
||||
return `Expected number to be greater or equal to ${schema.minimum}`
|
||||
case ValueErrorType.NumberMultipleOf:
|
||||
return `Expected number to be a multiple of ${schema.multipleOf}`
|
||||
case ValueErrorType.Number:
|
||||
return 'Expected number'
|
||||
case ValueErrorType.Object:
|
||||
return 'Expected object'
|
||||
case ValueErrorType.ObjectAdditionalProperties:
|
||||
return 'Unexpected property'
|
||||
case ValueErrorType.ObjectMaxProperties:
|
||||
return `Expected object to have no more than ${schema.maxProperties} properties`
|
||||
case ValueErrorType.ObjectMinProperties:
|
||||
return `Expected object to have at least ${schema.minProperties} properties`
|
||||
case ValueErrorType.ObjectRequiredProperty:
|
||||
return 'Required property'
|
||||
case ValueErrorType.Promise:
|
||||
return 'Expected Promise'
|
||||
case ValueErrorType.StringFormatUnknown:
|
||||
return `Unknown format '${schema.format}'`
|
||||
case ValueErrorType.StringFormat:
|
||||
return `Expected string to match '${schema.format}' format`
|
||||
case ValueErrorType.StringMaxLength:
|
||||
return `Expected string length less or equal to ${schema.maxLength}`
|
||||
case ValueErrorType.StringMinLength:
|
||||
return `Expected string length greater or equal to ${schema.minLength}`
|
||||
case ValueErrorType.StringPattern:
|
||||
return `Expected string to match '${schema.pattern}'`
|
||||
case ValueErrorType.String:
|
||||
return 'Expected string'
|
||||
case ValueErrorType.Symbol:
|
||||
return 'Expected symbol'
|
||||
case ValueErrorType.TupleLength:
|
||||
return `Expected tuple to have ${schema.maxItems || 0} elements`
|
||||
case ValueErrorType.Tuple:
|
||||
return 'Expected tuple'
|
||||
case ValueErrorType.Uint8ArrayMaxByteLength:
|
||||
return `Expected byte length less or equal to ${schema.maxByteLength}`
|
||||
case ValueErrorType.Uint8ArrayMinByteLength:
|
||||
return `Expected byte length greater or equal to ${schema.minByteLength}`
|
||||
case ValueErrorType.Uint8Array:
|
||||
return 'Expected Uint8Array'
|
||||
case ValueErrorType.Undefined:
|
||||
return 'Expected undefined'
|
||||
case ValueErrorType.Union:
|
||||
return 'Expected union value'
|
||||
case ValueErrorType.Void:
|
||||
return 'Expected void'
|
||||
case ValueErrorType.Kind:
|
||||
return `Expected kind '${schema[Types.Kind]}'`
|
||||
default:
|
||||
return 'Unknown error type'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"files": ["compiler/index.ts", "errors/index.ts", "system/index.ts", "value/index.ts", "typebox.ts"]
|
||||
"files": ["compiler/index.ts", "errors/index.ts", "system/index.ts", "type/index.ts", "value/index.ts", "index.ts"]
|
||||
}
|
||||
|
||||
40
src/type/any/any.ts
Normal file
40
src/type/any/any.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
export interface TAny extends TSchema {
|
||||
[Kind]: 'Any'
|
||||
static: any
|
||||
}
|
||||
|
||||
/** `[Json]` Creates an Any type */
|
||||
export function Any(options: SchemaOptions = {}): TAny {
|
||||
return { ...options, [Kind]: 'Any' } as unknown as TAny
|
||||
}
|
||||
29
src/type/any/index.ts
Normal file
29
src/type/any/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './any'
|
||||
62
src/type/array/array.ts
Normal file
62
src/type/array/array.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
import { CloneType } from '../clone/type'
|
||||
|
||||
export interface ArrayOptions extends SchemaOptions {
|
||||
/** The minimum number of items in this array */
|
||||
minItems?: number
|
||||
/** The maximum number of items in this array */
|
||||
maxItems?: number
|
||||
/** Should this schema contain unique items */
|
||||
uniqueItems?: boolean
|
||||
/** A schema for which some elements should match */
|
||||
contains?: TSchema
|
||||
/** A minimum number of contains schema matches */
|
||||
minContains?: number
|
||||
/** A maximum number of contains schema matches */
|
||||
maxContains?: number
|
||||
}
|
||||
export interface TArray<T extends TSchema = TSchema> extends TSchema, ArrayOptions {
|
||||
[Kind]: 'Array'
|
||||
static: Array<Static<T, this['params']>>
|
||||
type: 'array'
|
||||
items: T
|
||||
}
|
||||
/** `[Json]` Creates an Array type */
|
||||
export function Array<T extends TSchema>(schema: T, options: ArrayOptions = {}): TArray<T> {
|
||||
return {
|
||||
...options,
|
||||
[Kind]: 'Array',
|
||||
type: 'array',
|
||||
items: CloneType(schema),
|
||||
} as unknown as TArray<T>
|
||||
}
|
||||
29
src/type/array/index.ts
Normal file
29
src/type/array/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './array'
|
||||
48
src/type/async-iterator/async-iterator.ts
Normal file
48
src/type/async-iterator/async-iterator.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
import { CloneType } from '../clone/type'
|
||||
|
||||
export interface TAsyncIterator<T extends TSchema = TSchema> extends TSchema {
|
||||
[Kind]: 'AsyncIterator'
|
||||
static: AsyncIterableIterator<Static<T, this['params']>>
|
||||
type: 'AsyncIterator'
|
||||
items: T
|
||||
}
|
||||
/** `[JavaScript]` Creates a AsyncIterator type */
|
||||
export function AsyncIterator<T extends TSchema>(items: T, options: SchemaOptions = {}): TAsyncIterator<T> {
|
||||
return {
|
||||
...options,
|
||||
[Kind]: 'AsyncIterator',
|
||||
type: 'AsyncIterator',
|
||||
items: CloneType(items),
|
||||
} as unknown as TAsyncIterator<T>
|
||||
}
|
||||
29
src/type/async-iterator/index.ts
Normal file
29
src/type/async-iterator/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './async-iterator'
|
||||
105
src/type/awaited/awaited.ts
Normal file
105
src/type/awaited/awaited.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Intersect, type TIntersect } from '../intersect/index'
|
||||
import { Union, type TUnion } from '../union/index'
|
||||
import { type TPromise } from '../promise/index'
|
||||
import { CloneType } from '../clone/type'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsIntersect, IsUnion, IsPromise } from '../guard/type'
|
||||
// ------------------------------------------------------------------
|
||||
// FromRest
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromRest<T extends TSchema[], Acc extends TSchema[] = []> =
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? TFromRest<R, [...Acc, TFromSchema<L>]>
|
||||
: Acc
|
||||
// prettier-ignore
|
||||
function FromRest<T extends TSchema[]>(T: [...T]) : TFromRest<T> {
|
||||
return T.map(L => FromSchema(L)) as TFromRest<T>
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// FromIntersect
|
||||
// ----------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromIntersect<T extends TSchema[]> = TIntersect<TFromRest<T>>
|
||||
// prettier-ignore
|
||||
function FromIntersect<T extends TSchema[]>(T: [...T]): TFromIntersect<T> {
|
||||
return Intersect(FromRest(T) as TSchema[]) as unknown as TFromIntersect<T>
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// FromUnion
|
||||
// ----------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromUnion<T extends TSchema[]> = TUnion<TFromRest<T>>
|
||||
// prettier-ignore
|
||||
function FromUnion<T extends TSchema[]>(T: [...T]): TFromUnion<T> {
|
||||
return Union(FromRest(T) as TSchema[]) as unknown as TFromUnion<T>
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// Promise
|
||||
// ----------------------------------------------------------------
|
||||
type TFromPromise<T extends TSchema> = TFromSchema<T>
|
||||
// prettier-ignore
|
||||
function FromPromise<T extends TSchema>(T: T): TFromPromise<T> {
|
||||
return FromSchema(T) as TFromPromise<T>
|
||||
}
|
||||
// ----------------------------------------------------------------
|
||||
// FromSchema
|
||||
// ----------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromSchema<T extends TSchema> =
|
||||
T extends TIntersect<infer S> ? TIntersect<TFromRest<S>> :
|
||||
T extends TUnion<infer S> ? TUnion<TFromRest<S>> :
|
||||
T extends TPromise<infer S> ? TFromSchema<S> :
|
||||
T
|
||||
// prettier-ignore
|
||||
function FromSchema<T extends TSchema>(T: T): TFromSchema<T> {
|
||||
return (
|
||||
IsIntersect(T) ? FromIntersect(T.allOf) :
|
||||
IsUnion(T) ? FromUnion(T.anyOf) :
|
||||
IsPromise(T) ? FromPromise(T.item) :
|
||||
T
|
||||
) as TFromSchema<T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TAwaited
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TAwaited<T extends TSchema> = (
|
||||
TFromSchema<T>
|
||||
)
|
||||
/** `[JavaScript]` Constructs a type by recursively unwrapping Promise types */
|
||||
export function Awaited<T extends TSchema>(T: T, options: SchemaOptions = {}): TFromSchema<T> {
|
||||
return CloneType(FromSchema(T), options)
|
||||
}
|
||||
29
src/type/awaited/index.ts
Normal file
29
src/type/awaited/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './awaited'
|
||||
51
src/type/bigint/bigint.ts
Normal file
51
src/type/bigint/bigint.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
export interface BigIntOptions extends SchemaOptions {
|
||||
exclusiveMaximum?: bigint
|
||||
exclusiveMinimum?: bigint
|
||||
maximum?: bigint
|
||||
minimum?: bigint
|
||||
multipleOf?: bigint
|
||||
}
|
||||
export interface TBigInt extends TSchema, BigIntOptions {
|
||||
[Kind]: 'BigInt'
|
||||
static: bigint
|
||||
type: 'bigint'
|
||||
}
|
||||
/** `[JavaScript]` Creates a BigInt type */
|
||||
export function BigInt(options: BigIntOptions = {}): TBigInt {
|
||||
return {
|
||||
...options,
|
||||
[Kind]: 'BigInt',
|
||||
type: 'bigint',
|
||||
} as TBigInt
|
||||
}
|
||||
29
src/type/bigint/index.ts
Normal file
29
src/type/bigint/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './bigint'
|
||||
44
src/type/boolean/boolean.ts
Normal file
44
src/type/boolean/boolean.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
export interface TBoolean extends TSchema {
|
||||
[Kind]: 'Boolean'
|
||||
static: boolean
|
||||
type: 'boolean'
|
||||
}
|
||||
/** `[Json]` Creates a Boolean type */
|
||||
export function Boolean(options: SchemaOptions = {}): TBoolean {
|
||||
return {
|
||||
...options,
|
||||
[Kind]: 'Boolean',
|
||||
type: 'boolean',
|
||||
} as unknown as TBoolean
|
||||
}
|
||||
29
src/type/boolean/index.ts
Normal file
29
src/type/boolean/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './boolean'
|
||||
30
src/type/clone/index.ts
Normal file
30
src/type/clone/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * as TypeClone from './type'
|
||||
export * as ValueClone from './value'
|
||||
39
src/type/clone/type.ts
Normal file
39
src/type/clone/type.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Clone } from './value'
|
||||
|
||||
/** Clones a Rest */
|
||||
export function CloneRest<T extends TSchema[]>(schemas: T): T {
|
||||
return schemas.map((schema) => CloneType(schema)) as T
|
||||
}
|
||||
/** Clones a Type */
|
||||
export function CloneType<T extends TSchema>(schema: T, options: SchemaOptions = {}): T {
|
||||
return { ...Clone(schema), ...options }
|
||||
}
|
||||
62
src/type/clone/value.ts
Normal file
62
src/type/clone/value.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 ValueGuard from '../guard/value'
|
||||
|
||||
function ArrayType(value: unknown[]) {
|
||||
return (value as any).map((value: unknown) => Visit(value as any))
|
||||
}
|
||||
function DateType(value: Date) {
|
||||
return new Date(value.getTime())
|
||||
}
|
||||
function Uint8ArrayType(value: Uint8Array) {
|
||||
return new Uint8Array(value)
|
||||
}
|
||||
function RegExpType(value: RegExp) {
|
||||
return new RegExp(value.source, value.flags)
|
||||
}
|
||||
function ObjectType(value: Record<keyof any, unknown>) {
|
||||
const clonedProperties = Object.getOwnPropertyNames(value).reduce((acc, key) => ({ ...acc, [key]: Visit(value[key]) }), {})
|
||||
const clonedSymbols = Object.getOwnPropertySymbols(value).reduce((acc, key) => ({ ...acc, [key]: Visit(value[key as any]) }), {})
|
||||
return { ...clonedProperties, ...clonedSymbols }
|
||||
}
|
||||
// prettier-ignore
|
||||
function Visit(value: unknown): any {
|
||||
return (
|
||||
ValueGuard.IsArray(value) ? ArrayType(value) :
|
||||
ValueGuard.IsDate(value) ? DateType(value) :
|
||||
ValueGuard.IsUint8Array(value) ? Uint8ArrayType(value) :
|
||||
ValueGuard.IsRegExp(value) ? RegExpType(value) :
|
||||
ValueGuard.IsObject(value) ? ObjectType(value) :
|
||||
value
|
||||
)
|
||||
}
|
||||
/** Clones a value */
|
||||
export function Clone<T>(value: T): T {
|
||||
return Visit(value)
|
||||
}
|
||||
75
src/type/composite/composite.ts
Normal file
75
src/type/composite/composite.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema } from '../schema/index'
|
||||
import type { UnionToTuple, Assert, Evaluate } from '../helpers/index'
|
||||
import { Object, type TObject, type TProperties, type ObjectOptions } from '../object/index'
|
||||
import { Intersect, type TIntersect } from '../intersect/index'
|
||||
import { Index, type TIndex } from '../indexed/index'
|
||||
import { KeyOfPropertyKeys } from '../keyof/index'
|
||||
import { CloneType } from '../clone/type'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TCompositeKeys
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TCompositeKeys<T extends TObject[], Acc extends PropertyKey = never> =
|
||||
T extends [infer L extends TObject, ...infer R extends TObject[]]
|
||||
? TCompositeKeys<R, Acc | keyof L['properties']>
|
||||
: Acc
|
||||
// ------------------------------------------------------------------
|
||||
// TCompositeIndex
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TCompositeIndex<T extends TIntersect<TObject[]>, K extends string[], Acc extends TProperties = {}> =
|
||||
K extends [infer L extends string, ...infer R extends string[]]
|
||||
? TCompositeIndex<T, R, Acc & { [_ in L]: TIndex<T, [L]> }>
|
||||
: Acc
|
||||
// prettier-ignore
|
||||
type TCompositeReduce<T extends TObject[]> = UnionToTuple<TCompositeKeys<T>> extends infer K
|
||||
? Evaluate<TCompositeIndex<TIntersect<T>, Assert<K, string[]>>>
|
||||
: {} // ^ indexed via intersection of T
|
||||
// prettier-ignore
|
||||
type TCompositeResolve<T extends TObject[]> = TIntersect<T> extends TIntersect
|
||||
? TObject<TCompositeReduce<T>>
|
||||
: TObject<{}>
|
||||
function CompositeResolve<T extends TObject[]>(T: [...T]): TCompositeResolve<T> {
|
||||
const intersect: TSchema = Intersect(T, {})
|
||||
const keys = KeyOfPropertyKeys(intersect) as string[]
|
||||
const properties = keys.reduce((acc, key) => ({ ...acc, [key]: Index(intersect, [key]) }), {} as TProperties)
|
||||
return Object(properties) as TCompositeResolve<T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TComposite
|
||||
// ------------------------------------------------------------------
|
||||
export type TComposite<T extends TObject[]> = TCompositeResolve<T>
|
||||
|
||||
/** `[Json]` Creates a Composite object type */
|
||||
export function Composite<T extends TObject[]>(T: [...T], options?: ObjectOptions): TComposite<T> {
|
||||
return CloneType(CompositeResolve(T) as TObject, options) as TComposite<T>
|
||||
}
|
||||
29
src/type/composite/index.ts
Normal file
29
src/type/composite/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './composite'
|
||||
135
src/type/const/const.ts
Normal file
135
src/type/const/const.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { AssertRest, Evaluate } from '../helpers/index'
|
||||
import type { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
|
||||
import { Any, type TAny } from '../any/index'
|
||||
import { BigInt, type TBigInt } from '../bigint/index'
|
||||
import { Date, type TDate } from '../date/index'
|
||||
import { Function as FunctionType, type TFunction } from '../function/index'
|
||||
import { Literal, type TLiteral } from '../literal/index'
|
||||
import { type TNever } from '../never/index'
|
||||
import { Null, type TNull } from '../null/index'
|
||||
import { Object, type TObject } from '../object/index'
|
||||
import { Symbol, type TSymbol } from '../symbol/index'
|
||||
import { Tuple, type TTuple } from '../tuple/index'
|
||||
import { Readonly, type TReadonly } from '../readonly/index'
|
||||
import { Undefined, type TUndefined } from '../undefined/index'
|
||||
import { Uint8Array, type TUint8Array } from '../uint8array/index'
|
||||
import { Unknown, type TUnknown } from '../unknown/index'
|
||||
import { TypeClone } from '../clone/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ValueGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsArray, IsNumber, IsBigInt, IsUint8Array, IsDate, IsIterator, IsObject, IsAsyncIterator, IsFunction, IsUndefined, IsNull, IsSymbol, IsBoolean, IsString } from '../guard/value'
|
||||
// ------------------------------------------------------------------
|
||||
// FromArray
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromArray<T extends readonly unknown[]> =
|
||||
T extends readonly [infer L extends unknown, ...infer R extends unknown[]]
|
||||
? [FromValue<L, false>, ...TFromArray<R>]
|
||||
: T
|
||||
// prettier-ignore
|
||||
function FromArray<T extends readonly unknown[]>(T: [...T]): TFromArray<T> {
|
||||
return T.map(L => FromValue(L, false)) as TFromArray<T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<T extends Record<PropertyKey, unknown>> = {
|
||||
-readonly [K in keyof T]: FromValue<T[K], false> extends infer R extends TSchema
|
||||
? TReadonly<R>
|
||||
: TReadonly<TNever>
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromProperties<T extends Record<PropertyKey, unknown>>(value: T): TFromProperties<T> {
|
||||
return globalThis.Object.getOwnPropertyNames(value).reduce((acc, key) => {
|
||||
return { ...acc, [key]: Readonly(FromValue(value[key], false)) }
|
||||
}, {} as TProperties) as unknown as TFromProperties<T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ConditionalReadonly - Only applied if not root
|
||||
// ------------------------------------------------------------------
|
||||
type TConditionalReadonly<T extends TSchema, Root extends boolean> = Root extends true ? T : TReadonly<T>
|
||||
function ConditionalReadonly<T extends TSchema, Root extends boolean>(T: T, root: Root): TConditionalReadonly<T, Root> {
|
||||
return (root === true ? T : Readonly(T)) as unknown as TConditionalReadonly<T, Root>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromValue
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type FromValue<T, Root extends boolean> =
|
||||
T extends AsyncIterableIterator<unknown> ? TConditionalReadonly<TAny, Root> :
|
||||
T extends IterableIterator<unknown> ? TConditionalReadonly<TAny, Root> :
|
||||
T extends readonly unknown[] ? TReadonly<TTuple<AssertRest<TFromArray<T>>>> :
|
||||
T extends Uint8Array ? TUint8Array :
|
||||
T extends Date ? TDate :
|
||||
T extends Record<PropertyKey, unknown> ? TConditionalReadonly<TObject<Evaluate<TFromProperties<T>>>, Root> :
|
||||
T extends Function ? TConditionalReadonly<TFunction<[], TUnknown>, Root> :
|
||||
T extends undefined ? TUndefined :
|
||||
T extends null ? TNull :
|
||||
T extends symbol ? TSymbol :
|
||||
T extends number ? TLiteral<T> :
|
||||
T extends boolean ? TLiteral<T> :
|
||||
T extends string ? TLiteral<T> :
|
||||
T extends bigint ? TBigInt :
|
||||
TObject<{}>
|
||||
// prettier-ignore
|
||||
function FromValue<T, Root extends boolean>(value: T, root: Root): FromValue<T, Root> {
|
||||
return (
|
||||
IsAsyncIterator(value) ? ConditionalReadonly(Any(), root) :
|
||||
IsIterator(value) ? ConditionalReadonly(Any(), root) :
|
||||
IsArray(value) ? Readonly(Tuple(FromArray(value) as TSchema[])) :
|
||||
IsUint8Array(value) ? Uint8Array() :
|
||||
IsDate(value) ? Date() :
|
||||
IsObject(value) ? ConditionalReadonly(Object(FromProperties(value as Record<PropertyKey, unknown>) as TProperties), root) :
|
||||
IsFunction(value) ? ConditionalReadonly(FunctionType([], Unknown()), root) :
|
||||
IsUndefined(value) ? Undefined() :
|
||||
IsNull(value) ? Null() :
|
||||
IsSymbol(value) ? Symbol() :
|
||||
IsBigInt(value) ? BigInt() :
|
||||
IsNumber(value) ? Literal(value) :
|
||||
IsBoolean(value) ? Literal(value) :
|
||||
IsString(value) ? Literal(value) :
|
||||
Object({})
|
||||
) as FromValue<T, Root>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TConst
|
||||
// ------------------------------------------------------------------
|
||||
export type TConst<T> = FromValue<T, true>
|
||||
|
||||
/** `[JavaScript]` Creates a readonly const type from the given value. */
|
||||
export function Const</* const (not supported in 4.0) */ T>(T: T, options: SchemaOptions = {}): TConst<T> {
|
||||
return TypeClone.CloneType(FromValue(T, true), options) as TConst<T>
|
||||
}
|
||||
29
src/type/const/index.ts
Normal file
29
src/type/const/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './const'
|
||||
46
src/type/constructor-parameters/constructor-parameters.ts
Normal file
46
src/type/constructor-parameters/constructor-parameters.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Ensure } from '../helpers/index'
|
||||
import type { TConstructor } from '../constructor/index'
|
||||
import { Tuple, type TTuple } from '../tuple/index'
|
||||
import { CloneRest } from '../clone/type'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ConstructorParameters
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TConstructorParameters<T extends TConstructor<TSchema[], TSchema>> = (
|
||||
Ensure<TTuple<T['parameters']>>
|
||||
)
|
||||
|
||||
/** `[JavaScript]` Extracts the ConstructorParameters from the given Constructor type */
|
||||
export function ConstructorParameters<T extends TConstructor<TSchema[], TSchema>>(schema: T, options: SchemaOptions = {}): TConstructorParameters<T> {
|
||||
return Tuple(CloneRest(schema.parameters), { ...options })
|
||||
}
|
||||
29
src/type/constructor-parameters/index.ts
Normal file
29
src/type/constructor-parameters/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './constructor-parameters'
|
||||
67
src/type/constructor/constructor.ts
Normal file
67
src/type/constructor/constructor.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import type { Ensure } from '../helpers/index'
|
||||
import { CloneType, CloneRest } from '../clone/type'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TConstructorStatic
|
||||
// ------------------------------------------------------------------
|
||||
type ConstructorStaticReturnType<T extends TSchema, P extends unknown[]> = Static<T, P>
|
||||
// prettier-ignore
|
||||
type ConstructorStaticParameters<T extends TSchema[], P extends unknown[], Acc extends unknown[] = []> =
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? ConstructorStaticParameters<R, P, [...Acc, Static<L, P>]>
|
||||
: Acc
|
||||
// prettier-ignore
|
||||
type ConstructorStatic<T extends TSchema[], U extends TSchema, P extends unknown[]> = (
|
||||
Ensure<new (...param: ConstructorStaticParameters<T, P>) => ConstructorStaticReturnType<U, P>>
|
||||
)
|
||||
// ------------------------------------------------------------------
|
||||
// TConstructor
|
||||
// ------------------------------------------------------------------
|
||||
export interface TConstructor<T extends TSchema[] = TSchema[], U extends TSchema = TSchema> extends TSchema {
|
||||
[Kind]: 'Constructor'
|
||||
static: ConstructorStatic<T, U, this['params']>
|
||||
type: 'Constructor'
|
||||
parameters: T
|
||||
returns: U
|
||||
}
|
||||
/** `[JavaScript]` Creates a Constructor type */
|
||||
export function Constructor<T extends TSchema[], U extends TSchema>(parameters: [...T], returns: U, options?: SchemaOptions): TConstructor<T, U> {
|
||||
return {
|
||||
...options,
|
||||
[Kind]: 'Constructor',
|
||||
type: 'Constructor',
|
||||
parameters: CloneRest(parameters),
|
||||
returns: CloneType(returns),
|
||||
} as unknown as TConstructor<T, U>
|
||||
}
|
||||
29
src/type/constructor/index.ts
Normal file
29
src/type/constructor/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './constructor'
|
||||
56
src/type/date/date.ts
Normal file
56
src/type/date/date.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
export interface DateOptions extends SchemaOptions {
|
||||
/** The exclusive maximum timestamp value */
|
||||
exclusiveMaximumTimestamp?: number
|
||||
/** The exclusive minimum timestamp value */
|
||||
exclusiveMinimumTimestamp?: number
|
||||
/** The maximum timestamp value */
|
||||
maximumTimestamp?: number
|
||||
/** The minimum timestamp value */
|
||||
minimumTimestamp?: number
|
||||
/** The multiple of timestamp value */
|
||||
multipleOfTimestamp?: number
|
||||
}
|
||||
export interface TDate extends TSchema, DateOptions {
|
||||
[Kind]: 'Date'
|
||||
static: Date
|
||||
type: 'date'
|
||||
}
|
||||
/** `[JavaScript]` Creates a Date type */
|
||||
export function Date(options: DateOptions = {}): TDate {
|
||||
return {
|
||||
...options,
|
||||
[Kind]: 'Date',
|
||||
type: 'Date',
|
||||
} as unknown as TDate
|
||||
}
|
||||
29
src/type/date/index.ts
Normal file
29
src/type/date/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './date'
|
||||
174
src/type/deref/deref.ts
Normal file
174
src/type/deref/deref.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema } from '../schema/index'
|
||||
import type { Evaluate } from '../helpers/index'
|
||||
import type { TTuple } from '../tuple/index'
|
||||
import type { TIntersect } from '../intersect/index'
|
||||
import type { TUnion } from '../union/index'
|
||||
import type { TPromise } from '../promise/index'
|
||||
import type { TAsyncIterator } from '../async-iterator/index'
|
||||
import type { TIterator } from '../iterator/index'
|
||||
import type { TArray } from '../array/index'
|
||||
import type { TConstructor } from '../constructor/index'
|
||||
import type { TFunction } from '../function/index'
|
||||
import type { TRef } from '../ref/index'
|
||||
import type { TObject, TProperties } from '../object/index'
|
||||
import { CloneType, CloneRest } from '../clone/type'
|
||||
import { Discard } from '../discard/index'
|
||||
import { IsUndefined } from '../guard/value'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsConstructor, IsFunction, IsIntersect, IsUnion, IsTuple, IsArray, IsObject, IsPromise, IsAsyncIterator, IsIterator, IsRef } from '../guard/type'
|
||||
// ------------------------------------------------------------------
|
||||
// FromRest
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TFromRest<T extends TSchema[], Acc extends TSchema[] = []> = (
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? TFromRest<R, [...Acc, DerefResolve<L>]>
|
||||
: Acc
|
||||
)
|
||||
function FromRest(schema: TSchema[], references: TSchema[]) {
|
||||
return schema.map((schema) => Deref(schema, references))
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type FromProperties<T extends TProperties> = Evaluate<{
|
||||
[K in keyof T]: DerefResolve<T[K]>
|
||||
}>
|
||||
// prettier-ignore
|
||||
function FromProperties(properties: TProperties, references: TSchema[]) {
|
||||
return globalThis.Object.getOwnPropertyNames(properties).reduce((acc, key) => {
|
||||
return {...acc, [key]: Deref(properties[key], references) }
|
||||
}, {} as TProperties)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromConstructor(schema: TConstructor, references: TSchema[]) {
|
||||
schema.parameters = FromRest(schema.parameters, references)
|
||||
schema.returns = Deref(schema.returns, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromFunction(schema: TFunction, references: TSchema[]) {
|
||||
schema.parameters = FromRest(schema.parameters, references)
|
||||
schema.returns = Deref(schema.returns, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromIntersect(schema: TIntersect, references: TSchema[]) {
|
||||
schema.allOf = FromRest(schema.allOf, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromUnion(schema: TUnion, references: TSchema[]) {
|
||||
schema.anyOf = FromRest(schema.anyOf, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromTuple(schema: TTuple, references: TSchema[]) {
|
||||
if(IsUndefined(schema.items)) return schema
|
||||
schema.items = FromRest(schema.items, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromArray(schema: TArray, references: TSchema[]) {
|
||||
schema.items = Deref(schema.items, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromObject(schema: TObject, references: TSchema[]) {
|
||||
schema.properties = FromProperties(schema.properties, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromPromise(schema: TPromise, references: TSchema[]) {
|
||||
schema.item = Deref(schema.item, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromAsyncIterator(schema: TAsyncIterator, references: TSchema[]) {
|
||||
schema.items = Deref(schema.items, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromIterator(schema: TIterator, references: TSchema[]) {
|
||||
schema.items = Deref(schema.items, references)
|
||||
return schema
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromRef(schema: TRef, references: TSchema[]) {
|
||||
const target = references.find(remote => remote.$id === schema.$ref)
|
||||
if(target === undefined) throw Error(`Unable to dereference schema with $id ${schema.$ref}`)
|
||||
const discard = Discard(target, ['$id']) as TSchema
|
||||
return Deref(discard, references)
|
||||
}
|
||||
// prettier-ignore
|
||||
export type DerefResolve<T extends TSchema> =
|
||||
T extends TConstructor<infer S extends TSchema[], infer R extends TSchema> ? TConstructor<TFromRest<S>, DerefResolve<R>> :
|
||||
T extends TFunction<infer S extends TSchema[], infer R extends TSchema> ? TFunction<TFromRest<S>, DerefResolve<R>> :
|
||||
T extends TIntersect<infer S extends TSchema[]> ? TIntersect<TFromRest<S>> :
|
||||
T extends TUnion<infer S extends TSchema[]> ? TUnion<TFromRest<S>> :
|
||||
T extends TTuple<infer S extends TSchema[]> ? TTuple<TFromRest<S>> :
|
||||
T extends TObject<infer S extends TProperties> ? TObject<FromProperties<S>> :
|
||||
T extends TArray<infer S extends TSchema> ? TArray<DerefResolve<S>> :
|
||||
T extends TPromise<infer S extends TSchema> ? TPromise<DerefResolve<S>> :
|
||||
T extends TAsyncIterator<infer S extends TSchema> ? TAsyncIterator<DerefResolve<S>> :
|
||||
T extends TIterator<infer S extends TSchema> ? TIterator<DerefResolve<S>> :
|
||||
T extends TRef<infer S extends TSchema> ? DerefResolve<S> :
|
||||
T
|
||||
// prettier-ignore
|
||||
export function DerefResolve<T extends TSchema>(schema: T, references: TSchema[]): TDeref<T> {
|
||||
return (
|
||||
IsConstructor(schema) ? FromConstructor(schema, references) :
|
||||
IsFunction(schema) ? FromFunction(schema, references) :
|
||||
IsIntersect(schema) ? FromIntersect(schema, references) :
|
||||
IsUnion(schema) ? FromUnion(schema, references) :
|
||||
IsTuple(schema) ? FromTuple(schema, references) :
|
||||
IsArray(schema) ? FromArray(schema, references) :
|
||||
IsObject(schema) ? FromObject(schema, references) :
|
||||
IsPromise(schema) ? FromPromise(schema, references) :
|
||||
IsAsyncIterator(schema) ? FromAsyncIterator(schema, references) :
|
||||
IsIterator(schema) ? FromIterator(schema, references) :
|
||||
IsRef(schema) ? FromRef(schema, references) :
|
||||
schema
|
||||
) as TDeref<T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TDeref
|
||||
// ------------------------------------------------------------------
|
||||
export type TDeref<T extends TSchema> = DerefResolve<T>
|
||||
|
||||
/** `[Json]` Creates a dereferenced type */
|
||||
export function Deref<T extends TSchema>(schema: T, references: TSchema[]): TDeref<T> {
|
||||
return DerefResolve(CloneType(schema), CloneRest(references))
|
||||
}
|
||||
29
src/type/deref/index.ts
Normal file
29
src/type/deref/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './deref'
|
||||
35
src/type/discard/discard.ts
Normal file
35
src/type/discard/discard.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
function DiscardKey(value: Record<PropertyKey, any>, key: PropertyKey) {
|
||||
const { [key]: _, ...rest } = value
|
||||
return rest
|
||||
}
|
||||
export function Discard(value: Record<PropertyKey, any>, keys: PropertyKey[]) {
|
||||
return keys.reduce((acc, key) => DiscardKey(acc, key), value)
|
||||
}
|
||||
29
src/type/discard/index.ts
Normal file
29
src/type/discard/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './discard'
|
||||
58
src/type/enum/enum.ts
Normal file
58
src/type/enum/enum.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import { Literal, type TLiteral } from '../literal/index'
|
||||
import { Kind, Hint } from '../symbols/index'
|
||||
import { Union } from '../union/index'
|
||||
// ------------------------------------------------------------------
|
||||
// ValueGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsUndefined } from '../guard/value'
|
||||
// ------------------------------------------------------------------
|
||||
// TEnum
|
||||
// ------------------------------------------------------------------
|
||||
export type TEnumRecord = Record<TEnumKey, TEnumValue>
|
||||
export type TEnumValue = string | number
|
||||
export type TEnumKey = string
|
||||
export interface TEnum<T extends Record<string, string | number> = Record<string, string | number>> extends TSchema {
|
||||
[Kind]: 'Union'
|
||||
[Hint]: 'Enum'
|
||||
static: T[keyof T]
|
||||
anyOf: TLiteral<T[keyof T]>[]
|
||||
}
|
||||
/** `[Json]` Creates a Enum type */
|
||||
export function Enum<V extends TEnumValue, T extends Record<TEnumKey, V>>(item: T, options: SchemaOptions = {}): TEnum<T> {
|
||||
if (IsUndefined(item)) throw new Error('Enum undefined or empty')
|
||||
const values1 = globalThis.Object.getOwnPropertyNames(item)
|
||||
.filter((key) => isNaN(key as any))
|
||||
.map((key) => item[key]) as T[keyof T][]
|
||||
const values2 = [...new Set(values1)]
|
||||
const anyOf = values2.map((value) => Literal(value))
|
||||
return Union(anyOf, { ...options, [Hint]: 'Enum' }) as unknown as TEnum<T>
|
||||
}
|
||||
29
src/type/enum/index.ts
Normal file
29
src/type/enum/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './enum'
|
||||
34
src/type/error/error.ts
Normal file
34
src/type/error/error.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** The base Error type thrown for all TypeBox exceptions */
|
||||
export class TypeBoxError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
29
src/type/error/index.ts
Normal file
29
src/type/error/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './error'
|
||||
89
src/type/exclude/exclude-from-mapped-result.ts
Normal file
89
src/type/exclude/exclude-from-mapped-result.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import { MappedResult, type TMappedResult } from '../mapped/index'
|
||||
import { Exclude, type TExclude } from './exclude'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<
|
||||
K extends TProperties,
|
||||
T extends TSchema
|
||||
> = (
|
||||
{ [K2 in keyof K]: TExclude<K[K2], T> }
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromProperties<
|
||||
P extends TProperties,
|
||||
T extends TSchema
|
||||
>(P: P, U: T, options: SchemaOptions): TFromProperties<P, T> {
|
||||
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
|
||||
return {...Acc, [K2]: Exclude(P[K2], U, options) }
|
||||
}, {}) as TFromProperties<P, T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema
|
||||
> = (
|
||||
TFromProperties<R['properties'], T>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema
|
||||
>(R: R, T: T, options: SchemaOptions): TFromMappedResult<R, T> {
|
||||
return FromProperties(R.properties, T, options) as TFromMappedResult<R, T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ExcludeFromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExcludeFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<R, T>
|
||||
> = (
|
||||
TMappedResult<P>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function ExcludeFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<R, T>
|
||||
>(R: R, T: T, options: SchemaOptions): TMappedResult<P> {
|
||||
const P = FromMappedResult(R, T, options) as unknown as P
|
||||
return MappedResult(P)
|
||||
}
|
||||
96
src/type/exclude/exclude.ts
Normal file
96
src/type/exclude/exclude.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { UnionToTuple, AssertRest, AssertType, Assert } from '../helpers/index'
|
||||
import type { TMappedResult } from '../mapped/index'
|
||||
import { TemplateLiteralToUnion, type TTemplateLiteral } from '../template-literal/index'
|
||||
import { Union, type TUnion } from '../union/index'
|
||||
import { Never, type TNever } from '../never/index'
|
||||
import { type TLiteral } from '../literal/index'
|
||||
import { type Static } from '../static/index'
|
||||
import { type TUnionEvaluated } from '../union/index'
|
||||
import { ExtendsCheck, ExtendsResult } from '../extends/index'
|
||||
import { CloneType } from '../clone/type'
|
||||
import { ExcludeFromMappedResult, type TExcludeFromMappedResult } from './exclude-from-mapped-result'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/type'
|
||||
// ------------------------------------------------------------------
|
||||
// ExcludeResolve
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TExcludeTemplateLiteralResult<T extends string> = TUnionEvaluated<AssertRest<UnionToTuple<{ [K in T]: TLiteral<K> }[T]>>>
|
||||
// prettier-ignore
|
||||
type TExcludeTemplateLiteral<T extends TTemplateLiteral, U extends TSchema> = (
|
||||
Exclude<Static<T>, Static<U>> extends infer S ? TExcludeTemplateLiteralResult<Assert<S, string>> : never
|
||||
)
|
||||
// prettier-ignore
|
||||
type TExcludeArray<T extends TSchema[], U extends TSchema> = AssertRest<UnionToTuple<{
|
||||
[K in keyof T]: Static<AssertType<T[K]>> extends Static<U> ? never : T[K]
|
||||
}[number]>> extends infer R extends TSchema[] ? TUnionEvaluated<R> : never
|
||||
// prettier-ignore
|
||||
type TExcludeResolve<T extends TSchema, U extends TSchema> =
|
||||
T extends TTemplateLiteral ? TExcludeTemplateLiteral<T, U> :
|
||||
T extends TUnion<infer S> ? TExcludeArray<S, U> :
|
||||
T extends U
|
||||
? TNever
|
||||
: T
|
||||
// prettier-ignore
|
||||
function ExcludeResolve<L extends TSchema, R extends TSchema>(L: L, R: R): TExcludeResolve<L, R> {
|
||||
return (
|
||||
IsTemplateLiteral(L) ? ExcludeResolve(TemplateLiteralToUnion(L), R) :
|
||||
IsTemplateLiteral(R) ? ExcludeResolve(L, TemplateLiteralToUnion(R)) :
|
||||
IsUnion(L) ? (() => {
|
||||
const narrowed = L.anyOf.filter((inner) => ExtendsCheck(inner, R) === ExtendsResult.False)
|
||||
return (narrowed.length === 1 ? narrowed[0] : Union(narrowed))
|
||||
})() :
|
||||
ExtendsCheck(L, R) !== ExtendsResult.False ? Never() :
|
||||
L
|
||||
) as TExcludeResolve<L, R>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TExclude
|
||||
// ------------------------------------------------------------------
|
||||
export type TExclude<T extends TSchema, U extends TSchema> = TExcludeResolve<T, U>
|
||||
|
||||
/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */
|
||||
export function Exclude<L extends TMappedResult, R extends TSchema>(unionType: L, excludedMembers: R, options?: SchemaOptions): TExcludeFromMappedResult<L, R>
|
||||
/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */
|
||||
export function Exclude<L extends TSchema, R extends TSchema>(unionType: L, excludedMembers: R, options?: SchemaOptions): TExclude<L, R>
|
||||
/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */
|
||||
export function Exclude(unionType: TSchema, excludedMembers: TSchema, options: SchemaOptions = {}) {
|
||||
if (IsMappedResult(unionType)) {
|
||||
return ExcludeFromMappedResult(unionType, excludedMembers, options)
|
||||
} else {
|
||||
const E = ExcludeResolve(unionType, excludedMembers) as any
|
||||
return CloneType(E, options)
|
||||
}
|
||||
}
|
||||
30
src/type/exclude/index.ts
Normal file
30
src/type/exclude/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './exclude-from-mapped-result'
|
||||
export * from './exclude'
|
||||
776
src/type/extends/extends-check.ts
Normal file
776
src/type/extends/extends-check.ts
Normal file
@@ -0,0 +1,776 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 TAny, Any } from '../any/index'
|
||||
import { type TArray } from '../array/index'
|
||||
import { type TAsyncIterator } from '../async-iterator/index'
|
||||
import { type TBigInt } from '../bigint/index'
|
||||
import { type TBoolean } from '../boolean/index'
|
||||
import { type TConstructor } from '../constructor/index'
|
||||
import { type TDate } from '../date/index'
|
||||
import { type TFunction, Function as FunctionType } from '../function/index'
|
||||
import { type TInteger } from '../integer/index'
|
||||
import { type TIntersect } from '../intersect/index'
|
||||
import { type TIterator } from '../iterator/index'
|
||||
import { type TLiteral } from '../literal/index'
|
||||
import { type TNever } from '../never/index'
|
||||
import { type TNot } from '../not/index'
|
||||
import { type TNull } from '../null/index'
|
||||
import { type TNumber, Number } from '../number/index'
|
||||
import { type TObject } from '../object/index'
|
||||
import { type TPromise } from '../promise/index'
|
||||
import { type TRecord } from '../record/index'
|
||||
import { type TSchema } from '../schema/index'
|
||||
import { type TString, String } from '../string/index'
|
||||
import { type TSymbol } from '../symbol/index'
|
||||
import { type TTuple } from '../tuple/index'
|
||||
import { type TUint8Array } from '../uint8array/index'
|
||||
import { type TUndefined } from '../undefined/index'
|
||||
import { type TUnion } from '../union/index'
|
||||
import { type TUnknown, Unknown } from '../unknown/index'
|
||||
import { type TVoid } from '../void/index'
|
||||
|
||||
import { TemplateLiteralToUnion } from '../template-literal/index'
|
||||
import { PatternNumberExact, PatternStringExact } from '../patterns/index'
|
||||
import { Kind, Hint } from '../symbols/index'
|
||||
import { TypeBoxError } from '../error/index'
|
||||
import { TypeGuard, ValueGuard } from '../guard/index'
|
||||
|
||||
export class ExtendsResolverError extends TypeBoxError {}
|
||||
|
||||
export enum ExtendsResult {
|
||||
Union,
|
||||
True,
|
||||
False,
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// IntoBooleanResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IntoBooleanResult(result: ExtendsResult) {
|
||||
return result === ExtendsResult.False ? result : ExtendsResult.True
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Throw
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function Throw(message: string): never {
|
||||
throw new ExtendsResolverError(message)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// StructuralRight
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IsStructuralRight(right: TSchema): boolean {
|
||||
return (
|
||||
TypeGuard.IsNever(right) ||
|
||||
TypeGuard.IsIntersect(right) ||
|
||||
TypeGuard.IsUnion(right) ||
|
||||
TypeGuard.IsUnknown(right) ||
|
||||
TypeGuard.IsAny(right)
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function StructuralRight(left: TSchema, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsNever(right) ? FromNeverRight(left, right) :
|
||||
TypeGuard.IsIntersect(right) ? FromIntersectRight(left, right) :
|
||||
TypeGuard.IsUnion(right) ? FromUnionRight(left, right) :
|
||||
TypeGuard.IsUnknown(right) ? FromUnknownRight(left, right) :
|
||||
TypeGuard.IsAny(right) ? FromAnyRight(left, right) :
|
||||
Throw('StructuralRight')
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Any
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromAnyRight(left: TSchema, right: TAny) {
|
||||
return ExtendsResult.True
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromAny(left: TAny, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsIntersect(right) ? FromIntersectRight(left, right) :
|
||||
(TypeGuard.IsUnion(right) && right.anyOf.some((schema) => TypeGuard.IsAny(schema) || TypeGuard.IsUnknown(schema))) ? ExtendsResult.True :
|
||||
TypeGuard.IsUnion(right) ? ExtendsResult.Union :
|
||||
TypeGuard.IsUnknown(right) ? ExtendsResult.True :
|
||||
TypeGuard.IsAny(right) ? ExtendsResult.True :
|
||||
ExtendsResult.Union
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Array
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromArrayRight(left: TSchema, right: TArray) {
|
||||
return (
|
||||
TypeGuard.IsUnknown(left) ? ExtendsResult.False :
|
||||
TypeGuard.IsAny(left) ? ExtendsResult.Union :
|
||||
TypeGuard.IsNever(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromArray(left: TArray, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsObject(right) && IsObjectArrayLike(right) ? ExtendsResult.True :
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
!TypeGuard.IsArray(right) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.items, right.items))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// AsyncIterator
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromAsyncIterator(left: TAsyncIterator, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
!TypeGuard.IsAsyncIterator(right) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.items, right.items))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// BigInt
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromBigInt(left: TBigInt, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsBigInt(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Boolean
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromBooleanRight(left: TSchema, right: TBoolean) {
|
||||
return (
|
||||
TypeGuard.IsLiteralBoolean(left) ? ExtendsResult.True :
|
||||
TypeGuard.IsBoolean(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromBoolean(left: TBoolean, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsBoolean(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromConstructor(left: TConstructor, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
!TypeGuard.IsConstructor(right) ? ExtendsResult.False :
|
||||
left.parameters.length > right.parameters.length ? ExtendsResult.False :
|
||||
(!left.parameters.every((schema, index) => IntoBooleanResult(Visit(right.parameters[index], schema)) === ExtendsResult.True)) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.returns, right.returns))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Date
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromDate(left: TDate, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsDate(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Function
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromFunction(left: TFunction, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
!TypeGuard.IsFunction(right) ? ExtendsResult.False :
|
||||
left.parameters.length > right.parameters.length ? ExtendsResult.False :
|
||||
(!left.parameters.every((schema, index) => IntoBooleanResult(Visit(right.parameters[index], schema)) === ExtendsResult.True)) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.returns, right.returns))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Integer
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromIntegerRight(left: TSchema, right: TInteger) {
|
||||
return (
|
||||
TypeGuard.IsLiteral(left) && ValueGuard.IsNumber(left.const) ? ExtendsResult.True :
|
||||
TypeGuard.IsNumber(left) || TypeGuard.IsInteger(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromInteger(left: TInteger, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
TypeGuard.IsInteger(right) || TypeGuard.IsNumber(right) ? ExtendsResult.True :
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Intersect
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromIntersectRight(left: TSchema, right: TIntersect): ExtendsResult {
|
||||
return right.allOf.every((schema) => Visit(left, schema) === ExtendsResult.True)
|
||||
? ExtendsResult.True
|
||||
: ExtendsResult.False
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromIntersect(left: TIntersect, right: TSchema) {
|
||||
return left.allOf.some((schema) => Visit(schema, right) === ExtendsResult.True)
|
||||
? ExtendsResult.True
|
||||
: ExtendsResult.False
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Iterator
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromIterator(left: TIterator, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
!TypeGuard.IsIterator(right) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.items, right.items))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Literal
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromLiteral(left: TLiteral, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
TypeGuard.IsLiteral(right) && right.const === left.const ? ExtendsResult.True :
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsString(right) ? FromStringRight(left, right) :
|
||||
TypeGuard.IsNumber(right) ? FromNumberRight(left, right) :
|
||||
TypeGuard.IsInteger(right) ? FromIntegerRight(left, right) :
|
||||
TypeGuard.IsBoolean(right) ? FromBooleanRight(left, right) :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Never
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromNeverRight(left: TSchema, right: TNever) {
|
||||
return ExtendsResult.False
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromNever(left: TNever, right: TSchema) {
|
||||
return ExtendsResult.True
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Not
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function UnwrapTNot<T extends TNot>(schema: T): TUnknown | TNot['not'] {
|
||||
let [current, depth]: [TSchema, number] = [schema, 0]
|
||||
while (true) {
|
||||
if (!TypeGuard.IsNot(current)) break
|
||||
current = current.not
|
||||
depth += 1
|
||||
}
|
||||
return depth % 2 === 0 ? current : Unknown()
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromNot(left: TSchema, right: TSchema) {
|
||||
// TypeScript has no concept of negated types, and attempts to correctly check the negated
|
||||
// type at runtime would put TypeBox at odds with TypeScripts ability to statically infer
|
||||
// the type. Instead we unwrap to either unknown or T and continue evaluating.
|
||||
// prettier-ignore
|
||||
return (
|
||||
TypeGuard.IsNot(left) ? Visit(UnwrapTNot(left), right) :
|
||||
TypeGuard.IsNot(right) ? Visit(left, UnwrapTNot(right)) :
|
||||
Throw('Invalid fallthrough for Not')
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Null
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromNull(left: TNull, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsNull(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Number
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromNumberRight(left: TSchema, right: TNumber) {
|
||||
return (
|
||||
TypeGuard.IsLiteralNumber(left) ? ExtendsResult.True :
|
||||
TypeGuard.IsNumber(left) || TypeGuard.IsInteger(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromNumber(left: TNumber, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsInteger(right) || TypeGuard.IsNumber(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Object
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IsObjectPropertyCount(schema: TObject, count: number) {
|
||||
return Object.getOwnPropertyNames(schema.properties).length === count
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectStringLike(schema: TObject) {
|
||||
return IsObjectArrayLike(schema)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectSymbolLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0) || (
|
||||
IsObjectPropertyCount(schema, 1) && 'description' in schema.properties && TypeGuard.IsUnion(schema.properties.description) && schema.properties.description.anyOf.length === 2 && ((
|
||||
TypeGuard.IsString(schema.properties.description.anyOf[0]) &&
|
||||
TypeGuard.IsUndefined(schema.properties.description.anyOf[1])
|
||||
) || (
|
||||
TypeGuard.IsString(schema.properties.description.anyOf[1]) &&
|
||||
TypeGuard.IsUndefined(schema.properties.description.anyOf[0])
|
||||
))
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectNumberLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectBooleanLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectBigIntLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectDateLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectUint8ArrayLike(schema: TObject) {
|
||||
return IsObjectArrayLike(schema)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectFunctionLike(schema: TObject) {
|
||||
const length = Number()
|
||||
return IsObjectPropertyCount(schema, 0) || (IsObjectPropertyCount(schema, 1) && 'length' in schema.properties && IntoBooleanResult(Visit(schema.properties['length'], length)) === ExtendsResult.True)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectConstructorLike(schema: TObject) {
|
||||
return IsObjectPropertyCount(schema, 0)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectArrayLike(schema: TObject) {
|
||||
const length = Number()
|
||||
return IsObjectPropertyCount(schema, 0) || (IsObjectPropertyCount(schema, 1) && 'length' in schema.properties && IntoBooleanResult(Visit(schema.properties['length'], length)) === ExtendsResult.True)
|
||||
}
|
||||
// prettier-ignore
|
||||
function IsObjectPromiseLike(schema: TObject) {
|
||||
const then = FunctionType([Any()], Any())
|
||||
return IsObjectPropertyCount(schema, 0) || (IsObjectPropertyCount(schema, 1) && 'then' in schema.properties && IntoBooleanResult(Visit(schema.properties['then'], then)) === ExtendsResult.True)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Property
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function Property(left: TSchema, right: TSchema) {
|
||||
return (
|
||||
Visit(left, right) === ExtendsResult.False ? ExtendsResult.False :
|
||||
TypeGuard.IsOptional(left) && !TypeGuard.IsOptional(right) ? ExtendsResult.False :
|
||||
ExtendsResult.True
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromObjectRight(left: TSchema, right: TObject) {
|
||||
return (
|
||||
TypeGuard.IsUnknown(left) ? ExtendsResult.False :
|
||||
TypeGuard.IsAny(left) ? ExtendsResult.Union : (
|
||||
TypeGuard.IsNever(left) ||
|
||||
(TypeGuard.IsLiteralString(left) && IsObjectStringLike(right)) ||
|
||||
(TypeGuard.IsLiteralNumber(left) && IsObjectNumberLike(right)) ||
|
||||
(TypeGuard.IsLiteralBoolean(left) && IsObjectBooleanLike(right)) ||
|
||||
(TypeGuard.IsSymbol(left) && IsObjectSymbolLike(right)) ||
|
||||
(TypeGuard.IsBigInt(left) && IsObjectBigIntLike(right)) ||
|
||||
(TypeGuard.IsString(left) && IsObjectStringLike(right)) ||
|
||||
(TypeGuard.IsSymbol(left) && IsObjectSymbolLike(right)) ||
|
||||
(TypeGuard.IsNumber(left) && IsObjectNumberLike(right)) ||
|
||||
(TypeGuard.IsInteger(left) && IsObjectNumberLike(right)) ||
|
||||
(TypeGuard.IsBoolean(left) && IsObjectBooleanLike(right)) ||
|
||||
(TypeGuard.IsUint8Array(left) && IsObjectUint8ArrayLike(right)) ||
|
||||
(TypeGuard.IsDate(left) && IsObjectDateLike(right)) ||
|
||||
(TypeGuard.IsConstructor(left) && IsObjectConstructorLike(right)) ||
|
||||
(TypeGuard.IsFunction(left) && IsObjectFunctionLike(right))
|
||||
) ? ExtendsResult.True :
|
||||
(TypeGuard.IsRecord(left) && TypeGuard.IsString(RecordKey(left))) ? (() => {
|
||||
// When expressing a Record with literal key values, the Record is converted into a Object with
|
||||
// the Hint assigned as `Record`. This is used to invert the extends logic.
|
||||
return right[Hint] === 'Record' ? ExtendsResult.True : ExtendsResult.False
|
||||
})() :
|
||||
(TypeGuard.IsRecord(left) && TypeGuard.IsNumber(RecordKey(left))) ? (() => {
|
||||
return IsObjectPropertyCount(right, 0) ? ExtendsResult.True : ExtendsResult.False
|
||||
})() :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromObject(left: TObject, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
!TypeGuard.IsObject(right) ? ExtendsResult.False :
|
||||
(() => {
|
||||
for (const key of Object.getOwnPropertyNames(right.properties)) {
|
||||
if (!(key in left.properties) && !TypeGuard.IsOptional(right.properties[key])) {
|
||||
return ExtendsResult.False
|
||||
}
|
||||
if (TypeGuard.IsOptional(right.properties[key])) {
|
||||
return ExtendsResult.True
|
||||
}
|
||||
if (Property(left.properties[key], right.properties[key]) === ExtendsResult.False) {
|
||||
return ExtendsResult.False
|
||||
}
|
||||
}
|
||||
return ExtendsResult.True
|
||||
})()
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Promise
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromPromise(left: TPromise, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) && IsObjectPromiseLike(right) ? ExtendsResult.True :
|
||||
!TypeGuard.IsPromise(right) ? ExtendsResult.False :
|
||||
IntoBooleanResult(Visit(left.item, right.item))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Record
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function RecordKey(schema: TRecord) {
|
||||
return (
|
||||
PatternNumberExact in schema.patternProperties ? Number() :
|
||||
PatternStringExact in schema.patternProperties ? String() :
|
||||
Throw('Unknown record key pattern')
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function RecordValue(schema: TRecord) {
|
||||
return (
|
||||
PatternNumberExact in schema.patternProperties ? schema.patternProperties[PatternNumberExact] :
|
||||
PatternStringExact in schema.patternProperties ? schema.patternProperties[PatternStringExact] :
|
||||
Throw('Unable to get record value schema')
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromRecordRight(left: TSchema, right: TRecord) {
|
||||
const [Key, Value] = [RecordKey(right), RecordValue(right)]
|
||||
return (
|
||||
(
|
||||
TypeGuard.IsLiteralString(left) && TypeGuard.IsNumber(Key) && IntoBooleanResult(Visit(left, Value)) === ExtendsResult.True) ? ExtendsResult.True :
|
||||
TypeGuard.IsUint8Array(left) && TypeGuard.IsNumber(Key) ? Visit(left, Value) :
|
||||
TypeGuard.IsString(left) && TypeGuard.IsNumber(Key) ? Visit(left, Value) :
|
||||
TypeGuard.IsArray(left) && TypeGuard.IsNumber(Key) ? Visit(left, Value) :
|
||||
TypeGuard.IsObject(left) ? (() => {
|
||||
for (const key of Object.getOwnPropertyNames(left.properties)) {
|
||||
if (Property(Value, left.properties[key]) === ExtendsResult.False) {
|
||||
return ExtendsResult.False
|
||||
}
|
||||
}
|
||||
return ExtendsResult.True
|
||||
})() :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromRecord(left: TRecord, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
!TypeGuard.IsRecord(right) ? ExtendsResult.False :
|
||||
Visit(RecordValue(left), RecordValue(right))
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// RegExp
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromRegExp(left: TSchema, right: TSchema) {
|
||||
// Note: RegExp types evaluate as strings, not RegExp objects.
|
||||
// Here we remap either into string and continue evaluating.
|
||||
const L = TypeGuard.IsRegExp(left) ? String() : left
|
||||
const R = TypeGuard.IsRegExp(right) ? String() : right
|
||||
return Visit(L, R)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// String
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromStringRight(left: TSchema, right: TString) {
|
||||
return (
|
||||
TypeGuard.IsLiteral(left) && ValueGuard.IsString(left.const) ? ExtendsResult.True :
|
||||
TypeGuard.IsString(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromString(left: TString, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsString(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Symbol
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromSymbol(left: TSymbol, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsSymbol(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TemplateLiteral
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromTemplateLiteral(left: TSchema, right: TSchema) {
|
||||
// TemplateLiteral types are resolved to either unions for finite expressions or string
|
||||
// for infinite expressions. Here we call to TemplateLiteralResolver to resolve for
|
||||
// either type and continue evaluating.
|
||||
return (
|
||||
TypeGuard.IsTemplateLiteral(left) ? Visit(TemplateLiteralToUnion(left), right) :
|
||||
TypeGuard.IsTemplateLiteral(right) ? Visit(left, TemplateLiteralToUnion(right)) :
|
||||
Throw('Invalid fallthrough for TemplateLiteral')
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Tuple
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function IsArrayOfTuple(left: TTuple, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsArray(right) &&
|
||||
left.items !== undefined &&
|
||||
left.items.every((schema) => Visit(schema, right.items) === ExtendsResult.True)
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromTupleRight(left: TSchema, right: TTuple) {
|
||||
return (
|
||||
TypeGuard.IsNever(left) ? ExtendsResult.True :
|
||||
TypeGuard.IsUnknown(left) ? ExtendsResult.False :
|
||||
TypeGuard.IsAny(left) ? ExtendsResult.Union :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromTuple(left: TTuple, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) && IsObjectArrayLike(right) ? ExtendsResult.True :
|
||||
TypeGuard.IsArray(right) && IsArrayOfTuple(left, right) ? ExtendsResult.True :
|
||||
!TypeGuard.IsTuple(right) ? ExtendsResult.False :
|
||||
(ValueGuard.IsUndefined(left.items) && !ValueGuard.IsUndefined(right.items)) || (!ValueGuard.IsUndefined(left.items) && ValueGuard.IsUndefined(right.items)) ? ExtendsResult.False :
|
||||
(ValueGuard.IsUndefined(left.items) && !ValueGuard.IsUndefined(right.items)) ? ExtendsResult.True :
|
||||
left.items!.every((schema, index) => Visit(schema, right.items![index]) === ExtendsResult.True) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Uint8Array
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromUint8Array(left: TUint8Array, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsUint8Array(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Undefined
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromUndefined(left: TUndefined, right: TSchema) {
|
||||
return (
|
||||
IsStructuralRight(right) ? StructuralRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsRecord(right) ? FromRecordRight(left, right) :
|
||||
TypeGuard.IsVoid(right) ? FromVoidRight(left, right) :
|
||||
TypeGuard.IsUndefined(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Union
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromUnionRight(left: TSchema, right: TUnion): ExtendsResult {
|
||||
return right.anyOf.some((schema) => Visit(left, schema) === ExtendsResult.True)
|
||||
? ExtendsResult.True
|
||||
: ExtendsResult.False
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromUnion(left: TUnion, right: TSchema): ExtendsResult {
|
||||
return left.anyOf.every((schema) => Visit(schema, right) === ExtendsResult.True)
|
||||
? ExtendsResult.True
|
||||
: ExtendsResult.False
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Unknown
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromUnknownRight(left: TSchema, right: TUnknown) {
|
||||
return ExtendsResult.True
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromUnknown(left: TUnknown, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsNever(right) ? FromNeverRight(left, right) :
|
||||
TypeGuard.IsIntersect(right) ? FromIntersectRight(left, right) :
|
||||
TypeGuard.IsUnion(right) ? FromUnionRight(left, right) :
|
||||
TypeGuard.IsAny(right) ? FromAnyRight(left, right) :
|
||||
TypeGuard.IsString(right) ? FromStringRight(left, right) :
|
||||
TypeGuard.IsNumber(right) ? FromNumberRight(left, right) :
|
||||
TypeGuard.IsInteger(right) ? FromIntegerRight(left, right) :
|
||||
TypeGuard.IsBoolean(right) ? FromBooleanRight(left, right) :
|
||||
TypeGuard.IsArray(right) ? FromArrayRight(left, right) :
|
||||
TypeGuard.IsTuple(right) ? FromTupleRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsUnknown(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Void
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
function FromVoidRight(left: TSchema, right: TVoid) {
|
||||
return (
|
||||
TypeGuard.IsUndefined(left) ? ExtendsResult.True :
|
||||
TypeGuard.IsUndefined(left) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromVoid(left: TVoid, right: TSchema) {
|
||||
return (
|
||||
TypeGuard.IsIntersect(right) ? FromIntersectRight(left, right) :
|
||||
TypeGuard.IsUnion(right) ? FromUnionRight(left, right) :
|
||||
TypeGuard.IsUnknown(right) ? FromUnknownRight(left, right) :
|
||||
TypeGuard.IsAny(right) ? FromAnyRight(left, right) :
|
||||
TypeGuard.IsObject(right) ? FromObjectRight(left, right) :
|
||||
TypeGuard.IsVoid(right) ? ExtendsResult.True :
|
||||
ExtendsResult.False
|
||||
)
|
||||
}
|
||||
// prettier-ignore
|
||||
function Visit(left: TSchema, right: TSchema): ExtendsResult {
|
||||
return (
|
||||
// resolvable
|
||||
(TypeGuard.IsTemplateLiteral(left) || TypeGuard.IsTemplateLiteral(right)) ? FromTemplateLiteral(left, right) :
|
||||
(TypeGuard.IsRegExp(left) || TypeGuard.IsRegExp(right)) ? FromRegExp(left, right) :
|
||||
(TypeGuard.IsNot(left) || TypeGuard.IsNot(right)) ? FromNot(left, right) :
|
||||
// standard
|
||||
TypeGuard.IsAny(left) ? FromAny(left, right) :
|
||||
TypeGuard.IsArray(left) ? FromArray(left, right) :
|
||||
TypeGuard.IsBigInt(left) ? FromBigInt(left, right) :
|
||||
TypeGuard.IsBoolean(left) ? FromBoolean(left, right) :
|
||||
TypeGuard.IsAsyncIterator(left) ? FromAsyncIterator(left, right) :
|
||||
TypeGuard.IsConstructor(left) ? FromConstructor(left, right) :
|
||||
TypeGuard.IsDate(left) ? FromDate(left, right) :
|
||||
TypeGuard.IsFunction(left) ? FromFunction(left, right) :
|
||||
TypeGuard.IsInteger(left) ? FromInteger(left, right) :
|
||||
TypeGuard.IsIntersect(left) ? FromIntersect(left, right) :
|
||||
TypeGuard.IsIterator(left) ? FromIterator(left, right) :
|
||||
TypeGuard.IsLiteral(left) ? FromLiteral(left, right) :
|
||||
TypeGuard.IsNever(left) ? FromNever(left, right) :
|
||||
TypeGuard.IsNull(left) ? FromNull(left, right) :
|
||||
TypeGuard.IsNumber(left) ? FromNumber(left, right) :
|
||||
TypeGuard.IsObject(left) ? FromObject(left, right) :
|
||||
TypeGuard.IsRecord(left) ? FromRecord(left, right) :
|
||||
TypeGuard.IsString(left) ? FromString(left, right) :
|
||||
TypeGuard.IsSymbol(left) ? FromSymbol(left, right) :
|
||||
TypeGuard.IsTuple(left) ? FromTuple(left, right) :
|
||||
TypeGuard.IsPromise(left) ? FromPromise(left, right) :
|
||||
TypeGuard.IsUint8Array(left) ? FromUint8Array(left, right) :
|
||||
TypeGuard.IsUndefined(left) ? FromUndefined(left, right) :
|
||||
TypeGuard.IsUnion(left) ? FromUnion(left, right) :
|
||||
TypeGuard.IsUnknown(left) ? FromUnknown(left, right) :
|
||||
TypeGuard.IsVoid(left) ? FromVoid(left, right) :
|
||||
Throw(`Unknown left type operand '${left[Kind]}'`)
|
||||
)
|
||||
}
|
||||
export function ExtendsCheck(left: TSchema, right: TSchema): ExtendsResult {
|
||||
return Visit(left, right)
|
||||
}
|
||||
129
src/type/extends/extends-from-mapped-key.ts
Normal file
129
src/type/extends/extends-from-mapped-key.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import type { Assert } from '../helpers/index'
|
||||
import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index'
|
||||
import { Literal, type TLiteral, type TLiteralValue } from '../literal/index'
|
||||
import { Extends, type TExtends } from './extends'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromPropertyKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromPropertyKey<
|
||||
K extends PropertyKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
> = {
|
||||
[_ in K]: TExtends<TLiteral<Assert<K, TLiteralValue>>, U, L, R>
|
||||
}
|
||||
// prettier-ignore
|
||||
function FromPropertyKey<
|
||||
K extends PropertyKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
>(K: K, U: U, L: L, R: R, options: SchemaOptions): TFromPropertyKey<K, U, L, R> {
|
||||
return {
|
||||
[K]: Extends(Literal(K as TLiteralValue), U, L, R, options) as any
|
||||
} as TFromPropertyKey<K, U, L, R>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromPropertyKeys
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromPropertyKeys<
|
||||
K extends PropertyKey[],
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema,
|
||||
Acc extends TProperties = {}
|
||||
> = (
|
||||
K extends [infer LK extends PropertyKey, ...infer RK extends PropertyKey[]]
|
||||
? TFromPropertyKeys<RK, U, L, R, Acc & TFromPropertyKey<LK, U, L, R>>
|
||||
: Acc
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromPropertyKeys<
|
||||
K extends PropertyKey[],
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
>(K: [...K], U: U, L: L, R: R, options: SchemaOptions): TFromPropertyKeys<K, U, L, R> {
|
||||
return K.reduce((Acc, LK) => {
|
||||
return { ...Acc, ...FromPropertyKey(LK, U, L, R, options) }
|
||||
}, {} as TProperties) as TFromPropertyKeys<K, U, L, R>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromMappedKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedKey<
|
||||
K extends TMappedKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
> = (
|
||||
TFromPropertyKeys<K['keys'], U, L, R>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedKey<
|
||||
K extends TMappedKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema
|
||||
>(K: K, U: U, L: L, R: R, options: SchemaOptions): TFromMappedKey<K, U, L, R> {
|
||||
return FromPropertyKeys(K.keys, U, L, R, options) as TFromMappedKey<K, U, L, R>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ExtendsFromMappedKey
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExtendsFromMappedKey<
|
||||
T extends TMappedKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema,
|
||||
P extends TProperties = TFromMappedKey<T, U, L, R>
|
||||
> = (
|
||||
TMappedResult<P>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function ExtendsFromMappedKey<
|
||||
T extends TMappedKey,
|
||||
U extends TSchema,
|
||||
L extends TSchema,
|
||||
R extends TSchema,
|
||||
P extends TProperties = TFromMappedKey<T, U, L, R>
|
||||
>(T: T, U: U, L: L, R: R, options: SchemaOptions): TMappedResult<P> {
|
||||
const P = FromMappedKey(T, U, L, R, options) as unknown as P
|
||||
return MappedResult(P)
|
||||
}
|
||||
101
src/type/extends/extends-from-mapped-result.ts
Normal file
101
src/type/extends/extends-from-mapped-result.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import { MappedResult, type TMappedResult } from '../mapped/index'
|
||||
import { Extends, type TExtends } from './extends'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<
|
||||
P extends TProperties,
|
||||
Right extends TSchema,
|
||||
False extends TSchema,
|
||||
True extends TSchema
|
||||
> = (
|
||||
{ [K2 in keyof P]: TExtends<P[K2], Right, False, True> }
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromProperties<
|
||||
P extends TProperties,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema
|
||||
>(P: P, Right: Right, True: True, False: False, options: SchemaOptions): TFromProperties<P, Right, True, False> {
|
||||
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
|
||||
return {...Acc, [K2]: Extends(P[K2], Right, True, False, options) }
|
||||
}, {}) as TFromProperties<P, Right, True, False>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedResult<
|
||||
Left extends TMappedResult,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema
|
||||
> = (
|
||||
TFromProperties<Left['properties'], Right, True, False>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedResult<
|
||||
Left extends TMappedResult,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema
|
||||
>(Left: Left, Right: Right, True: True, False: False, options: SchemaOptions): TFromMappedResult<Left, Right, True, False> {
|
||||
return FromProperties(Left.properties, Right, True, False, options) as TFromMappedResult<Left, Right, True, False>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ExtendsFromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExtendsFromMappedResult<
|
||||
Left extends TMappedResult,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<Left, Right, True, False>
|
||||
> = (
|
||||
TMappedResult<P>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function ExtendsFromMappedResult<
|
||||
Left extends TMappedResult,
|
||||
Right extends TSchema,
|
||||
True extends TSchema,
|
||||
False extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<Left, Right, True, False>
|
||||
>(Left: Left, Right: Right, True: True, False: False, options: SchemaOptions): TMappedResult<P> {
|
||||
const P = FromMappedResult(Left, Right, True, False, options) as unknown as P
|
||||
return MappedResult(P)
|
||||
}
|
||||
55
src/type/extends/extends-undefined.ts
Normal file
55
src/type/extends/extends-undefined.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema } from '../schema/index'
|
||||
import type { TIntersect } from '../intersect/index'
|
||||
import type { TUnion } from '../union/index'
|
||||
import type { TNot } from '../not/index'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
/** Fast undefined check used for properties of type undefined */
|
||||
function Intersect(schema: TIntersect) {
|
||||
return schema.allOf.every((schema) => ExtendsUndefinedCheck(schema))
|
||||
}
|
||||
function Union(schema: TUnion) {
|
||||
return schema.anyOf.some((schema) => ExtendsUndefinedCheck(schema))
|
||||
}
|
||||
function Not(schema: TNot) {
|
||||
return !ExtendsUndefinedCheck(schema.not)
|
||||
}
|
||||
/** Fast undefined check used for properties of type undefined */
|
||||
// prettier-ignore
|
||||
export function ExtendsUndefinedCheck(schema: TSchema): boolean {
|
||||
return (
|
||||
schema[Kind] === 'Intersect' ? Intersect(schema as TIntersect) :
|
||||
schema[Kind] === 'Union' ? Union(schema as TUnion) :
|
||||
schema[Kind] === 'Not' ? Not(schema as TNot) :
|
||||
schema[Kind] === 'Undefined' ? true :
|
||||
false
|
||||
)
|
||||
}
|
||||
80
src/type/extends/extends.ts
Normal file
80
src/type/extends/extends.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import { type TUnion, Union } from '../union/index'
|
||||
import { TMappedKey, TMappedResult } from '../mapped/index'
|
||||
import { ExtendsCheck, ExtendsResult } from './extends-check'
|
||||
import { UnionToTuple } from '../helpers/index'
|
||||
import { CloneType } from '../clone/type'
|
||||
import { ExtendsFromMappedKey, type TExtendsFromMappedKey } from './extends-from-mapped-key'
|
||||
import { ExtendsFromMappedResult, type TExtendsFromMappedResult } from './extends-from-mapped-result'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsMappedKey, IsMappedResult } from '../guard/type'
|
||||
|
||||
// prettier-ignore
|
||||
type TExtendsResolve<L extends TSchema, R extends TSchema, T extends TSchema, U extends TSchema> = (
|
||||
(Static<L> extends Static<R> ? T : U) extends infer O extends TSchema ?
|
||||
UnionToTuple<O> extends [infer X extends TSchema, infer Y extends TSchema]
|
||||
? TUnion<[X, Y]>
|
||||
: O
|
||||
: never
|
||||
)
|
||||
// prettier-ignore
|
||||
function ExtendsResolve<L extends TSchema, R extends TSchema, T extends TSchema, U extends TSchema>(left: L, right: R, trueType: T, falseType: U): TExtendsResolve<L, R, T, U> {
|
||||
const R = ExtendsCheck(left, right)
|
||||
return (
|
||||
R === ExtendsResult.Union ? Union([trueType, falseType]) :
|
||||
R === ExtendsResult.True ? trueType :
|
||||
falseType
|
||||
) as unknown as TExtendsResolve<L, R, T, U>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TExtends
|
||||
// ------------------------------------------------------------------
|
||||
export type TExtends<L extends TSchema, R extends TSchema, T extends TSchema, F extends TSchema> = TExtendsResolve<L, R, T, F>
|
||||
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
export function Extends<L extends TMappedResult, R extends TSchema, T extends TSchema, F extends TSchema>(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtendsFromMappedResult<L, R, T, F>
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
export function Extends<L extends TMappedKey, R extends TSchema, T extends TSchema, F extends TSchema>(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtendsFromMappedKey<L, R, T, F>
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
export function Extends<L extends TSchema, R extends TSchema, T extends TSchema, F extends TSchema>(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtends<L, R, T, F>
|
||||
/** `[Json]` Creates a Conditional type */
|
||||
export function Extends<L extends TSchema, R extends TSchema, T extends TSchema, F extends TSchema>(L: L, R: R, T: T, F: F, options: SchemaOptions = {}) {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsMappedResult(L) ? ExtendsFromMappedResult(L, R, T, F, options) :
|
||||
IsMappedKey(L) ? CloneType(ExtendsFromMappedKey(L, R, T, F, options)) :
|
||||
CloneType(ExtendsResolve(L, R, T, F), options)
|
||||
) as TExtends<L, R, T, F>
|
||||
}
|
||||
33
src/type/extends/index.ts
Normal file
33
src/type/extends/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './extends-check'
|
||||
export * from './extends-from-mapped-key'
|
||||
export * from './extends-from-mapped-result'
|
||||
export * from './extends-undefined'
|
||||
export * from './extends'
|
||||
89
src/type/extract/extract-from-mapped-result.ts
Normal file
89
src/type/extract/extract-from-mapped-result.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import { MappedResult, type TMappedResult } from '../mapped/index'
|
||||
import { Extract, type TExtract } from './extract'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FromProperties
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromProperties<
|
||||
P extends TProperties,
|
||||
T extends TSchema
|
||||
> = (
|
||||
{ [K2 in keyof P]: TExtract<P[K2], T> }
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromProperties<
|
||||
P extends TProperties,
|
||||
T extends TSchema
|
||||
>(P: P, T: T, options: SchemaOptions): TFromProperties<P, T> {
|
||||
return globalThis.Object.getOwnPropertyNames(P).reduce((Acc, K2) => {
|
||||
return {...Acc, [K2]: Extract(P[K2], T, options) }
|
||||
}, {}) as TFromProperties<P, T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// FromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema
|
||||
> = (
|
||||
TFromProperties<R['properties'], T>
|
||||
)
|
||||
// prettier-ignore
|
||||
function FromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema
|
||||
>(R: R, T: T, options: SchemaOptions): TFromMappedResult<R, T> {
|
||||
return FromProperties(R.properties, T, options) as TFromMappedResult<R, T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// ExtractFromMappedResult
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExtractFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<R, T>
|
||||
> = (
|
||||
TMappedResult<P>
|
||||
)
|
||||
// prettier-ignore
|
||||
export function ExtractFromMappedResult<
|
||||
R extends TMappedResult,
|
||||
T extends TSchema,
|
||||
P extends TProperties = TFromMappedResult<R, T>
|
||||
>(R: R, T: T, options: SchemaOptions): TMappedResult<P> {
|
||||
const P = FromMappedResult(R, T, options) as unknown as P
|
||||
return MappedResult(P)
|
||||
}
|
||||
94
src/type/extract/extract.ts
Normal file
94
src/type/extract/extract.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Assert, AssertRest, AssertType, UnionToTuple } from '../helpers/index'
|
||||
import type { TMappedResult } from '../mapped/index'
|
||||
import { TemplateLiteralToUnion, type TTemplateLiteral } from '../template-literal/index'
|
||||
import { type TLiteral } from '../literal/index'
|
||||
import { Union, type TUnion } from '../union/index'
|
||||
import { type Static } from '../static/index'
|
||||
import { Never } from '../never/index'
|
||||
import { type TUnionEvaluated } from '../union/index'
|
||||
import { ExtendsCheck, ExtendsResult } from '../extends/index'
|
||||
import { CloneType } from '../clone/type'
|
||||
import { ExtractFromMappedResult, type TExtractFromMappedResult } from './extract-from-mapped-result'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// TypeGuard
|
||||
// ------------------------------------------------------------------
|
||||
import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/type'
|
||||
// ------------------------------------------------------------------
|
||||
// ExtractResolve
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
type TFromTemplateLiteralResult<T extends string> = TUnionEvaluated<AssertRest<UnionToTuple<{ [K in T]: TLiteral<K> }[T]>>>
|
||||
// prettier-ignore
|
||||
type TFromTemplateLiteral<T extends TTemplateLiteral, U extends TSchema> = Extract<Static<T>, Static<U>> extends infer S ? TFromTemplateLiteralResult<Assert<S, string>> : never
|
||||
// prettier-ignore
|
||||
type TFromArray<T extends TSchema[], U extends TSchema> = AssertRest<UnionToTuple<
|
||||
{ [K in keyof T]: Static<AssertType<T[K]>> extends Static<U> ? T[K] : never
|
||||
}[number]>> extends infer R extends TSchema[] ? TUnionEvaluated<R> : never
|
||||
// prettier-ignore
|
||||
type TExtractResolve<T extends TSchema, U extends TSchema> = (
|
||||
T extends TTemplateLiteral ? TFromTemplateLiteral<T, U> :
|
||||
T extends TUnion<infer S> ? TFromArray<S, U> :
|
||||
T
|
||||
)
|
||||
// prettier-ignore
|
||||
function ExtractResolve<L extends TSchema, R extends TSchema>(L: L, R: R): TExtractResolve<L, R> {
|
||||
return (
|
||||
IsTemplateLiteral(L) ? ExtractResolve(TemplateLiteralToUnion(L), R) :
|
||||
IsTemplateLiteral(R) ? ExtractResolve(L, TemplateLiteralToUnion(R) as any) :
|
||||
IsUnion(L) ? (() => {
|
||||
const narrowed = L.anyOf.filter((inner) => ExtendsCheck(inner, R) !== ExtendsResult.False)
|
||||
return (narrowed.length === 1 ? narrowed[0] : Union(narrowed))
|
||||
})() :
|
||||
ExtendsCheck(L, R) !== ExtendsResult.False ? L :
|
||||
Never()
|
||||
) as TExtractResolve<L, R>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// TExtract
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TExtract<T extends TSchema, U extends TSchema> = TExtractResolve<T, U>
|
||||
|
||||
/** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */
|
||||
export function Extract<L extends TMappedResult, R extends TSchema>(type: L, union: R, options?: SchemaOptions): TExtractFromMappedResult<L, R>
|
||||
/** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */
|
||||
export function Extract<L extends TSchema, R extends TSchema>(type: L, union: R, options?: SchemaOptions): TExtract<L, R>
|
||||
/** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */
|
||||
export function Extract(type: TSchema, union: TSchema, options: SchemaOptions = {}) {
|
||||
if (IsMappedResult(type)) {
|
||||
return ExtractFromMappedResult(type, union, options)
|
||||
} else {
|
||||
const E = ExtractResolve(type, union)
|
||||
return CloneType(E, options)
|
||||
}
|
||||
}
|
||||
30
src/type/extract/index.ts
Normal file
30
src/type/extract/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './extract-from-mapped-result'
|
||||
export * from './extract'
|
||||
67
src/type/function/function.ts
Normal file
67
src/type/function/function.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema, SchemaOptions } from '../schema/index'
|
||||
import type { Static } from '../static/index'
|
||||
import type { Ensure } from '../helpers/index'
|
||||
import { CloneType, CloneRest } from '../clone/type'
|
||||
import { Kind } from '../symbols/index'
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// FunctionStatic
|
||||
// ------------------------------------------------------------------
|
||||
type FunctionStaticReturnType<T extends TSchema, P extends unknown[]> = Static<T, P>
|
||||
// prettier-ignore
|
||||
type FunctionStaticParameters<T extends TSchema[], P extends unknown[], Acc extends unknown[] = []> =
|
||||
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
|
||||
? FunctionStaticParameters<R, P, [...Acc, Static<L, P>]>
|
||||
: Acc
|
||||
// prettier-ignore
|
||||
type FunctionStatic<T extends TSchema[], U extends TSchema, P extends unknown[]> = (
|
||||
Ensure<(...param: FunctionStaticParameters<T, P>) => FunctionStaticReturnType<U, P>>
|
||||
)
|
||||
// ------------------------------------------------------------------
|
||||
// TFunction
|
||||
// ------------------------------------------------------------------
|
||||
export interface TFunction<T extends TSchema[] = TSchema[], U extends TSchema = TSchema> extends TSchema {
|
||||
[Kind]: 'Function'
|
||||
static: FunctionStatic<T, U, this['params']>
|
||||
type: 'Function'
|
||||
parameters: T
|
||||
returns: U
|
||||
}
|
||||
/** `[JavaScript]` Creates a Function type */
|
||||
export function Function<T extends TSchema[], U extends TSchema>(parameters: [...T], returns: U, options?: SchemaOptions): TFunction<T, U> {
|
||||
return {
|
||||
...options,
|
||||
[Kind]: 'Function',
|
||||
type: 'Function',
|
||||
parameters: CloneRest(parameters),
|
||||
returns: CloneType(returns),
|
||||
} as unknown as TFunction<T, U>
|
||||
}
|
||||
29
src/type/function/index.ts
Normal file
29
src/type/function/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './function'
|
||||
30
src/type/guard/index.ts
Normal file
30
src/type/guard/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * as TypeGuard from './type'
|
||||
export * as ValueGuard from './value'
|
||||
618
src/type/guard/type.ts
Normal file
618
src/type/guard/type.ts
Normal file
@@ -0,0 +1,618 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 ValueGuard from './value'
|
||||
import { Kind, Hint, TransformKind, ReadonlyKind, OptionalKind } from '../symbols/index'
|
||||
import { TypeBoxError } from '../error/index'
|
||||
import { TransformOptions } from '../transform/index'
|
||||
import { TTemplateLiteral, TTemplateLiteralKind } from '../template-literal/index'
|
||||
import { TArray } from '../array/index'
|
||||
import { TBoolean } from '../boolean/index'
|
||||
import type { TRecord } from '../record/index'
|
||||
import type { TString } from '../string/index'
|
||||
import type { TUnion } from '../union/index'
|
||||
import type { TAny } from '../any/index'
|
||||
import type { TAsyncIterator } from '../async-iterator/index'
|
||||
import type { TBigInt } from '../bigint/index'
|
||||
import type { TConstructor } from '../constructor/index'
|
||||
import type { TFunction } from '../function/index'
|
||||
import type { TInteger } from '../integer/index'
|
||||
import type { TIntersect } from '../intersect/index'
|
||||
import type { TIterator } from '../iterator/index'
|
||||
import type { TLiteral, TLiteralValue } from '../literal/index'
|
||||
import type { TMappedKey, TMappedResult } from '../mapped/index'
|
||||
import type { TNever } from '../never/index'
|
||||
import type { TNot } from '../not/index'
|
||||
import type { TNull } from '../null/index'
|
||||
import type { TNumber } from '../number/index'
|
||||
import type { TObject, TAdditionalProperties, TProperties } from '../object/index'
|
||||
import type { TOptional } from '../optional/index'
|
||||
import type { TPromise } from '../promise/index'
|
||||
import type { TReadonly } from '../readonly/index'
|
||||
import type { TRef } from '../ref/index'
|
||||
import type { TRegExp } from '../regexp/index'
|
||||
import type { TSchema } from '../schema/index'
|
||||
import type { TSymbol } from '../symbol/index'
|
||||
import type { TTuple } from '../tuple/index'
|
||||
import type { TUint8Array } from '../uint8array/index'
|
||||
import type { TUndefined } from '../undefined/index'
|
||||
import type { TUnknown } from '../unknown/index'
|
||||
import type { TUnsafe } from '../unsafe/index'
|
||||
import type { TVoid } from '../void/index'
|
||||
import type { TDate } from '../date/index'
|
||||
import type { TThis } from '../recursive/index'
|
||||
|
||||
export class TypeGuardUnknownTypeError extends TypeBoxError {}
|
||||
|
||||
const KnownTypes = [
|
||||
'Any',
|
||||
'Array',
|
||||
'AsyncIterator',
|
||||
'BigInt',
|
||||
'Boolean',
|
||||
'Constructor',
|
||||
'Date',
|
||||
'Enum',
|
||||
'Function',
|
||||
'Integer',
|
||||
'Intersect',
|
||||
'Iterator',
|
||||
'Literal',
|
||||
'MappedKey',
|
||||
'MappedResult',
|
||||
'Not',
|
||||
'Null',
|
||||
'Number',
|
||||
'Object',
|
||||
'Promise',
|
||||
'Record',
|
||||
'Ref',
|
||||
'RegExp',
|
||||
'String',
|
||||
'Symbol',
|
||||
'TemplateLiteral',
|
||||
'This',
|
||||
'Tuple',
|
||||
'Undefined',
|
||||
'Union',
|
||||
'Uint8Array',
|
||||
'Unknown',
|
||||
'Void',
|
||||
]
|
||||
function IsPattern(value: unknown): value is string {
|
||||
try {
|
||||
new RegExp(value as string)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
function IsControlCharacterFree(value: unknown): value is string {
|
||||
if (!ValueGuard.IsString(value)) return false
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const code = value.charCodeAt(i)
|
||||
if ((code >= 7 && code <= 13) || code === 27 || code === 127) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
function IsAdditionalProperties(value: unknown): value is TAdditionalProperties {
|
||||
return IsOptionalBoolean(value) || IsSchema(value)
|
||||
}
|
||||
function IsOptionalBigInt(value: unknown): value is bigint | undefined {
|
||||
return ValueGuard.IsUndefined(value) || ValueGuard.IsBigInt(value)
|
||||
}
|
||||
function IsOptionalNumber(value: unknown): value is number | undefined {
|
||||
return ValueGuard.IsUndefined(value) || ValueGuard.IsNumber(value)
|
||||
}
|
||||
function IsOptionalBoolean(value: unknown): value is boolean | undefined {
|
||||
return ValueGuard.IsUndefined(value) || ValueGuard.IsBoolean(value)
|
||||
}
|
||||
function IsOptionalString(value: unknown): value is string | undefined {
|
||||
return ValueGuard.IsUndefined(value) || ValueGuard.IsString(value)
|
||||
}
|
||||
function IsOptionalPattern(value: unknown): value is string | undefined {
|
||||
return ValueGuard.IsUndefined(value) || (ValueGuard.IsString(value) && IsControlCharacterFree(value) && IsPattern(value))
|
||||
}
|
||||
function IsOptionalFormat(value: unknown): value is string | undefined {
|
||||
return ValueGuard.IsUndefined(value) || (ValueGuard.IsString(value) && IsControlCharacterFree(value))
|
||||
}
|
||||
function IsOptionalSchema(value: unknown): value is boolean | undefined {
|
||||
return ValueGuard.IsUndefined(value) || IsSchema(value)
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Modifiers
|
||||
// ------------------------------------------------------------------
|
||||
/** Returns true if this value has a Readonly symbol */
|
||||
export function IsReadonly<T extends TSchema>(value: T): value is TReadonly<T> {
|
||||
return ValueGuard.IsObject(value) && value[ReadonlyKind] === 'Readonly'
|
||||
}
|
||||
/** Returns true if this value has a Optional symbol */
|
||||
export function IsOptional<T extends TSchema>(value: T): value is TOptional<T> {
|
||||
return ValueGuard.IsObject(value) && value[OptionalKind] === 'Optional'
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Types
|
||||
// ------------------------------------------------------------------
|
||||
/** Returns true if the given value is TAny */
|
||||
export function IsAny(value: unknown): value is TAny {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Any') &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TArray */
|
||||
export function IsArray(value: unknown): value is TArray {
|
||||
return (
|
||||
IsKindOf(value, 'Array') &&
|
||||
value.type === 'array' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsSchema(value.items) &&
|
||||
IsOptionalNumber(value.minItems) &&
|
||||
IsOptionalNumber(value.maxItems) &&
|
||||
IsOptionalBoolean(value.uniqueItems) &&
|
||||
IsOptionalSchema(value.contains) &&
|
||||
IsOptionalNumber(value.minContains) &&
|
||||
IsOptionalNumber(value.maxContains)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TAsyncIterator */
|
||||
export function IsAsyncIterator(value: unknown): value is TAsyncIterator {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'AsyncIterator') &&
|
||||
value.type === 'AsyncIterator' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsSchema(value.items)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TBigInt */
|
||||
export function IsBigInt(value: unknown): value is TBigInt {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'BigInt') &&
|
||||
value.type === 'bigint' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalBigInt(value.exclusiveMaximum) &&
|
||||
IsOptionalBigInt(value.exclusiveMinimum) &&
|
||||
IsOptionalBigInt(value.maximum) &&
|
||||
IsOptionalBigInt(value.minimum) &&
|
||||
IsOptionalBigInt(value.multipleOf)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TBoolean */
|
||||
export function IsBoolean(value: unknown): value is TBoolean {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Boolean') &&
|
||||
value.type === 'boolean' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TConstructor */
|
||||
export function IsConstructor(value: unknown): value is TConstructor {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Constructor') &&
|
||||
value.type === 'Constructor' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsArray(value.parameters) &&
|
||||
value.parameters.every(schema => IsSchema(schema)) &&
|
||||
IsSchema(value.returns)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TDate */
|
||||
export function IsDate(value: unknown): value is TDate {
|
||||
return (
|
||||
IsKindOf(value, 'Date') &&
|
||||
value.type === 'Date' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.exclusiveMaximumTimestamp) &&
|
||||
IsOptionalNumber(value.exclusiveMinimumTimestamp) &&
|
||||
IsOptionalNumber(value.maximumTimestamp) &&
|
||||
IsOptionalNumber(value.minimumTimestamp) &&
|
||||
IsOptionalNumber(value.multipleOfTimestamp)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TFunction */
|
||||
export function IsFunction(value: unknown): value is TFunction {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Function') &&
|
||||
value.type === 'Function' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsArray(value.parameters) &&
|
||||
value.parameters.every(schema => IsSchema(schema)) &&
|
||||
IsSchema(value.returns)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TInteger */
|
||||
export function IsInteger(value: unknown): value is TInteger {
|
||||
return (
|
||||
IsKindOf(value, 'Integer') &&
|
||||
value.type === 'integer' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.exclusiveMaximum) &&
|
||||
IsOptionalNumber(value.exclusiveMinimum) &&
|
||||
IsOptionalNumber(value.maximum) &&
|
||||
IsOptionalNumber(value.minimum) &&
|
||||
IsOptionalNumber(value.multipleOf)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given schema is TProperties */
|
||||
export function IsProperties(value: unknown): value is TProperties {
|
||||
// prettier-ignore
|
||||
return (
|
||||
ValueGuard.IsObject(value) &&
|
||||
Object.entries(value).every(([key, schema]) => IsControlCharacterFree(key) && IsSchema(schema))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TIntersect */
|
||||
export function IsIntersect(value: unknown): value is TIntersect {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Intersect') &&
|
||||
(ValueGuard.IsString(value.type) && value.type !== 'object' ? false : true) &&
|
||||
ValueGuard.IsArray(value.allOf) &&
|
||||
value.allOf.every(schema => IsSchema(schema) && !IsTransform(schema)) &&
|
||||
IsOptionalString(value.type) &&
|
||||
(IsOptionalBoolean(value.unevaluatedProperties) || IsOptionalSchema(value.unevaluatedProperties)) &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TIterator */
|
||||
export function IsIterator(value: unknown): value is TIterator {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Iterator') &&
|
||||
value.type === 'Iterator' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsSchema(value.items)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is a TKind with the given name. */
|
||||
export function IsKindOf<T extends string>(value: unknown, kind: T): value is Record<PropertyKey, unknown> & { [Kind]: T } {
|
||||
return ValueGuard.IsObject(value) && Kind in value && value[Kind] === kind
|
||||
}
|
||||
/** Returns true if the given value is TLiteral<string> */
|
||||
export function IsLiteralString(value: unknown): value is TLiteral<string> {
|
||||
return IsLiteral(value) && ValueGuard.IsString(value.const)
|
||||
}
|
||||
/** Returns true if the given value is TLiteral<number> */
|
||||
export function IsLiteralNumber(value: unknown): value is TLiteral<number> {
|
||||
return IsLiteral(value) && ValueGuard.IsNumber(value.const)
|
||||
}
|
||||
/** Returns true if the given value is TLiteral<boolean> */
|
||||
export function IsLiteralBoolean(value: unknown): value is TLiteral<boolean> {
|
||||
return IsLiteral(value) && ValueGuard.IsBoolean(value.const)
|
||||
}
|
||||
/** Returns true if the given value is TLiteral */
|
||||
export function IsLiteral(value: unknown): value is TLiteral {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Literal') &&
|
||||
IsOptionalString(value.$id) && IsLiteralValue(value.const)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is a TLiteralValue */
|
||||
export function IsLiteralValue(value: unknown): value is TLiteralValue {
|
||||
return ValueGuard.IsBoolean(value) || ValueGuard.IsNumber(value) || ValueGuard.IsString(value)
|
||||
}
|
||||
/** Returns true if the given value is a TMappedKey */
|
||||
export function IsMappedKey(value: unknown): value is TMappedKey {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'MappedKey') &&
|
||||
ValueGuard.IsArray(value.keys) &&
|
||||
value.keys.every(key => ValueGuard.IsNumber(key) || ValueGuard.IsString(key))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TMappedResult */
|
||||
export function IsMappedResult(value: unknown): value is TMappedResult {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'MappedResult') &&
|
||||
IsProperties(value.properties)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TNever */
|
||||
export function IsNever(value: unknown): value is TNever {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Never') &&
|
||||
ValueGuard.IsObject(value.not) &&
|
||||
Object.getOwnPropertyNames(value.not).length === 0
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TNot */
|
||||
export function IsNot(value: unknown): value is TNot {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Not') &&
|
||||
IsSchema(value.not)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TNull */
|
||||
export function IsNull(value: unknown): value is TNull {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Null') &&
|
||||
value.type === 'null' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TNumber */
|
||||
export function IsNumber(value: unknown): value is TNumber {
|
||||
return (
|
||||
IsKindOf(value, 'Number') &&
|
||||
value.type === 'number' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.exclusiveMaximum) &&
|
||||
IsOptionalNumber(value.exclusiveMinimum) &&
|
||||
IsOptionalNumber(value.maximum) &&
|
||||
IsOptionalNumber(value.minimum) &&
|
||||
IsOptionalNumber(value.multipleOf)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TObject */
|
||||
export function IsObject(value: unknown): value is TObject {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Object') &&
|
||||
value.type === 'object' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsProperties(value.properties) &&
|
||||
IsAdditionalProperties(value.additionalProperties) &&
|
||||
IsOptionalNumber(value.minProperties) &&
|
||||
IsOptionalNumber(value.maxProperties)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TPromise */
|
||||
export function IsPromise(value: unknown): value is TPromise {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Promise') &&
|
||||
value.type === 'Promise' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsSchema(value.item)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TRecord */
|
||||
export function IsRecord(value: unknown): value is TRecord {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Record') &&
|
||||
value.type === 'object' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsAdditionalProperties(value.additionalProperties) &&
|
||||
ValueGuard.IsObject(value.patternProperties) &&
|
||||
((schema: Record<PropertyKey, unknown>) => {
|
||||
const keys = Object.getOwnPropertyNames(schema.patternProperties)
|
||||
return (
|
||||
keys.length === 1 &&
|
||||
IsPattern(keys[0]) &&
|
||||
ValueGuard.IsObject(schema.patternProperties) &&
|
||||
IsSchema(schema.patternProperties[keys[0]])
|
||||
)
|
||||
})(value)
|
||||
)
|
||||
}
|
||||
/** Returns true if this value is TRecursive */
|
||||
export function IsRecursive(value: unknown): value is { [Hint]: 'Recursive' } {
|
||||
return ValueGuard.IsObject(value) && Hint in value && value[Hint] === 'Recursive'
|
||||
}
|
||||
/** Returns true if the given value is TRef */
|
||||
export function IsRef(value: unknown): value is TRef {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Ref') &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsString(value.$ref)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TRegExp */
|
||||
export function IsRegExp(value: unknown): value is TRegExp {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'RegExp') &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsString(value.source) &&
|
||||
ValueGuard.IsString(value.flags)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TString */
|
||||
export function IsString(value: unknown): value is TString {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'String') &&
|
||||
value.type === 'string' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.minLength) &&
|
||||
IsOptionalNumber(value.maxLength) &&
|
||||
IsOptionalPattern(value.pattern) &&
|
||||
IsOptionalFormat(value.format)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TSymbol */
|
||||
export function IsSymbol(value: unknown): value is TSymbol {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Symbol') &&
|
||||
value.type === 'symbol' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TTemplateLiteral */
|
||||
export function IsTemplateLiteral(value: unknown): value is TTemplateLiteral<TTemplateLiteralKind[]> {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'TemplateLiteral') &&
|
||||
value.type === 'string' &&
|
||||
ValueGuard.IsString(value.pattern) &&
|
||||
value.pattern[0] === '^' &&
|
||||
value.pattern[value.pattern.length - 1] === '$'
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TThis */
|
||||
export function IsThis(value: unknown): value is TThis {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'This') &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsString(value.$ref)
|
||||
)
|
||||
}
|
||||
/** Returns true of this value is TTransform */
|
||||
export function IsTransform(value: unknown): value is { [TransformKind]: TransformOptions } {
|
||||
return ValueGuard.IsObject(value) && TransformKind in value
|
||||
}
|
||||
/** Returns true if the given value is TTuple */
|
||||
export function IsTuple(value: unknown): value is TTuple {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Tuple') &&
|
||||
value.type === 'array' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsNumber(value.minItems) &&
|
||||
ValueGuard.IsNumber(value.maxItems) &&
|
||||
value.minItems === value.maxItems &&
|
||||
(( // empty
|
||||
ValueGuard.IsUndefined(value.items) &&
|
||||
ValueGuard.IsUndefined(value.additionalItems) &&
|
||||
value.minItems === 0
|
||||
) || (
|
||||
ValueGuard.IsArray(value.items) &&
|
||||
value.items.every(schema => IsSchema(schema))
|
||||
))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TUndefined */
|
||||
export function IsUndefined(value: unknown): value is TUndefined {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Undefined') &&
|
||||
value.type === 'undefined' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TUnion<Literal<string | number>[]> */
|
||||
export function IsUnionLiteral(value: unknown): value is TUnion<TLiteral[]> {
|
||||
return IsUnion(value) && value.anyOf.every((schema) => IsLiteralString(schema) || IsLiteralNumber(schema))
|
||||
}
|
||||
/** Returns true if the given value is TUnion */
|
||||
export function IsUnion(value: unknown): value is TUnion {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Union') &&
|
||||
IsOptionalString(value.$id) &&
|
||||
ValueGuard.IsObject(value) &&
|
||||
ValueGuard.IsArray(value.anyOf) &&
|
||||
value.anyOf.every(schema => IsSchema(schema))
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TUint8Array */
|
||||
export function IsUint8Array(value: unknown): value is TUint8Array {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Uint8Array') &&
|
||||
value.type === 'Uint8Array' &&
|
||||
IsOptionalString(value.$id) &&
|
||||
IsOptionalNumber(value.minByteLength) &&
|
||||
IsOptionalNumber(value.maxByteLength)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TUnknown */
|
||||
export function IsUnknown(value: unknown): value is TUnknown {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Unknown') &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is a raw TUnsafe */
|
||||
export function IsUnsafe(value: unknown): value is TUnsafe<unknown> {
|
||||
return IsKindOf(value, 'Unsafe')
|
||||
}
|
||||
/** Returns true if the given value is TVoid */
|
||||
export function IsVoid(value: unknown): value is TVoid {
|
||||
// prettier-ignore
|
||||
return (
|
||||
IsKindOf(value, 'Void') &&
|
||||
value.type === 'void' &&
|
||||
IsOptionalString(value.$id)
|
||||
)
|
||||
}
|
||||
/** Returns true if the given value is TKind */
|
||||
export function IsKind(value: unknown): value is Record<PropertyKey, unknown> & { [Kind]: string } {
|
||||
return ValueGuard.IsObject(value) && Kind in value && ValueGuard.IsString(value[Kind]) && !KnownTypes.includes(value[Kind] as string)
|
||||
}
|
||||
/** Returns true if the given value is TSchema */
|
||||
export function IsSchema(value: unknown): value is TSchema {
|
||||
// prettier-ignore
|
||||
return (
|
||||
ValueGuard.IsObject(value)
|
||||
) && (
|
||||
IsAny(value) ||
|
||||
IsArray(value) ||
|
||||
IsBoolean(value) ||
|
||||
IsBigInt(value) ||
|
||||
IsAsyncIterator(value) ||
|
||||
IsConstructor(value) ||
|
||||
IsDate(value) ||
|
||||
IsFunction(value) ||
|
||||
IsInteger(value) ||
|
||||
IsIntersect(value) ||
|
||||
IsIterator(value) ||
|
||||
IsLiteral(value) ||
|
||||
IsMappedKey(value) ||
|
||||
IsMappedResult(value) ||
|
||||
IsNever(value) ||
|
||||
IsNot(value) ||
|
||||
IsNull(value) ||
|
||||
IsNumber(value) ||
|
||||
IsObject(value) ||
|
||||
IsPromise(value) ||
|
||||
IsRecord(value) ||
|
||||
IsRef(value) ||
|
||||
IsRegExp(value) ||
|
||||
IsString(value) ||
|
||||
IsSymbol(value) ||
|
||||
IsTemplateLiteral(value) ||
|
||||
IsThis(value) ||
|
||||
IsTuple(value) ||
|
||||
IsUndefined(value) ||
|
||||
IsUnion(value) ||
|
||||
IsUint8Array(value) ||
|
||||
IsUnknown(value) ||
|
||||
IsUnsafe(value) ||
|
||||
IsVoid(value) ||
|
||||
IsKind(value)
|
||||
)
|
||||
}
|
||||
88
src/type/guard/value.ts
Normal file
88
src/type/guard/value.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
/** Returns true if this value is an async iterator */
|
||||
export function IsAsyncIterator(value: unknown): value is AsyncIterableIterator<unknown> {
|
||||
return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.asyncIterator in value
|
||||
}
|
||||
/** Returns true if this value is an array */
|
||||
export function IsArray(value: unknown): value is unknown[] {
|
||||
return Array.isArray(value)
|
||||
}
|
||||
/** Returns true if this value is bigint */
|
||||
export function IsBigInt(value: unknown): value is bigint {
|
||||
return typeof value === 'bigint'
|
||||
}
|
||||
/** Returns true if this value is a boolean */
|
||||
export function IsBoolean(value: unknown): value is boolean {
|
||||
return typeof value === 'boolean'
|
||||
}
|
||||
/** Returns true if this value is a Date object */
|
||||
export function IsDate(value: unknown): value is Date {
|
||||
return value instanceof globalThis.Date
|
||||
}
|
||||
/** Returns true if this value is a function */
|
||||
export function IsFunction(value: unknown): value is Function {
|
||||
return typeof value === 'function'
|
||||
}
|
||||
/** Returns true if this value is an iterator */
|
||||
export function IsIterator(value: unknown): value is IterableIterator<unknown> {
|
||||
return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.iterator in value
|
||||
}
|
||||
/** Returns true if this value is null */
|
||||
export function IsNull(value: unknown): value is null {
|
||||
return value === null
|
||||
}
|
||||
/** Returns true if this value is number */
|
||||
export function IsNumber(value: unknown): value is number {
|
||||
return typeof value === 'number'
|
||||
}
|
||||
/** Returns true if this value is an object */
|
||||
export function IsObject(value: unknown): value is Record<PropertyKey, unknown> {
|
||||
return typeof value === 'object' && value !== null
|
||||
}
|
||||
/** Returns true if this value is RegExp */
|
||||
export function IsRegExp(value: unknown): value is RegExp {
|
||||
return value instanceof globalThis.RegExp
|
||||
}
|
||||
/** Returns true if this value is string */
|
||||
export function IsString(value: unknown): value is string {
|
||||
return typeof value === 'string'
|
||||
}
|
||||
/** Returns true if this value is symbol */
|
||||
export function IsSymbol(value: unknown): value is symbol {
|
||||
return typeof value === 'symbol'
|
||||
}
|
||||
/** Returns true if this value is a Uint8Array */
|
||||
export function IsUint8Array(value: unknown): value is Uint8Array {
|
||||
return value instanceof globalThis.Uint8Array
|
||||
}
|
||||
/** Returns true if this value is undefined */
|
||||
export function IsUndefined(value: unknown): value is undefined {
|
||||
return value === undefined
|
||||
}
|
||||
69
src/type/helpers/helpers.ts
Normal file
69
src/type/helpers/helpers.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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 { TSchema } from '../schema/index'
|
||||
import type { TProperties } from '../object/index'
|
||||
import type { TNever } from '../never/index'
|
||||
// ------------------------------------------------------------------
|
||||
// Helper: Common
|
||||
// ------------------------------------------------------------------
|
||||
export type TupleToIntersect<T extends any[]> = T extends [infer I] ? I : T extends [infer I, ...infer R] ? I & TupleToIntersect<R> : never
|
||||
export type TupleToUnion<T extends any[]> = { [K in keyof T]: T[K] }[number]
|
||||
export type UnionToIntersect<U> = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never
|
||||
export type UnionLast<U> = UnionToIntersect<U extends unknown ? (x: U) => 0 : never> extends (x: infer L) => 0 ? L : never
|
||||
export type UnionToTuple<U, Acc extends unknown[] = [], R = UnionLast<U>> = [U] extends [never] ? Acc : UnionToTuple<Exclude<U, R>, [Extract<U, R>, ...Acc]>
|
||||
export type Trim<T> = T extends `${' '}${infer U}` ? Trim<U> : T extends `${infer U}${' '}` ? Trim<U> : T
|
||||
export type Assert<T, E> = T extends E ? T : never
|
||||
export type Evaluate<T> = T extends infer O ? { [K in keyof O]: O[K] } : never
|
||||
export type Ensure<T> = T extends infer U ? U : never
|
||||
export type EmptyString = ''
|
||||
export type ZeroString = '0'
|
||||
// ------------------------------------------------------------------
|
||||
// Helper: Increment
|
||||
// ------------------------------------------------------------------
|
||||
type IncrementBase = { m: '9'; t: '01'; '0': '1'; '1': '2'; '2': '3'; '3': '4'; '4': '5'; '5': '6'; '6': '7'; '7': '8'; '8': '9'; '9': '0' }
|
||||
type IncrementTake<T extends keyof IncrementBase> = IncrementBase[T]
|
||||
type IncrementStep<T extends string> = T extends IncrementBase['m']
|
||||
? IncrementBase['t']
|
||||
: T extends `${infer L extends keyof IncrementBase}${infer R}`
|
||||
? L extends IncrementBase['m']
|
||||
? `${IncrementTake<L>}${IncrementStep<R>}`
|
||||
: `${IncrementTake<L>}${R}`
|
||||
: never
|
||||
type IncrementReverse<T extends string> = T extends `${infer L}${infer R}` ? `${IncrementReverse<R>}${L}` : T
|
||||
export type Increment<T extends string> = IncrementReverse<IncrementStep<IncrementReverse<T>>>
|
||||
/** Increments the given string value + 1 */
|
||||
export function Increment<T extends string>(T: T): Increment<T> {
|
||||
return (parseInt(T) + 1).toString() as Increment<T>
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Helper: Type Asserts
|
||||
// ------------------------------------------------------------------
|
||||
export type AssertProperties<T> = T extends TProperties ? T : TProperties
|
||||
export type AssertRest<T, E extends TSchema[] = TSchema[]> = T extends E ? T : []
|
||||
export type AssertType<T, E extends TSchema = TSchema> = T extends E ? T : TNever
|
||||
29
src/type/helpers/index.ts
Normal file
29
src/type/helpers/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './helpers'
|
||||
98
src/type/index.ts
Normal file
98
src/type/index.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/type
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2023 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.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './any/index'
|
||||
export * from './array/index'
|
||||
export * from './async-iterator/index'
|
||||
export * from './awaited/index'
|
||||
export * from './bigint/index'
|
||||
export * from './boolean/index'
|
||||
export * from './clone/index'
|
||||
export * from './composite/index'
|
||||
export * from './const/index'
|
||||
export * from './constructor/index'
|
||||
export * from './constructor-parameters/index'
|
||||
export * from './date/index'
|
||||
export * from './deref/index'
|
||||
export * from './discard/index'
|
||||
export * from './enum/index'
|
||||
export * from './error/index'
|
||||
export * from './exclude/index'
|
||||
export * from './extends/index'
|
||||
export * from './extract/index'
|
||||
export * from './function/index'
|
||||
export * from './guard/index'
|
||||
export * from './helpers/index'
|
||||
export * from './indexed/index'
|
||||
export * from './instance-type/index'
|
||||
export * from './integer/index'
|
||||
export * from './intersect/index'
|
||||
export * from './intrinsic/index'
|
||||
export * from './iterator/index'
|
||||
export * from './keyof/index'
|
||||
export * from './literal/index'
|
||||
export * from './mapped/index'
|
||||
export * from './never/index'
|
||||
export * from './not/index'
|
||||
export * from './null/index'
|
||||
export * from './number/index'
|
||||
export * from './object/index'
|
||||
export * from './omit/index'
|
||||
export * from './optional/index'
|
||||
export * from './parameters/index'
|
||||
export * from './partial/index'
|
||||
export * from './patterns/index'
|
||||
export * from './pick/index'
|
||||
export * from './promise/index'
|
||||
export * from './readonly/index'
|
||||
export * from './readonly-optional/index'
|
||||
export * from './record/index'
|
||||
export * from './recursive/index'
|
||||
export * from './ref/index'
|
||||
export * from './regexp/index'
|
||||
export * from './registry/index'
|
||||
export * from './required/index'
|
||||
export * from './rest/index'
|
||||
export * from './return-type/index'
|
||||
export * from './schema/index'
|
||||
export * from './sets/index'
|
||||
export * from './static/index'
|
||||
export * from './strict/index'
|
||||
export * from './string/index'
|
||||
export * from './symbol/index'
|
||||
export * from './symbols/index'
|
||||
export * from './template-literal/index'
|
||||
export * from './transform/index'
|
||||
export * from './tuple/index'
|
||||
export * from './type/index'
|
||||
export * from './uint8array/index'
|
||||
export * from './undefined/index'
|
||||
export * from './union/index'
|
||||
export * from './unknown/index'
|
||||
export * from './unsafe/index'
|
||||
export * from './void/index'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user