pax_global_header00006660000000000000000000000064150543757700014527gustar00rootroot0000000000000052 comment=e0ec98c9dbbf6f6b8777f121a2da38f2d09cf2ed sinclairzx81-typebox-e0ec98c/000077500000000000000000000000001505437577000162605ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/.github/000077500000000000000000000000001505437577000176205ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/.github/.keep000066400000000000000000000000001505437577000205330ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/.github/workflows/000077500000000000000000000000001505437577000216555ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/.github/workflows/build.yml000066400000000000000000000010251505437577000234750ustar00rootroot00000000000000name: Build on: [push, pull_request] jobs: TypeBox: runs-on: ${{ matrix.os }} strategy: matrix: node: [16.x, 18.x, 20.x] os: [ubuntu-latest, windows-latest, macOS-latest] steps: - uses: actions/checkout@v3 - name: Install Node uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} - name: Install Packages run: npm install - name: Build Library run: npm run build - name: Test Library run: npm run testsinclairzx81-typebox-e0ec98c/.github/workflows/nightly.yml000066400000000000000000000012641505437577000240610ustar00rootroot00000000000000name: Build Nightly on: schedule: - cron: '0 18 * * *' # 6pm Daily jobs: TypeBox: runs-on: ${{ matrix.os }} strategy: matrix: node: [20.x] os: [ubuntu-latest] steps: - uses: actions/checkout@v3 - name: Install Node uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} - name: Install Packages run: npm install - name: Install TypeScript Latest run: npm install typescript@latest - name: Build TypeBox run: npm run build - name: Install TypeScript Next run: npm install typescript@next - name: Build TypeBox run: npm run buildsinclairzx81-typebox-e0ec98c/.gitignore000066400000000000000000000000311505437577000202420ustar00rootroot00000000000000node_modules target dist sinclairzx81-typebox-e0ec98c/.vscode/000077500000000000000000000000001505437577000176215ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/.vscode/settings.json000066400000000000000000000003031505437577000223500ustar00rootroot00000000000000{ "files.exclude": { "node_modules": true, "package-lock.json": true }, "editor.suggest.showStatusBar": false, "typescript.tsdk": "node_modules\\typescript\\lib" }sinclairzx81-typebox-e0ec98c/changelog/000077500000000000000000000000001505437577000202075ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/changelog/0.17.1.md000066400000000000000000000021741505437577000212610ustar00rootroot00000000000000## [0.17.1](https://www.npmjs.com/package/@sinclair/typebox/v/0.17.1) - Remove default `additionalProperties: false` constraint from all object schemas. This update removes the `additionalProperties: false` constraint on all object schemas. This constraint was introduced on `0.16.x` but has resulted in significant downstream problems composing schemas whose types `intersect`. This is due to a JSON schema design principle where constraints should only be added (never removed), and that intersection types may require removal of the `additionalProperties` constraint in some cases, this had resulted in some ambiguity with respect to how TypeBox should handle such intersections. This update can also be seen as a precursor towards TypeBox potentially leveraging `unevaluatedProperties` for type intersection in future releases. Implementers should take note that in order to constrain the schema to known properties, one should apply the `additionalProperties: false` as the second argument to `Type.Object({...})`. ```typescript const T = Type.Object({ a: Type.String(), b: Type.Number() }, { additionalProperties: false })sinclairzx81-typebox-e0ec98c/changelog/0.17.4.md000066400000000000000000000027351505437577000212670ustar00rootroot00000000000000## [0.17.4](https://www.npmjs.com/package/@sinclair/typebox/v/0.17.4) Changes: - Added `Type.Box()` and `Type.Ref()` functions. Notes: This update provides the `Type.Box()` function to enable common related schemas to grouped under a common namespace; typically expressed as a `URI`. This functionality is primarily geared towards allowing one to define a common set of domain objects that may be shared across application domains running over a network. The `Type.Box()` is intended to be an analog to `XML` `xmlns` namespaces. The `Type.Ref()` function is limited to referencing from boxes only. The following is an example. ```typescript // Domain objects for the fruit service. const Fruit = Type.Box('https://fruit.domain.com', { Apple: Type.Object({ ... }), Orange: Type.Object({ ... }), }) // An order referencing types of the fruit service. const Order = Type.Object({ id: Type.String(), quantity: Type.Number(), item: Type.Union([ Type.Ref(Fruit, 'Apple'), Type.Ref(Fruit, 'Orange') ]) }) ``` > Note: As of this release, the `Type.Omit()`, `Type.Pick()`, `Type.Partial()`, `Type.Readonly()` and `Type.Intersect()` functions do not work with Reference Types. This may change in later revisions. For validation using `Ajv`, its possible to apply the `Box` directly as a schema. ```typescript ajv.addSchema(Fruit) // makes all boxed types known to Ajv ``` This functionality is flagged as `EXPERIMENTAL` and awaits community feedback.sinclairzx81-typebox-e0ec98c/changelog/0.17.6.md000066400000000000000000000033131505437577000212620ustar00rootroot00000000000000## [0.17.6](https://www.npmjs.com/package/@sinclair/typebox/v/0.17.6) Changes: - Added `Type.Rec(...)` function. Notes: This update introduces the `Type.Rec()` function for enabling Recursive Types. Please note that due to current inference limitations in TypeScript, TypeBox is unable to infer the type and resolves inner types to `any`. This functionality enables for complex self referential schemas to be composed. The following creates a binary expression syntax node with the expression self referential for left and right operands. ```typescript const Operator = Type.Union([ Type.Literal('+'), Type.Literal('-'), Type.Literal('/'), Type.Literal('*') ]) type Expression = Static // Defines a self referencing type. const Expression = Type.Rec(Self => Type.Object({ left: Type.Union([Self, Type.Number()]), right: Type.Union([Self, Type.Number()]), operator: Operator })) function evaluate(expression: Expression): number { const left = typeof expression.left !== 'number' ? evaluate(expression.left as Expression) // assert as Expression : expression.left const right = typeof expression.right !== 'number' ? evaluate(expression.right as Expression) // assert as Expression : expression.right switch(expression.operator) { case '+': return left + right case '-': return left - right case '*': return left * right case '/': return left / right } } const result = evaluate({ left: { left: 10, operator: '*', right: 4, }, operator: '+', right: 2, }) // -> 42 ``` This functionality is flagged as `EXPERIMENTAL` and awaits community feedback.sinclairzx81-typebox-e0ec98c/changelog/0.18.0.md000066400000000000000000000024311505437577000212550ustar00rootroot00000000000000## [0.18.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.18.0) Changes: - Function `Type.Intersect(...)` is now implemented with `allOf` and constrained with `unevaluatedProperties` (draft `2019-09`) - Function `Type.Dict(...)` has been deprecated and replaced with `Type.Record(...)`. - Function `Type.Strict(...)` now includes the `$schema` property referencing the `2019-09` draft. ### Type.Intersect(...) TypeBox now targets JSON schema draft `2019-09` for expressing `Type.Intersect(...)`. This is now expressed via `allOf` with additionalProperties constrained with `unevaluatedProperties`. Note that `unevaluatedProperties` is a feature of the `2019-09` specification. ### Type.Record(K, V) TypeBox has deprecated `Type.Dict(...)` in favor of the more generic `Type.Record(...)`. Where as `Type.Dict(...)` was previously expressed with `additionalProperties: { ... }`, `Type.Record(...)` is expressed with `patternProperties` and supports both `string` and `number` indexer keys. Additionally, `Type.Record(...)` supports string union arguments. This is analogous to TypeScript's utility record type `Record<'a' | 'b' | 'c', T>`. ## [0.17.7](https://www.npmjs.com/package/@sinclair/typebox/v/0.17.7) Changes: - Added optional `$id` argument on `Type.Rec()`. - Documentation updates.sinclairzx81-typebox-e0ec98c/changelog/0.18.1.md000066400000000000000000000006561505437577000212650ustar00rootroot00000000000000## [0.18.1](https://www.npmjs.com/package/@sinclair/typebox/v/0.18.1) - Function `Type.Enum(...)` now expressed with `anyOf`. This to remove the `allowUnionTypes` configuration required to use `enum` with in AJV strict. - Function `Type.Rec(...)` now takes a required `$id` as the first parameter. - Function `Type.Strict(...)` no longer includes a `$schema`. Callers can now optionally pass `CustomOptions` on `Type.Strict(...)`sinclairzx81-typebox-e0ec98c/changelog/0.19.0.md000066400000000000000000000013031505437577000212530ustar00rootroot00000000000000## [0.19.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.19.0) Updates: - Function `Type.Box(...)` removes `$id` parameter as first argument. - Function `Type.Ref(...)` is now overloaded to support referencing `Type.Box(...)` and `TSchema`. Notes: This update changes the signature of `Type.Box(...)` and removes the explicit `$id` passing on the first parameter. The `$id` must be passed as an option if the caller wants to reference that type. ```typescript const T = Type.String({ $id: 'T' }) const B = Type.Box({ T }, { $id: 'B' }) const R1 = Type.Ref(T) // const R1 = { $ref: 'T' } const R2 = Type.Ref(B, 'T') // const R2 = { $ref: 'B#/definitions/T' } ```sinclairzx81-typebox-e0ec98c/changelog/0.20.0.md000066400000000000000000000011741505437577000212510ustar00rootroot00000000000000## [0.20.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.20.0) Updates: - Function `Type.Rec(...)` signature change. - Minor documentation updates. Notes: The `Type.Rec(...)` function signature has been changed to allow passing the `$id` as a custom option. This is to align `Type.Rec(...)` with other functions that accept `$id` as an option. `Type.Rec(...)` can work with or without an explicit `$id`, but it is recommend to specify one if the recursive type is nested in an outer schema. ```typescript const Node = Type.Rec(Self => Type.Object({ id: Type.String(), nodes: Type.Array(Self) }), { $id: 'Node' }) ```sinclairzx81-typebox-e0ec98c/changelog/0.20.1.md000066400000000000000000000002221505437577000212430ustar00rootroot00000000000000## [0.20.1](https://www.npmjs.com/package/@sinclair/typebox/v/0.20.1) Updates: - TypeBox mandates TypeScript compiler version `4.3.5` and above.sinclairzx81-typebox-e0ec98c/changelog/0.21.0.md000066400000000000000000000010161505437577000212450ustar00rootroot00000000000000## [0.21.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.21.0) Updates: - TypeBox static inference has been updated inline with additional inference constraints added in TypeScript 4.5. All types now include a phantom `_infer` property which contains the inference TS type for a given schema. The type of this property is inferred at the construction of the schema, and referenced directly via `Static`. - `Type.Box(...)` has been renamed to `Type.Namespace(...)` to draw an analogy with XML's `xmlns` XSD types. sinclairzx81-typebox-e0ec98c/changelog/0.21.2.md000066400000000000000000000012561505437577000212550ustar00rootroot00000000000000## [0.21.2](https://www.npmjs.com/package/@sinclair/typebox/v/0.21.2) Updates: - TypeBox now correctly infers for nested union and intersect types. Before ```typescript const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.String() }) const C = Type.Object({ c: Type.String() }) const T = Type.Intersect([A, Type.Union([B, C])]) // type T = { a: string } & { b: string } & { c: string } ``` After ```typescript const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.String() }) const C = Type.Object({ c: Type.String() }) const T = Type.Intersect([A, Type.Union([B, C])]) // type T = { a: string } & ({ b: string } | { c: string }) ```sinclairzx81-typebox-e0ec98c/changelog/0.22.0.md000066400000000000000000000016771505437577000212630ustar00rootroot00000000000000## [0.22.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.22.0) Updates: - The type `TSchema` is now expressed as an HKT compatible interface. All types now extend the `TSchema` interface and are themselves also expressed as interfaces. This work was undertaken to explore recursive type aliases in future releases. - The phantom property `_infer` has been renamed to `$static`. Callers should not interact with this property as it will always be `undefined` and used exclusively for optimizing type inference in TypeScript 4.5 and above. - TypeBox re-adds the feature to deeply introspect schema properties. This feature was temporarily removed on the `0.21.0` update to resolve deep instantiation errors on TypeScript 4.5. - The `Type.Box(...)` and `Type.Rec(...)` functions internally rename the property `definitions` to `$defs` inline with JSON schema draft 2019-09 conventions. Reference [here](https://opis.io/json-schema/2.x/definitions.html).sinclairzx81-typebox-e0ec98c/changelog/0.23.0.md000066400000000000000000000015471505437577000212600ustar00rootroot00000000000000## [0.23.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.23.0) Updates: - The types `Type.Namespace(...)` and `Type.Ref(...)` are promoted to `Standard`. - TypeBox now includes an additional type named `TRef<...>` that is returned on calls to `Type.Ref(...)`. The `TRef<...>` includes a new `RefKind` symbol for introspection of the reference type. - TypeBox now maintains an internal dictionary of all schemas passed that contain an `$id` property. This dictionary is checked whenever a user attempts to reference a type and will throw if attempting to reference a target schema with no `$id`. - The types `Type.Partial(...)`, `Type.Required(...)`, `Type.Omit()` and `Type.Pick(...)` now support reference types. Note that when using these functions with references, TypeBox will replicate the source schema and apply the necessary modifiers to the replication.sinclairzx81-typebox-e0ec98c/changelog/0.23.1.md000066400000000000000000000002361505437577000212530ustar00rootroot00000000000000## [0.23.1](https://www.npmjs.com/package/@sinclair/typebox/v/0.23.1) Updates: - The `Type.KeyOf(...)` type can now accept references of `Type.Ref(TObject)`sinclairzx81-typebox-e0ec98c/changelog/0.23.3.md000066400000000000000000000001671505437577000212600ustar00rootroot00000000000000## [0.23.3](https://www.npmjs.com/package/@sinclair/typebox/v/0.23.3) Updates: - Fix: Rename BoxKind to NamespaceKindsinclairzx81-typebox-e0ec98c/changelog/0.24.0.md000066400000000000000000000040771505437577000212620ustar00rootroot00000000000000## [0.24.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.24.0) Changes: - The `kind` and `modifier` keywords are now expressed as symbol keys. This change allows AJV to leverage TypeBox schemas directly without explicit configuration of `kind` and `modifier` in strict mode. - `Type.Intersect([...])` now returns a composite `TObject` instead of a `allOf` schema representation. This change allows intersected types to be leveraged in calls to `Omit`, `Pick`, `Partial`, `Required`. - `Type.Void(...)` now generates a `{ type: null }` schema representation. This is principally used for RPC implementations where a RPC target function needs to respond with a serializable value for `void` return. - `Type.Rec(...)` renamed to `Type.Recursive(...)` and now supports non-mutual recursive type inference. Added: - `Type.Unsafe(...)`. This type enables custom schema representations whose static type is informed by generic type T. - `Type.Uint8Array(...)`. This is a non-standard schema that can be configured on AJV to enable binary buffer range validation. - Added optional extended `design` property on all schema options. This property can be used to specify design time metadata when rendering forms. Compiler: - TypeBox now provides an optional experimental type compiler that can be used to validate types without AJV. This compiler is not a standard JSON schema compiler and will only compile TypeBox's known schema representations. For full JSON schema validation, AJV should still be the preference. This compiler is a work in progress. Value: - TypeBox now provides a value generator that can generate default values from TypeBox types. Breaking Changes: - `Type.Intersect(...)` is constrained to accept types of `TObject` only. - `Type.Namespace(...)` has been removed. - The types `TUnion`, `TEnum`, `KeyOf` and `TLiteral[]` are all now expressed via `allOf`. For Open API users, Please consider `Type.Unsafe()` to express `enum` string union representations. Documentation on using `Type.Unsafe()` can be found [here](https://github.com/sinclairzx81/typebox#Unsafe-Types)sinclairzx81-typebox-e0ec98c/changelog/0.24.15.md000066400000000000000000000017231505437577000213430ustar00rootroot00000000000000## [0.24.15](https://www.npmjs.com/package/@sinclair/typebox/v/0.24.15) Added: - `Conditional.Extends(...)` This enables TypeBox to conditionally map types inline with TypeScripts structural equivalence checks. Tested against TypeScript 4.7.4. - `Conditional.Extract(...)` Which analogs TypeScripts `Extract<...>` utility type. Additional information [here](https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union) - `Conditional.Exclude(...)` Which analogs TypeScripts `Exclude<...>` utility type. Additional information [here](https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers) - `Type.Parameters(...)` Returns the parameters of a `TFunction` as a `TTuple` - `Type.ReturnType(...)` Returns the return type schema of a `TFunction` - `Type.ConstructorParameters(...)` Returns the parameters of a `TConstructor` as a `TTuple` - `Type.InstanceType(...)` Returns the instance type schema of a `TConstructor`sinclairzx81-typebox-e0ec98c/changelog/0.24.44.md000066400000000000000000000102771505437577000213510ustar00rootroot00000000000000## [0.24.44](https://www.npmjs.com/package/@sinclair/typebox/v/0.24.44) Updates: - [189](https://github.com/sinclairzx81/typebox/pull/189) Both `Value.Error(T, value)` and `TypeCheck.Error(value)` now return an iterator for validation errors. - [191](https://github.com/sinclairzx81/typebox/pull/191) TypeBox now provides a `TypeGuard` API that can be used to check the structural validity of TypeBox type. The TypeGuard can be used in reflection / code generation scenarios to resolve the appropriate inner `TSchema` type while traversing a outer type. - [197](https://github.com/sinclairzx81/typebox/pull/197) TypeBox now implements conditional runtime type mapping. This functionality is offered as separate import for the `0.24.0` release but may be provided as standard type in later releases. This API enables `type T = Foo extends Bar ? true : false` conditional checks to be implemented at runtime. This API also provides the `Exclude` and `Extract` utility types which are implemented through conditional types in TypeScript. - [199](https://github.com/sinclairzx81/typebox/pull/199) TypeBox now provides better support for variadic function and constructor signatures. Currently variadic types are mapped as `Tuple` types. - [200](https://github.com/sinclairzx81/typebox/pull/200) The types `TPick` and `TOmit` now support types of `TUnion[]>` to be used to select properties. Additionally, `KeyOf` now returns `TUnion[]>`, allowing `KeyOf` schemas to be passed to `TPick` and `TOmit`. - [214](https://github.com/sinclairzx81/typebox/pull/214) TypeBox now provides better support for i18n. To achieve this, TypeBox includes fixed mappable error codes on the `ValueError` type. These codes can be used by external implementers to create localized error messages. TypeBox may include localized error codes as an optional import in future releases. - [288](https://github.com/sinclairzx81/typebox/pull/228) TypeBox now allows users to implement custom string validator formats. These formats are internally shared between the `Value` and `TypeCompiler` API's. TypeBox does not currently provide any built in formats, however the standard expected set (email, uuid, uri, etc) may be provided via optional import (inline with ajv-formats usage) - [229](https://github.com/sinclairzx81/typebox/pull/229) The `Value.Cast()` function now implements automatic coercion of string, number and Boolean types. - [231](https://github.com/sinclairzx81/typebox/pull/231) TypeBox provides a new `Value.Diff()` and `Value.Patch()` utility API for JavaScript values. This API is intended to provide a basis for the efficient transmission of state updates across a network. This API can diff any JavaScript value (typed or untyped) but is recommended to be used in conjunction with a formal static type. - [236](https://github.com/sinclairzx81/typebox/pull/236) TypeBox now implements the `TNever` type. This type is analogous to TypeScript's `never` type and is used in instances a composition results in a non-reconcilable type. Currently this type is implemented for empty `TUnion<[]>` types only. Future releases may utilize this type for planned updates to `TIntersect` (for example `string & number` resolves to `never`) - [241](https://github.com/sinclairzx81/typebox/pull/241) [247](https://github.com/sinclairzx81/typebox/pull/247) TypeBox now exposes a ValuePointer API that can be used to mutate a value via an RFC6901 JSON Pointer. Previously this functionality was internally used by `Value.Diff()` and `Value.Patch()` functions but is now offered as an optional import for implementations that need to update values manually through pointer references. Additional: - This project now includes two reference code generation utilities that can be used in custom build tooling. The first is `TypeScriptCodeGen` which will remap TypeScript `interface` and `type` definitions to TypeBox types. The second is `TypeBoxCodeGen` which will map existing TypeBox types into TypeScript type definitions. These implementations are not expected to be part of the TypeBox package, but users are free to clone and enhance them in their existing tool chains. Reference implementations can be found https://github.com/sinclairzx81/typebox/tree/master/codegensinclairzx81-typebox-e0ec98c/changelog/0.24.49.md000066400000000000000000000010061505437577000213440ustar00rootroot00000000000000## [0.24.49](https://www.npmjs.com/package/@sinclair/typebox/v/0.24.49) Updates: - [264](https://github.com/sinclairzx81/typebox/pull/264) TypeBox now provides preliminary support for non Boolean `additionalProperties`. This allows existing `TObject` schemas to be augmented with additional properties of a known type. Additional: - TypeBox provides an additional reference `codegen` module for generating raw JSON Schema from TypeScript types via the TS compiler API. This generator may be used in future tooling.sinclairzx81-typebox-e0ec98c/changelog/0.24.6.md000066400000000000000000000013001505437577000212520ustar00rootroot00000000000000## [0.24.6](https://www.npmjs.com/package/@sinclair/typebox/v/0.24.6) Added: - TypeBox now offers a `TypeGuard` module for structurally checking TypeBox schematics. This module can be used in runtime type reflection scenarios where it's helpful to test a schema is of a particular form. This module can be imported under the `@sinclair/typebox/guard` import path. Example: ```typescript import { TypeGuard } from '@sinclair/typebox/guard' const T: any = {} // T is any const { type } = T // unsafe: type is any if(TypeGuard.IsString(T)) { const { type } = T // safe: type is 'string' } ```sinclairzx81-typebox-e0ec98c/changelog/0.24.8.md000066400000000000000000000006611505437577000212650ustar00rootroot00000000000000## [0.24.8](https://www.npmjs.com/package/@sinclair/typebox/v/0.24.8) Added: - `Value.Cast(T, value)` structurally casts a value into another form while retaining information within the original value. - `Value.Check(T, value)` provides slow dynamic type checking for values. For performance, one should consider the `TypeCompiler` or `Ajv` validator. - `Value.Errors(T, value)` returns an iterator of errors found in a given value.sinclairzx81-typebox-e0ec98c/changelog/0.25.0.md000066400000000000000000000017361505437577000212620ustar00rootroot00000000000000## [0.25.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.0) Updates: - [271](https://github.com/sinclairzx81/typebox/pull/271) Adds a new non-standard `Type.Date()` type. This type joins the existing `Type.UInt8Array()` as a promoted extended type used to represent core JavaScript primitives. It's inclusion was prompted by end user requirements to validate Date objects prior to writing them to Date supported API's and where serialization of the Date object is handled internally by the API. - [271](https://github.com/sinclairzx81/typebox/pull/271) Redesign of Extended Type representations. Extended types been updated to provide external validators (such as Ajv) additional standard proporties to use when defining the custom schema. These properties are `instanceOf` (used for validating a class `object` instances), and `typeOf` (when validating `value` types). Information on configuring AJV for these properties can be found in the AJV section of the TypeBox readme.sinclairzx81-typebox-e0ec98c/changelog/0.25.10.md000066400000000000000000000006131505437577000213340ustar00rootroot00000000000000## [0.25.10](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.10) Updates: - [283](https://github.com/sinclairzx81/typebox/pull/283) Updates the custom type validator callback signature to accept a schema instance. The schema instance may include additional constraints (such as options) that may be used during the validation process. `Custom.Set('', (schema, value) => { ... })`.sinclairzx81-typebox-e0ec98c/changelog/0.25.11.md000066400000000000000000000013601505437577000213350ustar00rootroot00000000000000## [0.25.11](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.11) Updates: - [286](https://github.com/sinclairzx81/typebox/pull/286) implements a FNV1A-64 non cryptographic hashing function in TypeBox. This function should not be used in place of cryptographic hashing functions, rather it's purpose is to provide relatively fast, hashing mechanism to assist with checks for arrays with uniqueItems constraints, specifically for cases where the array may contains reference values (such as objects, arrays, Dates and Uint8Array). This function is provided via `Value.Hash()` for convenience as the hash may be useful to generate a numeric identifier for values (with some considerations to React array rendering in absence of key or identifier)sinclairzx81-typebox-e0ec98c/changelog/0.25.18.md000066400000000000000000000007431505437577000213500ustar00rootroot00000000000000## [0.25.18](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.18) Updates: - [307](https://github.com/sinclairzx81/typebox/pull/307) implements date conversion when casting values with `Value.Cast(Type.Date(), ...)`. Castable values include numbers (interpretted as timestamps) and iso8601 string values. UNCASTABLE values will result in dates with values of `1970-01-01T00:00:00.000Z`. This version also includes more robust checks for Dates initialized with invalid values.sinclairzx81-typebox-e0ec98c/changelog/0.25.22.md000066400000000000000000000003341505437577000213370ustar00rootroot00000000000000## [0.25.22](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.22) Updates: - [323](https://github.com/sinclairzx81/typebox/pull/323) adds compiler support for UTF-16 (unicode) characters for schema identifiers. sinclairzx81-typebox-e0ec98c/changelog/0.25.23.md000066400000000000000000000007341505437577000213440ustar00rootroot00000000000000## [0.25.23](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.23) Updates: - [324](https://github.com/sinclairzx81/typebox/pull/324) TypeScript Language Service now presents JSDoc comments when inferring static object properties. (IntelliSense) - [325](https://github.com/sinclairzx81/typebox/pull/325) Additional property inference optimizations. Additional: - Huge thank you to GITHUB user [stevezhu](https://github.com/stevezhu) for these excellent contributions.sinclairzx81-typebox-e0ec98c/changelog/0.25.24.md000066400000000000000000000010361505437577000213410ustar00rootroot00000000000000## [0.25.24](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.23) Updates: - [331](https://github.com/sinclairzx81/typebox/pull/331) Implements an additional check specific to property types of `required & undefined`. This to ensure the property key exists when the property value extends `undefined`. - [331](https://github.com/sinclairzx81/typebox/pull/331) Documentation updates for AJV and TypeCompiler Additional: - [331](https://github.com/sinclairzx81/typebox/pull/331) Remove unused recursive code paths for create and cast.sinclairzx81-typebox-e0ec98c/changelog/0.25.9.md000066400000000000000000000006441505437577000212700ustar00rootroot00000000000000## [0.25.9](https://www.npmjs.com/package/@sinclair/typebox/v/0.25.9) Updates: - [282](https://github.com/sinclairzx81/typebox/pull/282) TypeBox now supports custom types. These types require the user to specify a custom `[Kind]` string on the type. Custom types can be registered via `Custom.Set('', (value) => { ... })` which allow the TypeCompiler and Value API's to make use of user defined validation logic.sinclairzx81-typebox-e0ec98c/changelog/0.26.0.md000066400000000000000000000363251505437577000212650ustar00rootroot00000000000000## [0.26.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.26.0) ## Overview TypeBox now provides "runtime conditional types" (formally the `Conditional` module) as standard on `Type.*`. Additional updates in this revision include automatic union and intersection unwrap, universal support for utility types, several ergonomic enhancements and additional options for framework integrators. This revision also carries out a number an internal refactorings to reduce the amount of submodule imports. Revision 0.26.0 is a milestone release for the TypeBox project and requires a minor semver update. ## Contents - Enhancements - [Standard Type Builder](#Standard-Type-Builder) - [Automatic Unwrap for Union and Intersect](#Automatic-Unwrap-for-Union-and-Intersect) - [Intersect and Union now Compose](#Intersect-and-Union-now-Compose) - [Runtime Conditional Types](#Runtime-Conditional-Types) - [Value Convert](#Value-Convert) - [Error Iterator](#Error-Iterator) - [Codegen without JIT](#Codegen-without-JIT) - [Standard Type (Composite)](#Standard-Type-Composite) - [Standard Type (Not)](#Standard-Type-Not) - [Extended Type (BigInt)](#Extended-Type-BigInt) - [Extended Type (Symbol)](#Extended-Type-Symbol) - Breaking - [Minimum TypeScript Version](#Minimum-TypeScript-Version) - [Intersect Schema Representation](#Intersect-Schema-Representation) - [Never Schema Representation](#Never-Schema-Representation) - [Value Cast and Convert](#Value-Cast-and-Convert) - [Moved TypeGuard Module](#Moved-TypeGuard-Module) - [Format Renamed to FormatRegistry](#Format-Renamed-to-FormatRegistry) - [Custom Renamed to TypeRegistry](#Custom-Renamed-to-TypeRegistry) ## Standard Type Builder Revision 0.26.0 exports a new type builder called `StandardType`. This builder only allows for the construction JSON Schema compliant types by omitting all Extended types. ```typescript import { StandardType as Type, Static } from '@sinclair/typebox' const T = Type.Date() // error: no such function ``` ## Automatic Unwrap for Union and Intersect Revision 0.26.0 will automatically unwrap unions and intersections for the following cases. ```typescript const T1 = Type.Union([Type.String(), Type.Number()]) // TUnion<[TString, TNumber]> const T2 = Type.Union([Type.String()]) // TString const T3 = Type.Union([]) // TNever ``` ## Intersect and Union now Compose Revision 0.26.0 re-enables support for union and intersection type composition. These types are also made compatible with `Pick`, `Omit`, `Partial`, `Required` and `KeyOf` utility types. ```typescript const A = Type.Object({ type: Type.Literal('A') }) const B = Type.Object({ type: Type.Literal('B') }) const C = Type.Object({ type: Type.Literal('C') }) const Union = Type.Union([A, B, C]) const Extended = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() }) const T = Type.Intersect([Union, Extended]) // type T = ({ // type: "A"; // } | { // type: "B"; // } | { // type: "C"; // }) & { // x: number; // y: number; // z: number; // } const K = Type.KeyOf(T) // type K = "type" | "x" | "y" | "z" const P = Type.Pick(T, ['type', 'x']) // type P = ({ // type: "A"; // } | { // type: "B"; // } | { // type: "C"; // }) & { // x: number; // } const O = Type.Partial(P) // type O = ({ // type?: "A" | undefined; // } | { // type?: "B" | undefined; // } | { // type?: "C" | undefined; // }) & { // x?: number | undefined; // } ``` ## Runtime Conditional Types Revision 0.26.0 adds the runtime conditional types `Extends`, `Extract` and `Exclude` as standard. #### TypeScript ```typescript type T0 = string extends number ? true : false // ^ false type T1 = Extract // ^ number type T2 = Exclude // ^ string ``` #### TypeBox ```typescript const T0 = Type.Extends(Type.String(), Type.Number(), Type.Literal(true), Type.Literal(false)) // ^ TLiteral const T1 = Type.Extract(Type.Union([Type.String(), Type.Number()]), Type.Number()) // ^ TNumber const T2 = Type.Exclude(Type.Union([Type.String(), Type.Number()]), Type.Number()) // ^ TString ``` ## Value Convert Revision 0.26.0 adds a new `Convert` function to the `Value.*` module. This function will perform a type coercion for any value mismatched to its type if a reasonable conversion is possible. ```typescript const T = Type.Number() const A = Value.Convert(T, '42') // const A: unknown = 42 - ... Convert(...) will return `unknown` const B = Value.Check(T, A) // const B = true - ... so should be checked ``` ## Error Iterator Revision 0.26.0 now returns a `ValueErrorIterator` for `.Errors(...)`. This iterator provides a utility function to obtain the first error only. To obtain all errors, continue to use `for-of` enumeration or array spread syntax. ```typescript const T = Type.Number() const First = Value.Errors(T, 'foo').First() // const First = { path: '', message: 'Expected number', ... } const All = [...Value.Errors(T, 'foo')] // const All = [{ path: '', message: 'Expected number', ... }] ``` ## Codegen without JIT Revision 0.26.0 adds a `.Code()` function to the `TypeCompiler` to enable code generation without JIT evaluation. ```typescript import { TypeCompiler } from '@sinclair/typebox/compiler' const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const C = TypeCompiler.Code(T) // return function check(value) { // return ( // (typeof value === 'object' && value !== null) && // !Array.isArray(value) && // typeof value.x === 'number' && // Number.isFinite(value.x) && // typeof value.y === 'number' && // Number.isFinite(value.y) // ) // } ``` ## Standard Type (Not) Revision 0.26.0 introduces the `Not` standard type. This type allows for the inversion of assertion logic which can be useful to narrow for broader types. #### Example 1 ```typescript const T = Type.Not(Type.String({ pattern: 'A|B|C' }), Type.String()) Value.Check(T, 'A') // false Value.Check(T, 'B') // false Value.Check(T, 'C') // false Value.Check(T, 'D') // true ``` #### Example 2 ```typescript const Even = Type.Number({ multipleOf: 2 }) const Odd = Type.Not(Even, Type.Number()) Value.Check(Even, 0) // true Value.Check(Even, 1) // false Value.Check(Even, 2) // true Value.Check(Odd, 0) // false Value.Check(Odd, 1) // true Value.Check(Odd, 2) // false ``` ## Standard Type (Composite) Revision 0.26.0 includes a new `Composite` standard type. This type will combine an array of `TObject[]` into a `TObject` by taking a union of any overlapping properties. ```typescript const A = Type.Object({ type: Type.Literal('A') }) const B = Type.Object({ type: Type.Literal('B') }) const C = Type.Object({ type: Type.Literal('C'), value: Type.Number() }) const T = Type.Composite([A, B, C]) // type T = { // type: 'A' | 'B' | 'C' // value: number // } ``` ## Extended Type (Symbol) Revision 0.26.0 provides provisional support for `Symbol` type validation. ```typescript const T = Type.Symbol() Value.Check(A, Symbol('Foo')) // true ``` ## Extended Type (BigInt) Revision 0.26.0 provides provisional support for `BigInt` type validation. ```typescript const T = Type.BigInt({ minimum: 10n }) Value.Check(B, 1_000_000n) // true ``` ## Breaking Changes The following are breaking changed in Revision 0.26.0 ## Minimum TypeScript Version Revision 0.26.0 requires a minimum recommended TypeScript version of `4.2.3`. Version `4.1.5` is no longer supported. ## Intersect Schema Representation Revision 0.26.0 changes the schema representation for `Intersect`. Revision 0.25.0 would construct a composite `object` type, in 0.26.0, `Intersect` is expressed as `anyOf`. If upgrading, consider using `Type.Composite(...)` to return backwards compatible representations. #### Intersect 0.25.0 ```typescript const T = Type.Intersect([ // const U = { Type.Object({ // type: 'object', x: Type.Number(), // required: ['x', 'y'], }), // properties: { Type.Object({ // x: { y: Type.Number(), // type: 'number' }) // }, ]) // y: { // type: 'number' // } // } // } ``` #### Intersect 0.26.0 ```typescript const T = Type.Intersect([ // const U = { Type.Object({ // type: 'object', x: Type.Number(), // allOf: [{ }), // type: 'object', Type.Object({ // required: [ 'x' ], y: Type.Number(), // properties: { }) // x: { type: 'number' } ]) // } // }, { // type: 'object', // required: ['y'], // properties: { // y: { type: 'number' } // } // }] // } ``` ## Never Schema Representation Revision 0.26.0 simplifies the representation for `TNever`. Previous versions of TypeBox used an illogical intersection of Boolean constants via `allOf`. In 0.26.0, `never` is expressed as a `not` schema of type `any`. #### Intersect 0.25.0 ```typescript const T = Type.Never() // const T = { // allOf: [ // { type: 'boolean', const: true } // { type: 'boolean', const: false } // ] // } ``` #### Intersect 0.26.0 ```typescript const T = Type.Never() // const T = { not: {} } ``` ## Value Cast and Convert Revision 0.26.0 removes the `Cast` functions ability to coerce values. Use the new `Convert` function prior to `Cast`. ```typescript const T = Type.Number() const V = Value.Cast(T, '42') // const V = 42 - 0.25.0 coerces to 42 const V = Value.Cast(T, Value.Convert(T, '42')) // const V = 42 - 0.26.0 convert then cast ``` ## Moved TypeGuard Module The `TypeGuard` is now imported via the `@sinclair/typebox` module. This move is due to the TypeBox compositor internally using the guard when constructing types. ```typescript import { TypeGuard } from '@sinclair/typebox/guard' // 0.25.0 import { TypeGuard } from '@sinclair/typebox' // 0.26.0 ``` ## Format Renamed to FormatRegistry The `Format` module has been renamed to `FormatRegistry` and moved to the `typebox.ts` module. ```typescript import { Format } from '@sinclair/typebox/format' // 0.25.0 import { FormatRegistry } from '@sinclair/typebox' // 0.26.0 ``` ## Custom Renamed to TypeRegistry The `Format` module has been renamed to `FormatRegistry` and moved to the `typebox.ts` module. ```typescript import { Custom } from '@sinclair/typebox/format' // 0.25.0 import { TypeRegistry } from '@sinclair/typebox' // 0.26.0 ```sinclairzx81-typebox-e0ec98c/changelog/0.26.2.md000066400000000000000000000035331505437577000212620ustar00rootroot00000000000000## [0.26.2](https://www.npmjs.com/package/@sinclair/typebox/v/0.26.2) Updates: - [331](https://github.com/sinclairzx81/typebox/pull/349) Revert 0.25.0 Intersect logic for Composite Notes: This PR reverts the logic on Type.Composite back to 0.25.0 Type.Intersect due to excessive type instantiation issues. On 0.26.0, Type.Composite attempted to take a union for overlapping properties, however due to the sophistication required to type map the unions for overlapping properties, this has resulted in type instantiation problems for some users upgrading to 0.26.0. As such, 0.26.2 reverts back to the 0.25.0 interpretation, but applies type mappings more inline with TS's interpretation of an overlapping varying property types. In the examples below, the type `C` is the evaluated type for Type.Composite. Note that TS will not union for overlapping properties and instead evaluate `never`. The 0.26.2 implementation falls inline with this evaluation. ```typescript { // evaluation case 1: non-varying type T = { a: number } & { a: number } type C = {[K in keyof T]: T[K] } // type C = { a: number } } { // evaluation case 2: varying type T = { a: number } & { a: string } type C = {[K in keyof T]: T[K] } // type C = { a: never } } { // evaluation case 3: single optional type T = { a?: number } & { a: number } type C = {[K in keyof T]: T[K] } // type C = { a: number } } { // evaluation case 4: all optional type T = { a?: number } & { a?: number } type C = {[K in keyof T]: T[K] } // type C = { a?: number | undefined } } ``` Note: the Type.Composite is intended to be a temporary type which can be replaced with a more general `Type.Mapped` in future revisions of TypeBox. As the infrastructure to support mapped types does not exist, users can use Type.Composite to partially replicate mapped type evaluation for composited object types only. sinclairzx81-typebox-e0ec98c/changelog/0.27.0.md000066400000000000000000000175731505437577000212720ustar00rootroot00000000000000## [0.27.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.27.0) ## Overview Revision 0.27.0 adds support for runtime [Template Literal Types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html). This revision does not include any functional breaking changes but does rename some public type aliases. As such this revision requires a minor semver increment. ## Contents - Enhancements - [Template Literal Types](#Template-Literal-Types) - [TemplateLiteralParser](#TemplateLiteralParser) - [WorkBench](#WorkBench) - Breaking Changes - [TSelf renamed to TThis](#TSelf-renamed-to-TThis) ## Template Literal Types Revision 0.27.0 adds support for Template Literal types. These types operate as a form of computed `TUnion>`. TypeBox encodes template literals using a subset of [ECMA 262](https://json-schema.org/understanding-json-schema/reference/regular_expressions.html) regular erxpressions which are applied to `pattern` properties of type `string`. This encoding enables JSON Schema validators to assert using existing regular expression checks. ### TypeScript TypeScript defines Template Literals using back tick quoted strings which may include embedded union groups. ```typescript type T = `option${'A'|'B'}` // type T = 'optionA' | 'optionB' type R = Record // type R = { // optionA: string // optionB: string // } ``` ### TypeBox TypeBox defines Template Literals using the `TemplateLiteral` function. This function accepts a sequence of TLiteral, TString, TNumber, TInteger and TBigInt which describe a sequence concatenations. The embedded TUnion type defines an option group which can later be expanded into a set of `TLiteral`. This expansion enables Template Literal types to also be used as Record keys. ```typescript const T = Type.TemplateLiteral([ // const T = { Type.Literal('option'), // pattern: '^option(A|B)$', Type.Union([ // type: 'string' Type.Literal('A'), // } Type.Literal('B') ]) ]) const R = Type.Record(T, Type.String()) // const R = { // type: 'object', // required: ['optionA', 'optionB'], // properties: { // optionA: { // type: 'string' // }, // optionB: { // type: 'string' // } // } // } type T = Static // type T = 'optionA' | 'optionB' type R = Static // type R = { // optionA: string // optionB: string // } ``` ## TemplateLiteralParser Template Literal types are encoded as `string` patterns. Because these types also need to act as composable union types, Revision 0.27.0 includes an expression parser / generator system specifically for regular expressions. This system is used during composition to allow templates to compose with other types, but can also be used in isolation to generate string sequences for the supported expression grammar. This functionality may be provided as standard on the `Value.*` sub module in subsequent revisions. The following generates a 8-bit binary sequence for the given expression. ```typescript import { TemplateLiteralParser, TemplateLiteralGenerator, TemplateLiteralFinite } from '@sinclair/typebox' const Bit = `(0|1)` // bit union const Byte = `${Bit}${Bit}${Bit}${Bit}${Bit}${Bit}${Bit}${Bit}` // byte sequence const E = TemplateLiteralParser.Parse(Byte) // parsed expression tree const F = TemplateLiteralFinite.Check(E) // is the expression finite? const S = [...TemplateLiteralGenerator.Generate(E)] // generate sequence // const S = [ // computed sequence // '00000000', '00000001', '00000010', '00000011', '00000100', // '00000101', '00000110', '00000111', '00001000', '00001001', // '00001010', '00001011', '00001100', '00001101', '00001110', // '00001111', '00010000', '00010001', '00010010', '00010011', // '00010100', '00010101', '00010110', '00010111', '00011000', // '00011001', '00011010', '00011011', '00011100', '00011101', // '00011110', '00011111', '00100000', '00100001', '00100010', // '00100011', '00100100', '00100101', '00100110', '00100111', // '00101000', '00101001', '00101010', '00101011', '00101100', // '00101101', '00101110', '00101111', '00110000', '00110001', // '00110010', '00110011', '00110100', '00110101', '00110110', // '00110111', '00111000', '00111001', '00111010', '00111011', // '00111100', '00111101', '00111110', '00111111', '01000000', // '01000001', '01000010', '01000011', '01000100', '01000101', // '01000110', '01000111', '01001000', '01001001', '01001010', // '01001011', '01001100', '01001101', '01001110', '01001111', // '01010000', '01010001', '01010010', '01010011', '01010100', // '01010101', '01010110', '01010111', '01011000', '01011001', // '01011010', '01011011', '01011100', '01011101', '01011110', // '01011111', '01100000', '01100001', '01100010', '01100011', // ... 156 more items // ] ``` ## Workbench To assist with TypeScript alignment and to prototype new features. A new web based compiler tool has been written that allows interactive cross compiling between TypeScript and TypeBox. This tool will be enhanced seperately from the TypeBox project, but can be used to quickly generate TypeBox type definitions from existing TypeScript types. [TypeBox Workbench Application](https://sinclairzx81.github.io/typebox-workbench) [TypeBox Workbench Project](https://github.com/sinclairzx81/typebox-workbench) ## Breaking Changes The following are breaking changes in Revision 0.27.0 ## TSelf renamed to TThis This rename is to align with TypeScript interfaces. Unlike `type` aliases, TypeScript `interface` types include a implicit `this` type. This change relates specifically to TypeBox's current Recursive type which passes the `TThis` parameter via callback. The `TThis` parameter can be seen as analogous to the implicit TypeScript interface `this`. Consider the following. ```typescript // type T = { id: string, nodes: this[] } // error: no implicit this interface Node { // ok: this is implicit for interfaces id: string, nodes: this[] } const T = Type.Recursive(This => // `This` === implicit 'this' for interface Type.Object({ // id: Type.String(), // Should `Recursive` be renamed to `Interface`? nodes: Type.Array(This) }) ) ``` Future revisions may rename `Recurisve` to `Interface`, but for now, just the `TSelf` has been renamed.sinclairzx81-typebox-e0ec98c/changelog/0.27.1.md000066400000000000000000000010701505437577000212540ustar00rootroot00000000000000## [0.27.1](https://www.npmjs.com/package/@sinclair/typebox/v/0.27.1) ## Updates - Adds a `Value.Mutate(left, right)` function. This function performs a deep mutable assignment on a value by internally remapping the `right` values on the `left`. Values omitted on the right will also be deleted on the left. This function can be useful scenarios where mutation of data is required without replacing existing reference values. An example of which might be React which tracks reference values to indicate redraw. This function is implemented by way of `ValuePointer`. sinclairzx81-typebox-e0ec98c/changelog/0.28.0.md000066400000000000000000000225701505437577000212640ustar00rootroot00000000000000## [0.28.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.28.0) ## Overview Revision 0.28.0 adds support for Indexed Access Types. This update also includes moderate breaking changes to Record and Composite types and does require a minor semver revision tick. ## Contents - Enhancements - [Indexed Access Types](#Indexed-Access-Types) - [KeyOf Tuple and Array](#KeyOf-Tuple-and-Array) - Breaking Changes - [Record Types Allow Additional Properties By Default](#Record-Types-Allow-Additional-Properties-By-Default) - [Composite Returns Intersect for Overlapping Properties](#Composite-Returns-Intersect-for-Overlapping-Properties) ## Indexed Access Types Revision 0.28.0 adds [Indexed Access Type](https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html) support with a new `Type.Index()` mapping type. These types allow for deep property lookups without needing to prop dive through JSON Schema properties. This type is based on the TypeScript implementation of Indexed Access Types and allows for generalized selection of properties for complex types irrespective of if that type is a Object, Union, Intersection, Array or Tuple. ```typescript // ---------------------------------------------------------- // The following types A and B are structurally equivalent, // but have varying JSON Schema representations. // ---------------------------------------------------------- const A = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean(), }) const B = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.String() }), Type.Object({ z: Type.Boolean() }) ]) // ---------------------------------------------------------- // TypeBox 0.27.0 - Non Uniform // ---------------------------------------------------------- const A_X = A.properties.x // TNumber const A_Y = A.properties.y // TString const A_Z = A.properties.z // TBoolean const B_X = B.allOf[0].properties.x // TNumber const B_Y = B.allOf[1].properties.y // TString const B_Z = B.allOf[2].properties.z // TBoolean // ---------------------------------------------------------- // TypeBox 0.28.0 - Uniform via Type.Index // ---------------------------------------------------------- const A_X = Type.Index(A, ['x']) // TNumber const A_Y = Type.Index(A, ['y']) // TString const A_Z = Type.Index(A, ['z']) // TBoolean const B_X = Type.Index(B, ['x']) // TNumber const B_Y = Type.Index(B, ['y']) // TString const B_Z = Type.Index(B, ['z']) // TBoolean ``` Indexed Access Types support has also been extended to Tuple and Array types. ```typescript // ----------------------------------------------------------- // Array // ----------------------------------------------------------- type T = string[] type I = T[number] // type T = string const T = Type.Array(Type.String()) const I = Type.Index(T, Type.Number()) // const I = TString // ----------------------------------------------------------- // Tuple // ----------------------------------------------------------- type T = ['A', 'B', 'C'] type I = T[0 | 1] // type I = 'A' | 'B' const T = Type.Array(Type.String()) const I = Type.Index(T, Type.Union([ // const I = TUnion<[ Type.Literal(0), // TLiteral<'A'>, Type.Literal(1), // TLiteral<'B'> ])) // ]> ``` ## KeyOf Tuple and Array Revision 0.28.0 includes additional `Type.KeyOf` support for Array and Tuple types. Keys of Array will always return `TNumber`, whereas keys of Tuple will return a LiteralUnion for each index of that tuple. ```typescript // ----------------------------------------------------------- // KeyOf: Tuple // ----------------------------------------------------------- const T = Type.Tuple([Type.Number(), Type.Number(), Type.Number()]) const K = Type.KeyOf(T) // const K = TUnion<[ // TLiteral<'0'>, // TLiteral<'1'>, // TLiteral<'2'>, // ]> // ----------------------------------------------------------- // KeyOf: Array // ----------------------------------------------------------- const T = Type.Array(Type.String()) const K = Type.KeyOf(T) // const K = TNumber ``` It is possible to combine KeyOf with Index types to extract properties from array and object constructs. ```typescript // ----------------------------------------------------------- // KeyOf + Index: Object // ----------------------------------------------------------- const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const K = Type.Index(T, Type.KeyOf(T)) // const K = TUnion<[ // TNumber, // TString, // TBoolean, // ]> // ----------------------------------------------------------- // KeyOf + Index: Tuple // ----------------------------------------------------------- const T = Type.Tuple([Type.Number(), Type.String(), Type.Boolean()]) const K = Type.Index(T, Type.KeyOf(T)) // const K = TUnion<[ // TNumber, // TString, // TBoolean, // ]> ``` ## Breaking Changes The following are breaking changes in Revision 0.28.0 ## Record Types Allow Additional Properties By Default Revision 0.28.0 no longer applies an automatic `additionalProperties: false` constraint to types of `TRecord`. Previously this constraint was set to prevent records with numeric keys from allowing unevaluated additional properties with non-numeric keys. This constraint worked in revisions up to 0.26.0, but since the move to use `allOf` intersect schema representations, this meant that types of Record could no longer be composed with intersections. This is due to the JSON Schema rules around extending closed schemas. Information on these rules can be found at the link below. https://json-schema.org/understanding-json-schema/reference/object.html#extending-closed-schemas For the most part, the omission of this constraint shouldn't impact existing record types with string keys, however numeric keys may cause problems. Consider the following where the validation unexpectedly succeeds for the following numeric keyed record. ```typescript const T = Type.Record(Type.Number(), Type.String()) const R = Value.Check(T, { a: null }) // true - Because `a` is non-numeric and thus is treated as an // additional unevaluated property. ``` Moving forward, Records with numeric keys "should" be constrained explicitly with `additionalProperties: false` via options if that record does not require composition through intersection. This is largely inline with the existing constraints one might apply to types of Object. ```typescript const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false }) const R = Value.Check(T, { a: null }) // false - Because `a` is non-numeric additional property ``` ## Composite Returns Intersect for Overlapping Properties This is a minor breaking change with respect to the schema returned for Composite objects with overlapping varying property types. Previously TypeBox would evaluate `TNever` by performing an internal `extends` check against each overlapping property type. However problems emerged using this implementation for users who needed to use Composite with types of `TUnsafe`. This is due to unsafe types being incompatible with TypeBox's internal extends logic. The solution implemented in 0.28.0 is to return the full intersection of all overlapping properties. The reasoning here is that if the overlapping properties of varying types result in an illogical intersection, this is semantically the same as resolving `never` for that property. This approach avoids the need to internally check if all overlapping properties extend or narrow one another. ```typescript const T = Type.Composite([ Type.Object({ x: Type.Number() }), // overlapping property 'x' of varying type Type.Object({ x: Type.String() }) ]) // ----------------------------------------------------------- // Revision 0.27.0 // ----------------------------------------------------------- const R = Type.Object({ x: Type.Never() // Never evaluated through extends checks. }) // ----------------------------------------------------------- // Revision 0.28.0 // ----------------------------------------------------------- const R = Type.Object({ x: Type.Intersect([ // Illogical intersections are semantically the same as never Type.Number(), Type.String() ]) }) ``` This implementation should make it more clear what the internal mechanics are for object compositing. Future revisions of TypeBox may however provide a utility function to test illogical intersections for Never for known types. sinclairzx81-typebox-e0ec98c/changelog/0.28.3.md000066400000000000000000000023021505437577000212560ustar00rootroot00000000000000## [0.28.3](https://www.npmjs.com/package/@sinclair/typebox/v/0.28.3) ## Overview Revision 0.28.3 adds a new Rest type to support variadic type composition. ## Contents - Enhancements - [Variadic Types](#Variadic-Types) ## Variadic Types Revision 0.28.3 adds a new type named `Type.Rest`. This type is used to extract a tuple array of type of `[...TSchema]`. The return value of this type is not strictly JSON Schema, however the tuple array can be used as a parameter to other types that accept tuples as their arguments. ### Tuple Concatenation ```typescript // TypeScript type A = [1, 2] type B = [3, 4] type C = [...A, ...B] // TypeBox const A = Type.Tuple([Type.Literal(1), Type.Literal(2)]) const B = Type.Tuple([Type.Literal(3), Type.Literal(4)]) const C = Type.Tuple([...Type.Rest(A), ...Type.Rest(B)]) ``` ### Tuple To Parameter ```typescript // TypeScript type P = [number, number] type F1 = (param: [...P]) => void type F2 = (param: [...P, number]) => void // TypeBox const P = Type.Tuple([Type.Number(), Type.Number()]) const F1 = Type.Function(Type.Rest(P), Type.Void()) const F2 = Type.Function([...Type.Rest(P), Type.Number()], Type.Void()) ``` sinclairzx81-typebox-e0ec98c/changelog/0.29.0.md000066400000000000000000000104761505437577000212670ustar00rootroot00000000000000## [0.29.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.29.0) ## Overview Revision 0.29.0 makes a minor interface and schema representation change to the `Type.Not` type. This revision also includes a fix for indexed access types on TypeScript 5.1.6. As this revision constitutes a breaking representation change for `Type.Not`, a minor semver revision is required. ## Contents - Enhancements - [Type.Not Representation Change](#Representation-Change) - [Not Inversion](#Not-Inversion) - [Inference Limitations](#Inference-Limitations) ## Type.Not Representation Change The `Type.Not` was first introduced in Revision 0.26.0. This type accepted two arguments, the first is the `not` type, the second is the `allowed` type. In 0.26.0, TypeBox would treat the `allowed` type as the inferred type with the schema represented in the following form. ### 0.26.0 ```typescript // allow all numbers except the number 42 // const T = Type.Not(Type.Literal(42), Type.Number()) // ^ ^ // not type allowed type // represented as // const T = { allOf: [ { not: { const: 42 } }, { type: 'number' } ] } // inferred as // type T = Static // type T = number ``` In 0.26.0. the rationale for the second `allowed` argument was provide a correct static type to infer, where one could describe what the type wasn't on the first and what it was on the second (with inference of operating on the second argument). This approach was to echo possible suggestions for negated type syntax in TypeScript. ```typescript type T = number & not 42 // not actual typescript syntax! ``` ### 0.29.0 Revision 0.29.0 changes the `Type.Not` type to take a single `not` argument only. This type statically infers as `unknown` ```typescript // allow all types except the literal number 42 // const T = Type.Not(Type.Literal(42)) // ^ // not type // represented as // const T = { not: { const: 42 } } // inferred as // type T = Static // type T = unknown ``` ### Upgrading to 0.29.0 In revision 0.29.0, you can express the 0.26.0 Not type via `Type.Intersect` which explicitly creates the `allOf` representation. The type inference works in this case as intersected `number & unknown` yields the most narrowed type (which is `number`) ```typescript // allow all numbers except the number 42 // const T = Type.Intersect([ Type.Not(Type.Literal(42)), Type.Number() ]) // ^ ^ // not type allowed type // represented as // const T = { allOf: [ { not: { const: 42 } }, { type: 'number' } ] } // inferred as // type T = Static // type T = number ``` The 0.29.0 `Not` type properly represents the JSON Schema `not` keyword in its simplest form, as well as making better use of intersection type narrowing capabilities of TypeScript. ## Not Inversion The not type can be inverted through nesting. ```typescript // not not string // const T = Type.Not(Type.Not(Type.String())) // represented as // const T = { not: { not: { type: "string" } } } // inferred as // type T = Static // type T = string ``` ## Inference Limitations Not types are synonymous with the concept of [negated types](https://github.com/microsoft/TypeScript/issues/4196) which are not supported in the TypeScript language. Because of this, it is not currently possible to infer negated types in a way one would naturally expect for some cases. Consider the following. ```typescript const T = Type.Intersect([Type.String(), Type.Not(Type.String())]) type T = Static // type T = string & not string // actual: string // expect: never ``` As such, the use of Not types should be used with some consideration to current limitations, and reserved primarily for narrowing cases such as the following. ```typescript const T = Type.Intersect([Type.String(), Type.Not(Type.Literal('disallowed string'))]) type T = Static // type T = string & not 'disallowed string' // actual: string // expect: string ``` sinclairzx81-typebox-e0ec98c/changelog/0.29.2.md000066400000000000000000000070441505437577000212660ustar00rootroot00000000000000## [0.29.2](https://www.npmjs.com/package/@sinclair/typebox/v/0.29.2) ## Overview Revision 0.29.2 includes enhancements to `Type.Index` This revision contains no breaking changes ## Contents - Enhancements - [Modifier Index Resolver](#Modifier-Index-Resolver) - [Indexed Intersect](#Indexed-Intersect) - [Indexed Union](#Indexed-Union) - [Composite](#Composite) ## Modifier Index Resolver Revision 0.29.2 re-introduces optional property narrowing for Indexed Access Types. This functionality is specific when indexing overlapping properties with one or more optional modifiers. Revision 0.28.0 attempted to implement this narrowing, however was pulled due to instantiation issues raised on issue [419](https://github.com/sinclairzx81/typebox/issues/419) (specific to composite narrowing) Revision 0.29.2 attempts to re-introduce this functionality using a different resolution strategy. It uses Indexed Access Types as the construct in which to apply such narrowing and expands upon Union and Intersection type normalization for optional modifier unwrap and remapping. This approach unifies Composite inference with Index Access Types and makes provisions for a possible `Type.Mapped` feature in later releases. ## Indexed Intersect The following are the index resolver cases for intersect types. ### Case 1 ```typescript const T = Type.Intersect([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Optional(Type.Number()) }) ]) const I = Type.Index(T, ['x']) // type I = TOptional> ``` ### Case 2 ```typescript const T = Type.Intersect([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() }) ]) const I = Type.Index(T, ['x']) // type I = TUnion<[TNumber, TNumber]> ``` ### Case 3 ```typescript const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() }) ]) const I = Type.Index(T, ['x']) // type I = TUnion<[TNumber, TNumber]> ``` ## Indexed Union The following are the index resolver cases for union types. ### Case 1 ```typescript const T = Type.Union([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Optional(Type.Number()) }) ]) const I = Type.Index(T, ['x']) // type I = TOptional> ``` ### Case 2 ```typescript const T = Type.Union([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() }) ]) const I = Type.Index(T, ['x']) // type I = TOptional> ``` ### Case 3 ```typescript const T = Type.Union([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() }) ]) const I = Type.Index(T, ['x']) // type I = TUnion<[TNumber, TNumber]> ``` ## Composite The following are the resolver cases for indexed types when applied to composite intersection. ### Case 1 ```typescript const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Optional(Type.Number()) }) ]) // type T = TObject<{ // x: TOptional> // }> ``` ### Case 2 ```typescript const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() }) ]) // type T = TObject<{ // x: TUnion<[TNumber, TNumber]> // }> ``` ### Case 3 ```typescript const T = Type.Composite([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() }) ]) // type T = TObject<{ // x: TUnion<[TNumber, TNumber]> // }> ```sinclairzx81-typebox-e0ec98c/changelog/0.30.0.md000066400000000000000000000565751505437577000212710ustar00rootroot00000000000000## [0.30.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.30.0) ## Overview Revision 0.30.0 is a milestone revision for the TypeBox project. It is primarily focused on internal optimizations, refactoring work to reduce package and bundle sizes, enable increased modularity of internal sub modules (with some considerations given to future ESM publishing), renaming internal functions to address react native bundling issues and consolidating shared internal modules to reduce overall code overhead. This revision also implements several new features, including new validation constraints for Array, new types for iterators, new utility types, a TypeScript code generation option for the compiler, enhancements made to modifiers and better options for TypeScript to TypeBox code translation. This revision also includes new examples including a transform type for handling IO encode an decode as well as a reference implementation for JSON Type Definition specification. This revision includes breaking changes and some deprecations. It requires a minor semver revision. ## Contents - Enhancements - [TypeScript Code Generation](#TypeScript-Code-Generation) - [Optional and Readonly](#Optional-and-Readonly) - [Iterator and AsyncIterator](#Iterator-and-AsyncIterator) - [Order Independent References](#Order-Independent-References) - [Value Submodules](#Value-Submodules) - [Array Contains Constraint](#Array-Contains-Constraint) - [Additional Utility Types](#Additional-Utility-Types) - [Reduced Package Size](#Reduced-Package-Size) - [TypeBox Codegen](#TypeBox-Codegen) - Examples - [JSON Type Definition](#JSON-Type-Definition) - [Prototype Types](#Prototype-Types) - [Transform Types](#Transform-Types) - Breaking - [Extended Type Representation-Change](#Extended-Type-Representation-Change) - [Modifier Symbol Deprecated](#Modifier-Deprecated) - [RegEx Renamed To RegExp](#RegEx-Renamed-To-RegExp) - [ValueErrorType Custom Renamed To Kind](#ValueErrorType-Custom-Renamed-To-Kind) ## TypeScript Code Generation Revision 0.30.0 adds TypeScript code generation support to the TypeCompiler. By specifying the language option on the `.Code()` function, TypeBox will add type annotations to the compiled output. This functionality can be used to produce typed TS functions for projects that preference AOT compilation. ```typescript const Code = TypeCompiler.Code(Type.String(), { // return function check(value: any): boolean { language: 'typescript' // return ( }) // (typeof value === 'string') // ) // } ``` ## Optional and Readonly Revision 0.30.0 deprecates the `[Modifier]` symbol and introduces two new symbols, `[Readonly]` and `[Optional]`. This change is carried out to simplify type inference as well as to simplify runtime mapping logic. This change should not implicate users leveraging the `Type.*` purely for type composition, however implementors using TypeBox for reflection and code generation should update to the new symbols. ```typescript // Revision 0.29.0 // const A = Type.ReadonlyOptional(Type.Number()) // const A: TReadonlyOptional = { // type: 'number', // [TypeBox.Modifier]: 'ReadonlyOptional' // } const B = Type.Readonly(Type.Number()) // const B: TReadonly = { // type: 'number', // [TypeBox.Modifier]: 'Readonly' // } const C = Type.Optional(Type.Number()) // const C: TOptional = { // type: 'number', // [TypeBox.Modifier]: 'Optional' // } // Revision 0.30.0 // const A = Type.ReadonlyOptional(Type.Number()) // const A: TReadonly> = { // type: 'number', // [TypeBox.Readonly]: 'Readonly', // [TypeBox.Optional]: 'Optional' // } const B = Type.Readonly(Type.Number()) // const B: TReadonly = { // type: 'number', // [TypeBox.Readonly]: 'Readonly' // } const C = Type.Optional(Type.Number()) // const C: TOptional = { // type: 'number', // [TypeBox.Optional]: 'Optional' // } ``` ## Iterator and AsyncIterator Revision 0.30.0 adds the types `Iterator` and `AsyncIterator`. These types add to the existing non-validatable extended type set and can be used build callable generator functions. These types are written primarily to describe RPC network interfaces that return multiple values. Examples of which may include web socket streams or reading database result cursors over a network. ```typescript // Revision 0.30.0 // const Enumerable = (T: T) => Type.Function([ Type.Number({ description: 'Start index' }), Type.Number({ description: 'End index' }) ], Type.Iterator(T)) const EnumerableNumber = Enumerable(Type.Number()) const Range: Static = function * (start: number, end: number) { for(let i = start; i < end; i++) yield i } const R = [...Range(10, 20)] // const R = [10, 11, 12, ..., 19] ``` ## Order Independent References Revision 0.30.0 adds an overload for `Ref` to enable non order dependent type referencing. Prior to this revision, reference targets needed to be defined first before being referenced. Revision 0.30.0 lifts this restriction and allows referencing of "yet to be defined" targets through the use of `typeof` operator. This overload borrows on TypeScript's ability to derive type information irrespective of topological ordering. This overload is implemented for "TypeScript to TypeBox" code generation utilities where TypeScript types are not guaranteed ordered in a runtime sorted fashion. ```typescript // Revision 0.29.0 // const R = Type.Ref(T) // Error: T isn't defined yet const T = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() }, { $id: 'T' }) // Revision 0.30.0 // const R = Type.Ref('T') // Ok: infer from typeof T const T = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() }, { $id: 'T' }) ``` ## Value Submodules Revision 0.30.0 carries out a number of refactorings for the `Value.*` modules to enable each submodule to be imported individually. These refactorings are support better "pay to play" library characteristics, allowing users to import only the submodules they need. This update also makes provisions for ESM publishing by removing internal namespaces. The top level `Value.*` namespace will remain on all subsequent versions of TypeBox. ```typescript // Revision 0.29.0 // import { Value } from '@sinclair/typebox/value' // Value.* namespace const A = Value.Create(Type.String()) // Revision 0.30.0 // import { Create } from '@sinclair/typebox/value/create' // Only Create() const A = Create(Type.String()) ``` ## Array Contains Constraint Revision 0.30.0 implements validation support for the `contains` keyword as well as the draft 2019-09 `minContains` and `maxContains` constraints on `Array`. Documentation on these constraints can be found https://json-schema.org/understanding-json-schema/reference/array.html#contains ```typescript // Revision 0.30.0 // const T = Type.Array(Type.Number(), { contains: Type.Literal(1), minContains: 3, maxContains: 5 }) Value.Check(T, [1, 1, 1]) // true - between 3 and 5 instances of 1 Value.Check(T, [1, 1, 1, 1, 1]) // true - between 3 and 5 instances of 1 Value.Check(T, [0, 1, 1, 1, 1, 1]) // true - between 3 and 5 instances of 1 Value.Check(T, [1, 1]) // false - less than 3 instances of 1 Value.Check(T, [1, 1, 1, 1, 1, 1]) // false - more than 5 instances of 1 Value.Check(T, [0]) // false - no instances of 1 ``` ## Additional Utility Types Revision 0.30.0 adds the utility types `Awaited`, `Uppercase`, `Lowercase`, `Capitalize`, and `Uncapitalize` to the supported type set. ```typescript // Revision 0.30.0 const T1 = Type.Awaited(Type.Promise(Type.String())) // const T1: TString const T2 = Type.Uppercase(Type.Literal('hello')) // const T2: TLiteral<'HELLO'> const T3 = Type.Lowercase(Type.Literal('HELLO')) // const T3: TLiteral<'hello'> const T4 = Type.Capitalize(Type.Literal('hello')) // const T4: TLiteral<'Hello'> const T5 = Type.Uncapitalize(Type.Literal('HELLO')) // const T5: TLiteral<'hELLO'> ``` A full list of TypeScript utility types can be found at this [link](https://www.typescriptlang.org/docs/handbook/utility-types.html). ## Reduced Package Size Revision 0.30.0 carries out several internal refactorings to reduce package and bundle sizes. This work is largely an ongoing process with provisional work carried out across `type`, `value` and `compiler` modules. Revision 0.30.0 manages to weigh in slightly less than Revision 0.29.0 with the additional functionality provided on the revision. ```typescript // Revision 0.29.0 // ┌──────────────────────┬────────────┬────────────┬─────────────┐ │ (index) │ Compiled │ Minified │ Compression │ ├──────────────────────┼────────────┼────────────┼─────────────┤ │ typebox/compiler │ '130.3 kb' │ ' 58.2 kb' │ '2.24 x' │ │ typebox/errors │ '113.3 kb' │ ' 49.8 kb' │ '2.27 x' │ │ typebox/system │ ' 78.8 kb' │ ' 32.2 kb' │ '2.45 x' │ │ typebox/value │ '180.0 kb' │ ' 77.7 kb' │ '2.32 x' │ │ typebox │ ' 77.7 kb' │ ' 31.7 kb' │ '2.45 x' │ └──────────────────────┴────────────┴────────────┴─────────────┘ // Revision 0.30.0 // ┌──────────────────────┬────────────┬────────────┬─────────────┐ │ (index) │ Compiled │ Minified │ Compression │ ├──────────────────────┼────────────┼────────────┼─────────────┤ │ typebox/compiler │ '129.4 kb' │ ' 58.6 kb' │ '2.21 x' │ │ typebox/errors │ '111.6 kb' │ ' 50.1 kb' │ '2.23 x' │ │ typebox/system │ ' 76.5 kb' │ ' 31.7 kb' │ '2.41 x' │ │ typebox/value │ '180.7 kb' │ ' 79.3 kb' │ '2.28 x' │ │ typebox │ ' 75.4 kb' │ ' 31.3 kb' │ '2.41 x' │ └──────────────────────┴────────────┴────────────┴─────────────┘ ``` ## TypeBox Codegen Revision 0.30.0 offers an external code generation API tool which can be used to programmatically convert TypeScript types into TypeBox types. [TypeBox-Code Project](https://github.com/sinclairzx81/typebox-codegen) ```typescript import * as Codegen from '@sinclair/typebox-codegen' const Code = Codegen.TypeScriptToTypeBox.Generate(` type T = { x: number, y: number, z: number } `) console.log(Code) // Output: // // import { Type, Static } from '@sinclair/typebox' // // type T = Static // const T = Type.Object({ // x: Type.Number(), // y: Type.Number(), // z: Type.Number() // }) ``` ## JSON Type Definition Revision 0.30.0 includes a reference implementation for JSON Type Definition (RFC 8927). This specification is currently under consideration for inclusion in the TypeBox library as an alternative schema representation for nominal type systems. The implementation currently contains all types expressed in the JSON Type Definition spec, but omits constraints such and `minimum` and `maximum` values (which are not formally represented in the specification). The implementation is offered as a single file which can be copied in to projects with TypeBox installed. This implementation may be enhanced over the next few revisions (with some potential to implement mapping types such as partial, required, omit, pick, keyof). This specification will be considered for inclusion under `@sinclair/typebox/typedef` if there is enough interest. ```typescript import { Type } from './typedef' // from: examples/typedef/typedef.ts const T3 = Type.Struct({ // const T3 = { x: Type.Float32(), // properties: { y: Type.Float32(), // x: { type: 'float32' }, z: Type.Float32() // y: { type: 'float32' }, }) // z: { type: 'float32' } // } // } const T2 = Type.Struct({ // const T3 = { x: Type.Float32(), // properties: { y: Type.Float32() // x: { type: 'float32' }, }) // y: { type: 'float32' } // } // } const U = Type.Union([ // const U = { T3, // discriminator: 'type', T2 // mapping: { ]) // 0: { // properties: { // x: { type: 'float32' }, // y: { type: 'float32' }, // z: { type: 'float32' } // } // }, // 1: { // properties: { // x: { type: 'float32' }, // y: { type: 'float32' } // } // } // } // } ``` ## Prototype Types Revision 0.30.0 renames `Experimental` types to `Prototype` types within the examples directory. Updates here include additional documentation and rationales for the existing types `UnionOneOf`, `UnionEnum`, `Const`, and includes two new types `Evaluate` and `PartialDeep`. These types are written as standalone modules and can be copied into a project for direct use. The TypeBox project is open to community discussions around the inclusion of these types in future revisions. ## Transform Types Revision 0.30.0 provides a reference implementation for Transform types. There has been some interest from users to offer combinators similar to Zod's `.transform()` function that permits remapping values during `.parse()` like operations. As TypeBox types do not have fluent combinators or a parse function (and are just JSON Schema objects), introducing similar functionality without augmenting types or implementing a `.parse()` on all types has proven to be particularily challenging. The reference Transform implementation implements a workable design by augmenting TypeBox types with codec functions outside the type system. These functions allow values to be structurally encoded and decoded through the `.parseLike()` functions `Encode()` and `Decode()`. TypeBox adopts the `io-ts` perspective for value transformation, viewing the act of transforming values primarily the role of dedicated codec system. As much of this functionality is considered high level and above and beyond the type system, Transform types will not likely be added to TypeBox type system; but rather added as an optional import in later revisions. ```typescript import { Transform, Encode, Decode } from './transform' const Timestamp = Transform(Type.Number(), { // The Transform function wraps a TypeBox type with two codec decode: (value) => new Date(value), // functions which implement logic to decode a received value encode: (value) => value.getTime(), // (i.e. number) into a application type (Date). The encode }) // function handles the reverse mapping. type N = Static // type N = { timestamp: number } // const N = Type.Object({ // Transform types are to be used like any other type and will timestamp: Timestamp // infer as the original TypeBox type. For example, the type `N` }) // above will infer as { timestamp: number } (as derived from // the TB type) const D = Decode(N, { timestamp: 123 }) // const D = { timestamp: Date(123) } // // The Decode function accepts any type plus a value. The Decode // function return type will be that of the transforms decode() // return type (which is Date), with the second argument statically // typed as N. This function acts as a kind of parse() that returns // the decoded type or throws on validation error. const E = Encode(N, { timestamp: new Date(123) }) // const E = { timestamp: 123 } // // The encode function performs the inverse, accepting the // decoded type { timestamp: Date } and re-encoding to the // target type { timestamp: number }. This function will // also throw on validation error. ``` ## Extended Type Representation Change Revision 0.30.0 updates representations for all extended types. This change is made due to TypeBox's observed role as a general purpose JavaScript validation library as well as to deprecate support for extended type validation in Ajv which was only ever partially functional at best. Attempts were made on Revision 0.25.0 to restructure extended types to provide Ajv hooks for custom type configuration. These hooks used the `type` property where `{ type: 'object', instanceOf: 'Type' }` was used to configure schematics for JavaScript objects, and `{ type: 'null', typeOf: 'Type' }` was used for JavaScript primitives. Despite these hooks, Ajv would still struggle with validation of primitive types (such as `undefined`), and for the types `Function`, `Constructor` and `Promise`; these were meaningless to Ajv and it did not make sense to try provide hooks for a validator that could not make use of them. This change represents a move towards a formal specification to express pure JavaScript constructs which is partially under discussion within the runtime type community. This change will implicate the use of `Uint8Array` and `Date` objects when configuring for Ajv. A supplimentary fallback will be provided in the `/examples` directory using `Type.Unsafe` ```typescript // Revision 0.29.0 // const T = Type.Date() // const T: TDate = { type: 'object', instanceOf: 'Date' } const U = Type.Undefined() // const U: TUndefined = { type: 'null', typeOf: 'Undefined' } // Revision 0.30.0 // const T = Type.Date() // const T: TDate = { type: 'Date' } const U = Type.Undefined() // const U: TUndefined = { type: 'undefined' } ``` ## RegEx Renamed To RegExp Revision 0.30.0 marks `Type.RegEx` as deprecated but provides `Type.RegExp` as an alternative (matching the JavaScript `RegExp` type name). Additionally this type has also been moved from the `Standard` to `Extended` type set. The `RegExp` type will no longer considered part of the Standard type set due to JavaScript Regular Expressions supporting a wider range of symbols and control characeters than is supported by the ECMA262 subset used by the JSON Schema specification. Information on the ECMA262 subset supported by JSON Schema can be found at the following Url https://json-schema.org/understanding-json-schema/reference/regular_expressions.html As `Type.RegEx()` is widely used, this function will be retained under the `@deprecated` annotation for the 0.30.0 revision. ```typescript // Revision 0.29.0 const T = Type.RegEx(/abc/) // Revision 0.30.0 const A = Type.RegEx(/abc/) // deprecation warning! const B = Type.RegExp(/abc/) // Extended Type const T = Type.String({ pattern: /abc/.source }) // Standard Type ``` For Unicode (UTF-16) support on 0.30.0, the recommendation is to continue using user defined formats. ```typescript import { Type, FormatRegistry } from '@sinclair/typebox' FormatRegistry.Set('emoji', value => /|\p{Extended_Pictographic}/gu.test(value)) const T = Type.String({ format: 'emoji' }) Value.Check(T, '♥️♦️♠️♣️') // Ok ``` For information on configuring custom formats on Ajv, refer to https://ajv.js.org/guide/formats.html#user-defined-formats sinclairzx81-typebox-e0ec98c/changelog/0.31.0.md000066400000000000000000000401211505437577000212460ustar00rootroot00000000000000## [0.31.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.31.0) ## Overview Revision 0.31.0 is a subsequent milestone revision for the TypeBox library and a direct continuation of the work carried out in 0.30.0 to optimize and prepare TypeBox for a 1.0 release candidate. This revision implements a new codec system with Transform types, provides configurable error message generation for i18n support, adds a library wide exception type named TypeBoxError and generalizes the Rest type to enable richer composition. This revision also finalizes optimization work to reduce the TypeBox package size. This revision contains relatively minor breaking changes due to internal type renaming. A minor semver revision is required. ## Contents - Enhancements - [Transform Types](#Transform-Types) - [Encode and Decode](#Encode-and-Decode) - [StaticEncode and StaticDecode](#StaticEncode-and-StaticDecode) - [Rest Types](#Rest-Types) - [Record Key](#Record-Key) - [TypeBoxError](#TypeBoxError) - [TypeSystemErrorFunction](#TypeSystemErrorFunction) - [Reduce Package Size](#Reduce-Package-Size) - Breaking - [JsonTypeBuilder and JavaScriptTypeBuilder](#JsonTypeBuilder-and-JavaScriptTypeBuilder) - [TypeSystemPolicy](#TypeSystemPolicy) ## Transform Types Revision 0.31.0 includes a new codec system referred to as Transform types. A Transform type is used to augment a regular TypeBox type with Encode and Decode functions. These functions are invoked via the new Encode and Decode functions available on both Value and TypeCompiler modules. The following shows a Transform type which increments and decrements a number. ```typescript import { Value } from '@sinclair/typebox/value' const T = Type.Transform(Type.Number()) // const T = { .Decode(value => value + 1) // type: 'number', .Encode(value => value - 1) // [Symbol(TypeBox.Kind)]: 'Number', // [Symbol(TypeBox.Transform)]: { // Decode: [Function: Decode], // Encode: [Function: Encode] // } // } const A = Value.Decode(T, 0) // const A: number = 1 const B = Value.Encode(T, 1) // const B: number = 0 ``` ## Encode and Decode Revision 0.31.0 includes new functions to Decode and Encode values. These functions are written in service to Transform types, but can be used equally well without them. These functions return a typed value that matches the type being transformed. TypeBox will infer decode and encode differently, yielding the correct type as derived from the codec implementation. The following shows decoding and encoding between number to Date. Note these functions will throw if the value is invalid. ```typescript const T = Type.Transform(Type.Number()) .Decode(value => new Date(value)) // number to Date .Encode(value => value.getTime()) // Date to number // Ok // const A = Value.Decode(T, 42) // const A = new Date(42) const B = Value.Encode(T, new Date(42)) // const B = 42 // Error // const C = Value.Decode(T, true) // Error: Expected number const D = Value.Encode(T, 'not a date') // Error: getTime is not a function ``` The Decode function is extremely fast when decoding regular TypeBox types; and TypeBox will by pass codec execution if the type being decoded contains no interior Transforms (and will only use Check). When using Transforms however, these functions may incur a performance penelty due to codecs operating structurally on values using dynamic techniques (as would be the case for applications manually decoding values). As such the Decode design is built to be general and opt in, but not necessarily high performance. ## StaticEncode and StaticDecode Revision 0.31.0 includes new inference types `StaticEncode` and `StaticDecode`. These types can be used to infer the encoded and decoded states of a Transform as well as regular TypeBox types. These types can be used to replace `Static` for `Request` and `Response` inference pipelines. The following shows an example `Route` function that uses Transform inference via `StaticDecode`. ```typescript // Route // export type RouteCallback = (request: StaticDecode) => StaticDecode // replace Static with StaticDecode export function Route( path: TPath, requestType: TRequest, responseType: TResponse, callback: RouteCallback ) { // route handling here ... const input = null // receive input const request = Value.Decode(requestType, input) const response = callback(request) const output = Value.Encode(responseType, response) // send output } // Route: Without Transform // const Timestamp = Type.Number() Route('/exampleA', Timestamp, Timestamp, (value) => { return value // value observed as number }) // Route: With Transform // const Timestamp = Type.Transform(Type.Number()) .Decode(value => new Date(value)) .Encode(value => value.getTime()) Route('/exampleB', Timestamp, Timestamp, (value) => { return value // value observed as Date }) ``` ## Rest Types Revision 0.31.0 updates the Rest type to support variadic tuple extraction from Union, Intersection and Tuple types. Previously the Rest type was limited to Tuple types only, but has been extended to other types to allow uniform remapping without having to extract types from specific schema representations. The following remaps a Tuple into a Union. ```typescript const T = Type.Tuple([ // const T = { Type.String(), // type: 'array', Type.Number() // items: [ ]) // { type: 'string' }, // { type: 'number' } // ], // additionalItems: false, // minItems: 2, // maxItems: 2, // } const R = Type.Rest(T) // const R = [ // { type: 'string' }, // { type: 'number' } // ] const U = Type.Union(R) // const U = { // anyOf: [ // { type: 'string' }, // { type: 'number' } // ] // } ``` This type can be used to remap Intersect a Composite ```typescript const I = Type.Intersect([ // const I = { Type.Object({ x: Type.Number() }), // allOf: [{ Type.Object({ y: Type.Number() }) // type: 'object', ]) // required: ['x'], // properties: { // x: { type: 'number' } // } // }, { // type: 'object', // required: ['y'], // properties: { // y: { type: 'number' } // } // }] // } const C = Type.Composite(Type.Rest(I)) // const C = { // type: 'object', // required: ['x', 'y'], // properties: { // 'x': { type: 'number' }, // 'y': { type: 'number' } // } // } ``` ## Record Key Revision 0.31.0 updates the inference strategy for Record types and generalizes RecordKey to TSchema. This update aims to help Record types compose better when used with generic functions. The update also removes the overloaded Record factory methods, opting for a full conditional inference path. It also removes the `RecordKey` type which would type error when used with Record overloads. The return type of Record will be TNever if passing an invalid key. Valid Record key types include TNumber, TString, TInteger, TTemplateLiteral, TLiteralString, TLiteralNumber and TUnion. ```typescript // 0.30.0 // import { RecordKey, TSchema } from '@sinclair/typebox' function StrictRecord(K: K, T: T) { return Type.Record(K, T, { additionalProperties: false }) // Error: RecordKey unresolvable to overload } // 0.31.0 // import { TSchema } from '@sinclair/typebox' function StrictRecord(K: K, T: T) { return Type.Record(K, T, { additionalProperties: false }) // Ok: dynamically mapped } const A = StrictRecord(Type.String(), Type.Null()) // const A: TRecord const B = StrictRecord(Type.Literal('A'), Type.Null()) // const B: TObject<{ A: TNull }> const C = StrictRecord(Type.BigInt(), Type.Null()) // const C: TNever ``` ## TypeBoxError Revision 0.31.0 updates all errors thrown by TypeBox to extend the sub type `TypeBoxError`. This can be used to help narrow down the source of errors in `try/catch` blocks. ```typescript import { Type, TypeBoxError } from '@sinclair/typebox' import { Value } from '@sinclair/typebox/value' try { const A = Value.Decode(Type.Number(), 'hello') } catch(error) { if(error instanceof TypeBoxError) { // typebox threw this error } } ``` ## TypeSystemErrorFunction Revision 0.31.0 adds functionality to remap error messages with the TypeSystemErrorFunction. This function is invoked whenever a validation error is generated in TypeBox. The following is an example of a custom TypeSystemErrorFunction using some of the messages TypeBox generates by default. TypeBox also provides the DefaultErrorFunction which can be used for fallthrough cases. ```typescript import { TypeSystemErrorFunction, DefaultErrorFunction } from '@sinclair/typebox/system' // Example CustomErrorFunction export function CustomErrorFunction(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` ... default: return DefaultErrorFunction(schema, errorType) } } // Sets the CustomErrorFunction TypeSystemErrorFunction.Set(CustomErrorFunction) ``` It is possible to call `.Set()` on the TypeSystemErrorFunction module prior to each call to `.Errors()`. This can be useful for applications that require i18n support in their validation pipelines. ## Reduce Package Size Revision 0.31.0 completes a full sweep of code optimizations and modularization to reduce package bundle size. The following table shows the bundle sizes inclusive of the new 0.31.0 functionality against 0.30.0. ```typescript // Revision 0.30.0 // ┌──────────────────────┬────────────┬────────────┬─────────────┐ │ (index) │ Compiled │ Minified │ Compression │ ├──────────────────────┼────────────┼────────────┼─────────────┤ │ typebox/compiler │ '131.4 kb' │ ' 59.4 kb' │ '2.21 x' │ │ typebox/errors │ '113.6 kb' │ ' 50.9 kb' │ '2.23 x' │ │ typebox/system │ ' 78.5 kb' │ ' 32.5 kb' │ '2.42 x' │ │ typebox/value │ '182.8 kb' │ ' 80.0 kb' │ '2.28 x' │ │ typebox │ ' 77.4 kb' │ ' 32.0 kb' │ '2.42 x' │ └──────────────────────┴────────────┴────────────┴─────────────┘ // Revision 0.31.0 // ┌──────────────────────┬────────────┬────────────┬─────────────┐ │ (index) │ Compiled │ Minified │ Compression │ ├──────────────────────┼────────────┼────────────┼─────────────┤ │ typebox/compiler │ '149.5 kb' │ ' 66.1 kb' │ '2.26 x' │ │ typebox/errors │ '112.1 kb' │ ' 49.4 kb' │ '2.27 x' │ │ typebox/system │ ' 83.2 kb' │ ' 37.1 kb' │ '2.24 x' │ │ typebox/value │ '191.1 kb' │ ' 82.7 kb' │ '2.31 x' │ │ typebox │ ' 73.0 kb' │ ' 31.9 kb' │ '2.29 x' │ └──────────────────────┴────────────┴────────────┴─────────────┘ ``` Additional code reductions may not be possible without implicating code maintainability. The `typebox` module may however be broken down into sub modules in later revisions to further bolster modularity, but is retained as a single file on this revision for historical reasons (not necessarily technical ones). ## JsonTypeBuilder and JavaScriptTypeBuilder Revision 0.31.0 renames the `StandardTypeBuilder` and `ExtendedTypeBuilder` to `JsonTypeBuilder` and `JavaScriptTypeBuilder` respectively. Applications that extend TypeBox's TypeBuilders will need to update to these names. ```typescript // 0.30.0 // export class ApplicationTypeBuilder extends ExtendedTypeBuilder {} // 0.31.0 // export class ApplicationTypeBuilder extends JavaScriptTypeBuilder {} ``` These builders also update the jsdoc comment to `[Json]` and `[JavaScript]` inline with this new naming convention. ## TypeSystemPolicy Revision 0.31.0 moves the `TypeSystem.Policy` configurations into a new type named `TypeSystemPolicy`. This change was done to unify internal policy checks used by the Value and Error modules during bundle size optimization; as well as to keep policy configurations contextually separate from the Type and Format API on the TypeSystem module. ```typescript // Revision 0.30.0 // import { TypeSystem } from '@sinclair/typebox/system' TypeSystem.AllowNaN = true // Revision 0.31.0 // import { TypeSystemPolicy } from '@sinclair/typebox/system' TypeSystemPolicy.AllowNaN = true TypeSystemPolicy.IsNumberLike(NaN) // true ```sinclairzx81-typebox-e0ec98c/changelog/0.32.0.md000066400000000000000000000653631505437577000212660ustar00rootroot00000000000000### 0.32.0 --- ### Revision Updates - [Revision 0.32.35](https://github.com/sinclairzx81/typebox/pull/914) Support Any for Record keys, Revert error message on required property, Fix order dependency for Union Convert. - [Revision 0.32.34](https://github.com/sinclairzx81/typebox/pull/914) Fix template literal generation for template literals embedded within template literals. - [Revision 0.32.33](https://github.com/sinclairzx81/typebox/pull/905) Pin ESM compiler target to ES2020. - [Revision 0.32.32](https://github.com/sinclairzx81/typebox/pull/898) Fix for Enum properties when used with Mapped types. - [Revision 0.32.31](https://github.com/sinclairzx81/typebox/pull/881) Fix for Cast. Dereference Union variants before scoring. - [Revision 0.32.30](https://github.com/sinclairzx81/typebox/pull/868) Support null object prototypes for Encode/Decode. - [Revision 0.32.29](https://github.com/sinclairzx81/typebox/pull/862) Key derive optimization to improve Intersect Encode/Decode performance. - [Revision 0.32.28](https://github.com/sinclairzx81/typebox/pull/861) Fix for TransformEncode introduced with 0.32.24, 0.32.25 optimizations. - [Revision 0.32.27](https://github.com/sinclairzx81/typebox/pull/854) Support for esm.sh and general build tooling updates. - [Revision 0.32.26](https://github.com/sinclairzx81/typebox/pull/851) Optimization for number checks, use Number.isFinite(x) over typeof `number`. - [Revision 0.32.25](https://github.com/sinclairzx81/typebox/pull/849) Optimizations for type builder to improve schema creation performance for computed types. - [Revision 0.32.24](https://github.com/sinclairzx81/typebox/pull/848) Optimizations for Convert to avoid unnecessary object initialization and cloning. - [Revision 0.32.22](https://github.com/sinclairzx81/typebox/pull/840) Add Support for Optional and Readonly Function and Constructor Arguments. - [Revision 0.32.21](https://github.com/sinclairzx81/typebox/pull/836) Refactor Array Conversion logic. Discard TNever on TComposite. - [Revision 0.32.20](https://github.com/sinclairzx81/typebox/pull/810) Fix compiler regression (TS 5.3.3 -> 5.4.2) generating Diff declaration structures. - [Revision 0.32.19](https://github.com/sinclairzx81/typebox/pull/805) Revert Union Convert logic added on 0.32.16. - [Revision 0.32.18](https://github.com/sinclairzx81/typebox/pull/801) Add explicit return type on TypeSystem.Type. - [Revision 0.32.17](https://github.com/sinclairzx81/typebox/pull/799) Detect ambiguous inference for StaticDecode when inferring as any. - [Revision 0.32.16](https://github.com/sinclairzx81/typebox/pull/791) Enhance Composite, Mapped, Indexed and Transform types. Intersect and Union Convert updates, Include Path in Validation Error. - [Revision 0.32.15](https://github.com/sinclairzx81/typebox/pull/774) Additional internal guards for Type Arrays, Map and Set structures. - [Revision 0.32.14](https://github.com/sinclairzx81/typebox/pull/753) Use barrel exports for submodules. - [Revision 0.32.13](https://github.com/sinclairzx81/typebox/pull/744) Add minLength and maxLength constraint for RegExp - [Revision 0.32.12](https://github.com/sinclairzx81/typebox/pull/740) Fix option assignment on Record types. - [Revision 0.32.11](https://github.com/sinclairzx81/typebox/pull/738) Optimize Extract, Exclude. Overloads for Template Literal - [Revision 0.32.10](https://github.com/sinclairzx81/typebox/pull/734) Export additional type infrastructure for Partial and Required - [Revision 0.32.9](https://github.com/sinclairzx81/typebox/pull/731) Generalize Composite to accept schematics of type TSchema[] - [Revision 0.32.8](https://github.com/sinclairzx81/typebox/pull/728) Ensure schema `default` annotation is cloned on Create. - [Revision 0.32.7](https://github.com/sinclairzx81/typebox/pull/727) Ensure schema `default` annotation is cloned on Default. - [Revision 0.32.6](https://github.com/sinclairzx81/typebox/pull/724) Export additional type infrastructure for mapping types - [Revision 0.32.5](https://github.com/sinclairzx81/typebox/pull/718) Update licence year span for 2024 - [Revision 0.32.4](https://github.com/sinclairzx81/typebox/pull/708) Ensure ErrorFunctionParameter type is exported - [Revision 0.32.3](https://github.com/sinclairzx81/typebox/pull/703) Simplify Record Static Type - [Revision 0.32.1](https://github.com/sinclairzx81/typebox/pull/701) Specify default exports for Web Pack ## [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) ### 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 ``` ### 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 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. ## Types Revision 0.32.0 adds three new types to the type system and makes enhancements to Readonly and Optional modifiers. ### 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. ### 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, // TLiteral<2>, // TLiteral<3> // ]>> const C = Type.Const({ // const C: TObject<{ x: 1, // x: TReadonly>, y: 2, // y: TReadonly>, z: 3 // z: TReadonly>, } 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`. ### 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. ### 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 // type T = string Value.Check(T, 'abc') // ok Value.Check(T, 'ABC') // ok // Extended Syntax const E = Type.RegExp(/|\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 ``` ### 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. ## Values Revision 0.32.0 adds two new functions to the Value module. ### 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. ### 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. ## 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. ```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' │ └──────────────────────┴────────────┴────────────┴─────────────┘ ``` ## Errors Revision 0.32.0 makes some enhancements to errors. ### 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. ## Breaking The following list the breaking changes in Revision 0.32.0. ### 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' ``` ### 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({ ... }) ``` ### 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' ``` ### 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) } }) ``` ### 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 ```sinclairzx81-typebox-e0ec98c/changelog/0.33.0.md000066400000000000000000000112411505437577000212510ustar00rootroot00000000000000### 0.33.0 --- ### Revision Updates - [Revision 0.33.22](https://github.com/sinclairzx81/typebox/pull/1065) - Rename TypeScript parsing infrastructure from `/parse` to `/syntax`. Remove Parse API from top level import. - [Revision 0.33.21](https://github.com/sinclairzx81/typebox/pull/1064) - [1063](https://github.com/sinclairzx81/typebox/issues/1063) Hotfix to resolve variable shadowing on Object (Parser Runtime) - [Revision 0.33.20](https://github.com/sinclairzx81/typebox/pull/1062) - Add TypeScript Parsing Infrastructure. Add Parse API to top level import. - [Revision 0.33.19](https://github.com/sinclairzx81/typebox/pull/1061) - Preemptive fix for TypeScript 5.8.0-dev (Type Fix for Immutable Function) - [Revision 0.33.18](https://github.com/sinclairzx81/typebox/pull/1060) - [1052](https://github.com/sinclairzx81/typebox/pull/1052) Export the Encode | Decode functions directly. Refactoring on Value submodule. - [1057](https://github.com/sinclairzx81/typebox/pull/1057) Export Object with var declaration to prevent global shadowing. Related Babel [Issue](https://github.com/babel/babel/issues/16943). - [Revision 0.33.17](https://github.com/sinclairzx81/typebox/pull/1042) - [1041](https://github.com/sinclairzx81/typebox/issues/1041) Avoid Exponentiation operator on Value.Hash - [Revision 0.33.16](https://github.com/sinclairzx81/typebox/pull/1015) - [1015](https://github.com/sinclairzx81/typebox/issues/1015) Add sub error iterators to ValueError - [Revision 0.33.15](https://github.com/sinclairzx81/typebox/pull/1025) - [1024](https://github.com/sinclairzx81/typebox/issues/1024) Fix to correctly resolve default Dates - [Revision 0.33.14](https://github.com/sinclairzx81/typebox/pull/1019) - [1019](https://github.com/sinclairzx81/typebox/pull/1019) Converting Large Numbers to BigInt - [Revision 0.33.13](https://github.com/sinclairzx81/typebox/pull/1011) - [1010](https://github.com/sinclairzx81/typebox/pull/1011) Fixes Value.Parse fails with recursive types - [Revision 0.33.12](https://github.com/sinclairzx81/typebox/pull/999) - [998](https://github.com/sinclairzx81/typebox/issues/998) Avoid losing precision when converting to bigints - [Revision 0.33.11](https://github.com/sinclairzx81/typebox/pull/994) - [993](https://github.com/sinclairzx81/typebox/issues/993) Prevent mutation on union values during Convert - [Revision 0.33.10](https://github.com/sinclairzx81/typebox/pull/991) - [907](https://github.com/sinclairzx81/typebox/issues/907) Add package.json metadata to specify possible side effect modules - [Revision 0.33.9](https://github.com/sinclairzx81/typebox/pull/984) - [887](https://github.com/sinclairzx81/typebox/issues/887) Generate Nested Intersect Errors - [Revision 0.33.8](https://github.com/sinclairzx81/typebox/pull/983) - [982](https://github.com/sinclairzx81/typebox/issues/982) Prevent Intersect Transform Encode callback from being called twice - [974](https://github.com/sinclairzx81/typebox/issues/974) Make strict the Encode and Decode return type - [975](https://github.com/sinclairzx81/typebox/issues/975) Support default annotation being assigned Functions for lazy value initialization on Create - [980](https://github.com/sinclairzx81/typebox/issues/980) Enable Mapping types to override user defined options from source type - [976](https://github.com/sinclairzx81/typebox/issues/976) Support Constraint Copy for Pick, Omit (inline with Partial / Required) (Trialing Implementation) - Flag Strict For Deprecation - [Revision 0.33.7](https://github.com/sinclairzx81/typebox/pull/964) - Additional updates to improve Default for enumerable objects. - [Revision 0.33.6](https://github.com/sinclairzx81/typebox/pull/963) - Add object traversal path for Default. Ensure enumerable objects are traversed. - [Revision 0.33.5](https://github.com/sinclairzx81/typebox/pull/959) - Provide better support for transforming properties with optional modifiers. - [Revision 0.33.4](https://github.com/sinclairzx81/typebox/pull/953) - Add Assert and Parse value functions. Add defacto AssertError type. - [Revision 0.33.3](https://github.com/sinclairzx81/typebox/pull/950) - Optimize Value Diff algorithm. Update edit sequence to INSERT, UPDATE then DELETE. - [Revision 0.33.2](https://github.com/sinclairzx81/typebox/pull/947) - Ensure user defined schema options are retained on mapping types, Pick, Omit and Mapped. - [Revision 0.33.1](https://github.com/sinclairzx81/typebox/pull/945) - Apply mutability fix for Intrinsic and Not schematics (inline with Default) - [Revision 0.33.0](https://github.com/sinclairzx81/typebox/pull/941) - Add InstanceMode to enable Clone, Freeze and Default schema initialization options. Optimize for Default. sinclairzx81-typebox-e0ec98c/changelog/0.34.0.md000066400000000000000000000315551505437577000212640ustar00rootroot00000000000000### 0.34.0 --- ### Revision Updates - [Revision 0.34.41](https://github.com/sinclairzx81/typebox/pull/1310) - Disable Node10 Module Resolution | TS7 Deprecation Warning. - [Revision 0.34.40](https://github.com/sinclairzx81/typebox/pull/1293) - Use Uniform over Reciprocal weighting on Cast Union Select - [Revision 0.34.39](https://github.com/sinclairzx81/typebox/pull/1296) - Guard for Array in Object and Record conversion - [Revision 0.34.38](https://github.com/sinclairzx81/typebox/pull/1282) - Preserve exact type matches in Union conversion - [Revision 0.34.37](https://github.com/sinclairzx81/typebox/pull/1278) - Fix Support nested Union selection when scoring for Cast - [Revision 0.34.36](https://github.com/sinclairzx81/typebox/pull/1276) - Fix Record Intersect on Cast - [Revision 0.34.35](https://github.com/sinclairzx81/typebox/pull/1265) - Deep Assign on Intersect Cast - [Revision 0.34.34](https://github.com/sinclairzx81/typebox/pull/1263) - Support Inference of Ref inside Recursive inside Module - [Revision 0.34.33](https://github.com/sinclairzx81/typebox/pull/1220) - Hotfix: Correct Invalid Import Specifier - [Revision 0.34.32](https://github.com/sinclairzx81/typebox/pull/1218) - Accelerated | High Performance Syntax Parsing - [Revision 0.34.31](https://github.com/sinclairzx81/typebox/pull/1209) - Use Tail Call Optimized Inference for Records with Large Union Keys - [Revision 0.34.30](https://github.com/sinclairzx81/typebox/pull/1198) - Additional Syntax Parsing Optimizations - [Revision 0.34.29](https://github.com/sinclairzx81/typebox/pull/1197) - Syntax Parsing Optimizations - [Revision 0.34.28](https://github.com/sinclairzx81/typebox/pull/1187) - Add Cast to Configurable Parse Pipeline - [Revision 0.34.27](https://github.com/sinclairzx81/typebox/pull/1182) - [1178](https://github.com/sinclairzx81/typebox/issues/1178) Support Deep Referential Transform Inference Inside Modules - [Revision 0.34.26](https://github.com/sinclairzx81/typebox/pull/1181) - Internal: Use Parser Context Threading for Generic Arguments. - [Revision 0.34.25](https://github.com/sinclairzx81/typebox/pull/1176) - Evaluate Conditional Expression for Instatiated Object Types - [Revision 0.34.24](https://github.com/sinclairzx81/typebox/pull/1175) - Add Support For Generic Parameter Syntax - [Revision 0.34.23](https://github.com/sinclairzx81/typebox/pull/1174) - Inline Instantiate Type Logic Local to Instantiate Module - [Revision 0.34.22](https://github.com/sinclairzx81/typebox/pull/1171) - Intrinsic Types Number, String, Boolean, etc Passthrough on Required and Partial Mapping - [Revision 0.34.21](https://github.com/sinclairzx81/typebox/pull/1168) - Reimplement Computed Record Types - [Revision 0.34.20](https://github.com/sinclairzx81/typebox/pull/1167) - Hotfix: Disable Computed Record Types - [Revision 0.34.19](https://github.com/sinclairzx81/typebox/pull/1166) - Hotfix: Republished due to NPM error - [Revision 0.34.18](https://github.com/sinclairzx81/typebox/pull/1164) - Hotfix: Internal Remap Imports - [Revision 0.34.17](https://github.com/sinclairzx81/typebox/pull/1162) - Add Argument() and Instantiate() Types and Instancing via Syntax support. - [Revision 0.34.16](https://github.com/sinclairzx81/typebox/pull/1156) - Export TypeBox String Parsing Infrastructure - [Revision 0.34.15](https://github.com/sinclairzx81/typebox/pull/1148) - [1147](https://github.com/sinclairzx81/typebox/issues/1147) Fix incorrect truncation for integers that exceed 32-bit values in Value.Convert - [Revision 0.34.14](https://github.com/sinclairzx81/typebox/pull/1140) - [1139](https://github.com/sinclairzx81/typebox/issues/1139) Update TypeCompiler Check for Promise (use instanceof Promise over Thenable check) - [Revision 0.34.13](https://github.com/sinclairzx81/typebox/pull/1124) - Pre emptive fix for TypeScript 5.8.0-nightly to resolve symbol narrowing on Convert. - [Revision 0.34.12](https://github.com/sinclairzx81/typebox/pull/1120) - [1119](https://github.com/sinclairzx81/typebox/issues/1119) Fix for Mutate Object Comparison - [1117](https://github.com/sinclairzx81/typebox/issues/1117) Re-Add Type.Recursive Documentation - [Revision 0.34.11](https://github.com/sinclairzx81/typebox/pull/1110) - Fix Compiler Emit for Deeply Referential Module Types - [Revision 0.34.10](https://github.com/sinclairzx81/typebox/pull/1107) - Fix Declaration Emit for Index and Mapped Types - Fix Record Inference Presentation when Embedded in Modules - Fix Record Mapping when using TImport as Key - Add Encode to Parse Operation List - [Revision 0.34.9](https://github.com/sinclairzx81/typebox/pull/1101) - User Defined Parse Pipelines - Access to Schema and References on TypeCheck - [Revision 0.34.8](https://github.com/sinclairzx81/typebox/pull/1098) - Fix for Computed Readonly and Optional Properties - [Revision 0.34.7](https://github.com/sinclairzx81/typebox/pull/1093) - Revert Ref(Schema) Signature with Deprecation Notice - [Revision 0.34.6](https://github.com/sinclairzx81/typebox/pull/1090) - Add Computed To Type and Kind Guards (IsSchema) - [Revision 0.34.5](https://github.com/sinclairzx81/typebox/pull/1088) - Record Types no longer TCompute for TRef Value Type (Modules) - [Revision 0.34.4](https://github.com/sinclairzx81/typebox/pull/1085) - Inference Path for Enum within Modules - [Revision 0.34.3](https://github.com/sinclairzx81/typebox/pull/1083) - Retain Array Elements on Value Default - [Revision 0.34.2](https://github.com/sinclairzx81/typebox/pull/1082) - Resolve import pathing issue introduced on 0.34.1 - [Revision 0.34.1](https://github.com/sinclairzx81/typebox/pull/1080) - Implement Computed Type Deref in Modules ## [0.34.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.34.0) ## Overview Revision 0.34.0 represents a significant milestone for the TypeBox project. This update changes how TypeBox manages type references (Ref) and introduces a new Module type to support mutual recursion and self-referencing types. Additionally, it includes a new submodule for parsing TypeScript syntax directly into TypeBox types. Please note that this release includes breaking changes to Ref and some deprecations. These updates require a minor semver revision. ## Contents - [Enhancements](#Enhancements) - [Module Types](#Module-Types) - [Syntax Types](#Syntax-Types) - [Breaking Changes](#Breaking-Changes) - [Ref](#Ref) - [Deref](#Deref) - [Strict](#Strict) ## Enhancements Below are the enhancements introduced in Version 0.34.0. ### Module Types Revision 0.34.0 introduces a new type, called Module. Modules are represented as JSON Schema $def schematics, specifically designed to support both mutual and self-recursive types. This addition resolves a longstanding issue in TypeBox, where complex recursive structures often encountered "definition order" problems, making certain recursive structures difficult to represent cleanly. With Modules, you can now define schematics within a Module context, allowing them to be referenced within the type system through a separate inference operation. ```typescript // The following creates a circular recursive type. const Module = Type.Module({ A: Type.Object({ b: Type.Ref('B') // Ref B: }), B: Type.Object({ c: Type.Ref('C') // Ref C: }), C: Type.Object({ a: Type.Ref('A') // Ref A: }), }) // Module types must be imported before use. const A = Module.Import('A') // const A: TImport<{...}, 'A'> type A = Static // type A = { // b: { // c: { // a: { // b: ... // } // } // } // } ``` ### Syntax Types Revision 0.34.0 introduces a new submodule for parsing TypeScript syntax directly into TypeBox types, implemented both at runtime and within the type system. This feature was made possible through the development of a separate project, [ParseBox](https://github.com/sinclairzx81/parsebox) (MIT-licensed), which provides a symmetric runtime and type-level parsing infrastructure. As of 0.34.0, Syntax Types are available as an opt-in feature, with the parsing infrastructure adding approximately 10kb (minified) to the existing type builder. With further optimizations, this feature may be elevated to a top-level import in future updates to minimize bundling size. To use Syntax Types, import them from the `@sinclair/typebox/syntax` path. ```typescript import { Parse } from '@sinclair/typebox/syntax' // All primitive types are supported const A = Parse('string') // const A: TString const B = Parse('number') // const B: TNumber const C = Parse('boolean') // const C: TBoolean // ... Multiline parsing is supported (but comments are not) const T = Parse(`{ x: number y: number z: number }`) // ... Parametertized parsing is supported const O = Parse({ T }, `T & { w: number }`) // const O: TIntersect<[ // TObject<{ // x: TNumber, // y: TNumber, // z: TNumber, // }>, // TObject<{ // w: TNumber // }> // ]> // ... Module parsing is also supported. const Math = Parse(`module Math { export interface X { x: number } export interface Y { y: number } export interface Z { z: number } export interface Vector extends X, Y, Z { type: 'Vector' } }`) const Vector = Math.Import('Vector') ``` Runtime parsing performance should be quite good; however, static parsing performance could be improved. TypeScript will invoke the parser for each property accessed at design time. Ongoing efforts within the ParseBox project aim to optimize string parsing in TypeScript, with additional research underway into type-level caching strategies within the TypeScript compiler. Additional optimizations will be explored over the course of 0.34.x. ## Breaking Changes The following are the breaking changes in Revision 0.34.0. ### Ref Revision 0.34.0 introduces a breaking change to Ref, modifying its signature to accept only constant string values. Previously, Ref could accept an existing TypeBox type, provided it had an $id assigned. ```typescript // Revision 0.33.0 const T = Type.String({ $id: 'T' }) const R = Type.Ref(T) type R = Static // type R = string // Revision 0.34.0 const T = Type.String({ $id: 'T' }) const R = Type.Ref('T') type R = Static // type R = unknown ``` In Revision 0.34.0, the inferred type for Ref is now unknown. Implementations using the previous version of Ref can switch to Unsafe to type the reference to the target value. ```typescript // Revision 0.34.0 const T = Type.String({ $id: 'T' }) const R = Type.Unsafe>(Type.Ref('T')) type R = Static // type R = string ``` ### Deref Revision 0.34.0 removes the Deref type, which was previously used to dereference schematics. Since the Ref signature has changed from TSchema to string, there is no longer a way to resolve reference types accurately. TypeBox may provide a prototype example of this type upon request. ### Strict Revision 0.34.0 removes the Strict type from the Type Builder, which was deprecated in version 0.33.8. This type was introduced several years ago in response to a change in Ajv that prohibited unknown keywords. At that time, TypeBox used string property keys for `kind` and `modifier`, which required either Ajv configuration or the use of Strict. These properties have since been updated to Symbol properties, resolving the issues with Ajv. However, the Strict type remained due to some use in ecosystem projects, which has since reduced. For those who still need Strict, the recommended approach is to use the JSON stringify/parse method outlined in the deprecation notice. ```typescript /** * @deprecated `[Json]` Omits compositing symbols from this schema. It is recommended * to use the JSON parse/stringify to remove compositing symbols if needed. This * is how Strict works internally. * * ```typescript * JSON.parse(JSON.stringify(Type.String())) * ``` */ export function Strict(schema: T): TStrict { return JSON.parse(JSON.stringify(schema)) } ```sinclairzx81-typebox-e0ec98c/example/000077500000000000000000000000001505437577000177135ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/example/annotation/000077500000000000000000000000001505437577000220655ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/example/annotation/annotation.ts000066400000000000000000000166171505437577000246220ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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` : Types.PatternNumberExact in schema.patternProperties ? `Record` : Types.PatternStringExact in schema.patternProperties ? `Record` : `{}` ) } 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) } }sinclairzx81-typebox-e0ec98c/example/annotation/index.ts000066400000000000000000000000341505437577000235410ustar00rootroot00000000000000export * from './annotation'sinclairzx81-typebox-e0ec98c/example/collections/000077500000000000000000000000001505437577000222315ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/example/collections/array.ts000066400000000000000000000450141505437577000237230ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/collections The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeCheck, TypeCompiler, ValueError } from '@sinclair/typebox/compiler' import { TSchema, Static, TypeBoxError } from '@sinclair/typebox' import { Value } from '@sinclair/typebox/value' // ---------------------------------------------------------------- // TypeArrayError // ---------------------------------------------------------------- export class TypeArrayError extends TypeBoxError { constructor(message: string) { super(`${message}`) } } export class TypeArrayLengthError extends TypeBoxError { constructor() { super('arrayLength not a number') } } // ---------------------------------------------------------------- // TypeArray // ---------------------------------------------------------------- export class TypeArray implements Iterable> { readonly #typeCheck: TypeCheck readonly #values: Static[] constructor(schema: T, arrayLength: number = 0) { if (typeof arrayLength !== 'number') throw new TypeArrayLengthError() this.#typeCheck = TypeCompiler.Compile(schema) this.#values = new Array(arrayLength) for (let i = 0; i < arrayLength; i++) { this.#values[i] = Value.Create(schema) } } // --------------------------------------------------- // Indexer // --------------------------------------------------- /** Sets the value at the given index */ public set(index: number, item: Static): void { this.#assertIndexInBounds(index) this.#assertItem(index, item) this.#values[index] = item } // --------------------------------------------------- // Array // --------------------------------------------------- /** Iterator for values in this array */ public [Symbol.iterator](): IterableIterator> { return this.#values[Symbol.iterator]() as IterableIterator } /** Gets the value at the given index */ public at(index: number): Static { this.#assertIndexInBounds(index) return this.#values[index] as T } /** * Gets the length of the array. This is a number one higher than the highest index in the array. */ public get length(): number { return this.#values.length } /** * Returns a string representation of an array. */ public toString(): string { return this.#values.toString() } /** * Returns a string representation of an array. The elements are converted to string using their toLocaleString methods. */ public toLocaleString(): string { return this.#values.toLocaleString() } /** * Removes the last element from an array and returns it. * If the array is empty, undefined is returned and the array is not modified. */ public pop(): Static | undefined { return this.#values.pop() } /** * Appends new elements to the end of an array, and returns the new length of the array. * @param items New elements to add to the array. */ public push(...items: Static[]): number { this.#assertItems(items) return this.#values.push(...items) } /** * Combines two or more arrays. * This method returns a new array without modifying any existing arrays. * @param items Additional arrays and/or items to add to the end of the array. */ public concat(...items: ConcatArray>[]): Static[] /** * Combines two or more arrays. * This method returns a new array without modifying any existing arrays. * @param items Additional arrays and/or items to add to the end of the array. */ public concat(...items: (T | ConcatArray>)[]): Static[] { this.#assertItems(items) return this.#values.concat(...items) as Static[] } /** * Adds all the elements of an array into a string, separated by the specified separator string. * @param separator A string used to separate one element of the array from the next in the resulting string. If omitted, the array elements are separated with a comma. */ public join(separator?: string): string { return this.#values.join(separator) } /** * Reverses the elements in an array in place. * This method mutates the array and returns a reference to the same array. */ public reverse(): Static[] { return this.#values.reverse() as Static[] } /** * Removes the first element from an array and returns it. * If the array is empty, undefined is returned and the array is not modified. */ public shift(): Static | undefined { return this.#values.shift() as Static | undefined } /** * Returns a copy of a section of an array. * For both start and end, a negative index can be used to indicate an offset from the end of the array. * For example, -2 refers to the second to last element of the array. * @param start The beginning index of the specified portion of the array. * If start is undefined, then the slice begins at index 0. * @param end The end index of the specified portion of the array. This is exclusive of the element at the index 'end'. * If end is undefined, then the slice extends to the end of the array. */ public slice(start?: number, end?: number): Static[] { return this.#values.slice(start, end) as Static[] } /** * Sorts an array in place. * This method mutates the array and returns a reference to the same array. * @param compareFn Function used to determine the order of the elements. It is expected to return * a negative value if the first argument is less than the second argument, zero if they're equal, and a positive * value otherwise. If omitted, the elements are sorted in ascending, ASCII character order. * ```ts * [11,2,22,1].sort((a, b) => a - b) * ``` */ public sort(compareFn?: (a: Static, b: Static) => number): this { this.#values.sort(compareFn as any) return this } /** * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements. * @param start The zero-based location in the array from which to start removing elements. * @param deleteCount The number of elements to remove. * @returns An array containing the elements that were deleted. */ public splice(start: number, deleteCount?: number): Static[] /** * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements. * @param start The zero-based location in the array from which to start removing elements. * @param deleteCount The number of elements to remove. * @param items Elements to insert into the array in place of the deleted elements. * @returns An array containing the elements that were deleted. */ public splice(start: number, deleteCount: number, ...items: Static[]): Static[] { this.#assertItems(items) return this.#values.splice(start, deleteCount, items) as Static[] } /** * Inserts new elements at the start of an array, and returns the new length of the array. * @param items Elements to insert at the start of the array. */ public unshift(...items: Static[]): number { this.#assertItems(items) return this.#values.unshift(items) } /** * Returns the index of the first occurrence of a value in an array, or -1 if it is not present. * @param searchElement The value to locate in the array. * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0. */ public indexOf(searchElement: Static, fromIndex?: number): number { return this.#values.indexOf(searchElement, fromIndex) } /** * Returns the index of the last occurrence of a specified value in an array, or -1 if it is not present. * @param searchElement The value to locate in the array. * @param fromIndex The array index at which to begin searching backward. If fromIndex is omitted, the search starts at the last index in the array. */ public lastIndexOf(searchElement: Static, fromIndex?: number): number { return this.#values.lastIndexOf(searchElement, fromIndex) } /** * Determines whether all the members of an array satisfy the specified test. * @param predicate A function that accepts up to three arguments. The every method calls * the predicate function for each element in the array until the predicate returns a value * which is coercible to the Boolean value false, or until the end of the array. * @param thisArg An object to which the this keyword can refer in the predicate function. * If thisArg is omitted, undefined is used as the this value. */ public every(predicate: (value: Static, index: number, array: Static[]) => value is Static, thisArg?: any): this is Static[] /** * Determines whether all the members of an array satisfy the specified test. * @param predicate A function that accepts up to three arguments. The every method calls * the predicate function for each element in the array until the predicate returns a value * which is coercible to the Boolean value false, or until the end of the array. * @param thisArg An object to which the this keyword can refer in the predicate function. * If thisArg is omitted, undefined is used as the this value. */ public every(predicate: (value: Static, index: number, array: Static[]) => unknown, thisArg?: any): boolean { return this.#values.every(predicate as any, thisArg) } /** * Determines whether the specified callback function returns true for any element of an array. * @param predicate A function that accepts up to three arguments. The some method calls * the predicate function for each element in the array until the predicate returns a value * which is coercible to the Boolean value true, or until the end of the array. * @param thisArg An object to which the this keyword can refer in the predicate function. * If thisArg is omitted, undefined is used as the this value. */ public some(predicate: (value: Static, index: number, array: T[]) => unknown, thisArg?: any): boolean { return this.#values.some(predicate as any, thisArg) } /** * Performs the specified action for each element in an array. * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ public forEach(callbackfn: (value: Static, index: number, array: Static[]) => void, thisArg?: any): void { return this.#values.forEach(callbackfn as any, thisArg) } /** * Calls a defined callback function on each element of an array, and returns an array that contains the results. * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value. */ public map(callbackfn: (value: Static, index: number, array: Static[]) => U, thisArg?: any): U[] { return this.#values.map(callbackfn as any, thisArg) } /** * Returns the elements of an array that meet the condition specified in a callback function. * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value. */ public filter(predicate: (value: Static, index: number, array: Static[]) => value is Static, thisArg?: any): Static[] /** * Returns the elements of an array that meet the condition specified in a callback function. * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array. * @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value. */ public filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[] public filter(predicate: any, thisArg: any): any { return this.#values.filter(predicate as any, thisArg) } /** * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ public reduce(callbackfn: (previousValue: Static, currentValue: Static, currentIndex: number, array: T[]) => Static): Static public reduce(callbackfn: (previousValue: Static, currentValue: Static, currentIndex: number, array: T[]) => Static, initialValue: Static): Static /** * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ public reduce(callbackfn: (previousValue: U, currentValue: Static, currentIndex: number, array: Static[]) => U, initialValue: U): U public reduce(callbackfn: any, initialValue?: any): any { return this.#values.reduce(callbackfn, initialValue) } /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ public reduceRight(callbackfn: (previousValue: Static, currentValue: Static, currentIndex: number, array: Static[]) => Static): Static public reduceRight(callbackfn: (previousValue: Static, currentValue: Static, currentIndex: number, array: Static[]) => Static, initialValue: T): Static /** * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function. * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array. * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value. */ public reduceRight(callbackfn: (previousValue: U, currentValue: Static, currentIndex: number, array: Static[]) => U, initialValue: U): U public reduceRight(callbackfn: any, initialValue?: any): any { return this.#values.reduceRight(callbackfn, initialValue) } // --------------------------------------------------- // Assertions // --------------------------------------------------- #formatError(errors: ValueError[]) { return errors.map((error) => `${error.message} ${error.path}`).join('. ') } /** Asserts the given values */ #assertIndexInBounds(index: number) { if (index >= 0 && index < this.#values.length) return throw new TypeArrayError(`Index ${index} is outside the bounds of this Array.`) } /** Asserts the given values */ #assertItem(index: number, item: unknown): asserts item is Static { if (this.#typeCheck.Check(item)) return const message = this.#formatError([...this.#typeCheck.Errors(item)]) throw new TypeArrayError(`Item at Index ${index} is invalid. ${message}`) } /** Asserts the given values */ #assertItems(items: unknown[]): asserts items is Static[] { for (let i = 0; i < items.length; i++) { this.#assertItem(i, items[i]) } } /** Creates a typed array from an existing array */ public static from(schema: T, iterable: IterableIterator> | Array>): TypeArray { if (globalThis.Array.isArray(iterable)) { const array = new TypeArray(schema, iterable.length) for (let i = 0; i < iterable.length; i++) { array.set(i, iterable[i]) } return array } const array = new TypeArray(schema) for (const value of iterable) { array.push(value) } return array } } sinclairzx81-typebox-e0ec98c/example/collections/index.ts000066400000000000000000000025461505437577000237170ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/collections The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' export * from './map' export * from './set' sinclairzx81-typebox-e0ec98c/example/collections/map.ts000066400000000000000000000144231505437577000233620ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/collections The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeCheck, TypeCompiler, ValueError } from '@sinclair/typebox/compiler' import { TSchema, Static, TypeBoxError } from '@sinclair/typebox' import { Value } from '@sinclair/typebox/value' // ---------------------------------------------------------------- // TypeMapKeyError // ---------------------------------------------------------------- export class TypeMapKeyError extends TypeBoxError { constructor(message: string) { super(`${message} for key`) } } export class TypeMapValueError extends TypeBoxError { constructor(key: unknown, message: string) { super(`${message} for key ${JSON.stringify(key)}`) } } // ---------------------------------------------------------------- // TypeMap // ---------------------------------------------------------------- // prettier-ignore type TypeMapEntries = | Iterable<[Static, Static]> | Array<[Static, Static]> /** Runtime type checked Map collection */ export class TypeMap { readonly #keycheck: TypeCheck readonly #valuecheck: TypeCheck readonly #keys: Map> readonly #values: Map> /** Constructs a new HashMap of the given key and value types. */ constructor(key: K, value: V, entries: TypeMapEntries = []) { this.#keycheck = TypeCompiler.Compile(key) this.#valuecheck = TypeCompiler.Compile(value) this.#keys = new Map>() this.#values = new Map>() for (const [key, value] of entries) { this.set(key, value) } } /** Iterator for this TypeMap */ public *[Symbol.iterator](): IterableIterator<[Static, Static]> { for (const [key, value] of this.#values) { yield [this.#keys.get(key)!, value] } } /** Iterator for the keys in this TypeMap */ public *keys(): IterableIterator> { yield* this.#keys.values() } /** Iterator for the values in this TypeMap */ public *values(): IterableIterator> { yield* this.#values.values() } /** Clears all entries in this map */ public clear(): void { this.#values.clear() this.#keys.clear() } /** Executes a provided function once per each key/value pair in the Map, in insertion order. */ public forEach(callbackfn: (value: Static, key: Static, map: TypeMap) => void, thisArg?: any): void { this.#values.forEach((value, key) => callbackfn(value, this.#keys.get(key)!, this)) } /** @returns the number of elements in the TypeMap. */ public get size(): number { return this.#values.size } /** * @returns boolean indicating whether an element with the specified key exists or not. */ public has(key: Static): boolean { this.#assertKey(key) return this.#values.has(this.#encodeKey(key)) } /** * Returns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map. * @returns Returns the element associated with the specified key. If no element is associated with the specified key, undefined is returned. */ public get(key: Static): Static | undefined { this.#assertKey(key) return this.#values.get(this.#encodeKey(key))! } /** * Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated. */ public set(key: Static, value: Static) { this.#assertKey(key) this.#assertValue(key, value) const encodedKey = this.#encodeKey(key) this.#keys.set(encodedKey, key) this.#values.set(encodedKey, value) } /** * @returns true if an element in the Map existed and has been removed, or false if the element does not exist. */ public delete(key: Static): boolean { this.#assertKey(key) const encodedKey = this.#encodeKey(key) this.#keys.delete(encodedKey) return this.#values.delete(encodedKey) } // --------------------------------------------------- // Encoder // --------------------------------------------------- /** Encodes the key as a 64bit numeric */ #encodeKey(key: Static) { return Value.Hash(key) } // --------------------------------------------------- // Assertions // --------------------------------------------------- #formatError(errors: ValueError[]) { return errors .map((error) => `${error.message} ${error.path}`) .join('. ') .trim() } /** Asserts the key matches the key schema */ #assertKey(key: unknown): asserts key is Static { if (this.#keycheck.Check(key)) return throw new TypeMapKeyError(this.#formatError([...this.#keycheck.Errors(key)])) } /** Asserts the key matches the value schema */ #assertValue(key: Static, value: unknown): asserts value is Static { if (this.#valuecheck.Check(value)) return throw new TypeMapValueError(key, this.#formatError([...this.#valuecheck.Errors(value)])) } } sinclairzx81-typebox-e0ec98c/example/collections/readme.md000066400000000000000000000002351505437577000240100ustar00rootroot00000000000000# Collections This example implements runtime type safe generic `Array`, `Map` and `Set` collection types using TypeBox types as the generic type arguments.sinclairzx81-typebox-e0ec98c/example/collections/set.ts000066400000000000000000000102261505437577000233750ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/collections The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeCheck, TypeCompiler, ValueError } from '@sinclair/typebox/compiler' import { TSchema, Static, TypeBoxError } from '@sinclair/typebox' import { Value } from '@sinclair/typebox/value' // ---------------------------------------------------------------- // Errors // ---------------------------------------------------------------- export class TypeSetError extends TypeBoxError { constructor(message: string) { super(`${message}`) } } // ---------------------------------------------------------------- // TypeSet // ---------------------------------------------------------------- /** Runtime type checked Set collection */ export class TypeSet { readonly #valuecheck: TypeCheck readonly values: Map> constructor(schema: T, iterable: Array | Iterable = []) { this.#valuecheck = TypeCompiler.Compile(schema) this.values = new Map>() for (const value of iterable) { this.add(value) } } /** Adds a value to this set */ public add(value: Static): this { this.#assertValue(value) this.values.set(this.#encodeKey(value), value) return this } /** Clears the values in this set */ public clear(): void { this.values.clear() } /** * Removes a specified value from the Set. * @returns Returns true if an element in the Set existed and has been removed, or false if the element does not exist. */ public delete(value: Static): boolean { return this.values.delete(this.#encodeKey(value)) } /** Executes a provided function once per each value in the Set object, in insertion order. */ public forEach(callbackfn: (value: Static, value2: Static, set: TypeSet) => void, thisArg?: any): void { this.values.forEach((value, value2) => callbackfn(value, value2, this), thisArg) } /** * @returns a boolean indicating whether an element with the specified value exists in the Set or not. */ public has(value: Static): boolean { return this.values.has(this.#encodeKey(value)) } /** * @returns the number of (unique) elements in Set. */ public get size(): number { return this.values.size } // --------------------------------------------------- // Encoder // --------------------------------------------------- #encodeKey(value: Static) { return Value.Hash(value) } // --------------------------------------------------- // Assertions // --------------------------------------------------- /** Formats errors */ #formatError(errors: ValueError[]) { return errors .map((error) => `${error.message} ${error.path}`) .join('. ') .trim() } /** Asserts the key matches the value schema */ #assertValue(value: unknown): asserts value is Static { if (this.#valuecheck.Check(value)) return throw new TypeSetError(this.#formatError([...this.#valuecheck.Errors(value)])) } } sinclairzx81-typebox-e0ec98c/example/formats/000077500000000000000000000000001505437577000213665ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/example/formats/date-time.ts000066400000000000000000000031641505437577000236130ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) 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 { IsDate } from './date' import { IsTime } from './time' const DATE_TIME_SEPARATOR = /t|\s/i /** * `[ajv-formats]` ISO8601 DateTime * @example `2020-12-12T20:20:40+00:00` */ export function IsDateTime(value: string, strictTimeZone?: boolean): boolean { const dateTime: string[] = value.split(DATE_TIME_SEPARATOR) return dateTime.length === 2 && IsDate(dateTime[0]) && IsTime(dateTime[1], strictTimeZone) } sinclairzx81-typebox-e0ec98c/example/formats/date.ts000066400000000000000000000035211505437577000226540ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) 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. ---------------------------------------------------------------------------*/ const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] const DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ function IsLeapYear(year: number): boolean { return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) } /** * `[ajv-formats]` ISO8601 Date component * @example `2020-12-12` */ export function IsDate(value: string): boolean { const matches: string[] | null = DATE.exec(value) if (!matches) return false const year: number = +matches[1] const month: number = +matches[2] const day: number = +matches[3] return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && IsLeapYear(year) ? 29 : DAYS[month]) } sinclairzx81-typebox-e0ec98c/example/formats/email.ts000066400000000000000000000031241505437577000230250ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) 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. ---------------------------------------------------------------------------*/ const Email = /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i /** * `[ajv-formats]` Internet Email Address [RFC 5321, section 4.1.2.](http://tools.ietf.org/html/rfc5321#section-4.1.2) * @example `user@domain.com` */ export function IsEmail(value: string): boolean { return Email.test(value) } sinclairzx81-typebox-e0ec98c/example/formats/index.ts000066400000000000000000000027321505437577000230510ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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-time' export * from './date' export * from './email' export * from './ipv4' export * from './ipv6' export * from './time' export * from './url' export * from './uuid' sinclairzx81-typebox-e0ec98c/example/formats/ipv4.ts000066400000000000000000000030721505437577000226220ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) 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. ---------------------------------------------------------------------------*/ const IPv4 = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/ /** * `[ajv-formats]` IPv4 address according to dotted-quad ABNF syntax as defined in [RFC 2673, section 3.2](http://tools.ietf.org/html/rfc2673#section-3.2) * @example `192.168.0.1` */ export function IsIPv4(value: string): boolean { return IPv4.test(value) } sinclairzx81-typebox-e0ec98c/example/formats/ipv6.ts000066400000000000000000000047231505437577000226300ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) 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. ---------------------------------------------------------------------------*/ const IPv6 = /^((([0-9a-f]{1,4}:){7}([0-9a-f]{1,4}|:))|(([0-9a-f]{1,4}:){6}(:[0-9a-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){5}(((:[0-9a-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9a-f]{1,4}:){4}(((:[0-9a-f]{1,4}){1,3})|((:[0-9a-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){3}(((:[0-9a-f]{1,4}){1,4})|((:[0-9a-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){2}(((:[0-9a-f]{1,4}){1,5})|((:[0-9a-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9a-f]{1,4}:){1}(((:[0-9a-f]{1,4}){1,6})|((:[0-9a-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9a-f]{1,4}){1,7})|((:[0-9a-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))$/i /** * `[ajv-formats]` IPv6 address as defined in [RFC 2373, section 2.2](http://tools.ietf.org/html/rfc2373#section-2.2). * @example `2001:0db8:85a3:0000:0000:8a2e:0370:7334` */ export function IsIPv6(value: string): boolean { return IPv6.test(value) } sinclairzx81-typebox-e0ec98c/example/formats/time.ts000066400000000000000000000041211505437577000226720ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) 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. ---------------------------------------------------------------------------*/ const TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i /** * `[ajv-formats]` ISO8601 Time component * @example `20:20:39+00:00` */ export function IsTime(value: string, strictTimeZone?: boolean): boolean { const matches: string[] | null = TIME.exec(value) if (!matches) return false const hr: number = +matches[1] const min: number = +matches[2] const sec: number = +matches[3] const tz: string | undefined = matches[4] const tzSign: number = matches[5] === '-' ? -1 : 1 const tzH: number = +(matches[6] || 0) const tzM: number = +(matches[7] || 0) if (tzH > 23 || tzM > 59 || (strictTimeZone && !tz)) return false if (hr <= 23 && min <= 59 && sec < 60) return true const utcMin = min - tzM * tzSign const utcHr = hr - tzH * tzSign - (utcMin < 0 ? 1 : 0) return (utcHr === 23 || utcHr === -1) && (utcMin === 59 || utcMin === -1) && sec < 61 } sinclairzx81-typebox-e0ec98c/example/formats/url.ts000066400000000000000000000036331505437577000225450ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) 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. ---------------------------------------------------------------------------*/ const Url = /^(?:https?|wss?|ftp):\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)(?:\.(?:[a-z0-9\u{00a1}-\u{ffff}]+-)*[a-z0-9\u{00a1}-\u{ffff}]+)*(?:\.(?:[a-z\u{00a1}-\u{ffff}]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/iu /** * `[ajv-formats:deprecated]` A uniform resource locator as defined in [RFC 1738](https://www.rfc-editor.org/rfc/rfc1738) * @example `http://domain.com` */ export function IsUrl(value: string) { return Url.test(value) } sinclairzx81-typebox-e0ec98c/example/formats/uuid.ts000066400000000000000000000030371505437577000227070ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) 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. ---------------------------------------------------------------------------*/ const Uuid = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i /** * `[ajv-formats]` A Universally Unique Identifier as defined by [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122). * @example `9aa8a673-8590-4db2-9830-01755844f7c1` */ export function IsUuid(value: string): boolean { return Uuid.test(value) } sinclairzx81-typebox-e0ec98c/example/index.ts000066400000000000000000000025051505437577000213740ustar00rootroot00000000000000import { TypeSystem } from '@sinclair/typebox/system' import { TypeCompiler } from '@sinclair/typebox/compiler' import { Value, ValuePointer } from '@sinclair/typebox/value' import { Type, TypeGuard, Kind, Static, TSchema } from '@sinclair/typebox' import { Syntax } from '@sinclair/typebox/syntax' // ----------------------------------------------------------- // Create: Type // ----------------------------------------------------------- const T = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) type T = Static console.log(T) // ----------------------------------------------------------- // Syntax: Type // ----------------------------------------------------------- const S = Syntax({ T }, `{ x: T, y: T, z: T }`) type S = Static // ----------------------------------------------------------- // Create: Value // ----------------------------------------------------------- const V = Value.Create(T) console.log(V) // ----------------------------------------------------------- // Compile: Type // ----------------------------------------------------------- const C = TypeCompiler.Compile(T) console.log(C.Code()) // ----------------------------------------------------------- // Check: Value // ----------------------------------------------------------- console.log(C.Check(V)) sinclairzx81-typebox-e0ec98c/example/prototypes/000077500000000000000000000000001505437577000221435ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/example/prototypes/discriminated-union.ts000066400000000000000000000104531505437577000264630ustar00rootroot00000000000000 /*-------------------------------------------------------------------------- @sinclair/typebox/prototypes The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Static, Kind, TSchema, TObject, SchemaOptions, CreateType, TLiteral, TypeRegistry, ValueGuard, KindGuard, TUnion } from '@sinclair/typebox' import { GetErrorFunction, SetErrorFunction } from 'src/errors/function' import { Value } from '@sinclair/typebox/value' // ------------------------------------------------------------------ // DiscriminatedUnionError // ------------------------------------------------------------------ const errorFunction = GetErrorFunction() // prettier-ignore SetErrorFunction((parameter) => { if (parameter.schema[Kind] !== 'DiscriminatedUnion') { return errorFunction(parameter) } const union = parameter.schema as TDiscriminatedUnion // Try generate error when value matches known discriminator literal if (ValueGuard.IsObject(parameter.value) && union.discriminator in parameter.value) { const variant = parameter.schema.anyOf.find((variant: TSchema) => union.discriminator in variant.properties && (variant.properties[union.discriminator] as TLiteral).const === (parameter.value as Record)[union.discriminator]) if (KindGuard.IsSchema(variant)) { const literal = variant.properties[union.discriminator] return `Invalid value for DiscriminatedUnion variant '${literal.const}'` } } // Return generic error containing possible discriminator types. const options = union.anyOf.map(object => object.properties[union.discriminator].const) as string[] return `Expected value of ${options.map(option => `'${option}'`).join(', ')} for DiscriminatedUnion` }) // ------------------------------------------------------------------ // TDiscriminatedUnionObject // // Constructs a base TObject type requiring 1 discriminator property // ------------------------------------------------------------------ // prettier-ignore type TDiscriminatedUnionProperties = { [_ in Discriminator]: TLiteral } // prettier-ignore type TDiscriminatedUnionObject = TObject> // ------------------------------------------------------------------ // DiscriminatedUnion // ------------------------------------------------------------------ // prettier-ignore TypeRegistry.Set('DiscriminatedUnion', (schema: TDiscriminatedUnion, value) => { return schema.anyOf.some(variant => Value.Check(variant, [], value)) }) // prettier-ignore export interface TDiscriminatedUnion extends TSchema { [Kind]: 'DiscriminatedUnion' static: Static> discriminator: Discriminator anyOf: Types } /** Creates a DiscriminatedUnion. */ // prettier-ignore export function DiscriminatedUnion[]>( discriminator: Discriminator, types: [...Types], options?: SchemaOptions ): TDiscriminatedUnion { return CreateType({ [Kind]: 'DiscriminatedUnion', anyOf: types, discriminator }, options) as never } sinclairzx81-typebox-e0ec98c/example/prototypes/from-schema.ts000066400000000000000000000267271505437577000247320ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/prototypes The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 Type from '@sinclair/typebox' // ------------------------------------------------------------------ // Schematics // ------------------------------------------------------------------ const IsExact = (value: unknown, expect: unknown) => value === expect const IsSValue = (value: unknown): value is SValue => Type.ValueGuard.IsString(value) || Type.ValueGuard.IsNumber(value) || Type.ValueGuard.IsBoolean(value) const IsSEnum = (value: unknown): value is SEnum => Type.ValueGuard.IsObject(value) && Type.ValueGuard.IsArray(value.enum) && value.enum.every((value) => IsSValue(value)) const IsSAllOf = (value: unknown): value is SAllOf => Type.ValueGuard.IsObject(value) && Type.ValueGuard.IsArray(value.allOf) const IsSAnyOf = (value: unknown): value is SAnyOf => Type.ValueGuard.IsObject(value) && Type.ValueGuard.IsArray(value.anyOf) const IsSOneOf = (value: unknown): value is SOneOf => Type.ValueGuard.IsObject(value) && Type.ValueGuard.IsArray(value.oneOf) const IsSTuple = (value: unknown): value is STuple => Type.ValueGuard.IsObject(value) && IsExact(value.type, 'array') && Type.ValueGuard.IsArray(value.items) const IsSArray = (value: unknown): value is SArray => Type.ValueGuard.IsObject(value) && IsExact(value.type, 'array') && !Type.ValueGuard.IsArray(value.items) && Type.ValueGuard.IsObject(value.items) const IsSConst = (value: unknown): value is SConst => Type.ValueGuard.IsObject(value) && Type.ValueGuard.IsObject(value['const']) const IsSString = (value: unknown): value is SString => Type.ValueGuard.IsObject(value) && IsExact(value.type, 'string') const IsSRef = (value: unknown): value is SRef => Type.ValueGuard.IsObject(value) && Type.ValueGuard.IsString(value.$ref) const IsSNumber = (value: unknown): value is SNumber => Type.ValueGuard.IsObject(value) && IsExact(value.type, 'number') const IsSInteger = (value: unknown): value is SInteger => Type.ValueGuard.IsObject(value) && IsExact(value.type, 'integer') const IsSBoolean = (value: unknown): value is SBoolean => Type.ValueGuard.IsObject(value) && IsExact(value.type, 'boolean') const IsSNull = (value: unknown): value is SBoolean => Type.ValueGuard.IsObject(value) && IsExact(value.type, 'null') const IsSProperties = (value: unknown): value is SProperties => Type.ValueGuard.IsObject(value) // prettier-ignore const IsSObject = (value: unknown): value is SObject => Type.ValueGuard.IsObject(value) && IsExact(value.type, 'object') && IsSProperties(value.properties) && (value.required === undefined || Type.ValueGuard.IsArray(value.required) && value.required.every((value: unknown) => Type.ValueGuard.IsString(value))) type SValue = string | number | boolean type SEnum = Readonly<{ enum: readonly SValue[] }> type SAllOf = Readonly<{ allOf: readonly unknown[] }> type SAnyOf = Readonly<{ anyOf: readonly unknown[] }> type SOneOf = Readonly<{ oneOf: readonly unknown[] }> type SProperties = Record type SObject = Readonly<{ type: 'object'; properties: SProperties; required?: readonly string[] }> type STuple = Readonly<{ type: 'array'; items: readonly unknown[] }> type SArray = Readonly<{ type: 'array'; items: unknown }> type SConst = Readonly<{ const: SValue }> type SRef = Readonly<{ $ref: string }> type SString = Readonly<{ type: 'string' }> type SNumber = Readonly<{ type: 'number' }> type SInteger = Readonly<{ type: 'integer' }> type SBoolean = Readonly<{ type: 'boolean' }> type SNull = Readonly<{ type: 'null' }> // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore type TFromRest = ( T extends readonly [infer L extends unknown, ...infer R extends unknown[]] ? TFromSchema extends infer S extends Type.TSchema ? TFromRest : TFromRest : Acc ) function FromRest(T: T): TFromRest { return T.map((L) => FromSchema(L)) as never } // ------------------------------------------------------------------ // FromEnumRest // ------------------------------------------------------------------ // prettier-ignore type TFromEnumRest = ( T extends readonly [infer L extends SValue, ...infer R extends SValue[]] ? TFromEnumRest]> : Acc ) function FromEnumRest(T: T): TFromEnumRest { return T.map((L) => Type.Literal(L)) as never } // ------------------------------------------------------------------ // AllOf // ------------------------------------------------------------------ // prettier-ignore type TFromAllOf = ( TFromRest extends infer Rest extends Type.TSchema[] ? Type.TIntersectEvaluated : Type.TNever ) function FromAllOf(T: T): TFromAllOf { return Type.IntersectEvaluated(FromRest(T.allOf), T) } // ------------------------------------------------------------------ // AnyOf // ------------------------------------------------------------------ // prettier-ignore type TFromAnyOf = ( TFromRest extends infer Rest extends Type.TSchema[] ? Type.TUnionEvaluated : Type.TNever ) function FromAnyOf(T: T): TFromAnyOf { return Type.UnionEvaluated(FromRest(T.anyOf), T) } // ------------------------------------------------------------------ // OneOf // ------------------------------------------------------------------ // prettier-ignore type TFromOneOf = ( TFromRest extends infer Rest extends Type.TSchema[] ? Type.TUnionEvaluated : Type.TNever ) function FromOneOf(T: T): TFromOneOf { return Type.UnionEvaluated(FromRest(T.oneOf), T) } // ------------------------------------------------------------------ // Enum // ------------------------------------------------------------------ // prettier-ignore type TFromEnum = ( TFromEnumRest extends infer Elements extends Type.TSchema[] ? Type.TUnionEvaluated : Type.TNever ) function FromEnum(T: T): TFromEnum { return Type.UnionEvaluated(FromEnumRest(T.enum)) } // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ // prettier-ignore type TFromTuple = ( TFromRest extends infer Elements extends Type.TSchema[] ? Type.TTuple : Type.TTuple<[]> ) // prettier-ignore function FromTuple(T: T): TFromTuple { return Type.Tuple(FromRest(T.items), T) as never } // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ // prettier-ignore type TFromArray = ( TFromSchema extends infer Items extends Type.TSchema ? Type.TArray : Type.TArray ) // prettier-ignore function FromArray(T: T): TFromArray { return Type.Array(FromSchema(T.items), T) as never } // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ // prettier-ignore type TFromConst = ( Type.Ensure> ) function FromConst(T: T) { return Type.Literal(T.const, T) } // ------------------------------------------------------------------ // Ref // ------------------------------------------------------------------ // prettier-ignore type TFromRef = ( Type.Ensure> ) function FromRef(T: T) { return Type.Ref(T['$ref']) } // ------------------------------------------------------------------ // Object // ------------------------------------------------------------------ type TFromPropertiesIsOptional = unknown extends R ? true : K extends R ? false : true // prettier-ignore type TFromProperties = Type.Evaluate<{ -readonly [K in keyof T]: TFromPropertiesIsOptional extends true ? Type.TOptional> : TFromSchema }> // prettier-ignore type TFromObject = ( TFromProperties[number]> extends infer Properties extends Type.TProperties ? Type.TObject : Type.TObject<{}> ) function FromObject(T: T): TFromObject { const properties = globalThis.Object.getOwnPropertyNames(T.properties).reduce((Acc, K) => { return { ...Acc, [K]: T.required && T.required.includes(K) ? FromSchema(T.properties[K]) : Type.Optional(FromSchema(T.properties[K])) } }, {} as Type.TProperties) return Type.Object(properties, T) as never } // ------------------------------------------------------------------ // FromSchema // ------------------------------------------------------------------ // prettier-ignore export type TFromSchema = ( T extends SAllOf ? TFromAllOf : T extends SAnyOf ? TFromAnyOf : T extends SOneOf ? TFromOneOf : T extends SEnum ? TFromEnum : T extends SObject ? TFromObject : T extends STuple ? TFromTuple : T extends SArray ? TFromArray : T extends SConst ? TFromConst : T extends SRef ? TFromRef : T extends SString ? Type.TString : T extends SNumber ? Type.TNumber : T extends SInteger ? Type.TInteger : T extends SBoolean ? Type.TBoolean : T extends SNull ? Type.TNull : Type.TUnknown ) /** Parses a TypeBox type from raw JsonSchema */ export function FromSchema(T: T): TFromSchema { // prettier-ignore return ( IsSAllOf(T) ? FromAllOf(T) : IsSAnyOf(T) ? FromAnyOf(T) : IsSOneOf(T) ? FromOneOf(T) : IsSEnum(T) ? FromEnum(T) : IsSObject(T) ? FromObject(T) : IsSTuple(T) ? FromTuple(T) : IsSArray(T) ? FromArray(T) : IsSConst(T) ? FromConst(T) : IsSRef(T) ? FromRef(T) : IsSString(T) ? Type.String(T) : IsSNumber(T) ? Type.Number(T) : IsSInteger(T) ? Type.Integer(T) : IsSBoolean(T) ? Type.Boolean(T) : IsSNull(T) ? Type.Null(T) : Type.Unknown(T || {}) ) as never } sinclairzx81-typebox-e0ec98c/example/prototypes/index.ts000066400000000000000000000027711505437577000236310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/prototypes The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './discriminated-union' export * from './from-schema' export * from './options' export * from './partial-deep' export * from './recursive-map' export * from './union-enum' export * from './union-oneof' sinclairzx81-typebox-e0ec98c/example/prototypes/options.ts000066400000000000000000000034031505437577000242060ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/prototypes The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, CloneType } from '@sinclair/typebox' // prettier-ignore export type TOptions> = ( Type & Options ) /** `[Prototype]` Augments a schema with additional generics aware properties */ // prettier-ignore export function Options>(type: Type, options: Options): TOptions { return CloneType(type, options) as never } sinclairzx81-typebox-e0ec98c/example/prototypes/partial-deep.ts000066400000000000000000000064651505437577000250750ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/prototypes The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeGuard, Type, TSchema, TIntersect, TUnion, TObject, TPartial, TProperties, Evaluate } from '@sinclair/typebox' // ------------------------------------------------------------------------------------- // TPartialDeepProperties // ------------------------------------------------------------------------------------- export type TPartialDeepProperties = { [K in keyof T]: TPartialDeep } function PartialDeepProperties(properties: T): TPartialDeepProperties { return Object.getOwnPropertyNames(properties).reduce((acc, key) => { return {...acc, [key]: PartialDeep(properties[key])} }, {}) as never } // ------------------------------------------------------------------------------------- // TPartialDeepRest // ------------------------------------------------------------------------------------- export type TPartialDeepRest = ( T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TPartialDeepRest]> : Acc ) function PartialDeepRest(rest: [...T]): TPartialDeepRest { return rest.map(schema => PartialDeep(schema)) as never } // ------------------------------------------------------------------------------------- // TPartialDeep // ------------------------------------------------------------------------------------- export type TPartialDeep = T extends TIntersect ? TIntersect> : T extends TUnion ? TUnion> : T extends TObject ? TPartial>>> : T export function PartialDeep(schema: T): TPartialDeep { return ( TypeGuard.IsIntersect(schema) ? Type.Intersect(PartialDeepRest(schema.allOf)) : TypeGuard.IsUnion(schema) ? Type.Union(PartialDeepRest(schema.anyOf)) : TypeGuard.IsObject(schema) ? Type.Partial(Type.Object(PartialDeepProperties(schema.properties))) : schema ) as never }sinclairzx81-typebox-e0ec98c/example/prototypes/readme.md000066400000000000000000000134271505437577000237310ustar00rootroot00000000000000# TypeBox Prototypes TypeBox prototypes are a set of types that are either under consideration for inclusion into the library, or have been requested by users but cannot be added to the library either due to complexity, using schematics that fall outside the supported TypeBox or should be expressed by users via advanced type composition. ## PartialDeep Maps the given schema as deep partial, making all properties and sub properties optional. This type is asked for on occation, but as there is no TypeScript equivalent and because this type is typically handled through end user type mapping, this type is left out of TypeBox. ```typescript import { PartialDeep } from './prototypes' const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number() }), y: Type.Object({ x: Type.Number(), y: Type.Number() }) }) const P = PartialDeep(T) type P = Static // type P = { // x?: { // x?: number, // y?: number // }, // y?: { // x?: number, // y?: number // }, // } ``` ## UnionEnum Creates an `enum` union string schema representation. This type is often requested by OpenAPI users, particularily for documentation presentation. As TypeBox standardizes on `anyOf` for all unions, this type is generally at odds with TypeBox's internal representation. Some considerations for internally remapping this type into a `anyOf` through composition have been considered (and would be feasible), but as TypeScript doesn't have multiple representations for unions, neither should TypeBox, making this type an unlikely candidate. ```typescript import { UnionEnum } from './prototypes' const T = UnionEnum(['A', 'B', 'C']) // const T = { // enum: ['A', 'B', 'C'] // } type T = Static // type T = 'A' | 'B' | 'C' ``` ## UnionOneOf Creates a `oneOf` union representation. This type is often requested by users looking for discriminated union support (which is not formally supported by JSON Schema). TypeBox omits this type as `oneOf` has the potential to create illogical schematics where values match more than one sub schema (making type inference extremely difficult). TypeBox preferences users explicitly narrowing on a overlapping union post type check, making `anyOf` the ideal representation, leaving the `oneOf` type an unlikely candidate for inclusion in the library. ```typescript import { UnionOneOf } from './prototypes' const T = UnionOneOf([ // const T = { Type.Literal('A'), // oneOf: [ Type.Literal('B'), // { const: 'A' }, Type.Literal('C') // { const: 'B' }, ]) // { const: 'C' }, // ] // } type T = Static // type T = 'A' | 'B' | 'C' ``` ## Options By default, TypeBox does not represent arbituary options as generics aware properties. However, there are cases where having options observable to the type system can be useful, for example conditionally mapping schematics based on custom metadata. The Options function makes user defined options generics aware. ```typescript import { Options } from './prototypes' const A = Options(Type.String(), { foo: 1 }) // Options type A = typeof A extends { foo: number } ? true : false // true: foo property is observable to the type system ``` ## Recursive Map The Recursive Map type enables deep structural remapping of a type and it's internal constituents. This type accepts a TSchema type and a mapping type function (expressed via HKT). The HKT is applied when traversing the type and it's interior. The mapping HKT can apply conditional tests to each visited type to remap into a new form. The following augments a schematic via Options, and conditionally remaps any schema with an default annotation to make it optional. ```typescript import { Type, TOptional, Static, TSchema } from '@sinclair/typebox' import { TRecursiveMap, TMappingType, Options } from './prototypes' // ------------------------------------------------------------------ // StaticDefault // ------------------------------------------------------------------ export interface StaticDefaultMapping extends TMappingType { output: ( this['input'] extends TSchema // if input schematic contains an default ? this['input'] extends { default: unknown } // annotation, remap it to be optional, ? TOptional // otherwise just return the schema as is. : this['input'] : this['input'] ) } export type StaticDefault = ( Static> ) // ------------------------------------------------------------------ // Usage // ------------------------------------------------------------------ const T = Type.Object({ x: Options(Type.String(), { default: 'hello' }), y: Type.String() }) type T = StaticDefault // { x?: string, y: string } type S = Static // { x: string, y: string }sinclairzx81-typebox-e0ec98c/example/prototypes/recursive-map.ts000066400000000000000000000204001505437577000252710ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/prototypes The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' // ------------------------------------------------------------------ // Mapping: Functions and Type // ------------------------------------------------------------------ export type TMappingFunction = (schema: Types.TSchema) => Types.TSchema export interface TMappingType { input: unknown output: unknown } // ------------------------------------------------------------------ // Record Parameters // ------------------------------------------------------------------ function GetRecordPattern(record: Types.TRecord): string { return globalThis.Object.getOwnPropertyNames(record.patternProperties)[0] } function GetRecordKey(record: Types.TRecord): Types.TSchema { const pattern = GetRecordPattern(record) return ( pattern === Types.PatternStringExact ? Types.String() : pattern === Types.PatternNumberExact ? Types.Number() : pattern === Types.PatternBooleanExact ? Types.Boolean() : Types.String({ pattern }) ) } function GetRecordValue(record: Types.TRecord): Types.TSchema { return record.patternProperties[GetRecordPattern(record)] } // ------------------------------------------------------------------ // Traversal // ------------------------------------------------------------------ // prettier-ignore type TApply = Result // prettier-ignore type TFromProperties }> = Result function FromProperties(properties: Types.TProperties, func: TMappingFunction): Types.TProperties { return globalThis.Object.getOwnPropertyNames(properties).reduce((result, key) => { return {...result, [key]: RecursiveMap(properties[key], func) } }, {}) } // prettier-ignore type TFromRest = ( Types extends [infer Left extends Types.TSchema, ...infer Right extends Types.TSchema[]] ? TFromRest]> : Result ) function FromRest(types: Types.TSchema[], func: TMappingFunction): Types.TSchema[] { return types.map(type => RecursiveMap(type, func)) } // prettier-ignore type TFromType )> = Result function FromType(type: Types.TSchema, func: TMappingFunction): Types.TSchema { return func(type) } // ------------------------------------------------------------------ // TRecursiveMap // ------------------------------------------------------------------ /** `[Prototype]` Applies a deep recursive map across the given type and sub types. */ // prettier-ignore export type TRecursiveMap, // Maps the Interior Parameterized Types Interior extends Types.TSchema = ( Exterior extends Types.TConstructor ? Types.TConstructor, TFromType> : Exterior extends Types.TFunction ? Types.TFunction, TFromType> : Exterior extends Types.TIntersect ? Types.TIntersect> : Exterior extends Types.TUnion ? Types.TUnion> : Exterior extends Types.TTuple ? Types.TTuple> : Exterior extends Types.TArray ? Types.TArray>: Exterior extends Types.TAsyncIterator ? Types.TAsyncIterator> : Exterior extends Types.TIterator ? Types.TIterator> : Exterior extends Types.TPromise ? Types.TPromise> : Exterior extends Types.TObject ? Types.TObject> : Exterior extends Types.TRecord ? Types.TRecordOrObject, TFromType> : Exterior ), // Modifiers Derived from Exterior Type Mapping IsOptional extends number = Exterior extends Types.TOptional ? 1 : 0, IsReadonly extends number = Exterior extends Types.TReadonly ? 1 : 0, Result extends Types.TSchema = ( [IsReadonly, IsOptional] extends [1, 1] ? Types.TReadonlyOptional : [IsReadonly, IsOptional] extends [0, 1] ? Types.TOptional : [IsReadonly, IsOptional] extends [1, 0] ? Types.TReadonly : Interior ) > = Result /** `[Prototype]` Applies a deep recursive map across the given type and sub types. */ // prettier-ignore export function RecursiveMap(type: Types.TSchema, func: TMappingFunction): Types.TSchema { // Maps the Exterior Type const exterior = Types.CloneType(FromType(type, func), type) // Maps the Interior Parameterized Types const interior = ( Types.KindGuard.IsConstructor(type) ? Types.Constructor(FromRest(type.parameters, func), FromType(type.returns, func), exterior) : Types.KindGuard.IsFunction(type) ? Types.Function(FromRest(type.parameters, func), FromType(type.returns, func), exterior) : Types.KindGuard.IsIntersect(type) ? Types.Intersect(FromRest(type.allOf, func), exterior) : Types.KindGuard.IsUnion(type) ? Types.Union(FromRest(type.anyOf, func), exterior) : Types.KindGuard.IsTuple(type) ? Types.Tuple(FromRest(type.items || [], func), exterior) : Types.KindGuard.IsArray(type) ? Types.Array(FromType(type.items, func), exterior) : Types.KindGuard.IsAsyncIterator(type) ? Types.AsyncIterator(FromType(type.items, func), exterior) : Types.KindGuard.IsIterator(type) ? Types.Iterator(FromType(type.items, func), exterior) : Types.KindGuard.IsPromise(type) ? Types.Promise(FromType(type.items, func), exterior) : Types.KindGuard.IsObject(type) ? Types.Object(FromProperties(type.properties, func), exterior) : Types.KindGuard.IsRecord(type) ? Types.Record(FromType(GetRecordKey(type), func), FromType(GetRecordValue(type), func), exterior) : Types.CloneType(exterior, exterior) ) // Modifiers Derived from Exterior Type Mapping const isOptional = Types.KindGuard.IsOptional(exterior) const isReadonly = Types.KindGuard.IsOptional(exterior) return ( isOptional && isReadonly ? Types.ReadonlyOptional(interior) : isOptional ? Types.Optional(interior) : isReadonly ? Types.Readonly(interior) : interior ) }sinclairzx81-typebox-e0ec98c/example/prototypes/union-enum.ts000066400000000000000000000046121505437577000246100ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/prototypes The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeRegistry, Kind, TSchema, SchemaOptions } from '@sinclair/typebox' // ------------------------------------------------------------------------------------- // TUnionEnum // ------------------------------------------------------------------------------------- export interface TUnionEnum extends TSchema { [Kind]: 'UnionEnum' static: T[number] enum: T } // ------------------------------------------------------------------------------------- // UnionEnum // ------------------------------------------------------------------------------------- /** `[Experimental]` Creates a Union type with a `enum` schema representation */ export function UnionEnum(values: [...T], options: SchemaOptions = {}) { function UnionEnumCheck(schema: TUnionEnum<(string | number)[]>, value: unknown) { return (typeof value === 'string' || typeof value === 'number') && schema.enum.includes(value) } if (!TypeRegistry.Has('UnionEnum')) TypeRegistry.Set('UnionEnum', UnionEnumCheck) return { ...options, [Kind]: 'UnionEnum', enum: values } as TUnionEnum }sinclairzx81-typebox-e0ec98c/example/prototypes/union-oneof.ts000066400000000000000000000047311505437577000247540ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/prototypes The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeRegistry, Kind, Static, TSchema, SchemaOptions } from '@sinclair/typebox' import { Value } from '@sinclair/typebox/value' // ------------------------------------------------------------------------------------- // TUnionOneOf // ------------------------------------------------------------------------------------- export interface TUnionOneOf extends TSchema { [Kind]: 'UnionOneOf' static: { [K in keyof T]: Static }[number] oneOf: T } // ------------------------------------------------------------------------------------- // UnionOneOf // ------------------------------------------------------------------------------------- /** `[Experimental]` Creates a Union type with a `oneOf` schema representation */ export function UnionOneOf(oneOf: [...T], options: SchemaOptions = {}) { function UnionOneOfCheck(schema: TUnionOneOf, value: unknown) { return 1 === schema.oneOf.reduce((acc: number, schema: any) => (Value.Check(schema, value) ? acc + 1 : acc), 0) } if (!TypeRegistry.Has('UnionOneOf')) TypeRegistry.Set('UnionOneOf', UnionOneOfCheck) return { ...options, [Kind]: 'UnionOneOf', oneOf } as TUnionOneOf }sinclairzx81-typebox-e0ec98c/example/standard/000077500000000000000000000000001505437577000215135ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/example/standard/index.ts000066400000000000000000000024731505437577000232000ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/standard-schema The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 './standard'sinclairzx81-typebox-e0ec98c/example/standard/readme.md000066400000000000000000000036701505437577000233000ustar00rootroot00000000000000### Standard Schema Reference implementation of [Standard Schema](https://github.com/standard-schema/standard-schema) for TypeBox. ### Example The following example augments a TypeBox schema with the required `~standard` interface. The `~standard` interface is applied via non-enumerable configuration enabling the schematics to continue to be used with strict compliant validators such as Ajv that would otherwise reject the non-standard `~standard` keyword. ```typescript import { StandardSchema } from './standard' import { Type } from '@sinclair/typebox' const T = StandardSchema(Type.Object({ // const A = { x: Type.Number(), // (non-enumerable) '~standard': { y: Type.Number(), // version: 1, z: Type.Number(), // vendor: 'TypeBox', })) // validate: [Function: validate] // }, // type: 'object', // properties: { // x: { type: 'number', [Symbol(TypeBox.Kind)]: 'Number' }, // y: { type: 'number', [Symbol(TypeBox.Kind)]: 'Number' }, // z: { type: 'number', [Symbol(TypeBox.Kind)]: 'Number' } // }, // required: [ 'x', 'y', 'z' ], // [Symbol(TypeBox.Kind)]: 'Object' // } const R = T['~standard'].validate({ x: 1, y: 2, z: 3 }) // const R = { // value: { x: 1, y: 2, z: 3 }, // issues: [] // } ```sinclairzx81-typebox-e0ec98c/example/standard/standard.ts000066400000000000000000000074701505437577000236730ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/standard-schema The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 { AssertError, Value, ValueError, ValueErrorType } from '@sinclair/typebox/value' import { TSchema, StaticDecode, CloneType } from '@sinclair/typebox' // ------------------------------------------------------------------ // StandardSchema // ------------------------------------------------------------------ interface StandardResult { value: Output issues: ValueError[] } interface StandardSchema { readonly "~standard": StandardSchemaProperties } interface StandardSchemaProperties { readonly version: 1 readonly vendor: 'TypeBox' readonly validate: (value: unknown) => StandardResult readonly types?: undefined } // ------------------------------------------------------------------ // Issues // ------------------------------------------------------------------ // prettier-ignore function CreateIssues(schema: TSchema, value: unknown, error: unknown): ValueError[] { const isAssertError = error instanceof AssertError ? error : undefined return !isAssertError ? [{errors: [], message: 'Unknown error', path: '/', type: ValueErrorType.Kind, schema, value }] : [...isAssertError.Errors()] } // ------------------------------------------------------------------ // Validate // ------------------------------------------------------------------ // prettier-ignore function CreateValidator(schema: Type, references: TSchema[]): (value: unknown) => StandardResult> { return (value: unknown): StandardResult> => { try { return { value: Value.Parse(schema, references, value), issues: [] } } catch (error) { return { value: undefined, issues: CreateIssues(schema, value, error) } } } } // ------------------------------------------------------------------ // StandardSchema // ------------------------------------------------------------------ /** Augments a TypeBox type with the `~standard` validation interface. */ export type TStandardSchema = ( Input & StandardSchema ) /** Augments a TypeBox type with the `~standard` validation interface. */ export function StandardSchema(schema: Type, references: TSchema[] = []): TStandardSchema> { const standard = { version: 1, vendor: 'TypeBox', validate: CreateValidator(schema, references) } return Object.defineProperty(CloneType(schema), "~standard", { enumerable: false, value: standard }) as never }sinclairzx81-typebox-e0ec98c/example/typedef/000077500000000000000000000000001505437577000213535ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/example/typedef/index.ts000066400000000000000000000024671505437577000230430ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/typedef The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './typedef'sinclairzx81-typebox-e0ec98c/example/typedef/readme.md000066400000000000000000000541601505437577000231400ustar00rootroot00000000000000# TypeDef TypeBox is considering support for the JSON Type Definition [RFC8927](https://www.rfc-editor.org/rfc/rfc8927) specification in future releases. This specification is similar to JSON Schema but provides a constrained type representation that enables schematics to map more naturally to [nominal type systems](https://en.wikipedia.org/wiki/Nominal_type_system) as well as offering type primitives such as `int8`, `uint32` or `float32`. JSON Type Definition can be useful in applications that need to express and share data structures in a way that can be understood by a wide range of programming languages outside of JavaScript. License MIT ## Contents - [Usage](#Usage) - [Types](#Types) - [Unions](#Unions) - [Check](#Check) ## Usage TypeBox currently doesn't publish TypeDef as part of the mainline package. However the TypeDef functionality is written to be a standalone module you can copy into your project. You will also need `@sinclair/typebox` installed. You can obtain the `typedef` module from `example/typedef/typedef.ts` contained within this repository. ```typescript import { Type, Static } from './typedef' const T = Type.Struct({ // const T = { x: Type.Float32(), // properties: { y: Type.Float32(), // x: { type: 'float32' }, z: Type.Float32() // y: { type: 'float32' }, }) // z: { type: 'float32' } // } // } type T = Static // type T = { // x: number, // y: number, // z: number // } ``` ## Types The following types are supported by the typedef module. Please note these types are not compatible with the JSON Schema specification and should not be combined with the standard TypeBox types. ```typescript ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐ │ TypeBox │ TypeScript │ JSON Type Definition │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Boolean() │ type T = boolean │ const T = { │ │ │ │ type: 'boolean' │ │ │ │ } │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.String() │ type T = string │ const T = { │ │ │ │ type: 'string' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Float32() │ type T = number │ const T = { │ │ │ │ type: 'float32' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Float64() │ type T = number │ const T = { │ │ │ │ type: 'float64' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Int8() │ type T = number │ const T = { │ │ │ │ type: 'int8' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Int16() │ type T = number │ const T = { │ │ │ │ type: 'int16' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Int32() │ type T = number │ const T = { │ │ │ │ type: 'int32' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Uint8() │ type T = number │ const T = { │ │ │ │ type: 'uint8' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Uint16() │ type T = number │ const T = { │ │ │ │ type: 'uint16' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Uint32() │ type T = number │ const T = { │ │ │ │ type: 'uint32' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Timestamp() │ type T = number │ const T = { │ │ │ │ type: 'timestamp' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Struct([ │ type T = { │ const T = { │ │ x: Type.Float32(), │ x: number, │ properties: { │ │ y: Type.Float32(), │ y: number │ x: number, │ │ ]) │ } │ y: number │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Array( │ type T = number[] │ const T = { │ │ Type.Float32() │ │ elements: { │ │ ) │ │ type: 'float32' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Record( │ type T = Record< │ const T = { │ │ Type.Float32() │ string, │ values: { │ │ ) │ number │ type: 'float32' │ │ │ > │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Enum([ │ type T = 'A' | 'B' | 'C' │ const T = { │ │ 'A', 'B', 'C' │ │ enum: [ │ │ ]) │ │ 'A', │ │ │ │ 'B', │ │ │ │ 'C' │ │ │ │ ] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Union([ │ type T = { │ const T = { │ │ Type.Struct({ │ kind: '0', │ discriminator: 'kind', │ │ x: Type.Float32() │ x: number │ mapping: { │ │ }), │ } | { │ '0': { │ │ Type.Struct({ │ kind: '1' │ properties: { │ │ y: Type.Float32() │ y: number │ x: { │ │ ]) │ } │ type: 'float32' │ │ ], 'kind') │ │ } │ │ │ │ } │ │ │ │ }, │ │ │ │ '1': { | │ │ │ properties: { │ │ │ │ y: { │ │ │ │ type: 'float32' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘ ``` ## Unions TypeBox supports JSON Type Definition discriminated unions with `Type.Union`. This type works similar its JSON Schema counterpart, but can only accept types of `Type.Struct` and will infer each struct with an additional named `discriminator` field. The representation for discriminated unions are also quite different, where instead of `anyOf` or `oneOf`, a set of `mapping` properties are used for each sub type. ```typescript const Vector2 = Type.Struct({ // const Vector2 = { x: Type.Float32(), // properties: { y: Type.Float32() // x: { type: 'float32' }, }) // y: { type: 'float32' } // } // } const Vector3 = Type.Struct({ // const Vector3 = { x: Type.Float32(), // properties: { y: Type.Float32(), // x: { type: 'float32' }, z: Type.Float32() // y: { type: 'float32' }, }) // z: { type: 'float32' } // } // } const Vector4 = Type.Struct({ // const Vector4 = { x: Type.Float32(), // properties: { y: Type.Float32(), // x: { type: 'float32' }, z: Type.Float32(), // y: { type: 'float32' }, w: Type.Float32() // z: { type: 'float32' }, }) // w: { type: 'float32' } // } // } const T = Type.Union([ // const T = { Vector2, // discriminator: 'type', Vector3, // mapping: { Vector4 // 0: { ]) // properties: { // x: { type: 'float32' }, // y: { type: 'float32' } // } // }, // 1: { // properties: { // x: { type: 'float32' }, // y: { type: 'float32' }, // z: { type: 'float32' } // } // }, // 2: { // properties: { // x: { type: 'float32' }, // y: { type: 'float32' }, // z: { type: 'float32' } // } // } // } // } type T = Static // type T = { // type: '0', // x: number, // y: number // } | { // type: '1', // x: number, // y: number, // y: number // } | { // type: '2', // x: number, // y: number, // y: number, // w: number // } ``` To type check a value matching the above union, the value will need to contain the discriminator property `type` with a value matching one of the sub type `mapping` keys. The inference type shown above can be a good reference point to understand the structure of the expected value. Nominal type systems will use the discriminator to an expected target type. The following are examples of valid and invalid union data. ```typescript const V = { x: 1, y: 1 } // invalid Vector2 const V = { type: '0', x: 1, y: 1 } // valid Vector2 const V = { type: '0', x: 1, y: 1, z: 1 } // invalid Vector2 const V = { type: '1', x: 1, y: 1, z: 1 } // valid Vector3 ``` ## Check TypeDef types are partially supported with the `TypeCompiler` and `Value` checking modules through the extensible type system in TypeBox. Please note these types are not optimized for JIT performance and do not provide deep error reporting support. For more fully featured validation support consider Ajv. Documentation of Ajv support can be found [here](https://ajv.js.org/json-type-definition.html). The following is TypeDef used with TypeBox's type checking infrastructure. ```typescript import { TypeCompiler } from '@sinclair/typebox/compiler' import { Value } from '@sinclair/typebox/value' const T = Type.Struct({ x: Type.Float32(), y: Type.Float32(), z: Type.Float32() }) const V = { x: 1, y: 2, z: 3 } const R1 = TypeCompiler.Compile(T).Check(V) // true const R2 = Value.Check(T, V) // true ```sinclairzx81-typebox-e0ec98c/example/typedef/typedef.ts000066400000000000000000000734071505437577000233760ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/typedef The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { SetErrorFunction, DefaultErrorFunction } from '@sinclair/typebox/errors' import * as Types from '@sinclair/typebox/type' // -------------------------------------------------------------------------- // Metadata // -------------------------------------------------------------------------- export interface Metadata { [name: string]: any } // -------------------------------------------------------------------------- // TArray // -------------------------------------------------------------------------- export interface TArray extends Types.TSchema { [Types.Kind]: 'TypeDef:Array' static: Types.Static[] elements: T } // -------------------------------------------------------------------------- // TBoolean // -------------------------------------------------------------------------- export interface TBoolean extends Types.TSchema { [Types.Kind]: 'TypeDef:Boolean' static: 'boolean' type: 'boolean' } // -------------------------------------------------------------------------- // TUnion // -------------------------------------------------------------------------- export type InferUnion = T extends [infer L extends TStruct, ...infer R extends TStruct[]] ? Types.Evaluate<{ [_ in D]: Index } & Types.Static> | InferUnion>> : never export interface TUnion extends Types.TSchema { [Types.Kind]: 'TypeDef:Union' static: InferUnion discriminator: D, mapping: T } // -------------------------------------------------------------------------- // TEnum // -------------------------------------------------------------------------- export interface TEnum extends Types.TSchema { [Types.Kind]: 'TypeDef:Enum' static: T[number] enum: [...T] } // -------------------------------------------------------------------------- // TFloat32 // -------------------------------------------------------------------------- export interface TFloat32 extends Types.TSchema { [Types.Kind]: 'TypeDef:Float32' type: 'float32' static: number } // -------------------------------------------------------------------------- // TFloat64 // -------------------------------------------------------------------------- export interface TFloat64 extends Types.TSchema { [Types.Kind]: 'TypeDef:Float64' type: 'float64' static: number } // -------------------------------------------------------------------------- // TInt8 // -------------------------------------------------------------------------- export interface TInt8 extends Types.TSchema { [Types.Kind]: 'TypeDef:Int8' type: 'int8' static: number } // -------------------------------------------------------------------------- // TInt16 // -------------------------------------------------------------------------- export interface TInt16 extends Types.TSchema { [Types.Kind]: 'TypeDef:Int16' type: 'int16' static: number } // -------------------------------------------------------------------------- // TInt32 // -------------------------------------------------------------------------- export interface TInt32 extends Types.TSchema { [Types.Kind]: 'TypeDef:Int32' type: 'int32' static: number } // -------------------------------------------------------------------------- // TUint8 // -------------------------------------------------------------------------- export interface TUint8 extends Types.TSchema { [Types.Kind]: 'TypeDef:Uint8' type: 'uint8' static: number } // -------------------------------------------------------------------------- // TUint16 // -------------------------------------------------------------------------- export interface TUint16 extends Types.TSchema { [Types.Kind]: 'TypeDef:Uint16' type: 'uint16' static: number } // -------------------------------------------------------------------------- // TUint32 // -------------------------------------------------------------------------- export interface TUint32 extends Types.TSchema { [Types.Kind]: 'TypeDef:Uint32' type: 'uint32' static: number } // -------------------------------------------------------------------------- // TProperties // -------------------------------------------------------------------------- export type TFields = Record // -------------------------------------------------------------------------- // TRecord // -------------------------------------------------------------------------- export interface TRecord extends Types.TSchema { [Types.Kind]: 'TypeDef:Record' static: Record> values: T } // -------------------------------------------------------------------------- // TString // -------------------------------------------------------------------------- export interface TString extends Types.TSchema { [Types.Kind]: 'TypeDef:String' type: 'string' static: string } // -------------------------------------------------------------------------- // TStruct // -------------------------------------------------------------------------- // used for structural type inference type OptionalKeys = { [K in keyof T]: T[K] extends (Types.TOptional) ? T[K] : never } type RequiredKeys = { [K in keyof T]: T[K] extends (Types.TOptional) ? never : T[K] } // static inference type ReadonlyOptionalPropertyKeys = { [K in keyof T]: T[K] extends Types.TReadonly ? (T[K] extends Types.TOptional ? K : never) : never }[keyof T] type ReadonlyPropertyKeys = { [K in keyof T]: T[K] extends Types.TReadonly ? (T[K] extends Types.TOptional ? never : K) : never }[keyof T] type OptionalPropertyKeys = { [K in keyof T]: T[K] extends Types.TOptional ? (T[K] extends Types.TReadonly ? never : K) : never }[keyof T] type RequiredPropertyKeys = keyof Omit | ReadonlyPropertyKeys | OptionalPropertyKeys> // prettier-ignore type StructStaticProperties> = Types.Evaluate<( Readonly>>> & Readonly>> & Partial>> & Required>> )> // prettier-ignore export type StructStatic = StructStaticProperties }> export interface StructMetadata extends Metadata { additionalProperties?: boolean } export interface TStruct extends Types.TSchema, StructMetadata { [Types.Kind]: 'TypeDef:Struct' static: StructStatic optionalProperties: { [K in Types.Assert, keyof T>]: T[K] } properties: { [K in Types.Assert, keyof T>]: T[K] } } // -------------------------------------------------------------------------- // TTimestamp // -------------------------------------------------------------------------- export interface TTimestamp extends Types.TSchema { [Types.Kind]: 'TypeDef:Timestamp' type: 'timestamp' static: string } // -------------------------------------------------------------------------- // Static // -------------------------------------------------------------------------- export type Static = Types.Static // -------------------------------------------------------------------------- // TimestampFormat // -------------------------------------------------------------------------- export namespace TimestampFormat { const DATE_TIME_SEPARATOR = /t|\s/i const TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i const DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] function IsLeapYear(year: number): boolean { return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) } function IsDate(str: string): boolean { const matches: string[] | null = DATE.exec(str) if (!matches) return false const year: number = +matches[1] const month: number = +matches[2] const day: number = +matches[3] return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && IsLeapYear(year) ? 29 : DAYS[month]) } function IsTime(str: string, strictTimeZone?: boolean): boolean { const matches: string[] | null = TIME.exec(str) if (!matches) return false const hr: number = +matches[1] const min: number = +matches[2] const sec: number = +matches[3] const tz: string | undefined = matches[4] const tzSign: number = matches[5] === '-' ? -1 : 1 const tzH: number = +(matches[6] || 0) const tzM: number = +(matches[7] || 0) if (tzH > 23 || tzM > 59 || (strictTimeZone && !tz)) return false if (hr <= 23 && min <= 59 && sec < 60) return true const utcMin = min - tzM * tzSign const utcHr = hr - tzH * tzSign - (utcMin < 0 ? 1 : 0) return (utcHr === 23 || utcHr === -1) && (utcMin === 59 || utcMin === -1) && sec < 61 } function IsDateTime(value: string, strictTimeZone?: boolean): boolean { const dateTime: string[] = value.split(DATE_TIME_SEPARATOR) return dateTime.length === 2 && IsDate(dateTime[0]) && IsTime(dateTime[1], strictTimeZone) } export function Check(value: string): boolean { return IsDateTime(value) } } // -------------------------------------------------------------------------- // ValueCheck // -------------------------------------------------------------------------- export class ValueCheckError extends Types.TypeBoxError { constructor(public readonly schema: Types.TSchema) { super('Unknown type') } } export namespace ValueCheck { // ------------------------------------------------------------------------ // Guards // ------------------------------------------------------------------------ function IsObject(value: unknown): value is Record { return typeof value === 'object' && value !== null && !globalThis.Array.isArray(value) } function IsArray(value: unknown): value is unknown[] { return globalThis.Array.isArray(value) } function IsString(value: unknown): value is string { return typeof value === 'string' } function IsInt(value: unknown, min: number, max: number): value is number { return typeof value === 'number' && globalThis.Number.isInteger(value) && value >= min && value < max } // ------------------------------------------------------------------------ // Types // ------------------------------------------------------------------------ function Array(schema: TArray, value: unknown): boolean { return IsArray(value) && value.every(value => Visit(schema.elements, value)) } function Boolean(schema: TBoolean, value: unknown): boolean { return typeof value === 'boolean' } function Enum(schema: TEnum, value: unknown): boolean { return typeof value === 'string' && schema.enum.includes(value) } function Float32(schema: TFloat32, value: unknown): boolean { return typeof value === 'number' } function Float64(schema: TFloat64, value: unknown): boolean { return typeof value === 'number' } function Int8(schema: TInt8, value: unknown): boolean { return IsInt(value, -128, 127) } function Int16(schema: TInt16, value: unknown): boolean { return IsInt(value, -32_768, 32_767) } function Int32(schema: TInt32, value: unknown): boolean { return IsInt(value, -2_147_483_648, 2_147_483_647) } function Uint8(schema: TUint8, value: unknown): boolean { return IsInt(value, 0, 255) } function Uint16(schema: TUint16, value: unknown): boolean { return IsInt(value, 0, 65535) } function Uint32(schema: TUint32, value: unknown): boolean { return IsInt(value, 0, 4_294_967_295) } function Record(schema: TRecord, value: unknown): boolean { return IsObject(value) && globalThis.Object.getOwnPropertyNames(value).every(key => Visit(schema.values, value[key])) } function String(schema: TString, value: unknown): boolean { return typeof value === 'string' } function Struct(schema: TStruct, value: unknown, descriminator?: string): boolean { if (!IsObject(value)) return false const optionalKeys = schema.optionalProperties === undefined ? [] : globalThis.Object.getOwnPropertyNames(schema.optionalProperties) const requiredKeys = schema.properties === undefined ? [] : globalThis.Object.getOwnPropertyNames(schema.properties) const unknownKeys = globalThis.Object.getOwnPropertyNames(value) for (const requiredKey of requiredKeys) { if (!(requiredKey in value)) return false const requiredProperty = value[requiredKey] const requiredSchema = (schema as any).properties[requiredKey] if (!Visit(requiredSchema, requiredProperty)) return false } for (const optionalKey of optionalKeys) { if (!(optionalKey in value)) continue const optionalProperty = value[optionalKey] const optionalSchema = (schema as any).properties[optionalKey] if (!Visit(optionalSchema, optionalProperty)) return false } if (schema.additionalProperties === true) return true const knownKeys = [...optionalKeys, ...requiredKeys] for (const unknownKey of unknownKeys) if (!knownKeys.includes(unknownKey) && (descriminator !== undefined && unknownKey !== descriminator)) return false for (const knownKey of knownKeys) if (!unknownKeys.includes(knownKey)) return false return true } function Timestamp(schema: TString, value: unknown): boolean { return IsString(value) && TimestampFormat.Check(value) } function Union(schema: TUnion, value: unknown): boolean { if (!IsObject(value)) return false if (!(schema.discriminator in value)) return false if (!IsString(value[schema.discriminator])) return false if (!(value[schema.discriminator] in schema.mapping)) return false const struct = schema.mapping[value[schema.discriminator]] as TStruct return Struct(struct, value, schema.discriminator) } function Visit(schema: Types.TSchema, value: unknown): boolean { const anySchema = schema as any switch (anySchema[Types.Kind]) { case 'TypeDef:Array': return Array(anySchema, value) case 'TypeDef:Boolean': return Boolean(anySchema, value) case 'TypeDef:Union': return Union(anySchema, value) case 'TypeDef:Enum': return Enum(anySchema, value) case 'TypeDef:Float32': return Float32(anySchema, value) case 'TypeDef:Float64': return Float64(anySchema, value) case 'TypeDef:Int8': return Int8(anySchema, value) case 'TypeDef:Int16': return Int16(anySchema, value) case 'TypeDef:Int32': return Int32(anySchema, value) case 'TypeDef:Uint8': return Uint8(anySchema, value) case 'TypeDef:Uint16': return Uint16(anySchema, value) case 'TypeDef:Uint32': return Uint32(anySchema, value) case 'TypeDef:Record': return Record(anySchema, value) case 'TypeDef:String': return String(anySchema, value) case 'TypeDef:Struct': return Struct(anySchema, value) case 'TypeDef:Timestamp': return Timestamp(anySchema, value) default: throw new ValueCheckError(anySchema) } } export function Check(schema: T, value: unknown): value is Types.Static { return Visit(schema, value) } } // -------------------------------------------------------------------------- // TypeGuard // -------------------------------------------------------------------------- export namespace TypeGuard { // ------------------------------------------------------------------------ // Guards // ------------------------------------------------------------------------ function IsObject(value: unknown): value is Record { return typeof value === 'object' } function IsArray(value: unknown): value is unknown[] { return globalThis.Array.isArray(value) } function IsOptionalBoolean(value: unknown): value is boolean | undefined { return IsBoolean(value) || value === undefined } function IsBoolean(value: unknown): value is boolean { return typeof value === 'boolean' } function IsString(value: unknown): value is string { return typeof value === 'string' } // ------------------------------------------------------------------------ // Types // ------------------------------------------------------------------------ export function TArray(schema: unknown): schema is TArray { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Array' && TSchema(schema['elements']) } export function TBoolean(schema: unknown): schema is TBoolean { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Boolean' && schema['type'] === 'boolean' } export function TUnion(schema: unknown): schema is TUnion { if(!(IsObject(schema) && schema[Types.Kind] === 'TypeDef:Union' && IsString(schema['discriminator']) && IsObject(schema['mapping']))) return false return globalThis.Object.getOwnPropertyNames(schema['mapping']).every(key => TSchema((schema['mapping'] as any)[key])) } export function TEnum(schema: unknown): schema is TEnum { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Enum' && IsArray(schema['enum']) && schema['enum'].every(item => IsString(item)) } export function TFloat32(schema: unknown): schema is TFloat32 { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Float32' && schema['type'] === 'float32' } export function TFloat64(schema: unknown): schema is TFloat64 { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Float64' && schema['type'] === 'float64' } export function TInt8(schema: unknown): schema is TInt8 { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Int8' && schema['type'] === 'int8' } export function TInt16(schema: unknown): schema is TInt16 { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Int16' && schema['type'] === 'int16' } export function TInt32(schema: unknown): schema is TInt32 { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Int32' && schema['type'] === 'int32' } export function TUint8(schema: unknown): schema is TUint8 { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Uint8' && schema['type'] === 'uint8' } export function TUint16(schema: unknown): schema is TUint16 { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Uint16' && schema['type'] === 'uint16' } export function TUint32(schema: unknown): schema is TUint32 { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Uint32' && schema['type'] === 'uint32' } export function TRecord(schema: unknown): schema is TRecord { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Record' && TSchema(schema['values']) } export function TString(schema: unknown): schema is TString { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:String' && schema['type'] === 'string' } export function TStruct(schema: unknown): schema is TStruct { if(!(IsObject(schema) && schema[Types.Kind] === 'TypeDef:Struct' && IsOptionalBoolean(schema['additionalProperties']))) return false const optionalProperties = schema['optionalProperties'] const requiredProperties = schema['properties'] const optionalCheck = optionalProperties === undefined || IsObject(optionalProperties) && globalThis.Object.getOwnPropertyNames(optionalProperties).every(key => TSchema(optionalProperties[key])) const requiredCheck = requiredProperties === undefined || IsObject(requiredProperties) && globalThis.Object.getOwnPropertyNames(requiredProperties).every(key => TSchema(requiredProperties[key])) return optionalCheck && requiredCheck } export function TTimestamp(schema: unknown): schema is TTimestamp { return IsObject(schema) && schema[Types.Kind] === 'TypeDef:Timestamp' && schema['type'] === 'timestamp' } export function TKind(schema: unknown): schema is Types.TKind { return IsObject(schema) && Types.Kind in schema && typeof (schema as any)[Types.Kind] === 'string' // TS 4.1.5: any required for symbol indexer } export function TSchema(schema: unknown): schema is Types.TSchema { // prettier-ignore return ( TArray(schema) || TBoolean(schema) || TUnion(schema) || TEnum(schema) || TFloat32(schema) || TFloat64(schema) || TInt8(schema) || TInt16(schema) || TInt32(schema) || TUint8(schema) || TUint16(schema) || TUint32(schema) || TRecord(schema) || TString(schema) || TStruct(schema) || TTimestamp(schema) || (TKind(schema) && Types.TypeRegistry.Has(schema[Types.Kind])) ) } } // -------------------------------------------------------------------------- // TypeRegistry // -------------------------------------------------------------------------- Types.TypeRegistry.Set('TypeDef:Array', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Boolean', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Union', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Int8', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Int16', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Int32', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Uint8', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Uint16', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Uint32', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Record', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:String', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Struct', (schema, value) => ValueCheck.Check(schema, value)) Types.TypeRegistry.Set('TypeDef:Timestamp', (schema, value) => ValueCheck.Check(schema, value)) // -------------------------------------------------------------------------- // TypeSystemErrorFunction // -------------------------------------------------------------------------- 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' case 'TypeDef:Int8': return 'Expected Int8' case 'TypeDef:Int16': return 'Expected Int16' case 'TypeDef:Int32': return 'Expected Int32' case 'TypeDef:Uint8': return 'Expected Uint8' case 'TypeDef:Uint16': return 'Expected Uint16' case 'TypeDef:Uint32': return 'Expected Uint32' case 'TypeDef:Record': return 'Expected Record' case 'TypeDef:String': return 'Expected String' case 'TypeDef:Struct': return 'Expected Struct' case 'TypeDef:Timestamp': return 'Expected Timestamp' } return DefaultErrorFunction(error) }) // -------------------------------------------------------------------------- // TypeDefBuilder // -------------------------------------------------------------------------- export class TypeDefBuilder { // ------------------------------------------------------------------------ // Core // ------------------------------------------------------------------------ protected Create(schema: Record, metadata: Record): any { const keys = globalThis.Object.getOwnPropertyNames(metadata) return keys.length > 0 ? { ...schema, metadata: { ...metadata } } : { ...schema } } /** [Standard] Removes compositing symbols from this schema */ public Strict(schema: T): T { return JSON.parse(JSON.stringify(schema)) as T } // ------------------------------------------------------------------------ // Modifiers // ------------------------------------------------------------------------ /** `[Standard]` Creates an Optional property */ public Optional(schema: T): Types.TOptional { return this.Optional(schema) } /** `[Standard]` Creates a Readonly property */ public Readonly(schema: T): Types.TReadonly { return this.Readonly(schema) } // ------------------------------------------------------------------------ // Types // ------------------------------------------------------------------------ /** [Standard] Creates a Array type */ public Array(elements: T, metadata: Metadata = {}): TArray { return this.Create({ [Types.Kind]: 'TypeDef:Array', elements }, metadata) } /** [Standard] Creates a Boolean type */ public Boolean(metadata: Metadata = {}): TBoolean { return this.Create({ [Types.Kind]: 'TypeDef:Boolean', type: 'boolean' }, metadata) } /** [Standard] Creates a Enum type */ public Enum(values: [...T], metadata: Metadata = {}): TEnum { return this.Create({[Types.Kind]: 'TypeDef:Enum', enum: values }, metadata ) } /** [Standard] Creates a Float32 type */ public Float32(metadata: Metadata = {}): TFloat32 { return this.Create({ [Types.Kind]: 'TypeDef:Float32', type: 'float32' }, metadata) } /** [Standard] Creates a Float64 type */ public Float64(metadata: Metadata = {}): TFloat64 { return this.Create({ [Types.Kind]: 'TypeDef:Float64', type: 'float64' }, metadata) } /** [Standard] Creates a Int8 type */ public Int8(metadata: Metadata = {}): TInt8 { return this.Create({ [Types.Kind]: 'TypeDef:Int8', type: 'int8' }, metadata) } /** [Standard] Creates a Int16 type */ public Int16(metadata: Metadata = {}): TInt16 { return this.Create({ [Types.Kind]: 'TypeDef:Int16', type: 'int16' }, metadata) } /** [Standard] Creates a Int32 type */ public Int32(metadata: Metadata = {}): TInt32 { return this.Create({ [Types.Kind]: 'TypeDef:Int32', type: 'int32' }, metadata) } /** [Standard] Creates a Uint8 type */ public Uint8(metadata: Metadata = {}): TUint8 { return this.Create({ [Types.Kind]: 'TypeDef:Uint8', type: 'uint8' }, metadata) } /** [Standard] Creates a Uint16 type */ public Uint16(metadata: Metadata = {}): TUint16 { return this.Create({ [Types.Kind]: 'TypeDef:Uint16', type: 'uint16' }, metadata) } /** [Standard] Creates a Uint32 type */ public Uint32(metadata: Metadata = {}): TUint32 { return this.Create({ [Types.Kind]: 'TypeDef:Uint32', type: 'uint32' }, metadata) } /** [Standard] Creates a Record type */ public Record(values: T, metadata: Metadata = {}): TRecord { return this.Create({ [Types.Kind]: 'TypeDef:Record', values },metadata) } /** [Standard] Creates a String type */ public String(metadata: Metadata = {}): TString { return this.Create({ [Types.Kind]: 'TypeDef:String', type: 'string' }, metadata) } /** [Standard] Creates a Struct type */ public Struct(fields: T, metadata: StructMetadata = {}): TStruct { 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) } /** [Standard] Creates a Union type */ public Union[], D extends string = 'type'>(structs: [...T], discriminator?: D): TUnion { discriminator = (discriminator || 'type') as D if (structs.length === 0) throw new Error('TypeDefBuilder: Union types must contain at least one struct') const mapping = structs.reduce((acc, current, index) => ({ ...acc, [index.toString()]: current }), {}) return this.Create({ [Types.Kind]: 'TypeDef:Union', discriminator, mapping }, {}) } /** [Standard] Creates a Timestamp type */ public Timestamp(metadata: Metadata = {}): TTimestamp { return this.Create({ [Types.Kind]: 'TypeDef:Timestamp', type: 'timestamp' }, metadata) } } /** JSON Type Definition Type Builder */ export const Type = new TypeDefBuilder() sinclairzx81-typebox-e0ec98c/hammer.mjs000066400000000000000000000120001505437577000202350ustar00rootroot00000000000000import * 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 task example/index.ts') } // ------------------------------------------------------------------------------- // Start // ------------------------------------------------------------------------------- export async function start() { await shell(`hammer run example/index.ts --dist target/example`) } // ------------------------------------------------------------------------------- // Benchmark // ------------------------------------------------------------------------------- export async function benchmark() { await Benchmark.compression() await Benchmark.measurement() } // ------------------------------------------------------------------------------- // Test // ------------------------------------------------------------------------------- export async function test_typescript() { for (const version of [ '4.9.5', '5.0.4', '5.1.3', '5.1.6', '5.2.2', '5.3.2', '5.3.3', '5.4.3', '5.4.5', '5.5.2', '5.5.3', '5.5.4', '5.6.2', '5.6.3', '5.7.2', '5.7.3', '5.8.2', '5.8.3', 'next', 'latest' ]) { await shell(`npm install typescript@${version} --no-save`) await test_static() } } export async function test_static() { await shell(`tsc -v`) await shell(`tsc -p test/static/tsconfig.json --noEmit --strict`) } export async function test_runtime(filter = '') { await shell(`hammer build ./test/runtime/index.ts --dist target/test/runtime --platform node`) await shell(`mocha target/test/runtime/index.js -g "${filter}"`) } export async function test(filter = '') { await test_static() await test_runtime(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 clean() await Promise.all([ Build.Package.build(target), Build.Esm.build(target), Build.Cjs.build(target), ]) await folder(target).add('readme.md') await folder(target).add('license') await shell(`cd ${target} && npm pack`) await build_check(target) } // ------------------------------------------------------------------------------- // Build To // ------------------------------------------------------------------------------- export async function build_to(remote = 'target/remote', target = 'target/build') { await clean() await Promise.all([ Build.Package.build(target), Build.Esm.build(target), Build.Cjs.build(target), ]) await folder(target).add('readme.md') await folder(target).add('license') await shell(`cd ${target} && npm pack`) const { version } = JSON.parse(Fs.readFileSync('package.json', 'utf8')) const filename = `${target}/sinclair-typebox-${version}.tgz` await folder(remote).add(filename) } // ------------------------------------------------------------------------------- // 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(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}`) await shell(`git push origin ${version}`) } // ------------------------------------------------------------- // Publish-Dev // ------------------------------------------------------------- export async function publish_dev(otp, target = 'target/build') { 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`) }sinclairzx81-typebox-e0ec98c/license000066400000000000000000000022631505437577000176300ustar00rootroot00000000000000TypeBox Json Schema Type Builder with Static Type Resolution for TypeScript The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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.sinclairzx81-typebox-e0ec98c/package-lock.json000066400000000000000000003641761505437577000215150ustar00rootroot00000000000000{ "name": "@sinclair/typebox", "version": "0.34.41", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox", "version": "0.34.41", "license": "MIT", "devDependencies": { "@arethetypeswrong/cli": "^0.13.2", "@sinclair/hammer": "^0.18.0", "@types/mocha": "^9.1.1", "@types/node": "^22.13.5", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", "mocha": "^11.1.0", "prettier": "^2.7.1", "typescript": "^5.9.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/@arethetypeswrong/core/node_modules/typescript": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=14.17" } }, "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", "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", "cpu": [ "loong64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { "node": ">=12" } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "optional": true, "engines": { "node": ">=14" } }, "node_modules/@sinclair/hammer": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/@sinclair/hammer/-/hammer-0.18.0.tgz", "integrity": "sha512-nIrsOWvvCV/SjTSU4qcOsY3mEO8ErN2WBWzbn6mVpqDajy36lG9WbDEfR6Agm3LbN2pdPl1HGjKuiHpbpOTZ2A==", "dev": true, "dependencies": { "esbuild": "0.15.7" }, "bin": { "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", "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", "dev": true }, "node_modules/@types/node": { "version": "22.13.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", "dev": true, "dependencies": { "undici-types": "~6.20.0" } }, "node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ajv-formats": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "dependencies": { "ajv": "^8.0.0" }, "peerDependencies": { "ajv": "^8.0.0" }, "peerDependenciesMeta": { "ajv": { "optional": true } } }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "engines": { "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", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "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", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "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", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { "node": ">=10" }, "funding": { "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", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chalk/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/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", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { "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": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" }, "engines": { "node": ">=12" } }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "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/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "dependencies": { "ms": "^2.1.3" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" } }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "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", "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" }, "engines": { "node": ">=12" }, "optionalDependencies": { "@esbuild/linux-loong64": "0.15.7", "esbuild-android-64": "0.15.7", "esbuild-android-arm64": "0.15.7", "esbuild-darwin-64": "0.15.7", "esbuild-darwin-arm64": "0.15.7", "esbuild-freebsd-64": "0.15.7", "esbuild-freebsd-arm64": "0.15.7", "esbuild-linux-32": "0.15.7", "esbuild-linux-64": "0.15.7", "esbuild-linux-arm": "0.15.7", "esbuild-linux-arm64": "0.15.7", "esbuild-linux-mips64le": "0.15.7", "esbuild-linux-ppc64le": "0.15.7", "esbuild-linux-riscv64": "0.15.7", "esbuild-linux-s390x": "0.15.7", "esbuild-netbsd-64": "0.15.7", "esbuild-openbsd-64": "0.15.7", "esbuild-sunos-64": "0.15.7", "esbuild-windows-32": "0.15.7", "esbuild-windows-64": "0.15.7", "esbuild-windows-arm64": "0.15.7" } }, "node_modules/esbuild-android-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "android" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-android-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "android" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-darwin-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "darwin" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-darwin-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "darwin" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-freebsd-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "freebsd" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-freebsd-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "freebsd" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-32": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", "cpu": [ "ia32" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-arm": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", "cpu": [ "arm" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-mips64le": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", "cpu": [ "mips64el" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-ppc64le": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", "cpu": [ "ppc64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-riscv64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", "cpu": [ "riscv64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-s390x": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", "cpu": [ "s390x" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-netbsd-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "netbsd" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-openbsd-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "openbsd" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-sunos-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "sunos" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-windows-32": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", "cpu": [ "ia32" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-windows-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-windows-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": ">=12" } }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "engines": { "node": ">=10" }, "funding": { "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.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, "bin": { "flat": "cli.js" } }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" }, "engines": { "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/glob/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { "node": ">=16 || 14 >=14.17" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "bin": { "he": "bin/he" } }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "engines": { "node": ">=0.12.0" } }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, "funding": { "url": "https://github.com/sponsors/isaacs" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "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": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { "node": ">=10" } }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/mocha": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", "dev": true, "dependencies": { "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", "chokidar": "^3.5.3", "debug": "^4.3.5", "diff": "^5.2.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", "minimatch": "^5.1.6", "ms": "^2.1.3", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^6.5.1", "yargs": "^17.7.2", "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha.js" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "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", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "dependencies": { "picomatch": "^2.2.1" }, "engines": { "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", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ] }, "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.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "engines": { "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "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", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "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", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { "is-number": "^7.0.0" }, "engines": { "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.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=14.17" } }, "node_modules/undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "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", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "dependencies": { "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", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/workerpool": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "node_modules/wrap-ansi/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "engines": { "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": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" } }, "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "engines": { "node": ">=12" } }, "node_modules/yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" }, "engines": { "node": ">=10" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } }, "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" }, "dependencies": { "typescript": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz", "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==", "dev": true } } }, "@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", "integrity": "sha512-IKznSJOsVUuyt7cDzzSZyqBEcZe+7WlBqTVXiF1OXP/4Nm387ToaXZ0fyLwI1iBlI/bzpxVq411QE2/Bt2XWWw==", "dev": true, "optional": true }, "@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "requires": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "dependencies": { "ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "requires": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "requires": { "ansi-regex": "^6.0.1" } } } }, "@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "optional": true }, "@sinclair/hammer": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/@sinclair/hammer/-/hammer-0.18.0.tgz", "integrity": "sha512-nIrsOWvvCV/SjTSU4qcOsY3mEO8ErN2WBWzbn6mVpqDajy36lG9WbDEfR6Agm3LbN2pdPl1HGjKuiHpbpOTZ2A==", "dev": true, "requires": { "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", "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", "dev": true }, "@types/node": { "version": "22.13.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", "dev": true, "requires": { "undici-types": "~6.20.0" } }, "ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, "ajv-formats": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "requires": { "ajv": "^8.0.0" } }, "ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "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", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { "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", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "requires": { "balanced-match": "^1.0.0" } }, "braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { "fill-range": "^7.1.1" } }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "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", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.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" } } } }, "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", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", "fsevents": "~2.3.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "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": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" }, "dependencies": { "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } } } }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { "color-name": "~1.1.4" } }, "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "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 }, "cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, "requires": { "ms": "^2.1.3" } }, "decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true }, "diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true }, "eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "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", "integrity": "sha512-7V8tzllIbAQV1M4QoE52ImKu8hT/NLGlGXkiDsbEU5PS6K8Mn09ZnYoS+dcmHxOS9CRsV4IRAMdT3I67IyUNXw==", "dev": true, "requires": { "@esbuild/linux-loong64": "0.15.7", "esbuild-android-64": "0.15.7", "esbuild-android-arm64": "0.15.7", "esbuild-darwin-64": "0.15.7", "esbuild-darwin-arm64": "0.15.7", "esbuild-freebsd-64": "0.15.7", "esbuild-freebsd-arm64": "0.15.7", "esbuild-linux-32": "0.15.7", "esbuild-linux-64": "0.15.7", "esbuild-linux-arm": "0.15.7", "esbuild-linux-arm64": "0.15.7", "esbuild-linux-mips64le": "0.15.7", "esbuild-linux-ppc64le": "0.15.7", "esbuild-linux-riscv64": "0.15.7", "esbuild-linux-s390x": "0.15.7", "esbuild-netbsd-64": "0.15.7", "esbuild-openbsd-64": "0.15.7", "esbuild-sunos-64": "0.15.7", "esbuild-windows-32": "0.15.7", "esbuild-windows-64": "0.15.7", "esbuild-windows-arm64": "0.15.7" } }, "esbuild-android-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.7.tgz", "integrity": "sha512-p7rCvdsldhxQr3YHxptf1Jcd86dlhvc3EQmQJaZzzuAxefO9PvcI0GLOa5nCWem1AJ8iMRu9w0r5TG8pHmbi9w==", "dev": true, "optional": true }, "esbuild-android-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.7.tgz", "integrity": "sha512-L775l9ynJT7rVqRM5vo+9w5g2ysbOCfsdLV4CWanTZ1k/9Jb3IYlQ06VCI1edhcosTYJRECQFJa3eAvkx72eyQ==", "dev": true, "optional": true }, "esbuild-darwin-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.7.tgz", "integrity": "sha512-KGPt3r1c9ww009t2xLB6Vk0YyNOXh7hbjZ3EecHoVDxgtbUlYstMPDaReimKe6eOEfyY4hBEEeTvKwPsiH5WZg==", "dev": true, "optional": true }, "esbuild-darwin-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.7.tgz", "integrity": "sha512-kBIHvtVqbSGajN88lYMnR3aIleH3ABZLLFLxwL2stiuIGAjGlQW741NxVTpUHQXUmPzxi6POqc9npkXa8AcSZQ==", "dev": true, "optional": true }, "esbuild-freebsd-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.7.tgz", "integrity": "sha512-hESZB91qDLV5MEwNxzMxPfbjAhOmtfsr9Wnuci7pY6TtEh4UDuevmGmkUIjX/b+e/k4tcNBMf7SRQ2mdNuK/HQ==", "dev": true, "optional": true }, "esbuild-freebsd-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.7.tgz", "integrity": "sha512-dLFR0ChH5t+b3J8w0fVKGvtwSLWCv7GYT2Y2jFGulF1L5HftQLzVGN+6pi1SivuiVSmTh28FwUhi9PwQicXI6Q==", "dev": true, "optional": true }, "esbuild-linux-32": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.7.tgz", "integrity": "sha512-v3gT/LsONGUZcjbt2swrMjwxo32NJzk+7sAgtxhGx1+ZmOFaTRXBAi1PPfgpeo/J//Un2jIKm/I+qqeo4caJvg==", "dev": true, "optional": true }, "esbuild-linux-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.7.tgz", "integrity": "sha512-LxXEfLAKwOVmm1yecpMmWERBshl+Kv5YJ/1KnyAr6HRHFW8cxOEsEfisD3sVl/RvHyW//lhYUVSuy9jGEfIRAQ==", "dev": true, "optional": true }, "esbuild-linux-arm": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.7.tgz", "integrity": "sha512-JKgAHtMR5f75wJTeuNQbyznZZa+pjiUHV7sRZp42UNdyXC6TiUYMW/8z8yIBAr2Fpad8hM1royZKQisqPABPvQ==", "dev": true, "optional": true }, "esbuild-linux-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.7.tgz", "integrity": "sha512-P3cfhudpzWDkglutWgXcT2S7Ft7o2e3YDMrP1n0z2dlbUZghUkKCyaWw0zhp4KxEEzt/E7lmrtRu/pGWnwb9vw==", "dev": true, "optional": true }, "esbuild-linux-mips64le": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.7.tgz", "integrity": "sha512-T7XKuxl0VpeFLCJXub6U+iybiqh0kM/bWOTb4qcPyDDwNVhLUiPcGdG2/0S7F93czUZOKP57YiLV8YQewgLHKw==", "dev": true, "optional": true }, "esbuild-linux-ppc64le": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.7.tgz", "integrity": "sha512-6mGuC19WpFN7NYbecMIJjeQgvDb5aMuvyk0PDYBJrqAEMkTwg3Z98kEKuCm6THHRnrgsdr7bp4SruSAxEM4eJw==", "dev": true, "optional": true }, "esbuild-linux-riscv64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.7.tgz", "integrity": "sha512-uUJsezbswAYo/X7OU/P+PuL/EI9WzxsEQXDekfwpQ23uGiooxqoLFAPmXPcRAt941vjlY9jtITEEikWMBr+F/g==", "dev": true, "optional": true }, "esbuild-linux-s390x": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.7.tgz", "integrity": "sha512-+tO+xOyTNMc34rXlSxK7aCwJgvQyffqEM5MMdNDEeMU3ss0S6wKvbBOQfgd5jRPblfwJ6b+bKiz0g5nABpY0QQ==", "dev": true, "optional": true }, "esbuild-netbsd-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.7.tgz", "integrity": "sha512-yVc4Wz+Pu3cP5hzm5kIygNPrjar/v5WCSoRmIjCPWfBVJkZNb5brEGKUlf+0Y759D48BCWa0WHrWXaNy0DULTQ==", "dev": true, "optional": true }, "esbuild-openbsd-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.7.tgz", "integrity": "sha512-GsimbwC4FSR4lN3wf8XmTQ+r8/0YSQo21rWDL0XFFhLHKlzEA4SsT1Tl8bPYu00IU6UWSJ+b3fG/8SB69rcuEQ==", "dev": true, "optional": true }, "esbuild-sunos-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.7.tgz", "integrity": "sha512-8CDI1aL/ts0mDGbWzjEOGKXnU7p3rDzggHSBtVryQzkSOsjCHRVe0iFYUuhczlxU1R3LN/E7HgUO4NXzGGP/Ag==", "dev": true, "optional": true }, "esbuild-windows-32": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.7.tgz", "integrity": "sha512-cOnKXUEPS8EGCzRSFa1x6NQjGhGsFlVgjhqGEbLTPsA7x4RRYiy2RKoArNUU4iR2vHmzqS5Gr84MEumO/wxYKA==", "dev": true, "optional": true }, "esbuild-windows-64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.7.tgz", "integrity": "sha512-7MI08Ec2sTIDv+zH6StNBKO+2hGUYIT42GmFyW6MBBWWtJhTcQLinKS6ldIN1d52MXIbiJ6nXyCJ+LpL4jBm3Q==", "dev": true, "optional": true }, "esbuild-windows-arm64": { "version": "0.15.7", "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.7.tgz", "integrity": "sha512-R06nmqBlWjKHddhRJYlqDd3Fabx9LFdKcjoOy08YLimwmsswlFBJV4rXzZCxz/b7ZJXvrZgj8DDv1ewE9+StMw==", "dev": true, "optional": true }, "escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "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.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" } }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, "foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, "requires": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" } }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "optional": true }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "requires": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "dependencies": { "minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } } } }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "requires": { "is-glob": "^4.0.1" } }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { "binary-extensions": "^2.0.0" } }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "requires": { "is-extglob": "^2.1.1" } }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, "is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, "jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "requires": { "@isaacs/cliui": "^8.0.2", "@pkgjs/parseargs": "^0.11.0" } }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" } }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { "p-locate": "^5.0.0" } }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { "chalk": "^4.1.0", "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": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "requires": { "brace-expansion": "^2.0.1" } }, "minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true }, "mocha": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", "dev": true, "requires": { "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", "chokidar": "^3.5.3", "debug": "^4.3.5", "diff": "^5.2.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", "minimatch": "^5.1.6", "ms": "^2.1.3", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^6.5.1", "yargs": "^17.7.2", "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" } }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "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", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "requires": { "yocto-queue": "^0.1.0" } }, "p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { "p-limit": "^3.0.2" } }, "package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "requires": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "dependencies": { "lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true } } }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, "prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true }, "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" } }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "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", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "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.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "requires": { "randombytes": "^2.1.0" } }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { "shebang-regex": "^3.0.0" } }, "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true }, "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", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "string-width-cjs": { "version": "npm:string-width@4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { "ansi-regex": "^5.0.1" } }, "strip-ansi-cjs": { "version": "npm:strip-ansi@6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { "ansi-regex": "^5.0.1" } }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { "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", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { "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.9.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true }, "undici-types": { "version": "6.20.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", "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", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "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", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { "isexe": "^2.0.0" } }, "workerpool": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, "wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "requires": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" }, "dependencies": { "ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true }, "ansi-styles": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, "string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "requires": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "requires": { "ansi-regex": "^6.0.1" } } } }, "wrap-ansi-cjs": { "version": "npm:wrap-ansi@7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "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": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true }, "yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" } }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true } } } sinclairzx81-typebox-e0ec98c/package.json000066400000000000000000000023101505437577000205420ustar00rootroot00000000000000{ "name": "@sinclair/typebox", "version": "0.34.41", "description": "Json Schema Type Builder with Static Type Resolution for TypeScript", "keywords": [ "typescript", "json-schema", "validate", "typecheck" ], "author": "sinclairzx81", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/sinclairzx81/typebox" }, "scripts": { "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:to": "hammer task build_to", "build": "hammer task build", "test": "hammer task test", "clean": "hammer task clean", "format": "hammer task format", "start": "hammer task start", "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": "^22.13.5", "ajv": "^8.12.0", "ajv-formats": "^2.1.1", "mocha": "^11.1.0", "prettier": "^2.7.1", "typescript": "^5.9.2" } } sinclairzx81-typebox-e0ec98c/readme.md000066400000000000000000003642361505437577000200550ustar00rootroot00000000000000

TypeBox

Json Schema Type Builder with Static Type Resolution for TypeScript



[![npm version](https://badge.fury.io/js/%40sinclair%2Ftypebox.svg)](https://badge.fury.io/js/%40sinclair%2Ftypebox) [![Downloads](https://img.shields.io/npm/dm/%40sinclair%2Ftypebox.svg)](https://www.npmjs.com/package/%40sinclair%2Ftypebox) [![Build](https://github.com/sinclairzx81/typebox/actions/workflows/build.yml/badge.svg)](https://github.com/sinclairzx81/typebox/actions/workflows/build.yml) [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
## Install ```bash $ npm install @sinclair/typebox --save ``` ## Example ```typescript import { Type, type Static } from '@sinclair/typebox' const T = Type.Object({ // const T = { x: Type.Number(), // type: 'object', y: Type.Number(), // required: ['x', 'y', 'z'], z: Type.Number() // properties: { }) // x: { type: 'number' }, // y: { type: 'number' }, // z: { type: 'number' } // } // } type T = Static // type T = { // x: number, // y: number, // z: number // } ``` ## Overview TypeBox is a runtime type builder that creates in-memory Json Schema objects that infer as TypeScript types. The schematics produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox offers a unified type that can be statically checked by TypeScript and runtime asserted using standard Json Schema validation. This library is designed to allow Json Schema to compose similar to how types compose within TypeScript's type system. It can be used as a simple tool to build up complex schematics or integrated into REST and RPC services to help validate data received over the wire. License MIT ## Contents - [Install](#install) - [Overview](#overview) - [Usage](#usage) - [Types](#types) - [Json](#types-json) - [JavaScript](#types-javascript) - [Options](#types-options) - [Properties](#types-properties) - [Generics](#types-generics) - [Recursive](#types-recursive) - [Modules](#types-modules) - [Template Literal](#types-template-literal) - [Indexed](#types-indexed) - [Mapped](#types-mapped) - [Conditional](#types-conditional) - [Transform](#types-transform) - [Guard](#types-guard) - [Unsafe](#types-unsafe) - [Values](#values) - [Assert](#values-assert) - [Create](#values-create) - [Clone](#values-clone) - [Check](#values-check) - [Convert](#values-convert) - [Default](#values-default) - [Clean](#values-clean) - [Cast](#values-cast) - [Decode](#values-decode) - [Encode](#values-decode) - [Parse](#values-parse) - [Equal](#values-equal) - [Hash](#values-hash) - [Diff](#values-diff) - [Patch](#values-patch) - [Errors](#values-errors) - [Mutate](#values-mutate) - [Pointer](#values-pointer) - [Syntax](#syntax) - [Create](#syntax-create) - [Parameters](#syntax-parameters) - [Generics](#syntax-generics) - [Options](#syntax-options) - [NoInfer](#syntax-no-infer) - [TypeRegistry](#typeregistry) - [Type](#typeregistry-type) - [Format](#typeregistry-format) - [TypeCheck](#typecheck) - [Ajv](#typecheck-ajv) - [TypeCompiler](#typecheck-typecompiler) - [TypeMap](#typemap) - [Usage](#typemap-usage) - [TypeSystem](#typesystem) - [Policies](#typesystem-policies) - [Error Function](#error-function) - [Workbench](#workbench) - [Codegen](#codegen) - [Ecosystem](#ecosystem) - [Benchmark](#benchmark) - [Compile](#benchmark-compile) - [Validate](#benchmark-validate) - [Compression](#benchmark-compression) - [Contribute](#contribute) ## Usage The following shows general usage. ```typescript import { Type, type Static } from '@sinclair/typebox' //-------------------------------------------------------------------------------------------- // // Let's say you have the following type ... // //-------------------------------------------------------------------------------------------- type T = { id: string, name: string, timestamp: number } //-------------------------------------------------------------------------------------------- // // ... you can express this type in the following way. // //-------------------------------------------------------------------------------------------- const T = Type.Object({ // const T = { id: Type.String(), // type: 'object', name: Type.String(), // properties: { timestamp: Type.Integer() // id: { }) // type: 'string' // }, // name: { // type: 'string' // }, // timestamp: { // type: 'integer' // } // }, // required: [ // 'id', // 'name', // 'timestamp' // ] // } //-------------------------------------------------------------------------------------------- // // ... then infer back to the original static type this way. // //-------------------------------------------------------------------------------------------- type T = Static // type T = { // id: string, // name: string, // timestamp: number // } //-------------------------------------------------------------------------------------------- // // ... or use the type to parse JavaScript values. // //-------------------------------------------------------------------------------------------- import { Value } from '@sinclair/typebox/value' const R = Value.Parse(T, value) // const R: { // id: string, // name: string, // timestamp: number // } ``` ## Types TypeBox types are Json Schema fragments that compose into more complex types. Each fragment is structured such that any Json Schema compliant validator can runtime assert a value the same way TypeScript will statically assert a type. TypeBox offers a set of Json Types which are used to create Json Schema compliant schematics as well as a JavaScript type set used to create schematics for constructs native to JavaScript. ### Json Types The following table lists the supported Json types. These types are fully compatible with the Json Schema Draft 7 specification. ```typescript ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐ │ TypeBox │ TypeScript │ Json Schema │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Any() │ type T = any │ const T = { } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Unknown() │ type T = unknown │ const T = { } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.String() │ type T = string │ const T = { │ │ │ │ type: 'string' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Number() │ type T = number │ const T = { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Integer() │ type T = number │ const T = { │ │ │ │ type: 'integer' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Boolean() │ type T = boolean │ const T = { │ │ │ │ type: 'boolean' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Null() │ type T = null │ const T = { │ │ │ │ type: 'null' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Literal(42) │ type T = 42 │ const T = { │ │ │ │ const: 42, │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Array( │ type T = number[] │ const T = { │ │ Type.Number() │ │ type: 'array', │ │ ) │ │ items: { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Object({ │ type T = { │ const T = { │ │ x: Type.Number(), │ x: number, │ type: 'object', │ │ y: Type.Number() │ y: number │ required: ['x', 'y'], │ │ }) │ } │ properties: { │ │ │ │ x: { │ │ │ │ type: 'number' │ │ │ │ }, │ │ │ │ y: { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Tuple([ │ type T = [number, number] │ const T = { │ │ Type.Number(), │ │ type: 'array', │ │ Type.Number() │ │ items: [{ │ │ ]) │ │ type: 'number' │ │ │ │ }, { │ │ │ │ type: 'number' │ │ │ │ }], │ │ │ │ additionalItems: false, │ │ │ │ minItems: 2, │ │ │ │ maxItems: 2 │ │ │ │ } │ │ │ │ │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ enum Foo { │ enum Foo { │ const T = { │ │ A, │ A, │ anyOf: [{ │ │ B │ B │ type: 'number', │ │ } │ } │ const: 0 │ │ │ │ }, { │ │ const T = Type.Enum(Foo) │ type T = Foo │ type: 'number', │ │ │ │ const: 1 │ │ │ │ }] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Const({ │ type T = { │ const T = { │ │ x: 1, │ readonly x: 1, │ type: 'object', │ │ y: 2, │ readonly y: 2 │ required: ['x', 'y'], │ │ } as const) │ } │ properties: { │ │ │ │ x: { │ │ │ │ type: 'number', │ │ │ │ const: 1 │ │ │ │ }, │ │ │ │ y: { │ │ │ │ type: 'number', │ │ │ │ const: 2 │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.KeyOf( │ type T = keyof { │ const T = { │ │ Type.Object({ │ x: number, │ anyOf: [{ │ │ x: Type.Number(), │ y: number │ type: 'string', │ │ y: Type.Number() │ } │ const: 'x' │ │ }) │ │ }, { │ │ ) │ │ type: 'string', │ │ │ │ const: 'y' │ │ │ │ }] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Union([ │ type T = string | number │ const T = { │ │ Type.String(), │ │ anyOf: [{ │ │ Type.Number() │ │ type: 'string' │ │ ]) │ │ }, { │ │ │ │ type: 'number' │ │ │ │ }] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Intersect([ │ type T = { │ const T = { │ │ Type.Object({ │ x: number │ allOf: [{ │ │ x: Type.Number() │ } & { │ type: 'object', │ │ }), │ y: number │ required: ['x'], │ │ Type.Object({ │ } │ properties: { │ │ y: Type.Number() │ │ x: { │ │ }) │ │ type: 'number' │ │ ]) │ │ } │ │ │ │ } │ │ │ │ }, { │ │ │ │ type: 'object', | │ │ │ required: ['y'], │ │ │ │ properties: { │ │ │ │ y: { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ }] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Composite([ │ type T = { │ const T = { │ │ Type.Object({ │ x: number, │ type: 'object', │ │ x: Type.Number() │ y: number │ required: ['x', 'y'], │ │ }), │ } │ properties: { │ │ Type.Object({ │ │ x: { │ │ y: Type.Number() │ │ type: 'number' │ │ }) │ │ }, │ │ ]) │ │ y: { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Never() │ type T = never │ const T = { │ │ │ │ not: {} │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Not( | type T = unknown │ const T = { │ │ Type.String() │ │ not: { │ │ ) │ │ type: 'string' │ │ │ │ } │ │ │ │ } │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Extends( │ type T = │ const T = { │ │ Type.String(), │ string extends number │ const: false, │ │ Type.Number(), │ ? true │ type: 'boolean' │ │ Type.Literal(true), │ : false │ } │ │ Type.Literal(false) │ │ │ │ ) │ │ │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Extract( │ type T = Extract< │ const T = { │ │ Type.Union([ │ string | number, │ type: 'string' │ │ Type.String(), │ string │ } │ │ Type.Number(), │ > │ │ │ ]), │ │ │ │ Type.String() │ │ │ │ ) │ │ │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Exclude( │ type T = Exclude< │ const T = { │ │ Type.Union([ │ string | number, │ type: 'number' │ │ Type.String(), │ string │ } │ │ Type.Number(), │ > │ │ │ ]), │ │ │ │ Type.String() │ │ │ │ ) │ │ │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Mapped( │ type T = { │ const T = { │ │ Type.Union([ │ [_ in 'x' | 'y'] : number │ type: 'object', │ │ Type.Literal('x'), │ } │ required: ['x', 'y'], │ │ Type.Literal('y') │ │ properties: { │ │ ]), │ │ x: { │ │ () => Type.Number() │ │ type: 'number' │ │ ) │ │ }, │ │ │ │ y: { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const U = Type.Union([ │ type U = 'open' | 'close' │ const T = { │ │ Type.Literal('open'), │ │ type: 'string', │ │ Type.Literal('close') │ type T = `on${U}` │ pattern: '^on(open|close)$' │ │ ]) │ │ } │ │ │ │ │ │ const T = Type │ │ │ │ .TemplateLiteral([ │ │ │ │ Type.Literal('on'), │ │ │ │ U │ │ │ │ ]) │ │ │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Record( │ type T = Record< │ const T = { │ │ Type.String(), │ string, │ type: 'object', │ │ Type.Number() │ number │ patternProperties: { │ │ ) │ > │ '^.*$': { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Partial( │ type T = Partial<{ │ const T = { │ │ Type.Object({ │ x: number, │ type: 'object', │ │ x: Type.Number(), │ y: number │ properties: { │ │ y: Type.Number() | }> │ x: { │ │ }) │ │ type: 'number' │ │ ) │ │ }, │ │ │ │ y: { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Required( │ type T = Required<{ │ const T = { │ │ Type.Object({ │ x?: number, │ type: 'object', │ │ x: Type.Optional( │ y?: number │ required: ['x', 'y'], │ │ Type.Number() | }> │ properties: { │ │ ), │ │ x: { │ │ y: Type.Optional( │ │ type: 'number' │ │ Type.Number() │ │ }, │ │ ) │ │ y: { │ │ }) │ │ type: 'number' │ │ ) │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Pick( │ type T = Pick<{ │ const T = { │ │ Type.Object({ │ x: number, │ type: 'object', │ │ x: Type.Number(), │ y: number │ required: ['x'], │ │ y: Type.Number() │ }, 'x'> │ properties: { │ │ }), ['x'] | │ x: { │ │ ) │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Omit( │ type T = Omit<{ │ const T = { │ │ Type.Object({ │ x: number, │ type: 'object', │ │ x: Type.Number(), │ y: number │ required: ['y'], │ │ y: Type.Number() │ }, 'x'> │ properties: { │ │ }), ['x'] | │ y: { │ │ ) │ │ type: 'number' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Index( │ type T = { │ const T = { │ │ Type.Object({ │ x: number, │ type: 'number' │ │ x: Type.Number(), │ y: string │ } │ │ y: Type.String() │ }['x'] │ │ │ }), ['x'] │ │ │ │ ) │ │ │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const A = Type.Tuple([ │ type A = [0, 1] │ const T = { │ │ Type.Literal(0), │ type B = [2, 3] │ type: 'array', │ │ Type.Literal(1) │ type T = [ │ items: [ │ │ ]) │ ...A, │ { const: 0 }, │ │ const B = Type.Tuple([ │ ...B │ { const: 1 }, │ | Type.Literal(2), │ ] │ { const: 2 }, │ | Type.Literal(3) │ │ { const: 3 } │ │ ]) │ │ ], │ │ const T = Type.Tuple([ │ │ additionalItems: false, │ | ...Type.Rest(A), │ │ minItems: 4, │ | ...Type.Rest(B) │ │ maxItems: 4 │ │ ]) │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Uncapitalize( │ type T = Uncapitalize< │ const T = { │ │ Type.Literal('Hello') │ 'Hello' │ type: 'string', │ │ ) │ > │ const: 'hello' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Capitalize( │ type T = Capitalize< │ const T = { │ │ Type.Literal('hello') │ 'hello' │ type: 'string', │ │ ) │ > │ const: 'Hello' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Uppercase( │ type T = Uppercase< │ const T = { │ │ Type.Literal('hello') │ 'hello' │ type: 'string', │ │ ) │ > │ const: 'HELLO' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Lowercase( │ type T = Lowercase< │ const T = { │ │ Type.Literal('HELLO') │ 'HELLO' │ type: 'string', │ │ ) │ > │ const: 'hello' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const R = Type.Ref('T') │ type R = unknown │ const R = { $ref: 'T' } │ │ │ │ │ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘ ``` ### JavaScript Types TypeBox provides an extended type set that can be used to create schematics for common JavaScript constructs. These types can not be used with any standard Json Schema validator; but can be used to frame schematics for interfaces that may receive Json validated data. JavaScript types are prefixed with the `[JavaScript]` JSDoc comment for convenience. The following table lists the supported types. ```typescript ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐ │ TypeBox │ TypeScript │ Extended Schema │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Constructor([ │ type T = new ( │ const T = { │ │ Type.String(), │ arg0: string, │ type: 'Constructor', │ │ Type.Number() │ arg0: number │ parameters: [{ │ │ ], Type.Boolean()) │ ) => boolean │ type: 'string' │ │ │ │ }, { │ │ │ │ type: 'number' │ │ │ │ }], │ │ │ │ returns: { │ │ │ │ type: 'boolean' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Function([ │ type T = ( │ const T = { │ | Type.String(), │ arg0: string, │ type: 'Function', │ │ Type.Number() │ arg1: number │ parameters: [{ │ │ ], Type.Boolean()) │ ) => boolean │ type: 'string' │ │ │ │ }, { │ │ │ │ type: 'number' │ │ │ │ }], │ │ │ │ returns: { │ │ │ │ type: 'boolean' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Promise( │ type T = Promise │ const T = { │ │ Type.String() │ │ type: 'Promise', │ │ ) │ │ item: { │ │ │ │ type: 'string' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = │ type T = │ const T = { │ │ Type.AsyncIterator( │ AsyncIterableIterator< │ type: 'AsyncIterator', │ │ Type.String() │ string │ items: { │ │ ) │ > │ type: 'string' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Iterator( │ type T = │ const T = { │ │ Type.String() │ IterableIterator │ type: 'Iterator', │ │ ) │ │ items: { │ │ │ │ type: 'string' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.RegExp(/abc/i) │ type T = string │ const T = { │ │ │ │ type: 'RegExp' │ │ │ │ source: 'abc' │ │ │ │ flags: 'i' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Uint8Array() │ type T = Uint8Array │ const T = { │ │ │ │ type: 'Uint8Array' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Date() │ type T = Date │ const T = { │ │ │ │ type: 'Date' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Undefined() │ type T = undefined │ const T = { │ │ │ │ type: 'undefined' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Symbol() │ type T = symbol │ const T = { │ │ │ │ type: 'symbol' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.BigInt() │ type T = bigint │ const T = { │ │ │ │ type: 'bigint' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Void() │ type T = void │ const T = { │ │ │ │ type: 'void' │ │ │ │ } │ │ │ │ │ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘ ``` ### Options You can pass Json Schema options on the last argument of any given type. Option hints specific to each type are provided for convenience. ```typescript // String must be an email const T = Type.String({ // const T = { format: 'email' // type: 'string', }) // format: 'email' // } // Number must be a multiple of 2 const T = Type.Number({ // const T = { multipleOf: 2 // type: 'number', }) // multipleOf: 2 // } // Array must have at least 5 integer values const T = Type.Array(Type.Integer(), { // const T = { minItems: 5 // type: 'array', }) // minItems: 5, // items: { // type: 'integer' // } // } ``` ### Properties Object properties can be modified with Readonly and Optional. The following table shows how these modifiers map between TypeScript and Json Schema. ```typescript ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐ │ TypeBox │ TypeScript │ Json Schema │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Object({ │ type T = { │ const T = { │ │ name: Type.ReadonlyOptional( │ readonly name?: string │ type: 'object', │ │ Type.String() │ } │ properties: { │ │ ) │ │ name: { │ │ }) │ │ type: 'string' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Object({ │ type T = { │ const T = { │ │ name: Type.Readonly( │ readonly name: string │ type: 'object', │ │ Type.String() │ } │ properties: { │ │ ) │ │ name: { │ │ }) │ │ type: 'string' │ │ │ │ } │ │ │ │ }, │ │ │ │ required: ['name'] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Object({ │ type T = { │ const T = { │ │ name: Type.Optional( │ name?: string │ type: 'object', │ │ Type.String() │ } │ properties: { │ │ ) │ │ name: { │ │ }) │ │ type: 'string' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘ ``` ### Generic Types Generic types can be created with generic functions. ```typescript const Nullable = (T: T) => { // type Nullable = T | null return Type.Union([T, Type.Null()]) } const T = Nullable(Type.String()) // type T = Nullable ``` ### Recursive Types Use the Recursive function to create recursive types. ```typescript const Node = Type.Recursive(This => Type.Object({ // const Node = { id: Type.String(), // $id: 'Node', nodes: Type.Array(This) // type: 'object', }), { $id: 'Node' }) // properties: { // id: { // type: 'string' // }, // nodes: { // type: 'array', // items: { // $ref: 'Node' // } // } // }, // required: [ // 'id', // 'nodes' // ] // } type Node = Static // type Node = { // id: string // nodes: Node[] // } function test(node: Node) { const id = node.nodes[0].nodes[0].id // id is string } ``` ### Module Types Module types are containers for a set of referential types. Modules act as namespaces, enabling types to reference one another via string identifiers. Modules support both singular and mutually recursive references, as well as deferred dereferencing for computed types such as Partial. Types imported from a module are expressed using the Json Schema `$defs` keyword. ```typescript const Module = Type.Module({ PartialUser: Type.Partial(Type.Ref('User')), // TComputed<'Partial', [TRef<'User'>]> User: Type.Object({ // TObject<{ id: Type.String(), // user: TString, name: Type.String(), // name: TString, email: Type.String() // email: TString }), // }> }) const User = Module.Import('User') // const User: TImport<{...}, 'User'> type User = Static // type User = { // id: string, // name: string, // email: string // } const PartialUser = Module.Import('PartialUser') // const PartialUser: TImport<{...}, 'PartialUser'> type PartialUser = Static // type PartialUser = { // id?: string, // name?: string, // email?: string // } ``` ### Template Literal Types TypeBox supports template literal types with the TemplateLiteral function. This type can be created using a syntax similar to the TypeScript template literal syntax or composed from exterior types. TypeBox encodes template literals as regular expressions which enables the template to be checked by Json Schema validators. This type also supports regular expression parsing that enables template patterns to be used for generative types. The following shows both TypeScript and TypeBox usage. ```typescript // TypeScript type K = `prop${'A'|'B'|'C'}` // type T = 'propA' | 'propB' | 'propC' type R = Record // type R = { // propA: string // propB: string // propC: string // } // TypeBox const K = Type.TemplateLiteral('prop${A|B|C}') // const K: TTemplateLiteral<[ // TLiteral<'prop'>, // TUnion<[ // TLiteral<'A'>, // TLiteral<'B'>, // TLiteral<'C'>, // ]> // ]> const R = Type.Record(K, Type.String()) // const R: TObject<{ // propA: TString, // propB: TString, // propC: TString, // }> ``` ### Indexed Access Types TypeBox supports indexed access types with the Index function. This function enables uniform access to interior property and element types without having to extract them from the underlying schema representation. Index types are supported for Object, Array, Tuple, Union and Intersect types. ```typescript const T = Type.Object({ // type T = { x: Type.Number(), // x: number, y: Type.String(), // y: string, z: Type.Boolean() // z: boolean }) // } const A = Type.Index(T, ['x']) // type A = T['x'] // // ... evaluated as // // const A: TNumber const B = Type.Index(T, ['x', 'y']) // type B = T['x' | 'y'] // // ... evaluated as // // const B: TUnion<[ // TNumber, // TString, // ]> const C = Type.Index(T, Type.KeyOf(T)) // type C = T[keyof T] // // ... evaluated as // // const C: TUnion<[ // TNumber, // TString, // TBoolean // ]> ``` ### Mapped Types TypeBox supports mapped types with the Mapped function. This function accepts two arguments, the first is a union type typically derived from KeyOf, the second is a mapping function that receives a mapping key `K` that can be used to index properties of a type. The following implements a mapped type that remaps each property to be `T | null`. ```typescript const T = Type.Object({ // type T = { x: Type.Number(), // x: number, y: Type.String(), // y: string, z: Type.Boolean() // z: boolean }) // } const M = Type.Mapped(Type.KeyOf(T), K => { // type M = { [K in keyof T]: T[K] | null } return Type.Union([Type.Index(T, K), Type.Null()]) // }) // ... evaluated as // // const M: TObject<{ // x: TUnion<[TNumber, TNull]>, // y: TUnion<[TString, TNull]>, // z: TUnion<[TBoolean, TNull]> // }> ``` ### Conditional Types TypeBox supports runtime conditional types with the Extends function. This function performs a structural assignability check against the first (`left`) and second (`right`) arguments and will return either the third (`true`) or fourth (`false`) argument based on the result. The conditional types Exclude and Extract are also supported. The following shows both TypeScript and TypeBox examples of conditional types. ```typescript // Extends const A = Type.Extends( // type A = string extends number ? 1 : 2 Type.String(), // Type.Number(), // ... evaluated as Type.Literal(1), // Type.Literal(2) // const A: TLiteral<2> ) // Extract const B = Type.Extract( // type B = Extract<1 | 2 | 3, 1> Type.Union([ // Type.Literal(1), // ... evaluated as Type.Literal(2), // Type.Literal(3) // const B: TLiteral<1> ]), Type.Literal(1) ) // Exclude const C = Type.Exclude( // type C = Exclude<1 | 2 | 3, 1> Type.Union([ // Type.Literal(1), // ... evaluated as Type.Literal(2), // Type.Literal(3) // const C: TUnion<[ ]), // TLiteral<2>, Type.Literal(1) // TLiteral<3>, ) // ]> ``` ### Transform Types TypeBox supports value decoding and encoding with Transform types. These types work in tandem with the Encode and Decode functions available on the Value and TypeCompiler submodules. Transform types can be used to convert Json encoded values into constructs more natural to JavaScript. The following creates a Transform type to decode numbers into Dates using the Value submodule. ```typescript import { Value } from '@sinclair/typebox/value' const T = Type.Transform(Type.Number()) .Decode(value => new Date(value)) // decode: number to Date .Encode(value => value.getTime()) // encode: Date to number const D = Value.Decode(T, 0) // const D = Date(1970-01-01T00:00:00.000Z) const E = Value.Encode(T, D) // const E = 0 ``` Use the StaticEncode or StaticDecode types to infer a Transform type. ```typescript import { Static, StaticDecode, StaticEncode } from '@sinclair/typebox' const T = Type.Transform(Type.Array(Type.Number(), { uniqueItems: true })) .Decode(value => new Set(value)) .Encode(value => [...value]) type D = StaticDecode // type D = Set type E = StaticEncode // type E = Array type T = Static // type T = Array ``` ### Unsafe Types TypeBox supports user defined types with Unsafe. This type allows you to specify both schema representation and inference type. The following creates an Unsafe type with a number schema that infers as string. ```typescript const T = Type.Unsafe({ type: 'number' }) // const T = { type: 'number' } type T = Static // type T = string - ? ``` The Unsafe type is often used to create schematics for extended specifications like OpenAPI. ```typescript const Nullable = (schema: T) => Type.Unsafe | null>({ ...schema, nullable: true }) const T = Nullable(Type.String()) // const T = { // type: 'string', // nullable: true // } type T = Static // type T = string | null const StringEnum = (values: [...T]) => Type.Unsafe({ type: 'string', enum: values }) const S = StringEnum(['A', 'B', 'C']) // const S = { // enum: ['A', 'B', 'C'] // } type S = Static // type S = 'A' | 'B' | 'C' ``` ### TypeGuard TypeBox can check its own types with the TypeGuard module. This module is written for type introspection and provides structural tests for every built-in TypeBox type. Functions of this module return `is` guards which can be used with control flow assertions to obtain schema inference for unknown values. The following guards that the value `T` is TString. ```typescript import { TypeGuard, Kind } from '@sinclair/typebox' const T = { [Kind]: 'String', type: 'string' } if(TypeGuard.IsString(T)) { // T is TString } ``` ## Values TypeBox provides an optional Value submodule that can be used to perform structural operations on JavaScript values. This submodule includes functionality to create, check and cast values from types as well as check equality, clone, diff and patch JavaScript values. This submodule is provided via optional import. ```typescript import { Value } from '@sinclair/typebox/value' ``` ### Assert Use the Assert function to assert a value is valid. ```typescript let value: unknown = 1 Value.Assert(Type.Number(), value) // throws AssertError if invalid ``` ### Create Use the Create function to create a value from a type. TypeBox will use default values if specified. ```typescript const T = Type.Object({ x: Type.Number(), y: Type.Number({ default: 42 }) }) const A = Value.Create(T) // const A = { x: 0, y: 42 } ``` ### Clone Use the Clone function to deeply clone a value. ```typescript const A = Value.Clone({ x: 1, y: 2, z: 3 }) // const A = { x: 1, y: 2, z: 3 } ``` ### Check Use the Check function to type check a value. ```typescript const T = Type.Object({ x: Type.Number() }) const R = Value.Check(T, { x: 1 }) // const R = true ``` ### Convert Use the Convert function to convert a value into its target type if a reasonable conversion is possible. This function may return an invalid value and should be checked before use. Its return type is `unknown`. ```typescript const T = Type.Object({ x: Type.Number() }) const R1 = Value.Convert(T, { x: '3.14' }) // const R1 = { x: 3.14 } const R2 = Value.Convert(T, { x: 'not a number' }) // const R2 = { x: 'not a number' } ``` ### Clean Use Clean to remove excess properties from a value. This function does not check the value and returns an unknown type. You should Check the result before use. Clean is a mutable operation. To avoid mutation, Clone the value first. ```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 } ``` ### Default Use Default to generate missing properties on a value using default schema annotations if available. This function does not check the value and returns an unknown type. You should Check the result before use. Default is a mutable operation. To avoid mutation, Clone the value first. ```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 } ``` ### Cast Use the Cast function to upcast a value into a target type. This function will retain as much information as possible from the original value. The Cast function is intended to be used in data migration scenarios where existing values need to be upgraded to match a modified type. ```typescript const T = Type.Object({ x: Type.Number(), y: Type.Number() }, { additionalProperties: false }) const X = Value.Cast(T, null) // const X = { x: 0, y: 0 } const Y = Value.Cast(T, { x: 1 }) // const Y = { x: 1, y: 0 } const Z = Value.Cast(T, { x: 1, y: 2, z: 3 }) // const Z = { x: 1, y: 2 } ``` ### Decode Use the Decode function to decode a value from a type or throw if the value is invalid. The return value will infer as the decoded type. This function will run Transform codecs if available. ```typescript const A = Value.Decode(Type.String(), 'hello') // const A = 'hello' const B = Value.Decode(Type.String(), 42) // throw ``` ### Encode Use the Encode function to encode a value to a type or throw if the value is invalid. The return value will infer as the encoded type. This function will run Transform codecs if available. ```typescript const A = Value.Encode(Type.String(), 'hello') // const A = 'hello' const B = Value.Encode(Type.String(), 42) // throw ``` ### Parse Use the Parse function to parse a value. This function calls the `Clone` `Clean`, `Default`, `Convert`, `Assert` and `Decode` Value functions in this exact order to process a value. ```typescript const R = Value.Parse(Type.String(), 'hello') // const R: string = "hello" const E = Value.Parse(Type.String(), undefined) // throws AssertError ``` You can override the order in which functions are run, or omit functions entirely using the following. ```typescript // Runs no functions. const R = Value.Parse([], Type.String(), 12345) // Runs the Assert() function. const E = Value.Parse(['Assert'], Type.String(), 12345) // Runs the Convert() function followed by the Assert() function. const S = Value.Parse(['Convert', 'Assert'], Type.String(), 12345) ``` ### Equal Use the Equal function to deeply check for value equality. ```typescript const R = Value.Equal( // const R = true { x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 3 } ) ``` ### Hash Use the Hash function to create a [FNV1A-64](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) non-cryptographic hash of a value. ```typescript const A = Value.Hash({ x: 1, y: 2, z: 3 }) // const A = 2910466848807138541n const B = Value.Hash({ x: 1, y: 4, z: 3 }) // const B = 1418369778807423581n ``` ### Diff Use the Diff function to generate a sequence of edits that will transform one value into another. ```typescript const E = Value.Diff( // const E = [ { x: 1, y: 2, z: 3 }, // { type: 'update', path: '/y', value: 4 }, { y: 4, z: 5, w: 6 } // { type: 'update', path: '/z', value: 5 }, ) // { type: 'insert', path: '/w', value: 6 }, // { type: 'delete', path: '/x' } // ] ``` ### Patch Use the Patch function to apply a sequence of edits. ```typescript const A = { x: 1, y: 2 } const B = { x: 3 } const E = Value.Diff(A, B) // const E = [ // { type: 'update', path: '/x', value: 3 }, // { type: 'delete', path: '/y' } // ] const C = Value.Patch(A, E) // const C = { x: 3 } ``` ### Errors Use the Errors function to enumerate validation errors. ```typescript const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const R = [...Value.Errors(T, { x: '42' })] // const R = [{ // schema: { type: 'number' }, // path: '/x', // value: '42', // message: 'Expected number' // }, { // schema: { type: 'number' }, // path: '/y', // value: undefined, // message: 'Expected number' // }] ``` ### Mutate Use the Mutate function to perform a deep mutable value assignment while retaining internal references. ```typescript const Y = { z: 1 } // const Y = { z: 1 } const X = { y: Y } // const X = { y: { z: 1 } } const A = { x: X } // const A = { x: { y: { z: 1 } } } Value.Mutate(A, { x: { y: { z: 2 } } }) // A' = { x: { y: { z: 2 } } } const R0 = A.x.y.z === 2 // const R0 = true const R1 = A.x.y === Y // const R1 = true const R2 = A.x === X // const R2 = true ``` ### Pointer Use ValuePointer to perform mutable updates on existing values using [RFC6901](https://www.rfc-editor.org/rfc/rfc6901) Json Pointers. ```typescript import { ValuePointer } from '@sinclair/typebox/value' const A = { x: 0, y: 0, z: 0 } ValuePointer.Set(A, '/x', 1) // A' = { x: 1, y: 0, z: 0 } ValuePointer.Set(A, '/y', 1) // A' = { x: 1, y: 1, z: 0 } ValuePointer.Set(A, '/z', 1) // A' = { x: 1, y: 1, z: 1 } ``` ## Syntax Types TypeBox provides experimental support for parsing TypeScript annotation syntax into TypeBox types. This feature is provided via optional import. ```typescript import { Syntax } from '@sinclair/typebox/syntax' ``` ### Create Use the Syntax function to create TypeBox types from TypeScript syntax ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgChQkWIhTYYwBgWKly1OoxZtO3foMkSGEdDXgAVOAF4Uo3AAoABkhwAuOOgCuIPjygAaOFR3Lx8-AkcASjgY2Jj2djhjUwt3cwB5PgArHgYYAB4ECTiS0rLyisrYhNi3OHMAOW9fAOKq9o7OuBqY4PqmsKg2rpHR+MT8AD4JCS5eeut5LEUGfLmeCCJ6ybHKmvWFmyLdk86euDrQlv9h07uy876rv1v7t-GCIA)) ```typescript const T = Syntax(`{ x: number, y: number }`) // const T: TObject<{ // x: TNumber, // y: TNumber // }> type T = Static // type T = { // x: number, // y: number // } ``` ### Parameters Syntax types can be parameterized to receive exterior types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgCgJDCOhrwAKnAC8KUbgAUAAyQ4AXHHQBXEHx5QANHFQHjp8wS0BKOK7ev27ODLmKDCgHk+ACseBhgAHgQJd1i4+ITEpLdPN304BQA5EzNLGOSCwqK4VNcbDOz7KHzi2rqPL3wAPikfeRQVNUxNJCV8Ky0ABSxYYCwmCIUm52LUtvhkfyDQ8Kia+o2C0rh0wLAYYFlxycrcpot1zav47fK9g6OJrJzzFuv3m8amoA)) ```typescript const T = Syntax(`{ x: number, y: number }`) // const T: TObject<{ // x: TNumber, // y: TNumber // }> const S = Syntax({ T }, `Partial`) // const S: TObject<{ // x: TOptional, // y: TOptional // }> ``` ### Generics Syntax types support generic parameters in the following way ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgChQkWIhTYYwBgWKly1OoxZtO3foMkSGEdDXgA1HgxjQ4AXhSjcACgAGAHgAaAGjgBNXwAtAD45CTg4HAAuOB84cLhUGID4iIAvGMD4-FcASgkjEzM4ACEsOhpLa2gae0dMFyQqmygCX1cEBOi4Zuh3AEZfAAZh4O8EpJ6rFvcRuEG4IbGEjKnqqFnh337lnPyJLl5S8uBK6Zq65AUld0OeCCJjit6oGlCIiPZ2ODun05fag5Oh8QaCweCIZCoV8Pt0kN0FpM5qshm0ElCMZisSCYRFJvCYnNJgsUWjseSKeDcXBVgTFr4kb5Vv0COjKezsTD8EA)) ```typescript const Vector = Syntax(` { x: X, y: Y, z: Z }`) const BasisVectors = Syntax({ Vector }, `{ x: Vector<1, 0, 0>, y: Vector<0, 1, 0>, z: Vector<0, 0, 1>, }`) type BasisVectors = Static // type BasisVectors = { // x: { x: 1, y: 0, z: 0 }, // y: { x: 0, y: 1, z: 0 }, // z: { x: 0, y: 0, z: 1 } // } ``` ### Options Options can be passed via the last parameter. ```typescript const T = Syntax(`number`, { minimum: 42 }) // const T = { // type: 'number', // minimum: 42 // } ``` ### NoInfer Syntax parsing is an expensive type level operation and can impact on language service performance. Use the NoInfer function parse syntax at runtime only. ```typescript import { NoInfer } from '@sinclair/typebox/syntax' const T = NoInfer(`number | string`) // const T: TSchema = { // anyOf: [ // { type: 'number' }, // { type: 'string' } // ] // } ``` ## TypeRegistry The TypeBox type system can be extended with additional types and formats using the TypeRegistry and FormatRegistry modules. These modules integrate deeply with TypeBox's internal type checking infrastructure and can be used to create application specific types, or register schematics for alternative specifications. ### TypeRegistry Use the TypeRegistry to register a type. The Kind must match the registered type name. ```typescript import { TSchema, Kind, TypeRegistry } from '@sinclair/typebox' TypeRegistry.Set('Foo', (schema, value) => value === 'foo') const Foo = { [Kind]: 'Foo' } as TSchema const A = Value.Check(Foo, 'foo') // const A = true const B = Value.Check(Foo, 'bar') // const B = false ``` ### FormatRegistry Use the FormatRegistry to register a string format. ```typescript import { FormatRegistry } from '@sinclair/typebox' FormatRegistry.Set('foo', (value) => value === 'foo') const T = Type.String({ format: 'foo' }) const A = Value.Check(T, 'foo') // const A = true const B = Value.Check(T, 'bar') // const B = false ``` ## TypeCheck TypeBox types target Json Schema Draft 7 and are compatible with any validator that supports this specification. TypeBox also provides a built-in type checking compiler designed specifically for TypeBox types that offers high performance compilation and value checking. The following sections detail using Ajv and the TypeBox compiler infrastructure. ## Ajv The following shows the recommended setup for Ajv. ```bash $ npm install ajv ajv-formats --save ``` ```typescript import { Type } from '@sinclair/typebox' import addFormats from 'ajv-formats' import Ajv from 'ajv' const ajv = addFormats(new Ajv({}), [ 'date-time', 'time', 'date', 'email', 'hostname', 'ipv4', 'ipv6', 'uri', 'uri-reference', 'uuid', 'uri-template', 'json-pointer', 'relative-json-pointer', 'regex' ]) const validate = ajv.compile(Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() })) const R = validate({ x: 1, y: 2, z: 3 }) // const R = true ``` ### TypeCompiler The TypeBox TypeCompiler is a high performance JIT validation compiler that transforms TypeBox types into optimized JavaScript validation routines. The compiler is tuned for fast compilation as well as fast value assertion. It is built to serve as a validation backend that can be integrated into larger applications. It can also be used for code generation. The TypeCompiler is provided as an optional import. ```typescript import { TypeCompiler } from '@sinclair/typebox/compiler' ``` Use the Compile function to JIT compile a type. Note that compilation is generally an expensive operation and should only be performed once per type during application start up. TypeBox does not cache previously compiled types, and applications are expected to hold references to each compiled type for the lifetime of the application. ```typescript const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck> const R = C.Check({ x: 1, y: 2, z: 3 }) // const R = true ``` Use the Errors function to generate diagnostic errors for a value. The Errors function will return an iterator that when enumerated; will perform an exhaustive check across the entire value yielding any error found. For performance, this function should only be called after a failed Check. Applications may also choose to yield only the first value to avoid exhaustive error generation. ```typescript const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck> const value = { } const first = C.Errors(value).First() // const first = { // schema: { type: 'number' }, // path: '/x', // value: undefined, // message: 'Expected number' // } const all = [...C.Errors(value)] // const all = [{ // schema: { type: 'number' }, // path: '/x', // value: undefined, // message: 'Expected number' // }, { // schema: { type: 'number' }, // path: '/y', // value: undefined, // message: 'Expected number' // }, { // schema: { type: 'number' }, // path: '/z', // value: undefined, // message: 'Expected number' // }] ``` Use the Code function to generate assertion functions as strings. This function can be used to generate code that can be written to disk as importable modules. This technique is sometimes referred to as Ahead of Time (AOT) compilation. The following generates code to check a string. ```typescript const C = TypeCompiler.Code(Type.String()) // const C = `return function check(value) { // return ( // (typeof value === 'string') // ) // }` ``` ## TypeMap TypeBox offers an external package for bidirectional mapping between TypeBox, Valibot, and Zod type libraries. It also includes syntax parsing support for Valibot and Zod and supports the Standard Schema specification. For more details on TypeMap, refer to the project repository. [TypeMap Repository](https://github.com/sinclairzx81/typemap) ### Usage TypeMap needs to be installed separately ```bash $ npm install @sinclair/typemap ``` Once installed it offers advanced structural remapping between various runtime type libraries ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA8A0cAyqgHYwCGBcAWhACZwC+cAZlBCHAOQACAzsFIBjADYVgUAPQx0GEBTDcAUMuERS-eMjgBeFHJy4AFAAMkuAFxxSAVxAAjDFEKprdx88IAvd-adQzKYAlHBwUlJw6pra1sgA8g4AVhjCMAA8CMphObl5+QWFRcW5ETlWKABy-s4A3NkljU3NBWVhblU1UPUtvX3FbXC+nZ7dDf0TE2VMAHyq0VrEesRklCbIoS1lC-BE1twWfqOuRwE+p87MKmoaiwBKy3T0xkTBAHRgFFD8GMZ2oqJNnltrd4HdrFlJltImEKh4Aj0oU1Bh14XVxkiBjChhcxpjGtMwkA)) ```typescript import { TypeBox, Syntax, Zod } from '@sinclair/typemap' const T = TypeBox(`{ x: number, y: number, z: number }`) // const T: TObject<{ // x: TNumber; // y: TNumber; // z: TNumber; // }> const S = Syntax(T) // const S: '{ x: number, y: number, z: number }' const R = Zod(S).parse(null) // const R: { // x: number; // y: number; // z: number; // } ``` ## TypeSystem The TypeBox TypeSystem module provides configurations to use either Json Schema or TypeScript type checking semantics. Configurations made to the TypeSystem module are observed by the TypeCompiler, Value and Error modules. ### Policies TypeBox validates using standard Json Schema assertion policies by default. The TypeSystemPolicy module can override some of these to have TypeBox assert values inline with TypeScript static checks. It also provides overrides for certain checking rules related to non-serializable values (such as void) which can be helpful in Json based protocols such as Json Rpc 2.0. The following overrides are available. ```typescript import { TypeSystemPolicy } from '@sinclair/typebox/system' // Disallow undefined values for optional properties (default is false) // // const A: { x?: number } = { x: undefined } - disallowed when enabled TypeSystemPolicy.ExactOptionalPropertyTypes = true // Allow arrays to validate as object types (default is false) // // const A: {} = [] - allowed in TS TypeSystemPolicy.AllowArrayObject = true // Allow numeric values to be NaN or + or - Infinity (default is false) // // const A: number = NaN - allowed in TS TypeSystemPolicy.AllowNaN = true // Allow void types to check with undefined and null (default is false) // // Used to signal void return on Json-Rpc 2.0 protocol TypeSystemPolicy.AllowNullVoid = true ``` ## Error Function Error messages in TypeBox can be customized by defining an ErrorFunction. This function allows for the localization of error messages as well as enabling custom error messages for custom types. By default, TypeBox will generate messages using the `en-US` locale. To support additional locales, you can replicate the function found in `src/errors/function.ts` and create a locale specific translation. The function can then be set via SetErrorFunction. The following example shows an inline error function that intercepts errors for String, Number and Boolean only. The DefaultErrorFunction is used to return a default error message. ```typescript import { SetErrorFunction, DefaultErrorFunction, ValueErrorType } 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) } }) const T = Type.Object({ // const T: TObject<{ x: Type.String(), // TString, y: Type.Number(), // TNumber, z: Type.Boolean() // TBoolean }) // }> const E = [...Value.Errors(T, { // const E = [{ x: null, // type: 48, y: null, // schema: { ... }, z: null // path: '/x', })] // value: null, // message: 'Expected string' // }, { // type: 34, // schema: { ... }, // path: '/y', // value: null, // message: 'Nombre attendu' // }, { // type: 14, // schema: { ... }, // path: '/z', // value: null, // message: '예상 부울' // }] ``` ## TypeBox Workbench TypeBox offers a web based code generation tool that can convert TypeScript types into TypeBox types as well as several other ecosystem libraries. [TypeBox Workbench Link Here](https://sinclairzx81.github.io/typebox-workbench/) ## TypeBox Codegen TypeBox provides a code generation library that can be integrated into toolchains to automate type translation between TypeScript and TypeBox. This library also includes functionality to transform TypeScript types to other ecosystem libraries. [TypeBox Codegen Link Here](https://github.com/sinclairzx81/typebox-codegen) ## Ecosystem The following is a list of community packages that offer general tooling, extended functionality and framework integration support for TypeBox. | Package | Description | | ------------- | ------------- | | [drizzle-typebox](https://www.npmjs.com/package/drizzle-typebox) | Generates TypeBox types from Drizzle ORM schemas | | [elysia](https://github.com/elysiajs/elysia) | Fast and friendly Bun web framework | | [fastify-type-provider-typebox](https://github.com/fastify/fastify-type-provider-typebox) | Fastify TypeBox integration with the Fastify Type Provider | | [feathersjs](https://github.com/feathersjs/feathers) | The API and real-time application framework | | [fetch-typebox](https://github.com/erfanium/fetch-typebox) | Drop-in replacement for fetch that brings easy integration with TypeBox | | [@lonli-lokli/fetcher-typebox](https://github.com/Lonli-Lokli/fetcher-ts/tree/master/packages/fetcher-typebox) | A strongly-typed fetch wrapper for TypeScript applications with optional runtime validation using TypeBox | | [h3-typebox](https://github.com/kevinmarrec/h3-typebox) | Schema validation utilities for h3 using TypeBox & Ajv | | [http-wizard](https://github.com/flodlc/http-wizard) | Type safe http client library for Fastify | | [json2typebox](https://github.com/hacxy/json2typebox) | Creating TypeBox code from Json Data | | [nominal-typebox](https://github.com/Coder-Spirit/nominal/tree/main/%40coderspirit/nominal-typebox) | Allows devs to integrate nominal types into TypeBox schemas | | [openapi-box](https://github.com/geut/openapi-box) | Generate TypeBox types from OpenApi IDL + Http client library | | [prismabox](https://github.com/m1212e/prismabox) | Converts a prisma.schema to TypeBox schema matching the database models | | [schema2typebox](https://github.com/xddq/schema2typebox) | Creating TypeBox code from Json Schemas | | [sveltekit-superforms](https://github.com/ciscoheat/sveltekit-superforms) | A comprehensive SvelteKit form library for server and client validation | | [ts2typebox](https://github.com/xddq/ts2typebox) | Creating TypeBox code from Typescript types | | [typebox-cli](https://github.com/gsuess/typebox-cli) | Generate Schema with TypeBox from the CLI | | [typebox-form-parser](https://github.com/jtlapp/typebox-form-parser) | Parses form and query data based on TypeBox schemas | | [typebox-schema-faker](https://github.com/iam-medvedev/typebox-schema-faker) | Generate fake data from TypeBox schemas for testing, prototyping and development | ## Benchmark This project maintains a set of benchmarks that measure Ajv, Value and TypeCompiler compilation and validation performance. These benchmarks can be run locally by cloning this repository and running `npm run benchmark`. The results below show for Ajv version 8.12.0 running on Node 20.10.0. For additional comparative benchmarks, please refer to [typescript-runtime-type-benchmarks](https://moltar.github.io/typescript-runtime-type-benchmarks/). ### Compile This benchmark measures compilation performance for varying types. ```typescript ┌────────────────────────────┬────────────┬──────────────┬──────────────┬──────────────┐ │ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │ ├────────────────────────────┼────────────┼──────────────┼──────────────┼──────────────┤ │ Literal_String │ 1000 │ ' 211 ms' │ ' 8 ms' │ ' 26.38 x' │ │ Literal_Number │ 1000 │ ' 185 ms' │ ' 5 ms' │ ' 37.00 x' │ │ Literal_Boolean │ 1000 │ ' 195 ms' │ ' 4 ms' │ ' 48.75 x' │ │ Primitive_Number │ 1000 │ ' 149 ms' │ ' 7 ms' │ ' 21.29 x' │ │ Primitive_String │ 1000 │ ' 135 ms' │ ' 5 ms' │ ' 27.00 x' │ │ Primitive_String_Pattern │ 1000 │ ' 193 ms' │ ' 10 ms' │ ' 19.30 x' │ │ Primitive_Boolean │ 1000 │ ' 152 ms' │ ' 4 ms' │ ' 38.00 x' │ │ Primitive_Null │ 1000 │ ' 147 ms' │ ' 4 ms' │ ' 36.75 x' │ │ Object_Unconstrained │ 1000 │ ' 1065 ms' │ ' 26 ms' │ ' 40.96 x' │ │ Object_Constrained │ 1000 │ ' 1183 ms' │ ' 26 ms' │ ' 45.50 x' │ │ Object_Vector3 │ 1000 │ ' 407 ms' │ ' 9 ms' │ ' 45.22 x' │ │ Object_Box3D │ 1000 │ ' 1777 ms' │ ' 24 ms' │ ' 74.04 x' │ │ Tuple_Primitive │ 1000 │ ' 485 ms' │ ' 11 ms' │ ' 44.09 x' │ │ Tuple_Object │ 1000 │ ' 1344 ms' │ ' 17 ms' │ ' 79.06 x' │ │ Composite_Intersect │ 1000 │ ' 606 ms' │ ' 14 ms' │ ' 43.29 x' │ │ Composite_Union │ 1000 │ ' 522 ms' │ ' 17 ms' │ ' 30.71 x' │ │ Math_Vector4 │ 1000 │ ' 851 ms' │ ' 9 ms' │ ' 94.56 x' │ │ Math_Matrix4 │ 1000 │ ' 406 ms' │ ' 10 ms' │ ' 40.60 x' │ │ Array_Primitive_Number │ 1000 │ ' 367 ms' │ ' 6 ms' │ ' 61.17 x' │ │ Array_Primitive_String │ 1000 │ ' 339 ms' │ ' 7 ms' │ ' 48.43 x' │ │ Array_Primitive_Boolean │ 1000 │ ' 325 ms' │ ' 5 ms' │ ' 65.00 x' │ │ Array_Object_Unconstrained │ 1000 │ ' 1863 ms' │ ' 21 ms' │ ' 88.71 x' │ │ Array_Object_Constrained │ 1000 │ ' 1535 ms' │ ' 18 ms' │ ' 85.28 x' │ │ Array_Tuple_Primitive │ 1000 │ ' 829 ms' │ ' 14 ms' │ ' 59.21 x' │ │ Array_Tuple_Object │ 1000 │ ' 1674 ms' │ ' 14 ms' │ ' 119.57 x' │ │ Array_Composite_Intersect │ 1000 │ ' 789 ms' │ ' 13 ms' │ ' 60.69 x' │ │ Array_Composite_Union │ 1000 │ ' 822 ms' │ ' 15 ms' │ ' 54.80 x' │ │ Array_Math_Vector4 │ 1000 │ ' 1129 ms' │ ' 14 ms' │ ' 80.64 x' │ │ Array_Math_Matrix4 │ 1000 │ ' 673 ms' │ ' 9 ms' │ ' 74.78 x' │ └────────────────────────────┴────────────┴──────────────┴──────────────┴──────────────┘ ``` ### Validate This benchmark measures validation performance for varying types. ```typescript ┌────────────────────────────┬────────────┬──────────────┬──────────────┬──────────────┬──────────────┐ │ (index) │ Iterations │ ValueCheck │ Ajv │ TypeCompiler │ Performance │ ├────────────────────────────┼────────────┼──────────────┼──────────────┼──────────────┼──────────────┤ │ Literal_String │ 1000000 │ ' 17 ms' │ ' 5 ms' │ ' 5 ms' │ ' 1.00 x' │ │ Literal_Number │ 1000000 │ ' 14 ms' │ ' 18 ms' │ ' 9 ms' │ ' 2.00 x' │ │ Literal_Boolean │ 1000000 │ ' 14 ms' │ ' 20 ms' │ ' 9 ms' │ ' 2.22 x' │ │ Primitive_Number │ 1000000 │ ' 17 ms' │ ' 19 ms' │ ' 9 ms' │ ' 2.11 x' │ │ Primitive_String │ 1000000 │ ' 17 ms' │ ' 18 ms' │ ' 10 ms' │ ' 1.80 x' │ │ Primitive_String_Pattern │ 1000000 │ ' 172 ms' │ ' 46 ms' │ ' 41 ms' │ ' 1.12 x' │ │ Primitive_Boolean │ 1000000 │ ' 14 ms' │ ' 19 ms' │ ' 10 ms' │ ' 1.90 x' │ │ Primitive_Null │ 1000000 │ ' 16 ms' │ ' 19 ms' │ ' 9 ms' │ ' 2.11 x' │ │ Object_Unconstrained │ 1000000 │ ' 437 ms' │ ' 28 ms' │ ' 14 ms' │ ' 2.00 x' │ │ Object_Constrained │ 1000000 │ ' 653 ms' │ ' 46 ms' │ ' 37 ms' │ ' 1.24 x' │ │ Object_Vector3 │ 1000000 │ ' 201 ms' │ ' 22 ms' │ ' 12 ms' │ ' 1.83 x' │ │ Object_Box3D │ 1000000 │ ' 961 ms' │ ' 37 ms' │ ' 19 ms' │ ' 1.95 x' │ │ Object_Recursive │ 1000000 │ ' 3715 ms' │ ' 363 ms' │ ' 174 ms' │ ' 2.09 x' │ │ Tuple_Primitive │ 1000000 │ ' 107 ms' │ ' 23 ms' │ ' 11 ms' │ ' 2.09 x' │ │ Tuple_Object │ 1000000 │ ' 375 ms' │ ' 28 ms' │ ' 15 ms' │ ' 1.87 x' │ │ Composite_Intersect │ 1000000 │ ' 377 ms' │ ' 22 ms' │ ' 12 ms' │ ' 1.83 x' │ │ Composite_Union │ 1000000 │ ' 337 ms' │ ' 30 ms' │ ' 17 ms' │ ' 1.76 x' │ │ Math_Vector4 │ 1000000 │ ' 137 ms' │ ' 23 ms' │ ' 11 ms' │ ' 2.09 x' │ │ Math_Matrix4 │ 1000000 │ ' 576 ms' │ ' 37 ms' │ ' 28 ms' │ ' 1.32 x' │ │ Array_Primitive_Number │ 1000000 │ ' 145 ms' │ ' 23 ms' │ ' 12 ms' │ ' 1.92 x' │ │ Array_Primitive_String │ 1000000 │ ' 152 ms' │ ' 22 ms' │ ' 13 ms' │ ' 1.69 x' │ │ Array_Primitive_Boolean │ 1000000 │ ' 131 ms' │ ' 20 ms' │ ' 13 ms' │ ' 1.54 x' │ │ Array_Object_Unconstrained │ 1000000 │ ' 2821 ms' │ ' 62 ms' │ ' 45 ms' │ ' 1.38 x' │ │ Array_Object_Constrained │ 1000000 │ ' 2958 ms' │ ' 119 ms' │ ' 134 ms' │ ' 0.89 x' │ │ Array_Object_Recursive │ 1000000 │ ' 14695 ms' │ ' 1621 ms' │ ' 635 ms' │ ' 2.55 x' │ │ Array_Tuple_Primitive │ 1000000 │ ' 478 ms' │ ' 35 ms' │ ' 28 ms' │ ' 1.25 x' │ │ Array_Tuple_Object │ 1000000 │ ' 1623 ms' │ ' 63 ms' │ ' 48 ms' │ ' 1.31 x' │ │ Array_Composite_Intersect │ 1000000 │ ' 1582 ms' │ ' 43 ms' │ ' 30 ms' │ ' 1.43 x' │ │ Array_Composite_Union │ 1000000 │ ' 1331 ms' │ ' 76 ms' │ ' 40 ms' │ ' 1.90 x' │ │ Array_Math_Vector4 │ 1000000 │ ' 564 ms' │ ' 38 ms' │ ' 24 ms' │ ' 1.58 x' │ │ Array_Math_Matrix4 │ 1000000 │ ' 2382 ms' │ ' 111 ms' │ ' 83 ms' │ ' 1.34 x' │ └────────────────────────────┴────────────┴──────────────┴──────────────┴──────────────┴──────────────┘ ``` ### Compression The following table lists esbuild compiled and minified sizes for each TypeBox module. ```typescript ┌──────────────────────┬────────────┬────────────┬─────────────┐ │ (index) │ Compiled │ Minified │ Compression │ ├──────────────────────┼────────────┼────────────┼─────────────┤ │ typebox/compiler │ '122.4 kb' │ ' 53.4 kb' │ '2.29 x' │ │ typebox/errors │ ' 67.6 kb' │ ' 29.6 kb' │ '2.28 x' │ │ typebox/syntax │ '132.9 kb' │ ' 54.2 kb' │ '2.45 x' │ │ typebox/system │ ' 7.4 kb' │ ' 3.2 kb' │ '2.33 x' │ │ typebox/value │ '150.1 kb' │ ' 62.2 kb' │ '2.41 x' │ │ typebox │ '106.8 kb' │ ' 43.2 kb' │ '2.47 x' │ └──────────────────────┴────────────┴────────────┴─────────────┘ ``` ## Contribute TypeBox is open to community contribution. Please ensure you submit an open issue before submitting your pull request. The TypeBox project prefers open community discussion before accepting new features. sinclairzx81-typebox-e0ec98c/src/000077500000000000000000000000001505437577000170475ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/compiler/000077500000000000000000000000001505437577000206615ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/compiler/compiler.ts000066400000000000000000001043031505437577000230440ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/compiler The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TransformEncode, TransformDecode, HasTransform, TransformDecodeCheckError, TransformEncodeCheckError } from '../value/transform/index' import { Errors, ValueErrorIterator } from '../errors/index' import { TypeSystemPolicy } from '../system/index' 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 { TArgument } from '../type/argument/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 { TImport } from '../type/module/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 { Ref, 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 { private readonly hasTransform: boolean 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 { return this.code } /** Returns the schema type used to validate */ public Schema(): T { return this.schema } /** Returns reference types used to validate */ public References(): TSchema[] { return this.references } /** Returns an iterator for each error in this value. */ public Errors(value: unknown): ValueErrorIterator { return Errors(this.schema, this.references, value) } /** Returns true if the value matches the compiled type. */ public Check(value: unknown): value is Static { return this.checkFunc(value) } /** Decodes a value or throws if error */ public Decode, Result extends Static = Static>(value: unknown): Result { if (!this.checkFunc(value)) throw new TransformDecodeCheckError(this.schema, value, this.Errors(value).First()!) return (this.hasTransform ? TransformDecode(this.schema, this.references, value) : value) as never } /** Encodes a value or throws if error */ public Encode, Result extends Static = Static>(value: unknown): Result { 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 as never } } // ------------------------------------------------------------------ // Character // ------------------------------------------------------------------ namespace Character { export function DollarSign(code: number) { return code === 36 } export function IsUnderscore(code: number) { return code === 95 } export function IsAlpha(code: number) { return (code >= 65 && code <= 90) || (code >= 97 && code <= 122) } export function IsNumeric(code: number) { return code >= 48 && code <= 57 } } // ------------------------------------------------------------------ // MemberExpression // ------------------------------------------------------------------ namespace MemberExpression { function IsFirstCharacterNumeric(value: string) { if (value.length === 0) return false return Character.IsNumeric(value.charCodeAt(0)) } function IsAccessor(value: string) { if (IsFirstCharacterNumeric(value)) return false for (let i = 0; i < value.length; i++) { const code = value.charCodeAt(i) const check = Character.IsAlpha(code) || Character.IsNumeric(code) || Character.DollarSign(code) || Character.IsUnderscore(code) if (!check) return false } return true } function EscapeHyphen(key: string) { return key.replace(/'/g, "\\'") } export function Encode(object: string, key: string) { return IsAccessor(key) ? `${object}.${key}` : `${object}['${EscapeHyphen(key)}']` } } // ------------------------------------------------------------------ // Identifier // ------------------------------------------------------------------ namespace Identifier { export function Encode($id: string) { const buffer: string[] = [] for (let i = 0; i < $id.length; i++) { const code = $id.charCodeAt(i) if (Character.IsNumeric(code) || Character.IsAlpha(code)) { buffer.push($id.charAt(i)) } else { buffer.push(`_${code}_`) } } return buffer.join('').replace(/__/g, '_') } } // ------------------------------------------------------------------ // LiteralString // ------------------------------------------------------------------ namespace LiteralString { export function Escape(content: string) { return content.replace(/'/g, "\\'") } } // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class TypeCompilerUnknownTypeError extends TypeBoxError { constructor(public readonly schema: TSchema) { super('Unknown type') } } 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)` } export function IsObjectLike(value: string): string { return !TypeSystemPolicy.AllowArrayObject ? `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))` : `(typeof ${value} === 'object' && ${value} !== null)` } export function IsRecordLike(value: string): string { return !TypeSystemPolicy.AllowArrayObject ? `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}) && !(${value} instanceof Date) && !(${value} instanceof Uint8Array))` : `(typeof ${value} === 'object' && ${value} !== null && !(${value} instanceof Date) && !(${value} instanceof Uint8Array))` } export function IsNumberLike(value: string): string { return TypeSystemPolicy.AllowNaN ? `typeof ${value} === 'number'` : `Number.isFinite(${value})` } export function IsVoidLike(value: string): string { 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: TSchema) { return schema[Kind] === 'Any' || schema[Kind] === 'Unknown' } // ---------------------------------------------------------------- // Types // ---------------------------------------------------------------- function* FromAny(schema: TAny, references: TSchema[], value: string): IterableIterator { yield 'true' } function* FromArgument(schema: TArgument, references: TSchema[], value: string): IterableIterator { yield 'true' } function* FromArray(schema: TArray, references: TSchema[], value: string): IterableIterator { 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 (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})`] : [] const checkCount = `const count = value.reduce((${accumulator}, ${parameter}) => ${checkExpression} ? acc + 1 : acc, 0)` const check = [`(count > 0)`, ...checkMinContains, ...checkMaxContains].join(' && ') yield `((${parameter}) => { ${checkCount}; return ${check}})(${value})` } if (schema.uniqueItems === true) { const check = `const hashed = hash(element); if(set.has(hashed)) { return false } else { set.add(hashed) } } return true` const block = `const set = new Set(); for(const element of value) { ${check} }` yield `((${parameter}) => { ${block} )(${value})` } } function* FromAsyncIterator(schema: TAsyncIterator, references: TSchema[], value: string): IterableIterator { yield `(typeof value === 'object' && Symbol.asyncIterator in ${value})` } function* FromBigInt(schema: TBigInt, references: TSchema[], value: string): IterableIterator { yield `(typeof ${value} === 'bigint')` if (IsBigInt(schema.exclusiveMaximum)) yield `${value} < BigInt(${schema.exclusiveMaximum})` if (IsBigInt(schema.exclusiveMinimum)) yield `${value} > BigInt(${schema.exclusiveMinimum})` if (IsBigInt(schema.maximum)) yield `${value} <= BigInt(${schema.maximum})` if (IsBigInt(schema.minimum)) yield `${value} >= BigInt(${schema.minimum})` if (IsBigInt(schema.multipleOf)) yield `(${value} % BigInt(${schema.multipleOf})) === 0` } function* FromBoolean(schema: TBoolean, references: TSchema[], value: string): IterableIterator { yield `(typeof ${value} === 'boolean')` } function* FromConstructor(schema: TConstructor, references: TSchema[], value: string): IterableIterator { yield* Visit(schema.returns, references, `${value}.prototype`) } function* FromDate(schema: TDate, references: TSchema[], value: string): IterableIterator { 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}` if (IsNumber(schema.maximumTimestamp)) yield `${value}.getTime() <= ${schema.maximumTimestamp}` if (IsNumber(schema.minimumTimestamp)) yield `${value}.getTime() >= ${schema.minimumTimestamp}` if (IsNumber(schema.multipleOfTimestamp)) yield `(${value}.getTime() % ${schema.multipleOfTimestamp}) === 0` } function* FromFunction(schema: TFunction, references: TSchema[], value: string): IterableIterator { yield `(typeof ${value} === 'function')` } function* FromImport(schema: TImport, references: TSchema[], value: string): IterableIterator { const members = globalThis.Object.getOwnPropertyNames(schema.$defs).reduce((result, key) => { return [...result, schema.$defs[key as never] as TSchema] }, [] as TSchema[]) yield* Visit(Ref(schema.$ref), [...references, ...members], value) } function* FromInteger(schema: TInteger, references: TSchema[], value: string): IterableIterator { yield `Number.isInteger(${value})` if (IsNumber(schema.exclusiveMaximum)) yield `${value} < ${schema.exclusiveMaximum}` if (IsNumber(schema.exclusiveMinimum)) yield `${value} > ${schema.exclusiveMinimum}` if (IsNumber(schema.maximum)) yield `${value} <= ${schema.maximum}` if (IsNumber(schema.minimum)) yield `${value} >= ${schema.minimum}` if (IsNumber(schema.multipleOf)) yield `(${value} % ${schema.multipleOf}) === 0` } function* FromIntersect(schema: TIntersect, references: TSchema[], value: string): IterableIterator { const check1 = schema.allOf.map((schema: TSchema) => CreateExpression(schema, references, value)).join(' && ') if (schema.unevaluatedProperties === false) { const keyCheck = CreateVariable(`${new RegExp(KeyOfPattern(schema))};`) const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key))` yield `(${check1} && ${check2})` } 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* FromIterator(schema: TIterator, references: TSchema[], value: string): IterableIterator { yield `(typeof value === 'object' && Symbol.iterator in ${value})` } function* FromLiteral(schema: TLiteral, references: TSchema[], value: string): IterableIterator { if (typeof schema.const === 'number' || typeof schema.const === 'boolean') { yield `(${value} === ${schema.const})` } else { yield `(${value} === '${LiteralString.Escape(schema.const)}')` } } function* FromNever(schema: TNever, references: TSchema[], value: string): IterableIterator { yield `false` } function* FromNot(schema: TNot, references: TSchema[], value: string): IterableIterator { const expression = CreateExpression(schema.not, references, value) yield `(!${expression})` } function* FromNull(schema: TNull, references: TSchema[], value: string): IterableIterator { yield `(${value} === null)` } function* FromNumber(schema: TNumber, references: TSchema[], value: string): IterableIterator { yield Policy.IsNumberLike(value) if (IsNumber(schema.exclusiveMaximum)) yield `${value} < ${schema.exclusiveMaximum}` if (IsNumber(schema.exclusiveMinimum)) yield `${value} > ${schema.exclusiveMinimum}` if (IsNumber(schema.maximum)) yield `${value} <= ${schema.maximum}` if (IsNumber(schema.minimum)) yield `${value} >= ${schema.minimum}` if (IsNumber(schema.multipleOf)) yield `(${value} % ${schema.multipleOf}) === 0` } function* FromObject(schema: TObject, references: TSchema[], value: string): IterableIterator { 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}` const knownKeys = Object.getOwnPropertyNames(schema.properties) for (const knownKey of knownKeys) { const memberExpression = MemberExpression.Encode(value, knownKey) const property = schema.properties[knownKey] if (schema.required && schema.required.includes(knownKey)) { yield* Visit(property, references, memberExpression) if (ExtendsUndefinedCheck(property) || IsAnyOrUnknown(property)) yield `('${knownKey}' in ${value})` } else { const expression = CreateExpression(property, references, memberExpression) yield Policy.IsExactOptionalProperty(value, knownKey, expression) } } if (schema.additionalProperties === false) { if (schema.required && schema.required.length === knownKeys.length) { yield `Object.getOwnPropertyNames(${value}).length === ${knownKeys.length}` } else { const keys = `[${knownKeys.map((key) => `'${key}'`).join(', ')}]` yield `Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key))` } } if (typeof schema.additionalProperties === 'object') { const expression = CreateExpression(schema.additionalProperties, references, `${value}[key]`) const keys = `[${knownKeys.map((key) => `'${key}'`).join(', ')}]` yield `(Object.getOwnPropertyNames(${value}).every(key => ${keys}.includes(key) || ${expression}))` } } function* FromPromise(schema: TPromise, references: TSchema[], value: string): IterableIterator { yield `${value} instanceof Promise` } function* FromRecord(schema: TRecord, references: TSchema[], value: string): IterableIterator { 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 = 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* FromRef(schema: TRef, references: TSchema[], value: string): IterableIterator { 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* FromRegExp(schema: TRegExp, references: TSchema[], value: string): IterableIterator { const variable = CreateVariable(`${new RegExp(schema.source, schema.flags)};`) yield `(typeof ${value} === 'string')` if (IsNumber(schema.maxLength)) yield `${value}.length <= ${schema.maxLength}` if (IsNumber(schema.minLength)) yield `${value}.length >= ${schema.minLength}` yield `${variable}.test(${value})` } function* FromString(schema: TString, references: TSchema[], value: string): IterableIterator { yield `(typeof ${value} === 'string')` if (IsNumber(schema.maxLength)) yield `${value}.length <= ${schema.maxLength}` if (IsNumber(schema.minLength)) yield `${value}.length >= ${schema.minLength}` if (schema.pattern !== undefined) { const variable = CreateVariable(`${new RegExp(schema.pattern)};`) yield `${variable}.test(${value})` } if (schema.format !== undefined) { yield `format('${schema.format}', ${value})` } } function* FromSymbol(schema: TSymbol, references: TSchema[], value: string): IterableIterator { yield `(typeof ${value} === 'symbol')` } function* FromTemplateLiteral(schema: TTemplateLiteral, references: TSchema[], value: string): IterableIterator { yield `(typeof ${value} === 'string')` const variable = CreateVariable(`${new RegExp(schema.pattern)};`) yield `${variable}.test(${value})` } function* FromThis(schema: TThis, references: TSchema[], value: string): IterableIterator { // Note: This types are assured to be hoisted prior to this call. Just yield the function. yield `${CreateFunctionName(schema.$ref)}(${value})` } function* FromTuple(schema: TTuple, references: TSchema[], value: string): IterableIterator { yield `Array.isArray(${value})` if (schema.items === undefined) return yield `${value}.length === 0` yield `(${value}.length === ${schema.maxItems})` for (let i = 0; i < schema.items.length; i++) { const expression = CreateExpression(schema.items[i], references, `${value}[${i}]`) yield `${expression}` } } function* FromUndefined(schema: TUndefined, references: TSchema[], value: string): IterableIterator { yield `${value} === undefined` } function* FromUnion(schema: TUnion, references: TSchema[], value: string): IterableIterator { const expressions = schema.anyOf.map((schema: TSchema) => CreateExpression(schema, references, value)) yield `(${expressions.join(' || ')})` } function* FromUint8Array(schema: TUint8Array, references: TSchema[], value: string): IterableIterator { yield `${value} instanceof Uint8Array` if (IsNumber(schema.maxByteLength)) yield `(${value}.length <= ${schema.maxByteLength})` if (IsNumber(schema.minByteLength)) yield `(${value}.length >= ${schema.minByteLength})` } function* FromUnknown(schema: TUnknown, references: TSchema[], value: string): IterableIterator { yield 'true' } function* FromVoid(schema: TVoid, references: TSchema[], value: string): IterableIterator { yield Policy.IsVoidLike(value) } function* FromKind(schema: TSchema, references: TSchema[], value: string): IterableIterator { const instance = state.instances.size state.instances.set(instance, schema) yield `kind('${schema[Kind]}', ${instance}, ${value})` } function* Visit(schema: TSchema, references: TSchema[], value: string, useHoisting: boolean = true): IterableIterator { 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)) { return yield `${functionName}(${value})` } else { // Note: In the case of cyclic types, we need to create a 'functions' record // to prevent infinitely re-visiting the CreateFunction. Subsequent attempts // to visit will be caught by the above condition. state.functions.set(functionName, '') const functionCode = CreateFunction(functionName, schema, references, 'value', false) state.functions.set(functionName, functionCode) return yield `${functionName}(${value})` } } switch (schema_[Kind]) { case 'Any': return yield* FromAny(schema_, references_, value) case 'Argument': return yield* FromArgument(schema_, references_, value) case 'Array': return yield* FromArray(schema_, references_, value) case 'AsyncIterator': return yield* FromAsyncIterator(schema_, references_, value) case 'BigInt': return yield* FromBigInt(schema_, references_, value) case 'Boolean': return yield* FromBoolean(schema_, references_, value) case 'Constructor': return yield* FromConstructor(schema_, references_, value) case 'Date': return yield* FromDate(schema_, references_, value) case 'Function': return yield* FromFunction(schema_, references_, value) case 'Import': return yield* FromImport(schema_, references_, value) case 'Integer': return yield* FromInteger(schema_, references_, value) case 'Intersect': return yield* FromIntersect(schema_, references_, value) case 'Iterator': return yield* FromIterator(schema_, references_, value) case 'Literal': return yield* FromLiteral(schema_, references_, value) case 'Never': return yield* FromNever(schema_, references_, value) case 'Not': return yield* FromNot(schema_, references_, value) case 'Null': return yield* FromNull(schema_, references_, value) case 'Number': return yield* FromNumber(schema_, references_, value) case 'Object': return yield* FromObject(schema_, references_, value) case 'Promise': return yield* FromPromise(schema_, references_, value) case 'Record': return yield* FromRecord(schema_, references_, value) case 'Ref': return yield* FromRef(schema_, references_, value) case 'RegExp': return yield* FromRegExp(schema_, references_, value) case 'String': return yield* FromString(schema_, references_, value) case 'Symbol': return yield* FromSymbol(schema_, references_, value) case 'TemplateLiteral': return yield* FromTemplateLiteral(schema_, references_, value) case 'This': return yield* FromThis(schema_, references_, value) case 'Tuple': return yield* FromTuple(schema_, references_, value) case 'Undefined': return yield* FromUndefined(schema_, references_, value) case 'Union': return yield* FromUnion(schema_, references_, value) case 'Uint8Array': return yield* FromUint8Array(schema_, references_, value) case 'Unknown': return yield* FromUnknown(schema_, references_, value) case 'Void': return yield* FromVoid(schema_, references_, value) default: 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(), // local functions variables: new Map(), // local variables instances: new Map() // exterior kind instances } // ---------------------------------------------------------------- // Compiler Factory // ---------------------------------------------------------------- function CreateExpression(schema: TSchema, references: TSchema[], value: string, useHoisting: boolean = true): string { return `(${[...Visit(schema, references, value, useHoisting)].join(' && ')})` } function CreateFunctionName($id: string) { return `check_${Identifier.Encode($id)}` } function CreateVariable(expression: string) { const variableName = `local_${state.variables.size}` state.variables.set(variableName, `const ${variableName} = ${expression}`) return variableName } 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') const expression = [...Visit(schema, references, value, useHoisting)].map((expression) => `${pad(4)}${expression}`).join(` &&${newline}`) return `function ${name}(${parameter})${returns} {${newline}${pad(2)}return (${newline}${expression}${newline}${pad(2)})\n}` } function CreateParameter(name: string, type: string) { const annotation = state.language === 'typescript' ? `: ${type}` : '' return `${name}${annotation}` } function CreateReturns(type: string) { return state.language === 'typescript' ? `: ${type}` : '' } // ---------------------------------------------------------------- // Compile // ---------------------------------------------------------------- function Build(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') const functions = [...state.functions.values()] const variables = [...state.variables.values()] // prettier-ignore const checkFunction = IsString(schema.$id) // ensure top level schemas with $id's are hoisted ? `return function check(${parameter})${returns} {\n return ${CreateFunctionName(schema.$id)}(value)\n}` : `return ${functionCode}` return [...variables, ...functions, checkFunction].join('\n') } /** Generates the code used to assert this type and returns it as a string */ export function Code(schema: T, references: TSchema[], options?: TypeCompilerCodegenOptions): string /** Generates the code used to assert this type and returns it as a string */ export function Code(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' } // prettier-ignore const [schema, references, options] = ( args.length === 2 && IsArray(args[1]) ? [args[0], args[1], defaults] : args.length === 2 && !IsArray(args[1]) ? [args[0], [], args[1]] : args.length === 3 ? [args[0], args[1], args[2]] : args.length === 1 ? [args[0], [], defaults] : [null, [], defaults] ) // compiler-reset state.language = options.language state.variables.clear() state.functions.clear() state.instances.clear() 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(schema: T, references: TSchema[] = []): TypeCheck { 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 (!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 (!FormatRegistry.Has(format)) return false const checkFunc = FormatRegistry.Get(format)! return checkFunc(value) } function hashFunction(value: unknown) { return Hash(value) } const checkFunction = compiledFunction(typeRegistryFunction, formatRegistryFunction, hashFunction) return new TypeCheck(schema, references, checkFunction, generatedCode) } } sinclairzx81-typebox-e0ec98c/src/compiler/index.ts000066400000000000000000000026131505437577000223420ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/compiler The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { ValueError, ValueErrorType, ValueErrorIterator } from '../errors/index' export * from './compiler' sinclairzx81-typebox-e0ec98c/src/errors/000077500000000000000000000000001505437577000203635ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/errors/errors.ts000066400000000000000000000725151505437577000222610ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/errors The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { 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 { Check } from '../value/check/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 { TImport } from '../type/module/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, ArrayMaxItems, ArrayMinContains, ArrayMinItems, ArrayUniqueItems, Array, AsyncIterator, BigIntExclusiveMaximum, BigIntExclusiveMinimum, BigIntMaximum, BigIntMinimum, BigIntMultipleOf, BigInt, Boolean, DateExclusiveMaximumTimestamp, DateExclusiveMinimumTimestamp, DateMaximumTimestamp, DateMinimumTimestamp, DateMultipleOfTimestamp, Date, Function, IntegerExclusiveMaximum, IntegerExclusiveMinimum, IntegerMaximum, IntegerMinimum, IntegerMultipleOf, Integer, IntersectUnevaluatedProperties, Intersect, Iterator, Kind, Literal, Never, Not, Null, NumberExclusiveMaximum, NumberExclusiveMinimum, NumberMaximum, NumberMinimum, NumberMultipleOf, Number, ObjectAdditionalProperties, ObjectMaxProperties, ObjectMinProperties, ObjectRequiredProperty, Object, Promise, RegExp, StringFormatUnknown, StringFormat, StringMaxLength, StringMinLength, StringPattern, String, Symbol, TupleLength, Tuple, Uint8ArrayMaxByteLength, Uint8ArrayMinByteLength, Uint8Array, Undefined, Union, Void, } // ------------------------------------------------------------------ // ValueError // ------------------------------------------------------------------ export interface ValueError { type: ValueErrorType schema: TSchema path: string value: unknown message: string errors: ValueErrorIterator[] } // ------------------------------------------------------------------ // ValueErrors // ------------------------------------------------------------------ export class ValueErrorsUnknownTypeError extends TypeBoxError { constructor(public readonly schema: TSchema) { super('Unknown type') } } // ------------------------------------------------------------------ // EscapeKey // ------------------------------------------------------------------ function EscapeKey(key: string): string { return key.replace(/~/g, '~0').replace(/\//g, '~1') // RFC6901 Path } // ------------------------------------------------------------------ // Guards // ------------------------------------------------------------------ function IsDefined(value: unknown): value is T { return value !== undefined } // ------------------------------------------------------------------ // ValueErrorIterator // ------------------------------------------------------------------ export class ValueErrorIterator { constructor(private readonly iterator: IterableIterator) {} public [Symbol.iterator]() { return this.iterator } /** Returns the first value error or undefined if no errors */ public First(): ValueError | undefined { const next = this.iterator.next() return next.done ? undefined : next.value } } // -------------------------------------------------------------------------- // Create // -------------------------------------------------------------------------- function Create(errorType: ValueErrorType, schema: TSchema, path: string, value: unknown, errors: ValueErrorIterator[] = []): ValueError { return { type: errorType, schema, path, value, message: GetErrorFunction()({ errorType, path, schema, value, errors }), errors, } } // -------------------------------------------------------------------------- // Types // -------------------------------------------------------------------------- function* FromAny(schema: TAny, references: TSchema[], path: string, value: any): IterableIterator {} function* FromArgument(schema: TAny, references: TSchema[], path: string, value: any): IterableIterator {} function* FromArray(schema: TArray, references: TSchema[], path: string, value: any): IterableIterator { if (!IsArray(value)) { return yield Create(ValueErrorType.Array, schema, path, value) } if (IsDefined(schema.minItems) && !(value.length >= schema.minItems)) { yield Create(ValueErrorType.ArrayMinItems, schema, path, value) } if (IsDefined(schema.maxItems) && !(value.length <= schema.maxItems)) { yield Create(ValueErrorType.ArrayMaxItems, schema, path, value) } for (let i = 0; i < value.length; i++) { yield* Visit(schema.items, references, `${path}/${i}`, value[i]) } // prettier-ignore if (schema.uniqueItems === true && !((function () { const set = new Set(); for (const element of value) { const hashed = Hash(element); if (set.has(hashed)) { return false } else { set.add(hashed) } } return true })())) { yield Create(ValueErrorType.ArrayUniqueItems, schema, path, value) } // contains if (!(IsDefined(schema.contains) || IsDefined(schema.minContains) || IsDefined(schema.maxContains))) { return } const containsSchema = IsDefined(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) } if (IsNumber(schema.minContains) && containsCount < schema.minContains) { yield Create(ValueErrorType.ArrayMinContains, schema, path, value) } if (IsNumber(schema.maxContains) && containsCount > schema.maxContains) { yield Create(ValueErrorType.ArrayMaxContains, schema, path, value) } } function* FromAsyncIterator(schema: TAsyncIterator, references: TSchema[], path: string, value: any): IterableIterator { if (!IsAsyncIterator(value)) yield Create(ValueErrorType.AsyncIterator, schema, path, value) } function* FromBigInt(schema: TBigInt, references: TSchema[], path: string, value: any): IterableIterator { if (!IsBigInt(value)) return yield Create(ValueErrorType.BigInt, schema, path, value) if (IsDefined(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) { yield Create(ValueErrorType.BigIntExclusiveMaximum, schema, path, value) } if (IsDefined(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) { yield Create(ValueErrorType.BigIntExclusiveMinimum, schema, path, value) } if (IsDefined(schema.maximum) && !(value <= schema.maximum)) { yield Create(ValueErrorType.BigIntMaximum, schema, path, value) } if (IsDefined(schema.minimum) && !(value >= schema.minimum)) { yield Create(ValueErrorType.BigIntMinimum, schema, path, value) } if (IsDefined(schema.multipleOf) && !(value % schema.multipleOf === BigInt(0))) { yield Create(ValueErrorType.BigIntMultipleOf, schema, path, value) } } function* FromBoolean(schema: TBoolean, references: TSchema[], path: string, value: any): IterableIterator { if (!IsBoolean(value)) yield Create(ValueErrorType.Boolean, schema, path, value) } function* FromConstructor(schema: TConstructor, references: TSchema[], path: string, value: any): IterableIterator { yield* Visit(schema.returns, references, path, value.prototype) } function* FromDate(schema: TDate, references: TSchema[], path: string, value: any): IterableIterator { if (!IsDate(value)) return yield Create(ValueErrorType.Date, schema, path, value) if (IsDefined(schema.exclusiveMaximumTimestamp) && !(value.getTime() < schema.exclusiveMaximumTimestamp)) { yield Create(ValueErrorType.DateExclusiveMaximumTimestamp, schema, path, value) } if (IsDefined(schema.exclusiveMinimumTimestamp) && !(value.getTime() > schema.exclusiveMinimumTimestamp)) { yield Create(ValueErrorType.DateExclusiveMinimumTimestamp, schema, path, value) } if (IsDefined(schema.maximumTimestamp) && !(value.getTime() <= schema.maximumTimestamp)) { yield Create(ValueErrorType.DateMaximumTimestamp, schema, path, value) } if (IsDefined(schema.minimumTimestamp) && !(value.getTime() >= schema.minimumTimestamp)) { yield Create(ValueErrorType.DateMinimumTimestamp, schema, path, value) } if (IsDefined(schema.multipleOfTimestamp) && !(value.getTime() % schema.multipleOfTimestamp === 0)) { yield Create(ValueErrorType.DateMultipleOfTimestamp, schema, path, value) } } function* FromFunction(schema: TFunction, references: TSchema[], path: string, value: any): IterableIterator { if (!IsFunction(value)) yield Create(ValueErrorType.Function, schema, path, value) } function* FromImport(schema: TImport, references: TSchema[], path: string, value: any): IterableIterator { const definitions = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema yield* Visit(target, [...references, ...definitions], path, value) } function* FromInteger(schema: TInteger, references: TSchema[], path: string, value: any): IterableIterator { if (!IsInteger(value)) return yield Create(ValueErrorType.Integer, schema, path, value) if (IsDefined(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) { yield Create(ValueErrorType.IntegerExclusiveMaximum, schema, path, value) } if (IsDefined(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) { yield Create(ValueErrorType.IntegerExclusiveMinimum, schema, path, value) } if (IsDefined(schema.maximum) && !(value <= schema.maximum)) { yield Create(ValueErrorType.IntegerMaximum, schema, path, value) } if (IsDefined(schema.minimum) && !(value >= schema.minimum)) { yield Create(ValueErrorType.IntegerMinimum, schema, path, value) } if (IsDefined(schema.multipleOf) && !(value % schema.multipleOf === 0)) { yield Create(ValueErrorType.IntegerMultipleOf, schema, path, value) } } function* FromIntersect(schema: TIntersect, references: TSchema[], path: string, value: any): IterableIterator { let hasError = false for (const inner of schema.allOf) { for (const error of Visit(inner, references, path, value)) { hasError = true yield error } } if (hasError) { return yield Create(ValueErrorType.Intersect, schema, path, value) } if (schema.unevaluatedProperties === false) { 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) } } } if (typeof schema.unevaluatedProperties === 'object') { 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() if (!next.done) yield next.value // yield interior } } } } function* FromIterator(schema: TIterator, references: TSchema[], path: string, value: any): IterableIterator { if (!IsIterator(value)) yield Create(ValueErrorType.Iterator, schema, path, value) } function* FromLiteral(schema: TLiteral, references: TSchema[], path: string, value: any): IterableIterator { if (!(value === schema.const)) yield Create(ValueErrorType.Literal, schema, path, value) } function* FromNever(schema: TNever, references: TSchema[], path: string, value: any): IterableIterator { yield Create(ValueErrorType.Never, schema, path, value) } function* FromNot(schema: TNot, references: TSchema[], path: string, value: any): IterableIterator { if (Visit(schema.not, references, path, value).next().done === true) yield Create(ValueErrorType.Not, schema, path, value) } function* FromNull(schema: TNull, references: TSchema[], path: string, value: any): IterableIterator { if (!IsNull(value)) yield Create(ValueErrorType.Null, schema, path, value) } function* FromNumber(schema: TNumber, references: TSchema[], path: string, value: any): IterableIterator { if (!TypeSystemPolicy.IsNumberLike(value)) return yield Create(ValueErrorType.Number, schema, path, value) if (IsDefined(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) { yield Create(ValueErrorType.NumberExclusiveMaximum, schema, path, value) } if (IsDefined(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) { yield Create(ValueErrorType.NumberExclusiveMinimum, schema, path, value) } if (IsDefined(schema.maximum) && !(value <= schema.maximum)) { yield Create(ValueErrorType.NumberMaximum, schema, path, value) } if (IsDefined(schema.minimum) && !(value >= schema.minimum)) { yield Create(ValueErrorType.NumberMinimum, schema, path, value) } if (IsDefined(schema.multipleOf) && !(value % schema.multipleOf === 0)) { yield Create(ValueErrorType.NumberMultipleOf, schema, path, value) } } function* FromObject(schema: TObject, references: TSchema[], path: string, value: any): IterableIterator { if (!TypeSystemPolicy.IsObjectLike(value)) return yield Create(ValueErrorType.Object, schema, path, value) if (IsDefined(schema.minProperties) && !(Object.getOwnPropertyNames(value).length >= schema.minProperties)) { yield Create(ValueErrorType.ObjectMinProperties, schema, path, value) } if (IsDefined(schema.maxProperties) && !(Object.getOwnPropertyNames(value).length <= schema.maxProperties)) { yield Create(ValueErrorType.ObjectMaxProperties, schema, path, value) } const requiredKeys = Array.isArray(schema.required) ? schema.required : ([] as string[]) const knownKeys = Object.getOwnPropertyNames(schema.properties) const unknownKeys = Object.getOwnPropertyNames(value) for (const requiredKey of requiredKeys) { if (unknownKeys.includes(requiredKey)) continue yield Create(ValueErrorType.ObjectRequiredProperty, schema.properties[requiredKey], `${path}/${EscapeKey(requiredKey)}`, undefined) } if (schema.additionalProperties === false) { for (const valueKey of unknownKeys) { if (!knownKeys.includes(valueKey)) { yield Create(ValueErrorType.ObjectAdditionalProperties, schema, `${path}/${EscapeKey(valueKey)}`, value[valueKey]) } } } if (typeof schema.additionalProperties === 'object') { for (const valueKey of unknownKeys) { if (knownKeys.includes(valueKey)) continue 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 (ExtendsUndefinedCheck(schema) && !(knownKey in value)) { yield Create(ValueErrorType.ObjectRequiredProperty, property, `${path}/${EscapeKey(knownKey)}`, undefined) } } else { if (TypeSystemPolicy.IsExactOptionalProperty(value, knownKey)) { yield* Visit(property, references, `${path}/${EscapeKey(knownKey)}`, value[knownKey]) } } } } function* FromPromise(schema: TPromise, references: TSchema[], path: string, value: any): IterableIterator { if (!IsPromise(value)) yield Create(ValueErrorType.Promise, schema, path, value) } function* FromRecord(schema: TRecord, references: TSchema[], path: string, value: any): IterableIterator { if (!TypeSystemPolicy.IsRecordLike(value)) return yield Create(ValueErrorType.Object, schema, path, value) if (IsDefined(schema.minProperties) && !(Object.getOwnPropertyNames(value).length >= schema.minProperties)) { yield Create(ValueErrorType.ObjectMinProperties, schema, path, value) } if (IsDefined(schema.maxProperties) && !(Object.getOwnPropertyNames(value).length <= schema.maxProperties)) { yield Create(ValueErrorType.ObjectMaxProperties, schema, path, value) } const [patternKey, patternSchema] = Object.entries(schema.patternProperties)[0] const regex = new RegExp(patternKey) for (const [propertyKey, propertyValue] of Object.entries(value)) { if (regex.test(propertyKey)) yield* Visit(patternSchema, references, `${path}/${EscapeKey(propertyKey)}`, propertyValue) } if (typeof schema.additionalProperties === 'object') { for (const [propertyKey, propertyValue] of Object.entries(value)) { if (!regex.test(propertyKey)) yield* Visit(schema.additionalProperties as TSchema, references, `${path}/${EscapeKey(propertyKey)}`, propertyValue) } } if (schema.additionalProperties === false) { for (const [propertyKey, propertyValue] of Object.entries(value)) { if (regex.test(propertyKey)) continue return yield Create(ValueErrorType.ObjectAdditionalProperties, schema, `${path}/${EscapeKey(propertyKey)}`, propertyValue) } } } function* FromRef(schema: TRef, references: TSchema[], path: string, value: any): IterableIterator { yield* Visit(Deref(schema, references), references, path, value) } function* FromRegExp(schema: TRegExp, references: TSchema[], path: string, value: any): IterableIterator { if (!IsString(value)) return yield Create(ValueErrorType.String, schema, path, value) if (IsDefined(schema.minLength) && !(value.length >= schema.minLength)) { yield Create(ValueErrorType.StringMinLength, schema, path, value) } if (IsDefined(schema.maxLength) && !(value.length <= schema.maxLength)) { yield Create(ValueErrorType.StringMaxLength, schema, path, value) } 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 { if (!IsString(value)) return yield Create(ValueErrorType.String, schema, path, value) if (IsDefined(schema.minLength) && !(value.length >= schema.minLength)) { yield Create(ValueErrorType.StringMinLength, schema, path, value) } if (IsDefined(schema.maxLength) && !(value.length <= schema.maxLength)) { yield Create(ValueErrorType.StringMaxLength, schema, path, value) } if (IsString(schema.pattern)) { const regex = new RegExp(schema.pattern) if (!regex.test(value)) { yield Create(ValueErrorType.StringPattern, schema, path, value) } } if (IsString(schema.format)) { if (!FormatRegistry.Has(schema.format)) { yield Create(ValueErrorType.StringFormatUnknown, schema, path, value) } else { const format = FormatRegistry.Get(schema.format)! if (!format(value)) { yield Create(ValueErrorType.StringFormat, schema, path, value) } } } } function* FromSymbol(schema: TSymbol, references: TSchema[], path: string, value: any): IterableIterator { if (!IsSymbol(value)) yield Create(ValueErrorType.Symbol, schema, path, value) } function* FromTemplateLiteral(schema: TTemplateLiteral, references: TSchema[], path: string, value: any): IterableIterator { 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* FromThis(schema: TThis, references: TSchema[], path: string, value: any): IterableIterator { yield* Visit(Deref(schema, references), references, path, value) } function* FromTuple(schema: TTuple, references: TSchema[], path: string, value: any): IterableIterator { 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) } if (!(value.length === schema.maxItems)) { return yield Create(ValueErrorType.TupleLength, schema, path, value) } if (!schema.items) { return } for (let i = 0; i < schema.items.length; i++) { yield* Visit(schema.items[i], references, `${path}/${i}`, value[i]) } } function* FromUndefined(schema: TUndefined, references: TSchema[], path: string, value: any): IterableIterator { if (!IsUndefined(value)) yield Create(ValueErrorType.Undefined, schema, path, value) } function* FromUnion(schema: TUnion, references: TSchema[], path: string, value: any): IterableIterator { if (Check(schema, references, value)) return const errors = schema.anyOf.map((variant) => new ValueErrorIterator(Visit(variant, references, path, value))) yield Create(ValueErrorType.Union, schema, path, value, errors) } function* FromUint8Array(schema: TUint8Array, references: TSchema[], path: string, value: any): IterableIterator { if (!IsUint8Array(value)) return yield Create(ValueErrorType.Uint8Array, schema, path, value) if (IsDefined(schema.maxByteLength) && !(value.length <= schema.maxByteLength)) { yield Create(ValueErrorType.Uint8ArrayMaxByteLength, schema, path, value) } if (IsDefined(schema.minByteLength) && !(value.length >= schema.minByteLength)) { yield Create(ValueErrorType.Uint8ArrayMinByteLength, schema, path, value) } } function* FromUnknown(schema: TUnknown, references: TSchema[], path: string, value: any): IterableIterator {} function* FromVoid(schema: TVoid, references: TSchema[], path: string, value: any): IterableIterator { if (!TypeSystemPolicy.IsVoidLike(value)) yield Create(ValueErrorType.Void, schema, path, value) } function* FromKind(schema: TSchema, references: TSchema[], path: string, value: any): IterableIterator { const check = TypeRegistry.Get(schema[Kind])! if (!check(schema, value)) yield Create(ValueErrorType.Kind, schema, path, value) } function* Visit(schema: T, references: TSchema[], path: string, value: any): IterableIterator { const references_ = IsDefined(schema.$id) ? [...references, schema] : references const schema_ = schema as any switch (schema_[Kind]) { case 'Any': return yield* FromAny(schema_, references_, path, value) case 'Argument': return yield* FromArgument(schema_, references_, path, value) case 'Array': return yield* FromArray(schema_, references_, path, value) case 'AsyncIterator': return yield* FromAsyncIterator(schema_, references_, path, value) case 'BigInt': return yield* FromBigInt(schema_, references_, path, value) case 'Boolean': return yield* FromBoolean(schema_, references_, path, value) case 'Constructor': return yield* FromConstructor(schema_, references_, path, value) case 'Date': return yield* FromDate(schema_, references_, path, value) case 'Function': return yield* FromFunction(schema_, references_, path, value) case 'Import': return yield* FromImport(schema_, references_, path, value) case 'Integer': return yield* FromInteger(schema_, references_, path, value) case 'Intersect': return yield* FromIntersect(schema_, references_, path, value) case 'Iterator': return yield* FromIterator(schema_, references_, path, value) case 'Literal': return yield* FromLiteral(schema_, references_, path, value) case 'Never': return yield* FromNever(schema_, references_, path, value) case 'Not': return yield* FromNot(schema_, references_, path, value) case 'Null': return yield* FromNull(schema_, references_, path, value) case 'Number': return yield* FromNumber(schema_, references_, path, value) case 'Object': return yield* FromObject(schema_, references_, path, value) case 'Promise': return yield* FromPromise(schema_, references_, path, value) case 'Record': return yield* FromRecord(schema_, references_, path, value) case 'Ref': return yield* FromRef(schema_, references_, path, value) case 'RegExp': return yield* FromRegExp(schema_, references_, path, value) case 'String': return yield* FromString(schema_, references_, path, value) case 'Symbol': return yield* FromSymbol(schema_, references_, path, value) case 'TemplateLiteral': return yield* FromTemplateLiteral(schema_, references_, path, value) case 'This': return yield* FromThis(schema_, references_, path, value) case 'Tuple': return yield* FromTuple(schema_, references_, path, value) case 'Undefined': return yield* FromUndefined(schema_, references_, path, value) case 'Union': return yield* FromUnion(schema_, references_, path, value) case 'Uint8Array': return yield* FromUint8Array(schema_, references_, path, value) case 'Unknown': return yield* FromUnknown(schema_, references_, path, value) case 'Void': return yield* FromVoid(schema_, references_, path, value) default: 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(schema: T, references: TSchema[], value: unknown): ValueErrorIterator /** Returns an iterator for each error in this value. */ export function Errors(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]) return new ValueErrorIterator(iterator) } sinclairzx81-typebox-e0ec98c/src/errors/function.ts000066400000000000000000000217661505437577000225740ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/system The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { ValueErrorIterator, 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 'Expected 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 /** Interior errors for this error */ errors: ValueErrorIterator[] } 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 } sinclairzx81-typebox-e0ec98c/src/errors/index.ts000066400000000000000000000025211505437577000220420ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/errors The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './errors' export * from './function' sinclairzx81-typebox-e0ec98c/src/index.ts000066400000000000000000000104621505437577000205310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 * from './type/clone/index' export * from './type/create/index' export * from './type/error/index' export * from './type/guard/index' export * from './type/helpers/index' export * from './type/patterns/index' export * from './type/registry/index' export * from './type/sets/index' export * from './type/symbols/index' // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ export * from './type/any/index' export * from './type/array/index' export * from './type/argument/index' export * from './type/async-iterator/index' export * from './type/awaited/index' export * from './type/bigint/index' export * from './type/boolean/index' export * from './type/composite/index' export * from './type/const/index' export * from './type/constructor/index' export * from './type/constructor-parameters/index' export * from './type/date/index' export * from './type/enum/index' export * from './type/exclude/index' export * from './type/extends/index' export * from './type/extract/index' export * from './type/function/index' export * from './type/indexed/index' export * from './type/instance-type/index' export * from './type/instantiate/index' export * from './type/integer/index' export * from './type/intersect/index' export * from './type/iterator/index' export * from './type/intrinsic/index' export * from './type/keyof/index' export * from './type/literal/index' export * from './type/module/index' export * from './type/mapped/index' export * from './type/never/index' export * from './type/not/index' export * from './type/null/index' export * from './type/number/index' export * from './type/object/index' export * from './type/omit/index' export * from './type/optional/index' export * from './type/parameters/index' export * from './type/partial/index' export * from './type/pick/index' export * from './type/promise/index' export * from './type/readonly/index' export * from './type/readonly-optional/index' export * from './type/record/index' export * from './type/recursive/index' export * from './type/ref/index' export * from './type/regexp/index' export * from './type/required/index' export * from './type/rest/index' export * from './type/return-type/index' export * from './type/schema/index' export * from './type/static/index' export * from './type/string/index' export * from './type/symbol/index' export * from './type/template-literal/index' export * from './type/transform/index' export * from './type/tuple/index' export * from './type/uint8array/index' export * from './type/undefined/index' export * from './type/union/index' export * from './type/unknown/index' export * from './type/unsafe/index' export * from './type/void/index' // ------------------------------------------------------------------ // Type.* // ------------------------------------------------------------------ export * from './type/type/index' sinclairzx81-typebox-e0ec98c/src/parser/000077500000000000000000000000001505437577000203435ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/parser/index.ts000066400000000000000000000025461505437577000220310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 Runtime from './runtime/index' export * as Static from './static/index' sinclairzx81-typebox-e0ec98c/src/parser/runtime/000077500000000000000000000000001505437577000220265ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/parser/runtime/guard.ts000066400000000000000000000120641505437577000235030ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 { IArray, IConst, IContext, IIdent, INumber, IOptional, IRef, IString, ITuple, IUnion } from './types' // ------------------------------------------------------------------ // Value Guard // ------------------------------------------------------------------ // prettier-ignore function HasPropertyKey(value: Record, key: Key): value is Record & { [_ in Key]: unknown } { return key in value } // prettier-ignore function IsObjectValue(value: unknown): value is Record { return typeof value === 'object' && value !== null } // prettier-ignore function IsArrayValue(value: unknown): value is unknown[] { return globalThis.Array.isArray(value) } // ------------------------------------------------------------------ // Parser Guard // ------------------------------------------------------------------ /** Returns true if the value is a Array Parser */ export function IsArray(value: unknown): value is IArray { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Array' && HasPropertyKey(value, 'parser') && IsObjectValue(value.parser) } /** Returns true if the value is a Const Parser */ export function IsConst(value: unknown): value is IConst { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Const' && HasPropertyKey(value, 'value') && typeof value.value === 'string' } /** Returns true if the value is a Context Parser */ export function IsContext(value: unknown): value is IContext { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Context' && HasPropertyKey(value, 'left') && IsParser(value.left) && HasPropertyKey(value, 'right') && IsParser(value.right) } /** Returns true if the value is a Ident Parser */ export function IsIdent(value: unknown): value is IIdent { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Ident' } /** Returns true if the value is a Number Parser */ export function IsNumber(value: unknown): value is INumber { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Number' } /** Returns true if the value is a Optional Parser */ export function IsOptional(value: unknown): value is IOptional { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Optional' && HasPropertyKey(value, 'parser') && IsObjectValue(value.parser) } /** Returns true if the value is a Ref Parser */ export function IsRef(value: unknown): value is IRef { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Ref' && HasPropertyKey(value, 'ref') && typeof value.ref === 'string' } /** Returns true if the value is a String Parser */ export function IsString(value: unknown): value is IString { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'String' && HasPropertyKey(value, 'options') && IsArrayValue(value.options) } /** Returns true if the value is a Tuple Parser */ export function IsTuple(value: unknown): value is ITuple { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Tuple' && HasPropertyKey(value, 'parsers') && IsArrayValue(value.parsers) } /** Returns true if the value is a Union Parser */ export function IsUnion(value: unknown): value is IUnion { return IsObjectValue(value) && HasPropertyKey(value, 'type') && value.type === 'Union' && HasPropertyKey(value, 'parsers') && IsArrayValue(value.parsers) } /** Returns true if the value is a Parser */ export function IsParser(value: unknown) { // prettier-ignore return ( IsArray(value) || IsConst(value) || IsContext(value) || IsIdent(value) || IsNumber(value) || IsOptional(value) || IsRef(value) || IsString(value) || IsTuple(value) || IsUnion(value) ) } sinclairzx81-typebox-e0ec98c/src/parser/runtime/index.ts000066400000000000000000000026351505437577000235130ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 Guard from './guard' export * as Token from './token' export * from './types' export * from './module' export * from './parse' sinclairzx81-typebox-e0ec98c/src/parser/runtime/module.ts000066400000000000000000000047041505437577000236700ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 './types' import { Parse } from './parse' // ------------------------------------------------------------------ // Module // ------------------------------------------------------------------ export class Module { constructor(private readonly properties: Properties) {} /** Parses using one of the parsers defined on this instance */ public Parse(key: Key, content: string, context: unknown): [] | [Types.StaticParser, string] /** Parses using one of the parsers defined on this instance */ public Parse(key: Key, content: string): [] | [Types.StaticParser, string] /** Parses using one of the parsers defined on this instance */ public Parse(...args: any[]): never { // prettier-ignore const [key, content, context] = ( args.length === 3 ? [args[0], args[1], args[2]] : args.length === 2 ? [args[0], args[1], undefined] : (() => { throw Error('Invalid parse arguments') })() ) return Parse(this.properties, this.properties[key], content, context) as never } } sinclairzx81-typebox-e0ec98c/src/parser/runtime/parse.ts000066400000000000000000000210451505437577000235120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------------------------*/ import * as Guard from './guard' import * as Token from './token' import * as Types from './types' // ------------------------------------------------------------------ // Context // ------------------------------------------------------------------ function ParseContext(moduleProperties: ModuleProperties, left: Parser, right: Parser, code: string, context: unknown): unknown[] { const result = ParseParser(moduleProperties, left, code, context) return result.length === 2 ? ParseParser(moduleProperties, right, result[1], result[0]) : [] } // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ function ParseArray(moduleProperties: ModuleProperties, parser: Parser, code: string, context: unknown): unknown[] { const buffer = [] as unknown[] let rest = code while (rest.length > 0) { const result = ParseParser(moduleProperties, parser, rest, context) if (result.length === 0) return [buffer, rest] buffer.push(result[0]) rest = result[1] } return [buffer, rest] } // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ function ParseConst(value: Value, code: string, context: unknown): [] | [Value, string] { return Token.Const(value, code) as never } // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ function ParseIdent(code: string, _context: unknown): [] | [string, string] { return Token.Ident(code) } // ------------------------------------------------------------------ // Number // ------------------------------------------------------------------ // prettier-ignore function ParseNumber(code: string, _context: unknown): [] | [string, string] { return Token.Number(code) } // ------------------------------------------------------------------ // Optional // ------------------------------------------------------------------ function ParseOptional(moduleProperties: ModuleProperties, parser: Parser, code: string, context: unknown): [] | [[unknown] | [], unknown] { const result = ParseParser(moduleProperties, parser, code, context) return (result.length === 2 ? [[result[0]], result[1]] : [[], code]) as never } // ------------------------------------------------------------------ // Ref // ------------------------------------------------------------------ function ParseRef(moduleProperties: ModuleProperties, ref: Ref, code: string, context: unknown): [] | [string, string] { const parser = moduleProperties[ref] if (!Guard.IsParser(parser)) throw Error(`Cannot dereference Parser '${ref}'`) return ParseParser(moduleProperties, parser, code, context) as never } // ------------------------------------------------------------------ // String // ------------------------------------------------------------------ // prettier-ignore function ParseString(options: string[], code: string, _context: unknown): [] | [string, string] { return Token.String(options, code) } // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ function ParseTuple(moduleProperties: ModuleProperties, parsers: [...Parsers], code: string, context: unknown): [] | [unknown[], string] { const buffer = [] as unknown[] let rest = code for (const parser of parsers) { const result = ParseParser(moduleProperties, parser, rest, context) if (result.length === 0) return [] buffer.push(result[0]) rest = result[1] } return [buffer, rest] } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore function ParseUnion(moduleProperties: ModuleProperties, parsers: [...Parsers], code: string, context: unknown): [] | [unknown, string] { for(const parser of parsers) { const result = ParseParser(moduleProperties, parser, code, context) if(result.length === 0) continue return result } return [] } // ------------------------------------------------------------------ // Parser // ------------------------------------------------------------------ // prettier-ignore function ParseParser(moduleProperties: Types.IModuleProperties, parser: Parser, code: string, context: unknown): [] | [Types.StaticParser, string] { const result = ( Guard.IsContext(parser) ? ParseContext(moduleProperties, parser.left, parser.right, code, context) : Guard.IsArray(parser) ? ParseArray(moduleProperties, parser.parser, code, context) : Guard.IsConst(parser) ? ParseConst(parser.value, code, context) : Guard.IsIdent(parser) ? ParseIdent(code, context) : Guard.IsNumber(parser) ? ParseNumber(code, context) : Guard.IsOptional(parser) ? ParseOptional(moduleProperties, parser.parser, code, context) : Guard.IsRef(parser) ? ParseRef(moduleProperties, parser.ref, code, context) : Guard.IsString(parser) ? ParseString(parser.options, code, context) : Guard.IsTuple(parser) ? ParseTuple(moduleProperties, parser.parsers, code, context) : Guard.IsUnion(parser) ? ParseUnion(moduleProperties, parser.parsers, code, context) : [] ) return ( result.length === 2 ? [parser.mapping(result[0], context), result[1]] : result ) as never } // ------------------------------------------------------------------ // Parse // ------------------------------------------------------------------ /** Parses content using the given Parser */ // prettier-ignore export function Parse(moduleProperties: Types.IModuleProperties, parser: Parser, code: string, context: unknown): [] | [Types.StaticParser, string] /** Parses content using the given Parser */ // prettier-ignore export function Parse(moduleProperties: Types.IModuleProperties, parser: Parser, code: string): [] | [Types.StaticParser, string] /** Parses content using the given Parser */ // prettier-ignore export function Parse(parser: Parser, content: string, context: unknown): [] | [Types.StaticParser, string] /** Parses content using the given Parser */ // prettier-ignore export function Parse(parser: Parser, content: string): [] | [Types.StaticParser, string] /** Parses content using the given parser */ // prettier-ignore export function Parse(...args: any[]): never { const withModuleProperties = typeof args[1] === 'string' ? false : true const [moduleProperties, parser, content, context] = withModuleProperties ? [args[0], args[1], args[2], args[3]] : [{}, args[0], args[1], args[2]] return ParseParser(moduleProperties, parser, content, context) as never } sinclairzx81-typebox-e0ec98c/src/parser/runtime/token.ts000066400000000000000000000174601505437577000235260ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // Chars // ------------------------------------------------------------------ // prettier-ignore namespace Chars { /** Returns true if the char code is a whitespace */ export function IsWhitespace(value: number): boolean { return value === 32 } /** Returns true if the char code is a newline */ export function IsNewline(value: number): boolean { return value === 10 } /** Returns true if the char code is a alpha */ export function IsAlpha(value: number): boolean { return ( (value >= 65 && value <= 90) || // A-Z (value >= 97 && value <= 122) // a-z ) } /** Returns true if the char code is zero */ export function IsZero(value: number): boolean { return value === 48 } /** Returns true if the char code is non-zero */ export function IsNonZero(value: number): boolean { return value >= 49 && value <= 57 } /** Returns true if the char code is a digit */ export function IsDigit(value: number): boolean { return ( IsNonZero(value) || IsZero(value) ) } /** Returns true if the char code is a dot */ export function IsDot(value: number): boolean { return value === 46 } /** Returns true if this char code is a underscore */ export function IsUnderscore(value: unknown): boolean { return value === 95 } /** Returns true if this char code is a dollar sign */ export function IsDollarSign(value: unknown): boolean { return value === 36 } } // ------------------------------------------------------------------ // Trim // ------------------------------------------------------------------ // prettier-ignore namespace Trim { /** Trims Whitespace and retains Newline, Tabspaces, etc. */ export function TrimWhitespaceOnly(code: string): string { for (let i = 0; i < code.length; i++) { if (Chars.IsWhitespace(code.charCodeAt(i))) continue return code.slice(i) } return code } /** Trims Whitespace including Newline, Tabspaces, etc. */ export function TrimAll(code: string): string { return code.trimStart() } } // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ /** Checks the value matches the next string */ // prettier-ignore function NextTokenCheck(value: string, code: string): boolean { if (value.length > code.length) return false for (let i = 0; i < value.length; i++) { if (value.charCodeAt(i) !== code.charCodeAt(i)) return false } return true } /** Gets the next constant string value or empty if no match */ // prettier-ignore function NextConst(value: string, code: string, ): [] | [string, string] { return NextTokenCheck(value, code) ? [code.slice(0, value.length), code.slice(value.length)] : [] } /** Takes the next constant string value skipping any whitespace */ // prettier-ignore export function Const(value: string, code: string): [] | [string, string] { if(value.length === 0) return ['', code] const char_0 = value.charCodeAt(0) return ( Chars.IsNewline(char_0) ? NextConst(value, Trim.TrimWhitespaceOnly(code)) : Chars.IsWhitespace(char_0) ? NextConst(value, code) : NextConst(value, Trim.TrimAll(code)) ) } // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ // prettier-ignore function IdentIsFirst(char: number) { return ( Chars.IsAlpha(char) || Chars.IsDollarSign(char) || Chars.IsUnderscore(char) ) } // prettier-ignore function IdentIsRest(char: number) { return ( Chars.IsAlpha(char) || Chars.IsDigit(char) || Chars.IsDollarSign(char) || Chars.IsUnderscore(char) ) } // prettier-ignore function NextIdent(code: string): [] | [string, string] { if (!IdentIsFirst(code.charCodeAt(0))) return [] for (let i = 1; i < code.length; i++) { const char = code.charCodeAt(i) if (IdentIsRest(char)) continue const slice = code.slice(0, i) const rest = code.slice(i) return [slice, rest] } return [code, ''] } /** Scans for the next Ident token */ // prettier-ignore export function Ident(code: string): [] | [string, string] { return NextIdent(Trim.TrimAll(code)) } // ------------------------------------------------------------------ // Number // ------------------------------------------------------------------ /** Checks that the next number is not a leading zero */ // prettier-ignore function NumberLeadingZeroCheck(code: string, index: number) { const char_0 = code.charCodeAt(index + 0) const char_1 = code.charCodeAt(index + 1) return ( ( // 1-9 Chars.IsNonZero(char_0) ) || ( // 0 Chars.IsZero(char_0) && !Chars.IsDigit(char_1) ) || ( // 0. Chars.IsZero(char_0) && Chars.IsDot(char_1) ) || ( // .0 Chars.IsDot(char_0) && Chars.IsDigit(char_1) ) ) } /** Gets the next number token */ // prettier-ignore function NextNumber(code: string): [] | [string, string] { const negated = code.charAt(0) === '-' const index = negated ? 1 : 0 if (!NumberLeadingZeroCheck(code, index)) { return [] } const dash = negated ? '-' : '' let hasDot = false for (let i = index; i < code.length; i++) { const char_i = code.charCodeAt(i) if (Chars.IsDigit(char_i)) { continue } if (Chars.IsDot(char_i)) { if (hasDot) { const slice = code.slice(index, i) const rest = code.slice(i) return [`${dash}${slice}`, rest] } hasDot = true continue } const slice = code.slice(index, i) const rest = code.slice(i) return [`${dash}${slice}`, rest] } return [code, ''] } /** Scans for the next number token */ // prettier-ignore export function Number(code: string) { return NextNumber(Trim.TrimAll(code)) } // ------------------------------------------------------------------ // String // ------------------------------------------------------------------ // prettier-ignore function NextString(options: string[], code: string): [] | [string, string] { const first = code.charAt(0) if(!options.includes(first)) return [] const quote = first for(let i = 1; i < code.length; i++) { const char = code.charAt(i) if(char === quote) { const slice = code.slice(1, i) const rest = code.slice(i + 1) return [slice, rest] } } return [] } /** Scans the next Literal String value */ // prettier-ignore export function String(options: string[], code: string) { return NextString(options, Trim.TrimAll(code)) } sinclairzx81-typebox-e0ec98c/src/parser/runtime/types.ts000066400000000000000000000276511505437577000235550ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 type IModuleProperties = Record // ------------------------------------------------------------------ // Static // ------------------------------------------------------------------ /** Force output static type evaluation for Arrays */ export type StaticEnsure = T extends infer R ? R : never /** Infers the Output Parameter for a Parser */ export type StaticParser = Parser extends IParser ? Output : unknown // ------------------------------------------------------------------ // Mapping // ------------------------------------------------------------------ export type IMapping = (input: Input, context: any) => Output /** Maps input to output. This is the default Mapping */ export const Identity = (value: unknown) => value /** Maps the output as the given parameter T */ // prettier-ignore export const As = (mapping: T): ((value: unknown) => T) => (_: unknown) => mapping // ------------------------------------------------------------------ // Parser // ------------------------------------------------------------------ export interface IParser { type: string mapping: IMapping } // ------------------------------------------------------------------ // Context // ------------------------------------------------------------------ // prettier-ignore export type ContextParameter<_Left extends IParser, Right extends IParser> = ( StaticParser ) export interface IContext extends IParser { type: 'Context' left: IParser right: IParser } /** `[Context]` Creates a Context Parser */ export function Context>>(left: Left, right: Right, mapping: Mapping): IContext> /** `[Context]` Creates a Context Parser */ export function Context(left: Left, right: Right): IContext> /** `[Context]` Creates a Context Parser */ export function Context(...args: unknown[]): never { const [left, right, mapping] = args.length === 3 ? [args[0], args[1], args[2]] : [args[0], args[1], Identity] return { type: 'Context', left, right, mapping } as never } // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ // prettier-ignore export type ArrayParameter = StaticEnsure< StaticParser[] > export interface IArray extends IParser { type: 'Array' parser: IParser } /** `[EBNF]` Creates an Array Parser */ export function Array>>(parser: Parser, mapping: Mapping): IArray> /** `[EBNF]` Creates an Array Parser */ export function Array(parser: Parser): IArray> /** `[EBNF]` Creates an Array Parser */ export function Array(...args: unknown[]): never { const [parser, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity] return { type: 'Array', parser, mapping } as never } // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ export interface IConst extends IParser { type: 'Const' value: string } /** `[TERM]` Creates a Const Parser */ export function Const>(value: Value, mapping: Mapping): IConst> /** `[TERM]` Creates a Const Parser */ export function Const(value: Value): IConst /** `[TERM]` Creates a Const Parser */ export function Const(...args: unknown[]): never { const [value, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity] return { type: 'Const', value, mapping } as never } // ------------------------------------------------------------------ // Ref // ------------------------------------------------------------------ export interface IRef extends IParser { type: 'Ref' ref: string } /** `[BNF]` Creates a Ref Parser. This Parser can only be used in the context of a Module */ export function Ref>(ref: string, mapping: Mapping): IRef> /** `[BNF]` Creates a Ref Parser. This Parser can only be used in the context of a Module */ export function Ref(ref: string): IRef /** `[BNF]` Creates a Ref Parser. This Parser can only be used in the context of a Module */ export function Ref(...args: unknown[]): never { const [ref, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity] return { type: 'Ref', ref, mapping } as never } // ------------------------------------------------------------------ // String // ------------------------------------------------------------------ export interface IString extends IParser { type: 'String' options: string[] } /** `[TERM]` Creates a String Parser. Options are an array of permissable quote characters */ export function String>(options: string[], mapping: Mapping): IString> /** `[TERM]` Creates a String Parser. Options are an array of permissable quote characters */ export function String(options: string[]): IString /** `[TERM]` Creates a String Parser. Options are an array of permissable quote characters */ export function String(...params: unknown[]): never { const [options, mapping] = params.length === 2 ? [params[0], params[1]] : [params[0], Identity] return { type: 'String', options, mapping } as never } // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ export interface IIdent extends IParser { type: 'Ident' } /** `[TERM]` Creates an Ident Parser where Ident matches any valid JavaScript identifier */ export function Ident>(mapping: Mapping): IIdent> /** `[TERM]` Creates an Ident Parser where Ident matches any valid JavaScript identifier */ export function Ident(): IIdent /** `[TERM]` Creates an Ident Parser where Ident matches any valid JavaScript identifier */ export function Ident(...params: unknown[]): never { const mapping = params.length === 1 ? params[0] : Identity return { type: 'Ident', mapping } as never } // ------------------------------------------------------------------ // Number // ------------------------------------------------------------------ export interface INumber extends IParser { type: 'Number' } /** `[TERM]` Creates an Number Parser */ export function Number>(mapping: Mapping): INumber> /** `[TERM]` Creates an Number Parser */ export function Number(): INumber /** `[TERM]` Creates an Number Parser */ export function Number(...params: unknown[]): never { const mapping = params.length === 1 ? params[0] : Identity return { type: 'Number', mapping } as never } // ------------------------------------------------------------------ // Optional // ------------------------------------------------------------------ // prettier-ignore export type OptionalParameter] | []> = ( Result ) export interface IOptional extends IParser { type: 'Optional' parser: IParser } /** `[EBNF]` Creates an Optional Parser */ export function Optional>>(parser: Parser, mapping: Mapping): IOptional> /** `[EBNF]` Creates an Optional Parser */ export function Optional(parser: Parser): IOptional> /** `[EBNF]` Creates an Optional Parser */ export function Optional(...args: unknown[]): never { const [parser, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity] return { type: 'Optional', parser, mapping } as never } // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ // prettier-ignore export type TupleParameter = StaticEnsure< Parsers extends [infer Left extends IParser, ...infer Right extends IParser[]] ? TupleParameter>]> : Result > export interface ITuple extends IParser { type: 'Tuple' parsers: IParser[] } /** `[BNF]` Creates a Tuple Parser */ export function Tuple>>(parsers: [...Parsers], mapping: Mapping): ITuple> /** `[BNF]` Creates a Tuple Parser */ export function Tuple(parsers: [...Parsers]): ITuple> /** `[BNF]` Creates a Tuple Parser */ export function Tuple(...args: unknown[]): never { const [parsers, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity] return { type: 'Tuple', parsers, mapping } as never } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore export type UnionParameter = StaticEnsure< Parsers extends [infer Left extends IParser, ...infer Right extends IParser[]] ? UnionParameter> : Result > export interface IUnion extends IParser { type: 'Union' parsers: IParser[] } /** `[BNF]` Creates a Union parser */ export function Union>>(parsers: [...Parsers], mapping: Mapping): IUnion> /** `[BNF]` Creates a Union parser */ export function Union(parsers: [...Parsers]): IUnion> /** `[BNF]` Creates a Union parser */ export function Union(...args: unknown[]): never { const [parsers, mapping] = args.length === 2 ? [args[0], args[1]] : [args[0], Identity] return { type: 'Union', parsers, mapping } as never } sinclairzx81-typebox-e0ec98c/src/parser/static/000077500000000000000000000000001505437577000216325ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/parser/static/index.ts000066400000000000000000000025431505437577000233150ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 Token from './token' export * from './parse' export * from './types' sinclairzx81-typebox-e0ec98c/src/parser/static/parse.ts000066400000000000000000000154641505437577000233260ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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 Tokens from './token' import * as Types from './types' // ------------------------------------------------------------------ // Context // ------------------------------------------------------------------ // prettier-ignore type ContextParser = ( Parse extends [infer Context extends unknown, infer Rest extends string] ? Parse : [] ) // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ // prettier-ignore type ArrayParser = ( Parse extends [infer Value1 extends unknown, infer Rest extends string] ? ArrayParser : [Result, Code] ) // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ // prettier-ignore type ConstParser = ( Tokens.Const extends [infer Match extends Value, infer Rest extends string] ? [Match, Rest] : [] ) // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ // prettier-ignore type IdentParser = ( Tokens.Ident extends [infer Match extends string, infer Rest extends string] ? [Match, Rest] : [] ) // ------------------------------------------------------------------ // Number // ------------------------------------------------------------------ // prettier-ignore type NumberParser = ( Tokens.Number extends [infer Match extends string, infer Rest extends string] ? [Match, Rest] : [] ) // ------------------------------------------------------------------ // Optional // ------------------------------------------------------------------ // prettier-ignore type OptionalParser = ( Parse extends [infer Value extends unknown, infer Rest extends string] ? [[Value], Rest] : [[], Code] ) // ------------------------------------------------------------------ // String // ------------------------------------------------------------------ // prettier-ignore type StringParser = ( Tokens.String extends [infer Match extends string, infer Rest extends string] ? [Match, Rest] : [] ) // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ // prettier-ignore type TupleParser = ( Parsers extends [infer Left extends Types.IParser, ...infer Right extends Types.IParser[]] ? Parse extends [infer Value extends unknown, infer Rest extends string] ? TupleParser : [] : [Result, Code] ) // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore type UnionParser = ( Parsers extends [infer Left extends Types.IParser, ...infer Right extends Types.IParser[]] ? Parse extends [infer Value extends unknown, infer Rest extends string] ? [Value, Rest] : UnionParser : [] ) // ------------------------------------------------------------------ // Parse // ------------------------------------------------------------------ // prettier-ignore type ParseCode = ( Type extends Types.Context ? ContextParser : Type extends Types.Array ? ArrayParser : Type extends Types.Const ? ConstParser : Type extends Types.Ident ? IdentParser : Type extends Types.Number ? NumberParser : Type extends Types.Optional ? OptionalParser : Type extends Types.String ? StringParser : Type extends Types.Tuple ? TupleParser : Type extends Types.Union ? UnionParser : [] ) // prettier-ignore type ParseMapping = ( (Parser['mapping'] & { input: Result, context: Context })['output'] ) /** Parses code with the given parser */ // prettier-ignore export type Parse = ( ParseCode extends [infer L extends unknown, infer R extends string] ? [ParseMapping, R] : [] ) sinclairzx81-typebox-e0ec98c/src/parser/static/token.ts000066400000000000000000000207621505437577000233310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // Chars // ------------------------------------------------------------------ // prettier-ignore namespace Chars { export type Empty = '' export type Space = ' ' export type Newline = '\n' export type Dot = '.' export type Hyphen = '-' export type Digit = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] export type Alpha = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ] } // ------------------------------------------------------------------ // Trim // ------------------------------------------------------------------ // prettier-ignore namespace Trim { // ------------------------------------------------------------------ // Whitespace Filters // ------------------------------------------------------------------ type W9 = `${W8}${W8}` // 512 type W8 = `${W7}${W7}` // 256 type W7 = `${W6}${W6}` // 128 type W6 = `${W5}${W5}` // 64 type W5 = `${W4}${W4}` // 32 type W4 = `${W3}${W3}` // 16 type W3 = `${W2}${W2}` // 8 type W2 = `${W1}${W1}` // 4 type W1 = `${W0}${W0}` // 2 type W0 = ` ` // 1 // ------------------------------------------------------------------ // TrimWhitespace // ------------------------------------------------------------------ /** Trims whitespace only */ export type TrimWhitespace = ( Code extends `${W4}${infer Rest extends string}` ? TrimWhitespace : Code extends `${W3}${infer Rest extends string}` ? TrimWhitespace : Code extends `${W1}${infer Rest extends string}` ? TrimWhitespace : Code extends `${W0}${infer Rest extends string}` ? TrimWhitespace : Code ) // ------------------------------------------------------------------ // Trim // ------------------------------------------------------------------ /** Trims Whitespace and Newline */ export type TrimAll = ( Code extends `${W4}${infer Rest extends string}` ? TrimAll : Code extends `${W3}${infer Rest extends string}` ? TrimAll : Code extends `${W1}${infer Rest extends string}` ? TrimAll : Code extends `${W0}${infer Rest extends string}` ? TrimAll : Code extends `${Chars.Newline}${infer Rest extends string}` ? TrimAll : Code ) } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ /** Scans for the next match union */ // prettier-ignore type NextUnion = ( Variants extends [infer Variant extends string, ...infer Rest1 extends string[]] ? NextConst extends [infer Match extends string, infer Rest2 extends string] ? [Match, Rest2] : NextUnion : [] ) // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ // prettier-ignore type NextConst = ( Code extends `${Value}${infer Rest extends string}` ? [Value, Rest] : [] ) /** Scans for the next constant value */ // prettier-ignore export type Const = ( Value extends '' ? ['', Code] : Value extends `${infer First extends string}${string}` ? ( First extends Chars.Newline ? NextConst> : First extends Chars.Space ? NextConst : NextConst> ) : never ) // ------------------------------------------------------------------ // Number // ------------------------------------------------------------------ // prettier-ignore type NextNumberNegate = ( Code extends `${Chars.Hyphen}${infer Rest extends string}` ? [Chars.Hyphen, Rest] : [Chars.Empty, Code] ) // prettier-ignore type NextNumberZeroCheck = ( Code extends `0${infer Rest}` ? NextUnion extends [string, string] ? false : true : true ) // prettier-ignore type NextNumberScan = ( NextUnion<[...Chars.Digit, Chars.Dot], Code> extends [infer Char extends string, infer Rest extends string] ? Char extends Chars.Dot ? HasDecimal extends false ? NextNumberScan : [Result, `.${Rest}`] : NextNumberScan : [Result, Code] ) // prettier-ignore export type NextNumber = ( NextNumberNegate extends [infer Negate extends string, infer Rest extends string] ? NextNumberZeroCheck extends true ? NextNumberScan extends [infer Number extends string, infer Rest2 extends string] ? Number extends Chars.Empty ? [] : [`${Negate}${Number}`, Rest2] : [] : [] : [] ) /** Scans for the next literal number */ export type Number = NextNumber> // ------------------------------------------------------------------ // String // ------------------------------------------------------------------ type NextStringQuote = NextUnion // prettier-ignore type NextStringBody = ( Code extends `${infer Char extends string}${infer Rest extends string}` ? Char extends Quote ? [Result, Rest] : NextStringBody : [] ) // prettier-ignore type NextString = ( NextStringQuote extends [infer Quote extends string, infer Rest extends string] ? NextStringBody extends [infer String extends string, infer Rest extends string] ? [String, Rest] : [] : [] ) /** Scans for the next literal string */ export type String = NextString> // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ type IdentLeft = [...Chars.Alpha, '_', '$'] // permissable first characters type IdentRight = [...Chars.Digit, ...IdentLeft] // permissible subsequent characters // prettier-ignore type NextIdentScan = ( NextUnion extends [infer Char extends string, infer Rest extends string] ? NextIdentScan : [Result, Code] ) // prettier-ignore type NextIdent = ( NextUnion extends [infer Left extends string, infer Rest1 extends string] ? NextIdentScan extends [infer Right extends string, infer Rest2 extends string] ? [`${Left}${Right}`, Rest2] : [] : [] ) /** Scans for the next Ident */ export type Ident = NextIdent> sinclairzx81-typebox-e0ec98c/src/parser/static/types.ts000066400000000000000000000127121505437577000233510ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/parsebox The MIT License (MIT) Copyright (c) 2024 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // Mapping // ------------------------------------------------------------------ /** * `[ACTION]` Inference mapping base type. Used to specify semantic actions for * Parser productions. This type is implemented as a higher-kinded type where * productions are received on the `input` property with mapping assigned * the `output` property. The parsing context is available on the `context` * property. */ export interface IMapping { context: unknown input: unknown output: unknown } /** `[ACTION]` Default inference mapping. */ export interface Identity extends IMapping { output: this['input'] } /** `[ACTION]` Maps the given argument `T` as the mapping output */ export interface As extends IMapping { output: T } // ------------------------------------------------------------------ // Parser // ------------------------------------------------------------------ /** Base type Parser implemented by all other parsers */ export interface IParser { type: string mapping: Mapping } // ------------------------------------------------------------------ // Context // ------------------------------------------------------------------ /** `[Context]` Creates a Context Parser */ export interface Context extends IParser { type: 'Context' left: Left right: Right } // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ /** `[EBNF]` Creates an Array Parser */ export interface Array extends IParser { type: 'Array' parser: Parser } // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ /** `[TERM]` Creates a Const Parser */ export interface Const extends IParser { type: 'Const' value: Value } // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ /** `[TERM]` Creates an Ident Parser. */ // prettier-ignore export interface Ident extends IParser { type: 'Ident' } // ------------------------------------------------------------------ // Number // ------------------------------------------------------------------ /** `[TERM]` Creates a Number Parser. */ // prettier-ignore export interface Number extends IParser { type: 'Number' } // ------------------------------------------------------------------ // Optional // ------------------------------------------------------------------ /** `[EBNF]` Creates a Optional Parser */ export interface Optional extends IParser { type: 'Optional' parser: Parser } // ------------------------------------------------------------------ // String // ------------------------------------------------------------------ /** `[TERM]` Creates a String Parser. Options are an array of permissable quote characters */ export interface String extends IParser { type: 'String' quote: Options } // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ /** `[BNF]` Creates a Tuple Parser */ export interface Tuple extends IParser { type: 'Tuple' parsers: [...Parsers] } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ /** `[BNF]` Creates a Union Parser */ export interface Union extends IParser { type: 'Union' parsers: [...Parsers] } sinclairzx81-typebox-e0ec98c/src/syntax/000077500000000000000000000000001505437577000203755ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/syntax/index.ts000066400000000000000000000024661505437577000220640ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/syntax The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './syntax' sinclairzx81-typebox-e0ec98c/src/syntax/mapping.ts000066400000000000000000001371671505437577000224170ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/syntax The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------------------------*/ import * as T from '../type/index' // ------------------------------------------------------------------ // // Dereference // // Referential types pull from the Context or defer dereferencing // for later execution. This overlaps with module dereferencing, // where named identifiers in the syntax are deferred until // instantiation. This code should be revised as part of a // general-purpose Instantiate module (next revision) // // ------------------------------------------------------------------ // prettier-ignore type TDereference = ( Key extends keyof Context ? Context[Key] : T.TRef ) // prettier-ignore const Dereference = (context: T.TProperties, key: string): T.TSchema => { return key in context ? context[key] : T.Ref(key) } // ------------------------------------------------------------------ // // Delimited // // Delimited sequences use an accumulated buffer to parse sequence // tokens. This approach is more scalable than using a Union + Tuple // + Epsilon pattern, as TypeScript can instantiate deeper when // tail-call recursive accumulators are employed. However, this // comes with a latent processing cost due to the need to decode // the accumulated buffer. // // - Encoding: [[, ','][], [] | []] // // ------------------------------------------------------------------ // prettier-ignore type TDelimitedDecode = ( Input extends [infer Left, ...infer Right] ? Left extends [infer Item, infer _] ? TDelimitedDecode : TDelimitedDecode : Result ) // prettier-ignore type TDelimited = Input extends [infer Left extends unknown[], infer Right extends unknown[]] ? TDelimitedDecode<[...Left, ...Right]> : [] // prettier-ignore const DelimitedDecode = (input: ([unknown, unknown] | unknown)[], result: unknown[] = []) => { return input.reduce((result, left) => { return T.ValueGuard.IsArray(left) && left.length === 2 ? [...result, left[0]] : [...result, left] }, []) } // prettier-ignore const Delimited = (input: [unknown, unknown]) => { const [left, right] = input as [unknown[], unknown[]] return DelimitedDecode([...left, ...right]) } // ------------------------------------------------------------------- // GenericReferenceParameterList: [[Type, ','][], [Type] | []] // ------------------------------------------------------------------- // prettier-ignore export type TGenericReferenceParameterListMapping = TDelimited // prettier-ignore export function GenericReferenceParameterListMapping(input: [unknown, unknown], context: unknown) { return Delimited(input) } // ------------------------------------------------------------------- // GenericReference: [, '<', GenericReferenceParameterList, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TGenericReferenceMapping'] ? T.TInstantiate, Args> : never : never > = Result // prettier-ignore export function GenericReferenceMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const type = Dereference(context as T.TProperties, input[0] as string) const args = input[2] as T.TSchema[] return T.Instantiate(type, args) } // ------------------------------------------------------------------- // GenericArgumentsList: [[, ','][], [] | []] // ------------------------------------------------------------------- // prettier-ignore export type TGenericArgumentsListMapping = TDelimited // prettier-ignore export function GenericArgumentsListMapping(input: [unknown, unknown], context: unknown) { return Delimited(input) } // ------------------------------------------------------------------- // GenericArguments: ['<', GenericArgumentsList, '>'] // ------------------------------------------------------------------- // prettier-ignore type GenericArgumentsContext = ( Arguments extends [...infer Left extends string[], infer Right extends string] ? GenericArgumentsContext }> : T.Evaluate ) // prettier-ignore export type TGenericArgumentsMapping = Input extends ['<', infer Arguments extends string[], '>'] ? Context extends infer Context extends T.TProperties ? GenericArgumentsContext : never : never // ... // prettier-ignore const GenericArgumentsContext = (_arguments: string[], context: T.TProperties) => { return _arguments.reduce((result, arg, index) => { return { ...result, [arg]: T.Argument(index) } }, context) } // prettier-ignore export function GenericArgumentsMapping(input: [unknown, unknown, unknown], context: unknown) { return input.length === 3 ? GenericArgumentsContext(input[1] as string[], context as T.TProperties) : {} } // ------------------------------------------------------------------- // KeywordString: 'string' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordStringMapping = T.TString // prettier-ignore export function KeywordStringMapping(input: 'string', context: unknown) { return T.String() } // ------------------------------------------------------------------- // KeywordNumber: 'number' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordNumberMapping = T.TNumber // prettier-ignore export function KeywordNumberMapping(input: 'number', context: unknown) { return T.Number() } // ------------------------------------------------------------------- // KeywordBoolean: 'boolean' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordBooleanMapping = T.TBoolean // prettier-ignore export function KeywordBooleanMapping(input: 'boolean', context: unknown) { return T.Boolean() } // ------------------------------------------------------------------- // KeywordUndefined: 'undefined' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordUndefinedMapping = T.TUndefined // prettier-ignore export function KeywordUndefinedMapping(input: 'undefined', context: unknown) { return T.Undefined() } // ------------------------------------------------------------------- // KeywordNull: 'null' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordNullMapping = T.TNull // prettier-ignore export function KeywordNullMapping(input: 'null', context: unknown) { return T.Null() } // ------------------------------------------------------------------- // KeywordInteger: 'integer' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordIntegerMapping = T.TInteger // prettier-ignore export function KeywordIntegerMapping(input: 'integer', context: unknown) { return T.Integer() } // ------------------------------------------------------------------- // KeywordBigInt: 'bigint' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordBigIntMapping = T.TBigInt // prettier-ignore export function KeywordBigIntMapping(input: 'bigint', context: unknown) { return T.BigInt() } // ------------------------------------------------------------------- // KeywordUnknown: 'unknown' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordUnknownMapping = T.TUnknown // prettier-ignore export function KeywordUnknownMapping(input: 'unknown', context: unknown) { return T.Unknown() } // ------------------------------------------------------------------- // KeywordAny: 'any' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordAnyMapping = T.TAny // prettier-ignore export function KeywordAnyMapping(input: 'any', context: unknown) { return T.Any() } // ------------------------------------------------------------------- // KeywordNever: 'never' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordNeverMapping = T.TNever // prettier-ignore export function KeywordNeverMapping(input: 'never', context: unknown) { return T.Never() } // ------------------------------------------------------------------- // KeywordSymbol: 'symbol' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordSymbolMapping = T.TSymbol // prettier-ignore export function KeywordSymbolMapping(input: 'symbol', context: unknown) { return T.Symbol() } // ------------------------------------------------------------------- // KeywordVoid: 'void' // ------------------------------------------------------------------- // prettier-ignore export type TKeywordVoidMapping = T.TVoid // prettier-ignore export function KeywordVoidMapping(input: 'void', context: unknown) { return T.Void() } // ------------------------------------------------------------------- // Keyword: KeywordString | KeywordNumber | KeywordBoolean | KeywordUndefined | KeywordNull | KeywordInteger | KeywordBigInt | KeywordUnknown | KeywordAny | KeywordNever | KeywordSymbol | KeywordVoid // ------------------------------------------------------------------- // prettier-ignore export type TKeywordMapping = Input // prettier-ignore export function KeywordMapping(input: unknown, context: unknown) { return input } // ------------------------------------------------------------------- // LiteralString: // ------------------------------------------------------------------- // prettier-ignore export type TLiteralStringMapping = Input extends T.TLiteralValue ? T.TLiteral : never // prettier-ignore export function LiteralStringMapping(input: string, context: unknown) { return T.Literal(input) } // ------------------------------------------------------------------- // LiteralNumber: // ------------------------------------------------------------------- // prettier-ignore export type TLiteralNumberMapping = Input extends `${infer Value extends number}` ? T.TLiteral : never // prettier-ignore export function LiteralNumberMapping(input: string, context: unknown) { return T.Literal(parseFloat(input)) } // ------------------------------------------------------------------- // LiteralBoolean: 'true' | 'false' // ------------------------------------------------------------------- // prettier-ignore export type TLiteralBooleanMapping = Input extends 'true' ? T.TLiteral : T.TLiteral // prettier-ignore export function LiteralBooleanMapping(input: 'true' | 'false', context: unknown) { return T.Literal(input === 'true') } // ------------------------------------------------------------------- // Literal: LiteralBoolean | LiteralNumber | LiteralString // ------------------------------------------------------------------- // prettier-ignore export type TLiteralMapping = Input // prettier-ignore export function LiteralMapping(input: unknown, context: unknown) { return input } // ------------------------------------------------------------------- // KeyOf: ['keyof'] | [] // ------------------------------------------------------------------- // prettier-ignore export type TKeyOfMapping = Input extends [unknown] ? true : false // prettier-ignore export function KeyOfMapping(input: [unknown] | [], context: unknown) { return input.length > 0 } // ------------------------------------------------------------------- // IndexArray: ['[', Type, ']'] | ['[', ']'][] // ------------------------------------------------------------------- // prettier-ignore type TIndexArrayMappingReduce = ( Input extends [infer Left extends unknown, ...infer Right extends unknown[]] ? Left extends ['[', infer Type extends T.TSchema, ']'] ? TIndexArrayMappingReduce : TIndexArrayMappingReduce : Result ) // prettier-ignore export type TIndexArrayMapping = Input extends unknown[] ? TIndexArrayMappingReduce : [] // prettier-ignore export function IndexArrayMapping(input: ([unknown, unknown, unknown] | [unknown, unknown])[], context: unknown) { return input.reduce((result: unknown[], current) => { return current.length === 3 ? [...result, [current[1]]] : [...result, []] }, [] as unknown[]) } // ------------------------------------------------------------------- // Extends: ['extends', Type, '?', Type, ':', Type] | [] // ------------------------------------------------------------------- // prettier-ignore export type TExtendsMapping = Input extends ['extends', infer Type extends T.TSchema, '?', infer True extends T.TSchema, ':', infer False extends T.TSchema] ? [Type, True, False] : [] // prettier-ignore export function ExtendsMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown] | [], context: unknown) { return input.length === 6 ? [input[1], input[3], input[5]] : [] } // ------------------------------------------------------------------- // Base: ['(', Type, ')'] | Keyword | Object | Tuple | Literal | Constructor | Function | Mapped | AsyncIterator | Iterator | ConstructorParameters | FunctionParameters | InstanceType | ReturnType | Argument | Awaited | Array | Record | Promise | Partial | Required | Pick | Omit | Exclude | Extract | Uppercase | Lowercase | Capitalize | Uncapitalize | Date | Uint8Array | GenericReference | Reference // ------------------------------------------------------------------- // prettier-ignore export type TBaseMapping = ( Input extends ['(', infer Type extends T.TSchema, ')'] ? Type : Input extends infer Type extends T.TSchema ? Type : never ) // prettier-ignore export function BaseMapping(input: [unknown, unknown, unknown] | unknown, context: unknown) { return T.ValueGuard.IsArray(input) && input.length === 3 ? input[1] : input } // ------------------------------------------------------------------- // Factor: [KeyOf, Base, IndexArray, Extends] // ------------------------------------------------------------------- // prettier-ignore type TFactorIndexArray = ( IndexArray extends [...infer Left extends unknown[], infer Right extends T.TSchema[]] ? ( Right extends [infer Indexer extends T.TSchema] ? T.TIndex, T.TIndexPropertyKeys> : Right extends [] ? T.TArray> : T.TNever ) : Type ) // prettier-ignore type TFactorExtends = ( Extends extends [infer Right extends T.TSchema, infer True extends T.TSchema, infer False extends T.TSchema] ? T.TExtends : Type ) // prettier-ignore export type TFactorMapping = Input extends [infer KeyOf extends boolean, infer Type extends T.TSchema, infer IndexArray extends unknown[], infer Extends extends unknown[]] ? KeyOf extends true ? TFactorExtends>, Extends> : TFactorExtends, Extends> : never // ... // prettier-ignore const FactorIndexArray = (Type: T.TSchema, indexArray: unknown[]): T.TSchema => { return indexArray.reduceRight((result, right) => { const _right = right as T.TSchema[] return ( _right.length === 1 ? T.Index(result, _right[0]) : _right.length === 0 ? T.Array(result, _right[0]) : T.Never() ) }, Type) } // prettier-ignore const FactorExtends = (Type: T.TSchema, Extends: T.TSchema[]) => { return Extends.length === 3 ? T.Extends(Type, Extends[0], Extends[1], Extends[2]) : Type } // prettier-ignore export function FactorMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [KeyOf, Type, IndexArray, Extends] = input as [boolean, T.TSchema, unknown[], T.TSchema[]] return KeyOf ? FactorExtends(T.KeyOf(FactorIndexArray(Type, IndexArray)), Extends) : FactorExtends(FactorIndexArray(Type, IndexArray), Extends) } // ------------------------------------------------------------------ // // ExprBinaryMapping // // TypeBox Union and Intersection types are flattened to prevent // excessive nesting of `anyOf` and `allOf`, ensuring a more // readable and presentable type for the user. This function // recursively reduces Union and Intersection types based on // binary expressions parsed from input. // // ------------------------------------------------------------------ // prettier-ignore type TExprBinaryMapping = ( Rest extends [infer Operator extends unknown, infer Right extends T.TSchema, infer Next extends unknown[]] ? ( TExprBinaryMapping extends infer Schema extends T.TSchema ? ( Operator extends '&' ? ( Schema extends T.TIntersect ? T.TIntersect<[Left, ...Types]> : T.TIntersect<[Left, Schema]> ) : Operator extends '|' ? ( Schema extends T.TUnion ? T.TUnion<[Left, ...Types]> : T.TUnion<[Left, Schema]> ) : never ) : never ) : Left ) // prettier-ignore function ExprBinaryMapping(Left: T.TSchema, Rest: unknown[]): T.TSchema { return ( Rest.length === 3 ? (() => { const [Operator, Right, Next] = Rest as [string, T.TSchema, unknown[]] const Schema = ExprBinaryMapping(Right, Next) if (Operator === '&') { return T.TypeGuard.IsIntersect(Schema) ? T.Intersect([Left, ...Schema.allOf]) : T.Intersect([Left, Schema]) } if (Operator === '|') { return T.TypeGuard.IsUnion(Schema) ? T.Union([Left, ...Schema.anyOf]) : T.Union([Left, Schema]) } throw 1 })() : Left ) } // ------------------------------------------------------------------- // ExprTermTail: ['&', Factor, ExprTermTail] | [] // ------------------------------------------------------------------- // prettier-ignore export type TExprTermTailMapping = Input // prettier-ignore export function ExprTermTailMapping(input: [unknown, unknown, unknown] | [], context: unknown) { return input } // ------------------------------------------------------------------- // ExprTerm: [Factor, ExprTermTail] // ------------------------------------------------------------------- // prettier-ignore export type TExprTermMapping = ( Input extends [infer Left extends T.TSchema, infer Rest extends unknown[]] ? TExprBinaryMapping : [] ) // prettier-ignore export function ExprTermMapping(input: [unknown, unknown], context: unknown) { const [left, rest] = input as [T.TSchema, unknown[]] return ExprBinaryMapping(left, rest) } // ------------------------------------------------------------------- // ExprTail: ['|', ExprTerm, ExprTail] | [] // ------------------------------------------------------------------- // prettier-ignore export type TExprTailMapping = Input // prettier-ignore export function ExprTailMapping(input: [unknown, unknown, unknown] | [], context: unknown) { return input } // ------------------------------------------------------------------- // Expr: [ExprTerm, ExprTail] // ------------------------------------------------------------------- // prettier-ignore export type TExprMapping = Input extends [infer Left extends T.TSchema, infer Rest extends unknown[]] ? TExprBinaryMapping : [] // prettier-ignore export function ExprMapping(input: [unknown, unknown], context: unknown) { const [left, rest] = input as [T.TSchema, unknown[]] return ExprBinaryMapping(left, rest) } // ------------------------------------------------------------------- // Type: GenericArguments -> Expr | Expr // ------------------------------------------------------------------- // prettier-ignore export type TTypeMapping = Input // prettier-ignore export function TypeMapping(input: unknown, context: unknown) { return input } // ------------------------------------------------------------------- // PropertyKey: | // ------------------------------------------------------------------- // prettier-ignore export type TPropertyKeyMapping = Input // prettier-ignore export function PropertyKeyMapping(input: string, context: unknown) { return input } // ------------------------------------------------------------------- // Readonly: ['readonly'] | [] // ------------------------------------------------------------------- // prettier-ignore export type TReadonlyMapping = Input extends [unknown] ? true : false // prettier-ignore export function ReadonlyMapping(input: [unknown] | [], context: unknown) { return input.length > 0 } // ------------------------------------------------------------------- // Optional: ['?'] | [] // ------------------------------------------------------------------- // prettier-ignore export type TOptionalMapping = Input extends [unknown] ? true : false // prettier-ignore export function OptionalMapping(input: [unknown] | [], context: unknown) { return input.length > 0 } // ------------------------------------------------------------------- // Property: [Readonly, PropertyKey, Optional, ':', Type] // ------------------------------------------------------------------- // prettier-ignore export type TPropertyMapping = Input extends [infer IsReadonly extends boolean, infer Key extends string, infer IsOptional extends boolean, string, infer Type extends T.TSchema] ? { [_ in Key]: ( [IsReadonly, IsOptional] extends [true, true] ? T.TReadonlyOptional : [IsReadonly, IsOptional] extends [true, false] ? T.TReadonly : [IsReadonly, IsOptional] extends [false, true] ? T.TOptional : Type ) } : never // prettier-ignore export function PropertyMapping(input: [unknown, unknown, unknown, unknown, unknown], context: unknown) { const [isReadonly, key, isOptional, _colon, type] = input as [boolean, string, boolean, ':', T.TSchema] return { [key]: ( isReadonly && isOptional ? T.ReadonlyOptional(type) : isReadonly && !isOptional ? T.Readonly(type) : !isReadonly && isOptional ? T.Optional(type) : type ) } } // ------------------------------------------------------------------- // PropertyDelimiter: [',', '\n'] | [';', '\n'] | [','] | [';'] | ['\n'] // ------------------------------------------------------------------- // prettier-ignore export type TPropertyDelimiterMapping = Input // prettier-ignore export function PropertyDelimiterMapping(input: [unknown, unknown] | [unknown], context: unknown) { return input } // ------------------------------------------------------------------- // PropertyList: [[Property, PropertyDelimiter][], [Property] | []] // ------------------------------------------------------------------- // prettier-ignore export type TPropertyListMapping = TDelimited // prettier-ignore export function PropertyListMapping(input: [unknown, unknown], context: unknown) { return Delimited(input) } // ------------------------------------------------------------------- // Object: ['{', PropertyList, '}'] // ------------------------------------------------------------------- // prettier-ignore type TObjectMappingReduce = ( PropertiesList extends [infer Left extends T.TProperties, ...infer Right extends T.TProperties[]] ? TObjectMappingReduce : { [Key in keyof Result]: Result[Key] } ) // prettier-ignore export type TObjectMapping = Input extends ['{', infer PropertyList extends T.TProperties[], '}'] ? T.TObject> : never // prettier-ignore export function ObjectMapping(input: [unknown, unknown, unknown], context: unknown) { const propertyList = input[1] as T.TProperties[] return T.Object(propertyList.reduce((result, property) => { return { ...result, ...property } }, {} as T.TProperties)) } // ------------------------------------------------------------------- // ElementList: [[Type, ','][], [Type] | []] // ------------------------------------------------------------------- // prettier-ignore export type TElementListMapping = TDelimited // prettier-ignore export function ElementListMapping(input: [unknown, unknown], context: unknown) { return Delimited(input) } // ------------------------------------------------------------------- // Tuple: ['[', ElementList, ']'] // ------------------------------------------------------------------- // prettier-ignore export type TTupleMapping = Input extends ['[', infer Types extends T.TSchema[], ']'] ? T.TTuple : never // prettier-ignore export function TupleMapping(input: [unknown, unknown, unknown], context: unknown) { return T.Tuple(input[1] as T.TSchema[]) } // ------------------------------------------------------------------- // Parameter: [, ':', Type] // ------------------------------------------------------------------- // prettier-ignore export type TParameterMapping = Input extends [string, ':', infer Type extends T.TSchema] ? Type : never // prettier-ignore export function ParameterMapping(input: [unknown, unknown, unknown], context: unknown) { const [_ident, _colon, type] = input as [string, ':', T.TSchema] return type } // ------------------------------------------------------------------- // ParameterList: [[Parameter, ','][], [Parameter] | []] // ------------------------------------------------------------------- // prettier-ignore export type TParameterListMapping = TDelimited // prettier-ignore export function ParameterListMapping(input: [unknown, unknown], context: unknown) { return Delimited(input) } // ------------------------------------------------------------------- // Function: ['(', ParameterList, ')', '=>', Type] // ------------------------------------------------------------------- // prettier-ignore export type TFunctionMapping = Input extends ['(', infer ParameterList extends T.TSchema[], ')', '=>', infer ReturnType extends T.TSchema] ? T.TFunction : never // prettier-ignore export function FunctionMapping(input: [unknown, unknown, unknown, unknown, unknown], context: unknown) { const [_lparan, parameterList, _rparan, _arrow, returnType] = input as ['(', T.TSchema[], ')', '=>', T.TSchema] return T.Function(parameterList, returnType) } // ------------------------------------------------------------------- // Constructor: ['new', '(', ParameterList, ')', '=>', Type] // ------------------------------------------------------------------- // prettier-ignore export type TConstructorMapping = Input extends ['new', '(', infer ParameterList extends T.TSchema[], ')', '=>', infer InstanceType extends T.TSchema] ? T.TConstructor : never // prettier-ignore export function ConstructorMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown], context: unknown) { const [_new, _lparan, parameterList, _rparan, _arrow, instanceType] = input as ['new', '(', T.TSchema[], ')', '=>', T.TSchema] return T.Constructor(parameterList, instanceType) } // ------------------------------------------------------------------- // Mapped: ['{', '[', , 'in', Type, ']', ':', Type, '}'] // ------------------------------------------------------------------- // prettier-ignore export type TMappedMapping = Input extends ['{', '[', infer _Key extends string, 'in', infer _Right extends T.TSchema, ']', ':', infer _Type extends T.TSchema, '}'] ? T.TLiteral<'Mapped types not supported'> : never // prettier-ignore export function MappedMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown], context: unknown) { const [_lbrace, _lbracket, _key, _in, _right, _rbracket, _colon, _type] = input as ['{', '[', string, 'in', T.TSchema, ']', ':', T.TSchema, '}'] return T.Literal('Mapped types not supported') } // ------------------------------------------------------------------- // AsyncIterator: ['AsyncIterator', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TAsyncIteratorMapping = Input extends ['AsyncIterator', '<', infer Type extends T.TSchema, '>'] ? T.TAsyncIterator : never // prettier-ignore export function AsyncIteratorMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['AsyncIterator', '<', T.TSchema, '>'] return T.AsyncIterator(type) } // ------------------------------------------------------------------- // Iterator: ['Iterator', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TIteratorMapping = Input extends ['Iterator', '<', infer Type extends T.TSchema, '>'] ? T.TIterator : never // prettier-ignore export function IteratorMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Iterator', '<', T.TSchema, '>'] return T.Iterator(type) } // ------------------------------------------------------------------- // Argument: ['Argument', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TArgumentMapping = Input extends ['Argument', '<', infer Type extends T.TSchema, '>'] ? Type extends T.TLiteral ? T.TArgument : T.TNever : never // prettier-ignore export function ArgumentMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { return T.KindGuard.IsLiteralNumber(input[2]) ? T.Argument(Math.trunc(input[2].const)) : T.Never() } // ------------------------------------------------------------------- // Awaited: ['Awaited', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TAwaitedMapping = Input extends ['Awaited', '<', infer Type extends T.TSchema, '>'] ? T.TAwaited : never // prettier-ignore export function AwaitedMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Awaited', '<', T.TSchema, '>'] return T.Awaited(type) } // ------------------------------------------------------------------- // Array: ['Array', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TArrayMapping = Input extends ['Array', '<', infer Type extends T.TSchema, '>'] ? T.TArray : never // prettier-ignore export function ArrayMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Array', '<', T.TSchema, '>'] return T.Array(type) } // ------------------------------------------------------------------- // Record: ['Record', '<', Type, ',', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TRecordMapping = Input extends ['Record', '<', infer Key extends T.TSchema, ',', infer Type extends T.TSchema, '>'] ? T.TRecordOrObject : never // prettier-ignore export function RecordMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, key, _comma, type, _rangle] = input as ['Record', '<', T.TSchema, ',', T.TSchema, '>'] return T.Record(key, type) } // ------------------------------------------------------------------- // Promise: ['Promise', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TPromiseMapping = Input extends ['Promise', '<', infer Type extends T.TSchema, '>'] ? T.TPromise : never // prettier-ignore export function PromiseMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Promise', '<', T.TSchema, '>'] return T.Promise(type) } // ------------------------------------------------------------------- // ConstructorParameters: ['ConstructorParameters', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TConstructorParametersMapping = Input extends ['ConstructorParameters', '<', infer Type extends T.TSchema, '>'] ? T.TConstructorParameters : never // prettier-ignore export function ConstructorParametersMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['ConstructorParameters', '<', T.TSchema, '>'] return T.ConstructorParameters(type) } // ------------------------------------------------------------------- // FunctionParameters: ['Parameters', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TFunctionParametersMapping = Input extends ['Parameters', '<', infer Type extends T.TSchema, '>'] ? T.TParameters : never // prettier-ignore export function FunctionParametersMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Parameters', '<', T.TSchema, '>'] return T.Parameters(type) } // ------------------------------------------------------------------- // InstanceType: ['InstanceType', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TInstanceTypeMapping = Input extends ['InstanceType', '<', infer Type extends T.TSchema, '>'] ? T.TInstanceType : never // prettier-ignore export function InstanceTypeMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['InstanceType', '<', T.TSchema, '>'] return T.InstanceType(type) } // ------------------------------------------------------------------- // ReturnType: ['ReturnType', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TReturnTypeMapping = Input extends ['ReturnType', '<', infer Type extends T.TSchema, '>'] ? T.TReturnType : never // prettier-ignore export function ReturnTypeMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['ReturnType', '<', T.TSchema, '>'] return T.ReturnType(type) } // ------------------------------------------------------------------- // Partial: ['Partial', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TPartialMapping = Input extends ['Partial', '<', infer Type extends T.TSchema, '>'] ? T.TPartial : never // prettier-ignore export function PartialMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Partial', '<', T.TSchema, '>'] return T.Partial(type) } // ------------------------------------------------------------------- // Required: ['Required', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TRequiredMapping = Input extends ['Required', '<', infer Type extends T.TSchema, '>'] ? T.TRequired : never // prettier-ignore export function RequiredMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Required', '<', T.TSchema, '>'] return T.Required(type) } // ------------------------------------------------------------------- // Pick: ['Pick', '<', Type, ',', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TPickMapping = Input extends ['Pick', '<', infer Type extends T.TSchema, ',', infer Key extends T.TSchema, '>'] ? T.TPick : never // prettier-ignore export function PickMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, key, _comma, type, _rangle] = input as ['Pick', '<', T.TSchema, ',', T.TSchema, '>'] return T.Pick(key, type) } // ------------------------------------------------------------------- // Omit: ['Omit', '<', Type, ',', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TOmitMapping = Input extends ['Omit', '<', infer Type extends T.TSchema, ',', infer Key extends T.TSchema, '>'] ? T.TOmit : never // prettier-ignore export function OmitMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, key, _comma, type, _rangle] = input as ['Omit', '<', T.TSchema, ',', T.TSchema, '>'] return T.Omit(key, type) } // ------------------------------------------------------------------- // Exclude: ['Exclude', '<', Type, ',', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TExcludeMapping = Input extends ['Exclude', '<', infer Type extends T.TSchema, ',', infer Key extends T.TSchema, '>'] ? T.TExclude : never // prettier-ignore export function ExcludeMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, key, _comma, type, _rangle] = input as ['Exclude', '<', T.TSchema, ',', T.TSchema, '>'] return T.Exclude(key, type) } // ------------------------------------------------------------------- // Extract: ['Extract', '<', Type, ',', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TExtractMapping = Input extends ['Extract', '<', infer Type extends T.TSchema, ',', infer Key extends T.TSchema, '>'] ? T.TExtract : never // prettier-ignore export function ExtractMapping(input: [unknown, unknown, unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, key, _comma, type, _rangle] = input as ['Extract', '<', T.TSchema, ',', T.TSchema, '>'] return T.Extract(key, type) } // ------------------------------------------------------------------- // Uppercase: ['Uppercase', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TUppercaseMapping = Input extends ['Uppercase', '<', infer Type extends T.TSchema, '>'] ? T.TUppercase : never // prettier-ignore export function UppercaseMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Uppercase', '<', T.TSchema, '>'] return T.Uppercase(type) } // ------------------------------------------------------------------- // Lowercase: ['Lowercase', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TLowercaseMapping = Input extends ['Lowercase', '<', infer Type extends T.TSchema, '>'] ? T.TLowercase : never // prettier-ignore export function LowercaseMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Lowercase', '<', T.TSchema, '>'] return T.Lowercase(type) } // ------------------------------------------------------------------- // Capitalize: ['Capitalize', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TCapitalizeMapping = Input extends ['Capitalize', '<', infer Type extends T.TSchema, '>'] ? T.TCapitalize : never // prettier-ignore export function CapitalizeMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Capitalize', '<', T.TSchema, '>'] return T.Capitalize(type) } // ------------------------------------------------------------------- // Uncapitalize: ['Uncapitalize', '<', Type, '>'] // ------------------------------------------------------------------- // prettier-ignore export type TUncapitalizeMapping = Input extends ['Uncapitalize', '<', infer Type extends T.TSchema, '>'] ? T.TUncapitalize : never // prettier-ignore export function UncapitalizeMapping(input: [unknown, unknown, unknown, unknown], context: unknown) { const [_name, _langle, type, _rangle] = input as ['Uncapitalize', '<', T.TSchema, '>'] return T.Uncapitalize(type) } // ------------------------------------------------------------------- // Date: 'Date' // ------------------------------------------------------------------- // prettier-ignore export type TDateMapping = T.TDate // prettier-ignore export function DateMapping(input: 'Date', context: unknown) { return T.Date() } // ------------------------------------------------------------------- // Uint8Array: 'Uint8Array' // ------------------------------------------------------------------- // prettier-ignore export type TUint8ArrayMapping = T.TUint8Array // prettier-ignore export function Uint8ArrayMapping(input: 'Uint8Array', context: unknown) { return T.Uint8Array() } // ------------------------------------------------------------------- // Reference: // ------------------------------------------------------------------- // prettier-ignore export type TReferenceMapping = Context extends T.TProperties ? Input extends string ? TDereference : never : never // prettier-ignore export function ReferenceMapping(input: string, context: unknown) { const target = Dereference(context as T.TProperties, input) return target } sinclairzx81-typebox-e0ec98c/src/syntax/parser.ts000066400000000000000000002746541505437577000222630ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/syntax The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Runtime, Static } from '../parser/index' import * as T from '../type/index' import * as S from './mapping' // ------------------------------------------------------------------ // Parser // // The following code is optimized inline types generated by a remote // compiler process. It is readonly and should not be modified. // ------------------------------------------------------------------ export type TGenericReferenceParameterList_0 = ( TType extends [infer _0, infer Input extends string] ? (Static.Token.Const<',', Input> extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : [] ) extends [infer _0, infer Input extends string] ? TGenericReferenceParameterList_0 : [Result, Input] export type TGenericReferenceParameterList = ( TGenericReferenceParameterList_0 extends [infer _0, infer Input extends string] ? ( (TType extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : [] : [] ) extends [infer _0 extends [unknown, unknown], infer Input extends string] ? [S.TGenericReferenceParameterListMapping<_0, Context>, Input] : [] export type TGenericReference = ( Static.Token.Ident extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TGenericReferenceParameterList extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TGenericReferenceMapping<_0, Context>, Input] : [] export type TGenericArgumentsList_0 = ( Static.Token.Ident extends [infer _0, infer Input extends string] ? (Static.Token.Const<',', Input> extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : [] ) extends [infer _0, infer Input extends string] ? TGenericArgumentsList_0 : [Result, Input] export type TGenericArgumentsList = ( TGenericArgumentsList_0 extends [infer _0, infer Input extends string] ? ( (Static.Token.Ident extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : [] : [] ) extends [infer _0 extends [unknown, unknown], infer Input extends string] ? [S.TGenericArgumentsListMapping<_0, Context>, Input] : [] export type TGenericArguments = ( Static.Token.Const<'<', Input> extends [infer _0, infer Input extends string] ? TGenericArgumentsList extends [infer _1, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _2, infer Input extends string] ? [[_0, _1, _2], Input] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown], infer Input extends string] ? [S.TGenericArgumentsMapping<_0, Context>, Input] : [] export type TKeywordString = Static.Token.Const<'string', Input> extends [infer _0 extends 'string', infer Input extends string] ? [S.TKeywordStringMapping<_0, Context>, Input] : [] export type TKeywordNumber = Static.Token.Const<'number', Input> extends [infer _0 extends 'number', infer Input extends string] ? [S.TKeywordNumberMapping<_0, Context>, Input] : [] export type TKeywordBoolean = Static.Token.Const<'boolean', Input> extends [infer _0 extends 'boolean', infer Input extends string] ? [S.TKeywordBooleanMapping<_0, Context>, Input] : [] export type TKeywordUndefined = Static.Token.Const<'undefined', Input> extends [infer _0 extends 'undefined', infer Input extends string] ? [S.TKeywordUndefinedMapping<_0, Context>, Input] : [] export type TKeywordNull = Static.Token.Const<'null', Input> extends [infer _0 extends 'null', infer Input extends string] ? [S.TKeywordNullMapping<_0, Context>, Input] : [] export type TKeywordInteger = Static.Token.Const<'integer', Input> extends [infer _0 extends 'integer', infer Input extends string] ? [S.TKeywordIntegerMapping<_0, Context>, Input] : [] export type TKeywordBigInt = Static.Token.Const<'bigint', Input> extends [infer _0 extends 'bigint', infer Input extends string] ? [S.TKeywordBigIntMapping<_0, Context>, Input] : [] export type TKeywordUnknown = Static.Token.Const<'unknown', Input> extends [infer _0 extends 'unknown', infer Input extends string] ? [S.TKeywordUnknownMapping<_0, Context>, Input] : [] export type TKeywordAny = Static.Token.Const<'any', Input> extends [infer _0 extends 'any', infer Input extends string] ? [S.TKeywordAnyMapping<_0, Context>, Input] : [] export type TKeywordNever = Static.Token.Const<'never', Input> extends [infer _0 extends 'never', infer Input extends string] ? [S.TKeywordNeverMapping<_0, Context>, Input] : [] export type TKeywordSymbol = Static.Token.Const<'symbol', Input> extends [infer _0 extends 'symbol', infer Input extends string] ? [S.TKeywordSymbolMapping<_0, Context>, Input] : [] export type TKeywordVoid = Static.Token.Const<'void', Input> extends [infer _0 extends 'void', infer Input extends string] ? [S.TKeywordVoidMapping<_0, Context>, Input] : [] export type TKeyword = ( TKeywordString extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordNumber extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordBoolean extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordUndefined extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordNull extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordInteger extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordBigInt extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordUnknown extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordAny extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordNever extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordSymbol extends [infer _0, infer Input extends string] ? [_0, Input] : TKeywordVoid extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends unknown, infer Input extends string] ? [S.TKeywordMapping<_0, Context>, Input] : [] export type TLiteralString = Static.Token.String<["'", '"', '`'], Input> extends [infer _0 extends string, infer Input extends string] ? [S.TLiteralStringMapping<_0, Context>, Input] : [] export type TLiteralNumber = Static.Token.Number extends [infer _0 extends string, infer Input extends string] ? [S.TLiteralNumberMapping<_0, Context>, Input] : [] export type TLiteralBoolean = ( Static.Token.Const<'true', Input> extends [infer _0, infer Input extends string] ? [_0, Input] : Static.Token.Const<'false', Input> extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends 'true' | 'false', infer Input extends string] ? [S.TLiteralBooleanMapping<_0, Context>, Input] : [] export type TLiteral = ( TLiteralBoolean extends [infer _0, infer Input extends string] ? [_0, Input] : TLiteralNumber extends [infer _0, infer Input extends string] ? [_0, Input] : TLiteralString extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends unknown, infer Input extends string] ? [S.TLiteralMapping<_0, Context>, Input] : [] export type TKeyOf = ( (Static.Token.Const<'keyof', Input> extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends [unknown] | [], infer Input extends string] ? [S.TKeyOfMapping<_0, Context>, Input] : [] export type TIndexArray_0 = ( ( Static.Token.Const<'[', Input> extends [infer _0, infer Input extends string] ? TType extends [infer _1, infer Input extends string] ? Static.Token.Const<']', Input> extends [infer _2, infer Input extends string] ? [[_0, _1, _2], Input] : [] : [] : [] ) extends [infer _0, infer Input extends string] ? [_0, Input] : (Static.Token.Const<'[', Input> extends [infer _0, infer Input extends string] ? (Static.Token.Const<']', Input> extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : []) extends [ infer _0, infer Input extends string, ] ? [_0, Input] : [] ) extends [infer _0, infer Input extends string] ? TIndexArray_0 : [Result, Input] export type TIndexArray = TIndexArray_0 extends [infer _0 extends ([unknown, unknown, unknown] | [unknown, unknown])[], infer Input extends string] ? [S.TIndexArrayMapping<_0, Context>, Input] : [] export type TExtends = ( ( Static.Token.Const<'extends', Input> extends [infer _0, infer Input extends string] ? TType extends [infer _1, infer Input extends string] ? Static.Token.Const<'?', Input> extends [infer _2, infer Input extends string] ? TType extends [infer _3, infer Input extends string] ? Static.Token.Const<':', Input> extends [infer _4, infer Input extends string] ? TType extends [infer _5, infer Input extends string] ? [[_0, _1, _2, _3, _4, _5], Input] : [] : [] : [] : [] : [] : [] ) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown, unknown] | [], infer Input extends string] ? [S.TExtendsMapping<_0, Context>, Input] : [] export type TBase = ( ( Static.Token.Const<'(', Input> extends [infer _0, infer Input extends string] ? TType extends [infer _1, infer Input extends string] ? Static.Token.Const<')', Input> extends [infer _2, infer Input extends string] ? [[_0, _1, _2], Input] : [] : [] : [] ) extends [infer _0, infer Input extends string] ? [_0, Input] : TKeyword extends [infer _0, infer Input extends string] ? [_0, Input] : TObject extends [infer _0, infer Input extends string] ? [_0, Input] : TTuple extends [infer _0, infer Input extends string] ? [_0, Input] : TLiteral extends [infer _0, infer Input extends string] ? [_0, Input] : TConstructor extends [infer _0, infer Input extends string] ? [_0, Input] : TFunction extends [infer _0, infer Input extends string] ? [_0, Input] : TMapped extends [infer _0, infer Input extends string] ? [_0, Input] : TAsyncIterator extends [infer _0, infer Input extends string] ? [_0, Input] : TIterator extends [infer _0, infer Input extends string] ? [_0, Input] : TConstructorParameters extends [infer _0, infer Input extends string] ? [_0, Input] : TFunctionParameters extends [infer _0, infer Input extends string] ? [_0, Input] : TInstanceType extends [infer _0, infer Input extends string] ? [_0, Input] : TReturnType extends [infer _0, infer Input extends string] ? [_0, Input] : TArgument extends [infer _0, infer Input extends string] ? [_0, Input] : TAwaited extends [infer _0, infer Input extends string] ? [_0, Input] : TArray extends [infer _0, infer Input extends string] ? [_0, Input] : TRecord extends [infer _0, infer Input extends string] ? [_0, Input] : TPromise extends [infer _0, infer Input extends string] ? [_0, Input] : TPartial extends [infer _0, infer Input extends string] ? [_0, Input] : TRequired extends [infer _0, infer Input extends string] ? [_0, Input] : TPick extends [infer _0, infer Input extends string] ? [_0, Input] : TOmit extends [infer _0, infer Input extends string] ? [_0, Input] : TExclude extends [infer _0, infer Input extends string] ? [_0, Input] : TExtract extends [infer _0, infer Input extends string] ? [_0, Input] : TUppercase extends [infer _0, infer Input extends string] ? [_0, Input] : TLowercase extends [infer _0, infer Input extends string] ? [_0, Input] : TCapitalize extends [infer _0, infer Input extends string] ? [_0, Input] : TUncapitalize extends [infer _0, infer Input extends string] ? [_0, Input] : TDate extends [infer _0, infer Input extends string] ? [_0, Input] : TUint8Array extends [infer _0, infer Input extends string] ? [_0, Input] : TGenericReference extends [infer _0, infer Input extends string] ? [_0, Input] : TReference extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends [unknown, unknown, unknown] | unknown, infer Input extends string] ? [S.TBaseMapping<_0, Context>, Input] : [] export type TFactor = ( TKeyOf extends [infer _0, infer Input extends string] ? TBase extends [infer _1, infer Input extends string] ? TIndexArray extends [infer _2, infer Input extends string] ? TExtends extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TFactorMapping<_0, Context>, Input] : [] export type TExprTermTail = ( ( Static.Token.Const<'&', Input> extends [infer _0, infer Input extends string] ? TFactor extends [infer _1, infer Input extends string] ? TExprTermTail extends [infer _2, infer Input extends string] ? [[_0, _1, _2], Input] : [] : [] : [] ) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends [unknown, unknown, unknown] | [], infer Input extends string] ? [S.TExprTermTailMapping<_0, Context>, Input] : [] export type TExprTerm = ( TFactor extends [infer _0, infer Input extends string] ? (TExprTermTail extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : [] ) extends [infer _0 extends [unknown, unknown], infer Input extends string] ? [S.TExprTermMapping<_0, Context>, Input] : [] export type TExprTail = ( ( Static.Token.Const<'|', Input> extends [infer _0, infer Input extends string] ? TExprTerm extends [infer _1, infer Input extends string] ? TExprTail extends [infer _2, infer Input extends string] ? [[_0, _1, _2], Input] : [] : [] : [] ) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends [unknown, unknown, unknown] | [], infer Input extends string] ? [S.TExprTailMapping<_0, Context>, Input] : [] export type TExpr = ( TExprTerm extends [infer _0, infer Input extends string] ? (TExprTail extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : [] ) extends [infer _0 extends [unknown, unknown], infer Input extends string] ? [S.TExprMapping<_0, Context>, Input] : [] export type TType = ( TGenericArguments extends [infer _0 extends T.TProperties, infer Input extends string] ? TExpr : [] extends [infer _0, infer Input extends string] ? [_0, Input] : TExpr extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends unknown, infer Input extends string] ? [S.TTypeMapping<_0, Context>, Input] : [] export type TPropertyKey = ( Static.Token.Ident extends [infer _0, infer Input extends string] ? [_0, Input] : Static.Token.String<["'", '"'], Input> extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends string, infer Input extends string] ? [S.TPropertyKeyMapping<_0, Context>, Input] : [] export type TReadonly = ( (Static.Token.Const<'readonly', Input> extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends [unknown] | [], infer Input extends string] ? [S.TReadonlyMapping<_0, Context>, Input] : [] export type TOptional = ( (Static.Token.Const<'?', Input> extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends [unknown] | [], infer Input extends string] ? [S.TOptionalMapping<_0, Context>, Input] : [] export type TProperty = ( TReadonly extends [infer _0, infer Input extends string] ? TPropertyKey extends [infer _1, infer Input extends string] ? TOptional extends [infer _2, infer Input extends string] ? Static.Token.Const<':', Input> extends [infer _3, infer Input extends string] ? TType extends [infer _4, infer Input extends string] ? [[_0, _1, _2, _3, _4], Input] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TPropertyMapping<_0, Context>, Input] : [] export type TPropertyDelimiter = ( (Static.Token.Const<',', Input> extends [infer _0, infer Input extends string] ? (Static.Token.Const<'\n', Input> extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : []) extends [ infer _0, infer Input extends string, ] ? [_0, Input] : (Static.Token.Const<';', Input> extends [infer _0, infer Input extends string] ? (Static.Token.Const<'\n', Input> extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : []) extends [ infer _0, infer Input extends string, ] ? [_0, Input] : (Static.Token.Const<',', Input> extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : (Static.Token.Const<';', Input> extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : (Static.Token.Const<'\n', Input> extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _0 extends [unknown, unknown] | [unknown], infer Input extends string] ? [S.TPropertyDelimiterMapping<_0, Context>, Input] : [] export type TPropertyList_0 = ( TProperty extends [infer _0, infer Input extends string] ? (TPropertyDelimiter extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : [] ) extends [infer _0, infer Input extends string] ? TPropertyList_0 : [Result, Input] export type TPropertyList = ( TPropertyList_0 extends [infer _0, infer Input extends string] ? ( (TProperty extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : [] : [] ) extends [infer _0 extends [unknown, unknown], infer Input extends string] ? [S.TPropertyListMapping<_0, Context>, Input] : [] export type TObject = ( Static.Token.Const<'{', Input> extends [infer _0, infer Input extends string] ? TPropertyList extends [infer _1, infer Input extends string] ? Static.Token.Const<'}', Input> extends [infer _2, infer Input extends string] ? [[_0, _1, _2], Input] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown], infer Input extends string] ? [S.TObjectMapping<_0, Context>, Input] : [] export type TElementList_0 = ( TType extends [infer _0, infer Input extends string] ? (Static.Token.Const<',', Input> extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : [] ) extends [infer _0, infer Input extends string] ? TElementList_0 : [Result, Input] export type TElementList = ( TElementList_0 extends [infer _0, infer Input extends string] ? ( (TType extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : [] : [] ) extends [infer _0 extends [unknown, unknown], infer Input extends string] ? [S.TElementListMapping<_0, Context>, Input] : [] export type TTuple = ( Static.Token.Const<'[', Input> extends [infer _0, infer Input extends string] ? TElementList extends [infer _1, infer Input extends string] ? Static.Token.Const<']', Input> extends [infer _2, infer Input extends string] ? [[_0, _1, _2], Input] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown], infer Input extends string] ? [S.TTupleMapping<_0, Context>, Input] : [] export type TParameter = ( Static.Token.Ident extends [infer _0, infer Input extends string] ? Static.Token.Const<':', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? [[_0, _1, _2], Input] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown], infer Input extends string] ? [S.TParameterMapping<_0, Context>, Input] : [] export type TParameterList_0 = ( TParameter extends [infer _0, infer Input extends string] ? (Static.Token.Const<',', Input> extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : []) : [] ) extends [infer _0, infer Input extends string] ? TParameterList_0 : [Result, Input] export type TParameterList = ( TParameterList_0 extends [infer _0, infer Input extends string] ? ( (TParameter extends [infer _0, infer Input extends string] ? [[_0], Input] : []) extends [infer _0, infer Input extends string] ? [_0, Input] : [[], Input] extends [infer _0, infer Input extends string] ? [_0, Input] : [] ) extends [infer _1, infer Input extends string] ? [[_0, _1], Input] : [] : [] ) extends [infer _0 extends [unknown, unknown], infer Input extends string] ? [S.TParameterListMapping<_0, Context>, Input] : [] export type TFunction = ( Static.Token.Const<'(', Input> extends [infer _0, infer Input extends string] ? TParameterList extends [infer _1, infer Input extends string] ? Static.Token.Const<')', Input> extends [infer _2, infer Input extends string] ? Static.Token.Const<'=>', Input> extends [infer _3, infer Input extends string] ? TType extends [infer _4, infer Input extends string] ? [[_0, _1, _2, _3, _4], Input] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TFunctionMapping<_0, Context>, Input] : [] export type TConstructor = ( Static.Token.Const<'new', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'(', Input> extends [infer _1, infer Input extends string] ? TParameterList extends [infer _2, infer Input extends string] ? Static.Token.Const<')', Input> extends [infer _3, infer Input extends string] ? Static.Token.Const<'=>', Input> extends [infer _4, infer Input extends string] ? TType extends [infer _5, infer Input extends string] ? [[_0, _1, _2, _3, _4, _5], Input] : [] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TConstructorMapping<_0, Context>, Input] : [] export type TMapped = ( Static.Token.Const<'{', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'[', Input> extends [infer _1, infer Input extends string] ? Static.Token.Ident extends [infer _2, infer Input extends string] ? Static.Token.Const<'in', Input> extends [infer _3, infer Input extends string] ? TType extends [infer _4, infer Input extends string] ? Static.Token.Const<']', Input> extends [infer _5, infer Input extends string] ? Static.Token.Const<':', Input> extends [infer _6, infer Input extends string] ? TType extends [infer _7, infer Input extends string] ? Static.Token.Const<'}', Input> extends [infer _8, infer Input extends string] ? [[_0, _1, _2, _3, _4, _5, _6, _7, _8], Input] : [] : [] : [] : [] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TMappedMapping<_0, Context>, Input] : [] export type TAsyncIterator = ( Static.Token.Const<'AsyncIterator', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TAsyncIteratorMapping<_0, Context>, Input] : [] export type TIterator = ( Static.Token.Const<'Iterator', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TIteratorMapping<_0, Context>, Input] : [] export type TArgument = ( Static.Token.Const<'Argument', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TArgumentMapping<_0, Context>, Input] : [] export type TAwaited = ( Static.Token.Const<'Awaited', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TAwaitedMapping<_0, Context>, Input] : [] export type TArray = ( Static.Token.Const<'Array', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TArrayMapping<_0, Context>, Input] : [] export type TRecord = ( Static.Token.Const<'Record', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<',', Input> extends [infer _3, infer Input extends string] ? TType extends [infer _4, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _5, infer Input extends string] ? [[_0, _1, _2, _3, _4, _5], Input] : [] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TRecordMapping<_0, Context>, Input] : [] export type TPromise = ( Static.Token.Const<'Promise', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TPromiseMapping<_0, Context>, Input] : [] export type TConstructorParameters = ( Static.Token.Const<'ConstructorParameters', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TConstructorParametersMapping<_0, Context>, Input] : [] export type TFunctionParameters = ( Static.Token.Const<'Parameters', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TFunctionParametersMapping<_0, Context>, Input] : [] export type TInstanceType = ( Static.Token.Const<'InstanceType', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TInstanceTypeMapping<_0, Context>, Input] : [] export type TReturnType = ( Static.Token.Const<'ReturnType', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TReturnTypeMapping<_0, Context>, Input] : [] export type TPartial = ( Static.Token.Const<'Partial', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TPartialMapping<_0, Context>, Input] : [] export type TRequired = ( Static.Token.Const<'Required', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TRequiredMapping<_0, Context>, Input] : [] export type TPick = ( Static.Token.Const<'Pick', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<',', Input> extends [infer _3, infer Input extends string] ? TType extends [infer _4, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _5, infer Input extends string] ? [[_0, _1, _2, _3, _4, _5], Input] : [] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TPickMapping<_0, Context>, Input] : [] export type TOmit = ( Static.Token.Const<'Omit', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<',', Input> extends [infer _3, infer Input extends string] ? TType extends [infer _4, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _5, infer Input extends string] ? [[_0, _1, _2, _3, _4, _5], Input] : [] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TOmitMapping<_0, Context>, Input] : [] export type TExclude = ( Static.Token.Const<'Exclude', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<',', Input> extends [infer _3, infer Input extends string] ? TType extends [infer _4, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _5, infer Input extends string] ? [[_0, _1, _2, _3, _4, _5], Input] : [] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TExcludeMapping<_0, Context>, Input] : [] export type TExtract = ( Static.Token.Const<'Extract', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<',', Input> extends [infer _3, infer Input extends string] ? TType extends [infer _4, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _5, infer Input extends string] ? [[_0, _1, _2, _3, _4, _5], Input] : [] : [] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TExtractMapping<_0, Context>, Input] : [] export type TUppercase = ( Static.Token.Const<'Uppercase', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TUppercaseMapping<_0, Context>, Input] : [] export type TLowercase = ( Static.Token.Const<'Lowercase', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TLowercaseMapping<_0, Context>, Input] : [] export type TCapitalize = ( Static.Token.Const<'Capitalize', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TCapitalizeMapping<_0, Context>, Input] : [] export type TUncapitalize = ( Static.Token.Const<'Uncapitalize', Input> extends [infer _0, infer Input extends string] ? Static.Token.Const<'<', Input> extends [infer _1, infer Input extends string] ? TType extends [infer _2, infer Input extends string] ? Static.Token.Const<'>', Input> extends [infer _3, infer Input extends string] ? [[_0, _1, _2, _3], Input] : [] : [] : [] : [] ) extends [infer _0 extends [unknown, unknown, unknown, unknown], infer Input extends string] ? [S.TUncapitalizeMapping<_0, Context>, Input] : [] export type TDate = Static.Token.Const<'Date', Input> extends [infer _0 extends 'Date', infer Input extends string] ? [S.TDateMapping<_0, Context>, Input] : [] export type TUint8Array = Static.Token.Const<'Uint8Array', Input> extends [infer _0 extends 'Uint8Array', infer Input extends string] ? [S.TUint8ArrayMapping<_0, Context>, Input] : [] export type TReference = Static.Token.Ident extends [infer _0 extends string, infer Input extends string] ? [S.TReferenceMapping<_0, Context>, Input] : [] const If = (result: [unknown, string] | [], left: (input: [unknown, string]) => [unknown, string] | [], right: () => [unknown, string] | [] = () => []): [unknown, string] | [] => (result.length === 2 ? left(result) : right()) export const GenericReferenceParameterList_0 = (input: string, context: T.TProperties, result: unknown[] = []): [unknown[], string] => If( If(Type(input, context), ([_0, input]) => If(Runtime.Token.Const(',', input), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => GenericReferenceParameterList_0(input, context, [...result, _0]), () => [result, input], ) as [unknown[], string] export const GenericReferenceParameterList = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(GenericReferenceParameterList_0(input, context), ([_0, input]) => If( If( If(Type(input, context), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_1, input]) => [[_0, _1], input], ), ), ([_0, input]) => [S.GenericReferenceParameterListMapping(_0 as [unknown, unknown], context), input], ) export const GenericReference = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Ident(input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(GenericReferenceParameterList(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.GenericReferenceMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const GenericArgumentsList_0 = (input: string, context: T.TProperties, result: unknown[] = []): [unknown[], string] => If( If(Runtime.Token.Ident(input), ([_0, input]) => If(Runtime.Token.Const(',', input), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => GenericArgumentsList_0(input, context, [...result, _0]), () => [result, input], ) as [unknown[], string] export const GenericArgumentsList = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(GenericArgumentsList_0(input, context), ([_0, input]) => If( If( If(Runtime.Token.Ident(input), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_1, input]) => [[_0, _1], input], ), ), ([_0, input]) => [S.GenericArgumentsListMapping(_0 as [unknown, unknown], context), input], ) export const GenericArguments = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('<', input), ([_0, input]) => If(GenericArgumentsList(input, context), ([_1, input]) => If(Runtime.Token.Const('>', input), ([_2, input]) => [[_0, _1, _2], input]))), ([_0, input]) => [S.GenericArgumentsMapping(_0 as [unknown, unknown, unknown], context), input], ) export const KeywordString = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('string', input), ([_0, input]) => [S.KeywordStringMapping(_0 as 'string', context), input]) export const KeywordNumber = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('number', input), ([_0, input]) => [S.KeywordNumberMapping(_0 as 'number', context), input]) export const KeywordBoolean = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('boolean', input), ([_0, input]) => [S.KeywordBooleanMapping(_0 as 'boolean', context), input]) export const KeywordUndefined = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('undefined', input), ([_0, input]) => [S.KeywordUndefinedMapping(_0 as 'undefined', context), input]) export const KeywordNull = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('null', input), ([_0, input]) => [S.KeywordNullMapping(_0 as 'null', context), input]) export const KeywordInteger = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('integer', input), ([_0, input]) => [S.KeywordIntegerMapping(_0 as 'integer', context), input]) export const KeywordBigInt = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('bigint', input), ([_0, input]) => [S.KeywordBigIntMapping(_0 as 'bigint', context), input]) export const KeywordUnknown = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('unknown', input), ([_0, input]) => [S.KeywordUnknownMapping(_0 as 'unknown', context), input]) export const KeywordAny = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('any', input), ([_0, input]) => [S.KeywordAnyMapping(_0 as 'any', context), input]) export const KeywordNever = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('never', input), ([_0, input]) => [S.KeywordNeverMapping(_0 as 'never', context), input]) export const KeywordSymbol = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('symbol', input), ([_0, input]) => [S.KeywordSymbolMapping(_0 as 'symbol', context), input]) export const KeywordVoid = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('void', input), ([_0, input]) => [S.KeywordVoidMapping(_0 as 'void', context), input]) export const Keyword = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( KeywordString(input, context), ([_0, input]) => [_0, input], () => If( KeywordNumber(input, context), ([_0, input]) => [_0, input], () => If( KeywordBoolean(input, context), ([_0, input]) => [_0, input], () => If( KeywordUndefined(input, context), ([_0, input]) => [_0, input], () => If( KeywordNull(input, context), ([_0, input]) => [_0, input], () => If( KeywordInteger(input, context), ([_0, input]) => [_0, input], () => If( KeywordBigInt(input, context), ([_0, input]) => [_0, input], () => If( KeywordUnknown(input, context), ([_0, input]) => [_0, input], () => If( KeywordAny(input, context), ([_0, input]) => [_0, input], () => If( KeywordNever(input, context), ([_0, input]) => [_0, input], () => If( KeywordSymbol(input, context), ([_0, input]) => [_0, input], () => If( KeywordVoid(input, context), ([_0, input]) => [_0, input], () => [], ), ), ), ), ), ), ), ), ), ), ), ), ([_0, input]) => [S.KeywordMapping(_0 as unknown, context), input], ) export const LiteralString = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.String(["'", '"', '`'], input), ([_0, input]) => [S.LiteralStringMapping(_0 as string, context), input]) export const LiteralNumber = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Number(input), ([_0, input]) => [S.LiteralNumberMapping(_0 as string, context), input]) export const LiteralBoolean = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( Runtime.Token.Const('true', input), ([_0, input]) => [_0, input], () => If( Runtime.Token.Const('false', input), ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.LiteralBooleanMapping(_0 as 'true' | 'false', context), input], ) export const Literal = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( LiteralBoolean(input, context), ([_0, input]) => [_0, input], () => If( LiteralNumber(input, context), ([_0, input]) => [_0, input], () => If( LiteralString(input, context), ([_0, input]) => [_0, input], () => [], ), ), ), ([_0, input]) => [S.LiteralMapping(_0 as unknown, context), input], ) export const KeyOf = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If(Runtime.Token.Const('keyof', input), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.KeyOfMapping(_0 as [unknown] | [], context), input], ) export const IndexArray_0 = (input: string, context: T.TProperties, result: unknown[] = []): [unknown[], string] => If( If( If(Runtime.Token.Const('[', input), ([_0, input]) => If(Type(input, context), ([_1, input]) => If(Runtime.Token.Const(']', input), ([_2, input]) => [[_0, _1, _2], input]))), ([_0, input]) => [_0, input], () => If( If(Runtime.Token.Const('[', input), ([_0, input]) => If(Runtime.Token.Const(']', input), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => IndexArray_0(input, context, [...result, _0]), () => [result, input], ) as [unknown[], string] export const IndexArray = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(IndexArray_0(input, context), ([_0, input]) => [S.IndexArrayMapping(_0 as ([unknown, unknown, unknown] | [unknown, unknown])[], context), input]) export const Extends = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If(Runtime.Token.Const('extends', input), ([_0, input]) => If(Type(input, context), ([_1, input]) => If(Runtime.Token.Const('?', input), ([_2, input]) => If(Type(input, context), ([_3, input]) => If(Runtime.Token.Const(':', input), ([_4, input]) => If(Type(input, context), ([_5, input]) => [[_0, _1, _2, _3, _4, _5], input])))), ), ), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.ExtendsMapping(_0 as [unknown, unknown, unknown, unknown, unknown, unknown] | [], context), input], ) export const Base = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If(Runtime.Token.Const('(', input), ([_0, input]) => If(Type(input, context), ([_1, input]) => If(Runtime.Token.Const(')', input), ([_2, input]) => [[_0, _1, _2], input]))), ([_0, input]) => [_0, input], () => If( Keyword(input, context), ([_0, input]) => [_0, input], () => If( _Object(input, context), ([_0, input]) => [_0, input], () => If( Tuple(input, context), ([_0, input]) => [_0, input], () => If( Literal(input, context), ([_0, input]) => [_0, input], () => If( Constructor(input, context), ([_0, input]) => [_0, input], () => If( Function(input, context), ([_0, input]) => [_0, input], () => If( Mapped(input, context), ([_0, input]) => [_0, input], () => If( AsyncIterator(input, context), ([_0, input]) => [_0, input], () => If( Iterator(input, context), ([_0, input]) => [_0, input], () => If( ConstructorParameters(input, context), ([_0, input]) => [_0, input], () => If( FunctionParameters(input, context), ([_0, input]) => [_0, input], () => If( InstanceType(input, context), ([_0, input]) => [_0, input], () => If( ReturnType(input, context), ([_0, input]) => [_0, input], () => If( Argument(input, context), ([_0, input]) => [_0, input], () => If( Awaited(input, context), ([_0, input]) => [_0, input], () => If( Array(input, context), ([_0, input]) => [_0, input], () => If( Record(input, context), ([_0, input]) => [_0, input], () => If( Promise(input, context), ([_0, input]) => [_0, input], () => If( Partial(input, context), ([_0, input]) => [_0, input], () => If( Required(input, context), ([_0, input]) => [_0, input], () => If( Pick(input, context), ([_0, input]) => [_0, input], () => If( Omit(input, context), ([_0, input]) => [_0, input], () => If( Exclude(input, context), ([_0, input]) => [_0, input], () => If( Extract(input, context), ([_0, input]) => [_0, input], () => If( Uppercase(input, context), ([_0, input]) => [_0, input], () => If( Lowercase(input, context), ([_0, input]) => [_0, input], () => If( Capitalize(input, context), ([_0, input]) => [_0, input], () => If( Uncapitalize(input, context), ([_0, input]) => [_0, input], () => If( Date(input, context), ([_0, input]) => [_0, input], () => If( Uint8Array(input, context), ([_0, input]) => [_0, input], () => If( GenericReference(input, context), ([_0, input]) => [_0, input], () => If( Reference(input, context), ([_0, input]) => [_0, input], () => [], ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ), ([_0, input]) => [S.BaseMapping(_0 as [unknown, unknown, unknown] | unknown, context), input], ) export const Factor = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(KeyOf(input, context), ([_0, input]) => If(Base(input, context), ([_1, input]) => If(IndexArray(input, context), ([_2, input]) => If(Extends(input, context), ([_3, input]) => [[_0, _1, _2, _3], input])))), ([_0, input]) => [S.FactorMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const ExprTermTail = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If(Runtime.Token.Const('&', input), ([_0, input]) => If(Factor(input, context), ([_1, input]) => If(ExprTermTail(input, context), ([_2, input]) => [[_0, _1, _2], input]))), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.ExprTermTailMapping(_0 as [unknown, unknown, unknown] | [], context), input], ) export const ExprTerm = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Factor(input, context), ([_0, input]) => If(ExprTermTail(input, context), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => [S.ExprTermMapping(_0 as [unknown, unknown], context), input], ) export const ExprTail = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If(Runtime.Token.Const('|', input), ([_0, input]) => If(ExprTerm(input, context), ([_1, input]) => If(ExprTail(input, context), ([_2, input]) => [[_0, _1, _2], input]))), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.ExprTailMapping(_0 as [unknown, unknown, unknown] | [], context), input], ) export const Expr = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(ExprTerm(input, context), ([_0, input]) => If(ExprTail(input, context), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => [S.ExprMapping(_0 as [unknown, unknown], context), input], ) export const Type = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If( GenericArguments(input, context), ([_0, input]) => Expr(input, _0 as T.TProperties), () => [], ), ([_0, input]) => [_0, input], () => If( Expr(input, context), ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.TypeMapping(_0 as unknown, context), input], ) export const PropertyKey = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( Runtime.Token.Ident(input), ([_0, input]) => [_0, input], () => If( Runtime.Token.String(["'", '"'], input), ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.PropertyKeyMapping(_0 as string, context), input], ) export const Readonly = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If(Runtime.Token.Const('readonly', input), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.ReadonlyMapping(_0 as [unknown] | [], context), input], ) export const Optional = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If(Runtime.Token.Const('?', input), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_0, input]) => [S.OptionalMapping(_0 as [unknown] | [], context), input], ) export const Property = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Readonly(input, context), ([_0, input]) => If(PropertyKey(input, context), ([_1, input]) => If(Optional(input, context), ([_2, input]) => If(Runtime.Token.Const(':', input), ([_3, input]) => If(Type(input, context), ([_4, input]) => [[_0, _1, _2, _3, _4], input])))), ), ([_0, input]) => [S.PropertyMapping(_0 as [unknown, unknown, unknown, unknown, unknown], context), input], ) export const PropertyDelimiter = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If( If(Runtime.Token.Const(',', input), ([_0, input]) => If(Runtime.Token.Const('\n', input), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => [_0, input], () => If( If(Runtime.Token.Const(';', input), ([_0, input]) => If(Runtime.Token.Const('\n', input), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => [_0, input], () => If( If(Runtime.Token.Const(',', input), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( If(Runtime.Token.Const(';', input), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( If(Runtime.Token.Const('\n', input), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => [], ), ), ), ), ), ([_0, input]) => [S.PropertyDelimiterMapping(_0 as [unknown, unknown] | [unknown], context), input], ) export const PropertyList_0 = (input: string, context: T.TProperties, result: unknown[] = []): [unknown[], string] => If( If(Property(input, context), ([_0, input]) => If(PropertyDelimiter(input, context), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => PropertyList_0(input, context, [...result, _0]), () => [result, input], ) as [unknown[], string] export const PropertyList = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(PropertyList_0(input, context), ([_0, input]) => If( If( If(Property(input, context), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_1, input]) => [[_0, _1], input], ), ), ([_0, input]) => [S.PropertyListMapping(_0 as [unknown, unknown], context), input], ) export const _Object = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('{', input), ([_0, input]) => If(PropertyList(input, context), ([_1, input]) => If(Runtime.Token.Const('}', input), ([_2, input]) => [[_0, _1, _2], input]))), ([_0, input]) => [S.ObjectMapping(_0 as [unknown, unknown, unknown], context), input], ) export const ElementList_0 = (input: string, context: T.TProperties, result: unknown[] = []): [unknown[], string] => If( If(Type(input, context), ([_0, input]) => If(Runtime.Token.Const(',', input), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => ElementList_0(input, context, [...result, _0]), () => [result, input], ) as [unknown[], string] export const ElementList = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(ElementList_0(input, context), ([_0, input]) => If( If( If(Type(input, context), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_1, input]) => [[_0, _1], input], ), ), ([_0, input]) => [S.ElementListMapping(_0 as [unknown, unknown], context), input], ) export const Tuple = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('[', input), ([_0, input]) => If(ElementList(input, context), ([_1, input]) => If(Runtime.Token.Const(']', input), ([_2, input]) => [[_0, _1, _2], input]))), ([_0, input]) => [S.TupleMapping(_0 as [unknown, unknown, unknown], context), input], ) export const Parameter = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Ident(input), ([_0, input]) => If(Runtime.Token.Const(':', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => [[_0, _1, _2], input]))), ([_0, input]) => [S.ParameterMapping(_0 as [unknown, unknown, unknown], context), input], ) export const ParameterList_0 = (input: string, context: T.TProperties, result: unknown[] = []): [unknown[], string] => If( If(Parameter(input, context), ([_0, input]) => If(Runtime.Token.Const(',', input), ([_1, input]) => [[_0, _1], input])), ([_0, input]) => ParameterList_0(input, context, [...result, _0]), () => [result, input], ) as [unknown[], string] export const ParameterList = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(ParameterList_0(input, context), ([_0, input]) => If( If( If(Parameter(input, context), ([_0, input]) => [[_0], input]), ([_0, input]) => [_0, input], () => If( [[], input], ([_0, input]) => [_0, input], () => [], ), ), ([_1, input]) => [[_0, _1], input], ), ), ([_0, input]) => [S.ParameterListMapping(_0 as [unknown, unknown], context), input], ) export const Function = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('(', input), ([_0, input]) => If(ParameterList(input, context), ([_1, input]) => If(Runtime.Token.Const(')', input), ([_2, input]) => If(Runtime.Token.Const('=>', input), ([_3, input]) => If(Type(input, context), ([_4, input]) => [[_0, _1, _2, _3, _4], input])))), ), ([_0, input]) => [S.FunctionMapping(_0 as [unknown, unknown, unknown, unknown, unknown], context), input], ) export const Constructor = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('new', input), ([_0, input]) => If(Runtime.Token.Const('(', input), ([_1, input]) => If(ParameterList(input, context), ([_2, input]) => If(Runtime.Token.Const(')', input), ([_3, input]) => If(Runtime.Token.Const('=>', input), ([_4, input]) => If(Type(input, context), ([_5, input]) => [[_0, _1, _2, _3, _4, _5], input]))), ), ), ), ([_0, input]) => [S.ConstructorMapping(_0 as [unknown, unknown, unknown, unknown, unknown, unknown], context), input], ) export const Mapped = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('{', input), ([_0, input]) => If(Runtime.Token.Const('[', input), ([_1, input]) => If(Runtime.Token.Ident(input), ([_2, input]) => If(Runtime.Token.Const('in', input), ([_3, input]) => If(Type(input, context), ([_4, input]) => If(Runtime.Token.Const(']', input), ([_5, input]) => If(Runtime.Token.Const(':', input), ([_6, input]) => If(Type(input, context), ([_7, input]) => If(Runtime.Token.Const('}', input), ([_8, input]) => [[_0, _1, _2, _3, _4, _5, _6, _7, _8], input]))), ), ), ), ), ), ), ([_0, input]) => [S.MappedMapping(_0 as [unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown], context), input], ) export const AsyncIterator = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('AsyncIterator', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.AsyncIteratorMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Iterator = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Iterator', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.IteratorMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Argument = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Argument', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.ArgumentMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Awaited = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Awaited', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.AwaitedMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Array = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Array', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input])))), ([_0, input]) => [S.ArrayMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Record = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Record', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const(',', input), ([_3, input]) => If(Type(input, context), ([_4, input]) => If(Runtime.Token.Const('>', input), ([_5, input]) => [[_0, _1, _2, _3, _4, _5], input])))), ), ), ([_0, input]) => [S.RecordMapping(_0 as [unknown, unknown, unknown, unknown, unknown, unknown], context), input], ) export const Promise = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Promise', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.PromiseMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const ConstructorParameters = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('ConstructorParameters', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.ConstructorParametersMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const FunctionParameters = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Parameters', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.FunctionParametersMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const InstanceType = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('InstanceType', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.InstanceTypeMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const ReturnType = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('ReturnType', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.ReturnTypeMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Partial = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Partial', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.PartialMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Required = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Required', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.RequiredMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Pick = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Pick', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const(',', input), ([_3, input]) => If(Type(input, context), ([_4, input]) => If(Runtime.Token.Const('>', input), ([_5, input]) => [[_0, _1, _2, _3, _4, _5], input])))), ), ), ([_0, input]) => [S.PickMapping(_0 as [unknown, unknown, unknown, unknown, unknown, unknown], context), input], ) export const Omit = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Omit', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const(',', input), ([_3, input]) => If(Type(input, context), ([_4, input]) => If(Runtime.Token.Const('>', input), ([_5, input]) => [[_0, _1, _2, _3, _4, _5], input])))), ), ), ([_0, input]) => [S.OmitMapping(_0 as [unknown, unknown, unknown, unknown, unknown, unknown], context), input], ) export const Exclude = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Exclude', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const(',', input), ([_3, input]) => If(Type(input, context), ([_4, input]) => If(Runtime.Token.Const('>', input), ([_5, input]) => [[_0, _1, _2, _3, _4, _5], input])))), ), ), ([_0, input]) => [S.ExcludeMapping(_0 as [unknown, unknown, unknown, unknown, unknown, unknown], context), input], ) export const Extract = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Extract', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const(',', input), ([_3, input]) => If(Type(input, context), ([_4, input]) => If(Runtime.Token.Const('>', input), ([_5, input]) => [[_0, _1, _2, _3, _4, _5], input])))), ), ), ([_0, input]) => [S.ExtractMapping(_0 as [unknown, unknown, unknown, unknown, unknown, unknown], context), input], ) export const Uppercase = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Uppercase', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.UppercaseMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Lowercase = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Lowercase', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.LowercaseMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Capitalize = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Capitalize', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.CapitalizeMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Uncapitalize = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If( If(Runtime.Token.Const('Uncapitalize', input), ([_0, input]) => If(Runtime.Token.Const('<', input), ([_1, input]) => If(Type(input, context), ([_2, input]) => If(Runtime.Token.Const('>', input), ([_3, input]) => [[_0, _1, _2, _3], input]))), ), ([_0, input]) => [S.UncapitalizeMapping(_0 as [unknown, unknown, unknown, unknown], context), input], ) export const Date = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('Date', input), ([_0, input]) => [S.DateMapping(_0 as 'Date', context), input]) export const Uint8Array = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Const('Uint8Array', input), ([_0, input]) => [S.Uint8ArrayMapping(_0 as 'Uint8Array', context), input]) export const Reference = (input: string, context: T.TProperties = {}): [unknown, string] | [] => If(Runtime.Token.Ident(input), ([_0, input]) => [S.ReferenceMapping(_0 as string, context), input]) sinclairzx81-typebox-e0ec98c/src/syntax/syntax.ts000066400000000000000000000063541505437577000223030ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/syntax The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------------------------*/ import * as t from '../type/index' import { Type, TType } from './parser' // ------------------------------------------------------------------ // NoInfer // ------------------------------------------------------------------ /** `[Experimental]` Parses type expressions into TypeBox types but does not infer */ export function NoInfer, Input extends string>(context: Context, input: Input, options?: t.SchemaOptions): t.TSchema /** `[Experimental]` Parses type expressions into TypeBox types but does not infer */ export function NoInfer(input: Input, options?: t.SchemaOptions): t.TSchema /** `[Experimental]` Parses type expressions into TypeBox types but does not infer */ // prettier-ignore export function NoInfer(...args: any[]): t.TSchema { const withContext = typeof args[0] === 'string' ? false : true const [context, code, options] = withContext ? [args[0], args[1], args[2] || {}] : [{}, args[0], args[1] || {}] const result = Type(code, context)[0] return t.KindGuard.IsSchema(result) ? t.CloneType(result, options) : t.Never(options) } /** `[Experimental]` Parses type expressions into TypeBox types */ // prettier-ignore export type TSyntax, Code extends string> = ( TType extends [infer Type extends t.TSchema, string] ? Type : t.TNever ) /** `[Experimental]` Parses type expressions into TypeBox types */ export function Syntax, Input extends string>(context: Context, input: Input, options?: t.SchemaOptions): TSyntax /** `[Experimental]` Parses type expressions into TypeBox types */ export function Syntax(annotation: Input, options?: t.SchemaOptions): TSyntax<{}, Input> /** `[Experimental]` Parses type expressions into TypeBox types */ export function Syntax(...args: any[]): never { return NoInfer.apply(null, args as never) as never } sinclairzx81-typebox-e0ec98c/src/system/000077500000000000000000000000001505437577000203735ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/system/index.ts000066400000000000000000000025171505437577000220570ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/system The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './policy' export * from './system' sinclairzx81-typebox-e0ec98c/src/system/policy.ts000066400000000000000000000102731505437577000222450ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/system The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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: Instancing // ------------------------------------------------------------------ /** * Configures the instantiation behavior of TypeBox types. The `default` option assigns raw JavaScript * references for embedded types, which may cause side effects if type properties are explicitly updated * outside the TypeBox type builder. The `clone` option creates copies of any shared types upon creation, * preventing unintended side effects. The `freeze` option applies `Object.freeze()` to the type, making * it fully readonly and immutable. Implementations should use `default` whenever possible, as it is the * fastest way to instantiate types. The default setting is `default`. */ export let InstanceMode: 'default' | 'clone' | 'freeze' = 'default' // ------------------------------------------------------------------ // TypeSystemPolicy: Checking // ------------------------------------------------------------------ /** 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 /** Checks this value using the ExactOptionalPropertyTypes policy */ export function IsExactOptionalProperty(value: Record, key: string) { return ExactOptionalPropertyTypes ? key in value : value[key] !== undefined } /** Checks this value using the AllowArrayObjects policy */ export function IsObjectLike(value: unknown): value is Record { const isObject = IsObject(value) return AllowArrayObject ? isObject : isObject && !IsArray(value) } /** Checks this value as a record using the AllowArrayObjects policy */ export function IsRecordLike(value: unknown): value is Record { return IsObjectLike(value) && !(value instanceof Date) && !(value instanceof Uint8Array) } /** Checks this value using the AllowNaN policy */ export function IsNumberLike(value: unknown): value is number { return AllowNaN ? IsNumber(value) : Number.isFinite(value) } /** Checks this value using the AllowVoidNull policy */ export function IsVoidLike(value: unknown): value is void { const isUndefined = IsUndefined(value) return AllowNullVoid ? isUndefined || value === null : isUndefined } } sinclairzx81-typebox-e0ec98c/src/system/system.ts000066400000000000000000000060121505437577000222660ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/system The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeRegistry, FormatRegistry } from '../type/registry/index' import { Unsafe, type TUnsafe } from '../type/unsafe/index' import { Kind } from '../type/symbols/index' import { TypeBoxError } from '../type/error/index' // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class TypeSystemDuplicateTypeKind extends TypeBoxError { constructor(kind: string) { super(`Duplicate type kind '${kind}' detected`) } } export class TypeSystemDuplicateFormat extends TypeBoxError { constructor(kind: string) { super(`Duplicate string format '${kind}' detected`) } } // ------------------------------------------------------------------ // TypeSystem // ------------------------------------------------------------------ export type TypeFactoryFunction> = (options?: Partial) => TUnsafe /** Creates user defined types and formats and provides overrides for value checking behaviours */ export namespace TypeSystem { /** Creates a new type */ export function Type>(kind: string, check: (options: Options, value: unknown) => boolean): TypeFactoryFunction { if (TypeRegistry.Has(kind)) throw new TypeSystemDuplicateTypeKind(kind) TypeRegistry.Set(kind, check) return (options: Partial = {}) => Unsafe({ ...options, [Kind]: kind }) } /** Creates a new string format */ export function Format(format: F, check: (value: string) => boolean): F { if (FormatRegistry.Has(format)) throw new TypeSystemDuplicateFormat(format) FormatRegistry.Set(format, check) return format } } sinclairzx81-typebox-e0ec98c/src/tsconfig.json000066400000000000000000000003011505437577000215500ustar00rootroot00000000000000{ "extends": "../tsconfig.json", "files": ["compiler/index.ts", "errors/index.ts", "parser/index.ts", "syntax/index.ts", "system/index.ts", "type/index.ts", "value/index.ts", "index.ts"] } sinclairzx81-typebox-e0ec98c/src/type/000077500000000000000000000000001505437577000200305ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/any/000077500000000000000000000000001505437577000206175ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/any/any.ts000066400000000000000000000032141505437577000217560ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/index' 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 CreateType({ [Kind]: 'Any' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/any/index.ts000066400000000000000000000024611505437577000223010ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/argument/000077500000000000000000000000001505437577000216525ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/argument/argument.ts000066400000000000000000000033421505437577000240460ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import { Kind } from '../symbols/index' export interface TArgument extends TSchema { [Kind]: 'Argument' static: unknown index: Index } /** `[JavaScript]` Creates an Argument Type. */ export function Argument(index: Index): TArgument { return CreateType({ [Kind]: 'Argument', index }) as never } sinclairzx81-typebox-e0ec98c/src/type/argument/index.ts000066400000000000000000000024661505437577000233410ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './argument' sinclairzx81-typebox-e0ec98c/src/type/array/000077500000000000000000000000001505437577000211465ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/array/array.ts000066400000000000000000000047221505437577000226410ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { Ensure } from '../helpers/index' import type { SchemaOptions, TSchema } from '../schema/index' import type { Static } from '../static/index' import { Kind } from '../symbols/index' 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 } type ArrayStatic = Ensure[]> export interface TArray extends TSchema, ArrayOptions { [Kind]: 'Array' static: ArrayStatic type: 'array' items: T } /** `[Json]` Creates an Array type */ export function Array(items: Type, options?: ArrayOptions): TArray { return CreateType({ [Kind]: 'Array', type: 'array', items }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/array/index.ts000066400000000000000000000024631505437577000226320ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/async-iterator/000077500000000000000000000000001505437577000227745ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/async-iterator/async-iterator.ts000066400000000000000000000036441505437577000263170ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' export interface TAsyncIterator extends TSchema { [Kind]: 'AsyncIterator' static: AsyncIterableIterator> type: 'AsyncIterator' items: T } /** `[JavaScript]` Creates a AsyncIterator type */ export function AsyncIterator(items: T, options?: SchemaOptions): TAsyncIterator { return CreateType({ [Kind]: 'AsyncIterator', type: 'AsyncIterator', items }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/async-iterator/index.ts000066400000000000000000000024741505437577000244620ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/awaited/000077500000000000000000000000001505437577000214465ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/awaited/awaited.ts000066400000000000000000000131071505437577000234360ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { Ensure } from '../helpers/index' import type { TSchema, SchemaOptions } from '../schema/index' import { Computed, type TComputed } from '../computed/index' import { Intersect, type TIntersect } from '../intersect/index' import { Union, type TUnion } from '../union/index' import { type TPromise } from '../promise/index' import { Ref, type TRef } from '../ref/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsIntersect, IsUnion, IsPromise, IsRef, IsComputed } from '../guard/kind' // ---------------------------------------------------------------- // FromComputed // ---------------------------------------------------------------- // prettier-ignore type TFromComputed = Ensure<( TComputed<'Awaited', [TComputed]> )> // prettier-ignore function FromComputed(target: Target, parameters: Parameters): TFromComputed { return Computed('Awaited', [Computed(target, parameters)]) as never } // ---------------------------------------------------------------- // Ref // ---------------------------------------------------------------- type TFromRef = Ensure]>> // prettier-ignore function FromRef($ref: Ref): TFromRef { return Computed('Awaited', [Ref($ref)]) as never } // ---------------------------------------------------------------- // FromIntersect // ---------------------------------------------------------------- // prettier-ignore type TFromIntersect = ( TIntersect> ) // prettier-ignore function FromIntersect(types: [...Types]): TFromIntersect { return Intersect(FromRest(types) as TSchema[]) as never } // ---------------------------------------------------------------- // FromUnion // ---------------------------------------------------------------- // prettier-ignore type TFromUnion = TUnion> // prettier-ignore function FromUnion(types: [...Types]): TFromUnion { return Union(FromRest(types) as TSchema[]) as never } // ---------------------------------------------------------------- // Promise // ---------------------------------------------------------------- type TFromPromise = TAwaited // prettier-ignore function FromPromise(type: Type): TFromPromise { return Awaited(type) as never } // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore type TFromRest = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TFromRest]> : Result ) // prettier-ignore function FromRest(types: [...Types]) : TFromRest { return types.map(type => Awaited(type)) as never } // ------------------------------------------------------------------ // TAwaited // ------------------------------------------------------------------ // prettier-ignore export type TAwaited = ( Type extends TComputed ? TFromComputed : Type extends TRef ? TFromRef : Type extends TIntersect ? TIntersect> : Type extends TUnion ? TUnion> : Type extends TPromise ? TAwaited : Type ) /** `[JavaScript]` Constructs a type by recursively unwrapping Promise types */ export function Awaited(type: T, options?: SchemaOptions): TAwaited { return CreateType( IsComputed(type) ? FromComputed(type.target, type.parameters) : IsIntersect(type) ? FromIntersect(type.allOf) : IsUnion(type) ? FromUnion(type.anyOf) : IsPromise(type) ? FromPromise(type.item) : IsRef(type) ? FromRef(type.$ref) : type, options, ) as never } sinclairzx81-typebox-e0ec98c/src/type/awaited/index.ts000066400000000000000000000024651505437577000231340ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/bigint/000077500000000000000000000000001505437577000213045ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/bigint/bigint.ts000066400000000000000000000036021505437577000231310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' import { CreateType } from '../create/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 CreateType({ [Kind]: 'BigInt', type: 'bigint' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/bigint/index.ts000066400000000000000000000024641505437577000227710ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/boolean/000077500000000000000000000000001505437577000214475ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/boolean/boolean.ts000066400000000000000000000033111505437577000234340ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' import { CreateType } from '../create/index' export interface TBoolean extends TSchema { [Kind]: 'Boolean' static: boolean type: 'boolean' } /** `[Json]` Creates a Boolean type */ export function Boolean(options?: SchemaOptions): TBoolean { return CreateType({ [Kind]: 'Boolean', type: 'boolean' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/boolean/index.ts000066400000000000000000000024651505437577000231350ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/clone/000077500000000000000000000000001505437577000211305ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/clone/index.ts000066400000000000000000000025121505437577000226070ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './type' export * from './value' sinclairzx81-typebox-e0ec98c/src/type/clone/type.ts000066400000000000000000000033101505437577000224560ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, SchemaOptions } from '../schema/index' import { Clone } from './value' /** Clones a Rest */ export function CloneRest(schemas: T): T { return schemas.map((schema) => CloneType(schema)) as never } /** Clones a Type */ export function CloneType(schema: T, options?: SchemaOptions): T { return options === undefined ? Clone(schema) : Clone({ ...options, ...schema }) } sinclairzx81-typebox-e0ec98c/src/type/clone/value.ts000066400000000000000000000046351505437577000226240ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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) { const result = {} as Record for (const key of Object.getOwnPropertyNames(value)) { result[key] = Visit(value[key]) } for (const key of Object.getOwnPropertySymbols(value)) { result[key] = Visit(value[key]) } return result } // 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(value: T): T { return Visit(value) } sinclairzx81-typebox-e0ec98c/src/type/composite/000077500000000000000000000000001505437577000220325ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/composite/composite.ts000066400000000000000000000123641505437577000244120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { IntersectEvaluated, type TIntersectEvaluated } from '../intersect/index' import { IndexFromPropertyKeys, type TIndexFromPropertyKeys } from '../indexed/index' import { KeyOfPropertyKeys, type TKeyOfPropertyKeys } from '../keyof/index' import { type TNever } from '../never/index' import { Object, type TObject, type TProperties, type ObjectOptions } from '../object/index' import { SetDistinct, TSetDistinct } from '../sets/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsNever } from '../guard/kind' // ------------------------------------------------------------------ // CompositeKeys // ------------------------------------------------------------------ // prettier-ignore type TCompositeKeys = ( T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TCompositeKeys]> : TSetDistinct ) // prettier-ignore function CompositeKeys(T: [...T]): TCompositeKeys { const Acc = [] as PropertyKey[] for(const L of T) Acc.push(...KeyOfPropertyKeys(L)) return SetDistinct(Acc) as never } // ------------------------------------------------------------------ // FilterNever // ------------------------------------------------------------------ // prettier-ignore type TFilterNever = ( T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? L extends TNever ? TFilterNever : TFilterNever : Acc ) // prettier-ignore function FilterNever(T: [...T]): TFilterNever { return T.filter(L => !IsNever(L)) as never } // ------------------------------------------------------------------ // CompositeProperty // ------------------------------------------------------------------ // prettier-ignore type TCompositeProperty = ( T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TCompositeProperty]> : TFilterNever ) // prettier-ignore function CompositeProperty(T: [...T], K: K): TCompositeProperty { const Acc = [] as TSchema[] for(const L of T) Acc.push(...IndexFromPropertyKeys(L, [K])) return FilterNever(Acc) as never } // ------------------------------------------------------------------ // CompositeProperties // ------------------------------------------------------------------ // prettier-ignore type TCompositeProperties = ( K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? TCompositeProperties> }> : Acc ) // prettier-ignore function CompositeProperties(T: [...T], K: [...K]): TCompositeProperties { const Acc = {} as never for(const L of K) { Acc[L] = IntersectEvaluated(CompositeProperty(T, L)) } return Acc } // ------------------------------------------------------------------ // Composite // ------------------------------------------------------------------ // prettier-ignore type TCompositeEvaluate< T extends TSchema[], K extends PropertyKey[] = TCompositeKeys, P extends TProperties = Evaluate>, R extends TObject = TObject

> = R // prettier-ignore export type TComposite = TCompositeEvaluate // prettier-ignore export function Composite(T: [...T], options?: ObjectOptions): TComposite { const K = CompositeKeys(T) const P = CompositeProperties(T, K) const R = Object(P, options) return R as never } sinclairzx81-typebox-e0ec98c/src/type/composite/index.ts000066400000000000000000000024671505437577000235220ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/computed/000077500000000000000000000000001505437577000216505ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/computed/computed.ts000066400000000000000000000042541505437577000240450ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/index' import { Kind } from '../symbols/symbols' // ------------------------------------------------------------------ // Computed // ------------------------------------------------------------------ export interface TComputed extends TSchema { [Kind]: 'Computed' target: Target parameters: Parameters } /** `[Internal]` Creates a deferred computed type. This type is used exclusively in modules to defer resolution of computable types that contain interior references */ export function Computed(target: Target, parameters: [...Parameters], options?: SchemaOptions): TComputed { return CreateType({ [Kind]: 'Computed', target, parameters }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/computed/index.ts000066400000000000000000000024661505437577000233370ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './computed' sinclairzx81-typebox-e0ec98c/src/type/const/000077500000000000000000000000001505437577000211565ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/const/const.ts000066400000000000000000000146201505437577000226570ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/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 [infer L extends unknown, ...infer R extends unknown[]] ? [FromValue, ...TFromArray] : T // prettier-ignore function FromArray(T: [...T]): TFromArray { return T.map(L => FromValue(L, false)) as never } // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties> = { -readonly [K in keyof T]: FromValue extends infer R extends TSchema ? TReadonly : TReadonly } // prettier-ignore function FromProperties>(value: T): TFromProperties { const Acc = {} as TProperties for(const K of globalThis.Object.getOwnPropertyNames(value)) Acc[K] = Readonly(FromValue(value[K], false)) return Acc as never } // ------------------------------------------------------------------ // ConditionalReadonly - Only applied if not root // ------------------------------------------------------------------ type TConditionalReadonly = Root extends true ? T : TReadonly function ConditionalReadonly(T: T, root: Root): TConditionalReadonly { return (root === true ? T : Readonly(T)) as never } // ------------------------------------------------------------------ // FromValue // ------------------------------------------------------------------ // prettier-ignore type FromValue = T extends AsyncIterableIterator ? TConditionalReadonly : T extends IterableIterator ? TConditionalReadonly : T extends readonly unknown[] ? TReadonly>>> : T extends Uint8Array ? TUint8Array : T extends Date ? TDate : T extends Record ? TConditionalReadonly>>, Root> : T extends Function ? TConditionalReadonly, Root> : T extends undefined ? TUndefined : T extends null ? TNull : T extends symbol ? TSymbol : T extends number ? TLiteral : T extends boolean ? TLiteral : T extends string ? TLiteral : T extends bigint ? TBigInt : TObject<{}> // prettier-ignore function FromValue(value: T, root: Root): FromValue { 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) 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 never } // ------------------------------------------------------------------ // TConst // ------------------------------------------------------------------ export type TConst = FromValue /** `[JavaScript]` Creates a readonly const type from the given value. */ export function Const(T: T, options?: SchemaOptions): TConst { return CreateType(FromValue(T, true), options) as never } sinclairzx81-typebox-e0ec98c/src/type/const/index.ts000066400000000000000000000024631505437577000226420ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/constructor-parameters/000077500000000000000000000000001505437577000245565ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/constructor-parameters/constructor-parameters.ts000066400000000000000000000043571505437577000316650ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TConstructor } from '../constructor/index' import { Tuple, type TTuple } from '../tuple/index' import { Never, type TNever } from '../never/index' import * as KindGuard from '../guard/kind' // ------------------------------------------------------------------ // ConstructorParameters // ------------------------------------------------------------------ // prettier-ignore export type TConstructorParameters = ( Type extends TConstructor ? TTuple : TNever ) /** `[JavaScript]` Extracts the ConstructorParameters from the given Constructor type */ export function ConstructorParameters(schema: Type, options?: SchemaOptions): TConstructorParameters { return (KindGuard.IsConstructor(schema) ? Tuple(schema.parameters, options) : Never(options)) as never } sinclairzx81-typebox-e0ec98c/src/type/constructor-parameters/index.ts000066400000000000000000000025041505437577000262360ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/constructor/000077500000000000000000000000001505437577000224155ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/constructor/constructor.ts000066400000000000000000000064321505437577000253570ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 type { TReadonlyOptional } from '../readonly-optional/index' import type { TReadonly } from '../readonly/index' import type { TOptional } from '../optional/index' import { CreateType } from '../create/type' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ // StaticConstructor // ------------------------------------------------------------------ type StaticReturnType = Static // prettier-ignore type StaticParameter = T extends TReadonlyOptional ? [Readonly>?] : T extends TReadonly ? [Readonly>] : T extends TOptional ? [Static?] : [Static] // prettier-ignore type StaticParameters = ( T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? StaticParameters]> : Acc ) // prettier-ignore type StaticConstructor = Ensure) => StaticReturnType> // ------------------------------------------------------------------ // TConstructor // ------------------------------------------------------------------ export interface TConstructor extends TSchema { [Kind]: 'Constructor' static: StaticConstructor type: 'Constructor' parameters: T returns: U } /** `[JavaScript]` Creates a Constructor type */ export function Constructor(parameters: [...T], returns: U, options?: SchemaOptions): TConstructor { return CreateType({ [Kind]: 'Constructor', type: 'Constructor', parameters, returns }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/constructor/index.ts000066400000000000000000000024711505437577000241000ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/create/000077500000000000000000000000001505437577000212735ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/create/immutable.ts000066400000000000000000000047331505437577000236310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 ImmutableArray(value: unknown[]) { return globalThis.Object.freeze(value as any).map((value: unknown) => Immutable(value as any)) } function ImmutableDate(value: Date) { return value } function ImmutableUint8Array(value: Uint8Array) { return value } function ImmutableRegExp(value: RegExp) { return value } function ImmutableObject(value: Record) { const result = {} as Record for (const key of Object.getOwnPropertyNames(value)) { result[key] = Immutable(value[key]) } for (const key of Object.getOwnPropertySymbols(value)) { result[key] = Immutable(value[key]) } return globalThis.Object.freeze(result) } /** Specialized deep immutable value. Applies freeze recursively to the given value */ // prettier-ignore export function Immutable(value: unknown): unknown { return ( ValueGuard.IsArray(value) ? ImmutableArray(value) : ValueGuard.IsDate(value) ? ImmutableDate(value) : ValueGuard.IsUint8Array(value) ? ImmutableUint8Array(value) : ValueGuard.IsRegExp(value) ? ImmutableRegExp(value) : ValueGuard.IsObject(value) ? ImmutableObject(value) : value ) } sinclairzx81-typebox-e0ec98c/src/type/create/index.ts000066400000000000000000000024621505437577000227560ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './type' sinclairzx81-typebox-e0ec98c/src/type/create/type.ts000066400000000000000000000035611505437577000226310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeSystemPolicy } from '../../system/policy' import { SchemaOptions } from '../schema/schema' import { Immutable } from './immutable' import { Clone } from '../clone/value' /** Creates TypeBox schematics using the configured InstanceMode */ export function CreateType(schema: Record, options?: SchemaOptions): unknown { const result = options !== undefined ? { ...options, ...schema } : schema switch (TypeSystemPolicy.InstanceMode) { case 'freeze': return Immutable(result) case 'clone': return Clone(result) default: return result } } sinclairzx81-typebox-e0ec98c/src/type/date/000077500000000000000000000000001505437577000207455ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/date/date.ts000066400000000000000000000041471505437577000222400ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' import { CreateType } from '../create/type' 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 CreateType({ [Kind]: 'Date', type: 'Date' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/date/index.ts000066400000000000000000000024621505437577000224300ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/discard/000077500000000000000000000000001505437577000214415ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/discard/discard.ts000066400000000000000000000032071505437577000234240ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, key: PropertyKey) { const { [key]: _, ...rest } = value return rest } /** Discards property keys from the given value. This function returns a shallow Clone. */ export function Discard(value: Record, keys: PropertyKey[]) { return keys.reduce((acc, key) => DiscardKey(acc, key), value) } sinclairzx81-typebox-e0ec98c/src/type/discard/index.ts000066400000000000000000000024651505437577000231270ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/enum/000077500000000000000000000000001505437577000207745ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/enum/enum.ts000066400000000000000000000052451505437577000223160ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 export type TEnumValue = string | number export type TEnumKey = string export interface TEnum = Record> extends TSchema { [Kind]: 'Union' [Hint]: 'Enum' static: T[keyof T] anyOf: TLiteral[] } /** `[Json]` Creates a Enum type */ export function Enum>(item: T, options?: SchemaOptions): TEnum { 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 never } sinclairzx81-typebox-e0ec98c/src/type/enum/index.ts000066400000000000000000000024621505437577000224570ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/error/000077500000000000000000000000001505437577000211615ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/error/error.ts000066400000000000000000000026751505437577000226740ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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) } } sinclairzx81-typebox-e0ec98c/src/type/error/index.ts000066400000000000000000000024631505437577000226450ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/exclude/000077500000000000000000000000001505437577000214615ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/exclude/exclude-from-mapped-result.ts000066400000000000000000000061651505437577000272130ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { 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 } ) // prettier-ignore function FromProperties< P extends TProperties, T extends TSchema >(P: P, U: T): TFromProperties { const Acc = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Exclude(P[K2], U) return Acc as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult< R extends TMappedResult, T extends TSchema > = ( TFromProperties ) // prettier-ignore function FromMappedResult< R extends TMappedResult, T extends TSchema >(R: R, T: T): TFromMappedResult { return FromProperties(R.properties, T) as never } // ------------------------------------------------------------------ // ExcludeFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TExcludeFromMappedResult< R extends TMappedResult, T extends TSchema, P extends TProperties = TFromMappedResult > = ( TMappedResult

) // prettier-ignore export function ExcludeFromMappedResult< R extends TMappedResult, T extends TSchema, P extends TProperties = TFromMappedResult >(R: R, T: T): TMappedResult

{ const P = FromMappedResult(R, T) return MappedResult(P) as never } sinclairzx81-typebox-e0ec98c/src/type/exclude/exclude-from-template-literal.ts000066400000000000000000000035201505437577000276660ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TExclude, Exclude } from './exclude' import { TemplateLiteralToUnion, type TTemplateLiteral, type TTemplateLiteralToUnion } from '../template-literal/index' // prettier-ignore export type TExcludeFromTemplateLiteral = ( TExclude, R> ) export function ExcludeFromTemplateLiteral(L: L, R: R): TExcludeFromTemplateLiteral { return Exclude(TemplateLiteralToUnion(L), R) as never } sinclairzx81-typebox-e0ec98c/src/type/exclude/exclude.ts000066400000000000000000000110461505437577000234640ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { UnionToTuple, AssertRest, AssertType } from '../helpers/index' import type { TMappedResult } from '../mapped/index' import { type TTemplateLiteral } from '../template-literal/index' import { Union, type TUnion } from '../union/index' import { Never, type TNever } from '../never/index' import { type Static } from '../static/index' import { type TUnionEvaluated } from '../union/index' import { ExtendsCheck, ExtendsResult } from '../extends/index' import { ExcludeFromMappedResult, type TExcludeFromMappedResult } from './exclude-from-mapped-result' import { ExcludeFromTemplateLiteral, type TExcludeFromTemplateLiteral } from './exclude-from-template-literal' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/kind' // ------------------------------------------------------------------ // ExcludeRest // ------------------------------------------------------------------ // prettier-ignore type TExcludeRest = AssertRest> extends Static ? never : L[K] }[number]>> extends infer R extends TSchema[] ? TUnionEvaluated : never function ExcludeRest(L: [...L], R: R) { const excluded = L.filter((inner) => ExtendsCheck(inner, R) === ExtendsResult.False) return excluded.length === 1 ? excluded[0] : Union(excluded) } // ------------------------------------------------------------------ // TExclude // ------------------------------------------------------------------ // prettier-ignore export type TExclude = ( L extends TUnion ? TExcludeRest : L extends R ? TNever : L ) /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ export function Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExcludeFromMappedResult /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ export function Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExcludeFromTemplateLiteral /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ export function Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExclude /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ export function Exclude(L: TSchema, R: TSchema, options: SchemaOptions = {}): any { // overloads if (IsTemplateLiteral(L)) return CreateType(ExcludeFromTemplateLiteral(L, R), options) if (IsMappedResult(L)) return CreateType(ExcludeFromMappedResult(L, R), options) // prettier-ignore return CreateType( IsUnion(L) ? ExcludeRest(L.anyOf, R) : ExtendsCheck(L, R) !== ExtendsResult.False ? Never() : L , options) } sinclairzx81-typebox-e0ec98c/src/type/exclude/index.ts000066400000000000000000000026221505437577000231420ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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-from-template-literal' export * from './exclude' sinclairzx81-typebox-e0ec98c/src/type/extends/000077500000000000000000000000001505437577000215025ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/extends/extends-check.ts000066400000000000000000000776011505437577000246120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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(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) } sinclairzx81-typebox-e0ec98c/src/type/extends/extends-from-mapped-key.ts000066400000000000000000000107671505437577000265320ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromPropertyKey // ------------------------------------------------------------------ // prettier-ignore type TFromPropertyKey< K extends PropertyKey, U extends TSchema, L extends TSchema, R extends TSchema > = { [_ in K]: TExtends>, 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 { return { [K]: Extends(Literal(K as TLiteralValue), U, L, R, Clone(options)) as any } as never } // ------------------------------------------------------------------ // 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> : 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 { return K.reduce((Acc, LK) => { return { ...Acc, ...FromPropertyKey(LK, U, L, R, options) } }, {} as TProperties) as never } // ------------------------------------------------------------------ // FromMappedKey // ------------------------------------------------------------------ // prettier-ignore type TFromMappedKey< K extends TMappedKey, U extends TSchema, L extends TSchema, R extends TSchema > = ( TFromPropertyKeys ) // 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 { return FromPropertyKeys(K.keys, U, L, R, options) as never } // ------------------------------------------------------------------ // ExtendsFromMappedKey // ------------------------------------------------------------------ // prettier-ignore export type TExtendsFromMappedKey< T extends TMappedKey, U extends TSchema, L extends TSchema, R extends TSchema, P extends TProperties = TFromMappedKey > = ( TMappedResult

) // prettier-ignore export function ExtendsFromMappedKey< T extends TMappedKey, U extends TSchema, L extends TSchema, R extends TSchema, P extends TProperties = TFromMappedKey >(T: T, U: U, L: L, R: R, options?: SchemaOptions): TMappedResult

{ const P = FromMappedKey(T, U, L, R, options) return MappedResult(P) as never } sinclairzx81-typebox-e0ec98c/src/type/extends/extends-from-mapped-result.ts000066400000000000000000000075751505437577000272630ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties< P extends TProperties, Right extends TSchema, False extends TSchema, True extends TSchema > = ( { [K2 in keyof P]: TExtends } ) // 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 { const Acc = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Extends(P[K2], Right, True, False, Clone(options)) return Acc as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult< Left extends TMappedResult, Right extends TSchema, True extends TSchema, False extends TSchema > = ( TFromProperties ) // 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 { return FromProperties(Left.properties, Right, True, False, options) as never } // ------------------------------------------------------------------ // ExtendsFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TExtendsFromMappedResult< Left extends TMappedResult, Right extends TSchema, True extends TSchema, False extends TSchema, P extends TProperties = TFromMappedResult > = ( TMappedResult

) // prettier-ignore export function ExtendsFromMappedResult< Left extends TMappedResult, Right extends TSchema, True extends TSchema, False extends TSchema, P extends TProperties = TFromMappedResult >(Left: Left, Right: Right, True: True, False: False, options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(Left, Right, True, False, options) return MappedResult(P) as never } sinclairzx81-typebox-e0ec98c/src/type/extends/extends-undefined.ts000066400000000000000000000043631505437577000254710ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 ) } sinclairzx81-typebox-e0ec98c/src/type/extends/extends.ts000066400000000000000000000101351505437577000235240ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' 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 { ExtendsFromMappedKey, type TExtendsFromMappedKey } from './extends-from-mapped-key' import { ExtendsFromMappedResult, type TExtendsFromMappedResult } from './extends-from-mapped-result' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsMappedKey, IsMappedResult } from '../guard/kind' // prettier-ignore type TExtendsResolve = ( (Static extends Static ? T : U) extends infer O extends TSchema ? UnionToTuple extends [infer X extends TSchema, infer Y extends TSchema] ? TUnion<[X, Y]> : O : never ) // prettier-ignore function ExtendsResolve(left: L, right: R, trueType: T, falseType: U): TExtendsResolve { const R = ExtendsCheck(left, right) return ( R === ExtendsResult.Union ? Union([trueType, falseType]) : R === ExtendsResult.True ? trueType : falseType ) as never } // ------------------------------------------------------------------ // TExtends // ------------------------------------------------------------------ export type TExtends = TExtendsResolve /** `[Json]` Creates a Conditional type */ export function Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtendsFromMappedResult /** `[Json]` Creates a Conditional type */ export function Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtendsFromMappedKey /** `[Json]` Creates a Conditional type */ export function Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtends /** `[Json]` Creates a Conditional type */ export function Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions) { // prettier-ignore return ( IsMappedResult(L) ? ExtendsFromMappedResult(L, R, T, F, options) : IsMappedKey(L) ? CreateType(ExtendsFromMappedKey(L, R, T, F, options)) : CreateType(ExtendsResolve(L, R, T, F), options) ) as never } sinclairzx81-typebox-e0ec98c/src/type/extends/index.ts000066400000000000000000000027201505437577000231620ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/extract/000077500000000000000000000000001505437577000215025ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/extract/extract-from-mapped-result.ts000066400000000000000000000061631505437577000272530ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { 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 } ) // prettier-ignore function FromProperties< P extends TProperties, T extends TSchema >(P: P, T: T): TFromProperties { const Acc = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Extract(P[K2], T) return Acc as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult< R extends TMappedResult, T extends TSchema > = ( TFromProperties ) // prettier-ignore function FromMappedResult< R extends TMappedResult, T extends TSchema >(R: R, T: T): TFromMappedResult { return FromProperties(R.properties, T) as never } // ------------------------------------------------------------------ // ExtractFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TExtractFromMappedResult< R extends TMappedResult, T extends TSchema, P extends TProperties = TFromMappedResult > = ( TMappedResult

) // prettier-ignore export function ExtractFromMappedResult< R extends TMappedResult, T extends TSchema, P extends TProperties = TFromMappedResult >(R: R, T: T): TMappedResult

{ const P = FromMappedResult(R, T) return MappedResult(P) as never } sinclairzx81-typebox-e0ec98c/src/type/extract/extract-from-template-literal.ts000066400000000000000000000035251505437577000277350ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Extract, type TExtract } from './extract' import { TemplateLiteralToUnion, type TTemplateLiteral, type TTemplateLiteralToUnion } from '../template-literal/index' // prettier-ignore export type TExtractFromTemplateLiteral = ( TExtract, R> ) export function ExtractFromTemplateLiteral(L: L, R: R): TExtractFromTemplateLiteral { return Extract(TemplateLiteralToUnion(L), R) as never } sinclairzx81-typebox-e0ec98c/src/type/extract/extract.ts000066400000000000000000000107451505437577000235330ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { AssertRest, AssertType, UnionToTuple } from '../helpers/index' import type { TMappedResult } from '../mapped/index' import { Union, type TUnion } from '../union/index' import { type Static } from '../static/index' import { Never, type TNever } from '../never/index' import { type TUnionEvaluated } from '../union/index' import { type TTemplateLiteral } from '../template-literal/index' import { ExtendsCheck, ExtendsResult } from '../extends/index' import { ExtractFromMappedResult, type TExtractFromMappedResult } from './extract-from-mapped-result' import { ExtractFromTemplateLiteral, type TExtractFromTemplateLiteral } from './extract-from-template-literal' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/kind' // ------------------------------------------------------------------ // ExtractRest // ------------------------------------------------------------------ // prettier-ignore type TExtractRest = AssertRest> extends Static ? L[K] : never }[number]>> extends infer R extends TSchema[] ? TUnionEvaluated : never function ExtractRest(L: [...L], R: R) { const extracted = L.filter((inner) => ExtendsCheck(inner, R) !== ExtendsResult.False) return extracted.length === 1 ? extracted[0] : Union(extracted) } // ------------------------------------------------------------------ // TExtract // ------------------------------------------------------------------ // prettier-ignore export type TExtract = ( L extends TUnion ? TExtractRest : L extends U ? L : TNever ) /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ export function Extract(type: L, union: R, options?: SchemaOptions): TExtractFromMappedResult /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ export function Extract(type: L, union: R, options?: SchemaOptions): TExtractFromTemplateLiteral /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ export function Extract(type: L, union: R, options?: SchemaOptions): TExtract /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ export function Extract(L: TSchema, R: TSchema, options?: SchemaOptions): never { // overloads if (IsTemplateLiteral(L)) return CreateType(ExtractFromTemplateLiteral(L, R), options) as never if (IsMappedResult(L)) return CreateType(ExtractFromMappedResult(L, R), options) as never // prettier-ignore return CreateType( IsUnion(L) ? ExtractRest(L.anyOf, R) : ExtendsCheck(L, R) !== ExtendsResult.False ? L : Never() , options) as never } sinclairzx81-typebox-e0ec98c/src/type/extract/index.ts000066400000000000000000000026221505437577000231630ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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-from-template-literal' export * from './extract' sinclairzx81-typebox-e0ec98c/src/type/function/000077500000000000000000000000001505437577000216555ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/function/function.ts000066400000000000000000000063631505437577000240620ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import type { Ensure } from '../helpers/index' import type { TReadonlyOptional } from '../readonly-optional/index' import type { TReadonly } from '../readonly/index' import type { TOptional } from '../optional/index' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ // StaticFunction // ------------------------------------------------------------------ type StaticReturnType = Static // prettier-ignore type StaticParameter = T extends TReadonlyOptional ? [Readonly>?] : T extends TReadonly ? [Readonly>] : T extends TOptional ? [Static?] : [Static] // prettier-ignore type StaticParameters = ( T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? StaticParameters]> : Acc ) // prettier-ignore type StaticFunction = Ensure<(...param: StaticParameters) => StaticReturnType> // ------------------------------------------------------------------ // TFunction // ------------------------------------------------------------------ export interface TFunction extends TSchema { [Kind]: 'Function' static: StaticFunction type: 'Function' parameters: T returns: U } /** `[JavaScript]` Creates a Function type */ export function Function(parameters: [...T], returns: U, options?: SchemaOptions): TFunction { return CreateType({ [Kind]: 'Function', type: 'Function', parameters, returns }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/function/index.ts000066400000000000000000000024661505437577000233440ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/guard/000077500000000000000000000000001505437577000211325ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/guard/index.ts000066400000000000000000000026111505437577000226110ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 KindGuard from './kind' export * as TypeGuard from './type' export * as ValueGuard from './value' sinclairzx81-typebox-e0ec98c/src/type/guard/kind.ts000066400000000000000000000315001505437577000224260ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TransformOptions } from '../transform/index' import type { TAny } from '../any/index' import type { TArgument } from '../argument/index' import type { TArray } from '../array/index' import type { TAsyncIterator } from '../async-iterator/index' import type { TBoolean } from '../boolean/index' import type { TComputed } from '../computed/index' import type { TBigInt } from '../bigint/index' import type { TConstructor } from '../constructor/index' import type { TFunction } from '../function/index' import type { TImport } from '../module/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, TProperties } from '../object/index' import type { TOptional } from '../optional/index' import type { TPromise } from '../promise/index' import type { TReadonly } from '../readonly/index' import type { TRecord } from '../record/index' import type { TRef } from '../ref/index' import type { TRegExp } from '../regexp/index' import type { TSchema } from '../schema/index' import type { TString } from '../string/index' import type { TSymbol } from '../symbol/index' import type { TTemplateLiteral } from '../template-literal/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 { TUnion } from '../union/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' /** `[Kind-Only]` Returns true if this value has a Readonly symbol */ export function IsReadonly(value: T): value is TReadonly { return ValueGuard.IsObject(value) && value[ReadonlyKind] === 'Readonly' } /** `[Kind-Only]` Returns true if this value has a Optional symbol */ export function IsOptional(value: T): value is TOptional { return ValueGuard.IsObject(value) && value[OptionalKind] === 'Optional' } /** `[Kind-Only]` Returns true if the given value is TAny */ export function IsAny(value: unknown): value is TAny { return IsKindOf(value, 'Any') } /** `[Kind-Only]` Returns true if the given value is TArgument */ export function IsArgument(value: unknown): value is TArgument { return IsKindOf(value, 'Argument') } /** `[Kind-Only]` Returns true if the given value is TArray */ export function IsArray(value: unknown): value is TArray { return IsKindOf(value, 'Array') } /** `[Kind-Only]` Returns true if the given value is TAsyncIterator */ export function IsAsyncIterator(value: unknown): value is TAsyncIterator { return IsKindOf(value, 'AsyncIterator') } /** `[Kind-Only]` Returns true if the given value is TBigInt */ export function IsBigInt(value: unknown): value is TBigInt { return IsKindOf(value, 'BigInt') } /** `[Kind-Only]` Returns true if the given value is TBoolean */ export function IsBoolean(value: unknown): value is TBoolean { return IsKindOf(value, 'Boolean') } /** `[Kind-Only]` Returns true if the given value is TComputed */ export function IsComputed(value: unknown): value is TComputed { return IsKindOf(value, 'Computed') } /** `[Kind-Only]` Returns true if the given value is TConstructor */ export function IsConstructor(value: unknown): value is TConstructor { return IsKindOf(value, 'Constructor') } /** `[Kind-Only]` Returns true if the given value is TDate */ export function IsDate(value: unknown): value is TDate { return IsKindOf(value, 'Date') } /** `[Kind-Only]` Returns true if the given value is TFunction */ export function IsFunction(value: unknown): value is TFunction { return IsKindOf(value, 'Function') } /** `[Kind-Only]` Returns true if the given value is TInteger */ export function IsImport(value: unknown): value is TImport { return IsKindOf(value, 'Import') } /** `[Kind-Only]` Returns true if the given value is TInteger */ export function IsInteger(value: unknown): value is TInteger { return IsKindOf(value, 'Integer') } /** `[Kind-Only]` Returns true if the given schema is TProperties */ export function IsProperties(value: unknown): value is TProperties { return ValueGuard.IsObject(value) } /** `[Kind-Only]` Returns true if the given value is TIntersect */ export function IsIntersect(value: unknown): value is TIntersect { return IsKindOf(value, 'Intersect') } /** `[Kind-Only]` Returns true if the given value is TIterator */ export function IsIterator(value: unknown): value is TIterator { return IsKindOf(value, 'Iterator') } /** `[Kind-Only]` Returns true if the given value is a TKind with the given name. */ export function IsKindOf(value: unknown, kind: T): value is Record & { [Kind]: T } { return ValueGuard.IsObject(value) && Kind in value && value[Kind] === kind } /** `[Kind-Only]` Returns true if the given value is TLiteral */ export function IsLiteralString(value: unknown): value is TLiteral { return IsLiteral(value) && ValueGuard.IsString(value.const) } /** `[Kind-Only]` Returns true if the given value is TLiteral */ export function IsLiteralNumber(value: unknown): value is TLiteral { return IsLiteral(value) && ValueGuard.IsNumber(value.const) } /** `[Kind-Only]` Returns true if the given value is TLiteral */ export function IsLiteralBoolean(value: unknown): value is TLiteral { return IsLiteral(value) && ValueGuard.IsBoolean(value.const) } /** `[Kind-Only]` Returns true if the given value is TLiteralValue */ export function IsLiteralValue(value: unknown): value is TLiteralValue { return ValueGuard.IsBoolean(value) || ValueGuard.IsNumber(value) || ValueGuard.IsString(value) } /** `[Kind-Only]` Returns true if the given value is TLiteral */ export function IsLiteral(value: unknown): value is TLiteral { return IsKindOf(value, 'Literal') } /** `[Kind-Only]` Returns true if the given value is a TMappedKey */ export function IsMappedKey(value: unknown): value is TMappedKey { return IsKindOf(value, 'MappedKey') } /** `[Kind-Only]` Returns true if the given value is TMappedResult */ export function IsMappedResult(value: unknown): value is TMappedResult { return IsKindOf(value, 'MappedResult') } /** `[Kind-Only]` Returns true if the given value is TNever */ export function IsNever(value: unknown): value is TNever { return IsKindOf(value, 'Never') } /** `[Kind-Only]` Returns true if the given value is TNot */ export function IsNot(value: unknown): value is TNot { return IsKindOf(value, 'Not') } /** `[Kind-Only]` Returns true if the given value is TNull */ export function IsNull(value: unknown): value is TNull { return IsKindOf(value, 'Null') } /** `[Kind-Only]` Returns true if the given value is TNumber */ export function IsNumber(value: unknown): value is TNumber { return IsKindOf(value, 'Number') } /** `[Kind-Only]` Returns true if the given value is TObject */ export function IsObject(value: unknown): value is TObject { return IsKindOf(value, 'Object') } /** `[Kind-Only]` Returns true if the given value is TPromise */ export function IsPromise(value: unknown): value is TPromise { return IsKindOf(value, 'Promise') } /** `[Kind-Only]` Returns true if the given value is TRecord */ export function IsRecord(value: unknown): value is TRecord { return IsKindOf(value, 'Record') } /** `[Kind-Only]` 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' } /** `[Kind-Only]` Returns true if the given value is TRef */ export function IsRef(value: unknown): value is TRef { return IsKindOf(value, 'Ref') } /** `[Kind-Only]` Returns true if the given value is TRegExp */ export function IsRegExp(value: unknown): value is TRegExp { return IsKindOf(value, 'RegExp') } /** `[Kind-Only]` Returns true if the given value is TString */ export function IsString(value: unknown): value is TString { return IsKindOf(value, 'String') } /** `[Kind-Only]` Returns true if the given value is TSymbol */ export function IsSymbol(value: unknown): value is TSymbol { return IsKindOf(value, 'Symbol') } /** `[Kind-Only]` Returns true if the given value is TTemplateLiteral */ export function IsTemplateLiteral(value: unknown): value is TTemplateLiteral { return IsKindOf(value, 'TemplateLiteral') } /** `[Kind-Only]` Returns true if the given value is TThis */ export function IsThis(value: unknown): value is TThis { return IsKindOf(value, 'This') } /** `[Kind-Only]` Returns true of this value is TTransform */ export function IsTransform(value: unknown): value is { [TransformKind]: TransformOptions } { return ValueGuard.IsObject(value) && TransformKind in value } /** `[Kind-Only]` Returns true if the given value is TTuple */ export function IsTuple(value: unknown): value is TTuple { return IsKindOf(value, 'Tuple') } /** `[Kind-Only]` Returns true if the given value is TUndefined */ export function IsUndefined(value: unknown): value is TUndefined { return IsKindOf(value, 'Undefined') } /** `[Kind-Only]` Returns true if the given value is TUnion */ export function IsUnion(value: unknown): value is TUnion { return IsKindOf(value, 'Union') } /** `[Kind-Only]` Returns true if the given value is TUint8Array */ export function IsUint8Array(value: unknown): value is TUint8Array { return IsKindOf(value, 'Uint8Array') } /** `[Kind-Only]` Returns true if the given value is TUnknown */ export function IsUnknown(value: unknown): value is TUnknown { return IsKindOf(value, 'Unknown') } /** `[Kind-Only]` Returns true if the given value is a raw TUnsafe */ export function IsUnsafe(value: unknown): value is TUnsafe { return IsKindOf(value, 'Unsafe') } /** `[Kind-Only]` Returns true if the given value is TVoid */ export function IsVoid(value: unknown): value is TVoid { return IsKindOf(value, 'Void') } /** `[Kind-Only]` Returns true if the given value is TKind */ export function IsKind(value: unknown): value is Record & { [Kind]: string } { return ValueGuard.IsObject(value) && Kind in value && ValueGuard.IsString(value[Kind]) } /** `[Kind-Only]` Returns true if the given value is TSchema */ export function IsSchema(value: unknown): value is TSchema { // prettier-ignore return ( IsAny(value) || IsArgument(value) || IsArray(value) || IsBoolean(value) || IsBigInt(value) || IsAsyncIterator(value) || IsComputed(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) ) } sinclairzx81-typebox-e0ec98c/src/type/guard/type.ts000066400000000000000000000542161505437577000224730ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 type { TAny } from '../any/index' import type { TArgument } from '../argument/index' import type { TArray } from '../array/index' import type { TAsyncIterator } from '../async-iterator/index' import type { TBoolean } from '../boolean/index' import type { TComputed } from '../computed/index' import type { TBigInt } from '../bigint/index' import type { TConstructor } from '../constructor/index' import type { TFunction } from '../function/index' import type { TImport } from '../module/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 { TRecord } from '../record/index' import type { TRef } from '../ref/index' import type { TRegExp } from '../regexp/index' import type { TSchema } from '../schema/index' import type { TString } from '../string/index' import type { TSymbol } from '../symbol/index' import type { TTemplateLiteral } from '../template-literal/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 } 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 = [ 'Argument', 'Any', 'Array', 'AsyncIterator', 'BigInt', 'Boolean', 'Computed', '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(value: T): value is TReadonly { return ValueGuard.IsObject(value) && value[ReadonlyKind] === 'Readonly' } /** Returns true if this value has a Optional symbol */ export function IsOptional(value: T): value is TOptional { 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 TArgument */ export function IsArgument(value: unknown): value is TArgument { // prettier-ignore return ( IsKindOf(value, 'Argument') && ValueGuard.IsNumber(value.index) ) } /** 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 TComputed */ export function IsComputed(value: unknown): value is TComputed { // prettier-ignore return ( IsKindOf(value, 'Computed') && ValueGuard.IsString(value.target) && ValueGuard.IsArray(value.parameters) && value.parameters.every((schema) => IsSchema(schema)) ) } /** 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 TImport */ export function IsImport(value: unknown): value is TImport { // prettier-ignore return ( IsKindOf(value, 'Import') && ValueGuard.HasPropertyKey(value, '$defs') && ValueGuard.IsObject(value.$defs) && IsProperties(value.$defs) && ValueGuard.HasPropertyKey(value, '$ref') && ValueGuard.IsString(value.$ref) && value.$ref in value.$defs // required ) } /** 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(value: unknown, kind: T): value is Record & { [Kind]: T } { return ValueGuard.IsObject(value) && Kind in value && value[Kind] === kind } /** Returns true if the given value is TLiteral */ export function IsLiteralString(value: unknown): value is TLiteral { return IsLiteral(value) && ValueGuard.IsString(value.const) } /** Returns true if the given value is TLiteral */ export function IsLiteralNumber(value: unknown): value is TLiteral { return IsLiteral(value) && ValueGuard.IsNumber(value.const) } /** Returns true if the given value is TLiteral */ export function IsLiteralBoolean(value: unknown): value is TLiteral { 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) => { 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) && IsOptionalNumber(value.maxLength) && IsOptionalNumber(value.minLength) ) } /** 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 { // 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[]> */ export function IsUnionLiteral(value: unknown): value is TUnion { 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 { 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 & { [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) || IsArgument(value) || IsArray(value) || IsBoolean(value) || IsBigInt(value) || IsAsyncIterator(value) || IsComputed(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) ) } sinclairzx81-typebox-e0ec98c/src/type/guard/value.ts000066400000000000000000000103021505437577000226120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // -------------------------------------------------------------------------- // PropertyKey // -------------------------------------------------------------------------- /** Returns true if this value has this property key */ export function HasPropertyKey(value: Record, key: K): value is Record & { [_ in K]: unknown } { return key in value } // -------------------------------------------------------------------------- // Object Instances // -------------------------------------------------------------------------- /** Returns true if this value is an async iterator */ export function IsAsyncIterator(value: unknown): value is AsyncIterableIterator { 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 { 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 { 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 } sinclairzx81-typebox-e0ec98c/src/type/helpers/000077500000000000000000000000001505437577000214725ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/helpers/helpers.ts000066400000000000000000000076251505437577000235160ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 [infer I] ? I : T extends [infer I, ...infer R] ? I & TupleToIntersect : never export type TupleToUnion = { [K in keyof T]: T[K] }[number] export type UnionToIntersect = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never export type UnionLast = UnionToIntersect 0 : never> extends (x: infer L) => 0 ? L : never export type UnionToTuple> = [U] extends [never] ? Acc : UnionToTuple, [Extract, ...Acc]> export type Trim = T extends `${' '}${infer U}` ? Trim : T extends `${infer U}${' '}` ? Trim : T export type Assert = T extends E ? T : never export type Evaluate = T extends infer O ? { [K in keyof O]: O[K] } : never export type Ensure = 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 = IncrementBase[T] type IncrementStep = T extends IncrementBase['m'] ? IncrementBase['t'] : T extends `${infer L extends keyof IncrementBase}${infer R}` ? L extends IncrementBase['m'] ? `${IncrementTake}${IncrementStep}` : `${IncrementTake}${R}` : never type IncrementReverse = T extends `${infer L}${infer R}` ? `${IncrementReverse}${L}` : T export type TIncrement = IncrementReverse>> /** Increments the given string value + 1 */ export function Increment(T: T): TIncrement { return (parseInt(T) + 1).toString() as never } // ------------------------------------------------------------------ // Helper: Type Asserts // ------------------------------------------------------------------ export type AssertProperties = T extends TProperties ? T : TProperties export type AssertRest = T extends E ? T : [] export type AssertType = T extends E ? T : TNever sinclairzx81-typebox-e0ec98c/src/type/helpers/index.ts000066400000000000000000000024651505437577000231600ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/type/index.ts000066400000000000000000000070131505437577000215100ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './argument/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 './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 './instantiate/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 './module/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 './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' sinclairzx81-typebox-e0ec98c/src/type/indexed/000077500000000000000000000000001505437577000214505ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/indexed/index.ts000066400000000000000000000026641505437577000231370ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './indexed-from-mapped-key' export * from './indexed-from-mapped-result' export * from './indexed-property-keys' export * from './indexed' sinclairzx81-typebox-e0ec98c/src/type/indexed/indexed-from-mapped-key.ts000066400000000000000000000106021505437577000264320ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { Index, type TIndex } from './indexed' import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // MappedIndexPropertyKey // ------------------------------------------------------------------ // prettier-ignore type TMappedIndexPropertyKey = { [_ in Key]: TIndex } // prettier-ignore function MappedIndexPropertyKey(type: Type, key: Key, options?: SchemaOptions): TMappedIndexPropertyKey { return { [key]: Index(type, [key], Clone(options)) } as never } // ------------------------------------------------------------------ // MappedIndexPropertyKeys // ------------------------------------------------------------------ // prettier-ignore type TMappedIndexPropertyKeys = ( PropertyKeys extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? TMappedIndexPropertyKeys> : Result ) // prettier-ignore function MappedIndexPropertyKeys< Type extends TSchema, PropertyKeys extends PropertyKey[] >(type: Type, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TMappedIndexPropertyKeys { return propertyKeys.reduce((result, left) => { return { ...result, ...MappedIndexPropertyKey(type, left, options) } }, {} as TProperties) as never } // ------------------------------------------------------------------ // MappedIndexProperties // ------------------------------------------------------------------ // prettier-ignore type TMappedIndexProperties = Evaluate< TMappedIndexPropertyKeys > // prettier-ignore function MappedIndexProperties(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TMappedIndexProperties { return MappedIndexPropertyKeys(type, mappedKey.keys, options) as never } // ------------------------------------------------------------------ // TIndexFromMappedKey // ------------------------------------------------------------------ // prettier-ignore export type TIndexFromMappedKey > = ( Ensure> ) // prettier-ignore export function IndexFromMappedKey >(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TMappedResult { const properties = MappedIndexProperties(type, mappedKey, options) return MappedResult(properties) as never } sinclairzx81-typebox-e0ec98c/src/type/indexed/indexed-from-mapped-result.ts000066400000000000000000000072541505437577000271710ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { IndexPropertyKeys, type TIndexPropertyKeys } from './indexed-property-keys' import { Index, type TIndex } from './index' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties = ( { [K2 in keyof Properties]: TIndex> } ) // prettier-ignore function FromProperties(type: Type, properties: Properties, options?: SchemaOptions): TFromProperties { const result = {} as Record for(const K2 of Object.getOwnPropertyNames(properties)) { result[K2] = Index(type, IndexPropertyKeys(properties[K2]), options) } return result as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult = ( TFromProperties ) // prettier-ignore function FromMappedResult(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TFromMappedResult { return FromProperties(type, mappedResult.properties, options) as never } // ------------------------------------------------------------------ // TIndexFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TIndexFromMappedResult > = ( TMappedResult ) // prettier-ignore export function IndexFromMappedResult >(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TMappedResult { const properties = FromMappedResult(type, mappedResult, options) return MappedResult(properties) as never } sinclairzx81-typebox-e0ec98c/src/type/indexed/indexed-property-keys.ts000066400000000000000000000112161505437577000262740ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TemplateLiteralGenerate, type TTemplateLiteralGenerate, type TTemplateLiteral } from '../template-literal/index' import type { TLiteral, TLiteralValue } from '../literal/index' import type { TInteger } from '../integer/index' import type { TNumber } from '../number/index' import type { TSchema } from '../schema/index' import type { TUnion } from '../union/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsTemplateLiteral, IsUnion, IsLiteral, IsNumber, IsInteger } from '../guard/kind' // ------------------------------------------------------------------ // FromTemplateLiteral // ------------------------------------------------------------------ // prettier-ignore type TFromTemplateLiteral> = (Keys) // prettier-ignore function FromTemplateLiteral(templateLiteral: TemplateLiteral): TFromTemplateLiteral { const keys = TemplateLiteralGenerate(templateLiteral) as string[] return keys.map(key => key.toString()) as never } // ------------------------------------------------------------------ // FromUnion // ------------------------------------------------------------------ // prettier-ignore type TFromUnion = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TFromUnion]> : Result ) // prettier-ignore function FromUnion(types: Types): TFromUnion { const result = [] as string[] for(const type of types) result.push(...IndexPropertyKeys(type)) return result as never } // ------------------------------------------------------------------ // FromLiteral // ------------------------------------------------------------------ // prettier-ignore type TFromLiteral = ( LiteralValue extends PropertyKey ? [`${LiteralValue}`] : [] ) // prettier-ignore function FromLiteral(literalValue: LiteralValue): TFromLiteral { return ( [(literalValue as string).toString()] // TS 5.4 observes TLiteralValue as not having a toString() ) as never } // ------------------------------------------------------------------ // IndexPropertyKeys // ------------------------------------------------------------------ // prettier-ignore export type TIndexPropertyKeys = ( Type extends TTemplateLiteral ? TFromTemplateLiteral : Type extends TUnion ? TFromUnion : Type extends TLiteral ? TFromLiteral : Type extends TNumber ? ['[number]'] : Type extends TInteger ? ['[number]'] : [] ) /** Returns a tuple of PropertyKeys derived from the given TSchema */ // prettier-ignore export function IndexPropertyKeys(type: Type): TIndexPropertyKeys { return [...new Set(( IsTemplateLiteral(type) ? FromTemplateLiteral(type) : IsUnion(type) ? FromUnion(type.anyOf) : IsLiteral(type) ? FromLiteral(type.const) : IsNumber(type) ? ['[number]'] : IsInteger(type) ? ['[number]'] : [] ))] as never } sinclairzx81-typebox-e0ec98c/src/type/indexed/indexed.ts000066400000000000000000000341141505437577000234430ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { TypeBoxError } from '../error/index' import { type TSchema, SchemaOptions } from '../schema/index' import { type Assert } from '../helpers/index' import { type TComputed, Computed } from '../computed/index' import { type TNever, Never } from '../never/index' import { type TArray } from '../array/index' import { type TIntersect } from '../intersect/index' import { type TMappedResult, type TMappedKey } from '../mapped/index' import { type TObject, type TProperties } from '../object/index' import { type TUnion } from '../union/index' import { type TRecursive } from '../recursive/index' import { type TRef } from '../ref/index' import { type TTuple } from '../tuple/index' import { IntersectEvaluated, type TIntersectEvaluated } from '../intersect/index' import { UnionEvaluated, type TUnionEvaluated } from '../union/index' import { IndexPropertyKeys, type TIndexPropertyKeys } from './indexed-property-keys' import { IndexFromMappedKey, type TIndexFromMappedKey } from './indexed-from-mapped-key' import { IndexFromMappedResult, type TIndexFromMappedResult } from './indexed-from-mapped-result' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsArray, IsIntersect, IsObject, IsMappedKey, IsMappedResult, IsNever, IsSchema, IsTuple, IsUnion, IsRef } from '../guard/kind' // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore type TFromRest = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TFromRest, TSchema>]> : Result ) // prettier-ignore function FromRest(types: [...Types], key: Key): TFromRest { return types.map(type => IndexFromPropertyKey(type, key)) as never } // ------------------------------------------------------------------ // FromIntersectRest // ------------------------------------------------------------------ // prettier-ignore type TFromIntersectRest = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? Left extends TNever ? TFromIntersectRest : TFromIntersectRest : Result ) // prettier-ignore function FromIntersectRest(types: [...Types]): TFromIntersectRest { return types.filter(type => !IsNever(type)) as never } // prettier-ignore type TFromIntersect = ( TIntersectEvaluated>> ) // prettier-ignore function FromIntersect(types: [...Types], key: Key): TFromIntersect { return ( IntersectEvaluated(FromIntersectRest(FromRest(types as TSchema[], key))) ) as never } // ------------------------------------------------------------------ // FromUnionRest // // The following accept a tuple of indexed key results. When evaluating // these results, we check if any result evaluated to TNever. For key // indexed unions, a TNever result indicates that the key was not // present on the variant. In these cases, we must evaluate the indexed // union to TNever (as given by a [] result). This logic aligns to the // following behaviour. // // Non-Overlapping Union // // type A = { a: string } // type B = { b: string } // type C = (A | B) & { a: number } // C is { a: number } // // Overlapping Union // // type A = { a: string } // type B = { a: string } // type C = (A | B) & { a: number } // C is { a: never } // // ------------------------------------------------------------------ // prettier-ignore type TFromUnionRest = Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? Left extends TNever ? [] : TFromUnionRest : Result // prettier-ignore function FromUnionRest(types: [...Types]): TFromUnionRest { return ( types.some(L => IsNever(L)) ? [] : types ) as never } // ------------------------------------------------------------------ // FromUnion // ------------------------------------------------------------------ // prettier-ignore type TFromUnion = ( TUnionEvaluated>> ) // prettier-ignore function FromUnion(types: [...Types], key: Key): TFromUnion { return ( UnionEvaluated(FromUnionRest(FromRest(types as TSchema[], key))) ) as never } // ------------------------------------------------------------------ // FromTuple // ------------------------------------------------------------------ // prettier-ignore type TFromTuple = ( Key extends keyof Types ? Types[Key] : Key extends '[number]' ? TUnionEvaluated : TNever ) // prettier-ignore function FromTuple(types: [...Types], key: Key): TFromTuple { return ( key in types ? types[key as number] : key === '[number]' ? UnionEvaluated(types) : Never() ) as never } // ------------------------------------------------------------------ // FromArray // ------------------------------------------------------------------ // prettier-ignore type TFromArray = ( Key extends '[number]' ? Type : TNever ) // prettier-ignore function FromArray(type: Type, key: Key): TFromArray { return ( key === '[number]' ? type : Never() ) as never } // ------------------------------------------------------------------ // FromProperty // ------------------------------------------------------------------ type AssertPropertyKey = Assert // prettier-ignore type TFromProperty = ( // evaluate for string keys Key extends keyof Properties ? Properties[Key] // evaluate for numeric keys : `${AssertPropertyKey}` extends `${AssertPropertyKey}` ? Properties[AssertPropertyKey] : TNever ) // prettier-ignore function FromProperty(properties: Properties, propertyKey: Key): TFromProperty { return (propertyKey in properties ? properties[propertyKey as string] : Never()) as never } // ------------------------------------------------------------------ // FromKey // ------------------------------------------------------------------ // prettier-ignore export type TIndexFromPropertyKey = ( Type extends TRecursive ? TIndexFromPropertyKey : Type extends TIntersect ? TFromIntersect : Type extends TUnion ? TFromUnion : Type extends TTuple ? TFromTuple : Type extends TArray ? TFromArray : Type extends TObject ? TFromProperty : TNever ) // prettier-ignore export function IndexFromPropertyKey(type: Type, propertyKey: Key): TIndexFromPropertyKey { return ( IsIntersect(type) ? FromIntersect(type.allOf, propertyKey) : IsUnion(type) ? FromUnion(type.anyOf, propertyKey) : IsTuple(type) ? FromTuple(type.items ?? [], propertyKey) : IsArray(type) ? FromArray(type.items, propertyKey) : IsObject(type) ? FromProperty(type.properties, propertyKey) : Never() ) as never } // ------------------------------------------------------------------ // FromKeys // ------------------------------------------------------------------ // prettier-ignore export type TIndexFromPropertyKeys = ( PropertyKeys extends [infer Left extends PropertyKey, ...infer Right extends PropertyKey[]] ? TIndexFromPropertyKeys, TSchema>]> : Result ) // prettier-ignore export function IndexFromPropertyKeys(type: Type, propertyKeys: [...PropertyKeys]): TIndexFromPropertyKeys { return propertyKeys.map(propertyKey => IndexFromPropertyKey(type, propertyKey)) as never } // ------------------------------------------------------------------ // FromSchema // ------------------------------------------------------------------ // prettier-ignore type FromSchema = ( TUnionEvaluated> ) // prettier-ignore function FromSchema(type: Type, propertyKeys: [...PropertyKeys]): FromSchema { return ( UnionEvaluated(IndexFromPropertyKeys(type, propertyKeys as PropertyKey[])) ) as never } // ------------------------------------------------------------------ // FromSchema // ------------------------------------------------------------------ // prettier-ignore export type TIndexFromComputed = ( TComputed<'Index', [Type, Key]> ) // prettier-ignore export function IndexFromComputed(type: Type, key: Key): TIndexFromComputed { return Computed('Index', [type, key]) } // ------------------------------------------------------------------ // TIndex // ------------------------------------------------------------------ // prettier-ignore export type TIndex = ( FromSchema ) /** `[Json]` Returns an Indexed property type for the given keys */ export function Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ export function Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ export function Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ export function Index(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TIndexFromMappedResult /** `[Json]` Returns an Indexed property type for the given keys */ export function Index(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TIndexFromMappedResult /** `[Json]` Returns an Indexed property type for the given keys */ export function Index(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TIndexFromMappedKey /** `[Json]` Returns an Indexed property type for the given keys */ export function Index>(T: Type, K: Key, options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ export function Index(type: Type, propertyKeys: readonly [...PropertyKeys], options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ export function Index(type: TSchema, key: any, options?: SchemaOptions): any { // computed-type if (IsRef(type) || IsRef(key)) { const error = `Index types using Ref parameters require both Type and Key to be of TSchema` if (!IsSchema(type) || !IsSchema(key)) throw new TypeBoxError(error) return Computed('Index', [type, key]) } // mapped-types if (IsMappedResult(key)) return IndexFromMappedResult(type, key, options) if (IsMappedKey(key)) return IndexFromMappedKey(type, key, options) // prettier-ignore return CreateType( IsSchema(key) ? FromSchema(type, IndexPropertyKeys(key)) : FromSchema(type, key as string[]) , options) as never } sinclairzx81-typebox-e0ec98c/src/type/instance-type/000077500000000000000000000000001505437577000226135ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/instance-type/index.ts000066400000000000000000000024731505437577000243000ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './instance-type' sinclairzx81-typebox-e0ec98c/src/type/instance-type/instance-type.ts000066400000000000000000000040711505437577000257500ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { type TSchema, SchemaOptions } from '../schema/index' import { type TConstructor } from '../constructor/index' import { type TNever, Never } from '../never/index' import * as KindGuard from '../guard/kind' // prettier-ignore export type TInstanceType ? InstanceType : TNever > = Result /** `[JavaScript]` Extracts the InstanceType from the given Constructor type */ export function InstanceType(schema: Type, options?: SchemaOptions): TInstanceType { return (KindGuard.IsConstructor(schema) ? CreateType(schema.returns, options) : Never(options)) as never } sinclairzx81-typebox-e0ec98c/src/type/instantiate/000077500000000000000000000000001505437577000223535ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/instantiate/index.ts000066400000000000000000000024711505437577000240360ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './instantiate' sinclairzx81-typebox-e0ec98c/src/type/instantiate/instantiate.ts000066400000000000000000000335611505437577000252560ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CloneType } from '../clone/type' import { type TSchema } from '../schema/index' import { type TArgument } from '../argument/index' import { type TUnknown, Unknown } from '../unknown/index' import { type TReadonlyOptional, ReadonlyOptional } from '../readonly-optional/index' import { type TReadonly, Readonly } from '../readonly/index' import { type TOptional, Optional } from '../optional/index' import { type TConstructor } from '../constructor/index' import { type TFunction } from '../function/index' import { type TIntersect } from '../intersect/index' import { type TUnion } from '../union/index' import { type TTuple } from '../tuple/index' import { type TArray } from '../array/index' import { type TAsyncIterator } from '../async-iterator/index' import { type TIterator } from '../iterator/index' import { type TPromise } from '../promise/index' import { type TObject, type TProperties, Object } from '../object/index' import { type TRecordOrObject, type TRecord, Record, RecordKey, RecordValue } from '../record/index' import * as ValueGuard from '../guard/value' import * as KindGuard from '../guard/kind' // ------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------ // prettier-ignore type TFromConstructor, TFromType> > = Result // prettier-ignore function FromConstructor(args: TSchema[], type: TConstructor): TConstructor { type.parameters = FromTypes(args, type.parameters) type.returns = FromType(args, type.returns) return type } // ------------------------------------------------------------------ // Function // ------------------------------------------------------------------ // prettier-ignore type TFromFunction, TFromType> > = Result // prettier-ignore function FromFunction(args: TSchema[], type: TFunction): TFunction { type.parameters = FromTypes(args, type.parameters) type.returns = FromType(args, type.returns) return type } // ------------------------------------------------------------------ // Intersect // ------------------------------------------------------------------ // prettier-ignore type TFromIntersect> > = Result // prettier-ignore function FromIntersect(args: TSchema[], type: TIntersect): TIntersect { type.allOf = FromTypes(args, type.allOf) return type } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore type TFromUnion> > = Result // prettier-ignore function FromUnion(args: TSchema[], type: TUnion): TUnion { type.anyOf = FromTypes(args, type.anyOf) return type } // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ // prettier-ignore type TFromTuple> > = Result // prettier-ignore function FromTuple(args: TSchema[], type: TTuple): TTuple { if(ValueGuard.IsUndefined(type.items)) return type type.items = FromTypes(args, type.items!) return type } // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ // prettier-ignore type TFromArray> > = Result // prettier-ignore function FromArray(args: TSchema[], type: TArray): TArray { type.items = FromType(args, type.items) return type } // ------------------------------------------------------------------ // AsyncIterator // ------------------------------------------------------------------ // prettier-ignore type TFromAsyncIterator> > = Result // prettier-ignore function FromAsyncIterator(args: TSchema[], type: TAsyncIterator): TAsyncIterator { type.items = FromType(args, type.items) return type } // ------------------------------------------------------------------ // Iterator // ------------------------------------------------------------------ // prettier-ignore type TFromIterator> > = Result // prettier-ignore function FromIterator(args: TSchema[], type: TIterator): TIterator { type.items = FromType(args, type.items) return type } // ------------------------------------------------------------------ // Promise // ------------------------------------------------------------------ // prettier-ignore type TFromPromise> > = Result // prettier-ignore function FromPromise(args: TSchema[], type: TPromise): TPromise { type.item = FromType(args, type.item) return type } // ------------------------------------------------------------------ // Object // ------------------------------------------------------------------ // prettier-ignore type TFromObject, Result extends TObject = TObject > = Result // prettier-ignore function FromObject(args: TSchema[], type: TObject): TObject { const mappedProperties = FromProperties(args, type.properties) return { ...type, ...Object(mappedProperties) } // retain options } // ------------------------------------------------------------------ // Object // ------------------------------------------------------------------ // prettier-ignore type TFromRecord, MappedValue extends TSchema = TFromType, Result extends TSchema = TRecordOrObject > = Result // prettier-ignore function FromRecord(args: TSchema[], type: TRecord): TRecord { const mappedKey = FromType(args, RecordKey(type)) const mappedValue = FromType(args, RecordValue(type)) const result = Record(mappedKey, mappedValue) return { ...type, ... result } as never // retain options } // ------------------------------------------------------------------ // Argument // ------------------------------------------------------------------ // prettier-ignore type TFromArgument = Result // prettier-ignore function FromArgument(args: TSchema[], argument: TArgument): TSchema { return argument.index in args ? args[argument.index] : Unknown() } // ------------------------------------------------------------------ // Property // ------------------------------------------------------------------ // prettier-ignore type TFromProperty ? true : false, IsOptional extends boolean = Type extends TOptional ? true : false, Mapped extends TSchema = TFromType, Result extends TSchema = ( [IsReadonly, IsOptional] extends [true, true] ? TReadonlyOptional : [IsReadonly, IsOptional] extends [true, false] ? TReadonly : [IsReadonly, IsOptional] extends [false, true] ? TOptional : Mapped ) > = Result // prettier-ignore function FromProperty(args: [...Args], type: Type): TFromProperty { const isReadonly = KindGuard.IsReadonly(type) const isOptional = KindGuard.IsOptional(type) const mapped = FromType(args, type) return ( isReadonly && isOptional ? ReadonlyOptional(mapped) : isReadonly && !isOptional ? Readonly(mapped) : !isReadonly && isOptional ? Optional(mapped) : mapped ) as never } // ------------------------------------------------------------------ // Properties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties } > = Result // prettier-ignore function FromProperties(args: TSchema[], properties: TProperties): TFromProperties { return globalThis.Object.getOwnPropertyNames(properties).reduce((result, key) => { return { ...result, [key]: FromProperty(args, properties[key]) } }, {}) as never } // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ // prettier-ignore export type TFromTypes = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TFromTypes]> : Result ) // prettier-ignore export function FromTypes(args: [...Args], types: [...Types]): TFromTypes { return types.map(type => FromType(args, type)) as never } // ------------------------------------------------------------------ // Type // ------------------------------------------------------------------ // prettier-ignore export type TFromType = ( Type extends TConstructor ? TFromConstructor : Type extends TFunction ? TFromFunction : Type extends TIntersect ? TFromIntersect : Type extends TUnion ? TFromUnion : Type extends TTuple ? TFromTuple : Type extends TArray ? TFromArray: Type extends TAsyncIterator ? TFromAsyncIterator : Type extends TIterator ? TFromIterator : Type extends TPromise ? TFromPromise : Type extends TObject ? TFromObject : Type extends TRecord ? TFromRecord : Type extends TArgument ? TFromArgument : Type ) // prettier-ignore function FromType(args: [...Args], type: TSchema): TFromType { return ( KindGuard.IsConstructor(type) ? FromConstructor(args, type) : KindGuard.IsFunction(type) ? FromFunction(args, type) : KindGuard.IsIntersect(type) ? FromIntersect(args, type) : KindGuard.IsUnion(type) ? FromUnion(args, type) : KindGuard.IsTuple(type) ? FromTuple(args, type) : KindGuard.IsArray(type) ? FromArray(args, type) : KindGuard.IsAsyncIterator(type) ? FromAsyncIterator(args, type) : KindGuard.IsIterator(type) ? FromIterator(args, type) : KindGuard.IsPromise(type) ? FromPromise(args, type) : KindGuard.IsObject(type) ? FromObject(args, type): KindGuard.IsRecord(type) ? FromRecord(args, type) : KindGuard.IsArgument(type) ? FromArgument(args, type) : type ) as never } // ------------------------------------------------------------------ // Instantiate // ------------------------------------------------------------------ /** `[JavaScript]` Instantiates a type with the given parameters */ // prettier-ignore export type TInstantiate > = Result /** `[JavaScript]` Instantiates a type with the given parameters */ // prettier-ignore export function Instantiate(type: Type, args: [...Args]): TInstantiate { return FromType(args, CloneType(type)) } sinclairzx81-typebox-e0ec98c/src/type/integer/000077500000000000000000000000001505437577000214655ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/integer/index.ts000066400000000000000000000024651505437577000231530ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './integer' sinclairzx81-typebox-e0ec98c/src/type/integer/integer.ts000066400000000000000000000036071505437577000235000ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface IntegerOptions extends SchemaOptions { exclusiveMaximum?: number exclusiveMinimum?: number maximum?: number minimum?: number multipleOf?: number } export interface TInteger extends TSchema, IntegerOptions { [Kind]: 'Integer' static: number type: 'integer' } /** `[Json]` Creates an Integer type */ export function Integer(options?: IntegerOptions): TInteger { return CreateType({ [Kind]: 'Integer', type: 'integer' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/intersect/000077500000000000000000000000001505437577000220305ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/intersect/index.ts000066400000000000000000000025761505437577000235210ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './intersect-evaluated' export * from './intersect-type' export * from './intersect' sinclairzx81-typebox-e0ec98c/src/type/intersect/intersect-create.ts000066400000000000000000000047361505437577000256530ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import { Kind } from '../symbols/index' import type { TIntersect, IntersectOptions } from './intersect-type' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsObject, IsSchema } from '../guard/kind' // ------------------------------------------------------------------ // IntersectCreate // ------------------------------------------------------------------ // prettier-ignore export function IntersectCreate(T: [...T], options: IntersectOptions = {}): TIntersect { const allObjects = T.every((schema) => IsObject(schema)) const clonedUnevaluatedProperties = IsSchema(options.unevaluatedProperties) ? { unevaluatedProperties: options.unevaluatedProperties } : {} return CreateType( (options.unevaluatedProperties === false || IsSchema(options.unevaluatedProperties) || allObjects ? { ...clonedUnevaluatedProperties, [Kind]: 'Intersect', type: 'object', allOf: T } : { ...clonedUnevaluatedProperties, [Kind]: 'Intersect', allOf: T }) , options) as never } sinclairzx81-typebox-e0ec98c/src/type/intersect/intersect-evaluated.ts000066400000000000000000000127321505437577000263550ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { SchemaOptions, TSchema } from '../schema/index' import { OptionalKind } from '../symbols/index' import { CreateType } from '../create/type' import { Discard } from '../discard/index' import { Never, type TNever } from '../never/index' import { Optional, type TOptional } from '../optional/index' import type { TReadonly } from '../readonly/index' import { TIntersect, IntersectOptions } from './intersect-type' import { IntersectCreate } from './intersect-create' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsOptional, IsTransform } from '../guard/kind' // ------------------------------------------------------------------ // IsIntersectOptional // ------------------------------------------------------------------ // prettier-ignore type TIsIntersectOptional = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? Left extends TOptional ? TIsIntersectOptional : false : true ) // prettier-ignore function IsIntersectOptional(types: [...Types]): TIsIntersectOptional { return types.every(left => IsOptional(left)) as never } // ------------------------------------------------------------------ // RemoveOptionalFromType // ------------------------------------------------------------------ // prettier-ignore type TRemoveOptionalFromType = ( Type extends TReadonly ? TReadonly> : Type extends TOptional ? TRemoveOptionalFromType : Type ) // prettier-ignore function RemoveOptionalFromType(type: Type): TRemoveOptionalFromType { return ( Discard(type, [OptionalKind]) ) as never } // ------------------------------------------------------------------ // RemoveOptionalFromRest // ------------------------------------------------------------------ // prettier-ignore type TRemoveOptionalFromRest = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? Left extends TOptional ? TRemoveOptionalFromRest]> : TRemoveOptionalFromRest : Result ) // prettier-ignore function RemoveOptionalFromRest(types: [...Types]): TRemoveOptionalFromRest { return types.map(left => IsOptional(left) ? RemoveOptionalFromType(left) : left) as never } // ------------------------------------------------------------------ // ResolveIntersect // ------------------------------------------------------------------ // prettier-ignore type TResolveIntersect = ( TIsIntersectOptional extends true ? TOptional>> : TIntersect> ) // prettier-ignore function ResolveIntersect(types: [...Types], options: SchemaOptions): TResolveIntersect { return ( IsIntersectOptional(types) ? Optional(IntersectCreate(RemoveOptionalFromRest(types) as TSchema[], options)) : IntersectCreate(RemoveOptionalFromRest(types) as TSchema[], options) ) as never } // ------------------------------------------------------------------ // IntersectEvaluated // ------------------------------------------------------------------ // prettier-ignore export type TIntersectEvaluated = ( Types extends [TSchema] ? Types[0] : Types extends [] ? TNever : TResolveIntersect ) /** `[Json]` Creates an evaluated Intersect type */ export function IntersectEvaluated>(types: [...Types], options: IntersectOptions = {}): Result { if (types.length === 1) return CreateType(types[0], options) as never if (types.length === 0) return Never(options) as never if (types.some((schema) => IsTransform(schema))) throw new Error('Cannot intersect transform types') return ResolveIntersect(types, options) as never } sinclairzx81-typebox-e0ec98c/src/type/intersect/intersect-type.ts000066400000000000000000000046171505437577000253670ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' // ------------------------------------------------------------------ // IntersectStatic // ------------------------------------------------------------------ // prettier-ignore type TIntersectStatic = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TIntersectStatic> : Acc // ------------------------------------------------------------------ // TIntersect // ------------------------------------------------------------------ // prettier-ignore export type TUnevaluatedProperties = undefined | TSchema | boolean // prettier-ignore export interface IntersectOptions extends SchemaOptions { unevaluatedProperties?: TUnevaluatedProperties } // prettier-ignore export interface TIntersect extends TSchema, IntersectOptions { [Kind]: 'Intersect' static: TIntersectStatic type?: 'object' allOf: [...T] } sinclairzx81-typebox-e0ec98c/src/type/intersect/intersect.ts000066400000000000000000000047451505437577000244120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import { Never, type TNever } from '../never/index' import { TIntersect, IntersectOptions } from './intersect-type' import { IntersectCreate } from './intersect-create' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsTransform } from '../guard/kind' // ------------------------------------------------------------------ // Intersect // ------------------------------------------------------------------ // prettier-ignore export type Intersect = ( Types extends [TSchema] ? Types[0] : Types extends [] ? TNever : TIntersect ) /** `[Json]` Creates an evaluated Intersect type */ export function Intersect(types: [...Types], options?: IntersectOptions): Intersect { if (types.length === 1) return CreateType(types[0], options) as never if (types.length === 0) return Never(options) as never if (types.some((schema) => IsTransform(schema))) throw new Error('Cannot intersect transform types') return IntersectCreate(types, options) as never } sinclairzx81-typebox-e0ec98c/src/type/intrinsic/000077500000000000000000000000001505437577000220325ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/intrinsic/capitalize.ts000066400000000000000000000033061505437577000245310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Intrinsic, type TIntrinsic } from './intrinsic' // prettier-ignore export type TCapitalize = TIntrinsic /** `[Json]` Intrinsic function to Capitalize LiteralString types */ export function Capitalize(T: T, options: SchemaOptions = {}): TCapitalize { return Intrinsic(T, 'Capitalize', options) } sinclairzx81-typebox-e0ec98c/src/type/intrinsic/index.ts000066400000000000000000000027271505437577000235210ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './capitalize' export * from './intrinsic-from-mapped-key' export * from './intrinsic' export * from './lowercase' export * from './uncapitalize' export * from './uppercase' sinclairzx81-typebox-e0ec98c/src/type/intrinsic/intrinsic-from-mapped-key.ts000066400000000000000000000105411505437577000274000ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { SchemaOptions } from '../schema/index' import type { TProperties } from '../object/index' import { Assert } from '../helpers/index' import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index' import { Intrinsic, type TIntrinsic, type IntrinsicMode } from './intrinsic' import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // MappedIntrinsicPropertyKey // ------------------------------------------------------------------ // prettier-ignore type TMappedIntrinsicPropertyKey< K extends PropertyKey, M extends IntrinsicMode, > = { [_ in K]: TIntrinsic>, M> } // prettier-ignore function MappedIntrinsicPropertyKey< K extends PropertyKey, M extends IntrinsicMode, >(K: K, M: M, options: SchemaOptions): TMappedIntrinsicPropertyKey { return { [K]: Intrinsic(Literal(K as TLiteralValue), M, Clone(options)) } as never } // ------------------------------------------------------------------ // MappedIntrinsicPropertyKeys // ------------------------------------------------------------------ // prettier-ignore type TMappedIntrinsicPropertyKeys< K extends PropertyKey[], M extends IntrinsicMode, Acc extends TProperties = {} > = ( K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? TMappedIntrinsicPropertyKeys> : Acc ) // prettier-ignore function MappedIntrinsicPropertyKeys< K extends PropertyKey[], M extends IntrinsicMode >(K: [...K], M: M, options: SchemaOptions): TMappedIntrinsicPropertyKeys { const result = K.reduce((Acc, L) => { return { ...Acc, ...MappedIntrinsicPropertyKey(L, M, options) } }, {} as TProperties) as never return result } // ------------------------------------------------------------------ // MappedIntrinsicProperties // ------------------------------------------------------------------ // prettier-ignore type TMappedIntrinsicProperties< K extends TMappedKey, M extends IntrinsicMode, > = ( TMappedIntrinsicPropertyKeys ) // prettier-ignore function MappedIntrinsicProperties< K extends TMappedKey, M extends IntrinsicMode, >(T: K, M: M, options: SchemaOptions): TMappedIntrinsicProperties { return MappedIntrinsicPropertyKeys(T['keys'], M, options) as never } // ------------------------------------------------------------------ // IntrinsicFromMappedKey // ------------------------------------------------------------------ // prettier-ignore export type TIntrinsicFromMappedKey< K extends TMappedKey, M extends IntrinsicMode, P extends TProperties = TMappedIntrinsicProperties > = ( TMappedResult

) // prettier-ignore export function IntrinsicFromMappedKey< K extends TMappedKey, M extends IntrinsicMode, P extends TProperties = TMappedIntrinsicProperties >(T: K, M: M, options: SchemaOptions): TMappedResult

{ const P = MappedIntrinsicProperties(T, M, options) return MappedResult(P) as never } sinclairzx81-typebox-e0ec98c/src/type/intrinsic/intrinsic.ts000066400000000000000000000163231505437577000244110ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { TemplateLiteral, TemplateLiteralParseExact, IsTemplateLiteralExpressionFinite, TemplateLiteralExpressionGenerate, type TTemplateLiteral, type TTemplateLiteralKind } from '../template-literal/index' import { IntrinsicFromMappedKey, type TIntrinsicFromMappedKey } from './intrinsic-from-mapped-key' import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' import { Union, type TUnion } from '../union/index' import { type TMappedKey } from '../mapped/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsMappedKey, IsTemplateLiteral, IsUnion, IsLiteral } from '../guard/kind' // ------------------------------------------------------------------ // Apply // ------------------------------------------------------------------ function ApplyUncapitalize(value: string): string { const [first, rest] = [value.slice(0, 1), value.slice(1)] return [first.toLowerCase(), rest].join('') } function ApplyCapitalize(value: string): string { const [first, rest] = [value.slice(0, 1), value.slice(1)] return [first.toUpperCase(), rest].join('') } function ApplyUppercase(value: string): string { return value.toUpperCase() } function ApplyLowercase(value: string): string { return value.toLowerCase() } // ------------------------------------------------------------------ // IntrinsicMode // ------------------------------------------------------------------ export type IntrinsicMode = 'Uppercase' | 'Lowercase' | 'Capitalize' | 'Uncapitalize' // ------------------------------------------------------------------ // FromTemplateLiteral // ------------------------------------------------------------------ // prettier-ignore type TFromTemplateLiteral = M extends IntrinsicMode ? T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]] ? [TIntrinsic, ...TFromTemplateLiteral] : T : T function FromTemplateLiteral(schema: TTemplateLiteral, mode: IntrinsicMode, options: SchemaOptions): TFromTemplateLiteral { // note: template literals require special runtime handling as they are encoded in string patterns. // This diverges from the mapped type which would otherwise map on the template literal kind. const expression = TemplateLiteralParseExact(schema.pattern) const finite = IsTemplateLiteralExpressionFinite(expression) if (!finite) return { ...schema, pattern: FromLiteralValue(schema.pattern, mode) } as any const strings = [...TemplateLiteralExpressionGenerate(expression)] const literals = strings.map((value) => Literal(value)) const mapped = FromRest(literals as any, mode) const union = Union(mapped) return TemplateLiteral([union], options) as never } // ------------------------------------------------------------------ // FromLiteralValue // ------------------------------------------------------------------ // prettier-ignore type TFromLiteralValue = ( T extends string ? M extends 'Uncapitalize' ? Uncapitalize : M extends 'Capitalize' ? Capitalize : M extends 'Uppercase' ? Uppercase : M extends 'Lowercase' ? Lowercase : string : T ) // prettier-ignore function FromLiteralValue(value: TLiteralValue, mode: IntrinsicMode) { return ( typeof value === 'string' ? ( mode === 'Uncapitalize' ? ApplyUncapitalize(value) : mode === 'Capitalize' ? ApplyCapitalize(value) : mode === 'Uppercase' ? ApplyUppercase(value) : mode === 'Lowercase' ? ApplyLowercase(value) : value ) : value.toString() ) } // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore type TFromRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromRest]> : Acc // prettier-ignore function FromRest(T: [...T], M: M): TFromRest { return T.map(L => Intrinsic(L, M)) as never } // ------------------------------------------------------------------ // TIntrinsic // ------------------------------------------------------------------ // prettier-ignore export type TIntrinsic = // Intrinsic-Mapped-Inference T extends TMappedKey ? TIntrinsicFromMappedKey : // Standard-Inference T extends TTemplateLiteral ? TTemplateLiteral> : T extends TUnion ? TUnion> : T extends TLiteral ? TLiteral> : T /** Applies an intrinsic string manipulation to the given type. */ export function Intrinsic(schema: T, mode: M, options?: SchemaOptions): TIntrinsicFromMappedKey /** Applies an intrinsic string manipulation to the given type. */ export function Intrinsic(schema: T, mode: M, options?: SchemaOptions): TIntrinsic /** Applies an intrinsic string manipulation to the given type. */ export function Intrinsic(schema: TSchema, mode: IntrinsicMode, options: SchemaOptions = {}): never { // prettier-ignore return ( // Intrinsic-Mapped-Inference IsMappedKey(schema) ? IntrinsicFromMappedKey(schema, mode, options) : // Standard-Inference IsTemplateLiteral(schema) ? FromTemplateLiteral(schema, mode, options) : IsUnion(schema) ? Union(FromRest(schema.anyOf, mode), options) : IsLiteral(schema) ? Literal(FromLiteralValue(schema.const, mode), options) : // Default Type CreateType(schema, options) ) as never } sinclairzx81-typebox-e0ec98c/src/type/intrinsic/lowercase.ts000066400000000000000000000033001505437577000243620ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Intrinsic, type TIntrinsic } from './intrinsic' // prettier-ignore export type TLowercase = TIntrinsic /** `[Json]` Intrinsic function to Lowercase LiteralString types */ export function Lowercase(T: T, options: SchemaOptions = {}): TLowercase { return Intrinsic(T, 'Lowercase', options) } sinclairzx81-typebox-e0ec98c/src/type/intrinsic/uncapitalize.ts000066400000000000000000000033221505437577000250720ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Intrinsic, type TIntrinsic } from './intrinsic' // prettier-ignore export type TUncapitalize = TIntrinsic /** `[Json]` Intrinsic function to Uncapitalize LiteralString types */ export function Uncapitalize(T: T, options: SchemaOptions = {}): TUncapitalize { return Intrinsic(T, 'Uncapitalize', options) } sinclairzx81-typebox-e0ec98c/src/type/intrinsic/uppercase.ts000066400000000000000000000033001505437577000243650ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Intrinsic, type TIntrinsic } from './intrinsic' // prettier-ignore export type TUppercase = TIntrinsic /** `[Json]` Intrinsic function to Uppercase LiteralString types */ export function Uppercase(T: T, options: SchemaOptions = {}): TUppercase { return Intrinsic(T, 'Uppercase', options) } sinclairzx81-typebox-e0ec98c/src/type/iterator/000077500000000000000000000000001505437577000216615ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/iterator/index.ts000066400000000000000000000024661505437577000233500ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './iterator' sinclairzx81-typebox-e0ec98c/src/type/iterator/iterator.ts000066400000000000000000000035701505437577000240670ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import { Kind } from '../symbols/index' export interface TIterator extends TSchema { [Kind]: 'Iterator' static: IterableIterator> type: 'Iterator' items: T } /** `[JavaScript]` Creates an Iterator type */ export function Iterator(items: T, options?: SchemaOptions): TIterator { return CreateType({ [Kind]: 'Iterator', type: 'Iterator', items }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/keyof/000077500000000000000000000000001505437577000211455ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/keyof/index.ts000066400000000000000000000026551505437577000226340ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './keyof-from-mapped-result' export * from './keyof-property-entries' export * from './keyof-property-keys' export * from './keyof' sinclairzx81-typebox-e0ec98c/src/type/keyof/keyof-from-mapped-result.ts000066400000000000000000000067061505437577000263640ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { SchemaOptions } from '../schema/index' import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { KeyOf, type TKeyOfFromType } from './keyof' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties = ( { [K2 in keyof Properties]: TKeyOfFromType } ) // prettier-ignore function FromProperties(properties: Properties, options?: SchemaOptions): TFromProperties { const result = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(properties)) result[K2] = KeyOf(properties[K2], Clone(options)) return result as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult = ( Evaluate> ) // prettier-ignore function FromMappedResult(mappedResult: MappedResult, options?: SchemaOptions): TFromMappedResult { return FromProperties(mappedResult.properties, options) as never } // ------------------------------------------------------------------ // KeyOfFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TKeyOfFromMappedResult< MappedResult extends TMappedResult, Properties extends TProperties = TFromMappedResult > = ( Ensure> ) // prettier-ignore export function KeyOfFromMappedResult< MappedResult extends TMappedResult, Properties extends TProperties = TFromMappedResult >(mappedResult: MappedResult, options?: SchemaOptions): TMappedResult { const properties = FromMappedResult(mappedResult, options) return MappedResult(properties) as never } sinclairzx81-typebox-e0ec98c/src/type/keyof/keyof-property-entries.ts000066400000000000000000000036711505437577000261720ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { IndexFromPropertyKeys } from '../indexed/indexed' import { KeyOfPropertyKeys } from './keyof-property-keys' import { TSchema } from '../schema/index' /** * `[Utility]` Resolves an array of keys and schemas from the given schema. This method is faster * than obtaining the keys and resolving each individually via indexing. This method was written * accellerate Intersect and Union encoding. */ export function KeyOfPropertyEntries(schema: TSchema): [key: string, schema: TSchema][] { const keys = KeyOfPropertyKeys(schema) as string[] const schemas = IndexFromPropertyKeys(schema, keys) return keys.map((_, index) => [keys[index], schemas[index]]) } sinclairzx81-typebox-e0ec98c/src/type/keyof/keyof-property-keys.ts000066400000000000000000000170431505437577000254720ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 ZeroString, type UnionToTuple, type TIncrement } from '../helpers/index' import type { TRecursive } from '../recursive/index' import type { TIntersect } from '../intersect/index' import type { TUnion } from '../union/index' import type { TTuple } from '../tuple/index' import type { TArray } from '../array/index' import type { TObject, TProperties } from '../object/index' import { SetUnionMany, SetIntersectMany, type TSetUnionMany, type TSetIntersectMany } from '../sets/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsIntersect, IsUnion, IsTuple, IsArray, IsObject, IsRecord } from '../guard/kind' // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore type TFromRest = ( Types extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromRest]> : Result ) // prettier-ignore function FromRest(types: [...Types]): TFromRest { const result = [] as PropertyKey[][] for(const L of types) result.push(KeyOfPropertyKeys(L)) return result as never } // ------------------------------------------------------------------ // FromIntersect // ------------------------------------------------------------------ // prettier-ignore type TFromIntersect, PropertyKeys extends PropertyKey[] = TSetUnionMany > = PropertyKeys // prettier-ignore function FromIntersect(types: [...Types]): TFromIntersect { const propertyKeysArray = FromRest(types) as PropertyKey[][] const propertyKeys = SetUnionMany(propertyKeysArray) return propertyKeys as never } // ------------------------------------------------------------------ // FromUnion // ------------------------------------------------------------------ // prettier-ignore type TFromUnion, PropertyKeys extends PropertyKey[] = TSetIntersectMany > = PropertyKeys // prettier-ignore function FromUnion(types: [...Types]): TFromUnion { const propertyKeysArray = FromRest(types) as PropertyKey[][] const propertyKeys = SetIntersectMany(propertyKeysArray) return propertyKeys as never } // ------------------------------------------------------------------ // FromTuple // ------------------------------------------------------------------ // prettier-ignore type TFromTuple = Types extends [infer _ extends TSchema, ...infer R extends TSchema[]] ? TFromTuple, [...Acc, Indexer]> : Acc // prettier-ignore function FromTuple(types: [...Types]): TFromTuple { return types.map((_, indexer) => indexer.toString()) as never } // ------------------------------------------------------------------ // FromArray // ------------------------------------------------------------------ // prettier-ignore type TFromArray<_ extends TSchema> = ( ['[number]'] ) // prettier-ignore function FromArray<_ extends TSchema>(_: _): TFromArray<_> { return ( ['[number]'] ) } // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties = ( UnionToTuple ) // prettier-ignore function FromProperties(T: Properties): TFromProperties { return ( globalThis.Object.getOwnPropertyNames(T) ) as never } // ------------------------------------------------------------------ // FromPatternProperties // ------------------------------------------------------------------ // prettier-ignore function FromPatternProperties(patternProperties: Record): string[] { if(!includePatternProperties) return [] const patternPropertyKeys = globalThis.Object.getOwnPropertyNames(patternProperties) return patternPropertyKeys.map(key => { return (key[0] === '^' && key[key.length - 1] === '$') ? key.slice(1, key.length - 1) : key }) } // ------------------------------------------------------------------ // KeyOfPropertyKeys // ------------------------------------------------------------------ // prettier-ignore export type TKeyOfPropertyKeys = ( Type extends TRecursive ? TKeyOfPropertyKeys : Type extends TIntersect ? TFromIntersect : Type extends TUnion ? TFromUnion : Type extends TTuple ? TFromTuple : Type extends TArray ? TFromArray : Type extends TObject ? TFromProperties : [] ) /** Returns a tuple of PropertyKeys derived from the given TSchema. */ // prettier-ignore export function KeyOfPropertyKeys(type: Type): TKeyOfPropertyKeys { return ( IsIntersect(type) ? FromIntersect(type.allOf) : IsUnion(type) ? FromUnion(type.anyOf) : IsTuple(type) ? FromTuple(type.items ?? []) : IsArray(type) ? FromArray(type.items) : IsObject(type) ? FromProperties(type.properties) : IsRecord(type) ? FromPatternProperties(type.patternProperties) : [] ) as never } // ---------------------------------------------------------------- // KeyOfPattern // ---------------------------------------------------------------- let includePatternProperties = false /** Returns a regular expression pattern derived from the given TSchema */ export function KeyOfPattern(schema: TSchema): string { includePatternProperties = true const keys = KeyOfPropertyKeys(schema) includePatternProperties = false const pattern = keys.map((key) => `(${key})`) return `^(${pattern.join('|')})$` } sinclairzx81-typebox-e0ec98c/src/type/keyof/keyof.ts000066400000000000000000000131131505437577000226310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { Assert, Ensure } from '../helpers/index' import type { TMappedResult } from '../mapped/index' import type { SchemaOptions } from '../schema/index' import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' import { Number, type TNumber } from '../number/index' import { Computed, TComputed } from '../computed/index' import { Ref, type TRef } from '../ref/index' import { KeyOfPropertyKeys, type TKeyOfPropertyKeys } from './keyof-property-keys' import { UnionEvaluated, type TUnionEvaluated } from '../union/index' import { KeyOfFromMappedResult, type TKeyOfFromMappedResult } from './keyof-from-mapped-result' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsMappedResult, IsRef, IsComputed } from '../guard/kind' // ------------------------------------------------------------------ // FromComputed // ------------------------------------------------------------------ // prettier-ignore type TFromComputed = Ensure< TComputed<'KeyOf', [TComputed]> > // prettier-ignore function FromComputed(target: Target, parameters: Parameters): TFromComputed { return Computed('KeyOf', [Computed(target, parameters)]) as never } // ------------------------------------------------------------------ // FromRef // ------------------------------------------------------------------ // prettier-ignore type TFromRef = Ensure< TComputed<'KeyOf', [TRef]> > // prettier-ignore function FromRef($ref: Ref): TFromRef { return Computed('KeyOf', [Ref($ref)]) as never } // ------------------------------------------------------------------ // KeyOfFromType // ------------------------------------------------------------------ // prettier-ignore /** `[Internal]` Used by KeyOfFromMappedResult */ export type TKeyOfFromType, PropertyKeyTypes extends TSchema[] = TKeyOfPropertyKeysToRest, Result = TUnionEvaluated > = Ensure // prettier-ignore function KeyOfFromType(type: Type, options?: SchemaOptions): TKeyOfFromType { const propertyKeys = KeyOfPropertyKeys(type) as PropertyKey[] const propertyKeyTypes = KeyOfPropertyKeysToRest(propertyKeys) const result = UnionEvaluated(propertyKeyTypes) return CreateType(result, options) as never } // ------------------------------------------------------------------ // FromPropertyKeys // ------------------------------------------------------------------ // prettier-ignore export type TKeyOfPropertyKeysToRest = ( PropertyKeys extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? L extends '[number]' ? TKeyOfPropertyKeysToRest : TKeyOfPropertyKeysToRest>]> : Result ) // prettier-ignore export function KeyOfPropertyKeysToRest(propertyKeys: [...PropertyKeys]): TKeyOfPropertyKeysToRest { return propertyKeys.map(L => L === '[number]' ? Number() : Literal(L as TLiteralValue)) as never } // ------------------------------------------------------------------ // TKeyOf // ------------------------------------------------------------------ // prettier-ignore export type TKeyOf = ( Type extends TComputed ? TFromComputed : Type extends TRef ? TFromRef : Type extends TMappedResult ? TKeyOfFromMappedResult : TKeyOfFromType ) /** `[Json]` Creates a KeyOf type */ export function KeyOf(type: Type, options?: SchemaOptions): TKeyOf { return (IsComputed(type) ? FromComputed(type.target, type.parameters) : IsRef(type) ? FromRef(type.$ref) : IsMappedResult(type) ? KeyOfFromMappedResult(type, options) : KeyOfFromType(type, options)) as never } sinclairzx81-typebox-e0ec98c/src/type/literal/000077500000000000000000000000001505437577000214645ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/literal/index.ts000066400000000000000000000024651505437577000231520ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './literal' sinclairzx81-typebox-e0ec98c/src/type/literal/literal.ts000066400000000000000000000044421505437577000234740ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ // TLiteralValue // ------------------------------------------------------------------ export type TLiteralValue = boolean | number | string // | bigint - supported but variant disable due to potential numeric type conflicts // ------------------------------------------------------------------ // TLiteral // ------------------------------------------------------------------ export interface TLiteral extends TSchema { [Kind]: 'Literal' static: T const: T } /** `[Json]` Creates a Literal type */ export function Literal(value: T, options?: SchemaOptions): TLiteral { return CreateType( { [Kind]: 'Literal', const: value, type: typeof value as 'string' | 'number' | 'boolean', }, options, ) as never } sinclairzx81-typebox-e0ec98c/src/type/mapped/000077500000000000000000000000001505437577000212765ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/mapped/index.ts000066400000000000000000000025611505437577000227610ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './mapped-key' export * from './mapped-result' export * from './mapped' sinclairzx81-typebox-e0ec98c/src/type/mapped/mapped-key.ts000066400000000000000000000033311505437577000237020ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import { Kind } from '../symbols/index' export interface TMappedKey extends TSchema { [Kind]: 'MappedKey' static: T[number] keys: T } // prettier-ignore export function MappedKey(T: [...T]): TMappedKey { return CreateType({ [Kind]: 'MappedKey', keys: T }) as never } sinclairzx81-typebox-e0ec98c/src/type/mapped/mapped-result.ts000066400000000000000000000034401505437577000244310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { TProperties } from '../object/index' import { Kind } from '../symbols/index' export interface TMappedResult extends TSchema { [Kind]: 'MappedResult' properties: T static: unknown } // prettier-ignore export function MappedResult(properties: T): TMappedResult { return CreateType({ [Kind]: 'MappedResult', properties }) as never } sinclairzx81-typebox-e0ec98c/src/type/mapped/mapped.ts000066400000000000000000000322261505437577000231210ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Ensure, Evaluate, Assert } from '../helpers/index' import { Kind, OptionalKind, ReadonlyKind } from '../symbols/index' import { CreateType } from '../create/type' import { Discard } from '../discard/index' // evaluation types import { Array, type TArray } from '../array/index' import { AsyncIterator, type TAsyncIterator } from '../async-iterator/index' import { Constructor, type TConstructor } from '../constructor/index' import { type TEnum, type TEnumRecord } from '../enum/index' import { Function as FunctionType, type TFunction } from '../function/index' import { IndexPropertyKeys, type TIndexPropertyKeys } from '../indexed/index' import { Intersect, type TIntersect } from '../intersect/index' import { Iterator, type TIterator } from '../iterator/index' import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' import { Object, type TObject, type TProperties, type ObjectOptions } from '../object/index' import { Optional, type TOptional } from '../optional/index' import { Promise, type TPromise } from '../promise/index' import { Readonly, type TReadonly } from '../readonly/index' import { Tuple, type TTuple } from '../tuple/index' import { Union, type TUnion } from '../union/index' // operator import { SetIncludes, type TSetIncludes } from '../sets/index' // mapping types import { MappedResult, type TMappedResult } from './mapped-result' import type { TMappedKey } from './mapped-key' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsArray, IsAsyncIterator, IsConstructor, IsFunction, IsIntersect, IsIterator, IsReadonly, IsMappedResult, IsMappedKey, IsObject, IsOptional, IsPromise, IsSchema, IsTuple, IsUnion } from '../guard/kind' // ------------------------------------------------------------------ // FromMappedResult // // We only evaluate the context (K) if it is a keyof P. Otherwise we // remap the back to a MappedResult with the expectation it will be // evaluated by an outer context. Note that overlapping keys in the // outer context may result in incorrect evaluation of the outer // context. Reproduction code below. // // type S = { // [L in 'A' | 'B']: { // [R in 'B' | 'C']: [L, R] // issue: overlapping 'B' // } // } // // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult = ( K extends keyof P ? FromSchemaType : TMappedResult

) // prettier-ignore function FromMappedResult(K: K, P: P): TFromMappedResult { return ( K in P ? FromSchemaType(K, P[K as string]) : MappedResult(P) ) as never } // ------------------------------------------------------------------ // MappedKeyToKnownMappedResultProperties // // This path is used when K is in the PropertyKey set of P. This is // the standard (fast) path when not nesting mapped types. // ------------------------------------------------------------------ // prettier-ignore type TMappedKeyToKnownMappedResultProperties = { [_ in K]: TLiteral> } // prettier-ignore function MappedKeyToKnownMappedResultProperties(K: K): TMappedKeyToKnownMappedResultProperties { return { [K]: Literal(K as TLiteralValue) } as never } // ------------------------------------------------------------------ // MappedKeyToUnknownMappedResultProperties // // This path is used when K is outside the set of P. This indicates // that the K originates from outside the current mappped type. This // path is very slow as we need to construct a full MappedResult // to be evaluated by the exterior mapped type. // ------------------------------------------------------------------ // prettier-ignore type TMappedKeyToUnknownMappedResultProperties

= ( P extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? TMappedKeyToUnknownMappedResultProperties> }> : Acc ) // prettier-ignore function MappedKeyToUnknownMappedResultProperties

(P: [...P]): TMappedKeyToUnknownMappedResultProperties

{ const Acc = {} as Record for(const L of P) Acc[L] = Literal(L as TLiteralValue) return Acc as never } // ------------------------------------------------------------------ // MappedKeyToMappedResultProperties // ------------------------------------------------------------------ // prettier-ignore type TMappedKeyToMappedResultProperties = ( TSetIncludes extends true ? TMappedKeyToKnownMappedResultProperties : TMappedKeyToUnknownMappedResultProperties

) // prettier-ignore function MappedKeyToMappedResultProperties(K: K, P: [...P]): TMappedKeyToMappedResultProperties { return ( SetIncludes(P, K) ? MappedKeyToKnownMappedResultProperties(K) : MappedKeyToUnknownMappedResultProperties(P) ) as never } // prettier-ignore type TFromMappedKey< K extends PropertyKey, P extends PropertyKey[], R extends TProperties = TMappedKeyToMappedResultProperties > = ( TFromMappedResult ) // prettier-ignore function FromMappedKey(K: K, P: [...P]): TFromMappedKey { const R = MappedKeyToMappedResultProperties(K, P) return FromMappedResult(K, R) as never } // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore type TFromRest = ( T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromRest]> : Acc ) // prettier-ignore function FromRest(K: K, T: [...T]): TFromRest { return T.map(L => FromSchemaType(K, L)) as never } // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type FromProperties }>> = R // prettier-ignore function FromProperties(K: K, T: T): FromProperties { const Acc = {} as Record for(const K2 of globalThis.Object.getOwnPropertyNames(T)) Acc[K2] = FromSchemaType(K, T[K2]) return Acc as never } // ------------------------------------------------------------------ // FromMappedPropertyKey // ------------------------------------------------------------------ // prettier-ignore type FromSchemaType = ( // unevaluated modifier types T extends TReadonly ? TReadonly> : T extends TOptional ? TOptional> : // unevaluated mapped types T extends TMappedResult ? TFromMappedResult : T extends TMappedKey ? TFromMappedKey : // unevaluated types T extends TConstructor ? TConstructor, FromSchemaType> : T extends TFunction ? TFunction, FromSchemaType> : T extends TAsyncIterator ? TAsyncIterator> : T extends TIterator ? TIterator> : T extends TIntersect ? TIntersect> : // note: special case for enums as these are mapped as union types. T extends TEnum ? TEnum : T extends TUnion ? TUnion> : T extends TTuple ? TTuple> : T extends TObject ? TObject> : T extends TArray ? TArray> : T extends TPromise ? TPromise> : T ) // prettier-ignore function FromSchemaType(K: K, T: T): FromSchemaType { // required to retain user defined options for mapped type const options = { ...T } return ( // unevaluated modifier types IsOptional(T) ? Optional(FromSchemaType(K, Discard(T, [OptionalKind]) as TSchema)) : IsReadonly(T) ? Readonly(FromSchemaType(K, Discard(T, [ReadonlyKind]) as TSchema)) : // unevaluated mapped types IsMappedResult(T) ? FromMappedResult(K, T.properties) : IsMappedKey(T) ? FromMappedKey(K, T.keys) : // unevaluated types IsConstructor(T) ? Constructor(FromRest(K, T.parameters), FromSchemaType(K, T.returns), options) : IsFunction(T) ? FunctionType(FromRest(K, T.parameters), FromSchemaType(K, T.returns), options) : IsAsyncIterator(T) ? AsyncIterator(FromSchemaType(K, T.items), options) : IsIterator(T) ? Iterator(FromSchemaType(K, T.items), options) : IsIntersect(T) ? Intersect(FromRest(K, T.allOf), options) : IsUnion(T) ? Union(FromRest(K, T.anyOf), options) : IsTuple(T) ? Tuple(FromRest(K, T.items ?? []), options) : IsObject(T) ? Object(FromProperties(K, T.properties), options) : IsArray(T) ? Array(FromSchemaType(K, T.items), options) : IsPromise(T) ? Promise(FromSchemaType(K, T.item), options) : T ) as never } // ------------------------------------------------------------------ // MappedFunctionReturnType // ------------------------------------------------------------------ // prettier-ignore export type TMappedFunctionReturnType = ( K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? TMappedFunctionReturnType }> : Acc ) // prettier-ignore export function MappedFunctionReturnType(K: [...K], T: T): TMappedFunctionReturnType { const Acc = {} as Record for(const L of K) Acc[L] = FromSchemaType(L, T) return Acc as never } // ------------------------------------------------------------------ // TMappedFunction // ------------------------------------------------------------------ // prettier-ignore export type TMappedFunction> = (T: I) => TSchema // ------------------------------------------------------------------ // TMapped // ------------------------------------------------------------------ // prettier-ignore export type TMapped< K extends PropertyKey[], F extends TMappedFunction, R extends TProperties = Evaluate>>, > = Ensure> /** `[Json]` Creates a Mapped object type */ export function Mapped, F extends TMappedFunction = TMappedFunction, R extends TMapped = TMapped>(key: K, map: F, options?: ObjectOptions): R /** `[Json]` Creates a Mapped object type */ export function Mapped = TMappedFunction, R extends TMapped = TMapped>(key: [...K], map: F, options?: ObjectOptions): R /** `[Json]` Creates a Mapped object type */ export function Mapped(key: any, map: Function, options?: ObjectOptions) { const K = IsSchema(key) ? IndexPropertyKeys(key) : (key as PropertyKey[]) const RT = map({ [Kind]: 'MappedKey', keys: K } as TMappedKey) const R = MappedFunctionReturnType(K, RT) return Object(R, options) } sinclairzx81-typebox-e0ec98c/src/type/module/000077500000000000000000000000001505437577000213155ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/module/compute.ts000066400000000000000000000576251505437577000233600ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/index' import { CloneType } from '../clone/index' import { Discard } from '../discard/index' import { Ensure, Evaluate } from '../helpers/index' import { type TSchema } from '../schema/index' import { Array, type TArray } from '../array/index' import { Awaited, type TAwaited } from '../awaited/index' import { AsyncIterator, type TAsyncIterator } from '../async-iterator/index' import { TComputed } from '../computed/index' import { Constructor, type TConstructor } from '../constructor/index' import { Index, type TIndex, type TIndexPropertyKeys } from '../indexed/index' import { TEnum, type TEnumRecord } from '../enum/index' import { Function as FunctionType, type TFunction } from '../function/index' import { Intersect, type TIntersect, type TIntersectEvaluated } from '../intersect/index' import { Iterator, type TIterator } from '../iterator/index' import { KeyOf, type TKeyOf } from '../keyof/index' import { Object, type TObject, type TProperties } from '../object/index' import { Omit, type TOmit } from '../omit/index' import { type TOptional } from '../optional/index' import { Pick, type TPick } from '../pick/index' import { Never, type TNever } from '../never/index' import { Partial, TPartial } from '../partial/index' import { type TReadonly } from '../readonly/index' import { RecordValue, RecordPattern, type TRecordOrObject, type TRecord } from '../record/index' import { type TRef } from '../ref/index' import { Required, type TRequired } from '../required/index' import { type TTransform } from '../transform/index' import { Tuple, type TTuple } from '../tuple/index' import { Union, type TUnion, type TUnionEvaluated } from '../union/index' // ------------------------------------------------------------------ // Symbols // ------------------------------------------------------------------ import { TransformKind, OptionalKind, ReadonlyKind } from '../symbols/index' // ------------------------------------------------------------------ // KindGuard // ------------------------------------------------------------------ import * as KindGuard from '../guard/kind' // ------------------------------------------------------------------ // // DereferenceParameters // // Dereferences TComputed parameters. It is important to note that // dereferencing anything other than these parameters may result // inference and evaluation problems, potentially resulting in a // stack overflow. All open TRef types must be preserved !!! // // ------------------------------------------------------------------ // prettier-ignore type TDereferenceParameters = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? Left extends TRef ? TDereferenceParameters]> : TDereferenceParameters]> : Result ) // prettier-ignore function DereferenceParameters(moduleProperties: ModuleProperties, types: [...Types]): TSchema[] { return types.map((type) => { return KindGuard.IsRef(type) ? Dereference(moduleProperties, type.$ref) : FromType(moduleProperties, type) }) as never } // prettier-ignore type TDereference ? TDereference : TFromType : TNever )> = Result // prettier-ignore function Dereference(moduleProperties: ModuleProperties, ref: Ref): TSchema { return ( ref in moduleProperties ? KindGuard.IsRef(moduleProperties[ref]) ? Dereference(moduleProperties, moduleProperties[ref].$ref) : FromType(moduleProperties, moduleProperties[ref]) : Never() ) as never } // ------------------------------------------------------------------ // // TComputed // // The following types support deferred evaluation // // ------------------------------------------------------------------ // ------------------------------------------------------------------ // Awaited // ------------------------------------------------------------------ // prettier-ignore type TFromAwaited = ( Parameters extends [infer T0 extends TSchema] ? TAwaited : never ) // prettier-ignore function FromAwaited(parameters: Parameters): TFromAwaited { return Awaited(parameters[0]) as never } // ------------------------------------------------------------------ // Index // ------------------------------------------------------------------ // prettier-ignore type TFromIndex = ( Parameters extends [infer T0 extends TSchema, infer T1 extends TSchema] // Note: This inferred result check is required to mitgate a "as never" // assertion on FromComputed resolution. This should be removed when // reimplementing TIndex to use TSchema as the primary key indexer. ? TIndex> extends infer Result extends TSchema ? Result : never : never ) // prettier-ignore function FromIndex(parameters: Parameters): TFromIndex { return Index(parameters[0], parameters[1]) as never } // ------------------------------------------------------------------ // KeyOf // ------------------------------------------------------------------ // prettier-ignore type TFromKeyOf = ( Parameters extends [infer T0 extends TSchema] ? TKeyOf : never ) // prettier-ignore function FromKeyOf(parameters: Parameters): TFromAwaited { return KeyOf(parameters[0]) as never } // ------------------------------------------------------------------ // Partial // ------------------------------------------------------------------ // prettier-ignore type TFromPartial = ( Parameters extends [infer T0 extends TSchema] ? TPartial : never ) // prettier-ignore function FromPartial(parameters: Parameters): TFromPartial { return Partial(parameters[0]) as never } // ------------------------------------------------------------------ // Omit // ------------------------------------------------------------------ // prettier-ignore type TFromOmit = ( Parameters extends [infer T0 extends TSchema, infer T1 extends TSchema] ? TOmit : never ) // prettier-ignore function FromOmit(parameters: Parameters): TFromPick { return Omit(parameters[0], parameters[1]) as never } // ------------------------------------------------------------------ // Pick // ------------------------------------------------------------------ // prettier-ignore type TFromPick = ( Parameters extends [infer T0 extends TSchema, infer T1 extends TSchema] ? TPick : never ) // prettier-ignore function FromPick(parameters: Parameters): TFromPick { return Pick(parameters[0], parameters[1]) as never } // ------------------------------------------------------------------ // Required // ------------------------------------------------------------------ // prettier-ignore type TFromRequired = ( Parameters extends [infer T0 extends TSchema] ? TRequired : never ) // prettier-ignore function FromRequired(parameters: Parameters): TFromPick { return Required(parameters[0]) as never } // ------------------------------------------------------------------ // Computed // ------------------------------------------------------------------ // prettier-ignore type TFromComputed > = ( Target extends 'Awaited' ? TFromAwaited : Target extends 'Index' ? TFromIndex : Target extends 'KeyOf' ? TFromKeyOf : Target extends 'Partial' ? TFromPartial : Target extends 'Omit' ? TFromOmit : Target extends 'Pick' ? TFromPick : Target extends 'Required' ? TFromRequired : TNever ) // prettier-ignore function FromComputed(moduleProperties: ModuleProperties, target: Target, parameters: Parameters): TFromComputed { const dereferenced = DereferenceParameters(moduleProperties, parameters) return ( target === 'Awaited' ? FromAwaited(dereferenced) : target === 'Index' ? FromIndex(dereferenced) : target === 'KeyOf' ? FromKeyOf(dereferenced) : target === 'Partial' ? FromPartial(dereferenced) : target === 'Omit' ? FromOmit(dereferenced) : target === 'Pick' ? FromPick(dereferenced) : target === 'Required' ? FromRequired(dereferenced) : Never() ) as never } // ------------------------------------------------------------------ // // Standard Types // // The following are the standard mappable types and structures // // ------------------------------------------------------------------ // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ // prettier-ignore type TFromArray = ( Ensure>> ) function FromArray(moduleProperties: ModuleProperties, type: Type): TFromArray { return Array(FromType(moduleProperties, type)) } // ------------------------------------------------------------------ // AsyncIterator // ------------------------------------------------------------------ // prettier-ignore type TFromAsyncIterator = ( TAsyncIterator> ) function FromAsyncIterator(moduleProperties: ModuleProperties, type: Type): TFromAsyncIterator { return AsyncIterator(FromType(moduleProperties, type)) } // ------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------ // prettier-ignore type TFromConstructor = ( TConstructor, TFromType> ) // prettier-ignore function FromConstructor( moduleProperties: ModuleProperties, parameters: [...Parameters], instanceType: InstanceType, ): TFromConstructor { return Constructor(FromTypes(moduleProperties, parameters as never), FromType(moduleProperties, instanceType) as never) as never } // ------------------------------------------------------------------ // Function // ------------------------------------------------------------------ // prettier-ignore type TFromFunction = Ensure< Ensure, TFromType>> > // prettier-ignore function FromFunction( moduleProperties: ModuleProperties, parameters: [...Parameters], returnType: ReturnType, ): TFromFunction { return FunctionType(FromTypes(moduleProperties, parameters as never), FromType(moduleProperties, returnType) as never) as never } // ------------------------------------------------------------------ // Intersect // ------------------------------------------------------------------ // prettier-ignore type TFromIntersect = ( Ensure>> ) function FromIntersect(moduleProperties: ModuleProperties, types: [...Types]): TFromIntersect { return Intersect(FromTypes(moduleProperties, types as never)) as never } // ------------------------------------------------------------------ // Iterator // ------------------------------------------------------------------ // prettier-ignore type TFromIterator = ( TIterator> ) function FromIterator(moduleProperties: ModuleProperties, type: Type): TFromIterator { return Iterator(FromType(moduleProperties, type)) } // ------------------------------------------------------------------ // Object // ------------------------------------------------------------------ // prettier-ignore type TFromObject = Ensure }>>> function FromObject(moduleProperties: ModuleProperties, properties: Properties): TFromObject { return Object( globalThis.Object.keys(properties).reduce((result, key) => { return { ...result, [key]: FromType(moduleProperties, properties[key]) as never } }, {} as TProperties), ) as never } // ------------------------------------------------------------------ // Record // // Note: Varying Runtime and Static path here as we need to retain // constraints on the Record. This requires remapping the entire // Record in the Runtime path but where the Static path is merely // a facade for the patternProperties regular expression. // ------------------------------------------------------------------ // prettier-ignore type TFromRecord> > = Result // prettier-ignore function FromRecord(moduleProperties: ModuleProperties, type: Type): never { const [value, pattern] = [FromType(moduleProperties, RecordValue(type)), RecordPattern(type)] const result = CloneType(type) result.patternProperties[pattern] = value return result as never } // ------------------------------------------------------------------ // Transform // ------------------------------------------------------------------ // prettier-ignore type TFromTransform ? TTransform, Output> : TTransform > = Result // prettier-ignore function FromTransform(moduleProperties: ModuleProperties, transform: Transform): TSchema { return (KindGuard.IsRef(transform)) ? { ...Dereference(moduleProperties, transform.$ref), [TransformKind]: transform[TransformKind] } : transform } // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ // prettier-ignore type TFromTuple = ( Ensure>> ) function FromTuple(moduleProperties: ModuleProperties, types: [...Types]): TFromTuple { return Tuple(FromTypes(moduleProperties, types as never)) as never } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore type TFromUnion = ( Ensure>> ) function FromUnion(moduleProperties: ModuleProperties, types: [...Types]): TFromUnion { return Union(FromTypes(moduleProperties, types as never)) as never } // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ // prettier-ignore type TFromTypes = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TFromTypes]> : Result ) function FromTypes(moduleProperties: ModuleProperties, types: [...Types]): TFromTypes { return types.map((type) => FromType(moduleProperties, type)) as never } // ------------------------------------------------------------------ // Type // ------------------------------------------------------------------ // prettier-ignore export type TFromType = ( // Modifier Type extends TOptional ? TOptional> : Type extends TReadonly ? TReadonly> : // Transform Type extends TTransform ? TFromTransform : // Types Type extends TArray ? TFromArray : Type extends TAsyncIterator ? TFromAsyncIterator : Type extends TComputed ? TFromComputed : Type extends TConstructor ? TFromConstructor : Type extends TFunction ? TFromFunction : Type extends TIntersect ? TFromIntersect : Type extends TIterator ? TFromIterator : Type extends TObject ? TFromObject : Type extends TRecord ? TFromRecord : Type extends TTuple ? TFromTuple : Type extends TEnum ? Type : // intercept enum before union Type extends TUnion ? TFromUnion : Type ) // prettier-ignore export function FromType(moduleProperties: ModuleProperties, type: Type): TFromType { return ( // Modifiers KindGuard.IsOptional(type) ? CreateType(FromType(moduleProperties, Discard(type, [OptionalKind]) as TSchema) as never, type) : KindGuard.IsReadonly(type) ? CreateType(FromType(moduleProperties, Discard(type, [ReadonlyKind]) as TSchema) as never, type) : // Transform KindGuard.IsTransform(type) ? CreateType(FromTransform(moduleProperties, type), type) : // Types KindGuard.IsArray(type) ? CreateType(FromArray(moduleProperties, type.items), type) : KindGuard.IsAsyncIterator(type) ? CreateType(FromAsyncIterator(moduleProperties, type.items), type) : KindGuard.IsComputed(type) ? CreateType(FromComputed(moduleProperties, type.target, type.parameters)) : KindGuard.IsConstructor(type) ? CreateType(FromConstructor(moduleProperties, type.parameters, type.returns), type) : KindGuard.IsFunction(type) ? CreateType(FromFunction(moduleProperties, type.parameters, type.returns), type) : KindGuard.IsIntersect(type) ? CreateType(FromIntersect(moduleProperties, type.allOf), type) : KindGuard.IsIterator(type) ? CreateType(FromIterator(moduleProperties, type.items), type) : KindGuard.IsObject(type) ? CreateType(FromObject(moduleProperties, type.properties), type) : KindGuard.IsRecord(type) ? CreateType(FromRecord(moduleProperties, type)) : KindGuard.IsTuple(type)? CreateType(FromTuple(moduleProperties, type.items || []), type) : KindGuard.IsUnion(type) ? CreateType(FromUnion(moduleProperties, type.anyOf), type) : type ) as never } // ------------------------------------------------------------------ // ComputeType // ------------------------------------------------------------------ // prettier-ignore export type TComputeType = ( Key extends keyof ModuleProperties ? TFromType : TNever ) // prettier-ignore export function ComputeType(moduleProperties: ModuleProperties, key: Key): TComputeType { return ( key in moduleProperties ? FromType(moduleProperties, moduleProperties[key as keyof ModuleProperties]) : Never() ) as never } // ------------------------------------------------------------------ // ComputeModuleProperties // ------------------------------------------------------------------ // prettier-ignore export type TComputeModuleProperties = Evaluate<{ [Key in keyof ModuleProperties]: TComputeType }> // prettier-ignore export function ComputeModuleProperties(moduleProperties: ModuleProperties): TComputeModuleProperties { return globalThis.Object.getOwnPropertyNames(moduleProperties).reduce((result, key) => { return {...result, [key]: ComputeType(moduleProperties, key) } }, {} as TProperties) as never } sinclairzx81-typebox-e0ec98c/src/type/module/index.ts000066400000000000000000000024641505437577000230020ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './module' sinclairzx81-typebox-e0ec98c/src/type/module/infer.ts000066400000000000000000000234171505437577000227770ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Ensure, Evaluate } from '../helpers/index' import { TSchema } from '../schema/index' import { TArray } from '../array/index' import { TAsyncIterator } from '../async-iterator/index' import { TConstructor } from '../constructor/index' import { TEnum, TEnumRecord } from '../enum/index' import { TFunction } from '../function/index' import { TIntersect } from '../intersect/index' import { TIterator } from '../iterator/index' import { TObject, TProperties } from '../object/index' import { TOptional } from '../optional/index' import { TRecord } from '../record/index' import { TReadonly } from '../readonly/index' import { TRef } from '../ref/index' import { TTuple } from '../tuple/index' import { TUnion } from '../union/index' import { Static } from '../static/index' import { TRecursive } from '../recursive/index' // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ // prettier-ignore type TInferArray = ( Ensure>> ) // ------------------------------------------------------------------ // AsyncIterator // ------------------------------------------------------------------ // prettier-ignore type TInferAsyncIterator = ( Ensure>> ) // ------------------------------------------------------------------ // Constructor // ------------------------------------------------------------------ // prettier-ignore type TInferConstructor = Ensure< new (...args: TInferTuple) => TInfer > // ------------------------------------------------------------------ // Function // ------------------------------------------------------------------ // prettier-ignore type TInferFunction = Ensure< (...args: TInferTuple) => TInfer > // ------------------------------------------------------------------ // Iterator // ------------------------------------------------------------------ // prettier-ignore type TInferIterator = ( Ensure>> ) // ------------------------------------------------------------------ // Intersect // ------------------------------------------------------------------ // prettier-ignore type TInferIntersect = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TInferIntersect> : Result ) // ------------------------------------------------------------------ // Object // ------------------------------------------------------------------ type ReadonlyOptionalPropertyKeys = { [Key in keyof Properties]: Properties[Key] extends TReadonly ? (Properties[Key] extends TOptional ? Key : never) : never }[keyof Properties] type ReadonlyPropertyKeys = { [Key in keyof Source]: Source[Key] extends TReadonly ? (Source[Key] extends TOptional ? never : Key) : never }[keyof Source] type OptionalPropertyKeys = { [Key in keyof Source]: Source[Key] extends TOptional ? (Source[Key] extends TReadonly ? never : Key) : never }[keyof Source] type RequiredPropertyKeys = keyof Omit | ReadonlyPropertyKeys | OptionalPropertyKeys> // prettier-ignore type InferPropertiesWithModifiers> = Evaluate<( Readonly>>> & Readonly>> & Partial>> & Required>> )> // prettier-ignore type InferProperties = InferPropertiesWithModifiers }> // prettier-ignore type TInferObject = ( InferProperties ) // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ // prettier-ignore type TInferTuple = ( Types extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TInferTuple]> : Result ) // ------------------------------------------------------------------ // Record // ------------------------------------------------------------------ // prettier-ignore type TInferRecord extends infer Key extends PropertyKey ? Key : never, InferedType extends unknown = TInfer, > = Ensure<{ [_ in InferredKey]: InferedType }> // ------------------------------------------------------------------ // Ref // ------------------------------------------------------------------ // prettier-ignore type TInferRef = ( Ref extends keyof ModuleProperties ? TInfer : unknown ) // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore type TInferUnion = ( Types extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TInferUnion> : Result ) // ------------------------------------------------------------------ // Infer // ------------------------------------------------------------------ // prettier-ignore type TInfer = ( Type extends TArray ? TInferArray : Type extends TAsyncIterator ? TInferAsyncIterator : Type extends TConstructor ? TInferConstructor : Type extends TFunction ? TInferFunction : Type extends TIntersect ? TInferIntersect : Type extends TIterator ? TInferIterator : Type extends TObject ? TInferObject : Type extends TRecord ? TInferRecord : Type extends TRef ? TInferRef : Type extends TTuple ? TInferTuple : Type extends TEnum ? Static : // intercept enum before union Type extends TUnion ? TInferUnion : Type extends TRecursive ? TInfer : Static ) // ------------------------------------------------------------------ // InferFromModuleKey // ------------------------------------------------------------------ /** Inference Path for Imports. This type is used to compute TImport `static` */ // prettier-ignore export type TInferFromModuleKey = ( Key extends keyof ModuleProperties ? TInfer : never ) sinclairzx81-typebox-e0ec98c/src/type/module/module.ts000066400000000000000000000076041505437577000231610ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/index' import { Kind } from '../symbols/index' import { SchemaOptions, TSchema } from '../schema/index' import { TProperties } from '../object/index' import { Static } from '../static/index' // ------------------------------------------------------------------ // Module Infrastructure Types // ------------------------------------------------------------------ import { ComputeModuleProperties, TComputeModuleProperties } from './compute' import { TInferFromModuleKey } from './infer' // ------------------------------------------------------------------ // Definitions // ------------------------------------------------------------------ export interface TDefinitions extends TSchema { static: { [K in keyof ModuleProperties]: Static } $defs: ModuleProperties } // ------------------------------------------------------------------ // Import // ------------------------------------------------------------------ // prettier-ignore export interface TImport extends TSchema { [Kind]: 'Import' static: TInferFromModuleKey $defs: ModuleProperties $ref: Key } // ------------------------------------------------------------------ // Module // ------------------------------------------------------------------ // prettier-ignore export class TModule> { private readonly $defs: ComputedModuleProperties constructor($defs: ModuleProperties) { const computed = ComputeModuleProperties($defs) const identified = this.WithIdentifiers(computed as never) this.$defs = identified as never } /** `[Json]` Imports a Type by Key. */ public Import(key: Key, options?: SchemaOptions): TImport { const $defs = { ...this.$defs, [key]: CreateType(this.$defs[key], options) } return CreateType({ [Kind]: 'Import', $defs, $ref: key }) as never } // prettier-ignore private WithIdentifiers($defs: ComputedModuleProperties): ComputedModuleProperties { return globalThis.Object.getOwnPropertyNames($defs).reduce((result, key) => { return { ...result, [key]: { ...$defs[key], $id: key }} }, {}) as never } } /** `[Json]` Creates a Type Definition Module. */ export function Module(properties: Properties): TModule { return new TModule(properties) } sinclairzx81-typebox-e0ec98c/src/type/never/000077500000000000000000000000001505437577000211475ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/never/index.ts000066400000000000000000000024621505437577000226320ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './never' sinclairzx81-typebox-e0ec98c/src/type/never/never.ts000066400000000000000000000032521505437577000226400ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface TNever extends TSchema { [Kind]: 'Never' static: never not: {} } /** `[Json]` Creates a Never type */ export function Never(options?: SchemaOptions): TNever { return CreateType({ [Kind]: 'Never', not: {} }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/not/000077500000000000000000000000001505437577000206305ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/not/index.ts000066400000000000000000000024611505437577000223120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './not' sinclairzx81-typebox-e0ec98c/src/type/not/not.ts000066400000000000000000000034721505437577000220060ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import { Kind } from '../symbols/index' export interface TNot extends TSchema { [Kind]: 'Not' static: T extends TNot ? Static : unknown not: T } /** `[Json]` Creates a Not type */ export function Not(type: Type, options?: SchemaOptions): TNot { return CreateType({ [Kind]: 'Not', not: type }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/null/000077500000000000000000000000001505437577000210025ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/null/index.ts000066400000000000000000000024621505437577000224650ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './null' sinclairzx81-typebox-e0ec98c/src/type/null/null.ts000066400000000000000000000032551505437577000223310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface TNull extends TSchema { [Kind]: 'Null' static: null type: 'null' } /** `[Json]` Creates a Null type */ export function Null(options?: SchemaOptions): TNull { return CreateType({ [Kind]: 'Null', type: 'null' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/number/000077500000000000000000000000001505437577000213205ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/number/index.ts000066400000000000000000000024641505437577000230050ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './number' sinclairzx81-typebox-e0ec98c/src/type/number/number.ts000066400000000000000000000035731505437577000231700ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface NumberOptions extends SchemaOptions { exclusiveMaximum?: number exclusiveMinimum?: number maximum?: number minimum?: number multipleOf?: number } export interface TNumber extends TSchema, NumberOptions { [Kind]: 'Number' static: number type: 'number' } /** `[Json]` Creates a Number type */ export function Number(options?: NumberOptions): TNumber { return CreateType({ [Kind]: 'Number', type: 'number' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/object/000077500000000000000000000000001505437577000212765ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/object/index.ts000066400000000000000000000024641505437577000227630ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './object' sinclairzx81-typebox-e0ec98c/src/type/object/object.ts000066400000000000000000000114351505437577000231200ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import type { Evaluate } from '../helpers/index' import type { TReadonly } from '../readonly/index' import type { TOptional } from '../optional/index' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsOptional } from '../guard/kind' // ------------------------------------------------------------------ // ObjectStatic // ------------------------------------------------------------------ type ReadonlyOptionalPropertyKeys = { [K in keyof T]: T[K] extends TReadonly ? (T[K] extends TOptional ? K : never) : never }[keyof T] type ReadonlyPropertyKeys = { [K in keyof T]: T[K] extends TReadonly ? (T[K] extends TOptional ? never : K) : never }[keyof T] type OptionalPropertyKeys = { [K in keyof T]: T[K] extends TOptional ? (T[K] extends TReadonly ? never : K) : never }[keyof T] type RequiredPropertyKeys = keyof Omit | ReadonlyPropertyKeys | OptionalPropertyKeys> // prettier-ignore type ObjectStaticProperties> = Evaluate<( Readonly>>> & Readonly>> & Partial>> & Required>> )> // prettier-ignore type ObjectStatic = ObjectStaticProperties }> // ------------------------------------------------------------------ // TProperties // ------------------------------------------------------------------ export type TPropertyKey = string | number // Consider making this PropertyKey export type TProperties = Record // ------------------------------------------------------------------ // TObject // ------------------------------------------------------------------ export type TAdditionalProperties = undefined | TSchema | boolean export interface ObjectOptions extends SchemaOptions { /** Additional property constraints for this object */ additionalProperties?: TAdditionalProperties /** The minimum number of properties allowed on this object */ minProperties?: number /** The maximum number of properties allowed on this object */ maxProperties?: number } export interface TObject extends TSchema, ObjectOptions { [Kind]: 'Object' static: ObjectStatic additionalProperties?: TAdditionalProperties type: 'object' properties: T required?: string[] } function RequiredKeys(properties: T): string[] { const keys: string[] = [] for (let key in properties) { if (!IsOptional(properties[key])) keys.push(key) } return keys } /** `[Json]` Creates an Object type */ function _Object(properties: T, options?: ObjectOptions): TObject { const required = RequiredKeys(properties) const schematic = required.length > 0 ? { [Kind]: 'Object', type: 'object', properties, required } : { [Kind]: 'Object', type: 'object', properties } return CreateType(schematic, options) as never } /** `[Json]` Creates an Object type */ export var Object = _Object sinclairzx81-typebox-e0ec98c/src/type/omit/000077500000000000000000000000001505437577000210005ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/omit/index.ts000066400000000000000000000026031505437577000224600ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './omit-from-mapped-key' export * from './omit-from-mapped-result' export * from './omit' sinclairzx81-typebox-e0ec98c/src/type/omit/omit-from-mapped-key.ts000066400000000000000000000101751505437577000253170ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, type TMappedKey } from '../mapped/index' import { Omit, type TOmit } from './omit' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromPropertyKey // ------------------------------------------------------------------ // prettier-ignore type TFromPropertyKey = { [_ in Key]: TOmit } // prettier-ignore function FromPropertyKey(type: Type, key: Key, options?: SchemaOptions): TFromPropertyKey { return { [key]: Omit(type, [key], Clone(options)) } as never } // ------------------------------------------------------------------ // FromPropertyKeys // ------------------------------------------------------------------ // prettier-ignore type TFromPropertyKeys = ( PropertyKeys extends [infer LK extends PropertyKey, ...infer RK extends PropertyKey[]] ? TFromPropertyKeys> : Result ) // prettier-ignore function FromPropertyKeys(type: Type, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TFromPropertyKeys { return propertyKeys.reduce((Acc, LK) => { return { ...Acc, ...FromPropertyKey(type, LK, options) } }, {} as TProperties) as never } // ------------------------------------------------------------------ // FromMappedKey // ------------------------------------------------------------------ // prettier-ignore type TFromMappedKey = ( TFromPropertyKeys ) // prettier-ignore function FromMappedKey(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TFromMappedKey { return FromPropertyKeys(type, mappedKey.keys, options) as never } // ------------------------------------------------------------------ // OmitFromMappedKey // ------------------------------------------------------------------ // prettier-ignore export type TOmitFromMappedKey > = ( TMappedResult ) // prettier-ignore export function OmitFromMappedKey >(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TMappedResult { const properties = FromMappedKey(type, mappedKey, options) return MappedResult(properties) as never } sinclairzx81-typebox-e0ec98c/src/type/omit/omit-from-mapped-result.ts000066400000000000000000000075551505437577000260550ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { SchemaOptions } from '../schema/index' import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Omit, type TOmit } from './omit' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties = ( { [K2 in keyof Properties]: TOmit } ) // prettier-ignore function FromProperties(properties: Properties, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TFromProperties { const result = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(properties)) result[K2] = Omit(properties[K2], propertyKeys, Clone(options)) return result as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult = ( Evaluate> ) // prettier-ignore function FromMappedResult(mappedResult: MappedResult, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TFromMappedResult { return FromProperties(mappedResult.properties, propertyKeys, options) as never } // ------------------------------------------------------------------ // TOmitFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TOmitFromMappedResult< MappedResult extends TMappedResult, PropertyKeys extends PropertyKey[], Properties extends TProperties = TFromMappedResult > = ( Ensure> ) // prettier-ignore export function OmitFromMappedResult< MappedResult extends TMappedResult, PropertyKeys extends PropertyKey[], Properties extends TProperties = TFromMappedResult >(mappedResult: MappedResult, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TMappedResult { const properties = FromMappedResult(mappedResult, propertyKeys, options) return MappedResult(properties) as never } sinclairzx81-typebox-e0ec98c/src/type/omit/omit.ts000066400000000000000000000247131505437577000223270ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { Discard } from '../discard/discard' import { TransformKind } from '../symbols/symbols' import type { SchemaOptions, TSchema } from '../schema/index' import type { TupleToUnion, Evaluate, Ensure } from '../helpers/index' import { type TRecursive } from '../recursive/index' import type { TMappedKey, TMappedResult } from '../mapped/index' import { Computed, TComputed } from '../computed/index' import { Literal, TLiteral, TLiteralValue } from '../literal/index' import { IndexPropertyKeys, type TIndexPropertyKeys } from '../indexed/index' import { Intersect, type TIntersect } from '../intersect/index' import { Union, type TUnion } from '../union/index' import { Object, type TObject, type TProperties } from '../object/index' import { type TRef } from '../ref/index' // ------------------------------------------------------------------ // Mapped // ------------------------------------------------------------------ import { OmitFromMappedKey, type TOmitFromMappedKey } from './omit-from-mapped-key' import { OmitFromMappedResult, type TOmitFromMappedResult } from './omit-from-mapped-result' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsMappedKey, IsIntersect, IsUnion, IsObject, IsSchema, IsMappedResult, IsLiteralValue, IsRef } from '../guard/kind' import { IsArray as IsArrayValue } from '../guard/value' // ------------------------------------------------------------------ // FromIntersect // ------------------------------------------------------------------ // prettier-ignore type TFromIntersect = ( Types extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromIntersect]> : Result ) // prettier-ignore function FromIntersect(types: Types, propertyKeys: PropertyKeys) { return types.map((type) => OmitResolve(type, propertyKeys)) as never } // ------------------------------------------------------------------ // FromUnion // ------------------------------------------------------------------ // prettier-ignore type TFromUnion = ( T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromUnion]> : Result ) // prettier-ignore function FromUnion(types: Types, propertyKeys: PropertyKeys) { return types.map((type) => OmitResolve(type, propertyKeys)) as never } // ------------------------------------------------------------------ // FromProperty // ------------------------------------------------------------------ // prettier-ignore function FromProperty(properties: Properties, key: Key): TProperties { const { [key]: _, ...R } = properties return R } // prettier-ignore type TFromProperties> = ( Evaluate> ) // prettier-ignore function FromProperties(properties: Properties, propertyKeys: PropertyKeys) { return propertyKeys.reduce((T, K2) => FromProperty(T, K2), properties as TProperties) } // ------------------------------------------------------------------ // FromObject // ------------------------------------------------------------------ // prettier-ignore type TFromObject = Ensure )>> // prettier-ignore function FromObject(properties: Properties, propertyKeys: PropertyKeys): TFromObject { const options = Discard(properties, [TransformKind, '$id', 'required', 'properties']) const omittedProperties = FromProperties(properties['properties'], propertyKeys) return Object(omittedProperties, options) as never } // ------------------------------------------------------------------ // UnionFromPropertyKeys // ------------------------------------------------------------------ // prettier-ignore type TUnionFromPropertyKeys = ( PropertyKeys extends [infer Key extends PropertyKey, ...infer Rest extends PropertyKey[]] ? Key extends TLiteralValue ? TUnionFromPropertyKeys]> : TUnionFromPropertyKeys : TUnion ) // prettier-ignore function UnionFromPropertyKeys(propertyKeys: PropertyKeys): TUnionFromPropertyKeys { const result = propertyKeys.reduce((result, key) => IsLiteralValue(key) ? [...result, Literal(key)]: result, [] as TLiteral[]) return Union(result) as never } // ------------------------------------------------------------------ // TOmitResolve // ------------------------------------------------------------------ // prettier-ignore export type TOmitResolve = ( Properties extends TRecursive ? TRecursive> : Properties extends TIntersect ? TIntersect> : Properties extends TUnion ? TUnion> : Properties extends TObject ? TFromObject, PropertyKeys> : TObject<{}> ) // prettier-ignore function OmitResolve(properties: Properties, propertyKeys: [...PropertyKeys]): TOmitResolve { return ( IsIntersect(properties) ? Intersect(FromIntersect(properties.allOf, propertyKeys)) : IsUnion(properties) ? Union(FromUnion(properties.anyOf, propertyKeys)) : IsObject(properties) ? FromObject(properties, propertyKeys) : Object({}) ) as never } // ------------------------------------------------------------------ // TOmit // // This mapping logic is to overly complex because of the decision // to use PropertyKey[] as the default selector. The PropertyKey[] // did make TMapped types simpler to implement, but a non-TSchema // selector makes supporting TComputed awkward as it requires // generalization via TSchema. This type should be reimplemented // in the next major revision to support TSchema as the primary // selector. // // ------------------------------------------------------------------ // prettier-ignore (do not export this type) type TResolvePropertyKeys = Key extends TSchema ? TIndexPropertyKeys : Key // prettier-ignore (do not export this type) type TResolveTypeKey = Key extends PropertyKey[] ? TUnionFromPropertyKeys : Key // prettier-ignore export type TOmit = ( Type extends TMappedResult ? TOmitFromMappedResult> : Key extends TMappedKey ? TOmitFromMappedKey : [IsTypeRef, IsKeyRef] extends [true, true] ? TComputed<'Omit', [Type, TResolveTypeKey]> : [IsTypeRef, IsKeyRef] extends [false, true] ? TComputed<'Omit', [Type, TResolveTypeKey]> : [IsTypeRef, IsKeyRef] extends [true, false] ? TComputed<'Omit', [Type, TResolveTypeKey]> : TOmitResolve> ) /** `[Json]` Constructs a type whose keys are picked from the given type */ export function Omit(type: Type, key: readonly [...Key], options?: SchemaOptions): TOmit /** `[Json]` Constructs a type whose keys are picked from the given type */ export function Omit(type: Type, key: Key, options?: SchemaOptions): TOmit /** `[Json]` Constructs a type whose keys are picked from the given type */ // prettier-ignore export function Omit(type: any, key: any, options?: SchemaOptions): any { const typeKey: TSchema = IsArrayValue(key) ? UnionFromPropertyKeys(key as PropertyKey[]) : key const propertyKeys: PropertyKey[] = IsSchema(key) ? IndexPropertyKeys(key) : key const isTypeRef: boolean = IsRef(type) const isKeyRef: boolean = IsRef(key) return ( IsMappedResult(type) ? OmitFromMappedResult(type, propertyKeys, options) : IsMappedKey(key) ? OmitFromMappedKey(type, key, options) : (isTypeRef && isKeyRef) ? Computed('Omit', [type, typeKey], options) : (!isTypeRef && isKeyRef) ? Computed('Omit', [type, typeKey], options) : (isTypeRef && !isKeyRef) ? Computed('Omit', [type, typeKey], options) : CreateType({ ...OmitResolve(type, propertyKeys), ...options }) ) as never } sinclairzx81-typebox-e0ec98c/src/type/optional/000077500000000000000000000000001505437577000216555ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/optional/index.ts000066400000000000000000000025441505437577000233410ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './optional-from-mapped-result' export * from './optional' sinclairzx81-typebox-e0ec98c/src/type/optional/optional-from-mapped-result.ts000066400000000000000000000061501505437577000275750ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Optional, type TOptionalWithFlag } from './optional' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties< P extends TProperties, F extends boolean, > = ( { [K2 in keyof P]: TOptionalWithFlag } ) // prettier-ignore function FromProperties< P extends TProperties, F extends boolean, >(P: P, F: F): TFromProperties { const Acc = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Optional(P[K2], F) return Acc as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult< R extends TMappedResult, F extends boolean, > = ( TFromProperties ) // prettier-ignore function FromMappedResult< R extends TMappedResult, F extends boolean, >(R: R, F: F): TFromMappedResult { return FromProperties(R.properties, F) as never } // ------------------------------------------------------------------ // OptionalFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TOptionalFromMappedResult< R extends TMappedResult, F extends boolean, P extends TProperties = TFromMappedResult > = ( TMappedResult

) // prettier-ignore export function OptionalFromMappedResult< R extends TMappedResult, F extends boolean, P extends TProperties = TFromMappedResult >(R: R, F: F): TMappedResult

{ const P = FromMappedResult(R, F) as unknown as P return MappedResult(P) } sinclairzx81-typebox-e0ec98c/src/type/optional/optional.ts000066400000000000000000000074511505437577000240610ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { Ensure } from '../helpers/index' import { OptionalKind } from '../symbols/index' import { Discard } from '../discard/index' import type { TMappedResult } from '../mapped/index' import { OptionalFromMappedResult, type TOptionalFromMappedResult } from './optional-from-mapped-result' import { IsMappedResult } from '../guard/kind' // ------------------------------------------------------------------ // RemoveOptional // ------------------------------------------------------------------ type TRemoveOptional = T extends TOptional ? S : T function RemoveOptional(schema: T) { return CreateType(Discard(schema, [OptionalKind])) } // ------------------------------------------------------------------ // AddOptional // ------------------------------------------------------------------ type TAddOptional = T extends TOptional ? TOptional : Ensure> function AddOptional(schema: T) { return CreateType({ ...schema, [OptionalKind]: 'Optional' }) } // prettier-ignore export type TOptionalWithFlag = F extends false ? TRemoveOptional : TAddOptional // prettier-ignore function OptionalWithFlag(schema: T, F: F) { return ( F === false ? RemoveOptional(schema) : AddOptional(schema) ) } // ------------------------------------------------------------------ // Optional // ------------------------------------------------------------------ export type TOptional = T & { [OptionalKind]: 'Optional' } /** `[Json]` Creates a Optional property */ export function Optional(schema: T, enable: F): TOptionalFromMappedResult /** `[Json]` Creates a Optional property */ export function Optional(schema: T, enable: F): TOptionalWithFlag /** `[Json]` Creates a Optional property */ export function Optional(schema: T): TOptionalFromMappedResult /** `[Json]` Creates a Optional property */ export function Optional(schema: T): TOptionalWithFlag /** `[Json]` Creates a Optional property */ export function Optional(schema: TSchema, enable?: boolean): any { const F = enable ?? true return IsMappedResult(schema) ? OptionalFromMappedResult(schema, F) : OptionalWithFlag(schema, F) } sinclairzx81-typebox-e0ec98c/src/type/parameters/000077500000000000000000000000001505437577000221735ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/parameters/index.ts000066400000000000000000000024701505437577000236550ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './parameters' sinclairzx81-typebox-e0ec98c/src/type/parameters/parameters.ts000066400000000000000000000042401505437577000247060ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TFunction } from '../function/index' import { Tuple, type TTuple } from '../tuple/index' import { Never, type TNever } from '../never/index' import * as KindGuard from '../guard/kind' // ------------------------------------------------------------------ // Parameters // ------------------------------------------------------------------ // prettier-ignore export type TParameters = ( Type extends TFunction ? TTuple : TNever ) /** `[JavaScript]` Extracts the Parameters from the given Function type */ export function Parameters(schema: Type, options?: SchemaOptions): TParameters { return (KindGuard.IsFunction(schema) ? Tuple(schema.parameters, options) : Never()) as never } sinclairzx81-typebox-e0ec98c/src/type/partial/000077500000000000000000000000001505437577000214645ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/partial/index.ts000066400000000000000000000025421505437577000231460ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './partial-from-mapped-result' export * from './partial' sinclairzx81-typebox-e0ec98c/src/type/partial/partial-from-mapped-result.ts000066400000000000000000000062561505437577000272220ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { SchemaOptions } from '../schema/index' import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Partial, type TPartial } from './partial' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties< P extends TProperties > = ( { [K2 in keyof P]: TPartial } ) // prettier-ignore function FromProperties< P extends TProperties >(K: P, options?: SchemaOptions): TFromProperties

{ const Acc = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = Partial(K[K2], Clone(options)) return Acc as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult< R extends TMappedResult > = ( Evaluate> ) // prettier-ignore function FromMappedResult< R extends TMappedResult >(R: R, options?: SchemaOptions): TFromMappedResult { return FromProperties(R.properties, options) as never } // ------------------------------------------------------------------ // TPartialFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TPartialFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult > = ( Ensure> ) // prettier-ignore export function PartialFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult >(R: R, options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(R, options) return MappedResult(P) as never } sinclairzx81-typebox-e0ec98c/src/type/partial/partial.ts000066400000000000000000000207461505437577000235010ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Evaluate, Ensure } from '../helpers/index' import type { TMappedResult } from '../mapped/index' import { type TReadonlyOptional } from '../readonly-optional/index' import { type TComputed, Computed } from '../computed/index' import { type TOptional, Optional } from '../optional/index' import { type TReadonly } from '../readonly/index' import { type TRecursive } from '../recursive/index' import { type TObject, type TProperties, Object } from '../object/index' import { type TIntersect, Intersect } from '../intersect/index' import { type TUnion, Union } from '../union/index' import { type TRef, Ref } from '../ref/index' import { type TBigInt } from '../bigint/index' import { type TBoolean } from '../boolean/index' import { type TInteger } from '../integer/index' import { type TLiteral } from '../literal/index' import { type TNull } from '../null/index' import { type TNumber } from '../number/index' import { type TString } from '../string/index' import { type TSymbol } from '../symbol/index' import { type TUndefined } from '../undefined/index' import { Discard } from '../discard/index' import { TransformKind } from '../symbols/index' import { PartialFromMappedResult, type TPartialFromMappedResult } from './partial-from-mapped-result' // ------------------------------------------------------------------ // KindGuard // ------------------------------------------------------------------ import * as KindGuard from '../guard/kind' // ------------------------------------------------------------------ // FromComputed // ------------------------------------------------------------------ // prettier-ignore type TFromComputed = Ensure< TComputed<'Partial', [TComputed]> > // prettier-ignore function FromComputed(target: Target, parameters: Parameters): TFromComputed { return Computed('Partial', [Computed(target, parameters)]) as never } // ------------------------------------------------------------------ // FromRef // ------------------------------------------------------------------ // prettier-ignore type TFromRef = Ensure< TComputed<'Partial', [TRef]> > // prettier-ignore function FromRef($ref: Ref): TFromRef { return Computed('Partial', [Ref($ref)]) as never } // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties = Evaluate<{ [K in keyof Properties]: Properties[K] extends (TReadonlyOptional) ? TReadonlyOptional : Properties[K] extends (TReadonly) ? TReadonlyOptional : Properties[K] extends (TOptional) ? TOptional : TOptional }> // prettier-ignore function FromProperties(properties: Properties): TFromProperties { const partialProperties = {} as TProperties for(const K of globalThis.Object.getOwnPropertyNames(properties)) partialProperties[K] = Optional(properties[K]) return partialProperties as never } // ------------------------------------------------------------------ // FromObject // ------------------------------------------------------------------ // prettier-ignore type TFromObject = Ensure )>> // prettier-ignore function FromObject(type: Type): TFromObject { const options = Discard(type, [TransformKind, '$id', 'required', 'properties']) const properties = FromProperties(type['properties']) return Object(properties, options) as never } // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore type TFromRest = ( Types extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromRest]> : Result ) // prettier-ignore function FromRest(types: [...Types]): TFromRest { return types.map(type => PartialResolve(type)) as never } // ------------------------------------------------------------------ // PartialResolve // ------------------------------------------------------------------ // prettier-ignore function PartialResolve(type: Type): TPartial { return ( // Mappable KindGuard.IsComputed(type) ? FromComputed(type.target, type.parameters) : KindGuard.IsRef(type) ? FromRef(type.$ref) : KindGuard.IsIntersect(type) ? Intersect(FromRest(type.allOf)) : KindGuard.IsUnion(type) ? Union(FromRest(type.anyOf)) : KindGuard.IsObject(type) ? FromObject(type) : // Intrinsic KindGuard.IsBigInt(type) ? type : KindGuard.IsBoolean(type) ? type : KindGuard.IsInteger(type) ? type : KindGuard.IsLiteral(type) ? type : KindGuard.IsNull(type) ? type : KindGuard.IsNumber(type) ? type : KindGuard.IsString(type) ? type : KindGuard.IsSymbol(type) ? type : KindGuard.IsUndefined(type) ? type : // Passthrough Object({}) ) as never } // ------------------------------------------------------------------ // TPartial // ------------------------------------------------------------------ // prettier-ignore export type TPartial = ( // Mappable Type extends TRecursive ? TRecursive> : Type extends TComputed ? TFromComputed : Type extends TRef ? TFromRef : Type extends TIntersect ? TIntersect> : Type extends TUnion ? TUnion> : Type extends TObject ? TFromObject> : // Intrinsic Type extends TBigInt ? Type : Type extends TBoolean ? Type : Type extends TInteger ? Type : Type extends TLiteral ? Type : Type extends TNull ? Type : Type extends TNumber ? Type : Type extends TString ? Type : Type extends TSymbol ? Type : Type extends TUndefined ? Type : // Passthrough TObject<{}> ) /** `[Json]` Constructs a type where all properties are optional */ export function Partial(type: MappedResult, options?: SchemaOptions): TPartialFromMappedResult /** `[Json]` Constructs a type where all properties are optional */ export function Partial(type: Type, options?: SchemaOptions): TPartial /** `[Json]` Constructs a type where all properties are optional */ export function Partial(type: TSchema, options?: SchemaOptions): unknown { if (KindGuard.IsMappedResult(type)) { return PartialFromMappedResult(type, options) } else { // special: mapping types require overridable options return CreateType({ ...PartialResolve(type), ...options }) } } sinclairzx81-typebox-e0ec98c/src/type/patterns/000077500000000000000000000000001505437577000216705ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/patterns/index.ts000066400000000000000000000024661505437577000233570ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './patterns' sinclairzx81-typebox-e0ec98c/src/type/patterns/patterns.ts000066400000000000000000000032341505437577000241020ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 const PatternBoolean = '(true|false)' export const PatternNumber = '(0|[1-9][0-9]*)' export const PatternString = '(.*)' export const PatternNever = '(?!.*)' export const PatternBooleanExact = `^${PatternBoolean}$` export const PatternNumberExact = `^${PatternNumber}$` export const PatternStringExact = `^${PatternString}$` export const PatternNeverExact = `^${PatternNever}$` sinclairzx81-typebox-e0ec98c/src/type/pick/000077500000000000000000000000001505437577000207565ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/pick/index.ts000066400000000000000000000026031505437577000224360ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './pick-from-mapped-key' export * from './pick-from-mapped-result' export * from './pick' sinclairzx81-typebox-e0ec98c/src/type/pick/pick-from-mapped-key.ts000066400000000000000000000102531505437577000252500ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, type TMappedKey } from '../mapped/index' import { Pick, type TPick } from './pick' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromPropertyKey // ------------------------------------------------------------------ // prettier-ignore type TFromPropertyKey = { [_ in Key]: TPick } // prettier-ignore function FromPropertyKey(type: Type, key: Key, options?: SchemaOptions): TFromPropertyKey { return { [key]: Pick(type, [key], Clone(options)) } as never } // ------------------------------------------------------------------ // FromPropertyKeys // ------------------------------------------------------------------ // prettier-ignore type TFromPropertyKeys = ( PropertyKeys extends [infer LeftKey extends PropertyKey, ...infer RightKeys extends PropertyKey[]] ? TFromPropertyKeys> : Result ) // prettier-ignore function FromPropertyKeys(type: Type, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TFromPropertyKeys { return propertyKeys.reduce((result, leftKey) => { return { ...result, ...FromPropertyKey(type, leftKey, options) } }, {} as TProperties) as never } // ------------------------------------------------------------------ // FromMappedKey // ------------------------------------------------------------------ // prettier-ignore type TFromMappedKey = ( TFromPropertyKeys ) // prettier-ignore function FromMappedKey(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TFromMappedKey { return FromPropertyKeys(type, mappedKey.keys, options) as never } // ------------------------------------------------------------------ // PickFromMappedKey // ------------------------------------------------------------------ // prettier-ignore export type TPickFromMappedKey > = ( TMappedResult ) // prettier-ignore export function PickFromMappedKey >(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TMappedResult { const properties = FromMappedKey(type, mappedKey, options) return MappedResult(properties) as never } sinclairzx81-typebox-e0ec98c/src/type/pick/pick-from-mapped-result.ts000066400000000000000000000075471505437577000260120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { SchemaOptions } from '../schema/index' import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Pick, type TPick } from './pick' import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties = ( { [K2 in keyof Properties]: TPick } ) // prettier-ignore function FromProperties(properties: Properties, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TFromProperties { const result = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(properties)) result[K2] = Pick(properties[K2], propertyKeys, Clone(options)) return result as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult = ( Evaluate> ) // prettier-ignore function FromMappedResult(mappedResult: MappedResult, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TFromMappedResult { return FromProperties(mappedResult.properties, propertyKeys, options) as never } // ------------------------------------------------------------------ // PickFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TPickFromMappedResult > = ( Ensure> ) // prettier-ignore export function PickFromMappedResult< MappedResult extends TMappedResult, PropertyKeys extends PropertyKey[], Properties extends TProperties = TFromMappedResult >(mappedResult: MappedResult, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TMappedResult { const properties = FromMappedResult(mappedResult, propertyKeys, options) return MappedResult(properties) as never } sinclairzx81-typebox-e0ec98c/src/type/pick/pick.ts000066400000000000000000000246231505437577000222630ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { Discard } from '../discard/discard' import type { TSchema, SchemaOptions } from '../schema/index' import type { TupleToUnion, Evaluate, Ensure } from '../helpers/index' import { type TRecursive } from '../recursive/index' import { Computed, type TComputed } from '../computed/index' import { Intersect, type TIntersect } from '../intersect/index' import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' import { Object, type TObject, type TProperties, type TPropertyKey } from '../object/index' import { Union, type TUnion } from '../union/index' import { type TMappedKey, type TMappedResult } from '../mapped/index' import { type TRef } from '../ref/index' import { IndexPropertyKeys, type TIndexPropertyKeys } from '../indexed/index' import { TransformKind } from '../symbols/symbols' // ------------------------------------------------------------------ // Guards // ------------------------------------------------------------------ import { IsMappedKey, IsMappedResult, IsIntersect, IsUnion, IsObject, IsSchema, IsLiteralValue, IsRef } from '../guard/kind' import { IsArray as IsArrayValue } from '../guard/value' // ------------------------------------------------------------------ // Infrastructure // ------------------------------------------------------------------ import { PickFromMappedKey, type TPickFromMappedKey } from './pick-from-mapped-key' import { PickFromMappedResult, type TPickFromMappedResult } from './pick-from-mapped-result' // ------------------------------------------------------------------ // FromIntersect // ------------------------------------------------------------------ // prettier-ignore type TFromIntersect = Types extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromIntersect]> : Result function FromIntersect(types: Types, propertyKeys: PropertyKeys): TFromIntersect { return types.map((type) => PickResolve(type, propertyKeys)) as never } // ------------------------------------------------------------------ // FromUnion // ------------------------------------------------------------------ // prettier-ignore type TFromUnion = Types extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromUnion]> : Result // prettier-ignore function FromUnion(types: Types, propertyKeys: PropertyKeys): TFromUnion { return types.map((type) => PickResolve(type, propertyKeys)) as never } // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties> = ( Evaluate> ) // prettier-ignore function FromProperties(properties: Properties, propertyKeys: PropertyKeys): TFromProperties { const result = {} as TProperties for(const K2 of propertyKeys) if(K2 in properties) result[K2 as TPropertyKey] = properties[K2 as keyof Properties] return result as never } // ------------------------------------------------------------------ // FromObject // ------------------------------------------------------------------ // prettier-ignore type TFromObject = Ensure )>> // prettier-ignore function FromObject(T: T, K: K): TFromObject { const options = Discard(T, [TransformKind, '$id', 'required', 'properties']) const properties = FromProperties(T['properties'], K) return Object(properties, options) as never } // ------------------------------------------------------------------ // UnionFromPropertyKeys // ------------------------------------------------------------------ // prettier-ignore type TUnionFromPropertyKeys = ( PropertyKeys extends [infer Key extends PropertyKey, ...infer Rest extends PropertyKey[]] ? Key extends TLiteralValue ? TUnionFromPropertyKeys]> : TUnionFromPropertyKeys : TUnion ) // prettier-ignore function UnionFromPropertyKeys(propertyKeys: PropertyKeys): TUnionFromPropertyKeys { const result = propertyKeys.reduce((result, key) => IsLiteralValue(key) ? [...result, Literal(key)]: result, [] as TLiteral[]) return Union(result) as never } // ------------------------------------------------------------------ // TPickResolve // ------------------------------------------------------------------ // prettier-ignore export type TPickResolve = ( Properties extends TRecursive ? TRecursive> : Properties extends TIntersect ? TIntersect> : Properties extends TUnion ? TUnion> : Properties extends TObject ? TFromObject, PropertyKeys> : TObject<{}> ) // prettier-ignore function PickResolve(properties: Properties, propertyKeys: [...PropertyKeys]): TPickResolve { return ( IsIntersect(properties) ? Intersect(FromIntersect(properties.allOf, propertyKeys)) : IsUnion(properties) ? Union(FromUnion(properties.anyOf, propertyKeys)) : IsObject(properties) ? FromObject(properties, propertyKeys) : Object({}) ) as never } // ------------------------------------------------------------------ // TPick // // This mapping logic is to overly complex because of the decision // to use PropertyKey[] as the default selector. The PropertyKey[] // did make TMapped types simpler to implement, but a non-TSchema // selector makes supporting TComputed awkward as it requires // generalization via TSchema. This type should be reimplemented // in the next major revision to support TSchema as the primary // selector. // // ------------------------------------------------------------------ // prettier-ignore (do not export this type) type TResolvePropertyKeys = Key extends TSchema ? TIndexPropertyKeys : Key // prettier-ignore (do not export this type) type TResolveTypeKey = Key extends PropertyKey[] ? TUnionFromPropertyKeys : Key // prettier-ignore export type TPick = ( Type extends TMappedResult ? TPickFromMappedResult> : Key extends TMappedKey ? TPickFromMappedKey : [IsTypeRef, IsKeyRef] extends [true, true] ? TComputed<'Pick', [Type, TResolveTypeKey]> : [IsTypeRef, IsKeyRef] extends [false, true] ? TComputed<'Pick', [Type, TResolveTypeKey]> : [IsTypeRef, IsKeyRef] extends [true, false] ? TComputed<'Pick', [Type, TResolveTypeKey]> : TPickResolve> ) /** `[Json]` Constructs a type whose keys are picked from the given type */ export function Pick(type: Type, key: readonly [...Key], options?: SchemaOptions): TPick /** `[Json]` Constructs a type whose keys are picked from the given type */ export function Pick(type: Type, key: Key, options?: SchemaOptions): TPick /** `[Json]` Constructs a type whose keys are picked from the given type */ // prettier-ignore export function Pick(type: any, key: any, options?: SchemaOptions): any { const typeKey: TSchema = IsArrayValue(key) ? UnionFromPropertyKeys(key as PropertyKey[]) : key const propertyKeys: PropertyKey[] = IsSchema(key) ? IndexPropertyKeys(key) : key const isTypeRef: boolean = IsRef(type) const isKeyRef: boolean = IsRef(key) return ( IsMappedResult(type) ? PickFromMappedResult(type, propertyKeys, options) : IsMappedKey(key) ? PickFromMappedKey(type, key, options) : (isTypeRef && isKeyRef) ? Computed('Pick', [type, typeKey], options) : (!isTypeRef && isKeyRef) ? Computed('Pick', [type, typeKey], options) : (isTypeRef && !isKeyRef) ? Computed('Pick', [type, typeKey], options) : CreateType({ ...PickResolve(type, propertyKeys), ...options }) ) as never } sinclairzx81-typebox-e0ec98c/src/type/promise/000077500000000000000000000000001505437577000215065ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/promise/index.ts000066400000000000000000000024651505437577000231740ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './promise' sinclairzx81-typebox-e0ec98c/src/type/promise/promise.ts000066400000000000000000000035511505437577000235400ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import { Kind } from '../symbols/index' export interface TPromise extends TSchema { [Kind]: 'Promise' static: Promise> type: 'Promise' item: TSchema } /** `[JavaScript]` Creates a Promise type */ export function Promise(item: T, options?: SchemaOptions): TPromise { return CreateType({ [Kind]: 'Promise', type: 'Promise', item }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/readonly-optional/000077500000000000000000000000001505437577000234705ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/readonly-optional/index.ts000066400000000000000000000024771505437577000251610ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './readonly-optional' sinclairzx81-typebox-e0ec98c/src/type/readonly-optional/readonly-optional.ts000066400000000000000000000033271505437577000275050ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 TReadonly, Readonly } from '../readonly/index' import { type TOptional, Optional } from '../optional/index' export type TReadonlyOptional = TOptional & TReadonly /** `[Json]` Creates a Readonly and Optional property */ export function ReadonlyOptional(schema: T): TReadonly> { return Readonly(Optional(schema)) as never } sinclairzx81-typebox-e0ec98c/src/type/readonly/000077500000000000000000000000001505437577000216455ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/readonly/index.ts000066400000000000000000000025441505437577000233310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './readonly-from-mapped-result' export * from './readonly' sinclairzx81-typebox-e0ec98c/src/type/readonly/readonly-from-mapped-result.ts000066400000000000000000000061441505437577000275600ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Readonly, type TReadonlyWithFlag } from './readonly' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties< P extends TProperties, F extends boolean, > = ( { [K2 in keyof P]: TReadonlyWithFlag } ) // prettier-ignore function FromProperties< P extends TProperties, F extends boolean, >(K: P, F: F): TFromProperties { const Acc = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = Readonly(K[K2], F) return Acc as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult< R extends TMappedResult, F extends boolean, > = ( TFromProperties ) // prettier-ignore function FromMappedResult< R extends TMappedResult, F extends boolean, >(R: R, F: F): TFromMappedResult { return FromProperties(R.properties, F) as never } // ------------------------------------------------------------------ // ReadonlyFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TReadonlyFromMappedResult< R extends TMappedResult, F extends boolean, P extends TProperties = TFromMappedResult > = ( TMappedResult

) // prettier-ignore export function ReadonlyFromMappedResult< R extends TMappedResult, F extends boolean, P extends TProperties = TFromMappedResult >(R: R, F: F): TMappedResult

{ const P = FromMappedResult(R, F) return MappedResult(P) as never } sinclairzx81-typebox-e0ec98c/src/type/readonly/readonly.ts000066400000000000000000000074521505437577000240420ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { Ensure } from '../helpers/index' import { ReadonlyKind } from '../symbols/index' import { Discard } from '../discard/index' import type { TMappedResult } from '../mapped/index' import { ReadonlyFromMappedResult, type TReadonlyFromMappedResult } from './readonly-from-mapped-result' import { IsMappedResult } from '../guard/kind' // ------------------------------------------------------------------ // RemoveReadonly // ------------------------------------------------------------------ type TRemoveReadonly = T extends TReadonly ? S : T function RemoveReadonly(schema: T) { return CreateType(Discard(schema, [ReadonlyKind])) } // ------------------------------------------------------------------ // AddReadonly // ------------------------------------------------------------------ type TAddReadonly = T extends TReadonly ? TReadonly : Ensure> function AddReadonly(schema: T) { return CreateType({ ...schema, [ReadonlyKind]: 'Readonly' }) } // prettier-ignore export type TReadonlyWithFlag = F extends false ? TRemoveReadonly : TAddReadonly // prettier-ignore function ReadonlyWithFlag(schema: T, F: F) { return ( F === false ? RemoveReadonly(schema) : AddReadonly(schema) ) } // ------------------------------------------------------------------ // TReadonly // ------------------------------------------------------------------ export type TReadonly = T & { [ReadonlyKind]: 'Readonly' } /** `[Json]` Creates a Readonly property */ export function Readonly(schema: T, enable: F): TReadonlyFromMappedResult /** `[Json]` Creates a Readonly property */ export function Readonly(schema: T, enable: F): TReadonlyWithFlag /** `[Json]` Creates a Readonly property */ export function Readonly(schema: T): TReadonlyFromMappedResult /** `[Json]` Creates a Readonly property */ export function Readonly(schema: T): TReadonlyWithFlag /** `[Json]` Creates a Readonly property */ export function Readonly(schema: TSchema, enable?: boolean): any { const F = enable ?? true return IsMappedResult(schema) ? ReadonlyFromMappedResult(schema, F) : ReadonlyWithFlag(schema, F) } sinclairzx81-typebox-e0ec98c/src/type/record/000077500000000000000000000000001505437577000213065ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/record/index.ts000066400000000000000000000024641505437577000227730ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './record' sinclairzx81-typebox-e0ec98c/src/type/record/record.ts000066400000000000000000000361161505437577000231430ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { Kind, Hint } from '../symbols/index' import type { TSchema } from '../schema/index' import type { Static } from '../static/index' import type { Evaluate, Ensure, Assert } from '../helpers/index' import { type TAny } from '../any/index' import { type TBoolean } from '../boolean/index' import { type TEnumRecord, type TEnum } from '../enum/index' import { type TInteger } from '../integer/index' import { type TLiteral, type TLiteralValue } from '../literal/index' import { type TNever, Never } from '../never/index' import { type TNumber, Number } from '../number/index' import { type TObject, type TProperties, type TAdditionalProperties, type ObjectOptions, Object } from '../object/index' import { type TRegExp } from '../regexp/index' import { type TString, String } from '../string/index' import { type TUnion, Union } from '../union/index' import { IsTemplateLiteralFinite, TIsTemplateLiteralFinite, type TTemplateLiteral } from '../template-literal/index' import { PatternStringExact, PatternNumberExact, PatternNeverExact } from '../patterns/index' import { IndexPropertyKeys } from '../indexed/index' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ import { IsUndefined } from '../guard/value' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsInteger, IsLiteral, IsAny, IsBoolean, IsNever, IsNumber, IsString, IsRegExp, IsTemplateLiteral, IsUnion, IsRef, IsComputed } from '../guard/kind' // ------------------------------------------------------------------ // RecordCreateFromPattern // ------------------------------------------------------------------ // prettier-ignore function RecordCreateFromPattern(pattern: string, T: TSchema, options: ObjectOptions): TRecord { return CreateType({ [Kind]: 'Record', type: 'object', patternProperties: { [pattern]: T } }, options) as never } // ------------------------------------------------------------------ // RecordCreateFromKeys // ------------------------------------------------------------------ // prettier-ignore function RecordCreateFromKeys(K: string[], T: TSchema, options: ObjectOptions): TObject { const result = {} as TProperties for(const K2 of K) result[K2] = T return Object(result, { ...options, [Hint]: 'Record' }) } // ------------------------------------------------------------------ // FromTemplateLiteralKey (Fast Inference) // ------------------------------------------------------------------ // prettier-ignore type TFromTemplateLiteralKeyInfinite = Ensure> // prettier-ignore type TFromTemplateLiteralKeyFinite> = ( Ensure>> ) // prettier-ignore type TFromTemplateLiteralKey = TIsTemplateLiteralFinite extends false ? TFromTemplateLiteralKeyInfinite : TFromTemplateLiteralKeyFinite // prettier-ignore function FromTemplateLiteralKey(K: Key, T: Type, options: ObjectOptions): TFromTemplateLiteralKey { return ( IsTemplateLiteralFinite(K) ? RecordCreateFromKeys(IndexPropertyKeys(K), T, options) : RecordCreateFromPattern(K.pattern, T, options) ) as never } // ------------------------------------------------------------------ // FromEnumKey (Special Case) // ------------------------------------------------------------------ // prettier-ignore type TFromEnumKey, Type extends TSchema> = Ensure> // ------------------------------------------------------------------ // FromUnionKey // ------------------------------------------------------------------ // prettier-ignore type TFromUnionKeyLiteralString, Type extends TSchema> = { [_ in Key['const']]: Type } // prettier-ignore type TFromUnionKeyLiteralNumber, Type extends TSchema> = { [_ in Key['const']]: Type } // prettier-ignore type TFromUnionKeyVariants = Keys extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? ( Left extends TUnion ? TFromUnionKeyVariants> : Left extends TLiteral ? TFromUnionKeyVariants> : Left extends TLiteral ? TFromUnionKeyVariants> : {}) : Result // prettier-ignore type TFromUnionKey> = ( Ensure>> ) // prettier-ignore function FromUnionKey(key: Key, type: Type, options: ObjectOptions): TFromUnionKey { return RecordCreateFromKeys(IndexPropertyKeys(Union(key)), type, options) as never } // ------------------------------------------------------------------ // FromLiteralKey // ------------------------------------------------------------------ // prettier-ignore type TFromLiteralKey = ( Ensure]: Type }>> ) // prettier-ignore function FromLiteralKey(key: Key, type: Type, options: ObjectOptions): TFromLiteralKey { return RecordCreateFromKeys([(key as string).toString()], type, options) as never } // ------------------------------------------------------------------ // TFromRegExpKey // ------------------------------------------------------------------ // prettier-ignore type TFromRegExpKey<_Key extends TRegExp, Type extends TSchema> = ( Ensure> ) // prettier-ignore function FromRegExpKey(key: Key, type: Type, options: ObjectOptions): TFromRegExpKey { return RecordCreateFromPattern(key.source, type, options) as never } // ------------------------------------------------------------------ // FromStringKey // ------------------------------------------------------------------ // prettier-ignore type TFromStringKey<_Key extends TString, Type extends TSchema> = ( Ensure> ) // prettier-ignore function FromStringKey(key: Key, type: Type, options: ObjectOptions): TFromStringKey { const pattern = IsUndefined(key.pattern) ? PatternStringExact : key.pattern return RecordCreateFromPattern(pattern, type, options) as never } // ------------------------------------------------------------------ // FromAnyKey // ------------------------------------------------------------------ // prettier-ignore type TFromAnyKey<_Key extends TAny, Type extends TSchema> = ( Ensure> ) // prettier-ignore function FromAnyKey(_: Key, type: Type, options: ObjectOptions): TFromAnyKey { return RecordCreateFromPattern(PatternStringExact, type, options) as never } // ------------------------------------------------------------------ // FromNeverKey // ------------------------------------------------------------------ // prettier-ignore type TFromNeverKey<_Key extends TNever, Type extends TSchema> = ( Ensure> ) // prettier-ignore function FromNeverKey(_key: Key, type: Type, options: ObjectOptions): TFromNeverKey { return RecordCreateFromPattern(PatternNeverExact, type, options) as never } // ------------------------------------------------------------------ // TromBooleanKey // ------------------------------------------------------------------ // prettier-ignore type TFromBooleanKey<_Key extends TBoolean, Type extends TSchema> = ( Ensure> ) // prettier-ignore function FromBooleanKey(_key: Key, type: Type, options: ObjectOptions): TFromBooleanKey { return Object({ true: type, false: type }, options) } // ------------------------------------------------------------------ // FromIntegerKey // ------------------------------------------------------------------ // prettier-ignore type TFromIntegerKey<_Key extends TSchema, Type extends TSchema> = ( Ensure> ) // prettier-ignore function FromIntegerKey(_key: Key, type: Type, options: ObjectOptions): TFromIntegerKey { return RecordCreateFromPattern(PatternNumberExact, type, options) as never } // ------------------------------------------------------------------ // FromNumberKey // ------------------------------------------------------------------ // prettier-ignore type TFromNumberKey<_Key extends TSchema, Type extends TSchema> = ( Ensure> ) // prettier-ignore function FromNumberKey(_: Key, type: Type, options: ObjectOptions): TFromNumberKey { return RecordCreateFromPattern(PatternNumberExact, type, options) as never } // ------------------------------------------------------------------ // TRecord // ------------------------------------------------------------------ // prettier-ignore type RecordStatic = ( // Note: We would return a Record here, but recursive Record types will // break when T is self recursive. We can mitigate this by using a Mapped instead. Evaluate<{ [_ in Assert, PropertyKey>]: Static }> ) // prettier-ignore export interface TRecord extends TSchema { [Kind]: 'Record' static: RecordStatic type: 'object' patternProperties: { [pattern: string]: Type } additionalProperties: TAdditionalProperties } // ------------------------------------------------------------------ // TRecordOrObject // ------------------------------------------------------------------ // prettier-ignore export type TRecordOrObject = ( Key extends TTemplateLiteral ? TFromTemplateLiteralKey : Key extends TEnum ? TFromEnumKey : // (Special: Ensure resolve Enum before Union) Key extends TUnion ? TFromUnionKey : Key extends TLiteral ? TFromLiteralKey : Key extends TBoolean ? TFromBooleanKey : Key extends TInteger ? TFromIntegerKey : Key extends TNumber ? TFromNumberKey : Key extends TRegExp ? TFromRegExpKey : Key extends TString ? TFromStringKey : Key extends TAny ? TFromAnyKey : Key extends TNever ? TFromNeverKey : TNever ) // ------------------------------------------------------------------ // TRecordOrObject // ------------------------------------------------------------------ /** `[Json]` Creates a Record type */ export function Record(key: Key, type: Type, options: ObjectOptions = {}): TRecordOrObject { // prettier-ignore return ( IsUnion(key) ? FromUnionKey(key.anyOf, type, options) : IsTemplateLiteral(key) ? FromTemplateLiteralKey(key, type, options) : IsLiteral(key) ? FromLiteralKey(key.const, type, options) : IsBoolean(key) ? FromBooleanKey(key, type, options) : IsInteger(key) ? FromIntegerKey(key, type, options) : IsNumber(key) ? FromNumberKey(key, type, options) : IsRegExp(key) ? FromRegExpKey(key, type, options) : IsString(key) ? FromStringKey(key, type, options) : IsAny(key) ? FromAnyKey(key, type, options) : IsNever(key) ? FromNeverKey(key, type, options) : Never(options) ) as never } // ------------------------------------------------------------------ // Record Utilities // ------------------------------------------------------------------ /** Gets the Records Pattern */ export function RecordPattern(record: TRecord): string { return globalThis.Object.getOwnPropertyNames(record.patternProperties)[0] } // ------------------------------------------------------------------ // RecordKey // ------------------------------------------------------------------ /** Gets the Records Key Type */ // prettier-ignore export type TRecordKey ? ( Key extends TNumber ? TNumber : Key extends TString ? TString : TString ) : TString > = Result /** Gets the Records Key Type */ // prettier-ignore export function RecordKey(type: Type): TRecordKey { const pattern = RecordPattern(type) return ( pattern === PatternStringExact ? String() : pattern === PatternNumberExact ? Number() : String({ pattern }) ) as never } // ------------------------------------------------------------------ // RecordValue // ------------------------------------------------------------------ /** Gets a Record Value Type */ // prettier-ignore export type TRecordValue ? Value : TNever ) > = Result /** Gets a Record Value Type */ // prettier-ignore export function RecordValue(type: Type): TRecordValue { return type.patternProperties[RecordPattern(type)] as never } sinclairzx81-typebox-e0ec98c/src/type/recursive/000077500000000000000000000000001505437577000220375ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/recursive/index.ts000066400000000000000000000024671505437577000235270ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './recursive' sinclairzx81-typebox-e0ec98c/src/type/recursive/recursive.ts000066400000000000000000000054611505437577000244240ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CloneType } from '../clone/type' import { CreateType } from '../create/type' import { IsUndefined } from '../guard/value' import { Kind, Hint } from '../symbols/index' import { Static } from '../static/index' // ------------------------------------------------------------------ // TThis // ------------------------------------------------------------------ export interface TThis extends TSchema { [Kind]: 'This' static: this['params'][0] $ref: string } // ------------------------------------------------------------------ // RecursiveStatic // ------------------------------------------------------------------ type RecursiveStatic = Static]> // ------------------------------------------------------------------ // TRecursive // ------------------------------------------------------------------ export interface TRecursive extends TSchema { [Hint]: 'Recursive' static: RecursiveStatic } // Auto Tracked For Recursive Types without ID's let Ordinal = 0 /** `[Json]` Creates a Recursive type */ export function Recursive(callback: (thisType: TThis) => T, options: SchemaOptions = {}): TRecursive { if (IsUndefined(options.$id)) (options as any).$id = `T${Ordinal++}` const thisType = CloneType(callback({ [Kind]: 'This', $ref: `${options.$id}` } as any)) thisType.$id = options.$id // prettier-ignore return CreateType({ [Hint]: 'Recursive', ...thisType }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/ref/000077500000000000000000000000001505437577000206045ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/ref/index.ts000066400000000000000000000024611505437577000222660ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './ref' sinclairzx81-typebox-e0ec98c/src/type/ref/ref.ts000066400000000000000000000063601505437577000217350ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeBoxError } from '../error/index' import { CreateType } from '../create/type' import { Kind } from '../symbols/index' import { TUnsafe } from '../unsafe/index' import { Static } from '../static/index' // ------------------------------------------------------------------ // TRef // ------------------------------------------------------------------ export interface TRef extends TSchema { [Kind]: 'Ref' static: unknown $ref: Ref } export type TRefUnsafe = TUnsafe> /** `[Json]` Creates a Ref type.*/ export function Ref($ref: Ref, options?: SchemaOptions): TRef /** * @deprecated `[Json]` Creates a Ref type. This signature was deprecated in 0.34.0 where Ref requires callers to pass * a `string` value for the reference (and not a schema). * * To adhere to the 0.34.0 signature, Ref implementations should be updated to the following. * * ```typescript * // pre-0.34.0 * * const T = Type.String({ $id: 'T' }) * * const R = Type.Ref(T) * ``` * should be changed to the following * * ```typescript * // post-0.34.0 * * const T = Type.String({ $id: 'T' }) * * const R = Type.Unsafe>(Type.Ref('T')) * ``` * You can also create a generic function to replicate the pre-0.34.0 signature if required * * ```typescript * const LegacyRef = (schema: T) => Type.Unsafe>(Type.Ref(schema.$id!)) * ``` */ export function Ref(type: Type, options?: SchemaOptions): TRefUnsafe /** `[Json]` Creates a Ref type. The referenced type must contain a $id */ export function Ref(...args: any[]): unknown { const [$ref, options] = typeof args[0] === 'string' ? [args[0], args[1]] : [args[0].$id, args[1]] if (typeof $ref !== 'string') throw new TypeBoxError('Ref: $ref must be a string') return CreateType({ [Kind]: 'Ref', $ref }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/regexp/000077500000000000000000000000001505437577000213225ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/regexp/index.ts000066400000000000000000000024641505437577000230070ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './regexp' sinclairzx81-typebox-e0ec98c/src/type/regexp/regexp.ts000066400000000000000000000045561505437577000231760ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { SchemaOptions } from '../schema/index' import type { TSchema } from '../schema/index' import { IsString } from '../guard/value' import { Kind } from '../symbols/index' export interface RegExpOptions extends SchemaOptions { /** The maximum length of the string */ maxLength?: number /** The minimum length of the string */ minLength?: number } export interface TRegExp extends TSchema { [Kind]: 'RegExp' static: `${string}` type: 'RegExp' source: string flags: string } /** `[JavaScript]` Creates a RegExp type */ export function RegExp(pattern: string, options?: RegExpOptions): TRegExp /** `[JavaScript]` Creates a RegExp type */ export function RegExp(regex: RegExp, options?: RegExpOptions): TRegExp /** `[JavaScript]` Creates a RegExp type */ export function RegExp(unresolved: RegExp | string, options?: RegExpOptions) { const expr = IsString(unresolved) ? new globalThis.RegExp(unresolved) : unresolved return CreateType({ [Kind]: 'RegExp', type: 'RegExp', source: expr.source, flags: expr.flags }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/registry/000077500000000000000000000000001505437577000217005ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/registry/format.ts000066400000000000000000000042551505437577000235460ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 type FormatRegistryValidationFunction = (value: string) => boolean /** A registry for user defined string formats */ const map = new Map() /** Returns the entries in this registry */ export function Entries() { return new Map(map) } /** Clears all user defined string formats */ export function Clear() { return map.clear() } /** Deletes a registered format */ export function Delete(format: string) { return map.delete(format) } /** Returns true if the user defined string format exists */ export function Has(format: string) { return map.has(format) } /** Sets a validation function for a user defined string format */ export function Set(format: string, func: FormatRegistryValidationFunction) { map.set(format, func) } /** Gets a validation function for a user defined string format */ export function Get(format: string) { return map.get(format) } sinclairzx81-typebox-e0ec98c/src/type/registry/index.ts000066400000000000000000000025551505437577000233660ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 FormatRegistry from './format' export * as TypeRegistry from './type' sinclairzx81-typebox-e0ec98c/src/type/registry/type.ts000066400000000000000000000042601505437577000232330ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 type TypeRegistryValidationFunction = (schema: TSchema, value: unknown) => boolean /** A registry for user defined types */ const map = new Map>() /** Returns the entries in this registry */ export function Entries() { return new Map(map) } /** Clears all user defined types */ export function Clear() { return map.clear() } /** Deletes a registered type */ export function Delete(kind: string) { return map.delete(kind) } /** Returns true if this registry contains this kind */ export function Has(kind: string) { return map.has(kind) } /** Sets a validation function for a user defined type */ export function Set(kind: string, func: TypeRegistryValidationFunction) { map.set(kind, func) } /** Gets a custom validation function for a user defined type */ export function Get(kind: string) { return map.get(kind) } sinclairzx81-typebox-e0ec98c/src/type/required/000077500000000000000000000000001505437577000216505ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/required/index.ts000066400000000000000000000025441505437577000233340ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './required-from-mapped-result' export * from './required' sinclairzx81-typebox-e0ec98c/src/type/required/required-from-mapped-result.ts000066400000000000000000000062101505437577000275600ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { SchemaOptions } from '../schema/index' import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Required, type TRequired } from './required' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties< P extends TProperties > = ( { [K2 in keyof P]: TRequired } ) // prettier-ignore function FromProperties< P extends TProperties >(P: P, options?: SchemaOptions): TFromProperties

{ const Acc = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Required(P[K2], options) return Acc as never } // ------------------------------------------------------------------ // FromMappedResult // ------------------------------------------------------------------ // prettier-ignore type TFromMappedResult< R extends TMappedResult > = ( Evaluate> ) // prettier-ignore function FromMappedResult< R extends TMappedResult >(R: R, options?: SchemaOptions): TFromMappedResult { return FromProperties(R.properties, options) as never } // ------------------------------------------------------------------ // TRequiredFromMappedResult // ------------------------------------------------------------------ // prettier-ignore export type TRequiredFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult > = ( Ensure> ) // prettier-ignore export function RequiredFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult >(R: R, options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(R, options) return MappedResult(P) as never } sinclairzx81-typebox-e0ec98c/src/type/required/required.ts000066400000000000000000000207731505437577000240510ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Evaluate, Ensure } from '../helpers/index' import type { TMappedResult } from '../mapped/index' import { type TReadonlyOptional } from '../readonly-optional/index' import { type TComputed, Computed } from '../computed/index' import { type TOptional } from '../optional/index' import { type TReadonly } from '../readonly/index' import { type TRecursive } from '../recursive/index' import { type TObject, type TProperties, Object } from '../object/index' import { type TIntersect, Intersect } from '../intersect/index' import { type TUnion, Union } from '../union/index' import { type TRef, Ref } from '../ref/index' import { type TBigInt } from '../bigint/index' import { type TBoolean } from '../boolean/index' import { type TInteger } from '../integer/index' import { type TLiteral } from '../literal/index' import { type TNull } from '../null/index' import { type TNumber } from '../number/index' import { type TString } from '../string/index' import { type TSymbol } from '../symbol/index' import { type TUndefined } from '../undefined/index' import { OptionalKind, TransformKind } from '../symbols/index' import { Discard } from '../discard/index' import { RequiredFromMappedResult, type TRequiredFromMappedResult } from './required-from-mapped-result' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import * as KindGuard from '../guard/kind' // ------------------------------------------------------------------ // FromComputed // ------------------------------------------------------------------ // prettier-ignore type TFromComputed = Ensure< TComputed<'Required', [TComputed]> > // prettier-ignore function FromComputed(target: Target, parameters: Parameters): TFromComputed { return Computed('Required', [Computed(target, parameters)]) as never } // ------------------------------------------------------------------ // FromRef // ------------------------------------------------------------------ // prettier-ignore type TFromRef = Ensure< TComputed<'Required', [TRef]> > // prettier-ignore function FromRef($ref: Ref): TFromRef { return Computed('Required', [Ref($ref)]) as never } // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ // prettier-ignore type TFromProperties = Evaluate<{ [K in keyof Properties]: Properties[K] extends (TReadonlyOptional) ? TReadonly : Properties[K] extends (TReadonly) ? TReadonly : Properties[K] extends (TOptional) ? S : Properties[K] }> // prettier-ignore function FromProperties(properties: Properties) { const requiredProperties = {} as TProperties for(const K of globalThis.Object.getOwnPropertyNames(properties)) requiredProperties[K] = Discard(properties[K], [OptionalKind]) as TSchema return requiredProperties as never } // ------------------------------------------------------------------ // FromObject // ------------------------------------------------------------------ // prettier-ignore type TFromObject = Ensure )>> // prettier-ignore function FromObject(type: Type): TFromObject { const options = Discard(type, [TransformKind, '$id', 'required', 'properties']) const properties = FromProperties(type['properties']) return Object(properties, options) as never } // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore type TFromRest = ( Types extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TFromRest]> : Result ) // prettier-ignore function FromRest(types: [...Types]) : TFromRest { return types.map(type => RequiredResolve(type)) as never } // ------------------------------------------------------------------ // RequiredResolve // ------------------------------------------------------------------ // prettier-ignore function RequiredResolve(type: Type): TRequired { return ( // Mappable KindGuard.IsComputed(type) ? FromComputed(type.target, type.parameters) : KindGuard.IsRef(type) ? FromRef(type.$ref) : KindGuard.IsIntersect(type) ? Intersect(FromRest(type.allOf)) : KindGuard.IsUnion(type) ? Union(FromRest(type.anyOf)) : KindGuard.IsObject(type) ? FromObject(type) : // Intrinsic KindGuard.IsBigInt(type) ? type : KindGuard.IsBoolean(type) ? type : KindGuard.IsInteger(type) ? type : KindGuard.IsLiteral(type) ? type : KindGuard.IsNull(type) ? type : KindGuard.IsNumber(type) ? type : KindGuard.IsString(type) ? type : KindGuard.IsSymbol(type) ? type : KindGuard.IsUndefined(type) ? type : // Passthrough Object({}) ) as never } // ------------------------------------------------------------------ // TRequired // ------------------------------------------------------------------ // prettier-ignore export type TRequired = ( // Mappable Type extends TRecursive ? TRecursive> : Type extends TComputed ? TFromComputed : Type extends TRef ? TFromRef : Type extends TIntersect ? TIntersect> : Type extends TUnion ? TUnion> : Type extends TObject ? TFromObject> : // Intrinsic Type extends TBigInt ? Type : Type extends TBoolean ? Type : Type extends TInteger ? Type : Type extends TLiteral ? Type : Type extends TNull ? Type : Type extends TNumber ? Type : Type extends TString ? Type : Type extends TSymbol ? Type : Type extends TUndefined ? Type : // Passthrough TObject<{}> ) /** `[Json]` Constructs a type where all properties are required */ export function Required(type: MappedResult, options?: SchemaOptions): TRequiredFromMappedResult /** `[Json]` Constructs a type where all properties are required */ export function Required(type: Type, options?: SchemaOptions): TRequired /** `[Json]` Constructs a type where all properties are required */ export function Required(type: Type, options?: SchemaOptions): never { if (KindGuard.IsMappedResult(type)) { return RequiredFromMappedResult(type, options) as never } else { // special: mapping types require overridable options return CreateType({ ...RequiredResolve(type), ...options }) as never } } sinclairzx81-typebox-e0ec98c/src/type/rest/000077500000000000000000000000001505437577000210055ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/rest/index.ts000066400000000000000000000024621505437577000224700ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './rest' sinclairzx81-typebox-e0ec98c/src/type/rest/rest.ts000066400000000000000000000051501505437577000223330ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TTuple } from '../tuple/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsIntersect, IsUnion, IsTuple } from '../guard/kind' // ------------------------------------------------------------------ // RestResolve // ------------------------------------------------------------------ // prettier-ignore type TRestResolve = T extends TIntersect ? S : T extends TUnion ? S : T extends TTuple ? S : [] // prettier-ignore function RestResolve(T: T) { return ( IsIntersect(T) ? T.allOf : IsUnion(T) ? T.anyOf : IsTuple(T) ? T.items ?? [] : [] ) as never } // ------------------------------------------------------------------ // TRest // ------------------------------------------------------------------ export type TRest = TRestResolve /** `[Json]` Extracts interior Rest elements from Tuple, Intersect and Union types */ export function Rest(T: T): TRest { return RestResolve(T) } sinclairzx81-typebox-e0ec98c/src/type/return-type/000077500000000000000000000000001505437577000223265ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/return-type/index.ts000066400000000000000000000024711505437577000240110ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './return-type' sinclairzx81-typebox-e0ec98c/src/type/return-type/return-type.ts000066400000000000000000000040431505437577000251750ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { type TSchema, type SchemaOptions } from '../schema/index' import { type TFunction } from '../function/index' import { type TNever, Never } from '../never/index' import * as KindGuard from '../guard/kind' // prettier-ignore export type TReturnType ? ReturnType : TNever > = Result /** `[JavaScript]` Extracts the ReturnType from the given Function type */ export function ReturnType(schema: Type, options?: SchemaOptions): TReturnType { return (KindGuard.IsFunction(schema) ? CreateType(schema.returns, options) : Never(options)) as never } sinclairzx81-typebox-e0ec98c/src/type/schema/000077500000000000000000000000001505437577000212705ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/schema/anyschema.ts000066400000000000000000000065471505437577000236240ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // Type: Module // ------------------------------------------------------------------ import type { TAny } 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 { TEnum } from '../enum/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 } from '../literal/index' import type { TNot } from '../not/index' import type { TNull } from '../null/index' import type { TNumber } from '../number/index' import type { TObject } from '../object/index' import type { TPromise } from '../promise/index' import type { TRecord } from '../record/index' import type { TThis } from '../recursive/index' import type { TRef } from '../ref/index' import type { TRegExp } from '../regexp/index' import type { TString } from '../string/index' import type { TSymbol } from '../symbol/index' import type { TTemplateLiteral } from '../template-literal/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 } from '../unknown/index' import type { TVoid } from '../void/index' import type { TSchema } from './schema' export type TAnySchema = | TSchema | TAny | TArray | TAsyncIterator | TBigInt | TBoolean | TConstructor | TDate | TEnum | TFunction | TInteger | TIntersect | TIterator | TLiteral | TNot | TNull | TNumber | TObject | TPromise | TRecord | TRef | TRegExp | TString | TSymbol | TTemplateLiteral | TThis | TTuple | TUndefined | TUnion | TUint8Array | TUnknown | TVoid sinclairzx81-typebox-e0ec98c/src/type/schema/index.ts000066400000000000000000000025201505437577000227460ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './anyschema' export * from './schema' sinclairzx81-typebox-e0ec98c/src/type/schema/schema.ts000066400000000000000000000040161505437577000231010ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Kind, Hint, ReadonlyKind, OptionalKind } from '../symbols/index' export interface SchemaOptions { $schema?: string /** Id for this schema */ $id?: string /** Title of this schema */ title?: string /** Description of this schema */ description?: string /** Default value for this schema */ default?: any /** Example values matching this schema */ examples?: any /** Optional annotation for readOnly */ readOnly?: boolean /** Optional annotation for writeOnly */ writeOnly?: boolean [prop: string]: any } export interface TKind { [Kind]: string } export interface TSchema extends TKind, SchemaOptions { [ReadonlyKind]?: string [OptionalKind]?: string [Hint]?: string params: unknown[] static: unknown } sinclairzx81-typebox-e0ec98c/src/type/sets/000077500000000000000000000000001505437577000210065ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/sets/index.ts000066400000000000000000000024611505437577000224700ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './set' sinclairzx81-typebox-e0ec98c/src/type/sets/set.ts000066400000000000000000000156531505437577000221630ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // SetIncludes // ------------------------------------------------------------------ // prettier-ignore export type TSetIncludes = ( T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? S extends L ? true : TSetIncludes : false ) /** Returns true if element right is in the set of left */ // prettier-ignore export function SetIncludes(T: [...T], S: S): TSetIncludes { return T.includes(S) as never } // ------------------------------------------------------------------ // SetIsSubset // ------------------------------------------------------------------ // prettier-ignore export type TSetIsSubset = ( T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? TSetIncludes extends true ? TSetIsSubset : false : true ) /** Returns true if left is a subset of right */ export function SetIsSubset(T: [...T], S: [...S]): TSetIsSubset { return T.every((L) => SetIncludes(S, L)) as never } // ------------------------------------------------------------------ // SetDistinct // ------------------------------------------------------------------ // prettier-ignore export type TSetDistinct = T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? TSetIncludes extends false ? TSetDistinct : TSetDistinct : Acc /** Returns a distinct set of elements */ export function SetDistinct(T: [...T]): TSetDistinct { return [...new Set(T)] as never } // ------------------------------------------------------------------ // SetIntersect // ------------------------------------------------------------------ // prettier-ignore export type TSetIntersect = ( T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? TSetIncludes extends true ? TSetIntersect : TSetIntersect : Acc ) /** Returns the Intersect of the given sets */ export function SetIntersect(T: [...T], S: [...S]): TSetIntersect { return T.filter((L) => S.includes(L)) as never } // ------------------------------------------------------------------ // SetUnion // ------------------------------------------------------------------ // prettier-ignore export type TSetUnion = ( [...T, ...S] ) /** Returns the Union of the given sets */ export function SetUnion(T: [...T], S: [...S]): TSetUnion { return [...T, ...S] } // ------------------------------------------------------------------ // SetComplement // ------------------------------------------------------------------ // prettier-ignore export type TSetComplement = ( T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? TSetIncludes extends true ? TSetComplement : TSetComplement : Acc ) /** Returns the Complement by omitting elements in T that are in S */ // prettier-ignore export function SetComplement(T: [...T], S: [...S]): TSetComplement { return T.filter(L => !S.includes(L)) as never } // ------------------------------------------------------------------ // SetIntersectMany // ------------------------------------------------------------------ // prettier-ignore type TSetIntersectManyResolve = ( T extends [infer L extends PropertyKey[], ...infer R extends PropertyKey[][]] ? TSetIntersectManyResolve> : Acc ) // prettier-ignore function SetIntersectManyResolve(T: [...T], Init: Acc): TSetIntersectManyResolve { return T.reduce((Acc: PropertyKey[], L: PropertyKey[]) => { return SetIntersect(Acc, L) }, Init) as never } // prettier-ignore export type TSetIntersectMany = ( T extends [infer L extends PropertyKey[]] ? L // Use left to initialize the accumulator for resolve : T extends [infer L extends PropertyKey[], ...infer R extends PropertyKey[][]] ? TSetIntersectManyResolve : [] ) // prettier-ignore export function SetIntersectMany(T: [...T]): TSetIntersectMany { return ( T.length === 1 ? T[0] // Use left to initialize the accumulator for resolve : T.length > 1 ? SetIntersectManyResolve(T.slice(1), T[0]) : [] ) as never } // ------------------------------------------------------------------ // SetUnionMany // ------------------------------------------------------------------ // prettier-ignore export type TSetUnionMany = ( T extends [infer L extends PropertyKey[], ...infer R extends PropertyKey[][]] ? TSetUnionMany> : Acc ) /** Returns the Union of multiple sets */ export function SetUnionMany(T: [...T]): TSetUnionMany { const Acc = [] as PropertyKey[] for (const L of T) Acc.push(...L) return Acc as never } sinclairzx81-typebox-e0ec98c/src/type/static/000077500000000000000000000000001505437577000213175ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/static/index.ts000066400000000000000000000024641505437577000230040ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './static' sinclairzx81-typebox-e0ec98c/src/type/static/static.ts000066400000000000000000000147251505437577000231670ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Evaluate } from '../helpers/index' import type { TOptional } from '../optional/index' import type { TReadonly } from '../readonly/index' import type { TArray } from '../array/index' import type { TAsyncIterator } from '../async-iterator/index' import type { TConstructor } from '../constructor/index' import type { TEnum } from '../enum/index' import type { TFunction } from '../function/index' import type { TIntersect } from '../intersect/index' import type { TImport } from '../module/index' import type { TIterator } from '../iterator/index' import type { TNot } from '../not/index' import type { TObject, TProperties } from '../object/index' import type { TPromise } from '../promise/index' import type { TRecursive } from '../recursive/index' import type { TRecord } from '../record/index' import type { TRef } from '../ref/index' import type { TTuple } from '../tuple/index' import type { TUnion } from '../union/index' import type { TUnsafe } from '../unsafe/index' import type { TSchema } from '../schema/index' import type { TTransform } from '../transform/index' import type { TNever } from '../never/index' // ------------------------------------------------------------------ // Import // ------------------------------------------------------------------ // prettier-ignore type TDecodeImport = ( Key extends keyof ModuleProperties ? TDecodeType extends infer Type extends TSchema ? Type extends TRef ? TDecodeImport : Type : TNever : TNever ) // ------------------------------------------------------------------ // Properties // ------------------------------------------------------------------ // prettier-ignore type TDecodeProperties = { [Key in keyof Properties]: TDecodeType } // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ // prettier-ignore type TDecodeTypes = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? TDecodeTypes]> : Result ) // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ // prettier-ignore export type TDecodeType = ( Type extends TOptional ? TOptional> : Type extends TReadonly ? TReadonly> : Type extends TTransform ? TUnsafe : Type extends TArray ? TArray> : Type extends TAsyncIterator ? TAsyncIterator> : Type extends TConstructor ? TConstructor, TDecodeType> : Type extends TEnum ? TEnum : // intercept for union. interior non decodable Type extends TFunction ? TFunction, TDecodeType> : Type extends TIntersect ? TIntersect> : Type extends TImport ? TDecodeImport : Type extends TIterator ? TIterator> : Type extends TNot ? TNot> : Type extends TObject ? TObject>> : Type extends TPromise ? TPromise> : Type extends TRecord ? TRecord> : Type extends TRecursive ? TRecursive> : Type extends TRef ? TRef : Type extends TTuple ? TTuple> : Type extends TUnion ? TUnion> : Type ) // ------------------------------------------------------------------ // Static // ------------------------------------------------------------------ export type StaticDecodeIsAny = boolean extends (Type extends TSchema ? true : false) ? true : false /** Creates an decoded static type from a TypeBox type */ // prettier-ignore export type StaticDecode extends true ? unknown : Static, Params> > = Result /** Creates an encoded static type from a TypeBox type */ export type StaticEncode> = Result /** Creates a static type from a TypeBox type */ export type Static = Result sinclairzx81-typebox-e0ec98c/src/type/string/000077500000000000000000000000001505437577000213365ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/string/index.ts000066400000000000000000000024641505437577000230230ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './string' sinclairzx81-typebox-e0ec98c/src/type/string/string.ts000066400000000000000000000054471505437577000232260ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ // TString // ------------------------------------------------------------------ export type StringFormatOption = | 'date-time' | 'time' | 'date' | 'email' | 'idn-email' | 'hostname' | 'idn-hostname' | 'ipv4' | 'ipv6' | 'uri' | 'uri-reference' | 'iri' | 'uuid' | 'iri-reference' | 'uri-template' | 'json-pointer' | 'relative-json-pointer' | 'regex' | ({} & string) // prettier-ignore export type StringContentEncodingOption = | '7bit' | '8bit' | 'binary' | 'quoted-printable' | 'base64' | ({} & string) export interface StringOptions extends SchemaOptions { /** The maximum string length */ maxLength?: number /** The minimum string length */ minLength?: number /** A regular expression pattern this string should match */ pattern?: string /** A format this string should match */ format?: StringFormatOption /** The content encoding for this string */ contentEncoding?: StringContentEncodingOption /** The content media type for this string */ contentMediaType?: string } export interface TString extends TSchema, StringOptions { [Kind]: 'String' static: string type: 'string' } /** `[Json]` Creates a String type */ export function String(options?: StringOptions): TString { return CreateType({ [Kind]: 'String', type: 'string' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/symbol/000077500000000000000000000000001505437577000213355ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/symbol/index.ts000066400000000000000000000024641505437577000230220ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './symbol' sinclairzx81-typebox-e0ec98c/src/type/symbol/symbol.ts000066400000000000000000000034061505437577000232150ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export type TSymbolValue = string | number | undefined export interface TSymbol extends TSchema, SchemaOptions { [Kind]: 'Symbol' static: symbol type: 'symbol' } /** `[JavaScript]` Creates a Symbol type */ export function Symbol(options?: SchemaOptions): TSymbol { return CreateType({ [Kind]: 'Symbol', type: 'symbol' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/symbols/000077500000000000000000000000001505437577000215205ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/symbols/index.ts000066400000000000000000000024651505437577000232060ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './symbols' sinclairzx81-typebox-e0ec98c/src/type/symbols/symbols.ts000066400000000000000000000033671505437577000235710ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ /** Symbol key applied to transform types */ export const TransformKind = Symbol.for('TypeBox.Transform') /** Symbol key applied to readonly types */ export const ReadonlyKind = Symbol.for('TypeBox.Readonly') /** Symbol key applied to optional types */ export const OptionalKind = Symbol.for('TypeBox.Optional') /** Symbol key applied to types */ export const Hint = Symbol.for('TypeBox.Hint') /** Symbol key applied to types */ export const Kind = Symbol.for('TypeBox.Kind') sinclairzx81-typebox-e0ec98c/src/type/template-literal/000077500000000000000000000000001505437577000232755ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/template-literal/finite.ts000066400000000000000000000120551505437577000251260ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TemplateLiteralParseExact } from './parse' import { TypeBoxError } from '../error/index' import type { TTemplateLiteral, TTemplateLiteralKind } from './index' import type { TUnion } from '../union/index' import type { TString } from '../string/index' import type { TBoolean } from '../boolean/index' import type { TNumber } from '../number/index' import type { TInteger } from '../integer/index' import type { TBigInt } from '../bigint/index' import type { TLiteral } from '../literal/index' import type { Expression } from './parse' // ------------------------------------------------------------------ // TemplateLiteralFiniteError // ------------------------------------------------------------------ export class TemplateLiteralFiniteError extends TypeBoxError {} // ------------------------------------------------------------------ // IsTemplateLiteralFiniteCheck // ------------------------------------------------------------------ // prettier-ignore function IsNumberExpression(expression: Expression): boolean { return ( expression.type === 'or' && expression.expr.length === 2 && expression.expr[0].type === 'const' && expression.expr[0].const === '0' && expression.expr[1].type === 'const' && expression.expr[1].const === '[1-9][0-9]*' ) } // prettier-ignore function IsBooleanExpression(expression: Expression): boolean { return ( expression.type === 'or' && expression.expr.length === 2 && expression.expr[0].type === 'const' && expression.expr[0].const === 'true' && expression.expr[1].type === 'const' && expression.expr[1].const === 'false' ) } // prettier-ignore function IsStringExpression(expression: Expression) { return expression.type === 'const' && expression.const === '.*' } // prettier-ignore type TFromTemplateLiteralKind = T extends TTemplateLiteral ? TFromTemplateLiteralKinds : T extends TUnion ? TFromTemplateLiteralKinds : T extends TString ? false : T extends TNumber ? false : T extends TInteger ? false : T extends TBigInt ? false : T extends TBoolean ? true : T extends TLiteral ? true : false // prettier-ignore type TFromTemplateLiteralKinds = T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]] ? TFromTemplateLiteralKind extends false ? false : TFromTemplateLiteralKinds : true // ------------------------------------------------------------------ // IsTemplateLiteralExpressionFinite // ------------------------------------------------------------------ // prettier-ignore export function IsTemplateLiteralExpressionFinite(expression: Expression): boolean { return ( IsNumberExpression(expression) || IsStringExpression(expression) ? false : IsBooleanExpression(expression) ? true : (expression.type === 'and') ? expression.expr.every((expr) => IsTemplateLiteralExpressionFinite(expr)) : (expression.type === 'or') ? expression.expr.every((expr) => IsTemplateLiteralExpressionFinite(expr)) : (expression.type === 'const') ? true : (() => { throw new TemplateLiteralFiniteError(`Unknown expression type`) })() ) } // ------------------------------------------------------------------ // TIsTemplateLiteralFinite // ------------------------------------------------------------------ // prettier-ignore export type TIsTemplateLiteralFinite = T extends TTemplateLiteral ? TFromTemplateLiteralKinds : false /** Returns true if this TemplateLiteral resolves to a finite set of values */ export function IsTemplateLiteralFinite(schema: T) { const expression = TemplateLiteralParseExact(schema.pattern) return IsTemplateLiteralExpressionFinite(expression) } sinclairzx81-typebox-e0ec98c/src/type/template-literal/generate.ts000066400000000000000000000156351505437577000254510ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { IsTemplateLiteralExpressionFinite, TIsTemplateLiteralFinite } from './finite' import { TemplateLiteralParseExact } from './parse' import { TypeBoxError } from '../error/index' import type { Assert } from '../helpers/index' import type { TBoolean } from '../boolean/index' import type { TTemplateLiteral, TTemplateLiteralKind } from './index' import type { TLiteral, TLiteralValue } from '../literal/index' import type { Expression, ExpressionAnd, ExpressionOr, ExpressionConst } from './parse' import type { TUnion } from '../union/index' // ------------------------------------------------------------------ // TemplateLiteralGenerateError // ------------------------------------------------------------------ export class TemplateLiteralGenerateError extends TypeBoxError {} // ------------------------------------------------------------------ // StringReducers // ------------------------------------------------------------------ // StringReduceUnary<"A", ["B", "C"]> -> ["AB", "AC"] // prettier-ignore type TStringReduceUnary = R extends [infer A extends string, ...infer B extends string[]] ? TStringReduceUnary : Acc // StringReduceBinary<['A', 'B'], ['C', 'D']> -> ["AC", "AD", "BC", "BD"] // prettier-ignore type TStringReduceBinary = L extends [infer A extends string, ...infer B extends string[]] ? TStringReduceBinary]> : Acc // StringReduceMany<[['A', 'B'], ['C', 'D'], ['E']]> -> [["ACE", "ADE", "BCE", "BDE"]] // prettier-ignore type TStringReduceMany = // consider optimizing T extends [infer L extends string[], infer R extends string[], ...infer Rest extends string[][]] ? TStringReduceMany<[TStringReduceBinary, ...Rest]> : T // Reduce<[['A', 'B'], ['C', 'D'], ['E']]> -> ["ACE", "ADE", "BCE", "BDE"] // prettier-ignore type TStringReduce> = 0 extends keyof O ? Assert : [] // ------------------------------------------------------------------ // FromTemplateLiteralUnionKinds // ------------------------------------------------------------------ // prettier-ignore type TFromTemplateLiteralUnionKinds = T extends [infer L extends TLiteral, ...infer R extends TLiteral[]] ? [`${L['const']}`, ...TFromTemplateLiteralUnionKinds] : [] // ------------------------------------------------------------------ // FromTemplateLiteralKinds // ------------------------------------------------------------------ // prettier-ignore type TFromTemplateLiteralKinds = T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]] ? ( L extends TTemplateLiteral ? TFromTemplateLiteralKinds<[...S, ...R], Acc> : L extends TLiteral ? TFromTemplateLiteralKinds : L extends TUnion ? TFromTemplateLiteralKinds]> : L extends TBoolean ? TFromTemplateLiteralKinds : Acc ) : Acc // ------------------------------------------------------------------ // TemplateLiteralExpressionGenerate // ------------------------------------------------------------------ // prettier-ignore function* GenerateReduce(buffer: string[][]): IterableIterator { if (buffer.length === 1) return yield* buffer[0] for (const left of buffer[0]) { for (const right of GenerateReduce(buffer.slice(1))) { yield `${left}${right}` } } } // prettier-ignore function* GenerateAnd(expression: ExpressionAnd): IterableIterator { return yield* GenerateReduce(expression.expr.map((expr) => [...TemplateLiteralExpressionGenerate(expr)])) } // prettier-ignore function* GenerateOr(expression: ExpressionOr): IterableIterator { for (const expr of expression.expr) yield* TemplateLiteralExpressionGenerate(expr) } // prettier-ignore function* GenerateConst(expression: ExpressionConst): IterableIterator { return yield expression.const } export function* TemplateLiteralExpressionGenerate(expression: Expression): IterableIterator { return expression.type === 'and' ? yield* GenerateAnd(expression) : expression.type === 'or' ? yield* GenerateOr(expression) : expression.type === 'const' ? yield* GenerateConst(expression) : (() => { throw new TemplateLiteralGenerateError('Unknown expression') })() } // ------------------------------------------------------------------ // TTemplateLiteralGenerate // ------------------------------------------------------------------ // prettier-ignore export type TTemplateLiteralGenerate> = F extends true ? ( T extends TTemplateLiteral ? TFromTemplateLiteralKinds extends infer R extends string[][] ? TStringReduce : [] : [] ) : [] /** Generates a tuple of strings from the given TemplateLiteral. Returns an empty tuple if infinite. */ export function TemplateLiteralGenerate(schema: T): TTemplateLiteralGenerate { const expression = TemplateLiteralParseExact(schema.pattern) // prettier-ignore return ( IsTemplateLiteralExpressionFinite(expression) ? [...TemplateLiteralExpressionGenerate(expression)] : [] ) as never } sinclairzx81-typebox-e0ec98c/src/type/template-literal/index.ts000066400000000000000000000027251505437577000247620ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './finite' export * from './generate' export * from './syntax' export * from './parse' export * from './pattern' export * from './union' export * from './template-literal' sinclairzx81-typebox-e0ec98c/src/type/template-literal/parse.ts000066400000000000000000000166621505437577000247720ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeBoxError } from '../error/index' // ------------------------------------------------------------------ // TemplateLiteralParserError // ------------------------------------------------------------------ export class TemplateLiteralParserError extends TypeBoxError {} // ------------------------------------------------------------------ // TemplateLiteralParse // ------------------------------------------------------------------ // prettier-ignore export type Expression = ExpressionAnd | ExpressionOr | ExpressionConst export type ExpressionConst = { type: 'const'; const: string } export type ExpressionAnd = { type: 'and'; expr: Expression[] } export type ExpressionOr = { type: 'or'; expr: Expression[] } // ------------------------------------------------------------------- // Unescape // // Unescape for these control characters specifically. Note that this // function is only called on non union group content, and where we // still want to allow the user to embed control characters in that // content. For review. // ------------------------------------------------------------------- // prettier-ignore function Unescape(pattern: string) { return pattern .replace(/\\\$/g, '$') .replace(/\\\*/g, '*') .replace(/\\\^/g, '^') .replace(/\\\|/g, '|') .replace(/\\\(/g, '(') .replace(/\\\)/g, ')') } // ------------------------------------------------------------------- // Control Characters // ------------------------------------------------------------------- function IsNonEscaped(pattern: string, index: number, char: string) { return pattern[index] === char && pattern.charCodeAt(index - 1) !== 92 } function IsOpenParen(pattern: string, index: number) { return IsNonEscaped(pattern, index, '(') } function IsCloseParen(pattern: string, index: number) { return IsNonEscaped(pattern, index, ')') } function IsSeparator(pattern: string, index: number) { return IsNonEscaped(pattern, index, '|') } // ------------------------------------------------------------------- // Control Groups // ------------------------------------------------------------------- function IsGroup(pattern: string) { if (!(IsOpenParen(pattern, 0) && IsCloseParen(pattern, pattern.length - 1))) return false let count = 0 for (let index = 0; index < pattern.length; index++) { if (IsOpenParen(pattern, index)) count += 1 if (IsCloseParen(pattern, index)) count -= 1 if (count === 0 && index !== pattern.length - 1) return false } return true } // prettier-ignore function InGroup(pattern: string) { return pattern.slice(1, pattern.length - 1) } // prettier-ignore function IsPrecedenceOr(pattern: string) { let count = 0 for (let index = 0; index < pattern.length; index++) { if (IsOpenParen(pattern, index)) count += 1 if (IsCloseParen(pattern, index)) count -= 1 if (IsSeparator(pattern, index) && count === 0) return true } return false } // prettier-ignore function IsPrecedenceAnd(pattern: string) { for (let index = 0; index < pattern.length; index++) { if (IsOpenParen(pattern, index)) return true } return false } // prettier-ignore function Or(pattern: string): Expression { let [count, start] = [0, 0] const expressions: Expression[] = [] for (let index = 0; index < pattern.length; index++) { if (IsOpenParen(pattern, index)) count += 1 if (IsCloseParen(pattern, index)) count -= 1 if (IsSeparator(pattern, index) && count === 0) { const range = pattern.slice(start, index) if (range.length > 0) expressions.push(TemplateLiteralParse(range)) start = index + 1 } } const range = pattern.slice(start) if (range.length > 0) expressions.push(TemplateLiteralParse(range)) if (expressions.length === 0) return { type: 'const', const: '' } if (expressions.length === 1) return expressions[0] return { type: 'or', expr: expressions } } // prettier-ignore function And(pattern: string): Expression { function Group(value: string, index: number): [number, number] { if (!IsOpenParen(value, index)) throw new TemplateLiteralParserError(`TemplateLiteralParser: Index must point to open parens`) let count = 0 for (let scan = index; scan < value.length; scan++) { if (IsOpenParen(value, scan)) count += 1 if (IsCloseParen(value, scan)) count -= 1 if (count === 0) return [index, scan] } throw new TemplateLiteralParserError(`TemplateLiteralParser: Unclosed group parens in expression`) } function Range(pattern: string, index: number): [number, number] { for (let scan = index; scan < pattern.length; scan++) { if (IsOpenParen(pattern, scan)) return [index, scan] } return [index, pattern.length] } const expressions: Expression[] = [] for (let index = 0; index < pattern.length; index++) { if (IsOpenParen(pattern, index)) { const [start, end] = Group(pattern, index) const range = pattern.slice(start, end + 1) expressions.push(TemplateLiteralParse(range)) index = end } else { const [start, end] = Range(pattern, index) const range = pattern.slice(start, end) if (range.length > 0) expressions.push(TemplateLiteralParse(range)) index = end - 1 } } return ( (expressions.length === 0) ? { type: 'const', const: '' } : (expressions.length === 1) ? expressions[0] : { type: 'and', expr: expressions } ) } // ------------------------------------------------------------------ // TemplateLiteralParse // ------------------------------------------------------------------ /** Parses a pattern and returns an expression tree */ export function TemplateLiteralParse(pattern: string): Expression { // prettier-ignore return ( IsGroup(pattern) ? TemplateLiteralParse(InGroup(pattern)) : IsPrecedenceOr(pattern) ? Or(pattern) : IsPrecedenceAnd(pattern) ? And(pattern) : { type: 'const', const: Unescape(pattern) } ) } // ------------------------------------------------------------------ // TemplateLiteralParseExact // ------------------------------------------------------------------ /** Parses a pattern and strips forward and trailing ^ and $ */ export function TemplateLiteralParseExact(pattern: string): Expression { return TemplateLiteralParse(pattern.slice(1, pattern.length - 1)) } sinclairzx81-typebox-e0ec98c/src/type/template-literal/pattern.ts000066400000000000000000000061541505437577000253300ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TTemplateLiteralKind } from './index' import { PatternNumber, PatternString, PatternBoolean } from '../patterns/index' import { Kind } from '../symbols/index' import { TypeBoxError } from '../error/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsTemplateLiteral, IsUnion, IsNumber, IsInteger, IsBigInt, IsString, IsLiteral, IsBoolean } from '../guard/kind' // ------------------------------------------------------------------ // TemplateLiteralPatternError // ------------------------------------------------------------------ export class TemplateLiteralPatternError extends TypeBoxError {} // ------------------------------------------------------------------ // TemplateLiteralPattern // ------------------------------------------------------------------ function Escape(value: string) { return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') } // prettier-ignore function Visit(schema: TSchema, acc: string): string { return ( IsTemplateLiteral(schema) ? schema.pattern.slice(1, schema.pattern.length - 1) : IsUnion(schema) ? `(${schema.anyOf.map((schema) => Visit(schema, acc)).join('|')})` : IsNumber(schema) ? `${acc}${PatternNumber}` : IsInteger(schema) ? `${acc}${PatternNumber}` : IsBigInt(schema) ? `${acc}${PatternNumber}` : IsString(schema) ? `${acc}${PatternString}` : IsLiteral(schema) ? `${acc}${Escape(schema.const.toString())}` : IsBoolean(schema) ? `${acc}${PatternBoolean}` : (() => { throw new TemplateLiteralPatternError(`Unexpected Kind '${schema[Kind]}'`) })() ) } export function TemplateLiteralPattern(kinds: TTemplateLiteralKind[]): string { return `^${kinds.map((schema) => Visit(schema, '')).join('')}\$` } sinclairzx81-typebox-e0ec98c/src/type/template-literal/syntax.ts000066400000000000000000000113741505437577000252010ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Assert, Trim } from '../helpers/index' import type { TTemplateLiteral, TTemplateLiteralKind } from './index' import { Literal, type TLiteral } from '../literal/index' import { Boolean, type TBoolean } from '../boolean/index' import { BigInt, type TBigInt } from '../bigint/index' import { Number, type TNumber } from '../number/index' import { String, type TString } from '../string/index' import { UnionEvaluated, type TUnionEvaluated } from '../union/index' import { Never } from '../never/index' // ------------------------------------------------------------------ // SyntaxParsers // ------------------------------------------------------------------ // prettier-ignore function* FromUnion(syntax: string): IterableIterator { const trim = syntax.trim().replace(/"|'/g, '') return ( trim === 'boolean' ? yield Boolean() : trim === 'number' ? yield Number() : trim === 'bigint' ? yield BigInt() : trim === 'string' ? yield String() : yield (() => { const literals = trim.split('|').map((literal) => Literal(literal.trim())) return ( literals.length === 0 ? Never() : literals.length === 1 ? literals[0] : UnionEvaluated(literals) ) })() ) } // prettier-ignore function* FromTerminal(syntax: string): IterableIterator { if (syntax[1] !== '{') { const L = Literal('$') const R = FromSyntax(syntax.slice(1)) return yield* [L, ...R] } for (let i = 2; i < syntax.length; i++) { if (syntax[i] === '}') { const L = FromUnion(syntax.slice(2, i)) const R = FromSyntax(syntax.slice(i + 1)) return yield* [...L, ...R] } } yield Literal(syntax) } // prettier-ignore function* FromSyntax(syntax: string): IterableIterator { for (let i = 0; i < syntax.length; i++) { if (syntax[i] === '$') { const L = Literal(syntax.slice(0, i)) const R = FromTerminal(syntax.slice(i)) return yield* [L, ...R] } } yield Literal(syntax) } // prettier-ignore type FromUnionLiteral = T extends `${infer L}|${infer R}` ? [TLiteral>, ...FromUnionLiteral] : T extends `${infer L}` ? [TLiteral>] : [] type FromUnion = TUnionEvaluated> // prettier-ignore type FromTerminal = T extends 'boolean' ? TBoolean : T extends 'bigint' ? TBigInt : T extends 'number' ? TNumber : T extends 'string' ? TString : FromUnion // prettier-ignore type FromString = T extends `{${infer L}}${infer R}` ? [FromTerminal, ...FromString] : // note: to correctly handle $ characters encoded in the sequence, we need to // lookahead and test against opening and closing union groups. T extends `${infer L}$\{${infer R1}\}${infer R2}` ? [TLiteral, ...FromString<`{${R1}}`>, ...FromString] : T extends `${infer L}$\{${infer R1}\}` ? [TLiteral, ...FromString<`{${R1}}`>] : T extends `${infer L}` ? [TLiteral] : [] // ------------------------------------------------------------------ // TTemplateLiteralSyntax // ------------------------------------------------------------------ // prettier-ignore export type TTemplateLiteralSyntax = ( TTemplateLiteral, TTemplateLiteralKind[]>> ) /** Parses TemplateLiteralSyntax and returns a tuple of TemplateLiteralKinds */ export function TemplateLiteralSyntax(syntax: string): TTemplateLiteralKind[] { return [...FromSyntax(syntax)] } sinclairzx81-typebox-e0ec98c/src/type/template-literal/template-literal.ts000066400000000000000000000112221505437577000271100ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Assert } from '../helpers/index' import type { TUnion } from '../union/index' import type { TLiteral } from '../literal/index' import type { TInteger } from '../integer/index' import type { TNumber } from '../number/index' import type { TBigInt } from '../bigint/index' import type { TString } from '../string/index' import type { TBoolean } from '../boolean/index' import type { TNever } from '../never/index' import type { Static } from '../static/index' import { TemplateLiteralSyntax, type TTemplateLiteralSyntax } from './syntax' import { TemplateLiteralPattern } from './pattern' import { EmptyString } from '../helpers/index' import { IsString } from '../guard/value' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ // TemplateLiteralStaticKind // ------------------------------------------------------------------ // prettier-ignore type TemplateLiteralStaticKind = T extends TUnion ? { [K in keyof U]: TemplateLiteralStatic, Acc> }[number] : T extends TTemplateLiteral ? `${Static}` : T extends TLiteral ? `${U}` : T extends TString ? `${string}` : T extends TNumber ? `${number}` : T extends TBigInt ? `${bigint}` : T extends TBoolean ? `${boolean}` : never // ------------------------------------------------------------------ // TemplateLiteralStatic // ------------------------------------------------------------------ // prettier-ignore type TemplateLiteralStatic = T extends [infer L, ...infer R] ? `${TemplateLiteralStaticKind}${TemplateLiteralStatic, Acc>}` : Acc // ------------------------------------------------------------------ // TTemplateLiteralKind // ------------------------------------------------------------------ // prettier-ignore export type TTemplateLiteralKind = | TTemplateLiteral | TUnion | TLiteral | TInteger | TNumber | TBigInt | TString | TBoolean | TNever // ------------------------------------------------------------------ // TTemplateLiteral // ------------------------------------------------------------------ // prettier-ignore export interface TTemplateLiteral extends TSchema { [Kind]: 'TemplateLiteral' static: TemplateLiteralStatic type: 'string' pattern: string // todo: it may be possible to infer this pattern } /** `[Json]` Creates a TemplateLiteral type from template dsl string */ export function TemplateLiteral(syntax: T, options?: SchemaOptions): TTemplateLiteralSyntax /** `[Json]` Creates a TemplateLiteral type */ export function TemplateLiteral(kinds: [...T], options?: SchemaOptions): TTemplateLiteral /** `[Json]` Creates a TemplateLiteral type */ // prettier-ignore export function TemplateLiteral(unresolved: TTemplateLiteralKind[] | string, options?: SchemaOptions): any { const pattern = IsString(unresolved) ? TemplateLiteralPattern(TemplateLiteralSyntax(unresolved)) : TemplateLiteralPattern(unresolved as TTemplateLiteralKind[]) return CreateType({ [Kind]: 'TemplateLiteral', type: 'string', pattern }, options) } sinclairzx81-typebox-e0ec98c/src/type/template-literal/union.ts000066400000000000000000000050141505437577000247750ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Static } from '../static/index' import type { TTemplateLiteral } from './template-literal' import type { UnionToTuple } from '../helpers/index' import { UnionEvaluated, type TUnionEvaluated } from '../union/index' import { Literal, type TLiteral } from '../literal/index' import { TemplateLiteralGenerate } from './generate' // ------------------------------------------------------------------ // TemplateLiteralToUnion // ------------------------------------------------------------------ // prettier-ignore export type TTemplateLiteralToUnionLiteralArray = ( T extends [infer L extends string, ...infer R extends string[]] ? TTemplateLiteralToUnionLiteralArray]> : Acc ) // prettier-ignore export type TTemplateLiteralToUnion< T extends TTemplateLiteral, U extends string[] = UnionToTuple> > = TUnionEvaluated> /** Returns a Union from the given TemplateLiteral */ export function TemplateLiteralToUnion(schema: TTemplateLiteral): TTemplateLiteralToUnion { const R = TemplateLiteralGenerate(schema) as string[] const L = R.map((S) => Literal(S)) return UnionEvaluated(L) } sinclairzx81-typebox-e0ec98c/src/type/transform/000077500000000000000000000000001505437577000220435ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/transform/index.ts000066400000000000000000000024671505437577000235330ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './transform' sinclairzx81-typebox-e0ec98c/src/type/transform/transform.ts000066400000000000000000000103041505437577000244240ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Static, StaticDecode } from '../static/index' import { TransformKind } from '../symbols/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsTransform } from '../guard/kind' // ------------------------------------------------------------------ // TransformBuilders // ------------------------------------------------------------------ export class TransformDecodeBuilder { constructor(private readonly schema: T) {} public Decode, U>>(decode: D): TransformEncodeBuilder { return new TransformEncodeBuilder(this.schema, decode) } } // prettier-ignore export class TransformEncodeBuilder { constructor(private readonly schema: T, private readonly decode: D) { } private EncodeTransform, StaticDecode>>(encode: E, schema: TTransform) { const Encode = (value: unknown) => schema[TransformKind as any].Encode(encode(value as any)) const Decode = (value: unknown) => this.decode(schema[TransformKind as any].Decode(value)) const Codec = { Encode: Encode, Decode: Decode } return { ...schema, [TransformKind]: Codec } } private EncodeSchema, StaticDecode>>(encode: E, schema: TSchema) { const Codec = { Decode: this.decode, Encode: encode } return { ...schema, [TransformKind]: Codec } } public Encode, StaticDecode>>(encode: E): TTransform> { return ( IsTransform(this.schema) ? this.EncodeTransform(encode, this.schema): this.EncodeSchema(encode, this.schema) ) as never } } // ------------------------------------------------------------------ // TransformStatic // ------------------------------------------------------------------ type TransformStatic = T extends TTransform ? S : Static // ------------------------------------------------------------------ // TTransform // ------------------------------------------------------------------ export type TransformFunction = (value: T) => U export interface TransformOptions { Decode: TransformFunction, O> Encode: TransformFunction> } export interface TTransform extends TSchema { static: TransformStatic [TransformKind]: TransformOptions [key: string]: any } /** `[Json]` Creates a Transform type */ export function Transform(schema: I): TransformDecodeBuilder { return new TransformDecodeBuilder(schema) } sinclairzx81-typebox-e0ec98c/src/type/tuple/000077500000000000000000000000001505437577000211615ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/tuple/index.ts000066400000000000000000000024631505437577000226450ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './tuple' sinclairzx81-typebox-e0ec98c/src/type/tuple/tuple.ts000066400000000000000000000052401505437577000226630ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ // TupleStatic // ------------------------------------------------------------------ // prettier-ignore type TupleStatic = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? TupleStatic]> : Acc // ------------------------------------------------------------------ // TTuple // ------------------------------------------------------------------ export interface TTuple extends TSchema { [Kind]: 'Tuple' static: TupleStatic type: 'array' items?: T additionalItems?: false minItems: number maxItems: number } /** `[Json]` Creates a Tuple type */ export function Tuple(types: [...Types], options?: SchemaOptions): TTuple { // prettier-ignore return CreateType( types.length > 0 ? { [Kind]: 'Tuple', type: 'array', items: types, additionalItems: false, minItems: types.length, maxItems: types.length } : { [Kind]: 'Tuple', type: 'array', minItems: types.length, maxItems: types.length }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/type/000077500000000000000000000000001505437577000210115ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/type/index.ts000066400000000000000000000036421505437577000224750ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // JsonTypeBuilder // ------------------------------------------------------------------ export { JsonTypeBuilder } from './json' // ------------------------------------------------------------------ // JavaScriptTypeBuilder // ------------------------------------------------------------------ import * as TypeBuilder from './type' import { JavaScriptTypeBuilder } from './javascript' /** JavaScript Type Builder with Static Resolution for TypeScript */ const Type = TypeBuilder as InstanceType export { JavaScriptTypeBuilder } export { Type } sinclairzx81-typebox-e0ec98c/src/type/type/javascript.ts000066400000000000000000000152451505437577000235360ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { JsonTypeBuilder } from './json' import { Argument, type TArgument } from '../argument/index' import { AsyncIterator, type TAsyncIterator } from '../async-iterator/index' import { Awaited, type TAwaited } from '../awaited/index' import { BigInt, type TBigInt, type BigIntOptions } from '../bigint/index' import { Constructor, type TConstructor } from '../constructor/index' import { ConstructorParameters, type TConstructorParameters } from '../constructor-parameters/index' import { Date, type TDate, type DateOptions } from '../date/index' import { Function as FunctionType, type TFunction } from '../function/index' import { InstanceType, type TInstanceType } from '../instance-type/index' import { Instantiate, type TInstantiate } from '../instantiate/index' import { Iterator, type TIterator } from '../iterator/index' import { Parameters, type TParameters } from '../parameters/index' import { Promise, type TPromise } from '../promise/index' import { RegExp, type TRegExp, RegExpOptions } from '../regexp/index' import { ReturnType, type TReturnType } from '../return-type/index' import { type TSchema, type SchemaOptions } from '../schema/index' import { Symbol, type TSymbol } from '../symbol/index' import { Uint8Array, type TUint8Array, type Uint8ArrayOptions } from '../uint8array/index' import { Undefined, type TUndefined } from '../undefined/index' import { Void, type TVoid } from '../void/index' /** JavaScript Type Builder with Static Resolution for TypeScript */ export class JavaScriptTypeBuilder extends JsonTypeBuilder { /** `[JavaScript]` Creates a Generic Argument Type */ public Argument(index: Index): TArgument { return Argument(index) } /** `[JavaScript]` Creates a AsyncIterator type */ public AsyncIterator(items: Type, options?: SchemaOptions): TAsyncIterator { return AsyncIterator(items, options) } /** `[JavaScript]` Constructs a type by recursively unwrapping Promise types */ public Awaited(schema: Type, options?: SchemaOptions): TAwaited { return Awaited(schema, options) } /** `[JavaScript]` Creates a BigInt type */ public BigInt(options?: BigIntOptions): TBigInt { return BigInt(options) } /** `[JavaScript]` Extracts the ConstructorParameters from the given Constructor type */ public ConstructorParameters(schema: Type, options?: SchemaOptions): TConstructorParameters { return ConstructorParameters(schema, options) } /** `[JavaScript]` Creates a Constructor type */ public Constructor(parameters: [...Parameters], instanceType: InstanceType, options?: SchemaOptions): TConstructor { return Constructor(parameters, instanceType, options) } /** `[JavaScript]` Creates a Date type */ public Date(options: DateOptions = {}): TDate { return Date(options) } /** `[JavaScript]` Creates a Function type */ public Function(parameters: [...Parameters], returnType: ReturnType, options?: SchemaOptions): TFunction { return FunctionType(parameters, returnType, options) } /** `[JavaScript]` Extracts the InstanceType from the given Constructor type */ public InstanceType(schema: Type, options?: SchemaOptions): TInstanceType { return InstanceType(schema, options) } /** `[JavaScript]` Instantiates a type with the given parameters */ public Instantiate(schema: Type, parameters: [...Parameters]): TInstantiate { return Instantiate(schema, parameters) } /** `[JavaScript]` Creates an Iterator type */ public Iterator(items: Type, options?: SchemaOptions): TIterator { return Iterator(items, options) } /** `[JavaScript]` Extracts the Parameters from the given Function type */ public Parameters(schema: Type, options?: SchemaOptions): TParameters { return Parameters(schema, options) } /** `[JavaScript]` Creates a Promise type */ public Promise(item: Type, options?: SchemaOptions): TPromise { return Promise(item, options) } /** `[JavaScript]` Creates a RegExp type */ public RegExp(pattern: string, options?: RegExpOptions): TRegExp /** `[JavaScript]` Creates a RegExp type */ public RegExp(regex: RegExp, options?: RegExpOptions): TRegExp /** `[JavaScript]` Creates a RegExp type */ public RegExp(unresolved: string | RegExp, options?: RegExpOptions) { return RegExp(unresolved as any, options) } /** `[JavaScript]` Extracts the ReturnType from the given Function type */ public ReturnType(type: Type, options?: SchemaOptions): TReturnType { return ReturnType(type, options) } /** `[JavaScript]` Creates a Symbol type */ public Symbol(options?: SchemaOptions): TSymbol { return Symbol(options) } /** `[JavaScript]` Creates a Undefined type */ public Undefined(options?: SchemaOptions): TUndefined { return Undefined(options) } /** `[JavaScript]` Creates a Uint8Array type */ public Uint8Array(options?: Uint8ArrayOptions): TUint8Array { return Uint8Array(options) } /** `[JavaScript]` Creates a Void type */ public Void(options?: SchemaOptions): TVoid { return Void(options) } } sinclairzx81-typebox-e0ec98c/src/type/type/json.ts000066400000000000000000000513321505437577000223360ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Any, type TAny } from '../any/index' import { Array, type TArray, type ArrayOptions } from '../array/index' import { Boolean, type TBoolean } from '../boolean/index' import { Composite, type TComposite } from '../composite/index' import { Const, type TConst } from '../const/index' import { Enum, type TEnum, type TEnumKey, type TEnumValue } from '../enum/index' import { Exclude, type TExclude, type TExcludeFromMappedResult, type TExcludeFromTemplateLiteral } from '../exclude/index' import { Extends, type TExtends, type TExtendsFromMappedKey, type TExtendsFromMappedResult } from '../extends/index' import { Extract, type TExtract, type TExtractFromMappedResult, type TExtractFromTemplateLiteral } from '../extract/index' import { Index, TIndex, type TIndexPropertyKeys, type TIndexFromMappedKey, type TIndexFromMappedResult, type TIndexFromComputed } from '../indexed/index' import { Integer, type IntegerOptions, type TInteger } from '../integer/index' import { Intersect, type IntersectOptions } from '../intersect/index' import { Capitalize, Uncapitalize, Lowercase, Uppercase, type TCapitalize, type TUncapitalize, type TLowercase, type TUppercase } from '../intrinsic/index' import { KeyOf, type TKeyOf } from '../keyof/index' import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' import { Mapped, type TMappedFunction, type TMapped, type TMappedResult } from '../mapped/index' import { Never, type TNever } from '../never/index' import { Not, type TNot } from '../not/index' import { Null, type TNull } from '../null/index' import { type TMappedKey } from '../mapped/index' import { Module, TModule } from '../module/index' import { Number, type TNumber, type NumberOptions } from '../number/index' import { Object, type TObject, type TProperties, type ObjectOptions } from '../object/index' import { Omit, type TOmit } from '../omit/index' import { Optional, type TOptionalWithFlag, type TOptionalFromMappedResult } from '../optional/index' import { Partial, type TPartial, type TPartialFromMappedResult } from '../partial/index' import { Pick, type TPick } from '../pick/index' import { Readonly, type TReadonlyWithFlag, type TReadonlyFromMappedResult } from '../readonly/index' import { ReadonlyOptional, type TReadonlyOptional } from '../readonly-optional/index' import { Record, type TRecordOrObject } from '../record/index' import { Recursive, type TRecursive, type TThis } from '../recursive/index' import { Ref, type TRef, type TRefUnsafe } from '../ref/index' import { Required, type TRequired, type TRequiredFromMappedResult } from '../required/index' import { Rest, type TRest } from '../rest/index' import { type TSchema, type SchemaOptions } from '../schema/index' import { String, type TString, type StringOptions } from '../string/index' import { TemplateLiteral, type TTemplateLiteral, type TTemplateLiteralKind, type TTemplateLiteralSyntax } from '../template-literal/index' import { Transform, TransformDecodeBuilder } from '../transform/index' import { Tuple, type TTuple } from '../tuple/index' import { Union } from '../union/index' import { Unknown, type TUnknown } from '../unknown/index' import { Unsafe, type TUnsafe, type UnsafeOptions } from '../unsafe/index' /** Json Type Builder with Static Resolution for TypeScript */ export class JsonTypeBuilder { // ------------------------------------------------------------------------ // Modifiers // ------------------------------------------------------------------------ /** `[Json]` Creates a Readonly and Optional property */ public ReadonlyOptional(type: Type): TReadonlyOptional { return ReadonlyOptional(type) } /** `[Json]` Creates a Readonly property */ public Readonly(type: Type, enable: Flag): TReadonlyFromMappedResult /** `[Json]` Creates a Readonly property */ public Readonly(type: Type, enable: Flag): TReadonlyWithFlag /** `[Json]` Creates a Optional property */ public Readonly(type: Type): TReadonlyFromMappedResult /** `[Json]` Creates a Readonly property */ public Readonly(type: Type): TReadonlyWithFlag /** `[Json]` Creates a Readonly property */ public Readonly(type: TSchema, enable?: boolean): any { return Readonly(type, enable ?? true) } /** `[Json]` Creates a Optional property */ public Optional(type: Type, enable: Flag): TOptionalFromMappedResult /** `[Json]` Creates a Optional property */ public Optional(type: Type, enable: Flag): TOptionalWithFlag /** `[Json]` Creates a Optional property */ public Optional(type: Type): TOptionalFromMappedResult /** `[Json]` Creates a Optional property */ public Optional(type: Type): TOptionalWithFlag /** `[Json]` Creates a Optional property */ public Optional(type: TSchema, enable?: boolean): any { return Optional(type, enable ?? true) } // ------------------------------------------------------------------------ // Types // ------------------------------------------------------------------------ /** `[Json]` Creates an Any type */ public Any(options?: SchemaOptions): TAny { return Any(options) } /** `[Json]` Creates an Array type */ public Array(items: Type, options?: ArrayOptions): TArray { return Array(items, options) } /** `[Json]` Creates a Boolean type */ public Boolean(options?: SchemaOptions): TBoolean { return Boolean(options) } /** `[Json]` Intrinsic function to Capitalize LiteralString types */ public Capitalize(schema: T, options?: SchemaOptions): TCapitalize { return Capitalize(schema, options) } /** `[Json]` Creates a Composite object type */ public Composite(schemas: [...T], options?: ObjectOptions): TComposite { return Composite(schemas, options) // (error) TS 5.4.0-dev - review TComposite implementation } /** `[JavaScript]` Creates a readonly const type from the given value. */ public Const(value: T, options?: SchemaOptions): TConst { return Const(value, options) } /** `[Json]` Creates a Enum type */ public Enum>(item: T, options?: SchemaOptions): TEnum { return Enum(item, options) } /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ public Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExcludeFromMappedResult /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ public Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExcludeFromTemplateLiteral /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ public Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExclude /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ public Exclude(unionType: TSchema, excludedMembers: TSchema, options?: SchemaOptions): any { return Exclude(unionType, excludedMembers, options) } /** `[Json]` Creates a Conditional type */ public Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtendsFromMappedResult /** `[Json]` Creates a Conditional type */ public Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtendsFromMappedKey /** `[Json]` Creates a Conditional type */ public Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtends /** `[Json]` Creates a Conditional type */ public Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions) { return Extends(L, R, T, F, options) } /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ public Extract(type: L, union: R, options?: SchemaOptions): TExtractFromMappedResult /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ public Extract(type: L, union: R, options?: SchemaOptions): TExtractFromTemplateLiteral /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ public Extract(type: L, union: R, options?: SchemaOptions): TExtract /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ public Extract(type: TSchema, union: TSchema, options?: SchemaOptions): any { return Extract(type, union, options) } /** `[Json]` Returns an Indexed property type for the given keys */ public Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ public Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ public Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ public Index(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TIndexFromMappedResult /** `[Json]` Returns an Indexed property type for the given keys */ public Index(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TIndexFromMappedKey /** `[Json]` Returns an Indexed property type for the given keys */ public Index>(T: Type, K: Key, options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ public Index(type: Type, propertyKeys: readonly [...PropertyKeys], options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ public Index(type: TSchema, key: any, options?: SchemaOptions): any { return Index(type, key, options) } /** `[Json]` Creates an Integer type */ public Integer(options?: IntegerOptions): TInteger { return Integer(options) } /** `[Json]` Creates an Intersect type */ public Intersect(types: [...Types], options?: IntersectOptions): Intersect { return Intersect(types, options) } /** `[Json]` Creates a KeyOf type */ public KeyOf(type: Type, options?: SchemaOptions): TKeyOf { return KeyOf(type, options) as never } /** `[Json]` Creates a Literal type */ public Literal(literalValue: LiteralValue, options?: SchemaOptions): TLiteral { return Literal(literalValue, options) } /** `[Json]` Intrinsic function to Lowercase LiteralString types */ public Lowercase(type: Type, options?: SchemaOptions): TLowercase { return Lowercase(type, options) } /** `[Json]` Creates a Mapped object type */ public Mapped, F extends TMappedFunction = TMappedFunction, R extends TMapped = TMapped>(key: K, map: F, options?: ObjectOptions): R /** `[Json]` Creates a Mapped object type */ public Mapped = TMappedFunction, R extends TMapped = TMapped>(key: [...K], map: F, options?: ObjectOptions): R /** `[Json]` Creates a Mapped object type */ public Mapped(key: any, map: TMappedFunction, options?: ObjectOptions): any { return Mapped(key, map, options) } /** `[Json]` Creates a Type Definition Module. */ public Module(properties: Properties): TModule { return Module(properties) } /** `[Json]` Creates a Never type */ public Never(options?: SchemaOptions): TNever { return Never(options) } /** `[Json]` Creates a Not type */ public Not(type: T, options?: SchemaOptions): TNot { return Not(type, options) } /** `[Json]` Creates a Null type */ public Null(options?: SchemaOptions): TNull { return Null(options) } /** `[Json]` Creates a Number type */ public Number(options?: NumberOptions): TNumber { return Number(options) } /** `[Json]` Creates an Object type */ public Object(properties: T, options?: ObjectOptions): TObject { return Object(properties, options) } /** `[Json]` Constructs a type whose keys are picked from the given type */ public Omit(type: Type, key: readonly [...Key], options?: SchemaOptions): TOmit /** `[Json]` Constructs a type whose keys are picked from the given type */ public Omit(type: Type, key: Key, options?: SchemaOptions): TOmit /** `[Json]` Constructs a type whose keys are omitted from the given type */ public Omit(schema: TSchema, selector: any, options?: SchemaOptions): any { return Omit(schema, selector, options) } /** `[Json]` Constructs a type where all properties are optional */ public Partial(type: MappedResult, options?: SchemaOptions): TPartialFromMappedResult /** `[Json]` Constructs a type where all properties are optional */ public Partial(type: Type, options?: SchemaOptions): TPartial /** `[Json]` Constructs a type where all properties are optional */ public Partial(type: TSchema, options?: SchemaOptions): any { return Partial(type, options) } /** `[Json]` Constructs a type whose keys are picked from the given type */ public Pick(type: Type, key: readonly [...Key], options?: SchemaOptions): TPick /** `[Json]` Constructs a type whose keys are picked from the given type */ public Pick(type: Type, key: Key, options?: SchemaOptions): TPick /** `[Json]` Constructs a type whose keys are picked from the given type */ public Pick(type: any, key: any, options?: SchemaOptions): any { return Pick(type, key, options) } /** `[Json]` Creates a Record type */ public Record(key: Key, value: Value, options?: ObjectOptions): TRecordOrObject { return Record(key, value, options) } /** `[Json]` Creates a Recursive type */ public Recursive(callback: (thisType: TThis) => T, options?: SchemaOptions): TRecursive { return Recursive(callback, options) } /** `[Json]` Creates a Ref type.*/ public Ref($ref: Ref, options?: SchemaOptions): TRef /** * @deprecated `[Json]` Creates a Ref type. This signature was deprecated in 0.34.0 where Ref requires callers to pass * a `string` value for the reference (and not a schema). * * To adhere to the 0.34.0 signature, Ref implementations should be updated to the following. * * ```typescript * // pre-0.34.0 * * const T = Type.String({ $id: 'T' }) * * const R = Type.Ref(T) * ``` * should be changed to the following * * ```typescript * // post-0.34.0 * * const T = Type.String({ $id: 'T' }) * * const R = Type.Unsafe>(Type.Ref('T')) * ``` * You can also create a generic function to replicate the pre-0.34.0 signature if required * * ```typescript * const LegacyRef = (schema: T) => Type.Unsafe>(Type.Ref(schema.$id!)) * ``` */ public Ref(type: Type, options?: SchemaOptions): TRefUnsafe /** `[Json]` Creates a Ref type. The referenced type must contain a $id */ public Ref(...args: any[]): unknown { return Ref(args[0] as string, args[1]) } /** `[Json]` Constructs a type where all properties are required */ public Required(type: MappedResult, options?: SchemaOptions): TRequiredFromMappedResult /** `[Json]` Constructs a type where all properties are required */ public Required(type: Type, options?: SchemaOptions): TRequired /** `[Json]` Constructs a type where all properties are required */ public Required(type: TSchema, options?: SchemaOptions): any { return Required(type, options) } /** `[Json]` Extracts interior Rest elements from Tuple, Intersect and Union types */ public Rest(type: Type): TRest { return Rest(type) } /** `[Json]` Creates a String type */ public String(options?: StringOptions): TString { return String(options) } /** `[Json]` Creates a TemplateLiteral type from template dsl string */ public TemplateLiteral(syntax: Syntax, options?: SchemaOptions): TTemplateLiteralSyntax /** `[Json]` Creates a TemplateLiteral type */ public TemplateLiteral(kinds: [...Kinds], options?: SchemaOptions): TTemplateLiteral /** `[Json]` Creates a TemplateLiteral type */ public TemplateLiteral(unresolved: TTemplateLiteralKind[] | string, options?: SchemaOptions) { return TemplateLiteral(unresolved as any, options) } /** `[Json]` Creates a Transform type */ public Transform(type: Type): TransformDecodeBuilder { return Transform(type) } /** `[Json]` Creates a Tuple type */ public Tuple(types: [...Types], options?: SchemaOptions): TTuple { return Tuple(types, options) } /** `[Json]` Intrinsic function to Uncapitalize LiteralString types */ public Uncapitalize(type: Type, options?: SchemaOptions): TUncapitalize { return Uncapitalize(type, options) } /** `[Json]` Creates a Union type */ public Union(types: [...Types], options?: SchemaOptions): Union { return Union(types, options) } /** `[Json]` Creates an Unknown type */ public Unknown(options?: SchemaOptions): TUnknown { return Unknown(options) } /** `[Json]` Creates a Unsafe type that will infers as the generic argument T */ public Unsafe(options?: UnsafeOptions): TUnsafe { return Unsafe(options) } /** `[Json]` Intrinsic function to Uppercase LiteralString types */ public Uppercase(schema: T, options?: SchemaOptions): TUppercase { return Uppercase(schema, options) } } sinclairzx81-typebox-e0ec98c/src/type/type/type.ts000066400000000000000000000077651505437577000223610ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // Type: Module // ------------------------------------------------------------------ export { Any } from '../any/index' export { Argument } from '../argument/index' export { Array } from '../array/index' export { AsyncIterator } from '../async-iterator/index' export { Awaited } from '../awaited/index' export { BigInt } from '../bigint/index' export { Boolean } from '../boolean/index' export { Composite } from '../composite/index' export { Const } from '../const/index' export { Constructor } from '../constructor/index' export { ConstructorParameters } from '../constructor-parameters/index' export { Date } from '../date/index' export { Enum } from '../enum/index' export { Exclude } from '../exclude/index' export { Extends } from '../extends/index' export { Extract } from '../extract/index' export { Function } from '../function/index' export { Index } from '../indexed/index' export { InstanceType } from '../instance-type/index' export { Instantiate } from '../instantiate/index' export { Integer } from '../integer/index' export { Intersect } from '../intersect/index' export { Capitalize, Uncapitalize, Lowercase, Uppercase } from '../intrinsic/index' export { Iterator } from '../iterator/index' export { KeyOf } from '../keyof/index' export { Literal } from '../literal/index' export { Mapped } from '../mapped/index' export { Module } from '../module/index' export { Never } from '../never/index' export { Not } from '../not/index' export { Null } from '../null/index' export { Number } from '../number/index' export { Object } from '../object/index' export { Omit } from '../omit/index' export { Optional } from '../optional/index' export { Parameters } from '../parameters/index' export { Partial } from '../partial/index' export { Pick } from '../pick/index' export { Promise } from '../promise/index' export { Readonly } from '../readonly/index' export { ReadonlyOptional } from '../readonly-optional/index' export { Record } from '../record/index' export { Recursive } from '../recursive/index' export { Ref } from '../ref/index' export { RegExp } from '../regexp/index' export { Required } from '../required/index' export { Rest } from '../rest/index' export { ReturnType } from '../return-type/index' export { String } from '../string/index' export { Symbol } from '../symbol/index' export { TemplateLiteral } from '../template-literal/index' export { Transform } from '../transform/index' export { Tuple } from '../tuple/index' export { Uint8Array } from '../uint8array/index' export { Undefined } from '../undefined/index' export { Union } from '../union/index' export { Unknown } from '../unknown/index' export { Unsafe } from '../unsafe/index' export { Void } from '../void/index' sinclairzx81-typebox-e0ec98c/src/type/uint8array/000077500000000000000000000000001505437577000221365ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/uint8array/index.ts000066400000000000000000000024701505437577000236200ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './uint8array' sinclairzx81-typebox-e0ec98c/src/type/uint8array/uint8array.ts000066400000000000000000000035571505437577000246260ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface Uint8ArrayOptions extends SchemaOptions { maxByteLength?: number minByteLength?: number } export interface TUint8Array extends TSchema, Uint8ArrayOptions { [Kind]: 'Uint8Array' static: Uint8Array type: 'uint8array' } /** `[JavaScript]` Creates a Uint8Array type */ export function Uint8Array(options?: Uint8ArrayOptions): TUint8Array { return CreateType({ [Kind]: 'Uint8Array', type: 'Uint8Array' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/undefined/000077500000000000000000000000001505437577000217715ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/undefined/index.ts000066400000000000000000000024671505437577000234610ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './undefined' sinclairzx81-typebox-e0ec98c/src/type/undefined/undefined.ts000066400000000000000000000033401505437577000243020ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface TUndefined extends TSchema { [Kind]: 'Undefined' static: undefined type: 'undefined' } /** `[JavaScript]` Creates a Undefined type */ export function Undefined(options?: SchemaOptions): TUndefined { return CreateType({ [Kind]: 'Undefined', type: 'undefined' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/union/000077500000000000000000000000001505437577000211605ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/union/index.ts000066400000000000000000000025621505437577000226440ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './union-evaluated' export * from './union-type' export * from './union' sinclairzx81-typebox-e0ec98c/src/type/union/union-create.ts000066400000000000000000000031751505437577000241270ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import { TUnion } from './union-type' import { Kind } from '../symbols/index' export function UnionCreate(T: [...T], options?: SchemaOptions): TUnion { return CreateType({ [Kind]: 'Union', anyOf: T }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/union/union-evaluated.ts000066400000000000000000000124011505437577000246260ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { SchemaOptions, TSchema } from '../schema/index' import { OptionalKind } from '../symbols/index' import { Discard } from '../discard/index' import { Never, type TNever } from '../never/index' import { Optional, type TOptional } from '../optional/index' import type { TReadonly } from '../readonly/index' import type { TUnion } from './union-type' import { UnionCreate } from './union-create' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsOptional } from '../guard/kind' // ------------------------------------------------------------------ // IsUnionOptional // ------------------------------------------------------------------ // prettier-ignore type TIsUnionOptional = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? Left extends TOptional ? true : TIsUnionOptional : false ) // prettier-ignore function IsUnionOptional(types: Types): TIsUnionOptional { return types.some(type => IsOptional(type)) as never } // ------------------------------------------------------------------ // RemoveOptionalFromRest // ------------------------------------------------------------------ // prettier-ignore type TRemoveOptionalFromRest = ( Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] ? Left extends TOptional ? TRemoveOptionalFromRest]> : TRemoveOptionalFromRest : Result ) // prettier-ignore function RemoveOptionalFromRest(types: Types): TRemoveOptionalFromRest { return types.map(left => IsOptional(left) ? RemoveOptionalFromType(left) : left) as never } // ------------------------------------------------------------------ // RemoveOptionalFromType // ------------------------------------------------------------------ // prettier-ignore type TRemoveOptionalFromType = ( Type extends TReadonly ? TReadonly> : Type extends TOptional ? TRemoveOptionalFromType : Type ) // prettier-ignore function RemoveOptionalFromType(T: Type): TRemoveOptionalFromType { return ( Discard(T, [OptionalKind]) ) as never } // ------------------------------------------------------------------ // ResolveUnion // ------------------------------------------------------------------ // prettier-ignore type TResolveUnion, IsOptional extends boolean = TIsUnionOptional > = ( IsOptional extends true ? TOptional> : TUnion ) // prettier-ignore function ResolveUnion(types: Types, options?: SchemaOptions): TResolveUnion { const isOptional = IsUnionOptional(types) return ( isOptional ? Optional(UnionCreate(RemoveOptionalFromRest(types) as TSchema[], options)) : UnionCreate(RemoveOptionalFromRest(types) as TSchema[], options) ) as never } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore export type TUnionEvaluated = ( Types extends [TSchema] ? Types[0] : Types extends [] ? TNever : TResolveUnion ) /** `[Json]` Creates an evaluated Union type */ export function UnionEvaluated>(T: [...Types], options?: SchemaOptions): Result { // prettier-ignore return ( T.length === 1 ? CreateType(T[0], options) : T.length === 0 ? Never(options) : ResolveUnion(T, options) ) as never } sinclairzx81-typebox-e0ec98c/src/type/union/union-type.ts000066400000000000000000000040041505437577000236350ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Static } from '../static/index' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ // UnionStatic // ------------------------------------------------------------------ // prettier-ignore type UnionStatic = { [K in keyof T]: T[K] extends TSchema ? Static : never }[number] // ------------------------------------------------------------------ // TUnion // ------------------------------------------------------------------ export interface TUnion extends TSchema { [Kind]: 'Union' static: UnionStatic anyOf: T } sinclairzx81-typebox-e0ec98c/src/type/union/union.ts000066400000000000000000000037401505437577000226640ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 TNever, Never } from '../never/index' import type { TUnion } from './union-type' import { CreateType } from '../create/type' import { UnionCreate } from './union-create' // prettier-ignore export type Union = ( T extends [] ? TNever : T extends [TSchema] ? T[0] : TUnion ) /** `[Json]` Creates a Union type */ export function Union(types: [...Types], options?: SchemaOptions): Union { // prettier-ignore return ( types.length === 0 ? Never(options) : types.length === 1 ? CreateType(types[0], options) : UnionCreate(types, options) ) as Union } sinclairzx81-typebox-e0ec98c/src/type/unknown/000077500000000000000000000000001505437577000215275ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/unknown/index.ts000066400000000000000000000024651505437577000232150ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './unknown' sinclairzx81-typebox-e0ec98c/src/type/unknown/unknown.ts000066400000000000000000000032461505437577000236030ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface TUnknown extends TSchema { [Kind]: 'Unknown' static: unknown } /** `[Json]` Creates an Unknown type */ export function Unknown(options?: SchemaOptions): TUnknown { return CreateType({ [Kind]: 'Unknown' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/unsafe/000077500000000000000000000000001505437577000213115ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/unsafe/index.ts000066400000000000000000000024641505437577000227760ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './unsafe' sinclairzx81-typebox-e0ec98c/src/type/unsafe/unsafe.ts000066400000000000000000000034531505437577000231470ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface UnsafeOptions extends SchemaOptions { [Kind]?: string } export interface TUnsafe extends TSchema { [Kind]: string static: T } /** `[Json]` Creates a Unsafe type that will infers as the generic argument T */ export function Unsafe(options: UnsafeOptions = {}): TUnsafe { return CreateType({ [Kind]: options[Kind] ?? 'Unsafe' }, options) as never } sinclairzx81-typebox-e0ec98c/src/type/void/000077500000000000000000000000001505437577000207715ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/type/void/index.ts000066400000000000000000000024621505437577000224540ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './void' sinclairzx81-typebox-e0ec98c/src/type/void/void.ts000066400000000000000000000032631505437577000223060ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/type The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' export interface TVoid extends TSchema { [Kind]: 'Void' static: void type: 'void' } /** `[JavaScript]` Creates a Void type */ export function Void(options?: SchemaOptions): TVoid { return CreateType({ [Kind]: 'Void', type: 'void' }, options) as never } sinclairzx81-typebox-e0ec98c/src/value/000077500000000000000000000000001505437577000201635ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/assert/000077500000000000000000000000001505437577000214645ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/assert/assert.ts000066400000000000000000000065751505437577000233520ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Errors, ValueErrorIterator, ValueError } from '../../errors/index' import { TypeBoxError } from '../../type/error/error' import { TSchema } from '../../type/schema/index' import { Static } from '../../type/static/index' import { Check } from '../check/check' // ------------------------------------------------------------------ // AssertError // ------------------------------------------------------------------ export class AssertError extends TypeBoxError { readonly #iterator: ValueErrorIterator error: ValueError | undefined constructor(iterator: ValueErrorIterator) { const error = iterator.First() super(error === undefined ? 'Invalid Value' : error.message) this.#iterator = iterator this.error = error } /** Returns an iterator for each error in this value. */ public Errors(): ValueErrorIterator { return new ValueErrorIterator(this.#Iterator()) } *#Iterator(): IterableIterator { if (this.error) yield this.error yield* this.#iterator } } // ------------------------------------------------------------------ // AssertValue // ------------------------------------------------------------------ function AssertValue(schema: TSchema, references: TSchema[], value: unknown): unknown { if (Check(schema, references, value)) return throw new AssertError(Errors(schema, references, value)) } // ------------------------------------------------------------------ // Assert // ------------------------------------------------------------------ /** Asserts a value matches the given type or throws an `AssertError` if invalid */ export function Assert(schema: T, references: TSchema[], value: unknown): asserts value is Static /** Asserts a value matches the given type or throws an `AssertError` if invalid */ export function Assert(schema: T, value: unknown): asserts value is Static /** Asserts a value matches the given type or throws an `AssertError` if invalid */ export function Assert(...args: any[]): unknown { return args.length === 3 ? AssertValue(args[0], args[1], args[2]) : AssertValue(args[0], [], args[1]) } sinclairzx81-typebox-e0ec98c/src/value/assert/index.ts000066400000000000000000000024651505437577000231520ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './assert' sinclairzx81-typebox-e0ec98c/src/value/cast/000077500000000000000000000000001505437577000211155ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/cast/cast.ts000066400000000000000000000314601505437577000224230ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, IsString, IsNumber, IsNull } from '../guard/index' import { TypeBoxError } from '../../type/error/index' import { Kind } from '../../type/symbols/index' import { Create } from '../create/index' import { Check } from '../check/index' import { Clone } from '../clone/index' import { Deref, Pushref } from '../deref/index' import type { TSchema } from '../../type/schema/index' import type { Static } from '../../type/static/index' import type { TArray } from '../../type/array/index' import type { TConstructor } from '../../type/constructor/index' import type { TImport } from '../../type/module/index' import type { TIntersect } from '../../type/intersect/index' import type { TObject } from '../../type/object/index' import type { TRecord } from '../../type/record/index' import type { TRef } from '../../type/ref/index' import type { TThis } from '../../type/recursive/index' import type { TTuple } from '../../type/tuple/index' import type { TUnion } from '../../type/union/index' import type { TNever } from '../../type/never/index' // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class ValueCastError extends TypeBoxError { constructor(public readonly schema: TSchema, message: string) { super(message) } } // ------------------------------------------------------------------ // The following logic assigns a score to a schema based on how well // it matches a given value. For object types, the score is calculated // by evaluating each property of the value against the schema's // properties. To avoid bias towards objects with many properties, // each property contributes equally to the total score. Properties // that exactly match literal values receive the highest possible // score, as literals are often used as discriminators in union types. // ------------------------------------------------------------------ function ScoreUnion(schema: TSchema, references: TSchema[], value: any): number { if (schema[Kind] === 'Object' && typeof value === 'object' && !IsNull(value)) { const object = schema as TObject const keys = Object.getOwnPropertyNames(value) const entries = Object.entries(object.properties) return entries.reduce((acc, [key, schema]) => { const literal = schema[Kind] === 'Literal' && schema.const === value[key] ? 100 : 0 const checks = Check(schema, references, value[key]) ? 10 : 0 const exists = keys.includes(key) ? 1 : 0 return acc + (literal + checks + exists) }, 0) } else if (schema[Kind] === 'Union') { const schemas = schema.anyOf.map((schema: TSchema) => Deref(schema, references)) const scores = schemas.map((schema: TSchema) => ScoreUnion(schema, references, value)) return Math.max(...scores) } else { return Check(schema, references, value) ? 1 : 0 } } function SelectUnion(union: TUnion, references: TSchema[], value: any): TSchema { const schemas = union.anyOf.map((schema) => Deref(schema, references)) let [select, best] = [schemas[0], 0] for (const schema of schemas) { const score = ScoreUnion(schema, references, value) if (score > best) { select = schema best = score } } return select } function CastUnion(union: TUnion, references: TSchema[], value: any) { if ('default' in union) { return typeof value === 'function' ? union.default : Clone(union.default) } else { const schema = SelectUnion(union, references, value) return Cast(schema, references, value) } } // ------------------------------------------------------------------ // Default // ------------------------------------------------------------------ function DefaultClone(schema: TSchema, references: TSchema[], value: any): any { return Check(schema, references, value) ? Clone(value) : Create(schema, references) } function Default(schema: TSchema, references: TSchema[], value: any): any { return Check(schema, references, value) ? value : Create(schema, references) } // ------------------------------------------------------------------ // Cast // ------------------------------------------------------------------ function FromArray(schema: TArray, references: TSchema[], value: any): any { if (Check(schema, references, value)) return Clone(value) const created = IsArray(value) ? Clone(value) : Create(schema, references) const minimum = IsNumber(schema.minItems) && created.length < schema.minItems ? [...created, ...Array.from({ length: schema.minItems - created.length }, () => null)] : created const maximum = IsNumber(schema.maxItems) && minimum.length > schema.maxItems ? minimum.slice(0, schema.maxItems) : minimum const casted = maximum.map((value: unknown) => Visit(schema.items, references, value)) if (schema.uniqueItems !== true) return casted const unique = [...new Set(casted)] if (!Check(schema, references, unique)) throw new ValueCastError(schema, 'Array cast produced invalid data due to uniqueItems constraint') return unique } function FromConstructor(schema: TConstructor, references: TSchema[], value: any): any { if (Check(schema, references, value)) return Create(schema, references) const required = new Set(schema.returns.required || []) const result = function () {} for (const [key, property] of Object.entries(schema.returns.properties)) { if (!required.has(key) && value.prototype[key] === undefined) continue result.prototype[key] = Visit(property as TSchema, references, value.prototype[key]) } return result } function FromImport(schema: TImport, references: TSchema[], value: unknown): boolean { const definitions = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema return Visit(target, [...references, ...definitions], value) } // ------------------------------------------------------------------ // Intersect // ------------------------------------------------------------------ function IntersectAssign(correct: unknown, value: unknown): unknown { // trust correct on mismatch | value on non-object if ((IsObject(correct) && !IsObject(value)) || (!IsObject(correct) && IsObject(value))) return correct if (!IsObject(correct) || !IsObject(value)) return value return globalThis.Object.getOwnPropertyNames(correct).reduce((result, key) => { const property = key in value ? IntersectAssign(correct[key], value[key]) : correct[key] return { ...result, [key]: property } }, {}) } function FromIntersect(schema: TIntersect, references: TSchema[], value: any): any { if (Check(schema, references, value)) return value const correct = Create(schema, references) const assigned = IntersectAssign(correct, value) return Check(schema, references, assigned) ? assigned : correct } function FromNever(schema: TNever, references: TSchema[], value: any): any { throw new ValueCastError(schema, 'Never types cannot be cast') } function FromObject(schema: TObject, references: TSchema[], value: any): any { if (Check(schema, references, value)) return value if (value === null || typeof value !== 'object') return Create(schema, references) const required = new Set(schema.required || []) const result = {} as Record for (const [key, property] of Object.entries(schema.properties)) { if (!required.has(key) && value[key] === undefined) continue result[key] = Visit(property, references, value[key]) } // additional schema properties if (typeof schema.additionalProperties === 'object') { const propertyNames = Object.getOwnPropertyNames(schema.properties) for (const propertyName of Object.getOwnPropertyNames(value)) { if (propertyNames.includes(propertyName)) continue result[propertyName] = Visit(schema.additionalProperties, references, value[propertyName]) } } return result } function FromRecord(schema: TRecord, references: TSchema[], value: any): any { if (Check(schema, references, value)) return Clone(value) if (value === null || typeof value !== 'object' || Array.isArray(value) || value instanceof Date) return Create(schema, references) const subschemaPropertyName = Object.getOwnPropertyNames(schema.patternProperties)[0] const subschema = schema.patternProperties[subschemaPropertyName] const result = {} as Record for (const [propKey, propValue] of Object.entries(value)) { result[propKey] = Visit(subschema, references, propValue) } return result } function FromRef(schema: TRef, references: TSchema[], value: any): any { return Visit(Deref(schema, references), references, value) } function FromThis(schema: TThis, references: TSchema[], value: any): any { return Visit(Deref(schema, references), references, value) } function FromTuple(schema: TTuple, references: TSchema[], value: any): any { if (Check(schema, references, value)) return Clone(value) if (!IsArray(value)) return Create(schema, references) if (schema.items === undefined) return [] return schema.items.map((schema, index) => Visit(schema, references, value[index])) } function FromUnion(schema: TUnion, references: TSchema[], value: any): any { return Check(schema, references, value) ? Clone(value) : CastUnion(schema, references, value) } function Visit(schema: TSchema, references: TSchema[], value: any): any { const references_ = IsString(schema.$id) ? Pushref(schema, references) : references const schema_ = schema as any switch (schema[Kind]) { // -------------------------------------------------------------- // Structural // -------------------------------------------------------------- case 'Array': return FromArray(schema_, references_, value) case 'Constructor': return FromConstructor(schema_, references_, value) case 'Import': return FromImport(schema_, references_, value) case 'Intersect': return FromIntersect(schema_, references_, value) case 'Never': return FromNever(schema_, references_, value) case 'Object': return FromObject(schema_, references_, value) case 'Record': return FromRecord(schema_, references_, value) case 'Ref': return FromRef(schema_, references_, value) case 'This': return FromThis(schema_, references_, value) case 'Tuple': return FromTuple(schema_, references_, value) case 'Union': return FromUnion(schema_, references_, value) // -------------------------------------------------------------- // DefaultClone // -------------------------------------------------------------- case 'Date': case 'Symbol': case 'Uint8Array': return DefaultClone(schema, references, value) // -------------------------------------------------------------- // Default // -------------------------------------------------------------- default: return Default(schema_, references_, value) } } // ------------------------------------------------------------------ // Cast // ------------------------------------------------------------------ /** Casts a value into a given type and references. The return value will retain as much information of the original value as possible. */ export function Cast(schema: T, references: TSchema[], value: unknown): Static /** Casts a value into a given type. The return value will retain as much information of the original value as possible. */ export function Cast(schema: T, value: unknown): Static /** Casts a value into a given type. The return value will retain as much information of the original value as possible. */ export function Cast(...args: any[]) { return args.length === 3 ? Visit(args[0], args[1], args[2]) : Visit(args[0], [], args[1]) } sinclairzx81-typebox-e0ec98c/src/value/cast/index.ts000066400000000000000000000024631505437577000226010ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './cast' sinclairzx81-typebox-e0ec98c/src/value/check/000077500000000000000000000000001505437577000212405ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/check/check.ts000066400000000000000000000514271505437577000226760ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeSystemPolicy } from '../../system/index' import { Deref, Pushref } from '../deref/index' import { Hash } from '../hash/index' import { Kind } from '../../type/symbols/index' import { KeyOfPattern } from '../../type/keyof/index' import { ExtendsUndefinedCheck } from '../../type/extends/index' import { TypeRegistry, FormatRegistry } from '../../type/registry/index' import { TypeBoxError } from '../../type/error/index' import type { TSchema } from '../../type/schema/index' import type { TAny } from '../../type/any/index' import type { TArgument } from '../../type/argument/index' import type { TArray } from '../../type/array/index' import type { TAsyncIterator } from '../../type/async-iterator/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 type { TImport } from '../../type/module/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 } 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, IsUint8Array, IsDate, IsPromise, IsFunction, IsAsyncIterator, IsIterator, IsBoolean, IsNumber, IsBigInt, IsString, IsSymbol, IsInteger, IsNull, IsUndefined } from '../guard/index' // ------------------------------------------------------------------ // KindGuard // ------------------------------------------------------------------ import { IsSchema } from '../../type/guard/kind' // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class ValueCheckUnknownTypeError extends TypeBoxError { constructor(public readonly schema: TSchema) { super(`Unknown type`) } } // ------------------------------------------------------------------ // TypeGuards // ------------------------------------------------------------------ function IsAnyOrUnknown(schema: TSchema) { return schema[Kind] === 'Any' || schema[Kind] === 'Unknown' } // ------------------------------------------------------------------ // Guards // ------------------------------------------------------------------ function IsDefined(value: unknown): value is T { return value !== undefined } // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ function FromAny(schema: TAny, references: TSchema[], value: any): boolean { return true } function FromArgument(schema: TArgument, references: TSchema[], value: any): boolean { return true } function FromArray(schema: TArray, references: TSchema[], value: any): boolean { if (!IsArray(value)) return false if (IsDefined(schema.minItems) && !(value.length >= schema.minItems)) { return false } if (IsDefined(schema.maxItems) && !(value.length <= schema.maxItems)) { return false } if (!value.every((value) => Visit(schema.items, references, value))) { return false } // prettier-ignore if (schema.uniqueItems === true && !((function() { const set = new Set(); for(const element of value) { const hashed = Hash(element); if(set.has(hashed)) { return false } else { set.add(hashed) } } return true })())) { return false } // contains if (!(IsDefined(schema.contains) || IsNumber(schema.minContains) || IsNumber(schema.maxContains))) { return true // exit } const containsSchema = IsDefined(schema.contains) ? schema.contains : Never() const containsCount = value.reduce((acc: number, value) => (Visit(containsSchema, references, value) ? acc + 1 : acc), 0) if (containsCount === 0) { return false } if (IsNumber(schema.minContains) && containsCount < schema.minContains) { return false } if (IsNumber(schema.maxContains) && containsCount > schema.maxContains) { return false } return true } function FromAsyncIterator(schema: TAsyncIterator, references: TSchema[], value: any): boolean { return IsAsyncIterator(value) } function FromBigInt(schema: TBigInt, references: TSchema[], value: any): boolean { if (!IsBigInt(value)) return false if (IsDefined(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) { return false } if (IsDefined(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) { return false } if (IsDefined(schema.maximum) && !(value <= schema.maximum)) { return false } if (IsDefined(schema.minimum) && !(value >= schema.minimum)) { return false } if (IsDefined(schema.multipleOf) && !(value % schema.multipleOf === BigInt(0))) { return false } return true } function FromBoolean(schema: TBoolean, references: TSchema[], value: any): boolean { return IsBoolean(value) } function FromConstructor(schema: TConstructor, references: TSchema[], value: any): boolean { return Visit(schema.returns, references, value.prototype) } function FromDate(schema: TDate, references: TSchema[], value: any): boolean { if (!IsDate(value)) return false if (IsDefined(schema.exclusiveMaximumTimestamp) && !(value.getTime() < schema.exclusiveMaximumTimestamp)) { return false } if (IsDefined(schema.exclusiveMinimumTimestamp) && !(value.getTime() > schema.exclusiveMinimumTimestamp)) { return false } if (IsDefined(schema.maximumTimestamp) && !(value.getTime() <= schema.maximumTimestamp)) { return false } if (IsDefined(schema.minimumTimestamp) && !(value.getTime() >= schema.minimumTimestamp)) { return false } if (IsDefined(schema.multipleOfTimestamp) && !(value.getTime() % schema.multipleOfTimestamp === 0)) { return false } return true } function FromFunction(schema: TFunction, references: TSchema[], value: any): boolean { return IsFunction(value) } function FromImport(schema: TImport, references: TSchema[], value: any): boolean { const definitions = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema return Visit(target, [...references, ...definitions], value) } function FromInteger(schema: TInteger, references: TSchema[], value: any): boolean { if (!IsInteger(value)) { return false } if (IsDefined(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) { return false } if (IsDefined(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) { return false } if (IsDefined(schema.maximum) && !(value <= schema.maximum)) { return false } if (IsDefined(schema.minimum) && !(value >= schema.minimum)) { return false } if (IsDefined(schema.multipleOf) && !(value % schema.multipleOf === 0)) { return false } return true } function FromIntersect(schema: TIntersect, references: TSchema[], value: any): boolean { const check1 = schema.allOf.every((schema) => Visit(schema, references, value)) if (schema.unevaluatedProperties === false) { const keyPattern = new RegExp(KeyOfPattern(schema)) const check2 = Object.getOwnPropertyNames(value).every((key) => keyPattern.test(key)) return check1 && check2 } else if (IsSchema(schema.unevaluatedProperties)) { const keyCheck = new RegExp(KeyOfPattern(schema)) const check2 = Object.getOwnPropertyNames(value).every((key) => keyCheck.test(key) || Visit(schema.unevaluatedProperties as TSchema, references, value[key])) return check1 && check2 } else { return check1 } } function FromIterator(schema: TIterator, references: TSchema[], value: any): boolean { return IsIterator(value) } function FromLiteral(schema: TLiteral, references: TSchema[], value: any): boolean { return value === schema.const } function FromNever(schema: TNever, references: TSchema[], value: any): boolean { return false } function FromNot(schema: TNot, references: TSchema[], value: any): boolean { return !Visit(schema.not, references, value) } function FromNull(schema: TNull, references: TSchema[], value: any): boolean { return IsNull(value) } function FromNumber(schema: TNumber, references: TSchema[], value: any): boolean { if (!TypeSystemPolicy.IsNumberLike(value)) return false if (IsDefined(schema.exclusiveMaximum) && !(value < schema.exclusiveMaximum)) { return false } if (IsDefined(schema.exclusiveMinimum) && !(value > schema.exclusiveMinimum)) { return false } if (IsDefined(schema.minimum) && !(value >= schema.minimum)) { return false } if (IsDefined(schema.maximum) && !(value <= schema.maximum)) { return false } if (IsDefined(schema.multipleOf) && !(value % schema.multipleOf === 0)) { return false } return true } function FromObject(schema: TObject, references: TSchema[], value: any): boolean { if (!TypeSystemPolicy.IsObjectLike(value)) return false if (IsDefined(schema.minProperties) && !(Object.getOwnPropertyNames(value).length >= schema.minProperties)) { return false } if (IsDefined(schema.maxProperties) && !(Object.getOwnPropertyNames(value).length <= schema.maxProperties)) { return false } const knownKeys = Object.getOwnPropertyNames(schema.properties) for (const knownKey of knownKeys) { const property = schema.properties[knownKey] if (schema.required && schema.required.includes(knownKey)) { if (!Visit(property, references, value[knownKey])) { return false } if ((ExtendsUndefinedCheck(property) || IsAnyOrUnknown(property)) && !(knownKey in value)) { return false } } else { if (TypeSystemPolicy.IsExactOptionalProperty(value, knownKey) && !Visit(property, references, value[knownKey])) { return false } } } if (schema.additionalProperties === false) { const valueKeys = Object.getOwnPropertyNames(value) // optimization: value is valid if schemaKey length matches the valueKey length if (schema.required && schema.required.length === knownKeys.length && valueKeys.length === knownKeys.length) { return true } else { return valueKeys.every((valueKey) => knownKeys.includes(valueKey)) } } else if (typeof schema.additionalProperties === 'object') { const valueKeys = Object.getOwnPropertyNames(value) return valueKeys.every((key) => knownKeys.includes(key) || Visit(schema.additionalProperties as TSchema, references, value[key])) } else { return true } } function FromPromise(schema: TPromise, references: TSchema[], value: any): boolean { return IsPromise(value) } function FromRecord(schema: TRecord, references: TSchema[], value: any): boolean { if (!TypeSystemPolicy.IsRecordLike(value)) { return false } if (IsDefined(schema.minProperties) && !(Object.getOwnPropertyNames(value).length >= schema.minProperties)) { return false } if (IsDefined(schema.maxProperties) && !(Object.getOwnPropertyNames(value).length <= schema.maxProperties)) { return false } const [patternKey, patternSchema] = Object.entries(schema.patternProperties)[0] const regex = new RegExp(patternKey) // prettier-ignore const check1 = Object.entries(value).every(([key, value]) => { return (regex.test(key)) ? Visit(patternSchema, references, value) : true }) // prettier-ignore const check2 = typeof schema.additionalProperties === 'object' ? Object.entries(value).every(([key, value]) => { return (!regex.test(key)) ? Visit(schema.additionalProperties as TSchema, references, value) : true }) : true const check3 = schema.additionalProperties === false ? Object.getOwnPropertyNames(value).every((key) => { return regex.test(key) }) : true return check1 && check2 && check3 } function FromRef(schema: TRef, references: TSchema[], value: any): boolean { return Visit(Deref(schema, references), references, value) } function FromRegExp(schema: TRegExp, references: TSchema[], value: any): boolean { const regex = new RegExp(schema.source, schema.flags) if (IsDefined(schema.minLength)) { if (!(value.length >= schema.minLength)) return false } if (IsDefined(schema.maxLength)) { if (!(value.length <= schema.maxLength)) return false } return regex.test(value) } function FromString(schema: TString, references: TSchema[], value: any): boolean { if (!IsString(value)) { return false } if (IsDefined(schema.minLength)) { if (!(value.length >= schema.minLength)) return false } if (IsDefined(schema.maxLength)) { if (!(value.length <= schema.maxLength)) return false } if (IsDefined(schema.pattern)) { const regex = new RegExp(schema.pattern) if (!regex.test(value)) return false } if (IsDefined(schema.format)) { if (!FormatRegistry.Has(schema.format)) return false const func = FormatRegistry.Get(schema.format)! return func(value) } return true } function FromSymbol(schema: TSymbol, references: TSchema[], value: any): boolean { return IsSymbol(value) } function FromTemplateLiteral(schema: TTemplateLiteral, references: TSchema[], value: any): boolean { return IsString(value) && new RegExp(schema.pattern).test(value) } function FromThis(schema: TThis, references: TSchema[], value: any): boolean { return Visit(Deref(schema, references), references, value) } function FromTuple(schema: TTuple, references: TSchema[], value: any): boolean { if (!IsArray(value)) { return false } if (schema.items === undefined && !(value.length === 0)) { return false } if (!(value.length === schema.maxItems)) { return false } if (!schema.items) { return true } for (let i = 0; i < schema.items.length; i++) { if (!Visit(schema.items[i], references, value[i])) return false } return true } function FromUndefined(schema: TUndefined, references: TSchema[], value: any): boolean { return IsUndefined(value) } function FromUnion(schema: TUnion, references: TSchema[], value: any): boolean { return schema.anyOf.some((inner) => Visit(inner, references, value)) } function FromUint8Array(schema: TUint8Array, references: TSchema[], value: any): boolean { if (!IsUint8Array(value)) { return false } if (IsDefined(schema.maxByteLength) && !(value.length <= schema.maxByteLength)) { return false } if (IsDefined(schema.minByteLength) && !(value.length >= schema.minByteLength)) { return false } return true } function FromUnknown(schema: TUnknown, references: TSchema[], value: any): boolean { return true } function FromVoid(schema: TVoid, references: TSchema[], value: any): boolean { return TypeSystemPolicy.IsVoidLike(value) } function FromKind(schema: TSchema, references: TSchema[], value: unknown): boolean { if (!TypeRegistry.Has(schema[Kind])) return false const func = TypeRegistry.Get(schema[Kind])! return func(schema, value) } function Visit(schema: T, references: TSchema[], value: any): boolean { const references_ = IsDefined(schema.$id) ? Pushref(schema, references) : references const schema_ = schema as any switch (schema_[Kind]) { case 'Any': return FromAny(schema_, references_, value) case 'Argument': return FromArgument(schema_, references_, value) case 'Array': return FromArray(schema_, references_, value) case 'AsyncIterator': return FromAsyncIterator(schema_, references_, value) case 'BigInt': return FromBigInt(schema_, references_, value) case 'Boolean': return FromBoolean(schema_, references_, value) case 'Constructor': return FromConstructor(schema_, references_, value) case 'Date': return FromDate(schema_, references_, value) case 'Function': return FromFunction(schema_, references_, value) case 'Import': return FromImport(schema_, references_, value) case 'Integer': return FromInteger(schema_, references_, value) case 'Intersect': return FromIntersect(schema_, references_, value) case 'Iterator': return FromIterator(schema_, references_, value) case 'Literal': return FromLiteral(schema_, references_, value) case 'Never': return FromNever(schema_, references_, value) case 'Not': return FromNot(schema_, references_, value) case 'Null': return FromNull(schema_, references_, value) case 'Number': return FromNumber(schema_, references_, value) case 'Object': return FromObject(schema_, references_, value) case 'Promise': return FromPromise(schema_, references_, value) case 'Record': return FromRecord(schema_, references_, value) case 'Ref': return FromRef(schema_, references_, value) case 'RegExp': return FromRegExp(schema_, references_, value) case 'String': return FromString(schema_, references_, value) case 'Symbol': return FromSymbol(schema_, references_, value) case 'TemplateLiteral': return FromTemplateLiteral(schema_, references_, value) case 'This': return FromThis(schema_, references_, value) case 'Tuple': return FromTuple(schema_, references_, value) case 'Undefined': return FromUndefined(schema_, references_, value) case 'Union': return FromUnion(schema_, references_, value) case 'Uint8Array': return FromUint8Array(schema_, references_, value) case 'Unknown': return FromUnknown(schema_, references_, value) case 'Void': return FromVoid(schema_, references_, value) default: if (!TypeRegistry.Has(schema_[Kind])) throw new ValueCheckUnknownTypeError(schema_) return FromKind(schema_, references_, value) } } // -------------------------------------------------------------------------- // Check // -------------------------------------------------------------------------- /** Returns true if the value matches the given type. */ export function Check(schema: T, references: TSchema[], value: unknown): value is Static /** Returns true if the value matches the given type. */ export function Check(schema: T, value: unknown): value is Static /** Returns true if the value matches the given type. */ export function Check(...args: any[]) { return args.length === 3 ? Visit(args[0], args[1], args[2]) : Visit(args[0], [], args[1]) } sinclairzx81-typebox-e0ec98c/src/value/check/index.ts000066400000000000000000000024641505437577000227250ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './check' sinclairzx81-typebox-e0ec98c/src/value/clean/000077500000000000000000000000001505437577000212455ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/clean/clean.ts000066400000000000000000000211461505437577000227030ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { KeyOfPropertyKeys } from '../../type/keyof/index' import { Check } from '../check/index' import { Clone } from '../clone/index' import { Deref, Pushref } from '../deref/index' import { Kind } from '../../type/symbols/index' import type { TSchema } from '../../type/schema/index' import type { TArray } from '../../type/array/index' import type { TImport } from '../../type/module/index' import type { TIntersect } from '../../type/intersect/index' import type { TObject } from '../../type/object/index' import type { TRecord } from '../../type/record/index' import type { TRef } from '../../type/ref/index' import type { TThis } from '../../type/recursive/index' import type { TTuple } from '../../type/tuple/index' import type { TUnion } from '../../type/union/index' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ // prettier-ignore import { HasPropertyKey, IsString, IsObject, IsArray, IsUndefined } from '../guard/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ // prettier-ignore import { IsKind } from '../../type/guard/kind' // ------------------------------------------------------------------ // IsCheckable // ------------------------------------------------------------------ function IsCheckable(schema: unknown): boolean { return IsKind(schema) && schema[Kind] !== 'Unsafe' } // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ function FromArray(schema: TArray, references: TSchema[], value: unknown): any { if (!IsArray(value)) return value return value.map((value) => Visit(schema.items, references, value)) } function FromImport(schema: TImport, references: TSchema[], value: unknown): any { const definitions = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema return Visit(target, [...references, ...definitions], value) } function FromIntersect(schema: TIntersect, references: TSchema[], value: unknown): any { const unevaluatedProperties = schema.unevaluatedProperties as TSchema const intersections = schema.allOf.map((schema) => Visit(schema, references, Clone(value))) const composite = intersections.reduce((acc: any, value: any) => (IsObject(value) ? { ...acc, ...value } : value), {}) if (!IsObject(value) || !IsObject(composite) || !IsKind(unevaluatedProperties)) return composite const knownkeys = KeyOfPropertyKeys(schema) as string[] for (const key of Object.getOwnPropertyNames(value)) { if (knownkeys.includes(key)) continue if (Check(unevaluatedProperties, references, value[key])) { composite[key] = Visit(unevaluatedProperties, references, value[key]) } } return composite } function FromObject(schema: TObject, references: TSchema[], value: unknown): any { if (!IsObject(value) || IsArray(value)) return value // Check IsArray for AllowArrayObject configuration const additionalProperties = schema.additionalProperties as TSchema for (const key of Object.getOwnPropertyNames(value)) { if (HasPropertyKey(schema.properties, key)) { value[key] = Visit(schema.properties[key], references, value[key]) continue } if (IsKind(additionalProperties) && Check(additionalProperties, references, value[key])) { value[key] = Visit(additionalProperties, references, value[key]) continue } delete value[key] } return value } function FromRecord(schema: TRecord, references: TSchema[], value: unknown): any { if (!IsObject(value)) return value const additionalProperties = schema.additionalProperties as TSchema const propertyKeys = Object.getOwnPropertyNames(value) const [propertyKey, propertySchema] = Object.entries(schema.patternProperties)[0] const propertyKeyTest = new RegExp(propertyKey) for (const key of propertyKeys) { if (propertyKeyTest.test(key)) { value[key] = Visit(propertySchema, references, value[key]) continue } if (IsKind(additionalProperties) && Check(additionalProperties, references, value[key])) { value[key] = Visit(additionalProperties, references, value[key]) continue } delete value[key] } return value } function FromRef(schema: TRef, references: TSchema[], value: unknown): any { return Visit(Deref(schema, references), references, value) } function FromThis(schema: TThis, references: TSchema[], value: unknown): any { return Visit(Deref(schema, references), references, value) } function FromTuple(schema: TTuple, references: TSchema[], value: unknown): any { if (!IsArray(value)) return value if (IsUndefined(schema.items)) return [] const length = Math.min(value.length, schema.items.length) for (let i = 0; i < length; i++) { value[i] = Visit(schema.items[i], references, value[i]) } // prettier-ignore return value.length > length ? value.slice(0, length) : value } function FromUnion(schema: TUnion, references: TSchema[], value: unknown): any { for (const inner of schema.anyOf) { if (IsCheckable(inner) && Check(inner, references, value)) { return Visit(inner, references, value) } } return value } function Visit(schema: TSchema, references: TSchema[], value: unknown): unknown { const references_ = IsString(schema.$id) ? Pushref(schema, references) : references const schema_ = schema as any switch (schema_[Kind]) { case 'Array': return FromArray(schema_, references_, value) case 'Import': return FromImport(schema_, references_, value) case 'Intersect': return FromIntersect(schema_, references_, value) case 'Object': return FromObject(schema_, references_, value) case 'Record': return FromRecord(schema_, references_, value) case 'Ref': return FromRef(schema_, references_, value) case 'This': return FromThis(schema_, references_, value) case 'Tuple': return FromTuple(schema_, references_, value) case 'Union': return FromUnion(schema_, references_, value) default: return value } } // ------------------------------------------------------------------ // Clean // ------------------------------------------------------------------ /** `[Mutable]` Removes excess properties from a value and returns the result. This function does not check the value and returns an unknown type. You should Check the result before use. Clean is a mutable operation. To avoid mutation, Clone the value first. */ export function Clean(schema: TSchema, references: TSchema[], value: unknown): unknown /** `[Mutable]` Removes excess properties from a value and returns the result. This function does not check the value and returns an unknown type. You should Check the result before use. Clean is a mutable operation. To avoid mutation, Clone the value first. */ export function Clean(schema: TSchema, value: unknown): unknown /** `[Mutable]` Removes excess properties from a value and returns the result. This function does not check the value and returns an unknown type. You should Check the result before use. Clean is a mutable operation. To avoid mutation, Clone the value first. */ export function Clean(...args: any[]) { return args.length === 3 ? Visit(args[0], args[1], args[2]) : Visit(args[0], [], args[1]) } sinclairzx81-typebox-e0ec98c/src/value/clean/index.ts000066400000000000000000000024641505437577000227320ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './clean' sinclairzx81-typebox-e0ec98c/src/value/clone/000077500000000000000000000000001505437577000212635ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/clone/clone.ts000066400000000000000000000063121505437577000227350ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { ObjectType as FromObject, ArrayType as FromArray, TypedArrayType, ValueType } from '../guard/index' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ import { IsArray, IsDate, IsMap, IsSet, IsObject, IsTypedArray, IsValueType } from '../guard/index' // ------------------------------------------------------------------ // Clonable // ------------------------------------------------------------------ function FromObject(value: FromObject): any { const Acc = {} as Record for (const key of Object.getOwnPropertyNames(value)) { Acc[key] = Clone(value[key]) } for (const key of Object.getOwnPropertySymbols(value)) { Acc[key] = Clone(value[key]) } return Acc } function FromArray(value: FromArray): any { return value.map((element: any) => Clone(element)) } function FromTypedArray(value: TypedArrayType): any { return value.slice() } function FromMap(value: Map): any { return new Map(Clone([...value.entries()])) } function FromSet(value: Set): any { return new Set(Clone([...value.entries()])) } function FromDate(value: Date): any { return new Date(value.toISOString()) } function FromValue(value: ValueType): any { return value } // ------------------------------------------------------------------ // Clone // ------------------------------------------------------------------ /** Returns a clone of the given value */ export function Clone(value: T): T { if (IsArray(value)) return FromArray(value) if (IsDate(value)) return FromDate(value) if (IsTypedArray(value)) return FromTypedArray(value) if (IsMap(value)) return FromMap(value) if (IsSet(value)) return FromSet(value) if (IsObject(value)) return FromObject(value) if (IsValueType(value)) return FromValue(value) throw new Error('ValueClone: Unable to clone value') } sinclairzx81-typebox-e0ec98c/src/value/clone/index.ts000066400000000000000000000024641505437577000227500ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './clone' sinclairzx81-typebox-e0ec98c/src/value/convert/000077500000000000000000000000001505437577000216435ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/convert/convert.ts000066400000000000000000000344601505437577000237020ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Clone } from '../clone/index' import { Check } from '../check/index' import { Deref, Pushref } from '../deref/index' import { Kind } from '../../type/symbols/index' import type { TSchema } from '../../type/schema/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 { TInteger } from '../../type/integer/index' import type { TIntersect } from '../../type/intersect/index' import type { TImport } from '../../type/module/index' import type { TLiteral } from '../../type/literal/index' import type { TNull } from '../../type/null/index' import type { TNumber } from '../../type/number/index' import type { TObject } from '../../type/object/index' import type { TRecord } from '../../type/record/index' import type { TRef } from '../../type/ref/index' import type { TThis } from '../../type/recursive/index' import type { TTuple } from '../../type/tuple/index' import type { TUnion } from '../../type/union/index' import type { TString } from '../../type/string/index' import type { TSymbol } from '../../type/symbol/index' import type { TUndefined } from '../../type/undefined/index' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ import { IsArray, IsObject, IsDate, IsUndefined, IsString, IsNumber, IsBoolean, IsBigInt, IsSymbol, HasPropertyKey } from '../guard/index' // ------------------------------------------------------------------ // Conversions // ------------------------------------------------------------------ function IsStringNumeric(value: unknown): value is string { return IsString(value) && !isNaN(value as any) && !isNaN(parseFloat(value)) } function IsValueToString(value: unknown): value is { toString: () => string } { return IsBigInt(value) || IsBoolean(value) || IsNumber(value) } function IsValueTrue(value: unknown): value is true { return value === true || (IsNumber(value) && value === 1) || (IsBigInt(value) && value === BigInt('1')) || (IsString(value) && (value.toLowerCase() === 'true' || value === '1')) } function IsValueFalse(value: unknown): value is false { return value === false || (IsNumber(value) && (value === 0 || Object.is(value, -0))) || (IsBigInt(value) && value === BigInt('0')) || (IsString(value) && (value.toLowerCase() === 'false' || value === '0' || value === '-0')) } function IsTimeStringWithTimeZone(value: unknown): value is string { return IsString(value) && /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i.test(value) } function IsTimeStringWithoutTimeZone(value: unknown): value is string { return IsString(value) && /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)?$/i.test(value) } function IsDateTimeStringWithTimeZone(value: unknown): value is string { return IsString(value) && /^\d\d\d\d-[0-1]\d-[0-3]\dt(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d(?::?\d\d)?)$/i.test(value) } function IsDateTimeStringWithoutTimeZone(value: unknown): value is string { return IsString(value) && /^\d\d\d\d-[0-1]\d-[0-3]\dt(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)?$/i.test(value) } function IsDateString(value: unknown): value is string { return IsString(value) && /^\d\d\d\d-[0-1]\d-[0-3]\d$/i.test(value) } // ------------------------------------------------------------------ // Convert // ------------------------------------------------------------------ function TryConvertLiteralString(value: unknown, target: string) { const conversion = TryConvertString(value) return conversion === target ? conversion : value } function TryConvertLiteralNumber(value: unknown, target: number) { const conversion = TryConvertNumber(value) return conversion === target ? conversion : value } function TryConvertLiteralBoolean(value: unknown, target: boolean) { const conversion = TryConvertBoolean(value) return conversion === target ? conversion : value } // prettier-ignore function TryConvertLiteral(schema: TLiteral, value: unknown) { return ( IsString(schema.const) ? TryConvertLiteralString(value, schema.const) : IsNumber(schema.const) ? TryConvertLiteralNumber(value, schema.const) : IsBoolean(schema.const) ? TryConvertLiteralBoolean(value, schema.const) : value ) } function TryConvertBoolean(value: unknown) { return IsValueTrue(value) ? true : IsValueFalse(value) ? false : value } function TryConvertBigInt(value: unknown) { const truncateInteger = (value: string) => value.split('.')[0] return IsStringNumeric(value) ? BigInt(truncateInteger(value)) : IsNumber(value) ? BigInt(Math.trunc(value)) : IsValueFalse(value) ? BigInt(0) : IsValueTrue(value) ? BigInt(1) : value } function TryConvertString(value: unknown) { return IsSymbol(value) && value.description !== undefined ? value.description.toString() : IsValueToString(value) ? value.toString() : value } function TryConvertNumber(value: unknown) { return IsStringNumeric(value) ? parseFloat(value) : IsValueTrue(value) ? 1 : IsValueFalse(value) ? 0 : value } function TryConvertInteger(value: unknown) { return IsStringNumeric(value) ? parseInt(value) : IsNumber(value) ? Math.trunc(value) : IsValueTrue(value) ? 1 : IsValueFalse(value) ? 0 : value } function TryConvertNull(value: unknown) { return IsString(value) && value.toLowerCase() === 'null' ? null : value } function TryConvertUndefined(value: unknown) { return IsString(value) && value === 'undefined' ? undefined : value } // ------------------------------------------------------------------ // note: this function may return an invalid dates for the regex // tests above. Invalid dates will however be checked during the // casting function and will return a epoch date if invalid. // Consider better string parsing for the iso dates in future // revisions. // ------------------------------------------------------------------ // prettier-ignore function TryConvertDate(value: unknown) { return ( IsDate(value) ? value : IsNumber(value) ? new Date(value) : IsValueTrue(value) ? new Date(1) : IsValueFalse(value) ? new Date(0) : IsStringNumeric(value) ? new Date(parseInt(value)) : IsTimeStringWithoutTimeZone(value) ? new Date(`1970-01-01T${value}.000Z`) : IsTimeStringWithTimeZone(value) ? new Date(`1970-01-01T${value}`) : IsDateTimeStringWithoutTimeZone(value) ? new Date(`${value}.000Z`) : IsDateTimeStringWithTimeZone(value) ? new Date(value) : IsDateString(value) ? new Date(`${value}T00:00:00.000Z`) : value ) } // ------------------------------------------------------------------ // Default // ------------------------------------------------------------------ function Default(value: unknown): unknown { return value } // ------------------------------------------------------------------ // Convert // ------------------------------------------------------------------ function FromArray(schema: TArray, references: TSchema[], value: any): any { const elements = IsArray(value) ? value : [value] return elements.map((element) => Visit(schema.items, references, element)) } function FromBigInt(schema: TBigInt, references: TSchema[], value: any): unknown { return TryConvertBigInt(value) } function FromBoolean(schema: TBoolean, references: TSchema[], value: any): unknown { return TryConvertBoolean(value) } function FromDate(schema: TDate, references: TSchema[], value: any): unknown { return TryConvertDate(value) } function FromImport(schema: TImport, references: TSchema[], value: unknown): unknown { const definitions = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema return Visit(target, [...references, ...definitions], value) } function FromInteger(schema: TInteger, references: TSchema[], value: any): unknown { return TryConvertInteger(value) } function FromIntersect(schema: TIntersect, references: TSchema[], value: any): unknown { return schema.allOf.reduce((value, schema) => Visit(schema, references, value), value) } function FromLiteral(schema: TLiteral, references: TSchema[], value: any): unknown { return TryConvertLiteral(schema, value) } function FromNull(schema: TNull, references: TSchema[], value: any): unknown { return TryConvertNull(value) } function FromNumber(schema: TNumber, references: TSchema[], value: any): unknown { return TryConvertNumber(value) } // prettier-ignore function FromObject(schema: TObject, references: TSchema[], value: any): unknown { if(!IsObject(value) || IsArray(value)) return value for(const propertyKey of Object.getOwnPropertyNames(schema.properties)) { if(!HasPropertyKey(value, propertyKey)) continue value[propertyKey] = Visit(schema.properties[propertyKey], references, value[propertyKey]) } return value } function FromRecord(schema: TRecord, references: TSchema[], value: any): unknown { const isConvertable = IsObject(value) && !IsArray(value) if (!isConvertable) return value const propertyKey = Object.getOwnPropertyNames(schema.patternProperties)[0] const property = schema.patternProperties[propertyKey] for (const [propKey, propValue] of Object.entries(value)) { value[propKey] = Visit(property, references, propValue) } return value } function FromRef(schema: TRef, references: TSchema[], value: any): unknown { return Visit(Deref(schema, references), references, value) } function FromString(schema: TString, references: TSchema[], value: any): unknown { return TryConvertString(value) } function FromSymbol(schema: TSymbol, references: TSchema[], value: any): unknown { return IsString(value) || IsNumber(value) ? Symbol(value) : value } function FromThis(schema: TThis, references: TSchema[], value: any): unknown { return Visit(Deref(schema, references), references, value) } // prettier-ignore function FromTuple(schema: TTuple, references: TSchema[], value: any): unknown { const isConvertable = IsArray(value) && !IsUndefined(schema.items) if(!isConvertable) return value return value.map((value, index) => { return (index < schema.items!.length) ? Visit(schema.items![index], references, value) : value }) } function FromUndefined(schema: TUndefined, references: TSchema[], value: any): unknown { return TryConvertUndefined(value) } function FromUnion(schema: TUnion, references: TSchema[], value: any): unknown { // Check if original value already matches one of the union variants for (const subschema of schema.anyOf) { if (Check(subschema, references, value)) { return value } } // Attempt conversion for each variant for (const subschema of schema.anyOf) { const converted = Visit(subschema, references, Clone(value)) if (!Check(subschema, references, converted)) continue return converted } return value } function Visit(schema: TSchema, references: TSchema[], value: any): unknown { const references_ = Pushref(schema, references) const schema_ = schema as any switch (schema[Kind]) { case 'Array': return FromArray(schema_, references_, value) case 'BigInt': return FromBigInt(schema_, references_, value) case 'Boolean': return FromBoolean(schema_, references_, value) case 'Date': return FromDate(schema_, references_, value) case 'Import': return FromImport(schema_, references_, value) case 'Integer': return FromInteger(schema_, references_, value) case 'Intersect': return FromIntersect(schema_, references_, value) case 'Literal': return FromLiteral(schema_, references_, value) case 'Null': return FromNull(schema_, references_, value) case 'Number': return FromNumber(schema_, references_, value) case 'Object': return FromObject(schema_, references_, value) case 'Record': return FromRecord(schema_, references_, value) case 'Ref': return FromRef(schema_, references_, value) case 'String': return FromString(schema_, references_, value) case 'Symbol': return FromSymbol(schema_, references_, value) case 'This': return FromThis(schema_, references_, value) case 'Tuple': return FromTuple(schema_, references_, value) case 'Undefined': return FromUndefined(schema_, references_, value) case 'Union': return FromUnion(schema_, references_, value) default: return Default(value) } } // ------------------------------------------------------------------ // Convert // ------------------------------------------------------------------ /** `[Mutable]` Converts any type mismatched values to their target type if a reasonable conversion is possible. */ export function Convert(schema: TSchema, references: TSchema[], value: unknown): unknown /** `[Mutable]` Converts any type mismatched values to their target type if a reasonable conversion is possible. */ export function Convert(schema: TSchema, value: unknown): unknown /** `[Mutable]` Converts any type mismatched values to their target type if a reasonable conversion is possible. */ // prettier-ignore export function Convert(...args: any[]) { return args.length === 3 ? Visit(args[0], args[1], args[2]) : Visit(args[0], [], args[1]) } sinclairzx81-typebox-e0ec98c/src/value/convert/index.ts000066400000000000000000000024661505437577000233320ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './convert' sinclairzx81-typebox-e0ec98c/src/value/create/000077500000000000000000000000001505437577000214265ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/create/create.ts000066400000000000000000000434111505437577000232440ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { HasPropertyKey } from '../guard/index' import { Check } from '../check/index' import { Clone } from '../clone/index' import { Deref, Pushref } from '../deref/index' import { TemplateLiteralGenerate, IsTemplateLiteralFinite } from '../../type/template-literal/index' import { PatternStringExact, PatternNumberExact } from '../../type/patterns/index' import { TypeRegistry } from '../../type/registry/index' import { Kind } from '../../type/symbols/index' import { TypeBoxError } from '../../type/error/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 { TImport } from '../../type/module/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 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 } 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' import { IsFunction } from '../guard/guard' // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class ValueCreateError extends TypeBoxError { constructor(public readonly schema: TSchema, message: string) { super(message) } } // ------------------------------------------------------------------ // Default // ------------------------------------------------------------------ function FromDefault(value: unknown) { return IsFunction(value) ? value() : Clone(value) } // ------------------------------------------------------------------ // Create // ------------------------------------------------------------------ function FromAny(schema: TAny, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return {} } } function FromArgument(schema: TAny, references: TSchema[]): any { return {} } function FromArray(schema: TArray, references: TSchema[]): any { if (schema.uniqueItems === true && !HasPropertyKey(schema, 'default')) { throw new ValueCreateError(schema, 'Array with the uniqueItems constraint requires a default value') } else if ('contains' in schema && !HasPropertyKey(schema, 'default')) { throw new ValueCreateError(schema, 'Array with the contains constraint requires a default value') } else if ('default' in schema) { return FromDefault(schema.default) } else if (schema.minItems !== undefined) { return Array.from({ length: schema.minItems }).map((item) => { return Visit(schema.items, references) }) } else { return [] } } function FromAsyncIterator(schema: TAsyncIterator, references: TSchema[]) { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return (async function* () {})() } } function FromBigInt(schema: TBigInt, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return BigInt(0) } } function FromBoolean(schema: TBoolean, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return false } } function FromConstructor(schema: TConstructor, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { const value = Visit(schema.returns, references) as any if (typeof value === 'object' && !Array.isArray(value)) { return class { constructor() { for (const [key, val] of Object.entries(value)) { const self = this as any self[key] = val } } } } else { return class {} } } } function FromDate(schema: TDate, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else if (schema.minimumTimestamp !== undefined) { return new Date(schema.minimumTimestamp) } else { return new Date() } } function FromFunction(schema: TFunction, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return () => Visit(schema.returns, references) } } function FromImport(schema: TImport, references: TSchema[]): any { const definitions = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema return Visit(target, [...references, ...definitions]) } function FromInteger(schema: TInteger, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else if (schema.minimum !== undefined) { return schema.minimum } else { return 0 } } function FromIntersect(schema: TIntersect, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { // -------------------------------------------------------------- // Note: The best we can do here is attempt to instance each // sub type and apply through object assign. For non-object // sub types, we just escape the assignment and just return // the value. In the latter case, this is typically going to // be a consequence of an illogical intersection. // -------------------------------------------------------------- const value = schema.allOf.reduce((acc, schema) => { const next = Visit(schema, references) as any return typeof next === 'object' ? { ...acc, ...next } : next }, {}) if (!Check(schema, references, value)) throw new ValueCreateError(schema, 'Intersect produced invalid value. Consider using a default value.') return value } } function FromIterator(schema: TIterator, references: TSchema[]) { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return (function* () {})() } } function FromLiteral(schema: TLiteral, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return schema.const } } function FromNever(schema: TNever, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { throw new ValueCreateError(schema, 'Never types cannot be created. Consider using a default value.') } } function FromNot(schema: TNot, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { throw new ValueCreateError(schema, 'Not types must have a default value') } } function FromNull(schema: TNull, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return null } } function FromNumber(schema: TNumber, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else if (schema.minimum !== undefined) { return schema.minimum } else { return 0 } } function FromObject(schema: TObject, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { const required = new Set(schema.required) const Acc = {} as Record for (const [key, subschema] of Object.entries(schema.properties)) { if (!required.has(key)) continue Acc[key] = Visit(subschema, references) } return Acc } } function FromPromise(schema: TPromise, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return Promise.resolve(Visit(schema.item, references)) } } function FromRecord(schema: TRecord, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return {} } } function FromRef(schema: TRef, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return Visit(Deref(schema, references), references) } } function FromRegExp(schema: TRegExp, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { throw new ValueCreateError(schema, 'RegExp types cannot be created. Consider using a default value.') } } function FromString(schema: TString, references: TSchema[]): any { if (schema.pattern !== undefined) { if (!HasPropertyKey(schema, 'default')) { throw new ValueCreateError(schema, 'String types with patterns must specify a default value') } else { return FromDefault(schema.default) } } else if (schema.format !== undefined) { if (!HasPropertyKey(schema, 'default')) { throw new ValueCreateError(schema, 'String types with formats must specify a default value') } else { return FromDefault(schema.default) } } else { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else if (schema.minLength !== undefined) { // prettier-ignore return Array.from({ length: schema.minLength }).map(() => ' ').join('') } else { return '' } } } function FromSymbol(schema: TSymbol, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else if ('value' in schema) { return Symbol.for(schema.value) } else { return Symbol() } } function FromTemplateLiteral(schema: TTemplateLiteral, references: TSchema[]) { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } if (!IsTemplateLiteralFinite(schema)) throw new ValueCreateError(schema, 'Can only create template literals that produce a finite variants. Consider using a default value.') const generated = TemplateLiteralGenerate(schema) as string[] return generated[0] } function FromThis(schema: TThis, references: TSchema[]): any { if (recursiveDepth++ > recursiveMaxDepth) throw new ValueCreateError(schema, 'Cannot create recursive type as it appears possibly infinite. Consider using a default.') if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return Visit(Deref(schema, references), references) } } function FromTuple(schema: TTuple, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } if (schema.items === undefined) { return [] } else { return Array.from({ length: schema.minItems }).map((_, index) => Visit((schema.items as any[])[index], references)) } } function FromUndefined(schema: TUndefined, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return undefined } } function FromUnion(schema: TUnion, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else if (schema.anyOf.length === 0) { throw new Error('ValueCreate.Union: Cannot create Union with zero variants') } else { return Visit(schema.anyOf[0], references) } } function FromUint8Array(schema: TUint8Array, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else if (schema.minByteLength !== undefined) { return new Uint8Array(schema.minByteLength) } else { return new Uint8Array(0) } } function FromUnknown(schema: TUnknown, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return {} } } function FromVoid(schema: TVoid, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { return void 0 } } function FromKind(schema: TSchema, references: TSchema[]): any { if (HasPropertyKey(schema, 'default')) { return FromDefault(schema.default) } else { throw new Error('User defined types must specify a default value') } } function Visit(schema: TSchema, references: TSchema[]): unknown { const references_ = Pushref(schema, references) const schema_ = schema as any switch (schema_[Kind]) { case 'Any': return FromAny(schema_, references_) case 'Argument': return FromArgument(schema_, references_) case 'Array': return FromArray(schema_, references_) case 'AsyncIterator': return FromAsyncIterator(schema_, references_) case 'BigInt': return FromBigInt(schema_, references_) case 'Boolean': return FromBoolean(schema_, references_) case 'Constructor': return FromConstructor(schema_, references_) case 'Date': return FromDate(schema_, references_) case 'Function': return FromFunction(schema_, references_) case 'Import': return FromImport(schema_, references_) case 'Integer': return FromInteger(schema_, references_) case 'Intersect': return FromIntersect(schema_, references_) case 'Iterator': return FromIterator(schema_, references_) case 'Literal': return FromLiteral(schema_, references_) case 'Never': return FromNever(schema_, references_) case 'Not': return FromNot(schema_, references_) case 'Null': return FromNull(schema_, references_) case 'Number': return FromNumber(schema_, references_) case 'Object': return FromObject(schema_, references_) case 'Promise': return FromPromise(schema_, references_) case 'Record': return FromRecord(schema_, references_) case 'Ref': return FromRef(schema_, references_) case 'RegExp': return FromRegExp(schema_, references_) case 'String': return FromString(schema_, references_) case 'Symbol': return FromSymbol(schema_, references_) case 'TemplateLiteral': return FromTemplateLiteral(schema_, references_) case 'This': return FromThis(schema_, references_) case 'Tuple': return FromTuple(schema_, references_) case 'Undefined': return FromUndefined(schema_, references_) case 'Union': return FromUnion(schema_, references_) case 'Uint8Array': return FromUint8Array(schema_, references_) case 'Unknown': return FromUnknown(schema_, references_) case 'Void': return FromVoid(schema_, references_) default: if (!TypeRegistry.Has(schema_[Kind])) throw new ValueCreateError(schema_, 'Unknown type') return FromKind(schema_, references_) } } // ------------------------------------------------------------------ // State // ------------------------------------------------------------------ const recursiveMaxDepth = 512 let recursiveDepth = 0 // ------------------------------------------------------------------ // Create // ------------------------------------------------------------------ /** Creates a value from the given schema and references */ export function Create(schema: T, references: TSchema[]): Static /** Creates a value from the given schema */ export function Create(schema: T): Static /** Creates a value from the given schema */ export function Create(...args: any[]) { recursiveDepth = 0 return args.length === 2 ? Visit(args[0], args[1]) : Visit(args[0], []) } sinclairzx81-typebox-e0ec98c/src/value/create/index.ts000066400000000000000000000024651505437577000231140ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './create' sinclairzx81-typebox-e0ec98c/src/value/decode/000077500000000000000000000000001505437577000214065ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/decode/decode.ts000066400000000000000000000045531505437577000232100ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { HasTransform, TransformDecode, TransformDecodeCheckError } from '../transform/index' import { Check } from '../check/index' import { Errors } from '../../errors/index' import type { TSchema } from '../../type/schema/index' import type { StaticDecode } from '../../type/static/index' /** Decodes a value or throws if error */ export function Decode, Result extends Static = Static>(schema: T, references: TSchema[], value: unknown): Result /** Decodes a value or throws if error */ export function Decode, Result extends Static = Static>(schema: T, value: unknown): Result /** Decodes a value or throws if error */ export function Decode(...args: any[]): any { const [schema, references, value] = args.length === 3 ? [args[0], args[1], args[2]] : [args[0], [], args[1]] if (!Check(schema, references, value)) throw new TransformDecodeCheckError(schema, value, Errors(schema, references, value).First()!) return HasTransform(schema, references) ? TransformDecode(schema, references, value) : value } sinclairzx81-typebox-e0ec98c/src/value/decode/index.ts000066400000000000000000000024651505437577000230740ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './decode' sinclairzx81-typebox-e0ec98c/src/value/default/000077500000000000000000000000001505437577000216075ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/default/default.ts000066400000000000000000000237241505437577000236130ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Check } from '../check/index' import { Clone } from '../clone/index' import { Deref, Pushref } from '../deref/index' import { Kind } from '../../type/symbols/index' import type { TSchema } from '../../type/schema/index' import type { TArray } from '../../type/array/index' import type { TImport } from '../../type/module/index' import type { TIntersect } from '../../type/intersect/index' import type { TObject } from '../../type/object/index' import type { TRecord } from '../../type/record/index' import type { TRef } from '../../type/ref/index' import type { TThis } from '../../type/recursive/index' import type { TTuple } from '../../type/tuple/index' import type { TUnion } from '../../type/union/index' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ import { IsArray, IsDate, IsFunction, IsObject, IsUndefined, HasPropertyKey } from '../guard/index' // ------------------------------------------------------------------ // TypeGuard // ------------------------------------------------------------------ import { IsKind } from '../../type/guard/kind' // ------------------------------------------------------------------ // ValueOrDefault // ------------------------------------------------------------------ function ValueOrDefault(schema: TSchema, value: unknown): unknown { const defaultValue = HasPropertyKey(schema, 'default') ? schema.default : undefined const clone = IsFunction(defaultValue) ? defaultValue() : Clone(defaultValue) return IsUndefined(value) ? clone : IsObject(value) && IsObject(clone) ? Object.assign(clone, value) : value } // ------------------------------------------------------------------ // HasDefaultProperty // ------------------------------------------------------------------ function HasDefaultProperty(schema: unknown): schema is TSchema { return IsKind(schema) && 'default' in schema } // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ function FromArray(schema: TArray, references: TSchema[], value: unknown): any { // if the value is an array, we attempt to initialize it's elements if (IsArray(value)) { for (let i = 0; i < value.length; i++) { value[i] = Visit(schema.items, references, value[i]) } return value } // ... otherwise use default initialization const defaulted = ValueOrDefault(schema, value) if (!IsArray(defaulted)) return defaulted for (let i = 0; i < defaulted.length; i++) { defaulted[i] = Visit(schema.items, references, defaulted[i]) } return defaulted } function FromDate(schema: TArray, references: TSchema[], value: unknown): any { // special case intercept for dates return IsDate(value) ? value : ValueOrDefault(schema, value) } function FromImport(schema: TImport, references: TSchema[], value: unknown): any { const definitions = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema return Visit(target, [...references, ...definitions], value) } function FromIntersect(schema: TIntersect, references: TSchema[], value: unknown): any { const defaulted = ValueOrDefault(schema, value) return schema.allOf.reduce((acc, schema) => { const next = Visit(schema, references, defaulted) return IsObject(next) ? { ...acc, ...next } : next }, {}) } function FromObject(schema: TObject, references: TSchema[], value: unknown): any { const defaulted = ValueOrDefault(schema, value) // return defaulted if (!IsObject(defaulted)) return defaulted const knownPropertyKeys = Object.getOwnPropertyNames(schema.properties) // properties for (const key of knownPropertyKeys) { // note: we need to traverse into the object and test if the return value // yielded a non undefined result. Here we interpret an undefined result as // a non assignable property and continue. const propertyValue = Visit(schema.properties[key], references, defaulted[key]) if (IsUndefined(propertyValue)) continue defaulted[key] = Visit(schema.properties[key], references, defaulted[key]) } // return if not additional properties if (!HasDefaultProperty(schema.additionalProperties)) return defaulted // additional properties for (const key of Object.getOwnPropertyNames(defaulted)) { if (knownPropertyKeys.includes(key)) continue defaulted[key] = Visit(schema.additionalProperties, references, defaulted[key]) } return defaulted } function FromRecord(schema: TRecord, references: TSchema[], value: unknown): any { const defaulted = ValueOrDefault(schema, value) if (!IsObject(defaulted)) return defaulted const additionalPropertiesSchema = schema.additionalProperties as TSchema const [propertyKeyPattern, propertySchema] = Object.entries(schema.patternProperties)[0] const knownPropertyKey = new RegExp(propertyKeyPattern) // properties for (const key of Object.getOwnPropertyNames(defaulted)) { if (!(knownPropertyKey.test(key) && HasDefaultProperty(propertySchema))) continue defaulted[key] = Visit(propertySchema, references, defaulted[key]) } // return if not additional properties if (!HasDefaultProperty(additionalPropertiesSchema)) return defaulted // additional properties for (const key of Object.getOwnPropertyNames(defaulted)) { if (knownPropertyKey.test(key)) continue defaulted[key] = Visit(additionalPropertiesSchema, references, defaulted[key]) } return defaulted } function FromRef(schema: TRef, references: TSchema[], value: unknown): any { return Visit(Deref(schema, references), references, ValueOrDefault(schema, value)) } function FromThis(schema: TThis, references: TSchema[], value: unknown): any { return Visit(Deref(schema, references), references, value) } function FromTuple(schema: TTuple, references: TSchema[], value: unknown): any { const defaulted = ValueOrDefault(schema, value) if (!IsArray(defaulted) || IsUndefined(schema.items)) return defaulted const [items, max] = [schema.items!, Math.max(schema.items!.length, defaulted.length)] for (let i = 0; i < max; i++) { if (i < items.length) defaulted[i] = Visit(items[i], references, defaulted[i]) } return defaulted } function FromUnion(schema: TUnion, references: TSchema[], value: unknown): any { const defaulted = ValueOrDefault(schema, value) for (const inner of schema.anyOf) { const result = Visit(inner, references, Clone(defaulted)) if (Check(inner, references, result)) { return result } } return defaulted } function Visit(schema: TSchema, references: TSchema[], value: unknown): any { const references_ = Pushref(schema, references) const schema_ = schema as any switch (schema_[Kind]) { case 'Array': return FromArray(schema_, references_, value) case 'Date': return FromDate(schema_, references_, value) case 'Import': return FromImport(schema_, references_, value) case 'Intersect': return FromIntersect(schema_, references_, value) case 'Object': return FromObject(schema_, references_, value) case 'Record': return FromRecord(schema_, references_, value) case 'Ref': return FromRef(schema_, references_, value) case 'This': return FromThis(schema_, references_, value) case 'Tuple': return FromTuple(schema_, references_, value) case 'Union': return FromUnion(schema_, references_, value) default: return ValueOrDefault(schema_, value) } } // ------------------------------------------------------------------ // Default // ------------------------------------------------------------------ /** `[Mutable]` Generates missing properties on a value using default schema annotations if available. This function does not check the value and returns an unknown type. You should Check the result before use. Default is a mutable operation. To avoid mutation, Clone the value first. */ export function Default(schema: TSchema, references: TSchema[], value: unknown): unknown /** `[Mutable]` Generates missing properties on a value using default schema annotations if available. This function does not check the value and returns an unknown type. You should Check the result before use. Default is a mutable operation. To avoid mutation, Clone the value first. */ export function Default(schema: TSchema, value: unknown): unknown /** `[Mutable]` Generates missing properties on a value using default schema annotations if available. This function does not check the value and returns an unknown type. You should Check the result before use. Default is a mutable operation. To avoid mutation, Clone the value first. */ export function Default(...args: any[]) { return args.length === 3 ? Visit(args[0], args[1], args[2]) : Visit(args[0], [], args[1]) } sinclairzx81-typebox-e0ec98c/src/value/default/index.ts000066400000000000000000000024661505437577000232760ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './default' sinclairzx81-typebox-e0ec98c/src/value/delta/000077500000000000000000000000001505437577000212545ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/delta/delta.ts000066400000000000000000000210651505437577000227210ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { HasPropertyKey, IsStandardObject, IsArray, IsTypedArray, IsValueType } from '../guard/index' import type { ObjectType, ArrayType, TypedArrayType, ValueType } from '../guard/index' import type { Static } from '../../type/static/index' import { ValuePointer } from '../pointer/index' import { Clone } from '../clone/index' import { Equal } from '../equal/equal' import { TypeBoxError } from '../../type/error/index' import { Literal, type TLiteral } from '../../type/literal/index' import { Object, type TObject } from '../../type/object/index' import { String, type TString } from '../../type/string/index' import { Unknown, type TUnknown } from '../../type/unknown/index' import { Union, type TUnion } from '../../type/union/index' // ------------------------------------------------------------------ // Commands // ------------------------------------------------------------------ // Note: A TypeScript 5.4.2 compiler regression resulted in the type // import paths being generated incorrectly. We can resolve this by // explicitly importing the correct TSchema types above. Note also // that the left-side annotations are optional, but since the types // are imported we might as well use them. We should check this // regression in future. The regression occured between TypeScript // versions 5.3.3 -> 5.4.2. export type Insert = Static export const Insert: TObject<{ type: TLiteral<'insert'> path: TString value: TUnknown }> = Object({ type: Literal('insert'), path: String(), value: Unknown(), }) export type Update = Static export const Update: TObject<{ type: TLiteral<'update'> path: TString value: TUnknown }> = Object({ type: Literal('update'), path: String(), value: Unknown(), }) export type Delete = Static export const Delete: TObject<{ type: TLiteral<'delete'> path: TString }> = Object({ type: Literal('delete'), path: String(), }) export type Edit = Static export const Edit: TUnion<[typeof Insert, typeof Update, typeof Delete]> = Union([Insert, Update, Delete]) // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class ValueDiffError extends TypeBoxError { constructor(public readonly value: unknown, message: string) { super(message) } } // ------------------------------------------------------------------ // Command Factory // ------------------------------------------------------------------ function CreateUpdate(path: string, value: unknown): Edit { return { type: 'update', path, value } } function CreateInsert(path: string, value: unknown): Edit { return { type: 'insert', path, value } } function CreateDelete(path: string): Edit { return { type: 'delete', path } } // ------------------------------------------------------------------ // AssertDiffable // ------------------------------------------------------------------ function AssertDiffable(value: unknown): asserts value is Record { if (globalThis.Object.getOwnPropertySymbols(value).length > 0) throw new ValueDiffError(value, 'Cannot diff objects with symbols') } // ------------------------------------------------------------------ // Diffing Generators // ------------------------------------------------------------------ function* ObjectType(path: string, current: ObjectType, next: unknown): IterableIterator { AssertDiffable(current) AssertDiffable(next) if (!IsStandardObject(next)) return yield CreateUpdate(path, next) const currentKeys = globalThis.Object.getOwnPropertyNames(current) const nextKeys = globalThis.Object.getOwnPropertyNames(next) // ---------------------------------------------------------------- // inserts // ---------------------------------------------------------------- for (const key of nextKeys) { if (HasPropertyKey(current, key)) continue yield CreateInsert(`${path}/${key}`, next[key]) } // ---------------------------------------------------------------- // updates // ---------------------------------------------------------------- for (const key of currentKeys) { if (!HasPropertyKey(next, key)) continue if (Equal(current, next)) continue yield* Visit(`${path}/${key}`, current[key], next[key]) } // ---------------------------------------------------------------- // deletes // ---------------------------------------------------------------- for (const key of currentKeys) { if (HasPropertyKey(next, key)) continue yield CreateDelete(`${path}/${key}`) } } function* ArrayType(path: string, current: ArrayType, next: unknown): IterableIterator { if (!IsArray(next)) return yield CreateUpdate(path, next) for (let i = 0; i < Math.min(current.length, next.length); i++) { yield* Visit(`${path}/${i}`, current[i], next[i]) } for (let i = 0; i < next.length; i++) { if (i < current.length) continue yield CreateInsert(`${path}/${i}`, next[i]) } for (let i = current.length - 1; i >= 0; i--) { if (i < next.length) continue yield CreateDelete(`${path}/${i}`) } } function* TypedArrayType(path: string, current: TypedArrayType, next: unknown): IterableIterator { if (!IsTypedArray(next) || current.length !== next.length || globalThis.Object.getPrototypeOf(current).constructor.name !== globalThis.Object.getPrototypeOf(next).constructor.name) return yield CreateUpdate(path, next) for (let i = 0; i < Math.min(current.length, next.length); i++) { yield* Visit(`${path}/${i}`, current[i], next[i]) } } function* ValueType(path: string, current: ValueType, next: unknown): IterableIterator { if (current === next) return yield CreateUpdate(path, next) } function* Visit(path: string, current: unknown, next: unknown): IterableIterator { if (IsStandardObject(current)) return yield* ObjectType(path, current, next) if (IsArray(current)) return yield* ArrayType(path, current, next) if (IsTypedArray(current)) return yield* TypedArrayType(path, current, next) if (IsValueType(current)) return yield* ValueType(path, current, next) throw new ValueDiffError(current, 'Unable to diff value') } // ------------------------------------------------------------------ // Diff // ------------------------------------------------------------------ export function Diff(current: unknown, next: unknown): Edit[] { return [...Visit('', current, next)] } // ------------------------------------------------------------------ // Patch // ------------------------------------------------------------------ function IsRootUpdate(edits: Edit[]): edits is [Update] { return edits.length > 0 && edits[0].path === '' && edits[0].type === 'update' } function IsIdentity(edits: Edit[]) { return edits.length === 0 } export function Patch(current: unknown, edits: Edit[]): T { if (IsRootUpdate(edits)) { return Clone(edits[0].value) as T } if (IsIdentity(edits)) { return Clone(current) as T } const clone = Clone(current) for (const edit of edits) { switch (edit.type) { case 'insert': { ValuePointer.Set(clone, edit.path, edit.value) break } case 'update': { ValuePointer.Set(clone, edit.path, edit.value) break } case 'delete': { ValuePointer.Delete(clone, edit.path) break } } } return clone as T } sinclairzx81-typebox-e0ec98c/src/value/delta/index.ts000066400000000000000000000024641505437577000227410ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './delta' sinclairzx81-typebox-e0ec98c/src/value/deref/000077500000000000000000000000001505437577000212505ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/deref/deref.ts000066400000000000000000000052061505437577000227100ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 '../../type/schema/index' import type { TRef } from '../../type/ref/index' import type { TThis } from '../../type/recursive/index' import { TypeBoxError } from '../../type/error/index' import { Kind } from '../../type/symbols/index' import { IsString } from '../guard/guard' export class TypeDereferenceError extends TypeBoxError { constructor(public readonly schema: TRef | TThis) { super(`Unable to dereference schema with $id '${schema.$ref}'`) } } function Resolve(schema: TThis | TRef, references: TSchema[]): TSchema { const target = references.find((target) => target.$id === schema.$ref) if (target === undefined) throw new TypeDereferenceError(schema) return Deref(target, references) } /** `[Internal]` Pushes a schema onto references if the schema has an $id and does not exist on references */ export function Pushref(schema: TSchema, references: TSchema[]): TSchema[] { if (!IsString(schema.$id) || references.some((target) => target.$id === schema.$id)) return references references.push(schema) return references } /** `[Internal]` Dereferences a schema from the references array or throws if not found */ export function Deref(schema: TSchema, references: TSchema[]): TSchema { // prettier-ignore return (schema[Kind] === 'This' || schema[Kind] === 'Ref') ? Resolve(schema as never, references) : schema } sinclairzx81-typebox-e0ec98c/src/value/deref/index.ts000066400000000000000000000024641505437577000227350ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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' sinclairzx81-typebox-e0ec98c/src/value/encode/000077500000000000000000000000001505437577000214205ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/encode/encode.ts000066400000000000000000000046131505437577000232310ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { HasTransform, TransformEncode, TransformEncodeCheckError } from '../transform/index' import { Check } from '../check/index' import { Errors } from '../../errors/index' import type { TSchema } from '../../type/schema/index' import type { StaticEncode } from '../../type/static/index' /** Encodes a value or throws if error */ export function Encode, Result extends Static = Static>(schema: T, references: TSchema[], value: unknown): Result /** Encodes a value or throws if error */ export function Encode, Result extends Static = Static>(schema: T, value: unknown): Result /** Encodes a value or throws if error */ export function Encode(...args: any[]): any { const [schema, references, value] = args.length === 3 ? [args[0], args[1], args[2]] : [args[0], [], args[1]] const encoded = HasTransform(schema, references) ? TransformEncode(schema, references, value) : value if (!Check(schema, references, encoded)) throw new TransformEncodeCheckError(schema, encoded, Errors(schema, references, encoded).First()!) return encoded } sinclairzx81-typebox-e0ec98c/src/value/encode/index.ts000066400000000000000000000024651505437577000231060ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './encode' sinclairzx81-typebox-e0ec98c/src/value/equal/000077500000000000000000000000001505437577000212725ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/equal/equal.ts000066400000000000000000000064101505437577000227520ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, IsDate, IsArray, IsTypedArray, IsValueType } from '../guard/index' import type { ObjectType, ArrayType, TypedArrayType, ValueType } from '../guard/index' // ------------------------------------------------------------------ // Equality Checks // ------------------------------------------------------------------ function ObjectType(left: ObjectType, right: unknown): boolean { if (!IsObject(right)) return false const leftKeys = [...Object.keys(left), ...Object.getOwnPropertySymbols(left)] const rightKeys = [...Object.keys(right), ...Object.getOwnPropertySymbols(right)] if (leftKeys.length !== rightKeys.length) return false return leftKeys.every((key) => Equal(left[key], right[key])) } function DateType(left: Date, right: unknown): any { return IsDate(right) && left.getTime() === right.getTime() } function ArrayType(left: ArrayType, right: unknown): any { if (!IsArray(right) || left.length !== right.length) return false return left.every((value, index) => Equal(value, right[index])) } function TypedArrayType(left: TypedArrayType, right: unknown): any { if (!IsTypedArray(right) || left.length !== right.length || Object.getPrototypeOf(left).constructor.name !== Object.getPrototypeOf(right).constructor.name) return false return left.every((value, index) => Equal(value, right[index])) } function ValueType(left: ValueType, right: unknown): any { return left === right } // ------------------------------------------------------------------ // Equal // ------------------------------------------------------------------ /** Returns true if the left value deep-equals the right */ export function Equal(left: T, right: unknown): right is T { if (IsDate(left)) return DateType(left, right) if (IsTypedArray(left)) return TypedArrayType(left, right) if (IsArray(left)) return ArrayType(left, right) if (IsObject(left)) return ObjectType(left, right) if (IsValueType(left)) return ValueType(left, right) throw new Error('ValueEquals: Unable to compare value') } sinclairzx81-typebox-e0ec98c/src/value/equal/index.ts000066400000000000000000000024641505437577000227570ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './equal' sinclairzx81-typebox-e0ec98c/src/value/guard/000077500000000000000000000000001505437577000212655ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/guard/guard.ts000066400000000000000000000212261505437577000227420ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // Types // ------------------------------------------------------------------ export type ObjectType = Record export type ArrayType = unknown[] export type ValueType = null | undefined | symbol | bigint | number | boolean | string // prettier-ignore export type TypedArrayType = | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array // -------------------------------------------------------------------------- // Iterators // -------------------------------------------------------------------------- /** Returns true if this value is an async iterator */ export function IsAsyncIterator(value: unknown): value is AsyncIterableIterator { return IsObject(value) && globalThis.Symbol.asyncIterator in value } /** Returns true if this value is an iterator */ export function IsIterator(value: unknown): value is IterableIterator { return IsObject(value) && globalThis.Symbol.iterator in value } // -------------------------------------------------------------------------- // Object Instances // -------------------------------------------------------------------------- /** Returns true if this value is not an instance of a class */ export function IsStandardObject(value: unknown): value is ObjectType { return IsObject(value) && (globalThis.Object.getPrototypeOf(value) === Object.prototype || globalThis.Object.getPrototypeOf(value) === null) } /** Returns true if this value is an instance of a class */ export function IsInstanceObject(value: unknown): value is ObjectType { return IsObject(value) && !IsArray(value) && IsFunction(value.constructor) && value.constructor.name !== 'Object' } // -------------------------------------------------------------------------- // JavaScript // -------------------------------------------------------------------------- /** Returns true if this value is a Promise */ export function IsPromise(value: unknown): value is Promise { return value instanceof globalThis.Promise } /** Returns true if this value is a Date */ export function IsDate(value: unknown): value is Date { return value instanceof Date && globalThis.Number.isFinite(value.getTime()) } /** Returns true if this value is an instance of Map */ export function IsMap(value: unknown): value is Map { return value instanceof globalThis.Map } /** Returns true if this value is an instance of Set */ export function IsSet(value: unknown): value is Set { return value instanceof globalThis.Set } /** 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 a typed array */ export function IsTypedArray(value: unknown): value is TypedArrayType { return globalThis.ArrayBuffer.isView(value) } /** Returns true if the value is a Int8Array */ export function IsInt8Array(value: unknown): value is Int8Array { return value instanceof globalThis.Int8Array } /** Returns true if the value is a Uint8Array */ export function IsUint8Array(value: unknown): value is Uint8Array { return value instanceof globalThis.Uint8Array } /** Returns true if the value is a Uint8ClampedArray */ export function IsUint8ClampedArray(value: unknown): value is Uint8ClampedArray { return value instanceof globalThis.Uint8ClampedArray } /** Returns true if the value is a Int16Array */ export function IsInt16Array(value: unknown): value is Int16Array { return value instanceof globalThis.Int16Array } /** Returns true if the value is a Uint16Array */ export function IsUint16Array(value: unknown): value is Uint16Array { return value instanceof globalThis.Uint16Array } /** Returns true if the value is a Int32Array */ export function IsInt32Array(value: unknown): value is Int32Array { return value instanceof globalThis.Int32Array } /** Returns true if the value is a Uint32Array */ export function IsUint32Array(value: unknown): value is Uint32Array { return value instanceof globalThis.Uint32Array } /** Returns true if the value is a Float32Array */ export function IsFloat32Array(value: unknown): value is Float32Array { return value instanceof globalThis.Float32Array } /** Returns true if the value is a Float64Array */ export function IsFloat64Array(value: unknown): value is Float64Array { return value instanceof globalThis.Float64Array } /** Returns true if the value is a BigInt64Array */ export function IsBigInt64Array(value: unknown): value is BigInt64Array { return value instanceof globalThis.BigInt64Array } /** Returns true if the value is a BigUint64Array */ export function IsBigUint64Array(value: unknown): value is BigUint64Array { return value instanceof globalThis.BigUint64Array } // -------------------------------------------------------------------------- // PropertyKey // -------------------------------------------------------------------------- /** Returns true if this value has this property key */ export function HasPropertyKey(value: Record, key: K): value is Record & { [_ in K]: unknown } { return key in value } // -------------------------------------------------------------------------- // Standard // -------------------------------------------------------------------------- /** Returns true of this value is an object type */ export function IsObject(value: unknown): value is ObjectType { return value !== null && typeof value === 'object' } /** Returns true if this value is an array, but not a typed array */ export function IsArray(value: unknown): value is ArrayType { return globalThis.Array.isArray(value) && !globalThis.ArrayBuffer.isView(value) } /** Returns true if this value is an undefined */ export function IsUndefined(value: unknown): value is undefined { return value === undefined } /** Returns true if this value is an null */ export function IsNull(value: unknown): value is null { return value === null } /** Returns true if this value is an boolean */ export function IsBoolean(value: unknown): value is boolean { return typeof value === 'boolean' } /** Returns true if this value is an number */ export function IsNumber(value: unknown): value is number { return typeof value === 'number' } /** Returns true if this value is an integer */ export function IsInteger(value: unknown): value is number { return globalThis.Number.isInteger(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 string */ export function IsString(value: unknown): value is string { return typeof value === 'string' } /** 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 a symbol */ export function IsSymbol(value: unknown): value is symbol { return typeof value === 'symbol' } /** Returns true if this value is a value type such as number, string, boolean */ export function IsValueType(value: unknown): value is ValueType { // prettier-ignore return ( IsBigInt(value) || IsBoolean(value) || IsNull(value) || IsNumber(value) || IsString(value) || IsSymbol(value) || IsUndefined(value) ) } sinclairzx81-typebox-e0ec98c/src/value/guard/index.ts000066400000000000000000000024641505437577000227520ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './guard' sinclairzx81-typebox-e0ec98c/src/value/hash/000077500000000000000000000000001505437577000211065ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/hash/hash.ts000066400000000000000000000127241505437577000224070ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { IsArray, IsBoolean, IsBigInt, IsDate, IsNull, IsNumber, IsObject, IsString, IsSymbol, IsUint8Array, IsUndefined } from '../guard/index' import { TypeBoxError } from '../../type/error/index' // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class ValueHashError extends TypeBoxError { constructor(public readonly value: unknown) { super(`Unable to hash value`) } } // ------------------------------------------------------------------ // ByteMarker // ------------------------------------------------------------------ enum ByteMarker { Undefined, Null, Boolean, Number, String, Object, Array, Date, Uint8Array, Symbol, BigInt, } // ------------------------------------------------------------------ // State // ------------------------------------------------------------------ let Accumulator = BigInt('14695981039346656037') const [Prime, Size] = [BigInt('1099511628211'), BigInt('18446744073709551616' /* 2 ^ 64 */)] const Bytes = Array.from({ length: 256 }).map((_, i) => BigInt(i)) const F64 = new Float64Array(1) const F64In = new DataView(F64.buffer) const F64Out = new Uint8Array(F64.buffer) // ------------------------------------------------------------------ // NumberToBytes // ------------------------------------------------------------------ function* NumberToBytes(value: number): IterableIterator { const byteCount = value === 0 ? 1 : Math.ceil(Math.floor(Math.log2(value) + 1) / 8) for (let i = 0; i < byteCount; i++) { yield (value >> (8 * (byteCount - 1 - i))) & 0xff } } // ------------------------------------------------------------------ // Hashing Functions // ------------------------------------------------------------------ function ArrayType(value: Array) { FNV1A64(ByteMarker.Array) for (const item of value) { Visit(item) } } function BooleanType(value: boolean) { FNV1A64(ByteMarker.Boolean) FNV1A64(value ? 1 : 0) } function BigIntType(value: bigint) { FNV1A64(ByteMarker.BigInt) F64In.setBigInt64(0, value) for (const byte of F64Out) { FNV1A64(byte) } } function DateType(value: Date) { FNV1A64(ByteMarker.Date) Visit(value.getTime()) } function NullType(value: null) { FNV1A64(ByteMarker.Null) } function NumberType(value: number) { FNV1A64(ByteMarker.Number) F64In.setFloat64(0, value) for (const byte of F64Out) { FNV1A64(byte) } } function ObjectType(value: Record) { FNV1A64(ByteMarker.Object) for (const key of globalThis.Object.getOwnPropertyNames(value).sort()) { Visit(key) Visit(value[key]) } } function StringType(value: string) { FNV1A64(ByteMarker.String) for (let i = 0; i < value.length; i++) { for (const byte of NumberToBytes(value.charCodeAt(i))) { FNV1A64(byte) } } } function SymbolType(value: symbol) { FNV1A64(ByteMarker.Symbol) Visit(value.description) } function Uint8ArrayType(value: Uint8Array) { FNV1A64(ByteMarker.Uint8Array) for (let i = 0; i < value.length; i++) { FNV1A64(value[i]) } } function UndefinedType(value: undefined) { return FNV1A64(ByteMarker.Undefined) } function Visit(value: any) { if (IsArray(value)) return ArrayType(value) if (IsBoolean(value)) return BooleanType(value) if (IsBigInt(value)) return BigIntType(value) if (IsDate(value)) return DateType(value) if (IsNull(value)) return NullType(value) if (IsNumber(value)) return NumberType(value) if (IsObject(value)) return ObjectType(value) if (IsString(value)) return StringType(value) if (IsSymbol(value)) return SymbolType(value) if (IsUint8Array(value)) return Uint8ArrayType(value) if (IsUndefined(value)) return UndefinedType(value) throw new ValueHashError(value) } function FNV1A64(byte: number) { Accumulator = Accumulator ^ Bytes[byte] Accumulator = (Accumulator * Prime) % Size } // ------------------------------------------------------------------ // Hash // ------------------------------------------------------------------ /** Creates a FNV1A-64 non cryptographic hash of the given value */ export function Hash(value: unknown) { Accumulator = BigInt('14695981039346656037') Visit(value) return Accumulator } sinclairzx81-typebox-e0ec98c/src/value/hash/index.ts000066400000000000000000000024631505437577000225720ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './hash' sinclairzx81-typebox-e0ec98c/src/value/index.ts000066400000000000000000000050461505437577000216470ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ // ------------------------------------------------------------------ // Errors (re-export) // ------------------------------------------------------------------ export { ValueError, ValueErrorType, ValueErrorIterator } from '../errors/index' // ------------------------------------------------------------------ // Guards // ------------------------------------------------------------------ export * from './guard/index' // ------------------------------------------------------------------ // Operators // ------------------------------------------------------------------ export * from './assert/index' export * from './cast/index' export * from './check/index' export * from './clean/index' export * from './clone/index' export * from './convert/index' export * from './create/index' export * from './decode/index' export * from './default/index' export * from './delta/index' export * from './encode/index' export * from './equal/index' export * from './hash/index' export * from './mutate/index' export * from './parse/index' export * from './pointer/index' export * from './transform/index' // ------------------------------------------------------------------ // Namespace // ------------------------------------------------------------------ export { Value } from './value/index' sinclairzx81-typebox-e0ec98c/src/value/mutate/000077500000000000000000000000001505437577000214625ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/mutate/index.ts000066400000000000000000000024651505437577000231500ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './mutate' sinclairzx81-typebox-e0ec98c/src/value/mutate/mutate.ts000066400000000000000000000122221505437577000233300ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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, IsTypedArray, IsValueType, type TypedArrayType } from '../guard/index' import { ValuePointer } from '../pointer/index' import { Clone } from '../clone/index' import { TypeBoxError } from '../../type/error/index' // ------------------------------------------------------------------ // IsStandardObject // ------------------------------------------------------------------ function IsStandardObject(value: unknown): value is Record { return IsObject(value) && !IsArray(value) } // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class ValueMutateError extends TypeBoxError { constructor(message: string) { super(message) } } // ------------------------------------------------------------------ // Mutators // ------------------------------------------------------------------ export type Mutable = { [key: string]: unknown } | unknown[] function ObjectType(root: Mutable, path: string, current: unknown, next: Record) { if (!IsStandardObject(current)) { ValuePointer.Set(root, path, Clone(next)) } else { const currentKeys = Object.getOwnPropertyNames(current) const nextKeys = Object.getOwnPropertyNames(next) for (const currentKey of currentKeys) { if (!nextKeys.includes(currentKey)) { delete current[currentKey] } } for (const nextKey of nextKeys) { if (!currentKeys.includes(nextKey)) { current[nextKey] = null } } for (const nextKey of nextKeys) { Visit(root, `${path}/${nextKey}`, current[nextKey], next[nextKey]) } } } function ArrayType(root: Mutable, path: string, current: unknown, next: unknown[]) { if (!IsArray(current)) { ValuePointer.Set(root, path, Clone(next)) } else { for (let index = 0; index < next.length; index++) { Visit(root, `${path}/${index}`, current[index], next[index]) } current.splice(next.length) } } function TypedArrayType(root: Mutable, path: string, current: unknown, next: TypedArrayType) { if (IsTypedArray(current) && current.length === next.length) { for (let i = 0; i < current.length; i++) { current[i] = next[i] } } else { ValuePointer.Set(root, path, Clone(next)) } } function ValueType(root: Mutable, path: string, current: unknown, next: unknown) { if (current === next) return ValuePointer.Set(root, path, next) } function Visit(root: Mutable, path: string, current: unknown, next: unknown) { if (IsArray(next)) return ArrayType(root, path, current, next) if (IsTypedArray(next)) return TypedArrayType(root, path, current, next) if (IsStandardObject(next)) return ObjectType(root, path, current, next) if (IsValueType(next)) return ValueType(root, path, current, next) } // ------------------------------------------------------------------ // IsNonMutableValue // ------------------------------------------------------------------ function IsNonMutableValue(value: unknown): value is Mutable { return IsTypedArray(value) || IsValueType(value) } function IsMismatchedValue(current: unknown, next: unknown) { // prettier-ignore return ( (IsStandardObject(current) && IsArray(next)) || (IsArray(current) && IsStandardObject(next)) ) } // ------------------------------------------------------------------ // Mutate // ------------------------------------------------------------------ /** `[Mutable]` Performs a deep mutable value assignment while retaining internal references */ export function Mutate(current: Mutable, next: Mutable): void { if (IsNonMutableValue(current) || IsNonMutableValue(next)) throw new ValueMutateError('Only object and array types can be mutated at the root level') if (IsMismatchedValue(current, next)) throw new ValueMutateError('Cannot assign due type mismatch of assignable values') Visit(current, '', current, next) } sinclairzx81-typebox-e0ec98c/src/value/parse/000077500000000000000000000000001505437577000212755ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/parse/index.ts000066400000000000000000000024641505437577000227620ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './parse' sinclairzx81-typebox-e0ec98c/src/value/parse/parse.ts000066400000000000000000000143641505437577000227670ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeBoxError } from '../../type/error/index' import { TransformDecode, TransformEncode, HasTransform } from '../transform/index' import { TSchema } from '../../type/schema/index' import { StaticDecode } from '../../type/static/index' import { Assert } from '../assert/index' import { Cast } from '../cast/index' import { Clean } from '../clean/index' import { Clone } from '../clone/index' import { Convert } from '../convert/index' import { Default } from '../default/index' // ------------------------------------------------------------------ // Guards // ------------------------------------------------------------------ import { IsArray, IsUndefined } from '../guard/index' // ------------------------------------------------------------------ // Error // ------------------------------------------------------------------ export class ParseError extends TypeBoxError { constructor(message: string) { super(message) } } // ------------------------------------------------------------------ // ParseRegistry // ------------------------------------------------------------------ export type TParseOperation = 'Assert' | 'Cast' | 'Clean' | 'Clone' | 'Convert' | 'Decode' | 'Default' | 'Encode' | ({} & string) export type TParseFunction = (type: TSchema, references: TSchema[], value: unknown) => unknown // prettier-ignore export namespace ParseRegistry { const registry = new Map([ ['Assert', (type, references, value: unknown) => { Assert(type, references, value); return value }], ['Cast', (type, references, value: unknown) => Cast(type, references, value)], ['Clean', (type, references, value: unknown) => Clean(type, references, value)], ['Clone', (_type, _references, value: unknown) => Clone(value)], ['Convert', (type, references, value: unknown) => Convert(type, references, value)], ['Decode', (type, references, value: unknown) => (HasTransform(type, references) ? TransformDecode(type, references, value) : value)], ['Default', (type, references, value: unknown) => Default(type, references, value)], ['Encode', (type, references, value: unknown) => (HasTransform(type, references) ? TransformEncode(type, references, value) : value)], ]) // Deletes an entry from the registry export function Delete(key: string): void { registry.delete(key) } // Sets an entry in the registry export function Set(key: string, callback: TParseFunction): void { registry.set(key, callback) } // Gets an entry in the registry export function Get(key: string): TParseFunction | undefined { return registry.get(key) } } // ------------------------------------------------------------------ // Default Parse Pipeline // ------------------------------------------------------------------ // prettier-ignore export const ParseDefault = [ 'Clone', 'Clean', 'Default', 'Convert', 'Assert', 'Decode' ] as const // ------------------------------------------------------------------ // ParseValue // ------------------------------------------------------------------ function ParseValue = StaticDecode>(operations: TParseOperation[], type: Type, references: TSchema[], value: unknown): Result { return operations.reduce((value, operationKey) => { const operation = ParseRegistry.Get(operationKey) if (IsUndefined(operation)) throw new ParseError(`Unable to find Parse operation '${operationKey}'`) return operation(type, references, value) }, value) as Result } // ------------------------------------------------------------------ // Parse // ------------------------------------------------------------------ /** Parses a value using the default parse pipeline. Will throws an `AssertError` if invalid. */ export function Parse, Result extends Output = Output>(schema: Type, references: TSchema[], value: unknown): Result /** Parses a value using the default parse pipeline. Will throws an `AssertError` if invalid. */ export function Parse, Result extends Output = Output>(schema: Type, value: unknown): Result /** Parses a value using the specified operations. */ export function Parse(operations: TParseOperation[], schema: Type, references: TSchema[], value: unknown): unknown /** Parses a value using the specified operations. */ export function Parse(operations: TParseOperation[], schema: Type, value: unknown): unknown /** Parses a value */ export function Parse(...args: any[]): unknown { // prettier-ignore const [operations, schema, references, value] = ( args.length === 4 ? [args[0], args[1], args[2], args[3]] : args.length === 3 ? IsArray(args[0]) ? [args[0], args[1], [], args[2]] : [ParseDefault, args[0], args[1], args[2]] : args.length === 2 ? [ParseDefault, args[0], [], args[1]] : (() => { throw new ParseError('Invalid Arguments') })() ) return ParseValue(operations, schema, references, value) } sinclairzx81-typebox-e0ec98c/src/value/pointer/000077500000000000000000000000001505437577000216435ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/pointer/index.ts000066400000000000000000000025061505437577000233250ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 ValuePointer from './pointer' sinclairzx81-typebox-e0ec98c/src/value/pointer/pointer.ts000066400000000000000000000111771505437577000237020ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeBoxError } from '../../type/error/index' // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ export class ValuePointerRootSetError extends TypeBoxError { constructor(public readonly value: unknown, public readonly path: string, public readonly update: unknown) { super('Cannot set root value') } } export class ValuePointerRootDeleteError extends TypeBoxError { constructor(public readonly value: unknown, public readonly path: string) { super('Cannot delete root value') } } // ------------------------------------------------------------------ // ValuePointer // ------------------------------------------------------------------ /** Provides functionality to update values through RFC6901 string pointers */ // prettier-ignore function Escape(component: string) { return component.indexOf('~') === -1 ? component : component.replace(/~1/g, '/').replace(/~0/g, '~') } /** Formats the given pointer into navigable key components */ // prettier-ignore export function* Format(pointer: string): IterableIterator { if (pointer === '') return let [start, end] = [0, 0] for (let i = 0; i < pointer.length; i++) { const char = pointer.charAt(i) if (char === '/') { if (i === 0) { start = i + 1 } else { end = i yield Escape(pointer.slice(start, end)) start = i + 1 } } else { end = i } } yield Escape(pointer.slice(start)) } /** Sets the value at the given pointer. If the value at the pointer does not exist it is created */ // prettier-ignore export function Set(value: any, pointer: string, update: unknown): void { if (pointer === '') throw new ValuePointerRootSetError(value, pointer, update) let [owner, next, key] = [null as any, value, ''] for (const component of Format(pointer)) { if (next[component] === undefined) next[component] = {} owner = next next = next[component] key = component } owner[key] = update } /** Deletes a value at the given pointer */ // prettier-ignore export function Delete(value: any, pointer: string): void { if (pointer === '') throw new ValuePointerRootDeleteError(value, pointer) let [owner, next, key] = [null as any, value as any, ''] for (const component of Format(pointer)) { if (next[component] === undefined || next[component] === null) return owner = next next = next[component] key = component } if (Array.isArray(owner)) { const index = parseInt(key) owner.splice(index, 1) } else { delete owner[key] } } /** Returns true if a value exists at the given pointer */ // prettier-ignore export function Has(value: any, pointer: string): boolean { if (pointer === '') return true let [owner, next, key] = [null as any, value as any, ''] for (const component of Format(pointer)) { if (next[component] === undefined) return false owner = next next = next[component] key = component } return Object.getOwnPropertyNames(owner).includes(key) } /** Gets the value at the given pointer */ // prettier-ignore export function Get(value: any, pointer: string): any { if (pointer === '') return value let current = value for (const component of Format(pointer)) { if (current[component] === undefined) return undefined current = current[component] } return current } sinclairzx81-typebox-e0ec98c/src/value/transform/000077500000000000000000000000001505437577000221765ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/transform/decode.ts000066400000000000000000000260361505437577000240000ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeSystemPolicy } from '../../system/policy' import { Kind, TransformKind } from '../../type/symbols/index' import { TypeBoxError } from '../../type/error/index' import { ValueError } from '../../errors/index' import { KeyOfPropertyKeys, KeyOfPropertyEntries } from '../../type/keyof/index' import { Deref, Pushref } from '../deref/index' import { Check } from '../check/index' import type { TSchema } from '../../type/schema/index' import type { TArray } from '../../type/array/index' import type { TImport } from '../../type/module/index' import type { TIntersect } from '../../type/intersect/index' import type { TNot } from '../../type/not/index' import type { TObject } from '../../type/object/index' import type { TRecord } from '../../type/record/index' import type { TRef } from '../../type/ref/index' import type { TThis } from '../../type/recursive/index' import type { TTuple } from '../../type/tuple/index' import type { TUnion } from '../../type/union/index' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ import { HasPropertyKey, IsObject, IsArray, IsValueType, IsUndefined as IsUndefinedValue } from '../guard/index' // ------------------------------------------------------------------ // KindGuard // ------------------------------------------------------------------ import { IsTransform, IsSchema, IsUndefined } from '../../type/guard/kind' // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ // thrown externally // prettier-ignore export class TransformDecodeCheckError extends TypeBoxError { constructor( public readonly schema: TSchema, public readonly value: unknown, public readonly error: ValueError ) { super(`Unable to decode value as it does not match the expected schema`) } } // prettier-ignore export class TransformDecodeError extends TypeBoxError { constructor( public readonly schema: TSchema, public readonly path: string, public readonly value: unknown, public readonly error: Error, ) { super(error instanceof Error ? error.message : 'Unknown error') } } // ------------------------------------------------------------------ // Decode // ------------------------------------------------------------------ // prettier-ignore function Default(schema: TSchema, path: string, value: any): unknown { try { return IsTransform(schema) ? schema[TransformKind].Decode(value) : value } catch (error) { throw new TransformDecodeError(schema, path, value, error as Error) } } // prettier-ignore function FromArray(schema: TArray, references: TSchema[], path: string, value: any): unknown { return (IsArray(value)) ? Default(schema, path, value.map((value: any, index) => Visit(schema.items, references, `${path}/${index}`, value))) : Default(schema, path, value) } // prettier-ignore function FromIntersect(schema: TIntersect, references: TSchema[], path: string, value: any): unknown { if (!IsObject(value) || IsValueType(value)) return Default(schema, path, value) const knownEntries = KeyOfPropertyEntries(schema) const knownKeys = knownEntries.map(entry => entry[0]) const knownProperties = { ...value } as Record for(const [knownKey, knownSchema] of knownEntries) if(knownKey in knownProperties) { knownProperties[knownKey] = Visit(knownSchema, references, `${path}/${knownKey}`, knownProperties[knownKey]) } if (!IsTransform(schema.unevaluatedProperties)) { return Default(schema, path, knownProperties) } const unknownKeys = Object.getOwnPropertyNames(knownProperties) const unevaluatedProperties = schema.unevaluatedProperties as TSchema const unknownProperties = { ...knownProperties } as Record for(const key of unknownKeys) if(!knownKeys.includes(key)) { unknownProperties[key] = Default(unevaluatedProperties, `${path}/${key}`, unknownProperties[key]) } return Default(schema, path, unknownProperties) } // prettier-ignore function FromImport(schema: TImport, references: TSchema[], path: string, value: unknown): unknown { const additional = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema const result = Visit(target, [...references, ...additional], path, value) return Default(schema, path, result) } function FromNot(schema: TNot, references: TSchema[], path: string, value: any): unknown { return Default(schema, path, Visit(schema.not, references, path, value)) } // prettier-ignore function FromObject(schema: TObject, references: TSchema[], path: string, value: any): unknown { if (!IsObject(value)) return Default(schema, path, value) const knownKeys = KeyOfPropertyKeys(schema) as string[] const knownProperties = { ...value } as Record for(const key of knownKeys) { if(!HasPropertyKey(knownProperties, key)) continue // if the property value is undefined, but the target is not, nor does it satisfy exact optional // property policy, then we need to continue. This is a special case for optional property handling // where a transforms wrapped in a optional modifiers should not run. if(IsUndefinedValue(knownProperties[key]) && ( !IsUndefined(schema.properties[key]) || TypeSystemPolicy.IsExactOptionalProperty(knownProperties, key) )) continue // decode property knownProperties[key] = Visit(schema.properties[key], references, `${path}/${key}`, knownProperties[key]) } if (!IsSchema(schema.additionalProperties)) { return Default(schema, path, knownProperties) } const unknownKeys = Object.getOwnPropertyNames(knownProperties) const additionalProperties = schema.additionalProperties as TSchema const unknownProperties = { ...knownProperties } as Record for(const key of unknownKeys) if(!knownKeys.includes(key)) { unknownProperties[key] = Default(additionalProperties, `${path}/${key}`, unknownProperties[key]) } return Default(schema, path, unknownProperties) } // prettier-ignore function FromRecord(schema: TRecord, references: TSchema[], path: string, value: any): unknown { if (!IsObject(value)) return Default(schema, path, value) const pattern = Object.getOwnPropertyNames(schema.patternProperties)[0] const knownKeys = new RegExp(pattern) const knownProperties = { ...value } as Record for(const key of Object.getOwnPropertyNames(value)) if(knownKeys.test(key)) { knownProperties[key] = Visit(schema.patternProperties[pattern], references, `${path}/${key}`, knownProperties[key]) } if (!IsSchema(schema.additionalProperties)) { return Default(schema, path, knownProperties) } const unknownKeys = Object.getOwnPropertyNames(knownProperties) const additionalProperties = schema.additionalProperties as TSchema const unknownProperties = {...knownProperties} as Record for(const key of unknownKeys) if(!knownKeys.test(key)) { unknownProperties[key] = Default(additionalProperties, `${path}/${key}`, unknownProperties[key]) } return Default(schema, path, unknownProperties) } // prettier-ignore function FromRef(schema: TRef, references: TSchema[], path: string, value: any): unknown { const target = Deref(schema, references) return Default(schema, path, Visit(target, references, path, value)) } // prettier-ignore function FromThis(schema: TThis, references: TSchema[], path: string, value: any): unknown { const target = Deref(schema, references) return Default(schema, path, Visit(target, references, path, value)) } // prettier-ignore function FromTuple(schema: TTuple, references: TSchema[], path: string, value: any): unknown { return (IsArray(value) && IsArray(schema.items)) ? Default(schema, path, schema.items.map((schema, index) => Visit(schema, references, `${path}/${index}`, value[index]))) : Default(schema, path, value) } // prettier-ignore function FromUnion(schema: TUnion, references: TSchema[], path: string, value: any): unknown { for (const subschema of schema.anyOf) { if (!Check(subschema, references, value)) continue // note: ensure interior is decoded first const decoded = Visit(subschema, references, path, value) return Default(schema, path, decoded) } return Default(schema, path, value) } // prettier-ignore function Visit(schema: TSchema, references: TSchema[], path: string, value: any): any { const references_ = Pushref(schema, references) const schema_ = schema as any switch (schema[Kind]) { case 'Array': return FromArray(schema_, references_, path, value) case 'Import': return FromImport(schema_, references_, path, value) case 'Intersect': return FromIntersect(schema_, references_, path, value) case 'Not': return FromNot(schema_, references_, path, value) case 'Object': return FromObject(schema_, references_, path, value) case 'Record': return FromRecord(schema_, references_, path, value) case 'Ref': return FromRef(schema_, references_, path, value) case 'Symbol': return Default(schema_, path, value) case 'This': return FromThis(schema_, references_, path, value) case 'Tuple': return FromTuple(schema_, references_, path, value) case 'Union': return FromUnion(schema_, references_, path, value) default: return Default(schema_, path, value) } } /** * `[Internal]` Decodes the value and returns the result. This function requires that * the caller `Check` the value before use. Passing unchecked values may result in * undefined behavior. Refer to the `Value.Decode()` for implementation details. */ export function TransformDecode(schema: TSchema, references: TSchema[], value: unknown): unknown { return Visit(schema, references, '', value) } sinclairzx81-typebox-e0ec98c/src/value/transform/encode.ts000066400000000000000000000261651505437577000240150ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { TypeSystemPolicy } from '../../system/policy' import { Kind, TransformKind } from '../../type/symbols/index' import { TypeBoxError } from '../../type/error/index' import { ValueError } from '../../errors/index' import { KeyOfPropertyKeys, KeyOfPropertyEntries } from '../../type/keyof/index' import { Deref, Pushref } from '../deref/index' import { Check } from '../check/index' import type { TSchema } from '../../type/schema/index' import type { TArray } from '../../type/array/index' import type { TImport } from '../../type/module/index' import type { TIntersect } from '../../type/intersect/index' import type { TNot } from '../../type/not/index' import type { TObject } from '../../type/object/index' import type { TRecord } from '../../type/record/index' import type { TRef } from '../../type/ref/index' import type { TThis } from '../../type/recursive/index' import type { TTuple } from '../../type/tuple/index' import type { TUnion } from '../../type/union/index' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ import { HasPropertyKey, IsObject, IsArray, IsValueType, IsUndefined as IsUndefinedValue } from '../guard/index' // ------------------------------------------------------------------ // KindGuard // ------------------------------------------------------------------ import { IsTransform, IsSchema, IsUndefined } from '../../type/guard/kind' // ------------------------------------------------------------------ // Errors // ------------------------------------------------------------------ // prettier-ignore export class TransformEncodeCheckError extends TypeBoxError { constructor( public readonly schema: TSchema, public readonly value: unknown, public readonly error: ValueError ) { super(`The encoded value does not match the expected schema`) } } // prettier-ignore export class TransformEncodeError extends TypeBoxError { constructor( public readonly schema: TSchema, public readonly path: string, public readonly value: unknown, public readonly error: Error, ) { super(`${error instanceof Error ? error.message : 'Unknown error'}`) } } // ------------------------------------------------------------------ // Encode // ------------------------------------------------------------------ // prettier-ignore function Default(schema: TSchema, path: string, value: any) { try { return IsTransform(schema) ? schema[TransformKind].Encode(value) : value } catch (error) { throw new TransformEncodeError(schema, path, value, error as Error) } } // prettier-ignore function FromArray(schema: TArray, references: TSchema[], path: string, value: any): any { const defaulted = Default(schema, path, value) return IsArray(defaulted) ? defaulted.map((value: any, index) => Visit(schema.items, references, `${path}/${index}`, value)) : defaulted } // prettier-ignore function FromImport(schema: TImport, references: TSchema[], path: string, value: unknown): unknown { const additional = globalThis.Object.values(schema.$defs) as TSchema[] const target = schema.$defs[schema.$ref] as TSchema const result = Default(schema, path, value) return Visit(target, [...references, ...additional], path, result) } // prettier-ignore function FromIntersect(schema: TIntersect, references: TSchema[], path: string, value: any) { const defaulted = Default(schema, path, value) if (!IsObject(value) || IsValueType(value)) return defaulted const knownEntries = KeyOfPropertyEntries(schema) const knownKeys = knownEntries.map(entry => entry[0]) const knownProperties = { ...defaulted } as Record for(const [knownKey, knownSchema] of knownEntries) if(knownKey in knownProperties) { knownProperties[knownKey] = Visit(knownSchema, references, `${path}/${knownKey}`, knownProperties[knownKey]) } if (!IsTransform(schema.unevaluatedProperties)) { return knownProperties } const unknownKeys = Object.getOwnPropertyNames(knownProperties) const unevaluatedProperties = schema.unevaluatedProperties as TSchema const properties = { ...knownProperties } as Record for(const key of unknownKeys) if(!knownKeys.includes(key)) { properties[key] = Default(unevaluatedProperties, `${path}/${key}`, properties[key]) } return properties } // prettier-ignore function FromNot(schema: TNot, references: TSchema[], path: string, value: any) { return Default(schema.not, path, Default(schema, path, value)) } // prettier-ignore function FromObject(schema: TObject, references: TSchema[], path: string, value: any) { const defaulted = Default(schema, path, value) if (!IsObject(defaulted)) return defaulted const knownKeys = KeyOfPropertyKeys(schema) as string[] const knownProperties = { ...defaulted } as Record for(const key of knownKeys) { if(!HasPropertyKey(knownProperties, key)) continue // if the property value is undefined, but the target is not, nor does it satisfy exact optional // property policy, then we need to continue. This is a special case for optional property handling // where a transforms wrapped in a optional modifiers should not run. if(IsUndefinedValue(knownProperties[key]) && ( !IsUndefined(schema.properties[key]) || TypeSystemPolicy.IsExactOptionalProperty(knownProperties, key) )) continue // encode property knownProperties[key] = Visit(schema.properties[key], references, `${path}/${key}`, knownProperties[key]) } if (!IsSchema(schema.additionalProperties)) { return knownProperties } const unknownKeys = Object.getOwnPropertyNames(knownProperties) const additionalProperties = schema.additionalProperties as TSchema const properties = { ...knownProperties } as Record for(const key of unknownKeys) if(!knownKeys.includes(key)) { properties[key] = Default(additionalProperties, `${path}/${key}`, properties[key]) } return properties } // prettier-ignore function FromRecord(schema: TRecord, references: TSchema[], path: string, value: any) { const defaulted = Default(schema, path, value) as Record if (!IsObject(value)) return defaulted const pattern = Object.getOwnPropertyNames(schema.patternProperties)[0] const knownKeys = new RegExp(pattern) const knownProperties = {...defaulted } as Record for(const key of Object.getOwnPropertyNames(value)) if(knownKeys.test(key)) { knownProperties[key] = Visit(schema.patternProperties[pattern], references, `${path}/${key}`, knownProperties[key]) } if (!IsSchema(schema.additionalProperties)) { return knownProperties } const unknownKeys = Object.getOwnPropertyNames(knownProperties) const additionalProperties = schema.additionalProperties as TSchema const properties = { ...knownProperties } as Record for(const key of unknownKeys) if(!knownKeys.test(key)) { properties[key] = Default(additionalProperties, `${path}/${key}`, properties[key]) } return properties } // prettier-ignore function FromRef(schema: TRef, references: TSchema[], path: string, value: any) { const target = Deref(schema, references) const resolved = Visit(target, references, path, value) return Default(schema, path, resolved) } // prettier-ignore function FromThis(schema: TThis, references: TSchema[], path: string, value: any) { const target = Deref(schema, references) const resolved = Visit(target, references, path, value) return Default(schema, path, resolved) } // prettier-ignore function FromTuple(schema: TTuple, references: TSchema[], path: string, value: any) { const value1 = Default(schema, path, value) return IsArray(schema.items) ? schema.items.map((schema, index) => Visit(schema, references, `${path}/${index}`, value1[index])) : [] } // prettier-ignore function FromUnion(schema: TUnion, references: TSchema[], path: string, value: any) { // test value against union variants for (const subschema of schema.anyOf) { if (!Check(subschema, references, value)) continue const value1 = Visit(subschema, references, path, value) return Default(schema, path, value1) } // test transformed value against union variants for (const subschema of schema.anyOf) { const value1 = Visit(subschema, references, path, value) if (!Check(schema, references, value1)) continue return Default(schema, path, value1) } return Default(schema, path, value) } // prettier-ignore function Visit(schema: TSchema, references: TSchema[], path: string, value: any): any { const references_ = Pushref(schema, references) const schema_ = schema as any switch (schema[Kind]) { case 'Array': return FromArray(schema_, references_, path, value) case 'Import': return FromImport(schema_, references_, path, value) case 'Intersect': return FromIntersect(schema_, references_, path, value) case 'Not': return FromNot(schema_, references_, path, value) case 'Object': return FromObject(schema_, references_, path, value) case 'Record': return FromRecord(schema_, references_, path, value) case 'Ref': return FromRef(schema_, references_, path, value) case 'This': return FromThis(schema_, references_, path, value) case 'Tuple': return FromTuple(schema_, references_, path, value) case 'Union': return FromUnion(schema_, references_, path, value) default: return Default(schema_, path, value) } } /** * `[Internal]` Encodes the value and returns the result. This function expects the * caller to pass a statically checked value. This function does not check the encoded * result, meaning the result should be passed to `Check` before use. Refer to the * `Value.Encode()` function for implementation details. */ export function TransformEncode(schema: TSchema, references: TSchema[], value: unknown): unknown { return Visit(schema, references, '', value) } sinclairzx81-typebox-e0ec98c/src/value/transform/has.ts000066400000000000000000000164551505437577000233340ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Deref, Pushref } from '../deref/index' import { Kind } from '../../type/symbols/index' import type { TSchema } from '../../type/schema/index' import type { TArray } from '../../type/array/index' import type { TAsyncIterator } from '../../type/async-iterator/index' import type { TConstructor } from '../../type/constructor/index' import type { TFunction } from '../../type/function/index' import type { TIntersect } from '../../type/intersect/index' import type { TIterator } from '../../type/iterator/index' import type { TImport } from '../../type/module/index' import type { TNot } from '../../type/not/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 { TThis } from '../../type/recursive/index' import type { TTuple } from '../../type/tuple/index' import type { TUnion } from '../../type/union/index' // ------------------------------------------------------------------ // KindGuard // ------------------------------------------------------------------ import { IsTransform, IsSchema } from '../../type/guard/kind' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ import { IsUndefined } from '../guard/index' // prettier-ignore function FromArray(schema: TArray, references: TSchema[]): boolean { return IsTransform(schema) || Visit(schema.items, references) } // prettier-ignore function FromAsyncIterator(schema: TAsyncIterator, references: TSchema[]): boolean { return IsTransform(schema) || Visit(schema.items, references) } // prettier-ignore function FromConstructor(schema: TConstructor, references: TSchema[]) { return IsTransform(schema) || Visit(schema.returns, references) || schema.parameters.some((schema) => Visit(schema, references)) } // prettier-ignore function FromFunction(schema: TFunction, references: TSchema[]) { return IsTransform(schema) || Visit(schema.returns, references) || schema.parameters.some((schema) => Visit(schema, references)) } // prettier-ignore function FromIntersect(schema: TIntersect, references: TSchema[]) { return IsTransform(schema) || IsTransform(schema.unevaluatedProperties) || schema.allOf.some((schema) => Visit(schema, references)) } // prettier-ignore function FromImport(schema: TImport, references: TSchema[]) { const additional = globalThis.Object.getOwnPropertyNames(schema.$defs).reduce((result, key) => [...result, schema.$defs[key as never]], [] as TSchema[]) const target = schema.$defs[schema.$ref] return IsTransform(schema) || Visit(target, [...additional, ...references]) } // prettier-ignore function FromIterator(schema: TIterator, references: TSchema[]) { return IsTransform(schema) || Visit(schema.items, references) } // prettier-ignore function FromNot(schema: TNot, references: TSchema[]) { return IsTransform(schema) || Visit(schema.not, references) } // prettier-ignore function FromObject(schema: TObject, references: TSchema[]) { return ( IsTransform(schema) || Object.values(schema.properties).some((schema) => Visit(schema, references)) || ( IsSchema(schema.additionalProperties) && Visit(schema.additionalProperties, references) ) ) } // prettier-ignore function FromPromise(schema: TPromise, references: TSchema[]) { return IsTransform(schema) || Visit(schema.item, references) } // prettier-ignore function FromRecord(schema: TRecord, references: TSchema[]) { const pattern = Object.getOwnPropertyNames(schema.patternProperties)[0] const property = schema.patternProperties[pattern] return IsTransform(schema) || Visit(property, references) || (IsSchema(schema.additionalProperties) && IsTransform(schema.additionalProperties)) } // prettier-ignore function FromRef(schema: TRef, references: TSchema[]) { if (IsTransform(schema)) return true return Visit(Deref(schema, references), references) } // prettier-ignore function FromThis(schema: TThis, references: TSchema[]) { if (IsTransform(schema)) return true return Visit(Deref(schema, references), references) } // prettier-ignore function FromTuple(schema: TTuple, references: TSchema[]) { return IsTransform(schema) || (!IsUndefined(schema.items) && schema.items.some((schema) => Visit(schema, references))) } // prettier-ignore function FromUnion(schema: TUnion, references: TSchema[]) { return IsTransform(schema) || schema.anyOf.some((schema) => Visit(schema, references)) } // prettier-ignore function Visit(schema: TSchema, references: TSchema[]): boolean { const references_ = Pushref(schema, references) const schema_ = schema as any if (schema.$id && visited.has(schema.$id)) return false if (schema.$id) visited.add(schema.$id) switch (schema[Kind]) { case 'Array': return FromArray(schema_, references_) case 'AsyncIterator': return FromAsyncIterator(schema_, references_) case 'Constructor': return FromConstructor(schema_, references_) case 'Function': return FromFunction(schema_, references_) case 'Import': return FromImport(schema_, references_) case 'Intersect': return FromIntersect(schema_, references_) case 'Iterator': return FromIterator(schema_, references_) case 'Not': return FromNot(schema_, references_) case 'Object': return FromObject(schema_, references_) case 'Promise': return FromPromise(schema_, references_) case 'Record': return FromRecord(schema_, references_) case 'Ref': return FromRef(schema_, references_) case 'This': return FromThis(schema_, references_) case 'Tuple': return FromTuple(schema_, references_) case 'Union': return FromUnion(schema_, references_) default: return IsTransform(schema) } } const visited = new Set() /** Returns true if this schema contains a transform codec */ export function HasTransform(schema: TSchema, references: TSchema[]): boolean { visited.clear() return Visit(schema, references) } sinclairzx81-typebox-e0ec98c/src/value/transform/index.ts000066400000000000000000000025441505437577000236620ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 './decode' export * from './encode' export * from './has' sinclairzx81-typebox-e0ec98c/src/value/value/000077500000000000000000000000001505437577000212775ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/src/value/value/index.ts000066400000000000000000000024751505437577000227660ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 Value from './value' sinclairzx81-typebox-e0ec98c/src/value/value/value.ts000066400000000000000000000037161505437577000227720ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { Errors, ValueErrorIterator } from '../../errors/index' export { Assert } from '../assert/index' export { Cast } from '../cast/index' export { Check } from '../check/index' export { Clean } from '../clean/index' export { Clone } from '../clone/index' export { Convert } from '../convert/index' export { Create } from '../create/index' export { Decode } from '../decode/index' export { Default } from '../default/index' export { Diff, Patch, Edit } from '../delta/index' export { Encode } from '../encode/index' export { Equal } from '../equal/index' export { Hash } from '../hash/index' export { Mutate, type Mutable } from '../mutate/index' export { Parse } from '../parse/index' sinclairzx81-typebox-e0ec98c/task/000077500000000000000000000000001505437577000172225ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/benchmark/000077500000000000000000000000001505437577000211545ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/benchmark/compression/000077500000000000000000000000001505437577000235155ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/benchmark/compression/index.ts000066400000000000000000000022741505437577000252010ustar00rootroot00000000000000import { shell } from '@sinclair/hammer' import { statSync, readdirSync } from 'fs' import { basename, extname } from 'path' export async function measure(test: string) { await shell(`hammer build task/benchmark/compression/module/${test}.ts --dist target/benchmark/compression`) const compiled = statSync(`target/benchmark/compression/${test}.js`) await shell(`hammer build task/benchmark/compression/module/${test}.ts --dist target/benchmark/compression --minify`) const minified = statSync(`target/benchmark/compression/${test}.js`) return { test: test.padEnd(20), compiled: `${(compiled.size / 1000).toFixed(1)} kb`.padStart(8), minified: `${(minified.size / 1000).toFixed(1)} kb`.padStart(8), ratio: compiled.size / minified.size, } } export async function compression() { const tests = readdirSync('task/benchmark/compression/module').map((name) => basename(name, extname(name))) const results = await Promise.all(tests.map((test) => measure(test))) const present = results.reduce((acc, c) => { return { ...acc, [c.test.replace(/-/g, '/')]: { Compiled: c.compiled, Minified: c.minified, Compression: `${c.ratio.toFixed(2)} x` } } }, {}) console.table(present) } sinclairzx81-typebox-e0ec98c/task/benchmark/compression/module/000077500000000000000000000000001505437577000250025ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/benchmark/compression/module/typebox-compiler.ts000066400000000000000000000001251505437577000306520ustar00rootroot00000000000000import { TypeCompiler } from '@sinclair/typebox/compiler' console.log(TypeCompiler) sinclairzx81-typebox-e0ec98c/task/benchmark/compression/module/typebox-errors.ts000066400000000000000000000001101505437577000303460ustar00rootroot00000000000000import * as Errors from '@sinclair/typebox/errors' console.log(Errors) sinclairzx81-typebox-e0ec98c/task/benchmark/compression/module/typebox-syntax.ts000066400000000000000000000001101505437577000303600ustar00rootroot00000000000000import * as Syntax from '@sinclair/typebox/syntax' console.log(Syntax) sinclairzx81-typebox-e0ec98c/task/benchmark/compression/module/typebox-system.ts000066400000000000000000000001171505437577000303650ustar00rootroot00000000000000import { TypeSystem } from '@sinclair/typebox/system' console.log(TypeSystem) sinclairzx81-typebox-e0ec98c/task/benchmark/compression/module/typebox-value.ts000066400000000000000000000001041505437577000301510ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' console.log(Value) sinclairzx81-typebox-e0ec98c/task/benchmark/compression/module/typebox.ts000066400000000000000000000001021505437577000270350ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' const T = Type.String() sinclairzx81-typebox-e0ec98c/task/benchmark/index.ts000066400000000000000000000001101505437577000226230ustar00rootroot00000000000000export * from './compression/index' export * from './measurement/index' sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/000077500000000000000000000000001505437577000235015ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/index.ts000066400000000000000000000002751505437577000251640ustar00rootroot00000000000000import { shell } from '@sinclair/hammer' export async function measurement() { await shell(`hammer run task/benchmark/measurement/module/index.ts --dist target/benchmark/measurement`) } sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/module/000077500000000000000000000000001505437577000247665ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/module/benchmark.ts000066400000000000000000000003741505437577000272740ustar00rootroot00000000000000export namespace Benchmark { export function Measure(execute: Function, iterations: number = 16_000_000) { const start = Date.now() for (let i = 0; i < iterations; i++) execute() return { iterations, completed: Date.now() - start } } } sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/module/cases.ts000066400000000000000000000101161505437577000264330ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' export namespace Cases { export const Literal_String = Type.Literal('hello') export const Literal_Number = Type.Literal(1) export const Literal_Boolean = Type.Literal(true) export const Primitive_Number = Type.Number() export const Primitive_String = Type.String() export const Primitive_String_Pattern = Type.String({ pattern: 'foo', default: 'foo' }) export const Primitive_Boolean = Type.Boolean() export const Primitive_Null = Type.Null() export const Object_Unconstrained = Type.Object({ number: Type.Number(), negNumber: Type.Number(), maxNumber: Type.Number(), string: Type.String(), longString: Type.String(), boolean: Type.Boolean(), deeplyNested: Type.Object({ foo: Type.String(), num: Type.Number(), bool: Type.Boolean(), }), }) export const Object_Constrained = Type.Object(Object_Unconstrained.properties, { additionalProperties: false, }) export const Object_Vector3 = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) export const Object_Box3D = Type.Object({ scale: Object_Vector3, position: Object_Vector3, rotate: Object_Vector3, pivot: Object_Vector3, }) export const Object_Recursive = Type.Recursive( (Recursive) => Type.Object({ id: Type.String(), nodes: Type.Array(Recursive), }), { default: { id: '', nodes: [ { id: '', nodes: [ { id: '', nodes: [] }, { id: '', nodes: [] }, { id: '', nodes: [] }, ], }, { id: '', nodes: [ { id: '', nodes: [] }, { id: '', nodes: [] }, { id: '', nodes: [] }, ], }, { id: '', nodes: [ { id: '', nodes: [] }, { id: '', nodes: [] }, { id: '', nodes: [] }, ], }, ], }, }, ) // prettier-ignore export const Tuple_Primitive = Type.Tuple([ Type.String(), Type.Number(), Type.Boolean() ]) // prettier-ignore export const Tuple_Object = Type.Tuple([ Type.Object({ x: Type.Number(), y: Type.Number() }), Type.Object({ a: Type.String(), b: Type.String() }) ]) // prettier-ignore export const Composite_Intersect = Type.Intersect([ Type.Object({ x: Type.Number(), y: Type.Number() }), Type.Object({ a: Type.String(), b: Type.String() }) ], { default: { x: 1, y: 2, a: 'a', b: 'b' } }) // prettier-ignore export const Composite_Union = Type.Union([ Type.Object({ x: Type.Number(), y: Type.Number() }), Type.Object({ a: Type.String(), b: Type.String() }) ], { default: { a: 'a', b: 'b' } }) export const Math_Vector4 = Type.Tuple([Type.Number(), Type.Number(), Type.Number(), Type.Number()]) export const Math_Matrix4 = Type.Array(Type.Array(Type.Number()), { default: [ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], ], }) export const Array_Primitive_Number = Type.Array(Type.Number(), { minItems: 4 }) export const Array_Primitive_String = Type.Array(Type.String(), { minItems: 4 }) export const Array_Primitive_Boolean = Type.Array(Type.Boolean(), { minItems: 4 }) export const Array_Object_Unconstrained = Type.Array(Object_Unconstrained, { minItems: 4 }) export const Array_Object_Constrained = Type.Array(Object_Constrained, { minItems: 4 }) export const Array_Object_Recursive = Type.Array(Object_Recursive, { minItems: 4 }) export const Array_Tuple_Primitive = Type.Array(Tuple_Primitive, { minItems: 4 }) export const Array_Tuple_Object = Type.Array(Tuple_Object, { minItems: 4 }) export const Array_Composite_Intersect = Type.Array(Composite_Intersect, { minItems: 4 }) export const Array_Composite_Union = Type.Array(Composite_Union, { minItems: 4 }) export const Array_Math_Vector4 = Type.Array(Math_Vector4, { minItems: 4 }) export const Array_Math_Matrix4 = Type.Array(Math_Matrix4, { minItems: 4 }) } sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/module/check.ts000066400000000000000000000022311505437577000264110ustar00rootroot00000000000000import { Cases } from './cases' import { Benchmark } from './benchmark' import { TypeCompiler } from '@sinclair/typebox/compiler' import { TSchema, TypeGuard } from '@sinclair/typebox' import { Value } from '@sinclair/typebox/value' import Ajv from 'ajv' const ajv = new Ajv() // ensure single instance export namespace CheckBenchmark { function Measure(type: string, schema: T) { console.log('CheckBenchmark.Measure(', type, ')') const iterations = 1_000_000 const V = Value.Create(schema) const AC = ajv.compile(schema) const A = Benchmark.Measure(() => { if (!AC(V)) throw Error() }, iterations) const CC = TypeCompiler.Compile(schema) const T = Benchmark.Measure(() => { if (!CC.Check(V)) throw Error() }, iterations) const VC = Benchmark.Measure(() => { if (!Value.Check(schema, V)) throw Error() }, iterations) return { type, ajv: A, compiler: T, value: VC } } export function* Execute() { for (const [type, schema] of Object.entries(Cases)) { if (!TypeGuard.IsSchema(schema)) throw Error('Invalid TypeBox schema') yield Measure(type, schema) } } } sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/module/compile.ts000066400000000000000000000032641505437577000267730ustar00rootroot00000000000000import { Cases } from './cases' import { Benchmark } from './benchmark' import { TypeCompiler } from '@sinclair/typebox/compiler' import { TSchema, TypeGuard } from '@sinclair/typebox' import Ajv from 'ajv' const ajv = new Ajv() // ensure single instance export namespace CompileBenchmark { function Measure(type: string, schema: T) { const iterations = 1000 console.log('CompileBenchmark.Measure(', type, ')') // ------------------------------------------------------------------------------- // Note: Ajv caches schemas by reference. To ensure we measure actual // compilation times, we must pass a new reference via { ...schema } // ------------------------------------------------------------------------------- const AC = Benchmark.Measure(() => ajv.compile({ ...schema }), iterations) const CC = Benchmark.Measure(() => TypeCompiler.Compile({ ...schema }), iterations) return { type, ajv: AC, compiler: CC } } export function* Execute() { for (const [type, schema] of Object.entries(Cases)) { if (!TypeGuard.IsSchema(schema)) throw Error('Invalid TypeBox schema') // ------------------------------------------------------------------------------- // Note: it is not possible to benchmark recursive schemas as ajv will cache and // track duplicate $id (resulting in compile error). It is not possible to ammend // recursive $id's without potentially biasing results, so we omit on this case. // ------------------------------------------------------------------------------- if (type === 'Object_Recursive' || type === 'Array_Object_Recursive') continue yield Measure(type, schema) } } } sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/module/index.ts000066400000000000000000000023011505437577000264410ustar00rootroot00000000000000import { CompileBenchmark } from './compile' import { CheckBenchmark } from './check' import { Result } from './result' export function present(results: Result[]) { console.table( results.reduce((acc, result) => { const ratio = result.ajv.completed / result.compiler.completed if (result.value) { return { ...acc, [result.type.padEnd(26, ' ')]: { Iterations: result.compiler.iterations, ValueCheck: `${result.value.completed} ms`.padStart(10), Ajv: `${result.ajv.completed} ms`.padStart(10), TypeCompiler: `${result.compiler.completed} ms`.padStart(10), Performance: `${ratio.toFixed(2)} x`.padStart(10, ' '), }, } } else { return { ...acc, [result.type.padEnd(26, ' ')]: { Iterations: result.compiler.iterations, Ajv: `${result.ajv.completed} ms`.padStart(10), TypeCompiler: `${result.compiler.completed} ms`.padStart(10), Performance: `${ratio.toFixed(2)} x`.padStart(10, ' '), }, } } }, {}), ) } present([...CompileBenchmark.Execute()]) present([...CheckBenchmark.Execute()]) sinclairzx81-typebox-e0ec98c/task/benchmark/measurement/module/result.ts000066400000000000000000000003361505437577000266560ustar00rootroot00000000000000export type Result = { type: string ajv: { iterations: number completed: number } compiler: { iterations: number completed: number } value?: { iterations: number completed: number } } sinclairzx81-typebox-e0ec98c/task/build/000077500000000000000000000000001505437577000203215ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/build/cjs/000077500000000000000000000000001505437577000211005ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/build/cjs/build.ts000066400000000000000000000031441505437577000225510ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { removeNotices } from '../notices/remove-notices' import { compile } from './compile' /** Builds the CommonJS version of this package */ export async function build(target: string) { console.log('building...cjs') const buildTarget = `${target}/build/cjs` await compile(buildTarget) await removeNotices(buildTarget) } sinclairzx81-typebox-e0ec98c/task/build/cjs/compile.ts000066400000000000000000000031521505437577000231010ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ declare function shell(command: string): Promise // prettier-ignore export async function compile(target: string) { const options = [ `--outDir ${target}`, '--target ES2020', '--module Node16', '--moduleResolution Node16', '--declaration', ].join(' ') await shell(`tsc -p ./src/tsconfig.json ${options}`) } sinclairzx81-typebox-e0ec98c/task/build/esm/000077500000000000000000000000001505437577000211055ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/build/esm/build.ts000066400000000000000000000032611505437577000225560ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { removeNotices } from '../notices/remove-notices' import { convertToEsm } from './convert-to-esm' import { compile } from './compile' /** Builds the ESM version of this package */ export async function build(target: string) { console.log('building...esm') const buildTarget = `${target}/build/esm` await compile(buildTarget) await convertToEsm(buildTarget) await removeNotices(buildTarget) } sinclairzx81-typebox-e0ec98c/task/build/esm/compile.ts000066400000000000000000000031531505437577000231070ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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. ---------------------------------------------------------------------------*/ declare function shell(command: string): Promise // prettier-ignore export async function compile(target: string) { const options = [ `--outDir ${target}`, '--target ES2020', '--module ESNext', '--moduleResolution Bundler', '--declaration', ].join(' ') await shell(`tsc -p ./src/tsconfig.json ${options}`) } sinclairzx81-typebox-e0ec98c/task/build/esm/convert-to-esm.ts000066400000000000000000000101321505437577000243340ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 Path from 'node:path' import * as Fs from 'node:fs' // ------------------------------------------------------------------ // Specifier Rewrite // ------------------------------------------------------------------ // prettier-ignore function replaceInlineImportSpecifiers(content: string): string { const pattern = /import\((.*?)\)/g while (true) { const match = pattern.exec(content) if (match === null) return content const captured = match[1] if(captured.includes('.mjs')) continue const specifier = captured.slice(1, captured.length - 1) content = content.replace(captured, `"${specifier}.mjs"`) } } // prettier-ignore function replaceExportSpecifiers(content: string): string { const pattern = /(export|import)(.*) from ('(.*)');/g while(true) { const match = pattern.exec(content) if(match === null) return content const captured = match[3] const specifier = captured.slice(1, captured.length - 1) content = content.replace(captured, `'${specifier}.mjs'`) } } function replaceSpecifiers(content: string): string { const pass1 = replaceExportSpecifiers(content) const pass2 = replaceInlineImportSpecifiers(pass1) return pass2 } // ------------------------------------------------------------------ // ConvertToEsm // ------------------------------------------------------------------ // prettier-ignore function shouldProcess(sourcePath: string) { const extname = Path.extname(sourcePath) return ['.js', '.ts'].includes(extname) } // prettier-ignore function newExtension(extname: string) { return ( extname === '.js' ? '.mjs' : extname === '.ts' ? '.mts' : extname ) } // prettier-ignore function processFile(sourcePath: string) { if(!shouldProcess(sourcePath)) return const extname = Path.extname(sourcePath) const dirname = Path.dirname(sourcePath) const basename = Path.basename(sourcePath, extname) const new_extname = newExtension(extname) const sourceContent = Fs.readFileSync(sourcePath, 'utf-8') const targetContent = replaceSpecifiers(sourceContent) const targetPath = `${Path.join(dirname, basename)}${new_extname}` Fs.writeFileSync(sourcePath, targetContent) Fs.renameSync(sourcePath, targetPath) } // prettier-ignore function processSourcePath(sourcePath: string) { const stat = Fs.statSync(sourcePath) if(stat.isDirectory()) return readDirectory(sourcePath) if(stat.isFile()) return processFile(sourcePath) } // prettier-ignore function readDirectory(sourceDirectory: string) { for(const entry of Fs.readdirSync(sourceDirectory)) { const sourcePath = Path.join(sourceDirectory, entry) processSourcePath(sourcePath) } } /** Converts the JavaScript and TypeScript declaration modules in the given source directory to use .mjs extensions */ export function convertToEsm(sourceDirectory: string) { readDirectory(sourceDirectory) } sinclairzx81-typebox-e0ec98c/task/build/index.ts000066400000000000000000000026071505437577000220050ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 Package from './package/build' export * as Esm from './esm/build' export * as Cjs from './cjs/build' sinclairzx81-typebox-e0ec98c/task/build/notices/000077500000000000000000000000001505437577000217655ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/build/notices/remove-notices.ts000066400000000000000000000066251505437577000253050ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 Path from 'node:path' import * as Fs from 'node:fs' // ---------------------------------------------------------------------- // Remove Module Level MIT Notice on Package Distribution // // The MIT copyright notice the unnecessarily increases the distribution // size of the package, this code removes it. The MIT license is available // in the package root. // // ---------------------------------------------------------------------- // prettier-ignore function escape(content: string) { return content.split('').map((c) => `\\${c}`).join('') } // prettier-ignore function removeNotice(content: string): string { const open = escape('/*--------------------------------------------------------------------------') const close = escape('---------------------------------------------------------------------------*/') const critera = 'Permission is hereby granted, free of charge' const pattern = new RegExp(`${open}[\\s\\S]*?${close}`, 'gm') while (true) { const match = pattern.exec(content) if (match === null) return content.trimStart() if (!match[0].includes(critera)) continue content = content.replace(match[0], '') } } // ------------------------------------------------------------------ // Directory Enumeration // ------------------------------------------------------------------ // prettier-ignore function processFile(sourcePath: string) { const sourceContent = Fs.readFileSync(sourcePath, 'utf-8') const targetContent = removeNotice(sourceContent) Fs.writeFileSync(sourcePath, targetContent) } // prettier-ignore function processSourcePath(sourcePath: string) { const stat = Fs.statSync(sourcePath) if(stat.isDirectory()) return readDirectory(sourcePath) if(stat.isFile()) return processFile(sourcePath) } // prettier-ignore function readDirectory(sourceDirectory: string) { for(const entry of Fs.readdirSync(sourceDirectory)) { const sourcePath = Path.join(sourceDirectory, entry) processSourcePath(sourcePath) } } /** Removes the MIT copyright notices from each source file in the given directory */ export function removeNotices(sourceDirectory: string) { readDirectory(sourceDirectory) } sinclairzx81-typebox-e0ec98c/task/build/package/000077500000000000000000000000001505437577000217145ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/task/build/package/build.ts000066400000000000000000000033501505437577000233640ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 { createPackageJsonRedirect } from './create-package-json-redirect' import { createPackageJson } from './create-package-json' /** Builds package.json and redirect directories */ export async function build(target: string) { console.log('building...package.json') const submodules = ['compiler', 'errors', 'parser', 'syntax', 'system', 'type', 'value'] await createPackageJsonRedirect(target, submodules) await createPackageJson(target, submodules) } sinclairzx81-typebox-e0ec98c/task/build/package/create-package-json-redirect.ts000066400000000000000000000047711505437577000276770ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 Fs from 'node:fs' // prettier-ignore function writeRedirect(target: string, submodule: string) { Fs.mkdirSync(`${target}/${submodule}`, { recursive: true }) Fs.writeFileSync(`${target}/${submodule}/package.json`,JSON.stringify({ main: `../build/cjs/${submodule}/index.js`, types: `../build/cjs/${submodule}/index.d.ts`, }, null, 2)) } // -------------------------------------------------------------------------------------------------------------------------- // Builds redirect directories for earlier versions of Node. Note that TypeScript will use these directories to // resolve types when tsconfig.json is configured for `moduleResolution: 'Node16'`. This approach is referred to as // `package-json-redirect` and enables correct type resolution in lieu of a correct end user configuration. // // https://github.com/andrewbranch/example-subpath-exports-ts-compat/tree/main/examples/node_modules/package-json-redirects // -------------------------------------------------------------------------------------------------------------------------- // prettier-ignore export function createPackageJsonRedirect(target: string, submodules: string[]) { submodules.forEach((submodule) => writeRedirect(target, submodule)) } sinclairzx81-typebox-e0ec98c/task/build/package/create-package-json.ts000066400000000000000000000074121505437577000260730ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2017-2025 Haydn Paterson (sinclair) 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 Fs from 'node:fs' import * as Path from 'node:path' // prettier-ignore export function createPackageJson(target: string, submodules: string[]) { const content = JSON.stringify(resolvePackageJson(submodules), null, 2) const targetPath = Path.join(target, 'package.json') const targetDir = Path.dirname(targetPath) Fs.mkdirSync(targetDir, { recursive: true }) Fs.writeFileSync(targetPath, content, 'utf-8') } // prettier-ignore function resolvePackageJson(submodules: string[]) { return { ...resolveMetadata(), ...resolveExports(submodules) } } // prettier-ignore function resolveSubmoduleExports(submodule: string) { return { require: { types: `./build/cjs/${submodule}/index.d.ts`, default: `./build/cjs/${submodule}/index.js`, }, import: { types: `./build/esm/${submodule}/index.d.mts`, default: `./build/esm/${submodule}/index.mjs`, } } } // prettier-ignore function resolveExports(submodules: string[]) { const exports = submodules.reduce((acc, submodule) => { return { ...acc, [`./${submodule}`]: resolveSubmoduleExports(submodule) } }, { // ... and root module ".": { "require": { "types": "./build/cjs/index.d.ts", "default": "./build/cjs/index.js", }, "import": { "types": "./build/esm/index.d.mts", "default": "./build/esm/index.mjs", } } }) return { exports } } // prettier-ignore function resolveMetadata() { const packagePath = Path.join(process.cwd(), 'package.json') const packageJson = JSON.parse(Fs.readFileSync(packagePath, 'utf-8')) return { name: packageJson.name, version: packageJson.version, description: packageJson.description, keywords: packageJson.keywords, author: packageJson.author, license: packageJson.license, repository: packageJson.repository, // flagged by socket.dev if not present scripts: { test: 'echo test' }, types: "./build/cjs/index.d.ts", main: "./build/cjs/index.js", module: "./build/esm/index.mjs", // disable auto bundle strategy: see https://github.com/esm-dev/esm.sh#bundling-strategy 'esm.sh': { 'bundle': false }, // specify modules with potential for side effects 'sideEffects': [ './build/esm/type/registry/format.mjs', './build/esm/type/registry/type.mjs', './build/esm/type/system/policy.mjs', './build/cjs/type/registry/format.js', './build/cjs/type/registry/type.js', './build/cjs/type/system/policy.js' ] } } sinclairzx81-typebox-e0ec98c/test/000077500000000000000000000000001505437577000172375ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/000077500000000000000000000000001505437577000207225ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/assert/000077500000000000000000000000001505437577000222235ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/assert/assert.ts000066400000000000000000000040731505437577000241000ustar00rootroot00000000000000import * as assert from 'assert' export namespace Assert { export function HasProperty(value: unknown, key: K): asserts value is Record { if (typeof value === 'object' && value !== null && key in value) return throw new Error(`Expected value to have property '${key as string}'`) } export function IsTrue(value: boolean): asserts value is true { return assert.strictEqual(value, true) } export function IsFalse(value: boolean): asserts value is false { return assert.strictEqual(value, false) } export function IsEqual(actual: unknown, expect: unknown) { if (actual instanceof Uint8Array && expect instanceof Uint8Array) { assert.equal(actual.length, expect.length) for (let i = 0; i < actual.length; i++) assert.equal(actual[i], expect[i]) } return assert.deepStrictEqual(actual, expect) } export function NotEqual(actual: unknown, expect: unknown) { return assert.notEqual(actual, expect) } /** Asserts a numeric value is within range of the expected */ export function InRange(value: number, expect: number, range: number) { if (Math.abs(value - expect) <= range) return throw Error('Expected value to be in range') } let nextIdOrdinal = 0 export function NextId() { return `$id-${nextIdOrdinal++}` } export function Throws(callback: Function) { try { callback() } catch { return } throw Error('Expected throw') } export async function ThrowsAsync(callback: Function) { try { await callback() } catch { return } throw Error('Expected throw') } export function IsInstanceOf any>(value: any, constructor: T): asserts value is InstanceType { if (value instanceof constructor) return throw Error(`Value is not instance of ${constructor}`) } export function IsTypeOf(value: any, type: T) { if (typeof value === type) return throw Error(`Value is not typeof ${type}`) } } sinclairzx81-typebox-e0ec98c/test/runtime/assert/index.ts000066400000000000000000000000311505437577000236740ustar00rootroot00000000000000export * from './assert' sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/000077500000000000000000000000001505437577000233125ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/any.ts000066400000000000000000000013321505437577000244500ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler-ajv/Any', () => { it('Should validate number', () => { const T = Type.Any() Ok(T, 1) }) it('Should validate string', () => { const T = Type.Any() Ok(T, 'hello') }) it('Should validate boolean', () => { const T = Type.Any() Ok(T, true) }) it('Should validate array', () => { const T = Type.Any() Ok(T, [1, 2, 3]) }) it('Should validate object', () => { const T = Type.Any() Ok(T, { a: 1, b: 2 }) }) it('Should validate null', () => { const T = Type.Any() Ok(T, null) }) it('Should validate undefined', () => { const T = Type.Any() Ok(T, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/array.ts000066400000000000000000000142401505437577000250010ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Array', () => { it('Should validate an array of any', () => { const T = Type.Array(Type.Any()) Ok(T, [0, true, 'hello', {}]) }) it('Should not validate varying array when item is number', () => { const T = Type.Array(Type.Number()) Fail(T, [1, 2, 3, 'hello']) }) it('Should validate for an array of unions', () => { const T = Type.Array(Type.Union([Type.Number(), Type.String()])) Ok(T, [1, 'hello', 3, 'world']) }) it('Should not validate for an array of unions where item is not in union.', () => { const T = Type.Array(Type.Union([Type.Number(), Type.String()])) Fail(T, [1, 'hello', 3, 'world', true]) }) it('Should validate for an empty array', () => { const T = Type.Array(Type.Union([Type.Number(), Type.String()])) Ok(T, []) }) it('Should validate for an array of intersection types', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.String() }) const C = Type.Intersect([A, B]) const T = Type.Array(C) Ok(T, [ { a: 'hello', b: 'hello' }, { a: 'hello', b: 'hello' }, { a: 'hello', b: 'hello' }, ]) }) it('Should not validate for an array of composite types when passing additionalProperties false', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.String() }) const C = Type.Composite([A, B], { additionalProperties: false }) const T = Type.Array(C) Fail(T, [ { a: 'hello', b: 'hello' }, { a: 'hello', b: 'hello' }, { a: 'hello', b: 'hello', c: 'additional' }, ]) }) it('Should validate an array of tuples', () => { const A = Type.String() const B = Type.Number() const C = Type.Tuple([A, B]) const T = Type.Array(C) Ok(T, [ ['hello', 1], ['hello', 1], ['hello', 1], ]) }) it('Should not validate an array of tuples when tuple values are incorrect', () => { const A = Type.String() const B = Type.Number() const C = Type.Tuple([A, B]) const T = Type.Array(C) Fail(T, [ [1, 'hello'], [1, 'hello'], [1, 'hello'], ]) }) it('Should not validate array with failed minItems', () => { const T = Type.Array(Type.Number(), { minItems: 3 }) Fail(T, [0, 1]) }) it('Should not validate array with failed maxItems', () => { const T = Type.Array(Type.Number(), { maxItems: 3 }) Fail(T, [0, 1, 2, 3]) }) // --------------------------------------------------------- // Unique Items // --------------------------------------------------------- it('Should validate array with uniqueItems when items are distinct objects', () => { const T = Type.Array(Type.Object({ x: Type.Number(), y: Type.Number() }), { uniqueItems: true }) Ok(T, [ { x: 0, y: 1 }, { x: 1, y: 0 }, ]) }) it('Should not validate array with uniqueItems when items are not distinct objects', () => { const T = Type.Array(Type.Object({ x: Type.Number(), y: Type.Number() }), { uniqueItems: true }) Fail(T, [ { x: 1, y: 0 }, { x: 1, y: 0 }, ]) }) it('Should not validate array with non uniqueItems', () => { const T = Type.Array(Type.Number(), { uniqueItems: true }) Fail(T, [0, 0]) }) // --------------------------------------------------------- // Contains // --------------------------------------------------------- it('Should validate for contains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1) }) Ok(T, [1]) Ok(T, [1, 2]) Fail(T, []) Fail(T, [2]) }) it('Should validate for minContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), minContains: 3 }) Ok(T, [1, 1, 1, 2]) Ok(T, [2, 1, 1, 1, 2]) Ok(T, [1, 1, 1]) Fail(T, []) Fail(T, [1, 1]) Fail(T, [2]) }) it('Should validate for maxContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), maxContains: 3 }) Ok(T, [1, 1, 1]) Ok(T, [1, 1]) Ok(T, [2, 2, 2, 2, 1, 1, 1]) Fail(T, [1, 1, 1, 1]) }) it('Should validate for minContains and maxContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), minContains: 3, maxContains: 5 }) Fail(T, [1, 1]) Ok(T, [1, 1, 1]) Ok(T, [1, 1, 1, 1]) Ok(T, [1, 1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1, 1]) }) it('Should not validate minContains or maxContains when contains is unspecified', () => { const T = Type.Array(Type.Number(), { minContains: 3, maxContains: 5 }) Fail(T, [1, 1]) Fail(T, [1, 1, 1]) Fail(T, [1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1, 1]) }) it('Should produce illogical schema when contains is not sub type of items', () => { const T = Type.Array(Type.Number(), { contains: Type.String(), minContains: 3, maxContains: 5 }) Fail(T, [1, 1]) Fail(T, [1, 1, 1]) Fail(T, [1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1, 1]) }) // ---------------------------------------------------------------- // Issue: https://github.com/sinclairzx81/typebox/discussions/607 // ---------------------------------------------------------------- it('Should correctly handle undefined array properties', () => { const Answer = Type.Object({ text: Type.String(), isCorrect: Type.Boolean(), }) const Question = Type.Object({ text: Type.String(), options: Type.Array(Answer, { minContains: 1, maxContains: 1, contains: Type.Object({ text: Type.String(), isCorrect: Type.Literal(true), }), }), }) Fail(Question, { text: 'A' }) Fail(Question, { text: 'A', options: [] }) Ok(Question, { text: 'A', options: [{ text: 'A', isCorrect: true }] }) Ok(Question, { text: 'A', options: [ { text: 'A', isCorrect: true }, { text: 'B', isCorrect: false }, ], }) Fail(Question, { text: 'A', options: [{ text: 'A', isCorrect: false }] }) Fail(Question, { text: 'A', options: [ { text: 'A', isCorrect: true }, { text: 'B', isCorrect: true }, ], }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/boolean.ts000066400000000000000000000014671505437577000253110ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Boolean', () => { it('Should validate a boolean', () => { const T = Type.Boolean() Ok(T, true) Ok(T, false) }) it('Should not validate a number', () => { const T = Type.Boolean() Fail(T, 1) }) it('Should not validate a string', () => { const T = Type.Boolean() Fail(T, 'true') }) it('Should not validate an array', () => { const T = Type.Boolean() Fail(T, [true]) }) it('Should not validate an object', () => { const T = Type.Boolean() Fail(T, {}) }) it('Should not validate an null', () => { const T = Type.Boolean() Fail(T, null) }) it('Should not validate an undefined', () => { const T = Type.Boolean() Fail(T, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/composite.ts000066400000000000000000000075261505437577000256760ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Assert } from '../assert' import { Ok, Fail } from './validate' describe('compiler-ajv/Composite', () => { it('Should compose two objects', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Composite([A, B], { additionalProperties: false }) Ok(T, { a: 'hello', b: 42 }) }) it('Should compose with partial', () => { const A = Type.Partial(Type.Object({ a: Type.Number() })) const B = Type.Partial(Type.Object({ b: Type.Number() })) const P = Type.Composite([A, B], { additionalProperties: false }) Ok(P, { a: 1, b: 2 }) Ok(P, { a: 1 }) Ok(P, { b: 1 }) Ok(P, {}) Fail(P, { a: 1, b: 2, c: 3 }) Fail(P, { c: 1 }) }) it('Should compose with overlapping same type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.Number() }) const P = Type.Composite([A, B]) Ok(P, { a: 1 }) Fail(P, { a: '1' }) }) it('Should not compose with overlapping varying type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.String() }) const T = Type.Composite([A, B]) Fail(T, { a: 1 }) Fail(T, { a: 'hello' }) Fail(T, {}) }) it('Should compose with deeply nest overlapping varying type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ b: Type.String() }) const C = Type.Object({ c: Type.Boolean() }) const D = Type.Object({ d: Type.Null() }) const T = Type.Composite([A, B, C, D]) Ok(T, { a: 1, b: 'hello', c: true, d: null }) }) it('Should not compose with deeply nest overlapping varying type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.String() }) const C = Type.Object({ a: Type.Boolean() }) const D = Type.Object({ a: Type.Null() }) const T = Type.Composite([A, B, C, D]) Fail(T, { a: 1 }) Fail(T, { a: 'hello' }) Fail(T, { a: false }) Fail(T, { a: null }) Fail(T, { a: [] }) Fail(T, {}) }) it('Should pick from composited type', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const C = Type.Object({ z: Type.Number() }) const T = Type.Composite([A, B, C]) const P = Type.Pick(T, ['x', 'y'], { additionalProperties: false }) Ok(P, { x: 1, y: 1 }) Fail(P, { x: 1, y: 1, z: 1 }) }) it('Should omit from composited type', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const C = Type.Object({ z: Type.Number() }) const T = Type.Composite([A, B, C]) const P = Type.Omit(T, ['z'], { additionalProperties: false }) Ok(P, { x: 1, y: 1 }) Fail(P, { x: 1, y: 1, z: 1 }) }) it('Should compose nested object properties', () => { const A = Type.Object({ x: Type.Object({ x: Type.Number() }) }) const B = Type.Object({ y: Type.Object({ x: Type.String() }) }) const T = Type.Composite([A, B]) Ok(T, { x: { x: 1 }, y: { x: '' } }) Fail(T, { x: { x: '1' }, y: { x: '' } }) Fail(T, { x: { x: 1 }, y: { x: 1 } }) }) // todo: move to composition / type guard spec it('Should compose and produce the same schema', () => { const T = Type.Object({ field: Type.Optional(Type.String()), }) const A = Type.Composite([T]) const B = Type.Composite([T]) Assert.IsEqual(A, B) }) // prettier-ignore it('Should composite intersection', () => { const T = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Number() }) ]), Type.Intersect([ Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }) ]), ]) Ok(T, { x: 1, y: 2, z: 3 }) Fail(T, { x: 1, y: 2, z: '3' }) Fail(T, { x: 1, y: 2 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/const.ts000066400000000000000000000015721505437577000250150ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler-ajv/Const', () => { it('Should validate 1', () => { const T = Type.Const(1) Ok(T, 1) }) it('Should validate 2', () => { const T = Type.Const('hello') Ok(T, 'hello') }) it('Should validate 3', () => { const T = Type.Const(true) Ok(T, true) }) it('Should validate 4', () => { const T = Type.Const({ x: 1, y: 2 }) Ok(T, { x: 1, y: 2 }) }) it('Should validate 5', () => { const T = Type.Const([1, 2, 3]) Ok(T, [1, 2, 3]) }) it('Should validate 6', () => { const T = Type.Const([1, true, 'hello']) Ok(T, [1, true, 'hello']) }) it('Should validate 7', () => { const T = Type.Const({ x: [1, 2, 3, 4], y: { x: 1, y: 2, z: 3 }, }) Ok(T, { x: [1, 2, 3, 4], y: { x: 1, y: 2, z: 3 }, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/date.ts000066400000000000000000000042311505437577000245770ustar00rootroot00000000000000// --------------------------------------------------- // No Longer Supported // --------------------------------------------------- // import { Type } from '@sinclair/typebox' // import { Ok, Fail } from './validate' // ---------------------------------------------------- // These tests are implemented by way of .addKeyword() // which are configured to use Value.Check() // ---------------------------------------------------- // describe('compiler-ajv/Date', () => { // it('Should not validate number', () => { // const T = Type.Date() // Fail(T, 1) // }) // it('Should not validate string', () => { // const T = Type.Date() // Fail(T, 'hello') // }) // it('Should not validate boolean', () => { // const T = Type.Date() // Fail(T, true) // }) // it('Should not validate array', () => { // const T = Type.Date() // Fail(T, [1, 2, 3]) // }) // it('Should not validate object', () => { // const T = Type.Date() // Fail(T, { a: 1, b: 2 }) // }) // it('Should not validate null', () => { // const T = Type.Date() // Fail(T, null) // }) // it('Should not validate undefined', () => { // const T = Type.Date() // Fail(T, undefined) // }) // it('Should validate Date', () => { // const T = Type.Date() // Ok(T, new Date()) // }) // it('Should not validate Date if is invalid', () => { // const T = Type.Date() // Fail(T, new Date('not-a-valid-date')) // }) // it('Should validate Date minimumTimestamp', () => { // const T = Type.Date({ minimumTimestamp: 10 }) // Fail(T, new Date(9)) // Ok(T, new Date(10)) // }) // it('Should validate Date maximumTimestamp', () => { // const T = Type.Date({ maximumTimestamp: 10 }) // Ok(T, new Date(10)) // Fail(T, new Date(11)) // }) // it('Should validate Date exclusiveMinimumTimestamp', () => { // const T = Type.Date({ exclusiveMinimumTimestamp: 10 }) // Fail(T, new Date(10)) // Ok(T, new Date(11)) // }) // it('Should validate Date exclusiveMaximumTimestamp', () => { // const T = Type.Date({ exclusiveMaximumTimestamp: 10 }) // Ok(T, new Date(9)) // Fail(T, new Date(10)) // }) // }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/enum.ts000066400000000000000000000022301505437577000246230ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Enum', () => { it('Should validate when emum uses default numeric values', () => { enum Kind { Foo, // = 0 Bar, // = 1 } const T = Type.Enum(Kind) Ok(T, 0) Ok(T, 1) }) it('Should not validate when given enum values are not numeric', () => { enum Kind { Foo, // = 0 Bar, // = 1 } const T = Type.Enum(Kind) Fail(T, 'Foo') Fail(T, 'Bar') }) it('Should validate when emum has defined string values', () => { enum Kind { Foo = 'foo', Bar = 'bar', } const T = Type.Enum(Kind) Ok(T, 'foo') Ok(T, 'bar') }) it('Should not validate when emum has defined string values and user passes numeric', () => { enum Kind { Foo = 'foo', Bar = 'bar', } const T = Type.Enum(Kind) Fail(T, 0) Fail(T, 1) }) it('Should validate when enum has one or more string values', () => { enum Kind { Foo, Bar = 'bar', } const T = Type.Enum(Kind) Ok(T, 0) Ok(T, 'bar') Fail(T, 'baz') Fail(T, 'Foo') Fail(T, 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/index.ts000066400000000000000000000012421505437577000247700ustar00rootroot00000000000000import './any' import './array' import './boolean' import './composite' import './const' import './date' import './enum' import './integer' import './intersect' import './keyof' import './literal' import './module' import './never' import './not' import './null' import './number' import './object' import './omit' import './optional' import './partial' import './pick' import './readonly-optional' import './readonly' import './recursive' import './record' import './ref' import './required' import './string-pattern' import './string' import './template-literal' import './tuple' import './uint8array' import './union' import './unknown' import './unsafe' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/integer.ts000066400000000000000000000027271505437577000253270ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Integer', () => { it('Should not validate number', () => { const T = Type.Integer() Fail(T, 3.14) }) it('Should validate integer', () => { const T = Type.Integer() Ok(T, 1) }) it('Should not validate string', () => { const T = Type.Integer() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Integer() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Integer() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Integer() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Integer() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.Integer() Fail(T, undefined) }) it('Should validate minimum', () => { const T = Type.Integer({ minimum: 10 }) Fail(T, 9) Ok(T, 10) }) it('Should validate maximum', () => { const T = Type.Integer({ maximum: 10 }) Ok(T, 10) Fail(T, 11) }) it('Should validate Date exclusiveMinimum', () => { const T = Type.Integer({ exclusiveMinimum: 10 }) Fail(T, 10) Ok(T, 11) }) it('Should validate Date exclusiveMaximum', () => { const T = Type.Integer({ exclusiveMaximum: 10 }) Ok(T, 9) Fail(T, 10) }) it('Should not validate NaN', () => { Fail(Type.Integer(), NaN) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/intersect.ts000066400000000000000000000146571505437577000256770ustar00rootroot00000000000000import { Type, Static } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Intersect', () => { it('Should intersect number and number', () => { const A = Type.Number() const B = Type.Number() const T = Type.Intersect([A, B], {}) Ok(T, 1) }) it('Should not intersect string and number', () => { const A = Type.String() const B = Type.Number() const T = Type.Intersect([A, B], {}) Fail(T, 1) Fail(T, '1') }) it('Should intersect two objects', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Ok(T, { x: 1, y: 1 }) }) it('Should not intersect two objects with internal additionalProperties false', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ y: Type.Number() }, { additionalProperties: false }) const T = Type.Intersect([A, B], {}) Fail(T, { x: 1, y: 1 }) }) it('Should intersect two objects and mandate required properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Ok(T, { x: 1, y: 1 }) Fail(T, { x: 1 }) Fail(T, { y: 1 }) }) it('Should intersect two objects with unevaluated properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Ok(T, { x: 1, y: 2, z: 1 }) }) it('Should intersect two objects and restrict unevaluated properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], { unevaluatedProperties: false }) Fail(T, { x: 1, y: 2, z: 1 }) }) it('Should intersect two objects and allow unevaluated properties of number', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], { unevaluatedProperties: Type.Number() }) Ok(T, { x: 1, y: 2, z: 3 }) Fail(T, { x: 1, y: 2, z: '1' }) }) it('Should intersect two union objects with overlapping properties of the same type', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ x: Type.Number() })]) const T = Type.Intersect([A, B]) Ok(T, { x: 1 }) Fail(T, { x: '1' }) }) it('Should not intersect two union objects with overlapping properties of varying types', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ x: Type.String() })]) const T = Type.Intersect([A, B]) Fail(T, { x: 1 }) Fail(T, { x: '1' }) }) it('Should intersect two union objects with non-overlapping properties', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ y: Type.Number() })]) const T = Type.Intersect([A, B]) Ok(T, { x: 1, y: 1 }) }) it('Should not intersect two union objects with non-overlapping properties for additionalProperties false', () => { const A = Type.Union([Type.Object({ x: Type.Number() }, { additionalProperties: false })]) const B = Type.Union([Type.Object({ y: Type.Number() }, { additionalProperties: false })]) const T = Type.Intersect([A, B]) Fail(T, { x: 1, y: 1 }) }) it('unevaluatedProperties with Record 1', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Ok(T, { x: 1, y: 2 }) }) it('unevaluatedProperties with Record 2', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Ok(T, { x: 1, y: 2, 0: 'hello' }) }) it('unevaluatedProperties with Record 3', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Fail(T, { x: 1, y: 2, 0: 1 }) }) it('unevaluatedProperties with Record 4', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Ok(T, { x: 1, y: 2 }) }) it('unevaluatedProperties with Record 5', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Ok(T, { x: 1, y: 2, z: true }) }) it('unevaluatedProperties with Record 6', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Fail(T, { x: 1, y: 2, z: 1 }) }) it('unevaluatedProperties with Record 7', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Ok(T, { x: 1, y: 2, 0: '' }) }) it('unevaluatedProperties with Record 8', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Ok(T, { x: 1, y: 2, 0: '', z: true }) }) it('unevaluatedProperties with Record 9', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Fail(T, { x: 1, y: 2, 0: '', z: 1 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/keyof.ts000066400000000000000000000017431505437577000250040ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/KeyOf', () => { it('Should validate with all object keys as a kind of union', () => { const T = Type.KeyOf( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) Ok(T, 'x') Ok(T, 'y') Ok(T, 'z') Fail(T, 'w') }) it('Should validate when using pick', () => { const T = Type.KeyOf( Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ['x', 'y'], ), ) Ok(T, 'x') Ok(T, 'y') Fail(T, 'z') }) it('Should validate when using omit', () => { const T = Type.KeyOf( Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ['x', 'y'], ), ) Fail(T, 'x') Fail(T, 'y') Ok(T, 'z') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/literal.ts000066400000000000000000000026651505437577000253270ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Literal', () => { it('Should validate literal number', () => { const T = Type.Literal(42) Ok(T, 42) }) it('Should validate literal string', () => { const T = Type.Literal('hello') Ok(T, 'hello') }) it('Should validate literal boolean', () => { const T = Type.Literal(true) Ok(T, true) }) it('Should not validate invalid literal number', () => { const T = Type.Literal(42) Fail(T, 43) }) it('Should not validate invalid literal string', () => { const T = Type.Literal('hello') Fail(T, 'world') }) it('Should not validate invalid literal boolean', () => { const T = Type.Literal(false) Fail(T, true) }) it('Should validate literal union', () => { const T = Type.Union([Type.Literal(42), Type.Literal('hello')]) Ok(T, 42) Ok(T, 'hello') }) it('Should not validate invalid literal union', () => { const T = Type.Union([Type.Literal(42), Type.Literal('hello')]) Fail(T, 43) Fail(T, 'world') }) // reference: https://github.com/sinclairzx81/typebox/issues/539 it('Should escape single quote literals', () => { const T = Type.Literal("it's") Ok(T, "it's") Fail(T, "it''s") }) it('Should escape multiple single quote literals', () => { const T = Type.Literal("'''''''''") Ok(T, "'''''''''") Fail(T, "''''''''") // minus 1 }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/module.ts000066400000000000000000000106071505437577000251530ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Module', () => { it('Should validate string', () => { const Module = Type.Module({ A: Type.String(), }) const T = Module.Import('A') Ok(T, 'hello') Fail(T, true) }) it('Should validate referenced string', () => { const Module = Type.Module({ A: Type.String(), B: Type.Ref('A'), }) const T = Module.Import('B') Ok(T, 'hello') Fail(T, true) }) it('Should validate self referential', () => { const Module = Type.Module({ A: Type.Object({ nodes: Type.Array(Type.Ref('A')), }), }) const T = Module.Import('A') Ok(T, { nodes: [{ nodes: [{ nodes: [] }, { nodes: [] }] }] }) Fail(T, { nodes: [{ nodes: [{ nodes: [] }, { nodes: false }] }] }) Fail(T, true) }) it('Should validate mutual recursive', () => { const Module = Type.Module({ A: Type.Object({ b: Type.Ref('B'), }), B: Type.Object({ a: Type.Union([Type.Ref('A'), Type.Null()]), }), }) const T = Module.Import('A') Ok(T, { b: { a: null } }) Ok(T, { b: { a: { b: { a: null } } } }) Fail(T, { b: { a: 1 } }) Fail(T, { b: { a: { b: { a: 1 } } } }) Fail(T, true) }) it('Should validate mutual recursive (Array)', () => { const Module = Type.Module({ A: Type.Object({ b: Type.Ref('B'), }), B: Type.Object({ a: Type.Array(Type.Ref('A')), }), }) const T = Module.Import('A') Ok(T, { b: { a: [{ b: { a: [] } }] } }) Fail(T, { b: { a: [{ b: { a: [null] } }] } }) Fail(T, true) }) it('Should validate deep referential', () => { const Module = Type.Module({ A: Type.Ref('B'), B: Type.Ref('C'), C: Type.Ref('D'), D: Type.Ref('E'), E: Type.Ref('F'), F: Type.Ref('G'), G: Type.Ref('H'), H: Type.Literal('hello'), }) const T = Module.Import('A') Ok(T, 'hello') Fail(T, 'world') }) // ---------------------------------------------------------------- // Modifiers // ---------------------------------------------------------------- it('Should validate objects with property modifiers 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Null()), y: Type.Readonly(Type.Null()), z: Type.Optional(Type.Null()), w: Type.Null(), }), }) const T = Module.Import('T') Ok(T, { x: null, y: null, w: null }) Ok(T, { y: null, w: null }) Fail(T, { x: 1, y: null, w: null }) }) it('Should validate objects with property modifiers 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Array(Type.Null())), y: Type.Readonly(Type.Array(Type.Null())), z: Type.Optional(Type.Array(Type.Null())), w: Type.Array(Type.Null()), }), }) const T = Module.Import('T') Ok(T, { x: [null], y: [null], w: [null] }) Ok(T, { y: [null], w: [null] }) Fail(T, { x: [1], y: [null], w: [null] }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1109 // ---------------------------------------------------------------- it('Should validate deep referential 1', () => { const Module = Type.Module({ A: Type.Union([Type.Literal('Foo'), Type.Literal('Bar')]), B: Type.Ref('A'), C: Type.Object({ ref: Type.Ref('B') }), D: Type.Union([Type.Ref('B'), Type.Ref('C')]), }) Ok(Module.Import('A') as never, 'Foo') Ok(Module.Import('A') as never, 'Bar') Ok(Module.Import('B') as never, 'Foo') Ok(Module.Import('B') as never, 'Bar') Ok(Module.Import('C') as never, { ref: 'Foo' }) Ok(Module.Import('C') as never, { ref: 'Bar' }) Ok(Module.Import('D') as never, 'Foo') Ok(Module.Import('D') as never, 'Bar') Ok(Module.Import('D') as never, { ref: 'Foo' }) Ok(Module.Import('D') as never, { ref: 'Bar' }) }) it('Should validate deep referential 2', () => { const Module = Type.Module({ A: Type.Literal('Foo'), B: Type.Ref('A'), C: Type.Ref('B'), D: Type.Ref('C'), E: Type.Ref('D'), }) Ok(Module.Import('A'), 'Foo') Ok(Module.Import('B'), 'Foo') Ok(Module.Import('C'), 'Foo') Ok(Module.Import('D'), 'Foo') Ok(Module.Import('E'), 'Foo') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/never.ts000066400000000000000000000014221505437577000250000ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Fail } from './validate' describe('compiler-ajv/Never', () => { it('Should not validate number', () => { const T = Type.Never() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.Never() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Never() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Never() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Never() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Never() Fail(T, null) }) it('Should validate undefined', () => { const T = Type.Never() Fail(T, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/not.ts000066400000000000000000000021231505437577000244600ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Not', () => { it('Should validate not number', () => { const T = Type.Not(Type.Number()) Fail(T, 1) Ok(T, '1') }) it('Should validate not not number', () => { const T = Type.Not(Type.Not(Type.Number())) Ok(T, 1) Fail(T, '1') }) it('Should validate not union', () => { // prettier-ignore const T = Type.Not(Type.Union([ Type.Literal('A'), Type.Literal('B'), Type.Literal('C') ])) Fail(T, 'A') Fail(T, 'B') Fail(T, 'C') Ok(T, 'D') }) it('Should validate not object intersection', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), Type.Object({ x: Type.Not(Type.Literal(0)), y: Type.Not(Type.Literal(0)), z: Type.Not(Type.Literal(0)), }), ]) Fail(T, { x: 0, y: 0, z: 0 }) Fail(T, { x: 1, y: 0, z: 0 }) Fail(T, { x: 1, y: 1, z: 0 }) Ok(T, { x: 1, y: 1, z: 1 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/null.ts000066400000000000000000000014201505437577000246310ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Null', () => { it('Should not validate number', () => { const T = Type.Null() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.Null() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Null() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Null() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Null() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Null() Ok(T, null) }) it('Should not validate undefined', () => { const T = Type.Null() Fail(T, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/number.ts000066400000000000000000000027031505437577000251540ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Number', () => { it('Should validate number', () => { const T = Type.Number() Ok(T, 3.14) }) it('Should validate integer', () => { const T = Type.Number() Ok(T, 1) }) it('Should not validate string', () => { const T = Type.Number() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Number() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Number() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Number() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Number() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.Number() Fail(T, undefined) }) it('Should validate minimum', () => { const T = Type.Number({ minimum: 10 }) Fail(T, 9) Ok(T, 10) }) it('Should validate maximum', () => { const T = Type.Number({ maximum: 10 }) Ok(T, 10) Fail(T, 11) }) it('Should validate Date exclusiveMinimum', () => { const T = Type.Number({ exclusiveMinimum: 10 }) Fail(T, 10) Ok(T, 11) }) it('Should validate Date exclusiveMaximum', () => { const T = Type.Number({ exclusiveMaximum: 10 }) Ok(T, 9) Fail(T, 10) }) it('Should not validate NaN', () => { Fail(Type.Number(), NaN) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/object.ts000066400000000000000000000104401505437577000251270ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Object', () => { it('Should not validate a number', () => { const T = Type.Object({}) Fail(T, 42) }) it('Should not validate a string', () => { const T = Type.Object({}) Fail(T, 'hello') }) it('Should not validate a boolean', () => { const T = Type.Object({}) Fail(T, true) }) it('Should not validate a null', () => { const T = Type.Object({}) Fail(T, null) }) it('Should not validate an array', () => { const T = Type.Object({}) Fail(T, [1, 2]) }) it('Should validate with correct property values', () => { const T = Type.Object({ a: Type.Number(), b: Type.String(), c: Type.Boolean(), d: Type.Array(Type.Number()), e: Type.Object({ x: Type.Number(), y: Type.Number() }), }) Ok(T, { a: 10, b: 'hello', c: true, d: [1, 2, 3], e: { x: 10, y: 20 }, }) }) it('Should not validate with incorrect property values', () => { const T = Type.Object({ a: Type.Number(), b: Type.String(), c: Type.Boolean(), d: Type.Array(Type.Number()), e: Type.Object({ x: Type.Number(), y: Type.Number() }), }) Fail(T, { a: 'not a number', // error b: 'hello', c: true, d: [1, 2, 3], e: { x: 10, y: 20 }, }) }) it('Should allow additionalProperties by default', () => { const T = Type.Object({ a: Type.Number(), b: Type.String(), }) Ok(T, { a: 1, b: 'hello', c: true, }) }) it('Should not allow an empty object if minProperties is set to 1', () => { const T = Type.Object( { a: Type.Optional(Type.Number()), b: Type.Optional(Type.String()), }, { additionalProperties: false, minProperties: 1 }, ) Ok(T, { a: 1 }) Ok(T, { b: 'hello' }) Fail(T, {}) }) it('Should not allow 3 properties if maxProperties is set to 2', () => { const T = Type.Object( { a: Type.Optional(Type.Number()), b: Type.Optional(Type.String()), c: Type.Optional(Type.Boolean()), }, { additionalProperties: false, maxProperties: 2 }, ) Ok(T, { a: 1 }) Ok(T, { a: 1, b: 'hello' }) Fail(T, { a: 1, b: 'hello', c: true, }) }) it('Should not allow additionalProperties if additionalProperties is false', () => { const T = Type.Object( { a: Type.Number(), b: Type.String(), }, { additionalProperties: false }, ) Fail(T, { a: 1, b: 'hello', c: true, }) }) it('Should not allow properties for an empty object when additionalProperties is false', () => { const T = Type.Object({}, { additionalProperties: false }) Ok(T, {}) Fail(T, { a: 10 }) }) it('Should validate with non-syntax property keys', () => { const T = Type.Object({ 'with-hyphen': Type.Literal(1), '0-leading': Type.Literal(2), '$-leading': Type.Literal(3), '!@#$%^&*(': Type.Literal(4), }) Ok(T, { 'with-hyphen': 1, '0-leading': 2, '$-leading': 3, '!@#$%^&*(': 4, }) }) it('Should validate schema additional properties of string', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) Ok(T, { x: 1, y: 2, z: 'hello', }) Fail(T, { x: 1, y: 2, z: 3, }) }) it('Should validate schema additional properties of array', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Array(Type.Number()), }, ) Ok(T, { x: 1, y: 2, z: [0, 1, 2], }) Fail(T, { x: 1, y: 2, z: 3, }) }) it('Should validate schema additional properties of object', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Object({ z: Type.Number(), }), }, ) Ok(T, { x: 1, y: 2, z: { z: 1 }, }) Fail(T, { x: 1, y: 2, z: 3, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/omit.ts000066400000000000000000000035341505437577000246370ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { strictEqual } from 'assert' describe('compiler-ajv/Omit', () => { it('Should omit properties on the source schema', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Omit(A, ['z']) Ok(T, { x: 1, y: 1 }) }) it('Should remove required properties on the target schema', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Omit(A, ['z']) strictEqual(T.required!.includes('z'), false) }) it('Should delete the required property if no required properties remain', () => { const A = Type.Object( { x: Type.Optional(Type.Number()), y: Type.Readonly(Type.Optional(Type.Number())), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Omit(A, ['z']) strictEqual(T.required, undefined) }) it('Should inherit options from the source object', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Omit(A, ['z']) strictEqual(A.additionalProperties, false) strictEqual(T.additionalProperties, false) }) it('Should omit with keyof object', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const B = Type.Object({ x: Type.Number(), y: Type.Number(), }) const T = Type.Omit(A, Type.KeyOf(B), { additionalProperties: false }) Ok(T, { z: 0 }) Fail(T, { x: 0, y: 0, z: 0 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/optional.ts000066400000000000000000000012761505437577000255150ustar00rootroot00000000000000import { strictEqual } from 'assert' import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler-ajv/Optional', () => { it('Should validate object with optional', () => { const T = Type.Object( { a: Type.Optional(Type.String()), b: Type.String(), }, { additionalProperties: false }, ) Ok(T, { a: 'hello', b: 'world' }) Ok(T, { b: 'world' }) }) it('Should remove required value from schema', () => { const T = Type.Object( { a: Type.Optional(Type.String()), b: Type.String(), }, { additionalProperties: false }, ) strictEqual(T.required!.includes('a'), false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/partial.ts000066400000000000000000000031501505437577000253150ustar00rootroot00000000000000import { Type, ReadonlyKind, OptionalKind } from '@sinclair/typebox' import { Ok } from './validate' import { Assert } from '../assert' describe('compiler-ajv/Partial', () => { it('Should convert a required object into a partial.', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Partial(A) Ok(T, { x: 1, y: 1, z: 1 }) Ok(T, { x: 1, y: 1 }) Ok(T, { x: 1 }) Ok(T, {}) }) it('Should update modifier types correctly when converting to partial', () => { const A = Type.Object( { x: Type.Readonly(Type.Optional(Type.Number())), y: Type.Readonly(Type.Number()), z: Type.Optional(Type.Number()), w: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Partial(A) Assert.IsEqual(T.properties.x[ReadonlyKind], 'Readonly') Assert.IsEqual(T.properties.x[OptionalKind], 'Optional') Assert.IsEqual(T.properties.y[ReadonlyKind], 'Readonly') Assert.IsEqual(T.properties.y[OptionalKind], 'Optional') Assert.IsEqual(T.properties.z[OptionalKind], 'Optional') Assert.IsEqual(T.properties.w[OptionalKind], 'Optional') }) it('Should inherit options from the source object', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Partial(A) Assert.IsEqual(A.additionalProperties, false) Assert.IsEqual(T.additionalProperties, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/pick.ts000066400000000000000000000036171505437577000246170ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { Assert } from '../assert' describe('compiler-ajv/Pick', () => { it('Should pick properties from the source schema', () => { const Vector3 = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Pick(Vector3, ['x', 'y']) Ok(T, { x: 1, y: 1 }) }) it('Should remove required properties on the target schema', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Pick(A, ['x', 'y']) Assert.IsEqual(T.required!.includes('z'), false) }) it('Should delete the required property if no required properties remain', () => { const A = Type.Object( { x: Type.Optional(Type.Number()), y: Type.Readonly(Type.Optional(Type.Number())), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Pick(A, ['x', 'y']) Assert.IsEqual(T.required, undefined) }) it('Should inherit options from the source object', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Pick(A, ['x', 'y']) Assert.IsEqual(A.additionalProperties, false) Assert.IsEqual(T.additionalProperties, false) }) it('Should pick with keyof object', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const B = Type.Object({ x: Type.Number(), y: Type.Number(), }) const T = Type.Pick(A, Type.KeyOf(B), { additionalProperties: false }) Ok(T, { x: 0, y: 0 }) Fail(T, { x: 0, y: 0, z: 0 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/readonly-optional.ts000066400000000000000000000013451505437577000273250ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' import { Assert } from '../assert' describe('compiler-ajv/ReadonlyOptional', () => { it('Should validate object with optional', () => { const T = Type.Object( { a: Type.Readonly(Type.Optional(Type.String())), b: Type.String(), }, { additionalProperties: false }, ) Ok(T, { a: 'hello', b: 'world' }) Ok(T, { b: 'world' }) }) it('Should remove required value from schema', () => { const T = Type.Object( { a: Type.Readonly(Type.Optional(Type.String())), b: Type.String(), }, { additionalProperties: false }, ) Assert.IsEqual(T.required!.includes('a'), false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/readonly.ts000066400000000000000000000013641505437577000255030ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' import { Assert } from '../assert' describe('compiler-ajv/Readonly', () => { it('Should validate object with readonly', () => { const T = Type.Object( { a: Type.Readonly(Type.String()), b: Type.Readonly(Type.String()), }, { additionalProperties: false }, ) Ok(T, { a: 'hello', b: 'world' }) }) it('Should retain required array on object', () => { const T = Type.Object( { a: Type.Readonly(Type.String()), b: Type.Readonly(Type.String()), }, { additionalProperties: false }, ) Assert.IsEqual(T.required!.includes('a'), true) Assert.IsEqual(T.required!.includes('b'), true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/record.ts000066400000000000000000000230721505437577000251440ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Record', () => { it('Should validate when all property values are numbers', () => { const T = Type.Record(Type.String(), Type.Number()) Ok(T, { a: 1, b: 2, c: 3 }) }) it('Should validate when all property keys are strings', () => { const T = Type.Record(Type.String(), Type.Number()) Ok(T, { a: 1, b: 2, c: 3, '0': 4 }) }) it('Should not validate when below minProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { minProperties: 4 }) Ok(T, { a: 1, b: 2, c: 3, d: 4 }) Fail(T, { a: 1, b: 2, c: 3 }) }) it('Should not validate when above maxProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { maxProperties: 4 }) Ok(T, { a: 1, b: 2, c: 3, d: 4 }) Fail(T, { a: 1, b: 2, c: 3, d: 4, e: 5 }) }) it('Should not validate with illogical minProperties | maxProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { minProperties: 5, maxProperties: 4 }) Fail(T, { a: 1, b: 2, c: 3 }) Fail(T, { a: 1, b: 2, c: 3, d: 4 }) Fail(T, { a: 1, b: 2, c: 3, d: 4, e: 5 }) }) it('Should validate when specifying string union literals when additionalProperties is true', () => { const K = Type.Union([Type.Literal('a'), Type.Literal('b'), Type.Literal('c')]) const T = Type.Record(K, Type.Number()) Ok(T, { a: 1, b: 2, c: 3, d: 'hello' }) }) it('Should not validate when specifying string union literals when additionalProperties is false', () => { const K = Type.Union([Type.Literal('a'), Type.Literal('b'), Type.Literal('c')]) const T = Type.Record(K, Type.Number(), { additionalProperties: false }) Fail(T, { a: 1, b: 2, c: 3, d: 'hello' }) }) it('Should validate for keyof records', () => { const T = Type.Object({ a: Type.String(), b: Type.Number(), c: Type.String(), }) const R = Type.Record(Type.KeyOf(T), Type.Number()) Ok(R, { a: 1, b: 2, c: 3 }) }) it('Should not validate for unknown key via keyof', () => { const T = Type.Object({ a: Type.String(), b: Type.Number(), c: Type.String(), }) const R = Type.Record(Type.KeyOf(T), Type.Number(), { additionalProperties: false }) Fail(R, { a: 1, b: 2, c: 3, d: 4 }) }) it('Should validate when specifying regular expressions', () => { const K = Type.RegExp(/^op_.*$/) const T = Type.Record(K, Type.Number()) Ok(T, { op_a: 1, op_b: 2, op_c: 3, }) }) it('Should not validate when specifying regular expressions and passing invalid property', () => { const K = Type.RegExp(/^op_.*$/) const T = Type.Record(K, Type.Number(), { additionalProperties: false }) Fail(T, { op_a: 1, op_b: 2, aop_c: 3, }) }) it('Should validate with quoted string pattern', () => { const K = Type.String({ pattern: "'(a|b|c)" }) const T = Type.Record(K, Type.Number()) Ok(T, { "'a": 1, "'b": 2, "'c": 3, }) }) it('Should validate with forward-slash pattern', () => { const K = Type.String({ pattern: '/(a|b|c)' }) const T = Type.Record(K, Type.Number()) Ok(T, { '/a': 1, '/b': 2, '/c': 3, }) }) // ------------------------------------------------------------ // Integer Keys // ------------------------------------------------------------ it('Should validate when all property keys are integers', () => { const T = Type.Record(Type.Integer(), Type.Number()) Ok(T, { '0': 1, '1': 2, '2': 3, '3': 4 }) }) it('Should validate when all property keys are integers, but one property is a string with varying type', () => { const T = Type.Record(Type.Integer(), Type.Number(), { additionalProperties: false }) Fail(T, { '0': 1, '1': 2, '2': 3, '3': 4, a: 'hello' }) }) it('Should not validate if passing a leading zeros for integers keys', () => { const T = Type.Record(Type.Integer(), Type.Number(), { additionalProperties: false }) Fail(T, { '00': 1, '01': 2, '02': 3, '03': 4, }) }) it('Should not validate if passing a signed integers keys', () => { const T = Type.Record(Type.Integer(), Type.Number(), { additionalProperties: false }) Fail(T, { '-0': 1, '-1': 2, '-2': 3, '-3': 4, }) }) // ------------------------------------------------------------ // Number Keys // ------------------------------------------------------------ it('Should validate when all property keys are numbers', () => { const T = Type.Record(Type.Number(), Type.Number()) Ok(T, { '0': 1, '1': 2, '2': 3, '3': 4 }) }) it('Should validate when all property keys are numbers, but one property is a string with varying type', () => { const T = Type.Record(Type.Number(), Type.Number(), { additionalProperties: false }) Fail(T, { '0': 1, '1': 2, '2': 3, '3': 4, a: 'hello' }) }) it('Should not validate if passing a leading zeros for numeric keys', () => { const T = Type.Record(Type.Number(), Type.Number(), { additionalProperties: false }) Fail(T, { '00': 1, '01': 2, '02': 3, '03': 4, }) }) it('Should not validate if passing a signed numeric keys', () => { const T = Type.Record(Type.Number(), Type.Number(), { additionalProperties: false }) Fail(T, { '-0': 1, '-1': 2, '-2': 3, '-3': 4, }) }) it('Should not validate when all property keys are numbers, but one property is a string with varying type', () => { const T = Type.Record(Type.Number(), Type.Number(), { additionalProperties: false }) Fail(T, { '0': 1, '1': 2, '2': 3, '3': 4, a: 'hello' }) }) // ------------------------------------------------------------ // AdditionalProperties // ------------------------------------------------------------ it('AdditionalProperties 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: true }) Ok(T, { 1: '', 2: '', x: 1, y: 2, z: 3 }) }) it('AdditionalProperties 2', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false }) Ok(T, { 1: '', 2: '', 3: '' }) }) it('AdditionalProperties 3', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false }) Fail(T, { 1: '', 2: '', x: '' }) }) it('AdditionalProperties 4', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean() }) Fail(T, { 1: '', 2: '', x: '' }) }) it('AdditionalProperties 5', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean() }) Ok(T, { 1: '', 2: '', x: true }) }) // ---------------------------------------------------------------- // TemplateLiteral // ---------------------------------------------------------------- it('TemplateLiteral 1', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number(), { additionalProperties: false }) Ok(R, { key0: 1, key1: 1, key2: 1, }) }) it('TemplateLiteral 2', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) Ok(R, { keyA: 0 }) }) it('TemplateLiteral 3', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number(), { additionalProperties: false }) Fail(R, { keyA: 0 }) }) it('TemplateLiteral 4', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const I = Type.Intersect([R, T], { unevaluatedProperties: false }) Ok(I, { x: 1, y: 2, key0: 1, key1: 1, key2: 1, }) }) it('TemplateLiteral 5', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const I = Type.Intersect([R, T]) Ok(I, { x: 1, y: 2, z: 3, key0: 1, key1: 1, key2: 1, }) }) it('TemplateLiteral 6', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const I = Type.Intersect([R, T], { unevaluatedProperties: false }) Fail(I, { x: 1, y: 2, z: 3, key0: 1, key1: 1, key2: 1, }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/916 // ---------------------------------------------------------------- it('Should validate for string keys', () => { const T = Type.Record(Type.String(), Type.Null(), { additionalProperties: false, }) Ok(T, { a: null, b: null, 0: null, 1: null, }) }) it('Should validate for number keys', () => { const T = Type.Record(Type.Number(), Type.Null(), { additionalProperties: false, }) Fail(T, { a: null, b: null, 0: null, 1: null, }) Ok(T, { 0: null, 1: null, }) }) it('Should validate for any keys', () => { const T = Type.Record(Type.Any(), Type.Null(), { additionalProperties: false, }) Ok(T, { a: null, b: null, 0: null, 1: null, }) }) it('Should validate for never keys', () => { const T = Type.Record(Type.Never(), Type.Null(), { additionalProperties: false, }) Ok(T, {}) Fail(T, { a: null, b: null, 0: null, 1: null, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/recursive.ts000066400000000000000000000034561505437577000257010ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { Assert } from '../assert/index' describe('compiler-ajv/Recursive', () => { it('Should generate default ordinal $id if not specified', () => { const Node = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) Assert.IsFalse(Node.$id === undefined) }) it('Should override default ordinal $id if specified', () => { const Node = Type.Recursive( (Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), { $id: 'Node' }, ) Assert.IsEqual(Node.$id === 'Node', true) }) it('Should validate recursive node type', () => { const Node = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) Ok(Node, { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, ], }) }) it('Should validate wrapped recursive node type', () => { const Node = Type.Tuple([ Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ), ]) Ok(Node, [ { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, ], }, ]) }) it('Should not validate wrapped recursive node type with invalid id', () => { const Node = Type.Tuple([ Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ), ]) Fail(Node, [ { id: 'A', nodes: [ { id: 1, nodes: [] }, { id: 'C', nodes: [] }, ], }, ]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/ref.ts000066400000000000000000000034301505437577000244360ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Ref', () => { // ---------------------------------------------------------------- // Deprecated // ---------------------------------------------------------------- it('Should validate for Ref(Schema)', () => { const T = Type.Number({ $id: 'T' }) const R = Type.Ref(T) Ok(R, 1234, [T]) Fail(R, 'hello', [T]) }) // ---------------------------------------------------------------- // Standard // ---------------------------------------------------------------- it('Should should validate when referencing a type', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { $id: 'T' }, ) const R = Type.Ref(T.$id!) Ok( R, { x: 1, y: 2, z: 3, }, [T], ) }) it('Should not validate when passing invalid data', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { $id: 'T' }, ) const R = Type.Ref(T.$id!) Fail( R, { x: 1, y: 2, }, [T], ) }) it('Should de-reference object property schema', () => { const R = Type.Object( { name: Type.String(), }, { $id: 'R' }, ) const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), r: Type.Optional(Type.Ref(R.$id!)), }, { $id: 'T' }, ) Ok(T, { x: 1, y: 2, z: 3 }, [R]) Ok(T, { x: 1, y: 2, z: 3, r: { name: 'hello' } }, [R]) Fail(T, { x: 1, y: 2, z: 3, r: { name: 1 } }, [R]) Fail(T, { x: 1, y: 2, z: 3, r: {} }, [R]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/required.ts000066400000000000000000000035441505437577000255100ustar00rootroot00000000000000import { Type, ReadonlyKind, OptionalKind } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { Assert } from '../assert' describe('compiler-ajv/Required', () => { it('Should convert a partial object into a required object', () => { const A = Type.Object( { x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), z: Type.Optional(Type.Number()), }, { additionalProperties: false }, ) const T = Type.Required(A) Ok(T, { x: 1, y: 1, z: 1 }) Fail(T, { x: 1, y: 1 }) Fail(T, { x: 1 }) Fail(T, {}) }) it('Should update modifier types correctly when converting to required', () => { const A = Type.Object({ x: Type.Readonly(Type.Optional(Type.Number())), y: Type.Readonly(Type.Number()), z: Type.Optional(Type.Number()), w: Type.Number(), }) const T = Type.Required(A) Assert.IsEqual(T.properties.x[ReadonlyKind], 'Readonly') Assert.IsEqual(T.properties.y[ReadonlyKind], 'Readonly') Assert.IsEqual(T.properties.z[OptionalKind], undefined) Assert.IsEqual(T.properties.w[OptionalKind], undefined) }) it('Should inherit options from the source object', () => { const A = Type.Object( { x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), z: Type.Optional(Type.Number()), }, { additionalPropeties: false }, ) const T = Type.Required(A) Assert.IsEqual(A.additionalPropeties, false) Assert.IsEqual(T.additionalPropeties, false) }) // it('Should construct new object when targetting reference', () => { // const T = Type.Object({ a: Type.String(), b: Type.String() }, { $id: 'T' }) // const R = Type.Ref(T) // const P = Type.Required(R) // strictEqual(P.properties.a.type, 'string') // strictEqual(P.properties.b.type, 'string') // }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/string-pattern.ts000066400000000000000000000033761505437577000266540ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/StringPattern', () => { //----------------------------------------------------- // Regular Expression //----------------------------------------------------- it('Should validate regular expression 1', () => { const T = Type.String({ pattern: /[012345]/.source }) Ok(T, '0') Ok(T, '1') Ok(T, '2') Ok(T, '3') Ok(T, '4') Ok(T, '5') }) it('Should validate regular expression 2', () => { const T = Type.String({ pattern: /true|false/.source }) Ok(T, 'true') Ok(T, 'true') Ok(T, 'true') Ok(T, 'false') Ok(T, 'false') Ok(T, 'false') Fail(T, '6') }) it('Should validate regular expression 3', () => { const T = Type.String({ pattern: /true|false/.source }) Fail(T, 'unknown') }) it('Should validate regular expression 4', () => { const T = Type.String({ pattern: /[\d]{5}/.source }) Ok(T, '12345') }) //----------------------------------------------------- // Regular Pattern //----------------------------------------------------- it('Should validate pattern 1', () => { const T = Type.String({ pattern: '[012345]' }) Ok(T, '0') Ok(T, '1') Ok(T, '2') Ok(T, '3') Ok(T, '4') Ok(T, '5') }) it('Should validate pattern 2', () => { const T = Type.String({ pattern: 'true|false' }) Ok(T, 'true') Ok(T, 'true') Ok(T, 'true') Ok(T, 'false') Ok(T, 'false') Ok(T, 'false') Fail(T, '6') }) it('Should validate pattern 3', () => { const T = Type.String({ pattern: 'true|false' }) Fail(T, 'unknown') }) it('Should validate pattern 4', () => { const T = Type.String({ pattern: '[\\d]{5}' }) Ok(T, '12345') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/string.ts000066400000000000000000000031321505437577000251670ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/String', () => { it('Should not validate number', () => { const T = Type.String() Fail(T, 1) }) it('Should validate string', () => { const T = Type.String() Ok(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.String() Fail(T, true) }) it('Should not validate array', () => { const T = Type.String() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.String() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.String() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.String() Fail(T, undefined) }) it('Should validate string format as email', () => { const T = Type.String({ format: 'email' }) Ok(T, 'name@domain.com') }) it('Should validate string format as uuid', () => { const T = Type.String({ format: 'uuid' }) Ok(T, '4a7a17c9-2492-4a53-8e13-06ea2d3f3bbf') }) it('Should validate string format as iso8601 date', () => { const T = Type.String({ format: 'date-time' }) Ok(T, '2021-06-11T20:30:00-04:00') }) it('Should validate minLength', () => { const T = Type.String({ minLength: 4 }) Ok(T, '....') Fail(T, '...') }) it('Should validate maxLength', () => { const T = Type.String({ maxLength: 4 }) Ok(T, '....') Fail(T, '.....') }) it('Should pass numeric 5 digit test', () => { const T = Type.String({ pattern: '[\\d]{5}' }) Ok(T, '12345') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/template-literal.ts000066400000000000000000000100151505437577000271240ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/TemplateLiteral', () => { // -------------------------------------------------------- // Finite // -------------------------------------------------------- it('Should validate finite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([]) Ok(T, '') Fail(T, 'X') }) it('Should validate finite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([Type.Boolean()]) Ok(T, 'true') Ok(T, 'false') Fail(T, 'X') }) it('Should validate finite pattern 2', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A') ]) Ok(T, 'A') Fail(T, 'X') }) it('Should validate finite pattern 3', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Literal('B') ]) Ok(T, 'AB') Fail(T, 'X') }) it('Should validate finite pattern 4', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), Type.Literal('C') ]), ]) Ok(T, 'AB') Ok(T, 'AC') Fail(T, 'X') }) it('Should validate finite pattern 5', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), Type.Literal('C') ]), Type.Literal('D'), ]) Ok(T, 'ABD') Ok(T, 'ACD') Fail(T, 'X') }) it('Should validate finite pattern 6', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Union([ Type.Literal('0'), Type.Literal('1') ]), Type.Union([ Type.Literal('0'), Type.Literal('1') ]), ]) Ok(T, '00') Ok(T, '01') Ok(T, '10') Ok(T, '11') Fail(T, 'X') }) // -------------------------------------------------------- // Infinite // -------------------------------------------------------- it('Should validate infinite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Number() ]) Ok(T, '1') Ok(T, '22') Ok(T, '333') Ok(T, '4444') Fail(T, 'X') }) it('Should validate infinite pattern 2', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Integer() ]) Ok(T, '1') Ok(T, '22') Ok(T, '333') Ok(T, '4444') Fail(T, 'X') }) it('Should validate infinite pattern 3', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.BigInt() ]) Ok(T, '1') Ok(T, '22') Ok(T, '333') Ok(T, '4444') Fail(T, 'X') }) it('Should validate infinite pattern 4', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.String() ]) Ok(T, '1') Ok(T, '22') Ok(T, '333') Ok(T, '4444') Ok(T, 'a') Ok(T, 'bb') Ok(T, 'ccc') Ok(T, 'dddd') }) it('Should validate infinite pattern 5', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Number() ]) Ok(T, 'A1') Ok(T, 'A22') Ok(T, 'A333') Ok(T, 'A4444') Fail(T, 'X') }) it('Should validate infinite pattern 6', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Integer() ]) Ok(T, 'A1') Ok(T, 'A22') Ok(T, 'A333') Ok(T, 'A4444') Fail(T, 'X') }) it('Should validate infinite pattern 7', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.BigInt() ]) Ok(T, 'A1') Ok(T, 'A22') Ok(T, 'A333') Ok(T, 'A4444') Fail(T, 'X') }) it('Should validate infinite pattern 8', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.String() ]) Ok(T, 'A1') Ok(T, 'A22') Ok(T, 'A333') Ok(T, 'A4444') Ok(T, 'Aa') Ok(T, 'Abb') Ok(T, 'Accc') Ok(T, 'Adddd') Fail(T, 'X') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/tuple.ts000066400000000000000000000034541505437577000250210ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Tuple', () => { it('Should validate tuple of [string, number]', () => { const A = Type.String() const B = Type.Number() const T = Type.Tuple([A, B]) Ok(T, ['hello', 42]) }) it('Should not validate tuple of [string, number] when reversed', () => { const A = Type.String() const B = Type.Number() const T = Type.Tuple([A, B]) Fail(T, [42, 'hello']) }) it('Should validate with empty tuple', () => { const T = Type.Tuple([]) Ok(T, []) }) it('Should not validate with empty tuple with more items', () => { const T = Type.Tuple([]) Fail(T, [1]) }) it('Should not validate with empty tuple with less items', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) Fail(T, [1]) }) it('Should validate tuple of objects', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Tuple([A, B]) Ok(T, [{ a: 'hello' }, { b: 42 }]) }) it('Should not validate tuple of objects when reversed', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Tuple([A, B]) Fail(T, [{ b: 42 }, { a: 'hello' }]) }) it('Should not validate tuple when array is less than tuple length', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Tuple([A, B]) Fail(T, [{ a: 'hello' }]) }) it('Should not validate tuple when array is greater than tuple length', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Tuple([A, B]) Fail(T, [{ a: 'hello' }, { b: 42 }, { b: 42 }]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/uint8array.ts000066400000000000000000000030051505437577000257660ustar00rootroot00000000000000// --------------------------------------------------- // No Longer Supported // --------------------------------------------------- // import { Type } from '@sinclair/typebox' // import { Ok, Fail } from './validate' // describe('compiler-ajv/Uint8Array', () => { // it('Should not validate number', () => { // const T = Type.Uint8Array() // Fail(T, 1) // }) // it('Should not validate string', () => { // const T = Type.Uint8Array() // Fail(T, 'hello') // }) // it('Should not validate boolean', () => { // const T = Type.Uint8Array() // Fail(T, true) // }) // it('Should not validate array', () => { // const T = Type.Uint8Array() // Fail(T, [1, 2, 3]) // }) // it('Should not validate object', () => { // const T = Type.Uint8Array() // Fail(T, { a: 1, b: 2 }) // }) // it('Should not validate null', () => { // const T = Type.Uint8Array() // Fail(T, null) // }) // it('Should not validate undefined', () => { // const T = Type.Uint8Array() // Fail(T, undefined) // }) // it('Should validate Uint8Array', () => { // const T = Type.Uint8Array() // Ok(T, new Uint8Array(100)) // }) // it('Should validate minByteLength', () => { // const T = Type.Uint8Array({ minByteLength: 4 }) // Ok(T, new Uint8Array(4)) // Fail(T, new Uint8Array(3)) // }) // it('Should validate maxByteLength', () => { // const T = Type.Uint8Array({ maxByteLength: 4 }) // Ok(T, new Uint8Array(4)) // Fail(T, new Uint8Array(5)) // }) // }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/union.ts000066400000000000000000000043751505437577000250230ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Union', () => { it('Should validate union of string, number and boolean', () => { const A = Type.String() const B = Type.Number() const C = Type.Boolean() const T = Type.Union([A, B, C]) Ok(T, 'hello') Ok(T, true) Ok(T, 42) }) it('Should validate union of objects', () => { const A = Type.Object({ a: Type.String() }, { additionalProperties: false }) const B = Type.Object({ b: Type.String() }, { additionalProperties: false }) const T = Type.Union([A, B]) Ok(T, { a: 'hello' }) Ok(T, { b: 'world' }) }) it('Should fail to validate for descriminated union types', () => { const A = Type.Object({ kind: Type.Literal('A'), value: Type.String() }) const B = Type.Object({ kind: Type.Literal('B'), value: Type.Number() }) const T = Type.Union([A, B]) Fail(T, { kind: 'A', value: 42 }) // expect { kind: 'A', value: string } Fail(T, { kind: 'B', value: 'hello' }) // expect { kind: 'B', value: number } }) it('Should validate union of objects where properties overlap', () => { const A = Type.Object({ a: Type.String() }, { additionalProperties: false }) const B = Type.Object({ a: Type.String(), b: Type.String() }, { additionalProperties: false }) const T = Type.Union([A, B]) Ok(T, { a: 'hello' }) // A Ok(T, { a: 'hello', b: 'world' }) // B }) it('Should validate union of overlapping property of varying type', () => { const A = Type.Object({ a: Type.String(), b: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ a: Type.String(), b: Type.String() }, { additionalProperties: false }) const T = Type.Union([A, B]) Ok(T, { a: 'hello', b: 42 }) // A Ok(T, { a: 'hello', b: 'world' }) // B }) it('Should validate union of literal strings', () => { const A = Type.Literal('hello') const B = Type.Literal('world') const T = Type.Union([A, B]) Ok(T, 'hello') // A Ok(T, 'world') // B }) it('Should not validate union of literal strings for unknown string', () => { const A = Type.Literal('hello') const B = Type.Literal('world') const T = Type.Union([A, B]) Fail(T, 'foo') // A Fail(T, 'bar') // B }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/unknown.ts000066400000000000000000000013361505437577000253640ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler-ajv/Unknown', () => { it('Should validate number', () => { const T = Type.Any() Ok(T, 1) }) it('Should validate string', () => { const T = Type.Any() Ok(T, 'hello') }) it('Should validate boolean', () => { const T = Type.Any() Ok(T, true) }) it('Should validate array', () => { const T = Type.Any() Ok(T, [1, 2, 3]) }) it('Should validate object', () => { const T = Type.Any() Ok(T, { a: 1, b: 2 }) }) it('Should validate null', () => { const T = Type.Any() Ok(T, null) }) it('Should validate undefined', () => { const T = Type.Any() Ok(T, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/unsafe.ts000066400000000000000000000007151505437577000251460ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Unsafe', () => { it('Should validate an unsafe type', () => { const T = Type.Unsafe({ type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' }, z: { type: 'number' }, }, additionalProperties: false, }) Ok(T, { x: 1, y: 2, z: 3 }) Fail(T, { x: 1, y: 2, z: 3, w: 4 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/validate.ts000066400000000000000000000065441505437577000254640ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Value } from '@sinclair/typebox/value' import { TSchema } from '@sinclair/typebox' import addFormats from 'ajv-formats' import Ajv, { AnySchema } from 'ajv/dist/2019' function schemaOf(schemaOf: string, value: unknown, schema: unknown) { switch (schemaOf) { case 'Constructor': return TypeGuard.IsConstructor(schema) && Value.Check(schema, value) case 'Function': return TypeGuard.IsFunction(schema) && Value.Check(schema, value) case 'Date': return TypeGuard.IsDate(schema) && Value.Check(schema, value) case 'Promise': return TypeGuard.IsPromise(schema) && Value.Check(schema, value) case 'Uint8Array': return TypeGuard.IsUint8Array(schema) && Value.Check(schema, value) case 'Undefined': return TypeGuard.IsUndefined(schema) && Value.Check(schema, value) case 'Void': return TypeGuard.IsVoid(schema) && Value.Check(schema, value) default: return false } } export function createAjv(references: AnySchema[]) { return addFormats(new Ajv({}), ['date-time', 'time', 'date', 'email', 'hostname', 'ipv4', 'ipv6', 'uri', 'uri-reference', 'uuid', 'uri-template', 'json-pointer', 'relative-json-pointer', 'regex']) .addKeyword({ type: 'object', keyword: 'instanceOf', validate: schemaOf }) .addKeyword({ type: 'null', keyword: 'typeOf', validate: schemaOf }) .addKeyword('exclusiveMinimumTimestamp') .addKeyword('exclusiveMaximumTimestamp') .addKeyword('minimumTimestamp') .addKeyword('maximumTimestamp') .addKeyword('minByteLength') .addKeyword('maxByteLength') .addSchema(references) } export function Ok(type: T, data: unknown, additional: AnySchema[] = []) { const ajv = createAjv(additional) function execute() { // required as ajv will throw if referenced schema is not found try { return ajv.validate(type, data) as boolean } catch { return false } } if (execute() === false) { console.log('---------------------------') console.log('type') console.log('---------------------------') console.log(JSON.stringify(type, null, 2)) console.log('---------------------------') console.log('data') console.log('---------------------------') console.log(JSON.stringify(data, null, 2)) console.log('---------------------------') console.log('errors') console.log('---------------------------') console.log(ajv.errorsText(ajv.errors)) throw Error('expected ok') } } export function Fail(type: T, data: unknown, additional: AnySchema[] = []) { const ajv = createAjv(additional) function execute() { // required as ajv will throw if referenced schema is not found try { return ajv.validate(type, data) as boolean } catch { return false } } if (execute() === true) { console.log('---------------------------') console.log('type') console.log('---------------------------') console.log(JSON.stringify(type, null, 2)) console.log('---------------------------') console.log('data') console.log('---------------------------') console.log(JSON.stringify(data, null, 2)) console.log('---------------------------') console.log('errors') console.log('---------------------------') console.log(ajv.errorsText(ajv.errors)) throw Error('expected ok') } } sinclairzx81-typebox-e0ec98c/test/runtime/compiler-ajv/void.ts000066400000000000000000000014141505437577000246230ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler-ajv/Void', () => { it('Should not validate number', () => { const T = Type.Void() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.Void() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Void() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Void() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Void() Fail(T, { a: 1, b: 2 }) }) it('Should validate null', () => { const T = Type.Null() Ok(T, null) }) it('Should not validate undefined', () => { const T = Type.Void() Fail(T, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/000077500000000000000000000000001505437577000225345ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/compiler/__members.ts000066400000000000000000000015261505437577000250400ustar00rootroot00000000000000import { TypeCompiler } from '@sinclair/typebox/compiler' import { Type, TypeGuard, ValueGuard } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('compiler/TypeCheckMembers', () => { it('Should return Schema', () => { const A = TypeCompiler.Compile(Type.Number(), [Type.String(), Type.Boolean()]) Assert.IsTrue(TypeGuard.IsNumber(A.Schema())) }) it('Should return References', () => { const A = TypeCompiler.Compile(Type.Number(), [Type.String(), Type.Boolean()]) Assert.IsTrue(TypeGuard.IsNumber(A.Schema())) Assert.IsTrue(TypeGuard.IsString(A.References()[0])) Assert.IsTrue(TypeGuard.IsBoolean(A.References()[1])) }) it('Should return Code', () => { const A = TypeCompiler.Compile(Type.Number(), [Type.String(), Type.Boolean()]) Assert.IsTrue(ValueGuard.IsString(A.Code())) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/any.ts000066400000000000000000000016121505437577000236730ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler/Any', () => { it('Should validate number', () => { const T = Type.Any() Ok(T, 1) }) it('Should validate string', () => { const T = Type.Any() Ok(T, 'hello') }) it('Should validate boolean', () => { const T = Type.Any() Ok(T, true) }) it('Should validate array', () => { const T = Type.Any() Ok(T, [1, 2, 3]) }) it('Should validate object', () => { const T = Type.Any() Ok(T, { a: 1, b: 2 }) }) it('Should validate null', () => { const T = Type.Any() Ok(T, null) }) it('Should validate undefined', () => { const T = Type.Any() Ok(T, undefined) }) it('Should validate bigint', () => { const T = Type.Any() Ok(T, BigInt(1)) }) it('Should validate symbol', () => { const T = Type.Any() Ok(T, Symbol(1)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/argument.ts000066400000000000000000000017051505437577000247310ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler/Argument', () => { it('Should validate number', () => { const T = Type.Argument(0) Ok(T, 1) }) it('Should validate string', () => { const T = Type.Argument(0) Ok(T, 'hello') }) it('Should validate boolean', () => { const T = Type.Argument(0) Ok(T, true) }) it('Should validate array', () => { const T = Type.Argument(0) Ok(T, [1, 2, 3]) }) it('Should validate object', () => { const T = Type.Argument(0) Ok(T, { a: 1, b: 2 }) }) it('Should validate null', () => { const T = Type.Argument(0) Ok(T, null) }) it('Should validate undefined', () => { const T = Type.Argument(0) Ok(T, undefined) }) it('Should validate bigint', () => { const T = Type.Argument(0) Ok(T, BigInt(1)) }) it('Should validate symbol', () => { const T = Type.Argument(0) Ok(T, Symbol(1)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/array.ts000066400000000000000000000142341505437577000242260ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Array', () => { it('Should validate an array of any', () => { const T = Type.Array(Type.Any()) Ok(T, [0, true, 'hello', {}]) }) it('Should not validate varying array when item is number', () => { const T = Type.Array(Type.Number()) Fail(T, [1, 2, 3, 'hello']) }) it('Should validate for an array of unions', () => { const T = Type.Array(Type.Union([Type.Number(), Type.String()])) Ok(T, [1, 'hello', 3, 'world']) }) it('Should not validate for an array of unions where item is not in union.', () => { const T = Type.Array(Type.Union([Type.Number(), Type.String()])) Fail(T, [1, 'hello', 3, 'world', true]) }) it('Should validate for an empty array', () => { const T = Type.Array(Type.Union([Type.Number(), Type.String()])) Ok(T, []) }) it('Should validate for an array of intersection types', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.String() }) const C = Type.Intersect([A, B]) const T = Type.Array(C) Ok(T, [ { a: 'hello', b: 'hello' }, { a: 'hello', b: 'hello' }, { a: 'hello', b: 'hello' }, ]) }) it('Should not validate for an array of composite types when passing additionalProperties false', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.String() }) const C = Type.Composite([A, B], { additionalProperties: false }) const T = Type.Array(C) Fail(T, [ { a: 'hello', b: 'hello' }, { a: 'hello', b: 'hello' }, { a: 'hello', b: 'hello', c: 'additional' }, ]) }) it('Should validate an array of tuples', () => { const A = Type.String() const B = Type.Number() const C = Type.Tuple([A, B]) const T = Type.Array(C) Ok(T, [ ['hello', 1], ['hello', 1], ['hello', 1], ]) }) it('Should not validate an array of tuples when tuple values are incorrect', () => { const A = Type.String() const B = Type.Number() const C = Type.Tuple([A, B]) const T = Type.Array(C) Fail(T, [ [1, 'hello'], [1, 'hello'], [1, 'hello'], ]) }) it('Should not validate array with failed minItems', () => { const T = Type.Array(Type.Number(), { minItems: 3 }) Fail(T, [0, 1]) }) it('Should not validate array with failed maxItems', () => { const T = Type.Array(Type.Number(), { maxItems: 3 }) Fail(T, [0, 1, 2, 3]) }) // --------------------------------------------------------- // Unique Items // --------------------------------------------------------- it('Should validate array with uniqueItems when items are distinct objects', () => { const T = Type.Array(Type.Object({ x: Type.Number(), y: Type.Number() }), { uniqueItems: true }) Ok(T, [ { x: 0, y: 1 }, { x: 1, y: 0 }, ]) }) it('Should not validate array with uniqueItems when items are not distinct objects', () => { const T = Type.Array(Type.Object({ x: Type.Number(), y: Type.Number() }), { uniqueItems: true }) Fail(T, [ { x: 1, y: 0 }, { x: 1, y: 0 }, ]) }) it('Should not validate array with non uniqueItems', () => { const T = Type.Array(Type.Number(), { uniqueItems: true }) Fail(T, [0, 0]) }) // --------------------------------------------------------- // Contains // --------------------------------------------------------- it('Should validate for contains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1) }) Ok(T, [1]) Ok(T, [1, 2]) Fail(T, []) Fail(T, [2]) }) it('Should validate for minContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), minContains: 3 }) Ok(T, [1, 1, 1, 2]) Ok(T, [2, 1, 1, 1, 2]) Ok(T, [1, 1, 1]) Fail(T, []) Fail(T, [1, 1]) Fail(T, [2]) }) it('Should validate for maxContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), maxContains: 3 }) Ok(T, [1, 1, 1]) Ok(T, [1, 1]) Ok(T, [2, 2, 2, 2, 1, 1, 1]) Fail(T, [1, 1, 1, 1]) }) it('Should validate for minContains and maxContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), minContains: 3, maxContains: 5 }) Fail(T, [1, 1]) Ok(T, [1, 1, 1]) Ok(T, [1, 1, 1, 1]) Ok(T, [1, 1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1, 1]) }) it('Should not validate minContains or maxContains when contains is unspecified', () => { const T = Type.Array(Type.Number(), { minContains: 3, maxContains: 5 }) Fail(T, [1, 1]) Fail(T, [1, 1, 1]) Fail(T, [1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1, 1]) }) it('Should produce illogical schema when contains is not sub type of items', () => { const T = Type.Array(Type.Number(), { contains: Type.String(), minContains: 3, maxContains: 5 }) Fail(T, [1, 1]) Fail(T, [1, 1, 1]) Fail(T, [1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1]) Fail(T, [1, 1, 1, 1, 1, 1]) }) // ---------------------------------------------------------------- // Issue: https://github.com/sinclairzx81/typebox/discussions/607 // ---------------------------------------------------------------- it('Should correctly handle undefined array properties', () => { const Answer = Type.Object({ text: Type.String(), isCorrect: Type.Boolean(), }) const Question = Type.Object({ text: Type.String(), options: Type.Array(Answer, { minContains: 1, maxContains: 1, contains: Type.Object({ text: Type.String(), isCorrect: Type.Literal(true), }), }), }) Fail(Question, { text: 'A' }) Fail(Question, { text: 'A', options: [] }) Ok(Question, { text: 'A', options: [{ text: 'A', isCorrect: true }] }) Ok(Question, { text: 'A', options: [ { text: 'A', isCorrect: true }, { text: 'B', isCorrect: false }, ], }) Fail(Question, { text: 'A', options: [{ text: 'A', isCorrect: false }] }) Fail(Question, { text: 'A', options: [ { text: 'A', isCorrect: true }, { text: 'B', isCorrect: true }, ], }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/async-iterator.ts000066400000000000000000000010441505437577000260470ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/AsyncIterator', () => { it('Should validate a async iterator 1', () => { async function* f() {} const T = Type.AsyncIterator(Type.Any()) Ok(T, f()) }) it('Should validate a async iterator 2', () => { const T = Type.AsyncIterator(Type.Any()) Ok(T, { [Symbol.asyncIterator]: () => {}, }) }) it('Should not validate a async iterator', () => { const T = Type.AsyncIterator(Type.Any()) Fail(T, {}) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/bigint.ts000066400000000000000000000040171505437577000243620ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/BigInt', () => { it('Should not validate number', () => { const T = Type.BigInt() Fail(T, 3.14) }) it('Should not validate NaN', () => { const T = Type.BigInt() Fail(T, NaN) }) it('Should not validate +Infinity', () => { const T = Type.BigInt() Fail(T, Infinity) }) it('Should not validate -Infinity', () => { const T = Type.BigInt() Fail(T, -Infinity) }) it('Should not validate integer', () => { const T = Type.BigInt() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.BigInt() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.BigInt() Fail(T, true) }) it('Should not validate array', () => { const T = Type.BigInt() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.BigInt() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.BigInt() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.BigInt() Fail(T, undefined) }) it('Should not validate symbol', () => { const T = Type.BigInt() Fail(T, Symbol()) }) it('Should validate bigint', () => { const T = Type.BigInt() Ok(T, BigInt(1)) }) it('Should validate minimum', () => { const T = Type.BigInt({ minimum: BigInt(10) }) Fail(T, BigInt(9)) Ok(T, BigInt(10)) }) it('Should validate maximum', () => { const T = Type.BigInt({ maximum: BigInt(10) }) Ok(T, BigInt(10)) Fail(T, BigInt(11)) }) it('Should validate Date exclusiveMinimum', () => { const T = Type.BigInt({ exclusiveMinimum: BigInt(10) }) Fail(T, BigInt(10)) Ok(T, BigInt(11)) }) it('Should validate Date exclusiveMaximum', () => { const T = Type.BigInt({ exclusiveMaximum: BigInt(10) }) Ok(T, BigInt(9)) Fail(T, BigInt(10)) }) it('Should not validate NaN', () => { Fail(Type.Number(), NaN) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/boolean.ts000066400000000000000000000017731505437577000245330ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Boolean', () => { it('Should validate a boolean', () => { const T = Type.Boolean() Ok(T, true) Ok(T, false) }) it('Should not validate a number', () => { const T = Type.Boolean() Fail(T, 1) }) it('Should not validate a string', () => { const T = Type.Boolean() Fail(T, 'true') }) it('Should not validate an array', () => { const T = Type.Boolean() Fail(T, [true]) }) it('Should not validate an object', () => { const T = Type.Boolean() Fail(T, {}) }) it('Should not validate an null', () => { const T = Type.Boolean() Fail(T, null) }) it('Should not validate an undefined', () => { const T = Type.Boolean() Fail(T, undefined) }) it('Should not validate bigint', () => { const T = Type.Boolean() Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.Boolean() Fail(T, Symbol(1)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/composite.ts000066400000000000000000000070231505437577000251100ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Composite', () => { it('Should compose two objects', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Composite([A, B], { additionalProperties: false }) Ok(T, { a: 'hello', b: 42 }) }) it('Should compose with partial', () => { const A = Type.Partial(Type.Object({ a: Type.Number() })) const B = Type.Partial(Type.Object({ b: Type.Number() })) const P = Type.Composite([A, B], { additionalProperties: false }) Ok(P, { a: 1, b: 2 }) Ok(P, { a: 1 }) Ok(P, { b: 1 }) Ok(P, {}) Fail(P, { a: 1, b: 2, c: 3 }) Fail(P, { c: 1 }) }) it('Should compose with overlapping same type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.Number() }) const P = Type.Composite([A, B]) Ok(P, { a: 1 }) Fail(P, { a: '1' }) }) it('Should not compose with overlapping varying type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.String() }) const T = Type.Composite([A, B]) Fail(T, { a: 1 }) Fail(T, { a: 'hello' }) Fail(T, {}) }) it('Should compose with deeply nest overlapping varying type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ b: Type.String() }) const C = Type.Object({ c: Type.Boolean() }) const D = Type.Object({ d: Type.Null() }) const T = Type.Composite([A, B, C, D]) Ok(T, { a: 1, b: 'hello', c: true, d: null }) }) it('Should not compose with deeply nest overlapping varying type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.String() }) const C = Type.Object({ a: Type.Boolean() }) const D = Type.Object({ a: Type.Null() }) const T = Type.Composite([A, B, C, D]) Fail(T, { a: 1 }) Fail(T, { a: 'hello' }) Fail(T, { a: false }) Fail(T, { a: null }) Fail(T, { a: [] }) Fail(T, {}) }) it('Should pick from composited type', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const C = Type.Object({ z: Type.Number() }) const T = Type.Composite([A, B, C]) const P = Type.Pick(T, ['x', 'y'], { additionalProperties: false }) Ok(P, { x: 1, y: 1 }) Fail(P, { x: 1, y: 1, z: 1 }) }) it('Should omit from composited type', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const C = Type.Object({ z: Type.Number() }) const T = Type.Composite([A, B, C]) const P = Type.Omit(T, ['z'], { additionalProperties: false }) Ok(P, { x: 1, y: 1 }) Fail(P, { x: 1, y: 1, z: 1 }) }) it('Should compose nested object properties', () => { const A = Type.Object({ x: Type.Object({ x: Type.Number() }) }) const B = Type.Object({ y: Type.Object({ x: Type.String() }) }) const T = Type.Composite([A, B]) Ok(T, { x: { x: 1 }, y: { x: '' } }) Fail(T, { x: { x: '1' }, y: { x: '' } }) Fail(T, { x: { x: 1 }, y: { x: 1 } }) }) // prettier-ignore it('Should composite intersection', () => { const T = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Number() }) ]), Type.Intersect([ Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }) ]), ]) Ok(T, { x: 1, y: 2, z: 3 }) Fail(T, { x: 1, y: 2, z: '3' }) Fail(T, { x: 1, y: 2 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/const.ts000066400000000000000000000015661505437577000242420ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler/Const', () => { it('Should validate 1', () => { const T = Type.Const(1) Ok(T, 1) }) it('Should validate 2', () => { const T = Type.Const('hello') Ok(T, 'hello') }) it('Should validate 3', () => { const T = Type.Const(true) Ok(T, true) }) it('Should validate 4', () => { const T = Type.Const({ x: 1, y: 2 }) Ok(T, { x: 1, y: 2 }) }) it('Should validate 5', () => { const T = Type.Const([1, 2, 3]) Ok(T, [1, 2, 3]) }) it('Should validate 6', () => { const T = Type.Const([1, true, 'hello']) Ok(T, [1, true, 'hello']) }) it('Should validate 7', () => { const T = Type.Const({ x: [1, 2, 3, 4], y: { x: 1, y: 2, z: 3 }, }) Ok(T, { x: [1, 2, 3, 4], y: { x: 1, y: 2, z: 3 }, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/constructor.ts000066400000000000000000000031701505437577000254720ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Constructor', () => { it('Should validate constructor 1', () => { const T = Type.Constructor([], Type.Object({})) Ok(T, class {}) }) it('Should validate constructor 2', () => { const T = Type.Constructor([Type.Number()], Type.Object({})) // note: constructor arguments are non-checkable Ok(T, class {}) }) it('Should validate constructor 3', () => { const T = Type.Constructor( [Type.Number()], Type.Object({ method: Type.Function([], Type.Void()), }), ) Ok( T, class { method() {} }, ) }) it('Should validate constructor 4', () => { const T = Type.Constructor( [Type.Number()], Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) Ok( T, class { get x() { return 1 } get y() { return 1 } get z() { return 1 } }, ) }) it('Should not validate constructor 1', () => { const T = Type.Constructor([Type.Number()], Type.Object({})) Fail(T, 1) }) it('Should not validate constructor 2', () => { const T = Type.Constructor( [Type.Number()], Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) Fail( T, class { get x() { return null } get y() { return null } get z() { return null } }, ) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/date.ts000066400000000000000000000037521505437577000240300ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Date', () => { it('Should not validate number', () => { const T = Type.Date() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.Date() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Date() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Date() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Date() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Date() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.Date() Fail(T, undefined) }) it('Should validate Date', () => { const T = Type.Date() Ok(T, new Date()) }) it('Should not validate bigint', () => { const T = Type.Date() Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.Date() Fail(T, Symbol(1)) }) it('Should not validate Date if is invalid', () => { const T = Type.Date() Fail(T, new Date('not-a-valid-date')) }) it('Should validate Date minimumTimestamp', () => { const T = Type.Date({ minimumTimestamp: 10 }) Fail(T, new Date(9)) Ok(T, new Date(10)) }) it('Should validate Date maximumTimestamp', () => { const T = Type.Date({ maximumTimestamp: 10 }) Fail(T, new Date(11)) Ok(T, new Date(10)) }) it('Should validate Date exclusiveMinimumTimestamp', () => { const T = Type.Date({ exclusiveMinimumTimestamp: 10 }) Fail(T, new Date(10)) Ok(T, new Date(11)) }) it('Should validate Date exclusiveMaximumTimestamp', () => { const T = Type.Date({ exclusiveMaximumTimestamp: 10 }) Fail(T, new Date(10)) Ok(T, new Date(9)) }) it('Should validate Date multipleOfTimestamp', () => { const T = Type.Date({ multipleOfTimestamp: 2 }) Fail(T, new Date(1)) Ok(T, new Date(2)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/enum.ts000066400000000000000000000022241505437577000240500ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Enum', () => { it('Should validate when emum uses default numeric values', () => { enum Kind { Foo, // = 0 Bar, // = 1 } const T = Type.Enum(Kind) Ok(T, 0) Ok(T, 1) }) it('Should not validate when given enum values are not numeric', () => { enum Kind { Foo, // = 0 Bar, // = 1 } const T = Type.Enum(Kind) Fail(T, 'Foo') Fail(T, 'Bar') }) it('Should validate when emum has defined string values', () => { enum Kind { Foo = 'foo', Bar = 'bar', } const T = Type.Enum(Kind) Ok(T, 'foo') Ok(T, 'bar') }) it('Should not validate when emum has defined string values and user passes numeric', () => { enum Kind { Foo = 'foo', Bar = 'bar', } const T = Type.Enum(Kind) Fail(T, 0) Fail(T, 1) }) it('Should validate when enum has one or more string values', () => { enum Kind { Foo, Bar = 'bar', } const T = Type.Enum(Kind) Ok(T, 0) Ok(T, 'bar') Fail(T, 'baz') Fail(T, 'Foo') Fail(T, 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/function.ts000066400000000000000000000014771505437577000247420ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Function', () => { it('Should validate function 1', () => { const T = Type.Function([Type.Number()], Type.Number()) Ok(T, function () {}) }) it('Should validate function 2', () => { const T = Type.Function([Type.Number()], Type.Number()) // note: validation only checks typeof 'function' Ok(T, function (a: string, b: string, c: string, d: string) {}) }) it('Should validate function 3', () => { const T = Type.Function([Type.Number()], Type.Number()) // note: validation only checks typeof 'function' Ok(T, function () { return 'not-a-number' }) }) it('Should not validate function', () => { const T = Type.Function([Type.Number()], Type.Number()) Fail(T, 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/index.ts000066400000000000000000000015531505437577000242170ustar00rootroot00000000000000import './__members' import './any' import './argument' import './array' import './async-iterator' import './bigint' import './boolean' import './composite' import './const' import './constructor' import './date' import './unicode' import './enum' import './function' import './integer' import './intersect' import './iterator' import './keyof' import './kind' import './literal' import './module' import './never' import './not' import './null' import './number' import './object' import './omit' import './optional' import './partial' import './pick' import './readonly-optional' import './readonly' import './recursive' import './record' import './ref' import './regexp' import './required' import './string-pattern' import './string' import './symbol' import './template-literal' import './tuple' import './uint8array' import './union' import './unknown' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/compiler/integer.ts000066400000000000000000000035701505437577000245460ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Integer', () => { it('Should not validate number', () => { const T = Type.Integer() Fail(T, 3.14) }) it('Should not validate NaN', () => { const T = Type.Integer() Fail(T, NaN) }) it('Should not validate +Infinity', () => { const T = Type.Integer() Fail(T, Infinity) }) it('Should not validate -Infinity', () => { const T = Type.Integer() Fail(T, -Infinity) }) it('Should validate integer', () => { const T = Type.Integer() Ok(T, 1) }) it('Should not validate string', () => { const T = Type.Integer() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Integer() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Integer() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Integer() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Integer() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.Integer() Fail(T, undefined) }) it('Should not validate bigint', () => { const T = Type.Integer() Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.Integer() Fail(T, Symbol(1)) }) it('Should validate minimum', () => { const T = Type.Integer({ minimum: 10 }) Fail(T, 9) Ok(T, 10) }) it('Should validate maximum', () => { const T = Type.Integer({ maximum: 10 }) Ok(T, 10) Fail(T, 11) }) it('Should validate Date exclusiveMinimum', () => { const T = Type.Integer({ exclusiveMinimum: 10 }) Fail(T, 10) Ok(T, 11) }) it('Should validate Date exclusiveMaximum', () => { const T = Type.Integer({ exclusiveMaximum: 10 }) Ok(T, 9) Fail(T, 10) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/intersect.ts000066400000000000000000000154531505437577000251140ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Intersect', () => { it('Should intersect number and number', () => { const A = Type.Number() const B = Type.Number() const T = Type.Intersect([A, B], {}) Ok(T, 1) }) it('Should not intersect string and number', () => { const A = Type.String() const B = Type.Number() const T = Type.Intersect([A, B], {}) Fail(T, 1) Fail(T, '1') }) it('Should intersect two objects', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Ok(T, { x: 1, y: 1 }) }) it('Should not intersect two objects with internal additionalProperties false', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ y: Type.Number() }, { additionalProperties: false }) const T = Type.Intersect([A, B], {}) Fail(T, { x: 1, y: 1 }) }) it('Should intersect two objects and mandate required properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Ok(T, { x: 1, y: 1 }) Fail(T, { x: 1 }) Fail(T, { y: 1 }) }) it('Should intersect two objects with unevaluated properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Ok(T, { x: 1, y: 2, z: 1 }) }) it('Should intersect two objects and restrict unevaluated properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], { unevaluatedProperties: false }) Fail(T, { x: 1, y: 2, z: 1 }) }) it('Should intersect two objects and allow unevaluated properties of number', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], { unevaluatedProperties: Type.Number() }) Ok(T, { x: 1, y: 2, z: 3 }) Fail(T, { x: 1, y: 2, z: '1' }) }) it('Should intersect two nested objects and allow unevaluated properties of number', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Object({ nested: Type.Intersect([A, B], { unevaluatedProperties: Type.Number() }) }) Ok(T, { nested: { x: 1, y: 2, z: 3 } }) Fail(T, { nested: { x: 1, y: 2, z: '1' } }) }) it('Should intersect two union objects with overlapping properties of the same type', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ x: Type.Number() })]) const T = Type.Intersect([A, B]) Ok(T, { x: 1 }) Fail(T, { x: '1' }) }) it('Should not intersect two union objects with overlapping properties of varying types', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ x: Type.String() })]) const T = Type.Intersect([A, B]) Fail(T, { x: 1 }) Fail(T, { x: '1' }) }) it('Should intersect two union objects with non-overlapping properties', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ y: Type.Number() })]) const T = Type.Intersect([A, B]) Ok(T, { x: 1, y: 1 }) }) it('Should not intersect two union objects with non-overlapping properties for additionalProperties false', () => { const A = Type.Union([Type.Object({ x: Type.Number() }, { additionalProperties: false })]) const B = Type.Union([Type.Object({ y: Type.Number() }, { additionalProperties: false })]) const T = Type.Intersect([A, B]) Fail(T, { x: 1, y: 1 }) }) it('unevaluatedProperties with Record 1', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Ok(T, { x: 1, y: 2 }) }) it('unevaluatedProperties with Record 2', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Ok(T, { x: 1, y: 2, 0: 'hello' }) }) it('unevaluatedProperties with Record 3', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Fail(T, { x: 1, y: 2, 0: 1 }) }) it('unevaluatedProperties with Record 4', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Ok(T, { x: 1, y: 2 }) }) it('unevaluatedProperties with Record 5', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Ok(T, { x: 1, y: 2, z: true }) }) it('unevaluatedProperties with Record 6', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Fail(T, { x: 1, y: 2, z: 1 }) }) it('unevaluatedProperties with Record 7', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Ok(T, { x: 1, y: 2, 0: '' }) }) it('unevaluatedProperties with Record 8', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Ok(T, { x: 1, y: 2, 0: '', z: true }) }) it('unevaluatedProperties with Record 9', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Fail(T, { x: 1, y: 2, 0: '', z: 1 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/iterator.ts000066400000000000000000000007631505437577000247430ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Iterator', () => { it('Should validate a iterator 1', () => { function* f() {} const T = Type.Iterator(Type.Any()) Ok(T, f()) }) it('Should validate a iterator 2', () => { const T = Type.Iterator(Type.Any()) Ok(T, { [Symbol.iterator]: () => {}, }) }) it('Should not validate a iterator', () => { const T = Type.Iterator(Type.Any()) Fail(T, {}) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/keyof.ts000066400000000000000000000017371505437577000242310ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/KeyOf', () => { it('Should validate with all object keys as a kind of union', () => { const T = Type.KeyOf( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) Ok(T, 'x') Ok(T, 'y') Ok(T, 'z') Fail(T, 'w') }) it('Should validate when using pick', () => { const T = Type.KeyOf( Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ['x', 'y'], ), ) Ok(T, 'x') Ok(T, 'y') Fail(T, 'z') }) it('Should validate when using omit', () => { const T = Type.KeyOf( Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ['x', 'y'], ), ) Fail(T, 'x') Fail(T, 'y') Ok(T, 'z') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/kind.ts000066400000000000000000000106161505437577000240350ustar00rootroot00000000000000import { TypeRegistry, Type, Kind, TSchema } from '@sinclair/typebox' import { TypeCompiler } from '@sinclair/typebox/compiler' import { Ok, Fail } from './validate' import { Assert } from '../assert' describe('compiler/Kind', () => { // ------------------------------------------------------------ // Fixtures // ------------------------------------------------------------ beforeEach(() => TypeRegistry.Set('PI', (_, value) => value === Math.PI)) afterEach(() => TypeRegistry.Delete('PI')) // ------------------------------------------------------------ // Tests // ------------------------------------------------------------ it('Should validate', () => { const T = Type.Unsafe({ [Kind]: 'PI' }) Ok(T, Math.PI) }) it('Should not validate', () => { const T = Type.Unsafe({ [Kind]: 'PI' }) Fail(T, Math.PI * 2) }) it('Should validate in object', () => { const T = Type.Object({ x: Type.Unsafe({ [Kind]: 'PI' }), }) Ok(T, { x: Math.PI }) }) it('Should not validate in object', () => { const T = Type.Object({ x: Type.Unsafe({ [Kind]: 'PI' }), }) Fail(T, { x: Math.PI * 2 }) }) it('Should validate in array', () => { const T = Type.Array(Type.Unsafe({ [Kind]: 'PI' })) Ok(T, [Math.PI]) }) it('Should not validate in array', () => { const T = Type.Array(Type.Unsafe({ [Kind]: 'PI' })) Fail(T, [Math.PI * 2]) }) it('Should validate in tuple', () => { const T = Type.Tuple([Type.Unsafe({ [Kind]: 'PI' })]) Ok(T, [Math.PI]) }) it('Should not validate in tuple', () => { const T = Type.Tuple([Type.Unsafe({ [Kind]: 'PI' })]) Fail(T, [Math.PI * 2]) }) // ------------------------------------------------------------ // Instances // ------------------------------------------------------------ it('Should receive kind instance on registry callback', () => { const stack: string[] = [] TypeRegistry.Set('Kind', (schema: unknown) => { // prettier-ignore return (typeof schema === 'object' && schema !== null && Kind in schema && schema[Kind] === 'Kind' && '$id' in schema && typeof schema.$id === 'string') ? (() => { stack.push(schema.$id); return true })() : false }) const A = { [Kind]: 'Kind', $id: 'A' } as TSchema const B = { [Kind]: 'Kind', $id: 'B' } as TSchema const T = Type.Object({ a: A, b: B }) const C = TypeCompiler.Compile(T) const R = C.Check({ a: null, b: null }) Assert.IsTrue(R) Assert.IsEqual(stack[0], 'A') Assert.IsEqual(stack[1], 'B') TypeRegistry.Delete('Kind') }) // ------------------------------------------------------------ // Instances Retain // ------------------------------------------------------------ it('Should retain kind instances on subsequent compile', () => { let stack: string[] = [] TypeRegistry.Set('Kind', (schema: unknown) => { // prettier-ignore return (typeof schema === 'object' && schema !== null && Kind in schema && schema[Kind] === 'Kind' && '$id' in schema && typeof schema.$id === 'string') ? (() => { stack.push(schema.$id); return true })() : false }) const A = { [Kind]: 'Kind', $id: 'A' } as TSchema const B = { [Kind]: 'Kind', $id: 'B' } as TSchema const C = { [Kind]: 'Kind', $id: 'C' } as TSchema const D = { [Kind]: 'Kind', $id: 'D' } as TSchema const T1 = Type.Object({ a: A, b: B }) const T2 = Type.Object({ a: C, b: D }) // Compile T1 and run check, expect A and B const C1 = TypeCompiler.Compile(T1) const R1 = C1.Check({ a: null, b: null }) Assert.IsTrue(R1) Assert.IsEqual(stack.length, 2) Assert.IsEqual(stack[0], 'A') Assert.IsEqual(stack[1], 'B') stack = [] // compile T2 and force instance.clear() const C2 = TypeCompiler.Compile(T2) // run T1 check const R2 = C1.Check({ a: null, b: null }) Assert.IsTrue(R2) Assert.IsEqual(stack.length, 2) Assert.IsEqual(stack[0], 'A') Assert.IsEqual(stack[1], 'B') stack = [] // run T2 check const R3 = C2.Check({ a: null, b: null }) Assert.IsTrue(R3) Assert.IsEqual(stack.length, 2) Assert.IsEqual(stack[0], 'C') Assert.IsEqual(stack[1], 'D') stack = [] // run T1 check const R4 = C1.Check({ a: null, b: null }) Assert.IsTrue(R4) Assert.IsEqual(stack.length, 2) Assert.IsEqual(stack[0], 'A') Assert.IsEqual(stack[1], 'B') stack = [] TypeRegistry.Delete('Kind') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/literal.ts000066400000000000000000000026611505437577000245450ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Literal', () => { it('Should validate literal number', () => { const T = Type.Literal(42) Ok(T, 42) }) it('Should validate literal string', () => { const T = Type.Literal('hello') Ok(T, 'hello') }) it('Should validate literal boolean', () => { const T = Type.Literal(true) Ok(T, true) }) it('Should not validate invalid literal number', () => { const T = Type.Literal(42) Fail(T, 43) }) it('Should not validate invalid literal string', () => { const T = Type.Literal('hello') Fail(T, 'world') }) it('Should not validate invalid literal boolean', () => { const T = Type.Literal(false) Fail(T, true) }) it('Should validate literal union', () => { const T = Type.Union([Type.Literal(42), Type.Literal('hello')]) Ok(T, 42) Ok(T, 'hello') }) it('Should not validate invalid literal union', () => { const T = Type.Union([Type.Literal(42), Type.Literal('hello')]) Fail(T, 43) Fail(T, 'world') }) // reference: https://github.com/sinclairzx81/typebox/issues/539 it('Should escape single quote literals', () => { const T = Type.Literal("it's") Ok(T, "it's") Fail(T, "it''s") }) it('Should escape multiple single quote literals', () => { const T = Type.Literal("'''''''''") Ok(T, "'''''''''") Fail(T, "''''''''") // minus 1 }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/module.ts000066400000000000000000000106031505437577000243710ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Module', () => { it('Should validate string', () => { const Module = Type.Module({ A: Type.String(), }) const T = Module.Import('A') Ok(T, 'hello') Fail(T, true) }) it('Should validate referenced string', () => { const Module = Type.Module({ A: Type.String(), B: Type.Ref('A'), }) const T = Module.Import('B') Ok(T, 'hello') Fail(T, true) }) it('Should validate self referential', () => { const Module = Type.Module({ A: Type.Object({ nodes: Type.Array(Type.Ref('A')), }), }) const T = Module.Import('A') Ok(T, { nodes: [{ nodes: [{ nodes: [] }, { nodes: [] }] }] }) Fail(T, { nodes: [{ nodes: [{ nodes: [] }, { nodes: false }] }] }) Fail(T, true) }) it('Should validate mutual recursive', () => { const Module = Type.Module({ A: Type.Object({ b: Type.Ref('B'), }), B: Type.Object({ a: Type.Union([Type.Ref('A'), Type.Null()]), }), }) const T = Module.Import('A') Ok(T, { b: { a: null } }) Ok(T, { b: { a: { b: { a: null } } } }) Fail(T, { b: { a: 1 } }) Fail(T, { b: { a: { b: { a: 1 } } } }) Fail(T, true) }) it('Should validate mutual recursive (Array)', () => { const Module = Type.Module({ A: Type.Object({ b: Type.Ref('B'), }), B: Type.Object({ a: Type.Array(Type.Ref('A')), }), }) const T = Module.Import('A') Ok(T, { b: { a: [{ b: { a: [] } }] } }) Fail(T, { b: { a: [{ b: { a: [null] } }] } }) Fail(T, true) }) it('Should validate deep referential', () => { const Module = Type.Module({ A: Type.Ref('B'), B: Type.Ref('C'), C: Type.Ref('D'), D: Type.Ref('E'), E: Type.Ref('F'), F: Type.Ref('G'), G: Type.Ref('H'), H: Type.Literal('hello'), }) const T = Module.Import('A') Ok(T, 'hello') Fail(T, 'world') }) // ---------------------------------------------------------------- // Modifiers // ---------------------------------------------------------------- it('Should validate objects with property modifiers 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Null()), y: Type.Readonly(Type.Null()), z: Type.Optional(Type.Null()), w: Type.Null(), }), }) const T = Module.Import('T') Ok(T, { x: null, y: null, w: null }) Ok(T, { y: null, w: null }) Fail(T, { x: 1, y: null, w: null }) }) it('Should validate objects with property modifiers 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Array(Type.Null())), y: Type.Readonly(Type.Array(Type.Null())), z: Type.Optional(Type.Array(Type.Null())), w: Type.Array(Type.Null()), }), }) const T = Module.Import('T') Ok(T, { x: [null], y: [null], w: [null] }) Ok(T, { y: [null], w: [null] }) Fail(T, { x: [1], y: [null], w: [null] }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1109 // ---------------------------------------------------------------- it('Should validate deep referential 1', () => { const Module = Type.Module({ A: Type.Union([Type.Literal('Foo'), Type.Literal('Bar')]), B: Type.Ref('A'), C: Type.Object({ ref: Type.Ref('B') }), D: Type.Union([Type.Ref('B'), Type.Ref('C')]), }) Ok(Module.Import('A') as never, 'Foo') Ok(Module.Import('A') as never, 'Bar') Ok(Module.Import('B') as never, 'Foo') Ok(Module.Import('B') as never, 'Bar') Ok(Module.Import('C') as never, { ref: 'Foo' }) Ok(Module.Import('C') as never, { ref: 'Bar' }) Ok(Module.Import('D') as never, 'Foo') Ok(Module.Import('D') as never, 'Bar') Ok(Module.Import('D') as never, { ref: 'Foo' }) Ok(Module.Import('D') as never, { ref: 'Bar' }) }) it('Should validate deep referential 2', () => { const Module = Type.Module({ A: Type.Literal('Foo'), B: Type.Ref('A'), C: Type.Ref('B'), D: Type.Ref('C'), E: Type.Ref('D'), }) Ok(Module.Import('A'), 'Foo') Ok(Module.Import('B'), 'Foo') Ok(Module.Import('C'), 'Foo') Ok(Module.Import('D'), 'Foo') Ok(Module.Import('E'), 'Foo') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/never.ts000066400000000000000000000017261505437577000242310ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Fail } from './validate' describe('compiler/Never', () => { it('Should not validate number', () => { const T = Type.Never() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.Never() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Never() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Never() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Never() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Never() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.Never() Fail(T, undefined) }) it('Should not validate bigint', () => { const T = Type.Never() Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.Never() Fail(T, Symbol(1)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/not.ts000066400000000000000000000021171505437577000237050ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Not', () => { it('Should validate not number', () => { const T = Type.Not(Type.Number()) Fail(T, 1) Ok(T, '1') }) it('Should validate not not number', () => { const T = Type.Not(Type.Not(Type.Number())) Ok(T, 1) Fail(T, '1') }) it('Should validate not union', () => { // prettier-ignore const T = Type.Not(Type.Union([ Type.Literal('A'), Type.Literal('B'), Type.Literal('C') ])) Fail(T, 'A') Fail(T, 'B') Fail(T, 'C') Ok(T, 'D') }) it('Should validate not object intersection', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), Type.Object({ x: Type.Not(Type.Literal(0)), y: Type.Not(Type.Literal(0)), z: Type.Not(Type.Literal(0)), }), ]) Fail(T, { x: 0, y: 0, z: 0 }) Fail(T, { x: 1, y: 0, z: 0 }) Fail(T, { x: 1, y: 1, z: 0 }) Ok(T, { x: 1, y: 1, z: 1 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/null.ts000066400000000000000000000017161505437577000240630ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Null', () => { it('Should not validate number', () => { const T = Type.Null() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.Null() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Null() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Null() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Null() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Null() Ok(T, null) }) it('Should not validate undefined', () => { const T = Type.Null() Fail(T, undefined) }) it('Should not validate bigint', () => { const T = Type.Null() Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.Null() Fail(T, Symbol(1)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/number.ts000066400000000000000000000035401505437577000243760ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Number', () => { it('Should validate number', () => { const T = Type.Number() Ok(T, 3.14) }) it('Should not validate NaN', () => { const T = Type.Number() Fail(T, NaN) }) it('Should not validate +Infinity', () => { const T = Type.Number() Fail(T, Infinity) }) it('Should not validate -Infinity', () => { const T = Type.Number() Fail(T, -Infinity) }) it('Should validate integer', () => { const T = Type.Number() Ok(T, 1) }) it('Should not validate string', () => { const T = Type.Number() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Number() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Number() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Number() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Number() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.Number() Fail(T, undefined) }) it('Should not validate bigint', () => { const T = Type.Number() Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.Number() Fail(T, Symbol(1)) }) it('Should validate minimum', () => { const T = Type.Number({ minimum: 10 }) Fail(T, 9) Ok(T, 10) }) it('Should validate maximum', () => { const T = Type.Number({ maximum: 10 }) Ok(T, 10) Fail(T, 11) }) it('Should validate Date exclusiveMinimum', () => { const T = Type.Number({ exclusiveMinimum: 10 }) Fail(T, 10) Ok(T, 11) }) it('Should validate Date exclusiveMaximum', () => { const T = Type.Number({ exclusiveMaximum: 10 }) Ok(T, 9) Fail(T, 10) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/object.ts000066400000000000000000000226451505437577000243630ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Object', () => { // ----------------------------------------------------- // TypeCompiler Only // ----------------------------------------------------- it('Should handle extends undefined check 1', () => { const T = Type.Object({ A: Type.Not(Type.Number()), B: Type.Union([Type.Number(), Type.Undefined()]), C: Type.Intersect([Type.Undefined(), Type.Undefined()]), }) Ok(T, { A: undefined, B: undefined, C: undefined, }) }) // https://github.com/sinclairzx81/typebox/issues/437 it('Should handle extends undefined check 2', () => { const T = Type.Object({ A: Type.Not(Type.Null()), }) Ok(T, { A: undefined }) Fail(T, { A: null }) Fail(T, {}) }) // ----------------------------------------------------- // Standard Checks // ----------------------------------------------------- it('Should not validate a number', () => { const T = Type.Object({}) Fail(T, 42) }) it('Should not validate a string', () => { const T = Type.Object({}) Fail(T, 'hello') }) it('Should not validate a boolean', () => { const T = Type.Object({}) Fail(T, true) }) it('Should not validate a null', () => { const T = Type.Object({}) Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.Object({}) Fail(T, undefined) }) it('Should not validate bigint', () => { const T = Type.Object({}) Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.Object({}) Fail(T, Symbol(1)) }) it('Should not validate an array', () => { const T = Type.Object({}) Fail(T, [1, 2]) }) it('Should validate with correct property values', () => { const T = Type.Object({ a: Type.Number(), b: Type.String(), c: Type.Boolean(), d: Type.Array(Type.Number()), e: Type.Object({ x: Type.Number(), y: Type.Number() }), }) Ok(T, { a: 10, b: 'hello', c: true, d: [1, 2, 3], e: { x: 10, y: 20 }, }) }) it('Should not validate with incorrect property values', () => { const T = Type.Object({ a: Type.Number(), b: Type.String(), c: Type.Boolean(), d: Type.Array(Type.Number()), e: Type.Object({ x: Type.Number(), y: Type.Number() }), }) Fail(T, { a: 'not a number', // error b: 'hello', c: true, d: [1, 2, 3], e: { x: 10, y: 20 }, }) }) it('Should allow additionalProperties by default', () => { const T = Type.Object({ a: Type.Number(), b: Type.String(), }) Ok(T, { a: 1, b: 'hello', c: true, }) }) it('Should not allow an empty object if minProperties is set to 1', () => { const T = Type.Object( { a: Type.Optional(Type.Number()), b: Type.Optional(Type.String()), }, { additionalProperties: false, minProperties: 1 }, ) Ok(T, { a: 1 }) Ok(T, { b: 'hello' }) Fail(T, {}) }) it('Should not allow 3 properties if maxProperties is set to 2', () => { const T = Type.Object( { a: Type.Optional(Type.Number()), b: Type.Optional(Type.String()), c: Type.Optional(Type.Boolean()), }, { additionalProperties: false, maxProperties: 2 }, ) Ok(T, { a: 1 }) Ok(T, { a: 1, b: 'hello' }) Fail(T, { a: 1, b: 'hello', c: true, }) }) it('Should not allow additionalProperties if additionalProperties is false', () => { const T = Type.Object( { a: Type.Number(), b: Type.String(), }, { additionalProperties: false }, ) Fail(T, { a: 1, b: 'hello', c: true, }) }) it('Should not allow properties for an empty object when additionalProperties is false', () => { const T = Type.Object({}, { additionalProperties: false }) Ok(T, {}) Fail(T, { a: 10 }) }) it('Should validate with non-syntax property keys', () => { const T = Type.Object({ 'with-hyphen': Type.Literal(1), '0-leading': Type.Literal(2), '$-leading': Type.Literal(3), '!@#$%^&*(': Type.Literal(4), 'node-mirror:release:0': Type.Literal(5), // issue: 353 'node-mirror:release:1': Type.Optional(Type.Literal(6)), // issue: 356 'node-mirror:release:2': Type.Union([Type.Literal(7), Type.Undefined()]), // key known "a'a": Type.Literal(8), '@onlyAtSymbol': Type.Literal(9), }) Ok(T, { 'with-hyphen': 1, '0-leading': 2, '$-leading': 3, '!@#$%^&*(': 4, 'node-mirror:release:0': 5, 'node-mirror:release:1': 6, 'node-mirror:release:2': 7, "a'a": 8, '@onlyAtSymbol': 9, }) }) it('Should validate schema additional properties of string', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) Ok(T, { x: 1, y: 2, z: 'hello', }) Fail(T, { x: 1, y: 2, z: 3, }) }) it('Should validate schema additional properties of array', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Array(Type.Number()), }, ) Ok(T, { x: 1, y: 2, z: [0, 1, 2], }) Fail(T, { x: 1, y: 2, z: 3, }) }) it('Should validate schema additional properties of object', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Object({ z: Type.Number(), }), }, ) Ok(T, { x: 1, y: 2, z: { z: 1 }, }) Fail(T, { x: 1, y: 2, z: 3, }) }) it('Should validate nested schema additional properties of string', () => { const T = Type.Object({ nested: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }) Ok(T, { nested: { x: 1, y: 2, z: 'hello', }, }) Fail(T, { nested: { x: 1, y: 2, z: 3, }, }) }) it('Should validate nested schema additional properties of array', () => { const T = Type.Object({ nested: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Array(Type.Number()), }, ), }) Ok(T, { nested: { x: 1, y: 2, z: [0, 1, 2], }, }) Fail(T, { nested: { x: 1, y: 2, z: 3, }, }) }) it('Should validate nested schema additional properties of object', () => { const T = Type.Object({ nested: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Object({ z: Type.Number(), }), }, ), }) Ok(T, { nested: { x: 1, y: 2, z: { z: 1 }, }, }) Fail(T, { nested: { x: 1, y: 2, z: 3, }, }) }) it('Should check for property key if property type is undefined', () => { const T = Type.Object({ x: Type.Undefined() }) Ok(T, { x: undefined }) Fail(T, {}) }) it('Should check for property key if property type extends undefined', () => { const T = Type.Object({ x: Type.Union([Type.Number(), Type.Undefined()]) }) Ok(T, { x: 1 }) Ok(T, { x: undefined }) Fail(T, {}) }) it('Should not check for property key if property type is undefined and optional', () => { const T = Type.Object({ x: Type.Optional(Type.Undefined()) }) Ok(T, { x: undefined }) Ok(T, {}) }) it('Should not check for property key if property type extends undefined and optional', () => { const T = Type.Object({ x: Type.Optional(Type.Union([Type.Number(), Type.Undefined()])) }) Ok(T, { x: 1 }) Ok(T, { x: undefined }) Ok(T, {}) }) it('Should check undefined for optional property of number', () => { const T = Type.Object({ x: Type.Optional(Type.Number()) }) Ok(T, { x: 1 }) Ok(T, { x: undefined }) // allowed by default Ok(T, {}) }) it('Should check undefined for optional property of undefined', () => { const T = Type.Object({ x: Type.Optional(Type.Undefined()) }) Fail(T, { x: 1 }) Ok(T, { x: undefined }) Ok(T, {}) }) it('Should check for required property of any', () => { const T = Type.Object({ x: Type.Any() }) Fail(T, {}) Ok(T, { x: undefined }) Ok(T, { x: 1 }) Ok(T, { x: true }) }) it('Should check for required property of unknown', () => { const T = Type.Object({ x: Type.Unknown() }) Fail(T, {}) Ok(T, { x: undefined }) Ok(T, { x: 1 }) Ok(T, { x: true }) }) it('Should check for required property of any (when optional)', () => { const T = Type.Object({ x: Type.Optional(Type.Any()) }) Ok(T, {}) Ok(T, { x: undefined }) Ok(T, { x: 1 }) Ok(T, { x: true }) }) it('Should check for required property of unknown (when optional)', () => { const T = Type.Object({ x: Type.Optional(Type.Unknown()) }) Ok(T, {}) Ok(T, { x: undefined }) Ok(T, { x: 1 }) Ok(T, { x: true }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/omit.ts000066400000000000000000000041461505437577000240610ustar00rootroot00000000000000import { Type, Kind } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { deepEqual, strictEqual } from 'assert' describe('compiler/Omit', () => { it('Should omit properties on the source schema', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Omit(A, ['z']) Ok(T, { x: 1, y: 1 }) }) it('Should remove required properties on the target schema', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Omit(A, ['z']) strictEqual(T.required!.includes('z'), false) }) it('Should inherit options from the source object', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Omit(A, ['z']) strictEqual(A.additionalProperties, false) strictEqual(T.additionalProperties, false) }) it('Should omit with keyof object', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const B = Type.Object({ x: Type.Number(), y: Type.Number(), }) const T = Type.Omit(A, Type.KeyOf(B), { additionalProperties: false }) Ok(T, { z: 0 }) Fail(T, { x: 0, y: 0, z: 0 }) }) it('Should support Omit of Literal', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const T = Type.Omit(A, Type.Literal('x'), { additionalProperties: false, }) Ok(T, { y: 1, z: 1 }) Fail(T, { x: 1, y: 1, z: 1 }) }) it('Should support Omit of Never', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Omit(A, Type.Never()) Fail(T, { y: 1, z: 1 }) Ok(T, { x: 1, y: 1, z: 1 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/optional.ts000066400000000000000000000012721505437577000247330ustar00rootroot00000000000000import { strictEqual } from 'assert' import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler/Optional', () => { it('Should validate object with optional', () => { const T = Type.Object( { a: Type.Optional(Type.String()), b: Type.String(), }, { additionalProperties: false }, ) Ok(T, { a: 'hello', b: 'world' }) Ok(T, { b: 'world' }) }) it('Should remove required value from schema', () => { const T = Type.Object( { a: Type.Optional(Type.String()), b: Type.String(), }, { additionalProperties: false }, ) strictEqual(T.required!.includes('a'), false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/partial.ts000066400000000000000000000032111505437577000245350ustar00rootroot00000000000000import { TypeSystem } from '@sinclair/typebox/system' import { Type, OptionalKind, ReadonlyKind } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { strictEqual } from 'assert' describe('compiler/Partial', () => { it('Should convert a required object into a partial', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Partial(A) Ok(T, { x: 1, y: 1, z: 1 }) Ok(T, { x: 1, y: 1 }) Ok(T, { x: 1 }) Ok(T, {}) }) it('Should update modifier types correctly when converting to partial', () => { const A = Type.Object( { x: Type.Readonly(Type.Optional(Type.Number())), y: Type.Readonly(Type.Number()), z: Type.Optional(Type.Number()), w: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Partial(A) strictEqual(T.properties.x[ReadonlyKind], 'Readonly') strictEqual(T.properties.x[OptionalKind], 'Optional') strictEqual(T.properties.y[ReadonlyKind], 'Readonly') strictEqual(T.properties.y[OptionalKind], 'Optional') strictEqual(T.properties.z[OptionalKind], 'Optional') strictEqual(T.properties.w[OptionalKind], 'Optional') }) it('Should inherit options from the source object', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Partial(A) strictEqual(A.additionalProperties, false) strictEqual(T.additionalProperties, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/pick.ts000066400000000000000000000041261505437577000240350ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { strictEqual } from 'assert' describe('compiler/Pick', () => { it('Should pick properties from the source schema', () => { const Vector3 = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Pick(Vector3, ['x', 'y']) Ok(T, { x: 1, y: 1 }) }) it('Should remove required properties on the target schema', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Pick(A, ['x', 'y']) strictEqual(T.required!.includes('z'), false) }) it('Should inherit options from the source object', () => { const A = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Pick(A, ['x', 'y']) strictEqual(A.additionalProperties, false) strictEqual(T.additionalProperties, false) }) it('Should pick with keyof object', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const B = Type.Object({ x: Type.Number(), y: Type.Number(), }) const T = Type.Pick(A, Type.KeyOf(B), { additionalProperties: false }) Ok(T, { x: 0, y: 0 }) Fail(T, { x: 0, y: 0, z: 0 }) }) it('Should support Pick of Literal', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const T = Type.Pick(A, Type.Literal('x'), { additionalProperties: false, }) Ok(T, { x: 1 }) Fail(T, { x: 1, y: 1, z: 1 }) }) it('Should support Pick of Never', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const T = Type.Pick(A, Type.Never(), { additionalProperties: false, }) Fail(T, { x: 1, y: 1, z: 1 }) Ok(T, {}) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/readonly-optional.ts000066400000000000000000000013461505437577000265500ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { strictEqual } from 'assert' describe('compiler/ReadonlyOptional', () => { it('Should validate object with optional', () => { const T = Type.Object( { a: Type.Readonly(Type.Optional(Type.String())), b: Type.String(), }, { additionalProperties: false }, ) Ok(T, { a: 'hello', b: 'world' }) Ok(T, { b: 'world' }) }) it('Should remove required value from schema', () => { const T = Type.Object( { a: Type.Readonly(Type.Optional(Type.String())), b: Type.String(), }, { additionalProperties: false }, ) strictEqual(T.required!.includes('a'), false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/readonly.ts000066400000000000000000000014031505437577000247170ustar00rootroot00000000000000import { deepStrictEqual, strictEqual } from 'assert' import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Readonly', () => { it('Should validate object with readonly', () => { const T = Type.Object( { a: Type.Readonly(Type.String()), b: Type.Readonly(Type.String()), }, { additionalProperties: false }, ) Ok(T, { a: 'hello', b: 'world' }) }) it('Should retain required array on object', () => { const T = Type.Object( { a: Type.Readonly(Type.String()), b: Type.Readonly(Type.String()), }, { additionalProperties: false }, ) strictEqual(T.required!.includes('a'), true) strictEqual(T.required!.includes('b'), true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/record.ts000066400000000000000000000253031505437577000243650ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Record', () => { // ------------------------------------------------------------- // Issues // ------------------------------------------------------------- it('Issue: https://github.com/sinclairzx81/typebox/issues/402', () => { const T = Type.Object({ foo: Type.Object({ bar: Type.Record(Type.String(), Type.Number()), }), }) Ok(T, { foo: { bar: { x: 42 } } }) Ok(T, { foo: { bar: {} } }) Fail(T, { foo: { bar: { x: '42' } } }) Fail(T, { foo: { bar: [] } }) Fail(T, { foo: {} }) Fail(T, { foo: [] }) Fail(T, {}) }) // ------------------------------------------------------------- // TypeBox Only: Date and Record // ------------------------------------------------------------- it('Should fail record with Date', () => { const T = Type.Record(Type.String(), Type.String()) Fail(T, new Date()) }) it('Should fail record with Uint8Array', () => { const T = Type.Record(Type.String(), Type.String()) Fail(T, new Uint8Array()) }) // ------------------------------------------------------------- // Standard Assertions // ------------------------------------------------------------- it('Should validate when all property values are numbers', () => { const T = Type.Record(Type.String(), Type.Number()) Ok(T, { a: 1, b: 2, c: 3 }) }) it('Should validate when all property keys are strings', () => { const T = Type.Record(Type.String(), Type.Number()) Ok(T, { a: 1, b: 2, c: 3, '0': 4 }) }) it('Should not validate when below minProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { minProperties: 4 }) Ok(T, { a: 1, b: 2, c: 3, d: 4 }) Fail(T, { a: 1, b: 2, c: 3 }) }) it('Should not validate when above maxProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { maxProperties: 4 }) Ok(T, { a: 1, b: 2, c: 3, d: 4 }) Fail(T, { a: 1, b: 2, c: 3, d: 4, e: 5 }) }) it('Should not validate with illogical minProperties | maxProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { minProperties: 5, maxProperties: 4 }) Fail(T, { a: 1, b: 2, c: 3 }) Fail(T, { a: 1, b: 2, c: 3, d: 4 }) Fail(T, { a: 1, b: 2, c: 3, d: 4, e: 5 }) }) it('Should validate when specifying string union literals when additionalProperties is true', () => { const K = Type.Union([Type.Literal('a'), Type.Literal('b'), Type.Literal('c')]) const T = Type.Record(K, Type.Number()) Ok(T, { a: 1, b: 2, c: 3, d: 'hello' }) }) it('Should not validate when specifying string union literals when additionalProperties is false', () => { const K = Type.Union([Type.Literal('a'), Type.Literal('b'), Type.Literal('c')]) const T = Type.Record(K, Type.Number(), { additionalProperties: false }) Fail(T, { a: 1, b: 2, c: 3, d: 'hello' }) }) it('Should validate for keyof records', () => { const T = Type.Object({ a: Type.String(), b: Type.Number(), c: Type.String(), }) const R = Type.Record(Type.KeyOf(T), Type.Number()) Ok(R, { a: 1, b: 2, c: 3 }) }) it('Should not validate for unknown key via keyof', () => { const T = Type.Object({ a: Type.String(), b: Type.Number(), c: Type.String(), }) const R = Type.Record(Type.KeyOf(T), Type.Number(), { additionalProperties: false }) Fail(R, { a: 1, b: 2, c: 3, d: 4 }) }) it('Should validate when specifying regular expressions', () => { const K = Type.RegExp(/^op_.*$/) const T = Type.Record(K, Type.Number()) Ok(T, { op_a: 1, op_b: 2, op_c: 3, }) }) it('Should not validate when specifying regular expressions and passing invalid property', () => { const K = Type.RegExp(/^op_.*$/) const T = Type.Record(K, Type.Number(), { additionalProperties: false }) Fail(T, { op_a: 1, op_b: 2, aop_c: 3, }) }) it('Should validate with quoted string pattern', () => { const K = Type.String({ pattern: "'(a|b|c)" }) const T = Type.Record(K, Type.Number()) Ok(T, { "'a": 1, "'b": 2, "'c": 3, }) }) it('Should validate with forward-slash pattern', () => { const K = Type.String({ pattern: '/(a|b|c)' }) const T = Type.Record(K, Type.Number()) Ok(T, { '/a': 1, '/b': 2, '/c': 3, }) }) // ------------------------------------------------------------ // Integer Keys // ------------------------------------------------------------ it('Should validate when all property keys are integers', () => { const T = Type.Record(Type.Integer(), Type.Number()) Ok(T, { '0': 1, '1': 2, '2': 3, '3': 4 }) }) it('Should validate when all property keys are integers, but one property is a string with varying type', () => { const T = Type.Record(Type.Integer(), Type.Number(), { additionalProperties: false }) Fail(T, { '0': 1, '1': 2, '2': 3, '3': 4, a: 'hello' }) }) it('Should not validate if passing a leading zeros for integers keys', () => { const T = Type.Record(Type.Integer(), Type.Number(), { additionalProperties: false }) Fail(T, { '00': 1, '01': 2, '02': 3, '03': 4, }) }) it('Should not validate if passing a signed integers keys', () => { const T = Type.Record(Type.Integer(), Type.Number(), { additionalProperties: false }) Fail(T, { '-0': 1, '-1': 2, '-2': 3, '-3': 4, }) }) // ------------------------------------------------------------ // Number Keys // ------------------------------------------------------------ it('Should validate when all property keys are numbers', () => { const T = Type.Record(Type.Number(), Type.Number()) Ok(T, { '0': 1, '1': 2, '2': 3, '3': 4 }) }) it('Should validate when all property keys are numbers, but one property is a string with varying type', () => { const T = Type.Record(Type.Number(), Type.Number(), { additionalProperties: false }) Fail(T, { '0': 1, '1': 2, '2': 3, '3': 4, a: 'hello' }) }) it('Should not validate if passing a leading zeros for numeric keys', () => { const T = Type.Record(Type.Number(), Type.Number(), { additionalProperties: false }) Fail(T, { '00': 1, '01': 2, '02': 3, '03': 4, }) }) it('Should not validate if passing a signed numeric keys', () => { const T = Type.Record(Type.Number(), Type.Number(), { additionalProperties: false }) Fail(T, { '-0': 1, '-1': 2, '-2': 3, '-3': 4, }) }) it('Should not validate when all property keys are numbers, but one property is a string with varying type', () => { const T = Type.Record(Type.Number(), Type.Number(), { additionalProperties: false }) Fail(T, { '0': 1, '1': 2, '2': 3, '3': 4, a: 'hello' }) }) // ------------------------------------------------------------ // AdditionalProperties // ------------------------------------------------------------ it('AdditionalProperties 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: true }) Ok(T, { 1: '', 2: '', x: 1, y: 2, z: 3 }) }) it('AdditionalProperties 2', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false }) Ok(T, { 1: '', 2: '', 3: '' }) }) it('AdditionalProperties 3', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false }) Fail(T, { 1: '', 2: '', x: '' }) }) it('AdditionalProperties 4', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean() }) Fail(T, { 1: '', 2: '', x: '' }) }) it('AdditionalProperties 5', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean() }) Ok(T, { 1: '', 2: '', x: true }) }) // ---------------------------------------------------------------- // TemplateLiteral // ---------------------------------------------------------------- it('TemplateLiteral 1', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number(), { additionalProperties: false }) Ok(R, { key0: 1, key1: 1, key2: 1, }) }) it('TemplateLiteral 2', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) Ok(R, { keyA: 0 }) }) it('TemplateLiteral 3', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number(), { additionalProperties: false }) Fail(R, { keyA: 0 }) }) it('TemplateLiteral 4', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const I = Type.Intersect([R, T], { unevaluatedProperties: false }) Ok(I, { x: 1, y: 2, key0: 1, key1: 1, key2: 1, }) }) it('TemplateLiteral 5', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const I = Type.Intersect([R, T]) Ok(I, { x: 1, y: 2, z: 3, key0: 1, key1: 1, key2: 1, }) }) it('TemplateLiteral 6', () => { const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const I = Type.Intersect([R, T], { unevaluatedProperties: false }) Fail(I, { x: 1, y: 2, z: 3, key0: 1, key1: 1, key2: 1, }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/916 // ---------------------------------------------------------------- it('Should validate for string keys', () => { const T = Type.Record(Type.String(), Type.Null(), { additionalProperties: false, }) Ok(T, { a: null, b: null, 0: null, 1: null, }) }) it('Should validate for number keys', () => { const T = Type.Record(Type.Number(), Type.Null(), { additionalProperties: false, }) Fail(T, { a: null, b: null, 0: null, 1: null, }) Ok(T, { 0: null, 1: null, }) }) it('Should validate for any keys', () => { const T = Type.Record(Type.Any(), Type.Null(), { additionalProperties: false, }) Ok(T, { a: null, b: null, 0: null, 1: null, }) }) it('Should validate for never keys', () => { const T = Type.Record(Type.Never(), Type.Null(), { additionalProperties: false, }) Ok(T, {}) Fail(T, { a: null, b: null, 0: null, 1: null, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/recursive.ts000066400000000000000000000034611505437577000251170ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' import { Ok, Fail } from './validate' describe('compiler/Recursive', () => { it('Should generate default ordinal $id if not specified', () => { const Node = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) Assert.IsEqual(Node.$id === undefined, false) }) it('Should override default ordinal $id if specified', () => { const Node = Type.Recursive( (Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), { $id: 'Node' }, ) Assert.IsEqual(Node.$id === 'Node', true) }) it('Should validate recursive node type', () => { const Node = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) Ok(Node, { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, ], }) }) it('Should validate wrapped recursive node type', () => { const Node = Type.Tuple([ Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ), ]) Ok(Node, [ { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, ], }, ]) }) it('Should not validate wrapped recursive node type with invalid id', () => { const Node = Type.Tuple([ Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ), ]) Fail(Node, [ { id: 'A', nodes: [ { id: 1, nodes: [] }, { id: 'C', nodes: [] }, ], }, ]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/ref.ts000066400000000000000000000042501505437577000236610ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { Assert } from '../assert/index' describe('compiler/Ref', () => { // ---------------------------------------------------------------- // Deprecated // ---------------------------------------------------------------- it('Should validate for Ref(Schema)', () => { const T = Type.Number({ $id: 'T' }) const R = Type.Ref(T) Ok(R, 1234, [T]) Fail(R, 'hello', [T]) }) // ---------------------------------------------------------------- // Standard // ---------------------------------------------------------------- it('Should should validate when referencing a type', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { $id: Assert.NextId() }, ) const R = Type.Ref(T.$id!) Ok( R, { x: 1, y: 2, z: 3, }, [T], ) }) it('Should not validate when passing invalid data', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { $id: Assert.NextId() }, ) const R = Type.Ref(T.$id!) Fail( R, { x: 1, y: 2, }, [T], ) }) it('Should de-reference object property schema', () => { const T = Type.Object( { name: Type.String(), }, { $id: 'R' }, ) const R = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), r: Type.Optional(Type.Ref(T.$id!)), }, { $id: 'T' }, ) Ok(R, { x: 1, y: 2, z: 3 }, [T]) Ok(R, { x: 1, y: 2, z: 3, r: { name: 'hello' } }, [T]) Fail(R, { x: 1, y: 2, z: 3, r: { name: 1 } }, [T]) Fail(R, { x: 1, y: 2, z: 3, r: {} }, [T]) }) it('Should reference recursive schema', () => { const T = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) const R = Type.Ref(T.$id!) Ok(R, { id: '', nodes: [{ id: '', nodes: [] }] }, [T]) Fail(R, { id: '', nodes: [{ id: 1, nodes: [] }] }, [T]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/regexp.ts000066400000000000000000000014061505437577000243770ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/RegExp', () => { it('Should validate regular expression 1', () => { const T = Type.RegExp(/foo/i) Ok(T, 'foo') Ok(T, 'Foo') Ok(T, 'fOO') Fail(T, 'bar') }) it('Should validate regular expression 2', () => { const T = Type.RegExp(/|\p{Extended_Pictographic}/gu) Ok(T, '♥️♦️♠️♣️') }) it('Should validate with minLength constraint', () => { const T = Type.RegExp(/(.*)/, { minLength: 3, }) Ok(T, 'xxx') Fail(T, 'xx') }) it('Should validate with maxLength constraint', () => { const T = Type.RegExp(/(.*)/, { maxLength: 3, }) Ok(T, 'xxx') Fail(T, 'xxxx') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/required.ts000066400000000000000000000035201505437577000247240ustar00rootroot00000000000000import { Type, ReadonlyKind, OptionalKind } from '@sinclair/typebox' import { Ok, Fail } from './validate' import { strictEqual } from 'assert' describe('compiler/Required', () => { it('Should convert a partial object into a required object', () => { const A = Type.Object( { x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), z: Type.Optional(Type.Number()), }, { additionalProperties: false }, ) const T = Type.Required(A) Ok(T, { x: 1, y: 1, z: 1 }) Fail(T, { x: 1, y: 1 }) Fail(T, { x: 1 }) Fail(T, {}) }) it('Should update modifier types correctly when converting to required', () => { const A = Type.Object({ x: Type.Readonly(Type.Optional(Type.Number())), y: Type.Readonly(Type.Number()), z: Type.Optional(Type.Number()), w: Type.Number(), }) const T = Type.Required(A) strictEqual(T.properties.x[ReadonlyKind], 'Readonly') strictEqual(T.properties.y[ReadonlyKind], 'Readonly') strictEqual(T.properties.z[OptionalKind], undefined) strictEqual(T.properties.w[OptionalKind], undefined) }) it('Should inherit options from the source object', () => { const A = Type.Object( { x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), z: Type.Optional(Type.Number()), }, { additionalPropeties: false }, ) const T = Type.Required(A) strictEqual(A.additionalPropeties, false) strictEqual(T.additionalPropeties, false) }) // it('Should construct new object when targetting reference', () => { // const T = Type.Object({ a: Type.String(), b: Type.String() }, { $id: 'T' }) // const R = Type.Ref(T) // const P = Type.Required(R) // strictEqual(P.properties.a.type, 'string') // strictEqual(P.properties.b.type, 'string') // }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/string-pattern.ts000066400000000000000000000033721505437577000260720ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/StringPattern', () => { //----------------------------------------------------- // Regular Expression //----------------------------------------------------- it('Should validate regular expression 1', () => { const T = Type.String({ pattern: /[012345]/.source }) Ok(T, '0') Ok(T, '1') Ok(T, '2') Ok(T, '3') Ok(T, '4') Ok(T, '5') }) it('Should validate regular expression 2', () => { const T = Type.String({ pattern: /true|false/.source }) Ok(T, 'true') Ok(T, 'true') Ok(T, 'true') Ok(T, 'false') Ok(T, 'false') Ok(T, 'false') Fail(T, '6') }) it('Should validate regular expression 3', () => { const T = Type.String({ pattern: /true|false/.source }) Fail(T, 'unknown') }) it('Should validate regular expression 4', () => { const T = Type.String({ pattern: /[\d]{5}/.source }) Ok(T, '12345') }) //----------------------------------------------------- // Regular Pattern //----------------------------------------------------- it('Should validate pattern 1', () => { const T = Type.String({ pattern: '[012345]' }) Ok(T, '0') Ok(T, '1') Ok(T, '2') Ok(T, '3') Ok(T, '4') Ok(T, '5') }) it('Should validate pattern 2', () => { const T = Type.String({ pattern: 'true|false' }) Ok(T, 'true') Ok(T, 'true') Ok(T, 'true') Ok(T, 'false') Ok(T, 'false') Ok(T, 'false') Fail(T, '6') }) it('Should validate pattern 3', () => { const T = Type.String({ pattern: 'true|false' }) Fail(T, 'unknown') }) it('Should validate pattern 4', () => { const T = Type.String({ pattern: '[\\d]{5}' }) Ok(T, '12345') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/string.ts000066400000000000000000000036371505437577000244230ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/String', () => { it('Should not validate number', () => { const T = Type.String() Fail(T, 1) }) it('Should validate string', () => { const T = Type.String() Ok(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.String() Fail(T, true) }) it('Should not validate array', () => { const T = Type.String() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.String() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.String() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.String() Fail(T, undefined) }) it('Should not validate bigint', () => { const T = Type.String() Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.String() Fail(T, Symbol(1)) }) it('Should validate string format as email', () => { const T = Type.String({ format: 'email' }) Ok(T, 'name@domain.com') }) it('Should validate string format as uuid', () => { const T = Type.String({ format: 'uuid' }) Ok(T, '4a7a17c9-2492-4a53-8e13-06ea2d3f3bbf') }) it('Should validate string format as iso8601 date', () => { const T = Type.String({ format: 'date-time' }) Ok(T, '2021-06-11T20:30:00-04:00') }) it('Should validate minLength', () => { const T = Type.String({ minLength: 4 }) Ok(T, '....') Fail(T, '...') }) it('Should validate maxLength', () => { const T = Type.String({ maxLength: 4 }) Ok(T, '....') Fail(T, '.....') }) it('Should pass numeric 5 digit test', () => { const T = Type.String({ pattern: '[\\d]{5}' }) Ok(T, '12345') }) it('Should should escape characters in the pattern', () => { const T = Type.String({ pattern: '/a/' }) Ok(T, '/a/') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/symbol.ts000066400000000000000000000017671505437577000244240ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Symbol', () => { it('Should not validate a boolean', () => { const T = Type.Symbol() Fail(T, true) Fail(T, false) }) it('Should not validate a number', () => { const T = Type.Symbol() Fail(T, 1) }) it('Should not validate a string', () => { const T = Type.Symbol() Fail(T, 'true') }) it('Should not validate an array', () => { const T = Type.Symbol() Fail(T, [true]) }) it('Should not validate an object', () => { const T = Type.Symbol() Fail(T, {}) }) it('Should not validate an null', () => { const T = Type.Symbol() Fail(T, null) }) it('Should not validate an undefined', () => { const T = Type.Symbol() Fail(T, undefined) }) it('Should not validate bigint', () => { const T = Type.Symbol() Fail(T, BigInt(1)) }) it('Should not validate symbol', () => { const T = Type.Symbol() Ok(T, Symbol(1)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/template-literal.ts000066400000000000000000000110231505437577000263460ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/TemplateLiteral', () => { // -------------------------------------------------------- // Finite // -------------------------------------------------------- it('Should validate finite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([]) Ok(T, '') Fail(T, 'X') }) it('Should validate finite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([Type.Boolean()]) Ok(T, 'true') Ok(T, 'false') Fail(T, 'X') }) it('Should validate finite pattern 2', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A') ]) Ok(T, 'A') Fail(T, 'X') }) it('Should validate finite pattern 3', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Literal('B') ]) Ok(T, 'AB') Fail(T, 'X') }) it('Should validate finite pattern 4', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), Type.Literal('C') ]), ]) Ok(T, 'AB') Ok(T, 'AC') Fail(T, 'X') }) it('Should validate finite pattern 5', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), Type.Literal('C') ]), Type.Literal('D'), ]) Ok(T, 'ABD') Ok(T, 'ACD') Fail(T, 'X') }) it('Should validate finite pattern 6', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Union([ Type.Literal('0'), Type.Literal('1') ]), Type.Union([ Type.Literal('0'), Type.Literal('1') ]), ]) Ok(T, '00') Ok(T, '01') Ok(T, '10') Ok(T, '11') Fail(T, 'X') }) // -------------------------------------------------------- // Infinite // -------------------------------------------------------- it('Should validate infinite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Number() ]) Ok(T, '1') Ok(T, '22') Ok(T, '333') Ok(T, '4444') Fail(T, 'X') }) it('Should validate infinite pattern 2', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Integer() ]) Ok(T, '1') Ok(T, '22') Ok(T, '333') Ok(T, '4444') Fail(T, 'X') }) it('Should validate infinite pattern 3', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.BigInt() ]) Ok(T, '1') Ok(T, '22') Ok(T, '333') Ok(T, '4444') Fail(T, 'X') }) it('Should validate infinite pattern 4', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.String() ]) Ok(T, '1') Ok(T, '22') Ok(T, '333') Ok(T, '4444') Ok(T, 'a') Ok(T, 'bb') Ok(T, 'ccc') Ok(T, 'dddd') }) it('Should validate infinite pattern 5', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Number() ]) Ok(T, 'A1') Ok(T, 'A22') Ok(T, 'A333') Ok(T, 'A4444') Fail(T, 'X') }) it('Should validate infinite pattern 6', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Integer() ]) Ok(T, 'A1') Ok(T, 'A22') Ok(T, 'A333') Ok(T, 'A4444') Fail(T, 'X') }) it('Should validate infinite pattern 7', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.BigInt() ]) Ok(T, 'A1') Ok(T, 'A22') Ok(T, 'A333') Ok(T, 'A4444') Fail(T, 'X') }) it('Should validate infinite pattern 8', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.String() ]) Ok(T, 'A1') Ok(T, 'A22') Ok(T, 'A333') Ok(T, 'A4444') Ok(T, 'Aa') Ok(T, 'Abb') Ok(T, 'Accc') Ok(T, 'Adddd') Fail(T, 'X') }) it('Should validate enum (implicit)', () => { enum E { A, B, C, } const T = Type.TemplateLiteral([Type.Literal('hello'), Type.Enum(E)]) Ok(T, 'hello0') Ok(T, 'hello1') Ok(T, 'hello2') Fail(T, 'hello3') }) it('Should validate enum (explicit)', () => { enum E { A, B = 'B', C = 'C', } const T = Type.TemplateLiteral([Type.Literal('hello'), Type.Enum(E)]) Ok(T, 'hello0') Ok(T, 'helloB') Ok(T, 'helloC') Fail(T, 'helloD') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/tuple.ts000066400000000000000000000034501505437577000242370ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Tuple', () => { it('Should validate tuple of [string, number]', () => { const A = Type.String() const B = Type.Number() const T = Type.Tuple([A, B]) Ok(T, ['hello', 42]) }) it('Should not validate tuple of [string, number] when reversed', () => { const A = Type.String() const B = Type.Number() const T = Type.Tuple([A, B]) Fail(T, [42, 'hello']) }) it('Should validate with empty tuple', () => { const T = Type.Tuple([]) Ok(T, []) }) it('Should not validate with empty tuple with more items', () => { const T = Type.Tuple([]) Fail(T, [1]) }) it('Should not validate with empty tuple with less items', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) Fail(T, [1]) }) it('Should validate tuple of objects', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Tuple([A, B]) Ok(T, [{ a: 'hello' }, { b: 42 }]) }) it('Should not validate tuple of objects when reversed', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Tuple([A, B]) Fail(T, [{ b: 42 }, { a: 'hello' }]) }) it('Should not validate tuple when array is less than tuple length', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Tuple([A, B]) Fail(T, [{ a: 'hello' }]) }) it('Should not validate tuple when array is greater than tuple length', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Tuple([A, B]) Fail(T, [{ a: 'hello' }, { b: 42 }, { b: 42 }]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/uint8array.ts000066400000000000000000000023631505437577000252160ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Uint8Array', () => { it('Should not validate number', () => { const T = Type.Uint8Array() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.Uint8Array() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Uint8Array() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Uint8Array() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Uint8Array() Fail(T, { a: 1, b: 2 }) }) it('Should not validate null', () => { const T = Type.Uint8Array() Fail(T, null) }) it('Should not validate undefined', () => { const T = Type.Uint8Array() Fail(T, undefined) }) it('Should validate Uint8Array', () => { const T = Type.Uint8Array() Ok(T, new Uint8Array(100)) }) it('Should validate minByteLength', () => { const T = Type.Uint8Array({ minByteLength: 4 }) Ok(T, new Uint8Array(4)) Fail(T, new Uint8Array(3)) }) it('Should validate maxByteLength', () => { const T = Type.Uint8Array({ maxByteLength: 4 }) Ok(T, new Uint8Array(4)) Fail(T, new Uint8Array(5)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/unicode.ts000066400000000000000000000032001505437577000245250ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler/Unicode', () => { // --------------------------------------------------------- // Identifiers // --------------------------------------------------------- it('Should support unicode identifiers', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { $id: '식별자', }, ) Ok(T, { x: 1, y: 2, }) }) it('Should support unicode identifier references', () => { const R = Type.Object( { x: Type.Number(), y: Type.Number(), }, { $id: '식별자', }, ) const T = Type.Object({ vector: Type.Ref(R.$id!), }) Ok( T, { vector: { x: 1, y: 2, }, }, [R], ) }) it('Should support unicode identifier recursion', () => { const Node = Type.Recursive( (Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), { $id: '식별자', }, ) Ok(Node, { id: 'A', nodes: [ { id: 'B', nodes: [ { id: 'C', nodes: [], }, ], }, ], }) }) // --------------------------------------------------------- // Properties // --------------------------------------------------------- it('Should support unicode properties', () => { const T = Type.Object({ 이름: Type.String(), }) Ok(T, { 이름: 'dave', }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/union.ts000066400000000000000000000043711505437577000242410ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Union', () => { it('Should validate union of string, number and boolean', () => { const A = Type.String() const B = Type.Number() const C = Type.Boolean() const T = Type.Union([A, B, C]) Ok(T, 'hello') Ok(T, true) Ok(T, 42) }) it('Should validate union of objects', () => { const A = Type.Object({ a: Type.String() }, { additionalProperties: false }) const B = Type.Object({ b: Type.String() }, { additionalProperties: false }) const T = Type.Union([A, B]) Ok(T, { a: 'hello' }) Ok(T, { b: 'world' }) }) it('Should fail to validate for descriminated union types', () => { const A = Type.Object({ kind: Type.Literal('A'), value: Type.String() }) const B = Type.Object({ kind: Type.Literal('B'), value: Type.Number() }) const T = Type.Union([A, B]) Fail(T, { kind: 'A', value: 42 }) // expect { kind: 'A', value: string } Fail(T, { kind: 'B', value: 'hello' }) // expect { kind: 'B', value: number } }) it('Should validate union of objects where properties overlap', () => { const A = Type.Object({ a: Type.String() }, { additionalProperties: false }) const B = Type.Object({ a: Type.String(), b: Type.String() }, { additionalProperties: false }) const T = Type.Union([A, B]) Ok(T, { a: 'hello' }) // A Ok(T, { a: 'hello', b: 'world' }) // B }) it('Should validate union of overlapping property of varying type', () => { const A = Type.Object({ a: Type.String(), b: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ a: Type.String(), b: Type.String() }, { additionalProperties: false }) const T = Type.Union([A, B]) Ok(T, { a: 'hello', b: 42 }) // A Ok(T, { a: 'hello', b: 'world' }) // B }) it('Should validate union of literal strings', () => { const A = Type.Literal('hello') const B = Type.Literal('world') const T = Type.Union([A, B]) Ok(T, 'hello') // A Ok(T, 'world') // B }) it('Should not validate union of literal strings for unknown string', () => { const A = Type.Literal('hello') const B = Type.Literal('world') const T = Type.Union([A, B]) Fail(T, 'foo') // A Fail(T, 'bar') // B }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/unknown.ts000066400000000000000000000013321505437577000246020ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok } from './validate' describe('compiler/Unknown', () => { it('Should validate number', () => { const T = Type.Any() Ok(T, 1) }) it('Should validate string', () => { const T = Type.Any() Ok(T, 'hello') }) it('Should validate boolean', () => { const T = Type.Any() Ok(T, true) }) it('Should validate array', () => { const T = Type.Any() Ok(T, [1, 2, 3]) }) it('Should validate object', () => { const T = Type.Any() Ok(T, { a: 1, b: 2 }) }) it('Should validate null', () => { const T = Type.Any() Ok(T, null) }) it('Should validate undefined', () => { const T = Type.Any() Ok(T, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/compiler/validate.ts000066400000000000000000000115341505437577000247010ustar00rootroot00000000000000import { TypeCompiler } from '@sinclair/typebox/compiler' import { Value } from '@sinclair/typebox/value' import { TSchema, FormatRegistry } from '@sinclair/typebox' // ------------------------------------------------------------------------- // Test Formats: https://github.com/ajv-validator/ajv-formats/blob/master/src/formats.ts // // - date-time // - email // - uuid // // ------------------------------------------------------------------------- const EMAIL = /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i const UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i const DATE_TIME_SEPARATOR = /t|\s/i const TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i const DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ const DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] function isLeapYear(year: number): boolean { return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) } function isDate(str: string): boolean { const matches: string[] | null = DATE.exec(str) if (!matches) return false const year: number = +matches[1] const month: number = +matches[2] const day: number = +matches[3] return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && isLeapYear(year) ? 29 : DAYS[month]) } function isTime(str: string, strictTimeZone?: boolean): boolean { const matches: string[] | null = TIME.exec(str) if (!matches) return false const hr: number = +matches[1] const min: number = +matches[2] const sec: number = +matches[3] const tz: string | undefined = matches[4] const tzSign: number = matches[5] === '-' ? -1 : 1 const tzH: number = +(matches[6] || 0) const tzM: number = +(matches[7] || 0) if (tzH > 23 || tzM > 59 || (strictTimeZone && !tz)) return false if (hr <= 23 && min <= 59 && sec < 60) return true // leap second const utcMin = min - tzM * tzSign const utcHr = hr - tzH * tzSign - (utcMin < 0 ? 1 : 0) return (utcHr === 23 || utcHr === -1) && (utcMin === 59 || utcMin === -1) && sec < 61 } function isDateTime(str: string, strictTimeZone?: boolean): boolean { const dateTime: string[] = str.split(DATE_TIME_SEPARATOR) return dateTime.length === 2 && isDate(dateTime[0]) && isTime(dateTime[1], strictTimeZone) } // ------------------------------------------------------------------------- // Use Formats // ------------------------------------------------------------------------- FormatRegistry.Set('email', (value) => EMAIL.test(value)) FormatRegistry.Set('uuid', (value) => UUID.test(value)) FormatRegistry.Set('date-time', (value) => isDateTime(value, true)) export function Ok(schema: T, data: unknown, references: any[] = []) { const C = TypeCompiler.Compile(schema, references) const result = C.Check(data) if (result !== Value.Check(schema, references, data)) { throw Error('Compiler and Value Check disparity') } if (result === false) { const errors = [...Value.Errors(schema, references, data)] if (errors.length === 0) throw Error('expected at least 1 error') } if (result === true) { const errors = [...Value.Errors(schema, references, data)] if (errors.length > 0) throw Error('expected no errors') } if (!result) { console.log('---------------------------') console.log('type') console.log('---------------------------') console.log(JSON.stringify(schema, null, 2)) console.log('---------------------------') console.log('data') console.log('---------------------------') console.log(JSON.stringify(data, null, 2)) console.log('---------------------------') console.log('errors') console.log('---------------------------') console.log(result) throw Error('expected ok') } } export function Fail(schema: T, data: unknown, references: any[] = []) { const C = TypeCompiler.Compile(schema, references) const result = C.Check(data) if (result !== Value.Check(schema, references, data)) { throw Error('Compiler and Value Check disparity') } if (result === false) { const errors = [...Value.Errors(schema, references, data)] if (errors.length === 0) throw Error('expected at least 1 error') } if (result === true) { const errors = [...Value.Errors(schema, references, data)] if (errors.length > 0) throw Error('expected no errors') } if (result) { console.log('---------------------------') console.log('type') console.log('---------------------------') console.log(JSON.stringify(schema, null, 2)) console.log('---------------------------') console.log('data') console.log('---------------------------') console.log(JSON.stringify(data, null, 2)) console.log('---------------------------') console.log('errors') console.log('---------------------------') console.log('none') throw Error('expected ok') } } sinclairzx81-typebox-e0ec98c/test/runtime/compiler/void.ts000066400000000000000000000015341505437577000240500ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Ok, Fail } from './validate' describe('compiler/Void', () => { it('Should not validate number', () => { const T = Type.Void() Fail(T, 1) }) it('Should not validate string', () => { const T = Type.Void() Fail(T, 'hello') }) it('Should not validate boolean', () => { const T = Type.Void() Fail(T, true) }) it('Should not validate array', () => { const T = Type.Void() Fail(T, [1, 2, 3]) }) it('Should not validate object', () => { const T = Type.Void() Fail(T, { a: 1, b: 2 }) }) it('Should validate null', () => { const T = Type.Void() Fail(T, null) }) it('Should validate undefined', () => { const T = Type.Void() Ok(T, undefined) }) it('Should validate void 0', () => { const T = Type.Void() Ok(T, void 0) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/000077500000000000000000000000001505437577000222365ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/errors/index.ts000066400000000000000000000000611505437577000237120ustar00rootroot00000000000000import './iterator/index' import './types/index' sinclairzx81-typebox-e0ec98c/test/runtime/errors/iterator/000077500000000000000000000000001505437577000240675ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/errors/iterator/index.ts000066400000000000000000000000241505437577000255420ustar00rootroot00000000000000import './iterator' sinclairzx81-typebox-e0ec98c/test/runtime/errors/iterator/iterator.ts000066400000000000000000000021511505437577000262670ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Errors } from '@sinclair/typebox/errors' import { Assert } from '../../assert' describe('errors/ValueErrorIterator', () => { it('Should return undefined for non error', () => { const R = Errors(Type.Number(), [], 1).First() Assert.IsEqual(R, undefined) }) it('Should return a value error when error', () => { const { type, path, message } = Errors(Type.Number(), [], '').First()! Assert.IsTypeOf(type, 'number') Assert.IsTypeOf(path, 'string') Assert.IsTypeOf(message, 'string') }) it('Should yield empty array for non error', () => { const R = [...Errors(Type.Number(), [], 1)] Assert.IsEqual(R.length, 0) }) it('Should yield array with 1 error when error', () => { const R = [...Errors(Type.Number(), [], 'foo')] Assert.IsEqual(R.length, 1) }) it('Should yield array with N errors when error', () => { // prettier-ignore const R = [...Errors(Type.Object({ x: Type.Number(), y: Type.Number() }), [], {})] // require object to invoke internal check Assert.IsEqual(R.length > 1, true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/000077500000000000000000000000001505437577000234025ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/array-contains.ts000066400000000000000000000010471505437577000267060ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ArrayMaxContainsItems', () => { const T = Type.Array(Type.Any(), { contains: Type.Literal(1) }) it('Should pass 0', () => { const R = Resolve(T, [1]) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, [2]) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ArrayContains) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/array-max-contains.ts000066400000000000000000000022161505437577000274700ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ArrayMaxContainsItems', () => { const T = Type.Array(Type.Any(), { contains: Type.Literal(1), maxContains: 4 }) it('Should pass 0', () => { const R = Resolve(T, [1, 1, 1, 1]) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, null) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Array) }) it('Should pass 2', () => { const R = Resolve(T, [1, 1, 1, 1, 1]) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ArrayMaxContains) }) it('Should pass 3', () => { const R = Resolve(T, []) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ArrayContains) }) it('Should pass 4', () => { const R = Resolve(T, [1, 2, 3, 4]) Assert.IsEqual(R.length, 0) }) it('Should pass 5', () => { const R = Resolve(T, [2, 3, 4]) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ArrayContains) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/array-max-items.ts000066400000000000000000000012741505437577000267760ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ArrayMaxItems', () => { const T = Type.Array(Type.Any(), { maxItems: 4 }) it('Should pass 0', () => { const R = Resolve(T, [1, 2, 3, 4]) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, null) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Array) }) it('Should pass 2', () => { const R = Resolve(T, [1, 2, 3, 4, 5]) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ArrayMaxItems) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/array-min-contains.ts000066400000000000000000000016641505437577000274740ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ArrayMinContainsItems', () => { const T = Type.Array(Type.Any(), { contains: Type.Literal(1), minContains: 4 }) it('Should pass 0', () => { const R = Resolve(T, [1, 1, 1, 1]) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, null) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Array) }) it('Should pass 2', () => { const R = Resolve(T, [1]) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ArrayMinContains) }) it('Should pass 3', () => { const R = Resolve(T, []) Assert.IsEqual(R.length, 2) Assert.IsEqual(R[0].type, ValueErrorType.ArrayContains) Assert.IsEqual(R[1].type, ValueErrorType.ArrayMinContains) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/array-min-items.ts000066400000000000000000000012571505437577000267750ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ArrayMinItems', () => { const T = Type.Array(Type.Any(), { minItems: 4 }) it('Should pass 0', () => { const R = Resolve(T, [1, 2, 3, 4]) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, null) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Array) }) it('Should pass 2', () => { const R = Resolve(T, []) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ArrayMinItems) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/array-unique-items.ts000066400000000000000000000012171505437577000275140ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ArrayUniqueItems', () => { const T = Type.Array(Type.Any(), { uniqueItems: true }) it('Should pass 0', () => { const R = Resolve(T, [1, 2, 3, 4]) Assert.IsEqual(R.length, 0) }) it('Should pass 2', () => { const R = Resolve(T, []) Assert.IsEqual(R.length, 0) }) it('Should pass 3', () => { const R = Resolve(T, [1, 1, 3, 4]) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ArrayUniqueItems) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/array.ts000066400000000000000000000014361505437577000250740ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Array', () => { const T = Type.Array(Type.Any()) it('Should pass 0', () => { const R = Resolve(T, [1, 2, 3]) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Array) }) it('Should pass 2', () => { const R = Resolve(T, {}) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Array) }) it('Should pass 3', () => { const R = Resolve(T, null) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Array) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/async-iterator.ts000066400000000000000000000010411505437577000267120ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/AsyncIterator', () => { const T = Type.AsyncIterator(Type.Any()) it('Should pass 0', () => { const R = Resolve(T, (async function* (): any {})()) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.AsyncIterator) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/bigint-exclusive-maximum.ts000066400000000000000000000010371505437577000307070ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/BigIntExclusiveMaximum', () => { const T = Type.BigInt({ exclusiveMaximum: 4n }) it('Should pass 0', () => { const R = Resolve(T, 0n) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 4n) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.BigIntExclusiveMaximum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/bigint-exclusive-minimum.ts000066400000000000000000000010371505437577000307050ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/BigIntExclusiveMinimum', () => { const T = Type.BigInt({ exclusiveMinimum: 4n }) it('Should pass 0', () => { const R = Resolve(T, 5n) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 4n) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.BigIntExclusiveMinimum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/bigint-maximum.ts000066400000000000000000000010041505437577000266740ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/BigIntMaximum', () => { const T = Type.BigInt({ maximum: 4n }) it('Should pass 0', () => { const R = Resolve(T, 0n) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 5n) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.BigIntMaximum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/bigint-minimum.ts000066400000000000000000000010041505437577000266720ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/BigIntMinimum', () => { const T = Type.BigInt({ minimum: 4n }) it('Should pass 0', () => { const R = Resolve(T, 4n) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 3n) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.BigIntMinimum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/bigint-multiple-of.ts000066400000000000000000000010151505437577000274560ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/BigIntMultipleOf', () => { const T = Type.BigInt({ multipleOf: 2n }) it('Should pass 0', () => { const R = Resolve(T, 0n) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1n) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.BigIntMultipleOf) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/bigint.ts000066400000000000000000000007461505437577000252350ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/BigInt', () => { const T = Type.BigInt() it('Should pass 0', () => { const R = Resolve(T, 0n) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.BigInt) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/boolean.ts000066400000000000000000000007531505437577000253760ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Boolean', () => { const T = Type.Boolean() it('Should pass 0', () => { const R = Resolve(T, true) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Boolean) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/date-exclusive-maximum-timestamp.ts000066400000000000000000000011051505437577000323450ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/DateExclusiveMaximumTimestamp', () => { const T = Type.Date({ exclusiveMaximumTimestamp: 4 }) it('Should pass 0', () => { const R = Resolve(T, new Date(0)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, new Date(4)) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.DateExclusiveMaximumTimestamp) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/date-exclusive-minimum-timestamp.ts000066400000000000000000000011051505437577000323430ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/DateExclusiveMinimumTimestamp', () => { const T = Type.Date({ exclusiveMinimumTimestamp: 4 }) it('Should pass 0', () => { const R = Resolve(T, new Date(5)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, new Date(4)) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.DateExclusiveMinimumTimestamp) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/date-maximum-timestamp.ts000066400000000000000000000010521505437577000303410ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/DateMaximumTimestamp', () => { const T = Type.Date({ maximumTimestamp: 4 }) it('Should pass 0', () => { const R = Resolve(T, new Date(0)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, new Date(5)) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.DateMaximumTimestamp) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/date-minimum-timestamp.ts000066400000000000000000000010521505437577000303370ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/DateMinimumTimestamp', () => { const T = Type.Date({ minimumTimestamp: 4 }) it('Should pass 0', () => { const R = Resolve(T, new Date(4)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, new Date(3)) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.DateMinimumTimestamp) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/date-multiple-of-timestamp.ts000066400000000000000000000010631505437577000311230ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/DateMultipleOfTimestamp', () => { const T = Type.Date({ multipleOfTimestamp: 2 }) it('Should pass 0', () => { const R = Resolve(T, new Date(0)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, new Date(1)) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.DateMultipleOfTimestamp) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/date.ts000066400000000000000000000007501505437577000246710ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Date', () => { const T = Type.Date() it('Should pass 0', () => { const R = Resolve(T, new Date()) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Date) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/function.ts000066400000000000000000000010131505437577000255720ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Function', () => { const T = Type.Function([], Type.Any()) it('Should pass 0', () => { const R = Resolve(T, function (): any {}) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Function) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/index.ts000066400000000000000000000034701505437577000250650ustar00rootroot00000000000000import './array-contains' import './array-max-contains' import './array-min-items' import './array-min-contains' import './array-max-items' import './array-unique-items' import './array' import './async-iterator' import './bigint-exclusive-maximum' import './bigint-exclusive-minimum' import './bigint-maximum' import './bigint-minimum' import './bigint-multiple-of' import './bigint' import './boolean' import './date-exclusive-maximum-timestamp' import './date-exclusive-minimum-timestamp' import './date-maximum-timestamp' import './date-minimum-timestamp' import './date-multiple-of-timestamp' import './date' import './function' import './integer-exclusive-maximum' import './integer-exclusive-minimum' import './integer-maximum' import './integer-minimum' import './integer-multiple-of' import './integer' import './intersect-unevaluated-properties' import './intersect' import './iterator' import './kind' import './literal' import './never' import './not' import './null' import './number-exclusive-maximum' import './number-exclusive-minimum' import './number-maximum' import './number-minimum' import './number' import './number-multiple-of' import './object-additional-properties' import './object-max-properties' import './object-min-properties' import './object-pointer-property' import './object-required-property' import './object' import './promise' import './record-pointer-property' import './regexp-max-length' import './regexp-min-length' import './regexp' import './string-format-unknown' import './string-format' import './string-max-length' import './string-min-length' import './string-pattern' import './string' import './symbol' import './tuple-length' import './tuple' import './uint8array-max-byte-length' import './uint8array-min-byte-length' import './uint8array' import './undefined' import './union' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/integer-exclusive-maximum.ts000066400000000000000000000010371505437577000310700ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/IntegerExclusiveMaximum', () => { const T = Type.Integer({ exclusiveMaximum: 4 }) it('Should pass 0', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 4) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.IntegerExclusiveMaximum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/integer-exclusive-minimum.ts000066400000000000000000000010371505437577000310660ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/IntegerExclusiveMinimum', () => { const T = Type.Integer({ exclusiveMinimum: 4 }) it('Should pass 0', () => { const R = Resolve(T, 5) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 4) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.IntegerExclusiveMinimum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/integer-maximum.ts000066400000000000000000000010041505437577000270550ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/IntegerMaximum', () => { const T = Type.Integer({ maximum: 4 }) it('Should pass 0', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 5) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.IntegerMaximum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/integer-minimum.ts000066400000000000000000000010041505437577000270530ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/IntegerMinimum', () => { const T = Type.Integer({ minimum: 4 }) it('Should pass 0', () => { const R = Resolve(T, 4) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 3) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.IntegerMinimum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/integer-multiple-of.ts000066400000000000000000000010151505437577000276370ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/IntegerMultipleOf', () => { const T = Type.Integer({ multipleOf: 2 }) it('Should pass 0', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.IntegerMultipleOf) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/integer.ts000066400000000000000000000007511505437577000254120ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Integer', () => { const T = Type.Integer() it('Should pass 0', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 0n) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Integer) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/intersect-unevaluated-properties.ts000066400000000000000000000024431505437577000324620ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/IntersectUnevaluatedProperties', () => { const T1 = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], { unevaluatedProperties: false, }) it('Should pass 0', () => { const R = Resolve(T1, { x: 1, y: 2 }) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T1, { x: 1, y: 2, z: 3 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.IntersectUnevaluatedProperties) }) const T2 = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], { unevaluatedProperties: Type.String(), }) it('Should pass 3', () => { const R = Resolve(T2, { x: 1, y: 2, z: '1' }) Assert.IsEqual(R.length, 0) }) it('Should pass 4', () => { const R = Resolve(T2, { x: 1, y: 2, a: 1, b: 2 }) Assert.IsEqual(R.length, 2) Assert.IsEqual(R[0].type, ValueErrorType.String) Assert.IsEqual(R[0].path, '/a') Assert.IsEqual(R[0].value, 1) Assert.IsEqual(R[1].type, ValueErrorType.String) Assert.IsEqual(R[1].path, '/b') Assert.IsEqual(R[1].value, 2) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/intersect.ts000066400000000000000000000045131505437577000257550ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Intersect', () => { it('Should pass 0', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const R = Resolve(T, { x: 1, y: 1 }) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const R = Resolve(T, { x: 1 }) Assert.IsEqual(R.length, 3) Assert.IsEqual(R[0].type, ValueErrorType.ObjectRequiredProperty) Assert.IsEqual(R[1].type, ValueErrorType.Number) Assert.IsEqual(R[2].type, ValueErrorType.Intersect) }) it('Should pass 2', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const R = Resolve(T, { y: 1 }) Assert.IsEqual(R.length, 3) Assert.IsEqual(R[0].type, ValueErrorType.ObjectRequiredProperty) Assert.IsEqual(R[1].type, ValueErrorType.Number) Assert.IsEqual(R[2].type, ValueErrorType.Intersect) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/887 // ---------------------------------------------------------------- it('Should pass 3', () => { const A = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const B = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ z: Type.Number() })]) const T = Type.Intersect([A, B]) const R = Resolve(T, {}) Assert.IsEqual(R.length, 11) Assert.IsEqual(R[0].type, ValueErrorType.ObjectRequiredProperty) Assert.IsEqual(R[1].type, ValueErrorType.Number) Assert.IsEqual(R[2].type, ValueErrorType.ObjectRequiredProperty) Assert.IsEqual(R[3].type, ValueErrorType.Number) Assert.IsEqual(R[4].type, ValueErrorType.Intersect) Assert.IsEqual(R[5].type, ValueErrorType.ObjectRequiredProperty) Assert.IsEqual(R[6].type, ValueErrorType.Number) Assert.IsEqual(R[7].type, ValueErrorType.ObjectRequiredProperty) Assert.IsEqual(R[8].type, ValueErrorType.Number) Assert.IsEqual(R[9].type, ValueErrorType.Intersect) Assert.IsEqual(R[10].type, ValueErrorType.Intersect) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/iterator.ts000066400000000000000000000010141505437577000255770ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Iterator', () => { const T = Type.Iterator(Type.Any()) it('Should pass 0', () => { const R = Resolve(T, (function* (): any {})()) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Iterator) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/kind.ts000066400000000000000000000016101505437577000246750ustar00rootroot00000000000000import { TypeRegistry, Kind, TSchema } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Kind', () => { // ---------------------------------------------------- // Fixture // ---------------------------------------------------- beforeEach(() => TypeRegistry.Set('Foo', (schema, value) => value === 'foo')) afterEach(() => TypeRegistry.Delete('Foo')) // ---------------------------------------------------- // Test // ---------------------------------------------------- const T = { [Kind]: 'Foo' } as TSchema it('Should pass 0', () => { const R = Resolve(T, 'foo') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Kind) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/literal.ts000066400000000000000000000027121505437577000254100ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Literal', () => { // ----------------------------------------------------- // LiteralString // ----------------------------------------------------- const T1 = Type.Literal('hello') it('Should pass 0', () => { const R = Resolve(T1, 'hello') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T1, 'world') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Literal) }) // ----------------------------------------------------- // LiteralNumber // ----------------------------------------------------- const T2 = Type.Literal(0) it('Should pass 2', () => { const R = Resolve(T2, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 3', () => { const R = Resolve(T2, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Literal) }) // ----------------------------------------------------- // LiteralBoolean // ----------------------------------------------------- const T3 = Type.Literal(true) it('Should pass 4', () => { const R = Resolve(T3, true) Assert.IsEqual(R.length, 0) }) it('Should pass 5', () => { const R = Resolve(T3, false) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Literal) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/never.ts000066400000000000000000000006031505437577000250700ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Never', () => { const T = Type.Never() it('Should pass 1', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Never) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/not.ts000066400000000000000000000007621505437577000245570ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Not', () => { const T = Type.Not(Type.String()) it('Should pass 0', () => { const R = Resolve(T, true) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 'hello') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Not) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/null.ts000066400000000000000000000007421505437577000247270ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Null', () => { const T = Type.Null() it('Should pass 0', () => { const R = Resolve(T, null) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/number-exclusive-maximum.ts000066400000000000000000000010341505437577000307200ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/NumberExclusiveMaximum', () => { const T = Type.Number({ exclusiveMaximum: 4 }) it('Should pass 0', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 4) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.NumberExclusiveMaximum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/number-exclusive-minimum.ts000066400000000000000000000010341505437577000307160ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/NumberExclusiveMinimum', () => { const T = Type.Number({ exclusiveMinimum: 4 }) it('Should pass 0', () => { const R = Resolve(T, 5) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 4) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.NumberExclusiveMinimum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/number-maximum.ts000066400000000000000000000010011505437577000267050ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/NumberMaximum', () => { const T = Type.Number({ maximum: 4 }) it('Should pass 0', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 5) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.NumberMaximum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/number-minimum.ts000066400000000000000000000010011505437577000267030ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/NumberMinimum', () => { const T = Type.Number({ minimum: 4 }) it('Should pass 0', () => { const R = Resolve(T, 4) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 3) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.NumberMinimum) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/number-multiple-of.ts000066400000000000000000000010121505437577000274670ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/NumberMultipleOf', () => { const T = Type.Number({ multipleOf: 2 }) it('Should pass 0', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.NumberMultipleOf) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/number.ts000066400000000000000000000007461505437577000252510ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Number', () => { const T = Type.Number() it('Should pass 0', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 0n) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Number) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/object-additional-properties.ts000066400000000000000000000027651505437577000315320ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ObjectAdditionalProperties', () => { // ---------------------------------------------------------- // additionalProperties: false // ---------------------------------------------------------- const T1 = Type.Object( { x: Type.Number(), }, { additionalProperties: false }, ) it('Should pass 0', () => { const R = Resolve(T1, { x: 1 }) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T1, { x: 1, y: 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ObjectAdditionalProperties) }) // ---------------------------------------------------------- // additionalProperties: TSchema // ---------------------------------------------------------- const T2 = Type.Object( { x: Type.Number(), }, { additionalProperties: Type.String() }, ) it('Should pass 2', () => { const R = Resolve(T2, { x: 1 }) Assert.IsEqual(R.length, 0) }) it('Should pass 3', () => { const R = Resolve(T2, { x: 1, a: 1, b: 2 }) Assert.IsEqual(R.length, 2) Assert.IsEqual(R[0].type, ValueErrorType.String) Assert.IsEqual(R[0].path, '/a') Assert.IsEqual(R[0].value, 1) Assert.IsEqual(R[1].type, ValueErrorType.String) Assert.IsEqual(R[1].path, '/b') Assert.IsEqual(R[1].value, 2) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/object-max-properties.ts000066400000000000000000000010671505437577000302010ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ObjectMaxProperties', () => { const T = Type.Object({}, { maxProperties: 2 }) it('Should pass 0', () => { const R = Resolve(T, { x: 1, y: 2 }) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, { x: 1, y: 2, z: 3 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ObjectMaxProperties) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/object-min-properties.ts000066400000000000000000000010531505437577000301720ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ObjectMinProperties', () => { const T = Type.Object({}, { minProperties: 2 }) it('Should pass 0', () => { const R = Resolve(T, { x: 1, y: 2 }) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, { x: 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.ObjectMinProperties) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/object-pointer-property.ts000066400000000000000000000116251505437577000305650ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ObjectPointerProperty', () => { // ---------------------------------------------------------------- // Known // ---------------------------------------------------------------- it('Should produce known pointer property path 1', () => { const T = Type.Object({ 'a/b': Type.String() }) const R = Resolve(T, { 'a/b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~1b') }) it('Should produce known pointer property path 2', () => { const T = Type.Object({ 'a~b': Type.String() }) const R = Resolve(T, { 'a~b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b') }) it('Should produce known pointer property path 3', () => { const T = Type.Object({ 'a/b~c': Type.String() }) const R = Resolve(T, { 'a/b~c': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~1b~0c') }) it('Should produce known pointer property path 4', () => { const T = Type.Object({ 'a~b/c': Type.String() }) const R = Resolve(T, { 'a~b/c': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b~1c') }) it('Should produce known pointer property path 5', () => { const T = Type.Object({ 'a~b/c/d': Type.String() }) const R = Resolve(T, { 'a~b/c/d': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b~1c~1d') }) it('Should produce known pointer property path 6', () => { const T = Type.Object({ 'a~b/c/d~e': Type.String() }) const R = Resolve(T, { 'a~b/c/d~e': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b~1c~1d~0e') }) // ---------------------------------------------------------------- // Unknown Additional // ---------------------------------------------------------------- it('Should produce unknown pointer property path 1', () => { const T = Type.Object({}, { additionalProperties: false }) const R = Resolve(T, { 'a/b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~1b') }) it('Should produce unknown pointer property path 2', () => { const T = Type.Object({}, { additionalProperties: false }) const R = Resolve(T, { 'a~b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b') }) // ---------------------------------------------------------------- // Unknown Constrained // ---------------------------------------------------------------- it('Should produce unknown constrained pointer property path 1', () => { const T = Type.Object({}, { additionalProperties: Type.String() }) const R = Resolve(T, { 'a/b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~1b') }) it('Should produce unknown constrained pointer property path 2', () => { const T = Type.Object({}, { additionalProperties: Type.String() }) const R = Resolve(T, { 'a~b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b') }) // ---------------------------------------------------------------- // Nested // ---------------------------------------------------------------- it('Should produce nested pointer 1', () => { const T = Type.Object({ 'x/y': Type.Object({ z: Type.Object({ w: Type.String(), }), }), }) const R = Resolve(T, { 'x/y': { z: { w: 1 } } }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/x~1y/z/w') }) it('Should produce nested pointer 2', () => { const T = Type.Object({ x: Type.Object({ 'y/z': Type.Object({ w: Type.String(), }), }), }) const R = Resolve(T, { x: { 'y/z': { w: 1 } } }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/x/y~1z/w') }) it('Should produce nested pointer 3', () => { const T = Type.Object({ x: Type.Object({ y: Type.Object({ 'z/w': Type.String(), }), }), }) const R = Resolve(T, { x: { y: { 'z/w': 1 } } }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/x/y/z~1w') }) // ---------------------------------------------------------------- // Nested Array // ---------------------------------------------------------------- it('Should produce nested array pointer property path 1', () => { const T = Type.Object({ 'x/y': Type.Object({ z: Type.Array(Type.String()), }), }) const R = Resolve(T, { 'x/y': { z: ['a', 'b', 1] } }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/x~1y/z/2') }) it('Should produce nested array pointer property path 2', () => { const T = Type.Object({ x: Type.Array( Type.Object({ 'y/z': Type.String(), }), ), }) const R = Resolve(T, { x: [{ 'y/z': 'a' }, { 'y/z': 'b' }, { 'y/z': 1 }] }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/x/2/y~1z') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/object-required-property.ts000066400000000000000000000014201505437577000307150ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/ObjectRequiredProperty', () => { const T = Type.Object({ x: Type.Number(), y: Type.Number() }) it('Should pass 0', () => { const R = Resolve(T, { x: 1, y: 2 }) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, { x: 1 }) Assert.IsEqual(R.length, 2) Assert.IsEqual(R[0].type, ValueErrorType.ObjectRequiredProperty) Assert.IsEqual(R[0].path, '/y') Assert.IsEqual(R[0].value, undefined) Assert.IsEqual(R[1].type, ValueErrorType.Number) Assert.IsEqual(R[1].path, '/y') Assert.IsEqual(R[1].value, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/object.ts000066400000000000000000000043341505437577000252240ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Object', () => { // ----------------------------------------------------------------- // Object // ----------------------------------------------------------------- const T1 = Type.Object({ x: Type.Number(), y: Type.Number() }) it('Should pass 0', () => { const R = Resolve(T1, { x: 1, y: 2 }) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T1, null) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Object) }) // ----------------------------------------------------------------- // Object: Optional // ----------------------------------------------------------------- const T2 = Type.Object({ x: Type.Optional(Type.Number()) }) it('Should pass 2', () => { const R = Resolve(T2, {}) Assert.IsEqual(R.length, 0) }) it('Should pass 3', () => { const R = Resolve(T2, { x: 1 }) Assert.IsEqual(R.length, 0) }) it('Should pass 4', () => { const R = Resolve(T2, { x: '' }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Number) Assert.IsEqual(R[0].path, '/x') Assert.IsEqual(R[0].value, '') }) // ----------------------------------------------------------------- // Object: Optional Multiple // ----------------------------------------------------------------- const T3 = Type.Partial(Type.Object({ x: Type.Number(), y: Type.Number() })) it('Should pass 5', () => { const R = Resolve(T3, {}) Assert.IsEqual(R.length, 0) }) it('Should pass 6', () => { const R = Resolve(T3, { x: 1 }) Assert.IsEqual(R.length, 0) }) it('Should pass 7', () => { const R = Resolve(T3, { y: 1 }) Assert.IsEqual(R.length, 0) }) it('Should pass 8', () => { const R = Resolve(T3, { x: 'a', y: 'b' }) Assert.IsEqual(R.length, 2) Assert.IsEqual(R[0].type, ValueErrorType.Number) Assert.IsEqual(R[0].path, '/x') Assert.IsEqual(R[0].value, 'a') Assert.IsEqual(R[1].type, ValueErrorType.Number) Assert.IsEqual(R[1].path, '/y') Assert.IsEqual(R[1].value, 'b') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/promise.ts000066400000000000000000000010031505437577000254220ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Promise', () => { const T = Type.Promise(Type.Any()) it('Should pass 0', () => { const R = Resolve(T, Promise.resolve(0)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Promise) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/record-pointer-property.ts000066400000000000000000000052601505437577000305730ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/RecordPointerProperty', () => { // ---------------------------------------------------------------- // Known // ---------------------------------------------------------------- it('Should produce known pointer property path 1', () => { const T = Type.Record(Type.String(), Type.String()) const R = Resolve(T, { 'a/b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~1b') }) it('Should produce known pointer property path 2', () => { const T = Type.Record(Type.String(), Type.String()) const R = Resolve(T, { 'a~b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b') }) // ---------------------------------------------------------------- // Unknown // ---------------------------------------------------------------- it('Should produce unknown pointer property path 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false, }) const R = Resolve(T, { 'a/b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~1b') }) it('Should produce unknown pointer property path 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false, }) const R = Resolve(T, { 'a~b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b') }) // ---------------------------------------------------------------- // Unknown Constrained // ---------------------------------------------------------------- it('Should produce unknown constrained pointer property path 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.String(), }) const R = Resolve(T, { 'a/b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~1b') }) it('Should produce unknown constrained pointer property path 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.String(), }) const R = Resolve(T, { 'a~b': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/a~0b') }) // ---------------------------------------------------------------- // PatternProperties // ---------------------------------------------------------------- it('Should produce pattern pointer property path 1', () => { const T = Type.Record(Type.TemplateLiteral('${string}/${string}/c'), Type.String(), { additionalProperties: false, }) const R = Resolve(T, { 'x/y/z': 1 }) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].path, '/x~1y~1z') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/regexp-max-length.ts000066400000000000000000000010611505437577000273040ustar00rootroot00000000000000import { Type, FormatRegistry } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/RegExpMaxLength', () => { const T = Type.RegExp(/(.*)/, { maxLength: 4, }) it('Should pass 0', () => { const R = Resolve(T, 'xxxx') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 'xxxxx') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.StringMaxLength) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/regexp-min-length.ts000066400000000000000000000010371505437577000273050ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/RegExpMinLength', () => { const T = Type.RegExp(/(.*)/, { minLength: 4, }) it('Should pass 0', () => { const R = Resolve(T, 'xxxx') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 'xxx') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.StringMinLength) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/regexp.ts000066400000000000000000000007621505437577000252510ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/RegExp', () => { const T = Type.RegExp(/123/) it('Should pass 0', () => { const R = Resolve(T, '123') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, '321') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.RegExp) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/resolve.ts000066400000000000000000000003441505437577000254320ustar00rootroot00000000000000import { Errors } from '@sinclair/typebox/errors' import { TSchema } from '@sinclair/typebox' /** Resolves errors */ export function Resolve(schema: T, value: unknown) { return [...Errors(schema, value)] } sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/string-format-unknown.ts000066400000000000000000000006661505437577000302530ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/StringFormatUnknown', () => { const T = Type.String({ format: 'unknown' }) it('Should pass 1', () => { const R = Resolve(T, '') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.StringFormatUnknown) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/string-format.ts000066400000000000000000000015741505437577000265550ustar00rootroot00000000000000import { Type, FormatRegistry } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/StringFormat', () => { // ---------------------------------------------- // Fixture // ---------------------------------------------- beforeEach(() => FormatRegistry.Set('foo', (value) => value === 'foo')) afterEach(() => FormatRegistry.Delete('foo')) // ---------------------------------------------- // Tests // ---------------------------------------------- const T = Type.String({ format: 'foo' }) it('Should pass 0', () => { const R = Resolve(T, 'foo') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 'bar') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.StringFormat) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/string-max-length.ts000066400000000000000000000010421505437577000273170ustar00rootroot00000000000000import { Type, FormatRegistry } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/StringMaxLength', () => { const T = Type.String({ maxLength: 4 }) it('Should pass 0', () => { const R = Resolve(T, '1234') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, '12345') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.StringMaxLength) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/string-min-length.ts000066400000000000000000000010201505437577000273110ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/StringMinLength', () => { const T = Type.String({ minLength: 4 }) it('Should pass 0', () => { const R = Resolve(T, '1234') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, '123') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.StringMinLength) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/string-pattern.ts000066400000000000000000000010151505437577000267300ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/StringPattern', () => { const T = Type.String({ pattern: '123' }) it('Should pass 0', () => { const R = Resolve(T, '123') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, '321') Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.StringPattern) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/string.ts000066400000000000000000000007531505437577000252650ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/String', () => { const T = Type.String() it('Should pass 0', () => { const R = Resolve(T, 'hello') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.String) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/symbol.ts000066400000000000000000000007551505437577000252660ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Symbol', () => { const T = Type.Symbol() it('Should pass 0', () => { const R = Resolve(T, Symbol(1)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Symbol) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/tuple-length.ts000066400000000000000000000034511505437577000263650ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/TupleLength', () => { // ---------------------------------------------- // Tuple: Empty // ---------------------------------------------- const T1 = Type.Tuple([]) it('Should pass 0', () => { const R = Resolve(T1, []) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T1, [1]) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.TupleLength) }) // ---------------------------------------------- // Tuple: One // ---------------------------------------------- const T2 = Type.Tuple([Type.Number()]) it('Should pass 2', () => { const R = Resolve(T2, [1]) Assert.IsEqual(R.length, 0) }) it('Should pass 3', () => { const R = Resolve(T2, []) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.TupleLength) }) it('Should pass 4', () => { const R = Resolve(T2, [1, 1]) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.TupleLength) }) // ---------------------------------------------- // Tuple: Element // ---------------------------------------------- const T3 = Type.Tuple([Type.Number(), Type.Number()]) it('Should pass 5', () => { const R = Resolve(T3, [1, 1]) Assert.IsEqual(R.length, 0) }) it('Should pass 6', () => { const R = Resolve(T3, ['a', 'b']) Assert.IsEqual(R.length, 2) Assert.IsEqual(R[0].type, ValueErrorType.Number) Assert.IsEqual(R[0].path, '/0') Assert.IsEqual(R[0].value, 'a') Assert.IsEqual(R[1].type, ValueErrorType.Number) Assert.IsEqual(R[1].path, '/1') Assert.IsEqual(R[1].value, 'b') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/tuple.ts000066400000000000000000000007451505437577000251110ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Tuple', () => { const T = Type.Tuple([]) it('Should pass 0', () => { const R = Resolve(T, []) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Tuple) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/uint8array-max-byte-length.ts000066400000000000000000000010771505437577000310700ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Uint8ArrayMaxByteLength', () => { const T = Type.Uint8Array({ maxByteLength: 4 }) it('Should pass 0', () => { const R = Resolve(T, new Uint8Array(4)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, new Uint8Array(5)) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Uint8ArrayMaxByteLength) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/uint8array-min-byte-length.ts000066400000000000000000000011171505437577000310610ustar00rootroot00000000000000import { Type, FormatRegistry } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Uint8ArrayMinByteLength', () => { const T = Type.Uint8Array({ minByteLength: 4 }) it('Should pass 0', () => { const R = Resolve(T, new Uint8Array(4)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, new Uint8Array(3)) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Uint8ArrayMinByteLength) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/uint8array.ts000066400000000000000000000010241505437577000260550ustar00rootroot00000000000000import { Type, FormatRegistry } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Uint8Array', () => { const T = Type.Uint8Array() it('Should pass 0', () => { const R = Resolve(T, new Uint8Array(4)) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, null) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Uint8Array) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/undefined.ts000066400000000000000000000007661505437577000257240ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Undefined', () => { const T = Type.Undefined() it('Should pass 0', () => { const R = Resolve(T, undefined) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 0) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/union.ts000066400000000000000000000014101505437577000250760ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorIterator, ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' describe('errors/type/Union', () => { const T = Type.Union([Type.String(), Type.Number()]) it('Should pass 0', () => { const R = Resolve(T, '1') Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, 1) Assert.IsEqual(R.length, 0) }) it('Should pass 2', () => { const R = Resolve(T, true) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Union) Assert.IsEqual(R[0].errors[0].First()?.type, ValueErrorType.String) Assert.IsEqual(R[0].errors[1].First()?.type, ValueErrorType.Number) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/errors/types/void.ts000066400000000000000000000016451505437577000247210ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ValueErrorType } from '@sinclair/typebox/errors' import { Resolve } from './resolve' import { Assert } from '../../assert' import { TypeSystemPolicy } from '@sinclair/typebox/system' describe('errors/type/Void', () => { const T = Type.Void() it('Should pass 0', () => { const R = Resolve(T, void 0) Assert.IsEqual(R.length, 0) }) it('Should pass 1', () => { const R = Resolve(T, undefined) Assert.IsEqual(R.length, 0) }) it('Should pass 2', () => { const R = Resolve(T, void 1) Assert.IsEqual(R.length, 0) }) it('Should pass 3', () => { const R = Resolve(T, null) Assert.IsEqual(R.length, 1) Assert.IsEqual(R[0].type, ValueErrorType.Void) }) it('Should pass 4', () => { TypeSystemPolicy.AllowNullVoid = true const R = Resolve(T, null) Assert.IsEqual(R.length, 0) TypeSystemPolicy.AllowNullVoid = false }) }) sinclairzx81-typebox-e0ec98c/test/runtime/index.ts000066400000000000000000000007311505437577000224020ustar00rootroot00000000000000import { TypeSystemPolicy } from '@sinclair/typebox/system' // ------------------------------------------------------------------ // InstanceMode: Freeze (Detect Unintended Side Effects) // ------------------------------------------------------------------ TypeSystemPolicy.InstanceMode = 'freeze' import './compiler/index' import './compiler-ajv/index' import './errors/index' import './syntax/index' import './system/index' import './type/index' import './value/index' sinclairzx81-typebox-e0ec98c/test/runtime/syntax/000077500000000000000000000000001505437577000222505ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/syntax/index.ts000066400000000000000000000000221505437577000237210ustar00rootroot00000000000000import './syntax' sinclairzx81-typebox-e0ec98c/test/runtime/syntax/syntax.ts000066400000000000000000000365611505437577000241610ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Syntax } from '@sinclair/typebox/syntax' import { Assert } from '../assert/index' // prettier-ignore describe('syntax/Syntax', () => { // ---------------------------------------------------------------- // Type Expressions // ---------------------------------------------------------------- it('Should parse Any', () => { const T = Syntax(`any`) Assert.IsTrue(TypeGuard.IsAny(T)) }) it('Should parse Array 1', () => { const T = Syntax(`number[]`) Assert.IsTrue(TypeGuard.IsArray(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items)) }) it('Should parse Array 2', () => { const T = Syntax(`Array`) Assert.IsTrue(TypeGuard.IsArray(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items)) }) it('Should parse AsyncIterator', () => { const T = Syntax(`AsyncIterator`) Assert.IsTrue(TypeGuard.IsAsyncIterator(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items)) }) it('Should parse Awaited', () => { const T = Syntax(`Awaited>`) Assert.IsTrue(TypeGuard.IsNumber(T)) }) it('Should parse BigInt', () => { const T = Syntax(`bigint`) Assert.IsTrue(TypeGuard.IsBigInt(T)) }) it('Should parse Boolean', () => { const T = Syntax(`boolean`) Assert.IsTrue(TypeGuard.IsBoolean(T)) }) it('Should parse ConstructorParameters', () => { const T = Syntax(`ConstructorParameters boolean>`) Assert.IsTrue(TypeGuard.IsTuple(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items![0])) Assert.IsTrue(TypeGuard.IsString(T.items![1])) }) it('Should parse Constructor', () => { const T = Syntax(`new (a: number, b: string) => boolean`) Assert.IsTrue(TypeGuard.IsConstructor(T)) Assert.IsTrue(TypeGuard.IsNumber(T.parameters[0])) Assert.IsTrue(TypeGuard.IsString(T.parameters[1])) Assert.IsTrue(TypeGuard.IsBoolean(T.returns)) }) it('Should parse Date', () => { const T = Syntax(`Date`) Assert.IsTrue(TypeGuard.IsDate(T)) }) it('Should parse Exclude', () => { const T = Syntax(`Exclude<1 | 2 | 3, 1>`) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(T.anyOf[0].const === 2) Assert.IsTrue(T.anyOf[1].const === 3) }) it('Should parse Extract', () => { const T = Syntax(`Extract<1 | 2 | 3, 1 | 2>`) Assert.IsTrue(TypeGuard.IsUnion(T)) // @ts-ignore fix: incorrect union order (result of UnionToTuple, replace with Tuple destructuring) Assert.IsTrue(T.anyOf[0].const === 1) // @ts-ignore fix: incorrect union order (result of UnionToTuple, replace with Tuple destructuring) Assert.IsTrue(T.anyOf[1].const === 2) }) it('Should parse Function', () => { const T = Syntax(`(a: number, b: string) => boolean`) Assert.IsTrue(TypeGuard.IsFunction(T)) Assert.IsTrue(TypeGuard.IsNumber(T.parameters[0])) Assert.IsTrue(TypeGuard.IsString(T.parameters[1])) Assert.IsTrue(TypeGuard.IsBoolean(T.returns)) }) it('Should parse Indexed 1', () => { const T = Syntax(`{ x: 1, y: 2, z: 3 }['x']`) Assert.IsTrue(T.const === 1) }) it('Should parse Indexed 2', () => { const T = Syntax(`{ x: 1, y: 2, z: 3 }['x' | 'y' | 'z']`) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(T.anyOf[0].const === 1) Assert.IsTrue(T.anyOf[1].const === 2) Assert.IsTrue(T.anyOf[2].const === 3) }) it('Should parse Indexed 3', () => { const T = Syntax(`{ x: 1, y: 2, z: 3 }`) const S = Syntax({ T }, `T[keyof T]`) Assert.IsTrue(TypeGuard.IsUnion(S)) Assert.IsTrue(S.anyOf[0].const === 1) Assert.IsTrue(S.anyOf[1].const === 2) Assert.IsTrue(S.anyOf[2].const === 3) }) it('Should parse Indexed 4', () => { const T = Syntax(`['A', 'B', 'C']`) const S = Syntax({ T }, `T[number]`) Assert.IsTrue(TypeGuard.IsUnion(S)) Assert.IsTrue(S.anyOf[0].const === 'A') Assert.IsTrue(S.anyOf[1].const === 'B') Assert.IsTrue(S.anyOf[2].const === 'C') }) it('Should parse Integer', () => { const T = Syntax(`integer`) Assert.IsTrue(TypeGuard.IsInteger(T)) }) it('Should parse Intersect 1', () => { const T = Syntax(`1 & 2`) Assert.IsTrue(TypeGuard.IsIntersect(T)) Assert.IsTrue(T.allOf[0].const === 1) Assert.IsTrue(T.allOf[1].const === 2) }) it('Should parse Intersect 2', () => { const T = Syntax(`1 & (2 & 3)`) // expect flatten Assert.IsTrue(TypeGuard.IsIntersect(T)) Assert.IsTrue(T.allOf[0].const === 1) Assert.IsTrue(T.allOf[1].const === 2) Assert.IsTrue(T.allOf[2].const === 3) }) it('Should parse Intersect 3', () => { const T = Syntax(`(1 | 2) & 3`) // operator precedence Assert.IsTrue(TypeGuard.IsIntersect(T)) Assert.IsTrue(TypeGuard.IsUnion(T.allOf[0])) Assert.IsTrue(T.allOf[1].const === 3) }) it('Should parse InstanceType 1', () => { const T = Syntax(`InstanceType { x: 1, y: 2 }>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(T.properties.x.const === 1) Assert.IsTrue(T.properties.y.const === 2) }) it('Should parse InstanceType 2', () => { const T = Syntax(`InstanceType`) // generalization issue Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should parse Iterator', () => { const T = Syntax(`Iterator`) Assert.IsTrue(TypeGuard.IsIterator(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items)) }) it('Should parse KeyOf 1', () => { const T = Syntax(`keyof { x: 1, y: 2 }`) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(T.anyOf[0].const === 'x') Assert.IsTrue(T.anyOf[1].const === 'y') }) it('Should parse KeyOf 2', () => { const T = Syntax(`keyof [0, 1]`) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(T.anyOf[0].const === '0') Assert.IsTrue(T.anyOf[1].const === '1') }) it('Should parse KeyOf 3', () => { const T = Syntax(`{ x: 1, y: 2 }`) const S = Syntax({ T }, `keyof T`) Assert.IsTrue(TypeGuard.IsUnion(S)) Assert.IsTrue(S.anyOf[0].const === 'x') Assert.IsTrue(S.anyOf[1].const === 'y') }) it('Should parse Literal Boolean 1', () => { const T = Syntax(`true`) Assert.IsTrue(T.const === true) }) it('Should parse Literal Boolean 2', () => { const T = Syntax(`false`) Assert.IsTrue(T.const === false) }) it('Should parse Literal Number', () => { const T = Syntax(`1`) Assert.IsTrue(T.const === 1) }) it('Should parse Literal String', () => { const T = Syntax(`'1'`) Assert.IsTrue(T.const === '1') }) it('Should parse Mapped (Pending)', () => { const T = Syntax(`{ [K in 1 | 2 | 3]: K }`) Assert.IsTrue(T.const === 'Mapped types not supported') }) it('Should parse Never', () => { const T = Syntax(`never`) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should parse Null', () => { const T = Syntax(`null`) Assert.IsTrue(TypeGuard.IsNull(T)) }) it('Should parse Number', () => { const T = Syntax(`number`) Assert.IsTrue(TypeGuard.IsNumber(T)) }) it('Should parse Object 1', () => { const T = Syntax(`{x: boolean, y: number, z: string, }`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(TypeGuard.IsString(T.properties.z)) }) it('Should parse Object 2', () => { const T = Syntax(`{x: boolean; y: number; z: string; }`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(TypeGuard.IsString(T.properties.z)) }) it('Should parse Object 3', () => { const T = Syntax(`{ x: boolean y: number z: string }`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(TypeGuard.IsString(T.properties.z)) }) it('Should parse Object 4', () => { const T = Syntax(`{ x: boolean; y: number; z: string; }`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(TypeGuard.IsString(T.properties.z)) }) it('Should parse Object 5', () => { const T = Syntax(`{ x: boolean, y: number, z: string, }`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(TypeGuard.IsString(T.properties.z)) }) it('Should parse Omit 1', () => { const T = Syntax(`Omit<{ x: boolean, y: number, z: string }, 'z'>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(('z' in T.properties) === false) }) it('Should parse Omit 2', () => { const T = Syntax(`Omit<{ x: boolean, y: number, z: string }, 'z' | 'y'>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(('y' in T.properties) === false) Assert.IsTrue(('z' in T.properties) === false) }) it('Should parse Parameters', () => { const T = Syntax(`Parameters<(a: number, b: string) => boolean>`) Assert.IsTrue(TypeGuard.IsTuple(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items![0])) Assert.IsTrue(TypeGuard.IsString(T.items![1])) }) it('Should parse Partial', () => { const T = Syntax(`Partial<{ x: boolean, y: number, z: string }>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(('required' in T) === false) }) it('Should parse Pick 1', () => { const T = Syntax(`Pick<{ x: boolean, y: number, z: string }, 'x' | 'y'>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(('z' in T.properties) === false) }) it('Should parse Pick 2', () => { const T = Syntax(`Pick<{ x: boolean, y: number, z: string }, 'x'>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(('y' in T.properties) === false) Assert.IsTrue(('z' in T.properties) === false) }) it('Should parse Promise', () => { const T = Syntax(`Promise`) Assert.IsTrue(TypeGuard.IsPromise(T)) Assert.IsTrue(TypeGuard.IsNumber(T.item)) }) it('Should parse ReadonlyOptional', () => { const T = Syntax(`{ readonly x?: boolean, readonly y?: number }`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsReadonly(T.properties.x)) Assert.IsTrue(TypeGuard.IsOptional(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(TypeGuard.IsReadonly(T.properties.y)) Assert.IsTrue(TypeGuard.IsOptional(T.properties.y)) }) it('Should parse Readonly', () => { const T = Syntax(`{ readonly x: boolean, readonly y: number }`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsBoolean(T.properties.x)) Assert.IsTrue(TypeGuard.IsReadonly(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsTrue(TypeGuard.IsReadonly(T.properties.y)) }) it('Should parse Record 1', () => { const T = Syntax(`Record`) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsNumber(T.patternProperties['^(.*)$'])) }) it('Should parse Record 2', () => { const T = Syntax(`Record`) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsNumber(T.patternProperties['^(0|[1-9][0-9]*)$'])) }) it('Should parse Record 3', () => { const T = Syntax(`Record<'x' | 'y', number>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) }) it('Should parse Recursive', () => { const T = Type.Recursive(This => Syntax({ This }, `{ id: string, nodes: This[] }`)) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.id)) Assert.IsTrue(TypeGuard.IsArray(T.properties.nodes)) Assert.IsTrue(TypeGuard.IsThis(T.properties.nodes.items)) }) it('Should parse Ref', () => { const T = Syntax('foo') Assert.IsTrue(TypeGuard.IsRef(T)) Assert.IsTrue(T.$ref === 'foo') }) it('Should parse Required', () => { const T = Syntax(`Required<{ x?: boolean, y?: number, z?: string }>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsEqual(T.required, ['x', 'y', 'z']) }) it('Should parse ReturnType 1', () => { const T = Syntax(`ReturnType<() => { x: 1, y: 2 }>`) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(T.properties.x.const === 1) Assert.IsTrue(T.properties.y.const === 2) }) it('Should parse ReturnType 2', () => { const T = Syntax(`ReturnType`) // generalization issue Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should parse String', () => { const T = Syntax(`string`) Assert.IsTrue(TypeGuard.IsString(T)) }) it('Should parse Symbol', () => { const T = Syntax(`symbol`) Assert.IsTrue(TypeGuard.IsSymbol(T)) }) it('Should parse Tuple', () => { const T = Syntax(`[0, 1, 2, 3]`) Assert.IsTrue(TypeGuard.IsTuple(T)) Assert.IsTrue(T.items![0].const === 0) Assert.IsTrue(T.items![1].const === 1) Assert.IsTrue(T.items![2].const === 2) Assert.IsTrue(T.items![3].const === 3) }) it('Should parse Uint8Array', () => { const T = Syntax(`Uint8Array`) Assert.IsTrue(TypeGuard.IsUint8Array(T)) }) it('Should parse Undefined', () => { const T = Syntax(`undefined`) Assert.IsTrue(TypeGuard.IsUndefined(T)) }) it('Should parse Union 1', () => { const T = Syntax(`1 | 2`) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(T.anyOf[0].const === 1) Assert.IsTrue(T.anyOf[1].const === 2) }) it('Should parse Union 2', () => { const T = Syntax(`1 | (2 | 3)`) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(T.anyOf[0].const === 1) Assert.IsTrue(T.anyOf[1].const === 2) Assert.IsTrue(T.anyOf[2].const === 3) }) it('Should parse Unknown', () => { const T = Syntax(`unknown`) Assert.IsTrue(TypeGuard.IsUnknown(T)) }) it('Should parse Void', () => { const T = Syntax(`void`) Assert.IsTrue(TypeGuard.IsVoid(T)) }) // ---------------------------------------------------------------- // Argument + Instantiation // ---------------------------------------------------------------- it('Should parse Argument 0', () => { const G = Syntax(`[Argument<0>]`) const T = Syntax({ G }, `G`) Assert.IsTrue(TypeGuard.IsTuple(T)) Assert.IsTrue(TypeGuard.IsArgument(T.items![0])) }) it('Should parse Argument 1', () => { const G = Syntax(`[Argument<0>]`) const T = Syntax({ G }, `G`) Assert.IsTrue(TypeGuard.IsTuple(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items![0])) }) it('Should parse Argument 2', () => { const G = Syntax(`[Argument<0>, Argument<1>]`) const T = Syntax({ G }, `G`) Assert.IsTrue(TypeGuard.IsTuple(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items![0])) Assert.IsTrue(TypeGuard.IsString(T.items![1])) }) it('Should parse Argument 3', () => { const G = Syntax(`[Argument<0>, Argument<1>]`) const T = Syntax({ G }, `G`) Assert.IsTrue(TypeGuard.IsTuple(T)) Assert.IsTrue(TypeGuard.IsNumber(T.items![0])) Assert.IsTrue(TypeGuard.IsUnknown(T.items![1])) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/system/000077500000000000000000000000001505437577000222465ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/system/index.ts000066400000000000000000000000561505437577000237260ustar00rootroot00000000000000import './policy/index' import './type/index' sinclairzx81-typebox-e0ec98c/test/runtime/system/policy/000077500000000000000000000000001505437577000235455ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/system/policy/allow-array-object.ts000066400000000000000000000044271505437577000276220ustar00rootroot00000000000000import { Ok, Fail } from '../../compiler/validate' import { TypeSystemPolicy } from '@sinclair/typebox/system' import { Type } from '@sinclair/typebox' describe('system/TypeSystemPolicy/AllowArrayObject', () => { beforeEach(() => { TypeSystemPolicy.AllowArrayObject = true }) afterEach(() => { TypeSystemPolicy.AllowArrayObject = false }) // --------------------------------------------------------------- // Object // --------------------------------------------------------------- it('Should validate arrays with empty objects', () => { const T = Type.Object({}) Ok(T, [0, 1, 2]) }) it('Should validate arrays with objects with length property', () => { const T = Type.Object({ length: Type.Number() }) Ok(T, [0, 1, 2]) }) it('Should validate arrays with objects with additionalProperties false when array has no elements', () => { const T = Type.Object({ length: Type.Number() }, { additionalProperties: false }) Ok(T, []) }) it('Should not validate arrays with objects with additionalProperties false when array has elements', () => { const T = Type.Object({ length: Type.Number() }, { additionalProperties: false }) Fail(T, [0, 1, 2]) }) it('Should not validate arrays with objects when length property is string', () => { const T = Type.Object({ length: Type.String() }) Fail(T, [0, 1, 2]) }) // --------------------------------------------------------------- // Record // --------------------------------------------------------------- it('Should validate arrays as Records with String Keys', () => { const T = Type.Record(Type.String(), Type.Number()) Ok(T, [0, 1, 2]) }) it('Should validate arrays as Records with Number Keys', () => { const T = Type.Record(Type.Number(), Type.Number()) Ok(T, [0, 1, 2]) }) it('Should validate arrays as Records with Integer Keys', () => { const T = Type.Record(Type.Integer(), Type.Number()) Ok(T, [0, 1, 2]) }) it('Should not validate arrays as Records with Object Values', () => { const T = Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) Ok(T, [ { x: 1, y: 1, z: 1 }, { x: 1, y: 1, z: 1 }, { x: 1, y: 1, z: 1 }, ]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/system/policy/allow-nan.ts000066400000000000000000000036561505437577000260170ustar00rootroot00000000000000import { Ok, Fail } from '../../compiler/validate' import { TypeSystemPolicy } from '@sinclair/typebox/system' import { Type } from '@sinclair/typebox' describe('system/TypeSystemPolicy/AllowNaN', () => { beforeEach(() => { TypeSystemPolicy.AllowNaN = true }) afterEach(() => { TypeSystemPolicy.AllowNaN = false }) // --------------------------------------------------------------- // Number // --------------------------------------------------------------- it('Should validate number with NaN', () => { const T = Type.Number() Ok(T, NaN) }) it('Should validate number with +Infinity', () => { const T = Type.Number() Ok(T, Infinity) }) it('Should validate number with -Infinity', () => { const T = Type.Number() Ok(T, -Infinity) }) // --------------------------------------------------------------- // Integer // // Note: The Number.isInteger() test will fail for NaN. Because // of this we cannot reasonably override NaN handling for integers. // --------------------------------------------------------------- it('Should not validate integer with NaN', () => { const T = Type.Integer() Fail(T, NaN) }) it('Should not validate integer with +Infinity', () => { const T = Type.Integer() Fail(T, Infinity) }) it('Should not validate integer with -Infinity', () => { const T = Type.Integer() Fail(T, -Infinity) }) // --------------------------------------------------------------- // BigInt // // Note: We expect failures here as bigint isn't IEEE754 // --------------------------------------------------------------- it('Should not validate bigint with NaN', () => { const T = Type.BigInt() Fail(T, NaN) }) it('Should not validate bigint with +Infinity', () => { const T = Type.BigInt() Fail(T, Infinity) }) it('Should not validate bigint with -Infinity', () => { const T = Type.BigInt() Fail(T, -Infinity) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/system/policy/allow-null-void.ts000066400000000000000000000015441505437577000271460ustar00rootroot00000000000000import { Ok } from '../../compiler/validate' import { TypeSystemPolicy } from '@sinclair/typebox/system' import { Type } from '@sinclair/typebox' describe('system/TypeSystemPolicy/AllowNullVoid', () => { beforeEach(() => { TypeSystemPolicy.AllowNullVoid = true }) afterEach(() => { TypeSystemPolicy.AllowNullVoid = false }) // --------------------------------------------------------------- // Object // --------------------------------------------------------------- it('Should validate with null', () => { const T = Type.Void() Ok(T, null) }) it('Should validate with undefined', () => { const T = Type.Void() Ok(T, undefined) }) it('Should validate with void 0', () => { const T = Type.Void() Ok(T, void 0) }) it('Should validate with void 1', () => { const T = Type.Void() Ok(T, void 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/system/policy/exact-optional-property-types.ts000066400000000000000000000022071505437577000320710ustar00rootroot00000000000000import { Ok, Fail } from '../../compiler/validate' import { TypeSystemPolicy } from '@sinclair/typebox/system' import { Type } from '@sinclair/typebox' describe('system/TypeSystemPolicy/ExactOptionalPropertyTypes', () => { beforeEach(() => { TypeSystemPolicy.ExactOptionalPropertyTypes = true }) afterEach(() => { TypeSystemPolicy.ExactOptionalPropertyTypes = false }) // --------------------------------------------------------------- // Number // --------------------------------------------------------------- it('Should not validate optional number', () => { const T = Type.Object({ x: Type.Optional(Type.Number()), }) Ok(T, {}) Ok(T, { x: 1 }) Fail(T, { x: undefined }) }) it('Should not validate undefined', () => { const T = Type.Object({ x: Type.Optional(Type.Undefined()), }) Ok(T, {}) Fail(T, { x: 1 }) Ok(T, { x: undefined }) }) it('Should validate optional number | undefined', () => { const T = Type.Object({ x: Type.Optional(Type.Union([Type.Number(), Type.Undefined()])), }) Ok(T, {}) Ok(T, { x: 1 }) Ok(T, { x: undefined }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/system/policy/index.ts000066400000000000000000000002201505437577000252160ustar00rootroot00000000000000import './allow-array-object' import './allow-nan' import './allow-null-void' import './exact-optional-property-types' import './instance-mode' sinclairzx81-typebox-e0ec98c/test/runtime/system/policy/instance-mode.ts000066400000000000000000000020631505437577000266440ustar00rootroot00000000000000import { TypeSystemPolicy } from '@sinclair/typebox/system' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('system/TypeSystemPolicy/InstanceMode', () => { after(() => { TypeSystemPolicy.InstanceMode = 'freeze' }) // --------------------------------------------------------------- // Number // --------------------------------------------------------------- it('Should use instance mode default', () => { TypeSystemPolicy.InstanceMode = 'default' const S = Type.String() const T = Type.Array(S) S.$id = 'updated' Assert.IsEqual(T.items.$id, 'updated') }) it('Should use instance mode clone', () => { TypeSystemPolicy.InstanceMode = 'clone' const S = Type.String() const T = Type.Array(S) S.$id = 'updated' Assert.IsEqual(T.items.$id, undefined) }) it('Should use instance mode freeze', () => { TypeSystemPolicy.InstanceMode = 'freeze' Assert.Throws(() => { const S = Type.String() const T = Type.Array(S) S.$id = 'updated' }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/system/type/000077500000000000000000000000001505437577000232275ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/system/type/format.ts000066400000000000000000000012721505437577000250710ustar00rootroot00000000000000import { Ok, Fail } from '../../compiler/validate' import { Assert } from '../../assert/index' import { TypeSystem } from '@sinclair/typebox/system' import { Type, FormatRegistry } from '@sinclair/typebox' describe('system/TypeSystem/Format', () => { it('Should create and validate a format', () => { const Foo = TypeSystem.Format('Foo', (value) => value === 'foo') const T = Type.String({ format: Foo }) Ok(T, 'foo') Fail(T, 'bar') FormatRegistry.Delete('Foo') }) it('Should throw if registering the same type twice', () => { TypeSystem.Format('Foo', () => true) Assert.Throws(() => TypeSystem.Format('Foo', () => true)) FormatRegistry.Delete('Foo') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/system/type/index.ts000066400000000000000000000000421505437577000247020ustar00rootroot00000000000000import './format' import './type' sinclairzx81-typebox-e0ec98c/test/runtime/system/type/type.ts000066400000000000000000000013621505437577000245620ustar00rootroot00000000000000import { Ok, Fail } from '../../compiler/validate' import { TypeSystem } from '@sinclair/typebox/system' import { TypeRegistry } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('system/TypeSystem/Type', () => { it('Should create and validate a type', () => { const Foo = TypeSystem.Type('Foo', (options, value) => { Assert.IsEqual(options.option, 'test') return value === 'foo' }) const T = Foo({ option: 'test' }) Ok(T, 'foo') Fail(T, 'bar') TypeRegistry.Delete('Foo') }) it('Should throw if registering the same type twice', () => { TypeSystem.Type('Foo', () => true) Assert.Throws(() => TypeSystem.Type('Foo', () => true)) TypeRegistry.Delete('Foo') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/000077500000000000000000000000001505437577000217035ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/clone/000077500000000000000000000000001505437577000230035ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/clone/clone.ts000066400000000000000000000131371505437577000244600ustar00rootroot00000000000000// -------------------------------------------------------------------- // $id deletion was omitted from 0.26.0 to reduce complexity overhead. // -------------------------------------------------------------------- // import { Type } from '@sinclair/typebox' // import { Assert } from '../../assert' // describe('type/Clone', () => { // it('Should retain source type $id for cloned objects', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Object({ x: S, y: S }) // Assert.equal(T.properties.x.$id, undefined) // Assert.equal(T.properties.y.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should retain source type $id when composing objects with cloned arrays', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Function([S], S) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Array', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Array(S) // Assert.equal(T.items.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Composite', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Composite([Type.Object({ a: S }), Type.Object({ b: S })]) // Assert.equal(T.properties.a.$id, undefined) // Assert.equal(T.properties.b.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Constructor', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Constructor([S], S) // Assert.equal(T.parameters[0].$id, undefined) // Assert.equal(T.returns.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Function', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Function([S], S) // Assert.equal(T.parameters[0].$id, undefined) // Assert.equal(T.returns.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Intersect', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Intersect([S, S]) // Assert.equal(T.allOf[0].$id, undefined) // Assert.equal(T.allOf[1].$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Intersect with unevaluatedProperties', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Intersect([S, S], { unevaluatedProperties: S }) // // @ts-ignore // Assert.equal(T.unevaluatedProperties.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Not', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Not(S, S) // Assert.equal(T.allOf[0].not.$id, undefined) // Assert.equal(T.allOf[1].$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Object', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Object({ x: S, y: S }) // Assert.equal(T.properties.x.$id, undefined) // Assert.equal(T.properties.y.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for nested Object', () => { // const S = Type.String({ $id: 'S' }) // const N = Type.Object({ s: S }, { $id: 'N' }) // const T = Type.Object({ x: S, y: S, z: N }) // Assert.equal(T.properties.x.$id, undefined) // Assert.equal(T.properties.y.$id, undefined) // Assert.equal(T.properties.z.$id, undefined) // Assert.equal(T.properties.z.properties.s.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Object additionalProperties', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Object({}, { additionalProperties: S }) // // @ts-ignore // Assert.equal(T.additionalProperties!.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Promise', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Promise(S) // Assert.equal(T.item.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Record', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Record(Type.String(), S) // Assert.equal(T.patternProperties['^.*$'].$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Tuple', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Tuple([S, S]) // Assert.equal(T.items![0]!.$id, undefined) // Assert.equal(T.items![1]!.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should remove cloned $id for Union', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Union([S, S]) // Assert.equal(T.anyOf[0]!.$id, undefined) // Assert.equal(T.anyOf[1]!.$id, undefined) // Assert.equal(S.$id, 'S') // }) // it('Should retain cloned $id for wrapped Recursive 1', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Object({ // x: Type.Recursive( // (Self) => // Type.Object({ // self: Type.Optional(Self), // }), // { $id: 'RecursiveClone' }, // ), // }) // Assert.equal(T.properties.x.$id, 'RecursiveClone') // Assert.equal(S.$id, 'S') // }) // it('Should retain cloned $id for wrapped Recursive 2', () => { // const S = Type.String({ $id: 'S' }) // const T = Type.Tuple([ // Type.Recursive( // (Self) => // Type.Object({ // self: Type.Optional(Self), // }), // { $id: 'RecursiveClone' }, // ), // ]) // Assert.equal(T.items![0].$id, 'RecursiveClone') // Assert.equal(S.$id, 'S') // }) // }) sinclairzx81-typebox-e0ec98c/test/runtime/type/clone/index.ts000066400000000000000000000000211505437577000244530ustar00rootroot00000000000000import './clone' sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/000077500000000000000000000000001505437577000233555ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/any.ts000066400000000000000000000067251505437577000245260ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Any', () => { it('Should extend Any', () => { type T = any extends any ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = any extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = any extends string ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.String()) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Boolean', () => { type T = any extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Number', () => { type T = any extends number ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Number()) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Integer', () => { type T = any extends number ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Array 1', () => { type T = any extends Array ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Array 2', () => { type T = any extends Array ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Array(Type.String())) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Tuple', () => { type T = any extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Object 1', () => { type T = any extends object ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Object 2', () => { type T = any extends {} ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Object 3', () => { type T = any extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Union 1', () => { type T = any extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Union 2', () => { type T = any extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Union([Type.Any(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = any extends null ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Null()) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Undefined', () => { type T = any extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Void', () => { type T = any extends void ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Void()) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Date', () => { type T = any extends Date ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Date()) Assert.IsEqual(R, ExtendsResult.Union) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/array.ts000066400000000000000000000267431505437577000250570ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Array', () => { // ---------------------------------------------- // Generic Varying // ---------------------------------------------- it('Should extend Array Varying 1', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array Varying 2', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array Varying 3', () => { type T = Array extends Array ? 1 : 2 // 1 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.String())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array Varying 4', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Number()), Type.Array(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) // ---------------------------------------------- // Any // ---------------------------------------------- it('Should extend Any', () => { type T = Array extends any ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = Array extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = Array extends string ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = Array extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = Array extends number ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = Array extends number ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 1', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array 2', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array 3', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Tuple', () => { type T = Array extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = Array extends object ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = Array extends {} ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 3', () => { type T = Array extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 4', () => { type T = Array extends { length: '1' } ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({ length: Type.Literal('1') })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 5', () => { type T = Array extends { length: number } ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Object({ length: Type.Number() })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 1', () => { type T = Array extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = Array extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = Array extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 4', () => { type T = Array extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 5', () => { type T = Array extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Array(Type.String())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = Array extends null ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = Array extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.Any()), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) // ---------------------------------------------- // Constrained // ---------------------------------------------- it('Should extend constrained Any', () => { type T = Array extends any ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Unknown', () => { type T = Array extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained String', () => { type T = Array extends string ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Boolean', () => { type T = Array extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Number', () => { type T = Array extends number ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Integer', () => { type T = Array extends number ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Array 1', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Array 2', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Array 3', () => { type T = Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Tuple', () => { type T = Array extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Object 1', () => { type T = Array extends object ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Object 2', () => { type T = Array extends {} ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Object 3', () => { type T = Array extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Object 4', () => { type T = Array extends { length: '1' } ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({ length: Type.Literal('1') })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Object 5', () => { type T = Array extends { length: number } ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Object({ length: Type.Number() })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Union 1', () => { type T = Array extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Null(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Union 2', () => { type T = Array extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Union 3', () => { type T = Array extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Union 4', () => { type T = Array extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Union 5', () => { type T = Array extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.String())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Null', () => { type T = Array extends null ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Undefined', () => { type T = Array extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Void', () => { type T = Array extends void ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = Array extends Date ? 1 : 2 const R = ExtendsCheck(Type.Array(Type.String()), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/async-iterator.ts000066400000000000000000000070141505437577000266730ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/AsyncIterator', () => { // ---------------------------------------------- // Generic Varying // ---------------------------------------------- it('Should extend AsyncIterator 1', () => { type T = AsyncIterableIterator extends AsyncIterableIterator ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.Any()), Type.AsyncIterator(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend AsyncIterator 2', () => { type T = AsyncIterableIterator extends AsyncIterableIterator ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.String()), Type.AsyncIterator(Type.String())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend AsyncIterator 3', () => { type T = AsyncIterableIterator<'hello'> extends AsyncIterableIterator ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.Literal('hello')), Type.AsyncIterator(Type.String())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend AsyncIterator 4', () => { type T = AsyncIterableIterator extends AsyncIterableIterator<'hello'> ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.String()), Type.AsyncIterator(Type.Literal('hello'))) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend AsyncIterator 5', () => { type T = AsyncIterableIterator extends AsyncIterableIterator<'hello' | number> ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.String()), Type.AsyncIterator(Type.Union([Type.Literal('hello'), Type.Number()]))) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend AsyncIterator 6', () => { type T = AsyncIterableIterator<'hello' | number> extends AsyncIterableIterator ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.Union([Type.Literal('hello'), Type.Number()])), Type.AsyncIterator(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) // -------------------------------------------------------------------- // Structural // -------------------------------------------------------------------- it('Should extends Any 1', () => { type T = AsyncIterableIterator extends any ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.Number()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extends Any 2', () => { type T = any extends AsyncIterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.AsyncIterator(Type.Number())) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extends Unknown 1', () => { type T = AsyncIterableIterator extends unknown ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.Number()), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extends Unknown 2', () => { type T = unknown extends AsyncIterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.AsyncIterator(Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extends Never 1', () => { type T = AsyncIterableIterator extends never ? 1 : 2 const R = ExtendsCheck(Type.AsyncIterator(Type.Number()), Type.Never()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extends Never 2', () => { type T = never extends AsyncIterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Never(), Type.AsyncIterator(Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/bigint.ts000066400000000000000000000075351505437577000252130ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/BigInt', () => { it('Should extend Any', () => { type T = bigint extends any ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = bigint extends unknown ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = bigint extends string ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = bigint extends boolean ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = bigint extends number ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = bigint extends number ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = bigint extends Array ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = bigint extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = bigint extends Record ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = bigint extends {} ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = bigint extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Object({ a: Type.Literal(10) })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = bigint extends number | string ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = bigint extends any | number ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = bigint extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 4', () => { type T = bigint extends boolean | bigint ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Union([Type.Boolean(), Type.BigInt()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = bigint extends null ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = bigint extends undefined ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = bigint extends undefined ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = bigint extends Date ? 1 : 2 const R = ExtendsCheck(Type.BigInt(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/boolean.ts000066400000000000000000000070351505437577000253510ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Boolean', () => { it('Should extend Any', () => { type T = boolean extends any ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = boolean extends string ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = boolean extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Number', () => { type T = boolean extends number ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = boolean extends number ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = boolean extends Array ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = boolean extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = boolean extends Record ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = boolean extends {} ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = boolean extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = boolean extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = boolean extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = boolean extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = boolean extends null ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = boolean extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = boolean extends void ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = boolean extends Date ? 1 : 2 const R = ExtendsCheck(Type.Boolean(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/constructor.ts000066400000000000000000000246141505437577000263210ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Constructor', () => { it('Should extend Function', () => { type T = (new () => number) extends () => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Function([], Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Constructor 1', () => { type T = (new () => number) extends new () => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Constructor([], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 2', () => { type T = (new () => any) extends new () => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 3', () => { type T = (new () => number) extends new () => any ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 4', () => { type T = (new (a: number) => number) extends new () => any ? 1 : 2 const R = ExtendsCheck(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([], Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Constructor 5', () => { type T = (new (a: number | string) => number) extends new (a: number) => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([Type.Union([Type.Number(), Type.String()])], Type.Number()), Type.Constructor([Type.Number()], Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 6', () => { type T = (new (a: number) => number) extends new (a: number | string) => any ? 1 : 2 const R = ExtendsCheck(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([Type.Union([Type.Number(), Type.String()])], Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Constructor 7', () => { type T = (new (a: number, b: number) => number) extends new (a: number) => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([Type.Number(), Type.Number()], Type.Number()), Type.Constructor([Type.Number()], Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Constructor 8', () => { type T = (new (a: number) => number) extends new (a: number, b: number) => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([Type.Number(), Type.Number()], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 9', () => { type T = (new () => number) extends new () => any ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Constructor([], Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 9', () => { type T = (new () => any) extends new () => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 10', () => { type T = (new () => Array) extends new () => object ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Array(Type.Any())), Type.Constructor([], Type.Object({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 11', () => { type T = (new () => Array) extends new () => object ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Array(Type.String())), Type.Constructor([], Type.Object({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 12', () => { type T = (new () => object) extends new () => Array ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Object({})), Type.Constructor([], Type.Array(Type.Any()))) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Constructor 13', () => { type T = (new (a: unknown) => number) extends new (a: any) => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([Type.Unknown()], Type.Number({})), Type.Constructor([Type.Any()], Type.Number({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 14', () => { type T = (new (a: any) => number) extends new (a: unknown) => number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([Type.Any()], Type.Number({})), Type.Constructor([Type.Unknown()], Type.Number({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 15', () => { type T = (new () => any) extends new () => unknown ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Any({})), Type.Constructor([], Type.Unknown({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Constructor 16', () => { type T = (new () => unknown) extends new () => any ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Unknown({})), Type.Constructor([], Type.Any({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Any', () => { type T = (new () => number) extends any ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = (new () => number) extends string ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = (new () => number) extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = (new () => number) extends number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = (new () => number) extends number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 1', () => { type T = (new () => number) extends Array ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 2', () => { type T = (new () => number) extends Array ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 3', () => { type T = (new () => number) extends Array ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = (new () => number) extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = (() => number) extends Record ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = (new () => number) extends object ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = (new () => number) extends {} ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 3', () => { type T = (new () => number) extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 4', () => { type T = (new () => number) extends { length: '1' } ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Object({ length: Type.Literal('1') })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = (new () => number) extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Null(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = (new () => number) extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = (new () => number) extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 4', () => { type T = (new () => number) extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 5', () => { type T = (new () => number) extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.String())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = (new () => number) extends null ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = (new () => number) extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = (new () => number) extends void ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = (new () => number) extends Date ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/date.ts000066400000000000000000000071141505437577000246450ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Date', () => { it('Should extend Any', () => { type T = Date extends any ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = Date extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = Date extends string ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = Date extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = Date extends number ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = Date extends number ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = Date extends Array ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = Date extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = Date extends Record ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = Date extends {} ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = Date extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = Date extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = Date extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = Date extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null', () => { type T = Date extends null ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = Date extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = Date extends void ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = Date extends Date ? 1 : 2 const R = ExtendsCheck(Type.Date(), Type.Date()) Assert.IsEqual(R, ExtendsResult.True) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/function.ts000066400000000000000000000237651505437577000255670ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Function', () => { it('Should extend Constructor 1', () => { type T = (() => number) extends new () => number ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Constructor([], Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Function 1', () => { type T = (() => number) extends () => number ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Function([], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 2', () => { type T = (() => any) extends () => number ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Any()), Type.Function([], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 3', () => { type T = (() => number) extends () => any ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Any()), Type.Function([], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 4', () => { type T = ((a: number) => number) extends () => any ? 1 : 2 const R = ExtendsCheck(Type.Function([Type.Number()], Type.Number()), Type.Function([], Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Function 5', () => { type T = ((a: number | string) => number) extends (a: number) => number ? 1 : 2 const R = ExtendsCheck(Type.Function([Type.Union([Type.Number(), Type.String()])], Type.Number()), Type.Function([Type.Number()], Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 6', () => { type T = ((a: number) => number) extends (a: number | string) => any ? 1 : 2 const R = ExtendsCheck(Type.Function([Type.Number()], Type.Number()), Type.Function([Type.Union([Type.Number(), Type.String()])], Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Function 7', () => { type T = ((a: number, b: number) => number) extends (a: number) => number ? 1 : 2 const R = ExtendsCheck(Type.Function([Type.Number(), Type.Number()], Type.Number()), Type.Function([Type.Number()], Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Function 8', () => { type T = ((a: number) => number) extends (a: number, b: number) => number ? 1 : 2 const R = ExtendsCheck(Type.Function([Type.Number()], Type.Number()), Type.Function([Type.Number(), Type.Number()], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 9', () => { type T = (() => number) extends () => any ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Function([], Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 9', () => { type T = (() => any) extends () => number ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Any()), Type.Function([], Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 10', () => { type T = (() => Array) extends () => object ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Array(Type.Any())), Type.Function([], Type.Object({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 11', () => { type T = (() => Array) extends () => object ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Array(Type.String())), Type.Function([], Type.Object({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 12', () => { type T = (() => object) extends () => Array ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Object({})), Type.Function([], Type.Array(Type.Any()))) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Function 13', () => { type T = ((a: unknown) => number) extends (a: any) => number ? 1 : 2 const R = ExtendsCheck(Type.Function([Type.Unknown()], Type.Number({})), Type.Function([Type.Any()], Type.Number({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 14', () => { type T = ((a: any) => number) extends (a: unknown) => number ? 1 : 2 const R = ExtendsCheck(Type.Function([Type.Any()], Type.Number({})), Type.Function([Type.Unknown()], Type.Number({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 15', () => { type T = (() => any) extends () => unknown ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Any({})), Type.Function([], Type.Unknown({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Function 16', () => { type T = (() => unknown) extends () => any ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Unknown({})), Type.Function([], Type.Any({}))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Any', () => { type T = (() => number) extends any ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = (() => number) extends string ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = (() => number) extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = (() => number) extends number ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = (() => number) extends number ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 1', () => { type T = (() => number) extends Array ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 2', () => { type T = (() => number) extends Array ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 3', () => { type T = (() => number) extends Array ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = (() => number) extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = (() => number) extends Record ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = (() => number) extends object ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = (() => number) extends {} ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 3', () => { type T = (() => number) extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 4', () => { type T = (() => number) extends { length: '1' } ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({ length: Type.Literal('1') })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 5', () => { type T = (() => number) extends { length: number } ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Object({ length: Type.Number() })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 1', () => { type T = (() => number) extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Null(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = (() => number) extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = (() => number) extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 4', () => { type T = (() => number) extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 5', () => { type T = (() => number) extends any | Array ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.String())])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = (() => number) extends null ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = (() => number) extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Function([], Type.Number()), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = (() => number) extends Date ? 1 : 2 const R = ExtendsCheck(Type.Constructor([], Type.Number()), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/index.ts000066400000000000000000000007761505437577000250460ustar00rootroot00000000000000import './any' import './array' import './async-iterator' import './bigint' import './boolean' import './constructor' import './date' import './function' import './integer' import './iterator' import './literal' import './not' import './null' import './number' import './object' import './promise' import './record' import './regexp' import './string' import './symbol' import './template-literal' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/integer.ts000066400000000000000000000072121505437577000253640ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Integer', () => { it('Should extend Any', () => { type T = number extends any ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = number extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = number extends string ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = number extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = number extends number ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Number()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Integer', () => { type T = number extends number ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array', () => { type T = number extends Array ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = number extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = number extends Record ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = number extends {} ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = number extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Object({ a: Type.Literal(10) })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = number extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = number extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = number extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = number extends null ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = number extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = number extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Integer(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = number extends Date ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/iterator.ts000066400000000000000000000064651505437577000255710ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Iterator', () => { // ---------------------------------------------- // Generic Varying // ---------------------------------------------- it('Should extend Iterator 1', () => { type T = IterableIterator extends IterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.Any()), Type.Iterator(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Iterator 2', () => { type T = IterableIterator extends IterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.String()), Type.Iterator(Type.String())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Iterator 3', () => { type T = IterableIterator<'hello'> extends IterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.Literal('hello')), Type.Iterator(Type.String())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Iterator 4', () => { type T = IterableIterator extends IterableIterator<'hello'> ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.String()), Type.Iterator(Type.Literal('hello'))) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Iterator 5', () => { type T = IterableIterator extends IterableIterator<'hello' | number> ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.String()), Type.Iterator(Type.Union([Type.Literal('hello'), Type.Number()]))) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Iterator 6', () => { type T = IterableIterator<'hello' | number> extends IterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.Union([Type.Literal('hello'), Type.Number()])), Type.Iterator(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) // -------------------------------------------------------------------- // Structural // -------------------------------------------------------------------- it('Should extends Any 1', () => { type T = IterableIterator extends any ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.Number()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extends Any 2', () => { type T = any extends IterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Iterator(Type.Number())) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extends Unknown 1', () => { type T = IterableIterator extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.Number()), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extends Unknown 2', () => { type T = unknown extends IterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Iterator(Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extends Never 1', () => { type T = IterableIterator extends never ? 1 : 2 const R = ExtendsCheck(Type.Iterator(Type.Number()), Type.Never()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extends Never 2', () => { type T = never extends IterableIterator ? 1 : 2 const R = ExtendsCheck(Type.Never(), Type.Iterator(Type.Number())) Assert.IsEqual(R, ExtendsResult.True) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/literal.ts000066400000000000000000000261531505437577000253700ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Literal', () => { // ------------------------------------------------------------------- // String Literal // ------------------------------------------------------------------- it('Should extend Any (String)', () => { type T = 'hello' extends any ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown (String)', () => { type T = 'hello' extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String (String)', () => { type T = 'hello' extends string ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.String()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Boolean (String)', () => { type T = 'hello' extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number (String)', () => { type T = 'hello' extends number ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer (String)', () => { type T = 'hello' extends number ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array (String)', () => { type T = 'hello' extends Array ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple (String)', () => { type T = 'hello' extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1 (String)', () => { type T = 'hello' extends {} ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2 (String)', () => { type T = 'hello' extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1 (String)', () => { type T = 'hello' extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2 (String)', () => { type T = 'hello' extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3 (String)', () => { type T = 'hello' extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null (String)', () => { type T = 'hello' extends null ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined (String)', () => { type T = 'hello' extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) // ------------------------------------------------------------------- // Number Literal // ------------------------------------------------------------------- it('Should extend Any (Number)', () => { type T = 10 extends any ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown (Number)', () => { type T = 10 extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String (Number)', () => { type T = 10 extends string ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean (Number)', () => { type T = 10 extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number (Number)', () => { type T = 10 extends number ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Number()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Integer (Number)', () => { type T = 10 extends number ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Integer()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array (Number)', () => { type T = 10 extends Array ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple (Number)', () => { type T = 10 extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1 (Number)', () => { type T = 10 extends {} ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2 (Number)', () => { type T = 10 extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1 (Number)', () => { type T = 10 extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2 (Number)', () => { type T = 10 extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3 (Number)', () => { type T = 10 extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null (Number)', () => { type T = 10 extends null ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined (Number)', () => { type T = 10 extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) // ------------------------------------------------------------------- // Boolean Literal // ------------------------------------------------------------------- it('Should extend Any (Boolean)', () => { type T = true extends any ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown (Boolean)', () => { type T = true extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String (Boolean)', () => { type T = true extends string ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean (Boolean)', () => { type T = true extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Number (Boolean)', () => { type T = true extends number ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer (Boolean)', () => { type T = true extends number ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array (Boolean)', () => { type T = true extends Array ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple (Boolean)', () => { type T = true extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 1', () => { type T = 'hello' extends Record ? 1 : 2 const R = ExtendsCheck(Type.Literal('hello'), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 2', () => { type T = 10 extends Record ? 1 : 2 const R = ExtendsCheck(Type.Literal(10), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 3', () => { type T = true extends Record ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1 (Boolean)', () => { type T = true extends {} ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2 (Boolean)', () => { type T = true extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1 (Boolean)', () => { type T = true extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2 (Boolean)', () => { type T = true extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3 (Boolean)', () => { type T = true extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null (Boolean)', () => { type T = true extends null ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined (Boolean)', () => { type T = true extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = true extends void ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = true extends Date ? 1 : 2 const R = ExtendsCheck(Type.Literal(true), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/not.ts000066400000000000000000000140551505437577000245320ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' // --------------------------------------------------------------------------- // Note: Not is equivalent to Unknown with the exception of nested negation. // --------------------------------------------------------------------------- describe('type/extends/Not', () => { // ------------------------------------------------------------------------- // Issue: type T = number extends not number ? true : false // true // type T = number extends unknown ? true : false // true // // TypeScript does not support type negation. The best TypeBox can do is // treat "not" as "unknown". From this standpoint, the extends assignability // check needs to return true for the following case to keep TypeBox aligned // with TypeScript static inference. // ------------------------------------------------------------------------- it('Should extend with unknown assignability check', () => { const A = Type.Number() const B = Type.Not(Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) // we would expect false }) // --------------------------------------------------------------------------- // Nested // --------------------------------------------------------------------------- it('Should extend with nested negation', () => { const T1 = Type.String() const T2 = Type.Not(T1) const T3 = Type.Not(T2) const T4 = Type.Not(T3) const T5 = Type.Not(T4) const R1 = ExtendsCheck(T1, Type.String()) const R2 = ExtendsCheck(T2, Type.String()) const R3 = ExtendsCheck(T3, Type.String()) const R4 = ExtendsCheck(T4, Type.String()) const R5 = ExtendsCheck(T5, Type.String()) Assert.IsEqual(R1, ExtendsResult.True) Assert.IsEqual(R2, ExtendsResult.False) Assert.IsEqual(R3, ExtendsResult.True) Assert.IsEqual(R4, ExtendsResult.False) Assert.IsEqual(R5, ExtendsResult.True) }) // --------------------------------------------------------------------------- // Not as Unknown Tests // --------------------------------------------------------------------------- it('Should extend Any', () => { type T = unknown extends any ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = unknown extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = unknown extends string ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = unknown extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = unknown extends number ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = unknown extends number ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 1', () => { type T = unknown extends Array ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 2', () => { type T = unknown extends Array ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Array(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = unknown extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = unknown extends {} ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 2', () => { type T = unknown extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = unknown extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = unknown extends any | number ? 1 : 2 // 1 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Union([Type.Any(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = unknown extends unknown | number ? 1 : 2 // 1 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Union([Type.Unknown(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 4', () => { type T = unknown extends unknown | any ? 1 : 2 // 1 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Union([Type.Unknown(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = unknown extends null ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = unknown extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = unknown extends void ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = unknown extends Date ? 1 : 2 const R = ExtendsCheck(Type.Not(Type.Number()), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/null.ts000066400000000000000000000074471505437577000247130ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Null', () => { it('Should extend Any', () => { type T = null extends any ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = null extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = null extends string ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = null extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = null extends number ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = null extends number ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = null extends Array ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = null extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = null extends Record ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = null extends {} ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 2', () => { type T = null extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 3', () => { type T = null extends object ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = null extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = null extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = null extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null', () => { type T = null extends null ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Null()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Undefined', () => { type T = null extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = null extends void ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = null extends Date ? 1 : 2 const R = ExtendsCheck(Type.Null(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/number.ts000066400000000000000000000072641505437577000252260ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Number', () => { it('Should extend Any', () => { type T = number extends any ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = number extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = number extends string ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = number extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = number extends number ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Number()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Integer', () => { type T = number extends number ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array', () => { type T = number extends Array ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = number extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = number extends Record ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = number extends {} ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = number extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = number extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = number extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = number extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = number extends null ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = number extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = number extends void ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = number extends Date ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/object.ts000066400000000000000000000222301505437577000251720ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Object', () => { // ---------------------------------------------------------- // Object // ---------------------------------------------------------- it('Should extend Object 1', () => { type T = { x: number; y: number } extends { x: number } ? 1 : 2 const A = Type.Object({ x: Type.Number(), y: Type.Number() }) const B = Type.Object({ x: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = { x: number } extends { x: number; y: number } ? 1 : 2 const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ x: Type.Number(), y: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 3', () => { type T = { x: number; y: string } extends { x: number } ? 1 : 2 const A = Type.Object({ x: Type.Number(), y: Type.String() }) const B = Type.Object({ x: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 4', () => { type T = { x: number } extends { x: number; y: string } ? 1 : 2 const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ x: Type.Number(), y: Type.String() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 5', () => { type T = { x: number | string } extends { x: number } ? 1 : 2 const A = Type.Object({ x: Type.Union([Type.Number(), Type.String()]) }) const B = Type.Object({ x: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 6', () => { type T = { x: number } extends { x: number | string } ? 1 : 2 const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ x: Type.Union([Type.Number(), Type.String()]) }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) // ---------------------------------------------------------- // Record // ---------------------------------------------------------- it('Should extend Record 2', () => { type T = { a: number; b: number } extends Record ? 1 : 2 const A = Type.Object({ a: Type.Number(), b: Type.Number() }) const B = Type.Record(Type.String(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 3', () => { type T = { a: number; b: number } extends Record ? 1 : 2 const A = Type.Object({ a: Type.Number(), b: Type.Number() }) const B = Type.Record(Type.Number(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 4', () => { type T = { a: number; b: number } extends Record<'a' | 'b', number> ? 1 : 2 const A = Type.Object({ a: Type.Number(), b: Type.Number() }) const B = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 5', () => { type T = { a: number; b: number } extends Record<'a' | 'b', number> ? 1 : 2 const A = Type.Object({ a: Type.Number(), b: Type.Number() }) const B = Type.Record(Type.String(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 6', () => { type T = { a: number; b: number } extends Record<'a' | 'b', number> ? 1 : 2 const A = Type.Object({ a: Type.Number(), b: Type.Number() }) const B = Type.Record(Type.Number(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) // ---------------------------------------------------------- // Standard // ---------------------------------------------------------- it('Should extend Any', () => { type T = { a: number } extends any ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = { a: number } extends string ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = { a: number } extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = { a: number } extends number ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = { a: number } extends number ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = { a: number } extends Array ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = { a: number } extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = { a: number } extends {} ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = { a: number } extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Object({ a: Type.Literal(10) })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 3', () => { type T = { a: number } extends object ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 1', () => { type T = { a: number } extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Union([Type.Null(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = { a: number } extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = { a: number } extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null', () => { type T = { a: number } extends null ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = { a: number } extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = { a: number } extends void ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = { a: number } extends Date ? 1 : 2 const R = ExtendsCheck(Type.Object({ a: Type.Number() }), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) // ---------------------------------------------------------------- // Optional // ---------------------------------------------------------------- it('Should extend optional 1', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.Optional(Type.Number()) }) const C = ExtendsCheck(A, B) Assert.IsEqual(C, ExtendsResult.True) }) it('Should extend optional 2', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.Optional(Type.Number()) }) const C = ExtendsCheck(B, A) Assert.IsEqual(C, ExtendsResult.False) }) it('Should extend optional 3', () => { const A = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Number(), }) const B = Type.Object({ y: Type.Number(), z: Type.Number(), }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend optional 4', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), }) const B = Type.Object({ y: Type.Number(), z: Type.Number(), }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend optional 5', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), }) const B = Type.Object({ y: Type.Number(), z: Type.Optional(Type.Number()), }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/promise.ts000066400000000000000000000222331505437577000254050ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Promise', () => { // ---------------------------------------------- // Generic Varying // ---------------------------------------------- it('Should extend Promise Varying 1', () => { type T = Promise extends Promise ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Promise(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Promise Varying 2', () => { type T = Promise extends Promise ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.String()), Type.Promise(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Promise Varying 3', () => { type T = Promise extends Promise ? 1 : 2 // 1 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Promise(Type.String())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Promise Varying 4', () => { type T = Promise extends Promise ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Promise(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) // ---------------------------------------------- // Any // ---------------------------------------------- it('Should extend Any', () => { type T = Promise extends any ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = Promise extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = Promise extends string ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = Promise extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = Promise extends number ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = Promise extends number ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = Promise extends Array ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = Promise extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = Promise extends Record ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = Promise extends {} ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = Promise extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 3', () => { type T = Promise extends object ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 1', () => { type T = Promise extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = Promise extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = Promise extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null', () => { type T = Promise extends null ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = Promise extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) // ---------------------------------------------- // Constrained // ---------------------------------------------- it('Should extend constrained Any', () => { type T = Promise extends any ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Unknown', () => { type T = Promise extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained String', () => { type T = Promise extends string ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Boolean', () => { type T = Promise extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Number', () => { type T = Promise extends number ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Any()), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Integer', () => { type T = Promise extends number ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Array', () => { type T = Promise extends Array ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Tuple', () => { type T = Promise extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Object 1', () => { type T = Promise extends {} ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Object 2', () => { type T = Promise extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Object 3', () => { type T = Promise extends object ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Union 1', () => { type T = Promise extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Union 2', () => { type T = Promise extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend constrained Union 2', () => { type T = Promise extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Null', () => { type T = Promise extends null ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend constrained Undefined', () => { type T = Promise extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = Promise extends void ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = Promise extends Date ? 1 : 2 const R = ExtendsCheck(Type.Promise(Type.Number()), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/record.ts000066400000000000000000000221151505437577000252040ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Record', () => { it('Should extend Record 1', () => { type T = Record<'a' | 'b', number> extends { a: number; b: number } ? 1 : 2 const A = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number()) const B = Type.Object({ a: Type.Number(), b: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 2', () => { type T = Record extends { a: number; b: number } ? 1 : 2 const A = Type.Record(Type.String(), Type.Number()) const B = Type.Object({ a: Type.Number(), b: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 3', () => { type T = Record extends { a: number; b: number } ? 1 : 2 const A = Type.Record(Type.Number(), Type.Number()) const B = Type.Object({ a: Type.Number(), b: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 4', () => { type T = Record<'a' | 'b', number> extends { a: number; b: number } ? 1 : 2 const A = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number()) const B = Type.Object({ a: Type.Number(), b: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 5', () => { type T = Record<'a' | 'b', number> extends { a: number; b: number } ? 1 : 2 const A = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number()) const B = Type.Object({ a: Type.Number(), b: Type.Number() }) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 6', () => { type T = Record extends Record<'a' | 'b', number> ? true : false const A = Type.Record(Type.String(), Type.Number()) const B = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 7', () => { type T = Record extends Record ? 1 : 2 const A = Type.Record(Type.String(), Type.Number()) const B = Type.Record(Type.String(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 8', () => { type T = Record extends Record ? 1 : 2 const A = Type.Record(Type.String(), Type.Number()) const B = Type.Record(Type.Number(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 9', () => { type T = Record extends Record<'a' | 'b', number> ? 1 : 2 const A = Type.Record(Type.Number(), Type.Number()) const B = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 10', () => { type T = Record extends Record ? 1 : 2 const A = Type.Record(Type.Number(), Type.Number()) const B = Type.Record(Type.String(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 11', () => { type T = Record extends Record ? 1 : 2 const A = Type.Record(Type.Number(), Type.Number()) const B = Type.Record(Type.Number(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) // ----- it('Should extend Record 12', () => { type T = Record extends Record ? 1 : 2 const A = Type.Record(Type.String(), Type.Number()) const B = Type.Record(Type.Integer(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 13', () => { type T = Record extends Record<'a' | 'b', number> ? 1 : 2 const A = Type.Record(Type.Integer(), Type.Number()) const B = Type.Record(Type.Union([Type.Literal('a'), Type.Literal('b')]), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 14', () => { type T = Record extends Record ? 1 : 2 const A = Type.Record(Type.Integer(), Type.Number()) const B = Type.Record(Type.String(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 15', () => { type T = Record extends Record ? 1 : 2 const A = Type.Record(Type.Integer(), Type.Number()) const B = Type.Record(Type.Integer(), Type.Number()) const R = ExtendsCheck(A, B) Assert.IsEqual(R, ExtendsResult.True) }) // ------------------------------------------------------------------- // Standard // ------------------------------------------------------------------- it('Should extend Any', () => { type T = Record extends any ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = Record extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = Record extends string ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = Record extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = Record extends number ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = Record extends number ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 1', () => { type T = Record extends Array ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 2', () => { type T = Record extends Array ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Array(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = Record extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 2', () => { type T = Record extends {} ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 3', () => { type T = Record extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = Record extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = Record extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Union([Type.Any(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = Record extends null ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = Record extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = Record extends void ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = Record extends Date ? 1 : 2 const R = ExtendsCheck(Type.Record(Type.Number(), Type.Number()), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/regexp.ts000066400000000000000000000111621505437577000252200ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' // ------------------------------------------------------------------ // Note: RegExp infers as type String // ------------------------------------------------------------------ describe('type/extends/RegExp', () => { it('Should extend Any', () => { type T = string extends any ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = string extends unknown ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = string extends string ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.RegExp(/xyz/)) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Boolean', () => { type T = string extends boolean ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = string extends number ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = string extends number ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = string extends Array ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = string extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 1', () => { type T = string extends Record ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 2', () => { type T = string extends Record ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Record(Type.Number(), Type.Unknown())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 3', () => { type T = string extends Record ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Record(Type.Number(), Type.RegExp(/xyz/))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 4', () => { type T = string extends Record ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Record(Type.Number(), Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = string extends {} ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = string extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.RegExp(/xyz/), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = number extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Number(), Type.RegExp(/xyz/)])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = number extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = number extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = number extends null ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = number extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = number extends void ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = number extends Date ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/string.ts000066400000000000000000000105531505437577000252370ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/String', () => { it('Should extend Any', () => { type T = string extends any ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = string extends unknown ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = string extends string ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.String()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Boolean', () => { type T = string extends boolean ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = string extends number ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = string extends number ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = string extends Array ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = string extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 1', () => { type T = string extends Record ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 2', () => { type T = string extends Record ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Unknown())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 3', () => { type T = string extends Record ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.String())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 4', () => { type T = string extends Record ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = string extends {} ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = string extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = number extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = number extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = number extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = number extends null ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = number extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = number extends void ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = number extends Date ? 1 : 2 const R = ExtendsCheck(Type.Number(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/symbol.ts000066400000000000000000000100251505437577000252300ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Symbol', () => { it('Should extend Any', () => { type T = symbol extends any ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = symbol extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = symbol extends string ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = symbol extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = symbol extends number ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = symbol extends number ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = symbol extends Array ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = symbol extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = symbol extends Record ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = symbol extends {} ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = symbol extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Object({ a: Type.Literal(10) })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = symbol extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = symbol extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = symbol extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 4', () => { type T = symbol extends boolean | symbol ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Union([Type.Boolean(), Type.Symbol()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = symbol extends null ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = symbol extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = symbol extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = symbol extends Date ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Symbol', () => { type T = symbol extends symbol ? 1 : 2 const R = ExtendsCheck(Type.Symbol(), Type.Symbol()) Assert.IsEqual(R, ExtendsResult.True) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/template-literal.ts000066400000000000000000000206721505437577000272010ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/TemplateLiteral', () => { // ------------------------------------------------------------------- // String Literal 'hello' // ------------------------------------------------------------------- it('Should extend Any (hello)', () => { type T = 'hello' extends any ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown (hello)', () => { type T = 'hello' extends unknown ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String (hello)', () => { type T = 'hello' extends string ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.String()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Boolean (hello)', () => { type T = 'hello' extends boolean ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number (hello)', () => { type T = 'hello' extends number ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer (hello)', () => { type T = 'hello' extends number ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array (hello)', () => { type T = 'hello' extends Array ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple (hello)', () => { type T = 'hello' extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1 (hello)', () => { type T = 'hello' extends {} ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2 (hello)', () => { type T = 'hello' extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1 (hello)', () => { type T = 'hello' extends number | string ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2 (hello)', () => { type T = 'hello' extends any | number ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3 (hello)', () => { type T = 'hello' extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null (hello)', () => { type T = 'hello' extends null ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined (hello)', () => { type T = 'hello' extends undefined ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Literal('hello')]), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) // ------------------------------------------------------------------- // String Literal 'hello' | 'world' // ------------------------------------------------------------------- it('Should extend Any (hello | world)', () => { type T = 'hello' | 'world' extends any ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown (hello | world)', () => { type T = 'hello' | 'world' extends unknown ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String (hello | world)', () => { type T = 'hello' | 'world' extends string ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.String()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Boolean (hello | world)', () => { type T = 'hello' | 'world' extends boolean ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number (hello | world)', () => { type T = 'hello' | 'world' extends number ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer (hello | world)', () => { type T = 'hello' | 'world' extends number ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array (hello | world)', () => { type T = 'hello' | 'world' extends Array ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple (hello | world)', () => { type T = 'hello' | 'world' extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1 (hello | world)', () => { type T = 'hello' | 'world' extends {} ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2 (hello | world)', () => { type T = 'hello' | 'world' extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1 (hello | world)', () => { type T = 'hello' | 'world' extends number | string ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2 (hello | world)', () => { type T = 'hello' | 'world' extends any | number ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3 (hello | world)', () => { type T = 'hello' | 'world' extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null (hello | world)', () => { type T = 'hello' | 'world' extends null ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined (hello | world)', () => { type T = 'hello' | 'world' extends undefined ? 1 : 2 const R = ExtendsCheck(Type.TemplateLiteral([Type.Union([Type.Literal('hello'), Type.Literal('world')])]), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/tuple.ts000066400000000000000000000171351505437577000250650ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Tuple', () => { it('Should extend Any', () => { type T = [string, number] extends any ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = [string, number] extends string ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = [string, number] extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = [string, number] extends number ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = [string, number] extends number ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 1', () => { type T = [string, number] extends Array ? 1 : 2 // 1 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array 2', () => { type T = [string, number] extends Array ? 1 : 2 // 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 3', () => { type T = [string, number] extends Array ? 1 : 2 // 1 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Union([Type.String(), Type.Number()]))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Array 4', () => { type T = [string, number] extends Array ? 1 : 2 // 1 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Union([Type.String(), Type.Number(), Type.Boolean()]))) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Tuple 1', () => { type T = [string, number] extends [string, number] ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Tuple 2', () => { type T = [string, number] extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple 3', () => { type T = [string, any] extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Any()]), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple 4', () => { type T = [string, number] extends [string, any] ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Any()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Tuple 5', () => { type T = [string, unknown] extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Unknown()]), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple 6', () => { type T = [string, number] extends [string, unknown] ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Unknown()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Tuple 7', () => { type T = [] extends [string, number] ? 1 : 2 const R = ExtendsCheck(Type.Tuple([]), Type.Tuple([Type.String(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple 8', () => { type T = [string, number] extends [] ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record 1', () => { type T = [string, number] extends Record ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 2', () => { type T = [string, number] extends Record ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Unknown())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 3', () => { type T = [string, number] extends Record ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.String())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Record 4', () => { type T = [string, number] extends Record ? 1 : 2 const R = ExtendsCheck(Type.String(), Type.Record(Type.Number(), Type.Number())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = [string, number] extends {} ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = [string, number] extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 3', () => { type T = [string, number] extends object ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Object({})) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 1', () => { type T = [string, number] extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = [string, number] extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = [string, number] extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null', () => { type T = [string, number] extends null ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = [string, number] extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = [string, number] extends void ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = [string, number] extends Date ? 1 : 2 const R = ExtendsCheck(Type.Tuple([Type.String(), Type.Number()]), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/uint8array.ts000066400000000000000000000075131505437577000260410ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Uint8Array', () => { it('Should extend Any', () => { type T = Uint8Array extends any ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = Uint8Array extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = Uint8Array extends string ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = Uint8Array extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = Uint8Array extends number ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = Uint8Array extends number ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = Uint8Array extends Array ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = Uint8Array extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Record', () => { type T = Uint8Array extends Record ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Record(Type.Number(), Type.Any())) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 1', () => { type T = Uint8Array extends {} ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = Uint8Array extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = Uint8Array extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = Uint8Array extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = Uint8Array extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null', () => { type T = Uint8Array extends null ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = Uint8Array extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = Uint8Array extends void ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = Uint8Array extends Date ? 1 : 2 const R = ExtendsCheck(Type.Uint8Array(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/undefined.ts000066400000000000000000000071031505437577000256670ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Undefined', () => { it('Should extend Any', () => { type T = undefined extends any ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = undefined extends string ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = undefined extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = undefined extends number ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = undefined extends number ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = undefined extends Array ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = undefined extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = undefined extends {} ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 2', () => { type T = undefined extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 3', () => { type T = undefined extends object ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = undefined extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = undefined extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = undefined extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null', () => { type T = undefined extends null ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = undefined extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Void', () => { type T = undefined extends void ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Void()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Date', () => { type T = undefined extends Date ? 1 : 2 const R = ExtendsCheck(Type.Undefined(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/union.ts000066400000000000000000000142671505437577000250670ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Union', () => { it('Should extend Any', () => { type T = number | string extends any ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = number | string extends string ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = number | string extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = number | string extends number ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = number | string extends number ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array', () => { type T = number | string extends Array ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = number | string extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = number | string extends {} ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Object({}, { additionalProperties: false })) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Object 2', () => { type T = number | string extends { a: 10 } ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = number | string extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 2', () => { type T = number | string extends any | number ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Any(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = number | string extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 4', () => { type T = any | boolean extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Union 5', () => { type T = any | string extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Union 6', () => { type T = any | {} extends {} ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Union 7', () => { type T = any extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Any(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.Union) }) it('Should extend Union 8', () => { type T = unknown | string extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Unknown(), Type.String()]), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 9', () => { type T = unknown extends boolean | number ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Boolean(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Null', () => { type T = number | string extends null ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = number | string extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = number | string extends void ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void 2', () => { type T = number | string | void extends void ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = number | string | void extends Date ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Number(), Type.String()]), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date 2', () => { type T = Date | number | string | void extends Date ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Date(), Type.Number(), Type.String()]), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend BigInt', () => { type T = bigint | number | string | void extends Date ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.BigInt(), Type.Number(), Type.String()]), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Symbol', () => { type T = symbol | number | string | void extends Date ? 1 : 2 const R = ExtendsCheck(Type.Union([Type.Symbol(), Type.Number(), Type.String()]), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/unknown.ts000066400000000000000000000075741505437577000254410ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Unknown', () => { it('Should extend Any', () => { type T = unknown extends any ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = unknown extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = unknown extends string ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = unknown extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = unknown extends number ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = unknown extends number ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 1', () => { type T = unknown extends Array ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 2', () => { type T = unknown extends Array ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Array(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = unknown extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = unknown extends {} ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 2', () => { type T = unknown extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = unknown extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = unknown extends any | number ? 1 : 2 // 1 const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Any(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = unknown extends unknown | number ? 1 : 2 // 1 const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Unknown(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 4', () => { type T = unknown extends unknown | any ? 1 : 2 // 1 const R = ExtendsCheck(Type.Unknown(), Type.Union([Type.Unknown(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = unknown extends null ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = unknown extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = unknown extends void ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Void()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Date', () => { type T = unknown extends Date ? 1 : 2 const R = ExtendsCheck(Type.Unknown(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/extends/void.ts000066400000000000000000000076771505437577000247070ustar00rootroot00000000000000import { Type, ExtendsCheck, ExtendsResult } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/extends/Void', () => { it('Should extend Any', () => { type T = void extends any ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Any()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Unknown', () => { type T = void extends unknown ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Unknown()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend String', () => { type T = void extends string ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.String()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Boolean', () => { type T = void extends boolean ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Boolean()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Number', () => { type T = void extends number ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Number()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Integer', () => { type T = void extends number ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Integer()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 1', () => { type T = void extends Array ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Array(Type.Any())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Array 2', () => { type T = void extends Array ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Array(Type.String())) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Tuple', () => { type T = void extends [number, number] ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Tuple([Type.Number(), Type.Number()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 1', () => { type T = void extends object ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 2', () => { type T = void extends {} ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Object({})) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Object 3', () => { type T = void extends { a: number } ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Object({ a: Type.Number() })) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 1', () => { type T = void extends number | string ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Union([Type.Number(), Type.String()])) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Union 2', () => { type T = void extends any | number ? 1 : 2 // 1 const R = ExtendsCheck(Type.Void(), Type.Union([Type.Any(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 3', () => { type T = void extends unknown | number ? 1 : 2 // 1 const R = ExtendsCheck(Type.Void(), Type.Union([Type.Unknown(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Union 4', () => { type T = void extends unknown | any ? 1 : 2 // 1 const R = ExtendsCheck(Type.Void(), Type.Union([Type.Unknown(), Type.String()])) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Null', () => { type T = void extends null ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Null()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Undefined', () => { type T = void extends undefined ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Undefined()) Assert.IsEqual(R, ExtendsResult.False) }) it('Should extend Void', () => { type T = void extends void ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Void()) Assert.IsEqual(R, ExtendsResult.True) }) it('Should extend Date', () => { type T = void extends Date ? 1 : 2 const R = ExtendsCheck(Type.Void(), Type.Date()) Assert.IsEqual(R, ExtendsResult.False) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/000077500000000000000000000000001505437577000230055ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/index.ts000066400000000000000000000001031505437577000244560ustar00rootroot00000000000000import './type/index' import './kind/index' import './value/index' sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/000077500000000000000000000000001505437577000237325ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/any.ts000066400000000000000000000006011505437577000250660ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TAny', () => { it('Should guard for TAny', () => { const R = KindGuard.IsAny(Type.Any()) Assert.IsTrue(R) }) it('Should not guard for TAny', () => { const R = KindGuard.IsAny(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/argument.ts000066400000000000000000000006401505437577000261240ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TArgument', () => { it('Should guard for TArgument', () => { const R = KindGuard.IsArgument(Type.Argument(0)) Assert.IsTrue(R) }) it('Should not guard for TArgument', () => { const R = KindGuard.IsArgument(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/array.ts000066400000000000000000000006321505437577000254210ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TArray', () => { it('Should guard for TArray', () => { const R = KindGuard.IsArray(Type.Array(Type.Number())) Assert.IsTrue(R) }) it('Should not guard for TArray', () => { const R = KindGuard.IsArray(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/async-iterator.ts000066400000000000000000000007471505437577000272560ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TAsyncIterator', () => { it('Should guard for TAsyncIterator', () => { const T = Type.AsyncIterator(Type.Any()) const R = KindGuard.IsAsyncIterator(T) Assert.IsTrue(R) }) it('Should not guard for TAsyncIterator', () => { const T = null const R = KindGuard.IsAsyncIterator(T) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/awaited.ts000066400000000000000000000030701505437577000257200ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/Awaited', () => { it('Should guard for Awaited 1', () => { const T = Type.Awaited(Type.String()) const R = KindGuard.IsString(T) Assert.IsTrue(R) }) it('Should guard for Awaited 2', () => { const T = Type.Awaited(Type.Promise(Type.String())) const R = KindGuard.IsString(T) Assert.IsTrue(R) }) it('Should guard for Awaited 3', () => { const T = Type.Awaited(Type.Awaited(Type.Promise(Type.String()))) const R = KindGuard.IsString(T) Assert.IsTrue(R) }) it('Should guard for Awaited 4', () => { const T = Type.Awaited(Type.Union([Type.Promise(Type.Promise(Type.String()))])) Assert.IsTrue(KindGuard.IsString(T)) }) it('Should guard for Awaited 5', () => { const T = Type.Awaited(Type.Union([Type.Promise(Type.Promise(Type.String())), Type.Number()])) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsTrue(KindGuard.IsString(T.anyOf[0])) Assert.IsTrue(KindGuard.IsNumber(T.anyOf[1])) }) it('Should guard for Awaited 6', () => { const T = Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.String()))])) Assert.IsTrue(KindGuard.IsString(T)) }) it('Should guard for Awaited 7', () => { const T = Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.String())), Type.Number()])) Assert.IsTrue(KindGuard.IsIntersect(T)) Assert.IsTrue(KindGuard.IsString(T.allOf[0])) Assert.IsTrue(KindGuard.IsNumber(T.allOf[1])) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/bigint.ts000066400000000000000000000006231505437577000255570ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TBigInt', () => { it('Should guard for TBigInt', () => { const R = KindGuard.IsBigInt(Type.BigInt()) Assert.IsTrue(R) }) it('Should not guard for TBigInt', () => { const R = KindGuard.IsBigInt(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/boolean.ts000066400000000000000000000006311505437577000257210ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TBoolean', () => { it('Should guard for TBoolean', () => { const R = KindGuard.IsBoolean(Type.Boolean()) Assert.IsTrue(R) }) it('Should not guard for TBoolean', () => { const R = KindGuard.IsBoolean(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/capitalize.ts000066400000000000000000000025321505437577000264310ustar00rootroot00000000000000import { KindGuard, Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/Capitalize', () => { it('Should guard for Capitalize 1', () => { const T = Type.Capitalize(Type.Literal('hello'), { $id: 'hello', foo: 1 }) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'Hello') Assert.IsEqual(T.$id, 'hello') Assert.IsEqual(T.foo, 1) }) it('Should guard for Capitalize 2', () => { const T = Type.Capitalize(Type.Literal('hello')) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'Hello') }) it('Should guard for Capitalize 3', () => { const T = Type.Capitalize(Type.Union([Type.Literal('hello'), Type.Literal('world')])) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'Hello') Assert.IsEqual(T.anyOf[1].const, 'World') }) it('Should guard for Capitalize 4', () => { const T = Type.Capitalize(Type.TemplateLiteral('hello${0|1}')) Assert.IsTrue(KindGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$') }) it('Should guard for Capitalize 5', () => { const T = Type.Capitalize(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])])) Assert.IsTrue(KindGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/composite.ts000066400000000000000000000134031505437577000263050ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TComposite', () => { it('Should guard for distinct properties', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) Assert.IsTrue(KindGuard.IsNumber(T.properties.x)) Assert.IsTrue(KindGuard.IsNumber(T.properties.y)) }) it('Should guard for overlapping properties', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() })]) Assert.IsTrue(KindGuard.IsIntersect(T.properties.x)) // @ts-ignore Assert.IsTrue(KindGuard.IsNumber(T.properties.x.allOf[0])) // @ts-ignore Assert.IsTrue(KindGuard.IsNumber(T.properties.x.allOf[1])) }) it('Should not produce optional property if all properties are not optional', () => { const T = Type.Composite([Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() })]) Assert.IsFalse(KindGuard.IsOptional(T.properties.x)) }) // Note for: https://github.com/sinclairzx81/typebox/issues/419 // Determining if a composite property is optional requires a deep check for all properties gathered during a indexed access // call. Currently, there isn't a trivial way to perform this check without running into possibly infinite instantiation issues. // The optional check is only specific to overlapping properties. Singular properties will continue to work as expected. The // rule is "if all composite properties for a key are optional, then the composite property is optional". Defer this test and // document as minor breaking change. // it('Should produce optional property if all composited properties are optional', () => { // prettier-ignore const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Optional(Type.Number()) }) ]) Assert.IsTrue(KindGuard.IsOptional(T.properties.x)) Assert.IsEqual(T.required, undefined) }) // prettier-ignore it('Should produce required property if some composited properties are not optional', () => { const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() }) ]) Assert.IsFalse(KindGuard.IsOptional(T.properties.x)) Assert.IsTrue(T.required!.includes('x')) }) // prettier-ignore it('Should preserve single optional property', () => { const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.Number()) }), ]) Assert.IsTrue(KindGuard.IsOptional(T.properties.x)) Assert.IsEqual(T.required, undefined) }) // ---------------------------------------------------------------- // Intersect // ---------------------------------------------------------------- // prettier-ignore it('Should composite Intersect 1', () => { const T = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }), ]), Type.Intersect([ Type.Object({ z: Type.Number() }), ]) ]) Assert.IsEqual(T, Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() })) }) // prettier-ignore it('Should composite Intersect 2', () => { const T = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() }), ]), Type.Intersect([ Type.Object({ x: Type.Number() }), ]) ]) Assert.IsEqual(T, Type.Object({ x: Type.Intersect([Type.Intersect([Type.Number(), Type.Number()]), Type.Number()]) })) }) // prettier-ignore it('Should composite Intersect 3', () => { const T = Type.Composite([ Type.Number(), Type.Boolean() ]) Assert.IsEqual(T, Type.Object({})) }) // prettier-ignore it('Should composite Intersect 4', () => { const T = Type.Composite([ Type.Number(), Type.Boolean(), Type.Object({ x: Type.String() }) ]) Assert.IsEqual(T, Type.Object({ x: Type.String() })) }) // prettier-ignore it('Should composite Intersect 5', () => { const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.String()) }), Type.Object({ x: Type.String() }) ]) Assert.IsEqual(T, Type.Object({ x: Type.Intersect([Type.String(), Type.String()]) })) }) // prettier-ignore it('Should composite Intersect 6', () => { const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.String()) }), Type.Object({ x: Type.Optional(Type.String()) }) ]) Assert.IsEqual(T, Type.Object({ x: Type.Optional(Type.Intersect([Type.String(), Type.String()])) })) }) // ---------------------------------------------------------------- // Union // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/789 // prettier-ignore it('Should composite Union 1 (non-overlapping)', () => { const T = Type.Composite([ Type.Union([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }), ]), Type.Union([ Type.Object({ z: Type.Number() }), ]) ]) Assert.IsEqual(T, Type.Object({ z: Type.Number() })) }) // https://github.com/sinclairzx81/typebox/issues/789 // prettier-ignore it('Should composite Union 2 (overlapping)', () => { const T = Type.Composite([ Type.Union([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() }), ]), Type.Union([ Type.Object({ x: Type.Number() }), ]) ]) Assert.IsEqual(T, Type.Object({ x: Type.Intersect([Type.Union([Type.Number(), Type.Number()]), Type.Number()]) })) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/computed.ts000066400000000000000000000023331505437577000261230ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TComputed', () => { // ---------------------------------------------------------------- // Schema // ---------------------------------------------------------------- it('Should guard for Schema', () => { const T = Type.Partial(Type.Ref('A')) Assert.IsTrue(KindGuard.IsComputed(T)) Assert.IsTrue(KindGuard.IsSchema(T)) }) // ---------------------------------------------------------------- // Record // ---------------------------------------------------------------- it('Should guard for Record 1', () => { const T = Type.Record(Type.String(), Type.String()) Assert.IsTrue(KindGuard.IsRecord(T)) }) it('Should guard for Record 3', () => { const T = Type.Record(Type.String(), Type.Ref('A')) Assert.IsTrue(KindGuard.IsRecord(T)) }) it('Should guard for Record 3', () => { const T = Type.Record(Type.String(), Type.Partial(Type.Ref('A'))) Assert.IsTrue(KindGuard.IsRecord(T)) }) it('Should guard for Record 4', () => { const T = Type.Record(Type.Ref('A'), Type.String()) Assert.IsTrue(KindGuard.IsNever(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/const.ts000066400000000000000000000107031505437577000254310ustar00rootroot00000000000000import { KindGuard, ValueGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TConstT', () => { // ---------------------------------------------------------------- // Identity Types // ---------------------------------------------------------------- it('Should guard for TConst 1', () => { const T = Type.Const(undefined) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsUndefined(T)) }) it('Should guard for TConst 2', () => { const T = Type.Const(null) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsNull(T)) }) it('Should guard for TConst 3', () => { const T = Type.Const(Symbol()) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsSymbol(T)) }) it('Should guard for TConst 4', () => { const T = Type.Const(1 as const) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 1) }) it('Should guard for TConst 5', () => { const T = Type.Const('hello' as const) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hello') }) it('Should guard for TConst 6', () => { const T = Type.Const(true as const) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, true) }) // ---------------------------------------------------------------- // Complex Types // ---------------------------------------------------------------- it('Should guard for TConst 7', () => { const T = Type.Const(100n as const) Assert.IsFalse(KindGuard.IsReadonly(T)) // TS disparity because TLiteral does not support Bigint Assert.IsTrue(KindGuard.IsBigInt(T)) }) it('Should guard for TConst 8', () => { const T = Type.Const(new Date()) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsDate(T)) }) it('Should guard for TConst 9', () => { const T = Type.Const(new Uint8Array()) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsUint8Array(T)) }) it('Should guard for TConst 10', () => { const T = Type.Const(function () {}) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsFunction(T)) Assert.IsTrue(T.parameters.length === 0) Assert.IsTrue(KindGuard.IsUnknown(T.returns)) }) it('Should guard for TConst 11', () => { const T = Type.Const(new (class {})()) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsObject(T)) // Object types that are neither Date or Uint8Array evaluate as empty objects Assert.IsEqual(T.properties, {}) }) it('Should guard for TConst 12', () => { const T = Type.Const((function* (): any {})()) const R = ValueGuard.IsIterator((function* (): any {})()) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsAny(T)) }) it('Should guard for TConst 13', () => { const T = Type.Const((async function* (): any {})()) const R = ValueGuard.IsAsyncIterator((function* (): any {})()) Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsAny(T)) }) it('Should guard for TConst 14', () => { const T = Type.Const({ x: 1, y: { z: 2, }, } as const) // root Assert.IsFalse(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsObject(T)) // x Assert.IsTrue(KindGuard.IsLiteral(T.properties.x)) Assert.IsEqual(T.properties.x.const, 1) // y Assert.IsTrue(KindGuard.IsReadonly(T.properties.y)) Assert.IsTrue(KindGuard.IsObject(T.properties.y)) // y.z Assert.IsTrue(KindGuard.IsReadonly(T.properties.y.properties.z)) Assert.IsTrue(KindGuard.IsLiteral(T.properties.y.properties.z)) Assert.IsEqual(T.properties.y.properties.z.const, 2) }) it('Should guard for TConst 15', () => { const T = Type.Const([1, 2, 3] as const) // root (arrays are always readonly as root) Assert.IsTrue(KindGuard.IsReadonly(T)) Assert.IsTrue(KindGuard.IsTuple(T)) Assert.IsTrue(T.items?.length === 3) // 0 Assert.IsFalse(KindGuard.IsReadonly(T.items![0])) Assert.IsTrue(KindGuard.IsLiteral(T.items![0])) // 1 Assert.IsFalse(KindGuard.IsReadonly(T.items![1])) Assert.IsTrue(KindGuard.IsLiteral(T.items![1])) // 2 Assert.IsFalse(KindGuard.IsReadonly(T.items![2])) Assert.IsTrue(KindGuard.IsLiteral(T.items![2])) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/constructor.ts000066400000000000000000000007021505437577000266660ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TConstructor', () => { it('Should guard for TConstructor', () => { const R = KindGuard.IsConstructor(Type.Constructor([], Type.Number())) Assert.IsTrue(R) }) it('Should not guard for TConstructor', () => { const R = KindGuard.IsConstructor(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/date.ts000066400000000000000000000006071505437577000252220ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TDate', () => { it('Should guard for TDate', () => { const R = KindGuard.IsDate(Type.Date()) Assert.IsTrue(R) }) it('Should not guard for TDate', () => { const R = KindGuard.IsDate(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/enum.ts000066400000000000000000000101331505437577000252440ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TEnum', () => { // ---------------------------------------------------------------- // Options // ---------------------------------------------------------------- it('Should guard for Options 1', () => { const T = Type.Enum({ x: 1 }, { extra: 'hello', $id: 'T' }) Assert.IsEqual(T.extra, 'hello') Assert.IsEqual(T.$id, 'T') }) it('Should guard for Options 2', () => { enum E { x, } const T = Type.Enum(E, { extra: 'hello', $id: 'T' }) Assert.IsEqual(T.extra, 'hello') Assert.IsEqual(T.$id, 'T') }) it('Should guard for Options 3', () => { enum E {} const T = Type.Enum(E, { extra: 'hello', $id: 'T' }) Assert.IsEqual(T.extra, 'hello') Assert.IsEqual(T.$id, 'T') }) it('Should guard for Options 4', () => { const T = Type.Enum({}, { extra: 'hello', $id: 'T' }) Assert.IsEqual(T.extra, 'hello') Assert.IsEqual(T.$id, 'T') }) // ---------------------------------------------------------------- // Empty // ---------------------------------------------------------------- it('Should guard for Empty 1', () => { const T = Type.Enum({}) Assert.IsTrue(KindGuard.IsNever(T)) }) it('Should guard for Empty 2', () => { enum E {} const T = Type.Enum(E) Assert.IsTrue(KindGuard.IsNever(T)) }) // ---------------------------------------------------------------- // Enum // ---------------------------------------------------------------- it('Should guard for TEnum Enum 0', () => { enum E {} const T = Type.Enum(E) Assert.IsTrue(KindGuard.IsNever(T)) }) it('Should guard for TEnum Enum 1', () => { enum E { A, } const T = Type.Enum(E) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, E.A) }) it('Should guard for TEnum Enum 2', () => { enum E { A = 1, B = 2, C = 3, } const T = Type.Enum(E) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, E.A) Assert.IsEqual(T.anyOf[1].const, E.B) Assert.IsEqual(T.anyOf[2].const, E.C) }) it('Should guard for TEnum Enum 3', () => { enum E { A = 'X', B = 'Y', C = 'Z', } const T = Type.Enum(E) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, E.A) Assert.IsEqual(T.anyOf[1].const, E.B) Assert.IsEqual(T.anyOf[2].const, E.C) }) it('Should guard for TEnum Enum 4', () => { enum E { A = 'X', B = 'Y', C = 'X', } const T = Type.Enum(E) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, E.A) Assert.IsEqual(T.anyOf[1].const, E.B) Assert.IsEqual(T.anyOf.length, 2) }) // ---------------------------------------------------------------- // Object Literal // ---------------------------------------------------------------- it('Should guard for TEnum Object Literal 0', () => { const T = Type.Enum({}) Assert.IsTrue(KindGuard.IsNever(T)) }) it('Should guard for TEnum Object Literal 1', () => { const T = Type.Enum({ A: 1 }) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 1) }) it('Should guard for TEnum Object Literal 2', () => { const T = Type.Enum({ A: 1, B: 2, C: 3, }) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 1) Assert.IsEqual(T.anyOf[1].const, 2) Assert.IsEqual(T.anyOf[2].const, 3) }) it('Should guard for TEnum Object Literal 3', () => { const T = Type.Enum({ A: 'X', B: 'Y', C: 'Z', }) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'X') Assert.IsEqual(T.anyOf[1].const, 'Y') Assert.IsEqual(T.anyOf[2].const, 'Z') }) it('Should guard for TEnum Object Literal 4', () => { const T = Type.Enum({ A: 'X', B: 'Y', C: 'X', }) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'X') Assert.IsEqual(T.anyOf[1].const, 'Y') Assert.IsEqual(T.anyOf.length, 2) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/exclude.ts000066400000000000000000000114661505437577000257430ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TExclude', () => { it('Should exclude string from number', () => { const T = Type.Exclude(Type.String(), Type.Number()) Assert.IsTrue(KindGuard.IsString(T)) }) it('Should exclude string from string', () => { const T = Type.Exclude(Type.String(), Type.String()) Assert.IsTrue(KindGuard.IsNever(T)) }) it('Should exclude string | number | boolean from string', () => { const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String()) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsTrue(KindGuard.IsNumber(T.anyOf[0])) Assert.IsTrue(KindGuard.IsBoolean(T.anyOf[1])) }) it('Should exclude string | number | boolean from string | boolean', () => { const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.Union([Type.String(), Type.Boolean()])) Assert.IsTrue(KindGuard.IsNumber(T)) }) // ------------------------------------------------------------------------ // TemplateLiteral | TemplateLiteral // ------------------------------------------------------------------------ it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Exclude(A, B) Assert.IsTrue(KindGuard.IsNever(T)) }) it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const)) }) // ------------------------------------------------------------------------ // TemplateLiteral | Union 1 // ------------------------------------------------------------------------ it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Exclude(A, B) Assert.IsTrue(KindGuard.IsNever(T)) }) it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A')]) const T = Type.Exclude(A, B) Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const)) }) // ------------------------------------------------------------------------ // Union | TemplateLiteral 1 // ------------------------------------------------------------------------ it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Exclude(A, B) Assert.IsTrue(KindGuard.IsNever(T)) }) it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const)) }) it('Should exclude with options', () => { const A = Type.String() const B = Type.String() const T = Type.Exclude(A, B, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/extract.ts000066400000000000000000000123541505437577000257610ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TExtract', () => { it('Should extract string from number', () => { const T = Type.Extract(Type.String(), Type.Number()) Assert.IsTrue(KindGuard.IsNever(T)) }) it('Should extract string from string', () => { const T = Type.Extract(Type.String(), Type.String()) Assert.IsTrue(KindGuard.IsString(T)) }) it('Should extract string | number | boolean from string', () => { const T = Type.Extract(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String()) Assert.IsTrue(KindGuard.IsString(T)) }) it('Should extract string | number | boolean from string | boolean', () => { const T = Type.Extract(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.Union([Type.String(), Type.Boolean()])) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsTrue(KindGuard.IsString(T.anyOf[0])) Assert.IsTrue(KindGuard.IsBoolean(T.anyOf[1])) }) // ------------------------------------------------------------------------ // TemplateLiteral | TemplateLiteral // ------------------------------------------------------------------------ it('Should extract TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const)) }) it('Should extract TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const)) }) it('Should extract TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A'].includes(T.const)) }) // ------------------------------------------------------------------------ // TemplateLiteral | Union 1 // ------------------------------------------------------------------------ it('Should extract TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const)) }) it('Should extract TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const)) }) it('Should extract TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A')]) const T = Type.Extract(A, B) Assert.IsTrue(['A'].includes(T.const)) }) // ------------------------------------------------------------------------ // Union | TemplateLiteral 1 // ------------------------------------------------------------------------ it('Should extract Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const)) }) it('Should extract Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const)) }) it('Should extract Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A'].includes(T.const)) }) it('Should extract with options', () => { const A = Type.String() const B = Type.String() const T = Type.Extract(A, B, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/function.ts000066400000000000000000000006601505437577000261310ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TFunction', () => { it('Should guard for TFunction', () => { const R = KindGuard.IsFunction(Type.Function([], Type.Number())) Assert.IsTrue(R) }) it('Should not guard for TFunction', () => { const R = KindGuard.IsFunction(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/import.ts000066400000000000000000000265031505437577000256220ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TImport', () => { it('Should guard for TImport', () => { const Module = Type.Module({ A: Type.String(), }) const A = Module.Import('A') const N = A.$defs[A.$ref] Assert.IsTrue(KindGuard.IsImport(A)) Assert.IsTrue(KindGuard.IsString(N)) }) // ---------------------------------------------------------------- // Computed: Options // ---------------------------------------------------------------- it('Should guard for TImport with Options 1', () => { const Module = Type.Module({ A: Type.String(), }) const A = Module.Import('A', { format: 'string' }) const N = A.$defs[A.$ref] Assert.IsTrue(KindGuard.IsImport(A)) Assert.IsTrue(KindGuard.IsString(N)) Assert.IsTrue(N.format === 'string') }) it('Should guard for TImport with Options 2', () => { const Module = Type.Module({ R: Type.Object({ x: Type.Number() }), A: Type.Ref('R'), }) const A = Module.Import('A', { test: 'test' }) const N = A.$defs[A.$ref] Assert.IsTrue(KindGuard.IsImport(A)) Assert.IsTrue(KindGuard.IsRef(N)) Assert.IsTrue(N.test === 'test') }) it('Should guard for TImport with Options 3', () => { const Module = Type.Module({ R: Type.Object({ x: Type.Number() }), A: Type.Partial(Type.Ref('R')), }) const A = Module.Import('A', { additionalProperties: false }) const N = A.$defs[A.$ref] Assert.IsTrue(KindGuard.IsImport(A)) Assert.IsTrue(KindGuard.IsObject(N)) Assert.IsTrue(N.additionalProperties === false) }) // ---------------------------------------------------------------- // Computed: Awaited // ---------------------------------------------------------------- it('Should compute for Awaited', () => { const Module = Type.Module({ T: Type.Promise(Type.String()), R: Type.Awaited(Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsString(T.$defs['R'])) }) // ---------------------------------------------------------------- // Computed: Index (Note: Pending Reimplementation of Index) // ---------------------------------------------------------------- it('Should compute for Index 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.String() }), I: Type.Literal('x'), R: Type.Index(Type.Ref('T'), Type.Ref('I')) as never, // fail }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'])) }) // ---------------------------------------------------------------- // Computed: Omit // ---------------------------------------------------------------- it('Should compute for Omit 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.Number() }), R: Type.Omit(Type.Ref('T'), Type.Literal('x')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsObject(T.$defs['R'])) Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.y)) // @ts-ignore Assert.IsTrue(T.$defs['R'].properties.x === undefined) }) it('Should compute for Omit 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.Number() }), K: Type.Literal('x'), R: Type.Omit(Type.Ref('T'), Type.Ref('K')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsObject(T.$defs['R'])) Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.y)) // @ts-ignore Assert.IsTrue(T.$defs['R'].properties.x === undefined) }) // ---------------------------------------------------------------- // Computed: Partial // ---------------------------------------------------------------- it('Should compute for Partial', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number() }), R: Type.Partial(Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsObject(T.$defs['R'])) Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x)) Assert.IsTrue(KindGuard.IsOptional(T.$defs['R'].properties.x)) }) // ---------------------------------------------------------------- // Computed: Pick // ---------------------------------------------------------------- it('Should compute for Pick 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.Number() }), R: Type.Pick(Type.Ref('T'), Type.Literal('x')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsObject(T.$defs['R'])) Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x)) // @ts-ignore Assert.IsTrue(T.$defs['R'].properties.y === undefined) }) it('Should compute for Pick 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.Number() }), K: Type.Literal('x'), R: Type.Pick(Type.Ref('T'), Type.Ref('K')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsObject(T.$defs['R'])) Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x)) // @ts-ignore Assert.IsTrue(T.$defs['R'].properties.y === undefined) }) // ---------------------------------------------------------------- // Computed: Record // ---------------------------------------------------------------- it('Should compute for Record 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.String() }), R: Type.Record(Type.String(), Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsRecord(T.$defs['R'])) // note: TRecord> are not computed. Only the Key is // computed as TypeBox needs to make a deferred call to transform from // TRecord to TObject for finite keys. Assert.IsTrue(KindGuard.IsRef(T.$defs['R'].patternProperties['^(.*)$'])) Assert.IsTrue(T.$defs['R'].patternProperties['^(.*)$'].$ref === 'T') }) it('Should compute for Record 2', () => { const Module = Type.Module({ T: Type.Number(), R: Type.Record(Type.Union([Type.Literal('x'), Type.Literal('y')]), Type.Ref('T')), }) // Retain reference if not computed const T = Module.Import('R') Assert.IsTrue(KindGuard.IsObject(T.$defs['R'])) Assert.IsTrue(KindGuard.IsRef(T.$defs['R'].properties.x)) Assert.IsTrue(KindGuard.IsRef(T.$defs['R'].properties.y)) }) it('Should compute for Record 3', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number() }), R: Type.Record(Type.Union([Type.Literal('x'), Type.Literal('y')]), Type.Partial(Type.Ref('T'))), }) // Dereference if computed const T = Module.Import('R') Assert.IsTrue(KindGuard.IsObject(T.$defs['R'])) Assert.IsTrue(KindGuard.IsObject(T.$defs['R'].properties.x)) Assert.IsTrue(KindGuard.IsObject(T.$defs['R'].properties.y)) }) // ---------------------------------------------------------------- // Computed: Required // ---------------------------------------------------------------- it('Should compute for Required', () => { const Module = Type.Module({ T: Type.Partial(Type.Object({ x: Type.Number() })), R: Type.Required(Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsObject(T.$defs['R'])) Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x)) Assert.IsFalse(KindGuard.IsOptional(T.$defs['R'].properties.x)) }) // ---------------------------------------------------------------- // Computed: KeyOf // ---------------------------------------------------------------- it('Should compute for KeyOf', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.String() }), R: Type.KeyOf(Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(KindGuard.IsUnion(T.$defs['R'])) Assert.IsTrue(KindGuard.IsLiteral(T.$defs['R'].anyOf[0])) Assert.IsTrue(KindGuard.IsLiteral(T.$defs['R'].anyOf[1])) Assert.IsTrue(T.$defs['R'].anyOf[0].const === 'x') Assert.IsTrue(T.$defs['R'].anyOf[1].const === 'y') }) // ---------------------------------------------------------------- // Modifiers: 1 // ---------------------------------------------------------------- it('Should compute for Modifiers 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Null()), y: Type.Readonly(Type.Null()), z: Type.Optional(Type.Null()), w: Type.Null(), }), }) const T = Module.Import('T') const R = T.$defs[T.$ref] Assert.IsTrue(KindGuard.IsObject(R)) Assert.IsTrue(KindGuard.IsNull(R.properties.x)) Assert.IsTrue(KindGuard.IsReadonly(R.properties.x)) Assert.IsTrue(KindGuard.IsOptional(R.properties.x)) Assert.IsTrue(KindGuard.IsNull(R.properties.y)) Assert.IsTrue(KindGuard.IsReadonly(R.properties.y)) Assert.IsFalse(KindGuard.IsOptional(R.properties.y)) Assert.IsTrue(KindGuard.IsNull(R.properties.z)) Assert.IsTrue(KindGuard.IsOptional(R.properties.z)) Assert.IsFalse(KindGuard.IsReadonly(R.properties.z)) Assert.IsTrue(KindGuard.IsNull(R.properties.w)) Assert.IsFalse(KindGuard.IsOptional(R.properties.w)) Assert.IsFalse(KindGuard.IsReadonly(R.properties.w)) }) // ---------------------------------------------------------------- // Modifiers: 2 // ---------------------------------------------------------------- it('Should compute for Modifiers 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Array(Type.Null())), y: Type.Readonly(Type.Array(Type.Null())), z: Type.Optional(Type.Array(Type.Null())), w: Type.Array(Type.Null()), }), }) const T = Module.Import('T') const R = T.$defs[T.$ref] Assert.IsTrue(KindGuard.IsObject(R)) Assert.IsTrue(KindGuard.IsArray(R.properties.x)) Assert.IsTrue(KindGuard.IsNull(R.properties.x.items)) Assert.IsTrue(KindGuard.IsReadonly(R.properties.x)) Assert.IsTrue(KindGuard.IsOptional(R.properties.x)) Assert.IsTrue(KindGuard.IsArray(R.properties.y)) Assert.IsTrue(KindGuard.IsNull(R.properties.y.items)) Assert.IsTrue(KindGuard.IsReadonly(R.properties.y)) Assert.IsFalse(KindGuard.IsOptional(R.properties.y)) Assert.IsTrue(KindGuard.IsArray(R.properties.z)) Assert.IsTrue(KindGuard.IsNull(R.properties.z.items)) Assert.IsTrue(KindGuard.IsOptional(R.properties.z)) Assert.IsFalse(KindGuard.IsReadonly(R.properties.z)) Assert.IsTrue(KindGuard.IsArray(R.properties.w)) Assert.IsTrue(KindGuard.IsNull(R.properties.w.items)) Assert.IsFalse(KindGuard.IsOptional(R.properties.w)) Assert.IsFalse(KindGuard.IsReadonly(R.properties.w)) }) // ---------------------------------------------------------------- // Modifiers: 3 // ---------------------------------------------------------------- it('Should compute for Modifiers 3', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Array(Type.Null()), }), // Computed Partial U: Type.Partial(Type.Ref('T')), }) const T = Module.Import('U') const R = T.$defs[T.$ref] Assert.IsTrue(KindGuard.IsObject(R)) Assert.IsTrue(KindGuard.IsArray(R.properties.x)) Assert.IsTrue(KindGuard.IsNull(R.properties.x.items)) Assert.IsTrue(KindGuard.IsOptional(R.properties.x)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/index.ts000066400000000000000000000017671505437577000254240ustar00rootroot00000000000000import './any' import './argument' import './array' import './async-iterator' import './awaited' import './bigint' import './boolean' import './capitalize' import './composite' import './computed' import './const' import './constructor' import './date' import './enum' import './exclude' import './extract' import './function' import './import' import './indexed' import './integer' import './intersect' import './iterator' import './keyof' import './kind' import './literal' import './lowercase' import './mapped' import './not' import './null' import './number' import './object' import './omit' import './partial' import './pick' import './promise' import './record' import './recursive' import './ref' import './regexp' import './required' import './rest' import './string' import './symbol' import './template-literal' import './this' import './tuple' import './uint8array' import './uncapitalize' import './undefined' import './union' import './unknown' import './unsafe' import './uppercase' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/indexed.ts000066400000000000000000000262171505437577000257320ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TIndex', () => { it('Should Index 1', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const I = Type.Index(T, ['x']) Assert.IsTrue(KindGuard.IsNumber(I)) }) it('Should Index 2', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(KindGuard.IsString(I.anyOf[1])) }) it('Should Index 3', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const I = Type.Index(T, Type.KeyOf(T)) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(KindGuard.IsString(I.anyOf[1])) }) it('Should Index 4', () => { const T = Type.Object({ ab: Type.Number(), ac: Type.String(), }) const I = Type.Index(T, Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])])) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(KindGuard.IsString(I.anyOf[1])) }) it('Should Index 5', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.String() })]) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(KindGuard.IsString(I.anyOf[1])) }) it('Should Index 6', () => { const T = Type.Union([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.String() })]) const I = Type.Index(T, ['x']) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(KindGuard.IsString(I.anyOf[1])) }) it('Should Index 7', () => { const T = Type.Array(Type.Null()) const I = Type.Index(T, Type.Number()) Assert.IsTrue(KindGuard.IsNull(I)) }) it('Should Index 6', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [0]) Assert.IsTrue(KindGuard.IsLiteralString(I)) Assert.IsEqual(I.const, 'hello') }) it('Should Index 8', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [1]) Assert.IsTrue(KindGuard.IsLiteralString(I)) Assert.IsEqual(I.const, 'world') }) it('Should Index 9', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [0, 1]) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsEqual(I.anyOf[0].const, 'hello') Assert.IsEqual(I.anyOf[1].const, 'world') }) it('Should Index 10', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [1, 0]) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsEqual(I.anyOf[0].const, 'world') Assert.IsEqual(I.anyOf[1].const, 'hello') }) it('Should Index 11', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [0, 0, 0, 1]) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsEqual(I.anyOf[0].const, 'hello') Assert.IsEqual(I.anyOf[1].const, 'hello') Assert.IsEqual(I.anyOf[2].const, 'hello') Assert.IsEqual(I.anyOf[3].const, 'world') }) it('Should Index 12', () => { const T = Type.Tuple([Type.String(), Type.Boolean()]) const I = Type.Index(T, Type.Number()) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsString(I.anyOf[0])) Assert.IsTrue(KindGuard.IsBoolean(I.anyOf[1])) }) it('Should Index 13', () => { const T = Type.Tuple([Type.String()]) const I = Type.Index(T, Type.Number()) Assert.IsTrue(KindGuard.IsString(I)) }) it('Should Index 14', () => { const T = Type.Tuple([]) const I = Type.Index(T, Type.Number()) Assert.IsTrue(KindGuard.IsNever(I)) }) it('Should Index 15', () => { const T = Type.Object({ 0: Type.Number(), }) const I = Type.Index(T, Type.Literal(0)) Assert.IsTrue(KindGuard.IsNumber(I)) }) it('Should Index 16', () => { const T = Type.Object({ 0: Type.Number(), }) const I = Type.Index(T, Type.Literal('0')) Assert.IsTrue(KindGuard.IsNumber(I)) }) it('Should Index 17', () => { const T = Type.Object({ '0': Type.Number(), }) const I = Type.Index(T, Type.Literal(0)) Assert.IsTrue(KindGuard.IsNumber(I)) }) it('Should Index 18', () => { const T = Type.Object({ '0': Type.Number(), }) const I = Type.Index(T, Type.Literal('0')) Assert.IsTrue(KindGuard.IsNumber(I)) }) it('Should Index 19', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.String(), 2: Type.Boolean(), }) const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal(2)])) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(KindGuard.IsBoolean(I.anyOf[1])) }) it('Should Index 20', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.String(), 2: Type.Boolean(), }) const I = Type.Index(T, Type.BigInt()) Assert.IsTrue(KindGuard.IsNever(I)) }) it('Should Index 21', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.String(), 2: Type.Boolean(), }) const I = Type.Index(T, Type.Object({})) Assert.IsTrue(KindGuard.IsNever(I)) }) it('Should Index 22', () => { const A = Type.Object({ x: Type.Literal('A') }) const B = Type.Object({ x: Type.Literal('B') }) const C = Type.Object({ x: Type.Literal('C') }) const D = Type.Object({ x: Type.Literal('D') }) const T = Type.Intersect([A, B, C, D]) const I = Type.Index(T, ['x']) Assert.IsTrue(KindGuard.IsIntersect(I)) Assert.IsTrue(KindGuard.IsLiteral(I.allOf[0])) Assert.IsTrue(KindGuard.IsLiteral(I.allOf[1])) Assert.IsTrue(KindGuard.IsLiteral(I.allOf[2])) Assert.IsTrue(KindGuard.IsLiteral(I.allOf[3])) }) it('Should Index 23', () => { const A = Type.Object({ x: Type.Literal('A') }) const B = Type.Object({ x: Type.Literal('B') }) const C = Type.Object({ x: Type.Literal('C') }) const D = Type.Object({ x: Type.Literal('D') }) const T = Type.Union([A, B, C, D]) const I = Type.Index(T, ['x']) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsLiteral(I.anyOf[0])) Assert.IsTrue(KindGuard.IsLiteral(I.anyOf[1])) Assert.IsTrue(KindGuard.IsLiteral(I.anyOf[2])) Assert.IsTrue(KindGuard.IsLiteral(I.anyOf[3])) }) it('Should Index 24', () => { const A = Type.Object({ x: Type.Literal('A'), y: Type.Number() }) const B = Type.Object({ x: Type.Literal('B') }) const C = Type.Object({ x: Type.Literal('C') }) const D = Type.Object({ x: Type.Literal('D') }) const T = Type.Intersect([A, B, C, D]) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsIntersect(I.anyOf[0])) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1])) }) it('Should Index 25', () => { const A = Type.Object({ x: Type.Literal('A'), y: Type.Number() }) const B = Type.Object({ x: Type.Literal('B'), y: Type.String() }) const C = Type.Object({ x: Type.Literal('C') }) const D = Type.Object({ x: Type.Literal('D') }) const T = Type.Intersect([A, B, C, D]) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsIntersect(I.anyOf[0])) Assert.IsTrue(KindGuard.IsIntersect(I.anyOf[1])) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1].allOf[0])) Assert.IsTrue(KindGuard.IsString(I.anyOf[1].allOf[1])) }) it('Should Index 26', () => { const T = Type.Recursive((This) => Type.Object({ x: Type.String(), y: Type.Number(), z: This, }), ) const I = Type.Index(T, ['x', 'y', 'z']) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsString(I.anyOf[0])) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1])) Assert.IsTrue(KindGuard.IsThis(I.anyOf[2])) }) it('Should Index 27', () => { const T = Type.Object({ 0: Type.String(), 1: Type.Number(), }) const I = Type.Index(T, [0, 1]) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsString(I.anyOf[0])) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1])) }) it('Should Index 28', () => { const T = Type.Object({ 0: Type.String(), '1': Type.Number(), }) const I = Type.Index(T, [0, '1']) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsString(I.anyOf[0])) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1])) }) it('Should Index 29', () => { const T = Type.Object({ 0: Type.String(), '1': Type.Number(), }) const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal('1')])) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsString(I.anyOf[0])) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1])) }) it('Should Index 30', () => { const T = Type.Object({ 0: Type.String(), '1': Type.Number(), }) const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal(1)])) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsString(I.anyOf[0])) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1])) // Note: Expect TNever for anyOf[1] but permit for TNumber due to IndexedAccess // Resolve() which currently cannot differentiate between string and numeric keys // on the object. This may be resolvable in later revisions, but test for this // fall-through to ensure case is documented. For review. }) // -------------------------------------------------------- // Modifier Optional Indexing // -------------------------------------------------------- it('Should Index 31', () => { const T = Type.Object({ x: Type.Optional(Type.String()), y: Type.Number(), }) const I = Type.Index(T, ['x']) Assert.IsTrue(KindGuard.IsOptional(I)) Assert.IsTrue(KindGuard.IsString(I)) }) it('Should Index 32', () => { const T = Type.Object({ x: Type.Optional(Type.String()), y: Type.Number(), }) const I = Type.Index(T, ['y']) Assert.IsFalse(KindGuard.IsOptional(I)) Assert.IsTrue(KindGuard.IsNumber(I)) }) it('Should Index 33', () => { const T = Type.Object({ x: Type.Optional(Type.String()), y: Type.Number(), }) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(KindGuard.IsOptional(I)) Assert.IsTrue(KindGuard.IsUnion(I)) Assert.IsTrue(KindGuard.IsString(I.anyOf[0])) Assert.IsTrue(KindGuard.IsNumber(I.anyOf[1])) }) it('Should Index 34', () => { const T = Type.String() const I = Type.Index(T, ['x']) Assert.IsTrue(KindGuard.IsNever(I)) }) it('Should Index 35', () => { const T = Type.Array(Type.String()) const I = Type.Index(T, Type.Number()) Assert.IsTrue(KindGuard.IsString(I)) }) it('Should Index 36', () => { const T = Type.Array(Type.String()) const I = Type.Index(T, ['[number]']) Assert.IsTrue(KindGuard.IsString(I)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/integer.ts000066400000000000000000000006311505437577000257370ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TInteger', () => { it('Should guard for TInteger', () => { const R = KindGuard.IsInteger(Type.Integer()) Assert.IsTrue(R) }) it('Should not guard for TInteger', () => { const R = KindGuard.IsInteger(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/intersect.ts000066400000000000000000000016601505437577000263050ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TIntersect', () => { it('Should guard for TIntersect', () => { const R = KindGuard.IsIntersect( Type.Intersect([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]), ) Assert.IsTrue(R) }) it('Should not guard for TIntersect', () => { const R = KindGuard.IsIntersect( Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]), ) Assert.IsFalse(R) }) it('Should throw for intersected transform types', () => { const N = Type.Transform(Type.Number()) .Decode((value) => value) .Encode((value) => value) Assert.Throws(() => Type.Intersect([N, N])) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/iterator.ts000066400000000000000000000007111505437577000261320ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TIterator', () => { it('Should guard for TIterator', () => { const T = Type.Iterator(Type.Any()) const R = KindGuard.IsIterator(T) Assert.IsTrue(R) }) it('Should not guard for TIterator', () => { const T = null const R = KindGuard.IsIterator(T) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/keyof.ts000066400000000000000000000040121505437577000254140ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TKeyOf', () => { it('Should KeyOf 1', () => { const T = Type.Object({ x: Type.Number(), y: Type.Number(), }) const K = Type.KeyOf(T) Assert.IsTrue(KindGuard.IsUnion(K)) Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[0])) Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[1])) }) it('Should KeyOf 2', () => { const T = Type.Recursive((Self) => Type.Object({ x: Type.Number(), y: Type.Array(Self), }), ) const K = Type.KeyOf(T) Assert.IsTrue(KindGuard.IsUnion(K)) Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[0])) Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[1])) }) it('Should KeyOf 3', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]) const K = Type.KeyOf(T) Assert.IsTrue(KindGuard.IsUnion(K)) Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[0])) Assert.IsTrue(KindGuard.IsLiteral(K.anyOf[1])) }) it('Should KeyOf 4', () => { const T = Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]) const K = Type.KeyOf(T) Assert.IsTrue(KindGuard.IsNever(K)) }) it('Should KeyOf 5', () => { const T = Type.Null() const K = Type.KeyOf(T) Assert.IsTrue(KindGuard.IsNever(K)) }) it('Should KeyOf 6', () => { const T = Type.Array(Type.Number()) const K = Type.KeyOf(T) Assert.IsTrue(KindGuard.IsNumber(K)) }) it('Should KeyOf 7', () => { const T = Type.Tuple([]) const K = Type.KeyOf(T) Assert.IsTrue(KindGuard.IsNever(K)) }) it('Should KeyOf 8', () => { const T = Type.Tuple([Type.Number(), Type.Null()]) const K = Type.KeyOf(T) Assert.IsTrue(KindGuard.IsUnion(K)) Assert.IsEqual(K.anyOf[0].const, '0') Assert.IsEqual(K.anyOf[1].const, '1') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/kind.ts000066400000000000000000000005251505437577000252310ustar00rootroot00000000000000import { KindGuard, Kind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TKind', () => { it('Should guard 1', () => { const T = { [Kind]: 'Kind' } Assert.IsTrue(KindGuard.IsKind(T)) }) it('Should guard 2', () => { const T = {} Assert.IsFalse(KindGuard.IsKind(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/literal.ts000066400000000000000000000011001505437577000257260ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TLiteral', () => { it('Should guard for TLiteral of String', () => { const R = KindGuard.IsLiteral(Type.Literal('hello')) Assert.IsTrue(R) }) it('Should guard for TLiteral of Number', () => { const R = KindGuard.IsLiteral(Type.Literal(42)) Assert.IsTrue(R) }) it('Should guard for TLiteral of Boolean', () => { const R = KindGuard.IsLiteral(Type.Literal(true)) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/lowercase.ts000066400000000000000000000025171505437577000262730ustar00rootroot00000000000000import { KindGuard, Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/Lowercase', () => { it('Should guard for Lowercase 1', () => { const T = Type.Lowercase(Type.Literal('HELLO'), { $id: 'hello', foo: 1 }) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hello') Assert.IsEqual(T.$id, 'hello') Assert.IsEqual(T.foo, 1) }) it('Should guard for Lowercase 2', () => { const T = Type.Lowercase(Type.Literal('HELLO')) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hello') }) it('Should guard for Lowercase 3', () => { const T = Type.Lowercase(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')])) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'hello') Assert.IsEqual(T.anyOf[1].const, 'world') }) it('Should guard for Lowercase 4', () => { const T = Type.Lowercase(Type.TemplateLiteral('HELLO${0|1}')) Assert.IsTrue(KindGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hello0|hello1)$') }) it('Should guard for Lowercase 5', () => { const T = Type.Lowercase(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(0), Type.Literal(1)])])) Assert.IsTrue(KindGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hello0|hello1)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/mapped.ts000066400000000000000000000450251505437577000255560ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' // prettier-ignore describe('guard/kind/Mapped', () => { it('Should guard mapped 1', () => { const T = Type.Mapped(Type.Union([ Type.Literal('x'), Type.Literal('y'), Type.Literal('z'), ]), _ => Type.Number(), { custom: 1 }) Assert.IsEqual(T, Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() }, { custom: 1 })) }) it('Should guard mapped 2', () => { const T = Type.Mapped(Type.Union([ Type.Literal('x'), Type.Literal('y'), Type.Literal('z'), ]), _ => Type.Number()) Assert.IsEqual(T, Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() })) }) it('Should guard mapped 3', () => { const T = Type.Mapped(Type.Union([ Type.Literal('x'), Type.Literal('y'), Type.Literal('z'), ]), K => K) Assert.IsEqual(T, Type.Object({ x: Type.Literal('x'), y: Type.Literal('y'), z: Type.Literal('z'), })) }) it('Should guard mapped 4', () => { const T = Type.Mapped(Type.TemplateLiteral('${0|1}${0|1}'), K => Type.Number()) Assert.IsEqual(T, Type.Object({ '00': Type.Number(), '01': Type.Number(), '10': Type.Number(), '11': Type.Number(), })) }) it('Should guard mapped 5', () => { const T = Type.Mapped(Type.TemplateLiteral('${a|b}'), X => Type.Mapped(Type.TemplateLiteral('${c|d}'), Y => Type.Mapped(Type.TemplateLiteral('${e|f}'), Z => Type.Tuple([X, Y, Z]) ) ) ) Assert.IsEqual(T, Type.Object({ a: Type.Object({ c: Type.Object({ e: Type.Tuple([Type.Literal("a"), Type.Literal("c"), Type.Literal("e")]), f: Type.Tuple([Type.Literal("a"), Type.Literal("c"), Type.Literal("f")]) }), d: Type.Object({ e: Type.Tuple([Type.Literal("a"), Type.Literal("d"), Type.Literal("e")]), f: Type.Tuple([Type.Literal("a"), Type.Literal("d"), Type.Literal("f")]) }), }), b: Type.Object({ c: Type.Object({ e: Type.Tuple([Type.Literal("b"), Type.Literal("c"), Type.Literal("e")]), f: Type.Tuple([Type.Literal("b"), Type.Literal("c"), Type.Literal("f")]) }), d: Type.Object({ e: Type.Tuple([Type.Literal("b"), Type.Literal("d"), Type.Literal("e")]), f: Type.Tuple([Type.Literal("b"), Type.Literal("d"), Type.Literal("f")]) }), }), })) }) it('Should guard mapped 6', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => K) Assert.IsEqual(M, Type.Object({ x: Type.Literal('x'), y: Type.Literal('y'), z: Type.Literal('z') })) }) it('Should guard mapped 7', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K)) Assert.IsEqual(M, Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() })) }) it('Should guard mapped 8', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K, { custom: 1 })) Assert.IsEqual(M, Type.Object({ x: Type.Number({ custom: 1 }), y: Type.String({ custom: 1 }), z: Type.Boolean({ custom: 1 }) })) }) // ---------------------------------------------------------------- // Extract // ---------------------------------------------------------------- it('Should guard mapped 9', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.String()) }) Assert.IsEqual(M, Type.Object({ x: Type.String() })) }) it('Should guard mapped 10', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.Union([ Type.String(), Type.Number() ])) }) Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.String(), Type.Number()]) })) }) it('Should guard mapped 11', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.Null()) }) Assert.IsEqual(M, Type.Object({ x: Type.Never() })) }) // ---------------------------------------------------------------- // Extends // ---------------------------------------------------------------- it('Should guard mapped 12', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => { return ( Type.Extends(K, Type.Literal('x'), Type.Literal(1), Type.Extends(K, Type.Literal('y'), Type.Literal(2), Type.Extends(K, Type.Literal('z'), Type.Literal(3), Type.Never()))) ) }) Assert.IsEqual(M, Type.Object({ x: Type.Literal(1), y: Type.Literal(2), z: Type.Literal(3), })) }) it('Should guard mapped 13', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => { return ( Type.Extends(Type.Index(T, K), Type.Number(), Type.Literal(3), Type.Extends(Type.Index(T, K), Type.String(), Type.Literal(2), Type.Extends(Type.Index(T, K), Type.Boolean(), Type.Literal(1), Type.Never()))) ) }) Assert.IsEqual(M, Type.Object({ x: Type.Literal(3), y: Type.Literal(2), z: Type.Literal(1), })) }) // ---------------------------------------------------------------- // Exclude // ---------------------------------------------------------------- it('Should guard mapped 14', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.String()) }) Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.Number(), Type.Boolean()]) })) }) it('Should guard mapped 15', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.Union([ Type.String(), Type.Number() ])) }) Assert.IsEqual(M, Type.Object({ x: Type.Boolean() })) }) it('Should guard mapped 16', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.Null()) }) Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) })) }) // ---------------------------------------------------------------- // Non-Evaluated // ---------------------------------------------------------------- it('Should guard mapped 17', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Array(Type.Index(T, K))) Assert.IsEqual(M, Type.Object({ x: Type.Array(Type.Number()) })) }) it('Should guard mapped 18', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Promise(Type.Index(T, K))) Assert.IsEqual(M, Type.Object({ x: Type.Promise(Type.Number()) })) }) it('Should guard mapped 19', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Function([Type.Index(T, K)], Type.Index(T, K))) Assert.IsEqual(M, Type.Object({ x: Type.Function([Type.Number()], Type.Number())})) }) it('Should guard mapped 20', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Tuple([Type.Index(T, K), Type.Index(T, K)])) Assert.IsEqual(M, Type.Object({ x: Type.Tuple([Type.Number(), Type.Number()]) })) }) it('Should guard mapped 21', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Union([Type.Index(T, K), Type.Index(T, K)])) Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.Number(), Type.Number()]) })) }) it('Should guard mapped 22', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Intersect([Type.Index(T, K), Type.Index(T, K)])) Assert.IsEqual(M, Type.Object({ x: Type.Intersect([Type.Number(), Type.Number()]) })) }) // ---------------------------------------------------------------- // Numeric Keys // ---------------------------------------------------------------- it('Should guard mapped 23', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => K) Assert.IsEqual(M, Type.Object({ 0: Type.Literal('0'), 1: Type.Literal('1'), 2: Type.Literal('2'), })) }) it('Should guard mapped 24', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K)) Assert.IsEqual(M, Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number(), })) }) it('Should guard mapped 25', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.String()) Assert.IsEqual(M, Type.Object({ 0: Type.String(), 1: Type.String(), 2: Type.String(), })) }) it('Should guard mapped 26', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Extends(K, Type.Literal('1'), Type.String(), Type.Number())) Assert.IsEqual(M, Type.Object({ 0: Type.Number(), 1: Type.String(), 2: Type.Number(), })) }) // ---------------------------------------------------------------- // Modifiers: Optional // ---------------------------------------------------------------- it('Should guard mapped 27', () => { const T = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Number() }) // subtractive const M = Type.Mapped(Type.KeyOf(T), K => Type.Optional(Type.Index(T, K), false)) Assert.IsEqual(M, Type.Object({ x: Type.Number(), y: Type.Number() })) }) it('Should guard mapped 28', () => { const T = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Number() }) // additive const M = Type.Mapped(Type.KeyOf(T), K => Type.Optional(Type.Index(T, K), true)) Assert.IsEqual(M, Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()) })) }) // ---------------------------------------------------------------- // Modifiers: Readonly // ---------------------------------------------------------------- it('Should guard mapped 27', () => { const T = Type.Object({ x: Type.Readonly(Type.Number()), y: Type.Number() }) // subtractive const M = Type.Mapped(Type.KeyOf(T), K => Type.Readonly(Type.Index(T, K), false)) Assert.IsEqual(M, Type.Object({ x: Type.Number(), y: Type.Number() })) }) it('Should guard mapped 28', () => { const T = Type.Object({ x: Type.Readonly(Type.Number()), y: Type.Number() }) // additive const M = Type.Mapped(Type.KeyOf(T), K => Type.Readonly(Type.Index(T, K), true)) Assert.IsEqual(M, Type.Object({ x: Type.Readonly(Type.Number()), y: Type.Readonly(Type.Number()) })) }) // ---------------------------------------------------------------- // Finite Boolean // ---------------------------------------------------------------- it('Should guard mapped 29', () => { const T = Type.TemplateLiteral('${boolean}') const M = Type.Mapped(T, K => K) Assert.IsEqual(M, Type.Object({ true: Type.Literal('true'), false: Type.Literal('false'), })) }) it('Should guard mapped 30', () => { const T = Type.TemplateLiteral('${0|1}${boolean}') const M = Type.Mapped(T, K => K) Assert.IsEqual(M, Type.Object({ '0true': Type.Literal('0true'), '0false': Type.Literal('0false'), '1true': Type.Literal('1true'), '1false': Type.Literal('1false'), })) }) it('Should guard mapped 31', () => { const T = Type.TemplateLiteral('${boolean}${0|1}') const M = Type.Mapped(T, K => K) Assert.IsEqual(M, Type.Object({ 'true0': Type.Literal('true0'), 'true1': Type.Literal('true1'), 'false0': Type.Literal('false0'), 'false1': Type.Literal('false1'), })) }) // ---------------------------------------------------------------- // Numeric Mapping // ---------------------------------------------------------------- it('Should guard mapped 32', () => { const T = Type.TemplateLiteral([ Type.Union([Type.Literal(0), Type.Literal(1)]), Type.Union([Type.Literal(0), Type.Literal(1)]), ]) const M = Type.Mapped(T, (K) => K) Assert.IsEqual(M, Type.Object({ '00': Type.Literal('00'), '01': Type.Literal('01'), '10': Type.Literal('10'), '11': Type.Literal('11'), })) }) // ---------------------------------------------------------------- // Indexed Key Remap // ---------------------------------------------------------------- it('Should guard mapped 33', () => { const T = Type.Object({ hello: Type.Number(), world: Type.String(), }) const M = Type.Mapped(Type.Uppercase(Type.KeyOf(T)), (K) => { return Type.Index(T, Type.Lowercase(K)) }) Assert.IsEqual(M, Type.Object({ HELLO: Type.Number(), WORLD: Type.String() })) }) // ---------------------------------------------------------------- // Partial // ---------------------------------------------------------------- it('Should guard mapped 34', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Partial(Type.Index(T, K)) }) Assert.IsEqual(M, Type.Object({ x: Type.Partial(Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), })), y: Type.Partial(Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), })), })) }) // ---------------------------------------------------------------- // Required // ---------------------------------------------------------------- it('Should guard mapped 35', () => { const T = Type.Object({ x: Type.Partial(Type.Object({ x: Type.Number(), y: Type.Number(), })), y: Type.Partial(Type.Object({ x: Type.Number(), y: Type.Number(), })), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Required(Type.Index(T, K)) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), })) }) // ------------------------------------------------------------------ // Pick With Key // ------------------------------------------------------------------ it('Should guard mapped 36', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number() }), y: Type.Object({ x: Type.Number(), y: Type.Number() }) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Pick(T, K) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }) }), y: Type.Object({ y: Type.Object({ x: Type.Number(), y: Type.Number(), }) }), })) }) // ------------------------------------------------------------------ // Pick With Result // ------------------------------------------------------------------ it('Should guard mapped 37', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Pick(Type.Index(T, K), ['x']) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ x: Type.Number() }), y: Type.Object({ x: Type.Number() }) })) }) // ------------------------------------------------------------------ // Omit With Key // ------------------------------------------------------------------ it('Should guard mapped 36', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number() }), y: Type.Object({ x: Type.Number(), y: Type.Number() }) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Omit(T, K) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ y: Type.Object({ x: Type.Number(), y: Type.Number(), }) }), y: Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }) }), })) }) // ------------------------------------------------------------------ // Omit With Result // ------------------------------------------------------------------ it('Should guard mapped 37', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Omit(Type.Index(T, K), ['x']) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ y: Type.Number() }), y: Type.Object({ y: Type.Number() }) })) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/not.ts000066400000000000000000000004451505437577000251050ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TNot', () => { it('Should guard for TNot', () => { const R = KindGuard.IsNot(Type.Not(Type.String())) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/null.ts000066400000000000000000000006071505437577000252570ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TNull', () => { it('Should guard for TNull', () => { const R = KindGuard.IsNull(Type.Null()) Assert.IsTrue(R) }) it('Should not guard for TNull', () => { const R = KindGuard.IsNull(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/number.ts000066400000000000000000000006231505437577000255730ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TNumber', () => { it('Should guard for TNumber', () => { const R = KindGuard.IsNumber(Type.Number()) Assert.IsTrue(R) }) it('Should not guard for TNumber', () => { const R = KindGuard.IsNumber(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/object.ts000066400000000000000000000007351505437577000255550ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TObject', () => { it('Should guard for TObject', () => { const R = KindGuard.IsObject( Type.Object({ x: Type.Number(), y: Type.Number(), }), ) Assert.IsTrue(R) }) it('Should not guard for TObject', () => { const R = KindGuard.IsObject(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/omit.ts000066400000000000000000000101011505437577000252430ustar00rootroot00000000000000import { KindGuard, Type, Kind, TransformKind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TOmit', () => { // ------------------------------------------------------------------------- // case: https://github.com/sinclairzx81/typebox/issues/384 // ------------------------------------------------------------------------- it('Should support TUnsafe omit properties with no Kind', () => { const T = Type.Omit(Type.Object({ x: Type.Unsafe({ x: 1 }), y: Type.Number() }), ['x']) Assert.IsEqual(T.required, ['y']) }) it('Should support TUnsafe omit properties with unregistered Kind', () => { const T = Type.Omit(Type.Object({ x: Type.Unsafe({ x: 1, [Kind]: 'UnknownOmitType' }), y: Type.Number() }), ['x']) Assert.IsEqual(T.required, ['y']) }) // ------------------------------------------------------------------------- // Standard Tests // ------------------------------------------------------------------------- it('Should Omit 1', () => { const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), }), ['x'], ) Assert.IsTrue(KindGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, ['y']) }) it('Should Omit 2', () => { const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Optional(Type.Number()), }), ['x'], ) Assert.IsTrue(KindGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, undefined) }) it('Should Omit 3', () => { const L = Type.Literal('x') const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) Assert.IsTrue(KindGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, ['y']) }) it('Should Omit 4', () => { const L = Type.Literal('x') const T = Type.Omit(Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]), L) Assert.IsEqual(KindGuard.IsNumber(T.allOf[1].properties.y), true) // @ts-ignore Assert.IsEqual(T.allOf[1].properties.x, undefined) }) it('Should Omit 5', () => { const L = Type.Union([Type.Literal('x'), Type.Literal('y')]) const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) // @ts-ignore Assert.IsEqual(T.properties.x, undefined) // @ts-ignore Assert.IsEqual(T.properties.y, undefined) // @ts-ignore Assert.IsEqual(T.required, undefined) }) it('Should Omit 6', () => { const L = Type.Union([Type.Literal('x'), Type.Literal('y'), Type.Literal('z')]) const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) // @ts-ignore Assert.IsEqual(T.properties.x, undefined) // @ts-ignore Assert.IsEqual(T.properties.y, undefined) // @ts-ignore Assert.IsEqual(T.required, undefined) }) it('Should Omit 7', () => { const L = Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])]) const T = Type.Omit( Type.Object({ ab: Type.Number(), ac: Type.Number(), ad: Type.Number(), }), L, ) Assert.IsTrue(KindGuard.IsNumber(T.properties.ad)) Assert.IsEqual(T.required, ['ad']) }) // ---------------------------------------------------------------- // Discard // ---------------------------------------------------------------- it('Should override $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Omit(A, ['x'], { $id: 'T' }) Assert.IsEqual(T.$id!, 'T') }) it('Should discard $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Omit(A, ['x']) Assert.IsFalse('$id' in T) }) it('Should discard transform', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const S = Type.Transform(T) .Decode((value) => value) .Encode((value) => value) const R = Type.Omit(S, ['x']) Assert.IsFalse(TransformKind in R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/partial.ts000066400000000000000000000073711505437577000257460ustar00rootroot00000000000000import { KindGuard, TypeRegistry, Type, Kind, TransformKind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TPartial', () => { it('Should produce a valid TSchema', () => { const T = Type.Partial(Type.Object({ x: Type.Number() })) Assert.IsTrue(KindGuard.IsSchema(T)) }) // ------------------------------------------------------------------------- // case: https://github.com/sinclairzx81/typebox/issues/364 // ------------------------------------------------------------------------- it('Should support TUnsafe partial properties with no Kind', () => { const T = Type.Partial(Type.Object({ x: Type.Unsafe({ x: 1 }) })) Assert.IsEqual(T.required, undefined) }) it('Should support TUnsafe partial properties with unknown Kind', () => { const T = Type.Partial(Type.Object({ x: Type.Unsafe({ [Kind]: 'UnknownPartialType', x: 1 }) })) Assert.IsEqual(T.required, undefined) }) it('Should support TUnsafe partial properties with known Kind', () => { TypeRegistry.Set('KnownPartialType', () => true) const T = Type.Partial(Type.Object({ x: Type.Unsafe({ [Kind]: 'KnownPartialType', x: 1 }) })) Assert.IsEqual(T.required, undefined) }) it('Should support applying partial to intersect', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const I = Type.Intersect([A, B]) const T = Type.Partial(I) Assert.IsEqual(T.allOf.length, 2) Assert.IsEqual(T.allOf[0].required, undefined) Assert.IsEqual(T.allOf[1].required, undefined) }) it('Should support applying partial to union', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const I = Type.Union([A, B]) const T = Type.Partial(I) Assert.IsEqual(T.anyOf.length, 2) Assert.IsEqual(T.anyOf[0].required, undefined) Assert.IsEqual(T.anyOf[1].required, undefined) }) // ---------------------------------------------------------------- // Discard // ---------------------------------------------------------------- it('Should override $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Partial(A, { $id: 'T' }) Assert.IsEqual(T.$id!, 'T') }) it('Should discard $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Partial(A) Assert.IsFalse('$id' in T) }) it('Should discard transform', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const S = Type.Transform(T) .Decode((value) => value) .Encode((value) => value) const R = Type.Partial(S) Assert.IsFalse(TransformKind in R) }) // ------------------------------------------------------------------ // Intrinsic Passthough // https://github.com/sinclairzx81/typebox/issues/1169 // ------------------------------------------------------------------ it('Should pass through on intrinsic types on union 1', () => { const T = Type.Partial( Type.Union([ Type.Number(), Type.Object({ x: Type.Number(), }), ]), ) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsTrue(KindGuard.IsNumber(T.anyOf[0])) Assert.IsTrue(KindGuard.IsObject(T.anyOf[1])) Assert.IsTrue(KindGuard.IsOptional(T.anyOf[1].properties.x)) }) it('Should pass through on intrinsic types on union 2', () => { const T = Type.Partial( Type.Union([ Type.Literal(1), Type.Object({ x: Type.Number(), }), ]), ) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsTrue(KindGuard.IsLiteral(T.anyOf[0])) Assert.IsTrue(KindGuard.IsObject(T.anyOf[1])) Assert.IsTrue(KindGuard.IsOptional(T.anyOf[1].properties.x)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/pick.ts000066400000000000000000000101301505437577000252230ustar00rootroot00000000000000import { KindGuard, Type, Kind, TransformKind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TPick', () => { // ------------------------------------------------------------------------- // case: https://github.com/sinclairzx81/typebox/issues/384 // ------------------------------------------------------------------------- it('Should support TUnsafe omit properties with no Kind', () => { const T = Type.Pick( Type.Object({ x: Type.Unsafe({ x: 1 }), y: Type.Number(), }), ['x'], ) Assert.IsEqual(T.required, ['x']) }) it('Should support TUnsafe omit properties with unregistered Kind', () => { const T = Type.Pick(Type.Object({ x: Type.Unsafe({ x: 1, [Kind]: 'UnknownPickType' }), y: Type.Number() }), ['x']) Assert.IsEqual(T.required, ['x']) }) // ------------------------------------------------------------------------- // Standard Tests // ------------------------------------------------------------------------- it('Should Pick 1', () => { const T = Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), }), ['x'], ) Assert.IsTrue(KindGuard.IsNumber(T.properties.x)) Assert.IsEqual(T.required, ['x']) }) it('Should Pick 2', () => { const T = Type.Pick( Type.Object({ x: Type.Optional(Type.Number()), y: Type.Number(), }), ['x'], ) Assert.IsTrue(KindGuard.IsNumber(T.properties.x)) Assert.IsEqual(T.required, undefined) }) it('Should Pick 3', () => { const L = Type.Literal('x') const T = Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) Assert.IsTrue(KindGuard.IsNumber(T.properties.x)) Assert.IsEqual(T.required, ['x']) }) it('Should Pick 4', () => { const L = Type.Literal('x') const T = Type.Pick(Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]), L) Assert.IsTrue(KindGuard.IsNumber(T.allOf[0].properties.x)) // @ts-ignore Assert.IsEqual(T.allOf[1].properties.y, undefined) }) it('Should Pick 5', () => { const L = Type.Union([Type.Literal('x'), Type.Literal('y')]) const T = Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) Assert.IsTrue(KindGuard.IsNumber(T.properties.x)) Assert.IsTrue(KindGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, ['x', 'y']) }) it('Should Pick 6', () => { const L = Type.Union([Type.Literal('x'), Type.Literal('y'), Type.Literal('z')]) const T = Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) Assert.IsTrue(KindGuard.IsNumber(T.properties.x)) Assert.IsTrue(KindGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, ['x', 'y']) }) it('Should Pick 7', () => { const L = Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])]) const T = Type.Pick( Type.Object({ ab: Type.Number(), ac: Type.Number(), ad: Type.Number(), }), L, ) Assert.IsTrue(KindGuard.IsNumber(T.properties.ab)) Assert.IsTrue(KindGuard.IsNumber(T.properties.ac)) Assert.IsEqual(T.required, ['ab', 'ac']) }) // ---------------------------------------------------------------- // Discard // ---------------------------------------------------------------- it('Should override $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Pick(A, ['x'], { $id: 'T' }) Assert.IsEqual(T.$id!, 'T') }) it('Should discard $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Pick(A, ['x']) Assert.IsFalse('$id' in T) }) it('Should discard transform', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const S = Type.Transform(T) .Decode((value) => value) .Encode((value) => value) const R = Type.Pick(S, ['x']) Assert.IsFalse(TransformKind in R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/promise.ts000066400000000000000000000006461505437577000257660ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TPromise', () => { it('Should guard for TPromise', () => { const R = KindGuard.IsPromise(Type.Promise(Type.Number())) Assert.IsTrue(R) }) it('Should not guard for TPromise', () => { const R = KindGuard.IsPromise(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/record.ts000066400000000000000000000156571505437577000255760ustar00rootroot00000000000000import { TypeGuard, PatternNumberExact, PatternStringExact, PatternString, PatternNeverExact } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TRecord', () => { // ------------------------------------------------------------- // Overloads // ------------------------------------------------------------- it('Should guard overload 1', () => { const T = Type.Record(Type.Union([Type.Literal('A'), Type.Literal('B')]), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.A)) Assert.IsTrue(TypeGuard.IsString(T.properties.B)) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 2', () => { const T = Type.Record(Type.Union([Type.Literal('A')]), Type.String(), { extra: 1 }) // unwrap as literal Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.A)) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 3', () => { // @ts-ignore const N = Type.Union([]) // Never const T = Type.Record(N, Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNeverExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 4', () => { // @ts-ignore const T = Type.Record(Type.BigInt(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should guard overload 5', () => { const T = Type.Record(Type.Literal('A'), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.A)) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 6', () => { const L = Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Record(L, Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.helloA)) Assert.IsTrue(TypeGuard.IsString(T.properties.helloB)) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 7', () => { const T = Type.Record(Type.Number(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNumberExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 8', () => { const T = Type.Record(Type.Integer(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNumberExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 9', () => { const T = Type.Record(Type.String(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternStringExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 10', () => { const L = Type.TemplateLiteral([Type.String(), Type.Literal('_foo')]) const T = Type.Record(L, Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[`^${PatternString}_foo$`])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 11', () => { const L = Type.Union([Type.Literal('A'), Type.Union([Type.Literal('B'), Type.Literal('C')])]) const T = Type.Record(L, Type.String()) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.A)) Assert.IsTrue(TypeGuard.IsString(T.properties.B)) Assert.IsTrue(TypeGuard.IsString(T.properties.C)) }) it('Should guard overload 12', () => { enum E { A = 'X', B = 'Y', C = 'Z', } const T = Type.Enum(E) const R = Type.Record(T, Type.Null()) Assert.IsTrue(TypeGuard.IsObject(R)) Assert.IsTrue(TypeGuard.IsNull(R.properties.X)) Assert.IsTrue(TypeGuard.IsNull(R.properties.Y)) Assert.IsTrue(TypeGuard.IsNull(R.properties.Z)) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/916 // ---------------------------------------------------------------- it('Should guard overload 13', () => { // @ts-ignore const T = Type.Record(Type.Never(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNeverExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 14', () => { // @ts-ignore const T = Type.Record(Type.Any(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternStringExact])) Assert.IsEqual(T.extra, 1) }) // ------------------------------------------------------------- // Variants // ------------------------------------------------------------- it('Should guard for TRecord', () => { const R = TypeGuard.IsRecord(Type.Record(Type.String(), Type.Number())) Assert.IsTrue(R) }) it('Should guard for TRecord with TObject value', () => { const R = TypeGuard.IsRecord( Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), }), ), ) Assert.IsTrue(R) }) it('Should not guard for TRecord', () => { const R = TypeGuard.IsRecord(null) Assert.IsFalse(R) }) it('Should not guard for TRecord with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsRecord(Type.Record(Type.String(), Type.Number(), { $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TRecord with TObject value with invalid Property', () => { const R = TypeGuard.IsRecord( Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: {} as any, }), ), ) Assert.IsFalse(R) }) it('Normalize: Should should normalize to TObject for single literal union value', () => { const K = Type.Union([Type.Literal('ok')]) const R = TypeGuard.IsObject(Type.Record(K, Type.Number())) Assert.IsTrue(R) }) it('Normalize: Should should normalize to TObject for multi literal union value', () => { const K = Type.Union([Type.Literal('A'), Type.Literal('B')]) const R = TypeGuard.IsObject(Type.Record(K, Type.Number())) Assert.IsTrue(R) }) // ------------------------------------------------------------------ // Evaluated: Dollar Sign Escape // https://github.com/sinclairzx81/typebox/issues/794 // ------------------------------------------------------------------ // prettier-ignore { const K = Type.TemplateLiteral('$prop${A|B|C}') // issue const T = Type.Record(K, Type.String()) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.$propA)) Assert.IsTrue(TypeGuard.IsString(T.properties.$propB)) Assert.IsTrue(TypeGuard.IsString(T.properties.$propC)) Assert.IsEqual(T.required, ['$propA', '$propB', '$propC']) } }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/recursive.ts000066400000000000000000000011531505437577000263110ustar00rootroot00000000000000import { KindGuard, PatternNumberExact, PatternStringExact, PatternString, PatternNumber } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TRecursive', () => { it('Should guard 1', () => { const T = Type.Recursive((This) => Type.Object({ nodes: This })) Assert.IsTrue(KindGuard.IsRecursive(T)) Assert.IsTrue(KindGuard.IsObject(T)) }) it('Should guard 2', () => { const T = Type.Recursive((This) => Type.Tuple([This])) Assert.IsTrue(KindGuard.IsRecursive(T)) Assert.IsTrue(KindGuard.IsTuple(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/ref.ts000066400000000000000000000022661505437577000250640ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TRef', () => { // ---------------------------------------------------------------- // Deprecated // ---------------------------------------------------------------- it('Should guard for Ref(Schema) 1', () => { const T = Type.Number({ $id: 'T' }) const R = Type.Ref(T) Assert.IsTrue(KindGuard.IsRef(R)) Assert.IsTrue(typeof R['$ref'] === 'string') }) it('Should guard for Ref(Schema) 2', () => { const T = Type.Number() Assert.Throws(() => Type.Ref(T)) }) it('Should guard for Ref(Schema) 3', () => { // @ts-ignore const T = Type.Number({ $id: null }) Assert.Throws(() => Type.Ref(T)) }) // ---------------------------------------------------------------- // Standard // ---------------------------------------------------------------- it('Should guard for TRef', () => { const T = Type.Number({ $id: 'T' }) const R = KindGuard.IsRef(Type.Ref(T)) Assert.IsTrue(R) }) it('Should not guard for TRef', () => { const R = KindGuard.IsRef(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/regexp.ts000066400000000000000000000011111505437577000255660ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TRegExp', () => { it('Should guard for TRegExp 1', () => { const T = Type.RegExp(/foo/, { $id: 'T' }) Assert.IsTrue(KindGuard.IsSchema(T)) }) it('Should guard for TRegExp 1', () => { const T = Type.RegExp(/foo/, { $id: 'T' }) Assert.IsTrue(KindGuard.IsRegExp(T)) }) it('Should guard for TRegExp 2', () => { const T = Type.RegExp('foo', { $id: 'T' }) Assert.IsTrue(KindGuard.IsRegExp(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/required.ts000066400000000000000000000072361505437577000261320ustar00rootroot00000000000000import { KindGuard, TypeRegistry, Type, Kind, TransformKind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TRequired', () => { it('Should produce a valid TSchema', () => { const T = Type.Required(Type.Object({ x: Type.Number() })) Assert.IsTrue(KindGuard.IsSchema(T)) }) it('Should support TUnsafe required properties with no Kind', () => { const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ x: 1 })) })) Assert.IsEqual(T.required, ['x']) }) it('Should support TUnsafe required properties with unknown Kind', () => { const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ [Kind]: 'UnknownRequiredType', x: 1 })) })) Assert.IsEqual(T.required, ['x']) }) it('Should support TUnsafe required properties with known Kind', () => { TypeRegistry.Set('KnownRequiredType', () => true) const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ [Kind]: 'KnownRequiredType', x: 1 })) })) Assert.IsEqual(T.required, ['x']) }) it('Should support applying required to intersect', () => { const A = Type.Object({ x: Type.Optional(Type.Number()) }) const B = Type.Object({ y: Type.Optional(Type.Number()) }) const I = Type.Intersect([A, B]) const T = Type.Required(I) Assert.IsEqual(T.allOf.length, 2) Assert.IsEqual(T.allOf[0].required, ['x']) Assert.IsEqual(T.allOf[1].required, ['y']) }) it('Should support applying required to union', () => { const A = Type.Object({ x: Type.Optional(Type.Number()) }) const B = Type.Object({ y: Type.Optional(Type.Number()) }) const I = Type.Union([A, B]) const T = Type.Required(I) Assert.IsEqual(T.anyOf.length, 2) Assert.IsEqual(T.anyOf[0].required, ['x']) Assert.IsEqual(T.anyOf[1].required, ['y']) }) // ---------------------------------------------------------------- // Discard // ---------------------------------------------------------------- it('Should override $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Required(A, { $id: 'T' }) Assert.IsEqual(T.$id!, 'T') }) it('Should discard $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Required(A) Assert.IsFalse('$id' in T) }) it('Should discard transform', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const S = Type.Transform(T) .Decode((value) => value) .Encode((value) => value) const R = Type.Required(S) Assert.IsFalse(TransformKind in R) }) // ------------------------------------------------------------------ // Intrinsic Passthough // https://github.com/sinclairzx81/typebox/issues/1169 // ------------------------------------------------------------------ it('Should pass through on intrinsic types on union 1', () => { const T = Type.Required( Type.Union([ Type.Number(), Type.Object({ x: Type.Optional(Type.Number()), }), ]), ) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsTrue(KindGuard.IsNumber(T.anyOf[0])) Assert.IsTrue(KindGuard.IsObject(T.anyOf[1])) Assert.IsFalse(KindGuard.IsOptional(T.anyOf[1].properties.x)) }) it('Should pass through on intrinsic types on union 2', () => { const T = Type.Required( Type.Union([ Type.Literal(1), Type.Object({ x: Type.Optional(Type.Number()), }), ]), ) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsTrue(KindGuard.IsLiteral(T.anyOf[0])) Assert.IsTrue(KindGuard.IsObject(T.anyOf[1])) Assert.IsFalse(KindGuard.IsOptional(T.anyOf[1].properties.x)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/rest.ts000066400000000000000000000040441505437577000252610ustar00rootroot00000000000000import { Type, KindGuard } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TRest', () => { it('Should guard 1', () => { // union never const A = Type.String() const B = Type.Union(Type.Rest(A)) Assert.IsTrue(KindGuard.IsNever(B)) }) it('Should guard 2', () => { // intersect never const A = Type.String() const B = Type.Intersect(Type.Rest(A)) Assert.IsTrue(KindGuard.IsNever(B)) }) it('Should guard 3', () => { // tuple const A = Type.Tuple([Type.Number(), Type.String()]) const B = Type.Union(Type.Rest(A)) Assert.IsTrue(KindGuard.IsUnion(B)) Assert.IsEqual(B.anyOf.length, 2) Assert.IsTrue(KindGuard.IsNumber(B.anyOf[0])) Assert.IsTrue(KindGuard.IsString(B.anyOf[1])) }) it('Should guard 4', () => { // tuple spread const A = Type.Tuple([Type.Literal(1), Type.Literal(2)]) const B = Type.Tuple([Type.Literal(3), Type.Literal(4)]) const C = Type.Tuple([...Type.Rest(A), ...Type.Rest(B)]) Assert.IsTrue(KindGuard.IsTuple(C)) Assert.IsEqual(C.items!.length, 4) Assert.IsEqual(C.items![0].const, 1) Assert.IsEqual(C.items![1].const, 2) Assert.IsEqual(C.items![2].const, 3) Assert.IsEqual(C.items![3].const, 4) }) it('Should guard 5', () => { // union to intersect const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.String() }) const C = Type.Union([A, B]) const D = Type.Intersect(Type.Rest(C)) Assert.IsTrue(KindGuard.IsIntersect(D)) Assert.IsEqual(D.allOf.length, 2) Assert.IsTrue(KindGuard.IsObject(D.allOf[0])) Assert.IsTrue(KindGuard.IsObject(D.allOf[1])) }) it('Should guard 6', () => { // intersect to composite const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.String() }) const C = Type.Intersect([A, B]) const D = Type.Composite(Type.Rest(C)) Assert.IsTrue(KindGuard.IsObject(D)) Assert.IsTrue(KindGuard.IsNumber(D.properties.x)) Assert.IsTrue(KindGuard.IsString(D.properties.y)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/string.ts000066400000000000000000000006231505437577000256110ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TString', () => { it('Should guard for TString', () => { const R = KindGuard.IsString(Type.String()) Assert.IsTrue(R) }) it('Should not guard for TString', () => { const R = KindGuard.IsString(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/symbol.ts000066400000000000000000000006231505437577000256100ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TSymbol', () => { it('Should guard for TSymbol', () => { const R = KindGuard.IsSymbol(Type.Symbol()) Assert.IsTrue(R) }) it('Should not guard for TSymbol', () => { const R = KindGuard.IsSymbol(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/template-literal.ts000066400000000000000000000025461505437577000275560ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TTemplateLiteral', () => { it('Should guard for empty TemplateLiteral', () => { const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([])) Assert.IsTrue(R) }) it('Should guard for TSchema', () => { const R = KindGuard.IsSchema(Type.TemplateLiteral([])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TTemplateLiteral)', () => { const T = Type.TemplateLiteral([Type.Literal('hello')]) const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([T, Type.Literal('world')])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TLiteral)', () => { const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Literal('hello')])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TString)', () => { const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.String()])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TNumber)', () => { const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Number()])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TBoolean)', () => { const R = KindGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Boolean()])) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/this.ts000066400000000000000000000005651505437577000252570ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TThis', () => { it('Should guard for TThis', () => { Type.Recursive((This) => { const R = KindGuard.IsThis(This) Assert.IsTrue(R) return Type.Object({ nodes: Type.Array(This) }) }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/tuple.ts000066400000000000000000000006531505437577000254370ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TTuple', () => { it('Should guard for TTuple', () => { const R = KindGuard.IsTuple(Type.Tuple([Type.Number(), Type.Number()])) Assert.IsTrue(R) }) it('Should not guard for TTuple', () => { const R = KindGuard.IsTuple(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/uint8array.ts000066400000000000000000000006531505437577000264140ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TUint8Array', () => { it('Should guard for TUint8Array', () => { const R = KindGuard.IsUint8Array(Type.Uint8Array()) Assert.IsTrue(R) }) it('Should not guard for TUint8Array', () => { const R = KindGuard.IsUint8Array(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/uncapitalize.ts000066400000000000000000000025601505437577000267750ustar00rootroot00000000000000import { KindGuard, Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/Uncapitalize', () => { it('Should guard for Uncapitalize 1', () => { const T = Type.Uncapitalize(Type.Literal('HELLO'), { $id: 'hello', foo: 1 }) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hELLO') Assert.IsEqual(T.$id, 'hello') Assert.IsEqual(T.foo, 1) }) it('Should guard for Uncapitalize 2', () => { const T = Type.Uncapitalize(Type.Literal('HELLO')) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hELLO') }) it('Should guard for Uncapitalize 3', () => { const T = Type.Uncapitalize(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')])) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'hELLO') Assert.IsEqual(T.anyOf[1].const, 'wORLD') }) it('Should guard for Uncapitalize 4', () => { const T = Type.Uncapitalize(Type.TemplateLiteral('HELLO${0|1}')) Assert.IsTrue(KindGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hELLO0|hELLO1)$') }) it('Should guard for Uncapitalize 5', () => { const T = Type.Uncapitalize(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(0), Type.Literal(1)])])) Assert.IsTrue(KindGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hELLO0|hELLO1)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/undefined.ts000066400000000000000000000006451505437577000262500ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TUndefined', () => { it('Should guard for TUndefined', () => { const R = KindGuard.IsUndefined(Type.Undefined()) Assert.IsTrue(R) }) it('Should not guard for TUndefined', () => { const R = KindGuard.IsUndefined(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/union.ts000066400000000000000000000023061505437577000254330ustar00rootroot00000000000000import { TSchema, KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TUnion', () => { it('Should guard for TUnion', () => { const R = KindGuard.IsUnion( Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]), ) Assert.IsTrue(R) }) it('Should not guard for TUnion', () => { const R = KindGuard.IsUnion(null) Assert.IsFalse(R) }) it('Transform: Should transform to never for zero length union', () => { const T = Type.Union([]) const R = KindGuard.IsNever(T) Assert.IsTrue(R) }) it('Transform: Should unwrap union type for array of length === 1', () => { const T = Type.Union([Type.String()]) const R = KindGuard.IsString(T) Assert.IsTrue(R) }) it('Transform: Should retain union if array length > 1', () => { const T = Type.Union([Type.String(), Type.Number()]) const R1 = KindGuard.IsUnion(T) const R2 = KindGuard.IsString(T.anyOf[0]) const R3 = KindGuard.IsNumber(T.anyOf[1]) Assert.IsTrue(R1) Assert.IsTrue(R2) Assert.IsTrue(R3) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/unknown.ts000066400000000000000000000006311505437577000260010ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TUnknown', () => { it('Should guard for TUnknown', () => { const R = KindGuard.IsUnknown(Type.Unknown()) Assert.IsTrue(R) }) it('Should not guard for TUnknown', () => { const R = KindGuard.IsUnknown(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/unsafe.ts000066400000000000000000000020611505437577000255620ustar00rootroot00000000000000import { Kind, KindGuard, TypeRegistry } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TUnsafe', () => { it('Should guard raw TUnsafe', () => { const T = Type.Unsafe({ x: 1 }) const R = KindGuard.IsUnsafe(T) Assert.IsTrue(R) }) it('Should guard raw TUnsafe as TSchema', () => { const T = Type.Unsafe({ x: 1 }) const R = KindGuard.IsSchema(T) Assert.IsTrue(R) }) it('Should guard override TUnsafe as TSchema when registered', () => { TypeRegistry.Set('UnsafeType', () => true) const T = Type.Unsafe({ [Kind]: 'UnsafeType' }) const R = KindGuard.IsSchema(T) Assert.IsTrue(R) TypeRegistry.Delete('UnsafeType') }) it('Should not guard TUnsafe with unregistered kind', () => { const T = Type.Unsafe({ [Kind]: 'UnsafeType' }) const R = KindGuard.IsUnsafe(T) Assert.IsFalse(R) }) it('Should not guard for TString', () => { const T = Type.String() const R = KindGuard.IsUnsafe(T) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/uppercase.ts000066400000000000000000000025171505437577000262760ustar00rootroot00000000000000import { KindGuard, Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/Uppercase', () => { it('Should guard for Uppercase 1', () => { const T = Type.Uppercase(Type.Literal('hello'), { $id: 'hello', foo: 1 }) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'HELLO') Assert.IsEqual(T.$id, 'hello') Assert.IsEqual(T.foo, 1) }) it('Should guard for Uppercase 2', () => { const T = Type.Uppercase(Type.Literal('hello')) Assert.IsTrue(KindGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'HELLO') }) it('Should guard for Uppercase 3', () => { const T = Type.Uppercase(Type.Union([Type.Literal('hello'), Type.Literal('world')])) Assert.IsTrue(KindGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'HELLO') Assert.IsEqual(T.anyOf[1].const, 'WORLD') }) it('Should guard for Uppercase 4', () => { const T = Type.Uppercase(Type.TemplateLiteral('hello${0|1}')) Assert.IsTrue(KindGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(HELLO0|HELLO1)$') }) it('Should guard for Uppercase 5', () => { const T = Type.Uppercase(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])])) Assert.IsTrue(KindGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(HELLO0|HELLO1)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/kind/void.ts000066400000000000000000000006071505437577000252460ustar00rootroot00000000000000import { KindGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/kind/TVoid', () => { it('Should guard for TVoid', () => { const R = KindGuard.IsVoid(Type.Void()) Assert.IsTrue(R) }) it('Should not guard for TVoid', () => { const R = KindGuard.IsVoid(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/000077500000000000000000000000001505437577000237665ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/any.ts000066400000000000000000000010351505437577000251240ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TAny', () => { it('Should guard for TAny', () => { const R = TypeGuard.IsAny(Type.Any()) Assert.IsTrue(R) }) it('Should not guard for TAny', () => { const R = TypeGuard.IsAny(null) Assert.IsFalse(R) }) it('Should not guard for TAny with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsAny(Type.Any({ $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/argument.ts000066400000000000000000000006401505437577000261600ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TArgument', () => { it('Should guard for TArgument', () => { const R = TypeGuard.IsArgument(Type.Argument(0)) Assert.IsTrue(R) }) it('Should not guard for TArgument', () => { const R = TypeGuard.IsArgument(null) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/array.ts000066400000000000000000000031411505437577000254530ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TArray', () => { it('Should guard for TArray', () => { const R = TypeGuard.IsArray(Type.Array(Type.Number())) Assert.IsTrue(R) }) it('Should not guard for TArray', () => { const R = TypeGuard.IsArray(null) Assert.IsFalse(R) }) it('Should guard for nested object TArray', () => { const R = TypeGuard.IsArray( Type.Array( Type.Object({ x: Type.Number(), y: Type.Number(), }), ), ) Assert.IsTrue(R) }) it('Should not guard for nested object TArray', () => { const R = TypeGuard.IsArray( Type.Array( Type.Object({ x: Type.Number(), y: {} as any, }), ), ) Assert.IsFalse(R) }) it('Should not guard for TArray with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsArray(Type.Array(Type.Number(), { $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TArray with invalid minItems', () => { // @ts-ignore const R = TypeGuard.IsArray(Type.Array(Type.String(), { minItems: '1' })) Assert.IsFalse(R) }) it('Should not guard for TArray with invalid maxItems', () => { // @ts-ignore const R = TypeGuard.IsArray(Type.Array(Type.String(), { maxItems: '1' })) Assert.IsFalse(R) }) it('Should not guard for TArray with invalid uniqueItems', () => { // @ts-ignore const R = TypeGuard.IsArray(Type.Array(Type.String(), { uniqueItems: '1' })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/async-iterator.ts000066400000000000000000000012741505437577000273060ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TAsyncIterator', () => { it('Should guard for TAsyncIterator', () => { const T = Type.AsyncIterator(Type.Any()) const R = TypeGuard.IsAsyncIterator(T) Assert.IsTrue(R) }) it('Should not guard for TAsyncIterator', () => { const T = null const R = TypeGuard.IsAsyncIterator(T) Assert.IsFalse(R) }) it('Should not guard for TAsyncIterator with invalid $id', () => { //@ts-ignore const T = Type.AsyncIterator(Type.Any(), { $id: 1 }) const R = TypeGuard.IsAsyncIterator(T) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/awaited.ts000066400000000000000000000030701505437577000257540ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/Awaited', () => { it('Should guard for Awaited 1', () => { const T = Type.Awaited(Type.String()) const R = TypeGuard.IsString(T) Assert.IsTrue(R) }) it('Should guard for Awaited 2', () => { const T = Type.Awaited(Type.Promise(Type.String())) const R = TypeGuard.IsString(T) Assert.IsTrue(R) }) it('Should guard for Awaited 3', () => { const T = Type.Awaited(Type.Awaited(Type.Promise(Type.String()))) const R = TypeGuard.IsString(T) Assert.IsTrue(R) }) it('Should guard for Awaited 4', () => { const T = Type.Awaited(Type.Union([Type.Promise(Type.Promise(Type.String()))])) Assert.IsTrue(TypeGuard.IsString(T)) }) it('Should guard for Awaited 5', () => { const T = Type.Awaited(Type.Union([Type.Promise(Type.Promise(Type.String())), Type.Number()])) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsString(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(T.anyOf[1])) }) it('Should guard for Awaited 6', () => { const T = Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.String()))])) Assert.IsTrue(TypeGuard.IsString(T)) }) it('Should guard for Awaited 7', () => { const T = Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.String())), Type.Number()])) Assert.IsTrue(TypeGuard.IsIntersect(T)) Assert.IsTrue(TypeGuard.IsString(T.allOf[0])) Assert.IsTrue(TypeGuard.IsNumber(T.allOf[1])) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/bigint.ts000066400000000000000000000010671505437577000256160ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TBigInt', () => { it('Should guard for TBigInt', () => { const R = TypeGuard.IsBigInt(Type.BigInt()) Assert.IsTrue(R) }) it('Should not guard for TBigInt', () => { const R = TypeGuard.IsBigInt(null) Assert.IsFalse(R) }) it('Should not guard for BigInt with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsBigInt(Type.BigInt({ $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/boolean.ts000066400000000000000000000011011505437577000257460ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TBoolean', () => { it('Should guard for TBoolean', () => { const R = TypeGuard.IsBoolean(Type.Boolean()) Assert.IsTrue(R) }) it('Should not guard for TBoolean', () => { const R = TypeGuard.IsBoolean(null) Assert.IsFalse(R) }) it('Should not guard for TBoolean with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsBoolean(Type.Boolean({ $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/capitalize.ts000066400000000000000000000025321505437577000264650ustar00rootroot00000000000000import { TypeGuard, Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/Capitalize', () => { it('Should guard for Capitalize 1', () => { const T = Type.Capitalize(Type.Literal('hello'), { $id: 'hello', foo: 1 }) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'Hello') Assert.IsEqual(T.$id, 'hello') Assert.IsEqual(T.foo, 1) }) it('Should guard for Capitalize 2', () => { const T = Type.Capitalize(Type.Literal('hello')) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'Hello') }) it('Should guard for Capitalize 3', () => { const T = Type.Capitalize(Type.Union([Type.Literal('hello'), Type.Literal('world')])) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'Hello') Assert.IsEqual(T.anyOf[1].const, 'World') }) it('Should guard for Capitalize 4', () => { const T = Type.Capitalize(Type.TemplateLiteral('hello${0|1}')) Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$') }) it('Should guard for Capitalize 5', () => { const T = Type.Capitalize(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])])) Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(Hello0|Hello1)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/composite.ts000066400000000000000000000134031505437577000263410ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TComposite', () => { it('Should guard for distinct properties', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) Assert.IsTrue(TypeGuard.IsNumber(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) }) it('Should guard for overlapping properties', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() })]) Assert.IsTrue(TypeGuard.IsIntersect(T.properties.x)) // @ts-ignore Assert.IsTrue(TypeGuard.IsNumber(T.properties.x.allOf[0])) // @ts-ignore Assert.IsTrue(TypeGuard.IsNumber(T.properties.x.allOf[1])) }) it('Should not produce optional property if all properties are not optional', () => { const T = Type.Composite([Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() })]) Assert.IsFalse(TypeGuard.IsOptional(T.properties.x)) }) // Note for: https://github.com/sinclairzx81/typebox/issues/419 // Determining if a composite property is optional requires a deep check for all properties gathered during a indexed access // call. Currently, there isn't a trivial way to perform this check without running into possibly infinite instantiation issues. // The optional check is only specific to overlapping properties. Singular properties will continue to work as expected. The // rule is "if all composite properties for a key are optional, then the composite property is optional". Defer this test and // document as minor breaking change. // it('Should produce optional property if all composited properties are optional', () => { // prettier-ignore const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Optional(Type.Number()) }) ]) Assert.IsTrue(TypeGuard.IsOptional(T.properties.x)) Assert.IsEqual(T.required, undefined) }) // prettier-ignore it('Should produce required property if some composited properties are not optional', () => { const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() }) ]) Assert.IsFalse(TypeGuard.IsOptional(T.properties.x)) Assert.IsTrue(T.required!.includes('x')) }) // prettier-ignore it('Should preserve single optional property', () => { const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.Number()) }), ]) Assert.IsTrue(TypeGuard.IsOptional(T.properties.x)) Assert.IsEqual(T.required, undefined) }) // ---------------------------------------------------------------- // Intersect // ---------------------------------------------------------------- // prettier-ignore it('Should composite Intersect 1', () => { const T = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }), ]), Type.Intersect([ Type.Object({ z: Type.Number() }), ]) ]) Assert.IsEqual(T, Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() })) }) // prettier-ignore it('Should composite Intersect 2', () => { const T = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() }), ]), Type.Intersect([ Type.Object({ x: Type.Number() }), ]) ]) Assert.IsEqual(T, Type.Object({ x: Type.Intersect([Type.Intersect([Type.Number(), Type.Number()]), Type.Number()]) })) }) // prettier-ignore it('Should composite Intersect 3', () => { const T = Type.Composite([ Type.Number(), Type.Boolean() ]) Assert.IsEqual(T, Type.Object({})) }) // prettier-ignore it('Should composite Intersect 4', () => { const T = Type.Composite([ Type.Number(), Type.Boolean(), Type.Object({ x: Type.String() }) ]) Assert.IsEqual(T, Type.Object({ x: Type.String() })) }) // prettier-ignore it('Should composite Intersect 5', () => { const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.String()) }), Type.Object({ x: Type.String() }) ]) Assert.IsEqual(T, Type.Object({ x: Type.Intersect([Type.String(), Type.String()]) })) }) // prettier-ignore it('Should composite Intersect 6', () => { const T = Type.Composite([ Type.Object({ x: Type.Optional(Type.String()) }), Type.Object({ x: Type.Optional(Type.String()) }) ]) Assert.IsEqual(T, Type.Object({ x: Type.Optional(Type.Intersect([Type.String(), Type.String()])) })) }) // ---------------------------------------------------------------- // Union // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/789 // prettier-ignore it('Should composite Union 1 (non-overlapping)', () => { const T = Type.Composite([ Type.Union([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }), ]), Type.Union([ Type.Object({ z: Type.Number() }), ]) ]) Assert.IsEqual(T, Type.Object({ z: Type.Number() })) }) // https://github.com/sinclairzx81/typebox/issues/789 // prettier-ignore it('Should composite Union 2 (overlapping)', () => { const T = Type.Composite([ Type.Union([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number() }), ]), Type.Union([ Type.Object({ x: Type.Number() }), ]) ]) Assert.IsEqual(T, Type.Object({ x: Type.Intersect([Type.Union([Type.Number(), Type.Number()]), Type.Number()]) })) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/computed.ts000066400000000000000000000023331505437577000261570ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TComputed', () => { // ---------------------------------------------------------------- // Schema // ---------------------------------------------------------------- it('Should guard for Schema', () => { const T = Type.Partial(Type.Ref('A')) Assert.IsTrue(TypeGuard.IsComputed(T)) Assert.IsTrue(TypeGuard.IsSchema(T)) }) // ---------------------------------------------------------------- // Record // ---------------------------------------------------------------- it('Should guard for Record 1', () => { const T = Type.Record(Type.String(), Type.String()) Assert.IsTrue(TypeGuard.IsRecord(T)) }) it('Should guard for Record 3', () => { const T = Type.Record(Type.String(), Type.Ref('A')) Assert.IsTrue(TypeGuard.IsRecord(T)) }) it('Should guard for Record 3', () => { const T = Type.Record(Type.String(), Type.Partial(Type.Ref('A'))) Assert.IsTrue(TypeGuard.IsRecord(T)) }) it('Should guard for Record 4', () => { const T = Type.Record(Type.Ref('A'), Type.String()) Assert.IsTrue(TypeGuard.IsNever(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/const.ts000066400000000000000000000107031505437577000254650ustar00rootroot00000000000000import { TypeGuard, ValueGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TConstT', () => { // ---------------------------------------------------------------- // Identity Types // ---------------------------------------------------------------- it('Should guard for TConst 1', () => { const T = Type.Const(undefined) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsUndefined(T)) }) it('Should guard for TConst 2', () => { const T = Type.Const(null) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsNull(T)) }) it('Should guard for TConst 3', () => { const T = Type.Const(Symbol()) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsSymbol(T)) }) it('Should guard for TConst 4', () => { const T = Type.Const(1 as const) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 1) }) it('Should guard for TConst 5', () => { const T = Type.Const('hello' as const) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hello') }) it('Should guard for TConst 6', () => { const T = Type.Const(true as const) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, true) }) // ---------------------------------------------------------------- // Complex Types // ---------------------------------------------------------------- it('Should guard for TConst 7', () => { const T = Type.Const(100n as const) Assert.IsFalse(TypeGuard.IsReadonly(T)) // TS disparity because TLiteral does not support Bigint Assert.IsTrue(TypeGuard.IsBigInt(T)) }) it('Should guard for TConst 8', () => { const T = Type.Const(new Date()) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsDate(T)) }) it('Should guard for TConst 9', () => { const T = Type.Const(new Uint8Array()) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsUint8Array(T)) }) it('Should guard for TConst 10', () => { const T = Type.Const(function () {}) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsFunction(T)) Assert.IsTrue(T.parameters.length === 0) Assert.IsTrue(TypeGuard.IsUnknown(T.returns)) }) it('Should guard for TConst 11', () => { const T = Type.Const(new (class {})()) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsObject(T)) // Object types that are neither Date or Uint8Array evaluate as empty objects Assert.IsEqual(T.properties, {}) }) it('Should guard for TConst 12', () => { const T = Type.Const((function* (): any {})()) const R = ValueGuard.IsIterator((function* (): any {})()) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsAny(T)) }) it('Should guard for TConst 13', () => { const T = Type.Const((async function* (): any {})()) const R = ValueGuard.IsAsyncIterator((function* (): any {})()) Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsAny(T)) }) it('Should guard for TConst 14', () => { const T = Type.Const({ x: 1, y: { z: 2, }, } as const) // root Assert.IsFalse(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsObject(T)) // x Assert.IsTrue(TypeGuard.IsLiteral(T.properties.x)) Assert.IsEqual(T.properties.x.const, 1) // y Assert.IsTrue(TypeGuard.IsReadonly(T.properties.y)) Assert.IsTrue(TypeGuard.IsObject(T.properties.y)) // y.z Assert.IsTrue(TypeGuard.IsReadonly(T.properties.y.properties.z)) Assert.IsTrue(TypeGuard.IsLiteral(T.properties.y.properties.z)) Assert.IsEqual(T.properties.y.properties.z.const, 2) }) it('Should guard for TConst 15', () => { const T = Type.Const([1, 2, 3] as const) // root (arrays are always readonly as root) Assert.IsTrue(TypeGuard.IsReadonly(T)) Assert.IsTrue(TypeGuard.IsTuple(T)) Assert.IsTrue(T.items?.length === 3) // 0 Assert.IsFalse(TypeGuard.IsReadonly(T.items![0])) Assert.IsTrue(TypeGuard.IsLiteral(T.items![0])) // 1 Assert.IsFalse(TypeGuard.IsReadonly(T.items![1])) Assert.IsTrue(TypeGuard.IsLiteral(T.items![1])) // 2 Assert.IsFalse(TypeGuard.IsReadonly(T.items![2])) Assert.IsTrue(TypeGuard.IsLiteral(T.items![2])) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/constructor.ts000066400000000000000000000026071505437577000267300ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TConstructor', () => { it('Should guard for TConstructor', () => { const R = TypeGuard.IsConstructor(Type.Constructor([], Type.Number())) Assert.IsTrue(R) }) it('Should not guard for TConstructor', () => { const R = TypeGuard.IsConstructor(null) Assert.IsFalse(R) }) it('Should not guard for TConstructor with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsConstructor(Type.Constructor([], Type.Number(), { $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TConstructor with invalid Params', () => { const R = TypeGuard.IsConstructor(Type.Constructor([{} as any, {} as any], Type.Number())) Assert.IsFalse(R) }) it('Should not guard for TConstructor with invalid Return', () => { const R = TypeGuard.IsConstructor(Type.Constructor([], {} as any)) Assert.IsFalse(R) }) it('Should guard for TConstructor with empty Rest Tuple', () => { const R = TypeGuard.IsConstructor(Type.Constructor(Type.Rest(Type.Tuple([])), Type.Number())) Assert.IsTrue(R) }) it('Should guard for TConstructor with Rest Tuple', () => { const R = TypeGuard.IsConstructor(Type.Constructor(Type.Rest(Type.Tuple([Type.Number(), Type.String()])), Type.Number())) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/date.ts000066400000000000000000000027671505437577000252670ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TDate', () => { it('Should guard for TDate', () => { const R = TypeGuard.IsDate(Type.Date()) Assert.IsTrue(R) }) it('Should not guard for TDate', () => { const R = TypeGuard.IsDate(null) Assert.IsFalse(R) }) it('Should not guard for TDate with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsDate(Type.Date({ $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TDate with invalid exclusiveMaximumTimestamp', () => { // @ts-ignore const R = TypeGuard.IsDate(Type.Date({ exclusiveMaximumTimestamp: '1' })) Assert.IsFalse(R) }) it('Should not guard for TDate with invalid exclusiveMinimumTimestamp', () => { // @ts-ignore const R = TypeGuard.IsDate(Type.Date({ exclusiveMinimumTimestamp: '1' })) Assert.IsFalse(R) }) it('Should not guard for TDate with invalid maximumTimestamp', () => { // @ts-ignore const R = TypeGuard.IsDate(Type.Date({ maximumTimestamp: '1' })) Assert.IsFalse(R) }) it('Should not guard for TDate with invalid minimumTimestamp', () => { // @ts-ignore const R = TypeGuard.IsDate(Type.Date({ minimumTimestamp: '1' })) Assert.IsFalse(R) }) it('Should not guard for TDate with invalid multipleOfTimestamp', () => { // @ts-ignore const R = TypeGuard.IsDate(Type.Date({ multipleOfTimestamp: '1' })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/enum.ts000066400000000000000000000101331505437577000253000ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TEnum', () => { // ---------------------------------------------------------------- // Options // ---------------------------------------------------------------- it('Should guard for Options 1', () => { const T = Type.Enum({ x: 1 }, { extra: 'hello', $id: 'T' }) Assert.IsEqual(T.extra, 'hello') Assert.IsEqual(T.$id, 'T') }) it('Should guard for Options 2', () => { enum E { x, } const T = Type.Enum(E, { extra: 'hello', $id: 'T' }) Assert.IsEqual(T.extra, 'hello') Assert.IsEqual(T.$id, 'T') }) it('Should guard for Options 3', () => { enum E {} const T = Type.Enum(E, { extra: 'hello', $id: 'T' }) Assert.IsEqual(T.extra, 'hello') Assert.IsEqual(T.$id, 'T') }) it('Should guard for Options 4', () => { const T = Type.Enum({}, { extra: 'hello', $id: 'T' }) Assert.IsEqual(T.extra, 'hello') Assert.IsEqual(T.$id, 'T') }) // ---------------------------------------------------------------- // Empty // ---------------------------------------------------------------- it('Should guard for Empty 1', () => { const T = Type.Enum({}) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should guard for Empty 2', () => { enum E {} const T = Type.Enum(E) Assert.IsTrue(TypeGuard.IsNever(T)) }) // ---------------------------------------------------------------- // Enum // ---------------------------------------------------------------- it('Should guard for TEnum Enum 0', () => { enum E {} const T = Type.Enum(E) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should guard for TEnum Enum 1', () => { enum E { A, } const T = Type.Enum(E) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, E.A) }) it('Should guard for TEnum Enum 2', () => { enum E { A = 1, B = 2, C = 3, } const T = Type.Enum(E) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, E.A) Assert.IsEqual(T.anyOf[1].const, E.B) Assert.IsEqual(T.anyOf[2].const, E.C) }) it('Should guard for TEnum Enum 3', () => { enum E { A = 'X', B = 'Y', C = 'Z', } const T = Type.Enum(E) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, E.A) Assert.IsEqual(T.anyOf[1].const, E.B) Assert.IsEqual(T.anyOf[2].const, E.C) }) it('Should guard for TEnum Enum 4', () => { enum E { A = 'X', B = 'Y', C = 'X', } const T = Type.Enum(E) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, E.A) Assert.IsEqual(T.anyOf[1].const, E.B) Assert.IsEqual(T.anyOf.length, 2) }) // ---------------------------------------------------------------- // Object Literal // ---------------------------------------------------------------- it('Should guard for TEnum Object Literal 0', () => { const T = Type.Enum({}) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should guard for TEnum Object Literal 1', () => { const T = Type.Enum({ A: 1 }) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 1) }) it('Should guard for TEnum Object Literal 2', () => { const T = Type.Enum({ A: 1, B: 2, C: 3, }) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 1) Assert.IsEqual(T.anyOf[1].const, 2) Assert.IsEqual(T.anyOf[2].const, 3) }) it('Should guard for TEnum Object Literal 3', () => { const T = Type.Enum({ A: 'X', B: 'Y', C: 'Z', }) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'X') Assert.IsEqual(T.anyOf[1].const, 'Y') Assert.IsEqual(T.anyOf[2].const, 'Z') }) it('Should guard for TEnum Object Literal 4', () => { const T = Type.Enum({ A: 'X', B: 'Y', C: 'X', }) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'X') Assert.IsEqual(T.anyOf[1].const, 'Y') Assert.IsEqual(T.anyOf.length, 2) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/exclude.ts000066400000000000000000000114661505437577000257770ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TExclude', () => { it('Should exclude string from number', () => { const T = Type.Exclude(Type.String(), Type.Number()) Assert.IsTrue(TypeGuard.IsString(T)) }) it('Should exclude string from string', () => { const T = Type.Exclude(Type.String(), Type.String()) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should exclude string | number | boolean from string', () => { const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String()) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsNumber(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsBoolean(T.anyOf[1])) }) it('Should exclude string | number | boolean from string | boolean', () => { const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.Union([Type.String(), Type.Boolean()])) Assert.IsTrue(TypeGuard.IsNumber(T)) }) // ------------------------------------------------------------------------ // TemplateLiteral | TemplateLiteral // ------------------------------------------------------------------------ it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Exclude(A, B) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const)) }) // ------------------------------------------------------------------------ // TemplateLiteral | Union 1 // ------------------------------------------------------------------------ it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Exclude(A, B) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A')]) const T = Type.Exclude(A, B) Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const)) }) // ------------------------------------------------------------------------ // Union | TemplateLiteral 1 // ------------------------------------------------------------------------ it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Exclude(A, B) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const)) }) it('Should exclude with options', () => { const A = Type.String() const B = Type.String() const T = Type.Exclude(A, B, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/extract.ts000066400000000000000000000123541505437577000260150ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TExtract', () => { it('Should extract string from number', () => { const T = Type.Extract(Type.String(), Type.Number()) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should extract string from string', () => { const T = Type.Extract(Type.String(), Type.String()) Assert.IsTrue(TypeGuard.IsString(T)) }) it('Should extract string | number | boolean from string', () => { const T = Type.Extract(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String()) Assert.IsTrue(TypeGuard.IsString(T)) }) it('Should extract string | number | boolean from string | boolean', () => { const T = Type.Extract(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.Union([Type.String(), Type.Boolean()])) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsString(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsBoolean(T.anyOf[1])) }) // ------------------------------------------------------------------------ // TemplateLiteral | TemplateLiteral // ------------------------------------------------------------------------ it('Should extract TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const)) }) it('Should extract TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const)) }) it('Should extract TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A'].includes(T.const)) }) // ------------------------------------------------------------------------ // TemplateLiteral | Union 1 // ------------------------------------------------------------------------ it('Should extract TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const)) }) it('Should extract TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const)) }) it('Should extract TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A')]) const T = Type.Extract(A, B) Assert.IsTrue(['A'].includes(T.const)) }) // ------------------------------------------------------------------------ // Union | TemplateLiteral 1 // ------------------------------------------------------------------------ it('Should extract Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[1].const)) Assert.IsTrue(['A', 'B', 'C'].includes(T.anyOf[2].const)) }) it('Should extract Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['A', 'B'].includes(T.anyOf[1].const)) }) it('Should extract Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Extract(A, B) Assert.IsTrue(['A'].includes(T.const)) }) it('Should extract with options', () => { const A = Type.String() const B = Type.String() const T = Type.Extract(A, B, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/function.ts000066400000000000000000000025101505437577000261610ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TFunction', () => { it('Should guard for TFunction', () => { const R = TypeGuard.IsFunction(Type.Function([], Type.Number())) Assert.IsTrue(R) }) it('Should not guard for TFunction', () => { const R = TypeGuard.IsFunction(null) Assert.IsFalse(R) }) it('Should not guard for TFunction with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsFunction(Type.Function([], Type.Number(), { $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TFunction with invalid Params', () => { const R = TypeGuard.IsFunction(Type.Function([{} as any, {} as any], Type.Number())) Assert.IsFalse(R) }) it('Should not guard for TFunction with invalid Return', () => { const R = TypeGuard.IsFunction(Type.Function([], {} as any)) Assert.IsFalse(R) }) it('Should guard for TFunction with empty Rest Tuple', () => { const R = TypeGuard.IsFunction(Type.Function(Type.Rest(Type.Tuple([])), Type.Number())) Assert.IsTrue(R) }) it('Should guard for TFunction with Rest Tuple', () => { const R = TypeGuard.IsFunction(Type.Function(Type.Rest(Type.Tuple([Type.Number(), Type.String()])), Type.Number())) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/import.ts000066400000000000000000000265031505437577000256560ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TImport', () => { it('Should guard for TImport', () => { const Module = Type.Module({ A: Type.String(), }) const A = Module.Import('A') const N = A.$defs[A.$ref] Assert.IsTrue(TypeGuard.IsImport(A)) Assert.IsTrue(TypeGuard.IsString(N)) }) // ---------------------------------------------------------------- // Computed: Options // ---------------------------------------------------------------- it('Should guard for TImport with Options 1', () => { const Module = Type.Module({ A: Type.String(), }) const A = Module.Import('A', { format: 'string' }) const N = A.$defs[A.$ref] Assert.IsTrue(TypeGuard.IsImport(A)) Assert.IsTrue(TypeGuard.IsString(N)) Assert.IsTrue(N.format === 'string') }) it('Should guard for TImport with Options 2', () => { const Module = Type.Module({ R: Type.Object({ x: Type.Number() }), A: Type.Ref('R'), }) const A = Module.Import('A', { test: 'test' }) const N = A.$defs[A.$ref] Assert.IsTrue(TypeGuard.IsImport(A)) Assert.IsTrue(TypeGuard.IsRef(N)) Assert.IsTrue(N.test === 'test') }) it('Should guard for TImport with Options 3', () => { const Module = Type.Module({ R: Type.Object({ x: Type.Number() }), A: Type.Partial(Type.Ref('R')), }) const A = Module.Import('A', { additionalProperties: false }) const N = A.$defs[A.$ref] Assert.IsTrue(TypeGuard.IsImport(A)) Assert.IsTrue(TypeGuard.IsObject(N)) Assert.IsTrue(N.additionalProperties === false) }) // ---------------------------------------------------------------- // Computed: Awaited // ---------------------------------------------------------------- it('Should compute for Awaited', () => { const Module = Type.Module({ T: Type.Promise(Type.String()), R: Type.Awaited(Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsString(T.$defs['R'])) }) // ---------------------------------------------------------------- // Computed: Index (Note: Pending Reimplementation of Index) // ---------------------------------------------------------------- it('Should compute for Index 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.String() }), I: Type.Literal('x'), R: Type.Index(Type.Ref('T'), Type.Ref('I')) as never, // fail }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsNumber(T.$defs['R'])) }) // ---------------------------------------------------------------- // Computed: Omit // ---------------------------------------------------------------- it('Should compute for Omit 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.Number() }), R: Type.Omit(Type.Ref('T'), Type.Literal('x')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsNumber(T.$defs['R'].properties.y)) // @ts-ignore Assert.IsTrue(T.$defs['R'].properties.x === undefined) }) it('Should compute for Omit 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.Number() }), K: Type.Literal('x'), R: Type.Omit(Type.Ref('T'), Type.Ref('K')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsNumber(T.$defs['R'].properties.y)) // @ts-ignore Assert.IsTrue(T.$defs['R'].properties.x === undefined) }) // ---------------------------------------------------------------- // Computed: Partial // ---------------------------------------------------------------- it('Should compute for Partial', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number() }), R: Type.Partial(Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsNumber(T.$defs['R'].properties.x)) Assert.IsTrue(TypeGuard.IsOptional(T.$defs['R'].properties.x)) }) // ---------------------------------------------------------------- // Computed: Pick // ---------------------------------------------------------------- it('Should compute for Pick 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.Number() }), R: Type.Pick(Type.Ref('T'), Type.Literal('x')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsNumber(T.$defs['R'].properties.x)) // @ts-ignore Assert.IsTrue(T.$defs['R'].properties.y === undefined) }) it('Should compute for Pick 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.Number() }), K: Type.Literal('x'), R: Type.Pick(Type.Ref('T'), Type.Ref('K')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsNumber(T.$defs['R'].properties.x)) // @ts-ignore Assert.IsTrue(T.$defs['R'].properties.y === undefined) }) // ---------------------------------------------------------------- // Computed: Record // ---------------------------------------------------------------- it('Should compute for Record 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.String() }), R: Type.Record(Type.String(), Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsRecord(T.$defs['R'])) // note: TRecord> are not computed. Only the Key is // computed as TypeBox needs to make a deferred call to transform from // TRecord to TObject for finite keys. Assert.IsTrue(TypeGuard.IsRef(T.$defs['R'].patternProperties['^(.*)$'])) Assert.IsTrue(T.$defs['R'].patternProperties['^(.*)$'].$ref === 'T') }) it('Should compute for Record 2', () => { const Module = Type.Module({ T: Type.Number(), R: Type.Record(Type.Union([Type.Literal('x'), Type.Literal('y')]), Type.Ref('T')), }) // Retain reference if not computed const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsRef(T.$defs['R'].properties.x)) Assert.IsTrue(TypeGuard.IsRef(T.$defs['R'].properties.y)) }) it('Should compute for Record 3', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number() }), R: Type.Record(Type.Union([Type.Literal('x'), Type.Literal('y')]), Type.Partial(Type.Ref('T'))), }) // Dereference if computed const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'].properties.x)) Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'].properties.y)) }) // ---------------------------------------------------------------- // Computed: Required // ---------------------------------------------------------------- it('Should compute for Required', () => { const Module = Type.Module({ T: Type.Partial(Type.Object({ x: Type.Number() })), R: Type.Required(Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsObject(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsNumber(T.$defs['R'].properties.x)) Assert.IsFalse(TypeGuard.IsOptional(T.$defs['R'].properties.x)) }) // ---------------------------------------------------------------- // Computed: KeyOf // ---------------------------------------------------------------- it('Should compute for KeyOf', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Number(), y: Type.String() }), R: Type.KeyOf(Type.Ref('T')), }) const T = Module.Import('R') Assert.IsTrue(TypeGuard.IsUnion(T.$defs['R'])) Assert.IsTrue(TypeGuard.IsLiteral(T.$defs['R'].anyOf[0])) Assert.IsTrue(TypeGuard.IsLiteral(T.$defs['R'].anyOf[1])) Assert.IsTrue(T.$defs['R'].anyOf[0].const === 'x') Assert.IsTrue(T.$defs['R'].anyOf[1].const === 'y') }) // ---------------------------------------------------------------- // Modifiers: 1 // ---------------------------------------------------------------- it('Should compute for Modifiers 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Null()), y: Type.Readonly(Type.Null()), z: Type.Optional(Type.Null()), w: Type.Null(), }), }) const T = Module.Import('T') const R = T.$defs[T.$ref] Assert.IsTrue(TypeGuard.IsObject(R)) Assert.IsTrue(TypeGuard.IsNull(R.properties.x)) Assert.IsTrue(TypeGuard.IsReadonly(R.properties.x)) Assert.IsTrue(TypeGuard.IsOptional(R.properties.x)) Assert.IsTrue(TypeGuard.IsNull(R.properties.y)) Assert.IsTrue(TypeGuard.IsReadonly(R.properties.y)) Assert.IsFalse(TypeGuard.IsOptional(R.properties.y)) Assert.IsTrue(TypeGuard.IsNull(R.properties.z)) Assert.IsTrue(TypeGuard.IsOptional(R.properties.z)) Assert.IsFalse(TypeGuard.IsReadonly(R.properties.z)) Assert.IsTrue(TypeGuard.IsNull(R.properties.w)) Assert.IsFalse(TypeGuard.IsOptional(R.properties.w)) Assert.IsFalse(TypeGuard.IsReadonly(R.properties.w)) }) // ---------------------------------------------------------------- // Modifiers: 2 // ---------------------------------------------------------------- it('Should compute for Modifiers 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Array(Type.Null())), y: Type.Readonly(Type.Array(Type.Null())), z: Type.Optional(Type.Array(Type.Null())), w: Type.Array(Type.Null()), }), }) const T = Module.Import('T') const R = T.$defs[T.$ref] Assert.IsTrue(TypeGuard.IsObject(R)) Assert.IsTrue(TypeGuard.IsArray(R.properties.x)) Assert.IsTrue(TypeGuard.IsNull(R.properties.x.items)) Assert.IsTrue(TypeGuard.IsReadonly(R.properties.x)) Assert.IsTrue(TypeGuard.IsOptional(R.properties.x)) Assert.IsTrue(TypeGuard.IsArray(R.properties.y)) Assert.IsTrue(TypeGuard.IsNull(R.properties.y.items)) Assert.IsTrue(TypeGuard.IsReadonly(R.properties.y)) Assert.IsFalse(TypeGuard.IsOptional(R.properties.y)) Assert.IsTrue(TypeGuard.IsArray(R.properties.z)) Assert.IsTrue(TypeGuard.IsNull(R.properties.z.items)) Assert.IsTrue(TypeGuard.IsOptional(R.properties.z)) Assert.IsFalse(TypeGuard.IsReadonly(R.properties.z)) Assert.IsTrue(TypeGuard.IsArray(R.properties.w)) Assert.IsTrue(TypeGuard.IsNull(R.properties.w.items)) Assert.IsFalse(TypeGuard.IsOptional(R.properties.w)) Assert.IsFalse(TypeGuard.IsReadonly(R.properties.w)) }) // ---------------------------------------------------------------- // Modifiers: 3 // ---------------------------------------------------------------- it('Should compute for Modifiers 3', () => { const Module = Type.Module({ T: Type.Object({ x: Type.Array(Type.Null()), }), // Computed Partial U: Type.Partial(Type.Ref('T')), }) const T = Module.Import('U') const R = T.$defs[T.$ref] Assert.IsTrue(TypeGuard.IsObject(R)) Assert.IsTrue(TypeGuard.IsArray(R.properties.x)) Assert.IsTrue(TypeGuard.IsNull(R.properties.x.items)) Assert.IsTrue(TypeGuard.IsOptional(R.properties.x)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/index.ts000066400000000000000000000017671505437577000254600ustar00rootroot00000000000000import './any' import './argument' import './array' import './async-iterator' import './awaited' import './bigint' import './boolean' import './capitalize' import './composite' import './computed' import './const' import './constructor' import './date' import './enum' import './exclude' import './extract' import './function' import './import' import './indexed' import './integer' import './intersect' import './iterator' import './keyof' import './kind' import './literal' import './lowercase' import './mapped' import './not' import './null' import './number' import './object' import './omit' import './partial' import './pick' import './promise' import './record' import './recursive' import './ref' import './regexp' import './required' import './rest' import './string' import './symbol' import './template-literal' import './this' import './tuple' import './uint8array' import './uncapitalize' import './undefined' import './union' import './unknown' import './unsafe' import './uppercase' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/indexed.ts000066400000000000000000000262171505437577000257660ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TIndex', () => { it('Should Index 1', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsNumber(I)) }) it('Should Index 2', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Should Index 3', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const I = Type.Index(T, Type.KeyOf(T)) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Should Index 4', () => { const T = Type.Object({ ab: Type.Number(), ac: Type.String(), }) const I = Type.Index(T, Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])])) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Should Index 5', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.String() })]) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Should Index 6', () => { const T = Type.Union([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.String() })]) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Should Index 7', () => { const T = Type.Array(Type.Null()) const I = Type.Index(T, Type.Number()) Assert.IsTrue(TypeGuard.IsNull(I)) }) it('Should Index 6', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [0]) Assert.IsTrue(TypeGuard.IsLiteralString(I)) Assert.IsEqual(I.const, 'hello') }) it('Should Index 8', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [1]) Assert.IsTrue(TypeGuard.IsLiteralString(I)) Assert.IsEqual(I.const, 'world') }) it('Should Index 9', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [0, 1]) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsEqual(I.anyOf[0].const, 'hello') Assert.IsEqual(I.anyOf[1].const, 'world') }) it('Should Index 10', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [1, 0]) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsEqual(I.anyOf[0].const, 'world') Assert.IsEqual(I.anyOf[1].const, 'hello') }) it('Should Index 11', () => { const T = Type.Tuple([Type.Literal('hello'), Type.Literal('world')]) const I = Type.Index(T, [0, 0, 0, 1]) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsEqual(I.anyOf[0].const, 'hello') Assert.IsEqual(I.anyOf[1].const, 'hello') Assert.IsEqual(I.anyOf[2].const, 'hello') Assert.IsEqual(I.anyOf[3].const, 'world') }) it('Should Index 12', () => { const T = Type.Tuple([Type.String(), Type.Boolean()]) const I = Type.Index(T, Type.Number()) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsBoolean(I.anyOf[1])) }) it('Should Index 13', () => { const T = Type.Tuple([Type.String()]) const I = Type.Index(T, Type.Number()) Assert.IsTrue(TypeGuard.IsString(I)) }) it('Should Index 14', () => { const T = Type.Tuple([]) const I = Type.Index(T, Type.Number()) Assert.IsTrue(TypeGuard.IsNever(I)) }) it('Should Index 15', () => { const T = Type.Object({ 0: Type.Number(), }) const I = Type.Index(T, Type.Literal(0)) Assert.IsTrue(TypeGuard.IsNumber(I)) }) it('Should Index 16', () => { const T = Type.Object({ 0: Type.Number(), }) const I = Type.Index(T, Type.Literal('0')) Assert.IsTrue(TypeGuard.IsNumber(I)) }) it('Should Index 17', () => { const T = Type.Object({ '0': Type.Number(), }) const I = Type.Index(T, Type.Literal(0)) Assert.IsTrue(TypeGuard.IsNumber(I)) }) it('Should Index 18', () => { const T = Type.Object({ '0': Type.Number(), }) const I = Type.Index(T, Type.Literal('0')) Assert.IsTrue(TypeGuard.IsNumber(I)) }) it('Should Index 19', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.String(), 2: Type.Boolean(), }) const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal(2)])) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsBoolean(I.anyOf[1])) }) it('Should Index 20', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.String(), 2: Type.Boolean(), }) const I = Type.Index(T, Type.BigInt()) Assert.IsTrue(TypeGuard.IsNever(I)) }) it('Should Index 21', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.String(), 2: Type.Boolean(), }) const I = Type.Index(T, Type.Object({})) Assert.IsTrue(TypeGuard.IsNever(I)) }) it('Should Index 22', () => { const A = Type.Object({ x: Type.Literal('A') }) const B = Type.Object({ x: Type.Literal('B') }) const C = Type.Object({ x: Type.Literal('C') }) const D = Type.Object({ x: Type.Literal('D') }) const T = Type.Intersect([A, B, C, D]) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsIntersect(I)) Assert.IsTrue(TypeGuard.IsLiteral(I.allOf[0])) Assert.IsTrue(TypeGuard.IsLiteral(I.allOf[1])) Assert.IsTrue(TypeGuard.IsLiteral(I.allOf[2])) Assert.IsTrue(TypeGuard.IsLiteral(I.allOf[3])) }) it('Should Index 23', () => { const A = Type.Object({ x: Type.Literal('A') }) const B = Type.Object({ x: Type.Literal('B') }) const C = Type.Object({ x: Type.Literal('C') }) const D = Type.Object({ x: Type.Literal('D') }) const T = Type.Union([A, B, C, D]) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsLiteral(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsLiteral(I.anyOf[1])) Assert.IsTrue(TypeGuard.IsLiteral(I.anyOf[2])) Assert.IsTrue(TypeGuard.IsLiteral(I.anyOf[3])) }) it('Should Index 24', () => { const A = Type.Object({ x: Type.Literal('A'), y: Type.Number() }) const B = Type.Object({ x: Type.Literal('B') }) const C = Type.Object({ x: Type.Literal('C') }) const D = Type.Object({ x: Type.Literal('D') }) const T = Type.Intersect([A, B, C, D]) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsIntersect(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) }) it('Should Index 25', () => { const A = Type.Object({ x: Type.Literal('A'), y: Type.Number() }) const B = Type.Object({ x: Type.Literal('B'), y: Type.String() }) const C = Type.Object({ x: Type.Literal('C') }) const D = Type.Object({ x: Type.Literal('D') }) const T = Type.Intersect([A, B, C, D]) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsIntersect(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsIntersect(I.anyOf[1])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1].allOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1].allOf[1])) }) it('Should Index 26', () => { const T = Type.Recursive((This) => Type.Object({ x: Type.String(), y: Type.Number(), z: This, }), ) const I = Type.Index(T, ['x', 'y', 'z']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) Assert.IsTrue(TypeGuard.IsThis(I.anyOf[2])) }) it('Should Index 27', () => { const T = Type.Object({ 0: Type.String(), 1: Type.Number(), }) const I = Type.Index(T, [0, 1]) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) }) it('Should Index 28', () => { const T = Type.Object({ 0: Type.String(), '1': Type.Number(), }) const I = Type.Index(T, [0, '1']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) }) it('Should Index 29', () => { const T = Type.Object({ 0: Type.String(), '1': Type.Number(), }) const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal('1')])) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) }) it('Should Index 30', () => { const T = Type.Object({ 0: Type.String(), '1': Type.Number(), }) const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal(1)])) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) // Note: Expect TNever for anyOf[1] but permit for TNumber due to IndexedAccess // Resolve() which currently cannot differentiate between string and numeric keys // on the object. This may be resolvable in later revisions, but test for this // fall-through to ensure case is documented. For review. }) // -------------------------------------------------------- // Modifier Optional Indexing // -------------------------------------------------------- it('Should Index 31', () => { const T = Type.Object({ x: Type.Optional(Type.String()), y: Type.Number(), }) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsString(I)) }) it('Should Index 32', () => { const T = Type.Object({ x: Type.Optional(Type.String()), y: Type.Number(), }) const I = Type.Index(T, ['y']) Assert.IsFalse(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsNumber(I)) }) it('Should Index 33', () => { const T = Type.Object({ x: Type.Optional(Type.String()), y: Type.Number(), }) const I = Type.Index(T, ['x', 'y']) Assert.IsTrue(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) }) it('Should Index 34', () => { const T = Type.String() const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsNever(I)) }) it('Should Index 35', () => { const T = Type.Array(Type.String()) const I = Type.Index(T, Type.Number()) Assert.IsTrue(TypeGuard.IsString(I)) }) it('Should Index 36', () => { const T = Type.Array(Type.String()) const I = Type.Index(T, ['[number]']) Assert.IsTrue(TypeGuard.IsString(I)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/integer.ts000066400000000000000000000027451505437577000260030ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TInteger', () => { it('Should guard for TInteger', () => { const R = TypeGuard.IsInteger(Type.Integer()) Assert.IsTrue(R) }) it('Should not guard for TInteger', () => { const R = TypeGuard.IsInteger(null) Assert.IsFalse(R) }) it('Should not guard for TInteger with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsInteger(Type.Integer({ $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TInteger with invalid multipleOf', () => { // @ts-ignore const R = TypeGuard.IsInteger(Type.Integer({ multipleOf: '1' })) Assert.IsFalse(R) }) it('Should not guard for TInteger with invalid minimum', () => { // @ts-ignore const R = TypeGuard.IsInteger(Type.Integer({ minimum: '1' })) Assert.IsFalse(R) }) it('Should not guard for TInteger with invalid maximum', () => { // @ts-ignore const R = TypeGuard.IsInteger(Type.Integer({ maximum: '1' })) Assert.IsFalse(R) }) it('Should not guard for TInteger with invalid exclusiveMinimum', () => { // @ts-ignore const R = TypeGuard.IsInteger(Type.Integer({ exclusiveMinimum: '1' })) Assert.IsFalse(R) }) it('Should not guard for TInteger with invalid exclusiveMaximum', () => { // @ts-ignore const R = TypeGuard.IsInteger(Type.Integer({ exclusiveMaximum: '1' })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/intersect.ts000066400000000000000000000016601505437577000263410ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TIntersect', () => { it('Should guard for TIntersect', () => { const R = TypeGuard.IsIntersect( Type.Intersect([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]), ) Assert.IsTrue(R) }) it('Should not guard for TIntersect', () => { const R = TypeGuard.IsIntersect( Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]), ) Assert.IsFalse(R) }) it('Should throw for intersected transform types', () => { const N = Type.Transform(Type.Number()) .Decode((value) => value) .Encode((value) => value) Assert.Throws(() => Type.Intersect([N, N])) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/iterator.ts000066400000000000000000000012171505437577000261700ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TIterator', () => { it('Should guard for TIterator', () => { const T = Type.Iterator(Type.Any()) const R = TypeGuard.IsIterator(T) Assert.IsTrue(R) }) it('Should not guard for TIterator', () => { const T = null const R = TypeGuard.IsIterator(T) Assert.IsFalse(R) }) it('Should not guard for TIterator with invalid $id', () => { //@ts-ignore const T = Type.Iterator(Type.Any(), { $id: 1 }) const R = TypeGuard.IsIterator(T) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/keyof.ts000066400000000000000000000040121505437577000254500ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TKeyOf', () => { it('Should KeyOf 1', () => { const T = Type.Object({ x: Type.Number(), y: Type.Number(), }) const K = Type.KeyOf(T) Assert.IsTrue(TypeGuard.IsUnion(K)) Assert.IsTrue(TypeGuard.IsLiteral(K.anyOf[0])) Assert.IsTrue(TypeGuard.IsLiteral(K.anyOf[1])) }) it('Should KeyOf 2', () => { const T = Type.Recursive((Self) => Type.Object({ x: Type.Number(), y: Type.Array(Self), }), ) const K = Type.KeyOf(T) Assert.IsTrue(TypeGuard.IsUnion(K)) Assert.IsTrue(TypeGuard.IsLiteral(K.anyOf[0])) Assert.IsTrue(TypeGuard.IsLiteral(K.anyOf[1])) }) it('Should KeyOf 3', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]) const K = Type.KeyOf(T) Assert.IsTrue(TypeGuard.IsUnion(K)) Assert.IsTrue(TypeGuard.IsLiteral(K.anyOf[0])) Assert.IsTrue(TypeGuard.IsLiteral(K.anyOf[1])) }) it('Should KeyOf 4', () => { const T = Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]) const K = Type.KeyOf(T) Assert.IsTrue(TypeGuard.IsNever(K)) }) it('Should KeyOf 5', () => { const T = Type.Null() const K = Type.KeyOf(T) Assert.IsTrue(TypeGuard.IsNever(K)) }) it('Should KeyOf 6', () => { const T = Type.Array(Type.Number()) const K = Type.KeyOf(T) Assert.IsTrue(TypeGuard.IsNumber(K)) }) it('Should KeyOf 7', () => { const T = Type.Tuple([]) const K = Type.KeyOf(T) Assert.IsTrue(TypeGuard.IsNever(K)) }) it('Should KeyOf 8', () => { const T = Type.Tuple([Type.Number(), Type.Null()]) const K = Type.KeyOf(T) Assert.IsTrue(TypeGuard.IsUnion(K)) Assert.IsEqual(K.anyOf[0].const, '0') Assert.IsEqual(K.anyOf[1].const, '1') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/kind.ts000066400000000000000000000005251505437577000252650ustar00rootroot00000000000000import { TypeGuard, Kind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TKind', () => { it('Should guard 1', () => { const T = { [Kind]: 'Kind' } Assert.IsTrue(TypeGuard.IsKind(T)) }) it('Should guard 2', () => { const T = {} Assert.IsFalse(TypeGuard.IsKind(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/literal.ts000066400000000000000000000017661505437577000260040ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TLiteral', () => { it('Should guard for TLiteral of String', () => { const R = TypeGuard.IsLiteral(Type.Literal('hello')) Assert.IsTrue(R) }) it('Should guard for TLiteral of Number', () => { const R = TypeGuard.IsLiteral(Type.Literal(42)) Assert.IsTrue(R) }) it('Should guard for TLiteral of Boolean', () => { const R = TypeGuard.IsLiteral(Type.Literal(true)) Assert.IsTrue(R) }) it('Should not guard for TLiteral of Null', () => { // @ts-ignore const R = TypeGuard.IsLiteral(Type.Literal(null)) Assert.IsFalse(R) }) it('Should not guard for TLiteral', () => { const R = TypeGuard.IsLiteral(null) Assert.IsFalse(R) }) it('Should not guard for TLiteral with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsLiteral(Type.Literal(42, { $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/lowercase.ts000066400000000000000000000025171505437577000263270ustar00rootroot00000000000000import { TypeGuard, Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/Lowercase', () => { it('Should guard for Lowercase 1', () => { const T = Type.Lowercase(Type.Literal('HELLO'), { $id: 'hello', foo: 1 }) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hello') Assert.IsEqual(T.$id, 'hello') Assert.IsEqual(T.foo, 1) }) it('Should guard for Lowercase 2', () => { const T = Type.Lowercase(Type.Literal('HELLO')) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hello') }) it('Should guard for Lowercase 3', () => { const T = Type.Lowercase(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')])) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'hello') Assert.IsEqual(T.anyOf[1].const, 'world') }) it('Should guard for Lowercase 4', () => { const T = Type.Lowercase(Type.TemplateLiteral('HELLO${0|1}')) Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hello0|hello1)$') }) it('Should guard for Lowercase 5', () => { const T = Type.Lowercase(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(0), Type.Literal(1)])])) Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hello0|hello1)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/mapped.ts000066400000000000000000000450251505437577000256120ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' // prettier-ignore describe('guard/type/Mapped', () => { it('Should guard mapped 1', () => { const T = Type.Mapped(Type.Union([ Type.Literal('x'), Type.Literal('y'), Type.Literal('z'), ]), _ => Type.Number(), { custom: 1 }) Assert.IsEqual(T, Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() }, { custom: 1 })) }) it('Should guard mapped 2', () => { const T = Type.Mapped(Type.Union([ Type.Literal('x'), Type.Literal('y'), Type.Literal('z'), ]), _ => Type.Number()) Assert.IsEqual(T, Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() })) }) it('Should guard mapped 3', () => { const T = Type.Mapped(Type.Union([ Type.Literal('x'), Type.Literal('y'), Type.Literal('z'), ]), K => K) Assert.IsEqual(T, Type.Object({ x: Type.Literal('x'), y: Type.Literal('y'), z: Type.Literal('z'), })) }) it('Should guard mapped 4', () => { const T = Type.Mapped(Type.TemplateLiteral('${0|1}${0|1}'), K => Type.Number()) Assert.IsEqual(T, Type.Object({ '00': Type.Number(), '01': Type.Number(), '10': Type.Number(), '11': Type.Number(), })) }) it('Should guard mapped 5', () => { const T = Type.Mapped(Type.TemplateLiteral('${a|b}'), X => Type.Mapped(Type.TemplateLiteral('${c|d}'), Y => Type.Mapped(Type.TemplateLiteral('${e|f}'), Z => Type.Tuple([X, Y, Z]) ) ) ) Assert.IsEqual(T, Type.Object({ a: Type.Object({ c: Type.Object({ e: Type.Tuple([Type.Literal("a"), Type.Literal("c"), Type.Literal("e")]), f: Type.Tuple([Type.Literal("a"), Type.Literal("c"), Type.Literal("f")]) }), d: Type.Object({ e: Type.Tuple([Type.Literal("a"), Type.Literal("d"), Type.Literal("e")]), f: Type.Tuple([Type.Literal("a"), Type.Literal("d"), Type.Literal("f")]) }), }), b: Type.Object({ c: Type.Object({ e: Type.Tuple([Type.Literal("b"), Type.Literal("c"), Type.Literal("e")]), f: Type.Tuple([Type.Literal("b"), Type.Literal("c"), Type.Literal("f")]) }), d: Type.Object({ e: Type.Tuple([Type.Literal("b"), Type.Literal("d"), Type.Literal("e")]), f: Type.Tuple([Type.Literal("b"), Type.Literal("d"), Type.Literal("f")]) }), }), })) }) it('Should guard mapped 6', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => K) Assert.IsEqual(M, Type.Object({ x: Type.Literal('x'), y: Type.Literal('y'), z: Type.Literal('z') })) }) it('Should guard mapped 7', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K)) Assert.IsEqual(M, Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() })) }) it('Should guard mapped 8', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K, { custom: 1 })) Assert.IsEqual(M, Type.Object({ x: Type.Number({ custom: 1 }), y: Type.String({ custom: 1 }), z: Type.Boolean({ custom: 1 }) })) }) // ---------------------------------------------------------------- // Extract // ---------------------------------------------------------------- it('Should guard mapped 9', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.String()) }) Assert.IsEqual(M, Type.Object({ x: Type.String() })) }) it('Should guard mapped 10', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.Union([ Type.String(), Type.Number() ])) }) Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.String(), Type.Number()]) })) }) it('Should guard mapped 11', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.Null()) }) Assert.IsEqual(M, Type.Object({ x: Type.Never() })) }) // ---------------------------------------------------------------- // Extends // ---------------------------------------------------------------- it('Should guard mapped 12', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => { return ( Type.Extends(K, Type.Literal('x'), Type.Literal(1), Type.Extends(K, Type.Literal('y'), Type.Literal(2), Type.Extends(K, Type.Literal('z'), Type.Literal(3), Type.Never()))) ) }) Assert.IsEqual(M, Type.Object({ x: Type.Literal(1), y: Type.Literal(2), z: Type.Literal(3), })) }) it('Should guard mapped 13', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const M = Type.Mapped(Type.KeyOf(T), K => { return ( Type.Extends(Type.Index(T, K), Type.Number(), Type.Literal(3), Type.Extends(Type.Index(T, K), Type.String(), Type.Literal(2), Type.Extends(Type.Index(T, K), Type.Boolean(), Type.Literal(1), Type.Never()))) ) }) Assert.IsEqual(M, Type.Object({ x: Type.Literal(3), y: Type.Literal(2), z: Type.Literal(1), })) }) // ---------------------------------------------------------------- // Exclude // ---------------------------------------------------------------- it('Should guard mapped 14', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.String()) }) Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.Number(), Type.Boolean()]) })) }) it('Should guard mapped 15', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.Union([ Type.String(), Type.Number() ])) }) Assert.IsEqual(M, Type.Object({ x: Type.Boolean() })) }) it('Should guard mapped 16', () => { const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.Null()) }) Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) })) }) // ---------------------------------------------------------------- // Non-Evaluated // ---------------------------------------------------------------- it('Should guard mapped 17', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Array(Type.Index(T, K))) Assert.IsEqual(M, Type.Object({ x: Type.Array(Type.Number()) })) }) it('Should guard mapped 18', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Promise(Type.Index(T, K))) Assert.IsEqual(M, Type.Object({ x: Type.Promise(Type.Number()) })) }) it('Should guard mapped 19', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Function([Type.Index(T, K)], Type.Index(T, K))) Assert.IsEqual(M, Type.Object({ x: Type.Function([Type.Number()], Type.Number())})) }) it('Should guard mapped 20', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Tuple([Type.Index(T, K), Type.Index(T, K)])) Assert.IsEqual(M, Type.Object({ x: Type.Tuple([Type.Number(), Type.Number()]) })) }) it('Should guard mapped 21', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Union([Type.Index(T, K), Type.Index(T, K)])) Assert.IsEqual(M, Type.Object({ x: Type.Union([Type.Number(), Type.Number()]) })) }) it('Should guard mapped 22', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Intersect([Type.Index(T, K), Type.Index(T, K)])) Assert.IsEqual(M, Type.Object({ x: Type.Intersect([Type.Number(), Type.Number()]) })) }) // ---------------------------------------------------------------- // Numeric Keys // ---------------------------------------------------------------- it('Should guard mapped 23', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => K) Assert.IsEqual(M, Type.Object({ 0: Type.Literal('0'), 1: Type.Literal('1'), 2: Type.Literal('2'), })) }) it('Should guard mapped 24', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K)) Assert.IsEqual(M, Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number(), })) }) it('Should guard mapped 25', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.String()) Assert.IsEqual(M, Type.Object({ 0: Type.String(), 1: Type.String(), 2: Type.String(), })) }) it('Should guard mapped 26', () => { const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), K => Type.Extends(K, Type.Literal('1'), Type.String(), Type.Number())) Assert.IsEqual(M, Type.Object({ 0: Type.Number(), 1: Type.String(), 2: Type.Number(), })) }) // ---------------------------------------------------------------- // Modifiers: Optional // ---------------------------------------------------------------- it('Should guard mapped 27', () => { const T = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Number() }) // subtractive const M = Type.Mapped(Type.KeyOf(T), K => Type.Optional(Type.Index(T, K), false)) Assert.IsEqual(M, Type.Object({ x: Type.Number(), y: Type.Number() })) }) it('Should guard mapped 28', () => { const T = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Number() }) // additive const M = Type.Mapped(Type.KeyOf(T), K => Type.Optional(Type.Index(T, K), true)) Assert.IsEqual(M, Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()) })) }) // ---------------------------------------------------------------- // Modifiers: Readonly // ---------------------------------------------------------------- it('Should guard mapped 27', () => { const T = Type.Object({ x: Type.Readonly(Type.Number()), y: Type.Number() }) // subtractive const M = Type.Mapped(Type.KeyOf(T), K => Type.Readonly(Type.Index(T, K), false)) Assert.IsEqual(M, Type.Object({ x: Type.Number(), y: Type.Number() })) }) it('Should guard mapped 28', () => { const T = Type.Object({ x: Type.Readonly(Type.Number()), y: Type.Number() }) // additive const M = Type.Mapped(Type.KeyOf(T), K => Type.Readonly(Type.Index(T, K), true)) Assert.IsEqual(M, Type.Object({ x: Type.Readonly(Type.Number()), y: Type.Readonly(Type.Number()) })) }) // ---------------------------------------------------------------- // Finite Boolean // ---------------------------------------------------------------- it('Should guard mapped 29', () => { const T = Type.TemplateLiteral('${boolean}') const M = Type.Mapped(T, K => K) Assert.IsEqual(M, Type.Object({ true: Type.Literal('true'), false: Type.Literal('false'), })) }) it('Should guard mapped 30', () => { const T = Type.TemplateLiteral('${0|1}${boolean}') const M = Type.Mapped(T, K => K) Assert.IsEqual(M, Type.Object({ '0true': Type.Literal('0true'), '0false': Type.Literal('0false'), '1true': Type.Literal('1true'), '1false': Type.Literal('1false'), })) }) it('Should guard mapped 31', () => { const T = Type.TemplateLiteral('${boolean}${0|1}') const M = Type.Mapped(T, K => K) Assert.IsEqual(M, Type.Object({ 'true0': Type.Literal('true0'), 'true1': Type.Literal('true1'), 'false0': Type.Literal('false0'), 'false1': Type.Literal('false1'), })) }) // ---------------------------------------------------------------- // Numeric Mapping // ---------------------------------------------------------------- it('Should guard mapped 32', () => { const T = Type.TemplateLiteral([ Type.Union([Type.Literal(0), Type.Literal(1)]), Type.Union([Type.Literal(0), Type.Literal(1)]), ]) const M = Type.Mapped(T, (K) => K) Assert.IsEqual(M, Type.Object({ '00': Type.Literal('00'), '01': Type.Literal('01'), '10': Type.Literal('10'), '11': Type.Literal('11'), })) }) // ---------------------------------------------------------------- // Indexed Key Remap // ---------------------------------------------------------------- it('Should guard mapped 33', () => { const T = Type.Object({ hello: Type.Number(), world: Type.String(), }) const M = Type.Mapped(Type.Uppercase(Type.KeyOf(T)), (K) => { return Type.Index(T, Type.Lowercase(K)) }) Assert.IsEqual(M, Type.Object({ HELLO: Type.Number(), WORLD: Type.String() })) }) // ---------------------------------------------------------------- // Partial // ---------------------------------------------------------------- it('Should guard mapped 34', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Partial(Type.Index(T, K)) }) Assert.IsEqual(M, Type.Object({ x: Type.Partial(Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), })), y: Type.Partial(Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), })), })) }) // ---------------------------------------------------------------- // Required // ---------------------------------------------------------------- it('Should guard mapped 35', () => { const T = Type.Object({ x: Type.Partial(Type.Object({ x: Type.Number(), y: Type.Number(), })), y: Type.Partial(Type.Object({ x: Type.Number(), y: Type.Number(), })), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Required(Type.Index(T, K)) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), })) }) // ------------------------------------------------------------------ // Pick With Key // ------------------------------------------------------------------ it('Should guard mapped 36', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number() }), y: Type.Object({ x: Type.Number(), y: Type.Number() }) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Pick(T, K) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }) }), y: Type.Object({ y: Type.Object({ x: Type.Number(), y: Type.Number(), }) }), })) }) // ------------------------------------------------------------------ // Pick With Result // ------------------------------------------------------------------ it('Should guard mapped 37', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Pick(Type.Index(T, K), ['x']) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ x: Type.Number() }), y: Type.Object({ x: Type.Number() }) })) }) // ------------------------------------------------------------------ // Omit With Key // ------------------------------------------------------------------ it('Should guard mapped 36', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number() }), y: Type.Object({ x: Type.Number(), y: Type.Number() }) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Omit(T, K) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ y: Type.Object({ x: Type.Number(), y: Type.Number(), }) }), y: Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }) }), })) }) // ------------------------------------------------------------------ // Omit With Result // ------------------------------------------------------------------ it('Should guard mapped 37', () => { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Omit(Type.Index(T, K), ['x']) }) Assert.IsEqual(M, Type.Object({ x: Type.Object({ y: Type.Number() }), y: Type.Object({ y: Type.Number() }) })) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/not.ts000066400000000000000000000011131505437577000251320ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TNot', () => { it('Should guard for TNot', () => { const R = TypeGuard.IsNot(Type.Not(Type.String())) Assert.IsTrue(R) }) it('Should not guard for TNot 1', () => { const R = TypeGuard.IsNot(Type.Not(null as any)) Assert.IsFalse(R) }) it('Should not guard for TNot with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsNot(Type.Not(Type.String()), { $id: 1 }) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/null.ts000066400000000000000000000010461505437577000253110ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TNull', () => { it('Should guard for TNull', () => { const R = TypeGuard.IsNull(Type.Null()) Assert.IsTrue(R) }) it('Should not guard for TNull', () => { const R = TypeGuard.IsNull(null) Assert.IsFalse(R) }) it('Should not guard for TNull with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsNull(Type.Null({ $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/number.ts000066400000000000000000000027151505437577000256330ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TNumber', () => { it('Should guard for TNumber', () => { const R = TypeGuard.IsNumber(Type.Number()) Assert.IsTrue(R) }) it('Should not guard for TNumber', () => { const R = TypeGuard.IsNumber(null) Assert.IsFalse(R) }) it('Should not guard for TNumber with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsNumber(Type.Number({ $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TNumber with invalid multipleOf', () => { // @ts-ignore const R = TypeGuard.IsNumber(Type.Number({ multipleOf: '1' })) Assert.IsFalse(R) }) it('Should not guard for TNumber with invalid minimum', () => { // @ts-ignore const R = TypeGuard.IsNumber(Type.Number({ minimum: '1' })) Assert.IsFalse(R) }) it('Should not guard for TNumber with invalid maximum', () => { // @ts-ignore const R = TypeGuard.IsNumber(Type.Number({ maximum: '1' })) Assert.IsFalse(R) }) it('Should not guard for TNumber with invalid exclusiveMinimum', () => { // @ts-ignore const R = TypeGuard.IsNumber(Type.Number({ exclusiveMinimum: '1' })) Assert.IsFalse(R) }) it('Should not guard for TNumber with invalid exclusiveMaximum', () => { // @ts-ignore const R = TypeGuard.IsNumber(Type.Number({ exclusiveMaximum: '1' })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/object.ts000066400000000000000000000052471505437577000256140ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TObject', () => { it('Should guard for TObject', () => { const R = TypeGuard.IsObject( Type.Object({ x: Type.Number(), y: Type.Number(), }), ) Assert.IsTrue(R) }) it('Should not guard for TObject', () => { const R = TypeGuard.IsObject(null) Assert.IsFalse(R) }) it('Should not guard for TObject with escape characters in property key', () => { const R = TypeGuard.IsObject( Type.Object({ 'hello\nworld': Type.Number(), }), ) Assert.IsFalse(R) }) it('Should not guard for TObject with invalid property values', () => { const R = TypeGuard.IsObject( Type.Object({ x: Type.Number(), y: {} as any, }), ) Assert.IsFalse(R) }) it('Should not guard for TObject with invalid additionalProperties', () => { const R = TypeGuard.IsObject( Type.Object( { x: Type.Number(), }, { // @ts-ignore additionalProperties: 'true', }, ), ) Assert.IsFalse(R) }) it('Should not guard for TObject with invalid $id', () => { const R = TypeGuard.IsObject( Type.Object( { x: Type.Number(), }, { // @ts-ignore $id: 1, }, ), ) Assert.IsFalse(R) }) it('Should not guard for TObject with invalid minProperties', () => { const R = TypeGuard.IsObject( Type.Object( { x: Type.Number(), }, { // @ts-ignore minProperties: '1', }, ), ) Assert.IsFalse(R) }) it('Should not guard for TObject with invalid maxProperties', () => { const R = TypeGuard.IsObject( Type.Object( { x: Type.Number(), }, { // @ts-ignore maxProperties: '1', }, ), ) Assert.IsFalse(R) }) it('Should guard for TObject with invalid additional properties', () => { const R = TypeGuard.IsObject( Type.Object( { x: Type.Number(), y: Type.Number(), }, { // @ts-ignore additionalProperties: 1, }, ), ) Assert.IsFalse(R) }) it('Should not guard for TObject with valid additional properties schema', () => { const R = TypeGuard.IsObject( Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), ) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/omit.ts000066400000000000000000000142271505437577000253140ustar00rootroot00000000000000import { TypeGuard, Type, Kind, TransformKind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TOmit', () => { // ------------------------------------------------------------------------- // case: https://github.com/sinclairzx81/typebox/issues/384 // ------------------------------------------------------------------------- it('Should support TUnsafe omit properties with no Kind', () => { const T = Type.Omit(Type.Object({ x: Type.Unsafe({ x: 1 }), y: Type.Number() }), ['x']) Assert.IsEqual(T.required, ['y']) }) it('Should support TUnsafe omit properties with unregistered Kind', () => { const T = Type.Omit(Type.Object({ x: Type.Unsafe({ x: 1, [Kind]: 'UnknownOmitType' }), y: Type.Number() }), ['x']) Assert.IsEqual(T.required, ['y']) }) // ------------------------------------------------------------------------- // Standard Tests // ------------------------------------------------------------------------- it('Should Omit 1', () => { const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), }), ['x'], ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, ['y']) }) it('Should Omit 2', () => { const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Optional(Type.Number()), }), ['x'], ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, undefined) }) it('Should Omit 3', () => { const L = Type.Literal('x') const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, ['y']) }) it('Should Omit 4', () => { const L = Type.Literal('x') const T = Type.Omit(Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]), L) Assert.IsEqual(TypeGuard.IsNumber(T.allOf[1].properties.y), true) // @ts-ignore Assert.IsEqual(T.allOf[1].properties.x, undefined) }) it('Should Omit 5', () => { const L = Type.Union([Type.Literal('x'), Type.Literal('y')]) const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) // @ts-ignore Assert.IsEqual(T.properties.x, undefined) // @ts-ignore Assert.IsEqual(T.properties.y, undefined) // @ts-ignore Assert.IsEqual(T.required, undefined) }) it('Should Omit 6', () => { const L = Type.Union([Type.Literal('x'), Type.Literal('y'), Type.Literal('z')]) const T = Type.Omit( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) // @ts-ignore Assert.IsEqual(T.properties.x, undefined) // @ts-ignore Assert.IsEqual(T.properties.y, undefined) // @ts-ignore Assert.IsEqual(T.required, undefined) }) it('Should Omit 7', () => { const L = Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])]) const T = Type.Omit( Type.Object({ ab: Type.Number(), ac: Type.Number(), ad: Type.Number(), }), L, ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.ad)) Assert.IsEqual(T.required, ['ad']) }) // ---------------------------------------------------------------- // Discard // ---------------------------------------------------------------- it('Should override $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Omit(A, ['x'], { $id: 'T' }) Assert.IsEqual(T.$id!, 'T') }) it('Should discard $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Omit(A, ['x']) Assert.IsFalse('$id' in T) }) it('Should discard transform', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const S = Type.Transform(T) .Decode((value) => value) .Encode((value) => value) const R = Type.Omit(S, ['x']) Assert.IsFalse(TransformKind in R) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/944 // ---------------------------------------------------------------- it('Should retain interior properties 1', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const T = Type.Omit(A, ['x']) Assert.IsFalse(T.additionalProperties as boolean) }) it('Should retain interior properties 2', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ y: Type.Number() }, { additionalProperties: false }) const U = Type.Union([A, B]) const T = Type.Omit(U, ['x']) Assert.IsFalse(T.anyOf[0].additionalProperties as boolean) Assert.IsFalse(T.anyOf[1].additionalProperties as boolean) }) it('Should retain interior properties 3', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ y: Type.Number() }, { additionalProperties: false }) const U = Type.Intersect([A, B]) const T = Type.Omit(U, ['x']) Assert.IsFalse(T.allOf[0].additionalProperties as boolean) Assert.IsFalse(T.allOf[1].additionalProperties as boolean) }) it('Should retain interior properties 4', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number() }, { additionalProperties: false }) const T = Type.Mapped(Type.TemplateLiteral('${x|y|z}'), (_) => Type.Omit(A, ['x'])) Assert.IsFalse(T.properties.x.additionalProperties as boolean) Assert.IsFalse(T.properties.y.additionalProperties as boolean) Assert.IsFalse(T.properties.z.additionalProperties as boolean) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/980 // ---------------------------------------------------------------- it('Should override properties in source type', () => { const A = Type.Object({ x: Type.Number() }, { title: 'A' }) const B = Type.Omit(A, ['x'], { title: 'B' }) Assert.IsEqual(A.title, 'A') Assert.IsEqual(B.title, 'B') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/partial.ts000066400000000000000000000102541505437577000257740ustar00rootroot00000000000000import { TypeGuard, TypeRegistry, Type, Kind, TransformKind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TPartial', () => { it('Should produce a valid TSchema', () => { const T = Type.Partial(Type.Object({ x: Type.Number() })) Assert.IsTrue(TypeGuard.IsSchema(T)) }) // ------------------------------------------------------------------------- // case: https://github.com/sinclairzx81/typebox/issues/364 // ------------------------------------------------------------------------- it('Should support TUnsafe partial properties with no Kind', () => { const T = Type.Partial(Type.Object({ x: Type.Unsafe({ x: 1 }) })) Assert.IsEqual(T.required, undefined) }) it('Should support TUnsafe partial properties with unknown Kind', () => { const T = Type.Partial(Type.Object({ x: Type.Unsafe({ [Kind]: 'UnknownPartialType', x: 1 }) })) Assert.IsEqual(T.required, undefined) }) it('Should support TUnsafe partial properties with known Kind', () => { TypeRegistry.Set('KnownPartialType', () => true) const T = Type.Partial(Type.Object({ x: Type.Unsafe({ [Kind]: 'KnownPartialType', x: 1 }) })) Assert.IsEqual(T.required, undefined) }) it('Should support applying partial to intersect', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const I = Type.Intersect([A, B]) const T = Type.Partial(I) Assert.IsEqual(T.allOf.length, 2) Assert.IsEqual(T.allOf[0].required, undefined) Assert.IsEqual(T.allOf[1].required, undefined) }) it('Should support applying partial to union', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const I = Type.Union([A, B]) const T = Type.Partial(I) Assert.IsEqual(T.anyOf.length, 2) Assert.IsEqual(T.anyOf[0].required, undefined) Assert.IsEqual(T.anyOf[1].required, undefined) }) // ---------------------------------------------------------------- // Discard // ---------------------------------------------------------------- it('Should override $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Partial(A, { $id: 'T' }) Assert.IsEqual(T.$id!, 'T') }) it('Should discard $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Partial(A) Assert.IsFalse('$id' in T) }) it('Should discard transform', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const S = Type.Transform(T) .Decode((value) => value) .Encode((value) => value) const R = Type.Partial(S) Assert.IsFalse(TransformKind in R) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/980 // ---------------------------------------------------------------- it('Should override properties in source type', () => { const A = Type.Object({ x: Type.Number() }, { title: 'A' }) const B = Type.Partial(A, { title: 'B' }) Assert.IsEqual(A.title, 'A') Assert.IsEqual(B.title, 'B') }) // ------------------------------------------------------------------ // Intrinsic Passthough // https://github.com/sinclairzx81/typebox/issues/1169 // ------------------------------------------------------------------ it('Should pass through on intrinsic types on union 1', () => { const T = Type.Partial( Type.Union([ Type.Number(), Type.Object({ x: Type.Number(), }), ]), ) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsNumber(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsObject(T.anyOf[1])) Assert.IsTrue(TypeGuard.IsOptional(T.anyOf[1].properties.x)) }) it('Should pass through on intrinsic types on union 2', () => { const T = Type.Partial( Type.Union([ Type.Literal(1), Type.Object({ x: Type.Number(), }), ]), ) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsLiteral(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsObject(T.anyOf[1])) Assert.IsTrue(TypeGuard.IsOptional(T.anyOf[1].properties.x)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/pick.ts000066400000000000000000000142561505437577000252740ustar00rootroot00000000000000import { TypeGuard, Type, Kind, TransformKind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TPick', () => { // ------------------------------------------------------------------------- // case: https://github.com/sinclairzx81/typebox/issues/384 // ------------------------------------------------------------------------- it('Should support TUnsafe omit properties with no Kind', () => { const T = Type.Pick( Type.Object({ x: Type.Unsafe({ x: 1 }), y: Type.Number(), }), ['x'], ) Assert.IsEqual(T.required, ['x']) }) it('Should support TUnsafe omit properties with unregistered Kind', () => { const T = Type.Pick(Type.Object({ x: Type.Unsafe({ x: 1, [Kind]: 'UnknownPickType' }), y: Type.Number() }), ['x']) Assert.IsEqual(T.required, ['x']) }) // ------------------------------------------------------------------------- // Standard Tests // ------------------------------------------------------------------------- it('Should Pick 1', () => { const T = Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), }), ['x'], ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.x)) Assert.IsEqual(T.required, ['x']) }) it('Should Pick 2', () => { const T = Type.Pick( Type.Object({ x: Type.Optional(Type.Number()), y: Type.Number(), }), ['x'], ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.x)) Assert.IsEqual(T.required, undefined) }) it('Should Pick 3', () => { const L = Type.Literal('x') const T = Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.x)) Assert.IsEqual(T.required, ['x']) }) it('Should Pick 4', () => { const L = Type.Literal('x') const T = Type.Pick(Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]), L) Assert.IsTrue(TypeGuard.IsNumber(T.allOf[0].properties.x)) // @ts-ignore Assert.IsEqual(T.allOf[1].properties.y, undefined) }) it('Should Pick 5', () => { const L = Type.Union([Type.Literal('x'), Type.Literal('y')]) const T = Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, ['x', 'y']) }) it('Should Pick 6', () => { const L = Type.Union([Type.Literal('x'), Type.Literal('y'), Type.Literal('z')]) const T = Type.Pick( Type.Object({ x: Type.Number(), y: Type.Number(), }), L, ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.x)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.y)) Assert.IsEqual(T.required, ['x', 'y']) }) it('Should Pick 7', () => { const L = Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])]) const T = Type.Pick( Type.Object({ ab: Type.Number(), ac: Type.Number(), ad: Type.Number(), }), L, ) Assert.IsTrue(TypeGuard.IsNumber(T.properties.ab)) Assert.IsTrue(TypeGuard.IsNumber(T.properties.ac)) Assert.IsEqual(T.required, ['ab', 'ac']) }) // ---------------------------------------------------------------- // Discard // ---------------------------------------------------------------- it('Should override $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Pick(A, ['x'], { $id: 'T' }) Assert.IsEqual(T.$id!, 'T') }) it('Should discard $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Pick(A, ['x']) Assert.IsFalse('$id' in T) }) it('Should discard transform', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const S = Type.Transform(T) .Decode((value) => value) .Encode((value) => value) const R = Type.Pick(S, ['x']) Assert.IsFalse(TransformKind in R) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/944 // ---------------------------------------------------------------- it('Should retain interior properties 1', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const T = Type.Pick(A, ['x']) Assert.IsFalse(T.additionalProperties as boolean) }) it('Should retain interior properties 2', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ y: Type.Number() }, { additionalProperties: false }) const U = Type.Union([A, B]) const T = Type.Pick(U, ['x']) Assert.IsFalse(T.anyOf[0].additionalProperties as boolean) Assert.IsFalse(T.anyOf[1].additionalProperties as boolean) }) it('Should retain interior properties 3', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ y: Type.Number() }, { additionalProperties: false }) const U = Type.Intersect([A, B]) const T = Type.Pick(U, ['x']) Assert.IsFalse(T.allOf[0].additionalProperties as boolean) Assert.IsFalse(T.allOf[1].additionalProperties as boolean) }) it('Should retain interior properties 4', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number() }, { additionalProperties: false }) const T = Type.Mapped(Type.TemplateLiteral('${x|y|z}'), (_) => Type.Pick(A, ['x'])) Assert.IsFalse(T.properties.x.additionalProperties as boolean) Assert.IsFalse(T.properties.y.additionalProperties as boolean) Assert.IsFalse(T.properties.z.additionalProperties as boolean) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/980 // ---------------------------------------------------------------- it('Should override properties in source type', () => { const A = Type.Object({ x: Type.Number() }, { title: 'A' }) const B = Type.Pick(A, ['x'], { title: 'B' }) Assert.IsEqual(A.title, 'A') Assert.IsEqual(B.title, 'B') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/promise.ts000066400000000000000000000021161505437577000260140ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TPromise', () => { it('Should guard for TPromise', () => { const R = TypeGuard.IsPromise(Type.Promise(Type.Number())) Assert.IsTrue(R) }) it('Should not guard for TPromise', () => { const R = TypeGuard.IsPromise(null) Assert.IsFalse(R) }) it('Should not guard for TPromise with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsPromise(Type.Promise(Type.Number(), { $id: 1 })) Assert.IsFalse(R) }) it('Should guard for TPromise with nested TObject', () => { const R = TypeGuard.IsPromise( Type.Promise( Type.Object({ x: Type.Number(), y: Type.Number(), }), ), ) Assert.IsTrue(R) }) it('Should not guard for TPromise with nested TObject', () => { const R = TypeGuard.IsPromise( Type.Promise( Type.Object({ x: Type.Number(), y: {} as any, }), ), ) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/record.ts000066400000000000000000000206171505437577000256220ustar00rootroot00000000000000import { TypeGuard, PatternNumberExact, PatternStringExact, PatternNeverExact, PatternString, PatternNumber } from '@sinclair/typebox' import { Type, RecordKey, RecordValue, RecordPattern } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TRecord', () => { // ------------------------------------------------------------- // Overloads // ------------------------------------------------------------- it('Should guard overload 1', () => { const T = Type.Record(Type.Union([Type.Literal('A'), Type.Literal('B')]), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.A)) Assert.IsTrue(TypeGuard.IsString(T.properties.B)) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 2', () => { const T = Type.Record(Type.Union([Type.Literal('A')]), Type.String(), { extra: 1 }) // unwrap as literal Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.A)) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 3', () => { // @ts-ignore const N = Type.Union([]) // Never const T = Type.Record(N, Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNeverExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 4', () => { // @ts-ignore const T = Type.Record(Type.BigInt(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsNever(T)) }) it('Should guard overload 5', () => { const T = Type.Record(Type.Literal('A'), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.A)) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 6', () => { const L = Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Record(L, Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.helloA)) Assert.IsTrue(TypeGuard.IsString(T.properties.helloB)) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 7', () => { const T = Type.Record(Type.Number(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNumberExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 8', () => { const T = Type.Record(Type.Integer(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNumberExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 9', () => { const T = Type.Record(Type.String(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternStringExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 10', () => { const L = Type.TemplateLiteral([Type.String(), Type.Literal('_foo')]) const T = Type.Record(L, Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[`^${PatternString}_foo$`])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 11', () => { const L = Type.Union([Type.Literal('A'), Type.Union([Type.Literal('B'), Type.Literal('C')])]) const T = Type.Record(L, Type.String()) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.A)) Assert.IsTrue(TypeGuard.IsString(T.properties.B)) Assert.IsTrue(TypeGuard.IsString(T.properties.C)) }) it('Should guard overload 12', () => { enum E { A = 'X', B = 'Y', C = 'Z', } const T = Type.Enum(E) const R = Type.Record(T, Type.Null()) Assert.IsTrue(TypeGuard.IsObject(R)) Assert.IsTrue(TypeGuard.IsNull(R.properties.X)) Assert.IsTrue(TypeGuard.IsNull(R.properties.Y)) Assert.IsTrue(TypeGuard.IsNull(R.properties.Z)) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/916 // // Added overload for Any and Never Keys // ---------------------------------------------------------------- it('Should guard overload 13', () => { // @ts-ignore const T = Type.Record(Type.Never(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternNeverExact])) Assert.IsEqual(T.extra, 1) }) it('Should guard overload 14', () => { // @ts-ignore const T = Type.Record(Type.Any(), Type.String(), { extra: 1 }) Assert.IsTrue(TypeGuard.IsRecord(T)) Assert.IsTrue(TypeGuard.IsString(T.patternProperties[PatternStringExact])) Assert.IsEqual(T.extra, 1) }) // ------------------------------------------------------------- // Variants // ------------------------------------------------------------- it('Should guard for TRecord', () => { const R = TypeGuard.IsRecord(Type.Record(Type.String(), Type.Number())) Assert.IsTrue(R) }) it('Should guard for TRecord with TObject value', () => { const R = TypeGuard.IsRecord( Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), }), ), ) Assert.IsTrue(R) }) it('Should not guard for TRecord', () => { const R = TypeGuard.IsRecord(null) Assert.IsFalse(R) }) it('Should not guard for TRecord with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsRecord(Type.Record(Type.String(), Type.Number(), { $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TRecord with TObject value with invalid Property', () => { const R = TypeGuard.IsRecord( Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: {} as any, }), ), ) Assert.IsFalse(R) }) it('Normalize: Should normalize to TObject for single literal union value', () => { const K = Type.Union([Type.Literal('ok')]) const R = TypeGuard.IsObject(Type.Record(K, Type.Number())) Assert.IsTrue(R) }) it('Normalize: Should normalize to TObject for multi literal union value', () => { const K = Type.Union([Type.Literal('A'), Type.Literal('B')]) const R = TypeGuard.IsObject(Type.Record(K, Type.Number())) Assert.IsTrue(R) }) it('Normalize: Should normalize boolean key into true and false', () => { const K = Type.Boolean() const R = Type.Record(K, Type.Number()) Assert.IsTrue(TypeGuard.IsObject(R)) Assert.IsTrue(TypeGuard.IsNumber(R.properties.true)) Assert.IsTrue(TypeGuard.IsNumber(R.properties.false)) }) // ------------------------------------------------------------------ // Utility Types // ------------------------------------------------------------------ it('Should return RecordPattern', () => { const R = Type.Record(Type.Number(), Type.Number()) const K = RecordPattern(R) Assert.IsTrue(typeof K === 'string') }) it('Should return RecordKey (Number)', () => { const R = Type.Record(Type.Number(), Type.Number()) const K = RecordKey(R) Assert.IsTrue(TypeGuard.IsNumber(K)) }) it('Should return RecordKey (String)', () => { const R = Type.Record(Type.String(), Type.Number()) const K = RecordKey(R) Assert.IsTrue(TypeGuard.IsString(K)) }) it('Should return RecordKey (RegExp)', () => { const R = Type.Record(Type.RegExp(/(a|b)/), Type.Number()) const K = RecordKey(R) Assert.IsTrue(TypeGuard.IsString(K)) // facade }) it('Should return RecordValue', () => { const R = Type.Record(Type.String(), Type.Literal(12345)) const V = RecordValue(R) Assert.IsTrue(TypeGuard.IsLiteral(V)) Assert.IsEqual(V.const, 12345) }) // ------------------------------------------------------------------ // Evaluated: Dollar Sign Escape // https://github.com/sinclairzx81/typebox/issues/794 // ------------------------------------------------------------------ // prettier-ignore { const K = Type.TemplateLiteral('$prop${A|B|C}') // issue const T = Type.Record(K, Type.String()) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsString(T.properties.$propA)) Assert.IsTrue(TypeGuard.IsString(T.properties.$propB)) Assert.IsTrue(TypeGuard.IsString(T.properties.$propC)) Assert.IsEqual(T.required, ['$propA', '$propB', '$propC']) } }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/recursive.ts000066400000000000000000000011531505437577000263450ustar00rootroot00000000000000import { TypeGuard, PatternNumberExact, PatternStringExact, PatternString, PatternNumber } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TRecursive', () => { it('Should guard 1', () => { const T = Type.Recursive((This) => Type.Object({ nodes: This })) Assert.IsTrue(TypeGuard.IsRecursive(T)) Assert.IsTrue(TypeGuard.IsObject(T)) }) it('Should guard 2', () => { const T = Type.Recursive((This) => Type.Tuple([This])) Assert.IsTrue(TypeGuard.IsRecursive(T)) Assert.IsTrue(TypeGuard.IsTuple(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/ref.ts000066400000000000000000000026531505437577000251200ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type, CloneType } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TRef', () => { // ---------------------------------------------------------------- // Deprecated // ---------------------------------------------------------------- it('Should guard for Ref(Schema) 1', () => { const T = Type.Number({ $id: 'T' }) const R = Type.Ref(T) Assert.IsTrue(TypeGuard.IsRef(R)) Assert.IsTrue(typeof R['$ref'] === 'string') }) it('Should guard for Ref(Schema) 2', () => { const T = Type.Number() Assert.Throws(() => Type.Ref(T)) }) it('Should guard for Ref(Schema) 3', () => { // @ts-ignore const T = Type.Number({ $id: null }) Assert.Throws(() => Type.Ref(T)) }) // ---------------------------------------------------------------- // Standard // ---------------------------------------------------------------- it('Should guard for TRef', () => { const T = Type.Number({ $id: 'T' }) const R = TypeGuard.IsRef(Type.Ref('T')) Assert.IsTrue(R) }) it('Should not guard for TRef', () => { const R = TypeGuard.IsRef(null) Assert.IsFalse(R) }) it('Should not guard for TRef with invalid $ref', () => { const T = Type.Number({ $id: 'T' }) const S = CloneType(Type.Ref('T')) // @ts-ignore S.$ref = 1 const R = TypeGuard.IsRef(S) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/regexp.ts000066400000000000000000000020741505437577000256330ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TRegExp', () => { it('Should guard for TRegExp 1', () => { const T = Type.RegExp(/foo/, { $id: 'T' }) Assert.IsTrue(TypeGuard.IsSchema(T)) }) it('Should guard for TRegExp 1', () => { const T = Type.RegExp(/foo/, { $id: 'T' }) Assert.IsTrue(TypeGuard.IsRegExp(T)) }) it('Should guard for TRegExp 2', () => { const T = Type.RegExp('foo', { $id: 'T' }) Assert.IsTrue(TypeGuard.IsRegExp(T)) }) it('Should not guard for TRegExp 1', () => { // @ts-ignore const T = Type.RegExp('foo', { $id: 1 }) Assert.IsFalse(TypeGuard.IsRegExp(T)) }) it('Should guard for RegExp constraint 1', () => { // @ts-ignore const T = Type.RegExp('foo', { maxLength: '1' }) Assert.IsFalse(TypeGuard.IsRegExp(T)) }) it('Should guard for RegExp constraint 2', () => { // @ts-ignore const T = Type.RegExp('foo', { minLength: '1' }) Assert.IsFalse(TypeGuard.IsRegExp(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/required.ts000066400000000000000000000101221505437577000261520ustar00rootroot00000000000000import { TypeGuard, TypeRegistry, Type, Kind, TransformKind } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TRequired', () => { it('Should produce a valid TSchema', () => { const T = Type.Required(Type.Object({ x: Type.Number() })) Assert.IsTrue(TypeGuard.IsSchema(T)) }) it('Should support TUnsafe required properties with no Kind', () => { const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ x: 1 })) })) Assert.IsEqual(T.required, ['x']) }) it('Should support TUnsafe required properties with unknown Kind', () => { const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ [Kind]: 'UnknownRequiredType', x: 1 })) })) Assert.IsEqual(T.required, ['x']) }) it('Should support TUnsafe required properties with known Kind', () => { TypeRegistry.Set('KnownRequiredType', () => true) const T = Type.Required(Type.Object({ x: Type.Optional(Type.Unsafe({ [Kind]: 'KnownRequiredType', x: 1 })) })) Assert.IsEqual(T.required, ['x']) }) it('Should support applying required to intersect', () => { const A = Type.Object({ x: Type.Optional(Type.Number()) }) const B = Type.Object({ y: Type.Optional(Type.Number()) }) const I = Type.Intersect([A, B]) const T = Type.Required(I) Assert.IsEqual(T.allOf.length, 2) Assert.IsEqual(T.allOf[0].required, ['x']) Assert.IsEqual(T.allOf[1].required, ['y']) }) it('Should support applying required to union', () => { const A = Type.Object({ x: Type.Optional(Type.Number()) }) const B = Type.Object({ y: Type.Optional(Type.Number()) }) const I = Type.Union([A, B]) const T = Type.Required(I) Assert.IsEqual(T.anyOf.length, 2) Assert.IsEqual(T.anyOf[0].required, ['x']) Assert.IsEqual(T.anyOf[1].required, ['y']) }) // ---------------------------------------------------------------- // Discard // ---------------------------------------------------------------- it('Should override $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Required(A, { $id: 'T' }) Assert.IsEqual(T.$id!, 'T') }) it('Should discard $id', () => { const A = Type.Object({ x: Type.Number() }, { $id: 'A' }) const T = Type.Required(A) Assert.IsFalse('$id' in T) }) it('Should discard transform', () => { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const S = Type.Transform(T) .Decode((value) => value) .Encode((value) => value) const R = Type.Required(S) Assert.IsFalse(TransformKind in R) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/980 // ---------------------------------------------------------------- it('Should override properties in source type', () => { const A = Type.Object({ x: Type.Number() }, { title: 'A' }) const B = Type.Required(A, { title: 'B' }) Assert.IsEqual(A.title, 'A') Assert.IsEqual(B.title, 'B') }) // ------------------------------------------------------------------ // Intrinsic Passthough // https://github.com/sinclairzx81/typebox/issues/1169 // ------------------------------------------------------------------ it('Should pass through on intrinsic types on union 1', () => { const T = Type.Required( Type.Union([ Type.Number(), Type.Object({ x: Type.Optional(Type.Number()), }), ]), ) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsNumber(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsObject(T.anyOf[1])) Assert.IsFalse(TypeGuard.IsOptional(T.anyOf[1].properties.x)) }) it('Should pass through on intrinsic types on union 2', () => { const T = Type.Required( Type.Union([ Type.Literal(1), Type.Object({ x: Type.Optional(Type.Number()), }), ]), ) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsLiteral(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsObject(T.anyOf[1])) Assert.IsFalse(TypeGuard.IsOptional(T.anyOf[1].properties.x)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/rest.ts000066400000000000000000000040441505437577000253150ustar00rootroot00000000000000import { Type, TypeGuard } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TRest', () => { it('Should guard 1', () => { // union never const A = Type.String() const B = Type.Union(Type.Rest(A)) Assert.IsTrue(TypeGuard.IsNever(B)) }) it('Should guard 2', () => { // intersect never const A = Type.String() const B = Type.Intersect(Type.Rest(A)) Assert.IsTrue(TypeGuard.IsNever(B)) }) it('Should guard 3', () => { // tuple const A = Type.Tuple([Type.Number(), Type.String()]) const B = Type.Union(Type.Rest(A)) Assert.IsTrue(TypeGuard.IsUnion(B)) Assert.IsEqual(B.anyOf.length, 2) Assert.IsTrue(TypeGuard.IsNumber(B.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(B.anyOf[1])) }) it('Should guard 4', () => { // tuple spread const A = Type.Tuple([Type.Literal(1), Type.Literal(2)]) const B = Type.Tuple([Type.Literal(3), Type.Literal(4)]) const C = Type.Tuple([...Type.Rest(A), ...Type.Rest(B)]) Assert.IsTrue(TypeGuard.IsTuple(C)) Assert.IsEqual(C.items!.length, 4) Assert.IsEqual(C.items![0].const, 1) Assert.IsEqual(C.items![1].const, 2) Assert.IsEqual(C.items![2].const, 3) Assert.IsEqual(C.items![3].const, 4) }) it('Should guard 5', () => { // union to intersect const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.String() }) const C = Type.Union([A, B]) const D = Type.Intersect(Type.Rest(C)) Assert.IsTrue(TypeGuard.IsIntersect(D)) Assert.IsEqual(D.allOf.length, 2) Assert.IsTrue(TypeGuard.IsObject(D.allOf[0])) Assert.IsTrue(TypeGuard.IsObject(D.allOf[1])) }) it('Should guard 6', () => { // intersect to composite const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.String() }) const C = Type.Intersect([A, B]) const D = Type.Composite(Type.Rest(C)) Assert.IsTrue(TypeGuard.IsObject(D)) Assert.IsTrue(TypeGuard.IsNumber(D.properties.x)) Assert.IsTrue(TypeGuard.IsString(D.properties.y)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/string.ts000066400000000000000000000021131505437577000256410ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TString', () => { it('Should guard for TString', () => { const R = TypeGuard.IsString(Type.String()) Assert.IsTrue(R) }) it('Should not guard for TString', () => { const R = TypeGuard.IsString(null) Assert.IsFalse(R) }) it('Should not guard for TString with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsString(Type.String({ $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TString with invalid minLength', () => { // @ts-ignore const R = TypeGuard.IsString(Type.String({ minLength: '1' })) Assert.IsFalse(R) }) it('Should not guard for TString with invalid maxLength', () => { // @ts-ignore const R = TypeGuard.IsString(Type.String({ maxLength: '1' })) Assert.IsFalse(R) }) it('Should not guard for TString with invalid pattern', () => { // @ts-ignore const R = TypeGuard.IsString(Type.String({ pattern: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/symbol.ts000066400000000000000000000010701505437577000256410ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TSymbol', () => { it('Should guard for TSymbol', () => { const R = TypeGuard.IsSymbol(Type.Symbol()) Assert.IsTrue(R) }) it('Should not guard for TSymbol', () => { const R = TypeGuard.IsSymbol(null) Assert.IsFalse(R) }) it('Should not guard for TSymbol with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsSymbol(Type.Symbol({ $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/template-literal.ts000066400000000000000000000076041505437577000276120ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type, CloneType, TemplateLiteralGenerate } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TTemplateLiteral', () => { it('Should guard for empty TemplateLiteral', () => { const R = TypeGuard.IsTemplateLiteral(Type.TemplateLiteral([])) Assert.IsTrue(R) }) it('Should guard for TSchema', () => { const R = TypeGuard.IsSchema(Type.TemplateLiteral([])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TTemplateLiteral)', () => { const T = Type.TemplateLiteral([Type.Literal('hello')]) const R = TypeGuard.IsTemplateLiteral(Type.TemplateLiteral([T, Type.Literal('world')])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TLiteral)', () => { const R = TypeGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Literal('hello')])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TString)', () => { const R = TypeGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.String()])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TNumber)', () => { const R = TypeGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Number()])) Assert.IsTrue(R) }) it('Should guard for TemplateLiteral (TBoolean)', () => { const R = TypeGuard.IsTemplateLiteral(Type.TemplateLiteral([Type.Boolean()])) Assert.IsTrue(R) }) it('Should not guard for missing ^ expression prefix', () => { const T = CloneType(Type.TemplateLiteral([Type.Literal('hello')])) // @ts-ignore T.pattern = T.pattern.slice(1) Assert.IsFalse(TypeGuard.IsTemplateLiteral(T)) }) it('Should not guard for missing $ expression postfix', () => { const T = CloneType(Type.TemplateLiteral([Type.Literal('hello')])) // @ts-ignore T.pattern = T.pattern.slice(0, T.pattern.length - 1) Assert.IsFalse(TypeGuard.IsTemplateLiteral(T)) }) // ---------------------------------------------------------------- // issue: https://github.com/sinclairzx81/typebox/issues/913 // ---------------------------------------------------------------- it('Should generate embedded template literal 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('X'), Type.Literal('Y')])]) const L = Type.TemplateLiteral([Type.Literal('KEY'), A, B]) const T = TemplateLiteralGenerate(L) Assert.IsEqual(T, ['KEYAX', 'KEYAY', 'KEYBX', 'KEYBY']) }) it('Should generate embedded template literal 2', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('X'), Type.Literal('Y')])]) const L = Type.TemplateLiteral([A, Type.Literal('KEY'), B]) const T = TemplateLiteralGenerate(L) Assert.IsEqual(T, ['AKEYX', 'AKEYY', 'BKEYX', 'BKEYY']) }) it('Should generate embedded template literal 3', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('X'), Type.Literal('Y')])]) const L = Type.TemplateLiteral([A, B, Type.Literal('KEY')]) const T = TemplateLiteralGenerate(L) Assert.IsEqual(T, ['AXKEY', 'AYKEY', 'BXKEY', 'BYKEY']) }) it('Should map embedded template literal', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('X'), Type.Literal('Y')])]) const L = Type.TemplateLiteral([Type.Literal('KEY'), A, B]) const T = Type.Mapped(L, (K) => Type.Null()) Assert.IsTrue(TypeGuard.IsObject(T)) Assert.IsTrue(TypeGuard.IsNull(T.properties.KEYAX)) Assert.IsTrue(TypeGuard.IsNull(T.properties.KEYAY)) Assert.IsTrue(TypeGuard.IsNull(T.properties.KEYBX)) Assert.IsTrue(TypeGuard.IsNull(T.properties.KEYBY)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/this.ts000066400000000000000000000011661505437577000253110ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TThis', () => { it('Should guard for TThis', () => { Type.Recursive((This) => { const R = TypeGuard.IsThis(This) Assert.IsTrue(R) return Type.Object({ nodes: Type.Array(This) }) }) }) it('Should guard for TThis with invalid $ref', () => { Type.Recursive((This) => { // @ts-ignore This.$ref = 1 const R = TypeGuard.IsThis(This) Assert.IsFalse(R) return Type.Object({ nodes: Type.Array(This) }) }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/tuple.ts000066400000000000000000000014171505437577000254720ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TTuple', () => { it('Should guard for TTuple', () => { const R = TypeGuard.IsTuple(Type.Tuple([Type.Number(), Type.Number()])) Assert.IsTrue(R) }) it('Should not guard for TTuple', () => { const R = TypeGuard.IsTuple(null) Assert.IsFalse(R) }) it('Should not guard for TTuple with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsTuple(Type.Tuple([Type.Number(), Type.Number()], { $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TTuple with invalid Items', () => { const R = TypeGuard.IsTuple(Type.Tuple([Type.Number(), {} as any])) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/uint8array.ts000066400000000000000000000017521505437577000264510ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TUint8Array', () => { it('Should guard for TUint8Array', () => { const R = TypeGuard.IsUint8Array(Type.Uint8Array()) Assert.IsTrue(R) }) it('Should not guard for TUint8Array', () => { const R = TypeGuard.IsUint8Array(null) Assert.IsFalse(R) }) it('Should not guard for TUint8Array with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsUint8Array(Type.Uint8Array({ $id: 1 })) Assert.IsFalse(R) }) it('Should not guard for TUint8Array with invalid minByteLength', () => { // @ts-ignore const R = TypeGuard.IsUint8Array(Type.Uint8Array({ minByteLength: '1' })) Assert.IsFalse(R) }) it('Should not guard for TUint8Array with invalid maxByteLength', () => { // @ts-ignore const R = TypeGuard.IsUint8Array(Type.Uint8Array({ maxByteLength: '1' })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/uncapitalize.ts000066400000000000000000000025601505437577000270310ustar00rootroot00000000000000import { TypeGuard, Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/Uncapitalize', () => { it('Should guard for Uncapitalize 1', () => { const T = Type.Uncapitalize(Type.Literal('HELLO'), { $id: 'hello', foo: 1 }) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hELLO') Assert.IsEqual(T.$id, 'hello') Assert.IsEqual(T.foo, 1) }) it('Should guard for Uncapitalize 2', () => { const T = Type.Uncapitalize(Type.Literal('HELLO')) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hELLO') }) it('Should guard for Uncapitalize 3', () => { const T = Type.Uncapitalize(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')])) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'hELLO') Assert.IsEqual(T.anyOf[1].const, 'wORLD') }) it('Should guard for Uncapitalize 4', () => { const T = Type.Uncapitalize(Type.TemplateLiteral('HELLO${0|1}')) Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hELLO0|hELLO1)$') }) it('Should guard for Uncapitalize 5', () => { const T = Type.Uncapitalize(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(0), Type.Literal(1)])])) Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hELLO0|hELLO1)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/undefined.ts000066400000000000000000000011231505437577000262740ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TUndefined', () => { it('Should guard for TUndefined', () => { const R = TypeGuard.IsUndefined(Type.Undefined()) Assert.IsTrue(R) }) it('Should not guard for TUndefined', () => { const R = TypeGuard.IsUndefined(null) Assert.IsFalse(R) }) it('Should not guard for TUndefined with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsUndefined(Type.Undefined({ $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/union.ts000066400000000000000000000041401505437577000254650ustar00rootroot00000000000000import { TSchema, TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TUnion', () => { it('Should guard for TUnion', () => { const R = TypeGuard.IsUnion( Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]), ) Assert.IsTrue(R) }) it('Should not guard for TUnion', () => { const R = TypeGuard.IsUnion(null) Assert.IsFalse(R) }) it('Should guard for TUnion with invalid $id', () => { const R = TypeGuard.IsUnion( // @ts-ignore Type.Union( [ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ], { // @ts-ignore $id: 1, }, ), ) Assert.IsFalse(R) }) it('Should not guard for TUnion with invalid variant', () => { const R = TypeGuard.IsUnion( Type.Union([ Type.Object({ x: Type.Number(), }), {} as TSchema, ]), ) Assert.IsFalse(R) }) it('Should not guard for TUnion with invalid object variant', () => { const R = TypeGuard.IsUnion( Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: {} as any, }), ]), ) Assert.IsFalse(R) }) it('Transform: Should transform to never for zero length union', () => { const T = Type.Union([]) const R = TypeGuard.IsNever(T) Assert.IsTrue(R) }) it('Transform: Should unwrap union type for array of length === 1', () => { const T = Type.Union([Type.String()]) const R = TypeGuard.IsString(T) Assert.IsTrue(R) }) it('Transform: Should retain union if array length > 1', () => { const T = Type.Union([Type.String(), Type.Number()]) const R1 = TypeGuard.IsUnion(T) const R2 = TypeGuard.IsString(T.anyOf[0]) const R3 = TypeGuard.IsNumber(T.anyOf[1]) Assert.IsTrue(R1) Assert.IsTrue(R2) Assert.IsTrue(R3) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/unknown.ts000066400000000000000000000011011505437577000260260ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TUnknown', () => { it('Should guard for TUnknown', () => { const R = TypeGuard.IsUnknown(Type.Unknown()) Assert.IsTrue(R) }) it('Should not guard for TUnknown', () => { const R = TypeGuard.IsUnknown(null) Assert.IsFalse(R) }) it('Should not guard for TUnknown with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsUnknown(Type.Unknown({ $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/unsafe.ts000066400000000000000000000020611505437577000256160ustar00rootroot00000000000000import { Kind, TypeGuard, TypeRegistry } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TUnsafe', () => { it('Should guard raw TUnsafe', () => { const T = Type.Unsafe({ x: 1 }) const R = TypeGuard.IsUnsafe(T) Assert.IsTrue(R) }) it('Should guard raw TUnsafe as TSchema', () => { const T = Type.Unsafe({ x: 1 }) const R = TypeGuard.IsSchema(T) Assert.IsTrue(R) }) it('Should guard override TUnsafe as TSchema when registered', () => { TypeRegistry.Set('UnsafeType', () => true) const T = Type.Unsafe({ [Kind]: 'UnsafeType' }) const R = TypeGuard.IsSchema(T) Assert.IsTrue(R) TypeRegistry.Delete('UnsafeType') }) it('Should not guard TUnsafe with unregistered kind', () => { const T = Type.Unsafe({ [Kind]: 'UnsafeType' }) const R = TypeGuard.IsUnsafe(T) Assert.IsFalse(R) }) it('Should not guard for TString', () => { const T = Type.String() const R = TypeGuard.IsUnsafe(T) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/uppercase.ts000066400000000000000000000025171505437577000263320ustar00rootroot00000000000000import { TypeGuard, Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/Uppercase', () => { it('Should guard for Uppercase 1', () => { const T = Type.Uppercase(Type.Literal('hello'), { $id: 'hello', foo: 1 }) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'HELLO') Assert.IsEqual(T.$id, 'hello') Assert.IsEqual(T.foo, 1) }) it('Should guard for Uppercase 2', () => { const T = Type.Uppercase(Type.Literal('hello')) Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'HELLO') }) it('Should guard for Uppercase 3', () => { const T = Type.Uppercase(Type.Union([Type.Literal('hello'), Type.Literal('world')])) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'HELLO') Assert.IsEqual(T.anyOf[1].const, 'WORLD') }) it('Should guard for Uppercase 4', () => { const T = Type.Uppercase(Type.TemplateLiteral('hello${0|1}')) Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(HELLO0|HELLO1)$') }) it('Should guard for Uppercase 5', () => { const T = Type.Uppercase(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(0), Type.Literal(1)])])) Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(HELLO0|HELLO1)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/type/void.ts000066400000000000000000000010461505437577000253000ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TVoid', () => { it('Should guard for TVoid', () => { const R = TypeGuard.IsVoid(Type.Void()) Assert.IsTrue(R) }) it('Should not guard for TVoid', () => { const R = TypeGuard.IsVoid(null) Assert.IsFalse(R) }) it('Should not guard for TVoid with invalid $id', () => { // @ts-ignore const R = TypeGuard.IsVoid(Type.Void({ $id: 1 })) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/value/000077500000000000000000000000001505437577000241215ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/value/guard.ts000066400000000000000000000132761505437577000256040ustar00rootroot00000000000000import { Assert } from '../../../assert/index' import { ValueGuard } from '@sinclair/typebox' describe('type/ValueGuard', () => { // ----------------------------------------------------- // IsSymbol // ----------------------------------------------------- it('Should guard symbol 1', () => { const R = ValueGuard.IsSymbol(Symbol()) Assert.IsTrue(R) }) it('Should guard symbol 2', () => { const R = ValueGuard.IsSymbol({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsNull // ----------------------------------------------------- it('Should guard null 1', () => { const R = ValueGuard.IsNull(null) Assert.IsTrue(R) }) it('Should guard null 2', () => { const R = ValueGuard.IsNull({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsUndefined // ----------------------------------------------------- it('Should guard undefined 1', () => { const R = ValueGuard.IsUndefined(undefined) Assert.IsTrue(R) }) it('Should guard undefined 2', () => { const R = ValueGuard.IsUndefined({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsBigInt // ----------------------------------------------------- it('Should guard bigint 1', () => { const R = ValueGuard.IsBigInt(1n) Assert.IsTrue(R) }) it('Should guard bigint 2', () => { const R = ValueGuard.IsBigInt(1) Assert.IsFalse(R) }) it('Should guard bigint 3', () => { const R = ValueGuard.IsBigInt('123') Assert.IsFalse(R) }) // ----------------------------------------------------- // IsNumber // ----------------------------------------------------- it('Should guard number 1', () => { const R = ValueGuard.IsNumber(1) Assert.IsTrue(R) }) it('Should guard number 2', () => { const R = ValueGuard.IsNumber(3.14) Assert.IsTrue(R) }) it('Should guard number 3', () => { const R = ValueGuard.IsNumber('') Assert.IsFalse(R) }) it('Should guard number 4', () => { const R = ValueGuard.IsNumber(NaN) Assert.IsTrue(R) }) // ----------------------------------------------------- // IsString // ----------------------------------------------------- it('Should guard string 1', () => { const R = ValueGuard.IsString('') Assert.IsTrue(R) }) it('Should guard string 2', () => { const R = ValueGuard.IsString(true) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsBoolean // ----------------------------------------------------- it('Should guard boolean 1', () => { const R = ValueGuard.IsBoolean(true) Assert.IsTrue(R) }) it('Should guard boolean 2', () => { const R = ValueGuard.IsBoolean(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsObject // ----------------------------------------------------- it('Should guard object 1', () => { const R = ValueGuard.IsObject({}) Assert.IsTrue(R) }) it('Should guard object 2', () => { const R = ValueGuard.IsObject(1) Assert.IsFalse(R) }) it('Should guard object 3', () => { const R = ValueGuard.IsObject([]) Assert.IsTrue(R) }) // ----------------------------------------------------- // IsArray // ----------------------------------------------------- it('Should guard array 1', () => { const R = ValueGuard.IsArray([]) Assert.IsTrue(R) }) it('Should guard array 2', () => { const R = ValueGuard.IsArray({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsFunction // ----------------------------------------------------- it('Should guard function 1', () => { const R = ValueGuard.IsFunction(function () {}) Assert.IsTrue(R) }) it('Should guard function 2', () => { const R = ValueGuard.IsFunction({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsAsyncIterator // ----------------------------------------------------- it('Should guard async iterator 1', () => { const R = ValueGuard.IsAsyncIterator((async function* (): any {})()) Assert.IsTrue(R) }) it('Should guard async iterator 2', () => { const R = ValueGuard.IsAsyncIterator((function* (): any {})()) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsAsyncIterator // ----------------------------------------------------- it('Should guard iterator 1', () => { const R = ValueGuard.IsIterator((function* (): any {})()) Assert.IsTrue(R) }) it('Should guard iterator 2', () => { const R = ValueGuard.IsIterator((async function* (): any {})()) Assert.IsFalse(R) }) it('Should guard iterator 3', () => { const R = ValueGuard.IsIterator([]) Assert.IsFalse(R) }) it('Should guard iterator 4', () => { const R = ValueGuard.IsIterator(new Uint8Array()) Assert.IsFalse(R) }) // ----------------------------------------------------- // Date // ----------------------------------------------------- it('Should guard date 1', () => { const R = ValueGuard.IsDate(new Date()) Assert.IsTrue(R) }) it('Should guard date 2', () => { const R = ValueGuard.IsDate({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // Date // ----------------------------------------------------- it('Should guard uint8array 1', () => { const R = ValueGuard.IsUint8Array(new Uint8Array()) Assert.IsTrue(R) }) it('Should guard uint8array 2', () => { const R = ValueGuard.IsUint8Array({}) Assert.IsFalse(R) }) it('Should guard uint8array 2', () => { const R = ValueGuard.IsUint8Array([]) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/guard/value/index.ts000066400000000000000000000000211505437577000255710ustar00rootroot00000000000000import './guard' sinclairzx81-typebox-e0ec98c/test/runtime/type/index.ts000066400000000000000000000003501505437577000233600ustar00rootroot00000000000000import './clone/index' import './extends/index' import './guard/index' import './intrinsic/index' import './normalize/index' import './options/index' import './registry/index' import './sets/index' import './template-literal/index' sinclairzx81-typebox-e0ec98c/test/runtime/type/intrinsic/000077500000000000000000000000001505437577000237055ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/intrinsic/index.ts000066400000000000000000000000251505437577000253610ustar00rootroot00000000000000import './intrinsic' sinclairzx81-typebox-e0ec98c/test/runtime/type/intrinsic/intrinsic.ts000066400000000000000000000164571505437577000262740ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Intrinsic } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/intrinsic/Intrinsic', () => { // ---------------------------------------------------- // Passthrough // ---------------------------------------------------- it('Should passthrough 1', () => { const T = Intrinsic(Type.String(), 'Capitalize') Assert.IsTrue(TypeGuard.IsString(T)) }) it('Should passthrough 2', () => { const T = Intrinsic(Type.Number(), 'Capitalize') Assert.IsTrue(TypeGuard.IsNumber(T)) }) it('Should passthrough 3', () => { const T = Intrinsic( Type.Object({ x: Type.Number(), }), 'Capitalize', ) Assert.IsTrue(TypeGuard.IsObject(T)) }) // ---------------------------------------------------- // Partial Passthrough // ---------------------------------------------------- it('Should partial passthrough 3', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Literal('hello') const U = Type.Union([A, B]) const T = Intrinsic(U, 'Capitalize') Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsObject(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsLiteral(T.anyOf[1])) Assert.IsEqual(T.anyOf[1].const, 'Hello') }) // ---------------------------------------------------- // Mode: Literal // ---------------------------------------------------- it('Should map literal: Capitalize', () => { const T = Intrinsic(Type.Literal('hello'), 'Capitalize') Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'Hello') }) it('Should map literal: Uncapitalize', () => { const T = Intrinsic(Type.Literal('HELLO'), 'Uncapitalize') Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hELLO') }) it('Should map literal: Uppercase', () => { const T = Intrinsic(Type.Literal('hello'), 'Uppercase') Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'HELLO') }) it('Should map literal: Lowercase', () => { const T = Intrinsic(Type.Literal('HELLO'), 'Lowercase') Assert.IsTrue(TypeGuard.IsLiteral(T)) Assert.IsEqual(T.const, 'hello') }) // ---------------------------------------------------- // Mode: Literal Union // ---------------------------------------------------- it('Should map literal union: Capitalize', () => { const T = Intrinsic(Type.Union([Type.Literal('hello'), Type.Literal('world')]), 'Capitalize') Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'Hello') Assert.IsEqual(T.anyOf[1].const, 'World') }) it('Should map literal union: Uncapitalize', () => { const T = Intrinsic(Type.Union([Type.Literal('Hello'), Type.Literal('World')]), 'Uncapitalize') Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'hello') Assert.IsEqual(T.anyOf[1].const, 'world') }) it('Should map literal union: Uppercase', () => { const T = Intrinsic(Type.Union([Type.Literal('hello'), Type.Literal('world')]), 'Uppercase') Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'HELLO') Assert.IsEqual(T.anyOf[1].const, 'WORLD') }) it('Should map literal union: Lowercase', () => { const T = Intrinsic(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')]), 'Lowercase') Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsEqual(T.anyOf[0].const, 'hello') Assert.IsEqual(T.anyOf[1].const, 'world') }) // ---------------------------------------------------- // Mode: TemplateLiteral // ---------------------------------------------------- it('Should map template literal: Capitalize', () => { const T = Intrinsic(Type.TemplateLiteral('hello${1|2}world'), 'Capitalize') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(Hello1world|Hello2world)$') }) it('Should map template literal: Uncapitalize', () => { const T = Intrinsic(Type.TemplateLiteral('HELLO${1|2}WORLD'), 'Uncapitalize') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hELLO1WORLD|hELLO2WORLD)$') }) it('Should map template literal: Uppercase', () => { const T = Intrinsic(Type.TemplateLiteral('hello${1|2}world'), 'Uppercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(HELLO1WORLD|HELLO2WORLD)$') }) it('Should map template literal: Lowercase', () => { const T = Intrinsic(Type.TemplateLiteral('HELLO${1|2}WORLD'), 'Lowercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hello1world|hello2world)$') }) // ---------------------------------------------------- // Mode: TemplateLiteral Numeric // ---------------------------------------------------- it('Should map template literal numeric: Capitalize', () => { const T = Intrinsic(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(1), Type.Literal(2)])]), 'Capitalize') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(Hello1|Hello2)$') }) it('Should map template literal numeric: Uncapitalize', () => { const T = Intrinsic(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(1), Type.Literal(2)])]), 'Uncapitalize') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hELLO1|hELLO2)$') }) it('Should map template literal numeric: Uppercase', () => { const T = Intrinsic(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(1), Type.Literal(2)])]), 'Uppercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(HELLO1|HELLO2)$') }) it('Should map template literal numeric: Lowercase', () => { const T = Intrinsic(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(1), Type.Literal(2)])]), 'Lowercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(hello1|hello2)$') }) // ---------------------------------------------------- // Mode: TemplateLiteral Patterns // ---------------------------------------------------- it('Should map template literal patterns 1', () => { const T = Intrinsic(Type.TemplateLiteral('HELLO${string}WORLD'), 'Lowercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^hello(.*)world$') }) it('Should map template literal patterns 2', () => { const T = Intrinsic(Type.TemplateLiteral('HELLO${number}WORLD'), 'Lowercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^hello(0|[1-9][0-9]*)world$') }) it('Should map template literal patterns 3', () => { const T = Intrinsic(Type.TemplateLiteral('${number}${string}'), 'Lowercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(0|[1-9][0-9]*)(.*)$') }) it('Should map template literal patterns 3', () => { const T = Intrinsic(Type.TemplateLiteral('${number}HELLO${string}'), 'Lowercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(0|[1-9][0-9]*)hello(.*)$') }) it('Should map template literal patterns 3', () => { const T = Intrinsic(Type.TemplateLiteral('${string|number}HELLO'), 'Lowercase') Assert.IsTrue(TypeGuard.IsTemplateLiteral(T)) Assert.IsEqual(T.pattern, '^(stringhello|numberhello)$') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/normalize/000077500000000000000000000000001505437577000237035ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/normalize/exclude.ts000066400000000000000000000013011505437577000256770ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/normalize/Exclude', () => { it('Normalize 1', () => { const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String()) const R = TypeGuard.IsUnion(T) Assert.IsTrue(R) }) it('Normalize 2', () => { const T = Type.Exclude(Type.Union([Type.String(), Type.Number()]), Type.String()) const R = TypeGuard.IsNumber(T) Assert.IsTrue(R) }) it('Normalize 3', () => { const T = Type.Exclude(Type.Union([Type.String()]), Type.String()) const R = TypeGuard.IsNever(T) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/normalize/extract.ts000066400000000000000000000020621505437577000257250ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/normalize/Extract', () => { it('Normalize 1', () => { const T = Type.Extract(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.Union([Type.String(), Type.Number()])) const R = TypeGuard.IsUnion(T) Assert.IsTrue(R) }) it('Normalize 2', () => { const T = Type.Extract(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String()) const R = TypeGuard.IsString(T) Assert.IsTrue(R) }) it('Normalize 3', () => { const T = Type.Extract(Type.Union([Type.String(), Type.Number()]), Type.String()) const R = TypeGuard.IsString(T) Assert.IsTrue(R) }) it('Normalize 4', () => { const T = Type.Extract(Type.Union([Type.String()]), Type.String()) const R = TypeGuard.IsString(T) Assert.IsTrue(R) }) it('Normalize 5', () => { const T = Type.Extract(Type.Union([]), Type.String()) const R = TypeGuard.IsNever(T) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/normalize/index.ts000066400000000000000000000001611505437577000253600ustar00rootroot00000000000000import './exclude' import './extract' import './intersect' import './indexed' import './record' import './union' sinclairzx81-typebox-e0ec98c/test/runtime/type/normalize/indexed.ts000066400000000000000000000134471505437577000257040ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/normalize/Index', () => { // --------------------------------------------------------- // Array // --------------------------------------------------------- it('Normalize Array 1', () => { const T = Type.Array(Type.String()) const I = Type.Index(T, Type.Number()) Assert.IsTrue(TypeGuard.IsString(I)) }) // --------------------------------------------------------- // Tuple // --------------------------------------------------------- it('Normalize Tuple 1', () => { const T = Type.Tuple([Type.String(), Type.Number()]) const I = Type.Index(T, Type.Number()) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) }) it('Normalize Tuple 2', () => { const T = Type.Tuple([Type.String(), Type.Number()]) const I = Type.Index(T, [0, 1]) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) }) it('Normalize Tuple 3', () => { const T = Type.Tuple([Type.String(), Type.Number()]) const I = Type.Index(T, ['0', '1']) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsNumber(I.anyOf[1])) }) it('Normalize Tuple 4', () => { const T = Type.Tuple([Type.String(), Type.Number()]) const I = Type.Index(T, ['0']) Assert.IsTrue(TypeGuard.IsString(I)) }) it('Normalize Tuple 5', () => { const T = Type.Tuple([Type.String(), Type.Number()]) const I = Type.Index(T, ['1']) Assert.IsTrue(TypeGuard.IsNumber(I)) }) // --------------------------------------------------------- // Intersect // --------------------------------------------------------- it('Normalize Intersect 1', () => { const T = Type.Intersect([Type.Object({ x: Type.Optional(Type.String()) }), Type.Object({ x: Type.Optional(Type.String()) })]) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsIntersect(I)) Assert.IsTrue(TypeGuard.IsString(I.allOf[0])) Assert.IsTrue(TypeGuard.IsString(I.allOf[1])) }) it('Normalize Intersect 2', () => { const T = Type.Intersect([Type.Object({ x: Type.Optional(Type.String()) }), Type.Object({ x: Type.String() })]) const I = Type.Index(T, ['x']) Assert.IsFalse(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsIntersect(I)) Assert.IsTrue(TypeGuard.IsString(I.allOf[0])) Assert.IsTrue(TypeGuard.IsString(I.allOf[1])) }) it('Normalize Intersect 3', () => { const T = Type.Intersect([Type.Object({ x: Type.String() }), Type.Object({ x: Type.String() })]) const I = Type.Index(T, ['x']) Assert.IsFalse(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsIntersect(I)) Assert.IsTrue(TypeGuard.IsString(I.allOf[0])) Assert.IsTrue(TypeGuard.IsString(I.allOf[1])) }) it('Normalize Intersect 4', () => { const T = Type.Intersect([Type.Object({ x: Type.String() })]) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsString(I)) }) it('Normalize Intersect 5', () => { const T = Type.Intersect([Type.Object({ x: Type.String() }), Type.Object({ y: Type.String() })]) const I = Type.Index(T, ['x', 'y']) Assert.IsFalse(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Normalize Intersect 6', () => { const T = Type.Recursive(() => Type.Intersect([Type.Object({ x: Type.String() }), Type.Object({ y: Type.String() })])) const I = Type.Index(T, ['x', 'y']) Assert.IsFalse(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) // --------------------------------------------------------- // Union // --------------------------------------------------------- it('Normalize Union 1', () => { const T = Type.Union([Type.Object({ x: Type.Optional(Type.String()) }), Type.Object({ x: Type.Optional(Type.String()) })]) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Normalize Union 2', () => { const T = Type.Union([Type.Object({ x: Type.Optional(Type.String()) }), Type.Object({ x: Type.String() })]) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Normalize Union 3', () => { const T = Type.Union([Type.Object({ x: Type.String() }), Type.Object({ x: Type.String() })]) const I = Type.Index(T, ['x']) Assert.IsFalse(TypeGuard.IsOptional(I)) Assert.IsTrue(TypeGuard.IsUnion(I)) Assert.IsTrue(TypeGuard.IsString(I.anyOf[0])) Assert.IsTrue(TypeGuard.IsString(I.anyOf[1])) }) it('Normalize Union 4', () => { const T = Type.Union([Type.Object({ x: Type.String() })]) const I = Type.Index(T, ['x']) Assert.IsTrue(TypeGuard.IsString(I)) }) it('Normalize Union 5', () => { const T = Type.Union([Type.Object({ x: Type.String() }), Type.Object({ y: Type.String() })]) // @ts-ignore const I = Type.Index(T, ['x', 'y']) Assert.IsFalse(TypeGuard.IsNever(I)) }) it('Normalize Union 6', () => { const T = Type.Recursive(() => Type.Union([Type.Object({ x: Type.String() }), Type.Object({ y: Type.String() })])) // @ts-ignore const I = Type.Index(T, ['x', 'y']) Assert.IsFalse(TypeGuard.IsNever(I)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/normalize/intersect.ts000066400000000000000000000011201505437577000262450ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/normalize/Intersect', () => { it('Normalize 1', () => { const T = Type.Intersect([Type.Number(), Type.String()]) const R = TypeGuard.IsIntersect(T) Assert.IsTrue(R) }) it('Normalize 2', () => { const T = Type.Intersect([Type.Number()]) const R = TypeGuard.IsNumber(T) Assert.IsTrue(R) }) it('Normalize 3', () => { const T = Type.Intersect([]) const R = TypeGuard.IsNever(T) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/normalize/record.ts000066400000000000000000000005701505437577000255330ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/normalize/Record', () => { it('Normalize 1', () => { const K = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Record(K, Type.String()) const R = TypeGuard.IsObject(T) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/normalize/union.ts000066400000000000000000000010741505437577000254050ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/normalize/Union', () => { it('Normalize 1', () => { const T = Type.Union([Type.Number(), Type.String()]) const R = TypeGuard.IsUnion(T) Assert.IsTrue(R) }) it('Normalize 2', () => { const T = Type.Union([Type.Number()]) const R = TypeGuard.IsNumber(T) Assert.IsTrue(R) }) it('Normalize 3', () => { const T = Type.Union([]) const R = TypeGuard.IsNever(T) Assert.IsTrue(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/options/000077500000000000000000000000001505437577000233765ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/options/assign-builder.ts000066400000000000000000000215641505437577000266660ustar00rootroot00000000000000import { JavaScriptTypeBuilder } from '@sinclair/typebox' import { Assert } from '../../assert/index' const Type = new JavaScriptTypeBuilder() // TypeBuilder will proxy calls through to the raw function API describe('type/options/AssignTypeBuilder', () => { it('Should assign options for Any', () => { const T = Type.Any({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Array', () => { const T = Type.Array(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for AsyncIterator', () => { const T = Type.AsyncIterator(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Awaited', () => { const T = Type.Awaited(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for BigInt', () => { const T = Type.BigInt({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Boolean', () => { const T = Type.Boolean({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Capitalize', () => { const T = Type.Capitalize(Type.Literal('hello'), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Composite', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Const', () => { const T = Type.Const(1, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Constructor', () => { const T = Type.Constructor([], Type.Any(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Date', () => { const T = Type.Date({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Enum', () => { const T = Type.Enum({}, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Exclude', () => { const T = Type.Exclude(Type.Union([Type.Literal(1), Type.Literal(2)]), Type.Literal(2), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Extends', () => { const T = Type.Extends(Type.String(), Type.String(), Type.Number(), Type.Null(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Extract', () => { const T = Type.Extract(Type.Union([Type.Literal(1), Type.Literal(2)]), Type.Literal(2), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Function', () => { const T = Type.Function([], Type.Any(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Integer', () => { const T = Type.Integer({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Intersect 1', () => { const T = Type.Intersect([], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Intersect 2', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() })], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Intersect 3', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Iterator', () => { const T = Type.Iterator(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for KeyOf', () => { const T = Type.KeyOf(Type.Object({ x: Type.Number() }), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Literal', () => { const T = Type.Literal(1, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Lowercase', () => { const T = Type.Lowercase(Type.Literal('hello'), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Mapped 1', () => { const M = Type.Mapped(Type.TemplateLiteral('${1|2|3}'), (K) => K, { foo: 'bar' }) Assert.IsEqual(M.foo, 'bar') }) it('Should assign options for Mapped 2', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), (K) => Type.Index(T, K), { foo: 'bar' }) Assert.IsEqual(M.foo, 'bar') }) it('Should assign options for Never', () => { const T = Type.Never({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Not', () => { const T = Type.Not(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Null', () => { const T = Type.Null({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Number', () => { const T = Type.Number({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Object', () => { const T = Type.Object( { x: Type.String(), }, { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Omit', () => { const T = Type.Omit( Type.Object({ x: Type.String(), y: Type.String(), }), ['x'], { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Partial', () => { const T = Type.Partial( Type.Object({ x: Type.String(), }), { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Pick', () => { const T = Type.Pick( Type.Object({ x: Type.String(), y: Type.String(), }), ['x'], { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Record', () => { const T = Type.Record(Type.String(), Type.Number(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Recursive', () => { const T = Type.Recursive( (This) => Type.Object({ x: Type.Number(), y: Type.Array(This), }), { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Ref 1', () => { const T = Type.Object({ x: Type.Number() }, { $id: 'T' }) const R = Type.Ref(T, { foo: 'bar' }) Assert.IsEqual(R.foo, 'bar') }) it('Should assign options for Ref 2', () => { const R = Type.Ref('T', { foo: 'bar' }) Assert.IsEqual(R.foo, 'bar') }) it('Should assign options for RegExp', () => { const R = Type.RegExp(/xyz/, { foo: 'bar' }) Assert.IsEqual(R.foo, 'bar') }) it('Should assign options for Partial', () => { const T = Type.Required( Type.Object({ x: Type.String(), }), { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for String', () => { const T = Type.String({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Symbol', () => { const T = Type.Symbol({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for TemplateLiteral 1', () => { const T = Type.TemplateLiteral('hello${1|2|3}', { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for TemplateLiteral 2', () => { const T = Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal('1'), Type.Literal('2'), Type.Literal('3')])], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Tuple 1', () => { const T = Type.Tuple([], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Tuple 2', () => { const T = Type.Tuple([Type.String(), Type.Number()], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Uint8Array', () => { const T = Type.Uint8Array({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Uncapitalize', () => { const T = Type.Uncapitalize(Type.Literal('hello'), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Undefined', () => { const T = Type.Undefined({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Union 1', () => { const T = Type.Union([], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Union 1', () => { const T = Type.Union([Type.String()], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Union 1', () => { const T = Type.Union([Type.String(), Type.Boolean()], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Unknown', () => { const T = Type.Unknown({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Uppercase', () => { const T = Type.Uppercase(Type.Literal('hello'), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Void', () => { const T = Type.Void({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/options/assign.ts000066400000000000000000000213561505437577000252410ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/options/Assign', () => { it('Should assign options for Any', () => { const T = Type.Any({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Array', () => { const T = Type.Array(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for AsyncIterator', () => { const T = Type.AsyncIterator(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Awaited', () => { const T = Type.Awaited(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for BigInt', () => { const T = Type.BigInt({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Boolean', () => { const T = Type.Boolean({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Capitalize', () => { const T = Type.Capitalize(Type.Literal('hello'), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Composite', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Const', () => { const T = Type.Const(1, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Constructor', () => { const T = Type.Constructor([], Type.Any(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Date', () => { const T = Type.Date({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Enum', () => { const T = Type.Enum({}, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Exclude', () => { const T = Type.Exclude(Type.Union([Type.Literal(1), Type.Literal(2)]), Type.Literal(2), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Extends', () => { const T = Type.Extends(Type.String(), Type.String(), Type.Number(), Type.Null(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Extract', () => { const T = Type.Extract(Type.Union([Type.Literal(1), Type.Literal(2)]), Type.Literal(2), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Function', () => { const T = Type.Function([], Type.Any(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Integer', () => { const T = Type.Integer({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Intersect 1', () => { const T = Type.Intersect([], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Intersect 2', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() })], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Intersect 3', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Iterator', () => { const T = Type.Iterator(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for KeyOf', () => { const T = Type.KeyOf(Type.Object({ x: Type.Number() }), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Literal', () => { const T = Type.Literal(1, { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Lowercase', () => { const T = Type.Lowercase(Type.Literal('hello'), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Mapped 1', () => { const M = Type.Mapped(Type.TemplateLiteral('${1|2|3}'), (K) => K, { foo: 'bar' }) Assert.IsEqual(M.foo, 'bar') }) it('Should assign options for Mapped 2', () => { const T = Type.Object({ x: Type.Number() }) const M = Type.Mapped(Type.KeyOf(T), (K) => Type.Index(T, K), { foo: 'bar' }) Assert.IsEqual(M.foo, 'bar') }) it('Should assign options for Never', () => { const T = Type.Never({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Not', () => { const T = Type.Not(Type.String(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Null', () => { const T = Type.Null({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Number', () => { const T = Type.Number({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Object', () => { const T = Type.Object( { x: Type.String(), }, { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Omit', () => { const T = Type.Omit( Type.Object({ x: Type.String(), y: Type.String(), }), ['x'], { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Partial', () => { const T = Type.Partial( Type.Object({ x: Type.String(), }), { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Pick', () => { const T = Type.Pick( Type.Object({ x: Type.String(), y: Type.String(), }), ['x'], { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Record', () => { const T = Type.Record(Type.String(), Type.Number(), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Recursive', () => { const T = Type.Recursive( (This) => Type.Object({ x: Type.Number(), y: Type.Array(This), }), { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Ref 1', () => { const T = Type.Object({ x: Type.Number() }, { $id: 'T' }) const R = Type.Ref(T, { foo: 'bar' }) Assert.IsEqual(R.foo, 'bar') }) it('Should assign options for Ref 2', () => { const R = Type.Ref('T', { foo: 'bar' }) Assert.IsEqual(R.foo, 'bar') }) it('Should assign options for RegExp', () => { const R = Type.RegExp(/xyz/, { foo: 'bar' }) Assert.IsEqual(R.foo, 'bar') }) it('Should assign options for Partial', () => { const T = Type.Required( Type.Object({ x: Type.String(), }), { foo: 'bar' }, ) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for String', () => { const T = Type.String({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Symbol', () => { const T = Type.Symbol({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for TemplateLiteral 1', () => { const T = Type.TemplateLiteral('hello${1|2|3}', { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for TemplateLiteral 2', () => { const T = Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal('1'), Type.Literal('2'), Type.Literal('3')])], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Tuple 1', () => { const T = Type.Tuple([], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Tuple 2', () => { const T = Type.Tuple([Type.String(), Type.Number()], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Uint8Array', () => { const T = Type.Uint8Array({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Uncapitalize', () => { const T = Type.Uncapitalize(Type.Literal('hello'), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Undefined', () => { const T = Type.Undefined({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Union 1', () => { const T = Type.Union([], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Union 1', () => { const T = Type.Union([Type.String()], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Union 1', () => { const T = Type.Union([Type.String(), Type.Boolean()], { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Unknown', () => { const T = Type.Unknown({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Uppercase', () => { const T = Type.Uppercase(Type.Literal('hello'), { foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) it('Should assign options for Void', () => { const T = Type.Void({ foo: 'bar' }) Assert.IsEqual(T.foo, 'bar') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/options/index.ts000066400000000000000000000000541505437577000250540ustar00rootroot00000000000000import './assign-builder' import './assign' sinclairzx81-typebox-e0ec98c/test/runtime/type/registry/000077500000000000000000000000001505437577000235535ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/registry/format.ts000066400000000000000000000013561505437577000254200ustar00rootroot00000000000000import { FormatRegistry } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/registry/Format', () => { it('Should set format', () => { FormatRegistry.Set('test#format1', () => true) }) it('Should get format', () => { FormatRegistry.Set('test#format2', () => true) const format = FormatRegistry.Get('test#format2') Assert.IsEqual(typeof format, 'function') }) it('Should return true if exists', () => { FormatRegistry.Set('test#format3', () => true) Assert.IsTrue(FormatRegistry.Has('test#format3')) }) it('Should clear formats', () => { FormatRegistry.Set('test#format4', () => true) FormatRegistry.Clear() Assert.IsFalse(FormatRegistry.Has('test#format4')) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/registry/index.ts000066400000000000000000000000421505437577000252260ustar00rootroot00000000000000import './format' import './type' sinclairzx81-typebox-e0ec98c/test/runtime/type/registry/type.ts000066400000000000000000000013061505437577000251040ustar00rootroot00000000000000import { TypeRegistry } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/registry/Type', () => { it('Should set type', () => { TypeRegistry.Set('test#type1', () => true) }) it('Should get type', () => { TypeRegistry.Set('test#type2', () => true) const format = TypeRegistry.Get('test#type2') Assert.IsEqual(typeof format, 'function') }) it('Should return true if exists', () => { TypeRegistry.Set('test#type3', () => true) Assert.IsTrue(TypeRegistry.Has('test#type3')) }) it('Should clear types', () => { TypeRegistry.Set('test#type4', () => true) TypeRegistry.Clear() Assert.IsFalse(TypeRegistry.Has('test#type4')) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/sets/000077500000000000000000000000001505437577000226615ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/sets/index.ts000066400000000000000000000000201505437577000243300ustar00rootroot00000000000000import './sets' sinclairzx81-typebox-e0ec98c/test/runtime/type/sets/sets.ts000066400000000000000000000123651505437577000242160ustar00rootroot00000000000000import * as Type from '@sinclair/typebox' import { Assert } from '../../assert' describe('type/sets', () => { // ---------------------------------------------------------------- // Distinct // ---------------------------------------------------------------- it('Should Distinct', () => { const R = Type.SetDistinct([1, 1, 2, 2]) Assert.IsEqual(R, [1, 2]) }) // ---------------------------------------------------------------- // Includes // ---------------------------------------------------------------- it('Should Includes 1', () => { const R = Type.SetIncludes([1, 2, 3, 4], 1) Assert.IsTrue(R) }) it('Should Includes 2', () => { const R = Type.SetIncludes([1, 2, 3, 4], 7) Assert.IsFalse(R) }) // ---------------------------------------------------------------- // IsSubset // ---------------------------------------------------------------- it('Should IsSubset 1', () => { const R = Type.SetIsSubset([1, 2], [1, 2]) Assert.IsTrue(R) }) it('Should IsSubset 2', () => { const R = Type.SetIsSubset([1, 2], [1, 2, 3]) Assert.IsTrue(R) }) it('Should IsSubset 3', () => { const R = Type.SetIsSubset([1, 2], [1]) Assert.IsFalse(R) }) // ---------------------------------------------------------------- // Intersect // ---------------------------------------------------------------- it('Should Intersect 1', () => { const R = Type.SetIntersect([1, 2], [1, 2]) Assert.IsEqual(R, [1, 2]) }) it('Should Intersect 2', () => { const R = Type.SetIntersect([1], [1, 2]) Assert.IsEqual(R, [1]) }) it('Should Intersect 3', () => { const R = Type.SetIntersect([1, 2], [1]) Assert.IsEqual(R, [1]) }) it('Should Intersect 4', () => { const R = Type.SetIntersect([], [1]) Assert.IsEqual(R, []) }) it('Should Intersect 5', () => { const R = Type.SetIntersect([1], []) Assert.IsEqual(R, []) }) it('Should Intersect 6', () => { const R = Type.SetIntersect([1], [2]) Assert.IsEqual(R, []) }) // ---------------------------------------------------------------- // Union // ---------------------------------------------------------------- it('Should Union 1', () => { const R = Type.SetUnion([1, 2], [1, 2]) Assert.IsEqual(R, [1, 2, 1, 2]) }) it('Should Union 2', () => { const R = Type.SetUnion([1], [1, 2]) Assert.IsEqual(R, [1, 1, 2]) }) it('Should Union 3', () => { const R = Type.SetUnion([1, 2], [1]) Assert.IsEqual(R, [1, 2, 1]) }) it('Should Union 4', () => { const R = Type.SetUnion([], [1]) Assert.IsEqual(R, [1]) }) it('Should Union 5', () => { const R = Type.SetUnion([1], []) Assert.IsEqual(R, [1]) }) // ---------------------------------------------------------------- // Complement // ---------------------------------------------------------------- it('Should Complement 1', () => { const R = Type.SetComplement([1, 2, 3, 4], [2, 3]) Assert.IsEqual(R, [1, 4]) }) it('Should Complement 2', () => { const R = Type.SetComplement([2, 3], [1, 2, 3, 4]) Assert.IsEqual(R, []) }) // ---------------------------------------------------------------- // IntersectMany // ---------------------------------------------------------------- it('Should IntersectMany 1', () => { const R = Type.SetIntersectMany([[1, 2, 3], [1, 2], [1]] as const) Assert.IsEqual(R, [1]) }) it('Should IntersectMany 2', () => { const R = Type.SetIntersectMany([[1], [1, 2], [1, 2, 3]] as const) Assert.IsEqual(R, [1]) }) it('Should IntersectMany 3', () => { const R = Type.SetIntersectMany([ [1, 2], [1, 2], ] as const) Assert.IsEqual(R, [1, 2]) }) it('Should IntersectMany 4', () => { const R = Type.SetIntersectMany([[1], [2]] as const) Assert.IsEqual(R, []) }) it('Should IntersectMany 5', () => { const R = Type.SetIntersectMany([[1], []] as const) Assert.IsEqual(R, []) }) it('Should IntersectMany 6', () => { const R = Type.SetIntersectMany([[], [1]] as const) Assert.IsEqual(R, []) }) it('Should IntersectMany 7', () => { const R = Type.SetIntersectMany([[1], [1], [1], [1], []] as const) Assert.IsEqual(R, []) }) it('Should IntersectMany 8', () => { const R = Type.SetIntersectMany([[], [1], [1], [1], [1]] as const) Assert.IsEqual(R, []) }) // ---------------------------------------------------------------- // UnionMany // ---------------------------------------------------------------- it('Should UnionMany 1', () => { const R = Type.SetUnionMany([[1, 2, 3], [1, 2], [1]] as const) Assert.IsEqual(R, [1, 2, 3, 1, 2, 1]) }) it('Should UnionMany 2', () => { const R = Type.SetUnionMany([[1], [1, 2], [1, 2, 3]] as const) Assert.IsEqual(R, [1, 1, 2, 1, 2, 3]) }) it('Should UnionMany 3', () => { const R = Type.SetUnionMany([ [1, 2], [1, 2], ] as const) Assert.IsEqual(R, [1, 2, 1, 2]) }) it('Should UnionMany 4', () => { const R = Type.SetUnionMany([[1], [2]] as const) Assert.IsEqual(R, [1, 2]) }) it('Should UnionMany 5', () => { const R = Type.SetUnionMany([[1], []] as const) Assert.IsEqual(R, [1]) }) it('Should UnionMany 6', () => { const R = Type.SetUnionMany([[], [1]] as const) Assert.IsEqual(R, [1]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/template-literal/000077500000000000000000000000001505437577000251505ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/type/template-literal/finite.ts000066400000000000000000000046041505437577000270020ustar00rootroot00000000000000import { TemplateLiteralParse, IsTemplateLiteralExpressionFinite, PatternString, PatternBoolean, PatternNumber } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/template-literal/IsTemplateLiteralExpressionFinite', () => { // --------------------------------------------------------------- // Finite // --------------------------------------------------------------- it('Finite 1', () => { const E = TemplateLiteralParse(`A`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsTrue(R) }) it('Finite 2', () => { const E = TemplateLiteralParse(`A|B`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsTrue(R) }) it('Finite 3', () => { const E = TemplateLiteralParse(`A(B|C)`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsTrue(R) }) it('Finite 4', () => { const E = TemplateLiteralParse(`${PatternBoolean}`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsTrue(R) }) it('Finite 5', () => { const E = TemplateLiteralParse(`\\.\\*`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsTrue(R) }) // --------------------------------------------------------------- // Infinite // --------------------------------------------------------------- it('Infinite 1', () => { const E = TemplateLiteralParse(`${PatternString}`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsFalse(R) }) it('Infinite 2', () => { const E = TemplateLiteralParse(`${PatternNumber}`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsFalse(R) }) it('Infinite 3', () => { const E = TemplateLiteralParse(`A|${PatternString}`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsFalse(R) }) it('Infinite 4', () => { const E = TemplateLiteralParse(`A|${PatternNumber}`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsFalse(R) }) it('Infinite 5', () => { const E = TemplateLiteralParse(`A(${PatternString})`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsFalse(R) }) it('Infinite 6', () => { const E = TemplateLiteralParse(`A(${PatternNumber})`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsFalse(R) }) it('Infinite 7', () => { const E = TemplateLiteralParse(`${PatternString}_foo`) const R = IsTemplateLiteralExpressionFinite(E) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/template-literal/generate.ts000066400000000000000000000156711505437577000273240ustar00rootroot00000000000000import { TemplateLiteralParse, TemplateLiteralExpressionGenerate } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/template-literal/TemplateLiteralExpressionGenerate', () => { // --------------------------------------------------------------- // Exact (No Default Unwrap) // --------------------------------------------------------------- it('Exact 1', () => { const E = TemplateLiteralParse('^$') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['^$']) }) it('Exact 2', () => { const E = TemplateLiteralParse('^A$') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['^A$']) }) // --------------------------------------------------------------- // Patterns // --------------------------------------------------------------- it('Pattern 1', () => { const E = TemplateLiteralParse('(true|false)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['true', 'false']) }) it('Pattern 2', () => { const E = TemplateLiteralParse('(0|[1-9][0-9]*)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['0', '[1-9][0-9]*']) }) it('Pattern 3', () => { const E = TemplateLiteralParse('.*') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['.*']) }) // --------------------------------------------------------------- // Expression // --------------------------------------------------------------- it('Expression 1', () => { const E = TemplateLiteralParse(')') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, [')']) }) it('Expression 2', () => { const E = TemplateLiteralParse('\\)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, [')']) }) it('Expression 3', () => { const E = TemplateLiteralParse('\\(') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['(']) }) it('Expression 4', () => { const E = TemplateLiteralParse('') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['']) }) it('Expression 5', () => { const E = TemplateLiteralParse('\\') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['\\']) }) it('Expression 6', () => { const E = TemplateLiteralParse('()') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['']) }) it('Expression 7', () => { const E = TemplateLiteralParse('(a)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['a']) }) it('Expression 8', () => { const E = TemplateLiteralParse('()))') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['))']) }) it('Expression 9', () => { const E = TemplateLiteralParse('())') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, [')']) }) it('Expression 10', () => { const E = TemplateLiteralParse('A|B') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A', 'B']) }) it('Expression 11', () => { const E = TemplateLiteralParse('A|(B)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A', 'B']) }) it('Expression 12', () => { const E = TemplateLiteralParse('A(B)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['AB']) }) it('Expression 13', () => { const E = TemplateLiteralParse('(A)B') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['AB']) }) it('Expression 14', () => { const E = TemplateLiteralParse('(A)|B') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A', 'B']) }) it('Expression 15', () => { const E = TemplateLiteralParse('|') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['']) }) it('Expression 16', () => { const E = TemplateLiteralParse('||') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['']) }) it('Expression 17', () => { const E = TemplateLiteralParse('||A') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A']) }) it('Expression 18', () => { const E = TemplateLiteralParse('A||') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A']) }) it('Expression 19', () => { const E = TemplateLiteralParse('A||B') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A', 'B']) }) it('Expression 20', () => { const E = TemplateLiteralParse('A|()|B') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A', '', 'B']) }) it('Expression 21', () => { const E = TemplateLiteralParse('A|(|)|B') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A', '', 'B']) }) it('Expression 22', () => { const E = TemplateLiteralParse('A|(||)|B') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A', '', 'B']) }) it('Expression 23', () => { const E = TemplateLiteralParse('|A(||)B|') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['AB']) }) it('Expression 24', () => { const E = TemplateLiteralParse('A(B)(C)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['ABC']) }) it('Expression 25', () => { const E = TemplateLiteralParse('A(B)|(C)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['AB', 'C']) }) it('Expression 26', () => { const E = TemplateLiteralParse('A(B|C)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['AB', 'AC']) }) it('Expression 27', () => { const E = TemplateLiteralParse('A|(B|C)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['A', 'B', 'C']) }) it('Expression 28', () => { const E = TemplateLiteralParse('((A)B)C') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['ABC']) }) it('Expression 29', () => { const E = TemplateLiteralParse('(0|1)(0|1)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['00', '01', '10', '11']) }) it('Expression 30', () => { const E = TemplateLiteralParse('(0|1)|(0|1)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['0', '1', '0', '1']) }) it('Expression 31', () => { const E = TemplateLiteralParse('(0|(1|0)|1)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['0', '1', '0', '1']) }) it('Expression 32', () => { const E = TemplateLiteralParse('(0(1|0)1)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['011', '001']) }) it('Expression 33', () => { const E = TemplateLiteralParse('\\$prop(1|2|3)') const R = [...TemplateLiteralExpressionGenerate(E)] Assert.IsEqual(R, ['$prop1', '$prop2', '$prop3']) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/template-literal/index.ts000066400000000000000000000001121505437577000266210ustar00rootroot00000000000000import './finite' import './generate' import './parse' import './pattern' sinclairzx81-typebox-e0ec98c/test/runtime/type/template-literal/parse.ts000066400000000000000000000271221505437577000266360ustar00rootroot00000000000000import { TemplateLiteralParse } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/template-literal/TemplateLiteralParser', () => { // --------------------------------------------------------------- // Throws // --------------------------------------------------------------- it('Throw 1', () => { Assert.Throws(() => TemplateLiteralParse('(')) }) it('Throw 2', () => { Assert.Throws(() => TemplateLiteralParse('(')) }) // --------------------------------------------------------------- // Exact (No Default Unwrap) // --------------------------------------------------------------- it('Exact 1', () => { const E = TemplateLiteralParse('^$') Assert.IsEqual(E, { type: 'const', const: '^$', }) }) it('Exact 2', () => { const E = TemplateLiteralParse('^A$') Assert.IsEqual(E, { type: 'const', const: '^A$', }) }) // --------------------------------------------------------------- // Patterns // --------------------------------------------------------------- it('Pattern 1', () => { const E = TemplateLiteralParse('(true|false)') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'true', }, { type: 'const', const: 'false', }, ], }) }) it('Pattern 2', () => { const E = TemplateLiteralParse('(0|[1-9][0-9]*)') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: '0', }, { type: 'const', const: '[1-9][0-9]*', }, ], }) }) it('Pattern 3', () => { const E = TemplateLiteralParse('.*') Assert.IsEqual(E, { type: 'const', const: '.*', }) }) // --------------------------------------------------------------- // Expression // --------------------------------------------------------------- it('Expression 1', () => { const E = TemplateLiteralParse(')') Assert.IsEqual(E, { type: 'const', const: ')', }) }) it('Expression 2', () => { const E = TemplateLiteralParse('\\)') Assert.IsEqual(E, { type: 'const', const: ')', }) }) it('Expression 3', () => { const E = TemplateLiteralParse('\\(') Assert.IsEqual(E, { type: 'const', const: '(', }) }) it('Expression 4', () => { const E = TemplateLiteralParse('') Assert.IsEqual(E, { type: 'const', const: '', }) }) it('Expression 5', () => { const E = TemplateLiteralParse('\\') Assert.IsEqual(E, { type: 'const', const: '\\', }) }) it('Expression 6', () => { const E = TemplateLiteralParse('()') Assert.IsEqual(E, { type: 'const', const: '', }) }) it('Expression 7', () => { const E = TemplateLiteralParse('(a)') Assert.IsEqual(E, { type: 'const', const: 'a', }) }) it('Expression 8', () => { const E = TemplateLiteralParse('()))') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'const', const: '', }, { type: 'const', const: '))', }, ], }) }) it('Expression 9', () => { const E = TemplateLiteralParse('())') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'const', const: '', }, { type: 'const', const: ')', }, ], }) }) it('Expression 10', () => { const E = TemplateLiteralParse('A|B') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 11', () => { const E = TemplateLiteralParse('A|(B)') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 12', () => { const E = TemplateLiteralParse('A(B)') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 13', () => { const E = TemplateLiteralParse('(A)B') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 14', () => { const E = TemplateLiteralParse('(A)|B') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 15', () => { const E = TemplateLiteralParse('|') Assert.IsEqual(E, { type: 'const', const: '', }) }) it('Expression 16', () => { const E = TemplateLiteralParse('||') Assert.IsEqual(E, { type: 'const', const: '', }) }) it('Expression 17', () => { const E = TemplateLiteralParse('||A') Assert.IsEqual(E, { type: 'const', const: 'A', }) }) it('Expression 18', () => { const E = TemplateLiteralParse('A||') Assert.IsEqual(E, { type: 'const', const: 'A', }) }) it('Expression 19', () => { const E = TemplateLiteralParse('A||B') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 20', () => { const E = TemplateLiteralParse('A|()|B') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: '', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 21', () => { const E = TemplateLiteralParse('A|(|)|B') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: '', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 22', () => { const E = TemplateLiteralParse('A|(||)|B') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: '', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 23', () => { const E = TemplateLiteralParse('|A(||)B|') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: '', }, { type: 'const', const: 'B', }, ], }) }) it('Expression 24', () => { const E = TemplateLiteralParse('A(B)(C)') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, { type: 'const', const: 'C', }, ], }) }) it('Expression 25', () => { const E = TemplateLiteralParse('A(B)|(C)') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'and', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, ], }, { type: 'const', const: 'C', }, ], }) }) it('Expression 26', () => { const E = TemplateLiteralParse('A(B|C)') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'const', const: 'A', }, { type: 'or', expr: [ { type: 'const', const: 'B', }, { type: 'const', const: 'C', }, ], }, ], }) }) it('Expression 27', () => { const E = TemplateLiteralParse('A|(B|C)') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: 'A', }, { type: 'or', expr: [ { type: 'const', const: 'B', }, { type: 'const', const: 'C', }, ], }, ], }) }) it('Expression 28', () => { const E = TemplateLiteralParse('((A)B)C') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'and', expr: [ { type: 'const', const: 'A', }, { type: 'const', const: 'B', }, ], }, { type: 'const', const: 'C', }, ], }) }) it('Expression 29', () => { const E = TemplateLiteralParse('(0|1)(0|1)') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'or', expr: [ { type: 'const', const: '0', }, { type: 'const', const: '1', }, ], }, { type: 'or', expr: [ { type: 'const', const: '0', }, { type: 'const', const: '1', }, ], }, ], }) }) it('Expression 30', () => { const E = TemplateLiteralParse('(0|1)|(0|1)') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'or', expr: [ { type: 'const', const: '0', }, { type: 'const', const: '1', }, ], }, { type: 'or', expr: [ { type: 'const', const: '0', }, { type: 'const', const: '1', }, ], }, ], }) }) it('Expression 31', () => { const E = TemplateLiteralParse('(0|(1|0)|1)') Assert.IsEqual(E, { type: 'or', expr: [ { type: 'const', const: '0', }, { type: 'or', expr: [ { type: 'const', const: '1', }, { type: 'const', const: '0', }, ], }, { type: 'const', const: '1', }, ], }) }) it('Expression 32', () => { const E = TemplateLiteralParse('(0(1|0)1)') Assert.IsEqual(E, { type: 'and', expr: [ { type: 'const', const: '0', }, { type: 'or', expr: [ { type: 'const', const: '1', }, { type: 'const', const: '0', }, ], }, { type: 'const', const: '1', }, ], }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/type/template-literal/pattern.ts000066400000000000000000000110001505437577000271650ustar00rootroot00000000000000import { Type, TTemplateLiteral, PatternNumber, PatternString, PatternBoolean } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/template-literal/TemplateLiteralPattern', () => { const Equal = (template: TTemplateLiteral, expect: string) => { const pattern = template.pattern.slice(1, template.pattern.length - 1) Assert.IsEqual(pattern, expect) } // --------------------------------------------------------------- // Escape // --------------------------------------------------------------- it('Escape 1', () => { const T = Type.TemplateLiteral([Type.Literal('.*')]) Assert.IsEqual(T.pattern, '^\\.\\*$') }) it('Escape 2', () => { const T = Type.TemplateLiteral([Type.Literal('(')]) Assert.IsEqual(T.pattern, '^\\($') }) it('Escape 3', () => { const T = Type.TemplateLiteral([Type.Literal(')')]) Assert.IsEqual(T.pattern, '^\\)$') }) it('Escape 4', () => { const T = Type.TemplateLiteral([Type.Literal('|')]) Assert.IsEqual(T.pattern, '^\\|$') }) // --------------------------------------------------------------- // Pattern // --------------------------------------------------------------- it('Pattern 1', () => { const T = Type.TemplateLiteral([Type.Number()]) Equal(T, `${PatternNumber}`) }) it('Pattern 2', () => { const T = Type.TemplateLiteral([Type.String()]) Equal(T, `${PatternString}`) }) it('Pattern 3', () => { const T = Type.TemplateLiteral([Type.Boolean()]) Equal(T, `${PatternBoolean}`) }) it('Pattern 4', () => { const T = Type.TemplateLiteral([Type.Literal('A'), Type.Number()]) Equal(T, `A${PatternNumber}`) }) it('Pattern 5', () => { const T = Type.TemplateLiteral([Type.Literal('A'), Type.String()]) Equal(T, `A${PatternString}`) }) it('Pattern 6', () => { const T = Type.TemplateLiteral([Type.Literal('A'), Type.Boolean()]) Equal(T, `A${PatternBoolean}`) }) it('Pattern 7', () => { const T = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Number()])]) Equal(T, `(A|${PatternNumber})`) }) it('Pattern 8', () => { const T = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.String()])]) Equal(T, `(A|${PatternString})`) }) it('Pattern 9', () => { const T = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Boolean()])]) Equal(T, `(A|${PatternBoolean})`) }) // --------------------------------------------------------------- // Template // --------------------------------------------------------------- it('Template 1', () => { const T = Type.TemplateLiteral([]) Equal(T, '') }) it('Template 2', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A') ]) Equal(T, 'A') }) it('Template 3', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Literal('B'), ]) Equal(T, 'AB') }) it('Template 4', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), ]) ]) Equal(T, 'AB') }) it('Template 5', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), Type.Literal('C'), ]) ]) Equal(T, 'A(B|C)') }) it('Template 6', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), Type.Literal('C'), ]), Type.Union([ Type.Literal('D'), Type.Literal('E'), ]) ]) Equal(T, 'A(B|C)(D|E)') }) it('Template 7', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.TemplateLiteral([Type.Literal('A')]), Type.TemplateLiteral([Type.Literal('B')]) ]) Equal(T, 'AB') }) it('Template 8', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.TemplateLiteral([ Type.Literal('B'), Type.Literal('C'), ]), Type.Literal('D') ]), ]) Equal(T, 'A(BC|D)') }) it('Template 9', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.TemplateLiteral([ Type.Literal('B'), Type.Literal('C'), ]), Type.Union([ Type.Literal('D'), Type.Literal('E') ]) ]), ]) Equal(T, 'A(BC|(D|E))') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/000077500000000000000000000000001505437577000220365ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/assert/000077500000000000000000000000001505437577000233375ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/assert/assert.ts000066400000000000000000000017041505437577000252120ustar00rootroot00000000000000import { Value, AssertError } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/Assert', () => { it('Should Assert', () => { Assert.Throws(() => Value.Assert(Type.String(), 1)) }) it('Should throw AssertError', () => { try { Value.Assert(Type.String(), 1) } catch (error) { if (error instanceof AssertError) { return } throw error } }) it('Should throw AssertError and produce Iterator', () => { try { Value.Assert(Type.String(), 1) } catch (error) { if (error instanceof AssertError) { const first = error.Errors().First() Assert.HasProperty(first, 'type') Assert.HasProperty(first, 'schema') Assert.HasProperty(first, 'path') Assert.HasProperty(first, 'value') Assert.HasProperty(first, 'message') return } throw error } }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/assert/index.ts000066400000000000000000000000221505437577000250100ustar00rootroot00000000000000import './assert' sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/000077500000000000000000000000001505437577000227705ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/any.ts000066400000000000000000000027621505437577000241360ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Any', () => { const T = Type.Any() it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from boolean', () => { const value = false const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result.getTime(100), 100) }) it('Should preserve', () => { const value = { a: 1, b: 2 } const result = Value.Cast(T, value) Assert.IsEqual(result, { a: 1, b: 2 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/array.ts000066400000000000000000000115141505437577000244600ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Array', () => { const T = Type.Array(Type.Number(), { default: [1, 2, 3] }) const E = [1, 2, 3] it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, [1]) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = [6, 7, 8] const result = Value.Cast(T, value) Assert.IsEqual(result, [6, 7, 8]) }) it('Should preserve with invalid element set to default', () => { const value = [6, 7, 8, 'hello', 9] const result = Value.Cast(T, value) Assert.IsEqual(result, [6, 7, 8, 0, 9]) }) // ----------------------------------------------------------------- // Constraints: Ranges // ----------------------------------------------------------------- it('Should cast array and truncate to maxItems from value', () => { const result = Value.Cast(Type.Array(Type.Number(), { maxItems: 3 }), [0, 1, 2, 4, 5, 6]) Assert.IsEqual(result, [0, 1, 2]) }) it('Should cast arrays and append array to minItems from value', () => { const result = Value.Cast(Type.Array(Type.Number(), { minItems: 6 }), [0, 1, 2]) Assert.IsEqual(result, [0, 1, 2, 0, 0, 0]) }) it('Should cast array and truncate to maxItems from default value', () => { const result = Value.Cast(Type.Array(Type.Number(), { maxItems: 3, default: [0, 1, 2, 4, 5, 6] }), null) Assert.IsEqual(result, [0, 1, 2]) }) it('Should cast arrays and append array to minItems from default value', () => { const result = Value.Cast(Type.Array(Type.Number({ default: 1 }), { minItems: 6, default: [0, 1, 2] }), null) Assert.IsEqual(result, [0, 1, 2, 1, 1, 1]) }) // ----------------------------------------------------------------- // Constraints: Unique // ----------------------------------------------------------------- it('Should cast arrays with uniqueItems with unique default value', () => { const result = Value.Cast(Type.Array(Type.Number(), { uniqueItems: true, default: [0, 1, 2] }), null) Assert.IsEqual(result, [0, 1, 2]) }) it('Should cast arrays with uniqueItems with unique value', () => { const result = Value.Cast(Type.Array(Type.Number(), { uniqueItems: true }), [0, 1, 2]) Assert.IsEqual(result, [0, 1, 2]) }) it('Should throw when casting arrays with uniqueItems and no value or default value', () => { Assert.Throws(() => Value.Cast(Type.Array(Type.Number(), { uniqueItems: true }), null)) }) it('Should throw when casting arrays with uniqueItems and not enough values to populate set', () => { Assert.Throws(() => Value.Cast(Type.Array(Type.Number(), { minItems: 3, uniqueItems: true }), [0, 1])) }) it('Should throw when casting arrays with uniqueItems and not enough default values to populate set', () => { Assert.Throws(() => Value.Cast(Type.Array(Type.Number(), { minItems: 3, uniqueItems: true, default: [0, 1] }), null)) }) // ----------------------------------------------------------------- // Suggestion: https://github.com/sinclairzx81/typebox/issues/239 // ----------------------------------------------------------------- it('Should remove duplicates if uniqueItems is true', () => { const T = Type.Array(Type.Number(), { uniqueItems: true }) const value = [1, 1, 2, 2] const result = Value.Cast(T, value) Assert.IsEqual(result, [1, 2]) }) it('Should should fill up with defaults to minItems', () => { const T = Type.Array(Type.Number(), { minItems: 3 }) const value = [1, 2] const result = Value.Cast(T, value) Assert.IsEqual(result, [1, 2, 0]) }) it('Should should truncate to maxItems', () => { const T = Type.Array(Type.Number(), { maxItems: 3 }) const value = [1, 2, 3, 4] const result = Value.Cast(T, value) Assert.IsEqual(result, [1, 2, 3]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/async-iterator.ts000066400000000000000000000022421505437577000263040ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/AsyncIterator', () => { const T = Type.AsyncIterator(Type.Any()) it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsTrue(Symbol.asyncIterator in result) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsTrue(Symbol.asyncIterator in result) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsTrue(Symbol.asyncIterator in result) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsTrue(Symbol.asyncIterator in result) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsTrue(Symbol.asyncIterator in result) }) it('Should preseve', () => { const value = (async function* () {})() const result = Value.Cast(T, value) Assert.IsTrue(value === result) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/bigint.ts000066400000000000000000000027341505437577000246220ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/BigInt', () => { const T = Type.BigInt() const E = BigInt(0) it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 0 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = BigInt(100) const result = Value.Cast(T, value) Assert.IsEqual(result, BigInt(100)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/boolean.ts000066400000000000000000000027171505437577000247660ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Boolean', () => { const T = Type.Boolean() const E = false it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 0 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, true) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/composite.ts000066400000000000000000000042631505437577000253470ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Composite', () => { const A = Type.Object({ x: Type.Number({ default: 0 }), y: Type.Number({ default: 1 }), z: Type.Number({ default: 2 }), }) const B = Type.Object({ a: Type.Number({ default: 'a' }), b: Type.Number({ default: 'b' }), c: Type.Number({ default: 'c' }), }) const T = Type.Composite([A, B]) const E = { x: 0, y: 1, z: 2, a: 'a', b: 'b', c: 'c', } it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = E const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast and preserve object', () => { const value = { x: 7, y: 8, z: 9 } const result = Value.Cast(T, value) Assert.IsEqual(result, { x: 7, y: 8, z: 9, a: 'a', b: 'b', c: 'c', }) }) it('Should upcast and preserve from incorrect properties', () => { const value = { x: {}, y: 8, z: 9 } const result = Value.Cast(T, value) Assert.IsEqual(result, { x: 0, y: 8, z: 9, a: 'a', b: 'b', c: 'c', }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/date.ts000066400000000000000000000023431505437577000242570ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Date', () => { const T = Type.Date() const E = new Date(0) it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.InRange(result.getTime(), new Date().getTime(), 1000) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.InRange(result.getTime(), new Date().getTime(), 1000) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.InRange(result.getTime(), new Date().getTime(), 1000) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.InRange(result.getTime(), new Date().getTime(), 1000) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.InRange(result.getTime(), new Date().getTime(), 1000) }) it('Should preseve', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result.getTime(), 100) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/enum.ts000066400000000000000000000032121505437577000243020ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Boolean', () => { enum Foo { A, B, } const T = Type.Enum(Foo) const E = Foo.A it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 123 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from enum A', () => { const value = Foo.A const result = Value.Cast(T, value) Assert.IsEqual(result, Foo.A) }) it('Should upcast from enum B', () => { const value = Foo.B const result = Value.Cast(T, value) Assert.IsEqual(result, Foo.B) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/import.ts000066400000000000000000000025361505437577000246600ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Import', () => { const T = Type.Module({ A: Type.Number(), }).Import('A') const E = 0 it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, 1) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preseve', () => { const value = 123 const result = Value.Cast(T, value) Assert.IsEqual(result, 123) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/index.ts000066400000000000000000000011231505437577000244440ustar00rootroot00000000000000import './any' import './array' import './async-iterator' import './bigint' import './boolean' import './composite' import './date' import './enum' import './import' import './integer' import './intersect' import './iterator' import './keyof' import './kind' import './literal' import './never' import './not' import './null' import './number' import './object' import './recursive' import './record' import './regexp' import './string' import './symbol' import './template-literal' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/integer.ts000066400000000000000000000022661505437577000250030ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Integer', () => { const T = Type.Integer() const E = 0 it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, 1) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/intersect.ts000066400000000000000000000076731505437577000253550ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Intersect', () => { it('Should cast from an invalid object', () => { // prettier-ignore const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const V = Value.Cast(T, 1) Assert.IsEqual(V, { x: 0, y: 0 }) }) it('Should cast from an partial object and preserve', () => { // prettier-ignore const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const V = Value.Cast(T, { x: 1 }) Assert.IsEqual(V, { x: 1, y: 0 }) }) it('Should cast and use default values', () => { // prettier-ignore const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number({ default: 42 }) }) ]) const V = Value.Cast(T, { x: 1 }) Assert.IsEqual(V, { x: 1, y: 42 }) }) it('Should throw with an illogical intersect', () => { // prettier-ignore const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.String() }) ]) Assert.Throws(() => Value.Cast(T, { x: 1 })) }) it('Should throw with an illogical intersect (primative)', () => { // prettier-ignore const T = Type.Intersect([ Type.Number(), Type.String() ]) Assert.Throws(() => Value.Cast(T, { x: 1 })) }) it('Should use last intersected default for equivalent sub schemas', () => { // prettier-ignore const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number({ default: 1000 }) }) ]) const V = Value.Cast(T, null) Assert.IsEqual(V, { x: 1000 }) }) it('Should use last intersected default for equivalent sub schemas (primitives)', () => { // prettier-ignore const T = Type.Intersect([ Type.Number(), Type.Number({ default: 1000 }) ]) const V = Value.Cast(T, null) Assert.IsEqual(V, 1000) }) it('Should preserve if default is specified', () => { // prettier-ignore const T = Type.Intersect([ Type.Number(), Type.Number({ default: 1000 }) ]) const V = Value.Cast(T, 2000) Assert.IsEqual(V, 2000) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1264 // ---------------------------------------------------------------- it('Should preserve intersected properties', () => { const T = Type.Intersect([ Type.Object({}), Type.Object({ name: Type.String(), age: Type.Optional(Type.Number()), location: Type.Object({ lat: Type.Number(), long: Type.Number(), }), greeting: Type.String(), }), ]) const V0 = Value.Cast(T, { greeting: 'Hello' }) const V1 = Value.Cast(T, { location: null, greeting: 'Hello' }) const V2 = Value.Cast(T, { location: { lat: 1 }, greeting: 'Hello' }) const V3 = Value.Cast(T, { location: { lat: 1, long: 1 }, greeting: 'Hello' }) Assert.IsEqual(V0, { name: '', location: { lat: 0, long: 0 }, greeting: 'Hello' }) Assert.IsEqual(V1, { name: '', location: { lat: 0, long: 0 }, greeting: 'Hello' }) Assert.IsEqual(V2, { name: '', location: { lat: 1, long: 0 }, greeting: 'Hello' }) Assert.IsEqual(V3, { name: '', location: { lat: 1, long: 1 }, greeting: 'Hello' }) }) // -------------------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1269#issuecomment-2993924180 // -------------------------------------------------------------------------- it('Should Cast with intersected Record', () => { const T = Type.Intersect([Type.Record(Type.TemplateLiteral('x-${string}'), Type.Unknown()), Type.Object({ name: Type.String() })]) const R = Value.Cast(T, {}) Assert.IsEqual(R, { name: '' }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/iterator.ts000066400000000000000000000021711505437577000251720ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Iterator', () => { const T = Type.Iterator(Type.Any()) it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsTrue(Symbol.iterator in result) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsTrue(Symbol.iterator in result) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsTrue(Symbol.iterator in result) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsTrue(Symbol.iterator in result) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsTrue(Symbol.iterator in result) }) it('Should preseve', () => { const value = (function* () {})() const result = Value.Cast(T, value) Assert.IsTrue(value === result) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/keyof.ts000066400000000000000000000030511505437577000244540ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/KeyOf', () => { const T = Type.KeyOf( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) const E = 'x' it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = 'y' const result = Value.Cast(T, value) Assert.IsEqual(result, 'y') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/kind.ts000066400000000000000000000035751505437577000242770ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type, Kind, TypeRegistry } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Kind', () => { // --------------------------------------------------------- // Fixtures // --------------------------------------------------------- before(() => TypeRegistry.Set('Kind', (schema, value) => value === 'hello' || value === 'world')) after(() => TypeRegistry.Clear()) // --------------------------------------------------------- // Tests // --------------------------------------------------------- const T = Type.Unsafe({ [Kind]: 'Kind', default: 'hello' }) const E = 'hello' it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = false const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = { a: 'hello', b: 'world' } const result = Value.Cast( Type.Object({ a: T, b: T, }), value, ) Assert.IsEqual(result, { a: 'hello', b: 'world' }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/literal.ts000066400000000000000000000027321505437577000250000ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Literal', () => { const T = Type.Literal('hello') const E = 'hello' it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preseve', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, 'hello') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/never.ts000066400000000000000000000021421505437577000244560ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Never', () => { const T = Type.Never() it('Should throw from string', () => { const value = 'hello' Assert.Throws(() => Value.Cast(T, value)) }) it('Should throw from number', () => { const value = 1 Assert.Throws(() => Value.Cast(T, value)) }) it('Should throw from boolean', () => { const value = false Assert.Throws(() => Value.Cast(T, value)) }) it('Should throw from object', () => { const value = {} Assert.Throws(() => Value.Cast(T, value)) }) it('Should throw from array', () => { const value = [1] Assert.Throws(() => Value.Cast(T, value)) }) it('Should throw from undefined', () => { const value = undefined Assert.Throws(() => Value.Cast(T, value)) }) it('Should throw from null', () => { const value = null Assert.Throws(() => Value.Cast(T, value)) }) it('Should upcast from date', () => { const value = null Assert.Throws(() => Value.Cast(T, value)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/not.ts000066400000000000000000000027641505437577000241510ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Not', () => { const T = Type.Not(Type.String(), { default: 0 }) it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, 0) // default }) it('Should upcast from number', () => { const value = 0 const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should preserve', () => { const value = 100 const result = Value.Cast(T, value) Assert.IsEqual(result, 100) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/null.ts000066400000000000000000000027041505437577000243150ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Null', () => { const T = Type.Null() const E = null it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preseve', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/number.ts000066400000000000000000000024661505437577000246400ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Number', () => { const T = Type.Number() const E = 0 it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, 1) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preseve', () => { const value = 123 const result = Value.Cast(T, value) Assert.IsEqual(result, 123) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/object.ts000066400000000000000000000072331505437577000246130ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Object', () => { const T = Type.Object({ a: Type.Number({ default: 'a' }), b: Type.Number({ default: 'b' }), c: Type.Number({ default: 'c' }), x: Type.Number({ default: 0 }), y: Type.Number({ default: 1 }), z: Type.Number({ default: 2 }), }) const E = { x: 0, y: 1, z: 2, a: 'a', b: 'b', c: 'c', } it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = E const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = { x: 7, y: 8, z: 9, a: 10, b: 11, c: 12 } const result = Value.Cast(T, value) Assert.IsEqual(result, { x: 7, y: 8, z: 9, a: 10, b: 11, c: 12, }) }) it('Should upcast and preserve partial object', () => { const value = { x: 7, y: 8, z: 9 } const result = Value.Cast(T, value) Assert.IsEqual(result, { x: 7, y: 8, z: 9, a: 'a', b: 'b', c: 'c', }) }) it('Should upcast and preserve partial object with incorrect properties', () => { const value = { x: {}, y: 8, z: 9 } const result = Value.Cast(T, value) Assert.IsEqual(result, { x: 0, y: 8, z: 9, a: 'a', b: 'b', c: 'c', }) }) it('Should upcast and preserve partial object and omit unknown properties', () => { const value = { x: 7, y: 8, z: 9, unknown: 'foo' } const result = Value.Cast(T, value) Assert.IsEqual(result, { x: 7, y: 8, z: 9, a: 'a', b: 'b', c: 'c', }) }) it('Should upcast and create invalid additional properties', () => { const result = Value.Cast( Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Object({ a: Type.Number(), b: Type.Number(), }), }, ), { x: 1, y: 2, z: true, }, ) Assert.IsEqual(result, { x: 1, y: 2, z: { a: 0, b: 0 }, }) }) it('Should upcast and preserve additional properties', () => { const result = Value.Cast( Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Object({ a: Type.Number(), b: Type.Number(), }), }, ), { x: 1, y: 2, z: { b: 1 }, }, ) Assert.IsEqual(result, { x: 1, y: 2, z: { a: 0, b: 1 }, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/record.ts000066400000000000000000000041021505437577000246130ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Record', () => { const T = Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) const E = {} it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = E const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = { a: { x: 1, y: 2, z: 3 }, b: { x: 4, y: 5, z: 6 }, } const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should preserve and patch invalid records', () => { const value = { a: { x: 1, y: 2, z: 3 }, b: { x: 4, y: 5, z: {} }, c: [1, 2, 3], d: 1, e: { x: 1, y: 2, w: 9000 }, } const result = Value.Cast(T, value) Assert.IsEqual(result, { a: { x: 1, y: 2, z: 3 }, b: { x: 4, y: 5, z: 0 }, c: { x: 0, y: 0, z: 0 }, d: { x: 0, y: 0, z: 0 }, e: { x: 1, y: 2, z: 0 }, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/recursive.ts000066400000000000000000000050301505437577000253450ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Recursive', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const E = { id: '', nodes: [] } it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = E const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, { id: 'D', nodes: [] }, ], } const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from varying types', () => { const TypeA = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const TypeB = Type.Recursive((This) => Type.Object({ id: Type.String(), name: Type.String({ default: 'test' }), nodes: Type.Array(This), }), ) const ValueA = { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, { id: 'D', nodes: [] }, ], } const ValueB = Value.Cast(TypeB, ValueA) // Assert.isEqual(ValueB, { // id: 'A', // name: 'test', // nodes: [ // { id: 'B', name: 'test', nodes: [] }, // { id: 'C', name: 'test', nodes: [] }, // { id: 'D', name: 'test', nodes: [] }, // ], // }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/regexp.ts000066400000000000000000000034001505437577000246270ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/RegExp', () => { const T = Type.RegExp(/foo/, { default: 'foo' }) const E = 'foo' it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, 'foo') }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = 'foo' const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) // ---------------------------------------------------------------- // Throw // ---------------------------------------------------------------- it('Should throw with no default', () => { const T = Type.RegExp(/foo/) Assert.Throws(() => Value.Cast(T, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/string.ts000066400000000000000000000022711505437577000246500ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/String', () => { const T = Type.String() const E = '' it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, 'hello') }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = 'foo' const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/symbol.ts000066400000000000000000000030341505437577000246450ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Symbol', () => { const T = Type.Symbol() it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsTypeOf(result, 'symbol') }) it('Should upcast from number', () => { const value = 0 const result = Value.Cast(T, value) Assert.IsTypeOf(result, 'symbol') }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsTypeOf(result, 'symbol') }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsTypeOf(result, 'symbol') }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsTypeOf(result, 'symbol') }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsTypeOf(result, 'symbol') }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsTypeOf(result, 'symbol') }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsTypeOf(result, 'symbol') }) it('Should preserve', () => { const value = Symbol('hello') const result = Value.Cast(T, value) Assert.IsEqual(result.description, value.description) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/template-literal.ts000066400000000000000000000030401505437577000266020ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/TemplateLiteral', () => { const T = Type.TemplateLiteral([Type.Literal('hello'), Type.Literal('world')]) const E = 'helloworld' it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preseve', () => { const value = 'helloworld' const result = Value.Cast(T, value) Assert.IsEqual(result, 'helloworld') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/tuple.ts000066400000000000000000000042171505437577000244750ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Tuple', () => { const T = Type.Tuple([Type.Number(), Type.String()]) const E = [0, ''] it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, [1, '']) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = [42, 'world'] const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast with empty', () => { const value = [] as any[] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should append with less than tuple length', () => { const value = [42] const result = Value.Cast(T, value) Assert.IsEqual(result, [42, '']) }) it('Should truncate with greater than tuple length', () => { const value = [42, '', true] const result = Value.Cast(T, value) Assert.IsEqual(result, [42, '']) }) it('Should preserve and patch invalid element', () => { const value = [{}, 'hello'] const result = Value.Cast(T, value) Assert.IsEqual(result, [0, 'hello']) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/uint8array.ts000066400000000000000000000030571505437577000254530ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Uint8Array', () => { const T = Type.Uint8Array({ default: new Uint8Array([0, 1, 2, 3]) }) const E = new Uint8Array([0, 1, 2, 3]) it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = new Uint8Array([6, 7, 8, 9, 10]) const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/undefined.ts000066400000000000000000000027351505437577000253100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Undefined', () => { const T = Type.Undefined() const E = undefined it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preseve', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/union.ts000066400000000000000000000262001505437577000244700ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Union', () => { const A = Type.Object( { type: Type.Literal('A'), x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const B = Type.Object( { type: Type.Literal('B'), a: Type.String(), b: Type.String(), c: Type.String(), }, { additionalProperties: false }, ) const T = Type.Union([A, B]) const E = { type: 'A', x: 0, y: 0, z: 0, } it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve A', () => { const value = { type: 'A', x: 1, y: 2, z: 3 } const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should preserve B', () => { const value = { type: 'B', a: 'a', b: 'b', c: 'c' } const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should infer through heuristics #1', () => { const value = { type: 'A', a: 'a', b: 'b', c: 'c' } const result = Value.Cast(T, value) Assert.IsEqual(result, { type: 'A', x: 0, y: 0, z: 0 }) }) it('Should infer through heuristics #2', () => { const value = { type: 'B', x: 1, y: 2, z: 3 } const result = Value.Cast(T, value) Assert.IsEqual(result, { type: 'B', a: '', b: '', c: '' }) }) it('Should infer through heuristics #3', () => { const value = { type: 'A', a: 'a', b: 'b', c: null } const result = Value.Cast(T, value) Assert.IsEqual(result, { type: 'A', x: 0, y: 0, z: 0 }) }) it('Should infer through heuristics #4', () => { const value = { type: 'B', x: 1, y: 2, z: {} } const result = Value.Cast(T, value) Assert.IsEqual(result, { type: 'B', a: '', b: '', c: '' }) }) it('Should infer through heuristics #5', () => { const value = { type: 'B', x: 1, y: 2, z: null } const result = Value.Cast(T, value) Assert.IsEqual(result, { type: 'B', a: '', b: '', c: '' }) }) it('Should infer through heuristics #6', () => { const value = { x: 1 } const result = Value.Cast(T, value) Assert.IsEqual(result, { type: 'A', x: 1, y: 0, z: 0 }) }) it('Should infer through heuristics #7', () => { const value = { a: null } // property existing should contribute const result = Value.Cast(T, value) Assert.IsEqual(result, { type: 'B', a: '', b: '', c: '' }) }) it('Should cast with default value (create)', () => { const result = Value.Cast( Type.Object({ id: Type.Number(), value: Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')], { default: 'C' }), }), { id: 42, value: 'D', }, ) Assert.IsEqual(result, { id: 42, value: 'C', }) }) it('Should cast with default value (preserve)', () => { const result = Value.Cast( Type.Object({ id: Type.Number(), value: Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')], { default: 'C' }), }), { id: 42, value: 'B', }, ) Assert.IsEqual(result, { id: 42, value: 'B', }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/880 // ---------------------------------------------------------------- // prettier-ignore it('Should dereference union variants', () => { const A = Type.Object({ type: Type.Literal('A') }, { $id: 'A' }) const B = Type.Object({ type: Type.Literal('B'), value: Type.Number() }, { $id: 'B' }) const RA = Type.Union([A, B]) const RB = Type.Union([Type.Ref('A'), Type.Ref('B')]) // variant 0 Assert.IsEqual(Value.Cast(RA, [A, B], { type: 'B' }), { type: 'B', value: 0 }) Assert.IsEqual(Value.Cast(RB, [A, B], { type: 'B' }), { type: 'B', value: 0 }) // variant 1 Assert.IsEqual(Value.Cast(RA, [A, B], { type: 'A' }), { type: 'A' }) Assert.IsEqual(Value.Cast(RB, [A, B], { type: 'A' }), { type: 'A' }) }) // ------------------------------------------------------------------------ // ref: https://github.com/sinclairzx81/typebox/issues/1268 // ------------------------------------------------------------------------ it('should correctly score nested union types #1', () => { const A = Type.Union([ Type.Union([ Type.Object({ type: Type.Literal('a'), name: Type.String(), in: Type.String(), }), Type.Object({ type: Type.Literal('b'), description: Type.Optional(Type.String()), nested: Type.Object({ a: Type.String(), b: Type.Optional(Type.String()), }), }), ]), Type.Object({ $ref: Type.String(), description: Type.Optional(Type.String()), }), ]) Assert.IsEqual( Value.Cast(A, { type: 'b', description: 'Hello World', nested: { b: 'hello', }, }), { type: 'b', description: 'Hello World', nested: { a: '', b: 'hello' }, }, ) }) it('should correctly score nested union types #2', () => { const A = Type.Union([ Type.Union([ Type.Object({ prop1: Type.String(), prop2: Type.String(), prop3: Type.String(), }), Type.Object({ prop1: Type.String(), prop4: Type.String(), prop5: Type.String(), }), ]), Type.Union([ Type.Object({ prop6: Type.String(), prop7: Type.String(), prop8: Type.String(), }), Type.Object({ prop1: Type.String(), prop9: Type.String(), prop10: Type.String(), }), ]), ]) // Picks the first union variant when the score is equal Assert.IsEqual( Value.Cast(A, { prop1: '', }), { prop1: '', prop2: '', prop3: '', }, ) Assert.IsEqual( Value.Cast(A, { prop1: '', prop4: '', }), { prop1: '', prop4: '', prop5: '', }, ) Assert.IsEqual( Value.Cast(A, { prop6: '', }), { prop6: '', prop7: '', prop8: '', }, ) }) it('should correctly score nested union types #3', () => { const A = Type.Union([ Type.Object({ prop1: Type.String(), prop2: Type.String(), prop3: Type.String(), }), Type.Object({ prop4: Type.String(), prop5: Type.String(), prop6: Type.String(), }), Type.Union([ Type.Object({ prop4: Type.String(), prop5: Type.String(), prop6: Type.String(), }), Type.Object({ prop1: Type.String(), prop2: Type.String(), prop7: Type.String(), prop8: Type.String(), }), ]), ]) Assert.IsEqual( Value.Cast(A, { prop1: '', prop2: '', prop7: '', }), { prop1: '', prop2: '', prop7: '', prop8: '', }, ) }) it('should correctly score nested union types #4', () => { const A = Type.Union([ Type.Object({ prop1: Type.String(), prop2: Type.String(), prop3: Type.String(), }), Type.Union([ Type.Object({ prop4: Type.String(), prop5: Type.String(), prop6: Type.String(), }), Type.Union([ Type.Object({ prop1: Type.String(), prop2: Type.String(), prop7: Type.String(), prop8: Type.String(), }), Type.Union([ Type.Object({ prop1: Type.String(), prop2: Type.String(), prop9: Type.String(), prop10: Type.String(), }), Type.Object({ prop1: Type.String(), prop2: Type.String(), prop11: Type.String(), prop12: Type.String(), }), ]), ]), ]), ]) Assert.IsEqual( Value.Cast(A, { prop1: '', prop2: '', prop9: '', }), { prop1: '', prop2: '', prop9: '', prop10: '', }, ) }) // ------------------------------------------------------------------------ // ref: https://github.com/sinclairzx81/typebox/issues/1292 // ------------------------------------------------------------------------ it('should correctly score object unions with shared properties #1', () => { const schema = Type.Union([ Type.Object({ summary: Type.Optional(Type.String()), description: Type.Optional(Type.String()), parameters: Type.Optional(Type.Array(Type.Any())), responses: Type.Optional(Type.Record(Type.String(), Type.Any())), requestBody: Type.Optional(Type.Any()), }), Type.Object({ $ref: Type.String(), summary: Type.Optional(Type.String()), }), ]) Assert.IsEqual( Value.Cast(schema, { summary: 'Test Summary', parameters: {}, }), { summary: 'Test Summary', parameters: [], }, ) }) it('should correctly score object unions with shared properties #2', () => { const A = Type.Union([ Type.Object({ prop1: Type.String(), prop2: Type.String(), prop3: Type.String(), }), Type.Object({ prop1: Type.String(), prop2: Type.String(), prop4: Type.String(), prop5: Type.String(), prop6: Type.String(), prop7: Type.String(), prop8: Type.String(), prop9: Type.String(), prop10: Type.String(), }), ]) Assert.IsEqual( Value.Cast(A, { prop1: '', prop2: '', prop7: '', }), { prop1: '', prop2: '', prop4: '', prop5: '', prop6: '', prop7: '', prop8: '', prop9: '', prop10: '', }, ) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/unknown.ts000066400000000000000000000027741505437577000250510ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Unknown', () => { const T = Type.Unknown() it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from boolean', () => { const value = false const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, value) }) it('Should upcast from date', () => { const value = new Date(100) const result: any = Value.Cast(T, value) Assert.IsEqual(result.getTime(), 100) }) it('Should preserve', () => { const value = { a: 1, b: 2 } const result = Value.Cast(T, value) Assert.IsEqual(result, { a: 1, b: 2 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/cast/void.ts000066400000000000000000000027241505437577000243060ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Void', () => { const T = Type.Void() const E = undefined it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should upcast from date', () => { const value = new Date(100) const result = Value.Cast(T, value) Assert.IsEqual(result, E) }) it('Should preserve', () => { const value = undefined const result = Value.Cast(T, value) Assert.IsEqual(result, undefined) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/000077500000000000000000000000001505437577000231135ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/check/any.ts000066400000000000000000000024341505437577000242550ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Any', () => { const T = Type.Any() it('Should pass string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/argument.ts000066400000000000000000000024471505437577000253140ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Argument', () => { const T = Type.Argument(0) it('Should pass string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/array.ts000066400000000000000000000136441505437577000246110ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Array', () => { it('Should pass number array', () => { const T = Type.Array(Type.Number()) const value = [1, 2, 3] const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail number array', () => { const T = Type.Array(Type.Number()) const value = ['a', 'b', 'c'] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass object array', () => { const T = Type.Array(Type.Object({ x: Type.Number() })) const value = [{ x: 1 }, { x: 1 }, { x: 1 }] const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail object array', () => { const T = Type.Array(Type.Object({ x: Type.Number() })) const value = [{ x: 1 }, { x: 1 }, 1] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(Type.Array(Type.Any()), value) Assert.IsEqual(result, false) }) it('Should validate array with unique primitive items', () => { const T = Type.Array(Type.Number(), { uniqueItems: true }) const result = Value.Check(T, [0, 1, 2]) Assert.IsEqual(result, true) }) it('Should not validate array with non-unique primitive items', () => { const T = Type.Array(Type.Number(), { uniqueItems: true }) const result = Value.Check(T, [0, 0, 2]) Assert.IsEqual(result, false) }) it('Should validate array with unique object items', () => { const T = Type.Array(Type.Object({ x: Type.Number(), y: Type.Number() }), { uniqueItems: true }) const result = Value.Check(T, [ { x: 1, y: 1 }, { x: 2, y: 2 }, { x: 3, y: 3 }, ]) Assert.IsEqual(result, true) }) it('Should not validate array with non-unique object items', () => { const T = Type.Array(Type.Object({ x: Type.Number(), y: Type.Number() }), { uniqueItems: true }) const result = Value.Check(T, [ { x: 1, y: 1 }, { x: 1, y: 1 }, { x: 3, y: 3 }, ]) Assert.IsEqual(result, false) }) // --------------------------------------------------------- // Contains // --------------------------------------------------------- it('Should validate for contains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1) }) Assert.IsTrue(Value.Check(T, [1])) Assert.IsTrue(Value.Check(T, [1, 2])) Assert.IsFalse(Value.Check(T, [])) Assert.IsFalse(Value.Check(T, [2])) }) it('Should validate for minContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), minContains: 3 }) Assert.IsTrue(Value.Check(T, [1, 1, 1, 2])) Assert.IsTrue(Value.Check(T, [2, 1, 1, 1, 2])) Assert.IsTrue(Value.Check(T, [1, 1, 1])) Assert.IsFalse(Value.Check(T, [])) Assert.IsFalse(Value.Check(T, [1, 1])) Assert.IsFalse(Value.Check(T, [2])) }) it('Should validate for maxContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), maxContains: 3 }) Assert.IsTrue(Value.Check(T, [1, 1, 1])) Assert.IsTrue(Value.Check(T, [1, 1])) Assert.IsTrue(Value.Check(T, [2, 2, 2, 2, 1, 1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1, 1])) }) it('Should validate for minContains and maxContains', () => { const T = Type.Array(Type.Number(), { contains: Type.Literal(1), minContains: 3, maxContains: 5 }) Assert.IsFalse(Value.Check(T, [1, 1])) Assert.IsTrue(Value.Check(T, [1, 1, 1])) Assert.IsTrue(Value.Check(T, [1, 1, 1, 1])) Assert.IsTrue(Value.Check(T, [1, 1, 1, 1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1, 1, 1, 1])) }) it('Should not validate minContains and maxContains when contains is unspecified', () => { const T = Type.Array(Type.Number(), { minContains: 3, maxContains: 5 }) Assert.IsFalse(Value.Check(T, [1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1, 1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1, 1, 1, 1])) }) it('Should produce illogical schema when contains is not sub type of items', () => { const T = Type.Array(Type.Number(), { contains: Type.String(), minContains: 3, maxContains: 5 }) Assert.IsFalse(Value.Check(T, [1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1, 1, 1])) Assert.IsFalse(Value.Check(T, [1, 1, 1, 1, 1, 1])) }) // ---------------------------------------------------------------- // Issue: https://github.com/sinclairzx81/typebox/discussions/607 // ---------------------------------------------------------------- it('Should correctly handle undefined array properties', () => { const Answer = Type.Object({ text: Type.String(), isCorrect: Type.Boolean(), }) const Question = Type.Object({ text: Type.String(), options: Type.Array(Answer, { minContains: 1, maxContains: 1, contains: Type.Object({ text: Type.String(), isCorrect: Type.Literal(true), }), }), }) Assert.IsFalse(Value.Check(Question, { text: 'A' })) Assert.IsFalse(Value.Check(Question, { text: 'A', options: [] })) Assert.IsTrue(Value.Check(Question, { text: 'A', options: [{ text: 'A', isCorrect: true }] })) Assert.IsTrue( Value.Check(Question, { text: 'A', options: [ { text: 'A', isCorrect: true }, { text: 'B', isCorrect: false }, ], }), ) Assert.IsFalse(Value.Check(Question, { text: 'A', options: [{ text: 'A', isCorrect: false }] })) Assert.IsFalse( Value.Check(Question, { text: 'A', options: [ { text: 'A', isCorrect: true }, { text: 'B', isCorrect: true }, ], }), ) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/async-iterator.ts000066400000000000000000000013611505437577000264300ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/AsyncIterator', () => { it('Should pass async iterator 1', () => { async function* f() {} const T = Type.AsyncIterator(Type.Any()) const result = Value.Check(T, f()) Assert.IsEqual(result, true) }) it('Should pass async iterator 2', () => { const T = Type.AsyncIterator(Type.Any()) const result = Value.Check(T, { [Symbol.asyncIterator]: () => {}, }) Assert.IsEqual(result, true) }) it('Should pass async iterator', () => { const T = Type.AsyncIterator(Type.Any()) const result = Value.Check(T, {}) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/bigint.ts000066400000000000000000000022561505437577000247440ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/BigInt', () => { const T = Type.BigInt() it('Should not validate NaN', () => { const T = Type.BigInt() const result = Value.Check(T, NaN) Assert.IsEqual(result, false) }) it('Should not validate +Infinity', () => { const T = Type.BigInt() const result = Value.Check(T, Infinity) Assert.IsEqual(result, false) }) it('Should not validate -Infinity', () => { const T = Type.BigInt() const result = Value.Check(T, -Infinity) Assert.IsEqual(result, false) }) it('Should fail integer', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail integer', () => { const value = 3.14 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass bigint', () => { const result = Value.Check(T, BigInt(0)) Assert.IsEqual(result, true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/boolean.ts000066400000000000000000000024531505437577000251060ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Boolean', () => { const T = Type.Boolean() it('Should fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/composite.ts000066400000000000000000000033551505437577000254730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Composite', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const B = Type.Object({ a: Type.String(), b: Type.String(), c: Type.String(), }) const T = Type.Composite([A, B]) it('Should pass composite', () => { const value = { x: 1, y: 1, z: 1, a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail intersect with invalid property', () => { const value = { x: true, y: 1, z: 1, a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail intersect with missing property', () => { const value = { y: 1, z: 1, a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail intersect with primitive value', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass intersect with optional properties', () => { const A = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), z: Type.Optional(Type.Number()), }) const B = Type.Object({ a: Type.String(), b: Type.String(), c: Type.String(), }) const T = Type.Composite([A, B]) const value = { a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/const.ts000066400000000000000000000021601505437577000246100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Const', () => { it('Should validate 1', () => { const T = Type.Const(1) Assert.IsTrue(Value.Check(T, 1)) }) it('Should validate 2', () => { const T = Type.Const('hello') Assert.IsTrue(Value.Check(T, 'hello')) }) it('Should validate 3', () => { const T = Type.Const(true) Assert.IsTrue(Value.Check(T, true)) }) it('Should validate 4', () => { const T = Type.Const({ x: 1, y: 2 }) Assert.IsTrue(Value.Check(T, { x: 1, y: 2 })) }) it('Should validate 5', () => { const T = Type.Const([1, 2, 3]) Assert.IsTrue(Value.Check(T, [1, 2, 3])) }) it('Should validate 6', () => { const T = Type.Const([1, true, 'hello']) Assert.IsTrue(Value.Check(T, [1, true, 'hello'])) }) it('Should validate 7', () => { const T = Type.Const({ x: [1, 2, 3, 4], y: { x: 1, y: 2, z: 3 }, }) Assert.IsTrue( Value.Check(T, { x: [1, 2, 3, 4], y: { x: 1, y: 2, z: 3 }, }), ) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/constructor.ts000066400000000000000000000036441505437577000260570ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Constructor', () => { it('Should validate constructor 1', () => { const T = Type.Constructor([], Type.Object({})) Assert.IsTrue(Value.Check(T, class {})) }) it('Should validate constructor 2', () => { const T = Type.Constructor([Type.Number()], Type.Object({})) // note: constructor arguments are non-checkable Assert.IsTrue(Value.Check(T, class {})) }) it('Should validate constructor 3', () => { const T = Type.Constructor( [Type.Number()], Type.Object({ method: Type.Function([], Type.Void()), }), ) Assert.IsTrue( Value.Check( T, class { method() {} }, ), ) }) it('Should validate constructor 4', () => { const T = Type.Constructor( [Type.Number()], Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) Assert.IsTrue( Value.Check( T, class { get x() { return 1 } get y() { return 1 } get z() { return 1 } }, ), ) }) it('Should not validate constructor 1', () => { const T = Type.Constructor([Type.Number()], Type.Object({})) Assert.IsFalse(Value.Check(T, 1)) }) it('Should not validate constructor 2', () => { const T = Type.Constructor( [Type.Number()], Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) Assert.IsFalse( Value.Check( T, class { get x() { return null } get y() { return null } get z() { return null } }, ), ) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/date.ts000066400000000000000000000051731505437577000244060ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Date', () => { const T = Type.Date() it('Should fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsFalse(result) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsFalse(result) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsFalse(result) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.IsFalse(result) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsFalse(result) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsFalse(result) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsFalse(result) }) it('Should pass Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsTrue(result) }) it('Should not validate Date if is invalid', () => { const value = new Date('not-a-valid-date') const result = Value.Check(T, value) Assert.IsFalse(result) }) it('Should validate Date minimumTimestamp', () => { const T = Type.Date({ minimumTimestamp: 10 }) const R1 = Value.Check(T, new Date(9)) const R2 = Value.Check(T, new Date(10)) Assert.IsFalse(R1) Assert.IsTrue(R2) }) it('Should validate Date maximumTimestamp', () => { const T = Type.Date({ maximumTimestamp: 10 }) const R1 = Value.Check(T, new Date(11)) const R2 = Value.Check(T, new Date(10)) Assert.IsFalse(R1) Assert.IsTrue(R2) }) it('Should validate Date exclusiveMinimumTimestamp', () => { const T = Type.Date({ exclusiveMinimumTimestamp: 10 }) const R1 = Value.Check(T, new Date(10)) const R2 = Value.Check(T, new Date(11)) Assert.IsFalse(R1) Assert.IsTrue(R2) }) it('Should validate Date exclusiveMaximumTimestamp', () => { const T = Type.Date({ exclusiveMaximumTimestamp: 10 }) const R1 = Value.Check(T, new Date(10)) const R2 = Value.Check(T, new Date(9)) Assert.IsFalse(R1) Assert.IsTrue(R2) }) it('Should validate Date multipleOfTimestamp', () => { const T = Type.Date({ multipleOfTimestamp: 2 }) const R1 = Value.Check(T, new Date(1)) const R2 = Value.Check(T, new Date(2)) Assert.IsFalse(R1) Assert.IsTrue(R2) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/enum.ts000066400000000000000000000014661505437577000244360ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Enum', () => { enum Foo { A = 1, B = 2, } const T = Type.Enum(Foo) it('Should pass enum option A', () => { const value = Foo.A const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass enum option B', () => { const value = Foo.A const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail unknown value', () => { const value = 'unknown' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/function.ts000066400000000000000000000017501505437577000253130ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Function', () => { it('Should validate function 1', () => { const T = Type.Function([Type.Number()], Type.Number()) Assert.IsTrue(Value.Check(T, function () {})) }) it('Should validate function 2', () => { const T = Type.Function([Type.Number()], Type.Number()) // note: validation only checks typeof 'function' Assert.IsTrue(Value.Check(T, function (a: string, b: string, c: string, d: string) {})) }) it('Should validate function 3', () => { const T = Type.Function([Type.Number()], Type.Number()) // note: validation only checks typeof 'function' Assert.IsTrue( Value.Check(T, function () { return 'not-a-number' }), ) }) it('Should not validate function', () => { const T = Type.Function([Type.Number()], Type.Number()) Assert.IsFalse(Value.Check(T, 1)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/index.ts000066400000000000000000000012621505437577000245730ustar00rootroot00000000000000import './any' import './argument' import './array' import './async-iterator' import './bigint' import './boolean' import './composite' import './const' import './constructor' import './date' import './enum' import './function' import './integer' import './intersect' import './iterator' import './keyof' import './kind' import './literal' import './module' import './never' import './not' import './null' import './number' import './object' import './recursive' import './ref' import './record' import './regexp' import './string' import './symbol' import './template-literal' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/value/check/integer.ts000066400000000000000000000020741505437577000251230ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Integer', () => { const T = Type.Integer() it('Should not validate NaN', () => { const T = Type.Integer() const result = Value.Check(T, NaN) Assert.IsEqual(result, false) }) it('Should not validate +Infinity', () => { const T = Type.Integer() const result = Value.Check(T, Infinity) Assert.IsEqual(result, false) }) it('Should not validate -Infinity', () => { const T = Type.Integer() const result = Value.Check(T, -Infinity) Assert.IsEqual(result, false) }) it('Should pass integer', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail integer', () => { const value = 3.14 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/intersect.ts000066400000000000000000000164231505437577000254710ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Intersect', () => { it('Should intersect number and number', () => { const A = Type.Number() const B = Type.Number() const T = Type.Intersect([A, B], {}) Assert.IsEqual(Value.Check(T, 1), true) }) it('Should not intersect string and number', () => { const A = Type.String() const B = Type.Number() const T = Type.Intersect([A, B], {}) Assert.IsEqual(Value.Check(T, 1), false) Assert.IsEqual(Value.Check(T, '1'), false) }) it('Should intersect two objects', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Assert.IsEqual(Value.Check(T, { x: 1, y: 1 }), true) }) it('Should not intersect two objects with internal additionalProperties false', () => { const A = Type.Object({ x: Type.Number() }, { additionalProperties: false }) const B = Type.Object({ y: Type.Number() }, { additionalProperties: false }) const T = Type.Intersect([A, B], {}) Assert.IsEqual(Value.Check(T, { x: 1, y: 1 }), false) }) it('Should intersect two objects and mandate required properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Assert.IsEqual(Value.Check(T, { x: 1, y: 1 }), true) Assert.IsEqual(Value.Check(T, { x: 1 }), false) Assert.IsEqual(Value.Check(T, { x: 1 }), false) }) it('Should intersect two objects with unevaluated properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], {}) Assert.IsEqual(Value.Check(T, { x: 1, y: 1, z: 1 }), true) }) it('Should intersect two objects and restrict unevaluated properties', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], { unevaluatedProperties: false }) Assert.IsEqual(Value.Check(T, { x: 1, y: 1, z: 1 }), false) }) it('Should intersect two objects and allow unevaluated properties of number', () => { const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.Number() }) const T = Type.Intersect([A, B], { unevaluatedProperties: Type.Number() }) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, z: 3 }), true) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, z: '1' }), false) }) it('Should intersect two union objects with overlapping properties of the same type', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ x: Type.Number() })]) const T = Type.Intersect([A, B]) Assert.IsEqual(Value.Check(T, { x: 1 }), true) Assert.IsEqual(Value.Check(T, { x: '1' }), false) }) it('Should not intersect two union objects with overlapping properties of varying types', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ x: Type.String() })]) const T = Type.Intersect([A, B]) Assert.IsEqual(Value.Check(T, { x: 1 }), false) Assert.IsEqual(Value.Check(T, { x: '1' }), false) }) it('Should intersect two union objects with non-overlapping properties', () => { const A = Type.Union([Type.Object({ x: Type.Number() })]) const B = Type.Union([Type.Object({ y: Type.Number() })]) const T = Type.Intersect([A, B]) Assert.IsEqual(Value.Check(T, { x: 1, y: 1 }), true) }) it('Should not intersect two union objects with non-overlapping properties for additionalProperties false', () => { const A = Type.Union([Type.Object({ x: Type.Number() }, { additionalProperties: false })]) const B = Type.Union([Type.Object({ y: Type.Number() }, { additionalProperties: false })]) const T = Type.Intersect([A, B]) Assert.IsEqual(Value.Check(T, { x: 1, y: 1 }), false) }) it('unevaluatedProperties with Record 1', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2 }), true) }) it('unevaluatedProperties with Record 2', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, 0: 'hello' }), true) }) it('unevaluatedProperties with Record 3', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: false, }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, 0: 1 }), false) }) it('unevaluatedProperties with Record 4', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2 }), true) }) it('unevaluatedProperties with Record 5', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, z: true }), true) }) it('unevaluatedProperties with Record 6', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, z: 1 }), false) }) it('unevaluatedProperties with Record 7', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, 0: '' }), true) }) it('unevaluatedProperties with Record 8', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, 0: '', z: true }), true) }) it('unevaluatedProperties with Record 9', () => { const T = Type.Intersect( [ Type.Record(Type.Number(), Type.String()), Type.Object({ x: Type.Number(), y: Type.Number(), }), ], { unevaluatedProperties: Type.Boolean(), }, ) Assert.IsEqual(Value.Check(T, { x: 1, y: 2, 0: '', z: 1 }), false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/iterator.ts000066400000000000000000000013001505437577000253060ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Iterator', () => { it('Should pass iterator 1', () => { function* f() {} const T = Type.Iterator(Type.Any()) const result = Value.Check(T, f()) Assert.IsEqual(result, true) }) it('Should pass iterator 2', () => { const T = Type.Iterator(Type.Any()) const result = Value.Check(T, { [Symbol.iterator]: () => {}, }) Assert.IsEqual(result, true) }) it('Should pass iterator', () => { const T = Type.Iterator(Type.Any()) const result = Value.Check(T, {}) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/keyof.ts000066400000000000000000000015541505437577000246050ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/KeyOf', () => { const T = Type.KeyOf( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) it('Should pass keyof', () => { const value = 'x' const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail keyof', () => { const value = 'w' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail keyof with undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail keyof with null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/kind.ts000066400000000000000000000100211505437577000244020ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { TypeRegistry, Type, Kind, TSchema } from '@sinclair/typebox' import { Assert } from '../../assert' describe('value/check/Kind', () => { // ------------------------------------------------------------ // Fixtures // ------------------------------------------------------------ beforeEach(() => TypeRegistry.Set('PI', (_, value) => value === Math.PI)) afterEach(() => TypeRegistry.Delete('PI')) // ------------------------------------------------------------ // Tests // ------------------------------------------------------------ it('Should validate', () => { const T = Type.Unsafe({ [Kind]: 'PI' }) Assert.IsTrue(Value.Check(T, Math.PI)) }) it('Should not validate', () => { const T = Type.Unsafe({ [Kind]: 'PI' }) Assert.IsFalse(Value.Check(T, Math.PI * 2)) }) it('Should validate in object', () => { const T = Type.Object({ x: Type.Unsafe({ [Kind]: 'PI' }), }) Assert.IsTrue(Value.Check(T, { x: Math.PI })) }) it('Should not validate in object', () => { const T = Type.Object({ x: Type.Unsafe({ [Kind]: 'PI' }), }) Assert.IsFalse(Value.Check(T, { x: Math.PI * 2 })) }) it('Should validate in array', () => { const T = Type.Array(Type.Unsafe({ [Kind]: 'PI' })) Assert.IsTrue(Value.Check(T, [Math.PI])) }) it('Should not validate in array', () => { const T = Type.Array(Type.Unsafe({ [Kind]: 'PI' })) Assert.IsFalse(Value.Check(T, [Math.PI * 2])) }) it('Should validate in tuple', () => { const T = Type.Tuple([Type.Unsafe({ [Kind]: 'PI' })]) Assert.IsTrue(Value.Check(T, [Math.PI])) }) it('Should not validate in tuple', () => { const T = Type.Tuple([Type.Unsafe({ [Kind]: 'PI' })]) Assert.IsFalse(Value.Check(T, [Math.PI * 2])) }) // ------------------------------------------------------------ // Instances // ------------------------------------------------------------ it('Should receive kind instance on registry callback', () => { const stack: string[] = [] TypeRegistry.Set('Kind', (schema: unknown) => { // prettier-ignore return (typeof schema === 'object' && schema !== null && Kind in schema && schema[Kind] === 'Kind' && '$id' in schema && typeof schema.$id === 'string') ? (() => { stack.push(schema.$id); return true })() : false }) const A = { [Kind]: 'Kind', $id: 'A' } as TSchema const B = { [Kind]: 'Kind', $id: 'B' } as TSchema const T = Type.Object({ a: A, b: B }) const R = Value.Check(T, { a: null, b: null }) Assert.IsTrue(R) Assert.IsEqual(stack[0], 'A') Assert.IsEqual(stack[1], 'B') TypeRegistry.Delete('Kind') }) it('Should retain kind instances on subsequent check', () => { let stack: string[] = [] TypeRegistry.Set('Kind', (schema: unknown) => { // prettier-ignore return (typeof schema === 'object' && schema !== null && Kind in schema && schema[Kind] === 'Kind' && '$id' in schema && typeof schema.$id === 'string') ? (() => { stack.push(schema.$id); return true })() : false }) const A = { [Kind]: 'Kind', $id: 'A' } as TSchema const B = { [Kind]: 'Kind', $id: 'B' } as TSchema const C = { [Kind]: 'Kind', $id: 'C' } as TSchema const D = { [Kind]: 'Kind', $id: 'D' } as TSchema const T1 = Type.Object({ a: A, b: B }) const T2 = Type.Object({ a: C, b: D }) // run T1 check const R2 = Value.Check(T1, { a: null, b: null }) Assert.IsTrue(R2) Assert.IsEqual(stack.length, 2) Assert.IsEqual(stack[0], 'A') Assert.IsEqual(stack[1], 'B') stack = [] // run T2 check const R3 = Value.Check(T2, { a: null, b: null }) Assert.IsTrue(R3) Assert.IsEqual(stack.length, 2) Assert.IsEqual(stack[0], 'C') Assert.IsEqual(stack[1], 'D') stack = [] // run T1 check const R4 = Value.Check(T1, { a: null, b: null }) Assert.IsTrue(R4) Assert.IsEqual(stack.length, 2) Assert.IsEqual(stack[0], 'A') Assert.IsEqual(stack[1], 'B') stack = [] TypeRegistry.Delete('Kind') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/literal.ts000066400000000000000000000014341505437577000251210ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Literal', () => { const T = Type.Literal('hello') it('Should pass literal', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail literal', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail literal with undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail literal with null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/module.ts000066400000000000000000000124731505437577000247570ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert' describe('value/check/Module', () => { it('Should validate string', () => { const Module = Type.Module({ A: Type.String(), }) const T = Module.Import('A') Assert.IsTrue(Value.Check(T, 'hello')) Assert.IsFalse(Value.Check(T, true)) }) it('Should validate referenced string', () => { const Module = Type.Module({ A: Type.String(), B: Type.Ref('A'), }) const T = Module.Import('B') Assert.IsTrue(Value.Check(T, 'hello')) Assert.IsFalse(Value.Check(T, true)) }) it('Should validate self referential', () => { const Module = Type.Module({ A: Type.Object({ nodes: Type.Array(Type.Ref('A')), }), }) const T = Module.Import('A') Assert.IsTrue(Value.Check(T, { nodes: [{ nodes: [{ nodes: [] }, { nodes: [] }] }] })) Assert.IsFalse(Value.Check(T, { nodes: [{ nodes: [{ nodes: [] }, { nodes: false }] }] })) Assert.IsFalse(Value.Check(T, true)) }) it('Should validate mutual recursive', () => { const Module = Type.Module({ A: Type.Object({ b: Type.Ref('B'), }), B: Type.Object({ a: Type.Union([Type.Ref('A'), Type.Null()]), }), }) const T = Module.Import('A') Assert.IsTrue(Value.Check(T, { b: { a: null } })) Assert.IsTrue(Value.Check(T, { b: { a: { b: { a: null } } } })) Assert.IsFalse(Value.Check(T, { b: { a: 1 } })) Assert.IsFalse(Value.Check(T, { b: { a: { b: { a: 1 } } } })) Assert.IsFalse(Value.Check(T, true)) }) it('Should validate mutual recursive (Array)', () => { const Module = Type.Module({ A: Type.Object({ b: Type.Ref('B'), }), B: Type.Object({ a: Type.Array(Type.Ref('A')), }), }) const T = Module.Import('A') Assert.IsTrue(Value.Check(T, { b: { a: [{ b: { a: [] } }] } })) Assert.IsFalse(Value.Check(T, { b: { a: [{ b: { a: [null] } }] } })) Assert.IsFalse(Value.Check(T, true)) }) it('Should validate deep referential', () => { const Module = Type.Module({ A: Type.Ref('B'), B: Type.Ref('C'), C: Type.Ref('D'), D: Type.Ref('E'), E: Type.Ref('F'), F: Type.Ref('G'), G: Type.Ref('H'), H: Type.Literal('hello'), }) const T = Module.Import('A') Assert.IsTrue(Value.Check(T, 'hello')) Assert.IsFalse(Value.Check(T, 'world')) }) // ---------------------------------------------------------------- // Modifiers // ---------------------------------------------------------------- it('Should validate objects with property modifiers 1', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Null()), y: Type.Readonly(Type.Null()), z: Type.Optional(Type.Null()), w: Type.Null(), }), }) const T = Module.Import('T') Assert.IsTrue(Value.Check(T, { x: null, y: null, w: null })) Assert.IsTrue(Value.Check(T, { y: null, w: null })) Assert.IsFalse(Value.Check(T, { x: 1, y: null, w: null })) }) it('Should validate objects with property modifiers 2', () => { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Array(Type.Null())), y: Type.Readonly(Type.Array(Type.Null())), z: Type.Optional(Type.Array(Type.Null())), w: Type.Array(Type.Null()), }), }) const T = Module.Import('T') Assert.IsTrue(Value.Check(T, { x: [null], y: [null], w: [null] })) Assert.IsTrue(Value.Check(T, { y: [null], w: [null] })) Assert.IsFalse(Value.Check(T, { x: [1], y: [null], w: [null] })) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1109 // ---------------------------------------------------------------- it('Should validate deep referential 1', () => { const Module = Type.Module({ A: Type.Union([Type.Literal('Foo'), Type.Literal('Bar')]), B: Type.Ref('A'), C: Type.Object({ ref: Type.Ref('B') }), D: Type.Union([Type.Ref('B'), Type.Ref('C')]), }) Assert.IsTrue(Value.Check(Module.Import('A') as never, 'Foo')) Assert.IsTrue(Value.Check(Module.Import('A') as never, 'Bar')) Assert.IsTrue(Value.Check(Module.Import('B') as never, 'Foo')) Assert.IsTrue(Value.Check(Module.Import('B') as never, 'Bar')) Assert.IsTrue(Value.Check(Module.Import('C') as never, { ref: 'Foo' })) Assert.IsTrue(Value.Check(Module.Import('C') as never, { ref: 'Bar' })) Assert.IsTrue(Value.Check(Module.Import('D') as never, 'Foo')) Assert.IsTrue(Value.Check(Module.Import('D') as never, 'Bar')) Assert.IsTrue(Value.Check(Module.Import('D') as never, { ref: 'Foo' })) Assert.IsTrue(Value.Check(Module.Import('D') as never, { ref: 'Bar' })) }) it('Should validate deep referential 2', () => { const Module = Type.Module({ A: Type.Literal('Foo'), B: Type.Ref('A'), C: Type.Ref('B'), D: Type.Ref('C'), E: Type.Ref('D'), }) Assert.IsTrue(Value.Check(Module.Import('A'), 'Foo')) Assert.IsTrue(Value.Check(Module.Import('B'), 'Foo')) Assert.IsTrue(Value.Check(Module.Import('C'), 'Foo')) Assert.IsTrue(Value.Check(Module.Import('D'), 'Foo')) Assert.IsTrue(Value.Check(Module.Import('E'), 'Foo')) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/never.ts000066400000000000000000000022321505437577000246010ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Never', () => { const T = Type.Never() it('Should fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/not.ts000066400000000000000000000017631505437577000242720ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Not', () => { it('Should validate with not number', () => { const T = Type.Not(Type.Number()) Assert.IsEqual(Value.Check(T, 1), false) Assert.IsEqual(Value.Check(T, 'A'), true) }) it('Should validate with union left', () => { // prettier-ignore const T = Type.Not(Type.Union([ Type.Literal('A'), Type.Literal('B'), Type.Literal('C') ])) Assert.IsEqual(Value.Check(T, 'A'), false) Assert.IsEqual(Value.Check(T, 'B'), false) Assert.IsEqual(Value.Check(T, 'C'), false) Assert.IsEqual(Value.Check(T, 'D'), true) }) it('Should validate with union right', () => { // prettier-ignore const T = Type.Not(Type.Number()) Assert.IsEqual(Value.Check(T, 1), false) Assert.IsEqual(Value.Check(T, 'A'), true) Assert.IsEqual(Value.Check(T, true), true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/null.ts000066400000000000000000000024451505437577000244420ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Null', () => { const T = Type.Null() it('Should fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/number.ts000066400000000000000000000035611505437577000247600ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Number', () => { const T = Type.Number() it('Should not validate NaN', () => { const T = Type.Number() const result = Value.Check(T, NaN) Assert.IsEqual(result, false) }) it('Should not validate +Infinity', () => { const T = Type.Number() const result = Value.Check(T, Infinity) Assert.IsEqual(result, false) }) it('Should not validate -Infinity', () => { const T = Type.Number() const result = Value.Check(T, -Infinity) Assert.IsEqual(result, false) }) it('Should fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail NaN', () => { const result = Value.Check(Type.Number(), NaN) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/object.ts000066400000000000000000000124541505437577000247370ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Object', () => { const T = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), a: Type.String(), b: Type.String(), c: Type.String(), }) it('Should pass object', () => { const value = { x: 1, y: 1, z: 1, a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail object with additional properties', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { additionalProperties: false }, ) const value = { x: 1, y: 1, z: 1, a: 1, } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object with invalid property', () => { const value = { x: true, y: 1, z: 1, a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object with missing property', () => { const value = { y: 1, z: 1, a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass object with optional properties', () => { const T = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), z: Type.Optional(Type.Number()), a: Type.String(), b: Type.String(), c: Type.String(), }) const value = { a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail object with null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object with undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should validate schema additional properties of string', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) Assert.IsEqual( Value.Check(T, { x: 1, y: 2, z: 'hello', }), true, ) Assert.IsEqual( Value.Check(T, { x: 1, y: 2, z: 3, }), false, ) }) it('Should validate schema additional properties of array', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Array(Type.Number()), }, ) Assert.IsEqual( Value.Check(T, { x: 1, y: 2, z: [0, 1, 2], }), true, ) Assert.IsEqual( Value.Check(T, { x: 1, y: 2, z: 3, }), false, ) }) it('Should validate schema additional properties of object', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.Object({ z: Type.Number(), }), }, ) Assert.IsEqual( Value.Check(T, { x: 1, y: 2, z: { z: 1 }, }), true, ) Assert.IsEqual( Value.Check(T, { x: 1, y: 2, z: 3, }), false, ) }) it('Should check for property key if property type is undefined', () => { const T = Type.Object({ x: Type.Undefined() }) Assert.IsEqual(Value.Check(T, { x: undefined }), true) Assert.IsEqual(Value.Check(T, {}), false) }) it('Should check for property key if property type extends undefined', () => { const T = Type.Object({ x: Type.Union([Type.Number(), Type.Undefined()]) }) Assert.IsEqual(Value.Check(T, { x: 1 }), true) Assert.IsEqual(Value.Check(T, { x: undefined }), true) Assert.IsEqual(Value.Check(T, {}), false) }) it('Should not check for property key if property type is undefined and optional', () => { const T = Type.Object({ x: Type.Optional(Type.Undefined()) }) Assert.IsEqual(Value.Check(T, { x: undefined }), true) Assert.IsEqual(Value.Check(T, {}), true) }) it('Should not check for property key if property type extends undefined and optional', () => { const T = Type.Object({ x: Type.Optional(Type.Union([Type.Number(), Type.Undefined()])) }) Assert.IsEqual(Value.Check(T, { x: 1 }), true) Assert.IsEqual(Value.Check(T, { x: undefined }), true) Assert.IsEqual(Value.Check(T, {}), true) }) it('Should check undefined for optional property of number', () => { const T = Type.Object({ x: Type.Optional(Type.Number()) }) Assert.IsEqual(Value.Check(T, { x: 1 }), true) Assert.IsEqual(Value.Check(T, { x: undefined }), true) // allowed by default Assert.IsEqual(Value.Check(T, {}), true) }) it('Should check undefined for optional property of undefined', () => { const T = Type.Object({ x: Type.Optional(Type.Undefined()) }) Assert.IsEqual(Value.Check(T, { x: 1 }), false) Assert.IsEqual(Value.Check(T, {}), true) Assert.IsEqual(Value.Check(T, { x: undefined }), true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/record.ts000066400000000000000000000206731505437577000247510ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Record', () => { it('Should pass record', () => { const T = Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) const value = { position: { x: 1, y: 2, z: 3, }, } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail when below minProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { minProperties: 4 }) Assert.IsEqual(Value.Check(T, { a: 1, b: 2, c: 3, d: 4 }), true) Assert.IsEqual(Value.Check(T, { a: 1, b: 2, c: 3 }), false) }) it('Should fail when above maxProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { maxProperties: 4 }) Assert.IsEqual(Value.Check(T, { a: 1, b: 2, c: 3, d: 4 }), true) Assert.IsEqual(Value.Check(T, { a: 1, b: 2, c: 3, d: 4, e: 5 }), false) }) it('Should fail with illogical minProperties | maxProperties', () => { const T = Type.Record(Type.String(), Type.Number(), { minProperties: 5, maxProperties: 4 }) Assert.IsEqual(Value.Check(T, { a: 1, b: 2, c: 3 }), false) Assert.IsEqual(Value.Check(T, { a: 1, b: 2, c: 3, d: 4 }), false) Assert.IsEqual(Value.Check(T, { a: 1, b: 2, c: 3, d: 4, e: 5 }), false) }) it('Should fail record with Date', () => { const T = Type.Record(Type.String(), Type.String()) const result = Value.Check(T, new Date()) Assert.IsEqual(result, false) }) it('Should fail record with Uint8Array', () => { const T = Type.Record(Type.String(), Type.String()) const result = Value.Check(T, new Uint8Array()) Assert.IsEqual(result, false) }) it('Should fail record with missing property', () => { const T = Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) const value = { position: { x: 1, y: 2, }, } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail record with invalid property', () => { const T = Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) const value = { position: { x: 1, y: 2, z: '3', }, } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass record with optional property', () => { const T = Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Optional(Type.Number()), }), ) const value = { position: { x: 1, y: 2, }, } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass record with optional property', () => { const T = Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Optional(Type.Number()), }), ) const value = { position: { x: 1, y: 2, }, } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should validate when specifying regular expressions', () => { const K = Type.RegExp(/^op_.*$/) const T = Type.Record(K, Type.Number()) const R = Value.Check(T, { op_a: 1, op_b: 2, op_c: 3, }) Assert.IsTrue(R) }) it('Should not validate when specifying regular expressions and passing invalid property', () => { const K = Type.RegExp(/^op_.*$/) const T = Type.Record(K, Type.Number(), { additionalProperties: false }) const R = Value.Check(T, { op_a: 1, op_b: 2, aop_c: 3, }) Assert.IsFalse(R) }) it('Should validate with quoted string pattern', () => { const K = Type.String({ pattern: "'(a|b|c)" }) const T = Type.Record(K, Type.Number()) const R = Value.Check(T, { "'a": 1, "'b": 2, "'c": 3, }) Assert.IsTrue(R) }) it('Should validate with forward-slash pattern', () => { const K = Type.String({ pattern: '/(a|b|c)' }) const T = Type.Record(K, Type.Number()) const R = Value.Check(T, { '/a': 1, '/b': 2, '/c': 3, }) Assert.IsTrue(R) }) // ------------------------------------------------- // Number Key // ------------------------------------------------- it('Should pass record with number key', () => { const T = Type.Record(Type.Number(), Type.String()) const value = { 0: 'a', 1: 'a', 2: 'a', } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should not pass record with invalid number key', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false }) const value = { a: 'a', 1: 'a', 2: 'a', } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) // ------------------------------------------------- // Integer Key // ------------------------------------------------- it('Should pass record with integer key', () => { const T = Type.Record(Type.Integer(), Type.String()) const value = { 0: 'a', 1: 'a', 2: 'a', } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should not pass record with invalid integer key', () => { const T = Type.Record(Type.Integer(), Type.String(), { additionalProperties: false }) const value = { a: 'a', 1: 'a', 2: 'a', } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) // ------------------------------------------------------------ // AdditionalProperties // ------------------------------------------------------------ it('AdditionalProperties 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: true }) const R = Value.Check(T, { 1: '', 2: '', x: 1, y: 2, z: 3 }) Assert.IsEqual(R, true) }) it('AdditionalProperties 2', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false }) const R = Value.Check(T, { 1: '', 2: '', 3: '' }) Assert.IsEqual(R, true) }) it('AdditionalProperties 3', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: false }) const R = Value.Check(T, { 1: '', 2: '', x: '' }) Assert.IsEqual(R, false) }) it('AdditionalProperties 4', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean() }) const R = Value.Check(T, { 1: '', 2: '', x: '' }) Assert.IsEqual(R, false) }) it('AdditionalProperties 5', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean() }) const R = Value.Check(T, { 1: '', 2: '', x: true }) Assert.IsEqual(R, true) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/916 // ---------------------------------------------------------------- it('Should validate for string keys', () => { const T = Type.Record(Type.String(), Type.Null(), { additionalProperties: false, }) const R = Value.Check(T, { a: null, b: null, 0: null, 1: null, }) Assert.IsEqual(R, true) }) it('Should validate for number keys', () => { const T = Type.Record(Type.Number(), Type.Null(), { additionalProperties: false, }) const R1 = Value.Check(T, { a: null, b: null, 0: null, 1: null, }) const R2 = Value.Check(T, { 0: null, 1: null, }) Assert.IsEqual(R1, false) Assert.IsEqual(R2, true) }) it('Should validate for any keys', () => { const T = Type.Record(Type.Any(), Type.Null(), { additionalProperties: false, }) const R = Value.Check(T, { a: null, b: null, 0: null, 1: null, }) Assert.IsEqual(R, true) }) it('Should validate for never keys', () => { const T = Type.Record(Type.Never(), Type.Null(), { additionalProperties: false, }) const R1 = Value.Check(T, {}) const R2 = Value.Check(T, { a: null, b: null, 0: null, 1: null, }) Assert.IsEqual(R1, true) Assert.IsEqual(R2, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/recursive.ts000066400000000000000000000032061505437577000254730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Recursive', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) it('Should pass recursive', () => { const value = { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, { id: 'D', nodes: [] }, ], } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail recursive with invalid id', () => { const value = { id: 'A', nodes: [ { id: 1, nodes: [] }, { id: 'C', nodes: [] }, { id: 'D', nodes: [] }, ], } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail rec with invalid nodes', () => { const value = { id: 'A', nodes: [ { id: 'B', nodes: 1 }, { id: 'C', nodes: [] }, { id: 'D', nodes: [] }, ], } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail recursive with missing id', () => { const value = { id: 'A', nodes: [{ nodes: [] }, { id: 'C', nodes: [] }, { id: 'D', nodes: [] }], } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail rec with missing nodes', () => { const value = { id: 'A', nodes: [{ id: 'B' }, { id: 'C', nodes: [] }, { id: 'D', nodes: [] }], } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/ref.ts000066400000000000000000000050731505437577000242440ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Ref', () => { // ---------------------------------------------------------------- // Deprecated // ---------------------------------------------------------------- it('Should validate for Ref(Schema)', () => { const T = Type.Number({ $id: 'T' }) const R = Type.Ref(T) Assert.IsTrue(Value.Check(T, [T], 1234)) Assert.IsFalse(Value.Check(T, [T], 'hello')) }) // ---------------------------------------------------------------- // Standard // ---------------------------------------------------------------- it('Should should validate when referencing a type', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { $id: Assert.NextId() }, ) const R = Type.Ref(T.$id!) Assert.IsEqual( Value.Check(R, [T], { x: 1, y: 2, z: 3, }), true, ) }) it('Should not validate when passing invalid data', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { $id: Assert.NextId() }, ) const R = Type.Ref(T.$id!) Assert.IsEqual( Value.Check(R, [T], { x: 1, y: 2, }), false, ) }) it('Should de-reference object property schema', () => { const T = Type.Object( { name: Type.String(), }, { $id: 'R' }, ) const R = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), r: Type.Optional(Type.Ref(T.$id!)), }, { $id: 'T' }, ) Assert.IsEqual(Value.Check(R, [T], { x: 1, y: 2, z: 3 }), true) Assert.IsEqual(Value.Check(R, [T], { x: 1, y: 2, z: 3, r: { name: 'hello' } }), true) Assert.IsEqual(Value.Check(R, [T], { x: 1, y: 2, z: 3, r: { name: 1 } }), false) Assert.IsEqual(Value.Check(R, [T], { x: 1, y: 2, z: 3, r: {} }), false) // Ok(R, { x: 1, y: 2, z: 3 }, [T]) // Ok(R, , [T]) // Fail(R, , [T]) // Fail(R, , [T]) }) it('Should reference recursive schema', () => { const T = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) const R = Type.Ref(T.$id!) Assert.IsEqual(Value.Check(R, [T], { id: '', nodes: [{ id: '', nodes: [] }] }), true) Assert.IsEqual(Value.Check(R, [T], { id: '', nodes: [{ id: 1, nodes: [] }] }), false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/regexp.ts000066400000000000000000000030431505437577000247550ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/RegExp', () => { // ------------------------------------------------- // Regular Expression // ------------------------------------------------- it('Should pass regular expression 1', () => { const T = Type.RegExp(/foo/) const value = 'foo' const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass regular expression 2', () => { const T = Type.RegExp(/foo/) const value = 'bar' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) // ------------------------------------------------- // Pattern // ------------------------------------------------- it('Should pass pattern 1', () => { const T = Type.RegExp('foo') const value = 'foo' const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass pattern 2', () => { const T = Type.RegExp('foo') const value = 'bar' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should validate with minLength constraint', () => { const T = Type.RegExp(/(.*)/, { minLength: 3, }) Assert.IsTrue(Value.Check(T, 'xxx')) Assert.IsFalse(Value.Check(T, 'xx')) }) it('Should validate with maxLength constraint', () => { const T = Type.RegExp(/(.*)/, { maxLength: 3, }) Assert.IsTrue(Value.Check(T, 'xxx')) Assert.IsFalse(Value.Check(T, 'xxxx')) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/string.ts000066400000000000000000000024511505437577000247730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/String', () => { const T = Type.String() it('Should pass string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/symbol.ts000066400000000000000000000026701505437577000247750ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Symbol', () => { const T = Type.Symbol() it('Should fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass symbol', () => { const value = Symbol(1) const result = Value.Check(T, value) Assert.IsEqual(result, true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/template-literal.ts000066400000000000000000000141221505437577000267300ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/TemplateLiteral', () => { // -------------------------------------------------------- // Finite // -------------------------------------------------------- it('Should validate finite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([]) Assert.IsEqual(Value.Check(T, ''), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate finite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([Type.Boolean()]) Assert.IsEqual(Value.Check(T, 'true'), true) Assert.IsEqual(Value.Check(T, 'false'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate finite pattern 2', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A') ]) Assert.IsEqual(Value.Check(T, 'A'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate finite pattern 3', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Literal('B') ]) Assert.IsEqual(Value.Check(T, 'AB'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate finite pattern 4', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), Type.Literal('C') ]), ]) Assert.IsEqual(Value.Check(T, 'AB'), true) Assert.IsEqual(Value.Check(T, 'AC'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate finite pattern 5', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Union([ Type.Literal('B'), Type.Literal('C') ]), Type.Literal('D'), ]) Assert.IsEqual(Value.Check(T, 'ABD'), true) Assert.IsEqual(Value.Check(T, 'ACD'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate finite pattern 6', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Union([ Type.Literal('0'), Type.Literal('1') ]), Type.Union([ Type.Literal('0'), Type.Literal('1') ]), ]) Assert.IsEqual(Value.Check(T, '00'), true) Assert.IsEqual(Value.Check(T, '01'), true) Assert.IsEqual(Value.Check(T, '10'), true) Assert.IsEqual(Value.Check(T, '11'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) // -------------------------------------------------------- // Infinite // -------------------------------------------------------- it('Should validate infinite pattern 1', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Number() ]) Assert.IsEqual(Value.Check(T, '1'), true) Assert.IsEqual(Value.Check(T, '22'), true) Assert.IsEqual(Value.Check(T, '333'), true) Assert.IsEqual(Value.Check(T, '4444'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate infinite pattern 2', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Integer() ]) Assert.IsEqual(Value.Check(T, '1'), true) Assert.IsEqual(Value.Check(T, '22'), true) Assert.IsEqual(Value.Check(T, '333'), true) Assert.IsEqual(Value.Check(T, '4444'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate infinite pattern 3', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.BigInt() ]) Assert.IsEqual(Value.Check(T, '1'), true) Assert.IsEqual(Value.Check(T, '22'), true) Assert.IsEqual(Value.Check(T, '333'), true) Assert.IsEqual(Value.Check(T, '4444'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate infinite pattern 4', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.String() ]) Assert.IsEqual(Value.Check(T, '1'), true) Assert.IsEqual(Value.Check(T, '22'), true) Assert.IsEqual(Value.Check(T, '333'), true) Assert.IsEqual(Value.Check(T, '4444'), true) Assert.IsEqual(Value.Check(T, 'a'), true) Assert.IsEqual(Value.Check(T, 'bb'), true) Assert.IsEqual(Value.Check(T, 'ccc'), true) Assert.IsEqual(Value.Check(T, 'dddd'), true) }) it('Should validate infinite pattern 5', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Number() ]) Assert.IsEqual(Value.Check(T, 'A1'), true) Assert.IsEqual(Value.Check(T, 'A22'), true) Assert.IsEqual(Value.Check(T, 'A333'), true) Assert.IsEqual(Value.Check(T, 'A4444'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate infinite pattern 6', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.Integer() ]) Assert.IsEqual(Value.Check(T, 'A1'), true) Assert.IsEqual(Value.Check(T, 'A22'), true) Assert.IsEqual(Value.Check(T, 'A333'), true) Assert.IsEqual(Value.Check(T, 'A4444'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate infinite pattern 7', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.BigInt() ]) Assert.IsEqual(Value.Check(T, 'A1'), true) Assert.IsEqual(Value.Check(T, 'A22'), true) Assert.IsEqual(Value.Check(T, 'A333'), true) Assert.IsEqual(Value.Check(T, 'A4444'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) it('Should validate infinite pattern 8', () => { // prettier-ignore const T = Type.TemplateLiteral([ Type.Literal('A'), Type.String() ]) Assert.IsEqual(Value.Check(T, 'A1'), true) Assert.IsEqual(Value.Check(T, 'A22'), true) Assert.IsEqual(Value.Check(T, 'A333'), true) Assert.IsEqual(Value.Check(T, 'A4444'), true) Assert.IsEqual(Value.Check(T, 'Aa'), true) Assert.IsEqual(Value.Check(T, 'Abb'), true) Assert.IsEqual(Value.Check(T, 'Accc'), true) Assert.IsEqual(Value.Check(T, 'Adddd'), true) Assert.IsEqual(Value.Check(T, 'X'), false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/tuple.ts000066400000000000000000000022201505437577000246100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Tuple', () => { it('Should pass tuple', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail when tuple is less than length', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const value = [1] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail when tuple is greater than length', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const value = [1, 1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass empty tuple', () => { const T = Type.Tuple([]) const value = [] as any[] const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail empty tuple', () => { const T = Type.Tuple([]) const value = [1] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/uint8array.ts000066400000000000000000000016411505437577000255730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Uint8Array', () => { it('Should pass Uint8Array', () => { const T = Type.Uint8Array() const value = new Uint8Array(4) const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail Uint8Array', () => { const T = Type.Uint8Array() const value = [0, 1, 2, 3] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Uint8Array with undefined', () => { const T = Type.Uint8Array() const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Uint8Array with null', () => { const T = Type.Uint8Array() const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/undefined.ts000066400000000000000000000024571505437577000254340ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Undefined', () => { const T = Type.Undefined() it('Should fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/union.ts000066400000000000000000000037621505437577000246230ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Union', () => { const A = Type.Object({ type: Type.Literal('A'), x: Type.Number(), y: Type.Number(), }) const B = Type.Object({ type: Type.Literal('B'), x: Type.Boolean(), y: Type.Boolean(), }) const T = Type.Union([A, B]) it('Should pass union A', () => { const value = { type: 'A', x: 1, y: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass union B', () => { const value = { type: 'B', x: true, y: false } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail union A', () => { const value = { type: 'A', x: true, y: false } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail union B', () => { const value = { type: 'B', x: 1, y: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass union A with optional properties', () => { const A = Type.Object({ type: Type.Literal('A'), x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), }) const B = Type.Object({ type: Type.Literal('B'), x: Type.Boolean(), y: Type.Boolean(), }) const T = Type.Union([A, B]) const value = { type: 'A' } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail union A with invalid optional properties', () => { const A = Type.Object({ type: Type.Literal('A'), x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), }) const B = Type.Object({ type: Type.Literal('B'), x: Type.Boolean(), y: Type.Boolean(), }) const T = Type.Union([A, B]) const value = { type: 'A', x: true, y: false } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/unknown.ts000066400000000000000000000024401505437577000251620ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Unknown', () => { const T = Type.Any() it('Should pass string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should pass Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/check/void.ts000066400000000000000000000024451505437577000244310ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Void', () => { const T = Type.Void() it('Should fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should pass undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.IsEqual(result, true) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.IsEqual(result, false) }) it('Should fail Date', () => { const value = new Date() const result = Value.Check(T, value) Assert.IsEqual(result, false) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/000077500000000000000000000000001505437577000231205ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/any.ts000066400000000000000000000004511505437577000242570ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Any', () => { it('Should clean 1', () => { const T = Type.Any() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/array.ts000066400000000000000000000011641505437577000246100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Array', () => { it('Should clean 1', () => { const T = Type.Any() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const T = Type.Array( Type.Object({ x: Type.Number(), y: Type.Number(), }), ) const R = Value.Clean(T, [undefined, null, { x: 1 }, { x: 1, y: 2 }, { x: 1, y: 2, z: 3 }]) Assert.IsEqual(R, [undefined, null, { x: 1 }, { x: 1, y: 2 }, { x: 1, y: 2 }]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/async-iterator.ts000066400000000000000000000005121505437577000264320ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/AsyncIterator', () => { it('Should clean 1', () => { const T = Type.AsyncIterator(Type.Number()) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/bigint.ts000066400000000000000000000004571505437577000247520ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/BigInt', () => { it('Should clean 1', () => { const T = Type.BigInt() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/boolean.ts000066400000000000000000000004611505437577000251100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Boolean', () => { it('Should clean 1', () => { const T = Type.Boolean() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/composite.ts000066400000000000000000000005731505437577000254770ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Composite', () => { it('Should clean 1', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/constructor.ts000066400000000000000000000006421505437577000260570ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Constructor', () => { it('Should clean 1', () => { const T = Type.Constructor([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], Type.Object({ z: Type.Number() })) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/date.ts000066400000000000000000000004531505437577000244070ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Date', () => { it('Should clean 1', () => { const T = Type.Date() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/enum.ts000066400000000000000000000004711505437577000244360ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Enum', () => { it('Should clean 1', () => { const T = Type.Enum({ x: 1, y: 2 }) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/function.ts000066400000000000000000000006341505437577000253200ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Function', () => { it('Should clean 1', () => { const T = Type.Function([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], Type.Object({ z: Type.Number() })) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/import.ts000066400000000000000000000125731505437577000250120ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Import', () => { // ---------------------------------------------------------------- // Clean // ---------------------------------------------------------------- it('Should clean 1', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number() }) }).Import('A') const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number() }) }).Import('A') const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean 3', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number() }) }).Import('A') const R = Value.Clean(T, { x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clean 4', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number() }) }).Import('A') const R = Value.Clean(T, { x: null }) Assert.IsEqual(R, { x: null }) }) // ---------------------------------------------------------------- // Nested // ---------------------------------------------------------------- it('Should clean nested 1', () => { const T = Type.Module({ A: Type.Object({ x: Type.Object({ y: Type.Number(), }), }), }).Import('A') const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean nested 2', () => { const T = Type.Module({ A: Type.Object({ x: Type.Object({ y: Type.Number(), }), }), }).Import('A') const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean nested 3', () => { const T = Type.Module({ A: Type.Object({ x: Type.Object({ y: Type.Number(), }), }), }).Import('A') const R = Value.Clean(T, { x: null }) Assert.IsEqual(R, { x: null }) }) it('Should clean nested 4', () => { const T = Type.Module({ A: Type.Object({ x: Type.Object({ y: Type.Number(), }), }), }).Import('A') const R = Value.Clean(T, { x: { y: null } }) Assert.IsEqual(R, { x: { y: null } }) }) // ---------------------------------------------------------------- // Additional Properties // ---------------------------------------------------------------- it('Should clean additional properties 1', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }).Import('A') const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean additional properties 2', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }).Import('A') const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean additional properties 3', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }).Import('A') const R = Value.Clean(T, { x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clean additional properties 4', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }).Import('A') const R = Value.Clean(T, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) // ---------------------------------------------------------------- // Additional Properties Discard // ---------------------------------------------------------------- it('Should clean additional properties discard 1', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }).Import('A') const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean additional properties discard 2', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }).Import('A') const R = Value.Clean(T, { k: '', d: null }) Assert.IsEqual(R, { k: '' }) }) it('Should clean additional properties discard 3', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }).Import('A') const R = Value.Clean(T, { k: '', d: null, x: 1 }) Assert.IsEqual(R, { k: '', x: 1 }) }) it('Should clean additional properties discard 4', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ), }).Import('A') const R = Value.Clean(T, { k: '', d: null, x: 1, y: 2 }) Assert.IsEqual(R, { k: '', x: 1, y: 2 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/index.ts000066400000000000000000000012161505437577000245770ustar00rootroot00000000000000import './any' import './array' import './async-iterator' import './bigint' import './boolean' import './composite' import './constructor' import './date' import './enum' import './function' import './import' import './integer' import './intersect' import './iterator' import './keyof' import './kind' import './literal' import './never' import './not' import './null' import './object' import './promise' import './record' import './recursive' import './ref' import './regexp' import './string' import './symbol' import './template-literal' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/integer.ts000066400000000000000000000004611505437577000251260ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Integer', () => { it('Should clean 1', () => { const T = Type.Integer() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/intersect.ts000066400000000000000000000250141505437577000254720ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' // prettier-ignore describe('value/clean/Intersect', () => { // ---------------------------------------------------------------- // Intersect // ---------------------------------------------------------------- it('Should clean 1', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean 3', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Clean(T, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should clean 4', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Clean(T, { x: 1, y: 2, z: 3 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) // ---------------------------------------------------------------- // Intersect Discard // ---------------------------------------------------------------- it('Should clean discard 1', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean discard 2', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Clean(T, { u: null }) Assert.IsEqual(R, {}) }) it('Should clean discard 3', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Clean(T, { u: null, x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should clean discard 4', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Clean(T, { u: null, x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) // ---------------------------------------------------------------- // Intersect Deep // ---------------------------------------------------------------- it('Should clear intersect deep 1', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clear intersect deep 2', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clear intersect deep 3', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clear intersect deep 4', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should clear intersect deep 5', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { x: 1, y: 2, z: 3 }) Assert.IsEqual(R, { x: 1, y: 2, z: 3 }) }) it('Should clear intersect deep 6', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { x: 1, y: 2, z: 3, w: 3 }) Assert.IsEqual(R, { x: 1, y: 2, z: 3, w: 3 }) }) it('Should clear intersect deep 7', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { x: 1, y: 2, z: 3, w: 3 }) Assert.IsEqual(R, { x: 1, y: 2, z: 3, w: 3 }) }) // ---------------------------------------------------------------- // Intersect Deep Discard // ---------------------------------------------------------------- it('Should clear intersect discard deep 1', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clear intersect discard deep 2', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { u: null }) Assert.IsEqual(R, {}) }) it('Should clear intersect discard deep 3', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { u: null, x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clear intersect discard deep 4', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { u: null, x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should clear intersect discard deep 5', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { u: null, x: 1, y: 2, z: 3 }) Assert.IsEqual(R, { x: 1, y: 2, z: 3 }) }) it('Should clear intersect discard deep 6', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { u: null, x: 1, y: 2, z: 3, w: 3 }) Assert.IsEqual(R, { x: 1, y: 2, z: 3, w: 3 }) }) it('Should clear intersect discard deep 7', () => { const T = Type.Intersect([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Intersect([ Type.Object({ z: Type.Number() }), Type.Object({ w: Type.Number() }) ]) ]) const R = Value.Clean(T, { u: null, x: 1, y: 2, z: 3, w: 3, a: 1 }) Assert.IsEqual(R, { x: 1, y: 2, z: 3, w: 3 }) }) // ---------------------------------------------------------------- // Intersect Invalid // ---------------------------------------------------------------- it('Should clean intersect invalid 1', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.String() }) ]) const R = Value.Clean(T, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) // types are ignored }) // ---------------------------------------------------------------- // Intersect Unevaluted Properties // ---------------------------------------------------------------- it('Should clean intersect unevaluated properties 1', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.String() }) ], { unevaluatedProperties: Type.String() }) const R = Value.Clean(T, { x: 1, y: 2, a: 1, b: '' }) Assert.IsEqual(R, { x: 1, y: 2, b: '' }) }) // ---------------------------------------------------------------- // Intersect Illogical // ---------------------------------------------------------------- it('Should clean illogical 1', () => { const T = Type.Intersect([ Type.Number(), Type.Object({ x: Type.Number() }) ]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean illogical 2', () => { const T = Type.Intersect([ Type.Number(), Type.Object({ x: Type.Number() }) ]) const R = Value.Clean(T, 1) Assert.IsEqual(R, 1) }) it('Should clean illogical 3', () => { const T = Type.Intersect([ Type.Number(), Type.Object({ x: Type.Number() }) ]) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean illogical 4', () => { const T = Type.Intersect([ Type.Number(), Type.Object({ x: Type.Number() }) ]) const R = Value.Clean(T, { x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clean illogical 5', () => { const T = Type.Intersect([ Type.Number(), Type.Object({ x: Type.Number() }), ]) const R = Value.Clean(T, { u: null, x: 1 }) Assert.IsEqual(R, { u: null, x: 1 }) // u retained from Number }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/iterator.ts000066400000000000000000000005001505437577000253140ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Iterator', () => { it('Should clean 1', () => { const T = Type.Iterator(Type.String()) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/keyof.ts000066400000000000000000000005401505437577000246040ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/KeyOf', () => { it('Should clean 1', () => { const T = Type.KeyOf(Type.Object({ x: Type.Number(), y: Type.Number() })) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/kind.ts000066400000000000000000000005101505437577000244110ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type, Kind } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Kind', () => { it('Should clean 1', () => { const T = Type.Unsafe({ [Kind]: 'Unknown' }) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/literal.ts000066400000000000000000000004621505437577000251260ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Literal', () => { it('Should clean 1', () => { const T = Type.Literal(1) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/never.ts000066400000000000000000000004551505437577000246130ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Never', () => { it('Should clean 1', () => { const T = Type.Never() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/not.ts000066400000000000000000000004631505437577000242730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Not', () => { it('Should clean 1', () => { const T = Type.Not(Type.Any()) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/null.ts000066400000000000000000000004531505437577000244440ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Null', () => { it('Should clean 1', () => { const T = Type.Null() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/number.ts000066400000000000000000000004571505437577000247660ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Number', () => { it('Should clean 1', () => { const T = Type.Number() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/object.ts000066400000000000000000000111261505437577000247370ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Object', () => { // ---------------------------------------------------------------- // Clean // ---------------------------------------------------------------- it('Should clean 1', () => { const T = Type.Object({ x: Type.Number() }) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const T = Type.Object({ x: Type.Number() }) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean 3', () => { const T = Type.Object({ x: Type.Number() }) const R = Value.Clean(T, { x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clean 4', () => { const T = Type.Object({ x: Type.Number() }) const R = Value.Clean(T, { x: null }) Assert.IsEqual(R, { x: null }) }) // ---------------------------------------------------------------- // Nested // ---------------------------------------------------------------- it('Should clean nested 1', () => { const T = Type.Object({ x: Type.Object({ y: Type.Number(), }), }) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean nested 2', () => { const T = Type.Object({ x: Type.Object({ y: Type.Number(), }), }) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean nested 3', () => { const T = Type.Object({ x: Type.Object({ y: Type.Number(), }), }) const R = Value.Clean(T, { x: null }) Assert.IsEqual(R, { x: null }) }) it('Should clean nested 4', () => { const T = Type.Object({ x: Type.Object({ y: Type.Number(), }), }) const R = Value.Clean(T, { x: { y: null } }) Assert.IsEqual(R, { x: { y: null } }) }) // ---------------------------------------------------------------- // Additional Properties // ---------------------------------------------------------------- it('Should clean additional properties 1', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean additional properties 2', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean additional properties 3', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) const R = Value.Clean(T, { x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clean additional properties 4', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) const R = Value.Clean(T, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) // ---------------------------------------------------------------- // Additional Properties Discard // ---------------------------------------------------------------- it('Should clean additional properties discard 1', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean additional properties discard 2', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) const R = Value.Clean(T, { k: '', d: null }) Assert.IsEqual(R, { k: '' }) }) it('Should clean additional properties discard 3', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) const R = Value.Clean(T, { k: '', d: null, x: 1 }) Assert.IsEqual(R, { k: '', x: 1 }) }) it('Should clean additional properties discard 4', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { additionalProperties: Type.String(), }, ) const R = Value.Clean(T, { k: '', d: null, x: 1, y: 2 }) Assert.IsEqual(R, { k: '', x: 1, y: 2 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/promise.ts000066400000000000000000000004731505437577000251520ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Promise', () => { it('Should clean 1', () => { const T = Type.Promise(Type.Any()) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/record.ts000066400000000000000000000101231505437577000247430ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Record', () => { // ---------------------------------------------------------------- // Clean // ---------------------------------------------------------------- it('Should clean 1', () => { const T = Type.Record(Type.Number(), Type.String()) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const T = Type.Record(Type.Number(), Type.String()) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean 3', () => { const T = Type.Record(Type.Number(), Type.String()) const R = Value.Clean(T, { 0: null }) Assert.IsEqual(R, { 0: null }) }) // ---------------------------------------------------------------- // Clean Discard // ---------------------------------------------------------------- it('Should clean discard 1', () => { const T = Type.Record(Type.Number(), Type.String()) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean discard 2', () => { const T = Type.Record(Type.Number(), Type.String()) const R = Value.Clean(T, { a: 1 }) Assert.IsEqual(R, {}) }) it('Should clean discard 3', () => { const T = Type.Record(Type.Number(), Type.String()) const R = Value.Clean(T, { a: 1, 0: null }) Assert.IsEqual(R, { 0: null }) }) // ---------------------------------------------------------------- // Additional Properties // ---------------------------------------------------------------- it('Should clean additional properties 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean additional properties 2', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean additional properties 3', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, { 0: null }) Assert.IsEqual(R, { 0: null }) }) // ---------------------------------------------------------------- // Additional Properties Discard // ---------------------------------------------------------------- it('Should clean additional properties discard 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean additional properties discard 2', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, { a: null }) Assert.IsEqual(R, {}) }) it('Should clean additional properties discard 3', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, { a: null, 0: null }) Assert.IsEqual(R, { 0: null }) }) // ---------------------------------------------------------------- // Additional Properties Keep // ---------------------------------------------------------------- it('Should clean additional properties keep 1', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean additional properties keep 2', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, { a: true }) Assert.IsEqual(R, { a: true }) }) it('Should clean additional properties keep 3', () => { const T = Type.Record(Type.Number(), Type.String(), { additionalProperties: Type.Boolean(), }) const R = Value.Clean(T, { a: true, 0: null }) Assert.IsEqual(R, { a: true, 0: null }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/recursive.ts000066400000000000000000000062361505437577000255060ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Recursive', () => { // ---------------------------------------------------------------- // Clean // ---------------------------------------------------------------- it('Should clean 1', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, { id: null }) Assert.IsEqual(R, { id: null }) }) it('Should clean 3', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, { id: null, nodes: null }) Assert.IsEqual(R, { id: null, nodes: null }) }) it('Should clean 4', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, { id: null, nodes: [] }) Assert.IsEqual(R, { id: null, nodes: [] }) }) it('Should clean 5', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, { id: null, nodes: [{ id: null }] }) Assert.IsEqual(R, { id: null, nodes: [{ id: null }] }) }) // ---------------------------------------------------------------- // Clean Discard // ---------------------------------------------------------------- it('Should clean discard 1', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean discard 2', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, { u: null, id: null }) Assert.IsEqual(R, { id: null }) }) it('Should clean discard 3', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, { u: null, id: null, nodes: null }) Assert.IsEqual(R, { id: null, nodes: null }) }) it('Should clean discard 4', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, { u: null, id: null, nodes: [] }) Assert.IsEqual(R, { id: null, nodes: [] }) }) it('Should clean discard 5', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) const R = Value.Clean(T, { u: null, id: null, nodes: [{ u: null, id: null }] }) Assert.IsEqual(R, { id: null, nodes: [{ id: null }] }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/ref.ts000066400000000000000000000035711505437577000242520ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Ref', () => { // ---------------------------------------------------------------- // Clean // ---------------------------------------------------------------- it('Should clean 1', () => { const A = Type.Object( { x: Type.Number(), }, { $id: 'A' }, ) const T = Type.Ref('A') const R = Value.Clean(T, [A], null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const A = Type.Object( { x: Type.Number(), }, { $id: 'A' }, ) const T = Type.Ref('A') const R = Value.Clean(T, [A], {}) Assert.IsEqual(R, {}) }) it('Should clean 3', () => { const A = Type.Object( { x: Type.Number(), }, { $id: 'A' }, ) const T = Type.Ref('A') const R = Value.Clean(T, [A], { x: null }) Assert.IsEqual(R, { x: null }) }) // ---------------------------------------------------------------- // Clean Discard // ---------------------------------------------------------------- it('Should clean discard 1', () => { const A = Type.Object( { x: Type.Number(), }, { $id: 'A' }, ) const T = Type.Ref('A') const R = Value.Clean(T, [A], null) Assert.IsEqual(R, null) }) it('Should clean discard 2', () => { const A = Type.Object( { x: Type.Number(), }, { $id: 'A' }, ) const T = Type.Ref('A') const R = Value.Clean(T, [A], { a: null }) Assert.IsEqual(R, {}) }) it('Should clean discard 3', () => { const A = Type.Object( { x: Type.Number(), }, { $id: 'A' }, ) const T = Type.Ref('A') const R = Value.Clean(T, [A], { a: null, x: null }) Assert.IsEqual(R, { x: null }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/regexp.ts000066400000000000000000000004611505437577000247630ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/RegExp', () => { it('Should clean 1', () => { const T = Type.RegExp('') const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/string.ts000066400000000000000000000004571505437577000250040ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/String', () => { it('Should clean 1', () => { const T = Type.String() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/symbol.ts000066400000000000000000000004571505437577000250030ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Symbol', () => { it('Should clean 1', () => { const T = Type.Symbol() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/template-literal.ts000066400000000000000000000005031505437577000267330ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/TemplateLiteral', () => { it('Should clean 1', () => { const T = Type.TemplateLiteral('') const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/tuple.ts000066400000000000000000000057101505437577000246240ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Tuple', () => { // ---------------------------------------------------------------- // Clean // ---------------------------------------------------------------- it('Should clean 1', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const R = Value.Clean(T, []) Assert.IsEqual(R, []) }) it('Should clean 3', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const R = Value.Clean(T, [1, 2]) Assert.IsEqual(R, [1, 2]) }) it('Should clean 4', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const R = Value.Clean(T, [1, 2, 3]) Assert.IsEqual(R, [1, 2]) }) // ---------------------------------------------------------------- // Clean Deep // ---------------------------------------------------------------- it('Should clean deep 1', () => { const T = Type.Tuple([ Type.Number(), Type.Object({ x: Type.Number(), }), ]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean deep 2', () => { const T = Type.Tuple([ Type.Number(), Type.Object({ x: Type.Number(), }), ]) const R = Value.Clean(T, []) Assert.IsEqual(R, []) }) it('Should clean deep 3', () => { const T = Type.Tuple([ Type.Number(), Type.Object({ x: Type.Number(), }), ]) const R = Value.Clean(T, [1]) Assert.IsEqual(R, [1]) }) it('Should clean deep 4', () => { const T = Type.Tuple([ Type.Number(), Type.Object({ x: Type.Number(), }), ]) const R = Value.Clean(T, [1, null]) Assert.IsEqual(R, [1, null]) }) it('Should clean deep 5', () => { const T = Type.Tuple([ Type.Number(), Type.Object({ x: Type.Number(), }), ]) const R = Value.Clean(T, [1, { x: null }]) Assert.IsEqual(R, [1, { x: null }]) }) it('Should clean deep 6', () => { const T = Type.Tuple([ Type.Number(), Type.Object({ x: Type.Number(), }), ]) const R = Value.Clean(T, [1, { u: null, x: null }]) Assert.IsEqual(R, [1, { x: null }]) }) // ---------------------------------------------------------------- // Clean Empty // ---------------------------------------------------------------- it('Should clean empty 1', () => { const T = Type.Tuple([]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean empty 2', () => { const T = Type.Tuple([]) const R = Value.Clean(T, []) Assert.IsEqual(R, []) }) it('Should clean empty 3', () => { const T = Type.Tuple([]) const R = Value.Clean(T, [1]) Assert.IsEqual(R, []) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/uint8array.ts000066400000000000000000000004671505437577000256050ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Uint8Array', () => { it('Should clean 1', () => { const T = Type.Uint8Array() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/undefined.ts000066400000000000000000000004651505437577000254360ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Undefined', () => { it('Should clean 1', () => { const T = Type.Undefined() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/union.ts000066400000000000000000000136661505437577000246340ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Union', () => { // ---------------------------------------------------------------- // Clean // ---------------------------------------------------------------- it('Should clean 1', () => { const T = Type.Union([Type.Number(), Type.Boolean()]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean 2', () => { const T = Type.Union([Type.Number(), Type.Boolean()]) const R = Value.Clean(T, 1) Assert.IsEqual(R, 1) }) it('Should clean 2', () => { const T = Type.Union([Type.Number(), Type.Boolean()]) const R = Value.Clean(T, true) Assert.IsEqual(R, true) }) // ---------------------------------------------------------------- // Clean Select // ---------------------------------------------------------------- it('Should clean select 1', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean select 2', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, {}) Assert.IsEqual(R, {}) }) it('Should clean select 3', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { x: null }) Assert.IsEqual(R, { x: null }) }) it('Should clean select 4', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { y: null }) Assert.IsEqual(R, { y: null }) }) // ---------------------------------------------------------------- // Clean Select Discard // ---------------------------------------------------------------- it('Should clean select discard 1', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean select discard 2', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { u: null }) Assert.IsEqual(R, { u: null }) // no match }) it('Should clean select discard 3', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { u: null, x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clean select discard 4', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { u: null, y: 1 }) Assert.IsEqual(R, { y: 1 }) }) // ---------------------------------------------------------------- // Clean Select Retain // ---------------------------------------------------------------- it('Should clean select retain 1', () => { const X = Type.Object({ x: Type.Number() }, { additionalProperties: Type.Null() }) const Y = Type.Object({ y: Type.Number() }, { additionalProperties: Type.Null() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) it('Should clean select retain 2', () => { const X = Type.Object({ x: Type.Number() }, { additionalProperties: Type.Null() }) const Y = Type.Object({ y: Type.Number() }, { additionalProperties: Type.Null() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { u: null }) Assert.IsEqual(R, { u: null }) }) it('Should clean select retain 3', () => { const X = Type.Object({ x: Type.Number() }, { additionalProperties: Type.Null() }) const Y = Type.Object({ y: Type.Number() }, { additionalProperties: Type.Null() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { u: null, x: 1 }) Assert.IsEqual(R, { u: null, x: 1 }) }) it('Should clean select retain 4', () => { const X = Type.Object({ x: Type.Number() }, { additionalProperties: Type.Null() }) const Y = Type.Object({ y: Type.Number() }, { additionalProperties: Type.Null() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { u: null, y: 1 }) Assert.IsEqual(R, { u: null, y: 1 }) }) // ---------------------------------------------------------------- // Clean Select First and Discard // ---------------------------------------------------------------- it('Should clean select first and discard 1', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }, { additionalProperties: Type.Null() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { u: null, x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should clean select first and discard 2', () => { const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }, { additionalProperties: Type.Null() }) const T = Type.Union([X, Y]) const R = Value.Clean(T, { u: null, y: 1 }) Assert.IsEqual(R, { u: null, y: 1 }) }) // ---------------------------------------------------------------- // Union Recursive // // https://github.com/sinclairzx81/typebox/issues/845 // ---------------------------------------------------------------- it('Should clean recursive with union', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.Number(), parent: Type.Union([This, Type.Null()]), }), ) const R = Value.Clean(T, { id: 1, unknown: 1, parent: { id: 2, unknown: 1, parent: null, }, }) Assert.IsEqual(R, { id: 1, parent: { id: 2, parent: null } }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/unknown.ts000066400000000000000000000004611505437577000251700ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Unknown', () => { it('Should clean 1', () => { const T = Type.Unknown() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clean/void.ts000066400000000000000000000004531505437577000244330ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/clean/Void', () => { it('Should clean 1', () => { const T = Type.Void() const R = Value.Clean(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clone/000077500000000000000000000000001505437577000231365ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/clone/clone.ts000066400000000000000000000075241505437577000246160ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Assert } from '../../assert/index' describe('value/clone/Clone', () => { // -------------------------------------------- // ValueType // -------------------------------------------- it('Should clone null', () => { const R = Value.Clone(null) Assert.IsEqual(R, null) }) it('Should clone undefined', () => { const R = Value.Clone(undefined) Assert.IsEqual(R, undefined) }) it('Should clone number', () => { const R = Value.Clone(1) Assert.IsEqual(R, 1) }) it('Should clone bigint', () => { const R = Value.Clone(1n) Assert.IsEqual(R, 1n) }) it('Should clone boolean', () => { const R = Value.Clone(true) Assert.IsEqual(R, true) }) it('Should clone string', () => { const R = Value.Clone('hello') Assert.IsEqual(R, 'hello') }) it('Should clone symbol', () => { const S = Symbol('hello') const R = Value.Clone(S) Assert.IsEqual(R, S) }) // -------------------------------------------- // ObjectType // -------------------------------------------- it('Should clone object #1', () => { const V = { x: 1, y: 2, z: 3, } const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone object #2', () => { const V = { x: 1, y: 2, z: 3, w: { a: 1, b: 2, c: 3, }, } const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone object #3', () => { const V = { x: 1, y: 2, z: 3, w: [0, 1, 2, 3, 4], } const R = Value.Clone(V) Assert.IsEqual(R, V) }) // -------------------------------------------- // ArrayType // -------------------------------------------- it('Should clone array #1', () => { const V = [1, 2, 3, 4] const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone array #2', () => { const V = [ [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], ] const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone array #3', () => { const V = [ { x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 3 }, ] const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Int8Array', () => { const V = new Int8Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Uint8Array', () => { const V = new Uint8Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Uint8ClampedArray', () => { const V = new Uint8ClampedArray([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Int16Array', () => { const V = new Int16Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Uint16Array', () => { const V = new Uint16Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Int32Array', () => { const V = new Int32Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Uint32Array', () => { const V = new Int32Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Float32Array', () => { const V = new Float32Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone Float64Array', () => { const V = new Float64Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone BigInt64Array', () => { const V = new BigInt64Array([1n, 2n, 3n, 4n]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) it('Should clone BigUint64Array', () => { const V = new BigUint64Array([1n, 2n, 3n, 4n]) const R = Value.Clone(V) Assert.IsEqual(R, V) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/clone/index.ts000066400000000000000000000000211505437577000246060ustar00rootroot00000000000000import './clone' sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/000077500000000000000000000000001505437577000235165ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/any.ts000066400000000000000000000020451505437577000246560ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Any', () => { const T = Type.Any() it('Should convert null', () => { const V = null const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert undefined', () => { const V = undefined const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert string', () => { const V = 'hello' const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert number', () => { const V = 42 const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert boolean', () => { const V = true const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert object', () => { const V = { x: 1 } const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert array', () => { const V = [1, 2, 3] const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/array.ts000066400000000000000000000042561505437577000252130ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Array', () => { it('Should convert array of number', () => { const T = Type.Array(Type.Number()) const R = Value.Convert(T, [1, 3.14, '1', '3.14', true, false, 'true', 'false', 'hello']) Assert.IsEqual(R, [1, 3.14, 1, 3.14, 1, 0, 1, 0, 'hello']) }) it('Should convert array of boolean', () => { const T = Type.Array(Type.Boolean()) const R = Value.Convert(T, [1, 3.14, '1', '3.14', true, false, 'true', 'false', 'hello']) Assert.IsEqual(R, [true, 3.14, true, '3.14', true, false, true, false, 'hello']) }) it('Should convert array of string', () => { const T = Type.Array(Type.String()) const R = Value.Convert(T, [1, 3.14, '1', '3.14', true, false, 'true', 'false', 'hello']) Assert.IsEqual(R, ['1', '3.14', '1', '3.14', 'true', 'false', 'true', 'false', 'hello']) }) it('Should convert array of date', () => { const T = Type.Array(Type.Date()) const R = Value.Convert(T, [1, '1', true, false, 'true', 'false', 'hello']) as any[] Assert.IsEqual(R[0].getTime(), 1) Assert.IsEqual(R[1].getTime(), 1) Assert.IsEqual(R[2].getTime(), 1) Assert.IsEqual(R[3].getTime(), 0) Assert.IsEqual(R[4].getTime(), 1) Assert.IsEqual(R[5].getTime(), 0) Assert.IsEqual(R[6], 'hello') }) // ---------------------------------------------------------------- // Array Coercion // ---------------------------------------------------------------- it('Should convert into array (convert interior)', () => { const T = Type.Array(Type.Number()) const R = Value.Convert(T, '1') Assert.IsEqual(R, [1]) }) it('Should convert into array (retain interior)', () => { const T = Type.Array(Type.Number()) const R = Value.Convert(T, 'A') Assert.IsEqual(R, ['A']) }) it('Should convert into array (object)', () => { const T = Type.Array( Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), ) const R = Value.Convert(T, { x: '1', y: true, z: null }) Assert.IsEqual(R, [{ x: 1, y: 1, z: null }]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/async-iterator.ts000066400000000000000000000007461505437577000270410ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/AsyncIterator', () => { const T = Type.AsyncIterator(Type.Any()) it('Should passthrough 1', () => { const V = (async function* () {})() const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should passthrough 2', () => { const V = 1 const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/bigint.ts000066400000000000000000000056041505437577000253470ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/BigInt', () => { it('Should convert bigint from string 1', () => { const T = Type.BigInt() const R = Value.Convert(T, '1') Assert.IsEqual(R, BigInt(1)) }) it('Should convert bigint from string 2', () => { const T = Type.BigInt() const R = Value.Convert(T, '3.14') Assert.IsEqual(R, BigInt(3)) }) it('Should convert bigint from string 3', () => { const T = Type.BigInt() const R = Value.Convert(T, 'true') Assert.IsEqual(R, BigInt(1)) }) it('Should convert bigint from string 4', () => { const T = Type.BigInt() const R = Value.Convert(T, 'false') Assert.IsEqual(R, BigInt(0)) }) it('Should convert bigint from string 5', () => { const T = Type.BigInt() const R = Value.Convert(T, '12345678901234567890') Assert.IsEqual(R, BigInt('12345678901234567890')) }) it('Should convert bigint from string 6', () => { const T = Type.BigInt() const R = Value.Convert(T, '-12345678901234567890') Assert.IsEqual(R, BigInt('-12345678901234567890')) }) it('Should convert bigint from string 7', () => { const T = Type.BigInt() const R = Value.Convert(T, '12345678901234567890.123') Assert.IsEqual(R, BigInt('12345678901234567890')) }) it('Should convert bigint from string 8', () => { const T = Type.BigInt() const R = Value.Convert(T, '-12345678901234567890.123') Assert.IsEqual(R, BigInt('-12345678901234567890')) }) it('Should convert bigint from number 1', () => { const T = Type.BigInt() const R = Value.Convert(T, 1) Assert.IsEqual(R, BigInt(1)) }) it('Should convert bigint from number 2', () => { const T = Type.BigInt() const R = Value.Convert(T, 3.14) Assert.IsEqual(R, BigInt(3)) }) it('Should convert bigint from number 3', () => { const T = Type.BigInt() const R = Value.Convert(T, Math.pow(2, 31)) Assert.IsEqual(R, BigInt(2147483648)) }) it('Should convert bigint from number 4', () => { const T = Type.BigInt() const R = Value.Convert(T, Number.MAX_SAFE_INTEGER) Assert.IsEqual(R, BigInt(9007199254740991)) }) it('Should convert bigint from number 5', () => { const T = Type.BigInt() const R = Value.Convert(T, 123456789012345.6789) Assert.IsEqual(R, BigInt(123456789012345)) }) it('Should convert bigint from number 6', () => { const T = Type.BigInt() const R = Value.Convert(T, -123456789012345.6789) Assert.IsEqual(R, BigInt(-123456789012345)) }) it('Should convert bigint from boolean 1', () => { const T = Type.BigInt() const R = Value.Convert(T, true) Assert.IsEqual(R, BigInt(1)) }) it('Should convert bigint from boolean 2', () => { const T = Type.BigInt() const R = Value.Convert(T, false) Assert.IsEqual(R, BigInt(0)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/boolean.ts000066400000000000000000000113731505437577000255120ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Boolean', () => { it('Should convert from string 1', () => { const T = Type.Boolean() const R = Value.Convert(T, '1') Assert.IsEqual(R, true) }) it('Should convert from string 2', () => { const T = Type.Boolean() const R = Value.Convert(T, '3.14') Assert.IsEqual(R, '3.14') }) it('Should convert from string 3', () => { const T = Type.Boolean() const R = Value.Convert(T, 'true') Assert.IsEqual(R, true) }) it('Should convert from string 4', () => { const T = Type.Boolean() const R = Value.Convert(T, 'false') Assert.IsEqual(R, false) }) it('Should convert from number 1', () => { const T = Type.Boolean() const R = Value.Convert(T, 1) Assert.IsEqual(R, true) }) it('Should convert from number 2', () => { const T = Type.Boolean() const R = Value.Convert(T, 3.14) Assert.IsEqual(R, 3.14) }) it('Should convert from number 3', () => { const T = Type.Boolean() const R = Value.Convert(T, 1.1) Assert.IsEqual(R, 1.1) }) it('Should convert from boolean 1', () => { const T = Type.Boolean() const R = Value.Convert(T, true) Assert.IsEqual(R, true) }) it('Should convert from boolean 2', () => { const T = Type.Boolean() const R = Value.Convert(T, false) Assert.IsEqual(R, false) }) // ---------------------------------------------------------- // Casts // ---------------------------------------------------------- it('Should convert string #1', () => { const value = 'hello' const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, 'hello') }) it('Should convert string #2', () => { const value = 'true' const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, true) }) it('Should convert string #3', () => { const value = 'TRUE' const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, true) }) it('Should convert string #4', () => { const value = 'false' const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, false) }) it('Should convert string #5', () => { const value = '0' const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, false) }) it('Should convert string #6', () => { const value = '1' const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, true) }) it('Should convert string #7', () => { const value = '0' const result = Value.Convert(Type.Boolean({ default: true }), value) Assert.IsEqual(result, false) }) it('Should convert string #8', () => { const value = '1' const result = Value.Convert(Type.Boolean({ default: false }), value) Assert.IsEqual(result, true) }) it('Should convert string #8', () => { const value = '2' const result = Value.Convert(Type.Boolean({ default: true }), value) Assert.IsEqual(result, '2') }) it('Should convert number #1', () => { const value = 0 const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, false) }) it('Should convert number #2', () => { const value = 1n const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, true) }) it('Should convert number #3', () => { const value = 1 const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, true) }) it('Should convert number #4', () => { const value = 2 const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, 2) }) it('Should convert number #5', () => { const value = 0 const result = Value.Convert(Type.Boolean({ default: true }), value) Assert.IsEqual(result, false) }) it('Should convert number #6', () => { const value = 1 const result = Value.Convert(Type.Boolean({ default: false }), value) Assert.IsEqual(result, true) }) it('Should convert number #7', () => { const value = 2 const result = Value.Convert(Type.Boolean({ default: true }), value) Assert.IsEqual(result, 2) }) it('Should convert true', () => { const value = true const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, true) }) it('Should convert false', () => { const value = false const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, false) }) it('Should convert object', () => { const value = {} const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, {}) }) it('Should convert array', () => { const value = [] as any[] const result = Value.Convert(Type.Boolean(), value) Assert.IsEqual(result, []) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/composite.ts000066400000000000000000000010261505437577000260670ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Composite', () => { it('Should convert properties', () => { // prettier-ignore const T = Type.Composite([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Boolean() }), Type.Object({ z: Type.Boolean() }) ]) const R = Value.Convert(T, { x: '42', y: 'true', z: 'hello' }) Assert.IsEqual(R, { x: 42, y: true, z: 'hello' }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/constructor.ts000066400000000000000000000007251505437577000264570ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Constructor', () => { const T = Type.Constructor([], Type.Any()) it('Should passthrough 1', () => { const V = class {} const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should passthrough 2', () => { const V = 1 const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/date.ts000066400000000000000000000035071505437577000250100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Date', () => { it('Should convert from number', () => { const result = Value.Convert(Type.Date(), 123) as Date Assert.IsEqual(result.getTime(), 123) }) it('Should convert from numeric string', () => { const result = Value.Convert(Type.Date(), '123') as Date Assert.IsEqual(result.getTime(), 123) }) it('Should convert from boolean true (interpretted as numeric 1)', () => { const result = Value.Convert(Type.Date(), true) as Date Assert.IsEqual(result.getTime(), 1) }) it('Should convert from datetime string', () => { const result = Value.Convert(Type.Date(), '1980-02-03T01:02:03.000Z') as Date Assert.IsEqual(result.toISOString(), '1980-02-03T01:02:03.000Z') }) it('Should convert from datetime string without timezone', () => { const result = Value.Convert(Type.Date(), '1980-02-03T01:02:03') as Date Assert.IsEqual(result.toISOString(), '1980-02-03T01:02:03.000Z') }) it('Should convert from time with timezone', () => { const result = Value.Convert(Type.Date(), '01:02:03.000Z') as Date Assert.IsEqual(result.toISOString(), '1970-01-01T01:02:03.000Z') }) it('Should convert from time without timezone', () => { const result = Value.Convert(Type.Date(), '01:02:03') as Date Assert.IsEqual(result.toISOString(), '1970-01-01T01:02:03.000Z') }) it('Should convert from date string', () => { const result = Value.Convert(Type.Date(), '1980-02-03') as Date Assert.IsEqual(result.toISOString(), '1980-02-03T00:00:00.000Z') }) it('Should convert invalid strings to unix epoch 0', () => { const result = Value.Convert(Type.Date(), 'invalid-date') as Date Assert.IsEqual(result, 'invalid-date') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/enum.ts000066400000000000000000000003211505437577000250260ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Enum', () => { it('Should convert', () => {}) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/function.ts000066400000000000000000000007251505437577000257170ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Function', () => { const T = Type.Function([], Type.Any()) it('Should passthrough 1', () => { const V = function () {} const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should passthrough 2', () => { const V = 1 const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/import.ts000066400000000000000000000017421505437577000254040ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' // prettier-ignore describe('value/convert/Import', () => { it('Should convert properties', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number(), y: Type.Boolean(), z: Type.Boolean() })}).Import('A') const R = Value.Convert(T, { x: '42', y: 'true', z: 'hello' }) Assert.IsEqual(R, { x: 42, y: true, z: 'hello' }) }) it('Should convert known properties', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number(), y: Type.Boolean() })}).Import('A') const R = Value.Convert(T, { x: '42', y: 'true', z: 'hello' }) Assert.IsEqual(R, { x: 42, y: true, z: 'hello' }) }) it('Should not convert missing properties', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number() }) }).Import('A') const R = Value.Convert(T, { }) Assert.IsEqual(R, { }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/index.ts000066400000000000000000000011461505437577000251770ustar00rootroot00000000000000import './any' import './array' import './async-iterator' import './bigint' import './boolean' import './composite' import './constructor' import './kind' import './date' import './enum' import './function' import './import' import './integer' import './intersect' import './iterator' import './keyof' import './literal' import './never' import './null' import './number' import './object' import './promise' import './recursive' import './record' import './regexp' import './string' import './symbol' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/integer.ts000066400000000000000000000063071505437577000255310ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Integer', () => { it('Should convert from string 1', () => { const T = Type.Integer() const R = Value.Convert(T, '3.14') Assert.IsEqual(R, 3) }) it('Should convert from string 2', () => { const T = Type.Integer() const R = Value.Convert(T, '42') Assert.IsEqual(R, 42) }) it('Should convert from boolean 1', () => { const T = Type.Integer() const R = Value.Convert(T, true) Assert.IsEqual(R, 1) }) it('Should convert from boolean 2', () => { const T = Type.Integer() const R = Value.Convert(T, false) Assert.IsEqual(R, 0) }) it('Should convert from number 1', () => { const T = Type.Integer() const R = Value.Convert(T, 3.14) Assert.IsEqual(R, 3) }) // ---------------------------------------------------------- // Casts // ---------------------------------------------------------- it('Should convert string #1', () => { const value = 'hello' const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, 'hello') }) it('Should convert string #2', () => { const value = '3.14' const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, 3) }) it('Should convert string #3', () => { const value = '-0' const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, -0) }) it('Should convert string #4', () => { const value = '-100' const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, -100) }) it('Should convert number', () => { const value = 42 const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, 42) }) it('Should convert true', () => { const value = true const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, 1) }) it('Should convert false', () => { const value = false const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, 0) }) it('Should convert object', () => { const value = {} const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, {}) }) it('Should convert array', () => { const value = [] as any[] const result = Value.Convert(Type.Integer(), value) Assert.IsEqual(result, []) }) // ---------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1147 // ---------------------------------------------------------- it('Should convert large Integer 1', () => { const N = 1738213389080 const R = Value.Convert(Type.Integer(), N) Assert.IsEqual(R, N) }) it('Should convert large Integer 2', () => { const N = 1738213389080.5555 const R = Value.Convert(Type.Integer(), N) Assert.IsEqual(R, 1738213389080) }) it('Should convert large Integer 3', () => { const N = '1738213389080' const R = Value.Convert(Type.Integer(), N) Assert.IsEqual(R, 1738213389080) }) it('Should convert large Integer 3', () => { const N = '1738213389080.555' const R = Value.Convert(Type.Integer(), N) Assert.IsEqual(R, 1738213389080) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/intersect.ts000066400000000000000000000027471505437577000261000ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Intersect', () => { it('Should convert intersected objects', () => { // prettier-ignore const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Convert(T, { x: '1', y: '2' }) Assert.IsEqual(R, { x: 1, y: 2 }) }) // ---------------------------------------------------------------- // Intersection Complex // ---------------------------------------------------------------- it('Should complex intersect 1', () => { // prettier-ignore const T = Type.Intersect([ Type.Number(), Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Convert(T, { x: '1', y: '2' }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should complex intersect 2', () => { // prettier-ignore const T = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }), Type.Number(), ]) const R = Value.Convert(T, { x: '3', y: '4' }) Assert.IsEqual(R, { x: 3, y: 4 }) }) it('Should complex intersect 3', () => { // prettier-ignore const T = Type.Intersect([ Type.Number(), Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]) const R = Value.Convert(T, '123') Assert.IsEqual(R, 123) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/iterator.ts000066400000000000000000000007261505437577000257240ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Iterator', () => { const T = Type.Iterator(Type.Any()) it('Should passthrough 1', () => { const V = (function* () {})() const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should passthrough 2', () => { const V = 1 const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/keyof.ts000066400000000000000000000003221505437577000252000ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/KeyOf', () => { it('Should convert', () => {}) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/kind.ts000066400000000000000000000025421505437577000250160ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { TypeRegistry, Kind, TSchema } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Kind', () => { // --------------------------------------------------------- // Fixtures // --------------------------------------------------------- beforeEach(() => TypeRegistry.Set('Kind', () => true)) afterEach(() => TypeRegistry.Delete('Kind')) // --------------------------------------------------------- // Test // --------------------------------------------------------- it('Should not convert value 1', () => { const T = { [Kind]: 'Kind' } as TSchema const R = Value.Convert(T, true) Assert.IsEqual(R, true) }) it('Should not convert value 2', () => { const T = { [Kind]: 'Kind' } as TSchema const R = Value.Convert(T, 42) Assert.IsEqual(R, 42) }) it('Should not convert value 3', () => { const T = { [Kind]: 'Kind' } as TSchema const R = Value.Convert(T, 'hello') Assert.IsEqual(R, 'hello') }) it('Should not convert value 4', () => { const T = { [Kind]: 'Kind' } as TSchema const R = Value.Convert(T, { x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should not convert value 5', () => { const T = { [Kind]: 'Kind' } as TSchema const R = Value.Convert(T, [0, 1]) Assert.IsEqual(R, [0, 1]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/literal.ts000066400000000000000000000047011505437577000255240ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/LiteralString', () => { it('Should convert from number 1', () => { const T = Type.Literal('1') const R = Value.Convert(T, 1) Assert.IsEqual(R, '1') }) it('Should convert from number 2', () => { const T = Type.Literal('1') const R = Value.Convert(T, 2) Assert.IsEqual(R, 2) }) it('Should convert from boolean', () => { const T = Type.Literal('true') const R = Value.Convert(T, true) Assert.IsEqual(R, 'true') }) }) describe('value/convert/LiteralNumber', () => { it('Should convert from number 1', () => { const T = Type.Literal(3.14) const R = Value.Convert(T, '3.14') Assert.IsEqual(R, 3.14) }) it('Should convert from number 2', () => { const T = Type.Literal(3.14) const R = Value.Convert(T, '3.15') Assert.IsEqual(R, '3.15') }) it('Should convert from boolean 1', () => { const T = Type.Literal(1) const R = Value.Convert(T, true) Assert.IsEqual(R, 1) }) it('Should convert from boolean 2', () => { const T = Type.Literal(0) const R = Value.Convert(T, false) Assert.IsEqual(R, 0) }) it('Should convert from boolean 3', () => { const T = Type.Literal(2) const R = Value.Convert(T, true) Assert.IsEqual(R, true) }) }) describe('value/convert/LiteralBoolean', () => { it('Should convert from number 1', () => { const T = Type.Literal(true) const R = Value.Convert(T, 3.14) Assert.IsEqual(R, 3.14) }) it('Should convert from number 2', () => { const T = Type.Literal(true) const R = Value.Convert(T, 1) Assert.IsEqual(R, true) }) it('Should convert from string 1', () => { const T = Type.Literal(true) const R = Value.Convert(T, 'true') Assert.IsEqual(R, true) }) it('Should convert from string 2', () => { const T = Type.Literal(false) const R = Value.Convert(T, 'false') Assert.IsEqual(R, false) }) it('Should convert from string 3', () => { const T = Type.Literal(true) const R = Value.Convert(T, '1') Assert.IsEqual(R, true) }) it('Should convert from string 4', () => { const T = Type.Literal(false) const R = Value.Convert(T, '0') Assert.IsEqual(R, false) }) it('Should convert from string 5', () => { const T = Type.Literal(false) const R = Value.Convert(T, '2') Assert.IsEqual(R, '2') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/never.ts000066400000000000000000000011031505437577000252000ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Never', () => { it('Should not convert 1', () => { const T = Type.Never() const R = Value.Convert(T, true) Assert.IsEqual(R, true) }) it('Should not convert 2', () => { const T = Type.Never() const R = Value.Convert(T, 42) Assert.IsEqual(R, 42) }) it('Should not convert 3', () => { const T = Type.Never() const R = Value.Convert(T, 'true') Assert.IsEqual(R, 'true') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/null.ts000066400000000000000000000010471505437577000250420ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Null', () => { const T = Type.Null() it('Should convert from string 1', () => { const R = Value.Convert(T, 'null') Assert.IsEqual(R, null) }) it('Should convert from string 2', () => { const R = Value.Convert(T, 'NULL') Assert.IsEqual(R, null) }) it('Should convert from string 3', () => { const R = Value.Convert(T, 'nil') Assert.IsEqual(R, 'nil') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/number.ts000066400000000000000000000044051505437577000253610ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Number', () => { const T = Type.Number() it('Should convert from string 1', () => { const R = Value.Convert(T, '3.14') Assert.IsEqual(R, 3.14) }) it('Should convert from string 2', () => { const R = Value.Convert(T, '42') Assert.IsEqual(R, 42) }) it('Should convert from boolean 1', () => { const R = Value.Convert(T, true) Assert.IsEqual(R, 1) }) it('Should convert from boolean 2', () => { const R = Value.Convert(T, false) Assert.IsEqual(R, 0) }) it('Should convert from number 1', () => { const R = Value.Convert(T, 3.14) Assert.IsEqual(R, 3.14) }) // ---------------------------------------------------------- // Casts // ---------------------------------------------------------- it('Should convert string #1', () => { const value = 'hello' const result = Value.Convert(Type.Number(), value) Assert.IsEqual(result, 'hello') }) it('Should convert string #2', () => { const value = '3.14' const result = Value.Convert(Type.Number(), value) Assert.IsEqual(result, 3.14) }) it('Should convert string #3', () => { const value = '-0' const result = Value.Convert(Type.Number(), value) Assert.IsEqual(result, -0) }) it('Should convert string #4', () => { const value = '-100' const result = Value.Convert(Type.Number(), value) Assert.IsEqual(result, -100) }) it('Should convert number', () => { const value = 42 const result = Value.Convert(Type.Number(), value) Assert.IsEqual(result, 42) }) it('Should convert true', () => { const value = true const result = Value.Convert(Type.Number(), value) Assert.IsEqual(result, 1) }) it('Should convert false', () => { const value = false const result = Value.Convert(Type.Number(), value) Assert.IsEqual(result, 0) }) it('Should convert object', () => { const value = {} const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, {}) }) it('Should convert array', () => { const value = [] as any[] const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, []) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/object.ts000066400000000000000000000016041505437577000253350ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' // prettier-ignore describe('value/convert/Object', () => { it('Should convert properties', () => { const T = Type.Object({ x: Type.Number(), y: Type.Boolean(), z: Type.Boolean() }) const R = Value.Convert(T, { x: '42', y: 'true', z: 'hello' }) Assert.IsEqual(R, { x: 42, y: true, z: 'hello' }) }) it('Should convert known properties', () => { const T = Type.Object({ x: Type.Number(), y: Type.Boolean() }) const R = Value.Convert(T, { x: '42', y: 'true', z: 'hello' }) Assert.IsEqual(R, { x: 42, y: true, z: 'hello' }) }) it('Should not convert missing properties', () => { const T = Type.Object({ x: Type.Number() }) const R = Value.Convert(T, { }) Assert.IsEqual(R, { }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/promise.ts000066400000000000000000000007231505437577000255460ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Promise', () => { const T = Type.Promise(Type.Any()) it('Should passthrough 1', () => { const V = Promise.resolve(1) const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should passthrough 2', () => { const V = 1 const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/record.ts000066400000000000000000000033631505437577000253510ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Record', () => { it('Should convert record value to numeric', () => { const T = Type.Record(Type.String(), Type.Number()) const V = Value.Convert(T, { x: '42', y: '24', z: 'hello' }) Assert.IsEqual(V, { x: 42, y: 24, z: 'hello' }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/930 // ---------------------------------------------------------------- it('Should convert record union 1', () => { const T = Type.Union([Type.Null(), Type.Record(Type.Number(), Type.Any())]) const V = Value.Convert(T, {}) Assert.IsEqual(V, {}) }) it('Should convert record union 2', () => { const T = Type.Union([Type.Record(Type.Number(), Type.Any()), Type.Null()]) const V = Value.Convert(T, {}) Assert.IsEqual(V, {}) }) it('Should convert record union 3', () => { const T = Type.Union([Type.Null(), Type.Record(Type.Number(), Type.Any())]) const V = Value.Convert(T, null) Assert.IsEqual(V, null) }) it('Should convert record union 4', () => { const T = Type.Union([Type.Record(Type.Number(), Type.Any()), Type.Null()]) const V = Value.Convert(T, null) Assert.IsEqual(V, null) }) it('Should convert record union 5', () => { const T = Type.Union([Type.Null(), Type.Record(Type.Number(), Type.Any())]) const V = Value.Convert(T, 'NULL') Assert.IsEqual(V, null) }) it('Should convert record union 6', () => { const T = Type.Union([Type.Record(Type.Number(), Type.Any()), Type.Null()]) const V = Value.Convert(T, 'NULL') Assert.IsEqual(V, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/recursive.ts000066400000000000000000000003261505437577000260760ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Recursive', () => { it('Should convert', () => {}) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/regexp.ts000066400000000000000000000003231505437577000253560ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/RegExp', () => { it('Should convert', () => {}) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/string.ts000066400000000000000000000041451505437577000254000ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/String', () => { const T = Type.String() it('Should convert from number 1', () => { const R = Value.Convert(T, 3.14) Assert.IsEqual(R, '3.14') }) it('Should convert from number 2', () => { const R = Value.Convert(T, 3) Assert.IsEqual(R, '3') }) it('Should convert from boolean 1', () => { const R = Value.Convert(T, true) Assert.IsEqual(R, 'true') }) it('Should convert from boolean 2', () => { const R = Value.Convert(T, false) Assert.IsEqual(R, 'false') }) it('Should convert from bigint', () => { const R = Value.Convert(T, BigInt(12345)) Assert.IsEqual(R, '12345') }) it('Should convert from symbol', () => { const R = Value.Convert(T, Symbol(12345)) Assert.IsEqual(R, '12345') }) // ---------------------------------------------------------- // Casts // ---------------------------------------------------------- it('Should convert string', () => { const value = 'hello' const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, 'hello') }) it('Should convert number #1', () => { const value = 42 const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, '42') }) it('Should convert number #2', () => { const value = 42n const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, '42') }) it('Should convert true', () => { const value = true const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, 'true') }) it('Should convert false', () => { const value = false const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, 'false') }) it('Should convert object', () => { const value = {} const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, {}) }) it('Should convert array', () => { const value = [] as any[] const result = Value.Convert(Type.String(), value) Assert.IsEqual(result, []) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/symbol.ts000066400000000000000000000007341505437577000253770ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Symbol', () => { const T = Type.Symbol() it('Should convert from number 1', () => { const R = Value.Convert(T, 3.14) as Symbol Assert.IsEqual(R.description, '3.14') }) it('Should convert from number 2', () => { const R = Value.Convert(T, 3) as Symbol Assert.IsEqual(R.description, '3') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/tuple.ts000066400000000000000000000013171505437577000252210ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Tuple', () => { it('Should convert from Array 1', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const R = Value.Convert(T, ['1', 'true']) Assert.IsEqual(R, [1, 1]) }) it('Should convert from Array 2', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const R = Value.Convert(T, ['1']) Assert.IsEqual(R, [1]) }) it('Should convert from Array 3', () => { const T = Type.Tuple([Type.Number(), Type.Number()]) const R = Value.Convert(T, ['1', '2', '3']) Assert.IsEqual(R, [1, 2, '3']) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/uint8array.ts000066400000000000000000000004051505437577000261730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Uint8Array', () => { it('Should convert from Array', () => { const T = Type.Uint8Array() }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/undefined.ts000066400000000000000000000007121505437577000260270ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Undefined', () => { const T = Type.Undefined() it('Should convert from string 1', () => { const R = Value.Convert(T, 'undefined') Assert.IsEqual(R, undefined) }) it('Should convert from string 2', () => { const R = Value.Convert(T, 'hello') Assert.IsEqual(R, 'hello') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/union.ts000066400000000000000000000100401505437577000252110ustar00rootroot00000000000000import { Convert, Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Union', () => { it('Should convert union variant', () => { const T = Type.Object({ x: Type.Union([Type.Number(), Type.Null()]), }) const V1 = Value.Convert(T, { x: '42' }) const V2 = Value.Convert(T, { x: 'null' }) const V3 = Value.Convert(T, { x: 'hello' }) Assert.IsEqual(V1, { x: 42 }) Assert.IsEqual(V2, { x: null }) Assert.IsEqual(V3, { x: 'hello' }) }) it('Should convert first variant in ambiguous conversion', () => { const T = Type.Object({ x: Type.Union([Type.Boolean(), Type.Number()]), }) const V1 = Value.Convert(T, { x: '1' }) Assert.IsEqual(V1, { x: true }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/787 // ---------------------------------------------------------------- // prettier-ignore it('Should convert Intersect Union', () => { const T = Type.Intersect([ Type.Union([ Type.Object({ a: Type.Number() }), Type.Object({ b: Type.Number() }), ]), Type.Object({ c: Type.Number() }), ]) const A = Convert(T, { a: '1', c: '2' }) const B = Convert(T, { b: '1', c: '2' }) const C = Convert(T, { a: '1', b: '2', c: '3' }) Assert.IsEqual(A, { a: 1, c: 2 }) Assert.IsEqual(B, { b: 1, c: 2 }) Assert.IsEqual(C, { a: 1, b: '2', c: 3 }) // note: matching on first }) it('Should preserve number type in string-first union when value already matches', () => { const T = Type.Union([Type.String(), Type.Number()]) const numValue = 42 const strValue = 'hello' const A = Value.Convert(T, numValue) const B = Value.Convert(T, strValue) Assert.IsEqual(typeof A, 'number') Assert.IsEqual(typeof B, 'string') Assert.IsEqual(A, 42) Assert.IsEqual(B, 'hello') }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1281 // Union conversion should preserve original type if valid // ---------------------------------------------------------------- it('Should preserve original type when value already matches union variant', () => { const T1 = Type.Object({ data: Type.Array(Type.Record(Type.String(), Type.Union([Type.String(), Type.Number(), Type.Null()]))), }) const T2 = Type.Object({ data: Type.Array(Type.Record(Type.String(), Type.Union([Type.Number(), Type.String(), Type.Null()]))), }) const testData = { data: [{ key1: 'hello', key2: 42, key3: null }], } const A = Value.Convert(T1, testData) const B = Value.Convert(T2, testData) // Both should preserve the original number type Assert.IsEqual(typeof (A as any).data[0].key2, 'number') Assert.IsEqual(typeof (B as any).data[0].key2, 'number') Assert.IsEqual((A as any).data[0].key2, 42) Assert.IsEqual((B as any).data[0].key2, 42) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1295 // ---------------------------------------------------------------- it('Should guard against Array conversion in Object', () => { const T = Type.Union([ Type.Object({ type: Type.Literal('A'), values: Type.Union([Type.String(), Type.Number()]), }), Type.Object({ type: Type.Literal('B'), values: Type.String(), }), ]) const converted = Value.Convert(T, [{ type: 'A', values: 1 }]) Assert.IsEqual(converted, [{ type: 'A', values: 1 }]) }) it('Should guard against Array conversion in Record', () => { const T = Type.Union([Type.Record(Type.String({ pattern: '^values$' }), Type.Union([Type.String(), Type.Number()])), Type.Record(Type.String({ pattern: '^type$' }), Type.Union([Type.String(), Type.Number()]))]) const converted = Value.Convert(T, [{ type: 'A', values: 1 }]) Assert.IsEqual(converted, [{ type: 'A', values: 1 }]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/unknown.ts000066400000000000000000000020551505437577000255670ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Unknown', () => { const T = Type.Unknown() it('Should convert null', () => { const V = null const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert undefined', () => { const V = undefined const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert string', () => { const V = 'hello' const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert number', () => { const V = 42 const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert boolean', () => { const V = true const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert object', () => { const V = { x: 1 } const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) it('Should convert array', () => { const V = [1, 2, 3] const R = Value.Convert(T, V) Assert.IsEqual(R, V) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/convert/void.ts000066400000000000000000000003211505437577000250230ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/Void', () => { it('Should convert', () => {}) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/000077500000000000000000000000001505437577000233015ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/create/_deferred.ts000066400000000000000000000005061505437577000255710ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Deferred', () => { it('Should use deferred value', () => { const T = Type.Any({ default: () => 1 }) const R = Value.Create(T) Assert.IsEqual(R, 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/any.ts000066400000000000000000000006211505437577000244370ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Any', () => { it('Should create value', () => { const T = Type.Any() Assert.IsEqual(Value.Create(T), {}) }) it('Should create default', () => { const T = Type.Any({ default: 1 }) Assert.IsEqual(Value.Create(T), 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/argument.ts000066400000000000000000000004431505437577000254740ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Argument', () => { it('Should create value', () => { const T = Type.Argument(0) Assert.IsEqual(Value.Create(T), {}) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/array.ts000066400000000000000000000011331505437577000247650ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Array', () => { it('Should create value', () => { const T = Type.Array(Type.String()) Assert.IsEqual(Value.Create(T), []) }) it('Should create default', () => { const T = Type.Array(Type.String(), { default: ['1'] }) Assert.IsEqual(Value.Create(T), ['1']) }) it('Should create with minItems', () => { const T = Type.Array(Type.String(), { minItems: 4 }) Assert.IsEqual(Value.Create(T), ['', '', '', '']) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/async-iterator.ts000066400000000000000000000007701505437577000266210ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/AsyncIterator', () => { it('Should create value', () => { const T = Type.AsyncIterator(Type.Any()) const R = Value.Create(T) Assert.IsTrue(Symbol.asyncIterator in R) }) it('Should create default', () => { const T = Type.AsyncIterator(Type.Any(), { default: 1 }) const R = Value.Create(T) Assert.IsEqual(R, 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/bigint.ts000066400000000000000000000006471505437577000251340ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/BigInt', () => { it('Should create value', () => { const T = Type.BigInt() Assert.IsEqual(Value.Create(T), BigInt(0)) }) it('Should create default', () => { const T = Type.BigInt({ default: true }) Assert.IsEqual(Value.Create(T), true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/boolean.ts000066400000000000000000000006461505437577000252760ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Boolean', () => { it('Should create value', () => { const T = Type.Boolean() Assert.IsEqual(Value.Create(T), false) }) it('Should create default', () => { const T = Type.Boolean({ default: true }) Assert.IsEqual(Value.Create(T), true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/composite.ts000066400000000000000000000027631505437577000256630ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Composite', () => { it('Should create value', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const B = Type.Object({ a: Type.Number(), b: Type.Number(), c: Type.Number(), }) const T = Type.Composite([A, B]) Assert.IsEqual(Value.Create(T), { x: 0, y: 0, z: 0, a: 0, b: 0, c: 0, }) }) it('Should create default', () => { const A = Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), z: Type.Number({ default: 3 }), }) const B = Type.Object({ a: Type.Number({ default: 4 }), b: Type.Number({ default: 5 }), c: Type.Number({ default: 6 }), }) const T = Type.Composite([A, B]) Assert.IsEqual(Value.Create(T), { x: 1, y: 2, z: 3, a: 4, b: 5, c: 6, }) }) it('Should create default and omit optionals', () => { const A = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const B = Type.Object({ a: Type.Optional(Type.Number()), b: Type.Optional(Type.Number()), c: Type.Optional(Type.Number()), }) const T = Type.Composite([A, B]) Assert.IsEqual(Value.Create(T), { x: 0, y: 0, z: 0, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/constructor.ts000066400000000000000000000015651505437577000262450ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Constructor', () => { it('Should create value', () => { const T = Type.Constructor( [], Type.Object({ test: Type.Function([], Type.Number({ default: 123 })), }), ) const C = Value.Create(T) const I = new C() const R = I.test() Assert.IsEqual(R, 123) }) it('Should create default', () => { const T = Type.Constructor( [], Type.Object({ test: Type.Function([], Type.Number({ default: 123 })), }), { default: () => class { test() { return 321 } }, }, ) const C = Value.Create(T) const I = new C() const R = I.test() Assert.IsEqual(R, 321) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/date.ts000066400000000000000000000017211505437577000245670ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Date', () => { it('Should create value', () => { const T = Type.Date() const A = Value.Create(T) const B = new Date() Assert.InRange(A.getTime(), B.getTime(), 1000) }) it('Should create default', () => { const T = Type.Date({ default: new Date(1001) }) const A = Value.Create(T) const B = new Date(1001) Assert.IsEqual(A, B) }) it('Should create value nested', () => { const T = Type.Object({ value: Type.Date() }) const A = Value.Create(T) const B = { value: new Date() } Assert.InRange(A.value.getTime(), B.value.getTime(), 1000) }) it('Should create default nested', () => { const T = Type.Object({ value: Type.Date({ default: new Date(1001) }) }) const A = Value.Create(T) const B = { value: new Date(1001) } Assert.IsEqual(A, B) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/enum.ts000066400000000000000000000007701505437577000246210ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Boolean', () => { it('Should create value', () => { enum Foo { A, B, } const T = Type.Enum(Foo) Assert.IsEqual(Value.Create(T), Foo.A) }) it('Should create default', () => { enum Foo { A, B, } const T = Type.Enum(Foo, { default: Foo.B }) Assert.IsEqual(Value.Create(T), Foo.B) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/function.ts000066400000000000000000000010711505437577000254750ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Function', () => { it('Should create value', () => { const T = Type.Function([], Type.Number({ default: 123 })) const F = Value.Create(T) const R = F() Assert.IsEqual(R, 123) }) it('Should create default', () => { const T = Type.Function([], Type.Number({ default: 123 }), { default: () => () => 321 }) const F = Value.Create(T) const R = F() Assert.IsEqual(R, 321) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/import.ts000066400000000000000000000046261505437577000251730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Import', () => { it('Should create value', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), }).Import('A') Assert.IsEqual(Value.Create(T), { x: 0, y: 0, z: 0, }) }) it('Should create value with optional properties', () => { const T = Type.Module({ A: Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), z: Type.Optional(Type.Number()), }), }).Import('A') Assert.IsEqual(Value.Create(T), {}) }) it('Should create default with default properties', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), z: Type.Number({ default: 3 }), }), }).Import('A') Assert.IsEqual(Value.Create(T), { x: 1, y: 2, z: 3, }) }) it('Should create nested object', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), w: Type.Object({ x: Type.Number({ default: 7 }), y: Type.Number(), z: Type.Number(), }), }), }).Import('A') Assert.IsEqual(Value.Create(T), { x: 0, y: 0, z: 0, w: { x: 7, y: 0, z: 0 }, }) }) it('Should create with default', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { default: { x: 1, y: 2, z: 3 } }, ), }).Import('A') Assert.IsEqual(Value.Create(T), { x: 1, y: 2, z: 3, }) }) // ---------------------------------------------------------------- // Mutation // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/726 it('Should clone defaults on assignment - no mutation', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), }, { default: { x: 1 } }, ), }).Import('A') const V = Value.Create(T) V.x = 123 Assert.IsEqual(T.$defs.A.default, { x: 1 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/index.ts000066400000000000000000000012661505437577000247650ustar00rootroot00000000000000import './_deferred' import './any' import './argument' import './array' import './async-iterator' import './bigint' import './boolean' import './composite' import './constructor' import './date' import './enum' import './function' import './import' import './integer' import './intersect' import './iterator' import './keyof' import './kind' import './literal' import './never' import './not' import './null' import './number' import './object' import './recursive' import './ref' import './record' import './regexp' import './string' import './symbol' import './template-literal' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/value/create/integer.ts000066400000000000000000000006341505437577000253110ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Integer', () => { it('Should create value', () => { const T = Type.Integer() Assert.IsEqual(Value.Create(T), 0) }) it('Should create default', () => { const T = Type.Integer({ default: 7 }) Assert.IsEqual(Value.Create(T), 7) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/intersect.ts000066400000000000000000000045671505437577000256650ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Intersect', () => { it('Should create value', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })]) const R = Value.Create(T) Assert.IsEqual(R, { x: 0, y: 0 }) }) it('Should create value with default', () => { const T = Type.Intersect([Type.Object({ x: Type.Number({ default: 100 }) }), Type.Object({ y: Type.Number({ default: 200 }) })]) const R = Value.Create(T) Assert.IsEqual(R, { x: 100, y: 200 }) }) it('Should create for overlapping intersection', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Number(), y: Type.Number() })]) const R = Value.Create(T) Assert.IsEqual(R, { x: 0, y: 0 }) }) it('Should create with last intersected overlapping default', () => { const T = Type.Intersect([Type.Object({ x: Type.Number({ default: 1 }) }), Type.Object({ x: Type.Number({ default: 2 }), y: Type.Number() })]) const R = Value.Create(T) Assert.IsEqual(R, { x: 2, y: 0 }) }) it('Should throw for non-constructable intersection 1', () => { const T = Type.Intersect([Type.Object({ x: Type.Number() }), Type.Object({ x: Type.String() })]) Assert.Throws(() => Value.Create(T)) }) it('Should throw for non-constructable intersection 2', () => { const T = Type.Intersect([Type.String(), Type.Number()]) Assert.Throws(() => Value.Create(T)) }) it('Should not throw for non-constructable intersection with default', () => { const T = Type.Intersect([Type.String(), Type.Number()], { default: 'hello' }) const R = Value.Create(T) Assert.IsEqual(R, 'hello') }) it('Should create from nested intersection', () => { const T = Type.Intersect([ Type.Object({ x: Type.Number({ default: 1 }), }), Type.Intersect([ Type.Object({ y: Type.Number({ default: 2 }), }), Type.Object({ z: Type.Number({ default: 3 }), }), ]), ]) const R = Value.Create(T) Assert.IsEqual(R, { x: 1, y: 2, z: 3 }) }) it('Should create non varying primitive', () => { const T = Type.Intersect([Type.Number(), Type.Number(), Type.Number()]) const R = Value.Create(T) Assert.IsEqual(R, 0) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/iterator.ts000066400000000000000000000007441505437577000255070ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Iterator', () => { it('Should create value', () => { const T = Type.Iterator(Type.Any()) const R = Value.Create(T) Assert.IsTrue(Symbol.iterator in R) }) it('Should create default', () => { const T = Type.Iterator(Type.Any(), { default: 1 }) const R = Value.Create(T) Assert.IsEqual(R, 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/keyof.ts000066400000000000000000000011221505437577000247620ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/KeyOf', () => { it('Should create value', () => { const T = Type.KeyOf( Type.Object({ x: Type.Number(), y: Type.Number(), }), ) Assert.IsEqual(Value.Create(T), 'x') }) it('Should create default', () => { const T = Type.KeyOf( Type.Object({ x: Type.Number(), y: Type.Number(), }), { default: 'y' }, ) Assert.IsEqual(Value.Create(T), 'y') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/kind.ts000066400000000000000000000016571505437577000246070ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type, Kind, TypeRegistry } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Kind', () => { // --------------------------------------------------------- // Fixtures // --------------------------------------------------------- beforeEach(() => TypeRegistry.Set('Kind', () => true)) afterEach(() => TypeRegistry.Delete('Kind')) // --------------------------------------------------------- // Tests // --------------------------------------------------------- it('Should create custom value with default', () => { const T = Type.Unsafe({ [Kind]: 'Kind', default: 'hello' }) Assert.IsEqual(Value.Create(T), 'hello') }) it('Should throw when no default value is specified', () => { TypeRegistry.Set('Kind', () => true) const T = Type.Unsafe({ [Kind]: 'Kind' }) Assert.Throws(() => Value.Create(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/literal.ts000066400000000000000000000013141505437577000253040ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Literal', () => { it('Should create literal string', () => { const T = Type.Literal('hello') Assert.IsEqual(Value.Create(T), 'hello') }) it('Should create literal number', () => { const T = Type.Literal(1) Assert.IsEqual(Value.Create(T), 1) }) it('Should create literal boolean', () => { const T = Type.Literal(true) Assert.IsEqual(Value.Create(T), true) }) it('Should create literal from default value', () => { const T = Type.Literal(true, { default: 'hello' }) Assert.IsEqual(Value.Create(T), 'hello') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/never.ts000066400000000000000000000004351505437577000247720ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Never', () => { it('Should create value', () => { const T = Type.Never() Assert.Throws(() => Value.Create(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/not.ts000066400000000000000000000012171505437577000244520ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Not', () => { it('Should throw without default value', () => { const T = Type.Not(Type.String()) Assert.Throws(() => Value.Create(T)) }) it('Should create value with default inner', () => { const T = Type.Not(Type.String(), { default: 100 }) const R = Value.Create(T) Assert.IsEqual(R, 100) }) it('Should create value with default outer', () => { const T = Type.Not(Type.String(), { default: 100 }) const R = Value.Create(T) Assert.IsEqual(R, 100) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/null.ts000066400000000000000000000006621505437577000246270ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Null', () => { it('Should create value', () => { const T = Type.Null() Assert.IsEqual(Value.Create(T), null) }) it('Should create null from default value', () => { const T = Type.Null({ default: 'hello' }) Assert.IsEqual(Value.Create(T), 'hello') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/number.ts000066400000000000000000000006311505437577000251410ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Number', () => { it('Should create value', () => { const T = Type.Number() Assert.IsEqual(Value.Create(T), 0) }) it('Should create default', () => { const T = Type.Number({ default: 7 }) Assert.IsEqual(Value.Create(T), 7) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/object.ts000066400000000000000000000041121505437577000251150ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Object', () => { it('Should create value', () => { const T = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) Assert.IsEqual(Value.Create(T), { x: 0, y: 0, z: 0, }) }) it('Should create value with optional properties', () => { const T = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()), z: Type.Optional(Type.Number()), }) Assert.IsEqual(Value.Create(T), {}) }) it('Should create default with default properties', () => { const T = Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), z: Type.Number({ default: 3 }), }) Assert.IsEqual(Value.Create(T), { x: 1, y: 2, z: 3, }) }) it('Should create nested object', () => { const T = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), w: Type.Object({ x: Type.Number({ default: 7 }), y: Type.Number(), z: Type.Number(), }), }) Assert.IsEqual(Value.Create(T), { x: 0, y: 0, z: 0, w: { x: 7, y: 0, z: 0 }, }) }) it('Should create with default', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { default: { x: 1, y: 2, z: 3 } }, ) Assert.IsEqual(Value.Create(T), { x: 1, y: 2, z: 3, }) }) // ---------------------------------------------------------------- // Mutation // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/726 it('Should clone defaults on assignment - no mutation', () => { const T = Type.Object( { x: Type.Number(), }, { default: { x: 1 } }, ) const V = Value.Create(T) V.x = 123 Assert.IsEqual(T.default, { x: 1 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/record.ts000066400000000000000000000010021505437577000251200ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Record', () => { it('Should create value', () => { const T = Type.Record(Type.String(), Type.Object({})) Assert.IsEqual(Value.Create(T), {}) }) it('Should create default', () => { const T = Type.Record(Type.String(), Type.Object({}), { default: { x: {}, }, }) Assert.IsEqual(Value.Create(T), { x: {} }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/recursive.ts000066400000000000000000000025171505437577000256650ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Recursive', () => { it('Should create value', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), ) Assert.IsEqual(Value.Create(T), { id: '', nodes: [], }) }) it('Should create default', () => { const T = Type.Recursive( (This) => Type.Object({ id: Type.String(), nodes: Type.Array(This), }), { default: 7 }, ) Assert.IsEqual(Value.Create(T), 7) }) it('Should throw on infinite type', () => { const T = Type.Recursive((This) => Type.Object({ x: This, }), ) Assert.Throws(() => Value.Create(T)) }) it('Should not throw on recursive type when terminating sub type proceeds self', () => { const T = Type.Recursive((This) => Type.Object({ x: Type.Union([Type.Null(), This]), }), ) Assert.IsEqual(Value.Create(T), { x: null }) }) it('Should not throw on recursive type when self is optional', () => { const T = Type.Recursive((This) => Type.Object({ x: Type.Optional(This), }), ) Assert.IsEqual(Value.Create(T), {}) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/ref.ts000066400000000000000000000020231505437577000244220ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Ref', () => { it('Should throw if target is undefined', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { $id: 'T', default: 'target' }, ) const R = Type.Ref('T') Assert.Throws(() => Value.Create(R)) }) it('Should create ref default if ref default is defined', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), z: Type.Number(), }, { $id: 'T', default: 'target' }, ) const R = Type.Ref('T', { default: 'override' }) Assert.IsEqual(Value.Create(R), 'override') // terminated at R default value }) it('Should dereference remote schema via $ref', () => { const R = Type.Number({ $id: 'R' }) const T = Type.Object({ x: Type.Ref('R') }) Assert.IsEqual(Value.Create(T, [R]), { x: 0 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/regexp.ts000066400000000000000000000013421505437577000251430ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/RegEx', () => { it('Should throw without a default value', () => { Assert.Throws(() => { const T = Type.RegExp(/foo/) Value.Create(T) }) }) it('Should create default', () => { const T = Type.RegExp(/foo/, { default: 'foo' }) Assert.IsEqual(Value.Create(T), 'foo') }) // ---------------------------------------------------------------- // Throw // ---------------------------------------------------------------- it('Should throw with no default', () => { const T = Type.RegExp(/foo/) Assert.Throws(() => Value.Create(T)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/string.ts000066400000000000000000000006461505437577000251650ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/String', () => { it('Should create value', () => { const T = Type.String() Assert.IsEqual(Value.Create(T), '') }) it('Should create default', () => { const T = Type.String({ default: 'hello' }) Assert.IsEqual(Value.Create(T), 'hello') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/symbol.ts000066400000000000000000000006751505437577000251660ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Symbol', () => { it('Should create value', () => { const T = Type.Symbol() const V = Value.Create(T) Assert.IsEqual(typeof V, 'symbol') }) it('Should create default', () => { const T = Type.Symbol({ default: true }) Assert.IsEqual(Value.Create(T), true) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/template-literal.ts000066400000000000000000000023511505437577000271170ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/TemplateLiteral', () => { it('Should create pattern 1', () => { const T = Type.TemplateLiteral([Type.Literal('A')]) const V = Value.Create(T) Assert.IsEqual(V, 'A') }) it('Should create pattern 2', () => { const T = Type.TemplateLiteral([Type.Literal('A'), Type.Literal('B')]) const V = Value.Create(T) Assert.IsEqual(V, 'AB') }) it('Should create pattern 3 (first only)', () => { const T = Type.TemplateLiteral([Type.Literal('A'), Type.Union([Type.Literal('B'), Type.Literal('C')])]) const V = Value.Create(T) Assert.IsEqual(V, 'AB') }) it('Should create pattern 4 (first only)', () => { const T = Type.TemplateLiteral([Type.Boolean()]) const V = Value.Create(T) Assert.IsEqual(V, 'true') }) it('Should throw on infinite pattern', () => { const T = Type.TemplateLiteral([Type.Number()]) Assert.Throws(() => Value.Create(T)) }) it('Should create on infinite pattern with default', () => { const T = Type.TemplateLiteral([Type.Number()], { default: 42 }) const V = Value.Create(T) Assert.IsEqual(V, 42) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/tuple.ts000066400000000000000000000016351505437577000250070ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Tuple', () => { it('Should create value', () => { const T = Type.Tuple([Type.Number(), Type.String()]) Assert.IsEqual(Value.Create(T), [0, '']) }) it('Should create default', () => { const T = Type.Tuple([Type.Number(), Type.String()], { default: [7, 'hello'] }) Assert.IsEqual(Value.Create(T), [7, 'hello']) }) it('Should create default elements', () => { const T = Type.Tuple([Type.Number({ default: 7 }), Type.String({ default: 'hello' })]) Assert.IsEqual(Value.Create(T), [7, 'hello']) }) it('Should create default by overriding elements', () => { const T = Type.Tuple([Type.Number({ default: 7 }), Type.String({ default: 'hello' })], { default: [32, 'world'] }) Assert.IsEqual(Value.Create(T), [32, 'world']) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/uint8array.ts000066400000000000000000000025101505437577000257550ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Uint8Array', () => { it('Should create value', () => { const T = Type.Uint8Array() const value = Value.Create(T) Assert.IsInstanceOf(value, Uint8Array) Assert.IsEqual(value.length, 0) }) it('Should create default', () => { const T = Type.Uint8Array({ default: new Uint8Array([0, 1, 2, 3]) }) const value = Value.Create(T) Assert.IsInstanceOf(value, Uint8Array) Assert.IsEqual(value.length, 4) Assert.IsEqual([value[0], value[1], value[2], value[3]], [0, 1, 2, 3]) }) it('Should create with minByteLength', () => { const T = Type.Uint8Array({ minByteLength: 4 }) const value = Value.Create(T) Assert.IsInstanceOf(value, Uint8Array) Assert.IsEqual(value.length, 4) Assert.IsEqual([value[0], value[1], value[2], value[3]], [0, 0, 0, 0]) }) it('Should create value nested', () => { const T = Type.Object({ value: Type.Uint8Array() }) Assert.IsEqual(Value.Create(T), { value: new Uint8Array() }) }) it('Should create default nested', () => { const T = Type.Object({ value: Type.Date({ default: new Uint8Array([1, 2, 3, 4]) }) }) Assert.IsEqual(Value.Create(T), { value: new Uint8Array([1, 2, 3, 4]) }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/undefined.ts000066400000000000000000000007071505437577000256160ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Undefined', () => { it('Should create value', () => { const T = Type.Undefined() Assert.IsEqual(Value.Create(T), undefined) }) it('Should create value from default value', () => { const T = Type.Undefined({ default: 'hello' }) Assert.IsEqual(Value.Create(T), 'hello') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/union.ts000066400000000000000000000022761505437577000250100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Union', () => { it('Should create union Object', () => { const A = Type.Object({ type: Type.Literal('A'), x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const B = Type.Object({ type: Type.Literal('B'), x: Type.String(), y: Type.String(), z: Type.String(), }) const T = Type.Union([A, B]) Assert.IsEqual(Value.Create(T), { type: 'A', x: 0, y: 0, z: 0, }) }) it('Should create union Null', () => { const A = Type.Null() const B = Type.Object({ type: Type.Literal('B'), x: Type.String(), y: Type.String(), z: Type.String(), }) const T = Type.Union([A, B]) Assert.IsEqual(Value.Create(T), null) }) it('Should create union Array', () => { const A = Type.Array(Type.String()) const B = Type.Object({ type: Type.Literal('B'), x: Type.String(), y: Type.String(), z: Type.String(), }) const T = Type.Union([A, B]) Assert.IsEqual(Value.Create(T), []) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/unknown.ts000066400000000000000000000006351505437577000253540ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Unknown', () => { it('Should create value', () => { const T = Type.Unknown() Assert.IsEqual(Value.Create(T), {}) }) it('Should create default', () => { const T = Type.Unknown({ default: 1 }) Assert.IsEqual(Value.Create(T), 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/create/void.ts000066400000000000000000000006701505437577000246150ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Void', () => { it('Should create value', () => { const T = Type.Void() Assert.IsEqual(Value.Create(T), undefined) }) it('Should create value from default value', () => { const T = Type.Void({ default: 'hello' }) Assert.IsEqual(Value.Create(T), 'hello') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/000077500000000000000000000000001505437577000234625ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/default/_deferred.ts000066400000000000000000000005131505437577000257500ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Deferred', () => { it('Should use deferred value', () => { const T = Type.Any({ default: () => 1 }) const R = Value.Default(T, 1) Assert.IsEqual(R, 1) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/any.ts000066400000000000000000000007171505437577000246260ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Any', () => { it('Should use default', () => { const T = Type.Any({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Any({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/array.ts000066400000000000000000000045101505437577000251500ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Array', () => { it('Should use default', () => { const T = Type.Array(Type.Number(), { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Array(Type.Number(), { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // Elements // ---------------------------------------------------------------- it('Should use default on elements', () => { const T = Type.Array(Type.Number({ default: 2 })) const R = Value.Default(T, [1, undefined, 3]) Assert.IsEqual(R, [1, 2, 3]) }) // ---------------------------------------------------------------- // Elements // ---------------------------------------------------------------- it('Should should retain array and only initialize undefined elements', () => { const T = Type.Array(Type.Literal('hello', { default: 'hello' })) const R = Value.Default(T, [1, undefined, 3]) Assert.IsEqual(R, [1, 'hello', 3]) }) // ---------------------------------------------------------------- // https://github.com/ubiquity-os-marketplace/command-start-stop/pull/86 // ---------------------------------------------------------------- it('Should retain arrays 1', () => { const U = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C'), Type.Literal('D')], { default: 'A' }) const T = Type.Array(U, { default: ['A', 'B', 'C', 'D'], uniqueItems: true }) Assert.IsEqual(Value.Default(T, undefined), ['A', 'B', 'C', 'D']) Assert.IsEqual(Value.Default(T, []), []) Assert.IsEqual(Value.Default(T, ['A']), ['A']) // initialize undefined element Assert.IsEqual(Value.Default(T, [undefined, 'B', 'C', 'D']), ['A', 'B', 'C', 'D']) }) it('Should retain arrays 2', () => { const U = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C'), Type.Literal('D')], { default: 'A' }) // undefined first element initialized by union default const T = Type.Array(U, { default: [undefined, 'B', 'C', 'D'], uniqueItems: true }) Assert.IsEqual(Value.Default(T, undefined), ['A', 'B', 'C', 'D']) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/async-iterator.ts000066400000000000000000000010131505437577000267710ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/AsyncIterator', () => { it('Should use default', () => { const T = Type.AsyncIterator(Type.Number(), { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.AsyncIterator(Type.Number(), { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/bigint.ts000066400000000000000000000007301505437577000253060ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/BigInt', () => { it('Should use default', () => { const T = Type.BigInt({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.BigInt({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/boolean.ts000066400000000000000000000007331505437577000254540ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Boolean', () => { it('Should use default', () => { const T = Type.Boolean({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Boolean({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/composite.ts000066400000000000000000000011611505437577000260330ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Composite', () => { it('Should use default', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Composite([Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() })], { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/constructor.ts000066400000000000000000000010151505437577000264140ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Constructor', () => { it('Should use default', () => { const T = Type.Constructor([], Type.Number(), { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Constructor([], Type.Number(), { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/date.ts000066400000000000000000000023071505437577000247510ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Date', () => { it('Should use default', () => { const T = Type.Date({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Date({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1024 // ---------------------------------------------------------------- it('Should use value if Date is valid', () => { const T = Type.Date({ default: new Date(1) }) const R = Value.Default(T, new Date(2)) as Date Assert.IsEqual(R.getTime(), 2) }) it('Should use default if Date is undefined', () => { const T = Type.Date({ default: new Date(1) }) const R = Value.Default(T, undefined) as Date Assert.IsEqual(R.getTime(), 1) }) it('Should use value if Date is invalid', () => { const T = Type.Date({ default: new Date(1) }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/enum.ts000066400000000000000000000007321505437577000250000ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Enum', () => { it('Should use default', () => { const T = Type.Enum({}, { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Enum({}, { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/function.ts000066400000000000000000000010041505437577000256520ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Function', () => { it('Should use default', () => { const T = Type.Function([], Type.Number(), { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Function([], Type.Number(), { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/import.ts000066400000000000000000000223461505437577000253530ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type, CloneType } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Import', () => { it('Should use default', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { default: 1 }, ), }).Import('A') const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number(), y: Type.Number(), }, { default: 1 }, ), }).Import('A') const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // Construction // ---------------------------------------------------------------- it('Should should fully construct object 1', () => { const T = Type.Module({ A: Type.Object( { x: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { default: {} }, ), y: Type.Object( { x: Type.Number({ default: 3 }), y: Type.Number({ default: 4 }), }, { default: {} }, ), }, { default: {} }, ), }).Import('A') const R = Value.Default(T, undefined) Assert.IsEqual(R, { x: { x: 1, y: 2 }, y: { x: 3, y: 4 } }) }) it('Should should fully construct object 2', () => { const T = Type.Module({ A: Type.Object( { x: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { default: {} }, ), y: Type.Object( { x: Type.Number({ default: 3 }), y: Type.Number({ default: 4 }), }, { default: {} }, ), }, { default: {} }, ), }).Import('A') const R = Value.Default(T, { x: null }) Assert.IsEqual(R, { x: null, y: { x: 3, y: 4 } }) }) it('Should should fully construct object 3', () => { const T = Type.Module({ A: Type.Object( { x: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { default: {} }, ), y: Type.Object( { x: Type.Number({ default: 3 }), y: Type.Number({ default: 4 }), }, { default: {} }, ), }, { default: {} }, ), }).Import('A') const R = Value.Default(T, { x: { x: null, y: null } }) Assert.IsEqual(R, { x: { x: null, y: null }, y: { x: 3, y: 4 } }) }) // ---------------------------------------------------------------- // Properties // ---------------------------------------------------------------- it('Should use property defaults 1', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { default: 1 }, ), }).Import('A') const R = Value.Default(T, {}) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should use property defaults 2', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number(), y: Type.Number(), }), }).Import('A') const R = Value.Default(T, {}) Assert.IsEqual(R, {}) }) it('Should use property defaults 3', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number(), }), }).Import('A') const R = Value.Default(T, {}) Assert.IsEqual(R, { x: 1 }) }) it('Should use property defaults 4', () => { const T = Type.Module({ A: Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number(), }), }).Import('A') const R = Value.Default(T, { x: 3 }) Assert.IsEqual(R, { x: 3 }) }) // ---------------------------------------------------------------- // AdditionalProperties // ---------------------------------------------------------------- it('Should use additional property defaults 1', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { additionalProperties: Type.Number({ default: 3 }), }, ), }).Import('A') const R = Value.Default(T, {}) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should use additional property defaults 2', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { additionalProperties: Type.Number({ default: 3 }), }, ), }).Import('A') const R = Value.Default(T, { x: null, y: null, z: undefined }) Assert.IsEqual(R, { x: null, y: null, z: 3 }) }) it('Should use additional property defaults 3', () => { const T = Type.Module({ A: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { additionalProperties: Type.Number(), }, ), }).Import('A') const R = Value.Default(T, { x: null, y: null, z: undefined }) Assert.IsEqual(R, { x: null, y: null, z: undefined }) }) // ---------------------------------------------------------------- // Mutation // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/726 it('Should retain defaults on operation', () => { const A = Type.Module({ A: Type.Object({ a: Type.Object( { b: Type.Array(Type.String(), { default: [] }), }, { default: {} }, ), }), }).Import('A') const value = Value.Default(A, {}) Assert.IsEqual(value, { a: { b: [] } }) Assert.IsEqual(A.$defs.A.properties.a.default, {}) Assert.IsEqual(A.$defs.A.properties.a.properties.b.default, []) }) // https://github.com/sinclairzx81/typebox/issues/726 it('Should retain schematics on operation', () => { const A = Type.Module({ A: Type.Object({ a: Type.Object( { b: Type.Array(Type.String(), { default: [] }), }, { default: {} }, ), }), }).Import('A') const B = CloneType(A) Value.Default(A, {}) Assert.IsEqual(A, B) }) // ---------------------------------------------------------------- // Traveral: https://github.com/sinclairzx81/typebox/issues/962 // ---------------------------------------------------------------- it('Should traverse into an object 1 (initialize)', () => { const M = Type.Module({ Y: Type.Object({ y: Type.String({ default: 'y' }) }), X: Type.Object({ x: Type.Ref('Y') }), }) const Y = M.Import('Y') const X = M.Import('X') Assert.IsEqual(Value.Default(Y, {}), { y: 'y' }) Assert.IsEqual(Value.Default(X, { x: {} }), { x: { y: 'y' } }) }) it('Should traverse into an object 2 (retain)', () => { const M = Type.Module({ Y: Type.Object({ y: Type.String({ default: 'y' }) }), X: Type.Object({ x: Type.Ref('Y') }), }) const Y = M.Import('Y') const X = M.Import('X') Assert.IsEqual(Value.Default(X, { x: { y: 1 } }), { x: { y: 1 } }) }) it('Should traverse into an object 3 (ignore on undefined)', () => { const M = Type.Module({ Y: Type.Object({ y: Type.String({ default: 'y' }) }), X: Type.Object({ x: Type.Ref('Y') }), }) const Y = M.Import('Y') const X = M.Import('X') Assert.IsEqual(Value.Default(X, { x: undefined }), { x: undefined }) }) // ---------------------------------------------------------------- // Exterior Object Defaults // ---------------------------------------------------------------- it('Should default exterior into an object 1', () => { const X = Type.Module({ A: Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) }).Import('A') const R = Value.Default(X, undefined) Assert.IsEqual(R, { x: 1 }) }) it('Should default exterior into an object 2', () => { const X = Type.Module({ A: Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) }).Import('A') const R = Value.Default(X, {}) Assert.IsEqual(R, { x: 1 }) }) it('Should default exterior into an object 3', () => { const X = Type.Module({ A: Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) }).Import('A') const R = Value.Default(X, { y: 3 }) Assert.IsEqual(R, { y: 3, x: 1 }) }) it('Should default exterior into an object 4', () => { const X = Type.Module({ A: Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) }).Import('A') const R = Value.Default(X, { y: 3, x: 7 }) Assert.IsEqual(R, { y: 3, x: 7 }) }) it('Should default exterior into an object 5', () => { const X = Type.Module({ A: Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) }).Import('A') const R = Value.Default(X, { x: 2 }) Assert.IsEqual(R, { x: 2 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/index.ts000066400000000000000000000012651505437577000251450ustar00rootroot00000000000000import './_deferred' import './any' import './array' import './async-iterator' import './bigint' import './boolean' import './composite' import './constructor' import './date' import './enum' import './function' import './import' import './integer' import './intersect' import './iterator' import './keyof' import './kind' import './literal' import './never' import './not' import './null' import './number' import './object' import './promise' import './record' import './recursive' import './ref' import './regexp' import './string' import './symbol' import './template-literal' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/value/default/integer.ts000066400000000000000000000007331505437577000254720ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Integer', () => { it('Should use default', () => { const T = Type.Integer({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Integer({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/intersect.ts000066400000000000000000000067621505437577000260450ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Intersect', () => { it('Should use default', () => { const T = Type.Intersect([Type.Number(), Type.String()], { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Intersect([Type.Number(), Type.String()], { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // Intersected // ---------------------------------------------------------------- it('Should use default intersected 1', () => { const A = Type.Object({ a: Type.Number({ default: 1 }), }) const B = Type.Object({ b: Type.Number({ default: 2 }), }) const T = Type.Intersect([A, B]) const R = Value.Default(T, {}) Assert.IsEqual(R, { a: 1, b: 2 }) }) it('Should use default intersected 2', () => { const A = Type.Object({ a: Type.Number(), }) const B = Type.Object({ b: Type.Number(), }) const T = Type.Intersect([A, B]) const R = Value.Default(T, {}) Assert.IsEqual(R, {}) }) it('Should use default intersected 3', () => { const A = Type.Object({ a: Type.Number({ default: 1 }), }) const B = Type.Object({ b: Type.Number({ default: 2 }), }) const T = Type.Intersect([A, B]) const R = Value.Default(T, { a: 3 }) Assert.IsEqual(R, { a: 3, b: 2 }) }) it('Should use default intersected 4', () => { const A = Type.Object({ a: Type.Number({ default: 1 }), }) const B = Type.Object({ b: Type.Number({ default: 2 }), }) const T = Type.Intersect([A, B]) const R = Value.Default(T, { a: 4, b: 5 }) Assert.IsEqual(R, { a: 4, b: 5 }) }) it('Should use default intersected 5', () => { const A = Type.Object({ a: Type.Number({ default: 1 }), }) const B = Type.Number({ default: 2 }) const T = Type.Intersect([A, B]) const R = Value.Default(T, {}) Assert.IsEqual(R, { a: 1 }) }) it('Should use default intersected 6', () => { const A = Type.Number({ default: 2 }) const B = Type.Object({ a: Type.Number({ default: 1 }), }) const T = Type.Intersect([A, B]) const R = Value.Default(T, {}) Assert.IsEqual(R, { a: 1 }) }) // ---------------------------------------------------------------- // Intersected Deep // ---------------------------------------------------------------- it('Should use default intersected deep 1', () => { const A = Type.Object({ a: Type.Number({ default: 1 }) }) const B = Type.Object({ b: Type.Number({ default: 2 }) }) const C = Type.Object({ c: Type.Number({ default: 3 }) }) const D = Type.Object({ d: Type.Number({ default: 4 }) }) const T1 = Type.Intersect([A, B]) const T2 = Type.Intersect([C, D]) const T = Type.Intersect([T1, T2]) const R = Value.Default(T, {}) Assert.IsEqual(R, { a: 1, b: 2, c: 3, d: 4 }) }) it('Should use default intersected deep 2', () => { const A = Type.Object({ a: Type.Number({}) }) const B = Type.Object({ b: Type.Number({}) }) const C = Type.Object({ c: Type.Number({}) }) const D = Type.Object({ d: Type.Number({}) }) const T1 = Type.Intersect([A, B]) const T2 = Type.Intersect([C, D]) const T = Type.Intersect([T1, T2]) const R = Value.Default(T, {}) Assert.IsEqual(R, {}) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/iterator.ts000066400000000000000000000007741505437577000256730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Iterator', () => { it('Should use default', () => { const T = Type.Iterator(Type.Number(), { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Iterator(Type.Number(), { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/keyof.ts000066400000000000000000000010331505437577000251440ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/KeyOf', () => { it('Should use default', () => { const T = Type.KeyOf(Type.Object({ x: Type.Number() }), { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.KeyOf(Type.Object({ x: Type.Number() }), { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/kind.ts000066400000000000000000000010021505437577000247500ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type, Kind } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Kind', () => { it('Should use default', () => { const T = Type.Unsafe({ [Kind]: 'Unknown', default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Unsafe({ [Kind]: 'Unknown', default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/literal.ts000066400000000000000000000007511505437577000254710ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Literal', () => { it('Should use default', () => { const T = Type.Literal('foo', { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Literal('foo', { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/never.ts000066400000000000000000000007251505437577000251550ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Never', () => { it('Should use default', () => { const T = Type.Never({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Never({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/not.ts000066400000000000000000000007551505437577000246410ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Not', () => { it('Should use default', () => { const T = Type.Not(Type.String(), { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Not(Type.String(), { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/null.ts000066400000000000000000000007221505437577000250050ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Null', () => { it('Should use default', () => { const T = Type.Null({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Null({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/number.ts000066400000000000000000000007301505437577000253220ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Number', () => { it('Should use default', () => { const T = Type.Number({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Number({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/object.ts000066400000000000000000000177211505437577000253100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type, CloneType } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Object', () => { it('Should use default', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { default: 1 }, ) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Object( { x: Type.Number(), y: Type.Number(), }, { default: 1 }, ) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // Construction // ---------------------------------------------------------------- it('Should should fully construct object 1', () => { const T = Type.Object( { x: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { default: {} }, ), y: Type.Object( { x: Type.Number({ default: 3 }), y: Type.Number({ default: 4 }), }, { default: {} }, ), }, { default: {} }, ) const R = Value.Default(T, undefined) Assert.IsEqual(R, { x: { x: 1, y: 2 }, y: { x: 3, y: 4 } }) }) it('Should should fully construct object 2', () => { const T = Type.Object( { x: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { default: {} }, ), y: Type.Object( { x: Type.Number({ default: 3 }), y: Type.Number({ default: 4 }), }, { default: {} }, ), }, { default: {} }, ) const R = Value.Default(T, { x: null }) Assert.IsEqual(R, { x: null, y: { x: 3, y: 4 } }) }) it('Should should fully construct object 3', () => { const T = Type.Object( { x: Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { default: {} }, ), y: Type.Object( { x: Type.Number({ default: 3 }), y: Type.Number({ default: 4 }), }, { default: {} }, ), }, { default: {} }, ) const R = Value.Default(T, { x: { x: null, y: null } }) Assert.IsEqual(R, { x: { x: null, y: null }, y: { x: 3, y: 4 } }) }) // ---------------------------------------------------------------- // Properties // ---------------------------------------------------------------- it('Should use property defaults 1', () => { const T = Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { default: 1 }, ) const R = Value.Default(T, {}) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should use property defaults 2', () => { const T = Type.Object({ x: Type.Number(), y: Type.Number(), }) const R = Value.Default(T, {}) Assert.IsEqual(R, {}) }) it('Should use property defaults 3', () => { const T = Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number(), }) const R = Value.Default(T, {}) Assert.IsEqual(R, { x: 1 }) }) it('Should use property defaults 4', () => { const T = Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number(), }) const R = Value.Default(T, { x: 3 }) Assert.IsEqual(R, { x: 3 }) }) // ---------------------------------------------------------------- // AdditionalProperties // ---------------------------------------------------------------- it('Should use additional property defaults 1', () => { const T = Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { additionalProperties: Type.Number({ default: 3 }), }, ) const R = Value.Default(T, {}) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should use additional property defaults 2', () => { const T = Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { additionalProperties: Type.Number({ default: 3 }), }, ) const R = Value.Default(T, { x: null, y: null, z: undefined }) Assert.IsEqual(R, { x: null, y: null, z: 3 }) }) it('Should use additional property defaults 3', () => { const T = Type.Object( { x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }, { additionalProperties: Type.Number(), }, ) const R = Value.Default(T, { x: null, y: null, z: undefined }) Assert.IsEqual(R, { x: null, y: null, z: undefined }) }) // ---------------------------------------------------------------- // Mutation // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/726 it('Should retain defaults on operation', () => { const A = Type.Object({ a: Type.Object( { b: Type.Array(Type.String(), { default: [] }), }, { default: {} }, ), }) const value = Value.Default(A, {}) Assert.IsEqual(value, { a: { b: [] } }) Assert.IsEqual(A.properties.a.default, {}) Assert.IsEqual(A.properties.a.properties.b.default, []) }) // https://github.com/sinclairzx81/typebox/issues/726 it('Should retain schematics on operation', () => { const A = Type.Object({ a: Type.Object( { b: Type.Array(Type.String(), { default: [] }), }, { default: {} }, ), }) const B = CloneType(A) Value.Default(A, {}) Assert.IsEqual(A, B) }) // ---------------------------------------------------------------- // Traveral: https://github.com/sinclairzx81/typebox/issues/962 // ---------------------------------------------------------------- it('Should traverse into an object 1 (initialize)', () => { const Y = Type.Object({ y: Type.String({ default: 'y' }) }) const X = Type.Object({ x: Y }) Assert.IsEqual(Value.Default(Y, {}), { y: 'y' }) Assert.IsEqual(Value.Default(X, { x: {} }), { x: { y: 'y' } }) }) it('Should traverse into an object 2 (retain)', () => { const Y = Type.Object({ y: Type.String({ default: 'y' }) }) const X = Type.Object({ x: Y }) Assert.IsEqual(Value.Default(X, { x: { y: 1 } }), { x: { y: 1 } }) }) it('Should traverse into an object 3 (ignore on undefined)', () => { const Y = Type.Object({ y: Type.String({ default: 'y' }) }) const X = Type.Object({ x: Y }) Assert.IsEqual(Value.Default(X, { x: undefined }), { x: undefined }) }) // ---------------------------------------------------------------- // Exterior Object Defaults // ---------------------------------------------------------------- it('Should default exterior into an object 1', () => { const X = Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) const R = Value.Default(X, undefined) Assert.IsEqual(R, { x: 1 }) }) it('Should default exterior into an object 2', () => { const X = Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) const R = Value.Default(X, {}) Assert.IsEqual(R, { x: 1 }) }) it('Should default exterior into an object 3', () => { const X = Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) const R = Value.Default(X, { y: 3 }) Assert.IsEqual(R, { y: 3, x: 1 }) }) it('Should default exterior into an object 4', () => { const X = Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) const R = Value.Default(X, { y: 3, x: 7 }) Assert.IsEqual(R, { y: 3, x: 7 }) }) it('Should default exterior into an object 5', () => { const X = Type.Object({ x: Type.String({ default: 1 }) }, { default: {} }) const R = Value.Default(X, { x: 2 }) Assert.IsEqual(R, { x: 2 }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/promise.ts000066400000000000000000000007231505437577000255120ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Promise', () => { it('Should use default', () => { const T = Type.Any({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Any({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/record.ts000066400000000000000000000051401505437577000253100ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Record', () => { it('Should use default', () => { const T = Type.Record(Type.String(), Type.Number(), { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Record(Type.String(), Type.Number(), { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // // ---------------------------------------------------------------- // // Properties // // ---------------------------------------------------------------- it('Should use property defaults 1', () => { const T = Type.Record(Type.Number(), Type.Number({ default: 1 })) const R = Value.Default(T, { 0: undefined }) Assert.IsEqual(R, { 0: 1 }) }) it('Should use property defaults 2', () => { const T = Type.Record(Type.Number(), Type.Number({ default: 1 })) const R = Value.Default(T, { 0: null }) Assert.IsEqual(R, { 0: null }) }) it('Should use property defaults 3', () => { const T = Type.Record(Type.Number(), Type.Number({ default: 1 })) const R = Value.Default(T, { a: undefined }) Assert.IsEqual(R, { a: undefined }) }) it('Should use property defaults 4', () => { const T = Type.Record(Type.Number(), Type.Number({ default: 1 })) const R = Value.Default(T, { 0: undefined }) Assert.IsEqual(R, { 0: 1 }) }) it('Should use property defaults 5', () => { const T = Type.Record(Type.Number(), Type.Number()) const R = Value.Default(T, { 0: undefined }) Assert.IsEqual(R, { 0: undefined }) }) it('Should use property defaults 6', () => { const T = Type.Record(Type.Number(), Type.Number({ default: 1 })) const R = Value.Default(T, {}) Assert.IsEqual(R, {}) }) // ---------------------------------------------------------------- // Additional Properties // ---------------------------------------------------------------- it('Should use additional property defaults 1', () => { const T = Type.Record(Type.Number(), Type.Number({ default: 1 }), { additionalProperties: Type.Number({ default: 3 }), }) const R = Value.Default(T, { 0: undefined, a: undefined }) Assert.IsEqual(R, { 0: 1, a: 3 }) }) it('Should use additional property defaults 2', () => { const T = Type.Record(Type.Number(), Type.Number({ default: 1 }), { additionalProperties: Type.Number(), }) const R = Value.Default(T, { 0: undefined, a: undefined }) Assert.IsEqual(R, { 0: 1, a: undefined }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/recursive.ts000066400000000000000000000045541505437577000260510ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { TSchema, Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' // prettier-ignore describe('value/default/Recursive', () => { it('Should use default', () => { const T = Type.Recursive((This) => Type.Object({ nodes: Type.Array(This) }, { default: 1 })) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Recursive((This) => Type.Object({ nodes: Type.Array(This) }, { default: 1 })) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // Recursive // ---------------------------------------------------------------- it('Should use default recursive values', () => { const T = Type.Recursive((This) => Type.Object({ id: Type.String({ default: 1 }), nodes: Type.Array(This, { default: [] }) // need this })) const R = Value.Default(T, { nodes: [{ nodes: [{ nodes: [{ id: null }] }, { nodes: [{ id: null }] }] }] }) Assert.IsEqual(R, { nodes: [{ nodes: [{ nodes: [{ id: null, nodes: [] }], id: 1 }, { nodes: [{ id: null, nodes: [] }], id: 1 }], id: 1 }], id: 1 }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1010 // ---------------------------------------------------------------- it('Should default Recursive Union', () => { const Binary = (node: Node) => Type.Object({ type: Type.Literal('Binary'), left: node, right: node }) const Node = Type.Object({ type: Type.Literal('Node'), value: Type.String({ default: 'X' }) }) const Expr = Type.Recursive(This => Type.Union([Binary(This), Node])) const R = Value.Default(Expr, { type: 'Binary', left: { type: 'Node' }, right: { type: 'Node' } }) Assert.IsEqual(R, { type: 'Binary', left: { type: 'Node', value: 'X' }, right: { type: 'Node', value: 'X' } }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/ref.ts000066400000000000000000000021521505437577000246060ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Ref', () => { it('Should use default', () => { const A = Type.String({ $id: 'A' }) const T = Type.Ref('A', { default: 1 }) const R = Value.Default(T, [A], undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const A = Type.String({ $id: 'A' }) const T = Type.Ref('A', { default: 1 }) const R = Value.Default(T, [A], null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // Foreign // ---------------------------------------------------------------- it('Should use default on foreign value', () => { const A = Type.String({ $id: 'A', default: 1 }) const T = Type.Ref('A') const R = Value.Default(T, [A], undefined) Assert.IsEqual(R, 1) }) it('Should use value on foreign value', () => { const A = Type.String({ $id: 'A', default: 1 }) const T = Type.Ref('A') const R = Value.Default(T, [A], null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/regexp.ts000066400000000000000000000007401505437577000253250ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/RegExp', () => { it('Should use default', () => { const T = Type.RegExp('', { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.RegExp('', { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/string.ts000066400000000000000000000007301505437577000253400ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/String', () => { it('Should use default', () => { const T = Type.String({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.String({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/symbol.ts000066400000000000000000000007301505437577000253370ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Symbol', () => { it('Should use default', () => { const T = Type.Symbol({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Symbol({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/template-literal.ts000066400000000000000000000010051505437577000272730ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/TemplateLiteral', () => { it('Should use default', () => { const T = Type.TemplateLiteral('hello', { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.TemplateLiteral('hello', { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/tuple.ts000066400000000000000000000033531505437577000251670ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Tuple', () => { it('Should use default', () => { const T = Type.Tuple([Type.Number(), Type.Number()], { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Tuple([Type.Number(), Type.Number()], { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // Elements // ---------------------------------------------------------------- it('Should use default elements 1', () => { const T = Type.Tuple([Type.Number({ default: 1 }), Type.Number({ default: 2 })], { default: [] }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) it('Should use default elements 2', () => { const T = Type.Tuple([Type.Number({ default: 1 }), Type.Number({ default: 2 })], { default: [] }) const R = Value.Default(T, undefined) Assert.IsEqual(R, [1, 2]) }) it('Should use default elements 3', () => { const T = Type.Tuple([Type.Number({ default: 1 }), Type.Number({ default: 2 })], { default: [] }) const R = Value.Default(T, [4, 5, 6]) Assert.IsEqual(R, [4, 5, 6]) }) it('Should use default elements 4', () => { const T = Type.Tuple([Type.Number({ default: 1 }), Type.Number({ default: 2 })]) const R = Value.Default(T, [4, 5, 6]) Assert.IsEqual(R, [4, 5, 6]) }) it('Should use default elements 5', () => { const T = Type.Tuple([Type.Number({ default: 1 }), Type.Number({ default: 2 })]) const R = Value.Default(T, [4]) Assert.IsEqual(R, [4, 2]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/uint8array.ts000066400000000000000000000007441505437577000261450ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Uint8Array', () => { it('Should use default', () => { const T = Type.Uint8Array({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Uint8Array({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/undefined.ts000066400000000000000000000007411505437577000257750ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Undefined', () => { it('Should use default', () => { const T = Type.Undefined({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Undefined({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/union.ts000066400000000000000000000101031505437577000251550ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type, Kind, TypeRegistry } from '@sinclair/typebox' import { Assert } from '../../assert/index' // prettier-ignore describe('value/default/Union', () => { it('Should use default', () => { const T = Type.Union([Type.Number(), Type.String()], { default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Union([Type.Number(), Type.String()], { default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) // ---------------------------------------------------------------- // Interior // ---------------------------------------------------------------- it('Should default interior 1', () => { const T = Type.Union([ Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }), Type.String({ default: 'hello' }), ]) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) it('Should default interior 2', () => { const T = Type.Union([ Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }), Type.String({ default: 'hello' }), ]) const R = Value.Default(T, undefined) Assert.IsEqual(R, 'hello') }) it('Should default interior 3', () => { const T = Type.Union([ Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }), Type.String({ default: 'hello' }), ]) const R = Value.Default(T, 'world') Assert.IsEqual(R, 'world') }) it('Should default interior 4', () => { const T = Type.Union([ Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }), Type.String({ default: 'hello' }), ]) const R = Value.Default(T, {}) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should default interior 5', () => { const T = Type.Union([ Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }), Type.String({ default: 'hello' }), ]) const R = Value.Default(T, { x: 3 }) Assert.IsEqual(R, { x: 3, y: 2 }) }) it('Should default interior 6', () => { const T = Type.Union([ Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }), Type.String({ default: 'hello' }), ]) const R = Value.Default(T, { x: 3, y: 4 }) Assert.IsEqual(R, { x: 3, y: 4 }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/993 // ---------------------------------------------------------------- it('Should return the original value if no schemas match (cloned interior variant)', async () => { const T = Type.Union([ Type.Tuple([Type.Number(), Type.Number()]), Type.Array(Type.Number()) ]) const value = ['hello'] const R = Value.Default(T, value) Assert.IsTrue(R === value) }) // ---------------------------------------------------------------- // Interior Unsafe // ---------------------------------------------------------------- it('Should default interior unsafe 1', () => { TypeRegistry.Set('DefaultUnsafe', (schema, value) => typeof value === 'string') const T = Type.Union([ Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }), Type.Unsafe({ [Kind]: 'DefaultUnsafe', default: 'hello' }), ]) const R = Value.Default(T, undefined) Assert.IsEqual(R, 'hello') TypeRegistry.Delete('DefaultUnsafe') }) it('Should default interior unsafe 2', () => { TypeRegistry.Set('DefaultUnsafe', (schema, value) => typeof value === 'string') const T = Type.Union([ Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }), }), Type.Unsafe({ [Kind]: 'DefaultUnsafe', default: 'hello' }), ]) const R = Value.Default(T, 'world') Assert.IsEqual(R, 'world') TypeRegistry.Delete('DefaultUnsafe') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/unknown.ts000066400000000000000000000007331505437577000255340ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Unknown', () => { it('Should use default', () => { const T = Type.Unknown({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Unknown({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/default/void.ts000066400000000000000000000007221505437577000247740ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/default/Void', () => { it('Should use default', () => { const T = Type.Void({ default: 1 }) const R = Value.Default(T, undefined) Assert.IsEqual(R, 1) }) it('Should use value', () => { const T = Type.Void({ default: 1 }) const R = Value.Default(T, null) Assert.IsEqual(R, null) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/delta/000077500000000000000000000000001505437577000231275ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/delta/diff.ts000066400000000000000000000313111505437577000244060ustar00rootroot00000000000000import { Value, Edit } from '@sinclair/typebox/value' import { Assert } from '../../assert/index' // ----------------------------------------------------------------- // Diff Factory // ----------------------------------------------------------------- function Update(path: string, value: unknown): Edit { return { type: 'update', path, value } as any } function Insert(path: string, value: unknown): Edit { return { type: 'insert', path, value } as any } function Delete(path: string): Edit { return { type: 'delete', path } as any } describe('value/delta/Diff', () => { // ---------------------------------------------------- // Null // ---------------------------------------------------- it('Should diff NULL null to null', () => { const A = null const B = null const D = Value.Diff(A, B) const E = [] as Edit[] Assert.IsEqual(D, E) }) it('Should diff NULL undefined to undefined', () => { const A = undefined const B = undefined const D = Value.Diff(A, B) const E = [] as Edit[] Assert.IsEqual(D, E) }) it('Should diff NULL string to string', () => { const A = 'hello' const B = 'hello' const D = Value.Diff(A, B) const E = [] as Edit[] Assert.IsEqual(D, E) }) it('Should diff NULL number to number', () => { const A = 1 const B = 1 const D = Value.Diff(A, B) const E = [] as Edit[] Assert.IsEqual(D, E) }) it('Should diff NULL boolean to boolean', () => { const A = true const B = true const D = Value.Diff(A, B) const E = [] as Edit[] Assert.IsEqual(D, E) }) it('Should diff NULL symbol to symbol', () => { const S = Symbol('A') const A = S const B = S const D = Value.Diff(A, B) const E = [] as Edit[] Assert.IsEqual(D, E) }) it('Should diff NULL object to object', () => { const A = { x: 1, y: 2, z: 3 } const B = { x: 1, y: 2, z: 3 } const D = Value.Diff(A, B) const E = [] as Edit[] Assert.IsEqual(D, E) }) it('Should diff NULL array to array', () => { const A = [1, 2, 3] const B = [1, 2, 3] const D = Value.Diff(A, B) const E = [] as Edit[] Assert.IsEqual(D, E) }) // ---------------------------------------------------- // Type Change Root // ---------------------------------------------------- it('Should diff TYPE change number to null', () => { const A = 1 const B = null const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff TYPE change null to undefined', () => { const A = null const B = undefined const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff TYPE change null to number', () => { const A = null const B = 1 const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff TYPE change null to boolean', () => { const A = null const B = true const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff TYPE change null to string', () => { const A = null const B = 'hello' const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff TYPE change null to symbol', () => { const A = null const B = Symbol('A') const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff TYPE change null to object', () => { const A = null const B = { x: 1, y: 1, z: 1 } const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff TYPE change null to array', () => { const A = null const B = [1, 2, 3] const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) // ---------------------------------------------------- // Value Change Root // ---------------------------------------------------- it('Should diff VALUE change number', () => { const A = 1 const B = 2 const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff VALUE change boolean', () => { const A = false const B = true const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff VALUE change string', () => { const A = 'hello' const B = 'world' const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) it('Should diff VALUE change symbol', () => { const A = Symbol('A') const B = Symbol('B') const D = Value.Diff(A, B) const E = [Update('', B)] Assert.IsEqual(D, E) }) // ---------------------------------------------------- // Array // ---------------------------------------------------- it('Should diff ELEMENT update', () => { const A = [1, 2, 3, 4] const B = [1, 2, 3, 9] const D = Value.Diff(A, B) const E = [Update('/3', 9)] Assert.IsEqual(D, E) }) it('Should diff ELEMENT push', () => { const A = [1, 2, 3, 4] const B = [1, 2, 3, 4, 5] const D = Value.Diff(A, B) const E = [Insert('/4', 5)] Assert.IsEqual(D, E) }) it('Should diff ELEMENT push twice', () => { const A = [1, 2, 3, 4] const B = [1, 2, 3, 4, 5, 6] const D = Value.Diff(A, B) const E = [Insert('/4', 5), Insert('/5', 6)] Assert.IsEqual(D, E) }) it('Should diff ELEMENT pop', () => { const A = [1, 2, 3, 4] const B = [1, 2, 3] const D = Value.Diff(A, B) const E = [Delete('/3')] Assert.IsEqual(D, E) }) it('Should diff ELEMENT pop twice', () => { const A = [1, 2, 3, 4] const B = [1, 2] const D = Value.Diff(A, B) const E = [Delete('/3'), Delete('/2')] Assert.IsEqual(D, E) }) it('Should diff ELEMENT unshift', () => { const A = [1, 2, 3, 4] const B = [2, 3, 4] const D = Value.Diff(A, B) const E = [Update('/0', 2), Update('/1', 3), Update('/2', 4), Delete('/3')] Assert.IsEqual(D, E) }) it('Should diff ELEMENT unshift twice', () => { const A = [1, 2, 3, 4] const B = [3, 4] const D = Value.Diff(A, B) const E = [Update('/0', 3), Update('/1', 4), Delete('/3'), Delete('/2')] Assert.IsEqual(D, E) }) // ---------------------------------------------------- // Object // ---------------------------------------------------- it('Should diff PROPERTY insert', () => { const A = { x: 1, y: 1 } const B = { x: 1, y: 1, z: 1 } const D = Value.Diff(A, B) const E = [Insert('/z', 1)] Assert.IsEqual(D, E) }) it('Should diff PROPERTY delete', () => { const A = { x: 1, y: 1, z: 1 } const B = { x: 1, y: 1 } const D = Value.Diff(A, B) const E = [Delete('/z')] Assert.IsEqual(D, E) }) it('Should diff PROPERTY update', () => { const A = { x: 1, y: 1, z: 1 } const B = { x: 1, y: 1, z: 2 } const D = Value.Diff(A, B) const E = [Update('/z', 2)] Assert.IsEqual(D, E) }) it('Should diff PROPERTY all values', () => { const A = { x: 1, y: 1, z: 1 } const B = { x: 2, y: 2, z: 2 } const D = Value.Diff(A, B) const E = [Update('/x', 2), Update('/y', 2), Update('/z', 2)] Assert.IsEqual(D, E) }) it('Should diff PROPERTY all delete, all insert', () => { const A = { x: 1, y: 1, z: 1 } const B = { a: 2, b: 2, c: 2 } const D = Value.Diff(A, B) const E = [Insert('/a', 2), Insert('/b', 2), Insert('/c', 2), Delete('/x'), Delete('/y'), Delete('/z')] Assert.IsEqual(D, E) }) it('Should diff PROPERTY insert, update, and delete order preserved', () => { const A = { x: 1, y: 1, z: 1, w: 1 } const B = { a: 2, b: 2, c: 2, w: 2 } const D = Value.Diff(A, B) const E = [Insert('/a', 2), Insert('/b', 2), Insert('/c', 2), Update('/w', 2), Delete('/x'), Delete('/y'), Delete('/z')] Assert.IsEqual(D, E) }) // ---------------------------------------------------- // Object Nested // ---------------------------------------------------- it('Should diff NESTED OBJECT diff type change update', () => { const A = { v: 1 } const B = { v: { x: 1, y: 1, z: 1 } } const D = Value.Diff(A, B) const E = [Update('/v', B.v)] Assert.IsEqual(D, E) }) it('Should diff NESTED OBJECT diff value change update', () => { const A = { v: 1 } const B = { v: 2 } const D = Value.Diff(A, B) const E = [Update('/v', B.v)] Assert.IsEqual(D, E) }) it('Should diff NESTED OBJECT diff partial property update', () => { const A = { v: { x: 1, y: 1, z: 1 } } const B = { v: { x: 2, y: 2, z: 2 } } const D = Value.Diff(A, B) const E = [Update('/v/x', B.v.x), Update('/v/y', B.v.y), Update('/v/z', B.v.z)] Assert.IsEqual(D, E) }) it('Should diff NESTED OBJECT diff partial property insert', () => { const A = { v: { x: 1, y: 1, z: 1 } } const B = { v: { x: 1, y: 1, z: 1, w: 1 } } const D = Value.Diff(A, B) const E = [Insert('/v/w', B.v.w)] Assert.IsEqual(D, E) }) it('Should diff NESTED OBJECT diff partial property delete', () => { const A = { v: { x: 1, y: 1, z: 1 } } const B = { v: { x: 1, y: 1 } } const D = Value.Diff(A, B) const E = [Delete('/v/z')] Assert.IsEqual(D, E) }) it('Should diff NESTED OBJECT ordered diff - update, insert and delete', () => { const A = { v: { x: 1, y: 1 } } const B = { v: { x: 2, w: 2 } } const D = Value.Diff(A, B) const E = [Insert('/v/w', B.v.w), Update('/v/x', B.v.x), Delete('/v/y')] Assert.IsEqual(D, E) }) // ---------------------------------------------------- // Array Nested // ---------------------------------------------------- it('Should diff NESTED ARRAY object diff type change update', () => { const A = [{ v: 1 }] const B = [{ v: { x: 1, y: 1, z: 1 } }] const D = Value.Diff(A, B) const E = [Update('/0/v', B[0].v)] Assert.IsEqual(D, E) }) it('Should diff NESTED ARRAY object diff value change update', () => { const A = [{ v: 1 }] const B = [{ v: 2 }] const D = Value.Diff(A, B) const E = [Update('/0/v', B[0].v)] Assert.IsEqual(D, E) }) it('Should diff NESTED ARRAY object diff partial property update', () => { const A = [{ v: { x: 1, y: 1, z: 1 } }] const B = [{ v: { x: 2, y: 2, z: 2 } }] const D = Value.Diff(A, B) const E = [Update('/0/v/x', B[0].v.x), Update('/0/v/y', B[0].v.y), Update('/0/v/z', B[0].v.z)] Assert.IsEqual(D, E) }) it('Should diff NESTED ARRAY object diff partial property insert', () => { const A = [{ v: { x: 1, y: 1, z: 1 } }] const B = [{ v: { x: 1, y: 1, z: 1, w: 1 } }] const D = Value.Diff(A, B) const E = [Insert('/0/v/w', B[0].v.w)] Assert.IsEqual(D, E) }) it('Should diff NESTED ARRAY object diff partial property delete', () => { const A = [{ v: { x: 1, y: 1, z: 1 } }] const B = [{ v: { x: 1, y: 1 } }] const D = Value.Diff(A, B) const E = [Delete('/0/v/z')] Assert.IsEqual(D, E) }) it('Should diff NESTED ARRAY insert update and delete order preserved', () => { const A = [{ v: { x: 1, y: 1 } }] const B = [{ v: { x: 2, w: 2 } }] const D = Value.Diff(A, B) const E = [Insert('/0/v/w', B[0].v.w), Update('/0/v/x', B[0].v.x), Delete('/0/v/y')] Assert.IsEqual(D, E) }) it('Should throw if attempting to diff a current value with symbol key', () => { const A = [{ [Symbol('A')]: 1, v: { x: 1, y: 1 } }] const B = [{ v: { x: 2, w: 2 } }] Assert.Throws(() => Value.Diff(A, B)) }) it('Should throw if attempting to diff a next value with symbol key', () => { const A = [{ v: { x: 1, y: 1 } }] const B = [{ [Symbol('A')]: 1, v: { x: 2, w: 2 } }] Assert.Throws(() => Value.Diff(A, B)) }) it('Should diff a Uint8Array (same size)', () => { const A = new Uint8Array([0, 1, 2, 3]) const B = new Uint8Array([0, 9, 2, 9]) const D = Value.Diff(A, B) const E = [Update('/1', 9), Update('/3', 9)] Assert.IsEqual(D, E) }) it('Should diff a Uint8Array (less than requires full update)', () => { const A = new Uint8Array([0, 1, 2, 3]) const B = new Uint8Array([0, 9, 2]) const D = Value.Diff(A, B) const E = [Update('', new Uint8Array([0, 9, 2]))] Assert.IsEqual(D, E) }) it('Should diff a Uint8Array (greater than requires full update)', () => { const A = new Uint8Array([0, 1, 2, 3]) const B = new Uint8Array([0, 9, 2, 3, 4]) const D = Value.Diff(A, B) const E = [Update('', new Uint8Array([0, 9, 2, 3, 4]))] Assert.IsEqual(D, E) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/937 // ---------------------------------------------------------------- it('Should generate no diff for undefined properties of current and next', () => { const A = { a: undefined } const B = { a: undefined } const D = Value.Diff(A, B) const E = [] as any Assert.IsEqual(D, E) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/delta/index.ts000066400000000000000000000000411505437577000246010ustar00rootroot00000000000000import './diff' import './patch' sinclairzx81-typebox-e0ec98c/test/runtime/value/delta/patch.ts000066400000000000000000000306511505437577000246030ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Assert } from '../../assert/index' describe('value/delta/Patch', () => { // ---------------------------------------------------- // Null // ---------------------------------------------------- it('Should patch NULL null to null', () => { const A = null const B = null const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NULL undefined to undefined', () => { const A = undefined const B = undefined const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NULL string to string', () => { const A = 'hello' const B = 'hello' const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NULL number to number', () => { const A = 1 const B = 1 const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NULL boolean to boolean', () => { const A = true const B = true const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NULL symbol to symbol', () => { const S = Symbol('A') const A = S const B = S const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NULL object to object', () => { const A = { x: 1, y: 2, z: 3 } const B = { x: 1, y: 2, z: 3 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NULL array to array', () => { const A = [1, 2, 3] const B = [1, 2, 3] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) // ---------------------------------------------------- // Type Change Root // ---------------------------------------------------- it('Should patch TYPE change number to null', () => { const A = 1 const B = null const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change null to undefined', () => { const A = null const B = undefined const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change null to number', () => { const A = null const B = 1 const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change null to boolean', () => { const A = null const B = true const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change null to string', () => { const A = null const B = 'hello' const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change null to symbol', () => { const A = null const B = Symbol('A') const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change null to object', () => { const A = null const B = { x: 1, y: 1, z: 1 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change null to array', () => { const A = null const B = [1, 2, 3] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change object to array', () => { const A = { x: 1, y: 2 } const B = [1, 2, 3] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch TYPE change array to object', () => { const A = [1, 2, 3] const B = { x: 1, y: 2 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) // ---------------------------------------------------- // Value Change Root // ---------------------------------------------------- it('Should patch VALUE change number', () => { const A = 1 const B = 2 const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch VALUE change boolean', () => { const A = false const B = true const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch VALUE change string', () => { const A = 'hello' const B = 'world' const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch VALUE change symbol', () => { const A = Symbol('A') const B = Symbol('B') const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) // ---------------------------------------------------- // Array // ---------------------------------------------------- it('Should patch ELEMENT update', () => { const A = [1, 2, 3, 4] const B = [1, 2, 3, 9] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch ELEMENT push', () => { const A = [1, 2, 3, 4] const B = [1, 2, 3, 4, 5] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch ELEMENT push twice', () => { const A = [1, 2, 3, 4] const B = [1, 2, 3, 4, 5, 6] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch ELEMENT pop', () => { const A = [1, 2, 3, 4] const B = [1, 2, 3] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch ELEMENT pop twice', () => { const A = [1, 2, 3, 4] const B = [1, 2] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch ELEMENT unshift', () => { const A = [1, 2, 3, 4] const B = [2, 3, 4] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch ELEMENT unshift twice', () => { const A = [1, 2, 3, 4] const B = [3, 4] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) // ---------------------------------------------------- // Object // ---------------------------------------------------- it('Should patch PROPERTY insert', () => { const A = { x: 1, y: 1 } const B = { x: 1, y: 1, z: 1 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch PROPERTY delete', () => { const A = { x: 1, y: 1, z: 1 } const B = { x: 1, y: 1 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch PROPERTY update', () => { const A = { x: 1, y: 1, z: 1 } const B = { x: 1, y: 1, z: 2 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch PROPERTY all values', () => { const A = { x: 1, y: 1, z: 1 } const B = { x: 2, y: 2, z: 2 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch PROPERTY all delete, all insert', () => { const A = { x: 1, y: 1, z: 1 } const B = { a: 2, b: 2, c: 2 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch PROPERTY update, insert and delete order preserved', () => { const A = { x: 1, y: 1, z: 1, w: 1 } const B = { a: 2, b: 2, c: 2, w: 2 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) // ---------------------------------------------------- // Object Nested // ---------------------------------------------------- it('Should patch NESTED OBJECT diff type change update', () => { const A = { v: 1 } const B = { v: { x: 1, y: 1, z: 1 } } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NESTED OBJECT diff value change update', () => { const A = { v: 1 } const B = { v: 2 } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NESTED OBJECT diff partial property update', () => { const A = { v: { x: 1, y: 1, z: 1 } } const B = { v: { x: 2, y: 2, z: 2 } } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NESTED OBJECT update, insert and delete order preserved', () => { const A = { v: { x: 1, y: 1 } } const B = { v: { x: 2, w: 2 } } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) // ---------------------------------------------------- // Array Nested // ---------------------------------------------------- it('Should patch NESTED ARRAY object diff type change update', () => { const A = [{ v: 1 }] const B = [{ v: { x: 1, y: 1, z: 1 } }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NESTED ARRAY object diff value change update', () => { const A = [{ v: 1 }] const B = [{ v: 2 }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NESTED ARRAY object diff partial property update', () => { const A = [{ v: { x: 1, y: 1, z: 1 } }] const B = [{ v: { x: 2, y: 2, z: 2 } }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NESTED ARRAY object diff partial property insert', () => { const A = [{ v: { x: 1, y: 1, z: 1 } }] const B = [{ v: { x: 1, y: 1, z: 1, w: 1 } }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NESTED ARRAY object diff partial property delete', () => { const A = [{ v: { x: 1, y: 1, z: 1 } }] const B = [{ v: { x: 1, y: 1 } }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch NESTED ARRAY object ordered diff - update, insert and delete', () => { const A = [{ v: { x: 1, y: 1 } }] const B = [{ v: { x: 2, w: 2 } }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch Uint8Array (same size)', () => { const A = [{ v: new Uint8Array([0, 1, 3]) }] const B = [{ v: new Uint8Array([0, 1, 2]) }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch Uint8Array (less than size)', () => { const A = [{ v: new Uint8Array([0, 1, 3]) }] const B = [{ v: new Uint8Array([0, 1]) }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) it('Should patch Uint8Array (greater than size)', () => { const A = [{ v: new Uint8Array([0, 1, 3]) }] const B = [{ v: new Uint8Array([0, 1, 2, 4]) }] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) // ---------------------------------------------------- // Mega Values // ---------------------------------------------------- it('Should patch MEGA value', () => { const A = [ { a: { x: 1, y: 1 } }, { b: { x: 1, y: 1, z: ['hello', 1, 2] } }, { c: { x: 1, y: 1 } }, { d: [ { a: 1 }, { a: 1 }, { a: 1 }, [ { a: { x: 1, y: 1 } }, { b: { x: 1, y: 1, z: ['hello', true, true, 2] } }, { c: { x: 1, y: 1 } }, { d: [{ a: 1 }, { a: 1 }, { a: 1 }], }, ], ], }, ] const B = [ 1, 2, { a: { x: 1, y: 'a' } }, { b: { x: true, y: 1, z: ['hello', true, true] } }, { c: { x: 1, y: 1 } }, { d: [ { a: 'hello' }, 1, 2, { a: 1 }, { a: 1 }, [ { a: { x: 1, y: 1 }, x: [1, 2, 3, 4] }, { c: { x: 1, y: 1 } }, { d: [{ a: 1 }, { a: 2 }, 'hello'], }, ], ], }, ] const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/937 // ---------------------------------------------------------------- it('Should generate no diff for undefined properties of current and next', () => { const A = { a: undefined } const B = { a: undefined } const D = Value.Diff(A, B) const P = Value.Patch(A, D) Assert.IsEqual(B, P) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/equal/000077500000000000000000000000001505437577000231455ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/equal/equal.ts000066400000000000000000000055371505437577000246360ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Assert } from '../../assert/index' describe('value/equal/Equal', () => { it('Should equal null value', () => { const R = Value.Equal(null, null) Assert.IsTrue(R) }) it('Should not equal null value', () => { const R = Value.Equal(null, 'null') Assert.IsFalse(R) }) it('Should equal undefined value', () => { const R = Value.Equal(undefined, undefined) Assert.IsTrue(R) }) it('Should not equal undefined value', () => { const R = Value.Equal(undefined, 'undefined') Assert.IsFalse(R) }) it('Should equal symbol value', () => { const S1 = Symbol.for('test') const S2 = Symbol.for('test') const R = Value.Equal(S1, S2) Assert.IsTrue(R) }) it('Should not equal symbol value', () => { const S1 = Symbol('test') const S2 = Symbol('test') const R = Value.Equal(S1, S2) Assert.IsFalse(R) }) it('Should equal string value', () => { const R = Value.Equal('hello', 'hello') Assert.IsTrue(R) }) it('Should not equal string value', () => { const R = Value.Equal('hello', 'world') Assert.IsFalse(R) }) it('Should equal number value', () => { const R = Value.Equal(1, 1) Assert.IsTrue(R) }) it('Should not equal number value', () => { const R = Value.Equal(1, 2) Assert.IsFalse(R) }) it('Should equal boolean value', () => { const R = Value.Equal(true, true) Assert.IsTrue(R) }) it('Should not equal boolean value', () => { const R = Value.Equal(true, false) Assert.IsFalse(R) }) it('Should equal array value', () => { const R = Value.Equal([0, 1, 2], [0, 1, 2]) Assert.IsTrue(R) }) it('Should not equal array value', () => { const R = Value.Equal([0, 1, 2], [0, 1, 3]) Assert.IsFalse(R) }) it('Should not equal array value with additional elements', () => { const R = Value.Equal([0, 1, 2], [0, 1, 2, 3]) Assert.IsFalse(R) }) it('Should equal object value', () => { const R = Value.Equal({ x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 3 }) Assert.IsTrue(R) }) it('Should not equal object value', () => { const R = Value.Equal({ x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 4 }) Assert.IsFalse(R) }) it('Should not equal object value with additional properties', () => { const R = Value.Equal({ x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 3, w: 1 }) Assert.IsFalse(R) }) it('Should equal typed array value', () => { const R = Value.Equal(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1, 2])) Assert.IsTrue(R) }) it('Should not equal typed array value', () => { const R = Value.Equal(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1, 3])) Assert.IsFalse(R) }) it('Should not equal typed array value with varying type', () => { const R = Value.Equal(new Uint8Array([0, 1, 2]), new Int8Array([0, 1, 2])) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/equal/index.ts000066400000000000000000000000211505437577000246150ustar00rootroot00000000000000import './equal' sinclairzx81-typebox-e0ec98c/test/runtime/value/guard/000077500000000000000000000000001505437577000231405ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/guard/guard.ts000066400000000000000000000377741505437577000246340ustar00rootroot00000000000000import { Assert } from '../../assert/index' import * as ValueGuard from '@sinclair/typebox/value' describe('value/guard/ValueGuard', () => { // ----------------------------------------------------- // IsNull // ----------------------------------------------------- it('Should guard Null 1', () => { const R = ValueGuard.IsNull(null) Assert.IsTrue(R) }) it('Should guard Null 2', () => { const R = ValueGuard.IsNull({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsUndefined // ----------------------------------------------------- it('Should guard Undefined 1', () => { const R = ValueGuard.IsUndefined(undefined) Assert.IsTrue(R) }) it('Should guard Undefined 2', () => { const R = ValueGuard.IsUndefined({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsBigInt // ----------------------------------------------------- it('Should guard BigInt 1', () => { const R = ValueGuard.IsBigInt(1n) Assert.IsTrue(R) }) it('Should guard BigInt 2', () => { const R = ValueGuard.IsBigInt(1) Assert.IsFalse(R) }) it('Should guard BigInt 3', () => { const R = ValueGuard.IsBigInt('123') Assert.IsFalse(R) }) // ----------------------------------------------------- // IsNumber // ----------------------------------------------------- it('Should guard Number 1', () => { const R = ValueGuard.IsNumber(1) Assert.IsTrue(R) }) it('Should guard Number 2', () => { const R = ValueGuard.IsNumber(3.14) Assert.IsTrue(R) }) it('Should guard Number 3', () => { const R = ValueGuard.IsNumber('') Assert.IsFalse(R) }) it('Should guard Number 4', () => { const R = ValueGuard.IsNumber(NaN) Assert.IsTrue(R) }) // ----------------------------------------------------- // IsString // ----------------------------------------------------- it('Should guard String 1', () => { const R = ValueGuard.IsString('') Assert.IsTrue(R) }) it('Should guard String 2', () => { const R = ValueGuard.IsString(true) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsBoolean // ----------------------------------------------------- it('Should guard Boolean 1', () => { const R = ValueGuard.IsBoolean(true) Assert.IsTrue(R) }) it('Should guard Boolean 2', () => { const R = ValueGuard.IsBoolean(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsObject // ----------------------------------------------------- it('Should guard Object 1', () => { const R = ValueGuard.IsObject({}) Assert.IsTrue(R) }) it('Should guard Object 2', () => { const R = ValueGuard.IsObject(1) Assert.IsFalse(R) }) it('Should guard Object 3', () => { const R = ValueGuard.IsObject([]) Assert.IsTrue(R) }) // ----------------------------------------------------- // IsArray // ----------------------------------------------------- it('Should guard Array 1', () => { const R = ValueGuard.IsArray([]) Assert.IsTrue(R) }) it('Should guard Array 2', () => { const R = ValueGuard.IsArray({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsAsyncIterator // ----------------------------------------------------- it('Should guard AsyncIterator 1', () => { const R = ValueGuard.IsAsyncIterator((async function* (): any {})()) Assert.IsTrue(R) }) it('Should guard AsyncIterator 2', () => { const R = ValueGuard.IsAsyncIterator((function* (): any {})()) Assert.IsFalse(R) }) // ----------------------------------------------------- // HasPropertyKey // ----------------------------------------------------- it('Should guard property key 1', () => { const O = { x: 10 } const R = ValueGuard.HasPropertyKey(O, 'x') Assert.IsTrue(R) }) it('Should guard property key 2', () => { const O = { x: 10 } const R = ValueGuard.HasPropertyKey(O, 'y') Assert.IsFalse(R) }) // ----------------------------------------------------- // IsDate // ----------------------------------------------------- it('Should guard Date 1', () => { const R = ValueGuard.IsDate(new Date()) Assert.IsTrue(R) }) it('Should guard Date 2', () => { const R = ValueGuard.IsDate({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsFunction // ----------------------------------------------------- it('Should guard Function 1', () => { const R = ValueGuard.IsFunction(function () {}) Assert.IsTrue(R) }) it('Should guard Function 2', () => { const R = ValueGuard.IsFunction({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsInteger // ----------------------------------------------------- it('Should guard Integer 1', () => { const R = ValueGuard.IsInteger(1) Assert.IsTrue(R) }) it('Should guard Integer 2', () => { const R = ValueGuard.IsInteger(3.14) Assert.IsFalse(R) }) it('Should guard Integer 3', () => { const R = ValueGuard.IsInteger(NaN) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsIterator // ----------------------------------------------------- it('Should guard Iterator 1', () => { const R = ValueGuard.IsIterator((function* () {})()) Assert.IsTrue(R) }) it('Should guard Iterator 2', () => { const R = ValueGuard.IsIterator({}) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsStandardObject // ----------------------------------------------------- it('Should guard StandardObject 1', () => { const R = ValueGuard.IsStandardObject({}) Assert.IsTrue(R) }) it('Should guard StandardObject 2', () => { const R = ValueGuard.IsStandardObject(1) Assert.IsFalse(R) }) it('Should guard StandardObject 3', () => { const R = ValueGuard.IsStandardObject([]) Assert.IsFalse(R) }) it('Should guard StandardObject 4', () => { const R = ValueGuard.IsStandardObject(new (class {})()) Assert.IsFalse(R) }) it('Should guard StandardObject 5', () => { const R = ValueGuard.IsStandardObject(Object.create(null)) Assert.IsTrue(R) }) // ----------------------------------------------------- // IsInstanceObject // ----------------------------------------------------- it('Should guard InstanceObject 1', () => { const R = ValueGuard.IsInstanceObject({}) Assert.IsFalse(R) }) it('Should guard InstanceObject 2', () => { const R = ValueGuard.IsInstanceObject(1) Assert.IsFalse(R) }) it('Should guard InstanceObject 3', () => { const R = ValueGuard.IsInstanceObject([]) Assert.IsFalse(R) }) it('Should guard InstanceObject 4', () => { const R = ValueGuard.IsInstanceObject(new (class {})()) Assert.IsTrue(R) }) // ----------------------------------------------------- // IsPromise // ----------------------------------------------------- it('Should guard Promise 1', () => { const R = ValueGuard.IsPromise(Promise.resolve(1)) Assert.IsTrue(R) }) it('Should guard Promise 2', () => { const R = ValueGuard.IsPromise(new (class {})()) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsSymbol // ----------------------------------------------------- it('Should guard Symbol 1', () => { const R = ValueGuard.IsSymbol(Symbol(1)) Assert.IsTrue(R) }) it('Should guard Symbol 2', () => { const R = ValueGuard.IsSymbol(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsTypedArray // ----------------------------------------------------- it('Should guard TypedArray 1', () => { const R = ValueGuard.IsTypedArray(new Uint8Array(1)) Assert.IsTrue(R) }) it('Should guard TypedArray 2', () => { const R = ValueGuard.IsTypedArray(new Float32Array(1)) Assert.IsTrue(R) }) it('Should guard TypedArray 3', () => { const R = ValueGuard.IsTypedArray(new ArrayBuffer(1)) Assert.IsFalse(R) }) it('Should guard TypedArray 4', () => { const R = ValueGuard.IsTypedArray(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsInt8Array // ----------------------------------------------------- it('Should guard Int8Array 1', () => { const R = ValueGuard.IsInt8Array(new Int8Array(1)) Assert.IsTrue(R) }) it('Should guard Int8Array 2', () => { const R = ValueGuard.IsInt8Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Int8Array 2', () => { const R = ValueGuard.IsInt8Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsUint8Array // ----------------------------------------------------- it('Should guard Uint8Array 1', () => { const R = ValueGuard.IsUint8Array(new Uint8Array(1)) Assert.IsTrue(R) }) it('Should guard Uint8Array 2', () => { const R = ValueGuard.IsUint8Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Uint8Array 2', () => { const R = ValueGuard.IsUint8Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsUint8ClampedArray // ----------------------------------------------------- it('Should guard Uint8ClampedArray 1', () => { const R = ValueGuard.IsUint8ClampedArray(new Uint8ClampedArray(1)) Assert.IsTrue(R) }) it('Should guard Uint8ClampedArray 2', () => { const R = ValueGuard.IsUint8ClampedArray(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Uint8ClampedArray 2', () => { const R = ValueGuard.IsUint8ClampedArray(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsInt16Array // ----------------------------------------------------- it('Should guard Int16Array 1', () => { const R = ValueGuard.IsInt16Array(new Int16Array(1)) Assert.IsTrue(R) }) it('Should guard Int16Array 2', () => { const R = ValueGuard.IsInt16Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Int16Array 2', () => { const R = ValueGuard.IsInt16Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsUint16Array // ----------------------------------------------------- it('Should guard Uint16Array 1', () => { const R = ValueGuard.IsUint16Array(new Uint16Array(1)) Assert.IsTrue(R) }) it('Should guard Uint16Array 2', () => { const R = ValueGuard.IsUint16Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Uint16Array 2', () => { const R = ValueGuard.IsUint16Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsInt32Array // ----------------------------------------------------- it('Should guard Int32Array 1', () => { const R = ValueGuard.IsInt32Array(new Int32Array(1)) Assert.IsTrue(R) }) it('Should guard Int32Array 2', () => { const R = ValueGuard.IsInt32Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Int32Array 2', () => { const R = ValueGuard.IsInt32Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsUint32Array // ----------------------------------------------------- it('Should guard Uint32Array 1', () => { const R = ValueGuard.IsUint32Array(new Uint32Array(1)) Assert.IsTrue(R) }) it('Should guard Uint32Array 2', () => { const R = ValueGuard.IsUint32Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Uint32Array 2', () => { const R = ValueGuard.IsUint32Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsFloat32Array // ----------------------------------------------------- it('Should guard Float32Array 1', () => { const R = ValueGuard.IsFloat32Array(new Float32Array(1)) Assert.IsTrue(R) }) it('Should guard Float32Array 2', () => { const R = ValueGuard.IsFloat32Array(new Float64Array(1)) Assert.IsFalse(R) }) it('Should guard Float32Array 2', () => { const R = ValueGuard.IsFloat32Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsFloat64Array // ----------------------------------------------------- it('Should guard Float64Array 1', () => { const R = ValueGuard.IsFloat64Array(new Float64Array(1)) Assert.IsTrue(R) }) it('Should guard Float64Array 2', () => { const R = ValueGuard.IsFloat64Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Float64Array 2', () => { const R = ValueGuard.IsFloat64Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsBigInt64Array // ----------------------------------------------------- it('Should guard BigInt64Array 1', () => { const R = ValueGuard.IsBigInt64Array(new BigInt64Array(1)) Assert.IsTrue(R) }) it('Should guard BigInt64Array 2', () => { const R = ValueGuard.IsBigInt64Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard BigInt64Array 2', () => { const R = ValueGuard.IsBigInt64Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsBigUint64Array // ----------------------------------------------------- it('Should guard BigUint64Array 1', () => { const R = ValueGuard.IsBigUint64Array(new BigUint64Array(1)) Assert.IsTrue(R) }) it('Should guard BigUint64Array 2', () => { const R = ValueGuard.IsBigUint64Array(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard BigUint64Array 2', () => { const R = ValueGuard.IsBigUint64Array(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsMap // ----------------------------------------------------- it('Should guard Map 1', () => { const R = ValueGuard.IsMap(new Map()) Assert.IsTrue(R) }) it('Should guard Map 2', () => { const R = ValueGuard.IsMap(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Map 2', () => { const R = ValueGuard.IsMap(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsSet // ----------------------------------------------------- it('Should guard Set 1', () => { const R = ValueGuard.IsSet(new Set()) Assert.IsTrue(R) }) it('Should guard Set 2', () => { const R = ValueGuard.IsSet(new Float32Array(1)) Assert.IsFalse(R) }) it('Should guard Set 2', () => { const R = ValueGuard.IsSet(1) Assert.IsFalse(R) }) // ----------------------------------------------------- // IsValueType // ----------------------------------------------------- it('Should guard value type 1', () => { const R = ValueGuard.IsValueType(1) Assert.IsTrue(R) }) it('Should guard value type 2', () => { const R = ValueGuard.IsValueType(true) Assert.IsTrue(R) }) it('Should guard value type 3', () => { const R = ValueGuard.IsValueType(false) Assert.IsTrue(R) }) it('Should guard value type 4', () => { const R = ValueGuard.IsValueType('hello') Assert.IsTrue(R) }) it('Should guard value type 5', () => { const R = ValueGuard.IsValueType(1n) Assert.IsTrue(R) }) it('Should guard value type 6', () => { const R = ValueGuard.IsValueType(null) Assert.IsTrue(R) }) it('Should guard value type 7', () => { const R = ValueGuard.IsValueType(undefined) Assert.IsTrue(R) }) it('Should guard value type 8', () => { const R = ValueGuard.IsValueType(function () {}) Assert.IsFalse(R) }) it('Should guard value type 9', () => { const R = ValueGuard.IsValueType({}) Assert.IsFalse(R) }) it('Should guard value type 10', () => { const R = ValueGuard.IsValueType([]) Assert.IsFalse(R) }) it('Should guard value type 11', () => { const R = ValueGuard.IsValueType(class {}) Assert.IsFalse(R) }) it('Should guard value type 12', () => { const R = ValueGuard.IsValueType(new (class {})()) Assert.IsFalse(R) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/guard/index.ts000066400000000000000000000000211505437577000246100ustar00rootroot00000000000000import './guard' sinclairzx81-typebox-e0ec98c/test/runtime/value/hash/000077500000000000000000000000001505437577000227615ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/hash/hash.ts000066400000000000000000000073061505437577000242620ustar00rootroot00000000000000import { Hash } from '@sinclair/typebox/value' import { Assert } from '../../assert/index' describe('value/hash/Hash', () => { it('Should hash number', () => { Assert.IsEqual('bigint', typeof Hash(1)) const A = Hash(1) const B = Hash(2) Assert.NotEqual(A, B) }) it('Should hash string', () => { Assert.IsEqual('bigint', typeof Hash('hello')) const A = Hash('hello') const B = Hash('world') Assert.NotEqual(A, B) }) it('Should hash boolean', () => { Assert.IsEqual('bigint', typeof Hash(true)) Assert.IsEqual('bigint', typeof Hash(false)) const A = Hash(true) const B = Hash(false) Assert.NotEqual(A, B) }) it('Should hash null', () => { Assert.IsEqual('bigint', typeof Hash(null)) const A = Hash(null) const B = Hash(undefined) Assert.NotEqual(A, B) }) it('Should hash array', () => { Assert.IsEqual('bigint', typeof Hash([0, 1, 2, 3])) const A = Hash([0, 1, 2, 3]) const B = Hash([0, 2, 2, 3]) Assert.NotEqual(A, B) }) it('Should hash object 1', () => { // prettier-ignore Assert.IsEqual('bigint', typeof Hash({ x: 1, y: 2 })) const A = Hash({ x: 1, y: 2 }) const B = Hash({ x: 2, y: 2 }) Assert.NotEqual(A, B) }) it('Should hash object 2', () => { const A = Hash({ x: 1, y: [1, 2] }) const B = Hash({ x: 1, y: [1, 3] }) Assert.NotEqual(A, B) }) it('Should hash object 3', () => { const A = Hash({ x: 1, y: undefined }) const B = Hash({ x: 1 }) Assert.NotEqual(A, B) }) it('Should hash object 4', () => { const A = Hash({ x: 1, y: new Uint8Array([0, 1, 2]) }) const B = Hash({ x: 1, y: [0, 1, 2] }) Assert.NotEqual(A, B) }) it('Should hash object 5', () => { const A = Hash({ x: 1, y: undefined }) const B = Hash({ x: 2, y: undefined }) Assert.NotEqual(A, B) }) it('Should hash Date', () => { Assert.IsEqual('bigint', typeof Hash(new Date())) const A = Hash(new Date(1)) const B = Hash(new Date(2)) Assert.NotEqual(A, B) }) it('Should hash Uint8Array', () => { Assert.IsEqual('bigint', typeof Hash(new Uint8Array([0, 1, 2, 3]))) const A = Hash(new Uint8Array([0, 1, 2, 3])) const B = Hash(new Uint8Array([0, 2, 2, 3])) Assert.NotEqual(A, B) }) it('Should hash undefined', () => { Assert.IsEqual('bigint', typeof Hash(undefined)) const A = Hash(undefined) const B = Hash(null) Assert.NotEqual(A, B) }) it('Should hash symbol 1', () => { Assert.IsEqual('bigint', typeof Hash(Symbol())) const A = Hash(Symbol(1)) const B = Hash(Symbol()) Assert.NotEqual(A, B) }) it('Should hash symbol 2', () => { Assert.IsEqual('bigint', typeof Hash(Symbol())) const A = Hash(Symbol(1)) const B = Hash(Symbol(2)) Assert.NotEqual(A, B) }) it('Should hash symbol 2', () => { Assert.IsEqual('bigint', typeof Hash(Symbol())) const A = Hash(Symbol(1)) const B = Hash(Symbol(1)) Assert.IsEqual(A, B) }) it('Should hash bigint 1', () => { Assert.IsEqual('bigint', typeof Hash(BigInt(1))) const A = Hash(BigInt(1)) const B = Hash(BigInt(2)) Assert.NotEqual(A, B) }) it('Should hash bigint 2', () => { Assert.IsEqual('bigint', typeof Hash(BigInt(1))) const A = Hash(BigInt(1)) const B = Hash(BigInt(1)) Assert.IsEqual(A, B) }) // ---------------------------------------------------------------- // Unicode // ---------------------------------------------------------------- it('Should hash unicode 1 (retain single byte hash)', () => { const hash = Hash('a') Assert.IsEqual(hash, 586962220959696054n) }) it('Should hash unicode 2', () => { const hash = Hash('안녕 세계') Assert.IsEqual(hash, 11219208047802711777n) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/hash/index.ts000066400000000000000000000000201505437577000244300ustar00rootroot00000000000000import './hash' sinclairzx81-typebox-e0ec98c/test/runtime/value/index.ts000066400000000000000000000004331505437577000235150ustar00rootroot00000000000000import './assert' import './cast' import './check' import './clean' import './clone' import './convert' import './create' import './default' import './delta' import './equal' import './guard' import './hash' import './mutate' import './parse' import './pointer' import './transform' sinclairzx81-typebox-e0ec98c/test/runtime/value/mutate/000077500000000000000000000000001505437577000233355ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/mutate/index.ts000066400000000000000000000000221505437577000250060ustar00rootroot00000000000000import './mutate' sinclairzx81-typebox-e0ec98c/test/runtime/value/mutate/mutate.ts000066400000000000000000000062221505437577000252060ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Assert } from '../../assert/index' describe('value/mutate/Mutate', () => { // -------------------------------------------- // Throw // -------------------------------------------- it('should throw 1', () => { // @ts-ignore Assert.Throws(() => Value.Mutate(1, 1)) }) it('should throw 2', () => { // @ts-ignore Assert.Throws(() => Value.Mutate({}, 1)) }) it('should throw 3', () => { // @ts-ignore Assert.Throws(() => Value.Mutate([], 1)) }) it('should throw 4', () => { // @ts-ignore Assert.Throws(() => Value.Mutate({}, [])) }) it('should throw 5', () => { // @ts-ignore Assert.Throws(() => Value.Mutate([], {})) }) // -------------------------------------------- // Mutate // -------------------------------------------- it('Should mutate 0', () => { const Y = { z: 1 } const X = { y: Y } const A = { x: X } Value.Mutate(A, {}) Assert.IsEqual(A, {}) }) it('Should mutate 1', () => { const Y = { z: 1 } const X = { y: Y } const A = { x: X } Value.Mutate(A, { x: { y: { z: 2 } } }) Assert.IsEqual(A.x.y.z, 2) Assert.IsEqual(A.x.y, Y) Assert.IsEqual(A.x, X) }) it('Should mutate 2', () => { const Y = { z: 1 } const X = { y: Y } const A = { x: X } Value.Mutate(A, { x: { y: { z: [1, 2, 3] } } }) Assert.IsEqual(A.x.y.z, [1, 2, 3]) Assert.IsEqual(A.x.y, Y) Assert.IsEqual(A.x, X) }) it('Should mutate 3', () => { const Y = { z: 1 } const X = { y: Y } const A = { x: X } Value.Mutate(A, { x: {} }) Assert.IsEqual(A.x.y, undefined) Assert.IsEqual(A.x, X) }) it('Should mutate 4', () => { const Y = { z: 1 } const X = { y: Y } const A = { x: X } Value.Mutate(A, { x: { y: 1 } }) Assert.IsEqual(A.x.y, 1) Assert.IsEqual(A.x, X) }) it('Should mutate 5', () => { const Y = { z: 1 } const X = { y: Y } const A = { x: X } Value.Mutate(A, { x: { y: [1, 2, 3] } }) Assert.IsEqual(A.x.y, [1, 2, 3]) Assert.IsEqual(A.x, X) }) it('Should mutate 6', () => { const Y = { z: 1 } const X = { y: Y } const A = { x: X } Value.Mutate(A, { x: [1, 2, 3] }) Assert.NotEqual(A.x, X) Assert.IsEqual(A.x, [1, 2, 3]) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1119 // ---------------------------------------------------------------- it('Should mutate array 1', () => { const A: unknown[] = [] Value.Mutate(A, []) Assert.IsEqual(A, []) }) it('Should mutate array 2', () => { const A: unknown[] = [] Value.Mutate(A, [1]) Assert.IsEqual(A, [1]) }) it('Should mutate array 3', () => { const A: unknown[] = [1, 2, 3] Value.Mutate(A, [1, 2]) Assert.IsEqual(A, [1, 2]) }) it('Should mutate array 4', () => { const A: unknown[] = [1, 2, 3] Value.Mutate(A, [1, 2, 3, 4]) Assert.IsEqual(A, [1, 2, 3, 4]) }) it('Should mutate array 5', () => { const A: unknown[] = [1, 2, 3] Value.Mutate(A, [{}, {}, {}, [1, 2, 3]]) Assert.IsEqual(A, [{}, {}, {}, [1, 2, 3]]) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/parse/000077500000000000000000000000001505437577000231505ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/parse/index.ts000066400000000000000000000000211505437577000246200ustar00rootroot00000000000000import './parse' sinclairzx81-typebox-e0ec98c/test/runtime/value/parse/parse.ts000066400000000000000000000103341505437577000246330ustar00rootroot00000000000000import { Value, AssertError, ParseRegistry } from '@sinclair/typebox/value' import { Type, TypeGuard } from '@sinclair/typebox' import { Assert } from '../../assert/index' // prettier-ignore describe('value/Parse', () => { it('Should Parse', () => { const A = Value.Parse(Type.Literal('hello'), 'hello') Assert.IsEqual(A, 'hello') }) it('Should not Parse', () => { Assert.Throws(() => Value.Parse(Type.Literal('hello'), 'world')) }) it('Should throw AssertError', () => { try { Value.Parse(Type.Literal('hello'), 'world') } catch(error) { if(error instanceof AssertError) { return } throw error } }) it('Should throw AssertError and produce Iterator', () => { try { Value.Parse(Type.Literal('hello'), 'world') } catch(error) { if(error instanceof AssertError) { const first = error.Errors().First() Assert.HasProperty(first, 'type') Assert.HasProperty(first, 'schema') Assert.HasProperty(first, 'path') Assert.HasProperty(first, 'value') Assert.HasProperty(first, 'message') return } throw error } }) // ---------------------------------------------------------------- // Default // ---------------------------------------------------------------- it('Should use Default values', () => { const X = Value.Parse(Type.Object({ x: Type.Number({ default: 1 }), y: Type.Number({ default: 2 }) }), { }) Assert.IsEqual(X, { x: 1, y: 2 }) }) it('Should throw on invalid Default values', () => { Assert.Throws(() => Value.Parse(Type.Object({ x: Type.Number({ default: null }), y: Type.Number({ default: null }) }), { })) }) // ---------------------------------------------------------------- // Convert // ---------------------------------------------------------------- it('Should Convert value 1', () => { const X = Value.Parse(Type.Object({ x: Type.Number(), y: Type.Number() }), { x: '1', y: '2' }) Assert.IsEqual(X, { x: 1, y: 2 }) }) it('Should Convert value 2', () => { const X = Value.Parse(Type.Array(Type.String()), [1, 2, 3, 4]) Assert.IsEqual(X, ['1', '2', '3', '4']) }) // ---------------------------------------------------------------- // Clean // ---------------------------------------------------------------- it('Should Clean value', () => { const X = Value.Parse(Type.Object({ x: Type.Number(), y: Type.Number() }), { x: 1, y: 2, z: 3 }) Assert.IsEqual(X, { x: 1, y: 2 }) }) // ---------------------------------------------------------------- // Decode // ---------------------------------------------------------------- it('Should Decode value', () => { const T = Type.Transform(Type.String()) .Decode(value => 'hello') .Encode(value => value) const X = Value.Parse(T, 'world') Assert.IsEqual(X, 'hello') }) // ---------------------------------------------------------------- // Operations // ---------------------------------------------------------------- it('Should run operations 1', () => { const A = Type.Object({ x: Type.Number() }) const I = { x: 1 } const O = Value.Parse([], A, I) Assert.IsTrue(I === O) }) it('Should run operations 2', () => { const A = Type.Object({ x: Type.Number() }) const I = { x: 1 } const O = Value.Parse(['Clone'], A, I) Assert.IsTrue(I !== O) }) it('Should run operations 3', () => { ParseRegistry.Set('Intercept', ( schema, references, value) => { throw 1 }) const A = Type.Object({ x: Type.Number() }) Assert.Throws(() => Value.Parse(['Intercept'], A, null)) ParseRegistry.Delete('Intercept') const F = ParseRegistry.Get('Intercept') Assert.IsEqual(F, undefined) }) it('Should run operations 4', () => { ParseRegistry.Set('Intercept', ( schema, references, value) => { Assert.IsEqual(value, 12345) Assert.IsTrue(TypeGuard.IsNumber(schema)) Assert.IsTrue(TypeGuard.IsString(references[0])) }) Value.Parse(['Intercept'], Type.Number(), [Type.String()], 12345) ParseRegistry.Delete('Intercept') }) it('Should run operations 5', () => { Assert.Throws(() => Value.Parse(['Intercept'], Type.String(), null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/pointer/000077500000000000000000000000001505437577000235165ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/pointer/index.ts000066400000000000000000000000231505437577000251700ustar00rootroot00000000000000import './pointer' sinclairzx81-typebox-e0ec98c/test/runtime/value/pointer/pointer.ts000066400000000000000000000264711505437577000255600ustar00rootroot00000000000000import { ValuePointer } from '@sinclair/typebox/value' import { Assert } from '../../assert/index' describe('value/pointer/Pointer', () => { //----------------------------------------------- // Format //----------------------------------------------- it('Should produce correct format #1', () => { const R = [...ValuePointer.Format('')] Assert.IsEqual(R, []) }) it('Should produce correct format #2', () => { const R = [...ValuePointer.Format('a')] Assert.IsEqual(R, ['a']) }) it('Should produce correct format #3', () => { const R = [...ValuePointer.Format('/')] Assert.IsEqual(R, ['']) }) it('Should produce correct format #4', () => { const R = [...ValuePointer.Format('/x')] Assert.IsEqual(R, ['x']) }) it('Should produce correct format #5', () => { const R = [...ValuePointer.Format('/x/')] Assert.IsEqual(R, ['x', '']) }) it('Should produce correct format #6', () => { const R = [...ValuePointer.Format('/x//')] Assert.IsEqual(R, ['x', '', '']) }) it('Should produce correct format #7', () => { const R = [...ValuePointer.Format('/x//y')] Assert.IsEqual(R, ['x', '', 'y']) }) it('Should produce correct format #8', () => { const R = [...ValuePointer.Format('/x//y/')] Assert.IsEqual(R, ['x', '', 'y', '']) }) it('Should produce correct format #9', () => { const R = [...ValuePointer.Format('/x/~0')] Assert.IsEqual(R, ['x', '~']) }) it('Should produce correct format #10', () => { const R = [...ValuePointer.Format('/x/~1')] Assert.IsEqual(R, ['x', '/']) }) it('Should produce correct format #11', () => { const R = [...ValuePointer.Format('/x/~0/')] Assert.IsEqual(R, ['x', '~', '']) }) it('Should produce correct format #12', () => { const R = [...ValuePointer.Format('/x/~1/')] Assert.IsEqual(R, ['x', '/', '']) }) it('Should produce correct format #13', () => { const R = [...ValuePointer.Format('/x/a~0b')] Assert.IsEqual(R, ['x', 'a~b']) }) it('Should produce correct format #14', () => { const R = [...ValuePointer.Format('/x/a~1b')] Assert.IsEqual(R, ['x', 'a/b']) }) it('Should produce correct format #15', () => { const R = [...ValuePointer.Format('/x/a~0b/')] Assert.IsEqual(R, ['x', 'a~b', '']) }) it('Should produce correct format #16', () => { const R = [...ValuePointer.Format('/x/a~1b/')] Assert.IsEqual(R, ['x', 'a/b', '']) }) it('Should produce correct format #17', () => { const R = [...ValuePointer.Format('/x/a~0b///y')] Assert.IsEqual(R, ['x', 'a~b', '', '', 'y']) }) it('Should produce correct format #18', () => { const R = [...ValuePointer.Format('/x/a~1b///y')] Assert.IsEqual(R, ['x', 'a/b', '', '', 'y']) }) it('Should produce correct format #19', () => { const R = [...ValuePointer.Format('/x/a~0b///')] Assert.IsEqual(R, ['x', 'a~b', '', '', '']) }) it('Should produce correct format #20', () => { const R = [...ValuePointer.Format('/x/a~1b///')] Assert.IsEqual(R, ['x', 'a/b', '', '', '']) }) //----------------------------------------------- // Get //----------------------------------------------- it('Should get array #1', () => { const V = [0, 1, 2, 3] Assert.IsEqual(ValuePointer.Get(V, ''), [0, 1, 2, 3]) Assert.IsEqual(ValuePointer.Get(V, '/'), undefined) Assert.IsEqual(ValuePointer.Get(V, '/0'), 0) Assert.IsEqual(ValuePointer.Get(V, '/1'), 1) Assert.IsEqual(ValuePointer.Get(V, '/2'), 2) Assert.IsEqual(ValuePointer.Get(V, '/3'), 3) }) it('Should get array #2', () => { const V = [{ x: 0 }, { x: 1 }, { x: 2 }, { x: 3 }] Assert.IsEqual(ValuePointer.Get(V, ''), [{ x: 0 }, { x: 1 }, { x: 2 }, { x: 3 }]) Assert.IsEqual(ValuePointer.Get(V, '/'), undefined) Assert.IsEqual(ValuePointer.Get(V, '/0'), { x: 0 }) Assert.IsEqual(ValuePointer.Get(V, '/1'), { x: 1 }) Assert.IsEqual(ValuePointer.Get(V, '/2'), { x: 2 }) Assert.IsEqual(ValuePointer.Get(V, '/3'), { x: 3 }) Assert.IsEqual(ValuePointer.Get(V, '/0/x'), 0) Assert.IsEqual(ValuePointer.Get(V, '/1/x'), 1) Assert.IsEqual(ValuePointer.Get(V, '/2/x'), 2) Assert.IsEqual(ValuePointer.Get(V, '/3/x'), 3) }) it('Should get object #1', () => { const V = { x: 0, y: 1, z: 2 } Assert.IsEqual(ValuePointer.Get(V, ''), { x: 0, y: 1, z: 2 }) Assert.IsEqual(ValuePointer.Get(V, '/'), undefined) Assert.IsEqual(ValuePointer.Get(V, '/x'), 0) Assert.IsEqual(ValuePointer.Get(V, '/y'), 1) Assert.IsEqual(ValuePointer.Get(V, '/z'), 2) }) it('Should get object #2', () => { const V = { x: { x: 0 }, y: { x: 1 }, z: { x: 2 } } Assert.IsEqual(ValuePointer.Get(V, ''), { x: { x: 0 }, y: { x: 1 }, z: { x: 2 } }) Assert.IsEqual(ValuePointer.Get(V, '/'), undefined) Assert.IsEqual(ValuePointer.Get(V, '/x'), { x: 0 }) Assert.IsEqual(ValuePointer.Get(V, '/y'), { x: 1 }) Assert.IsEqual(ValuePointer.Get(V, '/z'), { x: 2 }) }) it('Should get object #3', () => { const V = { '': { x: -1 }, x: { '': { x: 1 } }, y: { '': { x: 2 } }, z: { '': { x: 3 } } } Assert.IsEqual(ValuePointer.Get(V, ''), { '': { x: -1 }, x: { '': { x: 1 } }, y: { '': { x: 2 } }, z: { '': { x: 3 } } }) Assert.IsEqual(ValuePointer.Get(V, '/'), { x: -1 }) Assert.IsEqual(ValuePointer.Get(V, '/x'), { '': { x: 1 } }) Assert.IsEqual(ValuePointer.Get(V, '/y'), { '': { x: 2 } }) Assert.IsEqual(ValuePointer.Get(V, '/z'), { '': { x: 3 } }) Assert.IsEqual(ValuePointer.Get(V, '/x/'), { x: 1 }) Assert.IsEqual(ValuePointer.Get(V, '/y/'), { x: 2 }) Assert.IsEqual(ValuePointer.Get(V, '/z/'), { x: 3 }) Assert.IsEqual(ValuePointer.Get(V, '/x//x'), 1) Assert.IsEqual(ValuePointer.Get(V, '/y//x'), 2) Assert.IsEqual(ValuePointer.Get(V, '/z//x'), 3) }) //----------------------------------------------- // Has //----------------------------------------------- it('Should return has true for undefined', () => { const V = undefined Assert.IsEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for null', () => { const V = null Assert.IsEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for object', () => { const V = {} Assert.IsEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for array', () => { const V: any[] = [] Assert.IsEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for string', () => { const V = 'hello' Assert.IsEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for number', () => { const V = 42 Assert.IsEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for boolean', () => { const V = false Assert.IsEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for deeply nested', () => { const V = { '': { x: { y: { z: 1 } } }, x: 1, y: { x: 1 }, z: [{ x: 1 }, { y: 1 }], w: undefined, n: null, } // exists Assert.IsEqual(ValuePointer.Has(V, ''), true) Assert.IsEqual(ValuePointer.Has(V, '/'), true) Assert.IsEqual(ValuePointer.Has(V, '//x'), true) Assert.IsEqual(ValuePointer.Has(V, '//x/y'), true) Assert.IsEqual(ValuePointer.Has(V, '//x/y/z'), true) Assert.IsEqual(ValuePointer.Has(V, '/x'), true) Assert.IsEqual(ValuePointer.Has(V, '/y/x'), true) Assert.IsEqual(ValuePointer.Has(V, '/z'), true) Assert.IsEqual(ValuePointer.Has(V, '/z/0'), true) Assert.IsEqual(ValuePointer.Has(V, '/z/0/x'), true) Assert.IsEqual(ValuePointer.Has(V, '/z/1'), true) Assert.IsEqual(ValuePointer.Has(V, '/z/1/y'), true) Assert.IsEqual(ValuePointer.Has(V, '/x'), true) Assert.IsEqual(ValuePointer.Has(V, '/n'), true) }) //----------------------------------------------- // Set //----------------------------------------------- it('Should throw when setting root', () => { const V = {} Assert.Throws(() => ValuePointer.Set(V, '', { x: 1 })) }) it('Should set array values', () => { const V = [0, 1, 2] ValuePointer.Set(V, '/0', 3) ValuePointer.Set(V, '/1', 4) ValuePointer.Set(V, '/2', 5) Assert.IsEqual(V, [3, 4, 5]) }) it('Should set object values', () => { const V = { x: 0, y: 1, z: 2 } ValuePointer.Set(V, '/x', 3) ValuePointer.Set(V, '/y', 4) ValuePointer.Set(V, '/z', 5) Assert.IsEqual(V, { x: 3, y: 4, z: 5 }) }) it('Should set object values recursively #1', () => { const V = {} ValuePointer.Set(V, '/x/y/z', 1) Assert.IsEqual(V, { x: { y: { z: 1 } } }) }) it('Should set object values recursively #2', () => { const V = {} ValuePointer.Set(V, '/x/0/y/z/', 1) ValuePointer.Set(V, '/x/1/y/z/', 2) Assert.IsEqual(V, { x: { 0: { y: { z: { '': 1, }, }, }, 1: { y: { z: { '': 2, }, }, }, }, }) }) //----------------------------------------------- // Delete //----------------------------------------------- it('Should throw when deleting root', () => { const V = {} Assert.Throws(() => ValuePointer.Delete(V, '')) }) it('Should delete object properties', () => { const V = { x: { x: 1, y: 2, z: 3 }, y: { x: 3, y: 4, z: 5 }, } ValuePointer.Delete(V, '/x/y') ValuePointer.Delete(V, '/y') Assert.IsEqual(V, { x: { x: 1, z: 3 } }) }) it('Should be a noop if property does not exist', () => { const V = { x: { x: 1, y: 2, z: 3 }, y: { x: 3, y: 4, z: 5 }, } ValuePointer.Delete(V, '/x/w') ValuePointer.Delete(V, '/w') Assert.IsEqual(V, { x: { x: 1, y: 2, z: 3 }, y: { x: 3, y: 4, z: 5 }, }) }) it('Should not delete owner', () => { const V = { x: { y: { z: 1 } } } ValuePointer.Delete(V, '/x/y/z') Assert.IsEqual(V, { x: { y: {} } }) }) it('Should delete owner', () => { const V = { x: { y: { z: 1 } } } ValuePointer.Delete(V, '/x/y') Assert.IsEqual(V, { x: {} }) }) it('Should not throw if deleting null property', () => { const V = { x: { y: null } } ValuePointer.Delete(V, '/x/y/z') Assert.IsEqual(V, { x: { y: null } }) }) //----------------------------------------------- // Escapes //----------------------------------------------- it('Should support get ~0 pointer escape', () => { const V = { x: { '~': { x: 1 } }, } Assert.IsEqual(ValuePointer.Get(V, '/x/~0'), { x: 1 }) }) it('Should support get ~1 pointer escape', () => { const V = { x: { '/': { x: 1 } }, } Assert.IsEqual(ValuePointer.Get(V, '/x/~1'), { x: 1 }) }) it('Should support set ~0 pointer escape', () => { const V = { x: { '~': { x: 1 } }, } ValuePointer.Set(V, '/x/~0', { x: 2 }) Assert.IsEqual(V, { x: { '~': { x: 2 } }, }) }) it('Should support set ~1 pointer escape', () => { const V = { x: { '/': { x: 1 } }, } ValuePointer.Set(V, '/x/~1', { x: 2 }) Assert.IsEqual(V, { x: { '/': { x: 2 } }, }) }) it('Should support delete ~0 pointer escape', () => { const V = { x: { '~': { x: 1 } }, } ValuePointer.Delete(V, '/x/~0') Assert.IsEqual(V, { x: {}, }) }) it('Should support delete ~1 pointer escape', () => { const V = { x: { '/': { x: 1 } }, } ValuePointer.Delete(V, '/x/~1') Assert.IsEqual(V, { x: {}, }) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/000077500000000000000000000000001505437577000240515ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/_encoder.ts000066400000000000000000000035141505437577000262020ustar00rootroot00000000000000import { IsAsyncIterator, IsIterator, IsFunction, IsSymbol, IsDate } from '@sinclair/typebox/value' import { TSchema, StaticDecode, StaticEncode } from '@sinclair/typebox' import { TypeCompiler } from '@sinclair/typebox/compiler' import { Value } from '@sinclair/typebox/value' import { Assert } from '../../assert/index' function AssertSame(actual: unknown, expect: unknown) { if (IsAsyncIterator(actual) && IsAsyncIterator(expect)) return if (IsIterator(actual) && IsIterator(expect)) return if (IsSymbol(actual) && IsSymbol(expect)) return if (IsFunction(actual) && IsFunction(expect)) return if (IsDate(actual) && IsDate(expect)) { return Assert.IsEqual(actual.getTime(), expect.getTime()) } Assert.IsEqual(actual, expect) } export function Decode>(schema: T, references: TSchema[], value: unknown): R export function Decode>(schema: T, value: unknown): R export function Decode(...args: any[]) { const [schema, references, value] = args.length === 2 ? [args[0], [], args[1]] : [args[0], args[1], args[2]] const value1 = TypeCompiler.Compile(schema as TSchema, references).Decode(value) const value2 = Value.Decode(schema as TSchema, references, value) AssertSame(value1, value2) return value2 } export function Encode>(schema: T, references: TSchema[], value: unknown): R export function Encode>(schema: T, value: unknown): R export function Encode(...args: any[]) { const [schema, references, value] = args.length === 2 ? [args[0], [], args[1]] : [args[0], args[1], args[2]] const value1 = TypeCompiler.Compile(schema as TSchema, references).Encode(value) const value2 = Value.Encode(schema as TSchema, references, value) AssertSame(value1, value2) return value2 } sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/_nested.ts000066400000000000000000000032201505437577000260370ustar00rootroot00000000000000import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Nested', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T11 = Type.Transform(Type.Literal(1)) .Decode((value) => value) .Encode((value) => value) const T12 = Type.Transform(T11) .Decode((value) => value) .Encode((value) => value) const T13 = Type.Transform(T12) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Value.Decode(T13, 1) Assert.IsEqual(R, 1) }) it('Should encode identity', () => { const R = Value.Encode(T13, 1) Assert.IsEqual(R, 1) }) it('Should throw on identity decode', () => { Assert.Throws(() => Value.Decode(T13, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T21 = Type.Transform(Type.Literal(1)) .Decode((value) => 2 as const) .Encode((value) => 1 as const) const T22 = Type.Transform(T21) .Decode((value) => 3 as const) .Encode((value) => 2 as const) const T23 = Type.Transform(T22) .Decode((value) => 4 as const) .Encode((value) => 3 as const) it('Should decode mapped', () => { const R = Value.Decode(T23, 1) Assert.IsEqual(R, 4) }) it('Should encode mapped', () => { const R = Value.Encode(T23, 4) Assert.IsEqual(R, 1) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Value.Decode(T23, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/any.ts000066400000000000000000000021151505437577000252070ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Any', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Any()) .Decode((value) => value) .Encode((value) => value) it('Should decode mapped', () => { const R = Encoder.Decode(T0, 123) Assert.IsEqual(R, 123) }) it('Should encode mapped', () => { const R = Encoder.Encode(T0, 123) Assert.IsEqual(R, 123) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Any()) .Decode((value) => 1) .Encode((value) => 2) it('Should decode mapped', () => { const R = Encoder.Decode(T1, null) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, 2) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/array.ts000066400000000000000000000065471505437577000255530ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Array', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Array(Type.Number())) .Decode((value) => value) .Encode((value) => value) it('Should decode mapped', () => { const R = Encoder.Decode(T0, [0, 1, 2]) Assert.IsEqual(R, [0, 1, 2]) }) it('Should encode mapped', () => { const R = Encoder.Encode(T0, [0, 1, 2]) Assert.IsEqual(R, [0, 1, 2]) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Array(Type.Number())) .Decode((value) => 1) .Encode((value) => [0, 1, 2]) it('Should decode mapped', () => { const R = Encoder.Decode(T1, []) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, [0, 1, 2]) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) // -------------------------------------------------------- // Elements // -------------------------------------------------------- const B2 = Type.Transform(Type.Boolean()) .Decode((value) => (value ? 'TRUE' : 'FALSE')) .Encode((value) => (value === 'TRUE' ? true : false)) const T2 = Type.Array(B2) it('Should decode elements', () => { const R = Encoder.Decode(T2, [true, false]) Assert.IsEqual(R, ['TRUE', 'FALSE']) }) it('Should encode elements', () => { const R = Encoder.Encode(T2, ['TRUE', 'FALSE']) Assert.IsEqual(R, [true, false]) }) it('Should throw on elements decode', () => { Assert.Throws(() => Encoder.Decode(T2, null)) }) // -------------------------------------------------------- // Elements Contains (Not Supported) // -------------------------------------------------------- const N3 = Type.Transform(Type.Literal(1)) .Decode((value) => 'hello') .Encode((value) => 1 as const) const T3 = Type.Array(Type.Number(), { contains: N3, }) it('Should decode contains', () => { const R = Encoder.Decode(T3, [1, 2, 3]) Assert.IsEqual(R, [1, 2, 3]) }) it('Should throw on contains encode', () => { Assert.Throws(() => Encoder.Encode(T3, ['hello', 2, 3])) }) it('Should throw on contains decode', () => { Assert.Throws(() => Encoder.Decode(T3, null)) }) // ------------------------------------------------------------ // Set // ------------------------------------------------------------ const T4 = Type.Transform(Type.Array(Type.Number())) .Decode((value) => new Set(value)) .Encode((value) => [...value]) it('should decode set', () => { const R = Encoder.Decode(T4, [1, 1, 2, 3]) Assert.IsInstanceOf(R, Set) Assert.IsTrue(R.has(1)) Assert.IsTrue(R.has(2)) Assert.IsTrue(R.has(3)) }) it('should encode set', () => { const R = Encoder.Encode(T4, new Set([1, 2, 3])) Assert.IsEqual(R, [1, 2, 3]) }) it('Should throw on set decode', () => { Assert.Throws(() => Encoder.Decode(T4, {})) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/async-iterator.ts000066400000000000000000000027451505437577000273750ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/AsyncIterator', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.AsyncIterator(Type.Number())) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, (async function* (): any {})()) Assert.IsTrue(Symbol.asyncIterator in R) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, (async function* (): any {})()) Assert.IsTrue(Symbol.asyncIterator in R) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.AsyncIterator(Type.Number())) .Decode((value) => 1) .Encode((value) => (async function* (): any {})()) it('Should decode', () => { const R = Encoder.Decode(T1, (async function* (): any {})()) Assert.IsEqual(R, 1) }) it('Should encode', () => { const R = Encoder.Encode(T1, null) Assert.IsTrue(Symbol.asyncIterator in R) }) it('Should throw on decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/bigint.ts000066400000000000000000000024421505437577000256770ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/BigInt', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.BigInt()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, 5n) Assert.IsEqual(R, 5n) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, 5n) Assert.IsEqual(R, 5n) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.BigInt()) .Decode((value) => 1) .Encode((value) => 2n) it('Should decode mapped', () => { const R = Encoder.Decode(T1, 1n) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, 2n) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/boolean.ts000066400000000000000000000024651505437577000260470ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Boolean', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Boolean()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, true) Assert.IsEqual(R, true) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, false) Assert.IsEqual(R, false) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Boolean()) .Decode((value) => 1) .Encode((value) => true) it('Should decode mapped', () => { const R = Encoder.Decode(T1, true) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, true) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/constructor.ts000066400000000000000000000026001505437577000270040ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Constructor', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Constructor([], Type.Any())) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, class {}) Assert.IsTypeOf(R, 'function') }) it('Should encode identity', () => { const R = Encoder.Encode(T0, class {}) Assert.IsTypeOf(R, 'function') }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Constructor([], Type.Any())) .Decode((value) => 1) .Encode((value) => class {}) it('Should decode mapped', () => { const R = Encoder.Decode(T1, class {}) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsTypeOf(R, 'function') }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/date.ts000066400000000000000000000025411505437577000253400ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Date', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Date()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, new Date(123)) Assert.IsEqual(R, new Date(123)) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, new Date(123)) Assert.IsEqual(R, new Date(123)) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Date()) .Decode((value) => 1) .Encode((value) => new Date(0)) it('Should decode mapped', () => { const R = Encoder.Decode(T1, new Date(0)) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsInstanceOf(R, Date) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/enum.ts000066400000000000000000000025111505437577000253640ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Enum', () => { enum E { A, B, C, } // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Enum(E)) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, E.A) Assert.IsEqual(R, E.A) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, E.A) Assert.IsEqual(R, E.A) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Enum(E)) .Decode((value) => 1) .Encode((value) => E.A) it('Should decode mapped', () => { const R = Encoder.Decode(T1, E.A) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, E.A) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/function.ts000066400000000000000000000026031505437577000262470ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Function', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Function([], Type.Any())) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, class {}) Assert.IsTypeOf(R, 'function') }) it('Should encode identity', () => { const R = Encoder.Encode(T0, class {}) Assert.IsTypeOf(R, 'function') }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Function([], Type.Any())) .Decode((value) => 1) .Encode((value) => function () {}) it('Should decode mapped', () => { const R = Encoder.Decode(T1, function () {}) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsTypeOf(R, 'function') }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/import.ts000066400000000000000000000163671505437577000257500ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { TypeSystemPolicy } from '@sinclair/typebox/system' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' // prettier-ignore describe('value/transform/Import', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform( Type.Module({ A: Type.Object({ x: Type.Number(), y: Type.Number(), })}).Import('A'), ) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, undefined)) }) // ---------------------------------------------------------- // Object // ---------------------------------------------------------- const T1 = Type.Transform( Type.Module({ A: Type.Object({ x: Type.Number(), y: Type.Number(), })}).Import('A'), ) .Decode((value) => 42) .Encode((value) => ({ x: 1, y: 2 })) it('Should decode mapped', () => { const R = Encoder.Decode(T1, { x: 1, y: 2 }) Assert.IsEqual(R, 42) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, undefined)) }) // ---------------------------------------------------------- // Object: Transform Property // ---------------------------------------------------------- const N2 = Type.Transform(Type.Module({ A: Type.Integer() }).Import('A')) .Decode((value) => value.toString()) .Encode((value) => parseInt(value)) const T2 = Type.Object({ x: N2, y: N2, }) it('Should decode transform property', () => { const R = Encoder.Decode(T2, { x: 1, y: 2 }) Assert.IsEqual(R, { x: '1', y: '2' }) }) it('Should encode transform property', () => { const R = Encoder.Encode(T2, { x: '1', y: '2' }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on decode transform property', () => { Assert.Throws(() => Encoder.Decode(T2, undefined)) }) // ---------------------------------------------------------- // Object: Transform Property Nested (Twizzle) // ---------------------------------------------------------- const N3 = Type.Transform(Type.Module({ A: Type.Integer() }).Import('A')) .Decode((value) => value.toString()) .Encode((value) => parseInt(value)) const T3 = Type.Transform( Type.Object({ x: N3, y: N3, }), ) .Decode((value) => ({ x: value.y, y: value.x })) .Encode((value) => ({ x: value.y, y: value.x })) it('Should decode transform property nested', () => { const R = Encoder.Decode(T3, { x: 1, y: 2 }) Assert.IsEqual(R, { x: '2', y: '1' }) }) it('Should encode transform property nested', () => { const R = Encoder.Encode(T3, { x: '1', y: '2' }) Assert.IsEqual(R, { x: 2, y: 1 }) }) it('Should throw on decode transform property nested', () => { Assert.Throws(() => Encoder.Decode(T3, undefined)) }) // ---------------------------------------------------------- // Object Additional Properties // ---------------------------------------------------------- const N4 = Type.Transform(Type.Module({ A: Type.Integer() }).Import('A')) .Decode((value) => value.toString()) .Encode((value) => parseInt(value)) const T4 = Type.Transform( Type.Object( { x: Type.Number(), }, { additionalProperties: N4, }, ), ) .Decode((value) => value) .Encode((value) => value) it('Should decode additional property', () => { const R = Encoder.Decode(T4, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: '2' }) }) it('Should encode additional property', () => { const R = Encoder.Encode(T4, { x: 1, y: '5' }) Assert.IsEqual(R, { x: 1, y: 5 }) }) it('Should throw on additional property 1', () => { Assert.Throws(() => Encoder.Decode(T4, undefined)) }) it('Should throw on additional property 2', () => { Assert.Throws(() => Encoder.Decode(T4, { x: 1, y: true })) }) // ------------------------------------------------------------ // Map // ------------------------------------------------------------ const T5 = Type.Transform(Type.Module({ A: Type.Object({ x: Type.String(), y: Type.String() })}).Import('A')) .Decode((value) => new Map(Object.entries(value))) .Encode((value) => Object.fromEntries(value.entries()) as any) it('Should decode map', () => { const R = Encoder.Decode(T5, { x: 'hello', y: 'world' }) Assert.IsInstanceOf(R, Map) Assert.IsEqual(R.get('x'), 'hello') Assert.IsEqual(R.get('y'), 'world') }) it('Should encode map', () => { const R = Encoder.Encode( T5, new Map([ ['x', 'hello'], ['y', 'world'], ]), ) Assert.IsEqual(R, { x: 'hello', y: 'world' }) }) it('Should throw on map decode', () => { Assert.Throws(() => Encoder.Decode(T5, {})) }) // ------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1178 // ------------------------------------------------------------- // immediate it('Should transform embedded module codec 1', () => { const T = Type.Module({ A: Type.Transform(Type.String()) .Decode((value) => parseInt(value)) .Encode((value) => value.toString()), }).Import('A') const D = Value.Decode(T, '123') const E = Value.Encode(T, 123) Assert.IsEqual(D, 123) Assert.IsEqual(E, '123') }) // referential it('Should transform embedded module codec 2', () => { const T = Type.Module({ A: Type.Transform(Type.String()) .Decode((value) => parseInt(value)) .Encode((value) => value.toString()), B: Type.Ref('A'), }).Import('B') const D = Value.Decode(T, '123') const E = Value.Encode(T, 123) Assert.IsEqual(D, 123) Assert.IsEqual(E, '123') }) // deep-referential it('Should transform embedded module codec 3', () => { const T = Type.Module({ A: Type.Transform(Type.String()) .Decode((value) => parseInt(value)) .Encode((value) => value.toString()), B: Type.Ref('A'), C: Type.Ref('B'), D: Type.Ref('C'), E: Type.Ref('D'), }).Import('E') const D = Value.Decode(T, '123') const E = Value.Encode(T, 123) Assert.IsEqual(D, 123) Assert.IsEqual(E, '123') }) // interior-transform referential it('Should transform embedded module codec 4', () => { const T = Type.Module({ A: Type.String(), B: Type.Ref('A'), C: Type.Ref('B'), T: Type.Transform(Type.Ref('C')) .Decode((value) => parseInt(value as string)) .Encode((value) => value.toString()), X: Type.Ref('T'), Y: Type.Ref('X'), Z: Type.Ref('Y') }).Import('Z') const D = Value.Decode(T, '123') const E = Value.Encode(T, 123) Assert.IsEqual(D, 123) Assert.IsEqual(E, '123') }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/index.ts000066400000000000000000000011471505437577000255330ustar00rootroot00000000000000import './_nested' import './any' import './array' import './async-iterator' import './bigint' import './boolean' import './constructor' import './date' import './enum' import './function' import './import' import './integer' import './intersect' import './iterator' import './literal' import './never' import './not' import './null' import './number' import './object' import './promise' import './record' import './recursive' import './ref' import './string' import './symbol' import './template-literal' import './tuple' import './undefined' import './union' import './unknown' import './unsafe' import './void' sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/integer.ts000066400000000000000000000024421505437577000260600ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Integer', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Integer()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, 42) Assert.IsEqual(R, 42) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, 42) Assert.IsEqual(R, 42) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Integer()) .Decode((value) => 1) .Encode((value) => 2) it('Should decode mapped', () => { const R = Encoder.Decode(T1, 1) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, 2) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/intersect.ts000066400000000000000000000135721505437577000264310ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Intersect', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- // prettier-ignore const T0 = Type.Transform(Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ])) .Decode(value => value) .Encode(value => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- // prettier-ignore const T1 = Type.Transform(Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ])) .Decode((value) => 1) .Encode((value) => ({ x: 1, y: 2 })) it('Should decode mapped', () => { const R = Encoder.Decode(T1, { x: 1, y: 2 }) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) // -------------------------------------------------------- // Mapped Property // -------------------------------------------------------- const N2 = Type.Transform(Type.Number()) .Decode((value) => value.toString()) .Encode((value) => parseFloat(value)) // prettier-ignore const T2 = Type.Transform(Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: N2 }) ])) .Decode((value) => value) .Encode((value) => value) it('Should decode property', () => { const R = Encoder.Decode(T2, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: '2' }) }) it('Should encode property', () => { const R = Encoder.Encode(T2, { x: 1, y: '2' }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on property decode', () => { Assert.Throws(() => Encoder.Decode(T2, null)) }) // -------------------------------------------------------- // Unevaluated Property // -------------------------------------------------------- const N3 = Type.Transform(Type.Number()) .Decode((value) => value.toString()) .Encode((value) => parseFloat(value)) // prettier-ignore const T3 = Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ], { unevaluatedProperties: N3 }) it('Should decode unevaluated property', () => { const R = Encoder.Decode(T3, { x: 1, y: 2, z: 3 }) Assert.IsEqual(R, { x: 1, y: 2, z: '3' }) }) it('Should encode unevaluated property', () => { const R = Encoder.Encode(T3, { x: 1, y: 2, z: '3' }) Assert.IsEqual(R, { x: 1, y: 2, z: 3 }) }) it('Should throw on unevaluated property decode', () => { Assert.Throws(() => Encoder.Decode(T3, null)) }) // -------------------------------------------------------- // Transform Intersection Interior (Not Supported) // -------------------------------------------------------- it('Should throw on intersected interior transform types', () => { const N4 = Type.Transform(Type.Number()) .Decode((value) => value) .Encode((value) => value) Assert.Throws(() => Type.Intersect([N4, N4])) }) // -------------------------------------------------------- // Transform Intersection Exterior // -------------------------------------------------------- const T4 = Type.Transform(Type.Intersect([Type.Number(), Type.Number()])) .Decode((value) => value + 1) .Encode((value) => value - 1) it('Should decode exterior value type', () => { const R = Encoder.Decode(T4, 1) Assert.IsEqual(R, 2) }) it('Should encode exterior value type', () => { const R = Encoder.Encode(T4, 2) Assert.IsEqual(R, 1) }) it('Should throw on exterior value type decode', () => { Assert.Throws(() => Encoder.Decode(T4, null)) }) // -------------------------------------------------------- // https://github.com/sinclairzx81/typebox/discussions/672 // -------------------------------------------------------- // prettier-ignore { const A = Type.Object({ isHybrid: Type.Boolean() }) const T = Type.Transform(A) .Decode((value) => ({ isHybrid: value.isHybrid ? 1 : 0 })) .Encode((value) => ({ isHybrid: value.isHybrid === 1 ? true : false })) const I = Type.Intersect([ Type.Object({ model: Type.String() }), Type.Object({ features: Type.Array(T) }), ]) it('Should decode nested 1', () => { const value = Value.Decode(T, { isHybrid: true }) Assert.IsEqual(value, { isHybrid: 1 }) }) // prettier-ignore it('Should decode nested 2', () => { const value = Value.Decode(I, { model: 'Prius', features: [ { isHybrid: true }, { isHybrid: false } ], }) Assert.IsEqual(value, { model: 'Prius', features: [ { isHybrid: 1 }, { isHybrid: 0 } ], }) }) it('should encode nested 1', () => { let value = Value.Encode(T, { isHybrid: 1 }) Assert.IsEqual(value, { isHybrid: true }) }) // prettier-ignore it('Should encode nested 2', () => { const value = Value.Encode(I, { model: 'Prius', features: [ { isHybrid: 1 }, { isHybrid: 0 } ], }) Assert.IsEqual(value, { model: 'Prius', features: [ { isHybrid: true }, { isHybrid: false } ], }) }) } }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/iterator.ts000066400000000000000000000027041505437577000262550ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Iterator', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Iterator(Type.Number())) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, (function* (): any {})()) Assert.IsTrue(Symbol.iterator in R) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, (function* (): any {})()) Assert.IsTrue(Symbol.iterator in R) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Iterator(Type.Number())) .Decode((value) => 1) .Encode((value) => (function* (): any {})()) it('Should decode mapped', () => { const R = Encoder.Decode(T1, (function* (): any {})()) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsTrue(Symbol.iterator in R) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/literal.ts000066400000000000000000000045251505437577000260630ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Literal', () => { // ----------------------------------------------- // Identity // ----------------------------------------------- const T0 = Type.Transform(Type.Literal(123)) .Decode((value) => value) .Encode((value) => value) it('Should decode mapped', () => { const R = Encoder.Decode(T0, 123) Assert.IsEqual(R, 123) }) it('Should encode mapped', () => { const R = Encoder.Encode(T0, 123) Assert.IsEqual(R, 123) }) // ----------------------------------------------- // LiteralString // ----------------------------------------------- const T1 = Type.Transform(Type.Literal('hello')) .Decode((value) => 1) .Encode((value) => 'hello' as const) it('Should decode literal string', () => { const R = Encoder.Decode(T1, 'hello') Assert.IsEqual(R, 1) }) it('Should encode literal string', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, 'hello') }) it('Should throw on decode literal string', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) // ----------------------------------------------- // LiteralNumber // ----------------------------------------------- const T2 = Type.Transform(Type.Literal(2)) .Decode((value) => 1) .Encode((value) => 2 as const) it('Should decode literal number', () => { const R = Encoder.Decode(T2, 2) Assert.IsEqual(R, 1) }) it('Should encode literal number', () => { const R = Encoder.Encode(T2, null) Assert.IsEqual(R, 2) }) it('Should throw on decode literal number', () => { Assert.Throws(() => Encoder.Decode(T2, null)) }) // ----------------------------------------------- // LiteralBoolean // ----------------------------------------------- const T3 = Type.Transform(Type.Literal(true)) .Decode((value) => 1) .Encode((value) => true as const) it('Should decode literal boolean', () => { const R = Encoder.Decode(T3, true) Assert.IsEqual(R, 1) }) it('Should encode literal boolean', () => { const R = Encoder.Encode(T3, null) Assert.IsEqual(R, true) }) it('Should throw on decode literal boolean', () => { Assert.Throws(() => Encoder.Decode(T3, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/never.ts000066400000000000000000000022131505437577000255360ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Never', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Never()) .Decode((value) => value) // @ts-ignore .Encode((value) => value) it('Should throw on identity encode', () => { Assert.Throws(() => Encoder.Encode(T0, undefined)) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, undefined)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Never()) // @ts-ignore .Decode((value) => 1) // @ts-ignore .Encode((value) => 1) it('Should throw on mapped encode', () => { Assert.Throws(() => Encoder.Encode(T1, undefined)) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, undefined)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/not.ts000066400000000000000000000024551505437577000252270ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Not', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Not(Type.String())) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, 1) Assert.IsEqual(R, 1) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, 1) Assert.IsEqual(R, 1) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, '')) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Not(Type.String())) .Decode((value) => 1) .Encode((value) => 2) it('Should decode mapped', () => { const R = Encoder.Decode(T1, null) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, 2) }) it('Should throw on decode not', () => { Assert.Throws(() => Encoder.Decode(T1, 'hello')) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/null.ts000066400000000000000000000024631505437577000254000ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Null', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Null()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, null) Assert.IsEqual(R, null) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, null) Assert.IsEqual(R, null) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, undefined)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Null()) .Decode((value) => 1) .Encode((value) => null) it('Should decode mapped', () => { const R = Encoder.Decode(T1, null) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, 123) Assert.IsEqual(R, null) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, undefined)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/number.ts000066400000000000000000000024611505437577000257140ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Number', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Number()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, 42) Assert.IsEqual(R, 42) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, 42) Assert.IsEqual(R, 42) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Number()) .Decode((value) => value + 1) .Encode((value) => value - 1) it('Should decode mapped', () => { const R = Encoder.Decode(T1, 1) Assert.IsEqual(R, 2) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, 2) Assert.IsEqual(R, 1) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, undefined)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/object.ts000066400000000000000000000264371505437577000257030ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { TypeSystemPolicy } from '@sinclair/typebox/system' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' // prettier-ignore describe('value/transform/Object', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform( Type.Object({ x: Type.Number(), y: Type.Number(), }), ) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, undefined)) }) // ---------------------------------------------------------- // Object // ---------------------------------------------------------- const T1 = Type.Transform( Type.Object({ x: Type.Number(), y: Type.Number(), }), ) .Decode((value) => 42) .Encode((value) => ({ x: 1, y: 2 })) it('Should decode mapped', () => { const R = Encoder.Decode(T1, { x: 1, y: 2 }) Assert.IsEqual(R, 42) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, undefined)) }) // ---------------------------------------------------------- // Object: Transform Property // ---------------------------------------------------------- const N2 = Type.Transform(Type.Integer()) .Decode((value) => value.toString()) .Encode((value) => parseInt(value)) const T2 = Type.Object({ x: N2, y: N2, }) it('Should decode transform property', () => { const R = Encoder.Decode(T2, { x: 1, y: 2 }) Assert.IsEqual(R, { x: '1', y: '2' }) }) it('Should encode transform property', () => { const R = Encoder.Encode(T2, { x: '1', y: '2' }) Assert.IsEqual(R, { x: 1, y: 2 }) }) it('Should throw on decode transform property', () => { Assert.Throws(() => Encoder.Decode(T2, undefined)) }) // ---------------------------------------------------------- // Object: Transform Property Nested (Twizzle) // ---------------------------------------------------------- const N3 = Type.Transform(Type.Integer()) .Decode((value) => value.toString()) .Encode((value) => parseInt(value)) const T3 = Type.Transform( Type.Object({ x: N3, y: N3, }), ) .Decode((value) => ({ x: value.y, y: value.x })) .Encode((value) => ({ x: value.y, y: value.x })) it('Should decode transform property nested', () => { const R = Encoder.Decode(T3, { x: 1, y: 2 }) Assert.IsEqual(R, { x: '2', y: '1' }) }) it('Should encode transform property nested', () => { const R = Encoder.Encode(T3, { x: '1', y: '2' }) Assert.IsEqual(R, { x: 2, y: 1 }) }) it('Should throw on decode transform property nested', () => { Assert.Throws(() => Encoder.Decode(T3, undefined)) }) // ---------------------------------------------------------- // Object Additional Properties // ---------------------------------------------------------- const N4 = Type.Transform(Type.Integer()) .Decode((value) => value.toString()) .Encode((value) => parseInt(value)) const T4 = Type.Transform( Type.Object( { x: Type.Number(), }, { additionalProperties: N4, }, ), ) .Decode((value) => value) .Encode((value) => value) it('Should decode additional property', () => { const R = Encoder.Decode(T4, { x: 1, y: 2 }) Assert.IsEqual(R, { x: 1, y: '2' }) }) it('Should encode additional property', () => { const R = Encoder.Encode(T4, { x: 1, y: '5' }) Assert.IsEqual(R, { x: 1, y: 5 }) }) it('Should throw on additional property 1', () => { Assert.Throws(() => Encoder.Decode(T4, undefined)) }) it('Should throw on additional property 2', () => { Assert.Throws(() => Encoder.Decode(T4, { x: 1, y: true })) }) // ------------------------------------------------------------ // Map // ------------------------------------------------------------ const T5 = Type.Transform(Type.Object({ x: Type.String(), y: Type.String() })) .Decode((value) => new Map(Object.entries(value))) .Encode((value) => Object.fromEntries(value.entries()) as any) it('should decode map', () => { const R = Encoder.Decode(T5, { x: 'hello', y: 'world' }) Assert.IsInstanceOf(R, Map) Assert.IsEqual(R.get('x'), 'hello') Assert.IsEqual(R.get('y'), 'world') }) it('should encode map', () => { const R = Encoder.Encode( T5, new Map([ ['x', 'hello'], ['y', 'world'], ]), ) Assert.IsEqual(R, { x: 'hello', y: 'world' }) }) it('Should throw on map decode', () => { Assert.Throws(() => Encoder.Decode(T5, {})) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/859 // ---------------------------------------------------------------- it('Should decode for nested transform with renamed property', () => { class User { constructor(public name: string, public createdAt: Date) { } } const TDate = Type.Transform(Type.Number()) .Decode(v => new Date(v)) .Encode(v => v.getTime()) const TUser = Type.Transform(Type.Object({ name: Type.String(), created_at: TDate })) .Decode(v => new User(v.name, v.created_at)) .Encode(v => ({ name: v.name, created_at: v.createdAt })) const D = Value.Decode(TUser, { name: 'name', created_at: 0 }) const E = Value.Encode(TUser, D) Assert.IsEqual(E.name, 'name') Assert.IsEqual(E.created_at, 0) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/865 // ---------------------------------------------------------------- it('Should decode for null prototype', () => { const N = Type.Transform(Type.Number()) .Decode(value => value.toString()) .Encode(value => parseInt(value)) const T = Type.Object({ x: N }) const A = Object.create(null); A.x = 1 const B = Object.create(null); B.x = '1' const D = Value.Decode(T, A) const E = Value.Encode(T, B) Assert.IsEqual(D, { x: '1' }) Assert.IsEqual(E, { x: 1 }) }) // ---------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/958 // ---------------------------------------------------------------- it('Should not decode missing optional properties 0', () => { let Invoked = false const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => { Invoked = true; return value }) .Encode((value) => value) const T = Type.Object({ value: Type.Optional(S) }) const D = Value.Decode(T, { value: 'foo' }) Assert.IsEqual(D, { value: 'foo' }) Assert.IsTrue(Invoked) }) it('Should not decode missing optional properties 1', () => { let Invoked = false const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => { Invoked = true; return value }) .Encode((value) => value) const T = Type.Object({ value: Type.Optional(S) }) const D = Value.Decode(T, {}) Assert.IsEqual(D, {}) Assert.IsFalse(Invoked) }) it('Should not decode missing optional properties 2', () => { let Invoked = false const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => { Invoked = true; return value }) .Encode((value) => value) const T = Type.Object({ value: Type.Optional(S) }) const D = Value.Decode(T, { value: undefined }) Assert.IsEqual(D, { value: undefined }) Assert.IsFalse(Invoked) }) it('Should not decode missing optional properties 3 (ExactOptionalPropertyTypes)', () => { let [Invoked, Revert] = [false, TypeSystemPolicy.ExactOptionalPropertyTypes] TypeSystemPolicy.ExactOptionalPropertyTypes = true const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => { Invoked = true; return value }) .Encode((value) => value) const T = Type.Object({ value: Type.Optional(S) }) const D = Value.Decode(T, {}) Assert.IsEqual(D, {}) Assert.IsFalse(Invoked) TypeSystemPolicy.ExactOptionalPropertyTypes = Revert }) it('Should not decode missing optional properties 4 (ExactOptionalPropertyTypes)', () => { let [Invoked, Revert] = [false, TypeSystemPolicy.ExactOptionalPropertyTypes] TypeSystemPolicy.ExactOptionalPropertyTypes = true const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => { Invoked = true; return value }) .Encode((value) => value) const T = Type.Object({ value: Type.Optional(S) }) Assert.Throws(() => Value.Decode(T, { value: undefined })) Assert.IsFalse(Invoked) TypeSystemPolicy.ExactOptionalPropertyTypes = Revert }) it('Should not encode missing optional properties 0', () => { let Invoked = false const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => value) .Encode((value) => { Invoked = true; return value }) const T = Type.Object({ value: Type.Optional(S) }) const D = Value.Encode(T, { value: 'foo' }) Assert.IsEqual(D, { value: 'foo' }) Assert.IsTrue(Invoked) }) it('Should not encode missing optional properties 1', () => { let Invoked = false const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => value) .Encode((value) => { Invoked = true; return value }) const T = Type.Object({ value: Type.Optional(S) }) const D = Value.Encode(T, {}) Assert.IsEqual(D, {}) Assert.IsFalse(Invoked) }) it('Should not encode missing optional properties 2', () => { let Invoked = false const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => value) .Encode((value) => { Invoked = true; return value }) const T = Type.Object({ value: Type.Optional(S) }) const D = Value.Encode(T, { value: undefined }) Assert.IsEqual(D, { value: undefined }) Assert.IsFalse(Invoked) }) it('Should not encode missing optional properties 3 (ExactOptionalPropertyTypes)', () => { let [Invoked, Revert] = [false, TypeSystemPolicy.ExactOptionalPropertyTypes] TypeSystemPolicy.ExactOptionalPropertyTypes = true const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => value) .Encode((value) => { Invoked = true; return value }) const T = Type.Object({ value: Type.Optional(S) }) const D = Value.Encode(T, {}) Assert.IsEqual(D, {}) Assert.IsFalse(Invoked) TypeSystemPolicy.ExactOptionalPropertyTypes = Revert }) it('Should not encode missing optional properties 4 (ExactOptionalPropertyTypes)', () => { let [Invoked, Revert] = [false, TypeSystemPolicy.ExactOptionalPropertyTypes] TypeSystemPolicy.ExactOptionalPropertyTypes = true const S = Type.Transform(Type.RegExp(/foo/)) .Decode((value) => value) .Encode((value) => { Invoked = true; return value }) const T = Type.Object({ value: Type.Optional(S) }) Assert.Throws(() => Value.Encode(T, { value: undefined })) Assert.IsFalse(Invoked) TypeSystemPolicy.ExactOptionalPropertyTypes = Revert }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/promise.ts000066400000000000000000000026521505437577000261040ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Promise', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Promise(Type.Number())) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, Promise.resolve(1)) Assert.IsTrue(R instanceof Promise) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, Promise.resolve(1)) Assert.IsTrue(R instanceof Promise) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, undefined)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T = Type.Transform(Type.Promise(Type.Number())) .Decode((value) => 1) .Encode((value) => Promise.resolve(1)) it('Should decode mapped', () => { const R = Encoder.Decode(T, Promise.resolve(1)) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T, null) Assert.IsTrue(R instanceof Promise) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/record.ts000066400000000000000000000070671505437577000257110ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Type } from '@sinclair/typebox' describe('value/transform/Record', () => { // ------------------------------------------------------------ // Identity // ------------------------------------------------------------ const T0 = Type.Transform(Type.Record(Type.String(), Type.Boolean())) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, { a: true, b: false, }) Assert.IsEqual(R, { a: true, b: false, }) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, { a: true, b: false, }) Assert.IsEqual(R, { a: true, b: false, }) }) it('Should throw on identity', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // ------------------------------------------------------------ // Additional Properties True // ------------------------------------------------------------ const N1 = Type.Transform(Type.Number()) .Decode((value) => `number-${value.toString()}`) .Encode((value) => parseFloat(value.replace(/number-/g, ''))) const T1 = Type.Record(Type.Number(), N1) it('Should decode additional properties allowed', () => { const R = Encoder.Decode(T1, { 0: 1, a: true, }) Assert.IsEqual(R, { 0: 'number-1', a: true, }) }) it('Should encode additional properties allowed', () => { const R = Encoder.Encode(T1, { 0: 'number-1', a: true, }) Assert.IsEqual(R, { 0: 1, a: true, }) }) it('Should throw on additional properties allowed', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) // ------------------------------------------------------------ // Complex Transform // ------------------------------------------------------------ const N2 = Type.Transform(Type.Number()) .Decode((value) => `number-${value.toString()}`) .Encode((value) => parseFloat(value.replace(/number-/g, ''))) const B2 = Type.Transform(Type.Boolean()) .Decode((value) => (value ? 'TRUE' : 'FALSE')) .Encode((value) => (value === 'TRUE' ? true : false)) const T3 = Type.Record(Type.Number(), N2, { additionalProperties: B2 }) it('Should decode complex', () => { const R = Encoder.Decode(T3, { 0: 1, a: true, }) Assert.IsEqual(R, { 0: 'number-1', a: 'TRUE', }) }) it('Should encode complex', () => { const R = Encoder.Encode(T3, { 0: 'number-1', a: 'TRUE', }) Assert.IsEqual(R, { 0: 1, a: true, }) }) it('Should throw on complex decode', () => { Assert.Throws(() => Encoder.Decode(T3, null)) }) // ------------------------------------------------------------ // Map // ------------------------------------------------------------ const T4 = Type.Transform(Type.Record(Type.String(), Type.String())) .Decode((value) => new Map(Object.entries(value))) .Encode((value) => Object.fromEntries(value.entries())) it('should decode map', () => { const R = Encoder.Decode(T4, { x: 'hello', y: 'world' }) Assert.IsInstanceOf(R, Map) Assert.IsEqual(R.get('x'), 'hello') Assert.IsEqual(R.get('y'), 'world') }) it('should encode map', () => { const R = Encoder.Encode( T4, new Map([ ['x', 'hello'], ['y', 'world'], ]), ) Assert.IsEqual(R, { x: 'hello', y: 'world' }) }) it('Should throw on map decode', () => { Assert.Throws(() => Encoder.Decode(T4, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/recursive.ts000066400000000000000000000064111505437577000264320ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Recursive', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform( Type.Recursive((This) => Type.Object({ value: Type.Number(), nodes: Type.Array(This), }), ), ) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, { value: 1, nodes: [ { value: 2, nodes: [] }, { value: 3, nodes: [] }, ], }) Assert.IsEqual(R, { value: 1, nodes: [ { value: 2, nodes: [] }, { value: 3, nodes: [] }, ], }) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, { value: 1, nodes: [ { value: 2, nodes: [] }, { value: 3, nodes: [] }, ], }) Assert.IsEqual(R, { value: 1, nodes: [ { value: 2, nodes: [] }, { value: 3, nodes: [] }, ], }) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, undefined)) }) // ----------------------------------------------- // Mapped // ----------------------------------------------- const T1 = Type.Transform( Type.Recursive((This) => Type.Object({ value: Type.Number(), nodes: Type.Array(This), }), ), ) .Decode((value) => 1) .Encode((value) => ({ value: 1, nodes: [] })) it('Should decode mapped', () => { const R = Encoder.Decode(T1, { value: 1, nodes: [ { value: 2, nodes: [] }, { value: 3, nodes: [] }, ], }) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, { value: 1, nodes: [] }) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) // ----------------------------------------------- // Recursive Property Remap // ----------------------------------------------- const N2 = Type.Transform(Type.Number()) .Decode((value) => new Date(value)) .Encode((value) => value.getTime()) const T2 = Type.Recursive((This) => Type.Object({ value: N2, nodes: Type.Array(This), }), ) it('Should decode property', () => { const R = Encoder.Decode(T2, { value: 1, nodes: [ { value: 2, nodes: [] }, { value: 3, nodes: [] }, ], }) Assert.IsEqual(R, { value: new Date(1), nodes: [ { value: new Date(2), nodes: [] }, { value: new Date(3), nodes: [] }, ], }) }) it('Should encode property', () => { const R = Encoder.Encode(T2, { value: new Date(1), nodes: [ { value: new Date(2), nodes: [] }, { value: new Date(3), nodes: [] }, ], }) Assert.IsEqual(R, { value: 1, nodes: [ { value: 2, nodes: [] }, { value: 3, nodes: [] }, ], }) }) it('Should throw on decode property', () => { Assert.Throws(() => Encoder.Decode(T2, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/ref.ts000066400000000000000000000042041505437577000251750ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Ref', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const N0 = Type.Number({ $id: 'N0' }) const T0 = Type.Transform(Type.Ref('N0')) .Decode((value) => value) .Encode((value) => value) it('Should decode mapped', () => { const R = Encoder.Decode(T0, [N0], 0) Assert.IsEqual(R, 0) }) it('Should encode mapped', () => { const R = Encoder.Encode(T0, [N0], 0) Assert.IsEqual(R, 0) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const N1 = Type.Number({ $id: 'N1' }) const T1 = Type.Transform(Type.Unsafe(Type.Ref('N1'))) .Decode((value) => value + 1) .Encode((value) => value - 1) it('Should decode mapped', () => { const R = Encoder.Decode(T1, [N1], 0) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, [N1], 1) Assert.IsEqual(R, 0) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) // -------------------------------------------------------- // Mapped Remote // -------------------------------------------------------- const N2 = Type.Transform(Type.Number({ $id: 'N2' })) .Decode((value) => value + 1) .Encode((value) => value - 1) const T2 = Type.Transform(Type.Unsafe(Type.Ref('N2'))) .Decode((value) => value + 1) .Encode((value) => value - 1) it('Should decode mapped remote', () => { const R = Encoder.Decode(T2, [N2], 0) Assert.IsEqual(R, 2) }) it('Should encode mapped remote', () => { const R = Encoder.Encode(T2, [N2], 2) Assert.IsEqual(R, 0) }) it('Should throw on mapped remote decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/string.ts000066400000000000000000000026541505437577000257360ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/String', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- // const T0 = Type.Transform(Type.String()) // .Decode((value) => value) // .Encode((value) => value) // it('Should decode identity', () => { // const R = Encoder.Decode(T0, 'hello') // Assert.IsEqual(R, 'hello') // }) // it('Should encode identity', () => { // const R = Encoder.Encode(T0, 'hello') // Assert.IsEqual(R, 'hello') // }) // it('Should throw on identity decode', () => { // Assert.Throws(() => Encoder.Decode(T0, null)) // }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.String()) .Decode((value) => value.split('').reverse().join('')) .Encode((value) => value.split('').reverse().join('')) it('Should decode mapped', () => { const R = Encoder.Decode(T1, 'ABC') Assert.IsEqual(R, 'CBA') }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, 'CBA') Assert.IsEqual(R, 'ABC') }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/symbol.ts000066400000000000000000000027741505437577000257400ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/String', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Symbol()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, Symbol('hello')) Assert.IsEqual(R.description, 'hello') }) it('Should encode identity', () => { const R = Encoder.Encode(T0, Symbol('hello')) Assert.IsEqual(R.description, 'hello') }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Symbol()) .Decode((value) => Symbol(value.description?.split('').reverse().join(''))) .Encode((value) => Symbol(value.description?.split('').reverse().join(''))) it('Should decode mapped', () => { const R = Encoder.Decode(T1, Symbol('ABC')) Assert.IsEqual(R.description, 'CBA') }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, Symbol('CBA')) Assert.IsEqual(R.description, 'ABC') }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/template-literal.ts000066400000000000000000000027331505437577000276730ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/TemplateLiteral', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.TemplateLiteral([Type.Literal('hello')])) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, 'hello') Assert.IsEqual(R, 'hello') }) it('Should encode identity', () => { const R = Encoder.Encode(T0, 'hello') Assert.IsEqual(R, 'hello') }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.TemplateLiteral([Type.Literal('ABC')])) .Decode((value) => value.split('').reverse().join('') as 'CBA') .Encode((value) => value.split('').reverse().join('') as 'ABC') it('Should decode mapped', () => { const R = Encoder.Decode(T1, 'ABC') Assert.IsEqual(R, 'CBA') }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, 'CBA') Assert.IsEqual(R, 'ABC') }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/tuple.ts000066400000000000000000000066521505437577000255630ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Tuple', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Tuple([Type.Number(), Type.Number()])) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, [1, 2]) Assert.IsEqual(R, [1, 2]) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, [1, 2]) Assert.IsEqual(R, [1, 2]) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Tuple([Type.Number()])) .Decode((value) => [value[0] + 1] as [number]) .Encode((value) => [value[0] - 1] as [number]) it('Should decode mapped', () => { const R = Encoder.Decode(T1, [0]) Assert.IsEqual(R, [1]) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, [1]) Assert.IsEqual(R, [0]) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) // -------------------------------------------------------- // Mapped Element // -------------------------------------------------------- const N2 = Type.Transform(Type.Number()) .Decode((value) => value + 1) .Encode((value) => value - 1) const T2 = Type.Transform(Type.Tuple([N2])) .Decode((value) => value) .Encode((value) => value) it('Should decode mapped element', () => { const R = Encoder.Decode(T2, [0]) Assert.IsEqual(R, [1]) }) it('Should encode mapped element', () => { const R = Encoder.Encode(T2, [1]) Assert.IsEqual(R, [0]) }) it('Should throw on mapped element decode', () => { Assert.Throws(() => Encoder.Decode(T2, null)) }) // -------------------------------------------------------- // Mapped Element // -------------------------------------------------------- const N3 = Type.Transform(Type.Number()) .Decode((value) => value + 1) .Encode((value) => value - 1) const T3 = Type.Transform(Type.Tuple([N3])) .Decode((value) => [value[0].toString()]) .Encode((value) => [parseFloat(value[0])] as [number]) it('Should decode mapped element', () => { const R = Encoder.Decode(T3, [0]) Assert.IsEqual(R, ['1']) }) it('Should encode mapped element', () => { const R = Encoder.Encode(T3, ['1']) Assert.IsEqual(R, [0]) }) it('Should throw on mapped element decode', () => { Assert.Throws(() => Encoder.Decode(T3, null)) }) // ------------------------------------------------------------ // Set // ------------------------------------------------------------ const T4 = Type.Transform(Type.Tuple([Type.Number()])) .Decode((value) => new Set(value)) .Encode((value) => [...value] as any) it('should decode set', () => { const R = Encoder.Decode(T4, [1]) Assert.IsInstanceOf(R, Set) Assert.IsTrue(R.has(1)) }) it('should encode set', () => { const R = Encoder.Encode(T4, new Set([1])) Assert.IsEqual(R, [1]) }) it('Should throw on set decode', () => { Assert.Throws(() => Encoder.Decode(T4, {})) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/undefined.ts000066400000000000000000000025421505437577000263650ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Undefined', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Undefined()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, undefined) Assert.IsEqual(R, undefined) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, undefined) Assert.IsEqual(R, undefined) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Undefined()) .Decode((value) => null) .Encode((value) => undefined) it('Should decode mapped', () => { const R = Encoder.Decode(T1, undefined) Assert.IsEqual(R, null) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, undefined) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/union.ts000066400000000000000000000175701505437577000255630ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Type } from '@sinclair/typebox' describe('value/transform/Union', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- // prettier-ignore const T0 = Type.Transform(Type.Union([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ])) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, { x: 1 }) Assert.IsEqual(R, { x: 1 }) }) it('Should encode identity', () => { const R = Encoder.Encode(T0, { y: 2 }) Assert.IsEqual(R, { y: 2 }) }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- // prettier-ignore const T1 = Type.Transform(Type.Union([ Type.Object({ type: Type.Literal('hello') }), Type.Object({ type: Type.Literal('world') }) ])) .Decode((value) => 'test' as const) .Encode((value) => ({ type: 'hello' as const })) it('Should decode mapped', () => { const R = Encoder.Decode(T1, { type: 'hello' }) Assert.IsEqual(R, 'test') }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, 'test') Assert.IsEqual(R, { type: 'hello' }) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) // -------------------------------------------------------- // Mapped ValueType // -------------------------------------------------------- const M21 = Type.Transform(Type.Number()) .Decode((value) => value + 1) .Encode((value) => value - 1) const M22 = Type.Transform(M21) .Decode((value) => value + 1) .Encode((value) => value - 1) // prettier-ignore const T2 = Type.Transform(Type.Union([Type.String(), M22])) .Decode((value) => value) .Encode((value) => { if (value === 'hello') return 'world' return value }) it('Should decode value type 1', () => { const R = Encoder.Decode(T2, 0) Assert.IsEqual(R, 2) }) it('Should decode value type 2', () => { const R = Encoder.Decode(T2, 'hello') Assert.IsEqual(R, 'hello') }) it('Should encode value type 1', () => { const R = Encoder.Encode(T2, 'hello') Assert.IsEqual(R, 'world') }) it('Should encode value type 2', () => { const R = Encoder.Encode(T2, 2) Assert.IsEqual(R, 0) }) it('Should throw on value type decode', () => { Assert.Throws(() => Encoder.Decode(T2, null)) }) // -------------------------------------------------------- // Mapped ObjectType // -------------------------------------------------------- const N31 = Type.Transform( Type.Object({ x: Type.Number(), }), ) .Decode((value) => ({ x: value.x + 1 })) .Encode((value) => ({ x: value.x - 1 })) const N32 = Type.Transform( Type.Object({ x: Type.String(), }), ) .Decode((value) => ({ x: value.x.split('').reverse().join('') })) .Encode((value) => ({ x: value.x.split('').reverse().join('') })) // prettier-ignore const T3 = Type.Transform(Type.Union([N31, N32])) .Decode((value) => value) .Encode((value) => value) it('Should decode object types 1', () => { const R = Encoder.Decode(T3, { x: 0 }) Assert.IsEqual(R, { x: 1 }) }) it('Should decode object types 2', () => { const R = Encoder.Decode(T3, { x: 'abc' }) Assert.IsEqual(R, { x: 'cba' }) }) it('Should encode object types 1', () => { const R = Encoder.Encode(T3, { x: 1 }) Assert.IsEqual(R, { x: 0 }) }) it('Should encode object types 2', () => { const R = Encoder.Encode(T3, { x: 'cba' }) Assert.IsEqual(R, { x: 'abc' }) }) it('Should throw on object types decode', () => { Assert.Throws(() => Encoder.Decode(T3, null)) }) // -------------------------------------------------------- // Mapped Mixed Types // -------------------------------------------------------- const N41 = Type.Transform(Type.Number()) .Decode((value) => value + 1) .Encode((value) => value - 1) // prettier-ignore const N42 = Type.Transform(Type.Object({ x: Type.Number() })) .Decode((value) => ({ x: value.x + 1 })) .Encode((value) => ({ x: value.x - 1 })) const N43 = Type.Transform(Type.Tuple([Type.Number()])) .Decode((value) => [value[0] + 1]) .Encode((value) => [value[0] - 1] as [number]) // prettier-ignore const T4 = Type.Transform(Type.Union([N41, N42, N43])) .Decode((value) => typeof value === 'number' ? value + 1 : value) .Encode((value) => typeof value === 'number' ? value - 1 : value) it('Should decode mixed types 1', () => { const R = Encoder.Decode(T4, { x: 0 }) Assert.IsEqual(R, { x: 1 }) }) it('Should decode mixed types 2', () => { const R = Encoder.Decode(T4, 0) Assert.IsEqual(R, 2) }) it('Should decode mixed types 3', () => { const R = Encoder.Decode(T4, [0]) Assert.IsEqual(R, [1]) }) it('Should encode mixed types 1', () => { const R = Encoder.Encode(T4, { x: 1 }) Assert.IsEqual(R, { x: 0 }) }) it('Should encode mixed types 2', () => { const R = Encoder.Encode(T4, 2) Assert.IsEqual(R, 0) }) it('Should encode mixed types 3', () => { const R = Encoder.Encode(T4, [1]) Assert.IsEqual(R, [0]) }) it('Should throw on mixed types decode', () => { Assert.Throws(() => Encoder.Decode(T4, null)) }) // -------------------------------------------------------- // Interior Union Transform // // https://github.com/sinclairzx81/typebox/issues/631 // -------------------------------------------------------- const T51 = Type.Transform(Type.String()) .Decode((value) => new Date(value)) .Encode((value) => value.toISOString()) const T52 = Type.Union([Type.Null(), T51]) it('Should decode interior union 1', () => { const R = Encoder.Decode(T52, null) Assert.IsEqual(R, null) }) it('Should decode interior union 2', () => { const R = Encoder.Decode(T52, new Date().toISOString()) Assert.IsInstanceOf(R, Date) }) it('Should encode interior union 1', () => { const R = Encoder.Encode(T52, null) Assert.IsEqual(R, null) }) it('Should encode interior union 2', () => { const D = new Date() const R = Encoder.Encode(T52, D) Assert.IsEqual(R, D.toISOString()) }) it('Should throw on interior union decode', () => { Assert.Throws(() => Encoder.Decode(T52, {})) }) it('Should throw on interior union encode', () => { Assert.Throws(() => Encoder.Encode(T52, 1)) }) // prettier-ignore { // https://github.com/sinclairzx81/typebox/issues/676 // interior-type const S = Type.Transform(Type.String()) .Decode((value: string) => new globalThis.Date(value)) .Encode((value: Date) => value.toISOString()) // union-type const U = Type.Union([ Type.Object({ date: S }), Type.Number() ]) // expect date on decode const T1 = Type.Transform(U) .Decode((value) => { Assert.IsTypeOf(value, 'object') Assert.HasProperty(value, 'date') Assert.IsInstanceOf(value.date, globalThis.Date); return value }) .Encode((value) => value) // expect number on decode const T2 = Type.Transform(U) .Decode((value) => { Assert.IsTypeOf(value, 'number') return value }) .Encode((value) => value) it('Should decode interior union 1', () => { const R = Encoder.Decode(T1, { date: new globalThis.Date().toISOString() }) Assert.IsTypeOf(R, 'object') Assert.HasProperty(R, 'date') Assert.IsInstanceOf(R.date, globalThis.Date); }) it('Should decode interior union 2', () => { const R = Encoder.Decode(T2, 123) Assert.IsTypeOf(R, 'number') Assert.IsEqual(R, 123) }) } }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/unknown.ts000066400000000000000000000021311505437577000261150ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Unknown', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Unknown()) .Decode((value) => value) .Encode((value) => value) it('Should decode mapped', () => { const R = Encoder.Decode(T0, 123) Assert.IsEqual(R, 123) }) it('Should encode mapped', () => { const R = Encoder.Encode(T0, 123) Assert.IsEqual(R, 123) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Unknown()) .Decode((value) => 1) .Encode((value) => 2) it('Should decode mapped', () => { const R = Encoder.Decode(T1, null) Assert.IsEqual(R, 1) }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, null) Assert.IsEqual(R, 2) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/unsafe.ts000066400000000000000000000033171505437577000257060ustar00rootroot00000000000000import * as Encoder from './_encoder' import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type, Kind, TypeRegistry } from '@sinclair/typebox' describe('value/transform/Unsafe', () => { // -------------------------------------------------------- // Fixtures // -------------------------------------------------------- beforeEach(() => TypeRegistry.Set('Foo', (schema, value) => value !== null)) // throw on null afterEach(() => TypeRegistry.Delete('Foo')) const Foo = Type.Unsafe({ [Kind]: 'Foo' }) // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Foo) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Encoder.Decode(T0, 'hello') Assert.IsEqual(R, 'hello') }) it('Should encode identity', () => { const R = Encoder.Encode(T0, 'hello') Assert.IsEqual(R, 'hello') }) it('Should throw on identity decode', () => { Assert.Throws(() => Encoder.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Foo) .Decode((value) => value.split('').reverse().join('')) .Encode((value) => value.split('').reverse().join('')) it('Should decode mapped', () => { const R = Encoder.Decode(T1, 'ABC') Assert.IsEqual(R, 'CBA') }) it('Should encode mapped', () => { const R = Encoder.Encode(T1, 'CBA') Assert.IsEqual(R, 'ABC') }) it('Should throw on mapped decode', () => { Assert.Throws(() => Encoder.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/runtime/value/transform/void.ts000066400000000000000000000024411505437577000253630ustar00rootroot00000000000000import { Assert } from '../../assert' import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' describe('value/transform/Void', () => { // -------------------------------------------------------- // Identity // -------------------------------------------------------- const T0 = Type.Transform(Type.Void()) .Decode((value) => value) .Encode((value) => value) it('Should decode identity', () => { const R = Value.Decode(T0, undefined) Assert.IsEqual(R, undefined) }) it('Should encode identity', () => { const R = Value.Encode(T0, undefined) Assert.IsEqual(R, undefined) }) it('Should throw on identity decode', () => { Assert.Throws(() => Value.Decode(T0, null)) }) // -------------------------------------------------------- // Mapped // -------------------------------------------------------- const T1 = Type.Transform(Type.Void()) .Decode((value) => null) .Encode((value) => undefined) it('Should decode mapped', () => { const R = Value.Decode(T1, undefined) Assert.IsEqual(R, null) }) it('Should encode mapped', () => { const R = Value.Encode(T1, null) Assert.IsEqual(R, undefined) }) it('Should throw on mapped decode', () => { Assert.Throws(() => Value.Decode(T1, null)) }) }) sinclairzx81-typebox-e0ec98c/test/static/000077500000000000000000000000001505437577000205265ustar00rootroot00000000000000sinclairzx81-typebox-e0ec98c/test/static/any.ts000066400000000000000000000001571505437577000216700ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Any()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/argument.ts000066400000000000000000000007011505437577000227160ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' const T = Type.Object({ x: Type.Argument(0), y: Type.Argument(1), z: Type.Argument(2), }) const I = Type.Instantiate(T, [Type.Literal(1), Type.Literal(2), Type.Literal(3)]) // Infer as Broadest Type (Pending Generic Constraints) Expect(T).ToStatic<{ x: unknown y: unknown z: unknown }>() // Infer as Narrowed Type Expect(I).ToStatic<{ x: 1 y: 2 z: 3 }>() sinclairzx81-typebox-e0ec98c/test/static/array.ts000066400000000000000000000007541505437577000222220ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Array(Type.String())).ToStatic() Expect( Type.Array( Type.Object({ x: Type.Number(), y: Type.Boolean(), z: Type.String(), }), ), ).ToStatic< { x: number y: boolean z: string }[] >() Expect(Type.Array(Type.Array(Type.String()))).ToStatic() Expect(Type.Array(Type.Tuple([Type.String(), Type.Number()]))).ToStatic<[string, number][]>() sinclairzx81-typebox-e0ec98c/test/static/assert.ts000066400000000000000000000055421505437577000224050ustar00rootroot00000000000000import { Static, StaticDecode, StaticEncode, TSchema } from '@sinclair/typebox' // ------------------------------------------------------------------ // Symbols // ------------------------------------------------------------------ export declare const Unsatisfiable: unique symbol // Warning: `never` and `any` satisfy the constraint `extends Expected<...>` export type Expected<_> = { [Unsatisfiable]: never } // ------------------------------------------------------------------ // Gates // ------------------------------------------------------------------ export type If = T extends true ? Y : N export type And = If export type Or = If export type Not = If // ------------------------------------------------------------------ // Helpers // ------------------------------------------------------------------ export type Extends = [T] extends [U] ? true : false export type IsAny = 0 extends 1 & T ? true : false export type IsNever = Extends // ------------------------------------------------------------------ // Constraints // ------------------------------------------------------------------ // See https://github.com/microsoft/TypeScript/issues/51011 export type CircularHelper = [T] extends U ? T : Expected // See https://github.com/Microsoft/TypeScript/issues/27024 export type ConstrainEqual = (() => V extends T ? 1 : 2) extends () => V extends U ? 1 : 2 ? T : Expected export type ConstraintMutuallyExtend = CircularHelper // Circular Error on TS 5.4.0 // If U is never, there's nothing we can do // export type ComplexConstraint = If< // // If U is any, we can't use Expect or it would satisfy the constraint // And>, IsAny>, // never, // If< // Or< // // If they are both any we are happy // And, IsAny>, // // If T extends U, but not because it's any, we are happy // And, Not>> // >, // T, // Expected // > // > // ------------------------------------------------------------------ // Expect // ------------------------------------------------------------------ export type ExpectResult = If< IsNever>, { ToStaticNever(): void }, { ToStatic, U>>(): void ToStaticDecode, U>>(): void ToStaticEncode, U>>(): void // ToStatic>(): void // ToStaticDecode>(): void // ToStaticEncode>(): void } > export function Expect(schema: T) { return { ToStatic() {}, ToStaticNever() {}, ToStaticDecode() {}, ToStaticEncode() {}, } as ExpectResult } sinclairzx81-typebox-e0ec98c/test/static/async-iterator.ts000066400000000000000000000002401505437577000240360ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.AsyncIterator(Type.String())).ToStatic>() sinclairzx81-typebox-e0ec98c/test/static/awaited.ts000066400000000000000000000015721505437577000225210ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Awaited(Type.String())).ToStatic() Expect(Type.Awaited(Type.Promise(Type.String()))).ToStatic() Expect(Type.Awaited(Type.Promise(Type.Promise(Type.String())))).ToStatic() // One Level Expect(Type.Awaited(Type.Union([Type.Promise(Type.String()), Type.Number()]))).ToStatic() Expect(Type.Awaited(Type.Intersect([Type.Promise(Type.Object({ a: Type.String() })), Type.Object({ b: Type.Number() })]))).ToStatic<{ a: string } & { b: number }>() // Two Levels Expect(Type.Awaited(Type.Union([Type.Promise(Type.Promise(Type.String())), Type.Number()]))).ToStatic() Expect(Type.Awaited(Type.Intersect([Type.Promise(Type.Promise(Type.Object({ a: Type.String() }))), Type.Object({ b: Type.Number() })]))).ToStatic<{ a: string } & { b: number }>() sinclairzx81-typebox-e0ec98c/test/static/bigint.ts000066400000000000000000000001651505437577000223540ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.BigInt()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/boolean.ts000066400000000000000000000001671505437577000225210ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Boolean()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/capitalize.ts000066400000000000000000000011601505437577000232210ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Capitalize(Type.Literal('hello'))).ToStatic<'Hello'>() Expect(Type.Capitalize(Type.Union([Type.Literal('hello'), Type.Literal('world')]))).ToStatic<'Hello' | 'World'>() Expect(Type.Capitalize(Type.TemplateLiteral('hello${0|1}'))).ToStatic<'Hello0' | 'Hello1'>() // prettier-ignore Expect(Type.Capitalize(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(1), Type.Literal(2)])]))).ToStatic<'Hello1' | 'Hello2'>() // passthrough Expect(Type.Capitalize(Type.Object({ x: Type.Number() }))).ToStatic<{ x: number }>() sinclairzx81-typebox-e0ec98c/test/static/composite.ts000066400000000000000000000123301505437577000230770ustar00rootroot00000000000000import { Expect } from './assert' import { Type, TOptional, TObject, TUnion, TIntersect, TNumber, TString, TBoolean } from '@sinclair/typebox' // ---------------------------------------------------------------------------- // Overlapping - Non Varying // ---------------------------------------------------------------------------- { const A = Type.Object({ A: Type.Number(), }) const B = Type.Object({ A: Type.Number(), }) const T = Type.Composite([A, B]) Expect(T).ToStatic<{ A: number }>() } // ---------------------------------------------------------------------------- // Overlapping - Varying // ---------------------------------------------------------------------------- { const A = Type.Object({ A: Type.Number(), }) const B = Type.Object({ A: Type.String(), }) const T = Type.Composite([A, B]) Expect(T).ToStatic<{ A: never }>() } // ---------------------------------------------------------------------------- // Overlapping Single Optional // ---------------------------------------------------------------------------- { const A = Type.Object({ A: Type.Optional(Type.Number()), }) const B = Type.Object({ A: Type.Number(), }) const T = Type.Composite([A, B]) Expect(T).ToStatic<{ A: number }>() } // ---------------------------------------------------------------------------- // Overlapping All Optional (Deferred) // // Note for: https://github.com/sinclairzx81/typebox/issues/419 // ---------------------------------------------------------------------------- { const A = Type.Object({ A: Type.Optional(Type.Number()), }) const B = Type.Object({ A: Type.Optional(Type.Number()), }) const T = Type.Composite([A, B]) Expect(T).ToStatic<{ A?: number | undefined }>() } { const A = Type.Object({ A: Type.Optional(Type.Number()), }) const B = Type.Object({ A: Type.Number(), }) const T = Type.Composite([A, B]) Expect(T).ToStatic<{ A: number }>() } { const A = Type.Object({ A: Type.Number(), }) const B = Type.Object({ A: Type.Number(), }) const T = Type.Composite([A, B]) Expect(T).ToStatic<{ A: number }>() } // ---------------------------------------------------------------------------- // Distinct Properties // ---------------------------------------------------------------------------- { const A = Type.Object({ A: Type.Number(), }) const B = Type.Object({ B: Type.Number(), }) const T = Type.Composite([A, B]) Expect(T).ToStatic<{ A: number B: number }>() } // ---------------------------------------------------------------------------- // Intersection Quirk // // TypeScript has an evaluation quirk for the following case where the first // type evaluates the sub property as never, but the second evaluates the // entire type as never. There is probably a reason for this behavior, but // TypeBox supports the former evaluation. // // { x: number } & { x: string } -> { x: number } & { x: string } => { x: never } // { x: number } & { x: boolean } -> never -> ... // ---------------------------------------------------------------------------- { // prettier-ignore const T: TObject<{ x: TIntersect<[TNumber, TBoolean]> }> = Type.Composite([ Type.Object({ x: Type.Number() }), Type.Object({ x: Type.Boolean() }) ]) } // ------------------------------------------------------------------ // Intersect // ------------------------------------------------------------------ // prettier-ignore { const T: TObject<{ x: TNumber; y: TNumber; z: TNumber; }> = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }), ]), Type.Intersect([ Type.Object({ z: Type.Number() }) ]) ]) } // prettier-ignore { const T: TObject<{ x: TIntersect<[TNumber, TNumber]>; y: TIntersect<[TNumber, TNumber]>; }> = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }), ]), Type.Intersect([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }), ]) ]) } // prettier-ignore { const T: TObject<{ x: TIntersect<[TNumber, TNumber]>; }> = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Number() }), ]) ]) } // prettier-ignore { const T: TObject<{ x: TOptional>; }> = Type.Composite([ Type.Intersect([ Type.Object({ x: Type.Optional(Type.Number()) }), Type.Object({ x: Type.Optional(Type.Number()) }), ]) ]) } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore { const T: TObject<{ x: TNumber; }> = Type.Composite([ Type.Union([ Type.Object({ x: Type.Number() }), Type.Object({ y: Type.Number() }) ]), Type.Object({ x: Type.Number() }) ]) } // prettier-ignore { const T: TObject<{ x: TIntersect<[TUnion<[TString, TString]>, TNumber]>; }> = Type.Composite([ Type.Union([ Type.Object({ x: Type.String() }), Type.Object({ x: Type.String() }) ]), Type.Object({ x: Type.Number() }) ]) } sinclairzx81-typebox-e0ec98c/test/static/const.ts000066400000000000000000000031421505437577000222240ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' // ------------------------------------------------------------------ // Identity Types // ------------------------------------------------------------------ // prettier-ignore Expect(Type.Const(undefined)).ToStatic() // prettier-ignore Expect(Type.Const(null)).ToStatic() // prettier-ignore Expect(Type.Const(Symbol())).ToStatic() // prettier-ignore Expect(Type.Const(1 as const)).ToStatic<1>() // prettier-ignore Expect(Type.Const('hello' as const)).ToStatic<'hello'>() // prettier-ignore Expect(Type.Const(true as const)).ToStatic() // ------------------------------------------------------------------ // Complex Types // ------------------------------------------------------------------ // prettier-ignore Expect(Type.Const(100n)).ToStatic() // prettier-ignore Expect(Type.Const(new Date())).ToStatic() // prettier-ignore Expect(Type.Const(new Uint8Array())).ToStatic() // prettier-ignore Expect(Type.Const(function () {})).ToStatic<() => unknown>() // prettier-ignore Expect(Type.Const((function *(): any {})())).ToStatic() // prettier-ignore Expect(Type.Const((async function *(): any {})())).ToStatic() // todo: remove when dropping TS 4.0 // prettier-ignore Expect(Type.Const({ x: 1, y: { z: 2 } })).ToStatic<{ readonly x: number, readonly y: { readonly z: number }}>() // prettier-ignore Expect(Type.Const({ x: 1, y: { z: 2 } } as const)).ToStatic<{ readonly x: 1, readonly y: { readonly z: 2 }}>() // prettier-ignore Expect(Type.Const([1, 2, 3] as const)).ToStatic<[1, 2, 3]>() sinclairzx81-typebox-e0ec98c/test/static/constructor-parameters.ts000066400000000000000000000004761505437577000256330ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' const C = Type.Constructor( [Type.Number(), Type.String()], Type.Object({ method: Type.Function([Type.Number(), Type.String()], Type.Boolean()), }), ) const P = Type.ConstructorParameters(C) Expect(P).ToStatic<[number, string]>() sinclairzx81-typebox-e0ec98c/test/static/constructor.ts000066400000000000000000000034001505437577000234600ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { // simple const T = Type.Constructor([Type.Number(), Type.Boolean()], Type.String()) Expect(T).ToStatic string>() } { // nested // prettier-ignore const T = Type.Constructor([Type.Number(), Type.String()], Type.Object({ method: Type.Constructor([Type.Number(), Type.String()], Type.Boolean()), })) Expect(T).ToStatic { method: new (param_0: number, param_1: string) => boolean }>() } { // readonly-optional const T = Type.Constructor([Type.ReadonlyOptional(Type.Array(Type.Number()))], Type.Number()) Expect(T).ToStaticDecode number>() } { // readonly const T = Type.Constructor([Type.Readonly(Type.Array(Type.Number()))], Type.Number()) Expect(T).ToStaticDecode number>() } { // optional 1 const T = Type.Constructor([Type.Optional(Type.Number())], Type.Number()) Expect(T).ToStaticDecode number>() } { // optional 2 const T = Type.Constructor([Type.Number(), Type.Optional(Type.Number())], Type.Number()) Expect(T).ToStaticDecode number>() } { // decode 2 const S = Type.Transform(Type.Integer()) .Decode((value) => new Date(value)) .Encode((value) => value.getTime()) const T = Type.Constructor([S], Type.String()) Expect(T).ToStaticDecode string>() } { // decode 1 const S = Type.Transform(Type.Integer()) .Decode((value) => new Date(value)) .Encode((value) => value.getTime()) const T = Type.Constructor([Type.Number()], S) Expect(T).ToStaticDecode Date>() } sinclairzx81-typebox-e0ec98c/test/static/date.ts000066400000000000000000000001611505437577000220110ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Date()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/enum.ts000066400000000000000000000013361505437577000220450ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { // expect all variants enum E { A, B = 'hello', C = 42, } const T = Type.Enum(E) Expect(T).ToStatic() } { // expect all variants const T = Type.Enum({ A: 1, B: 2, C: 3, }) Expect(T).ToStatic<1 | 2 | 3>() } { // expect variant overlap to reduce const T = Type.Enum({ A: 1, B: 2, C: 2, // overlap }) Expect(T).ToStatic<1 | 2>() } { // expect empty enum to be string (as empty enums T[keyof T] evaluates as string) enum E {} const T = Type.Enum(E) Expect(T).ToStatic() } { // expect empty enum to be never const T = Type.Enum({}) Expect(T).ToStaticNever() } sinclairzx81-typebox-e0ec98c/test/static/exclude.ts000066400000000000000000000070061505437577000225320ustar00rootroot00000000000000import { Type, TLiteral, TUnion } from '@sinclair/typebox' import { Expect } from './assert' { const T = Type.Exclude(Type.String(), Type.String()) Expect(T).ToStaticNever() } { const T = Type.Exclude(Type.String(), Type.Number()) Expect(T).ToStatic() } { const T = Type.Exclude(Type.Union([Type.Number(), Type.String(), Type.Boolean()]), Type.Number()) Expect(T).ToStatic() } // ------------------------------------------------------------------------ // TemplateLiteral | TemplateLiteral // ------------------------------------------------------------------------ { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Exclude(A, B) Expect(T).ToStaticNever() } { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Exclude(A, B) Expect(T).ToStatic<'C'>() } { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Exclude(A, B) Expect(T).ToStatic<'C' | 'B'>() } // ------------------------------------------------------------------------ // TemplateLiteral | Union // ------------------------------------------------------------------------ { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Exclude(A, B) Expect(T).ToStaticNever() } { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Exclude(A, B) Expect(T).ToStatic<'C'>() } { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A')]) const T = Type.Exclude(A, B) Expect(T).ToStatic<'C' | 'B'>() } // ------------------------------------------------------------------------ // Union | TemplateLiteral // ------------------------------------------------------------------------ { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Exclude(A, B) Expect(T).ToStaticNever() } { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Exclude(A, B) Expect(T).ToStatic<'C'>() } { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Exclude(A, B) Expect(T).ToStatic<'C' | 'B'>() } // https://github.com/sinclairzx81/typebox/issues/737 { const U = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Object({ type: Type.Exclude(U, Type.Literal('A')), }) Expect(T).ToStatic<{ type: 'B' }>() } { const U = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Object({ type: Type.Exclude(U, Type.Literal('A')), }) Expect(T).ToStatic<{ type: 'B' | 'C' }>() } sinclairzx81-typebox-e0ec98c/test/static/extract.ts000066400000000000000000000072751505437577000225630ustar00rootroot00000000000000import { Type, TLiteral, TUnion } from '@sinclair/typebox' import { Expect } from './assert' { const T = Type.Extract(Type.String(), Type.String()) Expect(T).ToStatic() } { const T = Type.Extract(Type.String(), Type.Number()) Expect(T).ToStaticNever() } { const T = Type.Extract(Type.Union([Type.Number(), Type.String(), Type.Boolean()]), Type.Number()) Expect(T).ToStatic() } // ------------------------------------------------------------------------ // TemplateLiteral | TemplateLiteral // ------------------------------------------------------------------------ { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A' | 'B' | 'C'>() } { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A' | 'B'>() } { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A'>() } // ------------------------------------------------------------------------ // TemplateLiteral | Union // ------------------------------------------------------------------------ { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A' | 'B' | 'C'>() } { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A' | 'B'>() } { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A')]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A'>() } // ------------------------------------------------------------------------ // Union | TemplateLiteral // ------------------------------------------------------------------------ { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A' | 'B' | 'C'>() } { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A' | 'B'>() } { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Extract(A, B) Expect(T).ToStatic<'A'>() } // ------------------------------------------------------------------------ // Nested (Inference Test) // ------------------------------------------------------------------------ { const U = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Object({ type: Type.Extract(U, Type.Literal('A')), }) Expect(T).ToStatic<{ type: 'A' }>() } { const U = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Object({ type: Type.Extract(U, Type.Union([Type.Literal('A'), Type.Literal('B')])), }) Expect(T).ToStatic<{ type: 'A' | 'B' }>() } sinclairzx81-typebox-e0ec98c/test/static/function.ts000066400000000000000000000034311505437577000227240ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { // simple const T = Type.Function([Type.Number(), Type.Boolean()], Type.String()) Expect(T).ToStatic<(param_0: number, param_1: boolean) => string>() } { // nested // prettier-ignore const T = Type.Function([Type.Number(), Type.String()], Type.Object({ method: Type.Function([Type.Number(), Type.String()], Type.Boolean()), })) Expect(T).ToStatic<(param_0: number, param_1: string) => { method: (param_0: number, param_1: string) => boolean }>() } { // readonly-optional const T = Type.Function([Type.ReadonlyOptional(Type.Array(Type.Number()))], Type.Number()) Expect(T).ToStaticDecode<(param_0?: readonly number[]) => number>() } { // readonly const T = Type.Function([Type.Readonly(Type.Array(Type.Number()))], Type.Number()) Expect(T).ToStaticDecode<(param_0: readonly number[]) => number>() } { // optional 1 const T = Type.Function([Type.Optional(Type.Number())], Type.Number()) Expect(T).ToStaticDecode<(param_0?: number) => number>() } { // optional 2 const T = Type.Function([Type.Number(), Type.Optional(Type.Number())], Type.Number()) Expect(T).ToStaticDecode<(param_0: number, param_1?: number) => number>() } const F = Type.Constructor([Type.Readonly(Type.Array(Type.String()))], Type.Number()) { // decode 2 const S = Type.Transform(Type.Integer()) .Decode((value) => new Date(value)) .Encode((value) => value.getTime()) const T = Type.Function([S], Type.String()) Expect(T).ToStaticDecode<(param_0: Date) => string>() } { // decode 1 const S = Type.Transform(Type.Integer()) .Decode((value) => new Date(value)) .Encode((value) => value.getTime()) const T = Type.Function([Type.Number()], S) Expect(T).ToStaticDecode<(param_0: number) => Date>() } sinclairzx81-typebox-e0ec98c/test/static/import.ts000066400000000000000000000072141505437577000224140ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' // ------------------------------------------------------------------ // Enum 1 // ------------------------------------------------------------------ { enum Enum { A, B, } const T = Type.Module({ T: Type.Object({ value: Type.Enum(Enum), }), }).Import('T') Expect(T).ToStatic<{ value: Enum }>() } // ------------------------------------------------------------------ // Enum 2 // ------------------------------------------------------------------ { const T = Type.Module({ T: Type.Object({ value: Type.Enum({ x: 1, y: 2, }), }), }).Import('T') Expect(T).ToStatic<{ value: 1 | 2 }>() } // ------------------------------------------------------------------ // Record 1 // ------------------------------------------------------------------ // prettier-ignore { const T = Type.Module({ R: Type.Object({ x: Type.Number(), y: Type.Number() }), T: Type.Record(Type.String(), Type.Ref('R')), }).Import('T') type T = Static Expect(T).ToStatic<{ [key: string]: { x: number, y: number } }>() } // ------------------------------------------------------------------ // Record 2 // ------------------------------------------------------------------ // prettier-ignore { const T = Type.Module({ R: Type.Object({ x: Type.Number(), y: Type.Number() }), T: Type.Record(Type.String(), Type.Partial(Type.Ref('R'))), }).Import('T') type T = Static Expect(T).ToStatic<{ [key: string]: { x?: number, y?: number } }>() } // ------------------------------------------------------------------ // Modifiers 1 // ------------------------------------------------------------------ // prettier-ignore { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Null()), y: Type.Readonly(Type.Null()), z: Type.Optional(Type.Null()), w: Type.Null() }) }) const T = Module.Import('T') type T = Static Expect(T).ToStatic<{ readonly x?: null, readonly y: null, z?: null, w: null }>() } // ------------------------------------------------------------------ // Modifiers 2 // ------------------------------------------------------------------ // prettier-ignore { const Module = Type.Module({ T: Type.Object({ x: Type.ReadonlyOptional(Type.Array(Type.Null())), y: Type.Readonly(Type.Array(Type.Null())), z: Type.Optional(Type.Array(Type.Null())), w: Type.Array(Type.Null()) }) }) const T = Module.Import('T') type T = Static Expect(T).ToStatic<{ readonly x?: null[], readonly y: null[], z?:null[], w: null[] }>() } // ------------------------------------------------------------------ // Modifiers 3 // ------------------------------------------------------------------ // prettier-ignore { const Module = Type.Module({ T: Type.Object({ x: Type.Array(Type.Null()) }), // Computed Partial U: Type.Partial(Type.Ref('T')) }) const T = Module.Import('U') type T = Static Expect(T).ToStatic<{ x?: null[], }>() } // ------------------------------------------------------------------ // Ref inside Recursive // ------------------------------------------------------------------ // prettier-ignore { const Module = Type.Module({ T: Type.Recursive((_) => Type.Object({ M: Type.Ref("U"), }) ), U: Type.Union([ Type.Literal("A"), Type.Literal("B") ]), }); const T = Module.Import("T"); type T = Static; Expect(T).ToStatic<{ M: 'A'|'B' }>(); } sinclairzx81-typebox-e0ec98c/test/static/index.ts000066400000000000000000000021571505437577000222120ustar00rootroot00000000000000import './any' import './argument' import './array' import './async-iterator' import './awaited' import './bigint' import './boolean' import './capitalize' import './composite' import './const' import './constructor-parameters' import './constructor' import './date' import './deref' import './enum' import './extract' import './exclude' import './function' import './import' import './indexed' import './instance-type' import './intersect' import './iterator' import './keyof' import './literal' import './lowercase' import './mapped' import './modifier' import './namespace' import './never' import './not' import './null' import './number' import './object' import './omit' import './optional' import './parameters' import './partial' import './pick' import './readonly-optional' import './readonly' import './recursive' import './record' import './ref' import './regexp' import './required' import './rest' import './return-type' import './string' import './symbol' import './syntax' import './template-literal' import './transform' import './tuple' import './uncapitalize' import './union' import './unknown' import './uppercase' sinclairzx81-typebox-e0ec98c/test/static/indexed.ts000066400000000000000000000203121505437577000225140ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Object({ x: Type.Number(), y: Type.String(), }) const R = Type.Index(T, ['x', 'y']) type O = Static Expect(R).ToStatic() } { const T = Type.Tuple([Type.Number(), Type.String(), Type.Boolean()]) const R = Type.Index(T, Type.Union([Type.Literal('0'), Type.Literal('1')])) type O = Static Expect(R).ToStatic() } { const T = Type.Tuple([Type.Number(), Type.String(), Type.Boolean()]) const R = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal(1)])) type O = Static Expect(R).ToStatic() } { const T = Type.Object({ ab: Type.Number(), ac: Type.String(), }) const R = Type.Index(T, Type.TemplateLiteral([Type.Literal('a'), Type.Union([Type.Literal('b'), Type.Literal('c')])])) type O = Static Expect(R).ToStatic() } { const A = Type.Tuple([Type.String(), Type.Boolean()]) const R = Type.Index(A, Type.Number()) type O = Static Expect(R).ToStatic() } { const A = Type.Tuple([Type.String()]) const R = Type.Index(A, Type.Number()) type O = Static Expect(R).ToStatic() } { const A = Type.Tuple([]) const R = Type.Index(A, Type.Number()) type O = Static Expect(R).ToStaticNever() } { const A = Type.Object({}) const R = Type.Index(A, Type.BigInt()) // Support Overload type O = Static Expect(R).ToStaticNever() } { const A = Type.Array(Type.Number()) const R = Type.Index(A, Type.BigInt()) // Support Overload type O = Static Expect(R).ToStaticNever() } // ------------------------------------------------------------------ // Intersections // ------------------------------------------------------------------ { type A = { x: string; y: 1 } type B = { x: string; y: number } type C = A & B type R = C['y'] const A = Type.Object({ x: Type.String(), y: Type.Literal(1) }) const B = Type.Object({ x: Type.String(), y: Type.Number() }) const C = Type.Intersect([A, B]) const R = Type.Index(C, ['y']) type O = Static Expect(R).ToStatic<1>() } { type A = { x: string; y: 1 } type B = { x: string; y: number } type C = A & B type R = C['x'] const A = Type.Object({ x: Type.String(), y: Type.Literal(1) }) const B = Type.Object({ x: Type.String(), y: Type.Number() }) const C = Type.Intersect([A, B]) const R = Type.Index(C, ['x']) type O = Static Expect(R).ToStatic() } { type A = { x: string; y: 1 } type B = { x: string; y: number } type C = A & B type R = C['x' | 'y'] const A = Type.Object({ x: Type.String(), y: Type.Literal(1) }) const B = Type.Object({ x: Type.String(), y: Type.Number() }) const C = Type.Intersect([A, B]) const R = Type.Index(C, ['x', 'y']) type O = Static Expect(R).ToStatic() } { type A = { x: string; y: number } type B = { x: number; y: number } type C = A & B type R = C['x'] const A = Type.Object({ x: Type.String(), y: Type.Number() }) const B = Type.Object({ x: Type.Number(), y: Type.Number() }) const C = Type.Intersect([A, B]) const R = Type.Index(C, ['x']) type O = Static Expect(R).ToStaticNever() } { type A = { x: string; y: number } type B = { x: number; y: number } type C = A & B type R = C['y'] const A = Type.Object({ x: Type.String(), y: Type.Number() }) const B = Type.Object({ x: Type.Number(), y: Type.Number() }) const C = Type.Intersect([A, B]) const R = Type.Index(C, ['y']) type O = Static Expect(R).ToStatic() } { type A = { x: string; y: number } type B = { x: number; y: number } type C = A & B type R = C['x' | 'y'] const A = Type.Object({ x: Type.String(), y: Type.Number() }) const B = Type.Object({ x: Type.Number(), y: Type.Number() }) const C = Type.Intersect([A, B]) const R = Type.Index(C, ['x', 'y']) type O = Static Expect(R).ToStatic() } { type A = { x: string; y: 1 } type B = { x: string; y: number } type C = { x: string; y: number } type D = { x: string } type I = (A & B) & (C & D) type R = I['x' | 'y'] const A = Type.Object({ x: Type.String(), y: Type.Literal(1) }) const B = Type.Object({ x: Type.String(), y: Type.Number() }) const C = Type.Object({ x: Type.String(), y: Type.Number() }) const D = Type.Object({ x: Type.String() }) const I = Type.Intersect([Type.Intersect([A, B]), Type.Intersect([C, D])]) const R = Type.Index(I, ['x', 'y']) type O = Static Expect(R).ToStatic() } { type A = { x: string; y: 1 } type B = { x: number; y: number } type C = { x: string; y: number } type D = { x: string } type I = (A & B) & (C & D) type R = I['x' | 'y'] const A = Type.Object({ x: Type.String(), y: Type.Literal(1) }) const B = Type.Object({ x: Type.Number(), y: Type.Number() }) const C = Type.Object({ x: Type.String(), y: Type.Number() }) const D = Type.Object({ x: Type.String() }) const I = Type.Intersect([Type.Intersect([A, B]), Type.Intersect([C, D])]) const R = Type.Index(I, ['x', 'y']) // TUnion<[TIntersect<[TIntersect<[TString, TNumber]>, TIntersect<[TString, TString]>]>, TIntersect<[TIntersect<[TLiteral<...>, TNumber]>, TNumber]>]> // TUnion<[TUnion<[TString, TNumber, TString, TString]>, TUnion<[TLiteral<1>, TNumber, TNumber]>]> type O = Static Expect(R).ToStatic<1>() } { type A = { x: string; y: 1 } type B = { x: number; y: number } type C = { x: string; y: number } type D = { x: string } type I = (A | B) & (C & D) type R = I['x' | 'y'] const A = Type.Object({ x: Type.String(), y: Type.Literal(1) }) const B = Type.Object({ x: Type.Number(), y: Type.Number() }) const C = Type.Object({ x: Type.String(), y: Type.Number() }) const D = Type.Object({ x: Type.String() }) const I = Type.Intersect([Type.Union([A, B]), Type.Intersect([C, D])]) const R = Type.Index(I, ['x', 'y']) // TUnion<[TIntersect<[TUnion<[TString, TNumber]>, TIntersect<[TString, TIntersect<[TString, TIntersect<[]>]>, TIntersect<[]>]>]>, TIntersect<...>]> // TUnion<[TIntersect<[TUnion<[TString, TNumber]>, TIntersect<[TString, TString]>]>, TIntersect<[TUnion<[TLiteral<1>, TNumber]>, TNumber]>]> // TUnion<[TIntersect<[TUnion<[TString, TNumber]>, TString, TString]>, TIntersect<[TUnion<[TLiteral<1>, TNumber]>, TNumber]>]> type O = Static Expect(R).ToStatic() } { type A = { x: 'A'; y: 1 } type B = { x: 'B'; y: number } type C = { x: 'C'; y: number } type D = { x: 'D' } type I = A | B | C | D type R = I['x'] const A = Type.Object({ x: Type.Literal('A'), y: Type.Literal(1) }) const B = Type.Object({ x: Type.Literal('B'), y: Type.Number() }) const C = Type.Object({ x: Type.Literal('C'), y: Type.Number() }) const D = Type.Object({ x: Type.Literal('D') }) const I = Type.Union([A, B, C, D]) const R = Type.Index(I, ['x']) type O = Static Expect(R).ToStatic<'A' | 'B' | 'C' | 'D'>() } { type I = { x: string y: number z: I } type R = I['x' | 'y' | 'z'] const I = Type.Recursive((This) => Type.Object({ x: Type.String(), y: Type.Number(), z: This, }), ) const R = Type.Index(I, ['x', 'y', 'z']) // z unresolvable type O = Static Expect(R).ToStatic() } // ------------------------------------------------ // Numeric | String Variants // ------------------------------------------------ { const T = Type.Object({ 0: Type.Number(), '1': Type.String(), }) const R = Type.Index(T, [0, '1']) type O = Static Expect(R).ToStatic() } { const T = Type.Object({ '0': Type.Number(), '1': Type.String(), }) const R = Type.Index(T, Type.KeyOf(T)) type O = Static Expect(R).ToStatic() } { const P = Type.Tuple([Type.Number(), Type.String()]) const R = Type.Object({ x: Type.Index(P, [0, 1]), }) Expect(R).ToStatic<{ x: number | string }>() } { const T = Type.Array(Type.String()) const I = Type.Index(T, Type.Number()) Expect(I).ToStatic() } { const T = Type.Array(Type.String()) const I = Type.Index(T, ['[number]']) Expect(I).ToStatic() } sinclairzx81-typebox-e0ec98c/test/static/intersect.ts000066400000000000000000000025141505437577000231000ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const A = Type.Object({ A: Type.String(), B: Type.String(), }) const B = Type.Object({ X: Type.Number(), Y: Type.Number(), }) const T = Type.Intersect([A, B]) Expect(T).ToStatic< { A: string B: string } & { X: number Y: number } >() } { const A = Type.Object({ A: Type.Optional(Type.String()), }) const B = Type.Object({ B: Type.String(), }) const T = Type.Intersect([A, B]) Expect(T).ToStatic<{ A?: string | undefined } & { B: string }>() } // https://github.com/sinclairzx81/typebox/issues/113 // https://github.com/sinclairzx81/typebox/issues/187 { const A = Type.Object({ A: Type.String() }) const B = Type.Object({ B: Type.String() }) const C = Type.Object({ C: Type.String() }) const T = Type.Intersect([A, Type.Union([B, C])]) type T = Static const _0: T = { A: '', B: '' } const _1: T = { A: '', C: '' } const _3: T = { A: '', B: '', C: '' } // invert equivelence (expect true both cases) type T1 = T extends { A: string } & ({ B: string } | { C: string }) ? true : false type T2 = { A: string } & ({ B: string } | { C: string }) extends T ? true : false Expect(T).ToStatic<{ A: string } & ({ B: string } | { C: string })>() // solved! } sinclairzx81-typebox-e0ec98c/test/static/iterator.ts000066400000000000000000000002261505437577000227270ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Iterator(Type.String())).ToStatic>() sinclairzx81-typebox-e0ec98c/test/static/keyof.ts000066400000000000000000000035141505437577000222160ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { const K = Type.KeyOf( Type.Object({ A: Type.Null(), B: Type.Null(), C: Type.Null(), }), ) Expect(K).ToStatic<'A' | 'B' | 'C'>() } { const T = Type.Pick( Type.Object({ A: Type.Null(), B: Type.Null(), C: Type.Null(), }), ['A', 'B'], ) const K = Type.KeyOf(T) Expect(K).ToStatic<'A' | 'B'>() } { const T = Type.Omit( Type.Object({ A: Type.Null(), B: Type.Null(), C: Type.Null(), }), ['A', 'B'], ) const K = Type.KeyOf(T) Expect(K).ToStatic<'C'>() } { const T = Type.KeyOf( Type.Omit( Type.Object({ A: Type.Null(), B: Type.Null(), C: Type.Null(), }), ['A', 'B'], ), ) Expect(T).ToStatic<'C'>() } { { const A = Type.Object({ type: Type.Literal('A') }) const B = Type.Object({ type: Type.Literal('B') }) const C = Type.Object({ type: Type.Literal('C') }) const Union = Type.Union([A, B, C]) const Extended = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const T = Type.Intersect([Union, Extended]) const K1 = Type.KeyOf(T) Expect(K1).ToStatic<'type' | 'x' | 'y' | 'z'>() const P = Type.Omit(T, ['type', 'x']) const K2 = Type.KeyOf(P) Expect(K2).ToStatic<'y' | 'z'>() } } { const T = Type.Recursive((Self) => Type.Object({ a: Type.String(), b: Type.String(), c: Type.String(), d: Type.Array(Self), }), ) const K = Type.KeyOf(T) Expect(K).ToStatic<'a' | 'b' | 'c' | 'd'>() } { const T = Type.Object({ a: Type.Optional(Type.String()), b: Type.Optional(Type.String()), c: Type.Optional(Type.String()), }) const K = Type.KeyOf(T) Expect(K).ToStatic<'a' | 'b' | 'c'>() } sinclairzx81-typebox-e0ec98c/test/static/literal.ts000066400000000000000000000003241505437577000225310ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Literal('hello')).ToStatic<'hello'>() Expect(Type.Literal(true)).ToStatic() Expect(Type.Literal(42)).ToStatic<42>() sinclairzx81-typebox-e0ec98c/test/static/lowercase.ts000066400000000000000000000011531505437577000230620ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Lowercase(Type.Literal('HELLO'))).ToStatic<'hello'>() Expect(Type.Lowercase(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')]))).ToStatic<'hello' | 'world'>() Expect(Type.Lowercase(Type.TemplateLiteral('HELLO${0|1}'))).ToStatic<'hello0' | 'hello1'>() // prettier-ignore Expect(Type.Lowercase(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(1), Type.Literal(2)])]))).ToStatic<'hello1' | 'hello2'>() // passthrough Expect(Type.Lowercase(Type.Object({ x: Type.Number() }))).ToStatic<{ x: number }>() sinclairzx81-typebox-e0ec98c/test/static/mapped.ts000066400000000000000000000240521505437577000223470ustar00rootroot00000000000000import { Expect } from './assert' import { Static, Type } from '@sinclair/typebox' // prettier-ignore { // Generative const A = Type.Mapped(Type.Union([ Type.Literal('x'), Type.Literal('y'), Type.Literal('z'), ]), K => Type.Number()) Expect(A).ToStatic<{ x: number, y: number, z: number }> const B = Type.Mapped(Type.TemplateLiteral('${0|1}${0|1}'), K => Type.Number()) Expect(B).ToStatic<{ '00': number, '01': number, '10': number, '11': number, }> } // prettier-ignore { // Generative Nested const T = Type.Mapped(Type.TemplateLiteral('${a|b}'), X => Type.Mapped(Type.TemplateLiteral('${c|d}'), Y => Type.Mapped(Type.TemplateLiteral('${e|f}'), Z => Type.Tuple([X, Y, Z]) ) ) ) type E = { [X in `${'a' | 'b'}`]: { [Y in `${'c' | 'd'}`]: { [Z in `${'e' | 'f'}`]: [X, Y, Z] } } } Expect(T).ToStatic // ok } // prettier-ignore { // Identity const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const A = Type.Mapped(Type.KeyOf(T), K => K) Expect(A).ToStatic<{ x: 'x', y: 'y', z: 'z' }>() const B = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K)) Expect(B).ToStatic<{ x: number, y: string, z: boolean }>() } // prettier-ignore { // Extract const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const A = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.String()) }) Expect(A).ToStatic<{ x: string }> const B = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.Union([ Type.String(), Type.Number() ])) }) Expect(B).ToStatic<{ x: string | number }> const C = Type.Mapped(Type.KeyOf(T), K => { return Type.Extract(Type.Index(T, K), Type.Null()) }) Expect(C).ToStatic<{ x: never }> } // prettier-ignore { // Numeric Keys const T = Type.Object({ 0: Type.Number(), 1: Type.Number(), 2: Type.Number() }) const A = Type.Mapped(Type.KeyOf(T), K => Type.Index(T, K)) Expect(A).ToStatic<{ 0: number, 1: number, 2: number }> } // prettier-ignore { // Extends const T = Type.Object({ x: Type.Number(), y: Type.String(), z: Type.Boolean() }) const A = Type.Mapped(Type.KeyOf(T), K => { return ( Type.Extends(K, Type.Literal('x'), Type.Literal(1), Type.Extends(K, Type.Literal('y'), Type.Literal(2), Type.Extends(K, Type.Literal('z'), Type.Literal(3), Type.Never()))) ) }) Expect(A).ToStatic<{ x: 1, y: 2, z: 3 }> const B = Type.Mapped(Type.KeyOf(T), K => { return ( Type.Extends(Type.Index(T, K), Type.Number(), Type.Literal(3), Type.Extends(Type.Index(T, K), Type.String(), Type.Literal(2), Type.Extends(Type.Index(T, K), Type.Boolean(), Type.Literal(1), Type.Never()))) ) }) Expect(B).ToStatic<{ x: 3, y: 2, z: 1 }> } // prettier-ignore { // Exclude const T = Type.Object({ x: Type.Union([Type.String(), Type.Number(), Type.Boolean()]) }) const A = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.String()) }) Expect(A).ToStatic<{ x: number | boolean }> const B = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.Union([ Type.String(), Type.Number() ])) }) Expect(B).ToStatic<{ x: boolean }> const C = Type.Mapped(Type.KeyOf(T), K => { return Type.Exclude(Type.Index(T, K), Type.Null()) }) Expect(C).ToStatic<{ x: string | number | boolean }> } // prettier-ignore { // Non-Evaluated Indexed const T = Type.Object({ x: Type.Number() }) const A = Type.Mapped(Type.KeyOf(T), K => Type.Array(Type.Index(T, K))) Expect(A).ToStatic<{ x: number[] }> const B = Type.Mapped(Type.KeyOf(T), K => Type.Promise(Type.Index(T, K))) Expect(B).ToStatic<{ x: Promise }> const C = Type.Mapped(Type.KeyOf(T), K => Type.Function([Type.Index(T, K)], Type.Index(T, K))) Expect(C).ToStatic<{ x: (x: number) => number }> const D = Type.Mapped(Type.KeyOf(T), K => Type.Tuple([Type.Index(T, K), Type.Index(T, K)])) Expect(D).ToStatic<{ x: [number, number] }> const E = Type.Mapped(Type.KeyOf(T), K => Type.Union([Type.Index(T, K)])) Expect(E).ToStatic<{ x: number }> const F = Type.Mapped(Type.KeyOf(T), K => Type.Intersect([Type.Index(T, K)])) Expect(F).ToStatic<{ x: number }> } // prettier-ignore { // Modifiers const T = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Number() }) // Additive const A = Type.Mapped(Type.KeyOf(T), K => Type.Optional(Type.Index(T, K), true)) Expect(A).ToStatic<{ x?: number, y?: number}>() // Subtractive const S = Type.Mapped(Type.KeyOf(T), K => Type.Optional(Type.Index(T, K), false)) Expect(S).ToStatic<{ x: number, y: number}>() } // prettier-ignore { // Modifiers const T = Type.Object({ x: Type.Readonly(Type.Number()), y: Type.Number() }) // Additive const A = Type.Mapped(Type.KeyOf(T), K => Type.Readonly(Type.Index(T, K), true)) Expect(A).ToStatic<{ readonly x: number, readonly y: number}>() // Subtractive const S = Type.Mapped(Type.KeyOf(T), K => Type.Readonly(Type.Index(T, K), false)) Expect(S).ToStatic<{ x: number, y: number}>() } // ------------------------------------------------------------------ // Finite Boolean // ------------------------------------------------------------------ { const T = Type.TemplateLiteral('${boolean}') const M = Type.Mapped(T, (K) => K) Expect(M).ToStatic<{ true: 'true' false: 'false' }> } { const T = Type.TemplateLiteral('${0|1}${boolean}') const M = Type.Mapped(T, (K) => K) Expect(M).ToStatic<{ '0true': '0true' '0false': '0false' '1true': '1true' '1false': '1false' }> } { const T = Type.TemplateLiteral('${boolean}${0|1}') const M = Type.Mapped(T, (K) => K) Expect(M).ToStatic<{ true0: 'true0' false0: 'false0' true1: 'true1' false1: 'false1' }> } { const T = Type.TemplateLiteral([Type.Union([Type.Literal(0), Type.Literal(1)]), Type.Union([Type.Literal(0), Type.Literal(1)])]) const M = Type.Mapped(T, (K) => K) Expect(M).ToStatic<{ '00': '00' '01': '01' '10': '10' '11': '11' }> } { const T = Type.Object({ hello: Type.Number(), world: Type.String(), }) const M = Type.Mapped(Type.Uppercase(Type.KeyOf(T)), (K) => { return Type.Index(T, Type.Lowercase(K)) }) Expect(M).ToStatic<{ HELLO: number WORLD: string }> } // ------------------------------------------------------------------ // Interior Partial // ------------------------------------------------------------------ { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Partial(Type.Index(T, K)) }) Expect(M).ToStatic<{ x: { x?: number; y?: number } y: { x?: number; y?: number } }> } // ------------------------------------------------------------------ // Interior Required // ------------------------------------------------------------------ { const T = Type.Object({ x: Type.Partial( Type.Object({ x: Type.Number(), y: Type.Number(), }), ), y: Type.Partial( Type.Object({ x: Type.Number(), y: Type.Number(), }), ), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Required(Type.Index(T, K)) }) Expect(M).ToStatic<{ x: { x: number; y: number } y: { x: number; y: number } }> } // ------------------------------------------------------------------ // Pick With Key // ------------------------------------------------------------------ // prettier-ignore { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number() }), y: Type.Object({ x: Type.Number(), y: Type.Number() }) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Pick(T, K) }) Expect(M).ToStatic<{ x: { x: { x: number; y: number; }; }; y: { y: { x: number; y: number; }; }; }> } // ------------------------------------------------------------------ // Pick With Result // ------------------------------------------------------------------ { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Pick(Type.Index(T, K), ['x']) }) Expect(M).ToStatic<{ x: { x: number } y: { x: number } }> } // ------------------------------------------------------------------ // Omit With Key // ------------------------------------------------------------------ // prettier-ignore { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number() }), y: Type.Object({ x: Type.Number(), y: Type.Number() }) }) const M = Type.Mapped(Type.KeyOf(T), K => { return Type.Omit(T, K) }) Expect(M).ToStatic<{ x: { y: { x: number; y: number; }; }; y: { x: { x: number; y: number; }; }; }> } // ------------------------------------------------------------------ // Omit With Result // ------------------------------------------------------------------ { const T = Type.Object({ x: Type.Object({ x: Type.Number(), y: Type.Number(), }), y: Type.Object({ x: Type.Number(), y: Type.Number(), }), }) const M = Type.Mapped(Type.KeyOf(T), (K) => { return Type.Omit(Type.Index(T, K), ['x']) }) Expect(M).ToStatic<{ x: { y: number } y: { y: number } }> } // ------------------------------------------------------------------ // With Enum // issue: https://github.com/sinclairzx81/typebox/issues/897 // ------------------------------------------------------------------ { enum E { A, B, } const T = Type.Object({ a: Type.Enum(E) }) const M = Type.Mapped(Type.KeyOf(T), (K) => Type.Index(T, K)) Expect(M).ToStatic<{ a: E }> } sinclairzx81-typebox-e0ec98c/test/static/modifier.ts000066400000000000000000000006201505437577000226720ustar00rootroot00000000000000import { Expect } from './assert' import { Type, TSchema } from '@sinclair/typebox' // Asserts combinatory modifiers { const T = Type.Object({ A: Type.ReadonlyOptional(Type.String()), B: Type.Readonly(Type.String()), C: Type.Optional(Type.String()), D: Type.String(), }) Expect(T).ToStatic<{ readonly A?: string readonly B: string C?: string D: string }>() } sinclairzx81-typebox-e0ec98c/test/static/never.ts000066400000000000000000000002051505437577000222120ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { const T = Type.Never() Expect(T).ToStaticNever() } sinclairzx81-typebox-e0ec98c/test/static/not.ts000066400000000000000000000017131505437577000217000ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { // ------------------------------------------------------------------------- // Issue: type T = number extends not number ? true : false // true // type T = number extends unknown ? true : false // true // // TypeScript does not support type negation. The best TypeBox can do is // treat "not" as "unknown". From this standpoint, the extends assignability // check needs to return true for the following case to keep TypeBox aligned // with TypeScript static inference. // ------------------------------------------------------------------------- const A = Type.Number() const B = Type.Not(Type.Number()) const T = Type.Extends(A, B, Type.Literal(true), Type.Literal(false)) Expect(T).ToStatic() } { const T = Type.Not(Type.Number()) Expect(T).ToStatic() } { const T = Type.Not(Type.Not(Type.Number())) Expect(T).ToStatic() } sinclairzx81-typebox-e0ec98c/test/static/null.ts000066400000000000000000000001611505437577000220460ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Null()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/number.ts000066400000000000000000000001651505437577000223700ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Number()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/object.ts000066400000000000000000000021271505437577000223460ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { const T = Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }) Expect(T).ToStatic<{ A: string B: string C: string }>() } { const T = Type.Object({ A: Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }), B: Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }), C: Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }), }) Expect(T).ToStatic<{ A: { A: string B: string C: string } B: { A: string B: string C: string } C: { A: string B: string C: string } }>() } { const T = Type.Object( { A: Type.Number(), B: Type.Number(), C: Type.Number(), }, { additionalProperties: Type.Boolean(), }, ) // note: Pending TypeScript support for negated types. Expect(T).ToStatic<{ A: number B: number C: number }>() } sinclairzx81-typebox-e0ec98c/test/static/omit.ts000066400000000000000000000032171505437577000220510ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const A = Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }) const T = Type.Omit(A, ['A', 'B']) type T = Static Expect(T).ToStatic<{ C: string }>() } { const A = Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }) const keys = ['A', 'B'] as const const T = Type.Omit(A, keys) type T = Static Expect(T).ToStatic<{ C: string }>() } { const A = Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }) const B = Type.Object({ A: Type.String(), B: Type.String(), }) const T = Type.Omit(A, Type.KeyOf(B)) type T = Static Expect(T).ToStatic<{ C: string }>() } { const A = Type.Object({ type: Type.Literal('A') }) const B = Type.Object({ type: Type.Literal('B') }) const C = Type.Object({ type: Type.Literal('C') }) const Union = Type.Union([A, B, C]) const Extended = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const T = Type.Intersect([Union, Extended]) Expect(T).ToStatic< ( | { type: 'A' } | { type: 'B' } | { type: 'C' } ) & { x: number y: number z: number } >() const P = Type.Omit(T, ['type', 'x']) Expect(P).ToStatic< ({} | {} | {}) & { y: number z: number } >() const O = Type.Partial(P) Expect(O).ToStatic< ({} | {} | {}) & { y?: number | undefined z?: number | undefined } >() } sinclairzx81-typebox-e0ec98c/test/static/optional.ts000066400000000000000000000014301505437577000227210ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Object({ A: Type.Optional(Type.String()), }) type T = Static Expect(T).ToStatic<{ A?: string }>() } // Noop // prettier-ignore { const T = Type.Object({ A: Type.Optional(Type.String(), false), }) type T = Static Expect(T).ToStatic<{ A: string }>() } // Additive // prettier-ignore { const T = Type.Object({ A: Type.Optional(Type.String(), true), }) type T = Static Expect(T).ToStatic<{ A?: string }>() } // Subtractive // prettier-ignore { const T = Type.Object({ A: Type.Optional(Type.Optional(Type.String()), false) }) type T = Static Expect(T).ToStatic<{ A: string }>() } sinclairzx81-typebox-e0ec98c/test/static/parameters.ts000066400000000000000000000004601505437577000232410ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' const C = Type.Function( [Type.Number(), Type.String()], Type.Object({ method: Type.Function([Type.Number(), Type.String()], Type.Boolean()), }), ) const P = Type.Parameters(C) Expect(P).ToStatic<[number, string]>() sinclairzx81-typebox-e0ec98c/test/static/partial.ts000066400000000000000000000044571505437577000225440ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' import * as Types from '@sinclair/typebox' { const T = Type.Partial( Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }), ) type T = Static Expect(T).ToStatic<{ A?: string B?: string C?: string }>() } { { const A = Type.Object({ type: Type.Literal('A') }) const B = Type.Object({ type: Type.Literal('B') }) const C = Type.Object({ type: Type.Literal('C') }) const Union = Type.Union([A, B, C]) const Extended = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const T = Type.Intersect([Union, Extended]) Expect(T).ToStatic< ( | { type: 'A' } | { type: 'B' } | { type: 'C' } ) & { x: number y: number z: number } >() const P = Type.Partial(T) Expect(P).ToStatic< ( | { type?: 'A' | undefined } | { type?: 'B' | undefined } | { type?: 'C' | undefined } ) & { x?: number | undefined y?: number | undefined z?: number | undefined } >() } } { // https://github.com/sinclairzx81/typebox/issues/655 const T = Type.Object({ a: Type.ReadonlyOptional(Type.Number()), b: Type.Readonly(Type.Number()), c: Type.Optional(Type.Number()), d: Type.Number(), }) const R: Types.TObject<{ a: Types.TReadonlyOptional b: Types.TReadonlyOptional c: Types.TOptional d: Types.TOptional }> = Type.Partial(T) } // ------------------------------------------------------------------ // Intrinsic Passthough // https://github.com/sinclairzx81/typebox/issues/1169 // ------------------------------------------------------------------ // prettier-ignore { const T = Type.Partial(Type.Union([Type.Number(), Type.Object({ x: Type.Number() })])) Expect(T).ToStatic } // prettier-ignore { const T = Type.Partial(Type.Union([Type.Literal(1), Type.Object({ x: Type.Number() })])) Expect(T).ToStatic<1 | { x?: number }> } sinclairzx81-typebox-e0ec98c/test/static/pick.ts000066400000000000000000000037501505437577000220310ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const A = Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }) const T = Type.Pick(A, ['A', 'B']) type T = Static Expect(T).ToStatic<{ A: string B: string }>() } { const A = Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }) const keys = ['A', 'B'] as const const T = Type.Pick(A, ['A', 'B']) type T = Static Expect(T).ToStatic<{ A: string B: string }>() } { const A = Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }) const B = Type.Object({ A: Type.String(), B: Type.String(), }) const T = Type.Pick(A, Type.KeyOf(B)) type T = Static Expect(T).ToStatic<{ A: string B: string }>() } { const A = Type.Object({ type: Type.Literal('A') }) const B = Type.Object({ type: Type.Literal('B') }) const C = Type.Object({ type: Type.Literal('C') }) const Union = Type.Union([A, B, C]) const Extended = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const T = Type.Intersect([Union, Extended]) Expect(T).ToStatic< ( | { type: 'A' } | { type: 'B' } | { type: 'C' } ) & { x: number y: number z: number } >() const K = Type.KeyOf(T) Expect(K).ToStatic<'type' | 'x' | 'y' | 'z'>() const P = Type.Pick(T, ['type', 'x']) Expect(P).ToStatic< ( | { type: 'A' } | { type: 'B' } | { type: 'C' } ) & { x: number } >() const O = Type.Partial(P) Expect(O).ToStatic< ( | { type?: 'A' | undefined } | { type?: 'B' | undefined } | { type?: 'C' | undefined } ) & { x?: number | undefined } >() } sinclairzx81-typebox-e0ec98c/test/static/readonly-optional.ts000066400000000000000000000011351505437577000245360ustar00rootroot00000000000000import { Expect } from './assert' import { Type, TSchema, TReadonlyOptional } from '@sinclair/typebox' { const T = Type.Object({ A: Type.ReadonlyOptional(Type.String()), }) Expect(T).ToStatic<{ readonly A?: string }>() } { const T = Type.ReadonlyOptional(Type.String()) function test(_: TReadonlyOptional) {} test(T) } { const T = Type.Readonly(Type.String()) function test(_: TReadonlyOptional) {} // @ts-expect-error test(T) } { const T = Type.Optional(Type.String()) function test(_: TReadonlyOptional) {} // @ts-expect-error test(T) } sinclairzx81-typebox-e0ec98c/test/static/readonly.ts000066400000000000000000000014511505437577000227140ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Object({ A: Type.Readonly(Type.String()), }) type T = Static Expect(T).ToStatic<{ readonly A: string }>() } // Noop // prettier-ignore { const T = Type.Object({ A: Type.Readonly(Type.String(), false), }) type T = Static Expect(T).ToStatic<{ A: string }>() } // Additive // prettier-ignore { const T = Type.Object({ A: Type.Readonly(Type.String(), true), }) type T = Static Expect(T).ToStatic<{ readonly A: string }>() } // Subtractive // prettier-ignore { const T = Type.Object({ A: Type.Readonly(Type.Readonly(Type.String()), false) }) type T = Static Expect(T).ToStatic<{ A: string }>() } sinclairzx81-typebox-e0ec98c/test/static/record.ts000066400000000000000000000233461505437577000223640ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { // type K = string const K = Type.String() const T = Type.Record(K, Type.Number()) type T = Static Expect(T).ToStatic>() } { // type K = string const K = Type.RegExp(/foo|bar/) const T = Type.Record(K, Type.Number()) type T = Static Expect(T).ToStatic>() } { // type K = number const K = Type.Number() const T = Type.Record(K, Type.Number()) type T = Static Expect(T).ToStatic>() } { // type K = 'A' | 'B' | 'C' const K = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Record(K, Type.Number()) type T = Static Expect(T).ToStatic>() } { // type K = keyof { A: number, B: number, C: number } const K = Type.KeyOf( Type.Object({ A: Type.Number(), B: Type.Number(), C: Type.Number(), }), ) const T = Type.Record(K, Type.Number()) type T = Static Expect(T).ToStatic>() } { // type K = keyof Omit<{ A: number, B: number, C: number }, 'C'> const K = Type.KeyOf( Type.Omit( Type.Object({ A: Type.Number(), B: Type.Number(), C: Type.Number(), }), ['C'], ), ) const T = Type.Record(K, Type.Number()) type T = Static Expect(T).ToStatic>() } { const T = Type.Record(Type.Number(), Type.String()) Expect(T).ToStatic>() } { const T = Type.Record(Type.Integer(), Type.String()) Expect(T).ToStatic>() } { // Should support enum keys 1 enum E { A = 'X', B = 'Y', C = 'Z', } const T = Type.Record(Type.Enum(E), Type.Number()) Expect(T).ToStatic<{ X: number Y: number Z: number }>() } { // Should support enum keys 2 enum E { A, B, C, } const T = Type.Record(Type.Enum(E), Type.Number()) Expect(T).ToStatic<{ 0: number 1: number 2: number }>() } { // Should support enum keys 3 enum E { A = 1, B = '2', C = 'Z', } const T = Type.Record(Type.Enum(E), Type.Number()) Expect(T).ToStatic<{ 1: number 2: number Z: number }>() } { // should support infinite record keys // https://github.com/sinclairzx81/typebox/issues/604 const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) Expect(R).ToStatic>() } { // should support infinite record keys with intersect // https://github.com/sinclairzx81/typebox/issues/604 const K = Type.TemplateLiteral('key${number}') const R = Type.Record(K, Type.Number()) const T = Type.Object({ x: Type.Number(), y: Type.Number() }) const I = Type.Intersect([R, T]) Expect(I).ToStatic & { x: number; y: number }>() } { // expect T as Object enum E { A, B, C, } const T = Type.Record(Type.Enum(E), Type.Number()) Expect(T).ToStatic<{ 0: number 1: number 2: number }> } { // expect T as Partial Object enum E { A, B, C, } const T = Type.Partial(Type.Record(Type.Enum(E), Type.Number())) Expect(T).ToStatic<{ 0?: number 1?: number 2?: number }> } { // expect T to support named properties enum E { A = 'A', B = 'B', C = 'C', } const T = Type.Record(Type.Enum(E), Type.Number()) Expect(T).ToStatic<{ A: number B: number C: number }> } { // expect T to support named properties enum E {} const T = Type.Record(Type.Enum(E), Type.Number()) Expect(T).ToStatic<{ [x: string]: number }> } // ------------------------------------------------------------------ // Dollar Sign Escape // https://github.com/sinclairzx81/typebox/issues/794 // ------------------------------------------------------------------ // prettier-ignore { const K = Type.TemplateLiteral('$prop${A|B|C}') // issue const T = Type.Record(K, Type.String()) Expect(T).ToStatic<{ '$propA': string, '$propB': string, '$propC': string }>() } // ------------------------------------------------------------------ // https://github.com/sinclairzx81/typebox/issues/916 // ------------------------------------------------------------------ { const K = Type.Any() const T = Type.Record(K, Type.String()) Expect(T).ToStatic>() } { const K = Type.Never() const T = Type.Record(K, Type.String()) Expect(T).ToStatic<{}>() } // ------------------------------------------------------------------ // Deep Union // https://github.com/sinclairzx81/typebox/issues/1208 // ------------------------------------------------------------------ // prettier-ignore { const A = Type.Record(Type.Union([ Type.Literal(0), Type.Literal(1), Type.Literal(2), Type.Literal(3), Type.Literal(4), Type.Literal(5), Type.Literal(6), Type.Literal(7), Type.Literal(8), Type.Literal(9), Type.Literal(10), Type.Literal(11), Type.Literal(12), Type.Literal(13), Type.Literal(14), Type.Literal(15), Type.Literal(16), Type.Literal(17), Type.Literal(18), Type.Literal(19), Type.Literal(20), Type.Literal(21), Type.Literal(22), Type.Literal(23), Type.Literal(24), Type.Literal(25), Type.Literal(26), Type.Literal(27), Type.Literal(28), Type.Literal(29), Type.Literal(30), Type.Literal(31), Type.Literal(32), Type.Literal(33), Type.Literal(34), Type.Literal(35), Type.Literal(36), Type.Literal(37), Type.Literal(38), Type.Literal(39), Type.Literal(40), Type.Literal(41), Type.Literal(42), Type.Literal(43), Type.Literal(44), Type.Literal(45), Type.Literal(46), Type.Literal(47), Type.Literal(48), Type.Literal(49), Type.Literal(50), Type.Literal(51), Type.Literal(52), Type.Literal(53), Type.Literal(54), Type.Literal(55), Type.Literal(56), Type.Literal(57), Type.Literal(58), Type.Literal(59), Type.Literal(60), Type.Literal(61), Type.Literal(62), Type.Literal(63), // <- x64 Type.Literal(64), Type.Literal(65), Type.Literal(66), Type.Literal(67), Type.Literal(68), Type.Literal(69), Type.Literal(70), Type.Literal(71), Type.Literal(72), Type.Literal(73), Type.Literal(74), Type.Literal(75), Type.Literal(76), Type.Literal(77), Type.Literal(78), Type.Literal(79), Type.Literal(80), Type.Literal(81), Type.Literal(82), Type.Literal(83), Type.Literal(84), Type.Literal(85), Type.Literal(86), Type.Literal(87), Type.Literal(88), Type.Literal(89), Type.Literal(90), Type.Literal(91), Type.Literal(92), Type.Literal(93), Type.Literal(94), Type.Literal(95), Type.Literal(96), Type.Literal(97), Type.Literal(98), Type.Literal(99), Type.Literal(100), Type.Literal(101), Type.Literal(102), Type.Literal(103), Type.Literal(104), Type.Literal(105), Type.Literal(106), Type.Literal(107), Type.Literal(108), Type.Literal(109), Type.Literal(110), Type.Literal(111), Type.Literal(112), Type.Literal(113), Type.Literal(114), Type.Literal(115), Type.Literal(116), Type.Literal(117), Type.Literal(118), Type.Literal(119), Type.Literal(120), Type.Literal(121), Type.Literal(122), Type.Literal(123), Type.Literal(124), Type.Literal(125), Type.Literal(126), Type.Literal(127), // <- x128 ]), Type.String()) const B = Type.Record(Type.Union([ Type.Union([ Type.Literal(0), Type.Literal(1), Type.Literal(2), Type.Literal(3), Type.Literal(4), Type.Literal(5), Type.Literal(6), Type.Literal(7), Type.Literal(8), Type.Literal(9), Type.Literal(10), Type.Literal(11), Type.Literal(12), Type.Literal(13), Type.Literal(14), Type.Literal(15), Type.Literal(16), Type.Literal(17), Type.Literal(18), Type.Literal(19), Type.Literal(20), Type.Literal(21), Type.Literal(22), Type.Literal(23), Type.Literal(24), Type.Literal(25), Type.Literal(26), Type.Literal(27), Type.Literal(28), Type.Literal(29), Type.Literal(30), Type.Literal(31), ]), Type.Union([ Type.Literal(32), Type.Literal(33), Type.Literal(34), Type.Literal(35), Type.Literal(36), Type.Literal(37), Type.Literal(38), Type.Literal(39), Type.Literal(40), Type.Literal(41), Type.Literal(42), Type.Literal(43), Type.Literal(44), Type.Literal(45), Type.Literal(46), Type.Literal(47), Type.Literal(48), Type.Literal(49), Type.Literal(50), Type.Literal(51), Type.Literal(52), Type.Literal(53), Type.Literal(54), Type.Literal(55), Type.Literal(56), Type.Literal(57), Type.Literal(58), Type.Literal(59), Type.Literal(60), Type.Literal(61), Type.Literal(62), Type.Literal(63), // <- x64 ]), Type.Union([ Type.Literal(64), Type.Literal(65), Type.Literal(66), Type.Literal(67), Type.Literal(68), Type.Literal(69), Type.Literal(70), Type.Literal(71), Type.Literal(72), Type.Literal(73), Type.Literal(74), Type.Literal(75), Type.Literal(76), Type.Literal(77), Type.Literal(78), Type.Literal(79), Type.Literal(80), Type.Literal(81), Type.Literal(82), Type.Literal(83), Type.Literal(84), Type.Literal(85), Type.Literal(86), Type.Literal(87), Type.Literal(88), Type.Literal(89), Type.Literal(90), Type.Literal(91), Type.Literal(92), Type.Literal(93), Type.Literal(94), Type.Literal(95), ]), Type.Union([ Type.Literal(96), Type.Literal(97), Type.Literal(98), Type.Literal(99), Type.Literal(100), Type.Literal(101), Type.Literal(102), Type.Literal(103), Type.Literal(104), Type.Literal(105), Type.Literal(106), Type.Literal(107), Type.Literal(108), Type.Literal(109), Type.Literal(110), Type.Literal(111), Type.Literal(112), Type.Literal(113), Type.Literal(114), Type.Literal(115), Type.Literal(116), Type.Literal(117), Type.Literal(118), Type.Literal(119), Type.Literal(120), Type.Literal(121), Type.Literal(122), Type.Literal(123), Type.Literal(124), Type.Literal(125), Type.Literal(126), Type.Literal(127), // <- x128 ]) ]), Type.String()) type A = Static Expect(B).ToStatic() } sinclairzx81-typebox-e0ec98c/test/static/recursive.ts000066400000000000000000000036201505437577000231060ustar00rootroot00000000000000import { Static, Type } from '@sinclair/typebox' import { Expect } from './assert' { // identity const R = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) type T = Static Expect(R).ToStatic<{ id: string; nodes: T[] }>() } { // keyof const R = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) const T = Type.KeyOf(R) Expect(T).ToStatic<'id' | 'nodes'>() } { // partial const R = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) const T = Type.Partial(R) Expect(T).ToStatic<{ id?: string | undefined nodes?: Static[] | undefined }>() } { // required const R = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) const P = Type.Partial(R) const T = Type.Required(P) Expect(T).ToStatic<{ id: string nodes: Static[] }>() } { // pick const R = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) const T = Type.Pick(R, ['id']) Expect(T).ToStatic<{ id: string }>() } { // omit const R = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) const T = Type.Omit(R, ['id']) Expect(T).ToStatic<{ nodes: Static[] }>() } // prettier-ignore { // issue: https://github.com/sinclairzx81/typebox/issues/336 type JSONValue = | string | number | null | boolean | { [x: string]: JSONValue } | JSONValue[] const R = Type.Recursive((Node) => Type.Union([ Type.Null(), Type.String(), Type.Number(), Type.Boolean(), Type.Record(Type.String(), Node), Type.Array(Node) ])) Expect(R).ToStatic() } sinclairzx81-typebox-e0ec98c/test/static/ref.ts000066400000000000000000000004211505437577000216470ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.String({ $id: 'T' }) const R = Type.Ref('T') type T = Static type R = Static Expect(T).ToStatic() Expect(R).ToStatic() } sinclairzx81-typebox-e0ec98c/test/static/regexp.ts000066400000000000000000000001721505437577000223700ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.RegExp(/foo/)).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/required.ts000066400000000000000000000045471505437577000227300ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' import * as Types from '@sinclair/typebox' { const T = Type.Required( Type.Object({ A: Type.Optional(Type.String()), B: Type.Optional(Type.String()), C: Type.Optional(Type.String()), }), ) type T = Static Expect(T).ToStatic<{ A: string B: string C: string }>() } { { const A = Type.Object({ type: Type.Literal('A') }) const B = Type.Object({ type: Type.Literal('B') }) const C = Type.Object({ type: Type.Literal('C') }) const Union = Type.Union([A, B, C]) const Extended = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }) const T = Type.Intersect([Union, Extended]) const P = Type.Partial(T) Expect(P).ToStatic< ( | { type?: 'A' | undefined } | { type?: 'B' | undefined } | { type?: 'C' | undefined } ) & { x?: number | undefined y?: number | undefined z?: number | undefined } >() const R = Type.Required(P) Expect(R).ToStatic< ( | { type: 'A' } | { type: 'B' } | { type: 'C' } ) & { x: number y: number z: number } >() } } { // https://github.com/sinclairzx81/typebox/issues/655 const T = Type.Object({ a: Type.ReadonlyOptional(Type.Number()), b: Type.Readonly(Type.Number()), c: Type.Optional(Type.Number()), d: Type.Number(), }) const R: Types.TObject<{ a: Types.TReadonly b: Types.TReadonly c: Types.TNumber d: Types.TNumber }> = Type.Required(T) } // ------------------------------------------------------------------ // Intrinsic Passthough // https://github.com/sinclairzx81/typebox/issues/1169 // ------------------------------------------------------------------ // prettier-ignore { const T = Type.Required(Type.Union([Type.Number(), Type.Object({ x: Type.Optional(Type.Number()) })])) Expect(T).ToStatic } // prettier-ignore { const T = Type.Required(Type.Union([Type.Literal(1), Type.Object({ x: Type.Optional(Type.Number()) })])) Expect(T).ToStatic<1 | { x: number }> } sinclairzx81-typebox-e0ec98c/test/static/rest.ts000066400000000000000000000023161505437577000220550ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { // union never const A = Type.String() const B = Type.Union(Type.Rest(A)) Expect(B).ToStaticNever() } { // intersect never const A = Type.String() const B = Type.Intersect(Type.Rest(A)) Expect(B).ToStaticNever() } { // tuple const A = Type.Tuple([Type.Number(), Type.String()]) const B = Type.Union(Type.Rest(A)) Expect(B).ToStatic() } { // tuple spread const A = Type.Tuple([Type.Literal(1), Type.Literal(2)]) const B = Type.Tuple([Type.Literal(3), Type.Literal(4)]) const C = Type.Tuple([...Type.Rest(A), ...Type.Rest(B)]) Expect(C).ToStatic<[1, 2, 3, 4]>() } { // union to intersect const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.String() }) const C = Type.Union([A, B]) const D = Type.Intersect(Type.Rest(C)) Expect(D).ToStatic< { x: number } & { y: string } >() } { // intersect to composite const A = Type.Object({ x: Type.Number() }) const B = Type.Object({ y: Type.String() }) const C = Type.Intersect([A, B]) const D = Type.Composite(Type.Rest(C)) Expect(D).ToStatic<{ x: number y: string }>() } sinclairzx81-typebox-e0ec98c/test/static/return-type.ts000066400000000000000000000005401505437577000233730ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.ReturnType(Type.Function([], Type.String())) type T = Static Expect(T).ToStatic() } { const T = Type.ReturnType(Type.Function([Type.Number()], Type.Number())) type T = Static Expect(T).ToStatic() } sinclairzx81-typebox-e0ec98c/test/static/string.ts000066400000000000000000000001651505437577000224060ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.String()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/symbol.ts000066400000000000000000000001651505437577000224050ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Symbol()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/syntax.ts000066400000000000000000000010711505437577000224230ustar00rootroot00000000000000import { Expect } from './assert' import { Syntax } from '@sinclair/typebox/syntax' // prettier-ignore { const Basis = Syntax(`{ x: 1, y: 2, z: 3 }`) Expect(Basis).ToStatic<{ x: 1, y: 2, z: 3, }>() } // prettier-ignore { const Vector = Syntax(`{ x: X, y: Y, z: Z }`) const Basis = Syntax({ Vector }, `{ x: Vector<1, 0, 0>, y: Vector<0, 1, 0>, z: Vector<0, 0, 1>, }`) Expect(Basis).ToStatic<{ x: { x: 1, y: 0, z: 0 }, y: { x: 0, y: 1, z: 0 }, z: { x: 0, y: 0, z: 1 }, }>() } sinclairzx81-typebox-e0ec98c/test/static/template-literal.ts000066400000000000000000000070731505437577000243520ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { // Empty const T = Type.TemplateLiteral([]) Expect(T).ToStatic<''>() } { // Literal const T = Type.TemplateLiteral([Type.Literal('hello')]) Expect(T).ToStatic<'hello'>() } { // And Sequence const T = Type.TemplateLiteral([Type.Literal('hello'), Type.Literal('world')]) Expect(T).ToStatic<'helloworld'>() } { // And / Or Sequence const T = Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal('1'), Type.Literal('2')])]) Expect(T).ToStatic<'hello1' | 'hello2'>() } { // Auxiliary Template const A = Type.TemplateLiteral([Type.Union([Type.Literal('1'), Type.Literal('2')])]) const T = Type.TemplateLiteral([Type.Literal('hello'), A]) Expect(T).ToStatic<'hello1' | 'hello2'>() } { // TemplateLiteral Composition const A = Type.TemplateLiteral('${A|B}') const B = Type.TemplateLiteral('${C|D}') const T = Type.TemplateLiteral([A, B]) Expect(T).ToStatic<'AC' | 'AD' | 'BC' | 'BD'>() } { // String const T = Type.TemplateLiteral([Type.String()]) Expect(T).ToStatic<`${string}`>() } { // Number const T = Type.TemplateLiteral([Type.Number()]) Expect(T).ToStatic<`${number}`>() } { // Boolean const T = Type.TemplateLiteral([Type.Boolean()]) Expect(T).ToStatic<`${boolean}`>() } { // Enum Implicit enum E { A, B, C, } const A = Type.Enum(E) const T = Type.TemplateLiteral([Type.Literal('hello'), A]) Expect(T).ToStatic<'hello0' | 'hello1' | 'hello2'>() } { // Enum Explicit enum E { A, B = 'B', C = 'C', } const A = Type.Enum(E) const T = Type.TemplateLiteral([Type.Literal('hello'), A]) Expect(T).ToStatic<'hello0' | 'helloB' | 'helloC'>() } { // Enum Object Explicit const A = Type.Enum(Object.freeze({ a: 'A', b: 'B' })) const T = Type.TemplateLiteral([Type.Literal('hello'), A]) Expect(T).ToStatic<'helloA' | 'helloB'>() } // ------------------------------------------------------------------ // Dollar Sign Escape // https://github.com/sinclairzx81/typebox/issues/794 // ------------------------------------------------------------------ // prettier-ignore { const T = Type.TemplateLiteral('$prop${A|B|C}') // issue Expect(T).ToStatic<'$propA' | '$propB' | '$propC'>() } // prettier-ignore { const T = Type.TemplateLiteral('$prop${A|B|C}x') // trailing Expect(T).ToStatic<'$propAx' | '$propBx' | '$propCx'>() } // prettier-ignore { const T = Type.TemplateLiteral('$prop${A|B|C}x}') // non-greedy Expect(T).ToStatic<'$propAx}' | '$propBx}' | '$propCx}'>() } // prettier-ignore { const T = Type.TemplateLiteral('$prop${A|B|C}x}${X|Y}') // distributive - non-greedy Expect(T).ToStatic< '$propAx}X' | '$propBx}X' | '$propCx}X' | '$propAx}Y' | '$propBx}Y' | '$propCx}Y' >() } // prettier-ignore { const T = Type.TemplateLiteral('$prop${A|B|C}x}${X|Y}x') // distributive - non-greedy - trailing Expect(T).ToStatic< '$propAx}Xx' | '$propBx}Xx' | '$propCx}Xx' | '$propAx}Yx' | '$propBx}Yx' | '$propCx}Yx' >() } // --------------------------------------------------------------------- // issue: https://github.com/sinclairzx81/typebox/issues/913 // --------------------------------------------------------------------- { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('X'), Type.Literal('Y')])]) const L = Type.TemplateLiteral([Type.Literal('KEY'), A, B]) const T = Type.Mapped(L, (K) => Type.Null()) Expect(T).ToStatic<{ KEYAX: null KEYAY: null KEYBX: null KEYBY: null }>() } sinclairzx81-typebox-e0ec98c/test/static/transform.ts000066400000000000000000000241031505437577000231110ustar00rootroot00000000000000import { Type, TSchema, Static, StaticDecode, TObject, TNumber } from '@sinclair/typebox' import { TypeCheck } from '@sinclair/typebox/compiler' import { Value } from '@sinclair/typebox/value' import { Expect } from './assert' { // string > number const T = Type.Transform(Type.Number()) .Decode((value) => value.toString()) .Encode((value) => parseFloat(value)) Expect(T).ToStaticDecode() Expect(T).ToStaticEncode() Expect(T).ToStatic() } { // boolean > union const T = Type.Transform(Type.Boolean()) .Decode((value) => (value ? (1 as const) : (2 as const))) .Encode((value) => true) Expect(T).ToStatic() Expect(T).ToStaticDecode<1 | 2>() Expect(T).ToStaticEncode() } { // literal > union const T = Type.Transform(Type.Union([Type.Literal(1), Type.Literal(2)])) .Decode((value) => true as const) .Encode((value) => (value ? (1 as const) : (2 as const))) Expect(T).ToStatic<1 | 2>() Expect(T).ToStaticDecode() Expect(T).ToStaticEncode<1 | 2>() } { // nested: 1 > 2 > 3 const T1 = Type.Transform(Type.Literal(1)) .Decode((value) => 2 as const) .Encode((value) => 1 as const) const T2 = Type.Transform(T1) .Decode((value) => 3 as const) .Encode((value) => 2 as const) Expect(T1).ToStatic<1>() Expect(T1).ToStaticDecode<2>() Expect(T1).ToStaticEncode<1>() Expect(T2).ToStatic<2>() // resolve to base Expect(T2).ToStaticDecode<3>() Expect(T2).ToStaticEncode<2>() } { // nested: 1 > 2 > 3 > 4 const T1 = Type.Transform(Type.Literal(1)) .Decode((value) => 2 as const) .Encode((value) => 1 as const) const T2 = Type.Transform(T1) .Decode((value) => 3 as const) .Encode((value) => 2 as const) const T3 = Type.Transform(T2) .Decode((value) => 4 as const) .Encode((value) => 3 as const) Expect(T1).ToStatic<1>() Expect(T1).ToStaticDecode<2>() Expect(T1).ToStaticEncode<1>() Expect(T2).ToStatic<2>() Expect(T2).ToStaticDecode<3>() Expect(T2).ToStaticEncode<2>() Expect(T3).ToStatic<3>() Expect(T3).ToStaticDecode<4>() Expect(T3).ToStaticEncode<3>() } { // recursive > 1 // prettier-ignore const T = Type.Transform(Type.Recursive(This => Type.Object({ id: Type.String(), nodes: Type.Array(This) }))) .Decode((value) => 1 as const) .Encode((value) => ({ id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] } ] })) interface N { id: string nodes: this[] } Expect(T).ToStatic() Expect(T).ToStaticDecode<1>() Expect(T).ToStaticEncode() } { // recursive > 1 > 2 interface N { id: string nodes: this[] } // prettier-ignore const T1 = Type.Transform(Type.Recursive(This => Type.Object({ id: Type.String(), nodes: Type.Array(This) }))) .Decode((value) => 1 as const) .Encode((value) => ({ id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] } ] })) const T2 = Type.Transform(T1) .Decode((value) => 2 as const) .Encode((value) => 1 as const) Expect(T1).ToStatic() Expect(T1).ToStaticDecode<1>() Expect(T1).ToStaticEncode() Expect(T2).ToStatic<1>() Expect(T2).ToStaticDecode<2>() Expect(T2).ToStaticEncode<1>() } { // deep-nesting // prettier-ignore const T = Type.Transform(Type.Transform(Type.Transform(Type.Transform(Type.Transform(Type.Transform(Type.Transform(Type.Transform(Type.Transform(Type.Literal(1)) .Decode((value) => value) .Encode((value) => value)) .Decode((value) => value) .Encode((value) => value)) .Decode((value) => value) .Encode((value) => value)) .Decode((value) => value) .Encode((value) => value)) .Decode((value) => value) .Encode((value) => value)) .Decode((value) => value) .Encode((value) => value)) .Decode((value) => value) .Encode((value) => value)) .Decode((value) => value) .Encode((value) => value)) .Decode((value) => value) .Encode((value) => value) Expect(T).ToStatic<1>() Expect(T).ToStaticDecode<1>() Expect(T).ToStaticEncode<1>() } { // null to typebox type // prettier-ignore const T = Type.Transform(Type.Null()) .Decode(value => Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() })) .Encode(value => null) Expect(T).ToStatic() Expect(T).ToStaticDecode< TObject<{ x: TNumber y: TNumber z: TNumber }> >() Expect(T).ToStaticEncode() type T = StaticDecode type S = Static // type S = { // x: number; // y: number; // z: number; // } } { // ensure decode as optional // prettier-ignore const T = Type.Object({ x: Type.Optional(Type.Number()), y: Type.Optional(Type.Number()) }) Expect(T).ToStaticDecode<{ x?: number | undefined; y?: number | undefined }>() } { // ensure decode as readonly // prettier-ignore const T = Type.Object({ x: Type.Readonly(Type.Number()), y: Type.Readonly(Type.Number()) }) Expect(T).ToStaticDecode<{ readonly x: number; readonly y: number }>() } { // ensure decode as optional union // prettier-ignore const T = Type.Object({ x: Type.Optional(Type.Union([ Type.String(), Type.Number() ])) }) Expect(T).ToStaticDecode<{ x?: string | number | undefined }>() } { // should decode within generic function context // https://github.com/sinclairzx81/typebox/issues/554 // prettier-ignore // const ArrayOrSingle = (schema: T) => // Type.Transform(Type.Union([schema, Type.Array(schema)])[0]) // .Decode((value) => (Array.isArray(value) ? value : [value])) // .Encode((value) => (value.length === 1 ? value[0] : value) as Static[]); // const T = ArrayOrSingle(Type.String()) // Expect(T).ToStaticDecode() } { // should correctly decode record keys // https://github.com/sinclairzx81/typebox/issues/555 // prettier-ignore const T = Type.Object({ x: Type.Optional(Type.Record(Type.Number(), Type.String())) }) type A = StaticDecode type Test = E extends A ? true : false type E1 = Test type E2 = Test type E3 = Test type E4 = Test type E5 = Test // assignment const E1: E1 = true const E2: E2 = true const E3: E3 = true const E4: E4 = false const E5: E5 = true } { // should correctly decode array // https://github.com/sinclairzx81/typebox/issues/561 const T = Type.Object({ x: Type.Array(Type.Object({ y: Type.String() })), }) Expect(T).ToStaticDecode<{ x: { y: string }[] }>() } { // should decode generic union const GenericUnion = (t: T) => Type.Union([t, Type.Null()]) const T = Type.Transform(Type.String()) .Decode((value) => new Date(value)) .Encode((value) => value.toISOString()) Expect(T).ToStaticDecode() Expect(GenericUnion(T)).ToStaticDecode() } { // should decode generic tuple const GenericTuple = (t: T) => Type.Tuple([t, Type.Null()]) const T = Type.Transform(Type.String()) .Decode((value) => new Date(value)) .Encode((value) => value.toISOString()) Expect(T).ToStaticDecode() Expect(GenericTuple(T)).ToStaticDecode<[Date, null]>() } { // should decode generic intersect const GenericIntersect = (t: T) => Type.Intersect([t, Type.Literal(1)]) const T = Type.Transform(Type.Number()) .Decode((value) => value) .Encode((value) => value) Expect(T).ToStaticDecode() Expect(GenericIntersect(T)).ToStaticDecode<1>() } { // should decode enum enum E { A, B, C, } const T = Type.Transform(Type.Enum(E)) .Decode((value) => 1 as const) .Encode((value) => E.A) Expect(T).ToStaticDecode<1>() Expect(T).ToStaticEncode() } { // should transform functions const S = Type.Transform(Type.Number()) .Decode((value) => new Date(value)) .Encode((value) => value.getTime()) const T = Type.Function([S], S) Expect(T).ToStaticDecode<(x: Date) => Date>() Expect(T).ToStaticEncode<(x: number) => number>() } { // should transform constructors const S = Type.Transform(Type.Number()) .Decode((value) => new Date(value)) .Encode((value) => value.getTime()) const T = Type.Constructor([S], S) Expect(T).ToStaticDecode Date>() Expect(T).ToStaticEncode number>() } // ------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/798 // ------------------------------------------------------------- { const c1: TypeCheck = {} as any const x1 = c1.Decode({}) const x2 = Value.Decode({} as any, {}) } // ------------------------------------------------------------- // https://github.com/sinclairzx81/typebox/issues/1178 // ------------------------------------------------------------- // immediate { const T = Type.Module({ A: Type.Transform(Type.String()) .Decode((value) => parseInt(value)) .Encode((value) => value.toString()), }).Import('A') Expect(T).ToStaticDecode() Expect(T).ToStaticEncode() } // referential { const T = Type.Module({ A: Type.Transform(Type.String()) .Decode((value) => parseInt(value)) .Encode((value) => value.toString()), B: Type.Ref('A'), }).Import('B') Expect(T).ToStaticDecode() Expect(T).ToStaticEncode() } // deep-referential { const T = Type.Module({ A: Type.Transform(Type.String()) .Decode((value) => parseInt(value)) .Encode((value) => value.toString()), B: Type.Ref('A'), C: Type.Ref('B'), D: Type.Ref('C'), E: Type.Ref('D'), }).Import('E') Expect(T).ToStaticDecode() Expect(T).ToStaticEncode() } // interior-transform referential { const T = Type.Module({ A: Type.String(), B: Type.Ref('A'), C: Type.Ref('B'), T: Type.Transform(Type.Ref('C')) .Decode((value) => parseInt(value as string)) .Encode((value) => value.toString()), X: Type.Ref('T'), Y: Type.Ref('X'), Z: Type.Ref('Y'), }).Import('Z') Expect(T).ToStaticDecode() Expect(T).ToStaticEncode() } sinclairzx81-typebox-e0ec98c/test/static/tsconfig.json000066400000000000000000000001001505437577000232240ustar00rootroot00000000000000{ "extends": "../../tsconfig.json", "files": ["index.ts"] } sinclairzx81-typebox-e0ec98c/test/static/tuple.ts000066400000000000000000000003571505437577000222340ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Tuple([Type.Number(), Type.String(), Type.Boolean()]) type T = Static Expect(T).ToStatic<[number, string, boolean]>() } sinclairzx81-typebox-e0ec98c/test/static/uncapitalize.ts000066400000000000000000000011721505437577000235670ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Uncapitalize(Type.Literal('HELLO'))).ToStatic<'hELLO'>() Expect(Type.Uncapitalize(Type.Union([Type.Literal('HELLO'), Type.Literal('WORLD')]))).ToStatic<'hELLO' | 'wORLD'>() Expect(Type.Uncapitalize(Type.TemplateLiteral('HELLO${0|1}'))).ToStatic<'hELLO0' | 'hELLO1'>() // prettier-ignore Expect(Type.Uncapitalize(Type.TemplateLiteral([Type.Literal('HELLO'), Type.Union([Type.Literal(1), Type.Literal(2)])]))).ToStatic<'hELLO1' | 'hELLO2'>() // passthrough Expect(Type.Uncapitalize(Type.Object({ x: Type.Number() }))).ToStatic<{ x: number }>() sinclairzx81-typebox-e0ec98c/test/static/union.ts000066400000000000000000000036201505437577000222270ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const A = Type.String() const B = Type.Number() const T = Type.Union([A, B]) type T = Static Expect(T).ToStatic() } { const A = Type.Object({ A: Type.String(), B: Type.String(), }) const B = Type.Object({ X: Type.Number(), Y: Type.Number(), }) const T = Type.Union([A, B]) type T = Static Expect(T).ToStatic< | { A: string B: string } | { X: number Y: number } >() } { const A = Type.Object({ A: Type.String(), B: Type.String(), }) const B = Type.Object({ X: Type.Number(), Y: Type.Number(), }) const T = Type.Union([A, B, Type.Intersect([A, B])]) type T = Static Expect(T).ToStatic< | { A: string B: string } | { X: number Y: number } | ({ A: string B: string } & { X: number Y: number }) >() } { const T = Type.Union([]) Expect(T).ToStaticNever() } // prettier-ignore { // Scalable Union const X = Type.Object({ x: Type.Number() }) const Y = Type.Object({ y: Type.Number() }) const Z = Type.Object({ z: Type.Number() }) const W = Type.Object({ w: Type.Number() }) const T = Type.Union([ X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, X, Y, Z, W, ]) Expect(T).ToStatic< { x: number } | { y: number } | { z: number } | { w: number } >() } sinclairzx81-typebox-e0ec98c/test/static/unknown.ts000066400000000000000000000001671505437577000226010ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Unknown()).ToStatic() sinclairzx81-typebox-e0ec98c/test/static/uppercase.ts000066400000000000000000000011531505437577000230650ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Uppercase(Type.Literal('hello'))).ToStatic<'HELLO'>() Expect(Type.Uppercase(Type.Union([Type.Literal('hello'), Type.Literal('world')]))).ToStatic<'HELLO' | 'WORLD'>() Expect(Type.Uppercase(Type.TemplateLiteral('HELLO${0|1}'))).ToStatic<'HELLO0' | 'HELLO1'>() // prettier-ignore Expect(Type.Uppercase(Type.TemplateLiteral([Type.Literal('hello'), Type.Union([Type.Literal(1), Type.Literal(2)])]))).ToStatic<'HELLO1' | 'HELLO2'>() // passthrough Expect(Type.Uppercase(Type.Object({ x: Type.Number() }))).ToStatic<{ x: number }>() sinclairzx81-typebox-e0ec98c/tsconfig.json000066400000000000000000000011651505437577000207720ustar00rootroot00000000000000{ "compilerOptions": { "strict": true, "target": "ES2020", "module": "Node16", "moduleResolution": "Node16", "baseUrl": ".", "paths": { "@sinclair/typebox/compiler": ["src/compiler/index.ts"], "@sinclair/typebox/errors": ["src/errors/index.ts"], "@sinclair/typebox/parser": ["src/parser/index.ts"], "@sinclair/typebox/syntax": ["src/syntax/index.ts"], "@sinclair/typebox/system": ["src/system/index.ts"], "@sinclair/typebox/type": ["src/type/index.ts"], "@sinclair/typebox/value": ["src/value/index.ts"], "@sinclair/typebox": ["src/index.ts"], } } }sinclairzx81-typebox-e0ec98c/typebox.png000066400000000000000000032474021505437577000204740ustar00rootroot00000000000000PNG  IHDRա pHYs  :tEXtFileC:\Users\relay\Desktop\design\assets\sidewinder.blend\stEXtDate2023/07/02 20:42:53$BtEXtTime00:00:06:01ɨy tEXtFrame145~ tEXtCameraCamerah tEXtSceneScene!]tEXtRenderTime00:21.76iYtEXtcycles.ViewLayer.samples4096Kp$tEXtcycles.ViewLayer.total_time00:21.72f #%tEXtcycles.ViewLayer.render_time00:21.554\f.tEXtcycles.ViewLayer.synchronization_time00:00.17%6 IDATxۖd7\IYkEjRdU 2wssslj+??ǟ?02`B㏿/"Se1y.Rܜ/MKN2O25_[q*-?KyHA#|WMjl1㛪=1JDX%g?J]2Wd_c$ffWZ ?kqjO*sO yB7:g:O(1ڦNuFG9@? W?+IrGՖr̾ק qΑ5ٰ\}_/v@mvŚpͩ 4Z0TO u.kNLsOJNǰ~^xЙ})ĸ<36&`z?\81praƼWk!8m 0A Mqb!p5篅+M4YxXύvo{6S>}@6>ZsO2Ɨ>g"˘Oǚ]O>a|q?V;Ӥ:3_k<}:#G-zu 2{7s|%Ǣ/~p&^/uqG*C5;y0n}͒1o/qQ?/^\0vk1:! 9,Ɯs<\~3 qku= ^w]}lG#u#7Szρڨ?KQ4xiכǔΗm<&BK߈E'E{ 4)LOI?2p v8bf>]C۬Kbjދ'glĤ y ^cSZˋZTQ|aN]MCK53A ;zϼ=~Gai^#?u~P/~[??eG ex*b1v\}kU{k6T~aۙ5#w9ܲ3f&PlKs+\%B} X%EkK}h^.)+(޵ƖeOqn`5ƭO||s=v%_,0ru9ҡ59<\ :1VuP/};󒛢%{Xzݽcy)wRɾqƎan~Qi>Coi!ci}%I @AsI6ZT;1fv 6a|7i?Xg*<wr N>Yp/;XHuq' 0kRgcsz G 7`nNo\nY>dQ`>j'F6d6o솓'~kgcaj8zm2g68 'm{6W K"PZʜ:-j)mDkG,,wtq.!<E4%K!,xur kVfNIqGXfIUawrhDWː̱\CW,y'.s#BijOi| ˁ>e-q۵C6d>,ؙsvX4aI?0E%>1חPxsy˗lI?V> }o>HEu|_tw:g^҅j&6#yz%p+xA sSp9vY|[;(/Xv.pߎzXa& -rݸaɃgOS DzVD''kf*|Jou ?>j ~E+.8[_<5{͂mxhlA*Y3fihy"C q mF;|Y;ATVM\IxO<' cpl9>|rˉaw+q9ql> p"hL:5yZVHH8v7@[fo3$v;@`;^G+01!k_g\vzpz'LZk-D`GQ 6~NrlΛ\pi֙E)@B,ޯcblgJǻz-7%&<| &c;wkƿ]%/tQFuNfF0gkIHpWfnbSF]0t5$|1'J #Aڒ3;k?&XҊs ^lof]tNѢe!p/eg2n-6%>ˤU=&Rk+@-=qM5!t011c&WfnÏ6! n]r0I0l-un^#oK>pOYdz'Slh'e4d.2K|fsZ&\c-ܘd\`wؕKIL?HpFEYG`-$/{(5xĻ`kNϽq [d aoعnBr>M&IG^ 5H 9Oַxw,A乙6#急L%g#]@@}ZݛBEs3 }'Zc:`%y ?5;\L1 {$eD_<;N73ZN5UAm<=}7_pr9\pO|3G oťuxs-qn~\ =ۧd_~x"yxac6i0?2;"^ FK@<g9q66Bd9E+hC4kxBq֤nPzWY7"|-#bOR8Ok"==$Xq۸!ZG-_9|ffFc!.uL_qoMٻnGI릀9Z{W]_p O_PM|~̠whVlk([ 8i&L2NZ҆{&s<ly4c@kop%s$1,t\97ӄN>sj+O87d9f$K<80 1՘ƃľ&(ܬk#Sױ+1kӋ] t˥41ֻ]n] 'r,˞+W M}]Ns %z4c{;Kd|?\ƲGv8{`W%~5L㠛Br{%}hblb/~_Cwޢ71jMuh.GLkmNlغ&עȳu0LCnt9wEj ` +V{ ,>}}1p?ϾrCA_5ELhBCtZlx9uƳ(y!''JO絵?Xtz*0Ǐ}w%cM9;6ع$8Ėq雅<zg_Iq#91 ,+^3yڨ1Є]bŏ[~52ha2]?Z3r,Xq?aȕ-9qJN֗qm:@?vA;$2iq û{^j.7/֫w/%X<mY/n3~@)Gpt*Xkjo^tپ:pB}sg }AG67=v] $T&1#8r8z枾C8/ZKy K)2 rm]-Y fǏL-bZW0ђnCH`mWȨx󂂫h/>r:NF|q "yG(,%Wx}cs!5q,e?QpbgÁ %.f? lyqN#4o{ssG.`9N=b?3}_xÚIo QX 嵦ƟE|D wg{=U,ae=x#ԎW^NϹSYvk,Jn:inb3m2Skg6ooSGdKup=yZ̉x2A wMo<w{,sVfLh}mO1s(a¸7jǃi6 ϱOn@ G$ꁛh1 Yg\7Ĺ'iI]Wyƽܿ@ 8ӷ֌a޾|^֕i,Jn6>Gal~>1:/#i=46>D8!_2$PpTl_'n~06Tjlh ͷZ>V dgd?3vk;o.&i} aglO=:G`_^֕V;υX8-}9?4,290Ga6\Z'p {1\>P/cH}"B^yLNx :LA\<`Ym7G,2x%JH>ÿ9co'5Z~KΥie#`< uz.[ ҟq IIeE\!KYpG߉B|p3lf̾;0p?-/9ux4.WSLJCqӸYàݰ-fVlbń:ΤISA0MfkvxͭTcɻ:# M;׀? x&V8+߄q?͟L?͑t2~XC>Vi S|6J^2e l5%xaJi?\I X0K4:5s"|O\OC O?)Ef2eDK^XI0ο<\8y'>\>u촯V2737@9۞ΛDmdrzp:O' 8wx+_Ĺ!罃74g>5FRewPg?u{2|^OD?{:pt?"K>^?B IDAT!=GB B^7(Ȱ3S0WCZ7;@}͉b^>ݗ˱!GbkN;/*xwH`/Dٜ\L5*?'wlc{VخZ,ÉF\n\E6giGtTD- E+rk# O@?VwhY̒EaR5!(-WXdna9wrsO; ƽo_#~,]be@njuxk\A%Gm=|AeOQL gãO|q``6XmٞܮhɻhNT+ j"x|oxw5uܞSKjIzSi2Ӄo_ͷ?%/'ޔ*E4YP^l츙X&}\9/24mqX=Üu6Lޟ# Z #YC3*LbB Vfz|# IOhG ܏cM?99eB}m6̫#*z+DIKM,҇/s\qjfJ9MYcjkbcU1vjN[DeM [ {г3 ~ ٟ ^ &YYޛKv&KoA9?Γ̦ɞTn&9{"E7_]8e F|^ig+᠗78kw74.nPbkwGo\C#H8/5| /6W,R^4lO#<2^Q?|N5]55ׄIވvA`qµǫg^m'E)īH W? &.¶ۂdsR눫qT)d Z4:-52@|RǞxz76^{ ~^е{ =yn8Ϲ&AY5_u08 G^O0nyA<7c/sv%*nGo 0Kȱ,P D~/ oe202~oRoE돻"w6 ϽcTnh$`q6k6^!^Ӳx1܏WWkxasjFNg[̷SS:{8 zb1T!H4Ͽ!C`6C ˧/rOyC漳4ˊP:q>f[#ZW2q[׹vgSk<1m/xXb.OMSoIP.rFaFUWejiˏ:gV0s6y`s#]N>0=7arpOxSgX&r_FMG.B/~GB]\zgX 9k^cp^]sd3F^#Sճ7~(O pUs 8q8#^_^{J{5>wf]sSBv?NMɹ[JɖH!Vzv~jEO^1Y3x=*sr1zs=?=A˖fIB4o wPڲAXq)|u:@(}>G,#7u{i*aXa}?\٧/6Ʋp;5&EwQm3 b) -n{v[nmsD^m?P;\ ^Ѩ}./Bwrp i񝚈+ėF.3_oq%uha˼3-v,”jNx`fFT x{\9yq9X 9ܓ^ǾA97Oor JOI;5'kk Q"_~ g4m]M덇r&ηV-w%#h3 Do8g v`\c;֏=qet G3ٱә,V}qIH !Of-MXq`83m 2sy xך\—}V4[@N@6^YBT㟞{%&k? N ~cWOlKsK\ k=%1tZְK{WX~9@h[EĢkcٻX_>?On]Ek<v<׷PHaF-ǧzb|0=|F ֊r8Ϟy}8<֦@x@񙑫 r%d-F -7̘XxSaxoޓOoҜ Oۛ +41i^?r.8@oh1m䧔񬟰L ;,2[v NhAvxfb)J-ә],$5.r8WF\>%55!\nKL^t~1mY{r{lnwz8kh[yE"C {v&a3? z˾؀]hfa.5;koAڑc\G'rϑ[臋ӿyjN0zѾdó%1p/4/=M5凣ҷh'ađ3+1_92,wz Sb?-f,Ǩ+D6lOʅqjeN"ӏLE=לiNN'U3᭰SH'09D;4p=?D0_n_[4;hHqZ G >Ŝ>aV<Zjuo6du5uȔׯ_o ݫ?ȑ?gx( %q#y͞ y6kJQq~$}\}-fy(70iM{M$N v#>8wǷCoOkj|umfr)+r}> 1Mx 03q#yv/rBٛ{&# هb[~cx;z@ֵRҧt"1/l]u)?Jv }&:& 1lݓ'ԕ9Nq}!O4Ebbവ_ 0gll`wI 5,w@~+-!kْRn4`-?/p!acܜS!mΡ6I.0^%7W QO 8OG- < {66}/А&R0ŝs+Khz;h@95ǵ^ |LsY>bƋcq=SPÜdm= e?^'%frU{8ϓB 3<1։bW~̧g<*q-(e|g=W3rWK;١~u8>݂PrkoM+6Iak H4.NF~r=ŀOpv &#%.Y#\~ 6 !/u:Wp[[mGBLiXshigd &*ÁP^aFЙs8lw'/l6@g4sb?ou?Rkxl/G G{XcǩehsOyO0-\Tܤ}ukW9Ox28mk16,5uoxq9MKr5߸i\bOz{zmEjk>(Y&853MgUQ6A[d3Έm"ӳRA/0(ح?1Ję}rZ_(ۣ3}):F˘rhQ&'>>p`}=N{Սw8D^;Hh[Yd_ Ea|!io 87i+8Y2'xrƈ_lrLB-3\#Q]G3{kO},1>"~>ݏV G36vv^^M5ʄ~kڵ0Ь[ss_k=_ qZzxm syN[/>w)˹yA |<0E_Oqf < S?g|Z].3k1'6n3ɬi|w+Z AƟe^gt0 7+f}o/܀w)jZY7`9y{0!S8{=!FS_=cR`1'A8y @x0mh|ƽ43rlLs"2sVc @܁µȼAg$9tg/> qSȼ^q 0' &3:a3Qܖ'ʯ 16=g}RF As(6Ŕi])ϰ* "3mA:|#,2ߌ/~ƹή?ǗPhM f(\0I7\ i0JJRCxp:璛t'z:8$3$Зbg}樟 ]iXROa/-I-ro59aPZk~ 3oVkHzHj~+FCd{,5 !`ҿ<'ȋiC+İHSGlӜ>%ĬaY평]s|qDU'0JᏭ P듖&yyНU?cҿ&3;Kb\osq{>Gn4lp('%VOS9p~orbjX X8vO>{i4@Ay=bj԰:Vo&? o0YND3ACp{lպxCnexem& * 6ޫp\ҕ=VZڌȺDʋpdkco#y> (s7̉#VOhpv}YĞx/:Ƽcs3͸y{onx*QZvq4m0\n'"ɸ$qY4B6|?8>ڗ\!Ox׽f2lvĻ گϿـO|x\ѷT&b6Lpؽ7Y^iR1{fTjCOsMKqZFbij*q9>Wg>_pqJf=LrasLS^~eq+ݨt`ܘ gV5 m㷶;pcsX[Ic=6VP.L'@o Qjago6u{`5kw"Z$yzhL[s?\g]Ɂ⎆X89y"`%!t8Dqdmi\aBqCq#$utȗh3 <巠"$/R3}g]7 -O@ќbu-F~_ev8xa?yK{; #۪$&V;dbJ9Fs1L('uXX7ݨHIJHwTa1h/{}6nFXk8'&:#jCI$`ۋ6c zH={dz}sq6r՛\eMvd"v\?A?^9'd@Qmz[Lʿ_bxF&^k0%#3kci@ΥsMy<?vۀՙMo&._Ξm<]3l8E5 b? 8Ίj/&uN]l5;$o֗0(P-d r׬ fI<..Aߛ }KN3@⼽֞:Lm8ɵ_whټ\P _b4XIX3U V3v߯wOφ5u1Ǘ-c{g ;Yobƣw=5Y=%I+ln v=>kFyOΑ r8bc~N|& y6ױ̫UzS0>M۸DբY#,l:׸JE2o Y׿ o;ȃi {]R]ΧZ9Oul_vYWx0,N p3 %9Z,۳b 2C"y1T- ./P8w h޹aY҆s1I IDATCaz(>0]hMڧE^p+* r8g nj .wqOf9Il|`cgB.M<}jQ[Wtۺgv1vا<]4.s=}4OcJysφrrcΘL|TV'w^^ֽܑA q v@Y?_ `E3ath9>` H3_8[ٛg嬙Oc92Oł;ZX[/̩ IИۛcw7kə.Lfw\) ۗ,>Oǻޡ{ܣL>^XNn1v?R_0o K]Ǫ7#| p٤˘pܠG(a =1qƽgzN|4;sd'[W{Xlj?=?< !Z͘N6p/;_w GY5V0n g=Ecy]-q]6rwEFJ\r2?bۓy_+72$<6Y.Òsә)l`,*>DȝO"ϜjW^{3ɵoHٴ[Wj 0{Ώ6@ed/I&˸VM\pSQfxa' mmy؆ {έyÓ0m/GG=ȿ~D^hZpvxZwycye:n1dr5aV0e@`rT&JĢ:Wca]Ʃ| b<ǯyé47S֧tsn՞/V,qʰ\G kk5nO,k2T<3n>6gnlx&.xWе'F>p by.?!bڠ5$ޤ։ dngJs.O~e]gz㻾E?78,Cnd@C[hڭ5/kvl91oktuis=w5왗LyDΆ>jg2k/t;(G;Y6sҫۯQ~IJwlAhV6,>736_O{d}gS2y[WN퍻'9fwDxb L~e3^ MQ@֡q+.X>x9gYC7?r4YbՇq\"ksS!]G24/6rBbdQ G{b$*fX lt^qN5'9A=/΃cA aV cg 0Y30ssZ^|re&LyfCGa߾PFArẵ-QpwMjQH,N؈!8}df'9'}k6;.c=/:9 g6#K2G%ݶ6V +3<9˽tGo5iҼ'6SXbwTbg y+2-hxzX13*; 7r@Qnbz\J69X6i })'~FNi^wɱ>OcknmcVm`vm&LJ[1X #MrhV?4ic7G)~yYXBxd}]O8n&)?O#]_0)u˳OIZح6 Xj<ÿ9;zf 3z!ߢo`auhG3iI>B>dwUy{àrOrs:1`!<65.PwO1'L^7rn8S&)sA=iCkϕvֲqG#:>c}EmgZϧGLɳ$1Qk7=zҷSSH8#hb.^L)-˹xn~cMl]r=ėQ4FHi$8vb1>"cT4Ƹe? rm-Wz,wtUqQ5KXDkR4|lY09 YN4D!$o<\s^JG+Al5}?8 )E|ze- aS^k5=3&q%Oc٤_a|A'ˍee 7Ai_oǮ]Vùd:ԙ;Aj0*Ogs-!?&d<|jCx!a˒{0g^HO|p3?k.&){/h35ɪ[k-cqκ[gizϾ7j3/A3.ҋOLO^wNAsGEt= ovXHX$bg9B;yko}#T=x?Uy(ۆ@.0 y-kj==׏JK>8$^|OyǦMuYzu,OF'l.DL\Ve O'dWO\FZMO-M %5FW[W[3 rPyK56sփS^"QZeL~#-1K0Gb\DǍWrC"uj/fvkH p'5gI4Lnz3a葝g(E1+l,h gܩ\'Ü#8>lz.w%`ܗ͌耗P'z ;i=_zRN'n?, zn 2Pbg ;a:]ٚV,&l xva>a"lξ=Íj!'Yc5|yM^K-gsXô1_vwDKY[eXCs)8G.#>gfž%]m^+ԍ@3ON,׋aS>ֶ]ot֋3]^LxO3iOF[9ZX{j|JnQaLsj>GͩCƱ:sWW> l>^9Y# SV\ _O\B9֡s5 R'q+|Y,N^-=spnug^UojXc{cZ<4,>Vru^gHoOs~ \~Z83m<1$iIͳ??Bh v@ˀ8x>~v6Gy~δ< %Pc m$ƛ-u g WSp," y0^[f9k0x֛_ oM؋\ؒ-9^j"܎H>І‹sy~b#^c3~Dzӏ#z\SNp?]^z _E= }`vͶT8ʳnB9NU`f+nJsf᦯/;-22Oa[40gϿaP'|Ö37 o"Жl\7~Ƨ+ 5Kَ%Zg:x {OE4fG)\ A1h"=K{Oqc="],?Gb+/:)oAU3{sm`]9:+qVN_/s2e'Nj=j̍By-MY0{cp;9>r$:6cvQB/{\7=jAm91hjsy`hw:9ͣuxj5˵aI^Ϡ𱮦ϹȁB'{ CmoH`u9-7?C\w^O3s"gN:*+.;#hcgvc+Vn,!4yє|Y–_2p0xHdc>y :c֫ <zٶl|UwɒLp|Lej_g`ɚbh0.7E3s^NmpG; DfFs&^VL$=# YW-9"ʜ5F'8|#cmٹ̑>y5z܁v;9JaEF*֖^0z:m뼮g]-Dr06B½3yA<5BNW_\'?÷1̳m.!}%.?Н"d'FA N|ڮO% 3^ Vkpy}s𣧁OlXسP-Cvٵ5)N{kØK!gX"5-g>dB , l ݽHxh =_s)nY ή=)0GB5?ޯ/lhdЍ#'kokO\^m\HAfGƳ/ѡmN-?g!]M,&l˷Cf? X iXwA2g`Sڱslu!L^ԇ U8rbK/pY3t^tڠ0{YghL|)ӊ4"V!_n 7bi莧4@Z3|1 `Z:(ߙ 7'&r}k\"e#G~{c!,vSg`"h`ƿ5}ɛ‰]7WveopX Fbuy/t- lZ Uhp;fA>\][-Wwx/4I޸| <)#K˞5"I.d8n~ ~ Wkp\ehe3=:|/Kg[*.0koM%c UdV׫Y-O%hJ>xXSn#?ƚ8/2]m K4la0EkDKaDcC"`ӳ|s=k @?Ђ/%AUvIpr7ޙI N=2(u$RL.h6~|ZR1)^{zF]xڃCbMߟA-槇pf%-b.l7Th1C1 ܓ~y' 'r?SחNj\&\īv%7:훀p?|V^'5B\|N{g+A Xc?+v^BԐ^Ds@$b-3T@:3?O<[&ds%`Jziѱq)@xX,SYwCݼX`8ǷYY[\'&ðp'$;'t5,7SE{^*ߘO3>gɃ; D+׬i@|QOəRl0e"^Ώ[ֹ]>9佫Qw/+d'EbНԺ[& }6б=9'a|q>ߙ ƻ_㭂B;@6_E舖ٿbvɕxtg^S IDATx;KQ x\7cT.j\L:sV EuvN{5oVox{s>l:U,C'yn _S_D5-}Ŏow=k˟c:w"IH+Cd=CiSF|Wݰ#s7GZ[}a-td;RnrK9Ɂ;2!-yʙN$!Λu\)Ǘʟo0͑) gfiʒ:8 OyhW OսYosհ1㧟Xl3sHD}(gK @G_0QӺ]f|m'R׸,>R㿵.vr\<33m}yHhM#">_,<ϴC}gXy$>^2\cy|Hэ=4'pj.;#}&8ow|96#nW9ih }囐NT뙫I>~@ZFmC4s3eׯCAe?| IK>uZArJ"ti.8V3]Ƨ%Wo4D*u8ʝ"%hj^=#:6'?Nć|ÄM’7v3KVZ_[.q`rռF4u o~l9OXPɊ[v?AO?Jm[$;gf|.|bv*چEi|2eD;'W*t|`Yƴ8Ir$ wz=h!*̞>\fM2yӪXNjt>iBZ z>/<@}b8NӧL#x՚#YrNM؜oz$`nZY&eS儵kk0_W{ݮtp;|p𧬯ܨᚭNYJ1S1?q,O.F ,#;G']jM7sB^Kus3# 6\Q, ^,~Z!#Vrs$iY/.Y*Qrî˚[LEچ9Zir¯6Dl|Dn=429=P&s奃Ǣۈ77[ ߼cL6(`Yp;ӫ6T4piŵ q&?;5|h)69"`jn^r_x!<7 6Ҝi^%+bv>.&Nm 83D2L;l_w`fUI=kM>_U~6s~sb }DN#E'*"gu/~[gb\:sO`gX{oSQZ{P|phW\8?{rK/6e,&~Mvf2 ^jEASBՀȵ1xyۛ`Q䌟,pNC<1fÈ2,ijغFuѕw/sxY٣2羦qu󞹾"{z8ǩy~׀PPp4FlsBR}A@Z>ǜ:~pRsf.sQOkg}SسѲ8{q'S296?Zk }fti gs}iܾ>woʯњޛ}ۮmih׮oVg{z)RO7@AgԩuH7KHQNbqbDΙuRhi/bӼ쮱fPShXܞӳ>Oڵqu=:C\=(\}a|S?4g9ŽsϖH8B"%ɸ|]F.5Ϗ&Ap( FKEA L.@j~<6^8;:Z,ճzM>rzc\w?ا֏b97ILĵ8SOZU'f\>:fv^y9:I )ڹsb_]!1MGA|sT7XHos߳0o)A*E`jixxR2 i0T,y͜ٺFA~d*533LulFqZ XJ6}؍q䘘X T8O/Ve-'^ӛxk++_j*By\ZՓY2]Tj_ǐYY"owexVcrs V+˚dm˰{4'yZe!^,>gNr6ȩ jze.rs%ڒ4yB' PlW]]s$V'xޓ@>z*ڵ Np= 5qϣ=oO!T9guX$_^/Xڤ>' h6qkv9s~j2Ig@cV@~thkcqxg-ݾ[poCtz~xVzNC>[r~КΫo-;vl{90KuxJxf[u"&N=S kڮH8^| 7M#vԀqQy<\N0 28r iʜuMdr=ƜH(w\v ^o߯G 9kLW]+j]O|uMBXch"9݈SM6SE&xr*#|'6ekuO}eżg %k8_[G= ~f6+ 0i]q>B Z+r|fiۮ<@R]%_+'צ0nșP+=X$N,zsq9e4FG0'i\`'ɳ}|ylfQɎ=;kUī1q¸5{*v:=SX82C]\b9C>-h'2a23w TB3V,T?Yj޳SSF4#Eh!^ل|J mpe@)ԖD՜[|f=,E2+8B5 b%o᧺ X 2MyM_dT.ԳLRbrn;>ى[9/2G~okopo 54N=z<;G#{HWsfaK򓟼ŷ{<(C9"f]':.M{0_+]k14˞[НMcӘ2vR2N̤ۏSN&p>筫-uK~>S`َEΓW}g?<9v죊+sDZ:W/Vz ~z(J<9N''h gdg^6tM9MyPwXaLdXo7$f\Zd1O_gKi竣,s.=ġM08?Fg䜹<54N )_/ܸVc\s2|=t(ߞ Ytu'8%JAꞿF #mޔ6m>iB>K8>lj HWogӑ[呤%|Xv85KNk o)q,qʟTCӻD5%nǿj^8׶L^J=p-/UI߆hO4"8=vH.گ8ь?A FfX##nsQkIEN:3=ySwXSv# t.ZB7ݗJoys>%u"az9tF#?!Gj@'N܃SCsN9i`M,7k;4r?'D_uSJm̕?ũ;@YAlEHAj6͋^+̜I>snmY[|h\ m5تe8/?}>uMy|o5sCW^8߈0Ou:Oc:I#a'rqmhSd\-oN7)9UM!Ӵ=`fl> zzGj Wqe_\̃=;7xAsrhzjMq2uY?v浽 rq`W饪-0;(e3첌 ,ft~yk\OӇH{LbjJOr)fq\!4pY&)Wܽ"WM޽x5A(|6}ŗȯ#nc[5>rrzu\*~cn: 1^_5}}c0ᦢoXX$gVIՉϳp_rQ/qVjZGR~5zGge//3+ͫն9Tm/5R9_䔣:6C҆uz9VӘƹظWľU? k&z.k3gQmZ'hY!J>|s>cTQ)mڇL1ѠߺK_pX~G|k}sDt'iB0a{<3]^bn]?K B-D/րS 7Me`$^q2= 0>ϰaۓN,ADӺ0wM-w$@}BSԯ}/#fn`YsǻYɑj;zF]yY _}w3`68[X?2a3Ɵ>)\Ruo_ ݸu BmW d G{xWIuPͭi8~jt. ){ݏd$i7SQϹ"uѭWħljIml㈏ 9Yz[97,ԇL˙wM=kq cok\;t->||ui>33-Fdž.<2W7-3 A&P}h?̣{kg0*4bly 4*(!8sD=Of'gwW(haw6SI?s?z=krx7ŲP[##˵p(<>=IC'!"^K0|v[ク`@"suSuK>rHsx0:$hRӛg{>`0Rf44we(ii?26h랩=5@^aܪ8x8n?(>yAr1/vCXඁQS{bBV#B||֗埚żt]Cכk,^NY 'FKTjE2wcھKKnr"7YqoLJJ$#>'_+C8p<ܿ N,k~^&NNxF|*QzyU15ՑWT,S ۇg?>gϻ{RsE<ėbzҟOu'{nȈ?ÎrJޡ.sof#:{ SfF&%"jQCs4/0kV),~I&8oRC~sc]xz]cOAl^?ug=/?~^"3ȷ?\:~gO\Cr3g.>OɇhNT 8;$F,bn7 n[EִCs6 7wdoOP~U?ͼy:p1tdž_gQ Yj\'Euseu|eӗ]{8Ъ2.H)NNHyAs] gqFronj-\- 6j)&3qk-;⚹TxIFr`,!ߜ IDAT[թU%3 䍳:G(>~ c0ZVG{֤.]n@f&CeRˆMͥ~~wmynVn/M(Dx9%K5=$O&k)4)/"?}`޼^.'?aR7|a-m=EoSƅp}ee^w5pt"t<7s+|>,1G.{-g:S*s?rg+J { z,x:Gr'N)Q3ӁU1w W^JL .+7 т= 1Sz5eS.kѭ^Y{qBSGlok\ÝƉ7הqog_).]XAv+B?y ƕdӞ '@8ns&{oW@Y,ߎ Wq5K-RtX?9M QO]> PO|`c}5X]:O i 8&Xo/B7s~C˱:f{ʳ&w9^; GΟHg_H 8^|ړmxνr4|R >"@?f3c)&XOnggl7Bro Vx3]*r]xi>$:'!IlNN4]!9>Ǎ<,_)z& c2I;?\˪hS Hgv9!MXቾ, ?h1yg;>B9|gm.L&G*"*|3ɩapsɎ~>yDeE[yy&;/Y\'h}A0 34s$| ;%u :Yu]@l!Ƃ_ƴ޼sR(lw7t> /'vԎtqejtӫLKRs )gy{eNe*]n|_ EIo xٳZjd<ꙭ{Ѱ >#7ˉ㠏k{|oZ!ppgBrYyA;o/ϼ"yYux0gDyidѡjӒw!6^J}:Oyh!f'z /Z`:" N\ ]N]`nPԠ]h:j㑟\Λ[ oQh^-n1/Q z4/t98t[yBxx]c Mf9:Pv %~.h̍57|QjZl3 ?cr/ѓ5n3+WAYӊK>plk[u8G(^SuZstcG>X0trSHr BH_ӿ%=?e y/euMeU.Piߝ+ϥQ5#TӨ:BC_8½X9FS;@h ][m.ɘ`ڰ{N ^\:V|ܐ՞j|L{2/h|xk@Pfah)@Q}nlˁӚM*G9~{zktpY@zz=(-P|6l|1uN5' sZd*VDgƒ3"nS>?엇<|VwvEaਅe繗> w[<} Y\{ܫ' );z, g~8/OpĹ{uSךr_l6QM;>ݞ?cݩZ,"^̱HݷqZ)h_۞p}hßOho>Ks(9}o_hb6g=&,czW?p}s4Cng~띖Ds&5[Ώ/#NٴYɿRm<=k?e\qߌ۶=$mG^?>Z1|^m8\'4vpO`WaoqEjr.]sؽ?==o2;s>A>Ľ\\\`#aFKmv^8HYX~@?,\x5;99ˍ}yᗳo}L&&sa/k#AM#r@}@4$#3#οk>L]?ᙑ1˔wgj0ܿ9; =|fpOV"_nYJbOrw7Wŏr*3.è\ :G٧PEuyLۭfH<J'x ɴqB|&-jv2}d %34B$529:Vb4}8Ⱥ+sq.,7z]ϐ@ϝvs*p^fE. 'Gahd[4rλ U(͛Y2p2]kZo7!ER OE_}>]ݡ;$  B~v¿(xPTMy/oGfzϜj8NltUto]EY/,k|4I>i[*_& ?z(9+o67wCE$iUÎqJu>#OԠ1[q7]ץ|f[皚S#OiHjP{zNDaqh.Gwh5\ӪAX̣_p <|ΏɃE{羼j/%SK֔YoV"k,]7slk{z?92["U2G]ܟO/VCba/[ܷ?zJ.aX<'JX5}[3*qzhPr8v1o [wY1[wW13iBp贇x{ ڠ ]^W|ΐ ](bZM%fŗ_s3#Űp,턣g3u Mg ƽzq!Y+\;7d)Gtݫ5 ؇h?lIb~8fsU8*ܟV|_ʓZ/s 7Zބ%8PG :*zbYi9Ծ"- ׫!c#;ᵾ|81dw>1A-65EH?:^pŤ? KOo ذc5Tg9 YDj3`L>FNt$T;ClrA2Rl@a/~/UcjSz[=\7іUՄ7ȍ@3fh2^|2q1?"px@K[-OUr =ݚ&eO:Dz`pwV\Ugv˹\kN}/P-+TfT:s. LRC|ٝ15I^0;3s>O~Km777Iױ^ %='&_&A[?tM+s~Cs2g5ursL/л .` ,n+7|8MZ ^o߀bކw $|n< W>Znڕ;>7 ~t#Fqcj.>lpixFe3s$viŬyoVf/̙0Z]yp?l7B9 u~sH~"^}_RU\T2>@@Bn}iڞA@SE,u(Umo|Gpww=lEHA#h z\B/j'Zٕ{-ZvC5^ݯx6^znrGۙii\e9 ҾI<.#b;SWqUcYaV8xel_t4Fj}c}s =־+p^I_2\&Ɓ/hG7A\)@/mwZܙJ -0Ԫeg.3?% 4 f84F"}{] #<=2>oc>St4>發3lj7_1ɺtYTrM%k@^!Pjs2WWg}Xq?=LǽCw}ߐNR[c8@6l2.s#Ji>\ ։|0py~oŶo:Z>5[c13ж8xBn((v'c+ᰭKs \ ˥< Ϭϡt#mjΩQ>=5˻$6g-s\#s>>?xE <2;Q,Ko׿DޟYGJ̎S'Gs{i@Mfiq=}>+p{s"z$C29799o t9H:u|pK\X[\r~J]zw{cLߍl6lz^b]Vcd4W $'lR2鸭o|,*0O{MWY NvG' MI@ )g[~uqK4*ޯ Moݯ\/{fu˳'v)Ďa>҆ {"Bh\ |K<s:5›|e "4\+Í7 )] Ih(GwES-lHr_hy3c߽k Bk1#!?Zfܡ|5X!w~ |s=n_ +Km]Yͬ6~8Oc%w%o^yQ4?H?? Ն Zg瀟_r3vuDq}7 njv[fpm u?|:`[Mk6߿P6(L<2Z<ӷP\tGG^sL@G|“3Y<4gļƹA9P_]Բ_0x}p#$fm2p+G$(H.z49< [{KT?z\W>2EΛ !G=7fўyZ6Ϡ'cR5:΀YwboKs8ew`g3HufŃO^FAY IDATڰN['~GL9k>jyTn&kyc{6h[|-͜DXX7h-׾Krc7sR{d[3'[h\0T:$gX>}?\me brnt,2>]ֺ_M}}(N-o+jX_hH'[+Ty.S (>Y(i3+:W?b!i$lý{حfpQy|/𡅴ӻ2e{zj}t':b9oGYK,;!>ub$4P>mt}μ6쌒*ysrޖeOu'u|=aOfœRȤ^Br/Э13S!ýnˌfdj]%f_/:%tSaTT#2q"3_yvxbl* Q=sP+zrSZ! +I-pK\h%$0S~aō$9Anov5rG:%:5gne6mm3ZѦmIZޫKiX ϡXtYrC멫9:>O|n=?hd UAROXYo|+ b0+& n SԄ X ?\:'7F5Mp7~ko:,K_O' A%}#*hʉȧ1gW5vĵToP=r+ ܹEӚ[fp,CVɒu^g+ Y`^?A2'EjMȎV4͜l{7Fĕ_`]~)i\֢fi}ysB/Z_]eG7u*{LŒzX.r.*sJz '{rr6Iԟ~eO "qP/#lV=䧡|X|7j/]r[9K>FzyƇ$~ăe.p˳O'p1rsK߯㍕УE;vpq}OE|b9Pl4~H8mӸ%;G\iZg"5ɩ՟Sy/'E'd9>u8ߌCyl梿NG."9 ITzgv./u]͏FޜwwEw_rU[܎ﷷ  9"!&Z(j-nzC~B<ps曞z)e{{TYpgXB.Z&txw? 8(^ pώԑ'lvLQzĝ.רi9u7'p_N/`z!U$aLf:a>"Z0f3יo'?0d_vE;IatGgk S$D(tKu5~| hRCsm@ޖo_oLl f\Q~񭇣AΒ\tTCs <m23A9Qe`"USѶ|{s wT֫;DVH*'Qf (zݚ0?mʽ^!F-TIpy995VgYέM=6Lן83J|COp2mdUM.I ]DN#zG Npġ+_wbc`{,-\ۇ#àrDwj @ҫ$e ӑzĔI뙦XRw&,q:a3%|c]o2ѻ]ޠ3hg:ɷƄrfN &Rυ9hzz |>  ̘HHΙ2R8^)'!'@:ºsSי>.i.u& gg%%8@*0W<"=f`:R9ͩݫ+5Vx͘@c:=gx ɣ7̌E V69{و ,uZ rjG|Ks#C)s+]8>`ܤL4.^7O#tl* t~ \fz||$yL=nyb:@y&ol}0~~j=Фw%'|7f4<9 p^-Ʈl_0v\y_}LѓWLt5Waumjo`l=WUmP?p -ED˿l]?r;΁[A"s3?Dgw-xf1Q~3ouB H??D 7yRpf0eYlWzǢ:{<5<ɓ%=ា1pO!|^WG@hij~3f&.p~)n+^Pso\i96h'XI+J&Os: mԫj ssϭq]cQ{YL \45skKjޙ"uϬ$%yONrԆULڭ՘VZ,j.߳};s.xYQZ'd&aWgucW/έ=$+|Ӗo \D ݒacqs. gx_) ~R'r6q {p^uAޕ~96=<(Ѯ'%x+$ ڽ W ѸIMy7hDõmWm5drOƹ8{s/ 1D]| gy6)5ONjGK0-3.߾AqOO!aWZ&ps,:@A8pL|Bg^ nS+&.:r澬jwѴ{ #\)k<8ÓJ\#'M/틳Xx=Pz7,gI|/;5AW8JnJ0KIOr2GMfo 9̃=~0F!PN&_t]E@Y~g}8CHk=yWŸԈo"{_BpQc@O>f(aYǽ$>N]cȬv_ &}@v4sEG\Y B54<c{c.1c'R{/(*ZrGs~)U6;R:W3p/v0E2zD l* 4 5ooNK:ѳz骬ntʫxs~9gs =`}>gy@Zf7]N.~&89,\8ܰiǟg&/A4~|"9kqx& '~ :3^W=~׫ҭ~ gH+|gݥOjyd gC%PߥI+{:Xcm,V鍎(AcKЙYNV{ CRM)Lҳ ɽ5üs/Z/{:W<'J¾)Jz1GZNCBֵ ES8λl))†뤌s尮v?rgoWN /h{{Fs,71rMaP \W.c\fL` ӨCx@3_'Bd G%8jGSIţa3^㞿$)RB˹AOf8q4MY>nTwME±}:y{˰-(3Xm 5)\͒ta~ϯeR |OO/`Jx3gO&q{Q ~ѽ><Lk!G[4MWluGWlyu#w{043s= _/#7 'g 0v kN^@2`a7ްqØ@:/N(+nyAN:N})җYگʲ\; ~iEfY ztq,K<;d7>N˷4|u݁%s'~bO%boNrWWɊ0Q5lsf|M5;vj|@n?m=%qOvuLo5<_Q%w5؛4]x\Ü]7U1sдԤ{B 2'ǒj^{I @ܻ?e{lmQci9.LUiMM4 1]/>?]LvˀV(|_-;8"{Z ߶W4fmdpkm[{vrMtnKtǽ<4t1xR#C2][+\S7`sLS<ן5}G[{432_^mη0=<{ `@ xz6BD9w pg:DRrp}pOլεN̟B 9.Ȕ/)n6vw~~ϭ%|C8RsZ~gAҷ.1-RؐP F{q,eDIWB{ 74:Y!dNp}1鎛Y߻y'a?3wt@3;%HB.$X~PἳLPu ^1-J@k5W+XrX1l7ړE<+rLQAG&j+:<AS{K{\cbrRЅł|uHՁgC덉S-3K|n!Prw۱,G3jf ]RU}v "ȽH;qli<_,F{豑¶)^7_>x9c3qpV@5mpNNVo>bǷC*Xh{fc#8]_efv^ rB匿)Zx,nuúgt.ΐؽ|CpAL5}8}XߚHC^ףܿmG[op$vBif6^{ b7na5sj?4zK|n?ؼ.uto3 [ 6t0F)݋YDD j J:0|y70{[$9XW%詋/v{J:~I8Q.>*Is{uoSwN'U>sض ͢{Pm'5ʡX'†﮹(]>^&sh:C1@Z'cdd<` %UΈ'O֦ky8ODhH0F=h?3!F?vYN7 ~E'ވ=p~^8V4s$y6Z(HߪQ\-ܬA670.wt-۵Ǜt˜ j o<͵M$p:|uRB9Y?+Csiy-=yX7SVgBmU Ps>>/dԽqF5(E+gtR(qS/&<1\k}AH_.K= |oNy-51sX$ѓq=F-,l|^ pM\1\.2ojv.qO6wp徹hu^xtE~ '},pq᱁K^oҗHk16DYSW0vt zcw茚jKptij:[\skpB+B n(ynpoLkBkt[r/("UTsje|ҏ3vl\@,ֆ5HB+I %z]@NfmЀv3 <|X¹ n_gڝ;;j IDATr x*tnX{Е3qLP||Jr gDf5#Xoɓz(OCv)_+&_N3慚)A~i? ]4b9 Vkhl]}wLta[kvdy%y#1>*~_cK>~< 8h )w 2ɝ!z{Fߘr7".gJ~(8.oUXan#kA geN4D7NT2~pIPt|0-c{qK<:wD8w]nn,'Zn|y8u9ݽO-;eD&^w6@>rF߫u} ?_o --@P4}9sE*11G"cH:\'VA;>wp-ElZ `Lw8Ot,S,636 q6v\z'/ww9^" KrƬNFl=44L9,XΖ/pDl{jk2מmQ|KZX džM < cIѳelO/:gEe[p;_AA׶ҚY{ #g^^(\uz OŸxP\];d o~Ӂ5c#kosa.ͼlos]M17WOtI ?ݻ<ן/JAM_d-IүRS'6z4J_嵈k$6@ O omwp>+»ߵRz [Ɯ޹,y'fԞ//Grrn}rrsK +4Ѻ{!:ͬDFkohtdʲH?)Qm8]o;׾霿,]ʵ>48vŠ5Vkx {p۵;.8mȳslhIMo0 xϗ;Hk7M5tͽa{P @]V[t]ZFOƳ!8-1ʝ]7i[sΆf^&ZBxPrĂ[R,R1&!#q]ۖ($5 &vi3jkdR~~yRpI_{\6'DYO؈]}o7_c//Ҿ7/j?멱-th{|kk u})%4; )v7#wƅTc!#?c9ߩDx| e6&ZKTXv8e [9»vqXk(R@>jvMOV˗Xt H=bM1-_]>z]qШ榙Lo 70Cqo ~ޗDhi]歱i{,'f1wީJΈ, a814j'?~bd( L+G)_&f/|xA`}=C<>ーadrqE-QAØ~ /~n00Λ3䯆DC8#5GP'ѲܦVGogMѫ(m_!DD~H+(?A>#PXdl"aA T= UKhL:[zׯ Sg0h1LO`yN&S (܅3\^]9g'N1 #r>L%Z7qލ:Ga5(rLB{PN'`rH7HWɗDVIo>䍂W ffLI S(٦=P!orюXL16_tD3D 7 *iVRk4vY/b)yfjMӇ~=wKB'ZIRSOFc|>liqqM:=.'imϜɇ}*5hs`HY{߸W\G{:4h9}ob n]ك=ls~rYa_ Zs+fk(ٿb&>7#V#,ݿ'嘳 㨦l2\7=gPjplR$ڼֵ3ĶUr`̌?ĜryjIkLnv 1;׃y㏅qekeޜD1z,_ auzp]j qc,㬭`/r#oX?_1\nqOȇRxE; mrnc,!X?Oz1ښˡ)[h 晵<_bDPo\(+FS:o.9,bk?>t׵ mE>6xyGTN_GpQ7{~o~jUvj,̛c=ʿ@"^keK~jA;˶g?~Ǽ(A _]}{vL7 _ۢiR7<_7~~JO}F@kr;- ^F> +w$tcg[.T8}kI#Am%^-gyEƜAN~utj):6-^d&u%8p(Π<%:c4ؤ{/zҟx',y5ȯ2޳} ok[zח1?Oݓ}3[;Tste.8Y۵|Oa~tSggK-Pd<_w$1gi!~;:}}~kH {=W]xgX٦\<`@qB2pƛ 8Yg>S+=/;fJ9_/'c߇Zlɏƫm}]`I'i,Ix =A6 ݻ3G0pΗxV1ƿkhI^* *%-?sՅ| r¼J-Gc),c~1!=LCq56+ݡ'_hƽזQ?ޗ(Í3 ϦE3c=oq b{u[?Z ;^҂/\^=}Fsn:l2^6Os<1qQ~\i3=&'zvSOi c!>s4h`f-FygO.aݚlso7|Ͽq/'7'0CNI|f4'<`f  y8el`אG:e~gKJkH:p p'GM9 .='eOMx:7z]L%-n@5;|[/!I~9gq :!6i7SPCNZػ/|Дw8rCgQ{\8u/Pi7MP{Zeu]`}w~,:/q+eP_Vq?xsqw>1ҷr\Ѭ>BkF0Iܩk(8-(AH/6gˋpʊj|I _e`I1U99?Ų;{ɽ_us~Y7)^:D D@Ͻ3? <^xSi6[ls:יz}RHXIhG1~1я,CsgH\R.G=s9.g/=g,\zHH<{ۧRsOq׏#O#ƈck>%llb>6(p;3 }:yW1+xBww|8|4*o垏+97=GAib݁oNNL7~[;@̽{O][q>,#A>/F#?DS.+q2j$s4&4ؗߑ~uWͧߊw_(@F>''i0N7 ^h)̃J<&=ҋ~N&>ߧƍ;IvgzAz i,$ $1j]{4pЊZNŧ"kY{F~q}^yED z:= F} )o0FhK ?vg:~$;ij'I> @яW~4Ws<R-\)%7n(n:w7[4C.FhE~ˆÎ5cMýk(/hE ?)1vdm>n?9xkt+Ԋ>W#r8RܬxxdGxǷ3NŎS9DP&iB5\Đ^Vj t) Ǹ.h.b.y^&r^ב0xLN<ɗ<ٳ?p+Ok|J2+YI1;vo]W9d½|s/nǓZ nu 8ZSb5><"JsDizdJ-99O__Gb< 8qxً4-J`9ɹFrL ́Al h̩<@'uM_&盌KCϩ\Vb`ٿ.f pҞbc`x:l/zw.5;$7HʽY.OŵOLG1?}F`Sb76$2ٍ`>Z)#{̿ZrCIz9Lƅ669WG bݽM7Y8xD:Xxs,ݟɝ侇.q$+3ϾN\Ͳu`_#aFޖ99*ϤNf+Ō/)Ya?d;sǻL~Z;c}Ѻ,87 xkt}6g'c7y?9RvOR,Kj6M^v2xw$> ¶aKrF1!O?v$X VE> ؉1~=FjphH}`p:.3^8XQܐ[!O'"wkbI^&/d6n~+6 5\|9~bdА6%v~oօ/2&Fzjy5.7rZCx#s4@!K#ׁ&|1%b*ˑ}ZwL M=5;O#FcZ @i| xo\@X?)TBa{b:N&d2ߚl~zg|>Zp܋yqcrd?d8 u^p=/lf%Pڛqjˉ]IOYG#ŜOL})0Zx&xogI)W;oܬ 703ԥx︳b@u7۞=3?;/z .ʐs ">TLK“5 I1uFvp%Y*f"8/>2gE 9 G;$dhX_lSv

4`xa%3*m([V`XA֗*b({mlNx8#QPYs79r=9 :0e|غ5h^p݁=oo>"^texKx(} wju윁gr.a|Ѹ$ z2ǀ#?k02pEAN+̄bxtܕ#f |r$#8o$yԣFqYbe9cnx;ڧ<<:yO~~}Q zq@?f ' ~ LV ė#!Bk:x8GfeւfcHN?rb&nw1v;31~qL,t :䞖iS`; J{'h:cX^&7U-'{P7>` 4OL 3kt=(M.3|2gByhy{3F)Wzی?=d6<)!46͐b IDAT8<ēy PI>SQnG-cvĻr?uh FdԼ/Y}}/SP[YIB!MS#?^9< f6gN|F1\/]ѕZq5ÿC`jg5kQȸba[NඅݐF$l ֨8Jq#SanE^מC؍fc<;~8fo#MuKg]{ 7}?ON\V+Zx|'.9s:YFnHR=6Oӧpe|qkRɷBBu<s׳]c[zsI)+`fojfZs/Ns xw0Z_c*?((xwɬ si)Ot1^Q=F^-h]'#= 7 _"=f~_7 maZ&|:jwpo!:ɚ2==>a:/f.ϫ}1޳8{*Y ƛy^ao\giM~T66!cu~R~C᳑t6L{fpG~Zz4b=z 06:9Q"t-Cb;\ hf:>uqu8cCMP9z9X-pP%'Vj.uN>wPo*R;}7Ǿؽ# K7^8!n}Xru_+s";#sՊsAs$  c# =ӉG/>PI/0-y,%{eqސ?N?D^0>Q !U=`|w; ZLfXbgWqZd/cM_y{CĪ[ח|O{l Mh҃0*p\\fqj%^ia97@|d ֣홱Ŏ;>pqsι|0dcbr2sA#!i^cL@)_&s(gca_K;,ٿk"3s-9nYG >=R zz r;Ns˟#t ;4}TChR=Ok#"f%cq6O~ Z.{v<l['h?|o2;ă|Rwj4Z l4~8[0fMnhѵs>͇[ģym_Ow ?|coos!Ydg}x*w9k3i[[ I[w2 _k|,;cH'jS)yԬ+vM ypKaͱgGzZgMkrcY%j!,$jl;gFI6?Y*UrQZ|A,ഃ$#9}*5nk-=7:%_&g[̻O:.f\s uZxXYN-O?_ Уή+75n?4 Œb(xs>ą/p{{>㹜dYx4%X㋴d͘88-1{.g}<=B?`i w+|)[F͓^Ķdu}8H[B}G3T$.v~q1:E~ЍO{0VOVkȣ[ùCo^l4"\D3c>0i7Nkk:쟌Ќ0(hQULĸꬆ՜8Gņ.} ^{ Od&,eLǾss V_|KsoϏ=`[go;vG| \[fMW ~c0g<t P-zeFM'f3?cǺ< yq 7+~~#:`@u:bוpw4ey ZZ~$f#n  h.^8_h붺%,/4nXHs9sqKݷKV\El fYMˏٻ=2.8KSk9KC/ _P([Dfe a.?ol [/̠Bv4PǏ;ʏ'lB9$>ӔƲ˾&\O=KA9ce#Gp{B[2cprqރ>' xd ~xSeI aJW>R=+nįHhX~4D;6$oR.ۏ+'8b.%HB?֛0ީnެFk ->j%vGN pmI_55ܐ- /3 C8~tjg)ox`kI_i~[UV-/Tc!=γsϑbdqOiHjOOǁ0ЄzlӬ|I *Z`N8Yc`eUfGovGD\p&ywzg[(0xStg+:cNxd0|W`%0 uKo췽,4ojyۘFzz8żN2^͆@W@7 o%bsK+­ b,xyɱ0l6=9kko6[Olu=D)mNsLC5מx4(x9ƙwƁ5^x}H3_.۽gg&W=>eM=rl?)S!:SrӺǘoɱ u;{(R:W߽Ւ Z{}A(wh~`0/0y8^/z,b;_]aKB}SR!vn_\mƃxCա\OE~/M 31O @܄1p(aɆ&_X(. =x=R_lϋ1SmލI._nA lU'=d-yjq.G}57+p,K 5c'ؼ/6`kK<ʚ$Uy!˵ak<~B6g\ٛq;yij7ZN~YbMx27 coN[=Y8|LZrcwc]`:81N#|1o m s&tc.s09Gy6_s`N'kZ71pIt1{“|XSY5AW?:sn`'Kb1t<3Tl{qqe\qpnleZ i{=9EDL7vew$ mї}~yn)jV'TCt:seޜUr f||tpf-;pA UnCRPCo=pKqfz ,!@ko$ ~]Į0' +,?}mDx6.YHG.W> xzGjõF7|ikgd?p:%Co j1m0Xz[ ™Khn泥1` sul b@\| 8™&^{qc,u+[E C[@ |\5`XPksi@4mmug^s?67\rȏ;@]L,Cq;?E^]Ԇ6℟!X> F_e%{0Dp,{68v'XV u4ڍߏk;~Xfn׸WYK9*/v[1 h/t>M9ۗ`skyӋq,I=CJgP@cƴu2ξ- AKfF&HT9?;LL,߼ʞX!wr/u ?:j LMhq~HH i}u&>l7w X~h育oC5=ts!`4!!COLvd P9կIk7at5j-/)^soj)ў[e'}о~k}}i&g70|ڙ׸'Κ 8 "j0îT׎xSyV\ jxZ G_7N bg[=;ם)LESڄMjP!]'1{Yc ۏze!c(sĽ4&tLHLhNL>e+h#ObsT|?/5{8$Wfb,ȚU!msV˩5!"ZZ.yS|Ok[? oiF8)b=:RSr\1<5h憜uGkbKndk` =EݹwAAmdS.Es^Y{cKSdٛ LPo]"^E`(wyr/&0|_-xtı8Vq`&̯ƝqiEo5@1gr7U{Adt7yq⻒?s#m}6 k6<9^1f}XB梩c#w^/s4O3r6y7n&"sz#3it/lU.f UWeEPA{fag }K.-ê [n>{Q |V!g[૞!H>Vv7DAi ?c\'>tNr8*q5>0zH]15 m:K\͍GW1ђ/ l<1 2Y1a*ˆsdq:|>6ND@?=1K|+3S{|a`犸<@ӽ uæ0ABv@YKSu`)|Na^!g98r?u!gGёff1o<;19iNjeD(ksgUS`6k,9 &\cdamd .M'/+L<`oN/`YM8 π_׮):Owv̫̍cO.;sl^RkLW6:@="h `WU(9~dwvp5o #sߩU9'&opx10v \I0þzu@EKDzg|ъmwp )KD#FƳfʷ, 0E -%h&n7ϫU Kh fʸu?$mvL{J _;J 0&":"Լڡvڝ+3~0!iW]2`? ԑ0eBqS\М_WǦ`džMW6@V‡7} ׌|mGsK @g/?6[ָ_alCSY1یr=бSGg{5h^߱:bYŦb^卟[K1;s:]`6Rצ!4b8Wk7KC֋_3ލjŅ螗cD3wK.p ނOs_?c[ {)]WA t9Q'.8~e▓`=OX|rx5k/AYOcgVn?}sew -!/>gӠ\fƒVP6S]^G9=Mi rZlT g/u>, M2Mޭݧ­9揫=ƚe0$2 p}3sS'nW64?q@ܓaϿя]s6Sz?|]'cG3ȡpY|>aYO=/j{<<B0F@6^úy| amJBic>{ѷf;T,phn%TĖ.|x=ܠ%+ 1F}L LPNpJk?ZH IDATGub!? KWzzE&Khݘ89 ڽzMgO\Oba)bvhe?ry0ڬ)FsVn՛gkMr-A7ApxW-j.6a9D΃KHWV5gj.z:%jcŦDxp>8wެOKMzQ1c Fr!)rU N1N4pͽ=3RlU>60om|g:Ts PTA7A8'pG&46:4Xre!DwO^ 9rK~9x/B(\"n#j>gEmN2]^t0Az62_ Gz|(0X\7.rN؇& A̖ݧNJgXSL1#a7Lhbܢ^:i^}sɿ$@\#>4n5qƑ5[^)C{0{r/"׿§y 8?\?V#=-) 魍 k_oPcBs#1_~t98 E8q7~R[ @{~H{rY~"!FruBh> T%6 ~ޚmzV$5kyحZ^y>>0Q0$l鳥BƞTZ='Nh/0ֹُA0?s_8HMRDo:At#κ q4=gCHz!DZ @wvIk[uV b\ӤfwƲXFg1sc2ə_.ZZפd?L#Úܕ@uZ{)ONnͱNMtIɴҜ7"{ #:yNxmso<|mͦP[WR,xHolĸM|{˹+neko#l;X&tn7ka ߺvn`ADĭrjMlzV'(7͎~ J ͤ%u'f):N~a._bB>-$P$O'<]dc9ͣj.bfstI>F/rg9nn9eġA'kq0h۫%lsn:kϦ$`?c1RX^&L{<]瓇MCuj}Fcַ/ν)gJ)7{MOQl֟~&ߔo,`XӔ+1Mf^"? ˿; jٚY_hg06Aȝbƨ0kktOথ^ը=hH>G౅zpXzk|yfG{ ZPkٟ7@3pRsRۑ5>o Oj`Oy<ޓgܜpޜ qF!ݹ&4XXCrcL-(F 7mɇu:6ْ??  _a0::Yp Zw'Tb3M%lsܻD`fm'}O_ &-,ؙs(|, O&ry_K_#eRGCu W1*3Px́$ٞ(nioNS] })|^W<-):0ŕy{&5#\/\C܀SCֆO)yf{Bn _q~c;1>p7 אPaN3S::$9k8G9F5KcOIb5wFf 08~􉠍u;af8nPr҇DZ;jJ K4?-ank5Nb ^'彪Nk_\V.3#@ʹ%x ȡl Ͱ&\{cf'aڽYl?X-l QAAދ5)[*`}7Ko&ؽpsM`ͯkZog,B1}GeO_>q_1FΑ>!Wn!ƌ8E;˃ˮ=<;ۓ9 %{ ƾgi)}X}O7¡p8XMZN̶iU~b,CtS $GH2]lD ,JSlF;X;LY3T3a &ڳz9ђeal&v8ͩ+vx+Q^gإgx P'X |GYs>S'n/fkDj gB+?Gz `X9}vppPiyVc{,Ngh9hN^p-b<-a0^^1mg9co6k{{n:H |'Cv99EԞ _>,^9"V:St'B%GxJCrOYh4&>UCl:B\T} Cu-֠K>r9;hx>=S MX[ɽD6^6 ]j^69 ^UN=E=^Y>ZQx(%52\ k5zޔB&|VJ}HlF겐q7]O?͑ s8y}Ec:3OC<sb wq6kF,;z8|ʿp`nX,;A#RLev >(O1 e+E՗Z7wδ (|{#=2^}E+oe_8åFϔXے F:~$M1;ZǭyEWԅ4MW'L_>wL^~Z'H8.?)X΁>w _OdB;8'z^Or=7y.xp5o_0|a[m[mZv8龱{~k:E =j"κ2qyumoOs 8Ͳ=q{k=*g a 7<z:o}`yϯO gNNsLq4^fb2p yj[ߞ RJ ͛d<~+oI1q^ ⹱,sQ$\L23KӍJT514ap~Mل˽=tZ\<ٙn 6l\Zc| o&]~Z%֙2]qHf c7\M31<6 *zvx;%F3=X6qύJ] |5cܹSq>S$i',ź5\7)nRe}t~q:Ӈlnhv .zY;'g1&EkWI݃S UcG~%@.lیQ)s?XOEf9yZ)LDg31qC&fڬKno͜&Pʇ»pqF06ġd슴7ߤssY.lZ6V!THU+X4,1-`鯐џh ݵP "w}8mpc.]0=IfD"֦ا\.y@~8%&<,4n=_=Gz fG,3yt25Y3oNv~Ƿ#qwE6LNG6iDq8 >AjӎNxE{2<;͵M4ƹ'3_}M^]B_!oM9o\ t.N {xW-NyllG`mڲgGCc¼^\Z)fGEtjl,6ضi:gN(<ck}IgNSy}^*w=h.[|"^%L&մk#3P ]f2N?\Z+i:ql¾5$0΃"~Ήo>mc>r58K4JF×_Xo.6v/yy,z3X1х츨Aod$0`L"߾SS3 MplXgL+p oRp=ͷ{EDә/vY F^ǁuB@c㭻nC=a!~\%/ڬ1h|ՎMra\߃3K9ü\ǿEσLlz[V.]ͧ`YeX +=Y,}“u.Z@5wPm8i;B!) MUG.j,k>g!ObͶsQV"p_WI׀vaM@L=1øMvBN7NS Bn a0ࣕD,Amp1[E; _Mw0qzӄ+l[~Ke%nwh™;n穨3^Ja(7ބY}g"߰#!D޽{/Q۠[.]yf(:2Y97_4dʔK(Ge?)G4`I./xN{3>_`.72t9G,S9>gT}8˃6yΔ~=X*ӽ(&޵`olj)ک c&w2pz!1|>Aۈ&\廷p>w2;y zZ5qn]sĮE'1tネ_^/=3;uPrV1輊 E@YޝO9 %E ?yt&=<'H`mFj&?/*`6fZ$^brNRꥭ=A*ɳ# 9}- d+ߞi}y}l5$ ,[G/|&T8z>u=>Z֩|؍;a"j"*yj}AqvyCg"<6k:BƅGր_C~cZhwLQ`cPuS1*ݓ3~̇S x蔍SR)쭕CGyp=ݴaϐyZ.h3w@/px0:o׽| ̣b /gygd+IV*+ {hh}*L>j'4^[:=qʎG6tutbxavm2I/v<%>Oи_3ZDJry*3᷈N^5x8}??= /z_4!%V0ٷ[[ں3dЙ{=4CU6hƱJXwNf٪X@ɞ3vAPg!V޹E<;1q*P&x'9?Ius4n1kq3MdvӚ_0琳LjsM@|9),HXzZ>>* =kнV!@Dw9`n vX7\ i R1 ۓOUѾGs^ZGSd36FIXŇNx7xbitH GkFwd.fOg.tLD߄WEN{Ԗmvt$9sJ=Ŭy(b{Wg8hRSӷqٙDp@tSuΚ 1pZ Jb=1 IDATg|E@l_{՛;֏H1-LCGs3[2P׻vriAw$:ķv c]7Z>'s~-Zzu֊p9ܨ jn}lOZm=ϯ*hg@g[|_9C%Rx'T/P-6$&3-sQ8F`~(!{pL(&Fmx6vO| yn b]/9 %aU?LL{2 Pguګ'vyqГQxGs`b%G`ʹ+;#exrNO/v$B5= YIA/ݫa5F2-?H<$K~uNzs-cmWJX*Dc;k.ԃԚ 2bfi>3OJ ù:x3 e{AH\,IZ0Р\N ;-#e[  >: n)ׅ>2Q=;DҮsDY.i3/xLAXO?dx=?+-=|c]lcKA{V %x7E&i]Mm7~ x ƀ[m^ijQ O/k+֌?>_n@Lry7P{:`94N9F{ rtm sl=łQZ6 xڽSPxx .;h|5k-LL8 =aάp\{ <:%1 *A1M/Hsp]C#5*vmǑ/SL!+u|ˏĂX͓ݸ]ߛ{tF#p~hcNqh^w[J`>]/|A+PMVX"=΃a5Vehwojs#{ n(;6cVz"_NA}eڙ[&/kUEqz?k̓ꅚu듕)5<iƹg{V̴ |1 }W$E`pTD}׎Y5rrѷx?/<&}}xq6DOq0Z5s=؋h7c{Y=/y^܋J ]"(yᆟ=åʴ7ڿ){nw j7//Jk4l>h\g>go.{db߾^7C90x3A)V\:o \>oh g,?{~OPb*sk>3x oD.-嚞8+Oz>/3Ӻb\Lkc ,\}CҐCaCT>uspV9>pF/<}\__EOeʹ]#cDB9cX`zNǞ7So<\VًJ߰Wb^mΩshg97E ;ͫv݇r>W3^] |_Ι9{Z)7%ɤaޜ#.8Oԛc<.Eʽ)փw-4YO khGb>gp( D 4}Ax!tCY0ŀ3rxݐ=umHkl\rO6ęg#ͼU'r&ghj}] |JG|~ؘ8*R3"C4ڼ_h\rA0rS;A7izwٳ~Y;6_?O6&\5p9;RV7L\#ꉥ=4um$Nuk4pt'W^3 MY;Q js/X`ϸmQ^ݵTmI: K*[~ЋܿA7(Rּ9{Z֣&|;xY,e5}-OjJ \ݢ Pc@sZ:>X3 Ჳ"cTdI遺_[CGIGq0c^<cp}w KE|+V)lsө/P?lñ} .( m6xU>]FW;1`ڀ=^*!kgX[KOZrFXcaּZ^lL&R@zOܟjv*6^q:ce2GL/p3i3p:l9?P^2;!>W/ol{.LZo.+h4L(\A|J*VQy\'@ y 8?C0Վtq +v>lx$bTݿz眒>Cd ?Lz-hQXC `ᶹqӀu,D9^99(j#t!KOE /C=ݲ>|v4Ca8v֧F.흰^"qR shqqbwn=Pim«Gy-xLgwFUyIxY 7F!Y5-y>T 5zϩ{Ȏ3wW5 +9r6lFKW7ju9'% ,٧Y5a G"ܹ`*]lMG]!?gPs= Gz$N>c%?S8@aEz >q ms>h+;wąT]rNJ~l_8-:W4">ryyApC.D9]]86 ph-vzG.Qy>?/Nj`mr*fyi\ X|}LKu.&ZEaS@ң|N(3c3US Ny>"<15s^Zb?/njoꙋ|]YAkSWAUZ-lg!^ZJ.t9ĸy܍}-Q ۉ֧/+m5l^7љo`wTw}/"S7x$<YsbߡOːUo fr o~M9j̺k g|Tb;(V|ɝqhgi|2tgyADHs&{ä2b4J #߳[6LnG+S}(w퇓W+7EV x"9B’0W ~DWrM("k:igO=u`x|@8۪d\9h8AǽU;CEY>]yK0fA9Wiբo9:gb=9}(|sh;gUJ1E z 87X^?Dg5_xۯA=s{- &]Hـ[cƍIKiE;p57_zșԯ?#_HI ϣdf៿H,4P&2(Z?9Tj܏ɃxgF~k")K^sxK0@|8"ixM{{b³3}ǨfZs(ʒKpyeE|`;䙳.XS+lr?-)sqtuC8x$|!׆0"5a5 䞥6Qgt!67Qڜ{5om|Vy3 -Χ-AZ?1` /Oo ,#tzXƃ+<< ]ݿ7粳\d%-a Yޘ9 m#Y'lw{EP޽[jJ%)iڞu卑螼%x$~~&QnKrfb' XQ@vvװ(;gapQϊOa| a;ƒ`\߬Q*Bw]);4q؏7;ˋve| (]Szʑ}kW)[>{T{z "t3 ~a\nCK^fC v߀` C3V|C 8p(;u lC=qQk3&LLk/,Fmk5U7 0ʘ4qێ=yQE|'1ixРv8@SMAꣾ= =`挂+\nk.]*QG g^!S0vR:-@GN=V>wp}b?tk,=%%V4،f XFG1W?躘עQ2^JAeuGN'߱bZ@ ƝEA=8bC|zuu)%J{ )D?c,\l`64^X3dq.zߝ<\9[?70{]#Z6Y{*μzX*qLE>kr{Uu쁂_헧Z-򿸭'XpgßM.w=f͔=gpl0?>sՂ1G^qH=r *`1,}6Ƕ dE*|Tϰ4{;< ?U'Meob(LbayN$%^CԻՙqLpC*aN/G!*;c|A/V {ܓ2ǂ~ Y_qj9Eo[Ss}9O;IԾ<w`ځx&;:PnF)=wC6fF3Xy=*r?f7gUO;9|7]ͼ9V";1SnFz b[ZʋnNw[YGzbx5du? P>_e=H@?(%ΙN+XC!X* oraOX>:SEΘ8z^ DXg%Fw&{rܺ*܈79 yf>=0 *y9LĈ3f\&{Z܏yL־,s~zF/n-Fh51)>|pKGQvύ6럞pE6{ʗ{{aO,-9?˳3ug^/hu p Ak|6^O~EN&>2g8|R*v.X}wal~-u7j?zsc0 _,O<|9a/wyjF>[<x:ZW]سi|k 'jA̰s({of0%.G^'5HBdc(nle՞ a2B}%?D Zs/kYfkw̸X yxc> |g yփv~s宣CcYzk?ځ7*gCi?'Ĩ'ЭW߫2/"`j~}ᕷe1fr 7Ʒg3X*k'~f| g>]8zpqW zCu;}`~d< Q2Mg@ƴZ{㑪A( !l{'9/8D4J\xnHнH}n&%!>d'Hu{Tbm;؛c֤ ŸaK]zU y]]f`~wv{rǃHQ`x3ه%HN%FcNg>?o@{w6}z&⮳~}f`(G> {m+jcve&dz+WNBYo|p 莕ZG6I`Ew}kY#MpM+G`{gbl֤CAX38/O֒Cg>2~f7?twzA TയIkAbJFyFb_OĄG험HIT^ ůȆ2S$0Yɭ&oS.70v%f ciU3;uD!t6:a֙@q ѫ.Hod.>`9o 4Ώn$ށSbZh3O(\'K7}}|T[r @_Կ ;] Ƚo zM:jN*KorhC"_ẇ롘_ Da6\pI_4:9^/%P/2?J9ƑG'Mk7v{u?>bf7 veb9W4њ=+VդHSLXx|ΞӤ4ġPXc e3H^o࢑"NzK) IDAT#W8ҷ ^K#44F<2rY`ZV5231Œ Cb`ypz7ǰo >H[Թ( PX *ICA_> Y&J ؉ŕ:U&yLBܱ8g93ڋ pPx\痙>7Zo&åan1 K@Ae>'\Q)e!'x=SIyg5w^973w}\G&.\ÿ9ϙ ۀY"Xc~gcD,JrWt' 5~b_2[8r.͙ZAJ\bsfz YO.H8PVlطqq ʉc9ti%U!y8ܼ<6N>š1w'@#cވ >qh{xR՘oGٻŖ ,~h6r[ۃn&5)wzO5\f@6,@g 5̜?1{ b*“Ξg˜Po5ϊ޼sUΜoȤD "^ToZVj@؉u9LcԊVPMœ9zZ-_rhx7KޚJCS9l~=^u+=QsDT/O,8DXp nGdu1Det5>o>q-7ګσݺc̬zM-ѷfK37Z9*݄kps7>*#@Mv9]Y}8u 屻zH)C }jM*ss#w+=g{ý5#2PoșkkV .8^߳:!.ZZ; k}ZLs6.lEGݳW&mL!9z}u8w 8룸'0ɨӄ0wx6uK eY{Xp5\G{;SEaGWw}h"|Tem͋kk=qjV`-m4# R~{4uy`>16{rv?/Я Gn?MM\EEB0E?8:p͹ztz:]$?%_*xs%q GWK>X&p&`o9O 6fXMy!/AqB2NqӮiSlA{<ąk}zJdڽ3vXOuꀚK8G 9r_fM1#|F|O=҆TxG?pΫ:^`o>ҝʹW .5Ch.ebُ8?o^~V>?ŏ=SyƜ }FUZS>Hֱ{/M ƾܼ{4͇de9?eF7Wѵhj"9]XzD@=Y q]&>E~x~il0-H/k<%F?x[g$p瞍Jt96cμ0T;'zhr]o4չa4L3S*%t~sa Q7nLu; IK@L>>VT?=}Tc3P׈(yC` Ҿe"ϳW^òNŮnfEQ!=rO?0>>ۿ1sQopA֫CLxfuϖ˵㓐OhA >&'m{B)!,WSmΆ>\!?O/ro˻6g=,9?1 %9>0Hy {*heZlG;i1;fbxL Vx;#[}so>`ii~l|>2g"ϑ8b{6pc3[9ȼ2x8Vpj7,rs:3puHWY3O{r}ѫoٙ0v?'`?߲|`}c)#8C -c\|.3J74j֏oS<܄{Za \f=|コCcZM #ןZn50&pk?1좛7u 2o O#51mWXHL~MLJ߶W! zY39*(sڞ!s SJc=z>w ,Y{yCְV3 @C}(n͝ Ps}{gcKÆcFPZ"3!ɛ0q%\zggzqŗd>HDw8͆MxK+\aZ>7g"08OzK[꒼{vRNx;5Ժ8s^΃[Ϯ&%[y1-ap1b>t hͪՖz*Y"0.NhOx&. $}5{jbJ߈\TޭZQj9h̘ep-02~8W|9GtF՗jjp͆W*_ Qbgi8ŠkX~AuؙQΌ5]5x95\~`0.&u̜);­< b?#h.S !tqf{4Ab>*YXS9,}_ tba3=.3rhwJ`\WqƙM D.  +eÒVPue k V^>\󌙗zzvqC;V|l= P}hHDo]Q4N`/Egi}riω~<ṾDzLs֓Rz[MJ):gHjFnEp˳ ow?hpCxL0zgi܎dwֿ$F$p4&|)bW BZ'S=>yij^ZvΜ H`͖_C'cܔ8㵛όڡfZp5\߳2YtKoNZ9Hzv^#d.uOB:wiO)ƥ8u ZaGA~Yy=\|73zcɼ]WC>8a9Al{AbO='n X ;<o{rĚ[jgd<k|M ֜Ãwy087_֟7?7oJ]=aFɀt.A0}RX0g=|Yek& @EͰR4DgNЇ(<9RqC|;qKs87U3o =5o>|Z)r&y c_ 0Mv?.0ϗ׿*(g= S ui1a=,ppZ}%[Xð^}\4j݇?>q!~bse: ÍmV'w^BΦ{J7Jhͮ7ٿ}3\ $9+g"ت3d#X[^=[Mag\==9QDkqMRҘkpS]yZgxVd듲[ax<#[s^!^cOuL=K8Y Iń1o!j0{%O^'`Dzz^V~u]0!ӷ g`^P`%8x䗣||zloʿUdp<=n~4&}v5rJ5WEJ7-(9WHqx~ھoў^.[gl~2r7J|c˜ /匕I|iF;8PVvn=sXK#N8Ҧ2Ԓ=;$|LCn7qI͖9 ϰ!gǾr3-R} Wg=pe:'вS^J7gl^@GGvN*99d?Q`̑]<Ilg7rX,Wdw. hO&y=ǥ=0Z7Y^~fcH"gN68i4|;~m 7Bϊ #}8׆ߪ=b8=cGkk:%k@Í:VzC?֦O\l:I`yM`[s:%Q6ffT]xGsfҾOڣ{z8@pivE}>сfg İhI`x? Y,:F x!GE*鰦E]WAr~ho>{yΉKUv^ k&&>6$[_' .sCϮwyCУ-  kї\x{p)o(]&[9SװKғ@b,kj/Mz"u!XY1zߝIdc,d#/ @%77iЄ,'H]p%Z=8lbfC1E;IQW>n5wlJpu[quyz6nWfĔO_JV{]e^,gxu7qqjvx?i֋OQ> 3\;t;cb`i?m8>kγ~1h}93ux tKƾ0ro7t=;mZ4,S^54}j(=__m˵-Eķf$[$~;W/ y{><X7>;xJ_sFUc=yx}Ct`]8g+UizX'pP{aW۞z^~@T|SԿoaBo1?/y= I&o9oWm@hr1:|nI jWk8Q̜iQsV~أmEB,*{LP~Gk^=:kcIx&ί_½ !v/!M?FtCKq^{|Hs}F\^AcwN+B;gl'>U`šσ|L;G<2.7OY y/*ȿoE-#8cu!CG#=wO _= s%B؃q."z}4¹{ T|9︘MIs~4UzRx`o/̼5kr5:hzxFO[˱q9Ty!.4`~q8)v̸r_lD톡xrrzSyn=D'qCٛ{y>hYPs8=hOzfg&7=ftqA\9W`fXUxF<oJ|}0Bɭ 3/l\/Uca{[Fx6gzoP2^a _c%MSA %mx Pw c4ҟvo)Cט~j5 IDAT{^OG|:PwyWWW5~ j2h~@X6 NޭՀݸ9z17k4=!cx9Sզf^݂ vUCݠ૰CnC=|هo`{8.'^/0~#`o<x3Z< G$KFŕ#uC`߭Mp*¥e>h} <.Cwoj/a^=<[_!|9= H!)N굮9 \>w!=>H@tip/\ggvTsZ 1yq=@XO+dndX7|&ڸw75>ݫ}Zخ4G<~i.|6=Y7[:k<MJuZLkt̾$XƹWt ~OhpA )=d8!B:5g}sZI3i$nq|:<%w~FI ?|e~bED8-<Iü >Zd[[cS!-wvo+ 0 xpe+:\f 5LUkp^8xY ^WXw`p=uMzsx׉= ǐťK3j(="+cyvK^﹐exِg? <œzFιBK 0Ԛ Nʐ%8 f{fJٍ_ HF?%C gg)gL;à zJs8 zcb eaLO5}^.w 6*8rɜ?'2=vN'ϰ5Bm3dZ|j؊.'nS΃}^npS>c\|Mg\AygP<0ŧ7Ng6%rG>=c4~䜬!}~ԫׇ=\n1|9s@ ;$a]|'28q3-gRX>}c{Qey8.Wb&ot=m}nT&ksZZ8z#NAM-Ϲg=>oίH]ofxv,+ԍكd1ֶs= ÷h{>)2g" z %rZsj)Gxz&87ct]oO9 7o w  -Gn"YJsunqԤա!K Wy2ydN}S+̣@b!}=8ퟆno߬MG3,N"gM. L_7 LLj-CILɇCq4]qnUعfuJW =$k}xM^tcg&y_r?>( 8lBm3B]+byN'tҞ $`> (=SJaxva]_C&,񷆺SɎBXNH{vNb\o;8{G1qz%xj?ujYi)YG;r&:B^P+y"(3'gZ}60}}1x&܆_>5+[R HCVuKt9hfXÞ~Zu]3kAyyߋ}yYCr(;GFw$^bڮ}1Jry1s WjMY^qǟt?(:߳axv1M<Ü dL) arrr@_{y8R<\s.I49s>6f{E>Z2p >En77$8>O`_)i*]ȑxO@@XX=瑰YݯtI!LlU80{pENcstG/z]P*a h%ҀZ.PNKz[3TzuA[h1qUAkp[16VDLZk8Qpg_i FДq87=p1&k)N~1ϭb _,{LF#8{"/>g F)*{86X"w_$KGs; lpHmbnyg¨~`=],_.%6?Id$ފc~"o/ʒf%cފC]iv/IrGl-A\O_-\g9?x>L \/qMsF9pvx/ 4x_TymK qwM{׽fL7s+L$U/[Eةiɹ?P_ 93şrukydw2Za' {ppxL;M,GN-?D8BoDMR9spg%3p4Y>/3|~pA@}p> XF zIzp _qjbss*`hze54SKx.Ky}k$@8[$Y람_kܢ!_"Lތt<ħ\7K^ĩ4rQ.VjavPy~ zѫGʏ&K8l?N3"EB[ЩnjӞzI34:k{8j\̉5; F2q$9;a_-TNVeXN\1&(79 $~lAUnJWsEF;~k AZe9ZԔhͽ5S@*Fi/Τ ^l+,'L٩_gX5#/6Hv\/yt"xdbəsE{&/)XN`-Әpeo:~1Skr&:{e ] սOfE)=8~>#s\`s,λǍ.ǧj7~[ܺQ3fUℹ oItY!.o d=U^+bŽ‹ǻkޑڈ7DGE 5^2ϻ}x`Ui&ܶ N:3jįKg qh^{.'4v%=@ca{Q3*qSI`d}EԴe0ws҂$͉bGpP}:ttzy,= 0{WJp)m}u09 ;/ xh/a䂉ɚ{焳k7yct TF@县wV[L@4Þ79]MGNP{qb WDެ.kZľ}O<ɱ&i_j{j|{zxXk/sf)TίZ>#0qṛԐhR:{,~f%F[vTh,䩕eoC>RUj-y~!T*p%05$Ҝo%zjKv EDǞlܓ÷$3'i Iq6 ϟSs*D/ڗ0=V׎ڣjZ>IW3y@#Wft>dԵ^3{2ޮ_|.joN[[Ǜ'@b8;'lϥj k ӏRQqpr[rGaƤ|q"(D7I`xݿNgr4̹99>*\\K gxιQR ^k+Z3#ͱ2Ec4-EO%ul,,͘8m$.Xrۀ~i|ܿ{8[s%=HSa 鷛5`P$tÍ1ٌ)c[_qrBh&jZ5ClZf@KˣOkVΙ⚲%S~ȟ~اW _Wf{% gϗ\q4#6Z=_Rw CH8feO.:c u[-74J뱱1뫶ylIXV @G`eLrW>H?+0,[*;>f -6ҡ'csd3oZӐAy1?/*x1dsenH6O\7'gg ~=yg3PUns`,m3Lqtu'aDLyLR UktLD S\XhOF~9}EUr 3Wv҃$tl&r:V hp%{vb0>] {c,Vk) nD] Y<%!OZ`.֓:C&5 ?93lz."PYnr nVקK:P1ՕpIƲ_0^.I>hL {P FsP%8H7#&i!i&ݓfSwd2vaov@SK˓ց99~a!E4ޚ\* ٖxi0(l֕O^Bn|$˸\m_/O\x m2.qhb qvhfMeؙyccZ!bj K~IXɚ3OG1h9}1gB[1Uӌ&է%7{',qؒipmI_mۿ(+yGե9Zi /¥βfRp# =}_XtrQ*}kgv7uL@Pip:wflvXQg\ sdS[=`֛ /B߉'rVPKa铌O=7vu,˾z=wo^}ۤ1ټpjA[LZA E 8g> txxws$Hm7>#'CWDZU7;(0yqDė0ޭ+ilt~`&e NB.+qhz'J-HI 1?9pI$=禉o>Y Nz8,n_~aﱙ_OT_Mh0Z+ W5l;`+y@12;a-{C7 :&̓ B"I/݃oa9E6-C ^bS"Xp~`̈'<ʬkCeb&ǴDNxqQ| W1Oi A<1w#|3Ĝ\Xa~aZ "y Oϭ5-4dPo ٣"ځAcGsp3i8GCA*,7\Nu珴 X; %))pIpc3khJX]3]K8!^|ZkW7W/NӾ(l|0PnnD,·h ({4/ NS֞|(/'}"4hloD<&Fۡ=|GepaL݇!92^2K|m'"vLaM Xo1߸Fs & <FsE:_~9aqw' 3<]La+6ѻe"C$_;u6}0t۳>ڨƀ 6/s' 鸉aq&~SN\2~ێ_iy󬷎҈M&rg\hH\hk˅8'C p#?j53X^vV#s(^`MupP3 o&Z'E55G$:}Nn귖40Z?ZIiFz-Ot }yGZ%!@Z>3xtS!Ծ{#oI1}9g?$Z?o+Y!س3֦8޽{N6Re IDATn vc4MLOcn]^P{}jAln_hkA5^=5HꭹkX9c-p֣B3|j AtjSS{}n@hs%GAi oD1z"'`Zpd==V/aofz2gsKE0L׽y]aO Y2 xDØ╬]5l}1O u6͕*,BA0]_9{ɚ;kLo^I}wR$ { Hvsy~MFsdC0Sޭ#R_}͵pʣpĺʷ}zWc}Hy+Nlޏv+j* .Cɕygi| @xN5v=S-_7,|OWa9W<9:sxuyenNN42|.X~]'E}|N1:kDWz5m$ v6%\olvմH 濢>kjBfM!/j8+EI "}귫)Ű'(1?ܮd ft Oǚ a!@Y_ZAv0O" q yV/r8H[Ir9`-c9x5'j7osugXx.L$=u?1Jػs* $^ч38&kK4_,:DP{95BÙt8&Jor~pZY8OƎF0^U;r8o1ؒd,RO5:?w.jVr'Ⱥ`b Wk . %!G<ο!ؒ[;hf 2+Q@MpÑXlߑ!ENcS/XXkqnO](6?V_.5xm>^"5?Ͷ8vj?e`aА89ïM~}/O<4tO օJ ҥ݇ze'ګ3΢Q6-7Ip9ҍ;ċKS pgmY/hl|.N8]A7@CX>9|jmꃃqh! ;|&y՘˿[/ԻH@jAˣ9zaSC:;YNimb_~koJR=hSb,[O)!?%*q;`iT ㆗P/Գ~:E1 ß7ĕ݋2NC~,#&^1/d:5˸\%krxǼ{oj8>`ݿQ9}c޺'ј \ֱEE<~A'viȧ9h2AMGz [,Y~h5yzen+_7swoO 9m>a:Fh.{>浲bOpg,7s=\kF]^ճ}#!z\4g %Bt@WBw𿾽IG<,Ya\g:jZ3x@`i M=W85)C@/,6bи=FMyYUjqV!nHwUi ?cbygӑz1;xsRA,P&L9W7Ceڿ3z3qaXl? XMkT/f囏|I=-ۖ86s2PY8f _S,'_N&gaKȬ͏Obs:v=R?MJk+ruܹ͛X75 [Bs=" ǎI76)1 , 7rY~m?OUh^wтvNV4Vnw en+>{4%D;f4L0 Tٸuq =~ODq9c:\iż|Dars5ƽbvo]NƼ-aMN4YgtGcxZ_pE`^O]:.kv{5 Ce{Yδ+?CjY37ucCg~[#0p *η'ɗggmD[7hv Oc} hD%"318rQ!zkNsygP*BY^lzb? zQT~!| +v׉7rb k8B?~bVr+H)h==ҫ՜xyjYo.+VQsJYe}뛬rQ{X?h۴HC,ox$9" #eߓv _^ =ek&x8͈?gn"YйN#~ou>)2Nr'{umw]˕ڲ/4jm>PbT_X(/x^ 60zOQs') ˛h7M0}cwlk4#Zwm]_Ϣ5, p(6d6a |LMM-?u$ol9ک 7_~n[s$=8l&?Jzs'ۗ#N=H(rZcur7gZ;g5M=_mrG߻VyI<== $#0AUӸҵ?&bO@'硫?8o~`M/%EZ|M7*8L^ ~m6 :xk|^0/P'y3;|c*j+tG]zD^9v n1^+U}X^Z/gE<otayC.4OOۻKK?|,7u_dC")#uي/?}7_4ul3Փ~dhz 9pr|1>IQ즚1`q9o3l_&~vl^^r'_=ǠxEo{0Υ 4#9R5|yC˂S_9=wCa΁&ǿq&Qp'l` hlǀ~> 7],ٝ2͍x6fWAi|qk Oy.p59چ܊7tӹ#x=~>aW֕z9,'L_PLM L2nx ,9:}1=#Q5Zέr)3zў/6ԭ8ޠMKsSnWz.V/U{yGx=RJodL>c+ ^ͽ~#c=9|㯑 AW^aG =0˷{9χʂI<bk՘@]EZ"6uXgttүj~|bq/@(U$${M϶E8+&8 tN"q96Lt9fr {i);X hFl <&e&:>;],5X6"Kֿo ;x]`̸/h`i憏^7]5ɣCKvиSCZ=[H%J_ޒ;<o988;lK~|%?>{b?B\w$+@=kKj߮8~1i-fny(y1!zis9\杭{ xݷ%yo^}"y{z!JIk˝=Wbsb@=[ y XlXndT}sOxM YXQ|ti#ӯ0uZX7ZçlxfMn[j#ct.6w4h4`xt޵ tTk_z(?"? B7DL柞7fkq lٖdQ4ЯVDktXD뫗TWt/Q8m*9=\K,&a~sɶظyP,AҴe͗˜#Gp25 3^vؚ52e^H]cs PS]]ǵGsSc]oʧ:oxƃtIfQnwa)'ٷW93OAiބ ׉fGx}9,5BWQ9:]d=&"y9fA}ض7VXqvgܙk{J h^U=pZ?Kcl^Go\f'ZֺM|%:f}%TB+Fg06U\xyd{%zrccv ʻԞcU+<°/>hbT!^ @߶t.g1&r%/>#S-!4LͲs]ߝ(14S$Mc>DoHO>EW;#la)6%WW'Q̱;>~Nd, ۊ ph.G &A;[~"Ba74sGiȹwy{-z̞U^26]}$.iD ٣1]&&6w^/ݐbjv;3uO61ksfo70c qPF gX$"{f8%ױ0[wW<@ Ki31g@p IDAT W&7C,!g)!>9XN4M?P_]W1w/ КGVrßK_{aĶ'.*hVPiݔ7m 6}%x{,q=V-+K3%!"ok߹هʛop`ƬQh')yhY.6yH$Sk~j0˱CXc0z%w.,{fnjc|1-?C _a8g3Ca&v] x}7erC? D%p-4;sm_vk6w|?u}cД^{e{' 8"a :C<)~bH⟀ORbo V4ه#ض,0>dor,.;thz^ioұțCU7IglG2HIJx=6ofQ'z?͔x@szovgƽ2W*El)Pt݀Nׇø~~Gs3Nl_TG%]2ϫO 1Q0fBO}>Pyes~904@0%.s : qFn|Ȩ"b_?Kf-WR]6|Ƽ:f,Ggxxܑ^h) CG%w 3V9w>No9~~yk_r攈!q a+F.6u tΗ<3 oÇ!Ƶ[:Hb4'ʋޗ'xphm< *~RW),y|;5K[Ndwɟ{8όEboς-2Ts}^$ t1B{8=Ftb<62ݳuIAFO_ c.2o}(`2O_Kƞ`Pu94rZT'1W[my9^pnʔ%Fc;-G@3 ('GRH:c6B}{5sr=;@O},3)'ПGF`g(f}{3y2qns}{b˜+>*f§O׏&-ۊxUƕ}\_~ͤ/4Mg9׎c <ߑ^v68$vSD վ^p,NЩ{l> j@71:M( j0b縘jaŻG04L9YێSLY,P8s=&݈⹼bi l\iS:eO}d '&~2Xqri/NE}DZxդv޽=8srXg9|Rv g6aT$ K~[bhMt7AH-.1)0uvj ylz[S˅@E wu0>08S`;&يW|^w@#~f1ofp="nЂa<re;5T\_C?*>b[65O y^ߤڤյ:Y(gRSF5VfD ucRc& q1OF7- $ֻ.a1YoxL#&o?T'4'p`+b+q{*:z[}D?{~4+ϩ xv ;[pEh3o} /D͛<[=q G;CmĻ'YwZZ)gBlx ǂD,4l|PGnT~^_:ţr2^^$>۬O|q˼> ĹknԱB߸X[`˖/6;*s._:zO3/ 3<ƛ`:6D|!&$6Qw}z/QJ20½`^ wcoܵ2%ao96< KՅׇ7BY;\߶8N,|lD4D)99nTdѮ;\QGmsx~{?/8_= PO 4r6*V/(>|.8Oq\i7ɔхWQ<GCTj_Y8SXd^s̢ѓ$猺?_r1DB5pӝrPL^vg&;@cS@\O9%Lk* 8eh H{zٮ 'qpÂ9L?lf 1i[h8b O0މ/>7@&Pmeq3j$fzlWFC(&p#GڸT#J͇`oCha4BDCq'}x볖;0ghw?N?B)qT79/G/㳂t37 l5js89ua.;dy>Gu;O2`3M8-T/ x3C~OA6&zMyݜٽ4+=:k)c6D^MN7 `qOOΤXߘ`߫Ǻz H#NR%".:rZ+ojdƣk7f ڛ70qwpa7ktoU͚&B=UYe1C,W#n`5܍7v \Y|!esqqĎŏ\ Uh+ kM c{oL'5X49dg'9 4F_ĭrBE 8f>'=76dzвu2CuxX'bX c} ^/C$?R t{XDGNLҹNK;N3( s򒅠'x+}֮_k_W sh恮BZ=cx?2r$ n M^b-qh a"9|sExvwv3?-3Vǚ -,33sEh&Ʋ X_x9K1֋1AnnUdriš;Zy5{/zŋAښ5"<9Z GI֨y#$N&y#|IqF"5e==BO>XύIa3 TH~p% 1ߵb `xxxk'=&$B6omܡj}?OqΓ0;ewX?;2 #!ag 7}4uq&7NQ0<v c!'c~KD"]=RgVjzWVp9 k3㡽vS|PKА0m4cUwNOWf]-7F{ǁ}lv='œ/Zǒ~\ry_9j ~cլFj͍n82398V>5̱H:Fq,Ї>XZCma5:֟y[Lps!t }~9yp{Y@O~ h&kiOb'uo,{@;T\ybXYSype}KsL}-ԩ&8J8h0"V8#92@~ųW ci5lY 3g&@t{Z xDΈkjujrr_>\K5k `@DQ}]:qTރ'c),Ci "0F8ղ c%!@Y36O#v=8q~ _u :3KWRL<)rxْ.kxwͦ ߇^u^`y GX"C`s4--R"ia/5K/ġ95vgtrV>CNJw%ٱ=  ~r`[k)mWkׯ2v/n. 6zMB4ƌoVO.jgz/64L4tqwϸH?&k\ı^Qep4sXє>^%QiّB~m_ '1ADcyS=]L~y 55p33gt!Dž+>8 lo/hycI\Kᚥ)2,rȵ : 9˛z12[U).qg;ks?-'L0 X1yӳ5jre%*Qz$ꀝ?xcdMXc2ڃz |dlĘX-Y][˗X -k^J4'Oװ7==wZv?F{? j\6+u`xfyҏPEp`.>cr«ןwpo8&Jmk\.ff|N\ۉ|8Z`}lǒ@Rl#NbX/w&r&~̻\|p2%&蛈Z؏?\QT'^?6|OLjq'J\;U\wyX]מ8r[ S;*ԿZ{&1$*Ǽm9+ƫ17 / +doBq^qDmܬ1^=?RO$u>7ehb_frLxȇOcП|'Ŏe5W,bc<Ǚj;u Kn7^k[KXݜuSyAOP JylC\_;p٨(,U2)qXv8cC}tȹflJ!ʼnq˽GkSqv>_0b:>޾ZrdT>a>oˆq%f3;0} "<̽g%\>W\k@>&&Mn[qmP_N|y>M}*̲Ȭm t}k7|q MLm %ƻN-#޵Ł-ƞ)<8yN<Cx|\C[(߱9$'#xL}E~T ĮgB{s+)[9tYa/\J0 kX N 5c=ld}>: _8'z IDAT%7kŻ6K\~mazU!gpǐr."f#,:pfrdcz`=+&fL˥^ 8>e! ^k<V?LI { m q3ٳiy7YR_Z[6Cj[nCG'D $Ӂ a9jO\8m~$佇t~16_l|_z7 J1g'xY(Wq3P:΢t'_.{}Ǭ Ƭ؈$"PFvfځE.OM9v^3\v>1ΎBo=1*M̸zֺ=|^+ǩh gZ0&3Ãvᜣ1'{=VӘ$þ?1hrM7 ^\/>37I:юWOh|s(6AƛCbs,R{p~Aư15n}|.HO)^} bVr׼VV zX_YL6%x rS I/zY׆i'Wد~G,,6;"D~,ӅI$hqjReKZ-gʾ37t$Vkl{-f:qLNv48&tI߬>!#\iͦϧ0 ⱹ[kChbo#'ӱߪO]l?{mWu{*ꌞ춖;u~IX%O_'(K-&|?{aqXr߸Npv<nGkq+] CZVMgodV,{L26Me Mc1pG&HN-=:)ݖsuGnq'-oz4YA˓ ͎i]WV05l4zae a _6鿰f>LuL> HkMMf\8B{﹗XkD)8ّ{tD{`4\cB#`s/%krqԨبWȒzGtRkW\vI0J ^?5K<+60jY_9$=;q\3xvɍGFIM eru`O/=>dħѾ>jGw`'# q d,ΛYǖ(Kk A8Si._{Q@Dk!/E1W2mFǴy9BkrQpH\Hd 遲/☧YEX~ muiƳ<ܵT 8bmq5fۨ< mjsֶ`κГswH4i oϽmj<{̹cq={MO@m?Pr;>A ;гqc۹~џuc2xK.I8ѫ b|4ŭ.* ۋ#$xO?Pz'XkJ`L@][S4$A5zt܉uZDQ\2C؞dC g1qCNg ">xo (0ɣ'oEosH]&([dpt;'ZK@za-1>\Eѧs%}S&^+yţaa„Vt9I:7a`((SRw"+} ar ̑$+ 3~'~@k#ܩSy& &OXs5:]5vvDlpu^h u#ym>&2%[zNkL.,J/ pX33j6 %t^mɬVL ;I1̐z_XͷF0 o|ސn]:h~U)~4&zsWKztX `W^m>x[ qhl1ku`<:`{0@d}{xwꠑ1/]wAcH`xOW$ۏLIh1 E>iД,Pق ~ N_en}9&+ꓣ'웟z "ǟ\B-}X<aʷbn&v\{]|9-i^q1%X 4 慨5ylϳပ;dHԾԞ4u^QBX(l~Cĺ6cojv'*qJ?kLkV}F}6PoŸxB̡ g0烈dm:N6/lfRN+'NtT# 'b] -'k99n [BjŎAnz!Cm/ q.6~>3uD_O=<gC|b?pkivힱ.534[}@6to&2݄X$=}!%bYNlgE])BI_)%~S06nMRП`O'/OF?S_Rlϋ؇bOXYs/<2$[Fxޣ7µ^'P .c8fu<%% OjL-Ċ;g0o;u@x|Z =CsRN9 ASjgv_ke{ \0{1~۱hsVk3:E[T.KQ>y0MO^-f}ik1iTx OP' w-tsY?0l$9dr`1cM(xy8xc\p;Atƍ&23?t<.^F7ԗ~u~ri\ !G ,Ilx3/i&.شO.H$ph:zpy<,Z.Ofi|Zν״_JƠ˦@qgMm;מkL(x %ps؇[69'(?@q z"5C>y|X\㷦 mpdA|_;],a{^} Q$)5p!&+'r|8&mxho,BAG-m$ѹ=Ū7P$w 8_=>AgO}v6}< {`F:אLif~cT/{v~ܮ9Űqx˃!u~j/Y[kwitC2Z[/'ɤn~A LW]矕t'W3Ϡ}8w୵`:.~.Ę|'.EXv e7yq١ї4Y˓k&or+vxh]7Vw^ggyɵ2yvZõX\6a?P//4usi/4>|SV|91/Yi?}ؗ%X/9û^aGr,o+G K9|?kO:I e o1k̺#390TY^4[s>~ Y9 y!ҢϽ}}^'vɕ-ˑdilɤGMIIdg4dX+3#<<<"P|{f'cмJ8gc {1a0nBP=tWN$>v/){?\?W\@?]b^՞$Ng|='Sr."ú"3zs/8D[GlypĜ1ȰwM}rr u/;3_ڵ6NԈqL=Xk{ %r@m#Lщ95_l Ą8'̇ ћu q]7LUFB5\jf7~%6G'r_ ]C7^twg~3'}қ0]zW 9EUy׎脷c!_ ♺\1Nn_06~}x (&mX1? SƱAn.X35Qˌ~\)YzIO@˰XIr=oGk p3NLٗ&Yi3Zb-sr0Z%Ho\,N9@ے̖}fs}n oyG{>.irNs&vZ/0[0܌hzzN οӚɍ^}imAŠ2Unșד@C߲G #^s4͸ Ąց/+;Vl pv~qcD>aB9O|2m!u 2l₠p@GS(Lho#f96rƥޅ6ڥZ\mdbseG\&|ep#ā¢KسN*F ^<%/\Ộ)E_}Bg:ŵar^\`#:8ow'nM%IlS'xp4%yfk Yv<"d ͷ a6u\c\ @$&dt7Iy]MQƖvH1;%Od CfL\z+Giد2~x8xQ(-!l q<;_Z ^} |psÛNN;V捫fhKҢkیѻ S#8NdLӛڬփFeovG đ֓.kvq;zLn@g,kjok=h^d5&(LJub[^W>>z~)4'ـؘCwN+}!5I_(VF>6[o{yi gmHG#Y+MZђ 6Yಾ`Ү iAl~PɧCTx 8uSXr\YprYja\\_-Yf;tן: -U|yc6 ]='u/?u' EXK gE `o,b4,NߡZO6=胯X̞ L =$0*^rt a%Ze;~,=^;9\||sƸesF`rds*5w9:'Y3\2cs=lH胯,Ƿ89.`IbN}Kot |3gr !CQz=.|ې8{K!9f9*<5OCqLL K(k_7ؼ IDATr $b?ְl79ws 1MwFazAU" @aonxY3[=a =qp8&d6g9턳so1xgzY(CW1/'~Jwi`] ǹ֍ifәyA\Qz'e)ʞ5NG?Buʹ<~cS@j31ύXlRku>^~ 3 /{( xу -@$$pNdrmOGO Nk0qipFD/wcF g^|˹xL AW=wFV}.BӴMpwX *dyϞg<ÐyķZ&ՙNjwuxT&?'9 V$QU"3sk'ob6g%`4jn ͳ3*7ۿhCs"NA81ϙˡ5v2#}ݙrExߜs>=P9brCcSy?rt}F݋YG˴V1l6zx vq4vlzāص?a.{adH|ZCgŵOڤIv\]TTÊVoS9ԥw3lI2,B!ό6E xyx8I9o{4܌u6e SS fuxK\ü\< D>8ʬ4e^Snࠂq.py9%ަ+_ :mY`rߖ+8('9Vπ_o0':w<&9{~5W>Nef? 9<'fV^4.}dYRHZ`xpDY1b!xvcpX47B0Սij1f9W97s[j$,w^7b"Qwh#KjwՀ]i(Y} c+/+C?N,?1r3ϑ/V a~{ WW~sW:kۇs<"{;9 yqM9% NL~ĮtW<(M'#Х*ٵwe[^.ff|̊iv|͆!*5oC!k}8 "VzZv5 +^L % @:yBϞV-Fr; 1{],lӼccA(-&"6\@ 9 [V:֣-Y@!vcv@Q-oġ\Pr6mǷcⵞ&]ew(J#wkzs l0@Zoq Lo`fmA;pMD?uO!&a9#Εm9o㳖q$@S'[ߩ,.m^,w+qM䮨32胟h&3<58.Hk)I1{d{2ڹٳe 2>.S#°\^cJ.CyZlzYv|? :X7"{"oXf4$?w!ӓ页l.Y|cb#.]D5I?rPO?Jϖ77&,< ozG*xDsM02q5'ZF"_<>/MBƕk.}8͕ze(7]*F/~?cumŷo#X72'[uX/`sȎ8UT &&V/q{(1&/FN;y}9]t= L[\dZO$s>Dr,D> f_HˣrB*Q5c8Խf(ΐ-L:Mkh_М5H>0xrE]m#L+Rd(m0 Դe* ص>y-uZ#]#3 :QjAG)nk10@ټDcmKexgsY; 1kogF.kjǚzE: kr\XMX3i2beCi yYͅ4׿Vyӟݩ]r) Goh]t|;8<iP0g~g[|'\ss W{ ^eof}_$!&ـ~sX C͘6%i!unƭy\x^ȻWmN=#o̡ЯaW/:Ľgq_=7!G/v7~vm׃5;gQpM`7ٕ~gh3vY9Oj+9coVb3'jY\ܱP>TW-g90711/. S7e]cӞodݮa2g1x*Xr|cM&=Axr|l3鱱Z:G\!sx8#']qZ1Y? ۳6t9IECf'ʶ֊M6iPk{Pj?5rV E=Ogbb%\ 3q!n,_s,! BdsvkK{I. Ql$lk1T[rџX 7ߔGkSY[dn^3,?Qw sUЍ^xyGy.&奤֟~Ƃ.4ap'Gl[@q>qi۹ON_`+ I =$q7ߵcr13יyaؚ'zl[v[nFPX{ͻzdTϋE>abyZ.撝 t9cΖ:9) lՈ-9:ׅfjD94y| ȣT^[u;ax;a˚3촹Y)5Baг5Ds(DiDWQ/~|\0qDa96 q2omr`645}3:]~a0G~StN6/Y9^U+Ϫ4y\x}=; oa/^hzF`Oc~D%O!#nt5hgn6 rqb>k4vk%?ÖWpCN4{]Bsk(O KyႨoGJߎę={X#`6Z/);}ȋ;ӳ2_֨l DsA-P !^M/Vryrx.k]9|lw r1J4 j/XRģw ;Wr!0@[ymhM>]5z5&,!vfh!5uG84; yϺ+_.1݊[G<źgvfX,s,'#5}M°4H^yyn`gmuNZYi9HA.#Skv \]yskaLMadniVө5U`?Iw3?]ջGXho p0 6uXG׮ |rzl-aY@5%ͧ'e mk~yKu%=(S8 4.ky5lz2ps]Oe*b;d} u^>+\F9D</ +8\b)xĜgl}ZNgh(1}Pp5̆y\X $ 5ɩћ8 v|fܯB˱-SCn-OV$f(.p^.# J^a;0@YZks_6x/ܑ83#(xud^@Lx^X u{T#{dp6##8z휅XgI_jќ MvLaHOZKڰqbj9zkhrym? XFsȏ^r:1xx_^\8DbXd9F7;'EsA+pΚkg)|{z(W8(¸Bj` _ҫ"vNֆ5yBZc0/KbLvxy̑6@5390oO;ٳ|xiy06GT$o4(SfS k߷ݏԎݹu{& Һ!TK$u9g`?Z G'0z+yIP%p>>shƦG?b8:NZwz'Jqds#ƕ~gKpQ?RA9Enc5<y>jܵ{nz+ 09VผB2Nw9I~T85׏ʑ me/ܞK%v:r:|8n/s抃5_tJӵ$37塤HlϢ} ǣis8Z$gk/[';dos(Ixbdڰ74M'd}#LՕQ\#M7KMxis'>h}5[\O[d],`SpO㩡!dcK)d/{ƽ#0jaGO%)6.Ln^Fs;HkRljZ2lM?Ϯ=4/[L^7i K ˍk><2YCߠYQ[!lqq̲G%61?zvajḼ\?˺ڜ#?9@u,/Ġo D]M-G;Osم ֡ث07ZN|/Vkj|yhϹ!WhYN_uXGk 9ȉ-ΙĚĹIEh\'53O6 8e8v2&!6DJiBbk9߳/ ?OIw9)SgsV+^`ojKOwj4?<̺ޭkS n?8C}5|~msn3ֻ6q( 8ZG2;T~}2=pts, 3o싨 >$zGf|l!BBS&0hXM̚Z&lj5^96`D_2#z8/gJnHj= >)Qti0ks~_T87mBSV<;XNjnk@Q1wߋf/ꋋnco挓F^]eo=rֽُ8Yla9d'geZ/8_YS"r8]@d6䱽k9ڷL &E-١ s2 T c4ZIx(\c';633 b["BX`f,ǰs;W[_bwFB+!nMHGޕy~G5d2~I_G^n e_^n;1jT"ɗ5p8́}- |bzF,>zw?z.Y\Vr6#_>(A8lzϣ/[Z:'fd7 pp-| `[ךn Cb)0̥9̦eșs;u5 T"=Ez:_&=>ꉃ|< +l^g3oqlOo=sy#gx%;>mB 5V~bmg~G@a˲kMY8=뭱p[Fc,g+p-U&cbz&3QI{O@X'DEz!G1'8cI0;gͧ '᚞Қ{]0k|7*7tO?w,@ͥbkM㺄!4:y@'Ӽ~`pB}uv`9+x*V;;n\Ψ }#Tޣs5٬L-nt ]RЕ O\q^'n-tNGtdGY,9Xgt;].vpa>ŻN%.r_6u;86Ac׺_dׂ75jsF,o83 8tG_Tfض7Q2![[ŋc'zZn:` c`|7½9΋7vI.gO~c9a ?/02Hk ~Z/ƿ䅽d^LVfƼ͛Slf yz:cs:8?7~gSI[xEsɝad#iΚR3 ./Ғ(Xg7c'<OPÍ||-^/.`4ol0&|':<,@Nx,Uf$]cpd6\!1 yWI&~y^ I_r11ՅuX)8u@2Z6N%@;rgq5'vg#,f*`#2CU7^FO"HI; 0n5\=;q+En>lV=b` 7e#>Jəa\+.&ynepY\ӸWqΧtƶ l96&lO1mai]&{d6a[>G٬?ӑ)H wǏ N\w;aؾ1hXPqϵf+;5r9F 2Afsz FۥAذ>{z' džY/:_  멾'_Ll }P{8aflkLÓ qacŨk]!0kK4L%9. k[ዞiJԒLU':g7w\e-[g`hLi1.=q>&uW)\(Km:GAz6NsĹw=r $أF;l#,:z?ǁ _ X/&75g>̮h ֒{@ַ$oMK4R˟' m9 q~{R01צӯd>}["źvg7ν#x~.q3hI ;WGr7c;=[8d.Y8m2U`(@IWm&%zLۤTP$Jg/DgCoh wjPa@u@nHIopBFn]q8Qӓc];O#^ '#9e=4NE۬O0m,R~8YE,}|AÁ-y=?膃a޳F{VpGnΛ3 ۸Sͳ8N[<˝~679& =S4k9M1IA{{sC\>SUFKc[}V|yଃtH׵z8H;J)3/A!^mdg<=1GEqyOj~୉1C W}T_Bx>Rk kfCcf,=?N#,ϼXs3Mr^_H*Ξ:A} ׃П:\.3dYٺ9s|pE{gq7nqgXl_/e ELKj o =1lX[TM, &{,!OmtQt0U)ZhW>Y'pW8XGItYS驁6֘lyl;HG"7煲U8skм[Y$o˾v~dz_m7jD3V_vte*w$ ٧vgqt\NoHI?oz18/#-)t^ #wm\v-P[mZm$7"s'b maw.}fA~k/|kzNjg=w7F[ l=5xngxҦ7o=}cRu1n1{y L &!/;7LJeM p.aiqd4\ rľ\fy/=AmvrGO0G"C΁ewNed -=q(g\'Nq_2=8)/`N Ư%bY"M07&I gM VogQ>l ;׹;|Ugߑs)_J/qtԪYpF' 8eDu"!vY>'™g6|AporՇZ Dz HLrGSX{r7|X Zorkt\D j1eضu 6Nͼ߲<*Ϟ)9Gǐ'<ѹ`cE8< ^K5_`B^p\wIksZs-h&H^LL8Sq[3ҵ^űVou$|smXk4a`Znf'?{1ÙUycMV?^dž_' qF^ƃ7=y3Gu:z3C&+a85L'p2-7mmcdg"s0jx3qɣ=\/:y6s6edy~gWl>7=q|Z֋1 < FFƔNa B/g"jYp"Wkhz++Yv \;oyxҿo-|Zl_DX|{Atu͵>QQ">q'P7=puzLq$G$"tܩx s #z}r)ɺ_p;33C4YJs1+̜&œ o8ӡt Q[,peMF~,ոg82+‚\wPgӋmXo 587zysr{ND#hsql%ض;0[nAhKo?}N'm1ԑŴB{]oHvWp;>^wSraxT0ZIq^ N3uav֞8_@o&ON[ 9+,|Y>sAP96yn>&8{"ԜM vWN"&Pg}~pbʮ^ad: ẹɉg\$Hoߧ k.K^ sE}'"4ʽn-y9#&b=S8F{sfR&Fn B0^= pJ S^ַI5yMj%ISgyyH1\`>x}[KRm^F|>[Npvڦ7 -R7ܠq琑XJdr1w g]edȦ51鍟GRU~[y5Sd s.n-~lE=KkZ[KpTz*T DnL[c\3ڻm&S3dMcO-h0E˻F\>c0d -'>&cduJ,8Sܩyٿz#͵cJѹ)8 BQj=opm/[C4Ap5? fSy+5gڛs$g9/OR휈XSsa .2dP-0]Ilw#K+6<3)4,2 ?uyx?uyko z$5[N lD#͎Xx%ܖ=ga g.Q hj͋g!1\^Kn3~Z/i^/oߋK/+qu-~Biͬ{%. M>/4f m{>"٧~B\8bH8jB.W|9av4HXp$ɛcz،. ,h>QR=y-uh?u9#y|& ~?2ʜⳖr(RT$ϯma"x@ǮY[Scb5Dy/v„׷:oG$<ǧ',}|+;gIG[=Z Gׂxv0u>όw&Kh'4k9 !gԤMz_b{"4v,}.Ku|gS/ QldGj0Mkq[5Váz+;Y︬ۡCh{BFy8k=S})~qy.laG/niFP"9 Ė0b7 W)X8ʕI ɗ08o>_yݰBsqZP u̦u(;3LZýa۶#Է2M3R:i\:Y"ʻyWAoj(KǙ>7k j):1Jx|iN!` yK8Y; nOx"YO@]5ގ^ww܂:軜#յ=zv?zϲ띓؀{8΋ׯ; xix ? x"-)IOʊ&:xxZTLvkK{>\-5}.Z#K\i#@|W :mG{3ÚFISr3PuJ$#= `&K:5ǠbbM_pZŅ{54ܑ8u]Դ>O74ڴCKxF9Km:&Y `2ò{r%jT|\5Ȝ~ϧYM[\p0_VƕH-?|xls^qo#9:uU"jO_ Ͼ<\+±c{Y"#&H$C[.U09=?~j9Xk)Xܧna[ä$9R[ l/Կܶ?-R7dWvOm 7YlwkckF$<^1&B^G]?vYְkL4g9'?:&,x$3/K!gfQ@Է<7 6#}O(SPɹ{PC45'FH.WkS;.Z1R/2m5jReyi!yhj焨0jXOwV1"6zPnaCOQlEGx7 ͱ| e<ݯ iiQ $n=q9& q |p7@݋wEQrfJ*ϩk{gr.SXZgn6Ƭ [pOG/ߌ:Nsx 9ϊ xgz>R7e$w|.MI٧ e|BcU`^lZoD"f)ᬖ>| u\ܤ'}64N6SbdA6f sgV29G/4z,\|Nbś,еmS49Nt0BgPr*yya+_u???f`^(>Oz1__??Y3|ǟYGԐgTSOzjte'.W&bMx f!6V`% 0ոjI/'űry`_zDwz;G[HCqR&~PN'=J6Ȍw.Vbg+3V䧧TYzpy#t2&]Q8>zs+jAH &=' QF_hts{V~~=$XKl;upœ?Mn8y:Eb~U]hPw52Jv,l&}k?qZgƯP /-;[&!l>Fu$`۱,FePf3ځ/7nk8A5k,8]^@Bk%?NH0Ak˿=]oLp=8vp /7|!VRbXvZ}=:'=ܟI Hk0c։_y!Σqo-9qڳtԷ X[Cėl7j~EmxG_,wg3ߋ~Ä*]${';!|HVPI(BQgl;)Tj u8_`;4Vhgԩx)#C-r0 ax}u}^}}?}? ~GF9Y_+g>Q±6OOW0:vฎ..M}ȟssM` bxEr8vVK5Hӣ9+Vqnts*;y=O1+̜T,\kFtg<hl9ˉ[c:ygpuU m-;w>T)7{V cY`/xFs>?oc_Ͽ2$^=2zo;r?o_9Hs._1f:X>`9Z&ᣝ^rWxT nOi]E Xn.9.H[ jap R{#-{G.9Wb0ٻ\ &XѨueq΍C`FaNt́)Z%+h?WZbysCѦ) yoEd=7uPz5E 2-9 :7IO/{!Kn<-i>&q#?}w\xڎP|ug7o5]ptNrS9>Lnj4ˏ́|&H4|[t8I#)k7V0zI U#I9P :׿NJژԔjͬsےcqwՃuc#<5 &ktGipk]7HsI3좏o~c%}<>]Qg&IYwJ|5e74v~#I79?Z?Yr9˖b. o~E}& rcp^xe5I=yicqpٌd[{ +aY Vkd`VeLca4`T"r`8Mks/zꇽkvNIJvs 3Xy7[ia"{s5JgMhv꾓$7^jZEl̅崲T:hc!9'c}8t'l]˜2Mn[U9sjzG|?+\*Xlij_qp9e&(^{ Kż} vD3fH`ƁvM}mbI/ÍjÏuCCvC4/+N3[,kyn^@V|yݱlOyH=1wTd~#ԓpJJF8 FVHeEjwO0NRT@7xõQ5*c1X*0qE3FK\?C-]7ϸDȭg,^W~˗nMoW Gm3<}w|?{w㝷+En")znnO5|Ixı =p7rY9!b#yٲTl1u(A0KH3`n[e7ko\Y-;6caM9#sR=w_I!1. &6'wO\0Y#cGThWɭu1;6z^5#q맮kL\pl3лczPEdh{6⠏$: @c( ۬%8:D:g>kLc8kw{5u?xvχo?+"]bg <|c]qvY5Xٵe g z@pEy`dA+C>1낈dV'b@ل-FpP3ɉk<0HC^ĞᎳ0?{'q6lIWamkpWcɹ:6Ňp]:ekܧHS#sj>[kVpx|^~]Ɩ]xIk:\78FFm7;x61ݾI s9SݬL?ħ\LgA~6f9qKm#쨽c,;s1SljxenV@r3,̶6c6V4Ţ:I .Yeg(WV6hc[^2m..CuE8/š@ajxį<ɧRh PMr YK^0b䌈C zijCwƝ 'm隂G^Mا>jk3o'[_Zm+3-Sx|`R}R ?l]{ zJכC ` 6 ~ݾ+ۧ}i?m9h)G,, aB_n_e_|//{n;}{wq}Og@p?P}SNh\nm$UʶǶ9juzW?ޱ [9!fgp(k1Gkux{=4 rXǯ8̘1OiQaqjզ%)0g WWߙ 7oPz6mG5{Ivcؔ ̶V!{4){UXX@PF8ʲO>2fJzpn]\{/s 1aeAs:|dV|UY|G7Wp 6$|>AU, @=PD1 #Ԩq0H: znIW%`i{4Fͅ9_7ЮĪ>i?>nc>vUn'r[1gM7OASW[x0gAxY$&q C,=NVy4|mn(i>'GsŎƱ5םX>Su]6!6'gbm?3Nkn-1$40&x]wCj>ӂѱ#'ZOr:5|6~<`G&noΌÓ`L'ݨty|X}הj6 ~xHK8AzϱD#4ᜅ= n~sX>VPCK/t;~-'n %1faPiw5-Y.%GO{S^_ۂZxOU߄ar(/7RG׮ʏ|pWl~_6N {|V&..?vvyNjuK-:bCc}sin`{>cTS =NM@[p@>Xij`l ri97Ɖ [Ts\ǞlޟkOڻO8kʯ9#i5j)_ hyAh>Z">"lyy,_~<⽣&,Sgri[kdr0lswl X7ȖkM OLMX:[߃Gbi]9;o +:l=]k`#bW\fZN[P|Dtz'&1zJWb?-'p[HҶqĐp?<.< gwax77byў_MЂb⑧;` R{`sB\\p%~?% psw릦W)@e:i dyx,1v'  "E܉{!\g?c|Ƈx?L> 9Ǫ|ҭ5[0wԹU\}BS:;9Ȟ&ld/~C‰8ʉ\2wL-DpNxv.!xumr=BYok^Wڔa,9 o 7R^C^or Jά<͒>EsKnnٟgyOS;ؾcCo?~ۋGyR3S}`1{냻ևƔp<(_qHqs$r-$5nCItO;ev]Ty ` CK u$dŰ ]A0fQǯ;rH㺚サ$D^pO^!αw}&J3XS8n Jl>WɄ<ܗ{!s=\ pc<6>ׇkuq6xN ba)x"yΚ۞P/^5>Vmp/uo`D،Ύ,ͼ6 0ly`3Gћ#>3_ίk ގ ]>Njm$Mh'k-V5w$g+'L|cިA=nR]ʂ_6yc8:$ˑy\Cw3<"yO?Ҏ.CrmkLsZSq:Nsr0fkQ[ˇZ2/~\<ҩEqKl`F+ˢ{'n;8lrn,6b Ns_6o?vFGC8gbx?ZXN[e~gs_b-k}ˮAq"p46)tPV^ #8/fmNf(Zh5A$~Ʋ [}*>@>'i>眉|.ZPDF]+=⏙S;bN\hh2CYd w olK܍;c€t^yO 36/TYژPkpX%iwGO0s<5DFlWFtq[In6J >J>p o[ˋ521OQNp8f8[2D&?9&>ܦ^66~iN(&yN>a ؃% x0BZ%pXdΈ-a\48$L~?氝cscmdk7|2uVxg#}K5;{-Gd 8;5O}؜2#1)2|_t;AADI 5>?cy\WbOVx1 jJQ$'r: lc 5Q_1b2i9nJDz' 3/ ɓ)o;:yB6`+^st{۾ַ+˼ː'(`YY 1,AIP>,,T~=-og {}#`ˎ~pͱj&kr(kMPR#juΕ i=~_Lw&K[I˜_􇋽|-ǃOt@Ru۵ t?񩖹F[Yˁ M6q$z #jG]<^ ?Ͽ)fs- u;YJbW4b/,v}40Pt؎Iɚgɓa|XnYƍ6 CL=6Dxt)$رqsjp; gmynL|ܘfR76+O87g%#R ɊAg :'i' ősv&phX'CEX\1܃L5?'|+"6v'1Gslp䄺ۅ7J L۪s_WbѸ.'vlf~Ep`46t5~-b4pg@~ũk׿qq¥ƱaTޖ\n\ID Q_qMe+Ň 8Z :{Kec`j v9ȕǑm|֝n>*Ju 9RC eB,:& <84gx82&Nckg\`7tX8ٖ˞{ p[OBUZ{Q((7 X svT $Nȍ _?70O=Bh!i4sq5]^8s.2x;Jݐ__}Oo07ES}$lg wm99vYC,j3 +Ǯ/8gVZ"|0;/5~5a۾ŋ_šIE9 PQ.]l%/`y{$u8A~\?0A ~BienrUޙ6N_#̶.lاڿkZL4oC~ZcF }x8ض%fGGN._cL~k^ s(=d](-(kqQ-}q^.k/iS8ZnlK0n~"ڢokO=s*;P>-">,vϖCRx`]V'DYʆ䩇,p^}$;\GʃhMwH/#` L<&^' W֧o_/}7zn~+8×ևIh\Ve#-DV]!z?'~Uc4MM"OpzXvGbK1pe< [6Ր^NЈo!@H.JbpkKPBhS9o~9e,w,Hc7tJخq,xir૖omXu-t^Y^Nއ|Ұ}akJKur_gG7Ig\)192wÁ V}k@]sS-[&Fژӵ&|e%6&bEI_5{|hNxO)+Wh>i4oOFH̯tm0VF&}O&9d`v`*ֵn(;;VywxL˹-3x 2y xom _d?SBnY/kpbX"CBX0Dh.\=vkb j+KD9'4ms'ZJ[_Hj᧎J᩽/'^y v[bd> BX<&GDљŸro>j쮲SOML-F@N߽ü[֩Iɸ2N.,{.s9߭$#Xi*,D'[ 8#` ya6M5V=v&SKL˵ ()г}1??e6Xbe[ccadFwԋZbkr m%Kހد"9> bw5(ç_']FZkPύsʣLA'.zI7Vz{c$O>i.h1J hdZ/1ׇ7xCNB GYk48D=#k7K2y4J@P .Úkt|%";9'0SSX?@Z:#PsdGc؄s#X8!F2{K&;W;5yQb1t7!xeHKa`` fRP_PO9P]~8IT>Ƶ+׎%^W9 kM ɵR<͕z r >{|\8Ծ\\{ܜy(*<diyϰ4Ԫ6{λoJők_m_uIqTkM~h`G̳ktZZ/$Zfsi L]+}+A%= R_UUU/,N=nlKb ?=nO3$K&E1UyyǷc.\b "Ȱ.^'eDZ-kk鴷115 ;wsSKsj)w1_-^)F}PPp.%kQQ%et{':I,^pT-:cߍS&`YLhX(Ssb y'tj8lWGŰ9$d#b–!1ؖ]bI|}5P=¯1,JNy p+L%aXlb:6Ӱj# d標bc>5K-aDWD#H{ =y¶ O.V(bo=ysj\;'OrYtlsQ'&ҷVXtI`a"IW`pV8E$k[2-fL(8KELvs41{l]]9l`a 7vG/5`.#)zB[W=?c^ܰU+pc=y=?v}*s3/E}篓jdȻ=t&rqwLXf۸bY e'p7ruc=gmePl_|`>\6eM*ׁee>pCּNy㔷_^w _wVTk siVuй~5DO?(Iv=m,[θ1jWڀ+-ݶ}q5O9\j<+~sbOWOl4<$' &G=˟X3Ƽ#Qk>dh!ZI8Rd֜ xaɽuFZc|sos+䱽r,o7n,'J_"k%{g7+"6aq(`<'SjWyrZ\o_@FU?2Z"鏯!10,mz7P1F}Mep)o6]b ԉmc/]% St,Fr}[YR;q>sjAd3XY5Oyfbۛ>=.41أ:q&潠/<2цw.-C߄ǧ:x}t!n6b/97c1Z6-/"råxԠ#%M']H,N$99CpJ1o0@F;Jgt]Nu -nT6qsBw\ UDg5tg;CY7ùyD`Ǡ4'ִ1Ϻ;#wL8 W?e9SWeڑ%P`XcS")C/ʙ#dz8A9!;d!OPJ dH)F77+,a fy5cv=q% YZvڵ͘O1&SySb@?q%@rAopNQ_yͯs!kv{ܾ+{wz<*QZҶl]*4-^w4>m\g tgkS6}h\Z4f,cxݚṰң>bI"]BxD8'_itMIĹ5p,ıcε!D&k8Đh}&M%oϵƆO^DhX-}!Ԟux]|%ao1Q/::X2;PHgD](@#|2%_WIGl|a|bc ިԴ?ү=X]L k 9*NM\L.{0g_Ӻ|<+b{O0 '`won/jB-!UXQN|Guت(::45d@)XVP}uskȹ3<[sl,[t5MlCМ66|OS9|_kкf\>/>o;.}~&ёo2 Qmo{c wb$[1>X^Dq$nC<kϏ%bSo(~b˜o[4~) ~S&w6T!5i3Nƀ癏~c_3ϼ;>3>_9gq?dߵ=,,aD:~ÿz?3o?uۋ+xNE=IY(~\"̅19Vy-5 NAáͧ R595_sהq4@˭ 7 >&R;[!־8:^߯IڧhwFuzcf^`mQԂk_? X~hԓ3zfwYsl[Tc~,e~o݀Q _qlCf4y.fݫ_kc6|0-VL>srYyx fF+>~'9Țop/P{|9Bm;$2Y1?_I6)};Ԍ16L%i;ui $#u yScjrvrCs4Aļ{thOYxlJbԺ$'*|Z&18Of~dtoSЗ뀡y8 H_ LJv>8NTvg| ʟr.bCr| d׬5NyTN9wLzĺFO:1R5W[^F8//Wdz|́)ckc]Z!)Yfdn*?pœ;ym'|=6 sqؾ]b{ھ0:g_usooP@ <Z|~kyWu*eJع&FW1mSsab7.yҬb$$~|.erccgfT2&$@i#n}*=\[ۙShI:vz&ϭ\a#V,Kl`߸oa%c_\H|7`߁Z[DD ΅r\ $n(_g)H;Zۀ+0偍R37GOcb5 -6tx1c=ep1B!_kDG=?o~UX |Ntj#̍uϿyw}?@_o߬6o~IN|z`9:/,3X-"+Hvg4Ec`MX6q.)k8T>FBYMxG댼çC[.b(va`mk8ƏzSf.s={o[bÍ7\ǧ>ʕ:]`תF;ROmn6_ 6ޯ="Ũ?O%p\E?Sv9x@֊@Ϝ&VBT ߵ[Mb6nǸ|Z˔<whrK *Gu 鱓=ĕRדMuθuu^b O=cCwںfj_ƻbp8ć󾎹<+бS|u%f>=keX9TBZ"_yXax*Woۨئ0awp'xUu|XgKk+8r]$uDoauךhK<zqq쓳gAqInzd"y֜~AN}k u̅WNoǰY=؏H ۟Ѝվ_7߃8Ȅ\Xfm ΩxlRsc]O:k.bFeӪatǣra3~6sfѡ\N]$.ؾ\ͅS"&VcC#Bļ2; !dޓ>Wb2oF礱yؙil)Xs;he'~X5bõ~!rI}* 8؁wo޻^hͼy7qF/yxJrޑ4vGs|챵BC |NIjgYRs]skyx[61cDr=h-1}h]}xfөYW3cܰZs=׼~vۧ~i +c~&qrƒ\6}ۯoom}79PE7Moo-_O(>|}q.k گ S X_C='~7Yp@^7mZȆ1 Tȗ9oi6Y]Hsc!ڴ+lћZ&ͯ=\yȉb8^+f3\xysXɵ_i22 :ȲA:5|Z;i4 Izj:ZiiaO[;PIڰ*6]5og3l&{7 nCubC|baa0kVN5#*OkN^W5ɮZSg-@T"7< DݼNܦ/W0})oo,:nv3*܏BRqgQ}&ar~?ٸ~CvQku=8^ui_ Pbu0)ϼnէу\eja&NÅ[}N5HMd?2k'mZ>L|Ytjwraozwa#oaO菓IOySg^S] cc d:Jo 3^R{+2}6ڊ%EVIOHo7k2;up־yXLOJoENA"|! $4x+h#8XI_9˟O04'G'k{B3vܜXG$/6zaH2{]൵!Lq\kjjx|OpO/N=l&ީ[| &4'>sab̩1\qfJcCTM){lzv>mb9A^}3 ³9!y kՒwH7FKN6jwI',q;.gK*7̓ޙwXLkAǁY9FK7%;1sa xټq~yR7AK.sܖ cxp GcO%ֵ+Wt)W^冚3ug-wFl-L)D+mz!̕^Gn^2`E}n__sjrI9gM'5Q/c'@JFx7_{ٴ 9͚L_E?~go??c/|Dd aMjKOyo_]k~q@F+wu姏mx8_~goxǻn~P?.?3΅O.IA `uAu5vX?rq"1uy]&Nm9;<(浑?r 19q`Cև m{l@98:Gzv8RuH/Z趣.$y>$BlRk\G:k$U .uqEcԄm/F.ω)ڇԳ853&P߉)'8}Ԁ¯3j5}̺ɛcujzC>VL#ylv=-nWo2ܱoC̷ lͧ9{zD#A틓f^ꄳxؙs% Ppl?z[ji(ml+jp| r㐼ԙ#yW2jضph-;;9 S.\B]ڔ}XKw0 ]ޤ*3P|> O>bFGqrG<|ri37(M;]lȨ}/fjL6Y;(q1r^R$'f;/XF؛ْ5{!oqwv}1YX.;~r\6v*8۽J;:%:KN~y rh^+*vcҸMyqhZntSw\Nॐ{wbY`S cάbE05fD+{GKoƿ/_.mnO83kvviz/n|S0A>Z<_@kŗ}.]Gyw~νs"T9kphkao?Nq:a>Mk˻>׷y%~Z#–s`:q$9^aE9D[Fۓ+?:16wRkfp7xmOOCKMچbQb 8ѥK~'Ā'k)M3#_s [8Ȩd&~t}$ZbP$#O%w,[_:G5l^DZ\/ħ.v17]o)2s[c3xm+q a(2xkcj1n.0":1Ҿ0p^?iK'؏V,%9㞣^{T=<_zEy ^mx,y=vuH1qr\e (pjFD wݴƖT!>-k 6ÂP{Y_Qpy=r=WÇG9(#S"A=>GUC#I4޵\ hqٮ s|θ3GȬ J?Ik[7W>Br]1 ~g'QO!0 wv,ѫ<z^\-mb;jos/eL9߽%{aIˇN'l 30ԏm~6צLj m+kYB}\ԂJ8vbc-Q;Ot{[n{s}REBxpmG?{۟?{޿=GK9ŇV6#uZ&^O,XOӔ/wr|ӯ{~Ono}˗ܞT8(J`%?^<>t?o?s+D`.WY_^#scbNAy(JG&_! ܔٷCO: nqd7br]|Nl|x5|!?A,M\7"`(5oO҅l!l"^ɿ!5?`#)Þ}qf.^Ϲ6q/{XNNY{ƳT!= h2y>`IHW|yARx2ܳnClʅm3+J1jlZFFWԛzSbw>s2Ԫ{jx̩}-ͱ5]K?< 882eW}\rsϕ:_2~ 7=|p0.5vM2>k+LȺu5.ƍ%%E~`3TVnFjK-џ<߷½)</lWc'uµIM(:~c[r)Ňz-Gs6sL4O:L-k&3;alVi܃9jm:c;?x& @&C319_ w~ʦO'ڊq$#Ʊlsݾ.xvDY..vJjn܌6XbVR]rOpݦ&[r YN;ď5~h׃csF)xcO}뷑ސ-9H$"mw}^q{u2v|.^q1Veonh{q4% ߘx@K:=B 6LKZ߼hs;|"̶Z ުt>4&.<y9v|}rڛSc\ۀqf &ŝLs+Ì-|ɺ.liKy8'4!_G=d~ߗ~[oo}x Q6n'9ƴCO/"Aӱc*S9ZqOQ[|qOQyȆǧ#5mX^{ꉇxB`Ux!Wg^ =䮥W(c÷DXءgr嘓U1hF kpUf?q_m[ X cw¼@,[r|LڶwFOPMmrD.ãṈ?'NN\ޠ&yձM𾓕oym]BX8+tn-֋&ΎY<ͭ<:r0ָ1^3$ 5(Y>v}KǜԮ|㷰 K~ yxܔH(|7bXBS$/QSn\%wuz@{s±whr^!4H_[>*uS v%;OIw}Z v՛t{ZvB@GQ>-*S{Ů7Աp-vϜÜk׾߫ߋn~7K<,aP/L%eCG=~}wxLڻVg9Êũƴ~+yϹξל:ucv@&?'*m8Oq?TzEooo{UksOהd=OPv3f3Svd}WfٜzbcgC&ؼOT9ZI}ԯGzYY j&2Ņ]sMN?P?sHr h-wv*zSCO-l/yr-BR{7 ay%r`Kn9d\g!q۞+ry7uF=~߯%bxS֩ i}]NuF1n.;~v/a}cο'ǯCdy&x徢Ī9apWҍCYGZA;д/1/y4 GWm~|+rH#BzljCİ iHqynE"9'msczLrj_K?\ft& |+##c`@B7V?@wvE㶎8vxuU阌$#@M&KxڷJg; Z Ͷ] z8*'s:uǿ\oDL?ub??-t ơ~r&,]N,&d~v Bbf,$go0i.X>r N"3xgkfU3 bUݏǯ>_/XD.6ǘ-no1qL=˷؏׍L"HKlF$Gjl8e*s +d/JꚈQxB3l/^`a'ʬͲUly;e3y>l_'Qb<(qʈiG~ֱ;x|rtkQb ~jN٦Q]xf|y8$+q:wRxϘ |kyt]bU~wb1t<ؗ8#;r!75r.,{ &'0gNNgCTqxbs~>7A߶o}?׼Տ~9PiMXϓEĶR <~3?so˨ $sL&"9Ȥ6 H/R/PM\=iHyo|M/{$%qewHV r_7OpM0ܝ+6o%iY8uFo& ӀBgsw44G'_<30m| BsN!y|c>^d=.ǀ0=HL=XSzIV{d ı:y>ǢNf1=]Kw!Xqj ڗ'ik= j];aAطUΘs0^w ycGU\CqǦ1n~FYBs s+.’<[쇀M < y]nNt{` bkWov$ϱ胃"7rk$蛋СLc!ӳqarX1&vp 8ǝ~9<1PjyuF t%Oetrg w~x. c>X.?v0@yqͶydؕk})z2.=0跍)hЍ oX:K{lڿy[8^ZO2p92I!OQ0sdp2.g?BiaKi!xK{uB$>1x)4Zk>k539>]pwHTdXqgNuuvVdAG~:Ɩ#.=ipвs')fx?{isUsA52'|>!tDt 5'x,7K_{YQD;fQدXOߟ,Aw\ҿ1pc|bv| N\Lbxrp5nY4!2: 3&~]< ~3 94zcdox[Od\hE1xMIV=2昳-<~oɟxz>Zxݷ5r|0.OErgomo{]z\ObpQȱw9b>6J^ylfEzĄܿ0?~o|o}ǿ>.נc퓊D?U8X(uo,C~Skv0ygN[ݦ0沱Ԯe~EfnNW VnL$e: nNBxWzt˅_uSL,b̍z](( =وg:f>xN@^&)ަ!eXrt#ߊ'Ũ$%"(#c=vݣ7"\ɜ7O:'K.;~Qx?Iw>]k5x9C7gĜёTA fmZ}>*eӎjmf7YŨ<޼mֽxV{kNoSWU{e3ƿ? KN;˸ sfW*;8yj4@UHXCvؕss˾s-cgr)+#.pВqsxs8+/Tgoh49=PC4=Ck^Gzm._seh ˮkH?vbj٘O*j89 QMYĨt'uD0y>=L"RԸrgbSwr0bӜр8)U^Vs3t.2s2uq$J8J8]MGw%k60΄K҈뛶6Yz}&~⵷8y)5f',NJ-vv2#Ɵ[jsa$N&NK BJ/1Y  gKyH*W1gBָrߎ4˻~_ⰅV}tOnt}.NĹxkN 'g5чžy7s3Py|  x4vQsyVmMд=NE0[3R0q~<;@]xk.*h'ϕKΕĉ̓Z: ^ґ<;KN#HktϽ!A?b޹'܉-PvV9 wކ &MDgFI;j RURS&Ohory31\77^QO_r_^:Ѕ}vI&mL+UW{~__ܾ~oܞ{^?ou9DaO<4q,aULGg[駟,6`1d.{`z_Cg @ў:lG?{s‹ǿݷz0p'ac?3_7%;o2f[W`)Lb%)~.}k~ڵ_5f~_o ~εV֏<Zy!H0eWʓw87O礰s 6慯;\E jdvw%9>8L$oa|p+.u/ TaT69٣!юMlw끇I,09>J'Pv8R)%0؀bٺ l/RƛFSytXe6%_[qxQ Sg~>ib|9gwtȺ;mtSN>86r4&<(16hZب W+=joMI£c+<_DtI:eEcIt}B agؼb _ك M!7|Oa2.XbX9o[}Ǫd IDAT}~;sCmw:vCk[Z;a֕XNhS^ŵiNiAg"ЋrayDaFmGu1c~$.Wes^rw#J39Ow)PA'`_4@ <Ŕlw՘[5-x\'3O98m]Ǘ^QlVWS'p{@9OY|QŽ䃏qh'r+W 9eKv3ohe!+qs6qlȪP-8w){}T<]h~_ʺ[iPl>κ꯮}xgy^@gF=pȟTᔣH^^{|098˶wnE9ByYOP?j-csyiۓ@Cd-?6%l7I2BV_#xgG7;`c[mBSo(NI_h\dW.Y1Fc$tJ} Sqоԗ"[< zAlkn`5<;1ʃ7( w>'_  @(nD r9SZUF%,TST{`2rp`Փ m#ȜTYt4nNEŦGug &N֛6O_ty JvcMwfG]>˩2Dve_3N6}g K>v. nL;/8+88(Y,"9uJƘ׼v{ݾ苾?? _qh ⒡֊رmvo.ȟӏz'mQo^R r58uެm=wVAR`or*[rx~ ?{2VӦ˯]ﹽ/w~_ӕE]r`rF,OM[%N9ïSyҘGrA>E\Z1 -CHW⃃ X\uex] c-}N(0{ 3x0+rbr$kœGs޷oCG:2NvoG 10UB#h 9WLۼL _D8Y0ggLm9P` Aϱ9J^?\RmXR$ udr(a. M⢉-D:IRgoD ,r;_=aelvܮ^ 8DiOm4SY'5bgl֤R=ypqΥC~-Mq?3*O=qe0k`SS9tMT.̹.vhW߁!`OVMNF˭E L+c{ ^OL&5M'~՜q3wzuj!C:JӭAxG}:Σw\Qb;*՞H>ϛv+۸/Z<۟f )CR#ȚÃE/&qazoۯ|汞)pז]u#/5%^X`}W�a~hO''3ǭ !>VwTg>\ [ -V<_6#8 1|u( dsas|AG31q|YqL|e TOx5tKZya.Ze6D`!'vjiS?8fhƘ@r/jOP( ԪCKX =ݚ \q?p*+:na/6 {l,I+-"$&^`ӾL\mbn. cJݐ,;]yms]CS}.=)\'&e- gǘ9Sgk/;?Պwhfu =CCҎv~$'KF> p89q=!~{.Xj`+-̯Ÿyk874_Fz}{숫u+)n7 k9W瞏iר}YΣ*}5:e^&΁9~Sx}GԳ4tp8^|Apg rJ_Fքve<dRޓDqckt[ir=ܓW3 9,7~E8;^>u4b"+.u }(:ĭ;b,ZeN8mJr:Wlx~C< 2k"20 ѡ6cl:=܌ 4R a}>NrgC:4μ*wmf]gt!IqH>va:(UY#x^m}Ф;qXөbC/x}۠=c ob_ym|' 7ixVħc>z%^Pg |T!Kyw{B>Wͩ?- G7"31P3u%w mxcicWy0Df Oba u]t۞0S64"m˴zc|x9YUupΔi㬛bW$3."8[}6Q‡<_+@d8>Y_[owG=>nԏz[P ei}^}wݾ ,&zF^7 |d˶~|RmZwN,ڶs:<ŔV tN'yv"$)53%Z'_IpS8\VQZbWj'2>ؔ}AزO;'M͑׹O7w K,nv@.@}88FtƓ0Ǒוc>'k> 3Ux:WN\^KrL`՛G1&m=}j_7KdDB1"JvoPEg U6Kb*^Yse]#"60+8h?qb+<~h'/ƖeyX.h['zt(n0=:qpq~Oa48N .ZܖcC0 r.&$Ȉ1̳;ҜG;+ƳE+̳'0|=$a+t~ٯq@9)O|z (o+JzLG|5Ohl"'xIk[lKU>Xc9K\k>J#p}yȋk}Kn %T{vynK5MVp/w 9m =.vm97biƖR7z<2— <ٹl;jYzр_ hpTXyMڳP_Q72 *K$ UV4/v~=y կ/;Q{TP=u^j9O+Z9#X@XJl `k:KM.&3>?_e??W|hrNt(}o^韱}r;c<?5~]_}-Oe&̈́om+Cr_ ]#/j_N 6>8UB3 FjQl]8,b7m3wTpT6-#_=<ۯ:69Ԇ5aOE{?V~R!;T7'9g_d?A~,댝zO9vHq gMiq_y&ۺѨ/_csڃ6~π݄z;1E'MSD Iua}Ӕ>JhigI"OyG'@SUއ7gX*h}}qM^'H1Ekl`Il?uyԜByiŨC0YhLG32i gI^ث4L/)iね *Pi? Co&qI/D, >A'LWfv g7WUr1xပx ه:wL{w s/ֿf9ٸbU&.ↃF ^ <Nst<ǎo?;/q9!0Vسlf\? Jnr,ILb 2~{:ԁokf>(/O|(ûk ̥+~z~xb{b,p*5@NKn۫__-Q?ڝqԻ].jeB^p;o/ӢM~=X̂О#eo<թƽ0BFy\, Iy y:otv g1PPqke\R0|4~3oݾK=ϖK;1]Axݾno?ry_Jbz|G Bxm 4foH +R*xo9( c]L99 ]զΞPQ10`5, $y$NjwϵX](]_Ifsj֜m&1;Q.rHLb]GB8ABL#i,tgFN@:9/~R})Ӆ~t4:GreJmD (ɇE$.Ew+M@aɱo'wjł;P }qPwX~l}.lbm!"v6|۹рB{Pc•Zc]،!duϱl Ƅv8c O-}9}g K3f*vq.#7h~9ɋ :u>HqǗ)S?j Mg%mD+bE+s;k\pp*O*|dQ\̂/gc9>+$dHm5Lf`Y":d28ϛ%Vc$aHmZJ[sw$Υiit+a1\93Xe}p3ϛcXר ژ:9Ҙ\_1e#CUX3/SxW>kկ]p~IBC:qTg>s?g?􃷗z%[ t.շ )yHu[Z?pMvoȍ?s|bǓuyO2dRm WcO~`KQݝO?[O>RG{ac7ݶA6ǖ 4k17&1#]Qz}H}G-:x{xS,}ڼ-] (a5ʙ,@ӛ|#>jq+\S2Jņю!Y}6;'<6I}bV-at&iY}!X:.E-ƾ}U>7-׆A4]aha`N{Lq}%ka\ u ^S5?ո;u@O#$gNz} `cHČ!`$͸$)> "Z\O,ɝ=\:-b6{dy~>4ܹ] XT*HjnI.I/sMSG@A:@ˀ'[r8uŅ C>P ݺj!n}W&_Twϟ3m3Ȕ<Ղ@(S9=\F]wcO@4bV1͇ oTn5_tc>93hnu zc`nǺŰ%kL@)cxQd750jK>6t'֪^ѓ 0]2NǕ}?ܣFJ4'n\6E9A[Kj}}'cX!~5G"&@.97;EQxB[5Qwpg}WOOʑK s&.?XgR@n], ,t-x,WPI&.Aban5<ȣƞQ%. \P=uB핯zw'AS͂6$Juc/ ?n?}۷w>xzTDl&'ɷ\\K!\?o o@T%;?[p h[k֧j7H`2D&܅/h~a1CY!Isow.r }zfmQoj(wq厃Sbb 1cd`mbci2I&uFύ ݺFx{&XvZ;zRN+\0f;U5aʭAmV1<(%xRCTrcWT0Z}U~W#qp*q6͑Pg;ɓV\ձ# 5uC̆sYeb'SǴsyR/&r&AACN:32xx3x8Or\юC;\U}b1Cܱ7ו|B=&[Ev·V^ܿl'Y]@N p\|ΕhKlP!γ~b1?T"|9k::x2soD.,8#6V)W}G;v9J( %?ΥH<:F[ fv I}gμZnYLm.鬖cv8Sv amwQ?),&8Ѩ(PPʷy,.zo9_x+UI09bYY.]ɭ97$rܬ}gоӱ㏭R8v"{7nm(d|!U|z\9&vicN瞇HL A%^h\\hQ(0[lt,\:p^W+ 26O~Emǣ9xIu&{OߕqC,3s.W=4¬v &w}xg`749 5,Qs?sqOG=^!n,0,xm^Bv>d/臣ݾoo|$w\Q C~{笈NF;L$* O}jb*(ގ֡8a;|;x _;~ Ux͂_ {^809<(~!~18|Ͼ?ŷOT}{>R`NA620rƘn_߻?@yh)h$dxmd#d6UjE>jH~Wuz'bX~oyƯqK2>,N`.>umkT78#˓C1VkKlG><=7e^ Iwp-u5>>V<:vz>#G5iBbUx5gV53_os|# z=9}nhCblFH^بξ+:ӧ -/ dgSlKypmp)=2Sޣ1V-qtidnNͩV}_oת2ΆU{[jSEL37 78捩10]ҿ6.>ٝ-z>2e3tr SMMf8-sߝ,V8Вz\>LJ %/KhuS\V>vp\ \Pѽ- :k{ b1.}ʓ,/bH''8F UK nE 8K1 F"픂k`4NI4=(AGk\&]RCc:ws^t$V9P3&zKOcn%şpw *ih19<;> SJnܩN# C2O19?bws1'1G:[<\;'؂ ȽK,c.ɉJ ~Ƀ'1_0,~ֵ~?6%Qc,1r77b@ӟY d|ж0B4^0ȝs2 IB=1ؾ7ZĀ=zƱpmTQ_})>y8Gh@\T\rV%VqkpnOcN @FnшNr1I0ƿ+S܌XpA = ,L%ΥΗwcLRzfb v*&SI]&,(}X?Ko_e_zw>-}>=a0:K;6/8t=Y?t{~DO}se'(]m^sS;Շy9猋svq侐[VT3:ݿ6nj3c~>y795.B֌,թ6c8"e: S7|<~Ư>Qe5 ptD#jȎnWo?nos_{jbLs5s"u㴉є "vQjiVZ-Uw,R&|v=uI\u/ k掳zgH#k^瑧t#nSGr7WxY-P>,}Wӫ3Dkp[ .>esK-ak˕^'|67ڔ m)ĭ8/|1e,T=GeCMގ]_?Yq&>SYgLǔ]b'\gpde]v?ܝ̣(~!z$ivW/rd, d,d|:88….9d7ڙ_z/竄ZX[oML}Z060V.b;cKSNʩz}PoqK0iCyփ⒊xMus~jkם Ε9=K"5Lqca8ce\ A;b 22&Ew{*|f")lOwz@Q5x檪C2/wkc7<~xU]c|uBп,r#P!2~q.hԝC"8ZyKQkrۛ?ɯgXHfU=(T<>&:rIگؿxVLsL7./+Gp<@`'1/<7zyJ< Ȑy}۞f jdkXԘX~W}*uYM99z~S A׿޿O7ܞ{=쌝kKq`?㷿-z]I,}~\XX$GĝG# =؃G;ym$7xQQXkkQ!9m2ۍ!k[}PJPӳ?J:9|k6J^wrx?/ТB8gcd]n =Wzъ ɜC-> R1NK>&SgF_G=I^j_/ҖЩ?9jrw1`_`{}Gd67ҳ洃3iڠPƽ`G̾uc@/N f;12q;t<Ѩdp28:/s2Pc܎𮾬k3Ƅ_w,1Gxj\c wq"^"e;l!mOX{dY2m}`,@.d棋 ب }p(h36ơMh_8[0c@b` vt7ƴx(2̓p>O Ĝٻh׎84`₏1R>-,8=Up7w[&̀cCS9q<5/y\{o̤{N}8l=xq fųHŁW΢L7"8vIBWՁƞ1}: yo#Pȅ7b;1GGvzv8Hm+xLԌ^ ;g|q!9ks^v҃Tݐ{t#Hcc|byؓ\Bqcw Uj3]m?)_cs"^cEYgI%Îs3 -- ]R|ۧ8ܣ[Wr͂ڇo1}o s7ދ;kPZVoZR";uocԅ?Ǐy7;o|`c_)[BpqGY<,xx`\ I2_ Uq wԍPl.)#Ks`͎ɹ~lByFU~^׃}7qzğ]b;8[cg_B~w_? W8;ǐO}v IDATw-}VbL&j~ʖ;'_=ɋ|ቑNEQLAJEޡ^}=[_6.9 }?!&s\:;xybR=& K.|QUďE_ʉ.`i"zțx&Uk ~c>cMzq⩫a[!\G$\WɒܓrtIKS1yP]#ps~\#]ߥ>:Ϧ #\A^:zѷʼn5coލҚv1ө?c})wM4:s1džavO_u֛sSF KX)BW'Yߕ3φ鮋8 ?r'x\889X&Qw=V\AWEjOEM?Qu(}MK[\{pJ{!ܯ83;6@tn8lR.\GevSdb ;w:`FymL~Pů;eםppћ sNw72>璷e4X\KNCSC/\2?f vKs(}j:vP~ [sJ\w,*̻j\+oEJ5}K-Z&WI$NsqcS&\kP=/*NVÒqz ZX\?I8;lId>ZcsqR/ZN^^kaJ`YxݟgBz Z.("eN"yj upOl3v;0{7vZ7~\?ݞ}XM D\٩v<|}@[X˾&d׉ًߋxv!¤dQ-dxCׯ{^!U>[+lM:K`<FtBu'FC^Ȑg=kIxFFeb/s#+/Z'ME!ϛa/ˏB|7%Kn->Wl>2]u-w} .o. 4_s}:`õ}z$2!2;mf%pLSMŧqR"'f#G}R>VW+ǛxSC[=+a֜U؆hTn ntO6#,z/b;=Y{,14'KzO殶PniU.='us}e861:s5 ;6݀‘bUCqOݾ(!vڟj:cٮ޲Lҳ47N,v̶OXQw1ǫvAh`X̱ԟ4&[:]1bszoqs~pZg%Qn>ctcs7',3V*nM+F-WQZMoeɧ߲:e>;e2EQj|(Z`6  VzA&(ceB6({8I lɴ>NvL[UwWᮿ@V{U{{g{`=K弻F|\|Kx0ǒ49c|-l:#[jalpSb([,ryP$"o(#{;xG!27]Ʈr+t+'}ܭQ"379\&Dz!a{p(v~m@E'і mnO>|QOj]gZE{)-]`06̑=r.̵(a}T5KMkqSRc?#f}㩋U珌w2sS7^pe3>@i?^Qjyٲ#kHwez|~wۧO=Ŧb_ynXKɽmh:KϿ[mO艨<^,yqB9|1~3VEuz  3NT!zOn-9Qƛ"}CsllY*G, \:'ȌbwXdc{_7׭y{Y1/9˭S`*sJK($piq}}x=Yn[3zΫ`v`}[G 6DEY}ޚp'sn ƥ9:+`E2܁ggr5F}BL(:vƸ+qN\L8 v,_2 v2|/@S>Uxs훵 UaąƝ1Slݱb |sIA"7* ѝc]1 `EA./e& pi|1Bp\#_LrSL=dEO ' ]~85Ş PNj@?rR{:8}|ZO} <1< ?_2n/wOh:bAwdkr RAb}yNcV\Ne9tk^yY@4rvA(m[`JyW\7^?/q ՒO.{ٕCyvhS>/Fma6V39˝X|Q߃#gb(5tqtic_n^ ĂoOCra%A \A ZwH2rsÊKT]nj}sLA#VA$~qXSQ(f^Zo(u1 )Q&nW1cQ"b=6ڹs6@2o:/[}h=q.H͙M &5}[~rlP#m7\<|86 9T8X0BW|~^Z,[l6XG*"u~ߞI I 0XMN#qVz|{=_I(@> HLl(ni}c.97A]׹WX7#G5vp`+wr|WՕg*雃WG["+`r~Qٸ2m?y/7>We|D)P嶛~zOba^}?{o_5_{{{\Ϲ8g~9į_FEvZ5}5 `O{kt+/ s}!xxlk4掊m$pD%-[a斉]BZᆣ' Pp.JZZ,vk?06 臟MGO96 B>sL dlbV_aӒ8Y!g}.DnK5Ӷ?k1pn)F`KJ's./=uFZIES5.|X{'aӝ B[h ,bhW3y\VwP}Je=kpw ȹȸC86Uq<Ǖ"Ceu}`P\}F92|bkt3%/5%w sl@eu'`~|0^>g M#9@c v>OX/rmm.>~1 tSv{~o0m|Ϟw=yz/(p~?e]j', J]WYq0fAny~r`<"(M[ ?$}O@38tfPsSG@L9RIno n-3=ArC' ]BeN<\n|TWj!8=ߤ]Z|F :{`v ɑ~Xy#YkFOehl5|>yPϾ'Ŏ o:GtcS^R6j&'f_֋&pzbGt%Kxc#Rc$8ؔϊ G4<6J<䍷\N:wcv>R&g3Xig$ ]n‚'^#~29%6-7ۃenB'2tR6HXs%DC;wy^G"}*CXs1mT&yտ ra.21n A1:[fd V`ΘƘ3%w9mίve NC׶kCʂoV||csxg";P:8x-Ur]Or 1<$_>O 2q_Ӯ\-nc%uϔǩY<e,7>ivX~t{al29jbdž4%9zOS~[/hm32pHb,(PqR!.!(d^SpRqW粟D€KcSjVpzs4o?8XI `' L煔e#NdnX81nRymt";X˟/pQ5(6ԕ"L\@=w;CtO} vC>0a{(O(B9ccyw1yQG=}wՍor8\GcI<"j,ΘJ\Aˁ46JG?Q;b5q`WcՎo UUȽ!$xQ{%3:b{-xLi9vXx"@ޟ~8F"Waaz]K:w1^ Ϲ2XrcO VX r>P `gc4O)0jBx{j*/]ȼ ]mOa#<ts;\Y(cpq1lƭS7S O3qX45_C&~LNr>Xn Vw~gQv{~'?}>.* LzAJ>f <,|P\oxo鿟NPju< MǸ8U(Xd-ziQԯkqJơ J=J. eHwt9D|Í|J>vX{bpY$^Mw s9?i Wb#9xU"vWڼCG0<.:6}wǿoxc1˞rUDڒ^k׏?o|7#YdI4S:)qJl929A* tpr)ŵO sUq.bƪdUՓ2QiB-$2c25'pAa2 U$VsnS͋Mj< /YԦS' 9Q7S&[a?{L. \`Ԛ1w!Z58X rDWэf>! Oqn%V'?ܨclycĚ-)u9"kx]azƌkJz|O:6]YU%1lY}u|-T(to~$*ZRLkl hu <qHR=V*U' 9:a10)UQ@ׁ Y-2kԺYk=#S&ghc9?@Eoy|c]o:Υ#H֎kCG\C?ճCvSYLEJC§QKKZV P(Q(V*TC Fi@+ Dqmh‡,M|ﵯ};~c̱y_'zws1Z{ssʥnωE|,Xm?cbϹ +[KX D<~s9 ԀmN NpAabNGxԧGqOj7qWc(;fp,"9jH ?I0y`Ýc46#żi,k^-w./xs<ܨحOYDm2FVxar6Q'| IDATJ6LeS`yrSacfQqyoѵxjgyYmko. kJuу/kׯS?Iֻ>~=ϻmDaG6"'"hNb0&Am}Oo~6-bxٮ P1uy6pD|~ ھ7TR>&[dfOd2VkYG\ۊ|CkY~hźnFfy7|»;81Z6 ;tz bC6OБ~ֿ|}x_济"L?Gz|׻}߾_{[~cÒxEޛr$L2l9Ɗ:`Q;9a>n6 x_%ʶ'mG68 Q(c.Xob8♒?YKN- .2[?v;}%XoᆭjcԫCcBŘRU/͹wQpbn1k[j0eJkEp: Wg9cuS䍹uwK}ysy ,`lL&{njŴz_tuߙX zyDl56k^\d2kY!|Ffi1t;ׄI!!3i=v"ckF/#vM4y NLwiv1CS]14&k%𗵹c[XJ,߱귆N2s6Oۯf SeqPQS&scN79Vv H[&#Ϸer?j<砹l.~B[8'V/0M 3kM. aRL7i{\QRTyDI@D=*q+JLl6,HiLXx7Iz.&rJs,Yxu,/T~9@Hq+o 9LԮy S,Gl-%7rQ{`/W2է r`ܞn7<-oc2]r|YcV q5-pn6MÒ"`+1YudXFX.ѠJ dAkwa}cz[뜱'&m]e5RwLqӭk&otaQwQs3NXL٦Vl%pdm{6ǤceEΛy?̈́!7@q)p"]["9m,9`d4F8vZ>2|8ڠ/P(6[ w״Y_c Fc= v7YQ5;zG&/KŸ}GnC1^B] .yv\/sADg9\{7}ܾ{Oۃds;E[AWTF!U'< Fʜk]al ğwgy8&&Z?𰌞I;^_{>R2_#z#{W" P4j/Tykn_z=.WCXX ~cjǃr;BAynR4̚ȣq7zYt^$w?|͔P i>~g_tT#hNCcv7#8 R B9їOP؃_sknDӶ.LamSp@xK6S/Kl'Y:+ub/ԍ7Z3w澒s5m]_W1'2^;SSi浑#cnwqxɥ|yqr)5"8TPq~0k5j"N]ݍ5Njqwp9ng 0h >b:,Wl2晌{~1m~NLXc z6SrūuўFX67\/s`Q\$ \]FX}>)^?8 8/lٺ^j'I'% (B&Q/z;\,;M7I^oQp:62Xl֯/XO^ys_kS#9s|#DU&UV=_8bMNRբr;|*w U;fX Ivg pmYQ*߾X]|(޴R>A^V@.XC#57v\:ً%[cv @~ HE8Ϸ1ıULJ}@,rϜ tsk$&P'9@Uَ/>q{QI}njuJɃw $˪@SSV|#8G;aƪw>KxnZEׂ./&Xllo|2时/v0LCֹǽvS< [aw]ɉڳ>5? o'V>_l4&Y|/xGO<H7~|9|XOۗ"Cw<^x678Qs@6ulL bƧ=I8"%:v%b3ʌu~̧nnD xuݰkQKI`owY'8hܮ2K' qF'2s ҍ Υ#ҹ{,bBq\Iռ9siр`Fߟ4'X69%{ cS2q1&[L.W'״uۦ~ObW:3<~.ʽy(e-Z_mƳ+ǷpRB I+Z&GOQ{|Kߣk%;.v|As/ lmko V@vBvsИ,=fjR0);c5[3U"b8i7 XEjq$:Nb)'/GBob i4v WI-:rujFd"ofŴ]3MNq^~V'':vmFd 69w%.{qd=ܹ o1RɄBe5~jfw*η$cU X\0Fi̴-ƥg4bͅ>6q?9sG3gجr=(swpsIlgN:]tJ u/;p.s3GteKc)T NGrcGNHOHܛ?^x_xi3`s_ʫ #=aoYmC-pxNyMqsqe8ycDo3#Q- :cv TX!F,H* K7(<y SxE{lH;dvq<4Bu8\ Y5Ծz9}ݨ]MzFKR<2ߜ?1W}/}}‡k#& 8\}dS sDwD=__YCzSZ7*s.!d>k1)86@7ЛVپhˆq79/# GA"U ~;Ǯ#Vf0L?n̹ۘP֏4lXOpG$pލC,gxpF>V9R{MV?3Budc+8dlǼxOCoTKIeTz1c5~/훾~?'u6|֣&ؼQx9 .3ENg"R_>:{DZ1\x~[Yi$ӯ &Fלr|]ƌ]2;qqJYL|DuCؠ?m)u^lvcyk#y*փnLh8/W07;EU%׹xfrF{m[?\ŚCPc99~7rzg9Q̛918l IPbd7UuD[坛bu$ oyesع"?{\lH=WhSbyV<u]jgӧU4҉e=*t냇EYoS=8^ƪ:b3bc;|E3GC9bt"< n{*j뷑NvFU8M?$U e|)Mo2z\Vf>6?1cuSkDp-{ɧmqۧ?x{+_鴴 R hUF`kȌ辖 0y׻GO^ x_ۓ/[ɜ;NNEs7)-kOxȺmαlw@NX)RN'}yK'mcrj.Io3}7|}=;ďfe8wĝ #(ordu&uOkX4$q66"by }Q<1LcN^WvD[j7C}{x@)\G7=mo{t7Iw^cJ6d 9Fʣ5Go[7@b.gNIMq>;g! g>{#pO|WSdy0XEvSvX/}A(~W#<$1xM.y9Pg0fE̛҇_PjGXO%` C:# u:Ȗtֱl`i3taκQZ R{F{}Y?#^vHZ ;%'7L=^c= @\265O'~;sjU"PmA{ (rSҔ}jy'}[6j|g>?Rզؖ'Sv?!9crNgRkx}7oyϻ'oڦnS:o/LM iPs"!@"M t@Ŭ\;:CpmR$x:~e[`hOb6w8X m8»c.][pܤ@tCCY-`֞6SO{vķJu«m:~YGWǃ?3?e_x3 =΂=)-mo_/olةMa Ƴu:z Lj|a$ ^6Wj8٦N6o-fidsw1۳h0!snf঒OI'‹1tkY1 璏%dewSc 4T9!^tV:}%fm }ʩC? 91^X!l'?ë\ ֞G_W.7'Qq3PhpLqȩt&PJ>]wAg|`<'|#4ֽ-"Ӏ_㪢Ѽ=:rOg0G-WҡUë7KK$' p74o\Ԝ9GSGv 埁GPtOܘߟ;NL$<2q/ѭMtS0 bNlD`a g7(;ϧ=̗=:{́hQCΆ:wy!pK 꽽} S]sLw^wsҺX7sa`0C!dZ6VkG4T@<%7x^/xZRHPT{:sbF||gnQӻ;ސ@7*s @=N=YbkF嘤8o=ۼ{|sQF mcc̝c9qyu͡@1u0v5|r_va`\XcBYk 3r㍑y( 2ߴ󪛖}Yj&~G\56|m?o__rOd}=Oh|ϗ/n r0]vh}sN<ǃ+o7~.8䧛[?J7l LUsnby5 me<$Fr>6/Ŝs"yg3CE , Amx X3s)G͎Z6> ^+NGcYqv>kMU_yگ;'jބ R G D8wjWc{0ug!A~W:I"qU6_s1tu ܛ\X/yr0:`d5|GFԔǭf(XίW (wn~Io笶9||^B<Iik,z*3=U\uF9KlEr]NsW.s]m^\5pͱ~^'F^_&Jw_q`xL; !}]9CiC]b5Sar$gt_w=XzSCns> \2s:;?:E]nOrNۧ^e%#IM0;$sX.^>j(RƚAc)o @nu}iYŢ/Z;MsLdC$-OM9sjxdɨ3צKbad,E~ p)jҵQ^~#$nm5X;ly79vp)c+ƌQ/~% Msd`-s On$1=H>>c&3B] O=5\ݱ빳%Qn}0?8Ig)Ӆ6w8K/d3 JJsbz?&_7ྙqN08}ЗcلTBK?0Jvn&_ C2\^ի7k=9>!,Ɠyr-X)Z΍9l6vݾFt#H^[I*}Շ~ ۃk^;o/G/(h꺀Ku[z|}:O~ǃ[ߠ/MO?,i'/zuwiXAZ'fJ:?[psV?BK>=1"`m@I霁p$v?6EyNʱop`[n_?s\:_7-ڎ HRn GaӒΰנZ8\k;Vmehf j`QܽC$ؗ^{7vߡ )wby^1h烸s.ꍡmiA0y ^9tiYuvۋO6"?d'f#z0G;lUY02Ejgsw<VÑ͵lϷzY?[_KU䇞c'(Co,H503ǏCgњθО\`F9鵲׽190.䔌Mc6!i3/_c!H ym$w}trDrW'1,=0?lT*~<@ =r2A8H<Sʣˎ9yj93q6RDŽrmI$#n@ @nCïOK;R8횉_d\ݼH>o6^T5-O&$IO{ҲOj.>Ó|{άWNc.-M¤?_gc&GZr`AH24\Kp<^ "8Q,5~uD3p;+rp5X#\Ock^hx98΂Af`!?]AFkc;o_g2plAysQU{2Jy=ͤ>L. rn%WKlsWNFnbOL'z4h#oy}tRFpNLzDjK5ؼ/R]Bk3ϼg7JqŷmK?֙G})%-|/MvQ뜧xUMrH^PX懿M7CqCx T c G.I<8 Nyŏ4rW3ƚ50\m-^‘5ҍ'S?^,4+4^" 2z9uM+p|R֝o!y@['~t&#┶ۿR~߭C_|~ڧ~+_exqa+g䕩>Ԟ_wܾ+U9"^70>]baxQye6QWw?2iH\\,PEz϶pBr~ Y ]b?jęآc<3^n9ߛ` ϹSD8flE$8AuoOۍ9k]YeѸîxo['<$3s˛ ē>h"](xƤ96Ü8_h׆Ҟݸv?[\{=ϟeBw|Me2'Q>hg]q;p@Mt/e"5sT뢽|#=k91uH\6}:)|J"ođT9N0&!ȭ?9fmn^{/R ϧ V.3RCQ:$<u818Uesǯ;~߸LYq";n&oTY͉*mG.)xbxч&f%tcb_=1x<˚_ЙX+4Jخ8焔 8~G;zG.Π|bO 7J!/)XhJ؅'ٚAvlB91qx|@X&% K<cজ1_x? *ʐx{<8,[ ~84 _ b ֽf27 pY]5YZEy7MMepi΀=a%WɳaKb\to.hy)u.3A䵞%c'޵1񌡓G #oQg 93SQnX(8˔yQ/6" _\b~Aɱ9tyhCvj^o}Oq<x14ǎ c'?OoR'~q m-+/:pQ{ o//K=.{H7#D98ůlbȖzCrmj:D֙ ap$AXs~XYk>38qB|]H>&&{垌{T -k>O5w1R'5;Yo~1 ܑJ.hur&6lƔ|'ѩ?j9yNOxɸRxKAY{G^!ܜrむQ;fk#9YĘxpXB12W話>nJ}m8fs*`w s"|]]ԇ/F?Gs|hos:x\DNAB{#q'a ;.i~9ŏ/;8+"K i'/r9@, ̽Pt_ꏵ'v|͵G?#W?D5ȸ,]HW}Z_6fg+G;uj^Cyͷ߲B7lc~KRg}:Oݺ'ύP4 ;u[f(7^{c{Iql+^(X9fSK/ ^d)K>H\T p$WSA֮j!mډ]0]rN61NGCɦ?4v0XWpqO D LKK| ~KS_^qA'c[u1eYT 7wiRz}zš<ĦZVCQ+uڍx c"Jdw IDATI95cu*po9jphy[h|cx.U2>|J7%- K|E\|<'>5]6n"/g. 8'`[W.z>5Qbܚx8H!1)d1."]qH;֣_SwuքV,`hQmI^pjm}Gp]Q|HcM[1c[&k=`Z$@ d=JgjTH2IsLVBYM.BY[r 򋚅Y*qkdU% ]ȳ&:w2c1CFM*9p25A hգn/Z\|VQb2,Yo$Fv!1Yǃ-BMe=5>y>A׍AšD#}Sd`_ w0ҞM 5A9֙Nǰ9~@Bmmp2#ʹK Q.Nϡv[V xZh`]|}ozv7+iHV:)}MO?st_)j~gwC0xG!k,*8<%vw'9C]`T&-*pD^lTl#\=T% wfہ |Ahb[뚇39;r]61}&37h7>-tʡX>EaYI>9}}xbiSXhDztLbG<ڙUR_!^_y!YqW[Vk)චXFïմ> G4]N0pp"pRx^:ښ4p҉r_qsK6$[A\:`1iЫgX7ktq=|snTb>Wf~&#{s \>gLX'Oy0O ;[a1uNѩVp58|}c.<JoڬXX$9GB'qMW؆E\݆& &)ŵMbq{[(ni$9:ƶ5MC}pǼ熒Zr#u)vrՉ#f9tb 0ac_8ߵR?zt֜FiKsט|&Pqylv~3AF6~$iNI|9rq.]I؏ ' ^J!Re ^D\c'UpYo7?ڬu}^*kڻ|J xH7<gpw`p懼|U>j}>T?|]c\Ȭxf*|bܱsR|wc$:}9mܣc;~^Ob_4H#3VwNW" 'pbR[f4.ǔw,5O{^,.dϡ!5y)zA~zo?7>cyBnu +lX)_64՗oy{wk#HkgJsVr9sؐw51s5}'Zyq!N痮nT<^2nԧ_XJp0vHwڑ^-̝cczyZ cxs`97Ӭ8p#0L>\'7!+m˘_xy&%~GC/TwOCx+1tE'!j2-CrҡjΞ}ۯʯ߾㻿=߮|>C}服K0& xYv-CM\0.a:h'Se>Ñ{|^quk8#wع 6 {nݿ 8\ϻpF F|ƦYMiu1sSGk t*/(#:#8UeK{115/5tpn[cxwy4dE0?㑴l[}- G:  J%p!HUs#Ե9d "G6iK:w?>ncWxqScֻ8=}Ȭ#7K̟s9iX#erl^kqF? q7m/)_W gݜ8R.^ ĩyodwr&+7`"ŝaT"fs47ZVk>urp+a\$Yho߈eAg>ҳb!zϹdPo͛]Af7ws9qslrw((|)] >5MrֵS\1~r%t&Bz %lb4m|ɫ1&"CKF+oı $>qo븽28LPy ?(~nx!G7k΅&Vm Kw }aod|^׵rKѳsdCձAmbH/6λ.;z6F g WmM0y(K:<SrՏ=FLsFeXa/w;hxxHF]n&8rB2nlwF1OlTiw,UF;ݷOOO=6夏'5׵tY2vFsGy/ݾt?{߯o_s8av>S?9Н9z 7|!#a xh9# Nuc $ O6Y.Ϩfl>SsbdFmZNėh!~p,r۶ȊbLc0r/O}TP| `t9NLʘ{sXx>6񦲸R|L:T[*9EI~>^(YoNٸXV\DSG" Υ'Xbd n.k-@C5}s{g]_IRsC>0#E,N?' ,LYDF7g)Σdk}C [cO8Gn#20>韾Djc]SWcq8BB,~ij ,7mP6.w81»+W=Dڣ^r|$k㙜A.*;&EM%Q:Xz1qFKvg67rwS;j9G/eiܑok;'L!>tvOb\sA~VL)Cr8v-ֹ#=J\!w1Esy|pљ2N=8WG-S< n]YG{NՖZ,s9Du\ j5yعBjqz1^PW6 L7Y_ Ї3rתݠ69p_7ty7_Ks&Ø. G߫/cx;=7~mo5}˼ ÌM=_LJ:L|(>D6d <^ HUa(-6 Nt:%yڒv]0evrgsj׾L5W)0kds5ҢXSO3ordX5 @oʎZ6VtR&Fu뼰^ h*oSz0y`t~|h NC gV`v#p:$ro|&yZ%A~Ƨ?}3/m@`09ӹdm,]bz_蝁ϊK68'\_kÀ~.k#X| y @}ZD)'O{.? >rЊpOs`~ &e[}t'y>Sz$rsqm3!>+c 6%&?H/؜B;3qs pt5I#&;Ռ 4mQGFܽ_8TͶ#R@*Yrγ+yDR,wgbYl4uic)m NJ{6WA K1p?l.9h>xl. .km[IGs#ڐ Nh- QL-U JY3d?*oa UFm5^"Dky!Alk]rv2a(q-~839P ]|nLߜfF5&CϖI\[&ԕ8Q|~_C,(&~ۃ g0#Zt6AlÞ? `Zf;1 0Uӹ1i/?qlo̷9N gxıWMM!6&X5C8U2tQ0&(!4P8Y~Pc@CÄ̧kRNx`ัAdbn;8w9i\,8ο;Ցt|§=<Ҝ:PyQ\^=;>[*kC3^0q~#6(dOKlǙ$e6w;:̘فJxt">>yU>jx,j6\a#p l%SLj.zkz19ə!K&3yyĮ;'v{o?w~DQ//}g|Uǃyp"Tԥ<2X<؞'<Ei\O@v]Dg.`7Ϭ/̏Cё@x́,LK%ϾՑѡw% f}∟\TmJyܲCO,/|o|m0RCc9+>s=vԛkv~ɷy nb`4U5G3:㺮MpW\,ءiB> gu<ḡYTuYky\J|+>a.l T{e>0 )sB"O+F?KLLm;,]icLOsyHV.פq>B46kqňA@qǡo5+f3 g΃'֝ ]Xou@04ȓnFcsX?S8z>S-e>ôۤ \w 3j6R%4ΉY@tѽK$ hvA:Jk2ѻYz̀p8e/5vyU>:r@Q!j>fb2xiM1XДJInњ6Һ # p^ IÝZ{gv6&A\m]>;iǵ𢉭m6+PklbG=.=3n ^aHQ&gv8@1-P(.691F@ S1~ or}xX$k7/&y!D㪳♆]7w&VTK=>P:>7#?}G \i( V|WXf;Z2̧.wNq(X00V:q5rlYOCqPT**7_7K1O.swg><@*UOiYg(&xLlCFtmKrQ0Lĉ(%FΣv/ Vq7fÐ$ fsjzkSڄ/]EXPz?VXM707]}[[oo_=E9 z;a:O\ұ͕[tT1Ufg!둸bczi=0<X,`3=_=p&~o]g^~*s 614z4,x|AB?ӗZqhݍ#eU|p#}SKkY@Spu{n}5GTsGIQbmW.x[UZjpm+d]D O jO"kknзs?߼wtqrK5B$lր9KК\" o~\pɥleؼ st48rɩs>ŵqtԇiI[s1M*\p<}C.8Sȯdx:c2z$=*ɠ1T)m0] IDATu7xm5уq*4DŽ\qzJgL^ MnocyVe|ÑY9pOz1V!yuJ8|"H/欺E߹~7h_ e:dƄ7|ㅖy0]6<גb?r2#{.!+/1be +z (betJ 5T65qV~ | y'>8 MҾJqi1_rT݉M粺2#=6E?i%*>LH4'`Y >91rA4.Wױҏ?sIr8Cpô`Щ`6FV< BwWQNSr'.] &H8N+L>V̎TQJ\Cl`C؟;ƶ(۾>ss<;u4Y{:pۓj`XX՟Lnǘ?ա1S:U;mbs:2珮Gz@6-,!J:$}a})fHk>Q.bl2VBm9s%|իo|}8#֎uȃ3xI>}o}}盾C7oSVٗ[9ȕK Fv91褘͊/$f:4cb5Ljr#F//C|\2ھ; 7ksEUaЂ/m3L'bA\;iXI kCf[.8unT6r:6> }=&xu!Ԉvwddg0!G2H"T0V)4!u;_ hI'!Ha?-NCDg:)`q@Q,Qaw8~y<:ֱ뾟WfDr#暁P8m>X=ho~eK Y>t=;m׻o͟_~k>zL?+Zs;C{ot z#Sy+&=Ӕ+\2P[vPZ|DAl_<tӷ[}i\7+\_MM"Q5L ,% R EG&6>`lFy=޼+M8R_XbȧUcYgt3GMc;7enpoتS\T\h,vn?&|'b;J0܇ k "0 or¶?qfuĕb?G{CKSΥG$ ]cվ}9##Q$>Ǜ4hF 񳐩Ng?#co˜āzv fPݔ=wFvЂGcdii)yߚPnhN2ڬ Nz(lX{Z]k3{č9JMp-aY,+MPtEe\l,(Ȝ.ǮFc!N-sg ZA3,Fr.ECr,[ÙXtZu8̦3ƵNKwk^:ګt ral E0IG$~ЧSr:z҃rW|#4IOduΤAk`Muff gM+ GSe d<4NqdϪh] yL4v[ΑQ<90W-h㟈Kn0Lt6arD537 OJ :ónšњ&!Ο=}E|Թ{;bYG)dk31HNh  |P;>K\6h.EIk{̀3'GLNGp7Qrf]O]H֯$J?_/u_w}GoyOǷnk \sI 82,o6ʘM{[\[v=>o8z~/ t C4RԮZ7%,^_Ӳf0n.b& t9ySd= l|0ӆ9eAordV,?ɑ^0sGW׼nj2/vf:>:~ x\ΐFqO&ΛKH g/᧟wAfI\0-K}<ߤ#V+bBʺQ!OX&$uKD'VGq;٣ 75- |946FvțǕI'%Uk-k~zټ  f}^?[}I``*\9҂m͋_h ]6SNftg[rUO)M~ȳʁUog+cˋ}R&+.;~9q )Щpf&9{;;5)[Y8RkpfcZSDEͰn,I|Cu`|N}ឍ֛[1[[YSq /kjPV7P+k=uC]{R14Uu4D F5Od6lQQ;g\涗\=wc_xǦkq6u2qXL&͹>h M|wX0 !> hIp4}h>y1_سV}x(B+a˧7G,Rd:(}$ YIρ8j:ͪ&f_<, ѧ͜ڣRD\=3ctт,6ν(YDO, tR^u^Uw2Dg-nⳆ%<`t O m[ȶ8kH Ow檑Oc Ժͱ'W-=R@}󯳰CނW~Ǡam76A ~4FcId Lu5L ']\'C[9ɽKRa g®?ŷ)fKi$L薕pYhijtowu$6+<.H\VIЙoնᛞjI>xAeoCrYkk]b@0#şUfΔ:O ^'7ǯ~'~?Ϯos~s_h9U}1D䙕ftZt5 ~-Cdanj]9th:c/Խ2ʔ 5rWP2vH=q)Q'@Fzp׈6pydܜ:#y xvvgo9 1t2ן8Hf'E !uxOr4]}ȹ [{v];C)7uYqʽnV B \Iy׽}__{=ċ+ЬZv^WtjqeϹdUxg:g[xL AJ?k>=MauED}W>soӏ=x4_[e ea,=׵[:rj>H˶?~ݎkEdv&m!Okn/5Mv74PNM%y5y*䚯 U>KCkcctZV'7ZvȆ5؟8Q{YpnoջV*75:pgn!蹨qaa8NvsbɓkRoY=1=䖽nNQv %.|t0`L7"pDZP)vfYpĴtva4`3<9E i[7|obȡR|Kz#x(W%l|~zƜfr2|w[\'\=#| ); _:):⪍Xf%!5Y Ưk]1ӑs!A?h~h5 [._ryn0R4u@px>? S^'?/,(ϯ~Fc~RxS|kpz{O/T0H),> Ѿ?f>hu)͌ϬGї14#ʼcOtD5VVr\ 9 Ec&5hp*4Ư`H`]α3M1DuR Bq_1 37 (&7R~P%1<4/'s35@'^33|Vg9As>}_oyUzTꛛsѳ5OLm"W~3(s>!Lh >eCۜhl;ܘ'c F#־yZao)˨^<ƂN60(TT)#+7GSⳍcȏ=lf{6ĺOȽjq`sn)ɞB6%,O-h.uyiNyL}=DX+Nn-6Ss| ׮;y WLܵ0a~Rkߎ9GDvo2%C|d:vf.$ W  o~13TNZ>Goca3?^&it/ml3Wk2g/8DhlI1DL]\g%^IgtV$9@b`m`36I&`0UckȦn'ho~43%v9Oka?ew]O_23ou3DiY%뛜~sF4`H^\+_Õ_Zk>vM䵭ir a`em֋B`8N79|9"W~8b*i?/"byVLfحQ맹\!_bʄ}P C:Mw!FaQk4kp@&#ck7}F!UKcϵmݓ_#|<^!㏗< 멧E Rgrηi ɺB=]o2)%O\_#<7 Ħ/,yl5!壖2+SOQQ l|ck(jApk50#ixss>:&7|hs }nfF " 9{YfYg<.wrOsCcheጤ+7Ƨl6gkZsjh:LL>4 hv$UAw}1`'\+}|G=‰I#?oz9q;y Ю\K܎~߂LŒtq廃a/dZyqk;fCg7Q0ON rӐ&}VTo1gԞe.4ZI37ˑ;-!.0OOiW ^)z4O=P?[j$BtP/ &MT@e@7@%<"1;OxqO_vb`uu17 #6[-pO#(9AzĬsHfyNvR gBg.WîϾ~i?)X oӻک4\sG-!LCUU1&ur#p4c^T4^ۭ|h,; Hϗ(xe\ *ܽL^SR:E>WJ|Hcs]"&sԟkGh"SOrµ~z硤Va2_WF<`j?%bzހ[aļ̺9627}/{y"#mNSWo \ݏQg-D/gopszJLأ+<`݃AzW5-8QZj{rc_1%G+F\rl 2&uLdmX9_64-3|Ԅ\_J[%j i01 6|'8&(/NK7TΗk/4*n^+k`Ԕ\ePn Giet`ǎXNd8xZ53C rֱz6:%ysËx$9*3O˯9iT^FK9m:lM}N5)1ίamh!Z~o *ep6$:YTCYGёu<ƌ! NX*d`ߙ( I~2*61}7C# g]s$37{qF!91%7@f)3t6Y7ܣr Ҟ}yusO,} &B $ApNqx#[#uBt 7}O o߽zX_' z|frؽp q1,y|QxH֊u@|s~ PF?)6^r}9L<1vGG,EHW#+zIHºFH}] 0cCMI6C͹G^hۚ['8_GCE8i/> ;3๹k:_a"SPO&,s38_t Y<^\CھQx?G>Uԯ><7ݨQ#&i^M1'85"jZ$'$aוjq /5D뜙, ']O|D2h7\S)&h2ǃO&V}η6} i;7yJN#4W6p$mVxgeq7lXB<.맃TϊpmN$[rs;h4q =={\!@KZzÚPI6 SkŸQqX] N`gcD-;"8 t^U ;:LC 8-ڠ|̓y}@<{G^>pCExtrA<øȊnE4un,6;GhzyLy/˚õ(fẝo*M׺Kglg[K ƮslG<ݚCy2u Y݌bm۩|t^eh:w-s~t'9'A{cw07Ih3C0B nFUA4B |p  WȚip4Og0u#>03GsűoL-c"$Z ڲ* J<B=؎QlN ~N HrnT_*\#>p77?>Nf4(>B cq`'3 #QchHH^x4W[NS-Mr;ѝ85!yc5+&h#FO1n%VR wX܇^($(r;.`NƜlΚe@p;l'q{uH,2F|ϡ+[2AhX97w݃Y\hspۜB#5pɇ?N&%O7֌S;FЧI N ڊ0= (Pm=OE3lJ z5?h! h)|߆Of4s$9c`Grr5ۜs.pQvd%1~9zs| TT|ilF{`6Ko-s}ꮪ†{t,p\cO_&@WS{qqũOuza:#>koLıx2DK^W^M$!\; P| YsOk>.dn7YDF7Y10ec(gy,yQSh'o736MΚK7no$ZOfBKn}̱QsbѠϲkȉ~l];z}a%Qj5#&krx4|4] HUW*o{.>iб5Ҙk<ǡɫn]׾.os.ޔ8̍bslfMxHcC,k^k cMBȜNg [rߋlw cth!~Q4;%H!Nmos/0ۿUvAôLjȜy`KaGuH~c!g=ܞcNwYa89 ƒ⯶ۂ bW$:gdusmMFnіu׷ƄplgaDAO^8TF=v(^/Mh5k_˞|Jj#7"&63gmjYORJpm?˲,jR YNsG%&uz,s0L6M2GF@=XÛ~R_?8ˁ77$fN%o/Jq?nd1M KN]bt{Op]ӮVuqn^կ;q}}}?z/GPV:aA>jB[;\6^_&JX?/@3D@y`s̍u Iz Ut,`F0P>@Wfy&dy+!v.Vqrsx!-.Y9v6G|k>uh+|t09N>&^3 HAJ0*y|zd?ѲzSfik+O'qN1c *Xm5۪(eXw|&Ѻwp7imck^YcmԿwkkmm<f9e{ø>ӔK[[)kŐA&8xr6&xG)Osm _,<%jĂj_:۷rNOO |_]QI<ΎڧfL/qvשcCg|rXw1bcvٸ403gpncYgt,<|di܄>P2u;l'sF\c$bʼq;1M>qZ(k\Q Vh8!YbCX;ҚF0'~YТ~lN4L_VͺL}kF/Z 2@J g=8Ǖ(p GYpxN.5:㣜j GhMsX{~Ej= :Ŷ9)f Mq {&Zb4^$|umI4+HA3e0taTid0{X<&ͅ[`Wlpt(R}.ggR(`;bg jvס]ʬMqF 0\9~h~s N?Q0?QXʍꤾ^Fcram|MM1ԭm74k#?c L.8{;O 5\3G۠;Om`>ҥmv<_}닾go7ޣ>=Oc0SWfku'L73: 11A A?_f<&Am"}LP$4e [%&n,Nyz5&<]l19[ը؅́+ޚ;Sn;_oVNejEB&_ged6O;~4c3l_+3g~g__{~Qq)X\>&3#~,0ǬA,Fb,[` @7#ÏOA8=7~\Isf \Sƺ$r~ i$IKr}.l^_&yo9:w#Nɺ W + #CtOIH8/G}"[GMڃ!x"d&546ێ`ڋszl6~&ہgEQ9.q}Mc.dW<k>%MD8!\ԑΰ{Es@-4yrwLwl#w9j1zӷ3MɃhlRohk!Ct*"Zk![s^0i q|UT|&1_=^H= V#;u[~#~i0&dU$eRWgpX k%qlrznӖ?7\ɹf5io-5ՙ[M8ÄOɉN!"S[ om0TmrvN 1'Έxav (X2DKcgn{6uL.@kjq/0͋%E~GΤ0^rSP9ɡќd6O.sz@I0 #Һ xz%Hsolq%A'o{DbS Sr9#di?Scܴ@ׁKMxJ" n8l{WXbuSpψd|8EN,0C-nc3y#@.&u!M0 <ý" /D ˜ufge!~%`ƉdNIl&8)?5!2.o޻^]poFy?sM_nMח/B|f";|s`w,Z'lAszp?5 Itg,ؓ "#gTLd\}H>naP~~'5 ~ؼI ju2zA0 ]#c-؛׷y}FZ/5^ z!@ ט'^˿˯v}臾z7tg2yOֺm͞ q?}?Q}]\FyE@4c*s~}C yhcpHC7^ `WI)ͽs}|"YK5ma]B܇7~=dn<&͵WQמzrs±չz2I[; 0ٴ:s YVun5jJ.@ 1Ct58iVq1rVMyl_kCvJ@#q?h:pׅh\玾e8bhrN=gS._KڼCk=>YuQ,Y,1%,{Goa`(̞n?4GNtH"6~J=bWSxwsneM6t >qwj'f#֑ ^䮅Ƣʛ q#ON0 cl3R6och];g{:FԤ]iL:Zm|Nm^7n-&/ř',d)W*s<Of16U/,S($GX䁋Ìb_ 0tΓuXb҃MrͫuσmBTԻzyӯ'.9W,= B+ 'F Ês17>'wv[96K m:Ew+~}]qXC K6Ιfˤl.b-sG+\x4>fm$B ѡNKnԽ]O |ǟ\OnJ{ u*?Tt|S+׉N}CNˆ#T:F{&: IDATi j'4xΉ&曇&=A7V)Q<~sjpxW[~Z`0|Nv^Y`r>O^'3vlox"#8oy sEqBZF+IaO᯹>%/y7C )50v+28;wzw|cyjB~5K=r -A~O@߯{$ _"Vf6zv3G#>߄ ^g nZ`_}SA˪LpcyXU["-ݍR嫞(SSoإ5h8q\mXVZi}d\O5ko:%m?}M6î 6%MH㘊\[C`T[,ʆhr`o|.d?qc؉Kp_6HN"brb}fXD7w)b<ƥySFgc4ȱi vůf+CYo\=̧&8WM廉CL͕qh9Swγ'B!0,\O7䳖3_s؞l\p|X7y)#[5gҢ綾9on9@պ:;nTSk9$xWĞ9 !rNkB>',2gEmkzvp69+ft×4:b67_WIG4$:J -&Îiߢb?&0 GYF7AZ{^H5VEgb`cl)`2ko>o^O|-^+QS;R76]C??e_|}k?_˿\o}w{z_Oy5:KO nltuOHP7yR&%JF`5󤜻kif+dX#y͵% N vVj$&1/}]ּ֍v+x6'A }/<'fA?B<\_6oF>$[oM \hx.K *8@9Xs֤̺_-_z}G}b]ަT&u_v'л~g~\{ '&zROa3v,=BGd 66>DM jD+uk?e/PDH'}Ǡ9 9B:=Nġ誑kKڟz5)ץbZO4G75 |1GVmUa}8.]c]ٱnv8}$o"M 6iSMm;㘖2+ $ڷ'=/FZN0zX6EǗ4yƊ] c8]XV|Ǜtvvq&2'?~M'kG5ƺ޽;`w1 [p#s.˦D=qsv3O>w%37Wѿ\Go ^r l?Oa5 ɕ5f$.u:qN0{@i09xp;IE0iֿVqn s80elA=U0w/4CBy^RϓoN7Ŵ,Ã[:g9k^^[Λeq(\C= :FzpZj6=N8{ai=I0D3]k]Y3T8N{$@Mm ߊksbװ]z<"ԧ$V]~-Qoaƛi9+c$";Iަ5^ œ^mn. _:0v/ Y@vA[śtp{r6z FLwi!QmPo]n*C+Jm^lqnߣvKm|gE&$zʷƒ}#V&5rVE'귑}=[g -l/ .px)殏\!ulR-eՁ\ѯ|SכMo땯0Аo8ƇcEB&JW\>/?]?n~~ҍG" ;`ެNf{/ ^糾y dpQhn[V)lPʘhM<6x֪EI*Leu@R9A>CN@LLʗysyc8ёf# IM;xy7ئ8Ay!x]/F>JOA.}ɗ\ >JN P}~'~o|ψ?P!c&%nCLjI1lCKY`gԟrj,.PnOpӰ-n ZJf&F|iaG{nXB`4]7.,"ɂCE1<,!3ƘBYvg{L[vَ M|#%GMA:?7B#p?N1 ssaEk&6yy)}Hq{/9YߩiֱOz3сx58]v` nD/ |zusmLҭ|aj b6ob MG\' **~=/A$F#K!Or=|n6Y1*3VDM{9ٲqyS\YWWv\K||:^K5_n`tL&xŚn =_M&a re &}+ֿGn6 B,md8a qr3?A*s7_ȏ|]__}dhM.HST? v>s׿?wOwoGtj1o$'e)}(Qvc9Xfpm(pΧKhtĸw.|' !YԞ}2r0_Я6xcܩ^x.9謞a sǟLe"=BONf>ϱ΁pՕmք=6}9)$nrrS.ƞpj[jfb%Nפss;QG ^`D7/3F{2ǿ㪨=OQ6JJ?hrs]~>r9z6(=vn Ww9tDQk*Z$lHٴ1Ԇy mιU=36.i+ r͉8KFx] FMP"#s 6Ř$<L.c, ݬ T>js[{4)n8{cJPs{cm'X._5>^'uhcҧs?"XəD*,)aF;wS Xj\iEn{Ms~Wh6"05RL˶*!F,^}}ºlM$C Xm 1{qk& gKpך8;9A#̆8鎥!`N4,jG1R3FEF%0a_eҧ>~gzں#y2׊CZvmL,3h$Aɕ>,ҩq0avp K; z0LͿ4~!/$McWcF NvOa5p\^c8#Kp78qZ{ۙ SؒpxCͤ1ySp>%Cpt K:, ںo^4rN=\;wVKu^ц@D۾)rkVN~hvO\ wrZP[ )ͺLtz4rnCB:_Q١ܝ3=!9t"]y.*rEXDXsdth4's$*\@49ls^~}|NKor}n=ԓ7L/*-3\ 9;`𽇮>o?}O/w_+Lzhp>D捤mzBWA&|n=c=ecg9S^>sC$r֓7i%÷K½:(Ӧx?܎90 {ܿb|n{tV+ڢDc4b$] L]jn6fzJ^ Cɟ)W_LMbý6lmTv^*,n~zoT?7?IZ^3pc ľZM 78OȬ݆k:'cF4 qt$ 5*/|?ȘZEM4U4O |ٖ#,1)߈.{EF0uxV67+c>Z ONk ˤ%ئcҧE׽#" =u__3O4JMı=hq<6XRuC\Y'/.{l.|w' 7ru^x)6iP]\py!6gb,wJs JL,bRcڭo@vk1i/W.ih~Zӫ?:'G<)nr0<>}͂N;Mc-: S5>b~C1O:[$דz`M apI@Ww܉~sVrOA9`69bhܚĕ**'Ms5H13fo)`Ը&i~Z&vrUw$YiO#ʼ/*T圆ܮ~s&Wf{ڲC_]7ܴHG7A~p+!\/ >'4F0x m}Ǿr3r7{zz?]O a>͟s{ů>cξy򦾑Lhgd=K1B ͵U;޿?g~"O(6z7DZO?R0z$'t79iXo,xu2/̨;9(5 4 |0wX<lXpNMrE#&јv}&ZDb<J'cuO7<"ɛ`) !W{8fOLdɟR]Fz"ɸs:/-|CjLHDsVcb a31x{%Pq'V?S qAFiyisfF1T1u|D``-/gkAH}JL±3K]:0|qۼ}jAbqH yñ\'+>sRB̮_1S^$L|&1qLf9Eg5Et]Y^%~s 5Q)j{4w5a`ul>W1-+@m0&wLNG f;-~af^|΃8`/]w6|@fJY9fs$9'իy2U+%m`:-L4U[SޔS~2O, lrEԕ۱T.rt8) Him IDATG|glFi:i nVɃƶA圂n_Gue焯3!G鳮?x}ď'" oo7`i0?s,9}s2_Xgmpݨ5Z/狈S3 _{]KAӵ{H8`͎icMG5l4Ze;f%>{Uz\ܐ5"&4#}>OFA^߹|}'_/{ٓ#s|Y{;l,ƚ0M*ן׏O\Mz_[KZX~ҳǍfZr+~ks4t-utS|LQa:"<̾kaL=W9Kt0*_oTuCpߘ9|eх99,vg8;©LK&Lxwoh4prA"gs?_}0WA}f{E*Fܥg8!ggYU0=\ 4\5lcǵ RFKW~nM^CC {2"4pr^5 G&k7oˡ Xc~g3rRfJv2G їw* Ns?Mp lp FG_:zC ]?ׂS#x| xXDkw|+55d{VvƶzE8v%u t.cA iNT㰐I>ʱ)D/D h3kgL"2]' GogΞc4kؚtL`M:)NlIo ׻@W}/HDAS%!i5chB Tc)ocIڌ4MGAcJM/Hm6cXbD*BpWg5;sZs5;g7ð]ӬdФ߮S;56|.x}"$.LSتퟃ5)9x HP󤷀"|\I\N*͉'c}19Bl&7.Gy:$W6Λa\5CEzk'?SOh a{^ gm3:v7bK&mR']\0mEmleXxS6ǑP߭/8JFC3;g<   Y҅gb4 o9DTWw'7\=_r̈ĮFIHII-|0ϰsXES<9%^;%-re'je x Z\2E+y< ʗ19jEw k.ԶcP=,w/TFx N_~{߭Gn5i1@_=G־(ikhQѠ d^$@lO؝|>YQ!FHCM/7"/0? wSS9m\&e@Xojɽ`ngfhE'ә:ҷ/ѥiL;u'1x)+ܧ^qVց5FOY:Ӻ㊦E\܈gq_QΞI6vCC=X&h8. qlM6vNh]mу]ZX.wjqȜp(18J@yF3Ѧ+A4O?l=1Ufn8Ȼr/[]dM{RcqzϚykg㯆~6ܧW[-s;#^Vē&߇0?s?9A@fW}h.^?yyϻ`PǓ@̫47Qeomv%ℶW}xJc]ç/x&sn85kpέ} &0#51g'Z#0x(\t=95ƟRFZ~V_Y` 4KGB'C g?K*.?ѮΈFEΝm}гqlp{,ƘnbvsMdU8CWE'/w(*gN4m>N-PRBm SMZz\5C.F9_ܲ]N{3cJaZB\h WS 'DӔ{'#&W&߿jWtǠĝzO\#j'"1`u4yi-/r!qW8˾5[ɀh%`ɘfx:`1> .11qS92h}Oo9+`WB~ '(JI"-לL)3ɆQoH# q}7*1vŷTdH=OE[>S9i?7[r?{-È!-P˫pf -oYɱj=pO OLj\l996t鹓AZɷxŞ=0D*._8sQ-'k`/Eqяom>i_|+.>c|MkwF'hUZڏt[o>>}W|ŋȏ}o-#bC^~d ZI4հᗽ*%ntwF?6x>y'QyJ=O4ۤtu<P2#8{nPGԀq9X ؈0;ԊLfωD.{e<@S9Mkm\kXRp&s6X`w&M4f$Rā'(qcYZ6q`/~ J'$̹Ф@z?K͓ x;Ee^Xǻ]uϩu,,_ cI?j_kvk8coER6'$ fj6u+<LOci"nPt֫eNCf~47Ag3>#~؈Wy,UO.z3$f}=Fm|2:N'nxN cf5<":=`] A!w]:^җ}?Uo`!RO1Cܩl1ZS]Ocx{xw%>_tGK:QuQISZdekmLidi,53r_c#T1s +7z݆AH"V8qMt…XX!* SjH:kw%uZ;VMNmϻ>[4kkWTƑ= g0Zxf'".RmkƦE^l/<'vr[_&Gtq. XYqD򅕸5 4Y>"lE@6]Co'wp9:F9 =,<Ɠdk1I\i\ ͊q'Fe9"Ʀ7 c(p*ֲ\r;3絶%:ȦgʜYzGmh^3eS{SLr,fk*"=th62]zG8P?Q:S7YM?8W ئv~XBw\^p g8 /iȣ+xH)Ćِ1O>֗ "oׅdV .֤5 j k<9uc,2$Y:y`MZl#mq\=!Wc} oEtz*Ba]!́E A^SE}6|uMF󑋋Z@ A.qYL.0]WMSt9 5Yg[kU_ .-|Ub*ؘM9,c0h9ޓh6dZƩcWsx 'J[~9x,b}\55"}L|v6.-0_/(r\`sB ≒~Vh1E ǣ}Il]p7M']M9ߌ _(K~(! mqTwãd|%? s=-xFL_r^f7Lam_m(Y칏D+!Q{M<)yv -jk=TlcV?hTO`?#9Xƒ~}ܦ:=QuV2X~A΋~^8FPv>Z{r(=j̻tX/Lx7Tx=H 4I<Cy]O|峏O:nf[̓vyۏ@+xm¯z;+~_-ŠfW~E;[dޮEscX=[`_bb\u܌gzdX3 @_P…ݚXsNXbB$#i8ͬ:#d/5Ё$'et:0r~.DSwvR8O>oy |5]|?ټgy=Zp/8Յ;xrگGx M ևޤ:/@`9kpl S*|Qa8hKxz9 IDAT!?Aȹ4;beMo?ݾ?l{z=< C=J˴~lO^n~lEW< /Y[?< |Ԣuh^N^is|/llQ79 ?N>`qڊڴ}WTnטolĸHl)G$y'9 W{a؅`r}6pTܐ /Sk6

:`m޵N3'Cưj5 B;W,lxirNp@] xI(cժe @N}y[Q笳-L (Z814EyE T;ɀP֬)69~%6ˆ3s2wo#1 Wr,h{З{5՜p721=?f)rsk :WbS@x$ w"WWasX|V3>l}PP\h"L'/E5_$rٹ0} !h|KS.&{ƔycoE)=w{kvrW29+E{l]$vL˕ #i'[$uohXBF1 A'CR_{Il+g/h]n˂T6.> l+ho"p~]Lh֛DZ]ow>yh+/|nbpߜ=\,_?>~o=>yǵȭsADoij=QFSq1 .plZu/J8'L_"csN._TNg"[xh[}k^T6_QQ/O28 K^)kź:Ço\/E4jCfsd}Ml'@2O/N3naQPX A8uQ,\ip14fm)_CphG'#s|:FE$({ >RRzMv+vaJ#|^l!@?N]zFjJK:'O(ƾU]28vzYs7a{s)}V~rk:mG%&~jpS~T\Y5:emǬ{mj8BEx wyr].rm:D ]FZNV -aLn,ÑvaC;cCfK.[1gO?ju 2igKMx4<#'WZBj3 k$wɄJƐ(O0VcGml*~/H139s$-EO`u.j  fhVOwO|(xdDdb{|ɬpԹ+[8NŬfmԪ $1x I6N_uھuIxL;5ung81''M] <9~4AN}hWdݳ./ÂDOl+~[5}Ch[Ck׶ɮ\hYs?@4{l6dd]"yvPm$ɹQ qY3{5*uhYʕc8]AFs/ F*%$%8m)}"ҒM15@~-$kf|6au_4itğej{ 9dEgk'~˜b=ʏ?nbToz8bTtj ^7rG7.J\;h֛& ;q=dI&t/ŷbܣ_B{qM@؝@4qg p[Ӈ?s>?++^w7]KC'Tu'/L61TYj8 l9N{4nG}`pu.~$M{.R .BkMbG.Pu:(rc.v,1( Q=l'- F]1}`_?s'>ӎ/gO}}?q䑏 qcB~!/-aHt3eۈ%l"9~A<+x>s G`@aǗsC0PvjCfR55's4A/LZ?Yǫ!EK|walzykn٫# .~`)yr1Jݧ;8z;8z\xT(]ʮ; ֔>nZ7 t_E_ܮwU\?v9KDzn3)-} Ma .k[pqNVLj SNуL,뭆AtlQsIP<ӷ1誝FuSO8u P(jkQBSo˘ʓy$BECX?z4u1$+D`ȼ\+/LOp$iIQ5\diVcpS>O'ΟsӓQvs0֠٤v'YD{ r̦.ahAH& jp9֕+1H™rWy@Sq8Yuvl=)cȒdgyO-yB}d968g`cc͋뾠\~r?>w_m{ h-l)+Yơ8o)㯾 nH9콇*QÐ0%-ke%0<յPGΖ\da=R%ȹrbo&=p_ԏ{i586@\r{A;@g_- 1eW;!/:lnYek0{RK\SoOHޘs>2_=W'{b}_I6>P8k&fְbyw~k=~}"h |07 l=?;׼\\>V*=F9>yG?Fw2׌Xvd异 9XS`{̬8:ė*xǑKÏ*d Ws@[6pp ^' +!ywڜQ\i 艫.=/{>)ǭH:r~Si1퀭 >zǎ㝿|;_7}T\ MvnoQk9s|xR/"{(. 3U79xܲ'srg9~pI_cȷoyR phN65Dyл`G8sұ",삺ga#mᰖǻɽC=^_~l$E־l3&dm^GxCS#؝R%0G3>mL7<IVoyM۳B6qLt Iφ}S3 +Yˑ^BL}w???p<{%/=첹]Vmu?>w+?e:=ۏ_w]W||M77ɕI>#}}_^ 25Ǜ1 "zǬd ̲Zn}гP.TFs3fb1Mo8'Cvo.7mcѫќ[S Q6rr')vi %y Y\(X'sszgN }41kW&mn_=O)s0k4k[Kq7A6MJ!Cnؑba`9 04οn!3)I6n͏o;Oo|~:DIh>AkҽZ|cyHcw'7:glŅE6㽗_ڧb#bSrYھǮriֱm5ۭ3G3iWNzYsc1qlX( v9a0Mڊɑe SstMC[:W!d;&}8tONٽ#=?|;Xw:RVh[8WHa<8} ?|~X5 Sg4r8+*b"U.J eR t2T 8sѪl+hpe[=?h TlmƵZ0Th4#8.\H&A1#}أ̵n+&>qa9\&?G%<_B|f`9x$}ek`6\Xz!ll 'Rٓ\N /S9?F$}a/9ܿTx7UGr%Dw={tqͷo:9O9n&g :I f\ZDpnަo/<[ߠwX3 9b *Z28;NJ:9*#l =/}!lV3%Ho9I69axg2tBH+VqL8gf>v4$K qAO/)m_%Gw; /BlrG!hiL^q^HӰ?mZx<k9@?0E*vCG0ѧ5[3'3&u|oLh-Q~ qo\WD'jjv!/15gaq \ r5x[2Z<ˮ]6j7W;?{М_#Dl4%T$i>9Ba႗[-P\6l&:$LCFgx\YI>r-+'/g}V\ T9V#aV_j%ʷ0WszKsLߓ~Fʍ9ѦP,F1&`0[oe9; zzaY&:cd3-Sû ŵq(BI zֆNά=5Z&{y{eGUD+*R˿ub"|Ʋ ⼌S53rhY1Z+xga]p3 l f G% 4i>|p3X9Of=1ÕfqDZ .T:~{ +1h݊~'yb^utTgsic Xc IcPa'{x$ Ml&vR=@CGNgQZ7&;k4Xyn.pF9VfJ ֚cd57%I;s Λ9 69u -ap,L B~/c\c1Q_\e/_"RK ![o ә~l]\<9䥷nDhy46DCL5 `_*𡙑l 1Ncw)Kz^gc`-erqOSk´ٴ ':~W;kNW]sşXq1태c=GyN9}02t)혹m0zb9orEokCb6/Z/Go;̧־(Opf/C|QG=(?}(ǮL",ִ]l ûU͙WE5ح\ԓ15{t$gFr}Q%zcPoڮǑ-ф텽e^݇%31=7M:SV-!+8=&32\S  oGZ11pzA|M>3Ϫ>n?kz'rcacnJCY2w#_z.;F̍M>A}k MzTĜ<.w9 u86L. ښVN35~3q53/zl6=-m;.D˯$]MC[[!SJ]9[ɾ%J-%;&亪 _+cc?*6K"19OH0E@5yg̷͓bcγ;B`@f5hbi]ƃ h<ۜ eSr or1)-vCfLY6\Kcq&m_a`:tyf$2k}~gO~q__Ez#_VG ,GcӋ[VCkB˔Iu-7߬w=x鋟ٯ}TgG@k3ף Pߊ&8o.zC- MY6|~p-BxGtD>0cs- /.D_58#6/1\ؼ3]}ޟsǟ>ݟ7&p%,G'}҆c;^;@ߧ8 u qoY\;d@X>W8"mW]Лq.d~L-TgsGZ(5@^>?^Aގ -&h (B%яyXxQ/NM>85Fm)/k᜻<dfkn׺m˞c^= 8ڧKzTlM ~غ0;xi} A>ssK <, oKi/DLu6yFjs<}+3@L0 H9,1ǺrV^]19H1RN o]Fp'N+yo<5 j67l/`;Ztf%.bh㍟؋fZ{N~|3;{^ z9&7 Pˁ.F\+C`YjN2 I}^O %4'B9џt6k="7>/J)w=$8Cw2rDZ0<197rN V_mta+fU-^LGK<_lBؽ60fD8q鋹O.FD SE>f[sɨ!llvcq? 79uL* |m$vL)/N6d@=wa{p2y hphcLdZ, :\'~@3vD){YW-sdA g쮯jzۻ`U s;1¡&X6SǎޞOn8+PNuO> {?*cԍh]csMe.E7F~<^WIȭ|s'>M7^˺}QBP&^86put-=Sy:W~_o8=ӻrs]8_\990= \s^ K/q1ꚴ梊KwsӐC.sXucs-hωSCyc{۾?㑷 w>>ZطtkǰA>yϽowoьssLDmV\C"uHP4vm0(8}뾴@#hAd ;`zv~(ֵ#\1>!Ϩv +]sF<q3%.Fn)ޠ hbV6nz~ m~􃋗[o߽3W)@kbO~3z8Qc>v9r͟9ݣrDS&->W}-l@ԇC=.ŇE^ѽtsU^p>ns0yC@riw֒z`iXM_(S;<IPuŚYⴰ*tz6};Zr]H%z/z|ڙ΍c<&lM]ی{ ,=BIxD`)eXql{.=ceh!5CP(Տ mMnr:(X785s˪jq BL]=ѲD8ͫX}\qEJ@X+9q?1Ǿc\X/ƪ"V/u:AqL3x|5_Z<  . 4<4rjR\c"7у!'vcks6YGHM<kj;4:Lk ˩ #X0=,ħ)WoI#hg`;,bȡ>7O ʙV/~W 8"n۔mp}u ^'YS'=h_5~8;rHo]R#p(j-T{qH6U|)4h!=c/MgV(0~5 'Z: Ҫ7 ~|,=~C[=Sx/-ƈGplwd15;ԽB_E?7{߯'{W e&'܎ﻏs `WunRY;ŋ.Nk'8>  jJG .J+V.rA}p\ƍY>a:Kf o~qn?0{䙃.mlVTZˋһg~grhqh'Lw8W;sH+oGѩ~ iNLty;2\bIdI634Qxџ\KDXm/{\`;2JJXmXj"Xu>35N~gF_|kM~2V'Aa,юQLN=J?Xe=A1?H#E=Ξ(ԛ^ly4`/0$(cq 2ؖ|yRK'ַyA|Y\ud^ӫT ~X2=/ά<ٍa*xۜl N 9W'Zho}=p+4-/'.bEt{rO^OLiҖ\M^Y4k_<~o\U_tW.sS\8lk a(\mh!LڸoMJh>{Vwxupvs<`Yf 8&O>m;݃(' $*YԆEU\+J(GC>3ைjO[%WdMKSmb8j1s/},Jg4{q2XGTA0p6L$gÿZtxQ#̇b#<1=s~̐?&HIѕdɸ.]8-N}]ڵ;p|͕<]R'm=l˃ hok4Q#p [8d 18v tNSk#׎|#Z!fٌȜszbrlOܫ:W(:ؠȳ/4;ѡ/83)P9*%fHm}e~&X7Wxds,p' hD[b{\=[ёNer`dr K#`S+/~4l82Ħ~$!{gr됝wjY;?pq.v܀M)q݋pu89\Pĕq[V6 G.x xғ?xً_|f}̷|9ϺzP(Z`x׻}oտHi}wN0Vs>y^Pnkñք۟/|$|D8ج/ӷ A7&zN> J^3'{r4-e䜛p;Ďo0찧wN'`;u9%q?N%Q^/X{B^!<1 +=5~+'lI_ܠVWaASA ee,Փ<*l XA|ݲ9;e2w{ Ѳh9k: ?kOs$~嘢!m߃cPsYlƶ!PL?WP7| h[mKD'^dO2FBi2?9rjE[Fq11gb=&XɁ?sr.(`P~@aMN<#d_ ?\0ÁicөuiJ`}nVD)Nw37_RRGqK=Ci0ju$Acej6BGFfavj?nbye+c1]ZFԇGjtPgB׹DK %W?Ƚ%bp-8S9vߏ'' PŖt&."yaѳz碚<FzHl] X1ε7zbzpeGGIÅڬ OzGV&opyePlYlx ki0,Fqo= ,VSo7 iS?ُ^(f:Yc`gٖcv%ˉ4”cf/YQF?xi"gV9/\fOOV'F P'a #B_&T;-|_0v9Acm%c;)LFZD[!yzk|p 6w?D_X1vQyh; XrMǧSW%ǟ筿 kW׎Gcj@Y')-;1˃}E];T[ ȣ^s0ѷwu˅0. xpp @b՘:O8e }%|mKߥ91q\ޏ|N=ɟ?y5]zq5 #h9;"gxNC^zDc5eYHʘ=;~8F`y3B41OT.~b i11V$Bk繐0IW[lpOe1Lم[s3(tZ6Ef47vFV;7H\J?(}7no91zulۣ%fw=IpK1s|T4y˾}Wֽk<3zr4Q{UڇC0#uCfO IDAT1ė:s^! qя!6c%:Q7z._ϩ$3_ibmnc߉~d #ڼHx6|6fc;6M5|#ML伖<|)uϱ&͡sN|Q5_vq@.1WtgjoR{AOňVg k0v~ ǎpzM}Go:iᢐC4w^(wo4ffc>X|UZh<j`v!fj1zfr_Z 1ԨhCcz [Lʿ<[#9=q;~ӆyr\„ Mc8}@kQ<7M\2"*' J逯8m朓xhT~$>yq@ciu>T`@߽CdCîAU# nqpL1Suיc|r.VcvWk^.b y|cDŽftUz"7/+|5P#5)s.SOw?:߼_^RCﳎzxB%3 0Ǵ:ΰgQ u__8s0'[Uk8ލ~1ۉ _ZJygep?y|C}?G#wr_a2|3* W+_{[E}WWjOSǟctDѾ 5>gdư2DyuMm&yХ$.oGhW!cekzy! i=X;%ټv gr xC2cZ-=!"bpf\4%L΄ms&hl|#Ph&{N77MiczrwNKkULœ`DXa{9}gySB7ׯ9›J.4WteǠ,AV2rмdžX]oL;P)ǖsA<$z/On}:9ܗ`7M߾uHבpbT_/Ŵi՜Ɂ؀TxW?Nb`< }Pgoȉ fE1T~`>9eCg?iȺ '"0f98,2m.ՋG*)-s2~7*\}淩0y"{!lyg.?[ŬdmXf k7lެ>#哃u30+kMaYD?6߲Dr_7z}V >3g?'|;rpVLdh5I%f3׿!p} +^+W}u`xywp >Ԑ]\cdĞsʶ/P~L^|*?*-Zo)V/hdܚ1 0kt׍2z]Kn.<ɰ̳:iA_rb>REf\ǑfѰumk}]-Ǧe1dΗ}.>1նŵA-zD1y9'}i,| @^GGf͋T^6 35,/]ýkXr:l ;&yfjw=pOV;qָ%߳sPCxzR Y+H3%\xX,0n,%m TTq{_֞fScMG<^/[O(+mSZpιx`7inD@$uĮ9nq+!IyO=]ɁhncĘfZp>L&U+?d}> 7aP+F=;qma8ԡc<ʻD&TpT錡܊:7s|W 478?^>7(Wm߭OU6oS3Rs&csbaskH5fOZbpyqxLԏz,ޕK,K7j@ŏԴ3|\| <#-~!zŪYWdO[,`/~.>+FF;>4{w߹Kx}>R7olٮߩE83B#rdݒ߱FS=/Wot=UAM Ʃ kwpI`6SJ@g-(Toqc>8y?[dbL<)O>o|?󧮷M4ĴO=DK\б0PCfDf'_3ח/~~^7N?_`صT><xtq [{W_Ȏ*ܬ;,E|<$!_QYⱘ5 b ΖcGYԢz>dH'iԦmg^[c9%5<^}maPbbz<Y6)FXY0VTboj}5:8i7X61èWchfÕD\![lfR6+cq3s״=fk&YbI]!)-uo<+b&håw >Gvd~2, Wچ"b` ps)\x,!j;+óOcEgmMpƋ$45_X UEUc@sm_[v(%y5ҞԵ7>ac{(@lt%OuyZrw~/!1y~s~'{a 4uNw}شts}SZ:+43J4c. eZEZc2Ek C{$~FrŶ vkF¬Z'Ε `+XFv^GdPCzL ̃m1\\`F.b`9 g? D l$SiE pM!@+arr4 Z ŎvJ'h? V[78`\j~Ș2[ vo9&2oz5F8]Ja,=7Í=>Orau,&;Wck~ji.>)|SѯLa 1%~jUӡ1lP abw'6遑qQY;qd tTZlq/\t6'4qa%4bf g,> zǝcdD r͍Q y,̱H=Ff`lv09`s !L"RM+Eazmu7:l8bR0iúqm е="5!mzGDs96^1L{x(8RqcuI{.)֞98v2,B5B/ AޱM5Y5ECT_27L'q0웿zwDR>~{n=EDׯ#kuwMM&'~x gys6O!ڪ?m; M2NV; =z\czߜ}Jckię Y+)YLRYu%[ ]pbL Qf1e奼'2bW$0uu,J"C,C|0< @)\QxGN15 p?;~Zz%DjKmйA|Za +Fudhvkud*5zRx3XcFyfsp&ґ-'e;T%r492}wm)9%VV(mҎX+&PP֬unk *µu@?Oα#~^q6!<1K`H}gG fl}4s,8o"Ekk[ Mrzyq8&F.ch{/Fy c xQ<W [#}wPc;n&u|sWќ6lh~uA_TW4]u>^m*Ǹ ejcH7=LE<r&Qc]sCvvۛ ~~~-l W/`jQbjd3޸:lJ/ SnGݜdžԴ8a?_" χHy[x:^5|Y,c^ϼNr7m0Ԣ9:O Zh&ژ۾îOc䤯umMk@XepDYhn+x >i1p m8z2Xz|$BonE%log]'~g]og 4 ^q'g|D0'>Yo{}_G}ğ~~/~_m077} 970ES[jP3 ]7]D-!\ػ! /%e(Q,~@$Bq+^/d9CƠMe39L}{Cn4mBqG?6(}Dk;(6賮05_.uhi}/7ĝ"昭O ۸O0LnPvܚV fT&p&֬}9!kQ5S)ڬ7p}sO3%B# 8N_x>& x9`w W`׋ c@A7@f)o$ʍesXڵ5JW\$1Ok;]XEC֙'Y` (5<{ IDATfQCH XHs_m)dqţj5wա7rb: z VI)Ƅ!s} `l5BmS+c 0Ϫ1NA^:U#lWVmc ?8]CL*n.728ypo ]r1d=A=7Uz_חW\a~;;zlp Ϗphحu[ןϹ>ח}ً_Ty2js!/4CcxšyFjuVLUAhO7ԧ_K?=yq{0ֳ\lzpc퍿t}}ݣ6Fq_ F߱zΣQ& :5(!Mk,#GdaXp\KV. !f]w |zI%k.q7vCrHՎkog}b6yxXKgs0 SLc5ǁ_uV#ԇCl3 ~gSOk&|Ԣv*1OE>kX0L׽?b_ܶruụj('~- O6ܘ]YuucHlv ]۬ISY   øs ˡ:0eN3!j$a"62FKx_`'Dyl W{n_LA3H '?sk׮Fpxͺ^ erR !2s ufKWs`o0m4 ɑݦW140i"Ipȁgl 5GDq#6`,mbD6ztjD;lʠ}1 7cycQ^2Ǥ#3$GiF̞;b G9l`Oyf|YM͊3l\hum\- Ȳt֩l‘ 4}Zx#r*c8GS? + mư~畱}GZ2/48o71_%^ES;1h􍕋b^Ml:Lp $d9~R8SedDZ{ғ@7 9r[Wٸe}&CC}'á\ d2)lT-1ό$;}<ѝ>XhV>[?|%΍EKFE?: gӛ>%?ׄƅJƾ F%71nA9|Lh+֌ 3c~$B.0}: o UKX'Ʊ~RV~^scAo>₽="c""o}|w_ٟY߃|FZn19cܴzS?K~E;^K,87z&gh(7psnjJڙ|&&P3?%o/vTCϺ>w}s?zӞ(ivVjdVG6砉d^?T׮'?{3)<,;s S`f0q#;bx!;4q( 4!&זC`҈$Yz f9t<ѽx8#[Nz`5%cCt{CT zvy{Á  'YtiWtvz{ I_B"3ؑ2 pveyᑵJm]G#+:u-+ 㩏qq#d-R~x<=! 97I <E'F6YUI29T=tZXs)?j70͵sZF5@X]PAm[5Z@KnC ⁷8o k&s@C4s1֜շީjR 3~$cu;>aV-sufBP5/|⚉Vb!HK]/x WqBF;ۤv36_S+&fQKr28WX#M!dL9Q40񵼚XZ!n)hirTkyr Sx`c"`ozZLA}$t%cEiSN5kh7u @jnom{sl=Y%?~rMeo)$bϢ9)n<lC^?yX:LR}ahO/uwI* <6@]XRq)qI8_/\П?}G۾[qwm%^/)lSCpj3^o='\ Oz􇮯^=p x}_ޱGp+!rUE%8\ܗϓg>ʟ[Z56w}=]'|&^#c=a< fG.A^|}۷}nADM<ϸ25ʍOb?Trl?qxcmFĜKy[}>|Ӹa;co9'zsv%4̘3H8"C|sjcK6FK. ޸<~'!JLz^-'6+`l._d_2F_XLz8)%ck'Ǯ/(:.XbxƵ %{PI\}%S/у! ( ۈmp=~Ƶ>v%h9(7aW|@r )棾kT]t6bͷk"m--B(@~)Q-Vx<"5)'xHC]̈ .Ym<kΑɣ\c}4 ~L>9,yhj.Hq@9n}rD驱 $2H"9.¬kc@|}u:RrZ6-b=k8[Ǽ; 3up5|V'6[&Cd͸%QOkָe7ܻ:l\Ors!66N'#;_KnxaBpQ8fakiljdƺپ3;ֳBU_y-RfcwLr 1,cuj }|#u_ )ֿ>,OީY$3a+e9Î1?ͣK !/S C\ڹ0S9.Wz )Ts%Gl`\9 p4Lܼ j\;8 9v1ӗD/ǗSlcOil}b/ rL m M)fވcgs.^^__w}>|nν'?Rrʩi:!pkiϝ7>'|9?\__r/?ף9X\ܵ|ރLEﵻٵI <=y"ȥW!kll]'[o[&1{^'N,ֵyQǫa6]&q](l[*T8yJYJKkol:Pƌ?  @QJ,-L>iAHذOUS&kRJ\@~ud o3fXζLX_؇mwέ+Hm6jew{ m L1"Y]R(qU&YV~A#3,qjlr#׾/䮋<z[ 67^?'aÛ|NY 6dݴ$炚ڏm3wHzp,vW 8ߏu&XiS:V-a3XnE\:8)t7DVqgG 69cuqRVޔ|&/ig!V;GIl'{C9mxE1;q qGvC6~Ӛ`1#ɫ_MO֫/@uux-z^bUpjlz'iD5@ [4{h^9v5Cfn9Ei clKŻ_txO䂷\^0 |FX:-^`A a,z"v 9IՓCuD!{} ]dăK__)O}=]zr\ @?mqSg0>sz+-%/y-w-]w>֜\vx眯]tC-ܡwq=߸^y{{>ɾ!oh>gn5ΧK^_}~׾Z7lUF |x.K\A|MD/)58Ib8;-L\7(8< ; u+Y7|1Ƨ=I?pp0r Cj}j˞yQ[3֒ڥ0sKh(m=aRU}sޚ؆4܄qp}f櫯oo]/__YDbG??Y%I>LN~h3 4#Ɉ k8 b\S">. /?etIF?&WJL&^8 o~y>=<=zFƝ|P2t%{x> >t˅NG%I|F`"BzathLyQX {reDf#79M`uԱID|nݶwFz$o4HN&f9\7eyaEm6\bJ< IgB:N*lsDd9?)p%k3DMʝvu5eB o?1N" C+rCkEDycL\ 1[>H̺kyM֠0 d9{y;%"gc'l~XZ}5COέ;˦ PkC cR=sF3j[*[]y"_6 20+)xĩk:"Վqc_qjZ3:6D\O!vWWn ›i5񨟛 95 ~Pw)vi`!/!^>S1 Ftti AZ $7}RS@oi =48~I#Hb";uKu0s@1nӃ%/v"GjGf]lAjZtK~t$t:,׿ɟ z+~O}8moq/rwnT~ >zޟS[ pՃS2+'G>skRFୱly]?g/?c<i׽:O(͏hư8X:rI0LvI9 J0|751dGf_|X^>vğO m~{ Ck >*Oиcǥ0\ؼ(EJ{Rȍ'+i,\]-[Ԍަ ؔ pS#MK RdF, =X,KlT–u6fNHC=d "Sp3p<6>ݒq:Z%@a ģKTS\pT'/|l K[ 0Q1~ b82M-&H #. bhz,RkC6E4%W(iWIrrI+h;9K9:+ј(ic \θAgƌ9] qgfד;ÿ@'_^.zAoܽ2f!n>KV;|5Ǒ ' 6S>s4OᕽA­ڝo1Fi5\(GR؇ jQ 1`8&~ Wjh'f ]Zy$cűl Q'5gFXI - suAe0O\4/V`e?F $7C@~8n~!!n}7ѥO p,;.2ĭcm ' +ݰ\w5IhuzxJ0w]ߡQsO$J4M0}2f as53ґ4`Ug,|N 7`oF{g\̗Hp0Itx.{ܱ}X7nn}/fjrrCМbZ =t `n!?j=qBRK*_DlcpJ~䳨 Q@%Y= 7~JcG]C㚩i(8=~R-H#ʂUw'}/ u$u BS۳dZ?hc?L'BH0RG<ѴxA_}z T[,|Mۨ9ܕj>8HZ4__Pwc v_#Z1Qc|̕t |bhΘg0fCdSLxnxH閘KPT0Fb$?Z12Vw\X+leb~~q:u ^Әihn#ckP̶99kj2>yװX:J%ByF^cM >\s UO͡0[sa̼8H]|/nbf=6X~h`pj&WtHDPr642N=w֑kD-=koFjW cBĈR}tD5ưXq 7y8?nlr̝S UAeobz&-3uW)a'h{ 씍/n-c@dzbhm UY ?:cXk\1$P,v*0Zp(7p.bR.eVk>3.őS!yʥy;CɰvK^CC}{Ƨɤc\<*dN:<{?j\鉃_ 8VvGrg{Qѯz|M*Vn],rs}k7s 5Gia~;^ *jjw`^!7ǖ֛qp8.Ŷሡ8DyO2_6iyFcfIHy7 Eemm'oT#tƊ>S/GfÃ^P C,(#ֱKm-q̏AQ:ha;N'Ii3-{PRB޹îMՐҘϹ>s(&ݑRwYu>Cx/B?NN9p_|ov}|){'[T#&ᘖCͼf2qM8Q{=)u}7_[ۯ゙Ͻ>St?So P6652!\1ꧯAM.׾u?ﺾz_:/t&K`S\f8Rcx81"1.݃yL9-Lc;bZrve] -={25jj%choX"̝ g;i&/yIlb1S<Mm}mW1LFޗ v ΜdkD5(֩F`|au~Cn|慪}Gc8{LY蹪k&,_2N_lmZveYE1("ɜzq㍚.P=~#Î<7O$ P/C!HenMD:g-[7Ao&G?懯~~z3??~QN=`m-%| qOz׻;] YiדxQ Sm3*N{gaZ#G8UznL~WzW?3_ =ǹ7ɥݱ{ J -qX5^/{c'i2 :]Di=ٳŗ!0Pxcrcܖv]6S"cO;ψx;k:֒gVƭY:*Ln@f}w,EqM!tLhq=z1(~Uj6}C NN;݂q8F\/d0asBJ"^/};Gm9ɐ>BfX`)k0t,=]>uFOP9$Cfȭ7 L ۾$xP?{)A[5(xڜ:iquvInǩr Ry`:4W&6hip(5D2j哾J+d%7hC}LD)=g\'RrwCM"*#QY-YrE.ƞJ1s茈d>zp-"0w=ۿgӹ& n[qG1AiνyƮ=C/.jkׯI2Mo%996Ĭ#jg,y FNgqݛa8FƧ/ o)n/1(J1ABΛGbӘt+Yad_Y$#>ۚ,¬'k_Hi r%\OlcWPSC)~Aұ:[y: ٘ ~]ϽYt䌁F(7>ȏ+ϻhp_54*}h# f3Ƿ;u: =[0[rM?=s}?Cg= x Gg^.Tޝj \B:M^ȸ4yO cwsWܐt~>׺qPC^/џ~>>G/P<\qVaNg ;|զ= ͽTwsbnXdyX[]/~7\f% J'6q`2,QL$!#[o.`@ SҤ5Ms(r.U'l>w- r A4WMȑ8717ib% xwt0܎z#u S 70<5@nqܼl鰰_c~]ecn|[?d6Ob_fo+G]ÓiL׺`҄dsP1n/bi BԹPapLo>-io=M$ozyk *`֛zObT;vWƋ1 _c\C6u͉1V~3&`1_~C< }`<&_HŭSglptsTԯ0`A_nt_95sUn9X7l|'P;@וѶ5t3sFKx!c/ [S6$&xwUG9 ڟl px '4{`$G'"#U$}5,ibR88t26_OCB}ՂZ`1A֏FǸr໻ҧꙠ{ME Β>A-}!ƓKo xy_X٧CS9}mca"}9ŕ{j;J̜uygJ=$`F{nCVj6;eijjvVsk] 5U : {sư,6pٗ3|K5zH& )b(/{#8)e-ykƮE W, Ok#7狢kO㺓$ WS5x|{^^NI/45| T5M|pS/7n{/ %3 _/RHp|ccѲ| Or{孯<}>1MA<̟ٟ?<~͏}ӀѾ5s|莁k/mNE=ک+]ߊ:O͟/t#__O|<fSml8G}4`3:_y<-y"Û\?_{{Oi➛Z'y50+s3 B~q?y\"+[xʪp25hmjvח!i8͜'>',6\k!m6"a/oIK"@t,րqGװHn4/n9vj4GSڼ@*s > !<9}PNF:=6O+12%[믞x˿P $)-h 1aY>Xz]K"Y?m9龆߳xnӹ60@3KzY+Ҙ|ϣ)9=s9ӱ> A pw ]9A)x -隿{羟t˔0N,I맜}T5.GͿ`KS335<cf7$o/<2ڠi 7}]9?sEiASXh"k?É[(=f<[7\e[N'W/>m>5[PcVԡ6{MJFy`cYiΓY޼ 2&U,61Jrov-vb)0^' 6h|s B3~^|<.?}?w>~}_~BFf}O?&?!7`ubXr3![E ?#-o{3?xSoeH[e|\eM׸ӋX;`~]79<ǟ?zWuï`{n|܈as_٣CNqeVN k#qӐ.tCe08Zi*@ZnbR3{vL_#g|XXʜweB؜֐}_Մ]P/=鰺GSO?Cj{퐇N^g'kϞ8:&ԃYxc#wqgXxA% sS5]S mEvL(XĊу\9CE>/G'o~l-h{œbG??|ƅ &%ig}ΡuTa岞iGd|\Wu^nh`ulꪘ_*h8xdtfGk93j1EY˱h}BvOMmd筵_!8+ 07,/&hgoƴ!߾m'zmN B/3k#}fxVqj ߼M"a ;ܣw=-Hk!s ځ/v)osTeSl}Z:CU4\p7\6y ,CRE&/̀'c`^NHa_3WbMP36S}g`bkKM] z̞jY#eMӸB FtqfY{0>/ EkZ}#Ʋf$'ksuL쵟d2]k8r:إmTBŏp W^}';_ubڔT׃? r/KnESzv|^M MʮaLSO}"A_>/ǻ}C?eC60rMyǔ`k3 #KKݏ/C?|?VO߹OՍw^I5'z7#lۛR)3<J[_ny{`w/;gE9\@U;og$&QS(㕓>1zMZyJx޺֙`fC}Lxz$ic`11t(؋ 攅K{aiZPz3Mi uwpsc:-xqMM9|ؘ}g>Ȉ}heFM?vBÑ^<2qh.O[kfOv/Mc;;6V&i}ZS$ڒ$ZI^̮Cݍr| dC Gnlo4@a@Rld=0`p ?);}|9f^"yDzسvo&х1Wu ZGgX#r'c5Hk!#Q3=s.ugfe17̞Q.r[Tb~^*#ft078[AUK5;x;&L#r0\n k{z=̅BwQ=ы-ЖvU|4K#Ѧm;9ɸfp1ZdZ:}ph:;xcݲ'lj/ };9 l~ګ<W}N?BICUS7ڡfv~:d1zc}t&"ya4鹳_!rcss>Q(S#j=kJ{.sʼfSzS) ی?15ɛ`okO~|<:f zW7w~l!Ŕcresz?1ɣQ tNf|? YHM<$g!(_o?Iɏ//?ǯCY[_ڨiQ(33Za>w?kw{{sڇ5y`yyS=d;|\FH9W p:ϐE{9v:;v .9YL_D ZVchRG(޷ O~%|淜sHM7$Y>Jp|Ni^XK49&EOQp$6I29bQȡq$~^!M#?!r`y;c$䜯BLG2A9D rR+̌>ǰ^>ptڱb?hkmAqsBzXM.Ķ3Q4OcPYt3 Yמ>'Wi?Tknkvg>L׶/~U7Nzd)ThsR8Z65Sk8b0l zsOꂂ|<c)17gM ɹaZޤ&ѳ. kz2c1{F=5C1h_>Ǻ? ZϻFjDNZ%}Rzm=ws_$b${ѵw^>f;Ck9?]ϋ7bp?lT+g·^A ެM.js03yTx/d !/#G/&s K`[r;Z,[sl7l2x~:aC @?*"m566bFj1]k1<q8x;k 278aKo R}M/hrb?ڕ"=}971rrF4c#}apU45 hu 1`ZW.C"iwr9q槟f7f=!!ԫ gIr OHXꆴv?;`b ݄zb?OGDΣYtV[`(t]t $koAوu) y0u;&EyAGU,W6M[ѓ}8 IDATh@Iu4 ie7:nQڕ۽AsFgvR%jl[Zqۨ ytw,s=5+8Ȭ\][sɇnS qX,S̘ 9mX͓\n<{D]rכϟ0edl} {b,;;?t5| 5DL^(YIɇ0~u;`h+p?!k|x=!Z# 22W{Z+vTh>y~w&`b1qpy';~ǿ??گg|oTyAvjfzD$\x{~o??|!7u-?N"$mU jqQlֹCCX}$כqN:&^G" n5'5 \ 6w<<>n-#x:@Ubs:UzK<(f[/ ׼$%DQCk@pm@E #.<F*_ssT/Z*#ü5cLvş_!Zu/,R:unK&6ˬb2Ѭ 팇-?۶؋ԂF'lcc~4Vs'%^Q^`&ܴ+"Vބ) 2Qb-Çn{C#6+i$۝c7ND>UGkxz-ao`䚽dC*˪aܮb1v}㢀Bӝ0 >>f-=OqoqnEjy)Mq}>!p&fQԀJS(5J!fCt\ܸrϯ{`Xeh˃fmF#|q /ѐǑy<9҅ t.|2Y+| `[o5pzxz 1vӜ':c~ZU6:NuFo6yuCrh¦h9hCL/ě&Nn|$7s36kZǯ{O=~x/ǿINk"L=/Q]X3}k?|ϏmK+_4]ɝ렭ܗO~=ppo0v9|{>د=3٭`4esP$rs;`Fwӗb@\8w،',:5rMk O"&e%{5ɱ-d :wAoxG7IOGoX[2tⱼџ%İ{1^atxLj۾y}Țws[>ܰt}kԘ<9_, g{fl< 0_XCg6D)xh:T讅УJ6q./[9 [=zMxa6sj3ñu"&Ǵv1stkd&^s9LTɚOAiߑO!xm&!_7 ᖯxg/nⰥ58|&]p|>y:x-Z;-Xp(` ŧjz8s-eb iWalfra뀦r7ONbe/8|k6I R|7FouYdnRn 8,M_8λz//|O#&hGEy}U}=K{&@)."Yyy_P/$;9 |ow?~.>sc熄><&ߟ;~3?it<vIK߭~?>#?Wx!&JYq:mg/DD$Izf mꄀ8j72.dSBNs]i=|dB]|I|ÿ@8\ {zcDڂq.&.c `-A0ѥl:6&X'E6;%q손;cr0:X#ɻaKhd+[\p cYt1n?'R'}B - z{1HY'z9meDw0 n& ~rWU]zrQ6gul\ө1ڭ C=aD;LfnrL<;^Ʌ&ǯzM<ݚ_su^yհ4vtmHv>:WՂy#6Cb-cJch{%|n{wnha^a8<bwtϗ!OƔԓutX{4bO<\S"~2:xQY-n<ƅg2<ܬ}n\\"X6_gHfO@^ڝzek͓<ƌp lA?aE{"dM(󂄓,9ɫ7yEEpg02Xw,́򎽾^,yH@XW5AgM$ՃCαhn[ɽ>a{{!X~C}"[3> \ZWb}JMn S=^9GbkcO/YG-Xp+|1}!]r4FvW?z4r7(k_~|9sc&>Ao?_gM.p7p%oS#ή9/9geO2n5ce6> HLs&/zd]=86dƉ/+&~ f B{xq[|bGYEx?Vl2u?l I'|G#1 &_s?@k> [։M S; 7]4;MOC`:!'1ps[)JPW&Аd'^.gFa/z>W8ZHo?9KM$o C WcH|#Dگ/(ьFyL,Y˘:d &$ı! @lڴL^6+6能诶[DKQooc6q7'?8!8yp|Ω<7|AaVLɳX?HxÎp\ND_Տښ ۼt4 dFY䭻ζ}!hlZ֜O ys5ceGWy=4>{06އc:7w ^.I h"Bż1,z "xǐgD蹞Ķa4j{^4 @V3_.o'KsSG;'p;<ۙW䏗 -w/ٗP<ן$-@yl=}^lI hr:Lc e5Q]@Crbz8:7jk|k))iԑ;-ZoߺȖ}k"61koѨ$:/Ch>6r73ҁF 9õ*$_hph0=I{~l6M|kumn̹B .d$5Z$:(5q͞|a\Emqt\07r4h$&26Ǣ λs^mhue+=PFt?2ih`r`cpp9DI= dzJdXF 6}ǵ.njE'o^[術͕4(}}¯ w|t$$Nɵ~Mc?_z_ޟpٟ[ڢ?5'R)87C:}4)!37^gtdAշOƝ: g_zobcaP3^}{C=r'us/s?LPL&FcŒaĘSf_ά7LIU`mc E1 >Ff]pO:c#.~yfVw`ګ3I7N sԜQN6llz@ځiw73beǼbU6yu0Dtj p:><>W+<{S'\sn;\^VN _$wmwL5O'F)z8[ uŬ c.Ŧgq29a|-9R+35j}1>& :v-42aLu4sZt2[3V;Y'<,h7nǕ3`ѻӌT{.#kFcrا5|ym{&Xד&E:Eh>B[Dagf?y,=DkGSkLm0n}, hol$mњ8zThr';)aݣ(D/KkT^FW,0wǩ͓lr>Ke/5seXO/|?Co4zsFMHsQv>q웫r #dOBWEI3n䢔S<ڧ-$GK IDAT7eBij~m9BC Crz9(p&>8Gɯ6.p3O9{lw)=-'XHy: ⦙0B`ĕ]{l(6qXB;\eHӄ#A'y/7Z#1 `Fs:RN>G953KEo{`Ó{_xU?zMOO~?~?prq ־҃HU(,W r.akU *Pb|kFzs)Iqoy+-xt ?t2?|1ρ~+F:6M}[e[O#*u1 yX~m|zϛ̝s9`\xFm^GONϯ,z_#3iO4ys¢i~<7V37KV95xpԌA:|8~t"99W8dAcyZqNrƉb\֥=!K+3Rtxqʓ@%O5! '(4ܽ}0U&W9/ S6g ٘衡{L$ !9F~ 5;#5gǗ:x3qkMz3{? N>_,A[;2ۦEgw 6 NAi"{g:~ CbIO{Wܓ-I;&YKeNX{}yPY9_/J؇'/ʨ'f`=c Ox$ud'` ֏-)P ȥw/p4%4nG^Ѣ'^ff58Vh;%1q}!|k!V[.ڞ¢aG="A.>  etf+~WQ=qZ]m&FkN!0H ~ZހYxiď`:SV ʁN=ܹscNls/X`..m9V/91NKuGs d՟oO5Gh\z gTc,e{[Gи\l<ѿ6k~}o?>^X|ᮚs-=ao.q/Bs%SK)腄y D5Qn4~h&9pj)$q ܾ^\Q~K?XF[oP|aiﯟل>iXmϹ;9Qy'g?/aMRM7r{r4-u1<'9O}AzT8ɥ \b;318//8Xp2yɣ~N$&r!"ډP&?\1+7@qmJ",ـrDhd#:oaGp*Qp8S j Ƭu2TFw̯C,h`p=UGtq<=oNBd*3AZ:mp1s-#p56ϻ03ϱnB,uغ5|QoZL:z0=ē.c#z0MƲuYK123u{ TSvK6:Uf-15Y3,j.&fIdsu]Hm&E{/[)C~rk̺dO9# 1gÜFNRl=@4Nw؅W9#qN6?7:聏k8'qh._{|1B.m=5JX&X ?M]<? Z>!DsXB;cߐMHͩ=7o9<}A1n~9^l} G :>D6^3[Ϋoj:?sUrO3s>AW^u81.}!Dmr&7 ",|2@s[Ez(5k5~:\ozCdiM^tRP^ux̉/k>5?Üۗ3uMemuk:[&h?H?";flUy>[#j4ub&O__'PaBac-b;o?߲&O^__ χ W6}\d(wKk Ϻ~껼7>|_|,}KdQi'= C F_jqP)72߬/>yut~&Ǡ{:G7aXrGN5|ӲZ=smban+,GyCz}$\8z:Vԉf9dMkB G`y^,cv `]o3_l8w ӌ(wbkb#\FϓGcVퟘ`gc9=?= syLucڛ5M-նƖ^`I-1y{z: F-Xj;Tv//焑f/\1? '/pOs2j-ኢF8ב -p9 1{i|t=wsZ0W1uaܑU5G̡ϙ|h/S?qFBvd@Sdl'-f z[K>6Dr>V'.׿ЋgӜӛk'hL85<}AP>|H0ؑo;p\nj}looV9ئP= [9iN,~5xM 2haM?JV衲Ɯ?#mg(!e;F9]4u£M5kr$W@|Px;q^C2ְO|01,C҇⢇άiԯi.!uG.ޯr?H_ z =fg}emKO xy>+~*ɵr 807m:Ӿ6Cs#Pv|p =Rp)8y}Yk$Vx@qVSff!`[uş74pMQ2S|" =`58>@ k:s('keU\WE8 pDua63AʣpVdԀo 013M& x{!+=IÔǚ٩qb[Ep&Rp*Pa`.a3CqKD\h ͈>sv" 8Zp*I/Nv e܁> iI:fl&grޢ9c1Gg9d۞Pcbq6kc0EW;HC }|wdȉ8@'CW^O\_97E.$4ңe6$0 |bگ$/7F[rnbYb5lLLsOfJY˝CG4m񚭑ZG9YŴ_^s| 5a'rv6Vf]nqb5*Z:緾r“k:݋6Zݣ" rt)Uf 6@.b`h~l+My4ͨ]CilLsmz` ˇc`g^^lp xBa(9jށ[+QE]o=cymBӹ5yo7}Ԛ&g3:"K;MYZm?i7%Fm(kD'_XNojlN{7 _mR}|;y?u_?PlPгSPܝua}edJ3oMI( ch>RbcW;Hv3EM_+:w\xJLe@_s|ĉ 6 !{,̇Ғ;aO7p"5kAkRS Հ2zćK"cBؒ|=5$=euGk =FE g}cˈiÚ|ooFGH;ZL#.S6Ks>R[_ `'\B_=|w}{=~~/ſӺKxU웥DFkeSw$ůrϐyP)( OGb^%c8׸OF I| 1`lwhx# wK&.&>Py^iFw"DN{mf7Jc7,9דBB]iL.*ls!хtt&u~zZГ4{[hHehH-O.Ǩ#Z^n4D5fqHB"۱'/[v&l/۳m7xf~K_qPoH*k%u莽(@wFGF4.rnSP7E&yKH\ko桔J> vKyqcm=p]K'SFyvB"[bT|{lfg5jBs`18ʼn:74m涠IMIЦ(o&("8. ,kA6Vͣ٥L区=Tn^gyv5Xۋ1" Ԅ\q-yێ!~V\gs^ Zs-^I"mحŜӗ<8Dx>[Ěc4aA*n5fx 3i% `H t֡,o~>A<D{.ho\u2uA4oXt7->-]v5!G؛gn#1oşSKu(OuL-U ywD;ج4fp <3U%71 P׮\`3vnPQߢ@l^˶5Ozglրqa*8f0u&OJsm_B5|ΒXcBOҌc@PV" 59Ϲ"SQeqMpiqy;5kM9֘|c1,!{ I l6JtfK ,Io_c1C̨= ްOzy[+:5SՉ&f=&4 oH8)y/Gp]4gEf|Ԥ! z\6$BH|Leњf%L.|rӈ/ORkչ_J5N~nu>tф> {*+9oy?wy;?c?_E_~nrnIK w?`G'm֜ި~ gd֎ M8+po j4ǧnS{5xrk$qN YG5±:3&]fK!0cuh8/u1@ fLn1ّqΛp@w][؃xB~-:]v4lW!v^k ,щCc:,=9ƦʞD|U?^_vMv_{XdBw@uunг y1-g'MQ*J{/G_nDpFN7vACu8 O5U} wL;eNꉃBz 28wkr!vCρsejRlMjkq׉f|,%c =2 }bjM1<'61ij&fS轜 ̈́C @U/y%b2+pdʹ9SMAN' )z}k؛/T&pǬS{ɱy?L΍pon3"k<3t~H BIshMH")N 5vء&/vLD6ͶqQ426xXuoC:6'n3t}>9#ԡ?p.ok㸑}8cm8u}0N>ꐚo}7a?O8~JI0o%utO y"A >~p&6/S|CkMl W `,ߺb1iۤsze< lc,H,~! k>SYg£c܀MXg`fjum.Ϧ8 堊YBA!=;?2Ӽ#<Т7/uz0!X9T`_jr$Pf*C IDATZNY0~A!ϑ\"A8|=϶^W`bw0h(ɝ|EFnҤby͸D&JlHc[o2q(ZI)mQC=y\_@++&H߸Myfi y s7!^v`0L5|GpacC+fSc7BЀ/MX0'nVO(c>ý0@ =oOs~ a 9V^ Iw~ETF:7_OCA}ï=?=>S>7 ΍=|;_?ԾuW__oӇ衜š9XrudʕJ_@퀜šk7ϡaO>kz0ygjznoe h3}[{m~lN=sWb9Ve.ip>66>XLv>Jƕ4|Ps:mo HqAdeǛRoy5wujym$K[Ы٢]`Ms8vx!>}cs5aj#DGs8 -!5%5N˲v@ȯzYۏ `|I`?B0z?qba;֐o0`wa7/Ynn4Z/tJ)T?|/I1  yyQv4`@fae k=^&a DC \f]{(aO&+D/X\' aI`4؛ot2op4\ ykjdZVg\.BN/zaES~n==̓\vH'}浟ҦW$q= fP?&snFgBH6$47{9!ۯW{->cn5AGѸY\ 2=[l[{h'rNLbC;rD<`_mp`[c ?J,gF;`qzRǷ_–‹n:%כl"X'5)yєlCH/k.:2 ICG;ΨSICۺxV\☹&y{,h_]?_ǹ`&R>6O;6j^YAE!f9(.L Gc fп[:IP|aֵQ;ŸkR듞ʘ)xE4ؙ9w8yZWf _K*:|g2里~㨘pHp&2+^OU]bj\ZC5xoVCc<m;ns|4[{ uk߽kqz<?k v dP=7ִ6@ptx5\ovu}qq5H0-=̵.mŅ+u 7EvK}7{J;Qm mmIM"c4BGJ?0j6ml4!-_&6mhն203{ǻwqZ=]s_k8\y^gzތqkgsb_O>hiq7Y7G :䲭k͊[,r-C 2ckGw3߱7j {lЌ|$pd `yt׊ =-PUr?3J,}K%δkGh9#/ɏ14Gjz k-폝Uӭ|]@ ._f 'l&>]5^wxHȃʼG>&u8@19rb6El$떈A< =<FG8O HM~μ|~+? Sw&.ky}al;eI}q?k_F\Xw:cm+ ׃Uu`AM~׬}?D񆢞Ic(+#RήI1D[#&t͝3$[ᓵ?=52 0d/5!Xǭ@s=Z\FgSk!螌 kl&U9/>>QXh @:gc<…9ڵ^@frx~@%jHu՜8=#/Ss|o`iS Zml05p11BiSu %b<0a>;5'ٜh嗠mF>ПΓqr;wp.d˧5wg,z9fu h!JU]xe;N,e5\ bDV  6Fcw0== e&;$wa)X)es } Zc\8 8)%1#Cn[ر1BՖir8[(w{N %@6ˮ~Ws H&֍cHֹ}˂̭ QJs4u9{yɻ94۶6r^7 鸮1yn+, ?LJ BЛ1cVot9XsiX '`׊0qBq\ å[RY9Lrdg?{Ǒ5&Z|0n95QgN]q k-lCIJ4Iƍ/xso|%)Q2n8Wbtddd}R`9׈딠'V;r(0럀|o/ G?cb9`'?Da,3 9:EdR-uMgA䖛g$1F/=>$OZ3jΦel[8kCkY-9{Xc3_N7sZdʺI$ؖ`e)Dbc;"$ajꋱcҵL=e p 'Mĩ19iFuBT!pb5&)_.5fx|k'yKC~=!6} U[ۢsUBٳ?Gv7>hý.qad46gG3 xcd`MNґo{1vV!rLJ|5I |d͒ J sC}D6:qb!oG(i v >qRZp *߫0`C*" mtӜ@-_w{㍟YC0jAsĚO[9x~p=qwT40x|?6dW{bR%\"3Q  >^iW8\l|g (ꎼh~bX/e-vr>0aX'3ljo~VpLStN[MYb'11Y<ODn-t /MHD88Lgt~g٢fW:Uo1 #26\8!࢜'zEJX 64pt2+1G?,1:dcmB{[v`y1< 8{Ӆ3xkxp&q8?m> Uj躀q:̡O1"M>BK9h3>S?ι+Dz`xRFOɿ7֜8xiq?rpJQqD>}l $ե KiaeYSV_>xuuQ&/=T?XzLŃ\qCSj~k=[7>H}bňz1ZP.u <'tmZuG]{#lj(5upm{#Gz֝D߫k71E{n?xrX5N6I~Aɑe7o_7oꀅs۫z 鶹d_z]?}s5n+ʌJo"P73WнoR ,vXiN k.&ǜ$ ́2,vFX@v'\&9dq97 kuGSSb=Ociam'9[c`ܯ9V֔Zy8qMl 701#Eշ`l3"y "ɕȣc:)wa42cIN[k_'Etj.i1J k+ƴui*$/^z0+fY9AVs/ɥ恎s?DJ~Ũm棫P=5$p7S#y[+wxIJ%r3bSnEpEp.䑜\ONRvʰ5 E^"0u!0܍嵐{k&c]/=]dc`\7yq!WM[=9/&N&6\9-pR5@uCP G ;زw^&#{'1%rlwl$Q60/#.󅷸 a+yӆYpL+/8&kOw9]g].@DM-6H4u!$9ym#Sg+s S;ʀ'tWcd#m?I8,-^ >ajl;M9n};n ͵ drKX{AZ1l/P C#)g=yԗE4}~ ݿF 6bC^387cO̵,Z,#GMK=}dOsXć+kM gΗ46 >ثٍ3>cZϰ g:~bT٩&&\?cQỏe\ePۨDܬ%=?BM~Oz\>#cs@N8h^pFOnj 1j?d׭2Z;R ^g ൱$/߰>61_+ЦS8>{ʘï^ xÇ_EӚҢs1Rc<崯vCQU<2ۼlAc91%o5„1m aGnc7 U!Um3Mfq K>;>#jpm|YOr͹I88 ,͹smso8= ܺ;ZX]D1 բoj4+W y"%|坞hɍחffXQ|Ha\qϳ'nmȑW(G~6UA }Ro@ ea\ /00[qd\yGsq\QpZ0C_a޴F&DaLIa7b<4'Ǿ @QO@'&@xr j`r| N g{ ܈Mg @,0AbBAw8Rp(`',z^1^`cp~5 |!v<l|^3xI4QfbW`7rlNyHYI]fs,6;p܄L9mL\*6U ةv"B0M]cXX*Oc|,, ;#j=BMv޸m7 kh?ςĐ-`3u-{^Gb_I9X,00[p|u IDATcTt*sfph<Ÿ]妁{=<.Y%68>ެXƿ*JǹlÍ>>ֺY<򥗥D~Inss*zMl+<t N|3J=vf͌MQ%{-Hfzxy!c@x9Xcl^MZksol!@f50K톴ܜVjNP}XE\'O!ZANYSI9A\<=c'#:W].zso+Fd`0Z~ɗ~ITP|w<7] w}w^i17I$^KKtW5_u>ǭ#+7M'9hĜq½@oɓڰ\ʼsBDžF>ݫv~-@jZDCrd/Gx,(]R'%їw@g\_03uגs5ϑC8?K͚CXչG&|8% #9*^'$[T~ơ$JLT o`Y5h gcGrǖG8=Ś6vnh5%/u,`-gv0¶=t`5b?p`SSp>` >5F|ICH||'3& t[\`"O䫣3x,yH,;:oǾ<6|[rig4sY~*u>R ֢\Yp]5~cD|jV}e~hu WXvD0viC3 3O95 -.  ;b ¹*5L9?w+-u@(;AYJ|ul1:b6Hƾq&~9n,~uPO?˯i?MmZ99\~ۙ#zdZg=fO+-'vZpp..]Mh%ѷ!?`:l>+.+al{lB[P\_ NOvtA?iPϋx.?m4~'\O}$|-ѡ|#|tCf4yQ@,lc1v܀i"~8FoC!I1:b(vAyzp :nF7=圅]ǡg^%k^.>A$;_\_jW͢sWұ액.F&8@ 1 h]W 01&3 WᆊRA?~71ϩM]7~}{?˹ 4l`Ə>}}/}~_'=411oLΘ.d[Χ7;5{ ʒf&5"7gF!oHF[y^?ռ{_R [~M6=J>>~-HCٽ썭f3k$+>Y׋3qA<:>}:ٗs!k'ʆIrB?_keσe?q0gkC׋}}\aੇog嬹A^kavj6ORd}% uԐL&%*]Evρ5$flМkdlÃ1sͣJ cspT nN&1Ѷ/.~ vrO fV%ߜ@Lewkq?r¼7+964у7QY/ЀfEtKD9 Pj&%NZvůU7ܸc-%#nkaN 'ͣCH${ͪȘ#@xOM0ˣYgDqH-eoiꭊۿF/U1-f8-X{¥ʵ }j55F8 c)Sl,Egz Թ\<]8\/pb4u-cŠ,n^f:zV :_5rpڜ# }9FyӘpbZ(j5?,i<ȝZ/6&978Xbw k2Al5n|Ԋ \/X?1]$:BbADS:S8&ΰ{ Jd<g1b Nr/\S o2"x!J᮱;l 5Ǯ]+Gȉ)0Tź,ض2yT'". pmt wg4;p\<͞zజFF JXà<,PVJL}7^?~).d8?`uu {rs)S ~|>|_Y}kQy$`Wsmaz<2t\sdk ז4%D\de }+ ޷¢omEdk: hk`b-c{a/D މӸšk܇;hwOqMI1Yo0yn5p[wNaҞ;{iqVL͑Ӽb>Ŭ^,N'6sK]1ÅT׈KCڧX;Myl 7Nv)&נgkS]\ YM3uscw8]nq9SB'O1nf#{c06$sgGsN؎>~t9.[2"q6fW =:{ ʟ5 tȚ)%u|VS|xMNu1Wβ>/7WJ.Do&]&y-]1/Ih%Jfk(4DlZfӰ9|}$6B@82,79-ى}CH,kNnXqN 45QOl" @"zkc`: $LYO,duFf+;r 29qA1qZxO&2T."͛Q޴cے >-2T]ʜ\QL'Knw1| =j]n\دo!Bg,wPWҘ6F^]AF8us5ϝ;r OAMd>'lbGӱ8JF Ŧn*|S4`],+WOV .[ˍO䅍c E9{)8`1SA'%5dQ ~gt1Z7IzؕpL2룹̼7qirB@CD"kv!l< lOڝhƋ4Ԃq7'Ş4?lh,5$T%1mW*[o-G\1gԳV#Bg!;_%p5 ݛ4zAYexxs&΃L_'/ pu1~?=uB$,{rH| \!/xi0x3:,]aC VzW\!u! "sォj5_! ?ˈ$_v}}C)6*`fy;I7Xw3ZYr, 0%R 28v7@>E>c,/Y d]}-6Ǵ<0q|pU[t:P`3U_R'Y7We܅MH91NdtFvI~†؆̥ZĵU->8%Ss-x(Pxuݍ`?2:'/ gL!t&͑Űp{Q.D}0gT! %k;HD͢Q 8FʀɐBŞ9"\x2<  ֚1Ovp-z'˓s6F s|c_1Spiy LF,l_[ubAvKe1{ƃ@@[%1L7u^Χ .D8p䂏Pᜉ=?~Mȕq~?z7o4[{o=A1k%=%@U+.m5 ^͋h0Ȭ$MӦHKy֩{;#JO6\/Qgm-ȩk9T'>I,<|B9 t sYȫ5ꋥ`󆇉33x+!K.9M/q"pc5I,F=F>6h<|w`Bk=cQ>;~MԴTo> =Ɔ\Dq]Z>\i 8'~ yKcM8)FzxR~c;0Cӯ{0C}jvcjTߺ/HQ vC8ːIޏ؏^yom?_ Пܖ̼`gݿG?{V?E&\zP߂ڒc"srWo6?yC#|;j>9 ?@3Od}SAyn|Cs }jk$| U$kz26 cq"!=#[Rt|at\PX5:JG-t9ol眃|ubL *N{zYvo>:xOk-`}g VV o yL}F;/'@}Ey>u:9zqPͱGE=vös-?O՟'Z$-z*r]>R c M-5۶;c3Ijb1wZ$ϋ 8VDɍ_CYԏ(V }rV u%OS}-ca|0t'c&^c-YGmwFAz-ƪΧĥo\E(zaQy wvNŹCk,[: î:pZڝ_|W77O 3~1?4 b`_':$AEx $u.lLQOc Gdԗk| &87#OökysnǤu^Z⽛w͑I7ںNCI;7R.<6TꏈBe\ lp@~Ee;9.b &%uA|s>&`ЋpBmz&./qt\&.|-uRfCcL5 8ɬSnᑱi۞rS|g9䅑|ɤ1a0+`d7X^`O~]ejg1OPbC~ٯFG}d\lceX*i7oT3&pg DWGs)`mu yϽ~?S=yv<=\qV~[>1∉:C1& zX@4J֖| ƒao L}t.sY[U) VA_Rᰋ0zs8Ş{ \wԼzΞ^>Ndwze.Y9s/-=ymtXَ8(毙^*_Z]o,9sn20g#aF~6\̛EqύXl# <2j>g?"<&A!w΃Ȩ<{)$s62b,3{1A,&#o֣^OʯAvpazJ[,儜/Zl<}>35e ߴb^ΉvyhX1u>!<'eWdru"M\ב/s䃍Pb3B׆jMC3&N_wԷ?=[&уW)jc5$Dp}.>#FQ_]轢o^ +Sodj{Rq~4O9x(3P֋znHtF\ͤ fܹ8Ɲ5 ԭ̸r|21a4< ; 18dMg]amQy- ̛hb#[rp +r𽶥ϓP kjLPGXb^Z3e=Ƕ/$v&7pVkv}_XVqpomt.I 4M"S_?l:1Lo/??>~?ݾ7G>SyVø:~;~o(7PV i7 c3NVx's[ÿ: rf=T;29zTWVI/3gbS[9>]ëͩ~ٔ^Y3_؈ѓ% :4L9:7i9i/. )0K<-!<\5 Ȃq9R3{y\{bmpwh"x kg<*go>6 6׼1xƐ{۞dns?rH|{bFs8ǒ~qяk𘍭3 97>_cĮY'lSgt>?dGdm+MBy1cXYN@3bM:d)֞[7 8v 3XÆ|j=&CAԇ)mͥ%=s|8$}(|2~ל_OYwBVk9gcl<0<1?\wgP$] 1h"+xF`Ǽ怏'88_O7v!詠@gONB`EMKLMh\<Ibu?u޾W |6\~Ъfj9ćJqy\뼤 8G|j#,};v×ɠ '73>N<$vFp8NntQȍ5}׷'xo"YP3'2"x4է*W|{xuDIp1C{0;9\RN>ajMfؒcWC7&{-*_׼vEl^}Rɬuqy,I8 Qɟ]4G`Ԧ^,ؐ lfl!㓋q# r򏅎a8\W_9xͭ Mf8:?psr^j"f>8q#((exwUvw\hkZh9FnWa}` ~t.5%ہ #NBs!B27 #S@ z*Υ17\9bi~kGhE$}2o~Rj|vrCa3)$j zZR1ʛrp+ccC)+X k"ImQq-{vbym5Hgf,]|'~^jۂi?bh/ubWrHZE. 47ԝ7?m c7uZaJ캂m!¶ H sxs'O rLӾ)U0sn!u84B{`1.vg sTs'9?v Y.(t`I@: \(sD@Il?S?yӷ_~w 蘶a\Zo$My?o!ͪG #4|C??|I@z?_KYpo_/vqnp} PWE;#NM[o<'YCQ5ue—ֈV9 =銓Xc"uhs }=kBc5^j1ՖN&(kp=-c9֘9zjϹ'-=3P9w^w;s=w{U|#̦cs1',uF)XnvA쁼޷!J'WfӌB߬#_|N3ZQ.) Npk.ۣ_aFaޜ,sKeL% R"4m/h]86`]si&ET "ÑĖcXiĶExҵw5y鋶j#a o'¶6p\|ٖ1H 0nqJPp}FO~m9`c3?u#d!4y oM^'W1MȞC.&dPƪD? ~/ۺ"N1\6+g dLdޑh crYCl)k8MO,$ zID.{ǸxK5!B\kƾc9MQZc/A;bzv NՖZ\248ZF4i`[1']eg,D|7pO,qBiagGxOh)Uq??C4aWP:Zclwe =h_DB :ōSS࿷ k~QhmR\=v_p 4~ƕ,S\j /BT8D> @2B ~˷s߫ׯcΧ? Kqȣt19.yLV1͛߼?_޾;^x'}BQ+Ѹg oqjnȹ<${ê?p.Qbcݴ1Bߴh)CN5$S|E9X+[|=yoȁ-\Cd,6K6t>/L7@[=B^2賯91th|}/ +;+x9=zC?o{k_YnQ??Ol;wb}Z&yCiiY7b"#*cFAOqkWcChpf>anmqk}2ONVfꄜ~֎~ UmOٸKmWaE98x3R; Ԏc[9HJL4w^QE.é"k:־}.{wu4zRvX3bn,f{Ή'%ķel=demGb$K{}[k,싑9 FX ȃsۡrhL>"wIP9._/~o1a}抰([sxd=+5$ mY_$Bʥ!܁nٙ 0/O;f$XIvmp|Ԛzm#XnIirjq7řK76pVv .VG`ISGLKP^-#!zF$[cL#bbYCI6 ש15^Ű!r]N]U[Dcig1Z\ TvvCĊ8ƳC6!0M=<`( ;<6Fڌ0Pdv_Aʶʑ8mX\xrU=G x3:l'ҔƍX(WōũQ~ Ety!InAB8Cip[C:]|:T}߮}c#|b53zScVL0n歀As)?Iil&Qx{t l I 3E䗰slMFNy7ZS ziQ9ⅮfP ζܜ 'X?p 3>aZy.W7s 5@kNv'- Ƃ!D/9v9I FQDy{0xa@縀Aa7Q2؎1FT$WYH޺~gB4Cl8|ʱyՆ kD#ӃgM{Lwd/]l%kUĵմ)C IDATcb&X`D,Eټ0Xg&r3Ɣ)֙׆n+=8H 7O1]~~n˷w}Zԯ[ 5JRIg3>ox_EI?'JBkHB`'^۪6)$_L>7Hc1sYTeOJ62v|t|-#r:ߠRo\+8'<\azo7d055N Y{I克1`t3v=V瀄O$ a>\MLiW{>x5 Gv6OlmPmjm%lh/, ͕a8y,d~A*,rwq] "BA0Dsvl'nu'l# ZLh ۵+0 6築cU1)WGaK|GԾSBt*/%ث?\=ZNhN/p $s>A,AYƫO]^K{^@rb'arA^4O1,YsM@M}*_ :>&S7z5cM҄'N:|χ9xXb7>F&^冭 אMp&p=,x= R>5c𛼛}fM˙> #B67 2:8F6~ʅ{k7򻯗t\sn3#;_T8WG0F4([Жi6ڧUS';xbykUDz}t٫dJ25 9(퓂5$l/ ;;G+ym7⒜!?i8*,/F+,ml|%@cly7yAZ%ܬƗ_C7uD/Cc+nuRgoI{OI-+Fu-sB.~eʋ&7MQvzfL])Gozp7v|i2 5읎19l'҈D&qw5DMh6a,Y7r¥7U|^kn M=*#ړ wW @nj0qGoou_u{w>DT##ƣoܾ6%2|!`q!q ٖS8+ `\@c9HxVޞ^ϣn\O@ŗ9a^ƵIv 3Ec֠: Ů?X̝kI[# &EVo9kq{LJ;3-]`L1^!%c+ f+~XH6/lXyOs8:ђ[9we1̃0s2o 3f$9bE u3n {WBSb\WE&Uڬxfk!+VwKLQ A ֜5".Yd avwra|_HMP$ kW]do܉=j~1=[ P樝hy3\G$Fo5;֨v 8[85wF!Zs϶G-GD߮2Sk;|F³Q ּ,Z9f^QM3KrA2@<6 8`l9Mn3o Ii/L3gXgT{'riH坸mPtsA l@Ā4cbGCGGQtor[j/GeDm`Oo $5Ǟ`06d1'/1 &:cDh)5/tٍӈSiByR44NLl9&|Siu8|\!b;)W|n:M0pr"uTf05+c|r* 9%X'@ 9c>ۅ?8NLY>ܔWtE+K<ƅ%G(H;@Kж7r4]|泮75|}50w%(9ҵI4IjR_ѿ> y%h{hT&l)B~VbX[rٟRa|m ޭ3˥ywy4E%.!<ܲIiܶK9+>Z`1yUW#2I51Rk00j4 [DUT B91dұ F6AEm| Bk4[Gg5C]{Eضֻd'hbA- @\os]TAqmFz@b5OܚF&+Iz0O<b{/xaLк5 k1Ġ #~b)J6A%pq69 uIzcgC@̌a}2qݭ}sl|B| mVե~x4\>ŋA=kГc5rC䙇wvJܾLyl68;l*Wsnn4X'6>Kz;7BS,3=F2h1|8S0K'N8B_(~>B5A> ZLM 8l$Rfv{>9wa@a44[5'm4xs'9ޭŃ-a|ccuY#Ĕ^ê&HЗfֺfW :jy@CW𱽫qG&I҃h `#ӨO~:qMQk7_$٧kmٞ1!w;Em9;}r8މ=dX:F1, n ޘ|ӆϤ,4\*7MCd\7N igE.ƹ[816|+?JlA[;,^Bo{>؁a*{l?5iDщ@e΃^49PM#Yx{ uq ӟrNBt߈XyVZuԆ֞[ҷ3c\&3_ړN#m vfm+s>vr4>=us=_@kNƓP']|{@77$ CFfy?$kACg")t}ؿze v |6_q_~_n(*/^E|4%Ub`ؚjCcJ(̍)uxڎYw!^ 648(8yT5#z^j"ۈ~98'ro'j΁`Gl=Gb0aةQNV6땳v&,ƿY1qO֝4v/ Ij[UGàImFEٌ'G9y>@kSyho0o*Z37 α& _ 3Ll.hlg^Ki|Q*ds"̓kABw%_ΧPx !o YB>,S]rү$߯xu-oywg__0dn]z?zy/@z#d7__~ 9HEl|w}eLݲv|}#vB^ެDj8w#|+>]CߤB䊎ReCB 51Sb'lzs[\F}]+с?l_ͫWjfs_ίkͧԎW{}_zf^6hpaYr{&$}vٲ'#9l?fN+T uv-"$vnb]Gt gz`oō&cpkY sl-L@95PN>^XWxփ'e h- 2&_>cu2ss>`Xٮ<=?oЯ47Gro1O^o~sD_[{&jE^qhNҷ_Տ8 g&'y&9,ayyƱ&L^dzXFL1r/lcc}BL| %_}җO ɵat,f IˌV=ǹ~˫Q >ʷtYKxn|lG^= wǶE~n+KKF#>Ã}>[tsǼ )RÜC7`7nhn}Ql@a&2WǠנAp)F8¶5EvgRIШzO{*T gq$otA@K,Q[Ok0hn`s*yqqd!}ķFzjϑ75Dm@ ψP oK>_`O}Y `=8kkCV`k=\~:c-՟:9OZ&.3e4 e0KGܰCckRZMHmjwsjfk!БC(^_-`YdjT fq<4$6xi t8XlV7!6Xi /YCF\?G);\Dͺvk>z4d&V<M,Ws;y L8ap5lӁd{&-y|{X°qU@*4ɱC`5i֐7s"!'] *ov> 6{f.ќHnF+m:H3Ĝ:b1XbwyjIӸZ/;1aZ}KDzV0Ş!#Of;\`hVP diُl7ĝkkhFy'K`^* ^ 76Oqs-p?Ӂ%4^5aG11f/w3HsL@qUޛ$FNti Զ(R{pK4A#Ǐŷ90Ŋ&(=0F#ku~"8}@Y7*(keXGkPZGP3#ٜ'u}o9}U lˬ-b G ,Ю7w0'B`Y ~MrkZx-1 &Q n0Dg,e7~zU?} r&g5'դ$M+O14u1cA,zcxqu'TsqyZ)SSlMΣÞ{G#MN1B}͵|ۼj,.[TAnoy{n k5i%U}7Okmʨ v{Is8z__rhC* 0UФ3@ֽ0gVtΤ䣧ja!>W=dʵxsvs[c${F4/Ca7.g|=b8Ѡl/(3\1}>2良ٓ _2 ytdx']י$OcG- ]ϋV "ZɺbdFsNek/Q3%UіuQOjmwERcP׊-OF≻{Xfk( *~$wk*'Lk9s A\񝵲aÙj.-68i5/ 8F}g4!׀S6Hj_΍8Eeq&0g=mai vѓ_qz 96HW*!t/Xkw#[u;!1SDҹkm-wѸa+ 8z zn@b7g)^)6i"k8/5os=(،7h$u>vּ?Nu,vg3/ qاѱ`A|n-"]7m &j!v=[ kF\9 ρ~;)QNk$}ආ"H47яl|O@n౭$ׇ/u" =>[q_e GI'f\ZC'O!qs?K׫^*OW9óZp~|I8֟_~~7WUN^8uJ9w )ӽqCK 173l}I@-KX>S<zXۮ\ο,ZMso7K\7 ]@ }2sv-zC7zǪˬah2p}wJ?㢓Z0$f vF^+7rg]q=ǁ24e٦y-1]ϸW [KωjpfyX~Uӗ.xUægcf )E^֨Czr 9!,5$qG5udgy8"m)(̹ H>KhϜ#n!=ZzrjgGnys=l6gVu=u5Hsu}_-)9šWhEl``+|Zw? 3ܯ0n wi6,4/AFy!n:yaa0x% rZ9typjԧ56O^Rz#Lk&7vo~pKGgisڡE*< xݷ`[~尦E_46O9*TkH.w_-{L Yu`(ӧdαpӸ"f|_ֲaogce?f8Iuj0iη !/= ϥg!;'?F3w5 zG)aL=#Ggek pQ >Ћ(G3sc#<PZ<:|QH؉ ;+@cNVDcYW!uƔ%N Oe & a#IN=d`k3'q|# Lײ FcoF׶;x`<ꐍ8d{̷[2\sp\ج'}.F2\۸vM $flYySmxCf  c[Sjf{}{ݣW[:R+?KpU;l԰,G~z+F/W*npm|l#=2 X5Z\^J Zs;u&@^1* p _eqCͼIF {!" VwL' ~ƾsm`[ݬs=ukvu}YU~ROh^>nC7a^aptJBmGy_9~yP)g86:w | 9MkCad+zܬY*v' ..ۭ+Hwp Rdh!'{,7#|Hm}ɪUqG!~ 5|Q0,:@{ֺua>\ژzi%sZ|MD~ ɐc+h!6^9I8g3uU 􅰱 LY[go-^;*N_ gvr{z.<(.a(ӖMlr+* &.#6ΉZ 4D7vcP$BgJ3>]Ýw֘iL.zsi'8hL&=.WsNnr#1z 8;?v.PB01$ʾC[:i< JR܆k瑀0,IBo j>?PɨGσdm1L >Z9!|}}ͯj&[n<іjn?K^ 6rhfaW$~XR+jyCC7wu+8qpV>^ᇟŨoJ#w"Mel_cw ܼzgr:`# L>#u_5F!n>#t31]/޾ ⴡ=~3&\?P}kÝ{&bMp:εlQs LMݽ9̚}}9ESzx͵!#V!)%Y^A%P'N rd XRSg1ib0+&b ~lz7fGI ѹz0mͷA9#u Fͧ<ሕ#l]SlsSG"dG#yewF3rx]MX蘚mq,u58 s:9yLc2TMĆ2 zW_0`HCG \W8<8GWG³ޞ '0BN=)Y1=֏͂=Mp➸Rnm_hKF4q lG6k똘_X50!z1O?z5n9hXru˰}%WB\91;i=c?Wp$;=q:T=74n>IMrša؃ x!>.a)q57']$gƏLV]`-nX{=J",gNz%[5& O F=h^\ M&C4 kJ*1pžڼ8"Z$'#+zԁ mb?n,ff,c9Ѝ٥p/܀R9t3O966Iogv#C{nW)7W1Uq+e oI;&z aYk!,9SqGk1%T4@9X35NYɯ4t ]=Ho\r{E`8XV([hXSQ4)BEqL=b}kQ+z-#N6ŶV|Lk.z.7BCr |>qNyvi}M~_~c?޷E{%y8g>zO{7{LԄWq}wFQ)k>{p8&+q{'ɓ|~pzgb|yhĠўu-}x'EXF70c:m3=ߘ*gk_o1/1oRO[=>/^^z3~tOAnDxӮnz<-ei.g,?Ӊ<%/4S漧'WZ™Wnxqkx>~W'$^T%W*Τ^I0sd|bCM70xSM6ֶ7ZƱOYd~06p>dG|\kUvCMODm,>h&+cl%%LDj? k͉}Uxs~oܥo[3ů~(y>*xJPm䊣6ENǯ`v暖M ]i/֕k׃1w\e9_ ޛө#1Kcŕ>0 4nxnb(o^|ǚƮHb‘xㆳ4pO?X;>ƻ_@0$;z l+6^#|3щ\v8xΔLA3KU]ە;h:mI7ubeLm,Stj7Rv"("s|c^ѼvVﲱ>(~dƕ7$KfaLD[;ı`fwϤi& "1zձ. #ܵ pX;{7 m#Ԑ}ؚ5wdu/ߚݫ LYWmuzȅ;K|k6%X8-hzPA߬_N<[}ns:^߮Xo.NPyGlDx6V+s~p9 `0#^Bv!F 亊/g|wZGo&(r}:—̴~=z\jr{ +3G0o8piEس ܭ"9ǚK{o{z|ݚ"(#ЀhaML ͵opɠqp&rir,v77. \j, ѰMhf1N *pȕo\Dst:ZnϢ&QIZw>k2`P٬Ze/0nlwBu GRr7%I:7d >bB7N*9|^Lx`c7沭ZA6g6ӧ́:r6%$'sGntyw/ʅ/%g$\\LIZn? 5y}.]ZM9Mu{!D87t}Gqz1ʙ8xMw҄our:أysFrجI6ˢϭs`l:cGlrH.bט -^—ڔdŎdHQn$W×n46 Nvyo8_MCGHLwU%^)ݫKr&@i8Jt uຫ&A{8601{{:D]M$T{!'k|4cM乭m?8^V`g@@W랥u.#0@;!VdCc+ (o x=L7nD*Xʑ}w`G0Ip@͟Go9G!\@-}H m6(8'x❃YXV)l"X'/ U;'hD UK{<%xv2LX ʕ0oVs&m7{ndRSv1Cav?`u可9W;dT8q"sUȾ&["ԇ \&9sTK՟qd rJ~ d Dk8/±GH`0͋^h.sw&* YWaGI =[~#'Fg9 #v0=|Z 5uˁ(7Gsi_y,a$9{`ūҧb#O_!;S!ajz5#{]~6[囕G~n}z%#w ?c?/VLb8&2\8՝\>J&=-'U9G)}6IV_G'_fx HgIuT7Ա0c&_f6qjBo>s>OykR^߄+4MCnׅLK{_k_m_\s.=5&}/t> *.?n~z/|\>z?}#\;V7?zoӓ\p~nB+z§da*S}D>1m粞Zk%x\*&Ġ1(j+!b8tLx'c/KM!"?"dѱo$bPfbmǬ`ފ 6I>qΑʁvAb=O y}}̍]O}H/ܻp2;HNtصLojV\/4)z}Д4sNO1Bt MZ3'&e皻7js5-x?l] FZlC ;}$b?tOpo/` sBl{Tƕ%`f:𚣱y3H웥m>, sqػf<EG} qb7!6zJ}- Ga bV߈@^mqbQw ƪ%Ҕ'89X9igKTοn ;ik6WAD5:P&BLćcpgvxb.-XXYorwԛY &:B3e2K=LjT}fuÀS#7̳9I62q=99\\ɥjǠn+]??oެWEO[\7n8vXӯ͵Y7G~iT~Xu3uMVnĤ5$LOMz^?pMCy ?S/Ϛ%β&gbi'{k5Ӊdgh3ƣ`<~l&Hv-9C읜Y'*6ɝ3SM} Mԯ Tq/}}_gꕨz(f<_NyGH|*Oz1oбzz|}K??+_w~[w}}#?!/zk_Ѿ۷ k%q ;0Ʃ sr:<@٣T>{xi[5br{|* &zQ30pSvG &]Tb[-_unvgrW<7S7 уܣZuAxayɲ5,G8Ij}S*œwvr()Eƃt-_|> ׁ"(vzZ >s)rUP G\׼u=@yyFZEDҌ& DX3Z:wM?kksCu"=q5b[zR%={~b*}j`3X>σ18'_y )Wg8w\c'&^%E^';crynxKC܌-i3s\N޻m(}gK|Ok-Caв_ܕ#M" lCBuΌU"'[sB<[P,3ۜW= ?Q 4~NڷM@!fFS&);%~|L+|AsőtD=cvs=cҫ7u&Jc+\|iO{ vҺF`B35j;SC\ pcC ]kfqp}WWW{Uco8x|׾V[uN79r~`B%Gvrl^ yxu2ܡvEarL!Q$8 _)ZT h/yZ(hnM0KSϰMϙzc$ On7ģճBkJTh<0^ L{KP;NF:yvZffAb/Gr{&|w(D^ obcY"4!@'v?|&'ev<9=:ڐY7_' g0=Τî[מ)'Y gSVWh;:25Gi:Oj-;uWl>V}'vU:5U+1zc>!('q}\Sp-tA{Cl6a~lMKph!e6OSCDxpY2qM>o9ApAy0^d+(v=?X ȫ9qi'c88#sGj>?>$HAoԱdkˎxb\fܬ-,5ŗ{k5?pmbv!@bݧ۽GBQ, |(?Pإ%ċC x/DD>O" NJOjE IDAT01cғƪm{+ eh*Whr7&w_k^&gK>zD<,Eަ_>~G?!stM^ۿ;׃򰘟tv´R?37<8o X)O@7h\ϝ"sbX=9EbIcV;9} 0 @`s$ ^-!"5aIבk^:{+, y g?kkoo>O}g<5/т z_qƍiGz}aƉƭQĸTsw{~kt]7HM7+˿k{_7)q1LM;C]Aڻ;"87&G&GEsY<mtw(3ó&OyV\f9 j${Ң=g9C[fp;ٙxܙO&޽kJ [nc.Qf泯16[pLdlx\!`+ vTN;?͞|ozoب"6Ij6k-E b=ve_YbK\\ `OO4ow0Ds?9 K8l+;XbkA /͚ќw/lNp{"BoD7 8<̗%rē#+lE +#=$>}K v OذC\#136WeZpx o2vEJܘf E7 @ >s,u+ kohgks7>'c׳GWn &?H4}"5=8r̲-nhfv`-=ɬg޻S+3S]ޣw'7|mC>}G!z;2xCM6-_կM>_#??1/Pܮ:!:l/;K^ 6{1:rpx~W2i>'_eĆڸp]57Nlu:8§{Tew;h3Ԛ֞sczऐ6{:aۻgNaQ\0@-:Z՛ Vj=8"R`e-c%v|vO̘E&㎕&9?X'uE$9>j8r\brJݐx:^S zS9PR) i >hrkAssG[XpNhM5Z7M(Ĭ23&!Up0}*az6;4sJECtNBmplqh -fј4'{$&xv:u%csYs G2uaZ98vz2kDa-|fmzZ,C3vӇ@-t&HP8ٶ8%o[-xp3N|Fu_͘{xr`FL 5r,LAMCkuD:~ wT16|[7+ޭ7wƚk,g4 VrV\my/TA~%|0yC&1gNo5G%_Kᛄ)LYqV`l?9ԫ%b\oD&VUbC-%\V,d<pu9ԏ0g Ѻz u7ET1 dvLH~ܣwQ΋76z~1  &í!>>]}yؓ#+JCI\Z˵+ץ;8/:j تe@d脔;Ș-ErARz786Mj7uX\ b7ciTcMOߏ(;csvg%M~YGhWw>_(q@=h=I7듯/>SqjZǶ`88 V璮ZɆ;=&A}tmLց97I'uΰυ==6y}HG[-ˮg=뙾`@D~z;yK|Яɉ >p ?amx\1? Ow|xL"a[߆utn-=9 }GrLăg!6h'+MF|ʿN"g"9 !@v|%N]c|&2b^_Y4 ˍO!;;2;#G|YZH< $KIcs/>5nqQ^u,F \챔7`i諉)=1xls_\45'ՄSqQ9YqH>LFq]kcaOwO:N8zlpǟsj˱0I1i67yHO{!=_\2A:fTya'Eϙœ؛yk.'$4zֹ МAr?hjEק]ǝsiImG¥L+'o6j$Ɣ&s&w޽&Fc}5iǝk 33u,›c}T؅f5.rEsLի򑧈١X }?z]b`TF8%9_&,C3ɳ(zcmc|GCyYeg.4Y׽̉ݘ!8'wg|Le䒭[;?OVkko\pʔ>^3l;?9H5w0 hę 24bnXñwGh_Cș(CVs%c?kC>^O\%"}1{' [lsm"ՇaL">yYnƺ3c^m֩;M {/ϗ9:eKos.cʰK1dž7 $۱خc؀IcC3:sB+׽&ܛT9^v@F7M1xKkW~bEsj\6^Fwy0hcnۋ_v+؜0qh!? C a̔{j5p.hZ%):pQpX#aWfΧ9?57sgOyc^CK>x~?}FݍۜP<_|wrnp`͋^/~@s*֨_M2/zϜU}ld>;y?,N$\`L7jFBe )]K`yгr,l7r9ӫai|v7k<(1pfm18z >+gǟ).n24ag霭 ob}\`1ڒĐμ>,`rD _{=d3pEacZ<`>W@Y=t0 ScSy|m~R:@t-A2>5cnJd9[8or'6>g] mGZà&?v'5sv9 11Vhr Sbc։N'3R)N`ґw^<7w;lN ۱QYgrթCXhOr'!IcCq _ udlP8YՑ7sDtPSngݙ$\جIwq2rmoݎ7[ƵXA9 i|; @2l\d' D~DRkNeY.rMLoyۮxo 0@#>c|!UN*)߀y7#up%֡\~U6>PZظ gjW܄% ^gz?qY5>oBMd5Gf$~5c/ *P+KnOt ߹z~wGrnP9O21lr7%ud#-s TH>F!~J\sV!MЋν[f9I1W Zcx8lV8>Kc`ąllϱlu5O@Oj?/-h6^OO'\=ZZb>jܣ7hDz9"q=cv/5l{𑋙USk%6xH9v\NB>cɭ隋k3uMmnSWYZ Zky;l ,eb,]kǓ]lf1rDH3'wTⰲ5qenݍvA05аXo};duGjh]F_CV[v.M~ergX{ =]`ow/hq]bFz y F,c<񑿭iz$w>!H'C6DC1KAecj'#GaƮ}sݜ]貶2&TX=w~cn+X$W"8CV'ύ;~Zi‘5bZX`.0phʡMrڦ*ׂSDFgodxo}p̠JOsXd o:8u69 <殶wp%Oު At5&_pjf@gCt-xM#ƒI}5;>'?98N~Mɝyo BRl=𣕛ClhfχeiVh3YW"YKbb{8F @U6k\Bsj)6?Kq<ɻm+Nڣ#3džgWKbeўѰ6mpt F@ؠuiw17L}@4UE˱<ifg5i&жsܷ6aslu;1LGk$^~b9|QT^(LGt?|]/?u+NS }֜okd`^6P]ť\p2dn\z).<2v!=RCCL{:ͭc=Xտޠc-pqtY;+{vs,"5w>X΃} `v~fm?CWNm9# 0'Ae0;1,x4lN@I:kn2oNs\ _7.~~Lc-5]aˁO Ħzyj5TA 8[9W&h4n-30\sME!Ԟ!&x̽0 -ؑ:xmm~B]xnWٚ6k" p nA#D`SIklLO'GK~'F> 2|ĥ_ݵkAAuNmEd妑 j7Xb1ß\jʷƑ{E4 IDATr'} m'kI'h9B~V9_6`[{s0;^|9YdV#s=ӏq间w}a-0X`:4<:Rl{ybwn*ZH5L Cآ/ yay.x !lȀHa7yrˋͫ;XIӌͽ0= ~ 9ihw5'mwws"C/<XנöѺŏ]a=j] 31=}k_D7asLZ| j1' OK0[sZӲ-9h fSijD3e!Ա!(D\8D94T;M]:{ԮInv~\pI|i]_W{4a ylM$y>]NFjy{l|2֚9X79ĉNpt!e8Ls1G4$wdL=q(ʼėWcդxS:ͯfa. ĎN k2}=PSxX䡨\_寸>#?z;=7rW9ϙsǤK1{_x[&./B؏Eu? K8HqkͿ-pΰh'c̽ı&8^4|KJc|'/ /Má(ll'XK+gCtςwYrAKVݯ_~~]{~rf pkp 7O_;~wy7}<.sle/ k^cʧƼQ&/(;>-q༺EZ@tϺ5vL #DEmM"RbYbw~9_.rsQ>_{Al1yOUF@5h\ޭgYK7UbeL )K0 >yl\uB8Ke !IԔEN쩂wυ*9X]_^4<?ÿ16tw bJ\k͓0a`3k-V_&pd9Ɗ"7{ӸѰNTK eC>}Z;?zH!bɽ5F$I6,YXk >`lCPs'Ckq`H[35[ ^[pff}W+jxsNm8'DN>_t~ '8F5qpBl3T펽!ђ^ED^ `-e\;w]A!|R;ё[E; =W Np ? 0jS4gxv;MhX/o8wgz# >1%*- >r|Y9'{87UԜN&}2x5@ip`'e 8k>jzfK`[fX]-I >~taW9iN/x}z 59P~d12ZŮI.ԢF^RG| 3Ѻ;hx?\9z;ǟ{=_>lGi~gWuQY~S'V^# K~'ޜ7z}|I17h,?К~{FXC'&Sxɸ8pod ez۠r0ݕ{fb87t/:nsf?X~޾H?c*뫿ߤwǻa^/K%uS>w^?G].um\}^o}[kďpaBD?\1= `u9܉D5Oč9#CgcZfyK9ޜ(lpuAl _>=߭w58z>]r1:kJ}'Fu\1!:^OoAw G d!g.&KzիJq8|ݖ`/| yB3_7^wzM/OO̭^Qfr3:wj9Y3rd~% b3<9>A㊄CA1iqcQyJ8lZFL~cey=y"ZsyDɍ(ތI<9 6H\݇.c2s^NX]; q`M.,jVdj `<rjHI~ ]1˝Ee7ykc}'bXp_е8sl˒0SJٴKkTb%5a1[Je(i2T"9] 7~PO253R_;f^-7d(YSWjbní.ZC΍`y'μZ 1Y [X2JCqp3xkimsQH8l9@v_-RNtkP&X'8h ryg&S31Io=i[Bm[[A&h4( A0zY3;dMr+5 ;8/,p<8F,soC0TVΠq͙G[r)M+L5M[:qג"!~:dڬ= nppgbs8iU9?71̱1LL)o6bbm/6]U,GfOᏇUMM b/fWg{ !3e5K A& k/H/Ӹr|9xu[ éBn8-lc6O̝YN@Z]I7\H5a1\9/{Jly; M $ﱳOz}|.R.kB^ů~EREL>ئŞ|q=݄{W?]ٮ_K|/M=aup.*TWMF. s bԱ4koΪ|}+$ܿT39W.kr%цcMZgr/MT'Ez\ p}~oх|I Zuc:Åb fl6 'o{ۮ H^:'nHs<0̻F}Tg=z=Gd~]y׋^]ۆ/E]œ/GhNx`chL<px?t@X bHs&JQ L{J ͡`~A3-m9c 4`X:_54$a0܉/WUN=D 8响rnS/WOϱj *{:+z~&V\ϱbռ :5 4Ǡb3gɿ)pj`\F{{1rLEL>},_H汀Ңa^E8}gLE-)Ț>O[Vq5ˈ_z~k4jmfZ|+ι&k"Ҥ&{҅ñYjjpo06E ,O sOCz8ÿvGT9`rO&09as\;s}:B` #w?1$Py6د ې\YLv%)r@`s֥/ /G~kq7Sok8_YU;:픩> 5`2] 7ZT}#OP43qkQiz[C}faqL^8Zk*A8k6E6z}|7Md`XW9}:XkV5l6} lLy!c;+l\ ݨ=|]AM}er@v38&%>67mh&<$"OSsIzDei1/:gM?UkmNENV!_W~\V߹kSBds{uB۹<}=5a[55WF|z\㳺!!2*oFv/yE?}l2b88A9eS0ƮuCot_ +ċw$%=%|8$XKV1gOG$޼Mӹ؟p;~Cjqh4V: Epc ?A5f'ϝ U;K"78oՏ#ngv1֧סh38HԷkZ{gߙ+7,2ƺqQ{{#9I^Lr(\{0[ċkۖb/΀G6-1G1b,2mzQfs/90N Z2e65Ͱ5ȁ>$7` >Be>c>1pHsGO-I YGH4$7PǸx׼KZr>4"凴 r?y[t[;3kyOfpDm%;V4@ZcϏ؇qGx|+QRB,(k8?h JG0XN_~is_|G%`C.~q=|a?e¸xF fjn ʅ!ϩL>yy##Q#[~>'V^dWW~+w뵯} ?M6^f^;"+Ժ4|r8we/bͅpAMMu}o`mGNHqh|c6KyB!ưbH߬_ɟ/}W_Iַ9 BxEу|l<.Mq1lgqe?:Yr!]W⋮ Q]? IDAT?&̅ Dp/Vrqvs[NjV ZkۣU<91Zԕ}rqai|I<>ElxrpNt8wHXZk%1 KL5nfhټF<=HH]Ǜ{hlb OsٮhI1cN GXZrh@V;&!kpk_5<~ϜZd贘#GOi f[iAe0+?H{m[XZDj"{05kb8m~s`b'63V"s9>;MDG܆14q^/X {Ȱ.Κ˃jV~5&<$Xsg{Q6ӹ'1QxʏN+S/(}Gs,YBonzqG dqGf3@m`ۉi͞~oz\ɏ6}/!IW7J|POۦλmW<75wj/< \nчz@NU)47ɒ{-4Z;NL,4ω:y8Xc7wt1x}c,׺Y= y?dxqiγf9^bxsFthYН+Kӳ{3LcKø񯺬h`_`'ܠ/4/j\$cdˍk ̺ތwȿsN@kszՔ{[(|j^}fG-}ѣ=q,NQ Ġ8klrci [2+{޵TV Nj'!|S6 5^;b7i~"iWE9ų{> 8IaӟCE6?7C~:@^1T_ֵpǀ9HY+Κl9y̡cА 9qu^XFZAlKo~[sLGӺCq~g\_ xMo5D!F ӯTz>moWG_{oOU_+W| Ha!ڻv] NM%"WO.o0L3{v- ;fKÝc.rZp` {1>7#>K?B69k z/Bz xJ˛_8|~ﹾQzQ7/5vNηj:4. g=v}-5y;cZ$Ñ}LGߐ~0̱zn0GK&WϓyC0ĝ+U8tfa"(*ׅD4ع'+|{vmTmˍ7*N5{zo#KmЛ"PhFY;nT{~5v댥-`N4iL6sc[-v r|F,s qFvR}sL0}Rp2'o!!z+&y4[$<CFUa9Y%:'y`iAtygTGx51Mswp!=vF`90L=j+~w05=!}?7֑@1KWz{qcΛzMY͚qUR uJ@gEw`b&!Al-n.vNFu0Lkm?[2ñY%961xv>kqO`x69ŌcRN.N54U@S71QXԶj@1ٽӌـ:Nsyٟ늰rw%n155vZ>lՋ r>wV`>W WZHeh X=8Vyfq 9 "r+#BΞQ ڝT83%`ۈwwp=ẢIH"O]SG '!ogB 'sΆ[Mq#Qԍg5;tǢLĔǎγ]cqa^+" Pɣ:>ϭ$Oos6[jE# 8X %5+> Pwg]>>dj!i؆΁+F]m< {Dp4:^0W^_ꊷ8}uh~żmIN#5:4/G05Tu)cr{J%)s!~Jg~5׏rNRYxVúp|>E2=0qA;EMtxV8/>g:7a[qŽ"% \_Ñ Ɵb?;W1qڼҝjqfז|i7ņ M|'o3?)I(qߵ:g[ !o=ÏqB? {7:zL >?sSwRnhk}gm̡G,{zG>J[ ̱s=hCswc:|.N=Zu׼OhW18G&xtL3y.#YzV݌ ԰49=q$(4uFro{;/@$3dS_R<4~hʹtα xس As~,=W#. M=+'~8Nm:ό-od1i'_su57?8;oշvMcsg>@k<'d~bW#~M l,=9;|\. 6D[U FUcְb#%ќ>F*F٧fec j>p%-ѩUk0y=8ה:='nmht\W"|~P8Hm/h0bR=MPexi^l8WtԌOד5w4V4crh7nlIx⛾_`r5>㎎rF[35;/Tk5-&WRmMͧ}6qV8Y\+<"&3m3N0'I41ښ0s97W sO,o|\笅DSriMyR7#(Nھ2񁍆)}kv&q% QO ѐ@?i9rOXP +yb>^UXyQrp\Xk=$cx(C!*Ku;ф5&bቨzjzq`i_kHbD׍ osN>㙏\Pg?~}}-jq~DHo^}׬Ǯ{O^׃ b..~؇ziSuKDžˊ֢9N>ckmcu2˧_ s5./ԠOk=Fڒl<%jq\WFa帋5o~_k5}:ѻw VhJ9^q('ёfU G ךPW|쳮 ra77w%H`2Z89c`yۧϯp)_u/ͼi@sm6:X,jwbMka.L~lZ}(bfIѾ&/W%g4Mqs d9< j<`̜ݮ=}Mkcrֱ=6yİl#g}Q:Fz`ᢗy3 fZt[neBIzW qA?5kYyd?|6btӼBFtNj1;wi6|F3in}h0<'/*u4*/XUl+kFHEXN$?!$3J`ZF<x#(:Q1E:AtZ5'˗=M]Ap,4 LE:/H'd&aZHTUG9 ,&b\8VU1['3lv8hrXvn 3{ Hr Tr̐#"n90,~b : 6i;#0,%D }i8ECЍHgUeLNK-9VEHMĖ:Ds9M]>xX{IVP61!*cϡѝx a95IYkI־+1Th Jc<&`2mdsq|N!sS{A9pؼN@J[ Im>^eDh~9Zo⚷f bNX)\boSqcze+T"W#6s`]meoOi5+ J;kƃS9'Ʈ2;͒ax>95w4,QTp\/|s')Me|AtKŶ#Vr#ďpiYJȊu :`tOcc_#萉;FO/\HD)5y.C>zʅU*NnOJK@y|okHtrUIzwc.4w ;0R9O5Kw3?_x}tPOׯY?w|vU?#GU&J>]f\h ^kofI.HCz} _7`w -g;Ƨ ~뚅s Iu㚢Z@_LGKta=: ͠HI PYă[aQ FW+ֶk_+3 *pO V>)}!xTW?9n\];6/lCy^7pJ<ػ:W?׉h+ȓ|yk$>'_=&8k\*|c\Grsy+tOo}L|N@~>3QKdϩ\S#E9ߞׅim]Cm5==d;~ ahreIҽ_Ǝ/vfԒ5 :}v]yIkd/i &qi(4 C#ïmt6]+>#5ԲG׉VtZi]kBKп*cȓiR;h;kib_[ ^LJ@[Vߔ\L<;Xnʩl\mm4^N\)7=_*w֜m'}B889 FWgՑ!7:v\9_3_$m3bq cN@!2,Hos1Yҝ\aȬSm noMSFA]K5@!y[jq;56}?jp.P讶\^fl|Ϲp%m>^9ۺr'QCv(gAC C7s~VOB`%<ɟO><囀7\_ 1y}o>k/5]E/| ܟ~'q!~7(QJR{zbɱO:,Z]d1So'os;Yk;39nҗc1ylZungH=0V=]ן{Rz_~*鏂gOF{n|sc?"m?)Rlp5ڇe_KDLj G}o}իŃ({IJlEb}[OP7s0Z+55~GJ miB c6~3s]hq(༧/.ݹVbꬌ^a@76^#9ȧ7qdKdd1$m\G@x;/{1ݱzwԂSXc;GnCk!*9Id2=ϩBRK|֐>O.`?;JA-;=nw~|4mŘig_Ơӯ3`ИGԊ>6fc`j)'ۨ Rw{>&\;BQ[ ' F|E~ C6_]fM^׸Ém:;'q | GJu4}O?*[ ;ݿa']\p9^GC;kr~8+|8og4f 4@H1n7h/syl,}\LkOϼ8>̫8>4s:fxVcN։6 IDAT8LIMgαL3zG!Q/}ovM~! tg_?W6߬w|#}]~΋D,B{,nlzw{޿=sAL ZOk8>Y9[ 3JDY^"a82_Γ'h]'|=ʻ5!4(Ǫϣ#KB""G{hHEHs>opu֘7AEU@gNצK4h]O nb7V&Yb[o~+kWE..$T-OB弮$[<ӽ<[o=WS:c{>C<3qF&&lm`[@0X4uh?5k=iaMܱr4hY3:3P[ON'wi3/:G]VN!X'Ju  Ozt@R'G) Uj/:wbM{2-в "7zI (67n5}Ao!;y 5$|'s:iMjX8[90hxjh_)1ЪRKo\qX#=? yzb4h&'$FcWrc0M^<[ק1Nbϰ Uoi:5)u&H ߔ bɋfA{v&x3Nm۬;C=μ)m~{#WEZ>k,?zcvE @gTOfwier{M$p$b}r<-#l{o.٪~Cq4zy>J΋w1I.mm0\ Pu3q၃2i̊O=Lx Y#0廉c"V%7ƌ?p" dj}K_ccAҌNl{7m1iEŵ;py ?!z$V],0AY^|'X. 0olr?CgX9h@qy\"uXc>ryJRG${=M%jyp>vR` ŸmaRܦ?0n:sd(/bo[gI>[i 1BZF\ݲ@:Vcp8X_xE/ZoG"SʈS!5bX{ 3_{$ޞyrS㉈gd'y1EXڳ8NniAwiF!^p5?61pN,Hx|/K DcKLY7N,Jd<"#EpO23WYsr^NN^^)Dgj) b`0TЪFѪD"JFpEu?8S0Ĉ@ I $9Iz}k]}ֵu<ۈIM~2RkACyBV!]U )}0^Gj,o=oGgC *z"g=֋7T G/ydGcjpHnp2 v6<:r'6`kgv!sbh~5Y@ײ'cxNiuClG.mgȱ7J,EÚ͍ܶ9j~kWg:48Y8g4_c*p88 ٔ9yS{Ha搆HcjFN:N) faXe98p҂zu':}kh_[ё XC:䲁)'igɡxb+8sGfMl3fހd &yll%:b>hY&^>cw'7{3hzf QGE5S۵3nGHw^_078ꈛTp-_gXW̘|dHT9x~(2۠9cyK/̀; qٴFc0K|?(7yߜ90FIb9ǝTkzq_;W'="'Gi [~5jg'Vrhy": V# bzWOZ߀- h?s}?t3?O_FFw&Aozyx܃^'oo+ҫ ;7t/3u|y<^c_'oxe٨1$ex&Qd1qGriwrOh ȍhl;eެ^l[cX?\&hpSB֙CALcJn|K|~o8)S"<|Ǥ@}.KN'If_̞wrbWxGZr597OJ|8!vߔ"9Yh_MYh-#1OZmX^rpq/z 8s!Ւ rgp3{n7+N&, ;9 `wL)+Z'hu@Fg^fA-%sָǹ9 tLQa^-k Vxt["+%'jXL>j՗$ xh_7n/Q<%j$.}#Gi*#QhKBOYS5'z7'ץ/@ZU>_?i2rNvs(d_9` zETq L'o/?qv@t4& 7צ/v9'ͺ9kf=$OT*Wa)y\ 6w1'ש\5f?ǩꒁG–X9pw1׾xm`9<Š*ߙ? {pc';K,p]š81Z|~~BX;#,[Y" ?dr0 4pYP덍yLPfxghT5-  ռ0x%V`, ^ xqmI܉s4;E>?r8F޵xYQ<&6t&=qilљ]s8tX )9xSISK$$lm̡െ-8'f*1A(3bl}b/ǀ؟{31yC8muIA &w9:͙85oejc5:}͓UTW"?P|ouyh>xO*V@yc?rc$$sN^{65M!: 0u lzԠ ב%`Q%iKHt I_}<wtQc = ͚k~ݤʯhv&)_>{1g(&D,o>5 N~%m?k_/\"9"YH.́K>8Dx?L~rsnr~rXkgJ}^eo,Ħ/&XD圧p#˸#AE{Tآ}əZr}aK{4i9b@Qj:@+2ݗ)]GGit}ّ~deuh3:X(/ f ֺ[>}}jz'}:unGs$fDZ;x|"1,7df/noxL݅[#:QݝDF, &Y1xc_{*m=sP{1htEGDofk ZmO =:]qI Wz6P0; ixdo[crDO.0{*CyAn.rmэz=]Ps71O|&^S+#M8';Λg]vE+1 5EK& j7r'>I0R`Ū !}3! li޼re0ua7W`]÷-3ru\XMg1h{j^$pF}=(j'&88&66;Rsy&oޠwrFF7^^z;x@M?,J 6z^_e&v$ɱHx{ì p*E!WA%_5VqD}2`z.<ƀ ^%ͅ4:pӬ%ϯ̣fǒA(.R?"yH "y^WĥS(|`];uO}cZvqdh6.iɁ 旽L4՜_Cb:̸U0$4֟^,h*-'ĆG~q4)&GwĘC9!-]9Ptx+pN-s4g|燻a]L-4L3qc"}+C"JGl z=+u 83kፍ̎R- F0Wڳ>{K]7PG')V(|uKq3=WE[399\YsVeΞ f31prՓzX"ġcs$M =?8!I8pdkob=MD.@L $7 #sgyr=6]$kԆ}PVdQybFkvQ!4u<틁sh y"'QkF ƅs Įߘ.2:?оA8dw;{1-D;Dzc]osNKSt&ikӄ+ZH;KOAV'uo~otίM}O7^o}Oy+z)W}埸>?ѶSb1Ĺة1vᾎ(Cl<ͯ%6=^d_`T{o*RS|6H5d5 BvnMdN!}>ZeǀN85pZ^򒗄Oެ$"LJֆx j{Db/y&ǰv:sY3dB|×̰&?.ůsem.9gNFz:;}sB9K'fcŽ;3o?r4>n[Vk\#/5+NI1,WtS-l4O3. oP6\ϧiw"Nj\v8v猞$DGhrD 496͕/?̍Nc/ E 㜆06snl&G+yc*&?h1G`G?E/DxӑhG~#%:eIy IDAT;Xɔ\x|KC Pdz 35Uӊ'o'*ZՄ4:I]bJc{y9Px{/ck]cx0!3< o(59^֊Cpf#z8xCekhyf%yT[|Χhrnn_J1~6\SJ;dnCt dqDYXHznvߊR^d~~im\g:ho{^.: 7KXP-9dxq;t?W|SRz:ٛoL~F '[Zsa&k84':bG[4 2oZ2u>vDo0 +4,+aٗ7T kY}ybXۗ@Ϝ4CNh$i^Gq򼭏0צ6j!0#Db9`' &J(8hWFЌx638QDqjŸµ2ATXda_q&7'SHצxx;k.pYQ<&/I|uEEbm6%nDϊ.@.Z${rXc7 ]ungh>WcLT Z, p791PohMT٣q526>37\=|E_E98V޻5F sɈnw4U-_bP<닿俿z(.g;NWK|4 bZx_hύvȒchdeq7g~xrxGϧz<+b Allow.6-3 Awo[r9 $rC3TI1oao׍umw-! 6 ~K1Vq$Ewz>OshŢT+'Bf`ûF?ʜ =mû#׆H$(#ƚK26s63@@gsբu1u{j>u&&{S$WN W叆cw=UkAkʟl=*"Bx2JcG`4kה@zi =(A @Ntјkĥ# "IГO<:ߌEmJL36|'5 @}jj(yșx/m=շrިΉtGW2Y3}׻s[sN~sy6uXS Z}‘'Vb7 ?zѥq^.{8.$ۍ Os Yz>zAS"#&Iv 0Bbg ՚7<ε*?G k+h5.#|Mjul{l081t;csh:wD'7cjƟC*K{1r{Lm/!FFgdz^ڑXhfǭe&[cqΨPb xỤ}n@9GhlZ"*_b<Ǎ Π %֠5nxb{ͼ@z'9^z]Wg< #s>z?/[DPL͐]||犩uzI)1g#x!2cgE 7-vBʉ+Cޚ3NǚJ &ӱ|MәXwR6hd?(ybe+7Y\~?_˦n$CC1ll!:DCHj .?;8}+.ۣp4:}nM <{kf&1T}|*ϲW!L^Vޕ7mgsU885 k6=ܿ96]\@8Wޅh1h,x8-mςMݞ):a_>i鉳~<3VChl!*|y??w8 b:^z(.:E{ T{^cтC6)X0`Qji|h0a'Ip5~SoycY덓Y6WpPӈ{#іs?$K]!?0l*;6@~֌Xx&Dz$ ݸYA/1Ws1"HfYp#E 91 5ǭm+!uK6DZ/77qmr7Z2aMMhhr7Sê ɫw ԜeZQ>sn!s$Vl7}6ֆ$g 2 Iݶ;jXJőBOQ5X咍4u&KlY`\L~?~9b{#}qJoL-WR KO}!77\/֫FYW{d[*k0얭} W;Q<g|&:}ALEw8ZG_a˞ ̄E_f2kTJ.א |J_(}\篗?.}Wo ɜ{nUMڇ7i/cik͹^qtj@ϛwTLΣMT%ʄL{c10gI܀E1m$3n7~v"slъ|ݸX9y3|i^ᘜMr6?;j}bn4!ߠKXY9_rO[oƀjJ$rO5OhVGVF))cb<ah9MӮ2Bu1N50qUލBDt~B'~S8M5vݼ>;Q.[R8_=̎v?Eω3wc|r̹KoGrNE4%p]ȑZ,a &K9!jr3!vmra<6p:}fr#GAvs 6=m!s+_m4y(2fms{@Ɔ0Ϲwr=mRח.mp5CO,]v>֛TeſX&*Q#ٖp$ղPE0>aeLs8H08'"=O9o<H=N |72^z%|Ysz3RFO9`;NE _k}ll2 3SX`G⊱deؾlHNh!}l. 2qaĮ.>9=hɿu ҭ,ycysmmиD =kq_v{_7T e{T9מŋ/8 2ObHgN\l28oSk.e2b6Xb,[ FO;#L=':.9ko1<7 7d8ԡo z71pM?㯇k84acx<_Mkz1#7]W1߼+ a62V p9E~xk>5oX5=W^Kcaq|P7_>Bq9ZEd} ~e6 BKjuj F=ⶥpck3]p|ȍ_H$kMBk**.78 X5T\r^fD&?fz$d6OPlugnvhTz+MѢBη_KTf_摾=cY}@7>]J4u8X| mOi}NN`E2yesߴXCam~ #lf!frY䰎ȐuWpo׵2y?  D,eˑS8;uARDіu6>1u:~fTa:wir[})&W|] :-PZ2a<1uD1kPl1R;ku As}dG j܁ ґkipL#}稱:6'qxyܸr& Yqp]G=UssVf&\R{%r_ -!y/[Ayі` =u'>}ў$M[,PQ1!r&p鱹bJ7>())2M$:]#sd>͸Ӻ5yy7ۙʗ(Gå+ҡ'xgFo=A>0fOkv}ho :ymŇ,_Qs/&.if`->щ=,[0{M|Uԋ%م{v5+$m8o_4Er/eñk o4W#risD>{mFMKIj<4DGZ~yAHωB0ȀO,!djfS "4c:}g1%07nd,Lo!Lm8lp>Y{PON -hv<۱{V>7DMW\Su8'K~%9`m.km{r˳<7&0:gyw҈CL*et"s.vPzs11:ukh0ZD'gVq@FYg'q_c6Wh1zZZep tF( c4֣]&迒cQ o3z 7Mplm%8$9Ne\8Zꋯ}6'9ke$v{@ Q$kܘ_l"@/IJo0jVDa>?P.>lDց]#K8hƛ :o@~rδӚZ ayʚV}3yݨ=[Ĥ]gq4B IDATOlrZ[%D[q Huy\Okbڇ۟?v7j^dMcH: K5 eCU ^m7g籭>Ə LjWlhsƏ-yRDӏ5Kқl#>õn:/;MB6wbwxޛ;:o9ε:a6!rmRGRpcJʦǼ0gk]jlaX1Ѿwva9l{2!3OORA;Evks_ŻP8"}rnjaڋ[LEfEG='(>k jNۅ}xgo;ъl]-](I:,g4#&' ory8pmî=qmrF+L}+%< GyWW"D›9g$Wb*vzM$s,!w!*cPH5ͫt['Yo)qʻtW$La۶ >GxĄXq``G`#= ƿ4? Jl 퓅 u,y~ d`Dv'ɰZ4 [8ُ0C$%9i"V0L6s!>V֠6Ƕ>ÆvئG2ָOLo[ݔK^rPUI cćW_4EENL%"Nk]ų?@7 AW͏<ח}iHR)W ϭg*/?W7NO5~EUӍ?nf<=aft)k} o o숸87_=Oo9|pUРm.ޚgIulBM}@s 5Ы=CazYj}sSe¨ν~C8<FP7|qA6oC2f1ٗM[^!Co~k׊}ɬ@|ڢ|n$(B5lʊ8x4'CYeX 7Ktvmh|эz=O.bVH6Ű_bN힮ऩ`&ϧaTY?NcCxܠqy|rЕs*֢᾵{LxZnj΍(EaGM g49hoc>%q3Mލp$puٙѲԛpʘ0쵋["K_E5I3y3{C`utCe%9֕dGGϛu[S/ .@sbXF^Yz0vS{Xf6ecv{|iٚj#5(q2N^btqs,w8-qCa|t&kMq:G~~p59`Ls|NgϹzma{' 2b>$MFg-[DXppGA>p'5vvcɸvrqGౌ @TXjI\vBqޭ<yX48s gc4?FuO1v68tp_esO&퍏Mc:/7dG^pUe7/'9/ _mYϞYyD#<𢩺7nǐ=M8GusH9q'-ց ֳ';o0Ԉ! 5iX4b<6܊3x|9ww9뛞-qelm˸\-ξS0ҚٓShdNI<'ލ]3B{181rK{]+t:d].c><嶜7Õ:XW7o\+9zz3 5M, %w 7u,:7e0*0*7rr7V&ctǸYI+'??&pLZwqWrſw[9p,pA?;O]_^'#'i-]k=_9S7pω}C 7o#Awpi_7[]v֧`{YZƽbLGbžmm~6s6xYWQc6qM,uE'I7io`4 x@`1y̰nxa)QSu>@\`~'|\Z-!Æfןg&`%N5Ae.OF9#ksgAlzzLy"5cX7[^l+aը+kW9Hϓhj<$d3{eӢl<|l\+8zV?F{txuHxDGsnz7 jzCzE'ȱ8i<{aoylGu *V?r9~U[djNוok'$EA^-aWH ,(:sԘ`@`0d yFN]e ]9e0A07~]Np+1GG1ڰŮpDNrNs YGlӓτ947s`oxi^Wg$I%SYUf_;3*;]c4xrM Dz:]ʬaGv]2[͂;`7`̱,x`ҼtL\-LPa(8o+P $abonLbqr|3hhѩV[qG[4r F rɏ:W!:!Qت,sH0/PsHA$yE4AccbkY| 17v`FrQ0ZsFe\̇khp!Uo+vur FB'MHׄ߁bEs9 ^7"=[hšzCbkg;Mb`7ܓf}rAGڤ/ɏx7!>qΛ}^ϵO=`\j=}Bck\!1<50y(\̬yXrk!0醏]y=ǟ>okVۆ~X 9NlD9v'P\Û|dv͛kѯ}{_Uܨ+t#1yn9gR<1 ɑNz-b56Ms=.D\j.P;7&爝eim2ޣyd;5QmJ5ɣ5f}J܌U 8&Kfx>zN*}Zw̚|SϿ]~`aBN%籮qנx=Z_~O@wHAnabނnfWqK2)CK\قz> ?LDFiwAֺi9 W55uh³\Ԗ(1Ew,=AuZuq7c0y5x|ԵbڜֺKFpϾ&7pmc7K % ,س6R c>3S{mx>llYY>s-y 2;Z)&5:.% Qmsi&Sb^L775:8UMON >ӸS9΄&s?DC-]բ+ɜ4;qOVR͹,skL^Nvl^5h[cL'=4/t9#?]Ua"_75dwsZN`jo,Y]%vu^5 Ɯcб!P$=&&tj?h2"[kˈG[jZ\Tׇ<Z"}O۸tX=='_Ӛwtk ]ґ6M@0.-9ƛuoV5F\AkS6hh3WS`@4;Zy$q +2ݹ*[yd]kΛ="s%vljՉ,ՓQ̴7~{76ѡa]'1ǫ ^p=qQ!w*<0_/@#M~__w _izg )7|cLcGh:  0c&qZ3nV|$=nCLfu`čyX1-h!`lz OP}XkuZ: b|z~bMD I!mLLob^έMu5:qn|a?0сx4>8XW֢U0>#Z"?no7p*d3GgzqFM*B~{ }X:{ myڭSyh Z jtE&{[9xSWJr2'ek%esƲ&dt $g1eH0,k9wRBBVti6\piD -PÇv!e' l96t^bniw`l>',8v0Mz@Eت;,ClɃs1ÂPJ\1h^tD?aN8 '҅-M95goIDt]Ѹym/s(lܮqcV~c &KV {vAo [=oklz pFs9c;t.Na+:,1}XiJ&\MzlRވZyv\Η681} vFY~8 $x-sMQ"Ib'CAgkM5Ru鹣K.!S&HW,ԅ~͜[EPx .U j}i1E lfL;18Ƿ۲(.cll]7ƍ]WtNj&>a|'~&`W.\ hU'/)ں,JqGIVNE$ڡ7S317?ﹾ+zr/*$<Qbڙy>넰X86;i}p8G1녞!۴1~2A oӎ8AG0lEaWl*o9e137TwM`\ &KpU&rS}9&}^i ;Cfjf|W^Q/[f52(W~w~*VTFNf0%PҬ;z!oٞ7^jjد %l0ϵE,I3,k.HY'D<f;|YFӕ6f`yt< o:d8),Wql?z9I]?0ÃNzyE2=ipfkbrfQ\y8&4d.G66QEvA-8:&{l@qmV;^D,uvxydgkS ~44(aO+8~L5K[a[չng8l6@ m# vji>(kl!nz}ӧƘwMa:[>sxKs ZG;7.YiZWدxv4CF~79#RB^e-X8! ڔ뿁s,+Ox]{ݸA|pܼz^_8Pj͵?ƞ5$p03ds-]ΑaN"u$oz,o+;w8GϲLԾ-^&58pbJ~;E̍ nxM{A ?٬΢D6' E}=x^L貑7e,t+L^MabjO<-8ʅM??k8@H |WFŠ7^c^r@3(,w[o~ޑ: 2aϯU|=4+"Csfl􅷗c=ܾy< b-4t-!`=sn[1a')>/e捡h.vj:` ьcB Nk鯳֒&Ł8)ԡAWUR[ >3kx= G!w|4> 86+9z:ȅa/AĦn6e"$=Vn2|? B]N|@ 8Gj5ifr}&)VK.8s9W5,0zdhm̩8YhJ/2 nP:8 &GǤ`VW9q#ZA/pzs݃A9X':# [TF/ϙp7屗#pGzč<$cf1@[fpD@j6,'R;YM}1΅LЮ{wMƙ8'%X;&J)"/m7 IDAT.zCkCΉJKYl0af:0kbROʱmeA1u'סUsA@"v ˊcO=Xw_ ٬QxpW$qO'lڙb\"7͖sl6kH?bEipрJbt(/j*Ɲhۃsh#\DŽ$ h Ṇ{Al-Z7u`we$d7Gh8rX3[%X>9|#Ka>#탱0xs3Xl:&}q;Ee:B&qt:'^N N_*k@ bz,~ciJWHV3UO&ζrjN1ncrb,@u.鬶Br/c=Q 88!%>W%]vF˵c0 < )/=>s"eDso^/μrGzJ> 28@s0}[F_pv/l*"$c_ƊXq̑EGAn_^{^?In8e|;fנ6k/5y` Z&Ϲ\s~ϑges],:+<~` cYzLɠ1AKo>~:vrF<2^w\f[ՕӍ;}SokN]<*חW?2f8jr-o;;k.k'xis_GeaMByEqSɶ]f"iɃu<,|}F̈́Kv[жI^;Glcל“NEHaEqNcJ?y6oL`R +Ij˙?l/o›ස =R+MQLVЊ($81ܬ39K|Sь֣Q[וxlp(`m'(j ԜM>2&"+K?oNl#ZF`$60sv|5W#4'<+6m#Is7j.bȇ}xQ3Mn<^! (%OB̬M6 NA]qĨ# J$?]L`&oNF{ܿzz7Sz" t}zw+vbCO<~}k>m'Oѫ AIa,=,yG}:xuߏď]ɟz/+!X}Zz_<ֶ.aCAQU&eeDNىLHh@(" b; 0]AAQ(ZAdM]T߾/7ksG}gs1s=^tvx3?A>YI]ZN3.b;ZǟW5)&1An&⫏isgjJ| xF/sSߴ!x/~֣ץ߬s^AhnGyzxb@sM:nJ=|=)O_z=O)8$8V:ћ/{Eo8Ǒ%P2dʹm&0v )lG֑fanm:8L7\_ hZ JˏyQ>vna`#zco@;#Ӽ|ԔƂ1!e3l> wܶ#:. d`<³ŵ![uG%\OlCPT@4FVUPx?׵r\11>ȯE*1%09f5vU\u6:t>g->G cMjxa=Mv%M 6ѯu9SZGbz4$-/k̔ٸmC~dּXEegijqM7~DJ;=XlmU$mljj(39 A^)۱m&OԤPQ91`1[-9{x jYl'lKabk%jMuK1;}@F vO;xc65nYf?u9&FO a0g:LD[SZ6i>r nnYYoq!vfkpnV5# )p<|M{Yvmɖ:D'|W $BCZo?c].v ^?b74|O{z{_YoM#M?t_4CE>$7ҍG{bvhk[}>CQAK€2sj~s:vxQ̏=w2.."z$=1j7z7_o9_I=sR~Dgw}w=t=)Ow%/_"|A(`hxǪwwH>m/9 F%mږc+땿 ݆w2[XvCyƒx\ds5kdNz"1yof(x$z8\ "Z'{9nB[#cm|Rrv(o07ÛɺcjU3q0NXӷAKTjSC\\S?GD0Fs*_|FpkϭwOf>Ǟ#em!t4P|ڧ f&K={΀16j}[X%k ޸@mԢwkG#g,tvbr|rLL]=.vNhTh!#_M`>tخ#Qb̝m>HSږOό2Nkdn"N݇ckӧ&Iq vmpw_]=\=hr8Ml FNXsQ8띯p(7~}dMq^5 3"c2$1x}kt6'4M8w&vNXvh1_0zP9 l]ZfѾB7 ,쉄CzMldKc!Dž1_\6)-NZ'x[C`>1nZ+Ω{f1=1vC`\~xGKozM: =.9jO^x/$>:ނuɽ1\ h6A4OŸbt$B_Y2ܒ Nȁ5ws>*m"d%uhnp ,m6! fdL1_]C,&oQ=vcfZ0gDk<߬!ҨޞXqhܖD[A3x8nfR='OG_ꭚj0m Fm۾ tjKz "*+pi麦v0!/^x~u^~Ҏ;3]!Y\p8}Oy;t]rt ף_Go}wNo)Y-ȾAXyy=9zoz~$t׾zы? _=p}ˋ_|$iO{4ٯgX-R79i&wb/6qa-cR.P_RyE?jh2g(T'\sy-$~9~XǛ:WCr&j'.o$q=lspL.q$ŲFXK/cp< ΁~q㏽z ݮZO>⃯oo5~'$xH7ַ^/}]+^{03u޽AHF#K:iVlA6t2&4sd EN,laksPs.~Z7-.1tJNqԆgc'gR04̭9Fhǃڍ j fLCw$u\f~0/:x8W:2+b]FfW6[APh'gcpLC4ɵlo CxVP7 ArAM:؁Gk:5_Ӆki)XJ2d:ěh}16}l&ӨcW̲`ZLw `5 ^6&/vshoh3DZ4f۞ tt= |ù&V;{c>Hse4X׈pSP'Ѷjm0ѵI"AsґEXf-hZ2&u%X88utP{47Tv bt1[l )7rF01,jqaCK;8Q}~ڨ%HbGY m&^6:3C뮰pɷDSWGhktM˼oB[`|)k|fhΓ`M:&=duZ}mss;6֬I|ti=q2QIg^B"£SL&u%L$[nm\~ "Ļ'XL=yV Ÿp\lg=o8S^1GdzmSnǻx< k~/ xKw|y>=/ j`rݤ{^-iY8tӷoyeklGyO$57_Wůt\g4s3G7cG=rp#CU7~7u3G/p׾Ny~W{>/ޮw` vRponiyӟdwvB%OǶ _~s759\w4bMyFkf.8 䱪uuLYc\g7E<=X55&4ſzzxۼ[= hm{Ǯo]'7d{^/w$-Rw|gwL=91y>7r#Eˬ_߼{^7VsBl ̝l0s~N+h9kx \>\akB#ap(j|=CY e"N{.ksx q%<IJɵRq3hb;Tlq8T>z_,,sQMq 轟sbAꌶ}=Qˮ'#Tyc7WǪ =w`>8fh,\-JF>?؛rI]ʜ8ͮJ,qS)*p\;N[kt:V8nFp˩A)E\'mZH.gs M'kcouNB{s5S^Rg ߍvHܸYG_'N~I# 1 `g ^D!>|U-mHۓǽ2Ĵ9α眩)$F՘>*sDK4hƿF/60ck=07[%mp H Vr#$,1Bd\Z)Ʌ~`9)s~FrY'n(׿=D4',L a c=g^6 К.<¦w+,_C4xHB߹Hm?&?t/ b)\ FA0%6!| ;p4ŰItW9wS-ˏq24O88[k>>mCqS(Qb8j_'_`X֝aVSgkJIš?t[ WY-of ?ߏZ`rw]lEn!v8ha5P+-뼆w 1gʹ\{9ϼ-{_Nϼ~G_}~|sC9n3}IJk$7z ueҨ郗2ucZ7 9I#Vc&/Sty IDATc inVJp 'C5iQʫnН{tߕ1Vɓ_r1pANYbwMc5oL;E=aÖ3dga|9<nt[nʸ.zD-kBsO<(oDrP3d;n,kaoq,;@&].Vb&Lg]dYk%~LWOd\dfU,0o1r"HL&>zGl w+vb |[S'c]"ͻ@8GpXvGص2- ann@$'g a7h*t'X [ '//z^0gPHƀ ZuM fPCg_E*Tjo}£y,Hn $~Mx7$g`vs]MNj][L|&GA09 ^Yj}mWMU{F˖u1 .:sODsn-ar:FUh)DYG7Fd/6Fڹ޺zs[ ]$'f:64?F9%:T6` v/ѻs{fz=r]wV=COԻ~Okz,y"#^S^ۿwz7Kxg]|~:Dw3x򣡼í 5nBr.Zy=zuX6ˌX;Mhy u ͷ֔7e漚}pP"BAd 9}gIW҄} cF΋U_Ԕ~^. ]lْhnfl=.93&`eViT^g)2e`XӇɏ5MSV=NWN3.'8c9!\3|3Eu׶Gb3vHc2Xtf^C{}e֘s8X/M fCH#~o~`k^sY~k |eL{\0d,1COBh8wqVtbGknCuh=Q,>N_㙋c}v`ۑ@3:uO2NP9t`"zh쪥uc!ڰf>ƨX=mM1sʯ6%Ky ?ׅe5exÇ? #Np3uw^.G O.fkj/W*eJ\^k*s/F̽x#u7ۑY1c~ǂ#JÓMׅrci \Թh V7qDX^-Τcv Mx48`ktBt63"PoZxĎggm͕D 9 NJڌ0kt@a$ֱzd |4E$t b#sb Zk, drrɐs[DLL`tΎc~隽Η:֖+HO@ލ!֥ƻ;G8>a_< _8C:~fCѺ2%hM4L$҆ZK5pXmp]bQdi2R\23/87rvao싊'&ˑ+h  F$$wW~į wLgG+AыI7)c]M3R/{zG}ˈ u0<\??cCUdtVs+_Ou oM /;Ͽ^slE9~¨[V_xk_7~>3?[;8Ǐx*rģ֩y֏cH kUh2j{wau>pwXcBa,[}`3aZ$(\v#<mY{ qL'Ĭ},ǵu,A9IX ZC/s__Oyrnn?үx]'a  XY<;%5+?N0#7=%H76my^Xa9Zǔb3lAM47 6k&S+͹ G؃Ӟg !݃=/ɖF;V هĘprڳ 0U&D-o2wq]L]RElCx|7^6WNHzK9~N|-ܱGys1v AV?6`=C+{\Y'6=uelǘdNep 4i(bkJmjYvl1tyf9?U &0 &/1)_(A8I|4l3i#T!z64pCHb Mmd# \\q>0{'bq6!]&2!KVn z8^gʶ[xȕ &r-(c+[L]iˬa>lάfhw$h^%QDfi45Z'\#rQDyJe:}%\Z{YbؿEjLtw=L?=Z;-1WMT0gl[pȺX㩹l=kkׄ9vm~ Vv.}#xZF&hjG>hȧ>wgO" +lτ:CAuBCIi/~5 d)Gc%#*Y(z}Ɨ6 u<;7![Av!/#*U\茞Gä,ӜȘp4&lk lkMKb "#hb9#.r0sp*ZXqZ$W1hRNN8 TAbw\9Ru_1Zw b1FGG\xٹ;j-;"ɡޢ./9zU@0@}qі\)l%[J9@6a,z{\y{e/>?s 9?<~v]OG^?#?vɧݛRq=AOϼ>kwQA8n=~ҿE0Rte]d<ȺT5_zzUlfzk 2pX=Qb\-{|q$ʨ-dŨԇpkybߔittДsuʑD|kG%_/OQ i?>ZIG=:ƾ"w4}]z^Zd|\7\19\FUTjl|e<5z+9upaO>+x8OM~i_8jWu.e>q'~>kP>n.aM@eڞ\ȤkC7\li{V{OPa/q}n=?ؓlCCc!OwragfjV8o?Yek]A48\X8ؤ9Kً!RlkDs]vCǞ\HD.=3M݃y%2?#K|Sh+_ *0yheGg}n-N*(30co#"&w ߎYo}9o%W,>BL[[I|ł!F0sX/7c_WX֦dժD_RG^IV L068a4LZxz)^eBV}v FÚI<|3U;b v_ܩc"wxIhcs9Bga r]l (W.3؊uҬb[(5pĚRjMHxVwSY{>1M<$DŽZU/(]GeW1&Xg_y] zϵgLvկit`b"q8Ssb\F{ ΁/ax_Zbck\CR17חSт)1'8ѷ򤮆d\da5-fgɔ0 zfp@gFxxzZyaԾrfZXj`\i![u[H\=r8aQwŠzVW۹kba%VCLNoir*Ϗc@95_u mZ7KN3BCS:إ3.:6^6\Sg.S<6bʹCSm *NW#@ywYScb:(-I'8k:Nkޱzn|O1_^7ՍC߻?y;+B$Rk-}o~?sz@7x_`HZQ7MH(SfYt?x|gz[ L<>-M8%:\kܦq܌&_Ր9W3EK A|9Q.<03L7#>7 i)ֽ96_'߹Yq/*_:m*sWw4HG$'A5i/ snc}1|I؎S0XI?9}ZDݞ3&X;G JjϞzLQ^S_\:/ĥ3g&Ȩ@/Ea@py^ۯ9T5ȹFcjc6Δ+0/pj7yI\vLzyǡf^u5'嘝uwXlPV |⃫ulPIL#NhJgUn g! Néeo5ؓ\uR0C׍`Udk;~`W0ZG.('ƶjBk=,nw=$Ej&}0bwIFN]zpƫ5k?5! I4>3O`mDK#>fه i#sN=bQQOb9ܖʷ?U#Kt< oYX5]V ]^O 9qBo{y"7S }d00~o4=yD~czaw~]r].eo72S{GjNF.}rt9jxc>kbV^67is6Vplp::3j=5^z-_ l)qʻ!@zJ{% !cOoFHJ9g>㝯oƯw97N}Gw>"uR 淼ox8q_]k߸IhLsN _x?ט9ronYf dc$H;(#Z Xʆ>$[cذ~3GYvg쪈Xל̧-5o0cO^\Lz1MWs`W؎>P0ZQQ~ET(Tȑ 2Xx6XMZ8ژch^\ s`>'8of,o|zCz|72^M+vqϩ46,y/S?qݙq׭AnJ'1ܜ6ǂ ic7V^琯q@',?D Kxfa\9Zvy:}sXx W!iX)<3Q6@xĚs:sJYzn%pYϩÍh _`gX퇽']*]dp`af50Vj=r;wZ/ i}#0q$s&V=y%F.>gfcF.chϩf Kq9c w)eq%"my#\'y'jOQDRuH}3~sp$Ծ'`¶MeNiQ1{9g>k&9>fô47'u_kUFle9:u;W](}|f}5iLove1c47Z(>Fݡz"]+ oۃSI{V(x]&Agp-vwc ]6-pːNA%+=J1ԺyX,p:\w-Kog`O 13k*(h5NZ?05LL+<aQ:>YGӷcX_Fs=sHjuYiyJ/QAGocdu Ȅs <(5,:gϵ7†b˵Mւ.: }Bf7Q(?f~YĜڇk'y`y>be\ma{6сw__?L޹ IDAT_/]i+ґS(q]GΉc/kpq<|d3㬙,i\ûDk(L%+upԇB}x-=oĺAMW g8VL^/1e1f\S^K]O&H\9ۛϗ(PҦuOmi&MGuѨMCȁ=:H._`cs ʯ ZrY!a03u qw|-cZb 9؇c+1XCcq; !)`|?be_ܱc^9X缱qe zeV/V?8k͇oG{$)oTm:珗\gĒ$VJ?Y,& qm(Ja LtS-ؖ qϚtoEyJ2yjbu|;EH%'e[K2!Ay\7G8{@U@ktLSVo2jS¯vd&۩Zzݲ T&a=g#52 <2H; 'ęʇ#zZGN%Ws^c]?I־\ rpNô.$+5K\2wx@\yatꚵ3aߩ{&Iap-gb|{\XWˆȍe78a h™uN`g>,׾g78]//B~yŏ/SsS,%1>aIME)$5zh\'j!GbF\3Vzc,trCϩ-ԓC}SEAE25r^prk{6g:^䢫̌ҊSt400K,}Es1~hhqd4YPkf >\͘Un! !*AvMH8An;'j;nH՞ f!%Ӟ6"|Xٖk6애Q6\M Co! ׈ə5Wc׏؏\?z泞u_yݬKx ZlL̖jbjd`?qz8)%wR;bX&‡蟽w%yׯFoҋM޶A18kL~5,y3=kt䜟+2sGEP8I류<[&΋M>>WnuTS=:^^nϲݴ3=nϻyw\\Mo~7zWY]oh+7x^qpdq|Lt=rٙ6؛NR4f8&gk5}ZYsDz 7vk3;Ha6+Fukc76+ætT&KHm+U75`:^<0Y6MCiacL_R)ZRFpc$P  =6JMYV:82KN&b ,mFch$9 9'NWnrS 7 83'2;VMO#@xu&⬹x27":<)#Eo'޼95CcZh4JG̀t3B0y-'cwj7Dу4$pjLc?O cBh,=5ѤeMhCr84'3n*D1k)'9Aqb};1[s4&>ʶz$lŭN'h"Ði撐 <&Q>:ʇ(ԓ~.DM{5|clطŝ=7\Ơi$; 7H?FcjJ_(^_GODFW{gs ưfOGOϵ=MӸr0uGLOzE~F" jY2֢͇ _+p%/>>Hzg.SQA R1Xh3UEbxz~կ~]os"d]{C,\ӌloW k!/@>PR?zwg7-i_Lse!Y͵rFǢcl.﨣a2\ }_{ݬ+VS8yg߶`c4{v ]/^/~ɷ*C7O }o|yhN'wʹk} ׂ%`!+V!֠[I}$gBMQ>hOm2#ѳ5)x 43v|7u(M=5~_Q7DSQG뚺1(ER`bg]_ݎzv "3A7?7؉&Xb.b\tV7|/[qpۜ}nk !4M)TL,sK\}= 4NSFNlklVlx9C/[t/Ա @8ةQ':G|ΌDw^t\߭ӡ`zZͮ '@N f=uJ P h&|Cc\[س7X 4nGFUXgl2O ,CV]&͵L PeM߲W 9tk#fԑ8 cZ kk!O'JGY5݄H,j4)Yf'Q(ì8L9/6|b} c67j?dٺI-+<t9<8l^Xpvf^Z<2K̍/,ؖ F̀Gbes?&AsJEtj67myƳtc،Osn,Guxybsk;7.0JRl+pyB*qqw5biuN³ SM 窃9fJ,X ko_E2xG2nV}9q5lqOm?4_ĚAȇpQuF'̲l=#1a["/Ma13QɕXozUDt宗 "pXߐt:gs>:d)DP꨺l&8-f3<;Hq/}4OX?mҞ b&jqrqxh]b@84\|L78/bsO>w_t/>C>L7w酂6k߰<.yD KNsG 8Ѿ?1&=75jgܩ'mS;tFLo8n2Wz J6[=D~ >c+?::58Ԝ=='+l '-XE8&v:f>c[bP#6x[8Cμj"^wMG~C^]G|gFl%[{yc-1\ *\_ǯ׿W7^/-;,_+ŏ/Rw 7?ڍC@ѱun=nH/=S\91$0|s.P>9rp0"}]0NJQ㛆w1=EB!}Zi,c,qV{J{bG*:ɑ`b_%s [q\{~3:&8입/9<\=> CJKofD0Pe:*Ar6Ξҷj_z _p.]?6r wU)9s96V[^d>j+' 0s}'g]ּ'At/݊\og!iaלճ r<=5Z U4"}c.czVGtU @N&=|F@$*Q)z"Q\Ǥŷ…(~7Z½28$PX^ :|{~0k:pIQMZNJK.Ohb  -z71HC:_&55.GY˧Cε%ẃz'O`N.5|S'e¹/ͲO{C' 01~x96Y?Z.jx35Z 7Ι|;{=JcύՓ=f@1hnm0678Į<8>zG9~s>OOgn{;7ϵA7w'sxVHB%: -\m0xnZàX N M'rg2׃kAG2fN4y`휭i1D¯5L@`k9i>z׉sk67Aqk@Yj=,l'-dJm>nW@5>a79~q(Q3\r0'I' X${ <yЦvGwѽV{?,SpŹFCV8#lo?SNwa$,1{9&m?MCԮ5)GCm_ɉn/ei38/JP 9qm.EjU%B&!u #ha)(R9wex ܽ~ydi뱙Ff$OmS#O8}UDI^0ޟ8LF E '/Ʀ㔕k1Numc| :6|郉wms@Nƌz07J,g1V.2h za57GNϽQzx^W6/lG!eu-͓Kb;O҅<60M7DZ=!+v1j{gܻg;ܩ5}Bujp_Л~tX>nZvnܤ96.ޜ?w&t#C?䃮~W~_O8G'|npqojRå'z;ptVȹGsD@ p|.7+z?*y]/]~;_oz㛯{իso3z5?Z]89 ?1,yx̿M0?a2Vvu}YFP$Ny,q$v!ev;=胃 &Q鏹|++nMcd4`c8tg^_z^<D3+1 C=|}f3;yd<`Go8T#u :T:%;}Au`g[ 0:C3 vfh \ӭh7u嫖p$g| ^ck9t-"]hJGAOزE B.:Ğ>̥DzIu0S0.֘Q49Cup枕(}]ƍI.^@S6eĦw$ 2&@8¥1`7uӱyφY6"Xl4sNIk9$ rCASs:0u3\FPԙܩ9Pȳw3'ZбR#9܄ /L|$_{rkHj3F ֵsz,z-}vuLC]`&?cܚiD37=oZnkyj<}9 &':gA5, G?uIwRiz!p`aC㹛TZu W8sZ\gJd0Gٚct^q'\mvN6k'Mڋfi^{][h?CV.L2ȼ6Gb^-1Z0fn/up،ɝ^)  QclkhO5%9xUX;z xˣamɇ)\$g8kjG0wIZ]{ndPK@ I]՘m>\1}h,![i! "e4/ab9)t6AB+vٲҫgޜhG9LLu؝/I^7[{{0=8G IDATW0 /zj[.ѣ]p$'~y!L9P_0>ɿQ9:[(Ɯ@6i`տ#}Kb̴X.F^09y^s۟yDXwh3ԗ3iZ=)s7|W_F䋇\o0őZv<1q"zX3s߱yepA'61bl<ȐOyw{3yw>x_ߨqձJ*!Z -֖ZO?EfpB8cs,|dp$cS3_k}fgx}1vO}-ɲ BSgM{Ti$.9 >?+yG̓SWrssy},aR<<5`ߺdEjrDr-o$%YsG ,ZR;Ljg]&>kÚ`E([gcXî{.s!إK_y[&ӫXq5iw~9ʑ1lcN2;6P0&WM1Ӑw;Җ]YwvYӰࣕԕMkjϋ*/ᜇ{|0UY υ+~Φ @=s&7o8ޛ%,U .)}lkV.ӱi.WPFpxp~P#ݜ |M][TOџPO,JuCrZ}3V `1Rr6mӃoebİO+HsaJ칀m\z8#!qhL:Vݷ̿u$˔2ALJ -ʗ0J_g.ۇ R? 5S;O5}]b*csTw,h,g>p3}]]>x?WO }@?N|aύC߀њTU?VEpkq#ٶo F+d]Vn{zKg3R'CGFp J9p1闬 \ϩXhx~){4;r^{mf)v(# 8R9T|Հemlhux郴TIo1=O#{yN RU#n Soy[}x7!|`Un;y[yϼ͹{eh4$erk}3Zχ3|dEBy do9 %ΡqΟ\L _82"iQ;3ϕĢuYo!fc8$/0guAu{s2uܒp=NL7:dvhsb8y繳_{wt@}5)uphbkji!,Лa_`s9,uqTy _Sv:Gpja:(OS- akʭqf=y Ĭ̞voljKOmMl./3Sg'~&am-alVVg˽S"H(D-SQCh[n"EXI%j(hǶHhvR1mLՂ"7rks/yYs1s^grN*+L<14^fVe;gTi9#g-s䬁Is\NjM6c&@4_UsZ{$\k̈_,S9\{ddP4b:?8ROC6vUzW,qk>Q|5d1>b<2H]$5wcOl/".5G엇A].4/6[O&a/l&^S*ir,镚7)x!:aɬщP_qZ5]zY`ysd ]=}OV yo\gkNY$SısX9FS#nZp$jH5sh as:#(O+mrZ>RfV5{bJhRp ;&io)?,Kx>?<߷^+|Xq383;<|#q?mҟ:fi0ܱOmțcZo X :4K}L>yHŲ!}oO1Nz6![ _p6K+??=ސyc<` hvrgHNP-y+y_R6.4ɇ`z: 7\KWkJY. `+saX|ɇKzܦ?FϷlX Z^Zw|S>>zbn@G9$(?xOxn:Ovч{ϵ"޹z7SkSUz˜rG+Xzs& (@HY~ֻjPk~c%xNMfLhĴa'x+IEwQꙃ.yƱ# W 2 |c8W_{<)~~>F䌝]Ƶ:#YM?F`v{Mn} Rw^7t?6N`&y>!d~""x/b ]-VK.z#'8 gLG޶ro%/α$23M~AM7-uf\h4.]wO|HWsQ#,'ץ9Kƺԯ}4{ nƭEx .^?Ƒc;acy-f]aאO󲏡d V42 esG-)IOvԣm4XRwbD#ꡑg: a6(JM ߓ:\buE\=NInvi8b"?lDlm56BrMh}j?[Q!9 , )@FD>8ͅ<[g43oW?r l(?ġ(x>Oo"M36nt 0" nBWC1I41Q '?r(.(V[ S4Z0.P W3׎ ''k XO\^81<9-*ι Yj$<:#tF(ҧɉx&s->lƎHjlձ'lGZ]Wp99@@1˙}S 쑠8\.[юrRHdss1Ƭם/5!S3qT38zx 9b[cJs\z5=yzwێ뿮ǎn ; ?a$#2J뒍|}< ~~4006ŗHo>{&v:3:r{z<6Ap?\F9&C;nM–=dk ?Zx px??x[uם F\x0ƀ}ȟ? n,ϟ஫swx7J>UlrW5 ն6ꝩ?z{7ޛd((A7w\ Z2sw4r^H}X:b+9z??{/V5.`{uќ ujcx'ő1Jʾ\8wϪ`ElPƇ\Z:%S[b52Fb]q!`ѵ笸&2g.aE>ه;00ݺ)r~opb7w>,uqM/ew=q]0X^"bLt5^71 HsP/wr?k`Xbu.{nC*y} A#/J;'b]pr#K~ 65zx~<ǜq\L}H42Fi]UKQsvlxrfnp%JCgsc=kJHM|AAćuw©5%J_? ζL odt.*c5?S?ruq+GmbhƬE`/F55Ot% X; v/,8 BTZ0E+[A|N^J̓HLE2#ecZCtv3 l||ElI3.Ǝ{W^&5$45cg(]:ǟ` ./…oy{l=vȏ7;V]WNb2th^_䣉Zb'g#|ǎx% dsyӻi=8;'r")gvb rkBq֢bΕg>]q?U]q׹XͿTw2kmc!@ZրQc5]9kcP?c PxpS%@L^˻Ө+?P@F"W8Kdocd]8ट0-&5 QoNBySfoN`o~'?y87'Z݌FB0Ǟw ?=V5nb!׶k&KzJ =iyCcsX&J\lDLƇQ j̏+\9?Ξ[vඅ׸鋉:O\#xVżt9^]{EOUt5v}G8X*AaM tH\gD.b 6VU\h&SuX^SKIb05Vf3./ƭ}ܩdنKڏ"\loc] M~f hp$riE!:7̎GZM?>.$}8)9\ %A;&ɋ"=jeږ c\.#-yf\q V{p(sVuh<E h X1;{boCXTAh OC8~b)"C+ cZ0\p[Záb}t48K6 RgV/seZpF?Pi݈E}3X\ihnSH9 vⰃ>8Ɖˌ[Y^6>x1e]OՇU][1@;'%+s3۵ǜ5\ڸnNTޒmxџy>z7=ѡ4q9rx}iO~W˿%ɻ܈O'nSIV]C\۩ύıBjn`CVpy뀑[+}~ ۸@m{[[~@qA<{56g~8#\?dϞbE+%`sI9s}8ym !3^s_C[]#qu/|৴ ݌;<"v^ظmpګ%nE*oy_׎>Aay 7 _wKOn.__7nczecy~n~>xW~ f︬zu)uDzE|_WDy _cxbtxRrRƈ`UgџbFZ!2ěp/ns7k$>m(FZbsܼf]8M?p1̹ IDATXa4&&ۅ[40_l5X^Lx`VTO<.8?6B8cLDi.|l b2aK/911w%j9p7mP "\N>;|& VƵ. V1<|nlHN䜵Ô}  $+)@n $/&^m#u/" oۨ5>b˦.$BP\)KZG(y$X~_q#?1=Gk g ld4gO}6"c`+1J0Eۼ {u&kZyz<}ӟkA䍊f,u0hԄFUJ\82|xn3(wddzܘ3x`*>;V G5A8$PsM']#8;8cMpd7Wg|<.ğb+Ɉ]ד/pǑL$MFn^42&D,SGž<ӽ/eWmdBQ&vq\p֗xLi 3׎SO@rl}!9OvVO625 bw&qK4 wnb6S7}`_#X ɘkA8mK7s;?k i3A\| _J|#Ucb3zBq[oDK ڹOc /Fpď <#6Kĵ 8?>!M^awxO]12]zeMgvDǷk !B~a1.q̟i0m94\NT"B׋6rW=_T{b6άu{yN1sΕejjz]<|b5Z7tm+R{/|EO:y(EJLYyͫkαFXH#9X/G$Տ5@77o$w^} нprS?^©gE}o.wӧ7蝀}{?~_n@m HDcC{p3t#_O}3zGM}o"dl{c߀Ѻݺ1M'$^jɋp;OS '4*^|fz;Q<471š/ӐO|-gOuHRuc7:qi}ٔn)7& ݒ_[g8ٔ OknәSEJu){los}{Y+/}m somJaN|-oxғ웓Ic![ :<&(cH\ɛV:c,4v]}`~ўkfi\S,fݏ_{q̰;KNn/j~A&FdI9jN;Dbnھ3\Ȏ[Ħf8)j[#ubo\5 5>/y-8E2!85Xbrpg]an#)h7k:dႝk%܂((9:$%bgN=sKk lѤ~ML&eNzz}Xz{2̝des?>Z ɪ朣(YI҇U"YR3in_(jv\<@Sy9/;hH MlXX0\s旀<0~J.8e9|Z7WwH+!]Lg6yd ;SըK4:\h` _XҲ8u֍yQe⑳l|cP^go'~Y|?w/\"^4UF\)oFg<rWJ7n ;tן\d$H\[cpM N,jca4dsݸG#CnjE#,md|xso@Nk.;ku3\<&'ڹIFKG5q\\;P6[Di[m8XCr ~7܁{1OO쌣H?9kY.0u? |[W6spO!`8ՓUE#k_t:k,>us)u0>g)NpeZH^J9˹F@_M%vELDI6z%`M.Ə>s5=+ּ['G?Kl=mX`aa: /b ~e;/[V'GSqa__W{'14KkٿsSΎד~ꪙ`Ǐ ]Bs8i#|`Oj]zf&-] $cJ,ٚ{TL6eݮa@`hV8܊L~1ԬW`;-wgpUe:b~V ߘ.X.Og%Nx sB,{N,"@eqqdZKէgT:xN/1L3_ :Gn1ae~9z z$0K-r!bl/X%1<;]ڈ Z"N̓rWu" x2L4;e= =XuKrwH|:Fc$_eXGћ$4ꂋoy'?}#k]9')C}&szЇ>>~t<[?sDUu5=sQO|u{ 7t@şN~sn;'pkջFAM[nx?xooKRFAAfxyk:{|oh`ۑ} jv/G:i㛉Rb]̩de# 舫r_}+Й XԆwqaI]{ܚC|!i~{xM>5Iz7VlZqW 2~,(Zcn?xU_uǫ^Mu8չсg!ku:)OpF brg<sDmC57[v_j<|}Ix1Њo=vlǷHsu4"|㬣,ʗ>1Æ)ybZxpNVߙW7G|#i5IB$9T=EƆiyaȣF}Svrkye<̒4+! dWֵ=MZbGDu*j&3z;G^SYWdRC|95[|M#xBm@Tgy0u% zZ?Cáxl4ܚ bocqp'?A`o,n3_`ݳ;)"kHg ɍ Hj]Dcym:ZxilOӋG 3cNyKꈃnMe'\6pX;7P)5F^ `+ܨ89ew&j ATsP(^ mr]lyY ,` 3S} q';ͩY AéK(0@1"5mu],Qp|\Q K57o?0%s\$9I[ܦ;'e776TcbTܹYx1ۢۦ `n N4EԺ{z8gU[R l4m\\׀vۣ/@댏Dqg;8G9x9kPc_}FoL9('цd-g(v&2 }Zs),Ǡ91j42nB2Z8/Nݭ[v/PXBChЖMNrXx?y^cg9zjdaM*,ӨMwOzE/xԣ>G 7K Fh; Z9Fdp_ه~]_S>R2H^ESHd~h=foȀZg؞6ց<Ͼ;op^U}|7=xCz<;/{s+Z5Un_g7 ?ϻG=M-D8IVFj=yqF_%7%# 'l= /rGF|8Gi(֩}%@Ұ2u?CrUO8!<&0اRH`Ȥ[Z|?Kyuy='{ (N<ݯx>_OП]NL>T}mFx,cګ|经W׼O{@}X!5"Q?#H cNJspƶq#ǀMܻp , ہ;? ) Y̗@ZSd:s$ge}Cp>>u9$.E"H0 B:ǖCX䍓b5Gd%Y9rM8 D*P@>ᓾ?k]_cY]ضqTP?\g&xzXD\揄T08(7{:߹Zuw8(~Wk"Dz$+WuN%|:VM<<=1-(c~ޖMuλkXEkcl챇9$g:?߂{aHӇ# 5 y+N6#<& X jŊ8UHj/WqA`Dzspjz 9-'Ē/4熎Iz/BRik,Ue4COƙq,lZ? 0\tȱ4vׁwaT_pT}Df 豫}ds>q0 { z7O5ݲ1u(qĮZخ>;IHؗO:Ol8&Dpɴ1e#){{ڂ O|V]WrZ/B]i=0'h[iy,a1o6Ec0\N2h Zݠ|<㛿qꛎ e}A')i"ZVpO{+O0^tGMNȎM/y?<|9_E_p\\nG $TgIփ|hȲtv7;9&'AL>< hYKu8/8=McɽJi䡺%fϺ(dU%]))g !;DA qX/Ko7]wqofrN4 v{x/>WoZu$V!q@;nΫ'w y؇QXiydzł8mǎ[3x:2n#~a|0yb[ i0cήU:qb:5l 징D}~W;vQ9(Ai[fXR{{Zj/-Vclx+%=q㟵|^A_~ܼ8ogGqY}Ldw'Ӡ;mdMck@̨!qZ(_,I{\ܐv3 mrdxb; $ 0Ă5 Z3e"nK0_M-m ~NI6BmH%ؚ/8k)yEfYu]>5U`tk79OKmٞ֎^ oK⠪0W$7j9Oېܮ;FGsъ1>"ê4}Gc =My!B)XGdȖSXgpX^r)C`u^:/s9 \lZZ;(X^;ӂb/0jԾ1ЇHNU__0ChP[J % nbkIŧA҇'vT1 ]T[Ќ55԰D'm#RE.2"Ya q z'cVWpv3ox!x #1x IDATL`uI}EnWx/٨6e;G|_wP ,=~JoZz[C 'ǎncjjvM쩅1&~obo9]4 U\ÞH:ﬥJ\2\eZ3)W#q 9NH«uxd =>#/ lhyHƀ$׀ab\׊ Zs> љqڰ\ l9F|WC|N=RǼ3wg=f|q0I?7#7Tyb!q5&⹹W}V8ԯ1<"trAb"s[[A?őg)z.0 |19%?p2qS?|= 3k{o~?,}X9:u{&Hp8Q͢88 ;VOlz7׾W3Z puD&9ƠލLJky2ƽ88 M@+/{[oLs/?ԫ>0w͕#19LD6tMRIJ8?\!_3eo3s9y|2Fr%jW~|GǕ˭n39&!nW]Uky2;kw?绎/}q_SZ}piz,<ku2=>vɟuO~f;zHasܤ=F'}qn\0F<3Ӹ;h_٤N_X-i+ga=3IN:87zsR2/O6yĻ- XcKpT PѲ)8;I,Bce"Yx3vpXҭk"m Mfc~Ipc4?sh k ڹq&4Ksr0<\8Ko{rJBYBz+:< <БA! ܡ6f mbX!%1u]{`a5avƩ儣~1I+gd&9.42,f9Nص9}(0Sk;mƘy[ح2koN.:n2jӊ;n+tD=4se pPp<$T>ݦXasb.06&0by \Igu↙|ן&yƄ75v~lu\yLIi^A'37zcY:SRxI y.w&XoYFQP60 %A2'4|Ԯ HSKY9GLcnq0918G q5jOuMJ,} 8蠥[5RrCwW~v0=M}2l٠Θzؚb2DFXSwbP?\@e㫋%FZcWD|Єej25w϶Cc%.TGH's-RS0+GsI<\/ƒ9d*kqn,4$$v@T`:A,'\R"lZqUt@3.aU3op'!'f@ fIL̓ĜV"l0Y`*#憨g  T[k8&`$rqүWHej<1њ=#rm.3^.<{&j/J, =Lpro*2Yo؞ ŸIg=O{^1~G&+Oа`ȑѐ-И~OOy7__}xKB7n hs@LJ5\\87 Q1Mᵿ{3L8Vr  Y #s:_«.I|F2+?*gR1[_d,i0i$e䅭x.4MZך~JP:I0 o g7HV|Y0u%T?/Fշ/xq{)Zv=)UTǠ6kM[ox;ޥ8~5dTs> 'gXE^9b6AAzL-Y.ŕD %e/st؃o|rǁtnrķ8QӰd'Fm;FnVBI=d&cv}|(Վwm7rY!s4+N!0 ]NYC'6lz:=1L'ÑOM4kiqP2v/^SɁ3Ly0F;>,7h%?M#׊q~ɐ#Y Sө9/[BN$S4پ66:pb"2:mˈc8,\\9 ۉd3O⋿5j] _Bxb\ }nEivJG ʋ;U cX( ^IEF$D yd[CkP3``jO*YCml3NL[y3=ˠ2a~A}Sw @m\>[X MZn?fE&*DsE&:#5!jR"*'L5Z q>f8Dx:$' wq4N_, >}k(8Hnx ;c}fX:kC9yT rnݤ w7m'=6a(kO佐l2 /\Nc Sh'g(f]UqkBB#e+lNWMj7օ&kٌR3_<#Ql.Z7UyzԹ"[ ,(͑y%w3:N>Ef hrp'`CX#W狥氭S,0H4O兺68R1Pϻ%.sჽ_8ϻxXa=I#B$r\ke%8R?K^E{3fN]8BrW@XOA}ȅqԻB86#ysb7N3KɨkI-Bǝm\EEM 81h|a/cMq;9XyO~ǽO} =%VQBSG7o{O[nR/n$L=s .I By/o %1?jX(wر=2; M<.}S@խ.!KynpVd"]Ǽ*Ņ&1LsC8|2&.{l ao|5gb6]֫~S;BVýrFGgZ:qZ*~4ׅB` Jڄ._y&?u-vS!/S)T P\Cٚ|0cqZZ^& ~m6dH<c4 C> o,rh3c#,+;L eVm2L,1~'욧@JĶ2M@ g,/[786=s 4aցӇ'A7jМq+!V P= !|>A8 ` |)a[lꇩ9TZb]& 2tp  2Gch߃/AQ' ~΀o)<8[yb3þr]A5`H3Z냊qy2 8 m947O|cN}*Ȉ?7?)O=x71:ͻgZ@Hf/^7?q~c__?~'~xrnRkϽƼϹk2r2sEYM}o1ƅ ?'ZrŎ|楙&bu pi=Adm%\c^r*;j|z,rJD -4p0Fs_?u=TϱbIxW{zݩ`@pB=ѐs1vا?c>W7kows+Tezn񎿟~_|6&{ ! pK 4tUw0]` !B8HPgce /%hȊ:SlJwbB*CX0o Ҋ@ZÕhIXy{sj@³u :5rhF;&9T7yJm'y2'|dk}N懗 =Ǧ[$ϓwpmC2:8hfL^,xe^/u%Y$;'XcX#hU3p1,:H^ G2eySs8&mN f!=ANrCzF3'e?.= ʞqrą);\"8"a=' @{!;SDWŋ b2)NMhxh`V"31x㛈6Ӗ[:mJㄋ5iKd)Lȴ ðsCǻ5ծn )X# k|"}k+o9ȹt$gᦶ_Ә<_n|L"{#5,&2zɖv udDh aQ0ݰ i2كTΒTKǿ1^@z8`v, dP~\cXLeX8HIa8Js0' "buAo̺X_WƦs|1$E,i撡LS}mu2qtN/ hU"ğqLV[D%nqPPԂqJ%1^$v^ &L8WUZԎxxD,SsLARs$E $*E5&23 W?jW8p_LD7h#P^6a6 Uk}.s"@V2>/u2/cf22WuԶWQz7CblǿBxH6 NPAti%QEGSXqПq(،|_F!X<^!%_ebMAt|3~|Gs_ \H,Qz~~Ȼu]{_돯~ߝ ݦ N@-7T&e2{Np''֍k`kGY$ YƘ0&5v}$S%9 RUn16QX=|K= <,v5<;#APd>%$?e㺆}i{@ n0ogQcv|/~/潜# (X9H(bL ӱys(OW!W~ր_˕\ i! K=qjv^p]SOb *5y±>`u(Lsr JzOFrS\lx35b{F߉ -ɿs+!Dx18c<89 :c's^o$.d'ar)dmR샑mo\҆'Fd Ԫ4s0? 8'YJ r Ġc, l:+q \vgNH`M6|{Ukc2k?4RbnFRNUp\{—1l_{hb|!r|4Nlv=,a%6F:lm)csoyHIԮ\Ǚ۟mݺ.kl'9K3;RHAocO۹kbG?rt'aE D&A pkO[}WPS|?3|1`iM>W_{<+?8?Q nb殞^VF ȍXl<'v|>sr{n&mdU!tS1Ho+<❱2T IDATljRlW3H^abh92,% VT{Y'ۧ20];,F9 PC\9 y~)ZGВGV\Ged66/b:Dlk{<E}mrGǑ1_2? dyudW1%gW ԷcBCfrf4b'[㹎bkN n98рjby4wSဓYQxœat6}>_OF@6Ǚ:42v?;73wKYtF4fOQbO֊!" )mc*3rm9ɒ~'sb6h:w^Mf26!dI 1.P7pc/Ӑﭨ潳Vua|#2pcЋֵC^w$?4*ƹ !Im&b"lkH>.ƉYoύTQPKvBS /gr^P\71ʺ0n_/^cjm437O?} =N* HXF'L2F9z҈0/ spwܦ!>ê?ue5S{mKPyWJLtً=Ȍ&@HƄqxރeXr+lܸޢa ryzlWrw\V2?(5DW^[u޶=dhlbMHyNO2uwGVbN_LmVk~0)1;a!tBc~S{tnfOd–3~K7DyrH~hoaȅi\ZI:Cs0Zx=;9:47Y l[H3xFL!M:: \{sTLR n=`bxsnI(!\1Du6@Y5YH 8Oryr'Xpnmav19mbݍװkbr66&)'q:Dַo;#~OD#"1| ܯu_׎_t?]j%PFpA 'v֘ѹ~ )Y\hWx`HX< [egBpf-70Ԃ1yÚ+F}VW+L1yYjA-{5;)fVFDgf<ՏGco='CcQNnW4|~gtq~27oEHy~pq,sUudo 8ur %WGA3][ՍL7AOA5˻/ ؛껝}セf $@!!4-MiU*0x3ZU-C 6ČZ A@166ؘ&Rctz;sλ~{{#80Gr%f?S1`Z`8xnkbjKQo.x=r3~T,:dwUDngn \RCxR2/vT~gqc|ץ:Z.cC骯bUk[V$YjͣSB(h81 o@iGJ:4%Mrb8~x_7Mlvv.шL11}</kmD'gBNޏHSܔd̓OǜGYEiJxuYؖc؎8µ 9:׍Zv_i]r@lℍSqdz0 aLh+p-,tLwe̔?n@.kܹؑ'~9S@ma$sDlk6s-)tv|o \^~ĶMޣթP,/+yXk\ 觋R)I^7F.`q& gPZ3^q,hWQ43=(% G5/j,lKƶȪW Pf{SZ|e69rAƠg 3vz(X1e>I.@h$m\^@g ąy}o22֣=Xk<ͧ_ q9oI,OcjVrcnNՏEO:a' 'b 3Uol4 ̘ {}dZeJ_4m` )Z:ahb`|#.(wb`x\8JP}xsAP>H078ر/b(5Cl}Ns-ȵ"d+U;>󧉢 ַ}LKkjk}F|Rq+wL'S3ab$?yPn.?yG}_Ϙ\&Ӽv3tf^k^C㺩ǾwԒzF:N{t5Yz +n4h;̩mK'5wPK<!D@YǗ}/W34wQB}N,OҶ^*31&R7/?<21[' ]cw\V=[6X&[<א mHp"? g7D/g1: }F\7f옑r-%S.ȅf=&Vk]d N/k7c6g4{k[pki6A`Gss|bu_+OD& `׵l̊^ 6Kj`n c%]c 6$ O=úf}A,ժUe=`$MП` 03fӁ x Vcsi߾d ]0)usr zqO/s-=~R\yr#">(Bj hSC(d28qϿ|K(cqo"+U6Ps^`o.zG_/t#wa=p$9JΚ;g~I/ |}zGȚ//*B^8U)o%1KT^r73p'K?s !^a#8GrskpqLyX P~Kru0 y!ؔ HIRc< iAdn!Om5ر6?GcE6AO3v '덜}W~s`w8Aי9z탑6# n,2~ȵ؃/ +7p9F!Ɨ9A==-W Fmk}\:C@Zxg\p@7ruFOwi⇕sݠ;V8 4Gu-*|{UNNm. 'L>R1"I$w ? HkxEn8#n䕫m; E12|c;nPbe[!RÍ_^Vk]KP}lRLz0{`J`9&Tlk1ֿE*/Ĺ(XcJޏA@ԊOwߴVaDA1~do9b]e'˭bDpdmM3}|$u Gs>*uZ5911T~#w/PEݵbdyhl,-nx62%bg H5h0'dq+|g_ӡVK##qj?캨P\#~l RԹGh_'E YlsnU.+5Ϸ}/m&PG%?.WL2ٞ7Xyc;'P8Q#^`,szoF1\jx#Zy&|ȔF?׼`4Q;#'ϜWoJslg; u=] poXt9xW/wCk/R膚?ϓ;ucZOw%Vl!&FN1S9-/Ǟ#[nt` e4DVczȷA0nKm\\ :F&$zEh=(ɔ:z1h|\A8əS#j~|C}g;O3h摄 3bQ\1]?o] }r#g=uo4f?p|W\}=呇g?_|_k7^?N4׊cJjb a$ p\8FΟ:Y"0e;la' ẖ i|uϻdpvX%7V@pmB䖐w}؇~5rS}~awkLԦH33Gw [|juN<]/K09!G%(=rWɪltpuB?{H8 {2l-qm̳x٣ӏӘ*bS?CEX "5`Y欛'D7^=\8\`77Vq 76g}36mkl,y &1G ͺsWg^!P=hoqCغŕּ<04Glh|chjY< 0 &%*QZyE#yɹ$oM\/xS3?/<ľKخԇ1XI!u}Rլ͘dx/nR|n lZr}Hɹa_ 1v8F"!/~V'svu(0dq2N(6nӻr\rau #? FqmxkLia`8b3\.2&j]t7scy_Gcۺ\簏~n\jy11^|IFpGű'a;8m9o٬Bo~ kTuIvCmn֌&yJa񡁑;0vaZsG>'kI YhQr .^tIE0&9S IDATNx|tQv7>◽z tE?)3v}=|;=y}槽zKk7~7]o\xw3=ar;v%3YmHk~7khP"={'ȲMq<e r @5Y4~(,DɁq."^}җ]L4r[yΎCNe^cd?1W~?X o[]9Κ e%xUuߓxPF) .7Y ]cٷ_mrC4p&Ch0eަ2`֩8F"Ge|95!sN¯0V3 :qGR>>k6,fJէ:*N)\0O$|ÞIs8l]|$ů]TyWVn`2o吖Y7HK2Y , 0fZh6^Nb~$i<ȥc#j~Xn?k96c\G\yfض&۴Ʒݘ۲-]aO5LJ9yYCxǓ,ƌ-B7wJ-8yHGcCP[{`wQ9p!կ~'zwCݮ/_㜧 G[8CRY<ĐB;WRA}H>cMxbv:pKs;29'~µwer'nz]le#5xp`fF:!SI\/~~aDp Ԍ=.!sHTƢҘWL IOӖM[/[Ţ'xH1m%ȋ:wlMQ= Xh 6hYb[XD]iˍ%3B5\!l4ycOBM5 W`n;k m._e ,ȑNIR؍ˉ19*2. .p#W7m_PAv_o͜2Djfж̉7{ ;\܆c罨Z2(w-] 'YtcYBDzf{y;Z3˱uܸ& 1hEۙO$q2yJ1^*Kqv 3ioj̜:,|U!2Z'Zwc+ hed;H7HBṽWKYBIg/X.!y%ڋ6xĽ]Ny/zKT5{<+-N.PI:GV):~?^uʯ ׯ&%u“|A*!V^O?b<}y 11ʹ#0uo=u]aVZc 5pӀoH[v\O=ys^64Ҳ pnj:muЀ"c;OmC}__/ջQ?ztn,'Scw򎿷5`Un=V—=CꨉЗFL04/E/9qz{-mFs46>(q"1 ~.`.iPi\$8LeqԼzO @+->Qey'&56]ԟ}&am,P$qfQJygxfq:!ĉQq_ײ_J.~(7kQ˜7n1m}}Ҹ՚kh#.U~y?xfgV/ ǧyBc^iuP82x@vy[:&xi747ɭ\`Ak4ϭO sv.z|n[$n$+84C]p Sjk"6~yR8%_柂W~ &;*vCKdqg10IMå>>Ij,x9N1XK!i{AEWp/ wKibb=#|[OL{iy~{sT]^a<_^{1(05Q#)v2Ä0`A-QΖJePCn'Na֢/ 4<&D%\VJyFNL`Aܬal'Y lMV wmCaw6h&S}L'r/*&r)rlAS抄 NTģ\knquq];9 m;Ԏ3uoCs}ۏʛ\cQG+RAhn8(srbkk [ƞ/qVl0\TLjCA6hf𹭕,! D D#{8`G\e;ͣnXފ)Es`ߟخ|ʒa<؉cWAǩ+Q/qĨ}'_, 4#=L/28>xpX6G_cz{PfSc$~0зؑoV#R yCBX&!tD7eΟ~S'R|CT=xM+‡69ZIqpcH<2Do-S%| .Mi[8@#o_)ZVA aՍOsLnss?pIM;/kH-N?6>u^5.1c1e挊ܐk !1kQ#YG /›Y0dcȧOA0q`ҔtX#[ߠgENJyp=h;fOIOwX~=ԊN1 gϺ$S̷gB+ĭ?f lXFM5>d<<:v>c:#TqthױXvdq1SujU]uja]#O`ps({l޽7zy>^|#8YM_'RCqL|';7]u_ ׯ/ 'ou~W Ͻzsuѧ<0O,Lv̡{ |x5Vš 8+~)la9A-:o\G>{l.6]̝p}=dLRµqӔ7Vl0IS>: }4N정62!/8r^ oD~b-,q;F;|mpX漘D(ˏMc2:s3vw1mP-_gHL'ӌ⮼W|[zCˌM]7*}0i K0;P넣l9fN2"%3~݋p[䗚G. ]D9.nR9./ uq/.|l5냜41(!wjXxbƉNo ,jӸG盛[7U挤 _l(璓P1 XǼȳ 7vr-h/jsLz`Q_4`‰Pjz2XG˛w5L1k^U&_}<&Ʈc!Hø{bA8.@VN%*ApvA`lQ'}d/z1  !?ȫ/ ٲ[_4Ky? K (츹FxR O܄#a 27$4t|FK|ֻ\~շ]7]u,]{͍!<*lmpb|8Fe䀌}rkR{/J3CllΞ#1<Ä}a[{ H3%0ߠE0XX {ogz߿]B󢁏vܟ+Ս?ﱁrM͎Hm_GGm{Uuq=yy֗7S#HS?y.^T+̅w@ 7CPzbt>4׌`ylC}0.5(J~9N{{"?a<*/98'$J.i~lc-ʌm+YOhQO/ vz:1u9nݸ{DFPD +O}5>礲ZV2 ɫwx}lX|5ga-F?`e4[C- [qiXqa-pɶ9[p\+w-,}Ur>áTzHp'O.^mm8j2_;&vW3O-%q^A=Ao%`m' Vvd<@/M [늟kk>#om(ť\Ղ7xτe)WME->h \c 0v.>8 ff٫72\ny4vkD>OIxnb6&L8iusŤIӜ34OEpB aSZYt3!3S_5ZÏ9-NpFVe_YរSKdlͣ|b[7C^$ĤPy|7N]e=0tF\[Ab{6 xek`zR.hUuّ1F/tz8`Gn,`p3 gxe:t-/]ȰG<629oKqM//>S_Ok|0oymH{lMgFG_|7_[[G?s1o8hPy_s.%Rcd{yU:5p, L\~RQV0_);Sf0$Ջǟ13&5Oo9lfrxn̶0>bV}\<=_4e޾N5eW7x?=60Nǹԍ@"e\[x[̽m5FLSgPdGZ,=$y:ɽo eo;P_ GK7|:uqB1/O~̍m;YQìvGcOnqjy Z?"K<^XvrM 1:rυmL {穡)nƳѥUNs>_Z@{ Fl}ebtO262;@%5;y|^(GǍal 6 4 l ` X.uq*D0q #}J.Z`s֧>{a#S[fE ^ɏD{[9YySH_l.Fİ뚦G;rI XCM~v1y|Z"/O^#Qu Ick!GǸ׷~w^?''wꍛ,)&$>r_̏0pⱖy{lupvcq%_77 ,r sp֗{%8/^ cz.'Il+-""ئ"1!hns8#I_VY|sE\:qe8':nF#Qkj:1lHrl§ f4%Όi|>vvI?pO|b4Jm]9ԯslOeG<~emgI ^,ە{9ݺ^[~R'̬9ٍZ_ui;W~2.F8T$ 5{ZgLsBp|иpEFqpM/΃!'?, `|Y F:xcJHj6ȝI֓|€ƮdnU'UkΖ= ح1XGӮ2Gs3#0xaw-'/ǯp?|@۟V 5ylsvk0a}l@h9JfLxO  n+arUݼj!v=SCSbTn=f 5n?qp(cD<jgB틎BcV+QiӟI7 ?L]q V~Eǭg7X:J& {Hf(}&ùhb~I SaKm??|1;6>A_>0 ՗Z>aOu!j\ɭ{]Ɛ}91n}-kse6p6&8ą܊ OCNblij:H|^㘪Vju&]z ߺ?|Tdl3c 2?hҊ{b3πA{'.zρ4΋4Pz C};0ʼnߔyWCyyjh/3 lo=F3vHhyїSXiW[rrq/|HvӁqy"3$|l~atsޏ!9ՑGbj`̜Q +6s5vcx +rN\gȸ|Ȝ^ +G-&e^ gll Xnhᐣ75뛋-4‚ x1jfk;t-˿K ~}IϼF ث}324 6%p#t#?#oor 6@;.q.;x&KO;sjn9}HI4 ` -'Sĥe= .Dqwb-"7Z|7oys?^>x>+G/|47 Ox)@Miٻ&#x}^|իf'y"AtxWi~&= )^_) 腡xnQ ɑy3ձn\P/䟓R 5g+UXscKɫ62&"X8jSMH١c778жi9%͞60ns6`~bkL^+\j)YbP6kZ#k9μ'4x[C_B)z,PF@~F],օj( ޛ k ,6ȠGx~la[֦bNbyQ9s>LF3v'ciqؠNڃ|##QF"7jb/VT15_q(Mi3_xܱ53-`K_b;[\ omcI` ol&ze/uYc6.M\BőxQm]CV/v ƹ ȕBӏkc㘬cx;y~bO{}ŤRH 1'(qdgFFhf0'kNOqoQ%7+1/0' cq )z@?#|7 Tr)>!{e%VŦX5\l^X_R&^m#p_ЍZ3=8I $4mH;slg1@|9UOzPyaQI{ؘ8خeߔ7{ 蓷Ghzmיi,9^2a ڳvg EcN\,?:uA~\ ӃyO/('g4L/š#~~Z`@0e/"!xI/3pf_?vCcy m$[[fl[]e6΍Gn;>k;+A _O;r/#}˫F"%^w8bw>S7|uwt}+I䱚92~X!#Nnp@[O L-JGJ>KO=$ uF>PJIvRlaIm|BJ"kvh89;F$g>~\z=G{nϼ>sn9`ٝ7rJ[vS7 yv.{z[m\O>w1ǎB}z;։F>\.;`1ZDձ-PW[\_%E6$LMbS5A渲,5V +S-CWt؝y(%wCs?'x;g9WYGظ,7i7QۜkE|Hw6c8(.?q: medF{9̒dmp)֖>.hUW8M,[%k|bFL!neF/no\HεbO–N/e<|eJ lpLp E (w욋knU!c*SSoFzled- ^dnH0N;e#N:L1q2biX[Wh'E@+Sg]ܟP6Z\V\)K!;<9վXL_J[2&h ϩ u9摼3ud&j{ķz9 :TC/mY9o`f1k3gnC`?PU ! 1bT@Ǹ~Q ".Ao4pۜh]SltM4Bb<)2zTvb8N;Fy;Jڬ~87p"!< %E!>w˘f+sgޱ:t;g4ыGra϶WvOxѸWg`F`*u'_L)}mlju|s ?E^[M#p:nEq$+KC5ױ%|Bi ΋~p&AmNsh>V@ēNilq "Ls\y#&>pE$vűzٱLq]BdL_c œ=GX$L~o Ap'ħ l%alj©S.&zwoQ l8߮ &R0^O`N=uo|s"q0e3-a|eu/_h^/}ˮOgmY#B%k+==:ߝ7W}?S~GN#;߽{ysDGY{.\x* y/΁$ӏ1s~X3w$O㬻i ^"k_Qtîrz|gE/ '=9@Q\{Oޓos)x0ȋwosrMY>_57T+ǸcS[g- 9js+q0bл>2'S1cY8;ǶFjWof$.M0N]pRO#5iy;G ;{j(^ 'fq $K=yTH.JɓXm]'[^x϶zvS1-`OOcZ#[9}%IA\ZMCo1YXC'}Vͺh̔yG@YЉSr8KF{8k؉Ԧ$[ޜSiSK=p=28f6ldl[7-xpw3ˌRܘˡO'y`d/ǎъɜ׎ܠ:|\'?\p0 w`-儎!%sb.[o/co7[Ed|î~/ۿ󻮟x{zQESWC=ؽp38 }~4G`u_s 𣝱a7.eԂ ,|[>z{멺 0N3z#Pc?1l~=}-oӻ>_}n֟+7z샫 A D`@ }d ]zDyd#bk'xȆ{-UQ#|;-lZx.-=J?j\=ZxwP&r-\Ua쟚$A"Q>5W>k,fsHAs"#%[MܹzrQ< 0OC5v>9Nq1#<ݍ82M97y:x(L9\]w w|PKrA-3aH$-*V5Ko72T ;>'L&99z)C!G+@rYWw8J<أMG@p&1|,Q/92$g[5lyG޷zMǩ&K.FaO^^>18r8j4Zю]oV&,h=V1'p- +r\S`_./g6/Tφ{C/Fg'Q_#Q׽g &Ol8%N1*/~m˂"'>u6ay3k|7R=eG0M.~z[_}{F3?U7`a/H(;pC.Q?zUn'qސ2Lg΍2/m(x=(Q`,ӁMN0s9e87]oC,wJxE?Ega˱WGmlrw}/ƟX1 LDvM?b:D)`páM>=ű?r622x^c_G&&_r/! c`>ƈ~皨55GeͶyAsLM.i+7w6i㙮yg[G87Sp}| HZwtǩTF2:Qؕ'8cj"i|F:])sG$1W p>k|M.Ic$'VKF>^Gs-0M^'ܓc%fgةXG:Jl8s$KMEcGǔ &eYKfjciF| ةMaqqJ5=`J9˻[!o^=w|R^B7.8a1F>;oؔ\7Ȑ6Ö9ѧ?~Ǯ<ْQ(ө|xwz9v:W>1e> _\Z_\Xjhr;΁]>s{G}i ' Ao1_}7RyoCqG d fڗ`} qZzGF߲Ş7@lfo\;i3??p{8`zx\DK^<{)bx?쏞+fKu 幂D )?EwΗ'V8ccv܎?>%3v[뗽ZcGy\Ӗx̸h'SMdr"l؛;'F>*lZZr3UOV9'62qF'qU9"ZrLkwgi>mc"}kk  h iYz)( VƊM A.$Fk]}ϽWWB+*vR?p 0؁@Dtj1TT%Bah@ ܔS8.'q*|Q  mu3~c̱}9{51ǜkgw7kްןX61nr~mO~tnS{ݍoRre┌&DѬ<|L5&h)2ƏVK.0vce{XR,7'_JlW.j#I/胇?[-|R~&8_ˠ98s0]r_3(ׄA# H툩?7jAclCc[YCl ;Ȝkq)0MN'>fpz,\{9ԿM~ptdiC65p2P3WC1kg'tM[qfokƃa4P;ަF_9ˮzrnz 𝎟|rA\h?X(E6qw=z'1[yJ4`ˢȉY"j򍂑fwߖӋ#T35c',oi{o{j,rcio +AL#4$ȰޢXM HaUMzsa~j b]8K5[1p'T`b#9v8|syn* uacoDŽv4`iý0qx{_~{ӛ`}k~q{-7V9`{^zwWoo_nO'q7~$P<w2̫b)\Hz,c~KNz'{'Xp[P!a<\rDEQ [DPow|7ߞ|U4sot }?O[okJ1=^9^U'3[W||S|e.|<-9!ٸmXam`HXۍ5:(G.c#z:B{[qe|F|=ü18ɻ(2`=`v0Y8zs+5'FT7t  zcgMܖ{/gS*}L S07ˆ:kB#LA95Q#kz,de8TC$4Yx ;CN`Q7) #+Gֹx ǮМ;&`5G@;0y,PY ,=^iG\z0.mseطUSp`2e!hxۆy?1,зqJ5萝k6!=)C4@r%16xod=杷EwGs981^1=-$€t g@"lkq1b6ZN3 wpu r\I<$V~kqrL=mr<];p]rd3Mwh4/I& oTRX"9A9x]o,Oѵ8NkOiyFSk֢Tڰw,_\( mҼ2F[:Q;w#2(K)ڝ^X#+5h v>3ܦW"_x& (Vk%viG\sD/o>-q 佶`F}6rz3okOb` X;y͏ 7-9Zy+hy\qsB ^v\8z4-\2Hk]<ė 2N}?V+p oP^@ObJJdGz^xǏ'$ ]!i2h ĞYqD67 4.^㠯=sq +o/`uv "6.@$ن'}k%f}ͧ>A7_=i'a]Q][jُdh-o335mH6CxlO{@Z^2e~V?e_c9uyX\܉E,ص60 ~z\eLb7R/0ʉéY -sMz (Bnqs7[ڗuMcH VEcZpن;7p|yɢ97 [sc8P<{ܾKH77L3׎ Ʈ6}޳j>_{nnB=gD'9i|09t>.^s^(7sz yL v]-7y oesΕ7o.tG4{oX^ׅ֍}n_W^1^"u=7W=o{.}N1"Ҩaydgv5ړ/}|gRմq*X`eƫ|8ep0?6<6rs옣7 &qqb;DlkV2yso_mS·D]eZˆ<,\GGfӹ2וZ`S' -xq+vcE^C3)OC0\C,i90ۂ-áp6w涴V cOըlv.7z?fT{>7LJÝi<9qܱ7S}ֺw(Gx(IQ =~]O?}ͦqnfN[plth 8CH?Qqù?ǎ(>lD2F2;܃sİ;Z>JO?Vl*/DZ lp!]ǫ¥B'aD-"dջcL&]?n{vL.>o-[|t%rBf4:)70V:vg9vt`mU~?MuN'j:ixk/yEccXj@JL1O'$ڧ r+R{<1 &.ԏi,j?Mx.|st:憏[`hkL|L[up$͉$vkrdz1Z&7QJ'4qm*9,;%er$ ^m-EMZkkE5˫EO{&>kr7O:GSJ_oj} Jg:/W6桍w͸Xwk[.rbRk^K]/s Xx1m B D.x\9J gXb8j" &GUv-̫ʇ:f6%ؒ?rmm}dO yQ\ $9^..LJߓw(2 IDATmnjUs pb^v 7|SZ9 DqiIXã|M,nc\xOy_g}( 3x '=Fk[[^WKqGA EtcD Dij-7d'F=Z1"眇0ϓn]:U<R_ؖ+/*7?czkܼ'"3_CuW*=rH!s>w7no>W:eGxՐjD=lbW|]w쩙b{|3ˁBk>|Jԗm|C Z @nd\2ue̬S+q3'"_Wduo}7|կ~B㳾V5S†NBܰ=ݧ=}o|VoG ~Iםs@;MA .9&%7}} EӸ3sOanM+kmQggp 9=J>k+OikgَCG$C7[s\W"﫥*&_%*f1w3+2ɩOu!wYtI؇Om8~Cr wnŖޠ*Cnwr=e?8 ʳ0E8cAKct--mmm;xҷK V#]{|ϗd{ (h+c0lo;29,hS/9ìFnxv#/pZt⾵ ߘVν(/ml\Gj{OVd8O.N7LݣG-m' +ilFg}Smeo+G,P邏1GNKw0;Y9Dˣ@w?\31}p&v[ |ȑېN& Ֆ% _8M!s:^VM|Lfxei(,bO`. c^^بmnΗ>ԝP~F6(j웧 >7v~B8>f,7UC46觏zoQkLGLܑbag]=6+67|4~Sorh7>8iXh;C.sI?uRr4,~ۧvс``c-MB!Ȯ8vqRo!w<9%Մn pV ?ETلܱ&j0'n= ֐]P}{ۏ?r7//vU3drZ{eR\[[ؿwn__u{{?p)}~RXwo^HN3:k>kWi>FkG J]<IPGYq 9 rؚ?_>x{noxW^~ &H lb1}ϸ!%뎗n-|3OE{ XFk#7ZpwYQ٬I]7(XM1sr(}l|o=Гc}EL)c B.sMߺ0V֠{lÉ|&iMA{- W0N_ɓPL -i jҡ 6 2v+ {H%}~=4XK߼ tq2*}F05ϜJ(ǹo XMV5mEj(ت r)fd/ OrK:fBQo%;4cpHxh w,[]@rx36h8 _ sC klJub 8'z^D P~~=/8kLTh9AF1nb}8`5G{ r;]/ b>?][tC:c{Gѐpz..Ƅ^R6>eO!57Õ95GdcWG\jkL'yEr}`$|Tq&eז=Et ε󟘫6w m%W5c~'w^lXUx8'ցmtvI7!l{/FH`.饐Rl7.bRǥ\lM\dbgdS+gLeCM{|֝`/dG}l 'j ?>6dv`evfԳ99 e?}G2bT |>ih4ͼXx[~PhnbJ?X\d`\p? =e{wbqwz` 1n.u>dY[ܸS@x$'\M!B<`HJ#Ua1 tl=.K;H7&$.O0f?.<0MAY|PQ2\1:[H.|OSr{m&,;36`8` Q$׏q}Qu\ w3ecIj6(h2gh62uE9dDrc V&"}Fĥh8~1[eV(MfrPNN|:bѷqd`B `18s!xصN YHL:];ڈC-1jfNYVì#WuO@r“y47 2yAF׷}_W/"7z.WE7JÛur?o?7g-r۱|\ҤI5ܸ^Y=~cDZs;n,6m~xFy7 =#z+7V֦6PF%uyJ7>~o]=o&>)-\7 s90a|'C?`|4{Oؽ5cl_^4&fm{sY=UcTjóq&aY9Ssc114vpic뛳`jR?7k6[yȩmm\;£sb[|{MaAI@ gzR=#KgC,e^JWjm7mMO/YDfbyQ;fՅckkM[&Fk9ێ6;uL-%(ydtmkiS]іG2 g=F-b4zz[$;tg*{a%Gm#[7 QW,daõnx<]0@zzj(H`r K{qW^,> ze{0Xi| =Z9(1uhsE_?ȍS ܸp_M2Oql18!iXǚ~cL]Zy0xuط;M^h,xl[J;9l83*oS;|egR(pɵ'2\_D`[{7wsr_K le8G۠컭ꨡU{7{y+KPd<7Zvs2g\gݲ>7෭*/}^*b Y 0\! U,}0/ڥ#v~{L%5qH]vxdb:0W,-jEQ! x{A R>SpOy(Iishplic/ិ|sIw54Nv=!]-ɉ`CyYϱ5SB.ұIdjy|kx7}縐2r݉UA17ka+62ck?ޔ7mξ1qG+n6a_ם:,k1Fڧ.;U5΅X;߿p W>k^}#r hoC<{?rKN>B}~GT8sUZ];.DŽ @W->_7gpOފnGs>S駞=Ý}<7P}߾+Tӗ~k120d]@|"3oy3?khe]ƿF {MF=6)s%>ENS.6FbvY5bYJ6`+_ 0C/nh>Ӳ-Nj@c0|̹n*d c[P! /<,& qyr/pq#!Xj5wlFCc/9:9u/dJuHeݕe}1ӮvbNp_Xo~Yźzg6f'wD[kN|UkX_aTھIJ<}Na:vmd;'i[yMYEZ9Qf9x||48g->wd419?sSXI-9W~m`o-41[G0a􂟠?9}Ñ"h-D.X!kؓwݓ%z}ır6 Z15t| e37ӻϗhl;G c0~_b#v?N5=M3it|Z{Pt ͮN>猁 rgɷح!m'ONo1r\^#=0{gN2w-ib 7!Ī~fy<K;2'}@l )7_0E]m!d_i>OH:g'+9cM m"us>΃=0Q '^K 9^џO%w?67+͑g4&G}eb_YL$e͡gMYr?np̚/:K;`7k܄w(97nՍ,Fnxajԗ#j??o֍?1u)-7i /bhgo}[o AjS^5xnDz>nq@w(?uu#=~_~^}WO[VV;xW)Х#K,Oulj~~^=njy=YYvY|MfSmNC7BB;486k .P1m13KKudsQn,_Cx>CXmχr8M̹fo9zp%4h-N2?E>vд8ǙkK>0vFSAw2)<`v]]7-| rǽ ;st1oimoW^3b ݣO ᴏMc&NdȼחlZ9]wb5^a\hT)-)qܝ T'_:#D\lvL٠G1WG&<[4\lȱχr|l˦uwR״=6q׮<̳|ļκSsi7ϕY ܳ4/dK[}X_3h]|j #^A";I%!Wwׂx3b5FRo9b\DF%rZM32(Nxb݆B};'Rk?~xLg!\*5Ħ(odn9z: m.vmL!k:&=m[yw?o%$&6Р rNM;2VVk|8%'h|W<|h`FlbtU(73H91®\L`QSs3A[$xIe! =@GmmgB(K̃Cmtg$9 tu]J3G+2ȕ}3$Tu͓'.5 [~dͧ6kc9Ņ^e0-1dv]bg;<Ա,rG0MLS헸nz$4'H3 A9F3ߌ3tcFji;z6 GsV9'o{X8xP$9zƏn s pEj;Qca5jk̡@<"Cz;jol\8qL\+Wշ717yE7p88K6- ]ԕDӘXl'?qO^}I=yY78x7`\kGk[nȇ&s @٫9.O|5 }߾˿/S|9YS~֭gVgW7(yşy ixs2'`k%GOnY<͚UO[ LJל2< 9q<:VAj]E4qg<7e:bZ{L qg乑[ʎOwx^!,[pވw_ov^3u&Ljy =F7CǓOőzX.lr*cOqv$eW]}G|Tiuccךض{8nk{#?k߬%GdZ9\!L R!:oiS|&:K]ߴ7~8Z~_t(8{NFwιu*΍cW6 lFOxmk)(FI? ${kmVRRXL[% u! 85(F(8?ЉwH&}P6#iንp@:,C 'ofM@J `B!|; XrOb0G(ƚ 3'ho._iI' kAWAp3^[gJjsIj=^f#{w/ʔag]SE"-`0sLgI[T䃹C'ymǬ ͍Uk\5n7$b }YN,7OyewmG6^/w"`И/y.'<ر#^4j$8q'Egſ|.l\'lhlcMcQ ^G/>ӶIZa:lN7\x&vY'XD8pq sw q 7hg^cxNQ%Z&~a`9_H|Cb&>3q0O,,jޘV<&?l;$ld>nܤHN>0~s+7Yئ ̹aˉ[3n=uW^3o 6GBl@G[yEO>W葻KOs[^җ_% mn^ҩƟSo~cƹlۜx] JCywe_FGab`WV`tԢv%:vLG _|T;nɸE;a&l=;9Ok]DBR|*/> eڜcdx1~pٹU0Xqe< /o2"Rix|Űr- tŹW79!kc%f%7n)EsspV"</SX8;Fx2ZA=r.9bfѸgAR^9Vc)в7!LxO ΍\|p&Ձ;+i'ݩ7XaBjM}pB 'W#`2ֱA, <=&W @2~1XV M, fq8d-f4E=!HEdY'=mM),xCI`⑾\jPϱ9P;(Ϟ۹L K6IB0>861uq5 s8u;BPV&Ӥåwd8\h"`+S3'PXXr?R Vٌzf/$JG" ךCԖZt_sb,> b# =c#F)fRohkCfၔ3?֤YgTzw Tv[pX*LC AԴ5@jk^&usha.}-nƯꌹN>|`d\q0S#WlL{oZ7gs'r#oÞrs-{~4JMQh[<8LFcF!%s0-^]{<Oap08z8< ls =%:9c^;屓o X(CI#̬n>퍯?'_W 3A1bÀ|??uC"|Btn^kH]MOӷoo9Ora HGlN$7g ~ܞx1+W5`b7VCi fЇ>vٟ~7uϏ.SXr ۥ5 WL9&ks ^9a2E:<{>x 3Xi7`O?:sh+Fvo޴l9v߽p9_9 .u|ǭXǤotkc =gծ6¥ sSsHfc4-5#~ʔz>}e:jL8xAt3!-u[ t`D>8;]48B: }p~˦"k:;Y +; *XHE$rHxo;0VR[xë@6G;%WbO՗k ɹ6u9EDx`q-e9lelZZ$jmf}A ;!Y\rqQ-'0~3.rF4yY/:A&3x|pZO?p'hg=׉o/f$\4Zek ?ճz|V漊i-]up J=S'LvgژΪcyXд8o(~\{ P;o]5lM a`9Tojy^k%C2s~!bZ8Ș9EV >\:.^hC׋֗c6zS s G.̞gkp"}9^a6KYkN%vsyd@l.Npϵyɏf{,"z1 Daco\ . 36&ǟN>)NÓ5ƝD[53oWJέ|E3q޳ -Yㄡ9+'ӚwnpąHM7g05?9c+!KG'}^ _ۓ5[C;+ JW?n柼}Js?_ǁ^cW s/RRcu`afR摹{?Wo_g^/P'%i#׶~uF_ax;gq񡗼ͳ }̰^%l:n<;&%Fbe yj 9(\ XўuԛЎ1`%Q"ɇTqm;ߌ9 w\W'|ulqƊ"JjT^g$pxH!ut ssf>ˊ/AƘI cWmӂ%C^=BcWn6C:^;Oή+-#~M7 <,9ܛ#!e8Ʃ1Е75m}fst`x͝N[+S!Cnj}ȋ׹)V >2q_,׀i1]jmm_kSwT`ONp1eN6j= -O׮\63sƒH^WqC27.[cPy8Jű0g>ʱˎ,ܛ ƨ6_%]pVŤPpzAOK#2蛿I;ָH-l C{h!<70 큱L>֝jZ+'e+dA^zN=4'HoqL i gO>qL9/o9E6Q?)1#1•s\{vE58K#">rhqWo‘;CcGX7lLȁ=\m|Fig|ځze8Vg!cKG֓9? i*yf@mbFm&ѓSn-8 ^`Y19 jZTct1ᣦO<2G9>\yxBRV54/0 hԏJ7g8rrnD"xjLHӸOZsrj1+`&k=ODJ ?柸׿u_~YG>MNp X=*M'm__p?~ʸπy VQFޖqX!25 3+^g>?=#z⫛2*6ǹ6å>Թ3zoo{{uYd"Olyr m=.!F?׵|`47%iQtXlǕ1sEn-\b9($:u/"ׯ0ޟz!&7"*13VV <U7Kgsro,t _s6 N9bcBp xF 4󜶄s96̢W5Ʀg4P7)OЋ!/r=ќh@:N߁Q1s \I0RL+-m{Rwf16)kuB|7x~އtg@Kmd"W8:&wq71,2]spͧF Ց6s?F>˜gnik8c z {7U_Hʣr|Oӷl<+츸o ?Ɂ d>yF#dn.&[l޶&:Hߋ,\yK0$Ǒ*nOo/׿"P7/߂+B ițkg-[ag|_g?>On~ÿ-n@ae9b=7~~n<3t'1 Q_5r3i>~-p{w{Z@J 1KɼE9kO *k֩&f&8vݝ ;mFMz|k}q.8r=F>nY' O~p&˚._l'4o2vc//RN")7 jogB{69|i xI/)qw['l-VtWKSbc]֩|/p8jZ.|Ʉ}!)s|klٸWkXiB)`s3 mj-a'Zsk?-8 ec@x=X>~n"/%xnOP SQAr@{s%Qz75Ͳشօ›xt]Sfc!:Jp@/&Pq>=y|`T%sD^R7]1bu?I'4yIp?h06ixI # Zff<Bd%Fr &`z.>t%ʤޮnF,s%- )o&hd.b =&^bٜxĺx dW.xqlzƖR ^V49<0Ӳ]@j<|UB,yS:` ~k~EipӘc<I j;F'/8?%H(Yj;sAfs xOۉuVg_ۘCN曉o7 F3gD.ω)88G"-JQz\K ˸kO]׉pAQ!#qGnϼm]<LH&/(0Q*9ssjI9~5aY.gֈ(ܼ5G{#΍h(aWO&kT}vP-#e~m 6=ON]+`~9$~2t?]:A5X6oDc]O)v )g0K1 +K"R:ZtsЖ.X8f-g%wA6smbpL=6OT.'b>!^Mն%e5O]lDs}Zhbg9]eŞ IDATƍ8็U:u]봥מ3)1ndIvafaȌc_nti!8ڱZi]?^A`h#Kxܸ_v+8'xSGr\|DŽY{ Ҩm]G>ѽTo~2ߌg5X?@ځSyU '~V]sӆ\kzJ5 AVʹ 5LW<2WB]XvdkZ;2wͽ0'h屋D1:7x'zo}7~M^xܪ΄GS[A10y%%z>{L߾oOO^r`B4Aėf<+o?ҍWF|Ɵ\-Ɂ]Sw=>_]=ľze]-G7. h;K\|B-u`Ցp:6=gr.[ eԲrMܦ&AEVb_,R{٬Y$SFH=~1jp6A· j^,\w.}91ƨxV?Mw m%_eӸ3qR{e\LS=dݺ2z#Gl[u2 a'mCX_|f=`k4(Q=7C+;'@sYTz@0ad5 p3>o[[O2w u$(!0qSCƘOǺJ|5GjGpyL*Mt{N7Hc9 W9J*q:˜ ~ _.jh8/`13Z[='EdT ^Cds)F\j-?ӈc‡l${(qݺҸ@lCM3 utca^AetNi·Vd\]e++Yk4[E&AcxnlӮq$h`݀ceJ -<1S<<կ\3W[āG5[k޲]eKp8M^ؕyl aR:Z;'}<;|dbwxfU6Ư8|aHYȸk~ƛشn_>+g,K Z28eݨ(Npۅ}A%-KjgkEژXf+۴>eù~Jy>{4e(s;6cn)IHu`mѨ%\(uV. qQ7 tjy+>x^C؝|MlHӪkǪgY3`YEWs3511DK82vhw#SoZ \kDZI؛XMkͥ9LNcrZ] `2-׺Y+y=D]~ۨ:O9z3췥Ec[ElkCļsfcxߕhi@%F 8> MlJ96qߐq`PE'|O`%+g[ĨN33v7}빠:7؍="[ɚ/Hmx˪cu2+v}15Է{:Zb_d,*:uT+.=sD -r5'jl uK~ZMR#;'~څ1\m3q\.Bx?nNtqMd(9iӰv:=byWom/MoW?\̉aC? Ùt,n1ώٹ!/dܵ :j)AJ߼m}Wz'dZЕILv.)@[T OSf5^}[Ēc86l<9Ĕ4cAI!Jkc6. _o(wu14l F/6{5|O=`ri죈Df͢YdGv>ftܩ~gL{H 7j6݋r28M׵\<1%,[80#C8} X1KP }aOjQc's|f9%+x^crd2Ws]!q^kzO؝K:oaKi72N̠l'~To}!FN"vsV[>Y%.RsN}k])3 ς5m0cdx ,˭)VF0F3;q?{|Xf${-m_?M$ sAsqqA ֦VyM9ȃcI߆PZ>W_Z2\578Iv֝p v <@S̿W\o$_`yG;r'®[tA$-豮5v=\|K]੯7uA}N} ˃_@7}7ݾ雾yaO75n?W:gQoh,-|?~aZdyZyH[jg}DַkxGW'Hy[ofsDe41LU[K֌د m֍F`]ZP8Ҡ}xdG~4{{#i%z g~;کOs$ufR{N|?kMRL~{#s%Ӗx^ 2Quy|}]tǂt5qfycg5xk>鏕z=1y+O!\=&}7̯n *1 }WƈU)$j_jsKmBv}70ZvV]_Ҙ@.$yMW ܆qʐ&k_bfA}6nxy2% m3O%d(Oqη ^||&k|_'As]{ @)nkS8]LcOǙ<0Xk%7qZyw2QmաK-9vSW9>2ԏW]{uvcל_:#OuUwʖ?H+TRNKCJ\2I'wJ$06$z_(7s}{^k9cνϹ{|O? v׎u=}coHu۟e~*u^.׳+Yh= ܾG9 w8sL!6=X">\&gߓ]qW//u} _ ?qOֈnX3\m/f`d_ˆʸW\9+Ƙ7;raA&odp!6[=a˧}g>6oZ uЙX>Г>D1KgDHxհG {K#oT 8F4\q6&^Lj"?%C Kqh$E_xxkuoA_-Ʌ5['\~- 1Ryz>b;:!J$>ZZu'1Ol8p/+9G8ޡGShG\:>2xsvZ|m|bHq*9slx y4t&=B:KDO}ȯJq>qMk OpJkԦ=Y$|߈ױ/bzT| mԁ9Ɵ$@mhp[}g P) h]&b(&h7d Mc/K9)hgKg0\З=h9cL l.e ]yoQkR( W!rY'b`; 9(7f͵[eF~Am=pcg=>?dJ2' /(+ r2p"V~* |%G$~ p"xviZcsSl(ݘ`/X3W?8N`_{ʈ]Zadφ_cs|vtͤ_1mP0ʑ ^SS)nj8zHƫpbAxG/h|=,f;$ӛXt,Ά{C^T\}ڮ~/J7ܱ43Ink=bm}I^K6v bXn<}y3[9z  {ÿeE'G3<Anޙ{5p0cpI km3׻͐0"u庙*9,>n@x@S &ϓY`?cJߎW÷,B 8>oS| {0Wwם|ۮ7YY94~,4\d\  [ܙz#F考* oPL͖|eO><-,k !Fȟ_'_~_~}鋺 ڬÌ⬐CO^Ooĕ7obӳަYO/[|_oOs-=1Ops smbPh4޵9ػ,bTAxk+7 #隣3ꚅ8'͉?C !wЌ3 :yѕlj5&Nd8vϩ'2s{~x1s1ʉIg 0mzqn~x'uz\| \䦃'>$vrLJۊW c,? ߘlWZ3_hy`k4Ǘ;z/` &?ؙk^J(&ѓ75)=y~Ǟ8Rs:$6`C?@]7k(NœW ^:Zydz\{ F;? ܘm|KДG^j&Z<^m& {R=K֠56RF?Ɣ8 {=OZؑ}xf + zY-fvQYrz nsł-jbYks\%12Am_{&r C b7×6[4R~d(<}q>$㶾b't>.)ǜ/hkRAy=wB60}N: _?Fl.v[&SwҺ ۵IM.nmg35 |mBٜ8qsگs2kWkk(=ȌOe?wwBp|3|7O>|0<\#`s1R574y~G>i]LWzV+"~8Dm)k$7APBIMG;L䨌 OpVLGl>Ehҵ\ lA]pwjv0}~Z0j!<ַW3K o.Xϫ_ԗXofo>Si*M|?#MRg-֠2{#N/ 9^sO^?c?/NeDY* v}PiLyR}>;oso7~Q^ IDAT~?eF):?^g{J|ƕB'b(QfF/v>#tC5!me׋:zJ`s5qyo5U'o}3zXäy OM/%[<j9}.x\7?$7-±^H| o,.P : 6WD\7\k]MH[B!P5/`Y?{iMqaiez揌WxC卉glvqMWV~[w5aLY{M2qQ^ÅOf&L D9gr!}ͺeq@l|6a!c0u:Rԅ3QvGgW|aA Xh}mLx==B{d*=Ș66lڎ7)Cָʄ53>Q+Ek/j s˗f#\I'\Wro>GZ'obW>{tα4"ny-v6cmna*i&y uCkS8>/ FCt|6kހO9gxn&u Z8?ټO jXNEZyHŨF0޶^y V؋wn&g_4'}7ڵwX۬#?}Vf[M5qTtf5q/5%D\F:6$zL?U"Γ|[×D9m6 B-]~;Oz5HXA:l:=ˑ'z99p[W1yoo)|:_TI3"SktPBK;!_K 㓟r2. >vt(Cd[?M`fTܒ{0-s!WssDԽys32x2=z!GMCry9o{]@n}%Z@-X|rk7 MõS@dBH)Az,Y'P,68ٚÀ9՞^S`rpO_>Nzoo~;_%[d雈5]ll:lU|q<>r7~~@8'nG$M{b7ɬ'71 tL14T ax@z 丯cxmE;^/L!$K@l@ցK΅cgXt]Xm!_w|CFpg}0Pz\T9O_ |vWwoς&\8`c$7mD7抅S\h"yN=ٿ$abl`.J\3=O'^C1S#qhGc:$mA sF^Bz_`~=m:%7z\;=5wygĸ>%`N_!E_'So0>Zp$u0)9=}j.ș-G߳ F<=uWAꣿ{މ6Hy Wt^ANX=y^=c;-##m詭yk7@+{&ښCnۄUVvȲ 3'ۃ.!<2ǜ uܞK#h& w7~M..wc[ <`3hZ+~R_wk%aU>4-zf6䑽oPo7Ocdm~jycFQ' Bl1MflanrG]qEa[2\Y/x=J.&}~so.VD@DxZ'%P߭twԓ Ktj'e?Wo'͋GcM8> zh kMJ=+iHZf};39[k}t://r<mra} <9d߸=и6]9x2s9#aHWkI^"qO} !ʿDx|M͌xb'NɞcYాH仏dL& Fζ9ڈxtw=L+5uiSbv9R9=$=|۴6%qة'O{F΅3u"yysĤ}rP=`>ȏN;×2kz̀1+~,!9ܴ]"cjp?|*+; ?+WLㆂ\TKȜy&/y#Ԑ#ሯ٣/4}z4|5XbELu+M f|āAFb:7o7Cg=Z/c_g/?ѿ?u*$%ɴƟ훲6b|@}׿^?ҿaX_OOZQ Wz\fgî7 t9s]kDL,k4hTˆv~,bѫL s4"<[=\BWФ0{ {{]<s8zߦ=.|!sw8#\}c"Z'cKy#A82] >3ĩϘDۼcv9]fg:Tyy%P tq㢳\ՓB9rZ|ѐ|S֛sd\>ޯySA}% f}6S|Nꛔ+{mF߼pҟ:ʆ9H뜾\\19\91isll,c5 e1,!atk/[4qk~ȕ9}*޾SqڗH`"5qє\mqqfx<7G\,քF0zO$aoR:t;1~d_w ;?N>& eئ Ju秋d1{ ,ij00DYlUp "V'wwo(D-Qq89L*m]~i剝7ja|C>pE ,Cc_ԃw(7ASl/Hɚȝk*C\uvXj'|in|=U0An):v-ܙhCzx5 G~E8k(ȵ`xk$(ڂ5sck݈C`ϛ/&BPjFj@)/35ksSg9Zܣy|@Fc'?~OJw̕~ |$fByƇR}$\czAU 1x OloG' w'uHPoή.#1Z49Pl2?6f!zXmLc:6ƌ>d,312&q3fڏN*n%F={, 64$]}Lb["#qn7aj}뵂ٽT y斣6^inQgv֜ 3?Dq{jkE֟O]F/?|חc{P;LƳ~`Yˣzhm?oԗy|2 Qjԙک98'OED7^A,>}%]`jJtK|/מp0ѽ9?/@YdgF 6cH,75`m;~!7: V6::'[WY氬 ߉- Ot-Qa-w2kg MXFq1Xc18³6^O~{3:Ѹ ,󡰓1:MMAĉ[0~gQM+LZ7ϻ=l=? G;2Ɩp OM[c8ۚ٣yC6q:ukRф㟅g9sn iMe A˲^N \A Wj.6K.}kxA[fI:e?Gk>9)#'@~0=Q=1#a`G>,jٹƍv7~="~ܾ'&OfwnJv|`7Y|y6B s 7S5;^ ͳ֞!Rs`"!;kO Hf GfFg7@ֆ6ap*fN}1iwQ X]F XLt֬,8Ü6\G.P}QPsxGhxX{yà8o^*k#=s35w 4F1f)ށqf-ʱeu23FFTI( <1SٷHApwk1=:%hxLM/ثyO\;k_:"1F AK ep sLHl\*K D]cϠ iO_5w/}A7|힨OZwhk>uX7nzd'~o~ҟ /k?76SK_CoI|7D` ֿ78z%N>y 6fMsZ]s{~17^8W!"F?KH4><,Ua9֮ʿmǧ&GK?=('&-_^؋M f=es0<L7C{"!m368f1йuÜ' ]OM?o;љCߴ3h؇)883GBlŲ֪=_3# 9yMن 6 z?SK$r8N8kѵho߼_9s^wI=?ƩҺ&cs 6ozqtii&=&G\!p|sa]Z,4`pGbǎfzѨ!`͍9HuB:0V>X5p{Fyko kΏ\5^ҕ#Y>5M̂1NC~ƉWlٯq&ժ$Ga k39su'h-2}l1g+\>Wh 8v4}=(V=[Bp}$w#P]FD9rDF^ MY`Ej kWZ+Qtֺ۽@Ʈ~]։M sĔsGȚ ;-)ps;@8r5:opO\bd\zO?R8,a/{[>wO0uq)Q^ęܩɺ[7 E{WsyO)M޼L'fDСZ=<7{])Tjij2Z<9A*;oj"Qjkw]O2P]ˠL (#>WY::1쳚8\%Wh' ']. ks$1[yuu ۋs͊-hyNll$u[nqE<;ŽQY=嘂kEe[UƸ Ĥr&= wrhs%'iܘ,WUQ璯vzʤZ S[ H*|bNlՖkKs\s.j}˃-uIOJ||ZlW^cAƿ E FZG zCRDk79hR{LPN?mŀEnO.>=2t,SP5`+"d蘘d(g V.βdwJ&P>;0G<]Й@(;fcqx93 < {0L4fDv7h"m" 3 1yB"+܃oh8՞;Lp)ڴ@iշ6'+Gm(c#7`x+{TOj'h0./X0hp`D3k-'vgq{_rgͧ^YO5&4c8>fqFq9֍]p>k98B9'uS_t77%"~ 7c9mC?K x9&xbߓ:!4yE1$p6|1c9~XZ̞ <5wPMΙк zch&]o`o`8w-d۳xW@?mB7%1 sc1zCw'rKGޚz4W* 9 > )ݛě\;2e 7J;{nN"z "5Ldue83cjhO&%Md&ҳLw gG{XF ~n6OWY(᜻) d7<&[!kR| ze@ȴk9*nƔpn8v^x-ޓ0p+i*\ ^lM>?ʾL_?r(il׍C~Ko}_r@QČ$s8 &.ogOs}-k[mM\pV5u%z1>|$K_[H~5a>(Ar8Z/Męazn@Ffk7,d0G1~Ny֜239ԡw\WzajjlSGWk0fh6ˈ C-N:gxY >/uF`yiXTg>Ic𱅿[L 2zׅ؝R?=I{(Yw4N?,u٣ L݃v?z#2xT#y0MNcЇ5dL8oCb{LOsO~F. iA6g1L'ҵ6gr]#x۔E14y >[>__w&ݚ(%BFz{tzZ#LԸ'6>m}V o%3@mYĊxkP<>c6%9q\-c_Nk}j:џEc9=_wp4Kq~M諀 d9\Z~0xN/s޳eͯx`?f-1#6slvP]='D+~Y Z=ak~ cpnq!&<}k#ץ8G=~nWHHH7c@|N4m4q~j=]x9870cg*w-2ȫל+@{׬ b)MۘGphX/z$/ˁǝi-o{}0vrF, yywF?Q1qZ6qk!Lo{0þU?Ň4K6sG;9Eލ$<&pt(=oZ+ڻ7K̊k-s<Ϳ#ܼ$7v8ݞZ8fc7ju拶btwky:Cin{FM<B9}L$u֔}x||{[ɇbf!+Pp @ҿ4696JM<mܖ9o*ۨ ~KXn9jSH9U>oJZ!M(-M;yІJ9o~9ə8aPtY]> 05Ұ+vDc>. =.b&7mZb,? 󍿯5ۿ?q_/$hڼSOOo|g ?& 7Z'QV:#s;I|SH$cDib?ls]8druun~a;9Gl8{2zVl$Zϛ|ݙ>< oqk>{9hء89'Vݧ0?8lDČ.|y-14zq8827bX_2T9o]|sEl6reOc{!l&9fK$ ؍q7BŴ)LE*G Qrba賭y5+g8fXecd^>?wu޽k.Khky-B6ge|?eYAPØdKB*:7?'T,|wT&} #g7B6swzG=I|3g\1Xx:`9i߽Y }a/hmkymH?ewkpG=GyX"HRN#nƩ%\lcS!^cw7ԲsR/0B^P4~6<1Ot$*]vRj'-tss7ihy0X訉^(&.E'!8}B@ϕ;~}XRpnNar=P@ ?}vhIYn$c5 p50<3~f-vD0=ɕ=gO8H:XLt+f03Sʼn/? =mn,1ş-ihhZF?x kBg=fGyLizA8߸>C^n.bh.s\<{YACy{ ݻcM7fovkĭC<,Ċq}8^Sl$}I=5`~p?g~W/[n^77(x|_Ͼw_G}E7U5b}sa85Z7>|CT~o &t)hbh/XϷ${4Hi6:(R)gI1#<Ǟ6$Ϝ #ArZn~@6Ũ5B,a36﷾MIF<3 9~rZ&JZxU=µq u|ȁf롅Yq |;m3Ō[r\$$o7fdvν8 ]G{*YcTwiMMק I1CDK\XxuM}&BgNU%Ò|Aԑ2aE땱ឺ&s $pgi6ffit UCGY%L [81X'_ b,Bq2f:KñPxj"c|2a6Wʄ[&~8Wh0:)̵A ILNyht{{2*Κ{u) 5^y)-{%fF[8~PeD7<>3_So'7 __QmttkV#6c_*6?կP߼/"ͅ:}QͧxL1F|\'N#Nɑ֜cAhBG_p^~dP+<9kk$b3|!H)It iY۩MSswk37{tp9Gj<[si'6~8:$ \y߼렱HZ!]td2 YOō:깆+O'H"s,,lۛ3&Ak3Kl>q4QЉ\k%0Ue C>yrڲ'=q.^|6X|4Tl☕Yu߇j|<7IzԼI7ľFLӋ=%تK=!{(}3V\âtySk +>Ͱv)ٶy au  7rݘ..Trc#($ɗ_&WP ß9|9ͤi{>~ٓ>fiD@h .F@]'|cw; )kL`j9,_b\IY[ /AskfAn6A4{&條]HH8'yInܥ쵘鄘uhbJq9E.tkV MO8H5#BhTkva\<=SV!kͷIma"\W}r9}yxs;+6!**ƭEވB29M︬(ѕs $5gk  ,FF^ 圿i^^ )hDFku\HaGjd}Z"6tΰMLLaqz=5M#IrlX\SmH3I+>r͕ߌy-)h,(ԟm |xHّcn7Nϓ؇́¥樣Gzdr6U{Dz|h5)6,y~AH%H O?F43yQvV)8'nj&Yw:sS@WbYq&+eo?ptZ|x~-XiHOsFy%IhĹofGzC{gQg"Gf1ԣ1׻w(n}%io0f26(AczʿARr|r|0SLv9\cHxj Ejv= b)v3v6827'nX% s6f֮3W3Y"Er}=> gqo]H>`Z6tG>#Yu*T`dqhz;79= 5~őW _t|YwϟgT 3DD Ղ>xL/t gVzݯL-߳w̱ F2{3yW9™t퍖)1ϭf7&sqC@+@M4>#glInjN^']6&:^FsKZwگ|o&S\$.J9\q]>_Ю {/`l\0'?Ģba!Jy$l=kU .#|M,a؊שO kXGfhbɞ8f^ymX`R,VdAL(87v+ȞjdOYn>IGuھ'Ճl"r|Wpp=(&VEOa7S7gyJ5OAraY;6ߜg!=o2 {s!|]gbM\ZV gL#MUf4f[[ʉQ650<xZ z r` 1vP֌,̫uyj8U圐BM-I8rVÜO7p0Cp&5KNy< Szq ђ}Idbv078LNAƁ7b ôyy\l1*1dd.dЭ 3)ȼYȹeϫ0 ԚQ*X HF ѢP]99!G}=PX@ u<7xP=9p訛PB<7= Ctucfͭu<@j_͍c(-<Ompq-põ·H!7q 6rBs/`3[NҺ NJ-N87"ySߘٲPlmb&o3p? /b֛a|Vn &Sr$NBڢ۟N\+p}]^Ȓ=ѻwz-FX{%3?j |&0$sz<`kB'TϞu.\s{+\I9lUYQR|mroujqb]ު}m?u?;sQΫ%=pV__,p [FGO1AӔ>5f^ Hp`噵F5\ 5d g v5V@[7 >Jt ךm,S't\flZ1 ch{F3nùD=9ѕ~1dvAp$ZMㄓDZ]9MsG91}XsTi4#GNko<5O rO].+?9q2*(v:Z ֬MG'whŠ)Z19p͘n ;s^|C:e4hDގaN|>V1|ő&`l킗źpʹ4sLiēiեyQL-z;7>sr>A\zB6leޢK_u[deOXNbØ~FhG`ASmzr[^Nћ{GEC1n(]c96>hɀ6ɖO[+6]˝X#~lJ@|oᄣyk9X8fPun eӘ'i"IǓK~s =oi!;Bq\pI?)0~,5Y ;+r# c"\^!Oب@hٔ7N3“Lc=gWLӌoKP^Wc'$F\`#Q0Xr3ϕ _5D^f8Ղն;q15O>ў伱䉎H0?^\3‘77xՂg +Y{&1 (kA8uIw_;Qvˮ%, K3<ŧ&_VQE7y"X=Ǖ $}w\xc^!c26шukL;>%YDce=cru@ohHc)  9/`lc}3N9Bb!lyhdo<؜`z.!57!;bEyEd@ZATu  ^69evz2?#pAcbb8O뗳וqsAa hFN 37r#7 ĵg!X߲o%wlgWfkCa]`ԁN(x ]K}}̑9.sX\НXr]9X/^)Յ\C…9dC08%)r-[0`ug}nu"w=B, U^ 5u{Dargfș5N'U;sH(=SGFt/*OH}zXB9V bϹ<0Kآ|$֞'>gzWT%ֽ3op}bKCpp`؛pFMC~lO(&:e:r:1;䍍|^rѵ#@/`\ž#~g &}2G79(3/cA9ܸF%s3ҫBz^֩B%l5UbS\[=\;V^-|xZj-}$ &yr4FJ[+O]wɱd 6wYvCt0zX/GGD*N2~#~l9óg4&±;>YY/w-<ĵ1˚^}Z;+neqoHςh|_yw~SPKFpjTw8p'e<ֈlΟYr| N&x=\1"㵼~?p予q"C1F˖.  A4ѲޔǴtDZ ŖNϹ̯hk!\7O_y޸ԍ<7{ڊ}cCI}XB8+'ƴs!= 'nPshG 9T4ĒhMlb/ʉ*c$(0f<V/Ϭ jxx AsWtvt \3-ɮXzOI3=[?~ &|z `2s<1Mم_o`I<05FeZD6ci9VvZC-7ث#bcsspx9/ ۳{oLX_kߕMDWD|o>vw~Wۃ>vˠZ/cL;>_C9f'|Xw{!E9xk F`"Fٓ3F{ޅ}asҮ B>G[@54M5ǑZκd0ͷs50] nK#Ybm[b濻e9ڎ|d[D乁X#NfP ,G5!ņ6s@beE"18iy>`ۣTF_MqYøޞ=mM4k`T ]NΚ&v)o]ڛχB UoNӌ~ =VNKG+xs%09+>))>Fnc-jMEۗ2ɝg$Ncϲ9#̜TM~yߌ8?#8n?x3mX@='۵q:YamXK̼VkȮG_nk[qw\ߦ8bwiz귩Du؍h.h Sgڀ?|>cpX05~|ѷ{a]CE>4aф>eަih Bs,Nu'o5N &_x JµRONO"f^[|NrN;NѾY0W+\ɢ9[r1bzΪ9=.z7, 歭#L=zxn^0mz %Z'(uT7A׸v|N.>\?o~w\sHx9S:'L}@{ 2o¸7 xckVL6=Br90sҜ`v'&V7} :Dw1bS8+ӭ#޼H,d}OSgIǨqyB-"U_-\Fra֛uq$Ųbs& \llyxS;kMUMψgK/Jh)vn\ 'nph.@9<9>pրa } XO]Ru!'zo"۔Z;l]/o&?$ dYfߵz}a}s#*v!?5SlX󜋏sx5&GS*ǫA18 2:ec{_{zqʏ-4mΞ>}hNVHR/*=AwZ GЁl=!ر{|?cM(: IDATsݰ8(݊>QcR]iRkt+pEWa*l_8k7`\;^ͼatc 27T0";w+I*khn`O3kq<~>6%O,4붡qZC^82ѩ!qLOc}Mb[.D~4vlXoxjКW˹7Ƶ=+u4&f[>kٌScs̮}=m )QMx 6Zͽ[f$Ai}tx' 9xft ׬qϵ\٩渜yCP~r$ĉM[nxIhkx_p7 зB^{_o,\k :M!典31r3Roڟ<2REw~v&3yZ{{{|qfB4m5?hZ~NO=6/׼Vs!="yZ43RyBZOK>eU<;MVfP%)wk?Z N&ݣ=}kauo`B>}Yb?iu].Plg0o]ֆ1p]mc%yu$9sC0HxBtO8ͼY ֛k׆f ѳ@O&d1)Z`Ỷ;V;nRٛ"`͠LG!n|_Ip =y'LX:-vGofCmr9MUE2Ώ9ZVcǍĂw36}}:_5>ZMX ~<\yX2=pl:R[qß9K6 u&`kZ?8 (6p9w )y=N"9lpiE{$t#cq U,ü~h3<;v5`j1^;Oln%LJV\A| ̰ٖ6"=c_ؿ4!ȋp,-9 h~0}tek>1b4lBqpeV~ٞԑSh/m- o LÓo트ݿ؝l4Ayw:бY-955Y% &ɉխ8>Bi:o|N3<s|a_  5u(t>-n &;lW]_͏!e^Q,bkQ_>69C^Ne_uiɦ?yl$ uB4=߃".o঱4 g?eIVEu- tet3Ʊ`Րw=m%9z۝LP/ = vi=`PE VԔ{*gyGp<>h`ij s%(/j?$ZӝakJ/"=ڐA?WfY6ߔG>4 7"N@bsrpR7R991(db10<\ z6hL]" .Vjv@%##?a!=4obM (8緝<>l;'<΢{M-O<SDrrM#5ɻA^Pty Yl9'Ȍr&7CWjb`N^xNNk6Hjp>[̺W# c̟c%Ub{u 'fQ ި]H;Ǝ;.V[ xgL8BÓ(U7.s@` ZUՍ`a-n5Z3afÉFL9b$]X0χI>ǡ5Ƴqp>փE pT \;x‹ڱ`^ =l՝m~y!x-zxΓO-o-Oxj0ne)98϶$րLYH 퉻9j}'e2 7!\'f{1uVNO է}-!2L: L{c0>o[GBw׳q wedyj0vwb4L ov¬xuOOi5SsU lQ{5]3&c=Bbb@gyMOfι4>=Xlгd(^kl$&o1Cu`.M4F5b)P\c}Fko#F^I uM[qciM?JJ5]KR9ع#>^ox .fxi@}#obo[}d Aއ 0p|XӿO?pvK/|mĽ S'_c>[q V?Nhec,l'o-_(A˖PN49ua86*}ۓɱn™}3@:w؂ 97z)pJMxښ>|ޱJ;v90:>Vqa8baB͸mjڇ󾎄'-ˉko]b֊|ss8LcmN,8/*z_O=s)|#)yϷךѷV⻵׏k0q<8F)q53CI6g7Ľ_RZN)_MPxko bȿC9 B\w HXl[O 7GQG?~ l6* )>2jv7+ι_F.|4Iv0;^}FV8V`oY'W"c<"_=C2b̺nq'ȋD9 's%ш]3[tzz/O.@o.V8Xעݲۂ:uJy&v֍O8:&"`|-T=@^%F7./7~g浅9 7,': ]N~\lj=m5*P8 Ś{ǀ/ۇ;߳'GOM!0gwנd]٨׸`h Kr0>{Yc Q'F38م;EZF4Ǵuԟyn*wqؒ3c3q<^KPJ}hX6u?zxy>pi`^yyk9R'q|x:T^pa}(g :X\-Kbe:|G^I0q;6r݄:`۹l.e֩[vV|@!| {TƣXt{CͶ[OeĞ߫<(3NmphC:EgcҿU I*k5P0lJYLoe[Dq%7=6aze{I[x=`lr$/97.o [ ʹ;Cޡ5s Ԅ};0n-ֻF0/29G>GFUF#v 8>osb:G}s9OGңXܫ𞥶^;*:@rs\ug&$\Ǽֹw(t0֮\/x\>GF776L'>ĝZ07F?w,439x'(;yiK^9`ْƱrGvT v~ȵsUNI) 2cz5Lzwc"wjf,*|$8s谚ſkcP+Xuo.Pc^E-7 Ǘn'8칇9jŽy*'d鿁Z(|hBqت{]lUX+|Jsr2\県`sUxWTtszF/>ܟ 3l;#廘 |^Sh'kC/yv!v5MP Qk̐h$4jNE^/{m3rA^19 \}AߵiʹVϽPSAS {,[׎KqM>pXjy9F=xđ^GYV?܃^CXɚw{M^@I)>*kY/ =Cs YĔԩGD\N#v> z ́ iyIMЇ[;tfn'Mɉ/^ y^9P+cKx~@EcKV~%m8o9ٺjpX'SDsse!VSv>oZ4s_cfEuj/G4^lέ`o8 pɮA z_|عx-,gkt:M2Ů1?E Ǽf!M7 W.],9X6uHn>tg!;^Dx־\W@ck>5 wjiU03ѮZ6&kPS^ M}I[cY@=id~_zjkСW>xg[&;˫(Ǝ|A܇,OqFbkagi9uŗA4%m;8XEWm=|6).yo8c6dhbs5h|WϮ(ּIL 8ב s2^k7lâ4$|f3ݎn[:_ZԅԵ7kUDҜ-DL7KXlF"WPWrro)4-daY-`] 3?a\b =7&0[Ϡ~h Fj_ރ^oy\ly5]4+ ~h``>Xr0끃tC/ hGI`Z:5{ȥ{q3a6;6\& [>4M|58-{=2C7z< J. >)3:3lu[q#:ޙk#&juᦣ| ~@P|Snz^=ŵbzz59e@95;e=$ FW߲ͣ8-vx,'bߚ`ŒDYaz"χ,{𚯹$6yъ{G[;.{9؋Cw]g?i+| biT2%UK}#cW~a-Nn9Ÿo+ދ󉷩Ɵ\?Yc8 L]>DތLȖNy!Ut4Spb #w}ݫUK㙃w^4PCfmsz>|F@,(j\=Ó2Aw:'ݜs9KS38Ȧ0vuɡtŎtGG"4.Hܳw[/Jt$Y5lmqV䶗h| ƇWZ/ȐXk(=|mڈNMvpn|:ok5>[CzaXpэT(В3rbɫkt1S LN\qL1xf[ k~bY,ڴ,1 gZ2{-ܰK-bs@&L6;Ͼ@k\17D B'zE?p- /&waqNTŐsȺj8|%c؃'ryGFc+(qڸB~IN⯽͡MCz쬓aӄ68¹wHI06Tܚ̉UĠױ%fo+z1ocG3ܟϜtNC-S9yu8EM4 Ccv^&`hæ玀Kݝ0Io`\;Il+;ڳ9=77Pۯ hkD"w h3tCf] 1Ayd m0gDŽ?)hB~u>|D2Кo mO 6zi3>Smr&_0u`H9>$y1`!'-_"VM- wN&Ahz< IDAT ?}~`=̍hÃWt/s\ӈ[ǃ|vCό-.!v~?VN%6^XFyT|8΃n8?>4FNqv=IkN ں7-ȹ55ǟ;zWݛqWé6a׬+jR>}`]9iͲ3IoXfmֽThDB L^<ޱc2w :ՌV<k-ьd-+Ȗ-Z&׽of3D6\ ׁd Lw~.:[Bۡ8ٵX~|l8'.̺5MZ#;p: ļ :'V  6OƆ_F/{< /0 <C/ƃjMˢ4>/抟#B--k>\L'؍ .2: KlzFԖ:_ Vu>;za}·Q ?fǡ󍴏-ܩ-&Cڧ3b5ٚRhi>0tzWHZdlJ>Sc\|ЉH[n7=8e"H kRS@g@ĺyOCiB4c+ q>V+V'Y:w bN>6hkv4'9GnrLj5]=OhhఆMoj1:`ڦm,8~G,E+'dp߀Ȇ4 L"ߒ/`E9)`}AEN%}}` Z;FU0Pn tm+& R=єg;59 '<S,6` Oo nw\VqL X'Ul#'Py/I.|8Ѝ|=Ֆkopb<EI㌕':>xklx~j7?ڻnM0KB5;ClݜZi\t\8윇P̒Iqp<~.ѡs> ?.tAN> ll4'bK%lS`4?>Prg/\gУcN'\"8#t/D!~e4m"K}y]|`h Otw[ae2Yu@MXx 9qLlC<L'3FOAdAwo<6<:S!9D)=zm*<9֗lI)P-s`rC_u'X$s%qfTc@?##a!WRg. }>Dz~f_g,tn_0%ަq%hZ'n[d!j.Awx۴_^p)4@:A$,k9.c\1cAk)0F%nl 1i\[ ,a@,2X>=Qҫn?2MxIϊ8\ h[}P/B10xVL'ط]k9B|k~4>Gj7,ZEލG= WNf`}מ S? qe_ ]YW+,zESspڊk =b̠PNZ/t:Zӏ(,-b_ ƉQh`szc~N~Zh˹0ܣ$^y1XY|E\kҒLԪY.ǫ78vBCSs- 캯g@Ƶ>g_?ŹWwpJ`4(sŘ|Le:3f?Itv:a(6ot9-SrjƵΡgv796ks+,fkwS{k mIm+m!F,big & ݯ}_ 1>r/ I޿6n.$=RYO\aE|.Bx,bF8>/avͼ֓q>7Wo.ߩun9}q6Go92 Y69ݘ;jFo  haOa<UVs #C Vޏ5"M!.fS!P~ +]C3OWĺcqF40t5ߐCI{b3!o4>Kn0vu%ڇ-;<{r0҇`(r!񜷔/ sN{r*95HyRB\og(sz Ms4g4QzЄm &/ŀg@ԬǺsЌm\p$ZSoXò2!pr$%yH%H,ڴZy-?9P$xY`cR[#M1Km=[kq3-ӻ>-CHE^KAjX~/uh0wy3f;nW#7QadBa3ɨ;ρX=ε21 dz>vc%'Br#spk9ɚ; K[ZνU=l&)q|sL znE`cR<纜Np;FᘧV't,\d~L񄤾_X٧ 9}@Hxex8gxwͱ˱Ղ&aZcӽ6˽%d˭!ݹ݀kx,ullՆg)g0 "}L%TƧ$!#8~us֚>&3[wY{C5aTb&OpRl㹖ppܼڶm3MZ. 8-O?ٞf3'G<޶8I_v(ss;3uaüp1.575f]9M.Exr08'l0b~RcWr{dCEv$?[LP yXڬMƓ PkM6bƍon G@_9\heljL-09ЬS789́#;3X8q' ]P܊`\Ic_<)bH{ހx/,'jSKm5Xsp[چrY*P7<P>bcV1uVkw f5'PD_4LOږ b lْ9\I`$oh0()vgXK,أb; 16eЎ1iq\hLQN$fY`796.!-E*RVj܇ǜ$M5|yF\WYKCy(I0?WAӗL$z=+;}!hhNغ'W8G8CElޢi> Q黓PWj 9Q87z GIccPjTP]*FA houkXq #6l 7f}PpvG2,#yGOf@"&t݃hMv,L-#IY'3lx?jZT^ Z\o g -ux y#ល[ [_6!;9):?G9R7GnE.ڴ8Z{r"鋴XʟFLOR a ~l4Xsqyvxwjx$l 0-7Ժy- 'h{+,"Oa4I b숬P('pdD = BKjfӓr-1;ZG#Atݏeo,,p Nxq[4*uZ>Un4!aL{c?XwX`y!߀v9c}#fs60&u쩹`A i/օ'H"UxSkj=if3hy_B]t#ydڄ&=jUG ~ׄXKC7_`XaVC7O=qEN?pg,1Gs/ ȩ((x ɍ>̕иAuT tTCW+sz*Ϋ*}w JpM}S{FכĖzn$ `:búܳ}bSR>W'ȿsV>D},nlcg10>Wʏeׇk0w8y \?qs%OЛ$t1?@`\KYsǟ.IY$^/Wx.|,柳 v;%Or^&TDz߾/}t8I=K9zX:;!z%3 <i~˾C\t/yq0F"׫qZ0)MFs}[Z<Af7+|yպ1> _zN8ON*-` f:+FUH=&[6~FqclvT'g?:u :~SR=t'%oNxs j"g1&/Jb1|~=\+=OhMExx|dKߞǟ:6.tN}眢{?3 =޴?1lw]w #^ EO]_4oZefU S}wXK`γa!szE]sŢh?S#)q&\\cy6c+]fpj}rQo.k1Fp26{۴-[q:?pw e6gszmY; wmN{4vplsYGAqX^Ot\y~lrqypMZX%ߣ?ɘE9oc~&\C`cCO O9X>#u/#|bt{\߉:k}m'J:q!zT%Wp.ޠAe$5hglLW<>db_8_Au.$^IIs R\޾9c6(,A ;i 9`G/~9&wOOvr>T=03v-*~c?{zcMyR}+l=%یhg_p{Sk)1]9!>'92)뼘dLxH`ֿ}ġCGyx{.=.]:m^|x-잣+׿ñ$7DX6 N_~;@pz_ey>Sjs{M_ 81 M;ۓnƋ}x'ooƚ6>_yc~|弆H G8'p'qsB{i/sC/rM#Aa<;~As ̏L]rX=[#to{Ǿx7/ L~o>F\dt+)B\/ոk]ΣQ1rހP8_X};|ǩu oʤdۇu*.jNt0[9"zuVɷ~8zK&e{ [n- {.gw5:a%.1OSe[{{fZI*b}~][cOvMDq=PWl87|OBD IDATFx9g3~s#[+) 2R}<ֈdii;9 zj΃03ǐ3 ˹ʯV'Fh95%^3M4}[N hd`=}fqVw\Lvf_jFnQ1%WLsZa]kۣuĩ'E=<~Es=z1 vc핡\J~=LvCpsG'4.wĕ+Km[oqˑTfX_WD_E+8|jiQV7.z/Gx8/`[q|(wU>dLƩwwNy{`/hkV#y _g{ղ-{wX~,޾t+;cyvε/\xΗ亹?CۃhW=5kֈO'&Sr1k| )9M;K?h/Ep4ڞz{Vs/'+HOI_9r}&I3PrnZclj·EJ8;w~#|9]32^\,Ϭ:͓rmƶ7c$`m=vrbq9G `F_c?f!y} k:s`;X*{_;#0{]k>}83;|( 9ɲ@2Q95n7d1]9I>c| 8IP,ǫ}Zзq vjW}eaľ,cZ1{r)J?5HaL٦~Fuy$:g>RЏǦZ}uoNeXnڨu8 >eKv ` 6njΑYw xW5k>;c2#}:t ?GwMl<.4Zo]avz >?5Om}>eZgP  ZHd#9 Ts7d|} ЗLpǰE/1>hnOsiWk[/2[ u8>"~N ?O3>:^4I/X}*6G~ qO"o6'VXBUi}Cbs^[>am,2ӑNY扎^Ť-z1nۗknu8W\HvM&`7p .fߞDKݠsbjeL9+;OzBpL] Y8>vʸiI\ ox%Ð=~G~"(\#8 bqymPsQCG݀9dϕ=ߋ}u|i_۹_m1 (>cjw{?}*o:ql8͢?Ax<`.< PPޜvGnN x@́4 {xcr$}\Sބp;7G]O=]tTkXGga{zBcsb9-൏{K.hDIV?vx)H*zpEdes3w >9 G9o#15fy=|GF,c51Vem9߯-;F]lA}“ݏ Y=WkERy7 mO|^wuFKgMV~}|0mҔ+/7+I G[ qI{~~͡%FWy.z=?Ԧ%]a-::jl}BhLD\!YyޞZW}y.J^+o(O׬C|Hz])Vp>2NO!1p/S焺ڏכaհ[xp*| ?^ ֏:/F£پ4la]0>Wl9kW@1$4cm֎Y?Ѷ]/OTsM|5kT>!x GӭAn`f)=QO> /\a}Y>$~p]W~J b>-~ml`g=SĜ>!s 40O‰csMF7ܮ3Ҭ7Z$ F8P&Ǽr-Ѻspue_|>;Ŝ:ʵv_s`c}ƱjOYiXkILԵ/WVk!huaC _ߍ19w"ѡ`Գ=g5' MbNFpn&p[_/ߩo= z= WH:cǯan{ҋoiuNsc  y).|z^#E4g8H%p*(gu7fZ֚+fs zdu'H~f|,bcl8ۜ꣇|)&~ΜSUעO|qy\oxc9z1GY3̀Ʀr&(77D@rzlnqJ?>CC)W{qM_N?)޼q;9`S9A>iVNGk ?PIdXc{Agl‚;&6 ajN..7;#z[4~n>Z-yZ`_8o9#SV.󭎤0fy;= 9A6GFcqk4%qkqwN hSF4F\*&?x2NOdMMKn~ۀ /y/O 'zy(5YD'}c$^c3;y ytp?8lcqz'N-u׉|l#>6gc!|hL$>h‡ t #6{Hyc :irlFn %vג :LxB]wǚN=Yˮr<9\'g:v搂> 2 1l?1I f: dwM/ \ 3Zˣ.I"p22SdC=;`FLa]^\o8?i`熠tzopx?>s (A&{ZG,߃ŁDi%I^b7{o5d}&}4NчfHyǾՓj7a2GRN3 .b=c{F e<4 HàrA pZ;ucA?c Ae;;g46锗"謹OB'0槬a7-iʟζF^&*1zXƸ"-in#zX@-4g߻D:uR=$1x0IfЬ<5#~Z!g^}  p~܇Ao zΎkJDae49cqׇk}(zUm89[cѫ,o &tYS`R"n$DX=H>&awcZMfh76ag0gzEPN$Y60Vc'A-7'7HydtPt0ThZdYo6;F'ÈxȒ@߱ϥfr sVj$'> ?ߝSsoek"({}$J+ X_dɐam;6\/Dh}y~k؈qf{Ïпz5:Q1 ezr-a^>mZ[ɧu~[ӻ:f+ŵ8{oCkyzkaH">q8?q ::ckCT:\=pFBȟfTs0e\],^0 hq)99~R;x c5X01C+pאTL|}=s ϓAEjF Ռ1 o!sn dNNdTO&nжiL0HҗFadQN,N>u]6Eq 5b\&k.lpQx 칧3na@> B`Tu § [p˓k{+NM踽u6\Ⴣ#UI N!!@\G4;a@q fd}46&Qtڒ\ҿ>u\V}[˭(ȱdH鴾^%c bLɩ^)q#WCHv=7kLiPw1=;{cZ1(~ K N_6&~l[s4\HNg%>|z[5$Cg 0}]]p5h〕%'pJ]p:叟rv?.jLO[D< ev^lcue:;zG%jzV8xIp y|SwMWhר!\<)yC7̛W ߋC:_6HrEF|d74IsyaQl\'OmnscxEi.c[wyNevO6Ƒ,hhF7poasmG''v#N˱ ls0 亸gt`[y1oѝZ_Hi7PW}CtO7{ȧ1~}BɯbNflZ ?*CbW=юp~ Çd>7`xt6MSxp^.4hk~OO';j%OuA|[&Kgffӄ_tXkϼM?rbm`6 أӇ/@1,)5Gmrxnj=9P޳V&qρc@)hw?95~y|rzsRv<ǁC6۽ixN\5q[/99Px/0HKܫj M2 y(~3]?ooO`cb\K/  ;Z#OqN.a ;,HD::a'yŅ&^%285d.:W8cWLqDO7= ZdkO~,d'G (p4)Zalİ!===rl}Z vyu 4ђv.9VD}y6#%2! 募iActx-*{fL7>aqzy(f=ф7{an}lΥ7 1[mF/yl;ӊkAV{Eg@sפcz,?&Z6d"@2V:aRx y5{ z7zm?:vO+QGZ|qp,M%]yh.crs`mşȳi25+F;.ZD{0I=`ۘU`Y 3n3lc8a={?^"MM!<"Q[h.@l{kJ$gHb^ll=hܶiNE\k6ݧ>j6F<뜙M@G;L΋C tkQ 3e2 %Teljݫs52BOs )V1ԋ Tv9g3Ψpr Z76:CǞ+(ٹbVm|}!}\D#CD z2RpA8<>/O"`og#"=M~MT$[mhOC13R|s3WOu'h Ɍ1L>5j"o^|~M̎K {#Im؅w1M\tz7>MݖeMkv8pw'Ə]-ˈNwZHRN0ns+;1 Fn8ܫ'6.5_(ؙrN*b"% ɃMVgs" (˓?c{DIujT߻oa0#3"OYe~O" k%9@샞=[2av)>yZ73'§~h8rGM\qd /fnOлv 8MX4:eÙ{SLu;wu:? &^|Y=!i$2Oo8?n#!Y:jrF9ek`'<݃bGg{O{A{?B|~jqRm!Xڃ=V?OhR'9^}M|~31QP~/1ff'u,.iD2gB,? gLlMAC9k<:W1*1K X},(DN&?/"X if7s<<#qͲ˱:xzoiuc oo+w}N&kuATҠ'ʆW% ojdpFs7G51jC5y]INUko6?l{n"7@ll_K׵YՉ7sO9rGp@jqbo젞k7=~X{:5}ZÁ =0l!p" < s̈́.  Of|7^}-׻߸yU&x}q=vYqZsͬo>#]U'?$gz ڹɴSGR tY[1zzhbCm̋E 6l1:[$0s s[A\ҿx"O:N1ؘ7sr] pacЧ<q)Ddٯ'A9Kle -wze 57_x>]Wg5m,uB$_>ӱOu6;^dRh?'J>yDFWRTrK/q|RBwmM_ֆ>>\?Zc Otl_q_%/xi J&p-W>r#"Z`Ɇ_&v k9{.0 굡g AڲQY#(ygĺI 4M2gomhDdV?>Y1/XG7AN"Jn&fWJÿQs Z舶pZI+<׏lK>$a˹ =Ӽ$ ¯UXj6elp0g  8f{74@#c7N$r{7ShwC6SZhRu!\ s0-J't[`ˈ>,mH~ qa\g^jNCǑ{\pe3ܿ3 LǪo~~cFA]3 9'ن '<ѣ/g{A 7G^zeu:fJ/fY41Y.^lӿ>~0s̓oWr froƚWaEsa/7@1ҮsC^೟/rb ح84o|Ot]:1[xM0S WvHHFǾ4O[.+a9O 93w-ky$s&yјz!D0{ o.f7L1PŚSG|}7dz".{:;A+9=5k3Qs5Nj4|ރᚈ,3#)Fz/y `ڵ$q1gcNnb&gat?rlĐٳ9M n0vD^$go͋0~羊}i}_@,[;ky/6_rxYv1њVS5 cC5UQ׏CR=i5Cmv 'صlo~fBؘdK/ӛ[!al(|uat<ߖb7g [VM2 7vX%ll^ Kآ{ Ļ,:YlhB=l Sٳy$;IXvõ?GYl٫~Ç;ibSVOsjHl!2)Jxϡr %_OL݅qP'TNWwj(#L9Y66}qqD'8?Im#sz9Kj0+O#sZ/0うxOA,0w)rTmf 񌸁Mo8ZB_sRޞ-J ܼ$:! J@r$j.2񜖃[Ǿ.$È\@u4Q]Mp1-6yW |rOuN6;f9$xIjl4ʟ͟+|<˷/_EU ?1prM4 "c/d8uk7p̎Y@M!~(ݦn9u8ONX eO.b3D/j:a#GVV̌Z+kzFzL#Ysص(bgfy5/?LO|`{Nj ,¼Jv7#ж6@m~D|)͵q=,Ois]H~vaK9إǒ!ƭǁ&zMMٿn,ln}GьUgFhu{INӢ+A~cII|gײl#Q >=2Fpۃb*QphA1Ǟ$It >Spַq!<4w,C 0\lƭd#:J1bU:2gSlf\;ood-?dç{ mWg0֋@㲱boNMe er7 A s 2N~p[4a[|\1k]Mˍs}ߵk\ jla p|0ϵ;vWĽCgNY)Uxؓ1\ar ZKg$SmlydN1b38Ňi,G}'vYΎWzerBE?__9pā$>WsAk$eAr.X(5׿oɽ=^}>k ݃q5ObëW7zp`lץ"#b4[vYV79Nf~:$X'!%gOKKdMG` ? mnRG`_Ty$-){l9VcQP2Kc)ns$ڽzӲ[x6y{-!>gex<BLr}ۇٛ1 aΊs-%$ϻT\,݃h8{v}x~,8ѯļ)Z6{?79H:]=s{|gh+uh}?ùtط^y^N @KkKs=ǣg2fX,-c_miAɶ'䉎XRkҜ?z/2(`ͽq>|IAMl Qݴ3;6pڰN? ;oJT%94r+b~8qtzXZYQW5K5g5ӣG[ !aM{1&K-wq4L:Q ' _~@_,p08x炷Z'DĘƒaLj5Xg}amx#X[wf֬1A>'CX UN'GD9\آO2٬ v{4=(fϵ6nkG.uhos}b1a:_?YX1\,jQuߛUvYҏkkHJ'eՌ>$:KPbphu'2)8tbqdLvj̤c䎺޼L]Zc}ݜp}p~3Z\oj͢=\7z>C}4 uJ(Cs\`5۰Or;2_&C[Q[x5Hzt`uP?lp #؆V?Wu'0k#YUsC621ٹ/:yBLp?3M!6=Iwu8%5175 z Nz0-kX6k”ykonwOWG9f75PցV$+GwОcZB޵ŝz$ҳWcӿ_O}AݑwRhoZpCõ\tbəb&&9gf1{4/m3#\_ԣ-RRb읗^?]dt)o%})׃¾O ,R\Ӑ¶PNo('tH317 @ ^T?O l]Qđ$*9J!+xf?y>H~+랪5;מ]@(rؤl!cóz,9a;f~m5֭7w6%ItqƅGA 5/^zNj3!`'=@b5s{F f5ؓSpCcO"AO= j~?pHTr} IDAT i=g{֋C\! ͜(r/ uax?_F읽62(>Ԕ':J>Hyn66֒zDk#7FYg﮹>kDFǃi0eoc.CO-{)롩Ьs{|7/-vod>yZ$5I\Wy+s )n {lNm4if1sZ ʉZC^ܧރ/JXY*⃊=rX0.o4\뷱wj&\Σ/ Ǒљኑ@ 2pr>7W˻- ݞaP~?-qrHrm{B|iQY+簱>gipNwes?8fKR<"C~l%u4z848Sv_\Y1SgqAΞ~½~rN/=zny 4I\Tfc F;PsQs.a͚x\ R[ЯN(ܗ,Z.懠B; kj^"@?=$:`u|p?j a^$DN٦7}Cp1*YֱsDcRP\4FKȾowzdfŷ&amqlȆQ_?Sc\&S>^Ee>/ظ&j0?2w>M3з}_S ^(j\\hY+=0T<_1^zOm{M5pO0-1ZVL.DqM5w'毴L]'"K32]vdB8wSԗ7/*{{CMS &'1yS-3P'W=Km3 :N9Bbe;qyc0q^:kl'1.G^?s9p`&0c'j #|8/?'rPٺ7F:cSF5.{kX^s|sN]ta.uLԟ 5ᑒ:4s3Ou'?X\OJ6 dze'AĽ{HC*"^r珎p Z&-^1G-]+`1 k@ɼmY~\Z^? ZBbFڟZ0hzIH>3rZxQ:U xy%}B19)5LǛz8f48`}}}T2981"lwbGk)O(3>햰|8u?Ԛ:<0&-}Iz|19=iSzQop~K:bη7F({E+zp.G\g3p4¾Ψ X/ cׯXEcN-$iXaD>;@6ʝo$qʼn(y|xb~ ͼfDs[[?-uS]wu"}ݗ`taͯ%'iZc)|YFiq1w̙oxl)x]`S;ƱasB^ȖNmi=኶l6^'C048pl>:306$ՌG_`ipc3Zsk v70qz >lo=`][ !'k0kf׈h79͝J/m$)MXsDVIվǿZ>%^o͗fimp}aYzoړ5P99Xzb\pڰ =!Fd)8m5v=>ԦHcm11YMk"$#W_!5Յm_|#~fhs;rd3_Rfd6l@b:YX?yC9,h3$|I l׾>U;£qo]gL2$!zڍx.=^21S{agY ;\kCDx3E.a,Ә7^np^蝝Dڝ+do_ׇp]}lrĚر6MQ>^ N]77=J roiZbV/b=QT4'm0xl:1Ë(ד^O:'7]!kqTFBw4q±>$:Sg]14G'q"6~:B Wb!Ұѐ+~hՙGRrsW_tvӸ益Z5Rbi-3}mџͧ&xgkنO4ʠ=]R9ٯV'>}5t4BZn6׵Ol%II厉 8G9DzNs5l]];&ZM6Wo<.1fPr5ek3ZϷ::G<>8:Y9}&z ^ѺdC|@gr.-5!-ߣq͘ܗs]i0@akɹZsmΖ 1狳M]w_ ?!q/5C=c"|I̓4rgۋӽ!^ 9~lkkx %JXu.VF Hپceo}QJ81LD҂PyK_m脔s1v x1B͛ؿtѫ }=6O5Ͼ:Ve0m,/'C½MIC1<6[Xu9jQ(-<#uΒHN^ e|ԯ*s_ keD0txgq6:6xK%76xև'!ۏ7dEi :A:jukzsG':piU-3"F_>P.O jcbI1Z-H8P: L1`Y'cL<$,MiCvspS]lhȐ>0 q's|_Μ!*bȄf*g}֔-ڿg#bW4zЧ ]b&l".sk^|֡ Xp-,gLc?Tk)cHa)7\Zv|iˢppX<iY73Vyÿkr!cN/b&iY lg/r$O5.i;kpgcsHk>irSW"~Ͽ e=U}Ւ 6AX;aOf[OCxZ1"3.-<+!n{!cs.#w2Oɶ?L<'vǡ7w7) [`-\4wCͰjLC?iyy8bwFgp޵K 3\͍szf(++;-1C9xzsL'Y}Ӝ%sypอg@0%b ʰÜnY/6<ͿáiNst}>\ұ=n=]5z>WͥVU͇ͳ\3'ZXՑmbvh?'r8]?E]k{Yxh͒}EB@xz8=d]`C>2;a{*kcFaY=_\~րe$WiѹGE`@| @N|ׄC6~f'{}-'wks/; k43Nv/WS2Gl$MI:'`׾'Ax8ͻV&y ֘8[f:`(\o=e,_|Hެ5e???sE|h9b7ו:לV'ct泾t> O|\[j4o/ԫ1;8XLqH[hv538p+Of$ 0o䈯[9]68 X0o>rwizIn_ު89[Vs\͚$FNm]._s^VE;t~@B(1;[նTEFa^;E)As iŽyΌ 8#69DacmN|#7&],uxN؞$`ZV'pH?gN@0ތ51L>,ĘLŬH?c|Bqm b-G9$i*g[#:Hx|8\j]J)`$8Y';έ-Kwۅs Or?fvdǐ}.'[g~oHÙq3|Yf- v\gχf?=;0s>ꅃ5a@tG-Sa`N΅)- -'C4kz:XdnYJ5u}`/`vl`ωzd=n7c=rҖ;YԄ .={}֭\y4$`4(dA&ͽx8CiTl~j$U4M觧 ] }{^D/%|66 ZwA4ifdž㺏yb!/fs w=B4<ـBX3ohhr_.X'+zaZX5iq;bۚ8{(M?B0'Oǻa}k*4͎qG:]..@h7Ny~_MkioNh`[a;m_m:]UNbZ:vg{cr|G#-EYrsjp|}=#7~>*syšsgԲ)%F}}j Bthr\3YX{p8I >$8'érS3%|[96 g>7qBw3 ˧5%0=`Mo-k.q~ۇE6=dY f:si{ks-Ci UJ}4wBxߜuriA.?kתӈt?0=l*Eq-%N\Z6-amHA6?}S^|J%yB1[晏=Ɠ}mx`&㺈&AT^sfu-Ny[MtaԌafRs4.޽ "A|<ɷāGu;]Saq%@E+2}ykGryf]r8.ǁlJN(kDcmƕ6ӧprCˋQyL'8P?l盽n}k*tcF>9D FFva.A R[05 Dy`/tJ:~(R@ygޚ%*}RJu:٣_f_ēY .U?ZCfz[LcF)g+z`fUG>m|äg\ODMH²yqT$<,qw!{FI7\]&6[_o]MLR?'%65LL^qD;&b>}IJ׭ ?_5>MmQ $= 84z,~>9 C1"Lj:Fgk|#^i<+/?ҟ:?1sc˗&(ҸZē/<ɤ2|)KL _c$}b>MEigxx=I$Z'S&,wz6\z`? z~}uR[bJ==icy^*BX Kgd :sb+c|ؕʃӔYMئhlx=\Naop~K@ځ&l^k6g#: |{ 7Lh  ~;~qrG K:"MCy\^ NJG+J tA6M|%On0+f@gq'ײ2xl8w1 jxs@O)"z_|׶>xˆCqw}|i)3=~||ݛ ˅<|IcPcڊ1Њ݌o ^ IDAT~c%F0b·xok;i0Ӂ. _Ytf18\trpIKq?IM{ȵ8桙p@Q`h+p)v-Ww=+ĹFȮܗ(9p^Z8Y s] q)4Q6w6wG7s^.[yE`cbX'_ܫL؀xpeصVΥ]nb],FR+\8ALE!pw:7gP8XfwOaG`=~G7ArcsSg7Ψ#SH]6Cseb *<7q޳fCĂhO67/ >,kn4G174Ws},mĂ!d*ڼg9\ٻ6HPO"4֔(vfƦYN Wj0~A G|ٲ<]@Z g h` !1'ڃ5D]_e#^l!ۗUQC:䎗9灹9:o2?ߵ |WSu.-ó!>oX;~р ͹^ XtOS q/'|g|53yt$A"KAg("o&ׁXs)*+u\J"̠\wGY}b&f lME8T_%~y'p/ℝknME#>brfAi6MS_χ$l._=·@1ylƜes\`M!_x6DE/ M^f9}foy5c43s[AZfUi{=kCs^> '^z}R?`b߇AP]/ø~R_Svx$g^KC|yXg=5r[?~2hzՇC~lЋc\@OPNG 9sO:e2fCuH`r{ZA_{d6}U8j&07Sa5`9H|_ '~wejdW}əZȡ\}p֣lg`& pz%Ue֗kǀ+/Zw:\AOM6O~At/.~su:HOuk\:Ӥω[j୭vɻbmnw s]yS3A^U' rZs4f?Ԝ=?{saTG.lڻZI µ¾3' ٝἚ 9[cDzLSM]Pʢ!\GTNl; 9Vہyqbs[&u&.R ן/c8נ)j2mZ;> xS AC.Տ] _vP dъ~0oNb)"0f~đG#9X&hlS y "Z~pHs ZO[jb6.^i }<5@m:1#D~G]F/ysj~#|n=]9UV˕)3D.~Wj!0ck*6~S@x"HaMU-ǧ]oَL=PlIsFR1)}d^ UX ?cI8Z//IVijg59)m=V֗˫mݖwwދ^PH(X"&dV$SXQ, HӒ)dEQ-DMQD>k $i=lsuN:s{뭷\s5pmh5ZXae׸+58/,1& :z{ ϴN-|>hxDY7h7`==OQWew/`CGTxb(8zނWa 5=pcע/cʠ?c|C a̦Q;;m'Z/}#69_|hY~ITR1qt67.m]z/Pܙp"X-X0j<.|}|?7C;fXPZX:v\<^Gm>4q~xXH'ũlUP_ݗ;H \/ ySќo|=7x,Mp't'o69^;bb=ɱrjnrJv,SCtas1cΕQOS<9ޜf=7س[spÖ8sA=?#5zuihڄ{vﴭfVucI|_侀ޘ| ñ癤/;Yo_7. 4_|CSkOc+v̼R 8?g\76|UOx_ݯy;^J׮;irDcߵc06%ޱ:??6z_*;%TwsxyB26N|X;F`oIX1 <)Fo  ym W&'Վ>vM;`Gdo %]84|i69Ϋ89̋;6p[J4ykZfc©1(S.<Ǵ_>^a͚G{ld//9Qn{T3pC>%Y[NfRfis:a;94V{6 }~]!crߢxk03qF7~9X8<0e,+9@|UGtx_rOpakKC>p1pCq~,5-apgr㺄A7ls𭆝G#-Q`e Ӌt/h]? oc?@&rѪ-+;Jpi%O=691`+UxAb"Ҝ$! Cz }VƓ+?3b7ǖoX}p>@y=ׅçnBkNH8}?\d|;ű?BL19Ikf;B8lgÈH>;ZpO6 [+|) ?W-@u8] Ѹ'$S&>(c"c\Gr>땹!׏a8R)g.)w֘Y:ϕM?1y<@ s?h.h0<xs՞˧@b[/2Rqs=K/1iÀyuQ8ݙ?&p\B/Jb^osL; 2M #p_mj^/;?m2:SӴz2<{b)?D ` rv怫i1\B)ou5χlmѲƝ` vBձOݵyr0`?eLqvOO^GSh1GGi|HbH쑋R^,{{]gI+ii/Cvw^']@\bWt~6oVKIӋI[]nef5;BD5h%7gq?')ZY{_LC]' D?ɘO|`( w96ȸb,6hp"b01uw[ iF :=G>"#:O:Ohӣ?g9L֏$2z F@=2Nan8dS񬮯TCH%s<'(}'Z-&$ Wb²z@Gtx?ќLbI;tꭟCpY;+SzJɋs3( 03U-n,sZ'|[ >ñDx)~xN:y<1d4UDn/Hn=QPޔ">ו/k""s,{%s-=\q 4JȔOcOm >]=&#avj10kXlZsS/t _a=|{Iޞ?s Ga?[=wbV!%l_/u4s> GW 3;9ǜ~?-}d^'yzDB;i(ബiߡ(IΕDܘ5=hX*gn[1 svyk4t3 ac_"|Kt*4gOިAM>AXkJ a6MGo7/*Cv = r˚U*zU~;D[7ՙ5COxC"5&v辌}iO> αO D9p}ntCgW xgKo<%׃䘦w~.`ݮ ëɍySK4ozʼ93=[ <#$lx3fK3 Zc~PdZ3Y2BAo9 М2Ol&Zc˩NɌ TR_AC#rpETD䳛Z\I!Nwq zeb2c)bcK^]An|ZxL8"|։]?ؚX,>yk=r`!Ǥǡs+$b?v3zqrj~PG\`|鹜;<|fwit4p6 {}r83?(k߻vϋ#=˛r'74m똶{} @! Z$7Eֶd;f?'MO,> F> iVMxkli|pN%Xvkj_{E^''".jR`%ݣV3;05yEC*#XrPN 9[v=XO߽We{rkk*Agj;ο#f;#1f)jY[|M0쳆fa7| |8DtnI _(|>w)zu(r9- aNQ>9ǑBRӛh kxa|ME|:6EN-_?n?T{ q|f-]| 7J5"6km|,g9C8Li Ȏ¨X5tsW#&~GAL%/Zb^ u;yNaŦna1@{5o4qL8\ȱTm4`b4'K:PYXsp|]ױiO8߱;㚟Rs `-t[/ 0/>g3ڸlccK^&*KMG"z݄(px+4M}jeĚ jtx4W46-h_j':~7x45Ӻ/&g:QÉ_ORXO$.h .͖>%s 2qOsn\^֑Uvy"{ُZs޼p( ύ]4qYU}CMH^Mn[ێhzkuAmMv[;.Ej :;x <_r}bD?$j"8bJO8sFᰓ8 9aٺw/6b<7wEOpji(ChU@Բ8j=Sc-kp@?{4y-<#wG$ ɩV^cd| ɔK\y|p0+Rk~'7̡|RI+fB.kdKx”/X^=0?pj]|9&љhYq5)m<ǀ8}>zj}h0a-Zs8.ROQFi$|>R;$h[%)@.Szw ^Iz-aR`,hCq^o1 &ӵňDPtE֤또/J%Bîbm~R Hd1q^(ؘܣ;\ZG?x;6ʕS /zY;97OX<ِԍw0m0V loaisϏ9+YiXOLg7\9)@ۯM_XŻA}- H_pȷANr[.O}`Ma3/OZOx3%40AOΧ&/N7?ur`A[-Nj[_xq&v ӑd A\91W{}f:\T4ا< P;c}&G9 ~f}z\j/`oᡙZ^L=IuNldئiǢMёsI7HKtr@QŲnŒ;':dߚoW;FOU+sR fH̢Mj-|`@K,|h~h`sa8K={ xͷuޔ$o(ȷ҇&V\r̤)Fph"$G{jg0rUo\Zr#lsNr/n0fgOJUѓPa7@k[tv2DTs%%i"uX8GS >6v A= `gܬ hӆXSo};$p"£wslx9cF !̛}oy#|cBا~g2Wk+؎9"bǽZLe .kOB0j`-pXӉ\ 3u`ߝ&|iw桌E/e|y¶N.V{=K48$urMP 8R eIO+z5cǻ}=Ƅv2iy5g7̝'0}3@Nn'ʄCER鱆ub {c&lIy6t,@F(_ ˏ6_i&*Ƨ;7Mzzj| '=7q?1c8a9'Y~OJcl3XUuCiFkҞ3`Yev`Vz{. ,1NY.&QF[&6iy[ڂ,5PM76zp0P9)\YpOW>졇.Rrw[-KtQAFi;g5 vŠa>*6us45u!9!ňeo3)'iRN9G[IJW|\olh8FFw%M羚l1ǪFXK7n[ qk5s>&cFJZ?P"s~7 8|#sbٛ.R:j`Bf{AF7+uh#~5d[=p a=.jݯșh 3vcO֫ gb0T)8_l:'dOaoGNM>}0#p:l9oc\ZdڠY5OcXئĴu sW?Mca4)fΚlUEc!9o#G2=;1T`-!A' HV:>'x0'Wb+d嫿 q McMKH85ОNX2%çpw2ep/;`>#Dߌ;$>I s\j\8hb?]?EzTlQ3;1b| dp}cLp83dD]OF9.`9R*N&~4&}’Mϲ"\(qtO/dDX6rъ!q%Cƞ/s~ؒf=l G\a|rĨ?ja*bX&#Fm-GkΟZ˟s\  ?,k c1Mm0$`1KR= .E\\+ϵNIǐqDi}q77҉۰U~\uF^rqjAsS9^'cJpԗ6_aI\bf0HZ*#)S+,^ٵ\*섫\#AM߾{ Ģ|]5l9Jc39Na IxGWI9\kGss&жyilv$ڸ^)Tt0ҹzЎZY[ͳ=0qs)Y?>d> A=⃏b#3s ޹[j? z84˖ ΍/W乄y?掠Q~܈#s§$*l)r=*y brHOHoX\'>|Xu ^V1)v -^AYACC˒f~g7k`:܉>sB|ZfeH-Z) ίĆرLO4Ҙ{sc[I2z4F]m~󷬆cb5,{m: Yx̭&ήO-6{| /12,Zx?_EM(nN~O!5B3ٟu(#f@X͕$5 6#i-Z)-mM@kG88ýyY;iBT+\h]q)'隭!1_N.97 S.kXWAxXuV x:CL vbnEgyl@ʁ%/_}?:uɍv@ZcfJKHJ_@Wy tskv4NC7Zna{Yo Ey፾Gwh\ktjNKֺ/VV_.vM GU$Cy5&+[Cnyq֋V zq=~x3cIřdB1Go1P"? Ǣ-RB XߨM^uɶի/yN' !S &oiյk}4s(z&RAƒ5i5Ccw| ,;j0~|7b9 S+bcX}C@oXFhix vO<޵,2ՏoJ2N4jH1ux}s?=eũn @:'cR/'D:.;}Ns&&\$ W2Hdt+Z8mρGt02`Ms5qVjyo j56Ւ>*j_6r&p+>95=x)jB1^C5)!Oo4xLEd=J >g)]~ysԮq8κ9yz.X8+L!}Ȝ6zh>F"2q Xø_4J[iVW,p,z]_&fMb/)b63;1 W8qNy5 |XgVK~Of}=Αi$Z%XFObO |sK^Axt@ʜm{ / 1j{_{ϲmg6苗2%gdK0oy{OK$~Lctnoh9fʹGFYNG6j>7V|\x'ãV׵?o.2="%fisϙ{=Rbś IDATZMZX ?tHq]t^/uCh~.道`ЏA&n\pGFϲ%<n6h 3&yQdAijp)GztMk>*~VqɛgW[Fjjb,m98ƹu',a0ۧ~{g|݄.lK!{}ZfzO;,OIs}ns6E(T&_D7l&"\g{욓@47Z4ӎcy9N4Aܣ^{[hJ`W@=o"]#`hMr^|hskZ4~r1_4][Z4&<[ysN 3⑀1H'ͩ7ԦQ95G=F_?XC=<x>bx7}^Yypeb22wj"\v?\I/NE^ =~Nm5QBb{Tu hz^ɷbm8;#8nV= o/7&;/q']aO 9Z2Xpj>s\cqwza]&p@6uVG; {4 8k^3諁l~ф5D@cY׬'D8w1_`:4&~G5!}ı:BmóMPNry坍֝7anp/x`O~[qZѝ4ćn_p,r>"+iM=qֹsE~)ua r۸X 5w6( =C[pyP N͎c|#-}<(_O\/=\a9 ~zҟ|!5c +2ּhQ|w0ګpLK hOI4!85N_F ,6gW5У  k]8BeӳR^DE7v:;N yH5mK [?ƽQĶɓr.(C:/Y4Ӽ 2Ǵr+iirgcӃJ+wzN3}:v( -d*E"nāo95pl 8:=u1NpDO#k!d~3&|k 2ws$6hz|ǥf-xF[RbnԢi58l9RWzlE$b='~|GkHL&p.Ycz΍:$sˡtN!BkΘ{d )cl[1Gk8_DF(k]kd]UyĘ~/YWROPsRdBG7[ғ?Ť,=\cNGW~ã%ئ٘;\hW~fZy|PS׾ Oƣm\˻"sa9mݟ\p¸x`*"$Qk{? @3-ZcF{.&.6'sNg pZ'op?b9h*- Xm`_o#T ;dx!lھ|RI)]P˽aڵ59F|OE0`녧&נih}v[(*Ե(b>OL'#Lv$XgT&ȫGO°fra+̴z chw S*vf@-,O#lȖa?b1ʅ O 2/otۿYl6'6>.zk30koIyYNFAвG#9S(>.0=l~J07 =aIY_O-s=U& X2&XvC;xA^z+"_FF9otn^2EK1.ޒ~ӻbVМ7PD6nғkPra>@#1|sڭJss:_Ԗ͟{^-gޱ*X35q}tVrg6 g}bs,qŶ4,t9s$o+;VG\홇+n'KӁCcĄ1K3oߔ])kP\J-}Grc!~ F(۽n#QrQ}*ïBa?>XßkrAL-`>XLFI9P 1/x'vR:@YTDAaM#$`m{ w.IX86;CK^S.*q zI >%kaOnMVNPy$:0m.D>_ˤ~sAqR2e1\јàǯjo3sd 2~[`jS.K>< mIapu4թ)Ǎĥ5 #Gȼ>/ǧ!Yp9 mإ\p>- xrubmcmmw"f5si{zoٞ6U<;Nг|y8h&׋=^Cz dxk?3^Gʞ׽aMhjG`MZcKt챧uMg?9sl1,Γ9Ԏ3Y7}*j8Cke3 &Vn,X+ƐYL8/"(6rȮy5P]>L~_nﭜٽ^~4VQTpHIܩ0/0hhIjLĿ#9˞XF?s˟}o~#O|O77+No9yc^ΊNk-7y& ߎ.Fz99?udko#ƹ$KzҞ7 `ɑ DyiK;RgϟŹl]ѱS{c>k8ep% )cŘLJ`"ցƹ^H.k σҹ_(=?R1vYGiΠФm2'[Ź6<`q:Dv9Sv?pZ\j}oM:f驭\(<lJTbVёrr!>xY r6sǶ;`ǖv4qͩ6šzfXrἹ *Q{ <TG'oqϑiwҀkd } /f:x`ƚXFO׃pӟ RS'LmNQ:|x.Xy@i-JƉ*}nLγj{Y#2u2eӅ85Cx(9yѹd;.G]l[j= 澏i6QVI7Y̧}mz>CpU#ǒ`*OjI 2(HlԚP G*&12eK OO@tsa% AـX9-ܣ}۞\vh#kajLlpcM %k8{4<[9ۿ O<&0&pkvlr'g]9L1vk0v!M õt?=cQof/~MV>/.x^t"rGʼ5☃ϗxOB7?g(g&rs=~sC' el.MsxRQ˩# aA|3n%wMCm|Z۩;^+P<Աx9{l=)u`FzZU΍lkr 2Mӣux:LFjJ⪵P%v+М6n q?9)s1 Ξ3DAڥW:a{j /t?ǿ3?-PEhCIIsF6`jKoy\+c|ŝ)B] *r5.?/KO<,}VgŸ赾f-Y?ϗ\zE2x?A'-g f ? 2D4g?]MC'\L7!/kK{d}b*G} _~X=?=oy8r=ڭ> C,İ<`oUBJp9WYhX [f}:Z,ڀzYa/ov"Տ_JSWWJXIӆ@ ps}7Ϝ3bcEϩW_7~~IA|{>닦cz!߿ɧV%,bu^"٤e~W>>^h(4NߔIy9}C 6:DSv@>?Do4מrљ! %..D7mxނG߰ ̜PPJ=h_1x/}5M&8'Ln$66U-d'k0_F_X u6lA u 9&+[`gT $GQ!y#"L`2& SYŹC @v9zR6k72ݗ"ڮ5O#H^u<ǚm֖<SVfo7w`nޣM'! q$kcc9H#cϱߌ=Mh/Ӕhi5s:ظ_{qCއyd?KծI@1^Wɹ4Oz?//]uش붟 ّcF,}?99Yx {k*E+oQyOc|/ Dor1<&t]=MFcg%OcDg\3qE\V?p~+\2X03gbRk=m 6s4Vx-H/zVsT7sx1?}?~Zr<횸/9+̻8A9O=i{Gu\Oh38R&ѱB ~ Y$k GdC(L-4Ztc2۟-O$_33KFrH槶bn˜"r lL_ i: bV~>7>wSdc7ZsMAs8}\8IR)aZֿ˜ύ(:icBi6ܴ 7˵Wf wO.LR^ ѝsyɑq`?&}tC<QGq1Em8Lf;^s|5*;:ǓchY^νn{~8[+|p'OX.ߍynOfPsG #DŽ0[ý_+?gMokKz|OW dz稊e,<9h>O7'O;q5`Yx5xbL8s2N񽎼5KЯ+9h, 9/Kx*qDh]]&ܻ>:/Kq yޣ4(\oFO+3o54p 6EMt5\~ͦ0ߨsq.Eq!jM7 =k~K.մ>ch:{}/=sN%3ty/l|M0k*,cIPM/8o2'ꋝ#=v\$21-Dt?5["~SpyG?,1<-=tn;6ч IDAT򵁞>0sI{_RX/9qd %&7p/KexxkwM[ÜD^BӸhYabqE?Q$K%2\p] \BУ/," G3d aBJ*!`#xO=k{-Aa>Y;7P'Z{ 2bB0'UfNnFC_4(ω;ؠG? [uxޑOM7X8LNCpˈ]8M8ڗr;6\>1rF~b_MɗE4H=: 0Ϟ4֬E~;ɗZ6_o0;8b\,^[=)0NJ Z/_zhy6E䱿97Mp~|tu T_׼C?_G۪,KIC&. =vb%<>&[7+CDp<~?o?wߨK<ǎOU'H?g> n8R~cLnO.5ťKVyh竁y>}j#hfmr:^qB 3:GFgdkn>/!;7|St`=DԃS5FjrsS[Lݗoy'W\anY{bH_i,$6{h8w8LQߐ3TK문xyHHo a8}sH{x!~Lڜbj* ژ3NV]'!{%˃_u8p g޵hjF+:>UFj6 !2p%\BQyTLEa5|;=AَjD2}V_5rFa99yQA$.GlO(O႙Gj!ۀHd^6X?X"qkeS!*v+ 4[s9~$8#t=IȱrfmFΣygə<$ya}B÷~ڜ]!Ĕ31 zʠD֑- /_+::o} !"` {,941caro~_|?]x+0sEωפvBOqʕ'\{|Go87qrxjXʛ~_?0O~ =3ϟF~~N4d lj||Q4csmV$h^#ވMv&6Xid Lyr NYkCi?goH@8]/YI5EjOU ']x*s Ql,2F{_]$@viOkA/)?xƻ}alԔ}ddd؜CviV D67t1G['ETAL@:sD6 57RO<ڂlZb{봵> I7?___ǎ?ݱo~ȹ&[Ƽ N\cM}}`"רgu\;5z.hkcM}ǐN10Ka&;}dˮuW8@Xէ 7}G8F`y !Z|k[; 5x3{y>?ύQ$0Xۃ? \G dJG<`+i0r;WvEIbpxSΜۤ'ʌaz aᐖX{׵ŝjJzz˱Za9TfZ3_ c^{3:$Ex:l:b 0{OM 8%:N°qr_B&MlɟR;b|׮44q}8\#v~aq^4yelxiM6\*>xsN$6-X.o ̓J,:/C?`VuF~ \|^bG~pO_c|􃂖c Pu; й˹=9j!=) i0 !͹?y/WmR:8?Q1w40%vNrMl8&;p̀g r /b4b']@z)=aR;a+xi{txOxB=6Oߕ)r{{0~gx:aSYx1&DvJ42E? 4%b฻Xŋ=} 5z-zb:zyuKe/+\7z͹ vySGrA^i>.}!=ݜ>H0\]Ұݮsb,O5Qyq/zvZ}F8b*"kd\L7yvJHoo0'}s~ Iqqoq(wGe8n8#i!@Yo!WvNG]bZ7e-O| &[4Oss7IX9<[nD1`A+!NχNOt5y[VEڎ|Jkz0NfǏ>Vgʗ'ʕYj AcQ]Pw'4a>n2/2 n4k_SG#ume$= 'B94b21 gX,߸m3ڔ7CK~OJ?Tiz c2.@}uy_#w En*AHWJFE&(M#ܴƉ6 f&ډ5jFf:6^"8 |9g|k}yGAVO zm Xp)Y5>K8Zڜ#?1W=fo8 Ɨn~X4D3>/"t`q㵏6jGmOKNl\Up<S3:rLWÖs%滑c.|.S+(>+&ylGFE]k:V 5l@U4ϑId9 1|!hNv&#~1iOp׍20ί*K wwpy<=nEgX |dLŨ}8D.mP>B>#tf,z|r$fpqs׉^ kᬀ##Asy#Fr闌%yċC#:E0]x9|bXLsʛs_XؗC{/{<ZZUyS,FVbK|]@J+7>=ِvԹƜu$GrPfgM8|S (!%OךĻ~(b`2K=<<@]P0S\.xJr;8ŻPh߬O-NZvOL N?lplP,_yy479s|rs8lm _t`,}/ ݃"-`wo'Ci|O<+0'0 Y"'55KkZw.$/ >H>1D[OA.u֩Ehlxl\OW㟲9; @ M\:RY A7+/@d#Gqf 7jHl &`n£Lusɞv~ 67M3ϝOf|"օZuƋȶ#6ns9 PI#^;N׭O>~Ww/}'Qː>v&ڂO]Qׯo92z(Pr)߾"Xh kz6或8&q1/721挍ˍ/nY0rn>Î6-al c}7Y±9O7;Ldyd{o،[Nt_Z֎qcZ6̓6={VRzFIJ>f]y.S_#(ڸ֚cInJT10V93NC y \̘cCךƞ{|xk߇톅n7V0ƄNN纑2m :jU?Tr ;7)/u"!U={=V򸴙+NeDdg靗M;^ծg>B>X6FƶK{`nqOKd1ϱuVkSqm,94>+~4 ;=>9 qRL}΢x4pWn[b Ž,doX?~l56G\ZA\8Mқ-oMxс3iPqko M7sәޙ`q◫gݜ]ϼ~p$y?B~8-{ UD- rl%Q-C- s]&w%ͩ$$7BJ[=m1R@]2 n`fv~ Paڊw-5¼uU8V^ZT|8Ih-& ?ԋpU@BfC7s ϋ4}R *[89\9x[hq6w/qV̤poؐc.I߉pd~ aIM.15>2u}O^8:^5u`Lcg?jus6h3\3G&ʗ0i/զc>5*/'Y:Š}ÀY k^削Tsj"Ol;a̹47xP &Ob ivt;2fx1~փiΏcb}*Xߤ;@ =}UO86J׭O"mSsm쭐<  (^K63/c{ۖ)'&C5NbIs ̚<>w (*%CZ׃?9 Hh6-IFT8K"LsX6rFG#;!زI,bh=)?=q-+)u@V_86V`yʁ]SK=73 ULlɉLFpy(V"C2,u7Ƈs+PJaHc߅C.i90 P7NF'\CMSVlq#N<~y1v1?;OS9gǬL^~/$HOQ݀ïU"cU<ƊƜc=:=v'=F̮; Lt2A[]1>o 9–} 3~nu fL>v s W\bcZ j|ؽY 5q4c_֖<\hΦuesJ1j2#MD yjnSK)* 3_pYw!4ٍKP/ Arۙ9!ǁd^g.רdX6n`Z?؁kp"ΜsW? %9+r 훲k#.ư*ĉ9 EG(1dFڎw.ě"M>dAx;>4ha,^;XX5XeN<*ieR}aO󺂵E) S S2H,_WX̆ξ^Ĕp+2M2sNV>! OC%71^J<+U1JdlQ"s1k .ƣb}.e}bX,/*"8*lPpn7-r ۲oB~=wiԙЉH;g%jE%uemuJ_cɽ?h{^9*c ?Wrs!^m|43e01\s%9@v>.i% *4-qꜝ?RH|?(Y"."c*nE%l ԛm&ڌ~]>3fqfZ<12}0Ү IDAT雅=Sɋ_9P0v.x '5gl{skquq!6#m6vU Jbo plvgaG>xŷ~Ԕ|Sgl6'!f;6ەp=/zQ45k wyWvTu0`vS+_209÷>(6POm,/KcC\E~3YGWе{cpNe69+oҵ#ޥm<7M2ls sKaRZ^dK}z z"=u{Ƅ(˚HozaZ&0}ZáJ5=3ՆY8ikZ#a9~䓯VDs79&H ce怵/_)Xr?9{U_j6X n&9fU'|ͅ> cS 4,BN~'6 0A&:v`L=)4L=Ö a$eT_cpA*|-|ϣqF+b|\c2$HofB\v l|P|< *^XJ=_+F_ՊLJ;8c9>3˃mÅm~!XAbۈri"1d}ԯ"W3OT`LbeZA㸁+j1VH`5yΈxn~ڧ~G=&,nP/=^Ar>tK!5NKj\Q.rk vx鹪f(0dA<kmN~Nw$-ߦܸAQ!4+_24P_^ql9ٷO ssxd=p)Geε:[g,vhqg7_p 59܌sCI|kcLD=4n\,[pϥFFKNK VM+ q"ą[f`5hc;))zRœŅ_<&= X+8Ek Mf38JB} ?2Xw ?Fθ-r*?cNNt1&i䪑襥5]űE8k/eTHl*:[׬Aalpcl_ e} O}SG&}1tə'.N, 2m掉9 YXx<P>l?u2gKź` ٰ:\ l!!Vq7(L% *\\$겐4KAlGK`7`8 licƿk:(aQ?a/F=O4*y KjZ]pL4Qخ'<2ITĵMcj TBv 4901S”V~@~2b91a>klMuF|_/0ńq.ż+1a`pF~~9+~c UI֣k`fb28Ѣ+-k0˷1lXqX`ƼcJ#?ƞq0ݧcmjiCfIᚎ-X&&m|b)umvmAM GD==" <ظ,ge;x2VŞ| վV+:vGȓ?[˃إӘnՠώ]Iz'D܇uls'=;ۿ?}3>$E> CΎY?6ϗCdhO dy8}/8/8nU_ cK.gn8o?//DQ@.p7-{Ï=ozG&Zc\%?uD_p[g<ǗٗO~)\=5#ܫ6KiFP:2Nq3?mo]|ɕ!؅XEz&ڭ:t<|'s||o9ێ;M_~O)W}|T(7"\.7L6ܱ HN #sĕ~)K8R78q[BL<>wEo=> e;W;~版ic"RWc␐A^4^ؖI~G6֛5 G/F}4~hP[|>K(SWI:ւ|ǃ9qg~g'dΙat ܱi$ b߫} 5>X[^z|}; )^,_ˎE䅮um-S[ }pΣ[|sO{S/~?ɮ7<:;a_gM|y73G;}Cz;ٟZsLkMo zN f462eꪛՋN4<12|&X>hUm&-=sƮ~OÇz]8گ+qpzGln^SKK~nΏ`X.L~3k-.>Nε+C2N=}+s/==ǟ p8 Đ-l_xyac>}{6s][\X, 䋪:5atpkWgk~/[m`k ]3bfpYe [b3h"XL4(xɟsLppM j%: )m36%n1%֌1I|YUEMPQ3G &T9Ɨ>؆0%( IDATr~ Ųl6+ ]~Aί9əXGmp:X-#CwwH 1Mɟk(yr9z``1w zM5}lMo_IۋŚ_xO<1mx3\I[~ k^(+DL'8$W6rH瓩(.=ڲ:,N[]snm> |]͍mpa8n!`[oc.p0箑5J&<PO@1[űщLyPÑ+5'Yb7ג 01y oDŽn5i3i~sY"'xt}g\ `ҁ` f"ŘfADm|-Y; yL}w?Gݴ%c.9yэ>Iv +k^=g. dݨ cn\߭+nnbgy+_}糎oo8Կ됷 pM_QQK@:n {_z!ظD&B6W7Nx0[g>#>2}g6ͥyz/;Ky`wן:&p+t[ANNf&"qm3ƏFsbQuHjϿ?>>o?_w|^woxr~9Bnkxj(*QmHOzz| _ps yM\qJ;u1i}L7Op=xxʓs,R)78K+X\YH> p79~g\mtk] &S`hwAC;op+kz!f#LdgQ IPYg$j;S};#s\>TfC80ޞMsz?Nj~%`6j`pvY9ӗs8ZrG~]eoVt_)dz:-`|u+-\"V1nc r[;_ȮꝇSRB?f). cG5kgv1l~$oSkaXn\%t H7."~D׸6 wR+S"^Q.4@~+nj~Ap#%dX]g.FspLy¼6IШMo.-;9cE8lxҤJ>pbZ10'èxx1hlߤgMMbTx)Iru"ղi<!j81]k>ɻ< D ϳ'E lh Xfl Ff:FmnfLaIV#B54$ ;}~_E"6sn7б#i{qJ_¯/^ia(!KE6Ad|ȩ_e>rBp`s覛ηicA8M-/}菾x.LF會T̹ x3s=X5>z?g˿ǯƯq|֛!I`5qgu^2ω<7rb;X7-ji >Ts>kΗP8 ^֘csb#~kHEy9sֿOz‡zG[ۙ&حplg5j/Tzb?pS?_[ v絔@-;玽o\<m?ww|>:Fb@ 6r-K݇ >Ua~?΁];B 'f>;ىonxW/֢ތ'/ehM>ЁSK.k^["GO(ʯȈE'9'D@f7CdMgz`1Lx5X!^1x1--(%LsDV> `{kʭ8f]z#/Y;xO(p[[hK:z*l5: ڏolɺ_a\%wf@/1V#C*]Ϡ;y,6=g6C:[8ǐArGa{+:cl5|Z.c k3 ]bncox?\#2ɩks^ ly/vc㬡 x63@viW<6&\/&'$5ט(:bP0IiIA@-_4}\Yc/\y GiIQ&kzp nЙҧ若,&U177l4k]j fsAqq#8q34%jFXLˉÏ}i<(y3v^uAEp >[2Hs1p$7hfM3'>L51$ictuan~K|ЙU~u8xY$K{܉UQb)6u㐼F>^2˗\drNxN>gPAz jns䛾nH#$9K%w4OqGAbq~?/|8XuYWzϱG4/ӎewO:Pyo>>&^y͸0cnK;:_q`ҵ^BMF}1 Y`}&ƛSl~*oMG_/>{5S`> .½fBewQ_m? q Cd:˥= [1k}2"dyCry<b!Mu_w^E}cZc"nr 0&s$".˙{TbZ:. o ~b!k+vFLR[(X'76w''cy 7~pHUEEN^=wxPT lӨ!7IeH E L+ >ք,|E!a4o }xVΝ61ħ~|"CqǨ51?pՐ"̸@erxth/u58TBQp~ШA29ǽ9%NqNGƵI LHta<;I~cz`^M o=1#WQF-p=2+ 19g)u܌ǀ$W/yq~t"%?nB˭>S]j:OFK/O޸\ƜXiE8Op<'a' # ("KO[sOEv9Wk1m'c50l3cauǍA-7;ls]N)O^9:x1_L@}iY\ކkkruQќlr\j>2jC=HcLx'h}HbAy;7@3mZߊ#Õj9c|/`H\&8]N1 šjsP "\\cYkd /zzB}1DҨS{ &aUݱFCޠv?cZf]g]ໞ ㆑}Xws>CX&L!OZtg7hT7dE$7}QJ/B-n$lbع 3QCF#<5;āa5++us$j\wMٿџokE{Uɟc>W"ڶ9K@VN\<|ٌj7 WuMv^ Yl[wURcq񖷼M_jny}(Q[Fl0]8`߸d+פ>Ub~h@x={E"ć{x,Oy[bqsO![_[c0ue96%>bIO~t|c>TAo鬷p,7rry9g/ܫ4|f#K_?g|'닡>pM-;-bG,in3W[b63Z[σ]8ϭ 8` 3VHXZ! eŊ!!4;s6Lbh[ef>C=3#cn72O)PϠ:WZP{QDTCw֯"#q09#X`]LǂXhaIl]QٔSrb>2` 6qm# uca9ЕKyצ>Fa;VƂǞ{P4 ?͟,7;<[FצTfk?l$$jge]QEhS& l+HqB0 x.%~A؍Ye[eR0Ku bL.9^e!KBĈLmF[fip!Ŏ8U }Tն9.3;M֌Bp2Lkɿq 6opنB:̪ 6h.nN ǢdFx欁ʻL">aа-0JMlb ~'-c۾~_~UƤTd 潕X?0Ÿ94qMXmէ.HT_gWo}x8&QPq„`> %pelqoE{kJM{Fu5y,P*,;=h!E.ƹN 윓 SA0k3Hzq9pP9uZ_!Y` 7Ṝ靃8WV nQ7+޻u+NmO={+_ Nꅟos=b6cߐŝ|u"mR ܨ?nPu<n:0EzܡT|?zo@>pOCsŠzO,1w7y*1]*$==npAIwuDzn=?x^s|R˩z, {='[.AL*#`xT=-Q"[ ظԷ}?x?JK)c6tFc/8b=K\/Y=k‘#6>ڏ)i烾;!:ڼ52'ۡ6}C} Gp" 9j֫'bs a1`f磸;Q0'w?TH}| 3qL|lmLٍWo7 (]H'\ yIpt<眫K5^ '_=}ͫ˒ŐϪ2⯟#zk`Q2ær|Rw`e=&gj k=Y!o( ?x_4Ϙ9 ]]=:7Ar23_0-$wcq&ib5cwwXY#BN ]ڝTb*6\Gt0TrN#R"=^1!AF̍〙&(sN6^ 2sҪ~ʵAǘ5[ 3ߨYR]CslKmj-;փx WmS%؛%]u'W"_SΚY̎]<+=<]{^K]ƍqc`8k3" 8ĸһO1fllwj_oo,%<o]Zj]HP$0?3vCIw QIR*2sӣ@Bxvnv8:3f'ڌp:kL_Ɣ@F`kd ;\,D=!9+sǪ$i-\7?DߎR:n'wk#$l,`;:3xWЏ𶨧58'UKI/ IDATpsI)Zkb: ʉ}Ʒ"CXŎt'!7ƚmF'e =v]{,)2Eyg.o؟rl4 b gd1 5ܐa;qn{tlr`)FM\clWİ_Ƥ?؏`糩/>[_9~C4b(ܸ:7z^x=O>Oŝ_<"Nz0NF/e%Yn͍*|ta{("f+m:VJ?!ax˽n9o| 󑾉apgnFP6'18 kq <{9I˃@}7RUܜ"(xz|_}(nC/~S,-0&zʼewkdmbkR,+=Wa6׽o=>o}Ї^^_+oX(֍z'㢔/#?erRdR|җx98T nrc܍PgaϹ1uY1 PMq&66W~Zhhh1/y-=ߜ8-^3bnEb=u϶Zj 696,}>8KWc[cY8A#E 4KOm su)"ü8R?/cFbs0X•=?g09OvqC3G>Uw(Rz;qgF1yQc?`ꀝ1NjAjd>L '23-](?n'6> >>gS#_m׮SY v?yŴ& <Ի?W9!]g!fz`йmt {ʚ<\5Wmkb&T=Md))qBCBHdXW[Oߕ<6[m&+'je^H;"ďUƅf(Ō|6L{kb >Y#w g{X_䩏$& ƙ*L ;tֺOZGl|XIlNr27}~f=fGElh8T VjfֻĊ TAC-ͩ꨼[vxT}l l[h5 T 7S%@h $"ajcHss0u$-ĊghnǑOD{ֻwdǶԓ&A/`m9Nb6d_P3yG Wf͚N‹3jluS #:/Nen$F+mɍmޅu 79ɟ 7/+?Ua6\'y#Ͻ}ǭ7b<'8zS9q.>&n]p>O8>>n3 5"9wNj^"ݨȻ؇p"ן1b܈Ek,bb]cN]ī o97Bvw>C7ppdCrʗꛏيk8 ue*VE{˵anӳNdAR@zlFi6P︖!qqcLဝ3Kt; L>Cԯc={8&@g渖s⒘}Q# վ_nbRq7Uzz(B gBq?SOo4v ڊuN3.7t۸y#y@6A㋿W"5^*uw}e2W8ˇ @|޽^?e˻o|7/f.zz3_+Ϝ?s|7??s`yB 06sI"ӆ  !075yr0d̅ &Cd]纆ϸGnV?y5,M@A:9OL m=#§5͵lHg +K]!jOliHG\H 'x#yr0bIܻ67/9r4&MO y `Wmdd؆3^ujmnhݸv fj 9Q3C\^w4nnt ~6B|5c1Woa/BYg'v]-d31*)n̯͇yǓy9P&]g&s/ J=p-פdjgI6]g@tLw '!1#LoRƗdd:[XĹ:i LJ/:;:[pmuq\] wN`t;ckEFKs x~1^ 5]s<&1keK K[Mz8u݆lw6"0<#1Ƿg [{M'-<ȭ@7n|!nP&<|~\F9熘lWs1/ȗݤC0dxz1B#p]qӳf>#0Iƻ}WU&;Ywo~ˏwu!6vGT+ỵ//l=ʱZz{.r# D?7("qsxQN}W>ͷr|Ƨ}{l.ȉ߰sa6^yYNUVˤ;6_rz6[E`9&HVV˰u `&77a` yn/}fݐsY}sٟᦛ1|7P72<|Qznmo2ps<zz=&/T^`͵F^3j ͳfjg])zЛPccbqڞ#t2"H ntwlŶ3ԆCg}fͮyHO\sX>-C?CNj_os?]2+΃$Y-g'=8m2~?8iCÊ~D W/%/~~ ax? GAyG5t8YID_čX,'BcỉXU^jo4'0;H1 y~׏aHd5f}ԥ6_'a0Y~-#Xr]fyZK59cM1MwNV>FrS 3Xm*cEN5~RW1'=ٍn֭u!FH#B*ؼk8"nư[% 7u/c -#ޞake?dsHM`xpsZ$p39iu}]:(J`jb]Ǟey5t6 z Y,>tJ0m~[u0Nc03ζ~\;6`oȁbxHAbwh1pYpTw"7[ҷ +GOeV3/{Ql51Dqڏ3]>u4͹iNσaD,db+Ej5;@2vG;Mf xÏ Nv/˰u [F2n#L"9a@3EH1Gno%-Z1/G"1_Ɔ8NMz붪:s_^Ec4J}XV%ƲOc$AT@Q؀҉h4D}JKQCl{ _-xǘcuw}k9s99?9\ó ߬q qΙ8 ZaPxo<@gU;MYM1 t_ϖkq'=9Zzyu&`=&R8j6zq5ƝfgDmh /O^(KOaϙ;>kp bXs1NyB mƞ2?@9G^H Y_VvIuje_4a%gwG=T%>8C.kp];w]+lrLToԅO>~{ ,pM|.X<.=U0V5_.|r ,w&t5}+gk}x}^/D7 nL3&ǽo''4C \#p;H~?s<\p *Ӭ9h`1ȅ|w9'vO7 7u4ФCIPw|/Y;0_׾V7_k^؄㝚 xż7ﴣhPRQȂ*EAb<ԅ}055 7r( w3:M7uP"۱ɇ;d7.>wYTϗC ]5ksϜ#uͿ3AT5cU: Ӟ|<>&{gN}K{_] [)q7emcF0i6qu,kD#mr:1z6stob}u1/9jK?5Hz|f=9,-.Ŗ1HC6(H}hW^p<r<O;y פs2FM>ǽ}|?\/w|?w煊ox{ͣo.ʿhC~!w KG6 M}a kAò,Jf7`Z}Ĭ& Kz3.5<mOnߟ 7$nqo&ZouGLŃ_2qF<1jSw1dE}Æd8tc0éeIw[@.]auӮ˦y^˴* /^N<{[˙p0 BD հm@dϚEWOFZ,Dh$\rlĵd΢;- *MX9â#0x]`{Ӆkt8Cҡ=D:'{~%k"m.ƬqYԄXUm5oy1- 4tXZmu5״D SK2{'RKͲ%K::_5lew1!'`2{.CPm@yCd1#M91HQ!”u$m86 H'zuTxʘ9P3\.hM\ųK/&y&[k,6c7q(UB?qWx8ֺ:<\r檞vXqxh3Cm/</@/MR%6ɝ.r_w)l#vpx{.< \.DP ~(۾Uɔ&^O=gmwqxFwdt߸!~`Co Z9<~ow G@"lu7$r!#y&G:8gױShS.t}3xֳG{>ƻxGW}&s02\X}AZTx̗._x0E2xL %x ڣ|ޫw*/^q/{EV=ۤ$4cƔPr7t7_ێ_z/9'~M8[4>B㋡E=ޭw>]s`lw/uEtK^\|S@PXry܉'?~.ɺ& 8DG쟿ǧ}gO{ӎyw|B\qE Syϻ|.!3UDw@w߷=o9o;ČC>5ߦoL9ݗ~.f.3-yL/BncogLji"j^%,&^DzE'zϵ5$Z3RekçSrs'LKQL'9:ysEr섭ns_lMvE衲$6F[X@jMԖZK@hۘ5Yu(`'GvwZ'w4݇ԕ8dkZjйs/!K~l8x c#޻&B[g6dψE;ol_y=SIǍEyf@wɴZt5$֟'UvՂ>7|M@C3ru^=yXQ_4rֱzԅw>k.wϗ)?!ׅ0+O$y<^oL\YZVtq:7 ,ۿOt?板w*η[t}>|AfrOyd:2F Ԅ0sg9兽x,a_6 2w/ {<髞_.@x8{] qg>쳎:'y7]{>)y2~ ކ9L=Zl5P^y1[kn.C'<1^0n6Ω3N\"vqoLk'GܓWS#`3kAWv!$"ƘM|06u@?tA]U=H1<^`+Boq\ {I)Th\LjMu͒,q2$ԅu1x/ϙE0G 84=ucZfxC= [P{j]q/˵4~š@IMs1D\O#cM=dw]$e=% ۊ/6f}8Ψ!hG>suk , g|wSJE/2 z/wcxGbj&_ʖs2?!_;\2Lׁ?1|s~HL]n>7k\PG5 /&xƋ~_:s>ǟz/k.R$w׀לwE 0Y'W˯Ưyaث%u>̆6!:T46xܓY/9>ųF;-,|ү?y{^s6W9TrU}-[Iwl2PڝwK0fYq3n^6>lxxd:0?>??V{&JO ͷ7z3~ro9o8Oёwq8>??H|X ZrVKB-6%rtM܏~Y1{ `Θ?E_W C(|n4ޮo~?Q]U\m>&[C7F)_/Y{?}ӷ/V:2\qy/o9G>ҟK_K-3}bG~8 21ixkb`Z$;8v@حq5qF!4gL5O9W:*ƈĤo[ Y JDǍ 99/ͣs\W%ء9\.nT7k]k`XAL6pu1,q7Ll\li,UN0 Dkdhr8~ F`[~nvUbF-9s.:IjA=XZ{qk=:gV,6%,+eLn>sgLaXv%{ 1sF4{"E1G :g.Z1jd𵢓 9&ɌDž!{ǒcDA]ɣ:uq$;2[WM\xs V3A$o=3qNB%_v骊“Q!zb?R PED/LhY|%,0|`a8fm]XrsKQM6<xr1_D)wct4%U^%3W 3!P5k @GN_jp_U Xܣ&q8uĩ&c1O׽K8> 7~}RF9oo`\kU4ܼ~pomùc2i?&﮳Pa 85-fH8:t1Y(b4?{ ]`"tkǙv:Dp&5X=Hz\WgY:\qjz/8%\|SJA|gv+YFaѭVnq2)QX8랾V4w3yP`|zN513${FHȓg=?[/ɟ𒨋l̳d>˾zg ˟E 7r:vLoe´~|:y6J"w0=O,g9f\d۞jm9m|iB9ߦGGq)n~!~~5'#ߖ \ȟM {Qj?_&m*knB`3ژgns73p>M^!`r~̜w].y{E`R̟ޠ-ח"&%J4;cwȩL @5r3/_kkkyLIyksҶ8 {Wcsgsw~Ƿ|x}65-2g9w[cb~~<~\v]ȝsKNN%!']̮坥l;~.,R?uP^_~?X5:8mfc. |!5^F*0<Էf1QLxSr|w~q.<5yv&}~;>c[->eo)_T͛蝪O׍>b<7.-2$YB5IS l.N00f,%"9y|Oi犪B׸F]GaɿLsqr$aVg=yܧM&$=p sebo#uQZ[a_5?vXY{,2GSD̤Edy`ѡ)ZY@X0S}uՓ+9'x­LYkz1hxӏY 1}b/aKP2qԟ"[o{zx?ecgo׷~o27"@@anp/`+uc:)4AbTb?Ӌ/X%GI"gp]9?S BaH8^][ f쇴c Vm+lC.Q;oE3GW>l4b>.>ponsQ;\ J\X;mj@=ng&ι=&1K@H5̘"Ҟ?vC+-V psp)x5ͩ}WPr*R7ٵyk_]{?zn8~w}assۭK.Z/ݩh({̹Hwv1Xyo㕯|8X#fje1NjV'9utxԯկ~mII]u6ƛ&Qҍ/?}~#{5>_t5sScr?k}6!# Gx^{8EFNU cU[L;Xv/4s܄`mE _ڦV>2 wz%kk^skZt!H!W7cޓBx'{I1&esXz%ݖ_F#YX-)˿-Ő\r$THl#豧c2v 8[Ѣ XkCjqqG@`ǀ%Ĝ4e_6DZ'ȃRg S89Ʊ]S4r8a["K6&5*0,Ǣ|j-Wl:45>} 4klI1t5.=a-}nm$Z99cdm8#~ވXc| ,nq60GhA93BPf \>ʓpv<<%5-a cuy6hyٴ`{d씊I] O:&4.c\8]G%i޼C`=׸Ǜ<:,컱MN]5<|x[:Wja9Lrg|u=^UD@5i6uܚV4e/>9pOK KlΉ <~n8ñ;D$L*80 4xhw/6)ôz_69srr5a3s_f>aA B<Ռ1K8k fbAǪ6f&m8DA.kܸmv}ҚFj8ũ'&C$FEn#߽Ycp]K[_-^z6Y&Jߙ cxyb[0]ﰁ2v/~鋎gOJ9]SN÷c>Ss6zbHbh,5I@;HhaX5j[/^_Dǀ-~:S,'v` ̟*s=h<|%\ @cY a 6|Y <_q7PCzpjsLN&^N;]89|X1)Ҁ/]گĦ挢{YC`M361sQpTN_˜4SI{$fTC.PRkb0XsQrn2Lm|KMds} ?+|=vW~:ϕPsU9PXI~G'=݇ǯp1rK ^#ݺqq%#V6sE+8r&ȱp1x?yr7e»" Ⱦ!@ ,a .)7?g/O>j._\tr4w~Mք}'yt=-;|?xO=cg0u` !'.d(phB\T<8R7b)kZ<,!cjÝ%u])4,]3\15SxL~p`lô i9:cW-s_:Y6aXsRA臭Kjɐ{&r}3c : ՛^e~3tظgY`x- IDAT!QT׵t<&CBcgL/4l$)@@z|i#2[1 |Tm;Zy0#VϜ5]*QS_aT;Z&5 ݓ Y?o?vA밝]#]7izImu=Q Eqsh#W&O0ʰ6gs_O+NUWYZ w6pbM-MMsH6Oڳ&p(x͍ueO*S}qURc98F`v J~058B }$'6+sͳVUjth2Z 7:?nR^* ߕZÅolVuxD0a=u^>>zcu0 c')5˦h ;9'·㼦 Py/b {tV W!&F"%"|Ep[M H#op,aOzMMD1͇ؐaqغQ;TeўA,+#{&^\EIxC^<^H?6oÆyׅ%`̶ Y&=?<S\]5Ob[~ooH]yOޝη~8볭 (K=u6ԙO F$`4~ ޤQ{؃O 0hZfY?_[oӟA2M b T =,ܙjɀͬAkkl^?9q61>Df2?%PYW}Ba.3#;r"5xKˠ2ӵrM+_ģ;]R__@)!LY({d=5@6ڕ9Г5D>kKgc-Sq1:~yx x7sruO:YWD!@vE_w޲[<˅vq>MN~"~0?D?2\L.6PRFXZ"6GYm3e?蝀 ?< {{!>Oc@gd?G[?mOymx'Z]^Y{{\{D YvFx+ٳ桟)by;LK3(gƤ~Ac~V:Ռc ^&JɆ9g !pu CRO1Ča.P. WiPu1ar?X4$(*O!h^@=c%H6G[;zg^d࿀id\桵5 Buʘ`f\ԁpڕMhd[='9tMm7(5Vu i"ZI4#!{@5^g4ْ9kN\&Bߓp)Ck!uh5zs+Y]+a Nx:dv(s'~'FI8 bņZD0tl77Ә,^8ڞ339TM496 cjyaH77@ke2vc3cw @[fͻe-uL:AtP6/P,ps=3ϻ<]tG4^B: l\;^lsk 36`^_onWs|| +rյ vMԋ1|SꣾQ%dNoNGǷ>~2Ȟ\6@_^?7f<1SZ=&qq4k˿ke:tJ`9yx{Iuy'ǶטуK=Xy?ga#kV[i;6]yMCجR[ui;.d0٭qgH=d}z|h)]Nj\kNd<ͻM"2Xge/|?|X?^ܯt4lV-v=kzgi\o.Kh3q+Ri 9:M{I_󡕸g^cٶ3{!A`hLvnA&WYtMWAc >3vſw?!:=6txƎO5~+oZ,p/UGn6+(J?كM3x͢XO|Wk: $(vI82_1&j|c1~ܰ;q i0\anx[&ǾOKC Ӽ[ffLy.۩/XuLE5Ge6(dHs^yIGY2?u;ܹb4W5I1)qu9T@y8n/#z3N4iQ N709{rߨ7}~'fۗϸ8\uv\N{Lʣ5RˆaIWK~$]bgķeu`/S\O@ߛdh=fJ嘒wRç@ZGOFw m>u?cx1$a<@s5[X/!dܶ{Sd5k$YcXl_Ajm*{~RC"[k`{Y=\MܜlUqV4yXU3i]:M=>]6CpU>#h^]Jz|㗓X}7vzrsO>~Ԝp\&t__pOFm;GP2+fh:pYDwLufX&j~,\u ٖc{`6ȋ(ܙ縪,ؗNӎيE*uRmX%M-/REFg(?iN*ef"Zu٤r: 6(N K̹L9[7.nTd;~+/,h5ڍK{W|/a;8Ox@Vc9ޙXc8rO 0Mutcjn|ƉuMDfXaj뢮iubډUCO:cl/56娟mrt\ 1:Ac,a{5fpPe^~7LT"Alm7jlڮK`yF0+Ћ/ku1^3?볎?ް*jtYkie )Y8cς;:~~Ooǀ::l:bk'gҖ`ԃ^Z^c26WR5׍}9gά&6F'ZhYG.t6ΞVXӬNh<>*.^{TLR 9]\ȱ5E5;VpjM߁`p8ݍԸ6_mLxu?N:Tcxi 3ޱjťhfYsQⱆއs6r'?6AЉ5Fe[ld%I6|̦)kq=^<'8nZl*g8@cks1>0e N<'xs ˬU>[t^>a[g<2/a@Q\2ȶlvM? X~E9^i )lG%(1K2Π|3/*E:KΆcQsl5/Am7ksL[kEzs r& ˼mkԄ |&fv&gO.6'rk| d^ɩӭy5 6'kMX7M.q́|:,^" m.''ZۄV-{[™^ K:PS J[f#vpR- ;0Gpkb N\>896Hoy&ch=}ҌM݆X$ eZ-=K{,xi+h4j2V]4p#+`,EcdQU?ga\#}9H" GBKkRG$+ã6I,A f1U f=<ɛuE3Yw)n˻jJ=` dl[9̋cca$oZ<^eiK6e!Zj{׻>zʖ/2񟰊5bI9>^n.ߓD_L+] ax1/|U;&:ڨr.rFp4rzdY5jbgQD,췜 V3A5?6mycQ/ۥ_Xo3ô3ډv`01hǕ:bNktd|wjuEN `a7nr=&Mm-bH0hw3*>gQMJ?9Wmm/;}C/86~x5'i؏c0 1@rc1,OLpX ;nܚ˟owoaT.%rNk󹞷ρq< m ;_l/z/7>3?٭7_@r+_;$ pL*2=G]-)4h}1s@MSטfj[_e1jf82é<3 y*Ǫu4ڬ >. C^c&7hĘ޺狀@fm =4xYä[k9] j̴{B} _8w%i/^budaQQ^P34/IpRSix7cŵ2yfAD~!#O!XxlH h|6Ǭk9i3ԟй2FfvNwh(zP;Zc.lccvJbXNUq.5%~lz^hF*u3 GQ|!ũ/Ȍ"kFm-E_ŮM!q1f.V͟D}QӋH3K?mi4Mlpg!Ѹ ym#<;t5bkVƘ(<澉XR0sEBp̓?k"\Vl@vc%˿ GtAW&z}^ПEJRg,A?Ds*q] '?خl{p.]9k~BՠBS`1]~kN?crмNƞn6pc),5 9kO({]sXa/)};7w0daz眰9_F>߆mEKc2s2mOr$''ƺjىچ9Q Nfh7LI⎅s{ѣag85csI wiZ/&<~ǎoc\^ JGyg|xqӍwsܪ@^"LsP1g)Ώ ׾ O|b4 jw`a;^ N i[.}7f^:!={ GH<̀)UC\0] "~b t}/&04Wl^j2V\W{}9Qj(}"W} c5k.% rE>c?j|ތ/[' BֲKUjp΋4އ]b^dͱyVVbY*7"{;둑dmҺ3x<wa-+ht9㉵ȏFC$W%no6'c}\?;/<^/j&|^ }ڲ>kuU0e'-4;&I,֑irdsslI/y6ۖ'z/x\ⲍJkAza:t'ʱO?6k~'QCɝ- ̫ص69X`i?%)51\G1g}kz}zx[Oo8=Ue & (t Fc v9pXK=qB8cJO˺u_> $p0_C Z;k [sӯ6b(`-nRy.+qoöKB0]ǩEj K2N9ܶPigM Nwm#GZ}qS/TJ I+Z4և=q) L.Dm+ϣ<:dWjҊw\8&WI#' Z"ɠ=zy> qGsuS mο2仯6KM|ؘ;jkq׌6B|X5 (.l9v\P@V45GDhB!m[Op%u)VשZpIj 2O`#4۰2m/WP9fj rw:9E $^'y7s@uM֋`G' g.= #9r%7g^S(`'7ߊu颟}Dx=@!o7t|G|5xʴ#b=x>}'euPyۭǗ|#7=0EpW=;u{/\f@ ޘ?/6%#|\pii+  KtCqo'zbH}5^qNI]m8/;*m`"6-]ԅ9T0Nݸ+hbWb~xP\>C5a8"*~x_kA cwSgr :Xjc>i6;:xf q?8 Ouy#|Dx1pp\u̴^*zb!K3w7crK0`Hb֝b/Kbj"ӞˏyEoh!On䢝lF/4Ybq2e,瓼+A헽{=Ę=:k{4 [-+jagݔ$ҙ4SYнLp}N:*V'V㰋`4OiSo<̙Jg=ͦ i06@Os 5(^b{*j3=ve^jUr:҇TX\1Wx`@rm\'FB}1{kS:mM_̔6|?%OeXA=~?~id r[_<3,O}xbv3/nxnS+{? sQaszuςҠЏQx Y|gOO]J5=qs;Xa :Y~,&}'5 [ҹ&uξ`/2>*k~`n"zs^MxG}ї ?;LӍ#v /x:rяj!0@w ZxT.%R9JJ:Y0*A~hWY7 r; yLq0-n I|fOvEhBX+嗐 -\FcoMĚ5ɷ|;\=L<g'OuɌswm*X/5./u$T K GwIW _ڄ'w_^i3_esk0Kl53b/hq $c$"]Ka=ƍcH3]P" <2gGU|g7\VUwz0Z5oF[N4h(Ws,2B 滆ZSOBĴZ\M92< vMq^-q&S1s0؆,핝;/a knK.`ȓca'[Ͷmƿton!CDቑqpїC7GT2b[ %rfl39 µAV$敯][4 ݉8gۦ{'5qc:`OA?-/9*:,@q6˫kMc %Mư5fc!^:FZ7^67kbe?:&;X5{ak.@Z#Nb8p\M3 !n Xh#:1ZF/fk5&.o`Y%fLa15iķNGĚwM 8QnQ$n*,D|7+ٖ7^1K3ŗ!x9Pƅ_7+)8x3?W7Nb԰bșp[G?Jfq;Ϋ{t~?֟_yΕ&;d~*}D%4e׻?S7+Ol3`?(aM46cj3k8Z#e5?8y-\$,?W6`m&^+c^o@:(Ay3.<8yupΜ` w.J|Θ/9>??kQ7wo8-mQ ?&%zQC΁|s09Zox\7+v* bOAm-g:C׀I,c>ɗ`I/o% ?W)s7>=n^ M99b${;M~1/ҔWjy/6q9~ꋍ]foM\ِڶ|zڵ#}of;9sI6[0L'xiIPzk lGrk˚7!tefX.] !\f$Lg^sgpJ:lZ¥NyBfќ3WSrǒ业o¿gC|HfVA̾溡!>׹p'm'b׻w-EI~|Xr+zO4^T֬ﲞB]+Prcz89mʳBMk$Ǯ5=Όc4ӟç,`yZȉn{ƶ1fdLCx_qmq*~s(ZhG{(l%@'iE:$qp†rq;yjIl1=z.*t gO,l^D ؚ\ΫKhmo=-@6pzv9Ư@EѳNr$A8s=sشՍJh*E>&6)@J?Els{06X[FɁmԍ=r~::l內Fq[۵W7"F._Ш'>YpkQ @el-2FxB Z4J tFh;:g1a1""4a`߶4"/] Z* ޑW&o÷n\zmǮ5e[oͱ#X J۔I39Vʅ[W}'_ԧ؇nɥkbr5tMTݏۥM 9:z 7;WL>~jL!Wox]_ˤ$Pz i~mk7ݔXz;\'*~Q&#hV˹'Au0ÿS`u>ǬE*%we,bLMфn$Ci}Iξ| ߹EJntMw|waxtӍ9#ұq6p?q|7+NEKcY03BƮŌh%P ܜW=Rwڀqƻ{&90niLkl7{]7b "!5BO:b&piAcD;Z+ lYaX,hGiysBx6%/8֌k L1|CjFƔ XP.hD_s3 ;F s-Gqs1X:"_2Z_2(meGCjb{b R\~*,| -bo6%DԊͿɁk3oӏˆ|O/?s{?hQN'l$gN+/8%G=fek >Éi=\ܝ8)n>$!ufYy1 bclаo0UC[+ě9P$9h6~yu܆t&t<.)Ur8!IRį4k|~V7_/?>>Kq!6B;SMi Hȅ" 5хz8lΚ-RE'l4&m-6EIj>C =u) ݉`d?F@s1 u)ls|Z[n>n;H.c<DP+'TNo,Qqޥ~Zp %'~dI&vCy=oMYv1ݠ2Ǎ,00s{;_J-5Lm:\=ko9ht^C?/<^ګ@K<~&| CLH Y -İi ÚK,,aH-2ՠ(t4!)OL4sbWn7dt0 VC=&AbhAn~Ÿ|h^\ʥfZtN㵎 ۄUS6ll#rq*8{'є+}0\pNIͰkcŏ賾-cn:ZOf]bc(LNwɝTjj#1XFAO}vta v:g]C,0x!w7nbdYȭu"2+)c":a[ 3ךŞ|LNG+V{ DƊC5l's0kkZ /t02H]cc"!tPKe3$jK24<'ZkQH>H' a<#~WBMyI/RI,64&In-எju,r HPF.}bM/Q1]'.a JJj5t m_X%Oo:g>zdhH $Uw'~Ÿ?^%\\TW_qם_O:`] _>^WB g3d|MucMk 3Qti|Qʄ\jx"D",N0"t cR6c1/_al|K5Kՙ]'5}95k[^d2_9/2&ɸ2yݩ4S7< ɘ]sD`pރTJ=^*8NkAv &]/"v~Yͼr n|nܭ]1{-وm9t=\Rqك/cG> a?{RV9 9r\lh㑏|/Vg oTg •d=(P8@|?%$<@>x.xTDCJx 6۵m_Aq>>?xK~vvɩ{8h覑H~Cp$!U- BzBL *{tt`{D+`^Q>a," 띘jű'WR7OPp.;ٚeł`Yun׾-<4?bd1Zct7%7I ß=[^1L?L~-LHvCuASţ+꒔Fx(HŢ sP NbM1k:zBzFh)q%akj4p 3 ƒL \0-q kǝc,Ń:X[C-l~Mɱ{r7p''Yˆ񙃕Ȭ& v?@F4bo& ~š̓t䭑 W'A]m )k;#Z.2h.ncߡe9{p$/6yX~rW][Swx/eڭ|/9G8JN};ycjjѫ30&Ϳ& /FR/lbe^я陿/x*CJ'[Գ`ךgÊ),o<{[dd24R}PAcqq8ǹ[Hik{y;C#|. :H|FġU~ sa.<)x}l[>՜ܩo)zӸ—[,-B~ 瀿QW#C"9wWc}}odB`5QD7ɟ*+y9iM/+G y Yׄ`_C|Q_ݣ499^I.~;kS<`0:p>?>ozq-;rapD`\,n'H<n|ë5f ;I`~ n$-@6qYۅ 抏n e< tC={"HV->u.~q'j?"?{*,nPFYԬks!mqVér/>5aq,O= Ee96!=vE?5i3yOD[Zu8y$jM -ohlSNNE#l,_ym U6G#~4L1ga?)g9R}9S,kیFZGSwb]Őֺ-<" hRX,I7ZrPv[jT,H!3` ^C ef(56gCa8mn0q'ņ2r8Ѳ%l%tiw6&Þ䤛nBj~eYxu`7FCьW}AjkZa_]ukX2]yb08 [>Ee+N6+$8Cژ;O*a.p"ZV3 ݦDK~zoKF g9,v,fWxD4SIߵ5IsI =~Bcg.ǘz\x_al \l{=.EBH>H.l&+~eǫ^x}Wα8yMx8>?g;EwxgmZY0_ꕯ:~W~Y׹rmBC*5K>6ᬡ-cJnYܗE툜؇{\ l术[c\$0:l^Bk燹;}s@cJHmXBllE[5uKf",ևvk|aǡ$g%lzӋ7?pR3`{9?$De{5@&SS3)ӻ9+=LMW3O]I1]nM ,68`_,L<Igݘѭo@G;ˁAC'O] 6j yPe{|K`Y*NBþ`F}5{йlxMv=ghǿӾ˿xߴcw%*-!V ίgoyd'OtS7?}|Kޅ.ֶbIsw8xՎ&$pCشDeך6>"`ϱ!7L eʶgqltüx~4؋vtlc y}|\IzٚIv |m2 h|c6-vش:> fϠ|?=cG)'6.Jn\,p%KO^5dpۥԱ gMw9Q/3n'Ʋ"`=6Bq<ѕ`D7_bn/wq{hGɦFZMr`nwQXe8אxĴxjm-C|Əsxc3D=>0n#OS7!>[.{ 1mOblRs8M>m[)۟>񸨁E9Wl2&|89DX~m 5ГV?#m3For,7 2(aNj  ]|!idq]8x1ŤYϢo;lvϰ b0j\4. metZ=/t}WKo/Ąt7WAt꨿e} sMho|6y/Hoݼt 9tMho/я L3z[nײcOe?3 0RSWx_x?ob:1l.ؼ~YOo~e.s>#wkG|}|!̹sD\dGn|B?$h-\nc`LjuQ3Bruū`]~)g ׅ\62`G 6pmV>ߘͩ{b#-Rgȉ|f:x$kWuӸ1Ӽ ۇs='+m ~$sK0 QD~]&ܐujI++3@Fogz6lWCkLKr,|}sK7v&xhX\7dMjtb:Td0(6R9r8zYv4O¨֟"rnvA =șo+|uV9| 8[1iۺy!zn5b37P;T62fh8c9n,LY}ij@-~Y){<վ7wyJ|Or?q0OLͦ`f(nw}׏Oy\0V|[,-:㺞[͙6o cvypw}nwpr`tÝs>pރc+?\]c"(3%.Co&YX=u-#y߭Cpg07kZcD?@9 ]</ |e'q,|<' *cq[?*f!uCkZuDk,^P;ۈ-/ę뉠yrm4 =G}AQV ?&*i jYsf+Bxxļ~9M ًm`X5 ֳۤcH?nj=?ksIOnroGر|Z*Ep,=cZ/J26籷^\[U+Vu eOu/m`t!?|_zx3x%٭A:u{[grb꽺;ǟ/"1.a40FwkٟwMo+^яy797H7p[j,!wE'~'dLzɾ1&Xq%f7=c[lqjݲ^/ %Ork6"u`욺8q] ]0aqZXv։L+4Ɯy7 i ÏSB;c6|W6hW3"$!klwz'YLF &ᔸsW3[_~.&k.I5_~rn;nc9^ME4k F`KؚHn؅]Ω vg+Ny4t "Kr_E4f93$w5!-_GQ@sӕ#Ϙ^j-5>)Wų>t\AK,)цc%YT_y\O ,/Ҽ'<([|lB."&WtZz*~b< KS6xf(:\XSX^刋) ð>p4|鼐+}EF#A,,[G "k|>?>Ek֧d/| 'Nh\?aMS EZed&0 _ x||Z( 2N1W/?xwt lί{=sYnupdT~tX^?/ H%><`z%.:Լ|˦i{!l00&Dk &䃒/8_C|Bc"CX=M6Լ169#op{z|SwGSlH .IE9B-r]Hs54s~\?] ޶AG @3o"Yq&46p-UjsC21BK]_r0  ~n˘}EZ}FbzQzK9K7qq7˯w~[.VeY[;_<yɀy;g_..cjǞ0(ؠ+=v|Kx.IhF#">]/51 w"cQ35{낗xcj,: 6 ߯ x_x/<xӾx ?xk[+`oIPqG}&W=,Lx[.?cžY/΋Sڸ4fٸ%K}A ^z4Q^2ą[`#] 18$ m\| Vxj/tMpMa5Bc+0n,<#_@+fcoAS]Nsis;uP/k261)l^3 biV:`tL屔ǣ>WIP'5}dN2")  հB'\e4nȆ-'i)74ޞ+8v=a;g 5ኣ9-1Lp:Xs ^j'P4T׍Ńk`IXcLPx_^mNJE5/jYk:f^ ˸]pM`؀4k5!qcj]^%41`Zge ͱoE$ۊwb}SxsxxM|< 9:/},}f՟?GS„ 8 ]~#칈u\9M>/ܴ7(g/KwHRǻWpw #'O??3bZ/@&7ր}s)P7| g8YK\d_=O|/L`x~;87o-ʋwS{+z lɋg@ʻB֙ϯc;n Z:0j+`ī\yȿ<~ojG$Lή_9"*ƞgYrzzگO쒿jZ8ַ7wI 0[s?_-{.'Wַ<8(_vB IDAT [0׾.|Y3w}ʔugƖ>ץ&r`nL|?9?S>x|P{uėxߡ/Ǘ|ɗZ9}s5 /~sG9ȀgF>|#xW}8ŹWH 4{]+<ƹ yIIfo)ZkNM]c^Dȣx]wG6 ԠvcCZ6$=n{P&rqmfRLrΘz\Wh t`mpz  *.L#Q9`h-6n'[!C2U?1sVu9; 4~k6pdGZ8ą1s> \[N8f#HC ~dX{I_g50Wq#͍L_9؃&y`Iؙ! pV/r m5 ܚ ~1q+#e@'añ&Eъ E\9]g Jbc.S`En+Ap|3޸ l[o#@=Ujk] 0t(( A>bSXOrMhkrc|2N4y&?pGoNL CcRۛ7uQvs#9FbZ!=r.ĦIN&ʔ3뎬#aYl,۹E4L6[۩p}u7E>+AL˃Y8~~.&?'ɵ$Jg^hp#5\g(J >R>W[9=Y"9Y-)M( t4(8KGl1n~'O AX^R7:dewWY/kaʁqjH¸y,ecK˅Da71CrK?ٞ5|B)M:N&$9?7/XZL9ћ:LEDã~HyByM:R{̿?-[\v<pg"Ï;o8FY q*k_9^r!k0w" }Efo^{|7WS{^<Ҋuam(5~>x#s{ '+ZWI˨ȟ%jnrn\aN(>O~G?#?([#{,˹ KS~a_/&%.{~UǗ}ٓdĜh!! G{>Ё_)yTrc;T=rO J-_WNS;Px=w;O{/ 4Rc9=DUO2U-l.;W݂b#@|o }ȗ^pt/]1ov]{V\>' ?RO͵}[WGL9~}dz~:׊3.)EΣ|wx.~oYq494~n=>xE{wCsy65qs\׎!vE~Uc& ev &-9BѰ&@G&^Jb*4dLy:vLgn嘋@y~nkfr \Ћ뇶)\vaÞZf:+z.j l:lOcGE^ 4u`mҗ/c◛*kb,Ůo ߲')+xdMwh$Y^;JcH~98/ (֏qȽD' =i9Óvuaspqx Pq7\6>|sFx|~ WDαg"kX'[a0x> {=VjUݯ=,>:2kaD~*ϋ>yj)ܟ A"3\ Z{dxr|nR?k$X0R&pi)L3F ('01H_f%1#V|ƒ`Vqa$$cDpK|0/'78b">YT9Nf '3B@DC|GU3 ʯ͈g $ >jSA@lW1À XvgP0O/GyO?y ?9F~A,}Y+{V^cI^FJngf6N5|\|mp\S#/Cf}:H F:G7g]jM\?9.\ҏsUDj>W|r0Ӗh]ηQ6ܼn~2mYs}kѸym[H!69Myk#k=]v(O|zn avq|)x"|PLn9g]/s[ޛ7{H~- ּ.ٌ_ =O+kn<""uHuvӞ/9)aáDYf7?xg*>pf:O}nօIY ܵctCK OFi -!wC}C@{7CW`CW0|.tf;|!`$?y{ρv<^<~`#4mjlsvvdHOa4x"?m01mO=^ʿt˗X8XGȻ[{1C>dEj|9E2ezB.g%fo鯚Y4|z'?Z~ <׭9>Ov;N֑)i׶rݍP27Ό~갣\ ƕIFsФiTnQ{k4_/NXه=`<uCǂ;.o;^鋍$s{Xl7[Ns<]>|u#og>8w|Y¦~LE<.>:#('OcyȞ?c斣#G-^ 4tqsr'+ta%\Qq0z6u!LSlbr5i^94|&\pF$`4g|b#)}驩ZȂ\ Z1OcbrtO@"ڃҟK+,.yXj+0uܲR1]$>$9~ cB8 38i jMEZ-kr lqTNw96Ϻ'__X LKGO=8=|͒F*Od?-v˃} [Ofd:h~Ejk[͍+sc9V>`F:I~B+D|TCkQvXܒ VUoX"`݁gEcJ<ЭlӨNؑ;lx AAPw[ʡ HÑiNBXz_T|vvvt ̋2Zd;Op=pm|~JXsGD=Ș{ OlI<ѣm1y^C[O*'@wjpB $`ɼGkHs Qn^)+H1]3g^_|jG rBǰ!禞K~F!{OZo;+ҽyڦxڝ1b{BD7=,䄋٩?:D-@N;8!0jc?'52y;7.䚜g/ꬕN[pf^Z9Ns[^t/r=vuމu!7Ȯ C=oe=fil o,e􎦷K8}D|x&q۞g9 VyjyKnWlAv^Q{<[U'1ۏ wPbHre?cǛM0X`u:}r}c(:/"oyێEǝw>..}x7=~|_^1b8v?=6:9kwF7xE^c&ræ}e>}P~ h,rwx)709^r6 R|L֦|iģ5̊ZlC|4v Au{mYp-<#tL{'`gX'!zS OrLM|*_hZ9:ؙ/8g]b\^G)mX+ojZ^ ,k m"M ;95:Z̚ūy)_=fN٪O2N%lp!='Cӣ[;ķ989<"<o_`9J>R?=75!n4rN}Zjj(`\H25?1iص| /1H_vs{g e7~X\ߵx` Y~cgeݚC0 bp}p"Lx1|lr8>7綗}YOcO?zVa{?gn,ލ<㹗0 Cxcy8Fn~yw-c5<9?is>r \<6.y*D Ǝ^cSnd^ܭ?,KYpq/~7; .p#o_=~ZyqY HkwNFpyzbd26cms#!-O@D# Qdj6sů;>_;z^u5>ӷ,~\7G`/ċY6կ ܼ jp#֘ 5vmQL6@5/6Lpn>Gs=N]upк7C63bZ_#A6(/7T+[:.h<羏R>^!].ܤ<䙮uc'ٹz{κe\I iStj ֲ%Wox}ߘ2S:o~G{~#Η~uvߜoBԐM~|oɅ;ugo1|o ?7z{str1;^ <yWxrl|i5Wn3M I;~As"p6ȩљs_4Gmk1|v/kl~/~?:ȟ&~Ke,{mfVpݹϦal 9(z "6qlpܰ=}BN hycaxl`l/#uOD_Đ4,#"cXXuƇ6kEM :.%qCfnV\un%GǰDK ̱Kʩ]Y=g,܊[OŨeǰvR;ձE vt#Cx\4`yC)-zAs\zb9DcJ38sF.ͨ Sb>Ou+9A*{l^?d2Dėhb_YKcFz.o6X,Ո\F<:x>i6E̅r9\8w x!xz2}_ }mN Tn꛻s!~GߙZ'K5y2R{>ō<4sgyXBM職ަ#_n+gI?_`JF]4-`d t62mo{|q޵ʿq\(;/<^7HΜ/y,D4FrA?ʳ.qrh-nŰ1rV/s7ܨ.4`tG}-QD٘5zx^?CpIG7+ H}ծc07օo<;/0{E{";;fR^wz ULW;eN-Ugٶ ȥ_vswj"E~1w}̟3w|۷E41әs?|__3K޹ڀa"6zHcnӻ~Q_pO.U2:v4T 4o,΅zw? O;G+/8a6Hם5MjC="7ٳ~mԀr >N{^D3P[b2#%A2!4<D ּ%9$a׏C?dm3XY+Ĭ}+nqm6 a92\7szێ5,b<ߡZP{S-}u`81NuЦT IDATh8ѥ<;;^b5F7RC@ؠ5%PbTs{H؎"3׍ش#1[;G/X1#/_ȌQؔsD `7S+X#A[b1S q.Ķ~pз>F =,chG9Y,<u1`цZKgݶxeXrQжxEd<<< j|-3|s)H“HNDq+!L;q$mXן ^VP9Y8*uN;ɓ4{}s}}0uRۑHezSC`͘nF#qĨk=\pR¯OMj̮yθ g}M!C2SXV9\*ȉP.u \'5R rrZ%+}u/bF|s"`sHC+$FIdU$di\?Ę9szsH-|;70y1nȱ&3Y&Ɖ!~rXk'gg\{#ϋ~N!Ld 0%W!mD(-玟;Sο_?,WP^Бz~pE/X]g P}y3\3y(*ɒO(tx\1Qh0+czwxӛߤߧ!_0/\ȍw]poN7>xx~7a{+,q\N]ֿo_7׿pA/uz-ΜwiǟweƞÍx>gǿ8nU]7c3ǭjnN9ٳq1 |SGpԼen=rr­8|x\9GeqR; -0%Ɖu8ءVu-8YN\fD_+u;G.gP0^%X9O3z3^5q_ŗ"w|hUbjs,.&џO¥P:$97ϲd`$Ic`C|׊Pl1_21?w5mcZk!w7L$'‰01D!!~=6w~ASo ҹ88V-q |1*xl]\kř"+o eͯWڂěgCq| 1ש2pl/A7dr޶蘞3q紁LX iƧ5TZ dytq1][rhk_"Yk [6.WuzhZ.Cf9ctA>QͺU,䆻\vnא`L׮NdƮ7W%\5F}n{ I&4?c+󱵜u]j& IQ `S;sE_ }\ vqd3NI"hc$1IR{p^kl2$ؑirwl6Q 2Bc1}#NpglH67Ύ314s=ѣi^1Oo'e~1`h%#^sm.dL$c*~3WCq:؞Hg. xyj膬98h~'gb'c.%yrvU>psI ?ڪG]w-h3 W_0ͼ9Ї,}߼oEt c|mQ-|n`P0pd/xƜXk\glw)6ß!8l-Cg?!} spV5ptybʃ61X ,(t ѯtk~ύpVַ8ꘋD:I#88qsu|Aj/){ O f݇c9l/ɵ(3l7:*ζvbrtjŠ:s]lS;ͯqbq^qFSU۷T؂w_I7fqxVÑw}Q_Z \mWI^Lc`۸#8&fl#и§Xͯ AgL bGM\6x nmfCxÉ'ټX Zsd.WTKЍcxkp)/bxtfo>"IS/[y45cy2q6~y38sU%yHOӸmo9^/2Y v#j0<-40ϫ_Kǿ|=&Acݑa$bt1g+89 kklU{̉Te%&/hٯ8(pFo zMגg传viwwݨ;O}Sms,:ǞA+ @Vu7p< Ó|;}φWOYrVj:t} ꪬ.pYMXv8`A16>=-Q!F;?|b?TW=q}rw_/;q_ro#-Mߓ_!;/}Mzlϩo {Ox2ܸ-7>?O+z<*M\c&~;A;rͫ7gַju{.Pχ<HϹkDO[fiL꫟||ˋ_z󝷁p{?l-|ُ _H8#нyr\Kt-?VL^xj<(\S~8vsF=P! ܟ(ơ4nlC{ǗvtL\Zr=CWZ xIB6/D c6q4q1yj;7l쯞++A aq ǒ֊tz ܷFO?ǀy|PO"W sxjbq95[/_ƙAۊ4`=JHw c[!ďMwxѶpx Gے[fi>9[͓\Tf?ƥnKyFtӹQ+[aQ5[k(c[6oW9/G)BY^ \y^8bz{nMp/04d pc-bpB7ɵZ&Ҍ51<`fIlűYxQ88{O(6>%C @+' Mv5X\sB<ZQ]` Bf wn$^Q/tpPY:Nt𸭼W]H[X,*[1Fve˙u2Vؑ<Ik@{Ϸc-~SؑjPd-ŷvcF%EK`GkQmFZu<-ol4lƘad ''%i*K2`Fd4SY681lE AN j†gquLy:x8ZZJo0哞'eC2wpkǞh\yos_}9OR}pTD׾=~w~|"#!>t>$__y`Gu92 Xh72qxy%〿5OO{|T$xIfiw~w=/?_~u>yʮl+yf8[}O>?&@ _6 fxe~>q=ogLjhc?^-bbW3}1|6Za ZNV|:붵#|yb?d1Q>֣]Ew!boeqeǠ/EÀrkh{uSȚ477{MTn8ٯ:i!q߸5rv%S&|9-bhHmt@Zlzd5NSج;✾U}4d\їWm ZfKN/<SӸ;]wXN|o掏,F䋰YLy1vğVQmV]x1Oh4༼MeQj7k||0#Pg.QZ8$ǹJ8SnB-@znYKp2/dO\,l90hn riPoj9$MȺ3;_l5x[{RZ깱2 7qݭ>FkM"~krfdlw:!Ş6~l/ Nr}[Lߘ2c1H=g7Y~eig8\٧*h~!N|j`bn_B'{7k,?K~)8|W<`jԅ6+m5?IH 2G2ID׺ [pz@X9kn3jڻc[!J63s`u9X w _ї|*᪻5Wߞ?>ޟ;-rP>1Iww~j#sqf6̷BmPX`s:l[39~V7J7E>In%Mw /B仜}1sl/fZ+xhIϙ7Z+mP`=5 q=sLdg8/z 2vƋU]ȮʖZOݿߟ>/[Է,.uޚÃk%Ě _R>\}椆0:-ż guay-r9x4?XA)#7 <5^/x 6[ϯ|!B`[f;sj0~n y[*G)_gu, QoD)8Hb?|1n>8<ɣ B0^ckw<;Oƴc`}w[։V3q`O;9Dwb jm`Wc- "g,k^%<{NИC2^+,8 CX c=uZpmɯgVlpbt^{ep:X^Z 00./`1lF^ nnˑޚ6]%_N{l* T2EcK95zj#z 9j '=.g׌^VTl357vFcmib*j&׍!瓠GNq'EVG9ĕu"FoMōF">DpDGKg=FL÷?G#}皁i ܾ0?Ñ'|?(q%s[?Oޗ>~~0.9G8y<#$垉6Olkr0WqL{3=z%kqr/TNsSS?ǎgx IDATff,`p{g+cTˤ9u7vb f;ox\bu`zuķЗ!_'Lƒ}wWߙ#~5m=A.Iϯ1+4bqz_7g﷾j>%gǧ~<_¯5_? ǷP~:'8=n[/r{{k- 1^uVU2cd| >xOt_o<_i`0LS-2SEQ%Ln{xfk"ݢWϯ]~w'm-zZn玉ͱJncW_K~o|Ư?3)|[GiR5;^m9ޓO@O[ߔ`'OGa[?}cj :fV~`~9~?~1iM>< ?נs@[9̷__G>cV[iLOQQJ|zCsE-W]@A# ;*sח +؈dʫoӁ?ʍ;ڛj6%Tf/[_z[ 6/ƴ}jzn$8ny7_ȩ̈́yg/m  n[(8,ڸNl Aa4^(u[1 +H -:bPt~b?1uNM\cOjve|4"߿rZ q`hFHlVb(o<ʆ7c'u/%cE:ȱn(6$b*zzn2x8ݛ(X7/w it{Ĩ3@Fruzsl8JZT# vtrvK6ϦO,E1ZOPP'0j!&!3>P׃$> _O[wiǮ'|yhz'ߥ S5(?ox}?bh=9W^NT;Lmoz| +I!2B~<|CkhFί}Ï?&>*lh+y}CGcZLlHB|'yz__ɱdx8>S_-ۇ%㜲>_>O3$bm]\OjUATv ޟO7}?){X->cK~3>|)|z͜X3zm0-ݯ;l}>1k1пxesp??bo婨DŽM!;em~ʚuK" x1y0Tg[]#a׏+=\Y3Wo•_\?5Wtx̯Otsw\v4E)ODgDs qqJv\>[6 Ax5mo˹5BJ<>>q͹4QgjJ~% wEܡ"Q=eFy5c3Vv@9qM`oˣ5senA'\#}LORdZѯ-Wi=4 >Θfa,5=ܓd.낄}㪜Dn/Ajfxu`͸FdžPsavQD6UQƬ?NvAՇ}F˅2&_W@XkSle׆qroBbMG{\d=qY~]eㆫ|mU얣ƃx+.iA1y?~*6o/c/kxםU9 \ 3Wau Sr^NO/Gy-=خmmqpO=84X+}"?}֝;W!D$;H ܋,C%r/cCoM"']̬o7x/v 6p $|M۱VLkx46'X>B"3&]4 z9ȋ 򥽑pj5xcz-v;k='r"a7-ʗ^bU{mrgRX[<-CB 8!3pp_"5Ì,z7b~b.;kLgx}>k228g؅߭u-7ܛOE}7r%Jˉ YsȹԋɼxE-mX#Wwq 9+\ڍceZo s/zyCiwQQ6*yn|Dz^xz29]3? w|'L`sм26DJb2t ..Rgnjch-pߵŧ5>[7 -؁|z<[Ȉɖw2 oAMMN.vcƠ~&-0''Vu[_9d׫fx9yRxO=YFbD-O.XK4'};} jss|x XW P|bo1̆xь^(Q^xpñYw/TڼWlc͞ ]8i M+9WR@pf#+%.1҂q( \kp|l{f/ȈNĻvIq) ^i ֻg4{L9w s{:B H=v0>-Љ16ƈLk-v i=ו런vguUжnrV@`osy[zh|ˋy.7,퉯rN !/;0hKlkҸ챓NAF|u9_(PK-/:AnX!葮ktH+Jľ_}$>6-VޤsA~'cǖ'j3s|8?yU?3,$ ٙrLld?xZ#'/Cq;1+dTE7i4#h%5Fyk1AmkESqsIpF8#!Xy/ `xxڪ-?ĺ;dq`k|z-7Ȗr]L:uu&2mOqB_Lw[\x39CgII͡3TP0@4 ͋vڃg݁̋D̅Þ&GWcAn5ZL4AeB^n%'g`-v,@G1Pa475o~t3X@\S[(d`~#ܸ_4އ8?+JĄ+7 u^Uc?itembs*qZnug0j 4+lʅ*iЄ}4O|?5>u\lh{[u?G!'} |퍸woo>DwtL[meJ/>R #vqBO;N˾Dfm'?[aff0eC߇B0y GT,G 81&=aO9_[y; +79CԖH 3nsq6|:ErFb͵ }ň`Zj8njk^M:'quiVzv*yzvϠP753#WL!]vO7N)l6&o\ܪ- )A9_o8t鐭b=sQ8t8yug仵G .c1om`1Q팹fcsK.;En[Tr`P:Ȯ9DOW&$"I9αC2X1t\s5eƝ+Xp]S\f@v9Lÿ{$-mDXى3|Sx?CH| r>kulJn!x:0#Y{Ց]*fvvI@܌$874ܚ(0`tvu .'2?;«j'F_]MwgPM^l+!+;޽_\( :t|DUԝw)*-tdԌ '7Wb~[˭ubLq ~B`p&sTsqMNr^IXa85칎3NgsX`yl}v}c? "ӃBC[}:2ld2U\su:0Aŝ^ pLX!^&us3pܯWCalN[{z0*P9,&%(A"B媍 őLϚ)ݓIM>PO@^zZZ3QqqP )jV9N[}*_c|_/nݎ_Ǐyhi6yMN1K:; baGyր)-.,LՍ F f˗㓶 #6אj7y2g{Q`}ؠ_s#-ߚO#Ac9ᚡZu`o8'm?ݣ N.NkLGӉ <'LA!\q\/6PW>sqv氖 qx\u mꏍXP}Bdpnx]O\-Y?C=c{ʃiXet(ݧVNDrL:|*;^#ۧ&2xఀh M@YSdѷkZh:^v[m㉿{*fz_b;Eǀ]=2 x#=ux7ëRF.G?r2\W͵rm//C(N|p8 _ë6ݿ_>Yg_6<7n)|?`wAHX~o9-"NG㮕1e>FS35w|\X-Ew{n[&kglH|n`.O^C`ءyqG'I] 6hv{,]+Rj#ߺOp`cpul{ϛ7K=&v vFd5pb6c^9yBp7=du?&=^v8Og'2vɓN@H~!Sujit6rsR؛It#_u±o2`j?9vƑA}:7/q߲r5>W~/*"?:jomzt?W|I>W~#58u 8-W^M6Íߛ^SC5vm 7LLj=;~q\A 0ZZq;NPGHjވ6):VǍYsX8w9)2=o=.[>wz+;%yjʚ4f0ULqE@5+d5kUrW8߄cpϨs g\9U1wlmۚ;U+߈͋`@ PC_K"p쉄M!{d@2,Gi֌YIfb5pmTL֣T{eVޯo4}xNNչ7 zY[ukڸ;|>h{,:9kCn;Ep&J%mlٸ 6Jbdn-mtlK)m&󾻮:otIuiSݔ_Aɹ|`/xofFO™K9N×x\azc4Z:9esogsp[-_rcR3c`א\:=9YȏW!QoF-gnp1oq7SK|R3bFE"0oXouy₨71XUQ6Yo.`9&7 2:b3`> Lo{Ah^ږaYmW7h= oeH'/D-H5s Cc1$^վ#⺵{Sn(VĜ^G.(XVݠC˱ioOX}[ǫ/ޝ=.eNj"u#P:$r$_ڟ R=m謭2. ..L)"|wݦGx%F.i,VFhwW>)rtA4Rmh#fN9= &缔Mߜpſ3A";[(g]_w6P,n$/}>J`WF[Rl#IIŏ_X1+x{!1#KW~A:_̉[cY>Ʌ\n(-0^txMPI 9X3|%E1Tl.z}[9[2]wp`J<δy^8u! 70no>ZO#ϔ*h_,ikl\l#AVT^!v|<<}8:O,vy>c|!p<٢o~$i20ۭU7zjؐ갉$fCJp7#>k=@8>x>l[V`1޼CԣWnqii\Nde_p~j>9^󃅶2HYe[5V4ժ>T,0[0[1g _ƴooVkCnV>`"ZcX_؊(p1;V}_˧_l;~03p# X+8x9~q oll)Bm#8'Ӯ\*x::*sl"2SP߳%I(`:i/vA #ԈXS}غ/~G{&y- S7h2Ƙ-o rB;S s~q zkʕZ㮍MKxR4JCx ;v=;v>Q6U_n91B SK27Fg'^{h-'Q{{mD$nc@?U91ŏƷY9{t<K>*/k.*x.1Ӌ^,n~ 3fmL~OkqN~񿍧rD*w@`ʑOef֋Qw0"e- 6l%F t [/Jh֔9|^8xuV+ٟ3Tsj`w:F2lw^˟cLĩ>l=E@ a sܗ&66k0~ tpo]b46y5<|VDSeb4u wMXq7sW˷ޮOpO:JmsRSRZĕŖd%@쫶}ӛO>/E?>mj&? }R;pS?ʍj07— QޛG9eX͗1e| Sڡrm5x`4\r6EH"`:1aOo-a*WpuZ0(9Sg <c\6Kg|osd԰&RH;_ MM9I !-LA^_^QC^ܦ]| ˔X}~b.W|m̻qyp;0|jN 4:ܲ_Hü ] iqy6k|7nk=m̓qَx:9Ǵ(/lMo+BϹY˕^ 宨mjc:~oFtj4dSͧɅ~}vO)*ё`,aHLшu?nv?of0ͩ- nejmι 17@Ϧo:GQ|Wr k,^u\]"mgZL>&~Yxs _oRag,&r-Vl!vs2z=\Ǝ7 " ~<Q +B|jr[-[ t/|arQ$|Ok{hyTp@2 >Qp?"9QJB澂/wG$r>:d3q I(6)<glwx÷ur[aB%hbKPC,ݐ_|xyAe`lpȃ0dYԖXcBN^|Yc?9i~ڎ~.&kR;OQ`QN |1F8BČ\ld$qn#7MV 9I$^ße_+/KHRȓqzjօik3yo] u.n^ܭ=lJ2 SZUߩ;0dh95^[o'8Bd뎬EYMۗ+#МW T w_#uv}%_[FW1$hUOT0k@; \bv4s5c wWtoppid՛O1011@t*T8`w̌?v8yYk}||~r6Z) f_W'6yƯfOx{~ڛۚG,C'^NpdlȖ!8F8tT%NWp|Bm2r Aוy7kqk ;tYq`cp9a]D(Pqivrzc|94/l_E]k`̰i=^6Hca_D}YZj<L$b<*>x 3/oTpAُs=jYe_[@Ӈ=Q [#Gn!vAmԮ8X_H'6}q{|`܈f}u>]<)9u 2vh8j ez' =n $"’\70\x_Ʈ?:-SM:aRL$97>`w}Ĭl^Tg5`&С2"d$x!'>_|o7k,:4l} Kb`5ohuk1\[SV'HGlh0mdNj\' NwNGyn6vj俾Ơ:ל>vTBͨk4Ibzo{xǗJ \t_GV[^|gC+G÷ir=S9.^rOjobY£-^/Uf<~̉ߍ`҈C+rcaq?m1wȬD@VR {VϜ-ɥ1ͱg"h-~`|i7! ҫw 69?Ec(BmŨ@K@ͼV];:b~1O;;o1]ظobOYN2PziFy :jiΉͩ>a.,1G~LC=1h'&[n-eNҼU1ޘ@ǛDO@>F:7:ƮẺ1*%  ck4|qVD=wW.\M:{֕85t6UUWwcbs^X UB4rafӝ56s̀H˸Qc9nhf@fwٿfj\ ^ꟍAG/RWlኍqn5]",bܫJ&ccC̗Yul Uӕ$Er.L[cj![q1K6d,-BrSxxpE'ǹso9\y7vyT0|lѥc}|?k~5-5Nb %Pt0 2SW} oNHL[.~'OWJcC8/m9mtImZ`H fM: 8K-P?EWV8G8}mr7vbu-0Cpiƒq:Z嘐 X0ΚQu tk{\4$fNۘro_,ysTO0DHَ?rdLn q$Mcy Eni0Ǔɱ6W6'txdZ~ĵSBX r@WCoKϞWl@ç^c9vgS1r` ~3 CF"bGlN6b4:UA@@sWi Öqs뎡Cq_.]p;s/+/`yys\M|]k6Lt~B=BU!󱺋ml15\\b/6abOlY! yo#FGs<?rǏ׻VtjrEGQSUOQgpA^§ K2wx cHgzSϴck^y{AC|a~c 19"j`ۙr=;>-@/Ḻ[rV}|q{^b\nS5^>;Sm( qGZk}͍rȰ0NkGė9tjwx݂IB>.>(u3>o\޵Mݮ}|ӼAuh?Hp%u|fxM{nﲒRb+No|Ԯsr"DsfBas^vyuvq1u=Ưpq#@1bbs\C|?J-w3> 5n&ai3sT;d`"(3s vM x~tt#Pрj CcMP9ꑘԮ E.8XP8{Z|˛x1rcDWsbfP]"s$m}qbEtgiUz8NrDC&ca;M$&7ǢzjC <͞ˤ 3.8ІC'G -WI§݊JSBRm;;iR8w@`!F:1ؘe a`7`T,>G1ql&1s xkay8..64}w'b$r:H<܄kvHC@`"y|%cc Gp]ě>W"66L*6Ê|ӱY9Vͩuw0 Q۠[[c,\kqi1^|m\x,ˁzFvZ RZzx#ىv@mP#%/9ʇ҉aę/`76cNߋM:Üf-D ^m6ggtW_O/.iC9׫jkE>k TƤuЪŭo7͏Y '2H^\#lqNh&R8i96'걹c{+CƤo>ûk|%}xW M+ |qpcTS6QDD-k~2z:NVy^Y\Ie 4H' IDAT}Y.\Jqcv̗]Ģ֮)]3P_}Wɱ6DY+uAU;ǃ):=*sN!,2m )tX$Y%Cy "fgs=%Aʕ:4*%8{.ŎO9]4$2\$f^d<|xZ<ͯ,4Ti`?_Y,ѸBON ?q }M51ބ(O7 oގ.hamBy[h|['͟[ZаDV#V#:I 㻏p8h۵[\O^2|m ?`Ҭmwg㫼K}pG+s [,&|#}p{~hˍT`8᳼ cڒp2|Mc&EcMq>Bתdbx_bm/2h7}ޠʯ|SY *h;Znrձ)x/MfI~{J?>:Q+6mUvq PF%U̜WqJW_M}@x57ÓټOk"Ѱ~X%7ϭ } Ӊ#s8eޜc4/scMr?(S{\uK?LqREvg>68yOb3^/\և*o#/x\=vOd[B-UXrFW~i'`m8Yg.,ZO >|_Oݯ<9pO6!k`JFpE,x2v>}sÿ{?S ht[ȨթFəx4|}v[cn y|`9˾Exb`0.P Nln?.5)[=uwxa{qn_&9RaCmq69k;q0/\7\D81԰x9tgc~=Bb0N y9gx\q40Ƶmmq޵Qd ˍNM÷N3POkqkZ`gi&;v#Nfoa-V'5h =WεJuk fb4oŖXbqU5~:Zɝ9esDlVI˕o95ry/"_k8#.~k@]ދLh$pc{ '64ٸNC{kOϠޤGgb́ZƎ֎i&ӥTc]j8/.nN(F蘝"jЭ=4ddw~pVwh%x7L-Ӕ3 n<$ϋ OwC]Aau .0p}TG1.Kس"SN\5=ya?qo;5aXnt PQ/M|Ē -`ANM>~`cex+IÀ gNwZpC#I^j]׊:$ΐӚ0spvK x|1,ww9#p峥h:UM-j#c_31-ϐ!r_D1jY.OoND7 8y ^5.s `څF&> LF#=v]/8[8qX޼ܿE`_r\03R-fOm󨉪"uvc׿kk&/b-h MS?J|N~ëp10xocdXȏt]9N[MvU%Iirk;qM5lL\[P^.Ж] ٍ@s7̯=^ ;J6$&I8]XϑבEĩ&G.wa\ω,_K^cXcab7 с'ҍ\fC=0-O;9hֺ@*{6 xeNç )l7Ċqk?hmhsQ&-p]FKeQ8ܗFvpcoʹ:l.gH;ƔFbq!QЄ߯ZO3=֚ou1O൸|i4rB1ͧk\ݥgDDj/2܍<;6)#csLP=v2u:VPHظڤHr fhXKú Xj*I<B]ħ4 6Gݏ+2YL\cF1s_f.3^uYBߘson\k2Xhlf.V0H7ﭙqGXyA$\S$U{Bbbv8iPR| /,iMSG5"-+:⴯ ՟>hTz!#ǫ!aK=dwŋQ׷|1E[@M~pck/9H<32#$&r->mdp"gR\zQ6y|m<}غ}0Nd\Xv"MհbF8LruUv\srK_bjr~w3o!~gw?·@!VlEɩ_ƶ#/[io]KOqB Z_3ws:Ӭlt@M7 ΅NBlÓ-LZrݶ>'klO,3Y.76U@XܰmEN ym^($?n1ŋm{,x5XrҨHX3:굅qO|vk!P6{E7>+|;8Mac9_rMxC'3QPutSbݐs̫2{m seZI)Z>WOyIy+>DY#3FϋV^f{ٴ4b 1+}FQi"?*opv#1fTu8AђL7#͔nw\>4Qkq;G$=4p2B8qr[5'<џ1yMo0CZw7k|טD׋n4~u6 FY\}31ė[sq"[n$ho2ĥNktdŢrq]xM/C^!<;'6  | ඵǷY:ofXk2vC2(8R9u Z|w> rMז w4[ F[[5_JF̒im}hJ+Ln[gmW{pZTĀci#vA&MxKb=d6! Nk{ ldo01ؙHqus_k9TK| 6FON7'XJ֠JlNK.ܔ9Wbӫ}{~>_E=ւ_q4[Ɂ ?ǁȅu))lՇy?:a3vtcڇZө q1++57ԫcֵ<~BܓgH,FX$i{٤&A0Ԯ|xhH=@r*_b0r~J56j;|hM̉j;Wv^ablݟ?C<]K[ֳ'gߘo8)=BEpz^r4xNO&О\5Urz׺/f-hgMѹpoȬ6Zԍb v$į)뀩/IF6-l:v/w b|cxpP@cM_#u،͉uܮӎL=c0rpd3sQm5 &8OxsCvٰ$>zӔ'~LBﱣ9z2#7xVEVjAq"oJ0/Rd/gskdg]8D/ D܀!@q)H. L2*kj3gDdֿ˂|̈#FD󸾵VfC멺!{O~ݽÉ7$+I~ lXMayf2z3`Ɂv,\>|L|V[Cݧ=#jWOپn^ֹɇmh\rv|XkW/ysT5hiJr/{B,1{S Asl}c v j~){ŨzО(fm{^=>oS"ଇWtt~h ]/ބ3;"WݩWkt4N_jHÿKl!hD1W4~sYgfs;?<$%:jFlɽb.s/{{>Z\!ג`}xfk{ح"󜘍5Ii`쉩:sRۓRr/\9}$ Iw5jmݑͻXa<[tsGW<:\8N͋}!.~ .^<>>O_݄~5[myZ6ƅIJv|]R1j|\nYHő{s "Ft~hkT?gGX6@sb=h8u-:/~Ka ș/ÜXo_o|BEs?o3-u#gی'C?95Y&Ͱok_j[+{yuW{^o$~C}su׵_rSxhoq·MD)I!^8=S4dN\Z;?\5^0tEr ^/X7ot)'yN 5[kzؿe'#6og 2N] /5~`暳ltZNչ\U9&< 8 =οz ^m^kd{>!`a $;?Ic ɚC}tkY4+)1ʩn(pwf dH=EBۨc;ܓb@Fܧ.q1ao/'_p57r<=?u[E G׃Q ?3̡'<mn.$=yFjۧ=Wƭq9c(i5אԻq=}CjXa`Nék^kᓇehI8m_fq'zFl/nyO9HutGLƪMs?ٿژ$1hp0־ZN?`ay,v)7_g#?OJ^$)!'&8G֎m/L;Fl=z%Uf2 ܃7Zkl[~'[k|r Ɗu3p͹j|{,k@?}\IOkW-=no$D]`/6 ^+m_gX>vm7V76Z|HI>0x5#\LMؗ캍C9.~۠i6]gǤ=ҏb 0Բ`}ݿZуsjoD4g5.FC]gFpُWu&rmn߼Xp|Y` }*XWR`C؃E KZd[kI3獄^%M~¿g׬zOÐ?{ߐ<.2%܋rL A~/Ro _7^g&hT/1_or+{ Pԡ{l5o$'iA< IDATɕ7 :Ƶx{DA^~ӋOca&GnP*p#r@{8֎*;qgrs~kk&܇M4Ğ@GJiɗrW~{; "{±-$O?8 Tr@RҿB,}m6 %Vϧ}Gi97pV<Y]ѮN~)u6P`ti_ 3> v[}?c z`n|Hln>8dQ|sHKp&uM$Ƀɹz~PU' u7rMwoj/iH{}F^c˼5yeb:L^EŌo9EqL_~訳WzI/p__r.4RM`Ăõ}ɪ1K:Y{Kƾ6<;0y!Ggy~u' 1XMyr޳E8g˘5k8w徏W#9/?,+7uڂ2L#enW&Z_sn6I/&py4'Ɩ7fv;+pfY>(!b*@r?GG} h!~7 ʴfsZ!Y=CikbP5O Xs[>5ɅyF#?W\8t"X.s7<5MqC_5#*Q.sY%YHz',(͓Eߑ%7Q<0/'>.n; $YxMhbe2*y~w(7]36:lM՛0y' 5nđ]oߨXZ3LK)79o/wHo a~CR{uBćwr_̨h3yHWXySCbUVbJN^:Y̡ܱ:e-qLp.qI⋍82j<8,_Ɏٞkk _[_=/g0+n/d\1RCSytxO-{D_y\ְ\_r~C nF4g6 ru0ш76Aik7)WS?1>W%_~o/|_?o{?{coۿ_k?x P)*j\8o77fW,S-LF|+?|~ݿw!G~wηgFW9EcrxLNsTy5n`X¶~BX9\W/@.¦ѓNYD`1`3_Zk*A3qEu¹⠞7|s*0s[zqp*C !W.]Ŝ| G[+ȑx9/:{%SQqMleFM4bM8%b㬿9G#\~xȂ7BŐ/Jr{<}\fNhjoO_j` _xB$yfYKaEɽk(!U@wR/uy*OW2X,!~D.,RFu$KXb_щj3qlX}yo&P,8sz\;M9j~C0[b< 88a}a{_$6 KȗIy9/rccu[]98 eg@&2%]@reo~qa9 Y,:):+=NB1g< ?;?Ğ綟/&gpzL߼w,9Fs%cxךxzj<8j2>;k_(v%|r=A`w[_ãg?ԣF1.Z\P|Y޻Ŷf*7'93^- &^؛~x~k6l?qb3Gt>`Id's)52S zװ:ɿlb1l~A9m ikM7 o+}lgz3ۯM<L&6_;>vX[o51?&Bj{uL9}H~|#`oW\>хmjn8=._#h('qx씃yۃq5>L̳q[7B1ؽN@Zo{7C&?^fGpcUA;B'rrq$9buϕJy|8:&O?,:vrXZIW}͈!4Z֦dbA{33F_乓v./oH~3~C'~/kZ>AoW=Scw7%࡬ܨ2+Y8fjД~>CΗOߏ˼~O)OlQK tW&s&7:ᥦ[ UiqLӽ_8;ku˞K pC/ok~+/~s_z}f&Cm2U`M#?ySa)X9&zz'yР̼Cmrn\#ӏZ z)Oktgzso6XҖwk/ɑq5Ŀk!6D}܆r31x󼲚gL;%Z"] Sӳ鳷8ωع.[цo8<k"畢حeq7u\<۹mNx;4ɂ6'IG؛L0ֽ:W_ߣɅ,zARƬ$g'>-n9},\{tAC~dv컙 oqf>z;c~4܊\9=G|Ƭ3~C,#gL6ut14yXӓ CW>.(~|l˞sM/}d|ǟSYkq"'wuʺɪ5j&g??Nvl>ζQlܞ7xΞSc{fK\eX~56Nj+b5̓hgލD{5Ƽ%=0j_~LB>WWO_3eM-f/ќ R^"fľ97}s(́Q<쓀46T>k@4Abz@d\A<[Po|o47+zu:El'Ѻaauy{८_KM-fg`|gt8'&fz>|G\n|xFSfT*Fɷ8T7rn\ 5_~9s ,1ɠob|[99~O(SRp1^ 2's^/0pfwokxu5`D)ɄY]#菁ak 744kh*U#N]P+i7(muW+[WQ Lwj/`>|Ӭ']\[!:crV.fw΢Y$ 5 .<_<,n+N(( > u"xN>h!Wz3 _ڝ&|5/ QD項7/DI^z:3iۏ᱆99?)v$Q1mݱ1>G=b *CA9؋ol^^+`Αps((쿺sqs-iv(Y\Iyl2O0bۑ9M^Z!5pr\K$ˆ^rϒ| \,{K 9䄉5l pmfi Т56b<ѫ.|!M<8ט}U>p—~Em8h$\ MmB@yتe{L~XS?蠷͈I8;f}bŁ83<ߵ6qP %LpkEr;uLߋi̊+vnڻڙ78gة"ti3Mu)HXgyvh`q=.dKmX${`HyS/luOdq0=936ݳ`ְo iD"<7؛4xs/>ڏPC1!A Ujy~ѽ\#jœr)1SdРҷg2IS,澩M`lj^2 ]M}| Cn`FHo/蝘IB`E0屗TuE,_Ws i/q r &h2_,#1˭mZA7jh28~ph6Ųb4'hIpz2mXԾ^LI]vT{ CO?!&fBFun˵:,&Q_mxCf| KYܟ!WO6%2M}gq/]//_>~h˼;?q~=RS?C@ ;̱w}Osv5{ _,9\\WՉ~%=պj®'bN|o4ho77Ls~{}4|^ wmM 셉3͍MU^sZSr|s}cM/'y8㧺6bޱ`,>1n~; Z/\C 4Q;N L i\<5@Hszc#E롮^mwn 4zX}.#x s0 j1y? -̫?',ڻ_0CB&u^E<hk;j $I0U]uD:FB84F?705sʬĖl5XKs ρq6ڇ9c )FxaVαRݧnQԢ'&g; 㲌j/5h ){ƛE %h;tBٗo|Ayλ sM>xa#~a pm5?wL~r=U:eN~VZ\\SeqNl!dh~R-o\t r,/6Rτh19hUƯJCLJ "F'—g|ܛ;ǀW|\*F'z1шj" w>s|-Vħyur}hĽ׊T/Op0gj:ԨϾH!}n2 D}ҹYGm#?_Lq6XxC+ӓ} FH5IˉjMRݽ6Ą=~反LzungUdnowoFK',Y]ԟ/+yݝ>g!\ YG 3gٖ{]bG#'fp t\c\o-bkhw{5'8aC\z_gC̴{DIض{=_L@38mfty'Ĝ;#X3dw2ߞœ/k8A\j" :QC1?c&< ,$;:l::6XEyPVᴔ\D *\L=_X3YXWCf{؀o&p"&?.[PawqwMВuFO2˭18YVчF`6cI9\=&=a}q}S -kkv)Ok#!RW;1踘̈́uAÏu[Hm>un_|cMRAyV^)}\8؟zs£Ű Ik ~rep-=+IՄ{?xrLbg5YcGO>uds,t{8\nپmaY [)lݼnۈ9a,c``prjBMf3м_)5T;4x61Yp張3CY#ŅdI9/,ZFܓ=s:Υ/qÓCB)=\$8*GA>kʐ=8 IDATX ?☜~\D^[R2;xsqk052f1p߁?b4RC#gM zՎ<8~\֑eFt ɽomj^Hg4V׼<&neEK$O-_.c?%aps>B7sF.ƦbGԗa lkӾ=+mI;qX+\pa#I!7S~6D~ (6K1W[1\825馞{吃>yS+>st7fp1*#I8QX ;ۂy<@&a!*a\=P;mvܳ漑Q3cbzlkԸ=-jGx{S6XFF{pQ:@Y5dW'֐q]\O=uC9o*ƗH{ gYdĢ 2k= hlq 1BhE ?NrcǩdVW`q8Q[ߑ7zܱeoum5*+8cWoƑSwCK#XYx3>: UXs_}$?0BkJЪg 3bmzP>4g/iJhQ&.|`_G3Tӳ\btTk!>ÿ/br湥_<^+;NJ#ixؔLLɹy`w#VymԖ/$M Zkb/:Uu&I|{>[Ζ AG-|o 5QdR3Yi-`b hDF n>KzKe|^Zڞrʞu!y nO d|1&ɱ#xj=9=l|k/ 6C5oQ>b܇)}ڑ\2+b$~뗿Fپۣ3K-"6WG%f{,R0a:gP1lSr6鮬<&Ǭ}NΏ}͍Q{]z yߞL؇z9؍e~n\$'^Scx,1!fx5zh  )sr҉bg3@|[D3!Rc~&%ipȞNFwuވM #rsWEZǧA|7/{8aos:b t0Nqb[Qe8yBT{z@f&$j? ^Vp mDNa@gL_>y P ½~G6ӣQ1Ɔyr=h'+$ N['79.JXrOR7";c۽~Dw~}i+ׅ!"^N&\^#t=r\'pG-}|%hќ닊֋QMu7)i+sI`=WA=,9ޡ|y0^{皒9wQY3RV<=97`N{bEm ۀQRF㱀I, ij\IWN1oI$}o‚'H/>Yc= 3O f'Rc:M_>W͆L H|j^XV{WM_и&/l@nЎ:ĽxWGΎK|>zaZ$wnjޓv}H.2{.痈ՠ%O֡`i+Ć`'E1;1׏f Eņj@̌rLVrȒKݺq/܏fbCI/mfdyYaQrL,<ԁ{?ˆQ,U{`?jjLđAg7E?DB*{j'~jzb9.Il37ڹT#Zǰ ɱ}Af?qc~u艇oX[UËHڊ%ZO嫧g4~&>>'y8&þ''b3GSlmn[pأb 85NXEx.$3wk?= 5\`zR۳$'gFA \x_W;SGܦ9"ɗ/'2N?Y&8if=g:Ql{@LM97I*zir8jc}kJ:hz;Ĝ=UlkV*Y֫H67 ]oi>0+)s/}k5R56!^lipre^8eP7B 2:ѧr?ؤNsPcoB5@|cJ%'r;t͡+=y>e,rk+vC3 6ҀUW`&3 إ <;Q<PY6͚F\Z=J/<]ahur>86 @',KnnnEԇwxWx)یIs,ϛo͹q;i8zG bLx=̶  wS`:}0OhO}`ZO45@u7;=K̍ه6dRj: oC_ $￵TfH*þb-ƊS VMƶg?Rx&뎬HJ.ϱ4_FuJyCb\3-ZbG'Z|+z9RRZ nk꾾/fu/H$X+E⬾h` K$q;CXjPt돮3&t{ᗽǾϹةf: N'/G2hx ^ 12,Ӝ)):>s|p;A)`٪xxrɏ!VZʧӿ*ԣVCsa:c3멆!bȣdʲ۹wŒ(eq<_%'%~Al4KC_)9yMY֮lɱqߢ h Ib~\x72LS@հV 1`z 4ǎsLJ>P ]6=zIh%y1 KHȄmHx5w^L~,k A{? r_d -^uXByk^6&N}{dE|9 Ɍwn" "rvĸ[a!0(s`}K sz|'#f<\^p#=0 o &kݗuclb2ȓڬK638_]*%>C8/7,kh`vG[Z3E{>/+ S>E#N}~c'4Fm5|fx#^@- f?'>ǾLf.c ڌgR}߸u>;^c[كI~2ئͥrɁ9W7Yslqc; DC3kRk}k&s|2z[뽺QDeDQa!GWy3S3xepLMop.um;. ^}wgn{v(rиMLu>xHa}jXz|C5mdBrȸ®\Xpqu88h0F}Y2Љhå<i۬bmw D^#8<>oi_/ĜLȣ\L@5/LE#_c;sp_v)/© i<ν 怿9;__Y[[ɠp}r]~' =>u✼ėwH~s?U#_HGmgɤ. "$C?eZXcô=~sŴv5ӳ#~w'!P_6i&[U(K,]#;H+ԟZo)uOTG~Nޞ'903TS~zbG_NGӭqH+jg;$-^ pq􈄣/ݯ7A2kUP!<7(z0CVcYꌧ1F+'15SF{kw;sgu\\C5:szk [s{rlj7nTm6'NbU: _o/7+匁bCR3t^# {Y;>,ssns!q&A5>#V8gM5jWZuTKucW߸tnL1՝Cְ1M5$pcǽKq# ˛3<17<`șags`!8b31KM%|awrzԳo9ڷ]ILs c~\94f>7jk ~ʛԻֵϳ H7R?8U iXyW58wp52ӽ ñA&`<{9ɤ{i,a{;?WE)Ξ h*lğf<,TB37oS ph@2m`ĺU&zc}c{LJcZ~;PHO0u|-)ӳɖ:ֶOK:y2mG/WwlOLR'bn7Yl1 lG海x'}TzN Zȏ5ZYiwM_510qғVSI@tyk=GGOGؼW3N]H.4'lkD}AJ,^@N~Cؙ4p[~Ք^.&ڈŏWg$V-c~9h=Vz3[ǓԔ怭y7a?"KM;}1m<)-_vCZ7ʥڍFZ_`?ȩpNۼd7Ek~`fʜ2GI@: ڼa='jE,_rM>x/\Qs?,X3v}h/r#]ܵ%nu7Ty d4.пrWYas;YF7_̱GMmOτK̹&H=kղ5sHehnµ1rKoFq'ފ~.ylk>15$<̾oE4gXCDCk^R#;xc͑XO|)=vω ,O9s>޽@夆%vr/#x/짥Ȉq84;ͽ1ԐY":Yv,ۚНtnC&ph'}/kd|]Za@S ׃9ݻ26kuoc0P+;C'h{|bIvPۛB6sb? yN- NE4#~H45r&IH'{2al^#>X7ާY n=u?ps߽]=klHrmɳk7):ylwuVGqSι7+|`IF`Kx(&P 5!]F <ԦYZRn<9!͑uset2_/\1XuZᘓd6BsF~r\@ѫF!Ornۗ9}]jМuXs6|]7Hi;>kj gF6я]F0T"COd>7 -y/?+ 3pNȥ] 3·H|c9Cy.XDL~Ij>6קƆ?~&>zM.4/=J|s=wuS9rA<M>xL:(ګҁ)w<`xCZx*DÅ?AFE-]z2dQmy98}옔ƽ(VY7|бjhT'Ћ&cK<%eHAא`1197\GF/h ը  40fwmoA34#SI;x}Qy IDAT}# m5'tсnR";7Q[@jQ)cA)Yk#~Q -׽ܴ ~Ԙ*_,#^ rȭkDIOxќdPW+#~nM_ڇF%k0p KD!^q7QC_ǨI[#I'|>, 2vk6<&xNvg^]?#cxW}eep/jz>XkZ d{?51.v"gmMhw_m!BYp䧏x}i`p,OvR82)KbuXLX%Liȭ?ѣCmb˩F)>?tldY\.Yăi>_ed $aakI zOm,&śg,gƑ@pZv/QE^aS<棙Ni9{ԏs5 j}Յ[P$ou<D?{ywJO۹&OV-|Gŏ#cRY6`x 4_2LjHgb9Y䟶1ځr8yӼ/V֕OŲyʗL}yscbgI=m 1xjft_1EB垏vj'dDݧ,1 tyЁCcLn˺A3$ˉOdP&\橳x\MrmK> ɜך[립Lbޣ5]>EÙծ CzmDG恬wOĵb9iRkgxM_kSᨎJ_ʹO e?}}[PJ]_qmM%diRC_nri|cI?}Oj8ioeruyBmzZGL$/}X>}^έirK6ϸqb?n/ f$khKpNKym|Κ@~'chyޚ˟ch;6)3s=?++ s"ߛg\9Cpj d8o.xvΙ?K"Zϭ^k[^{?OԵ H},Curvg _A_ i[Vdiz}k[!7/7؍[i#pMDm/X^zxQV8ɷ}g.%>ZnJ|mhSs  oXYDNn0 4W =؏?F3jb մ!_!~@M|5}>>'?/9־cƁzY%c/?$οX}`g8~eߓ_9sS0u tD!uoTgVe;|_sS=KW19\1|<~3֗o\}:ýuDOnr؛:45H /\V" nb?OYw @ 'ZG/$dk67oUܽTKp_վ1dl)3uܑq)fq-*\SWF)zG} '4ĞjO<+nuڏ~k-ktϰ7Œ̟>T},x3]ķjvs:}QԄVFDIt4^;֒u~9/vϺI6:I5YQ;>c;<9/c-[g/v/O k]u}C +{m1C9o^0\zus◟^ܰhZ[ky4A7 ^ű2YePȅg#g\W[SaMLwʙڂ&P|c# @.':Vt=,fu/~c3y`+b{+L J5HG,w 02Խ>yJS*޵Rғ|F{G~y/ '?QۼHʜMBw]wGv>Fcボ#^}PA|zԶax{̛"~䓷5;%u'G詣_۾v͓ I gO7z*2SoKKp˷gl1SѮ`k-\ekr 1%%딽vDAk;ح;ϵ59_'x|3N\͵:rjg^a7If_j)zKߘ7L_S%1sC> f~JKkT13^.K?D9g?|m - ?'\3HƜs#t9?:zKD&3? H)K`h(G (-nbY\{PžgÜ~mL7)qz缹8i&=O:P@_&^j <>}eߔsk6XVu [k~jܚl,=o̿Y᨝L/ԊCrCyXKz~b_-5˳y=`G8z"[l;'5Z`/g4nÝ焞5鼯求{ :2ns5bs#!QE79lŭnjJxgHX>m KcO23 GOXoǙ6?-w;+S3;esL൧mE-(WçnBdwCO^֋ms=srǨ3BCls-iox~ތgU匭aˀ;62ZSfs&x4Eds \Wci63ckז7ߤ\g]ePb]?c[xmy1jqr7;̍\?r^3Z,hjkmccl?N/kL E_ڰ̉k5v' lg൲󋹿[x95TrvbO$L15=9{~n%\ɑ$Qonu;KjvW`dp7772If֩ܶ/gܧ ~t4hygNzI=`Y S<>ư<ڗ<: "Y(%=?^2P? kobB ʭМ3~yߙ@Ro b9 4{嚣-ԟH3?݇?1Ϣ<^ȵ UfX0訞$+a;h  @bVT$`ߺzVlԖ-j#gH|>у{zs(h6Ҋ񿼦V70O:L?Nl ?=^ΫtĶ']r{srӈ O~Ash>1̋?4߼1p R9ʉKAbdla`4s z7ԼX^ZuPWsChٳ-\=/>r]d:JO,מ;ӓ~gR~F80rfl Kgsۯ~3/DF3 O L!^4 >C~ 6q R?b[).;5C7Z˒S36]r/̌md' zeo8m{%szi9I6kOFu]=h~=yR =e9 dtZF㸦60-p H0;Ӟs*0G9x.9n#9Ze/FμgOy`m h~ǹ -o/U%cF݈% >8|=1s|2 o4_,Uqָ<5by:DcИ6^x6hfotf'P{#=Ze)>sPηcO.st-%S=Iq3<O/?NO%'ٲעǁ>==]I7xעeMOc<F9 ߼G'"A9ε>h_y>8- .3y`;_* 51s9se@p't>??u/}d{;1{ ~͝ 3T;|ޟnH (ѵw{"xqy~*&}HoPm;q5?'`&9dF7y7k”5-]@Чv~&uZ77h^r2ڰׁf'V*$/4rKfb,EB{p Qf$2ȅv4L v8őƹl# v o33 ^x#i%`1kO2θ͇"9ůx{5Bn?L#kgPtX˦X 2jz z6'C˽swFP/W~Rx?g <=nry78oΚʝHtJ6+ѻϬ(D?#_< 4|~prBLވ?ugK(;sZ}]/ p`(LK"o !?I-'7ፁ׿,?~!N6] IDAT}u|Ӏ}7|"{&ώh.q;1$8#L Kݒs]j1>W>oBX-RhHn8X \sq+? )wҚWSqB9x 4>oy{T N'j:f\K]{FnYW[4,^~s޼h6oh"gXp;Nl#^8< UmMν V_r>ܲ]% 7y c>д^-1xj}wå,``JO cg.pZ?s$:ph o^(\h/{88VX>"){H9}p -ՁlOm9-zBzE$ 9X]b>ř#=`'>|ח7V>ϵu{D>k?rޝc=r/[0˧ oOG9\7="zO<- Ѿ|nj&Ŀs E6>(O 8GSk\[ƅp_MAg;-vX}7ɂ`MDaLΦnױZ ^G_^n>(+FK_ d녃́' 7U5fu=Wa<7ٵ>q9?ciieuO]w4\7͎XdsԞr:mx\B+(!x[0i#5EG h akk3oˮ\Y=FzrcʗywO4oMK~$19G07LLk1pf_ cϫ1 (bG4'I6zDi;cZ3ҏ&qOvֆaa$C莼GXO\Y1A)jU~v?p6tmQ\wb^d|Y> =\#LC0yPo夞\@Qwm_ypNΠ=hˑ!}V&yHԛZ7> 7?r;j3e PpݳTm4s$νaϺ۩ڶCC" $5EGH==}j1tdq;ßbR5ݪ osⵓ[s|gҖEw>TS8ݧ-g wfW2u.c6Hx 3;6ĝ2t3֚`7L9;ރúO7t4^܏Ris^{_9NOuqy^.xow}t t!kn$ro>><Wo][ź% Fm>rS|$zV!,;y jFv$b ~|#K(W|h &C" 4{0m_ Idt8;as_xl|xiv,_|hS!LkƂ _GDs4ToR4B%=i]_Bĺ}?Drt\#{t<尽dFl4FməI ^5խ6%/q뮅pE8]T:<bW"^P9~z%]?z{w&g"4j=h=>eT4qph /c% J@v}a%"S<$ndp/Jw)Hq1ոROjdXd}PJ!%@dm_6fbuӏ0Cx`ʭJ$Ol4l7V'{8|΍kweUq8>N5BhM\AOF۴WNvI9{BhFN|MK}n.\ah"qt(`/>49>3/^Q?:eHl.qs_#ބ{"5і ة='k G1r=Zn_3Kka">yrh?eGg)F\cxqշ- .Goz YakхN0ؘ]X_r5C<#{59α sz2Wzf-/~4':HlKƱT~ |"e-|Ƙ>(fQ^d[X$ ڱvLj t-< Z;uY< +8]cȳW !@ǵ>7?9,@9yrsGⲷlղ~Bqs9#ݨ> mr -M/.0piȊ<`tHнƾZ\ 7Np7IߣN?ck1gi[/r#_=)ZqX?[甋;s֣WΛdj Y^)~o;[I_Hp䅦z\09?v z,UBvnY]_Ƒw1&1[Eti֎fXn]QralNĥGNr(vDZ^aZvilcr{Ã6Bv~H>ut N= vGh(zCõGm&yE ̹s!^"U^uI >7bӋj5n~אGiߞ/{Q$N^ƷAX=um4g~w'4rת9=3ãa3P7.RsDj@&abavfC_NPOJj74X@e#h_@^8yb1mu0ےȖ~]g4(y*>v356?G1L; 7=4;qzrCRx]5Zm:ghCGn9q6 '.2=n2&o!vue#ߌ \W;<8_̄r[/9coNP36J-hjb}RF'u34#_Døa e J[Tdk 5t!82G&Aש<IC &/GɋkQO^x5!HjQ$vx=gC3;J{A{80oZr>`y}Qr'*5ß JT=rX彐CCKv>0s_- }ЖjG~d{MWVoq{)1ҘX0klAݾnr8r|j_sz!50ٺڳ3QgKkokLj'!ckZrEL'$ί?ie*dBYk㽒՞>A)oя-9/ُ4ӰS3ev]>9]2q:IWKp-cuB6] eq6Y%-+Vp8t`$N@(Mõ Bֵ{O߹yZ2%#ټ܏vSs:48u9l/#LfCkDKra4t*^r-" ,1<$~1^³;*_ܦ  zP#N Az7UE_qv`ʻ-Xs:mRZ/gvu\덝8G_LXdv ^I~;8!g9M'7>\^:W8z}P¾aO˕*!OW϶r ΃iñp :{w=X|(mK잳 "Ư䧐-\a, EW21Kt?'hjݖ!,6y}yO>Gݺ_;/FiDXۥo}>t_jX-dž\oU'Jpr?«kO_0> M+snˇW~0/"polUSZ3B"0um9HpN,}>ϹvZ&ؼ,-nݨ9j@ˬaFs'V0ש5wURA=b,0REcHGAc6p/?#HA8ZwiPKѭйɶNh{"&[rcuտl<+RbK!Ѣ:L@mwgg-vA`chw7I~Adž0pd&%#% Cn-[ΝCef|3[gj#n{,`=qFc.85n}3~,/c;Rj$[FbR/ӧal!c /̋q2/PCeeco!W8ݛZ1\Gcs D_t= c_{z9\`2&ǟx,1PkJx&U{pH0oU؀2hSaIOhA!"q17jYN8 X#@VJZ<4 cΐy(keϵc@b^]R|{leK8*߳.=@!/s;5-8lK3k Ҝ&*b&)lkS ziWTH9uk8;'gκe:F'5`2 o"ۏL`ɚhfcy=f98rpP 1譚y3dFG[IgZ?X#sҿ&8k/@)9f >9eDՔdu\lxJ\;Og[V탴c kgӌM^{{9f< ӴZwѭ7I;ܳWlS7-~uXڿq-CvF&m>Aw-{s-B'%Aouz~}aeOrt;G= qpgXނuU?S? hYs/nI%  ]wAIOs+R>_IfVf>//|)IيsNrBrZ4PSq |h!n`}cataB _&XlBm3 #yt_A^~&6ɋ6@X-u:ɸ6@Zfè*l2Oax Ә&n\i fe_갶\^\uQY8} 8ŒXo@K{4Ȇ' %܊ rAijyw|Vkγ8XMS>x볣;2=ཇ`Q~dpߒq־eVXV' 9 #^\gymL Kf3Oy6=r s%ªx*eM>8u][^GIYN͋*̼`Z&ۍ3ȚͶ4M99חhJ (nxL'uOwt5< bfOˑDw[K9O.Xr㉗~Z֐FtNvl7X'k%_#MeoOBz똆[y]գ7e6W ʚ.j%8)jL/X*?}]Ư-Nz'٢xDsXs*quhUt} VÚ0.I7D9$-Ђyl2 IDAT7̲qO(|??4@܆3/rxhrNLx/,i AkkÞ:kҁZ ->RJ4G>:~ uCrhYkPs>_$OXǦr}F~xW7e9k9AnSa<_t#:_/d,6X$GJ)u}r$~kд4Vv̮Y9^n!˽r4c{B.5&z[a3my?k, V1@{uCAd6Ey\+k=v_Xr|M 8o'u/BKу&G#$O' cׄ ,MRS&Yj@U6Ds"r4NXOpr.nFm{K 1ÝxU# ޸B<-Ifr;>g_/>B9o,I퇦joSD'5{4"w7D~j i͹j[7 b6abL턎L,zRD'P(51;yXۘ bŤK/F^d9X%FGeiG/1D@XN8y>5UDXcSmWQy-~EO>e(H~EX)zl1XwFmk$ZƗ~A.rN,ȣǸo煋;@GO181O^u)masj {9tHnrB.ͪ\nWkx}@zXQCOew͂u @#V'ޱc:AV$nj=#RΥqdy>7kk'8YRvN?9%l#GͶ7S/:CshBH}1zpH-Ψ Az rys-'uo {Y[ lkx#d:=ywc %T7E \r%ι  ~/IjX_j1#;u0C[%m@@)dO VJw8j4OX,{z{x ;2Fpe[pyu[>l Z]Đ;?c{,:/HƾiXb@6|zqܿ抩@MPQfR˂}hwCVۛ^9rZ{-#Ԑ`OP ç5Mkkt /%ܴnWG }_#sZ[%Mr`KWKtd^Sz ?"|FxB;VswVΥ d~&!h9&J/%d"s'\w٧g=^S y΅Fj7sJl3?#3.3#xNgNXmW{7+\>Axp~`|%. CJ~j7h\ ,p [q֋ƭ+ϲ zX}hĵfA=6toԷ j*N/t\

{O,gFs^NȎ펂-uLS5?$,]PkقOj 2-7&-d\G9޵UGMeAeŞjIx&$Рncw%ka)ڒ~b;Aɝ~TuhE*'i$qC:qr;Zy uϖh к䳖Иc1UߙXɝnV4 suм~ˠQb 2Gݍc|߾}zm5prCUprjauyDN]rK=xiL7LU"M,cSˏD0[a7-ɾEarc2ɝ8RThY&\2|l#yK)dLbX^@YUbs7Dc_sWU f_t<ύ'M xE6BPSIgk|>Ov8W^eMS>~M_Űp?/Ys3Q\՘H,< dc^Brg=|ᄔ5쟹[zCx˟U8xp+C k&{e'>=2UÃ^)dkV+("^#.VǣrajOEzb\@17~&27aܓqh>{vMh.V2"qf-!9ڲekD Coms%\+j7ɒǑp{0ֶ l4gb,=HL=qqCgNm帏`@xoyl*5uߜ~uq/1JAܿ{Ȋ(QtǷ@Kfd>Աfk izvaJqAgI07X5 @$vힹ{} kSt^|.;  `rFFS9ǴjkCUpbrtLS0Xܩ]7101^d׸Ia*[CΗf[_RVŔioI\)1h٬F!^[5r< uFOxK]rk<YWKL/'y  V[zZRC&;XGXrht1@&{ Ŏʁqre} 'nhGA=Oaal@"'Y4ujB/g1/\ 'gz1<U"ox8LS#)2[=GMC_[2{֮X6 yr-X[bJ /J:a3$ǭ!2LhťGXup5BobW&wN"yc#kCMejN>9zٿ99?h6})T9gcsƆ8v닔Ow1LJN?|/w0׉_r= ќybsd~c]ŝ`|=7rT J.h(~ކ2 3[C,½P  {H5<{]Q3wXhkGf s,=vǜbܗjQu׈ʶs~t/ʓ8 k٫]ѕkāCz>"#}Ib+XSQjmCy\z/|k|է>ޢC'ndI.XK:#rNXOT:H ayvRLdѩj!y|. dLm(1ZI!ڪ[k!6;.m8Z|pxݚ ah̋/W8kx8}Hùd}ZF,\.3lZĭ]*>r̭4m'{ t=6i~7aI-ϱseqTzi Q|*'7#8]uMr׭X@֠IاkLbSYWR8_І9D0 ,Ǚ̖.=M7 a!݃h|j>|-}Чh5Z}BtjU;ɟAOټ8BPp,5-f86m mrدOkR}2bF,sB +#lf&/'wӯlދ>O9w<|a ?_fB]|/Z_W >יbpcG^ 6abј{+}q{9/*cO\h},;){u _=b\'~ RAQ3h\~0KO#dwGlfǵ5ҡt;p7ܜ h؛Ƕj97y!杹7ƹm>ty(S{pJ¯M7,Nj$f}+f[8G̾qy.+ws; B1+?(WM^Oq"b /G{C%Nh|rfX_M(x'39|4瘟'QGYWjOݟVB3<}'.,MIB4bg~7\;9`ocړ'e Rm:X<U+9O[k~d6%͒zB-CLǐ-)(=P?*'Õ0+Q|Ƕ̺c4yÔQ.YpF e<D lf.go&-^pǽ[8}$qg\ {4~h~yNxyxlƒd}2M-oq? eqIc !ZF˅]84xdj2bɿ$<<ޣvB=0=qtGOnJrT7[V3_/D0>r+ҡ>}GpxiDȷNn:\='KIga $d5cH؆w#7ˡ=|GpOn.k5{x%nC9_,] vd^/ֱ@Nje~>~h16'6:Zg[-.$NYjqu޾|>7RS~y} ^T#TMKA!YڵR>{uR:~y؞%1y}KqA[joq[xlL|.L뭈,Mhҗ+c Qu`A[Y0Ŏ5j#*'倉EyWj L;gΈnɰWG,4dj+ft2Nlizc}GJʽC'^7NayA.&ڝ=x`…d._X@|+;my4ʑ:c_7m""5z.VY*9&e15\3#:]+<@{ wlW:W*`H8Ѿzȷ_=y;L{8} De/n~GSkF,C3|NHppyTF8ŇU}̹J0%6o m!}85ic<)gCuLzמk,~9hS)9ӓpngr9`zINOp)ol цy _.$\s)MCt6ôd ` <[N1%Q1<^r2Ôjr3S!>GaɁwZlBi$phVn/|Gz!"_8;7*;)BaN795 I_9oOa 29s{[T^u.AIȅ5^-q2w{+ӻb 9%0w9<HжQ.R<,- _^K~Sx!^~7)vOZ2.8#_P ~ t}氛K˙"OX8O&>y}KU7 ԱҋoJI߽w.(J#(ػy 9N"1w;#ٿ>XXe,~Avt?TR,Egy,#5 n'n4z($hOI wnO~x2xL\flDl c'5>,Ojfzqѐ'Elɣ6q#Xcy7zFBbҽ.Ŧ8 I5vvl= 4˲-+L9pAqZ[xv~djUq63:qYZ)^ qaLǨc-kN"g 4s>h$pwo$҇v;]/ĒL{y5g hN'Upo'1-3{& td<61EV|^ ~6g7Ɲp.sA<0s= P닠plIrB˙/]L8CB<0e*6diWf8!˒i^M{|1Ϥ:xg=/#IiGt qҲa='?NE6dFrP 8'49/ak%AԼ<faԫɫudv9n H%;\5.hv69oBCiDPp| _/wNoNkŚGeyQg coxcd_t| ̟>:`r%fQË6k@.Mցʏr 6x;a"ɒA3%`eZlE(|椊V#QOһk|~§O#l?k;~B{OHֺф/~c~zM}\^=k}ڐ鬩z\/!c Уom6U~kCT~G[) xTݾg£կ(/fg%sJ{:7x:Gy<3KdƝʾ^o^`45s<|泠?4 ҼX6F7lƆǛG}SjcsW+xo,d̶.̫7sS.Xiz(61;fUz5g~O76ij|=bMzl_xhkm [@=ʟړ^.lXsJ lz0=d ?q*XZ_@ ^t[{齹 "w{đqIͭ{~\0qb;Y~{tԘTsj25&M<17pBą;4W =Ǭ}xW{/&@l&w8r p8պpfF6}#cHc6obnAw#:}BVk#{h]?Ѓ-^ }TKAe^ sΕͱp<;/9Shv?yW,C{Ѭn) "}H/;%b{/ܰtyG0tc~>^nHD^Ǫ$RpEϭ##c~cvx r5yi^wBkbPd]gX!9N%n /)V8ί<Bfv\ ܎5:p̹ ӓ AzNg'\w= y]c+%X'Wĭ\^u ^ky,E{[07Vp.P:*S#mKAVfKXżkqS\ÍF2frbwOuLظ/8` t ɷmÄ VWdAPlN8ݘ7p|E7"IÔIy c;ϗ#A|=ZX븽D3@77/ڋY<^=gO0g-=5<7tFgEpJg& )fx㺴fp:քd;apЋ-ZaκvA8;jl'.GfπY8,-h_Y8`Ŀ)?duND`t4#x4pc]^`gXo+C G2}LM󕖡{N4ZL4F7 WBoܐeQuPrR)k "Ƽ 7#v[^/iy @[?Q}n<_S׮юaJD~jubHn-kn?N`ΛՐ" 80:;ӌ)J#5:sY'v0:drnya9`\:??=U*5 X`aщHG2N)?DDk.WOɵ` ,_ $h*'vj9"2 Icxwr4Y7[,=cE+A8$ՖұKo~a&e<28y><$y3snН畱2Klxجp>'Dr6bڴƎPՙ€x!_hO"spc) 0}4"fpx֌GOx'`@M~G p~+?8:"׃Jwv(st6ӣYxYx<u"~=Xn ָ {?;KσoEP!.>ؼہGݠYh]6`uM|//h .do9z9lu:.!]pz O':!x@&DsNXxf{s}gﻣ2{نbOĉk|i4OkeXXiXN( >r-~rؖ 8ؖSqF,%5KđUxS>r^Soto\;'3Ԥq..hZSc461ĵ^pgEysZ(=y+x;5to I\9yS%9hXƫȿv׉iDӖ|DZ5xN47_GSWؗv>m. OVpFkst>4'gZ}9SkpL%mR;˛  1n.o`h[(`ZsY=3&m5$$5,7~X|NG+ǥV3Qqpվ+$wU-Av$32+ZK![kWobfMR\I=E8Kn}%(̸"]Y5d`|.sSk7&_g@̉Kϲ% CPd9ecMk=:SkǡR &˵ix@q/μr2t=́f_m|Ή>5,G#gԝ:d~fF(l)Jjd=E>v . k393c~߮L\,[HX~sc) *4g^84szFlK29&sF/.UNd֦{ato 's֜'Az <3[›,^ 6P[w 2mu |YrTo|Su&_,oIj;׊äqq}9'iڤHWw{ghsj!gQĩ%1z} QOM r]֩b7ŔF;^ hd 5G-WmG'b8>eVW1c1\ v.>WpszMC ÖogN-EWuod0Qn@2$s"ǡ$>g 'Nű<>7QzcuB;WsQv7!azpMцh'Xޒg=sȲt|ǏuƁu j:A~sjI=X_ߡ8rgk r^פHdžSieV7sPoɮ Gng<:&螝eKPK岦$N{s!69?n7.!3(ObYi+~8oZjn88}h:"Nf4KA%DqaM5̍;8DjwCje=[<~[PDx΍D"w zw5zV.%I߱~_}ڽٹpD:,zX)qн8p?ӌƻQ˶,0Z uz}OM0~GFyAu ˡPG>8*}!b] 6mmx/,ǔUQ?0"px8a5cٽ&k*#)\#IrKׁfsSim!=ڡ׸6͉X8t|Tnbwe=Π[/Y͎bXĕ{ N;3\0&_'] &zb͞^.TW8w14;߃'Ϳ!UFHշژ6q}6R]cVe,gK@bp}sNpt_c5Z8\wK|urDmJGFqs`)XNbNǿ?{-YGvWW=2lQJf')2rY=t99oL "JE h&GN6.X܀qG3:}4I`;b?=67a 9hnSΏ9P8DvjUzW!vDkmvG|N,gqk(h1zƆe0ZS5P&·(cn꫽l|)$ Ipow Gx`\_^*i!<Ήג/ *5쟻 zFHk ȕTGՑ)R+~xM H,wcԉg8M Ư^i#Pw7c9OxbD7O2,Oչס+QSWG%Su IDAT]m%yic3 Mhߞf4g6p=,uDxϺ6>P׹*;I Oð |=l6X-0u4$'\>~umia (IK yjf??3ùs{qӳX0aأstf' l=/הsC{̐k%}z' s>cռbg}"XN9c8ɣ'22BKpE 1@8 :{o@G4Vѓ8^"?[saI>?EBuksԛnծAI:O6` IJ1US |K %~4H'/`P|1Ik `=g5]C)4;kk۵ؗ|:|>Hd0jV+IrS# s45`6aNmvⷴޝ;-cÓ AG<րw%yҾ޿{ѯ[P:N,8Ll2n1:7Ç8-KqC&!p_M`u\nXݟ:eGXQcO{Zqd넥>)&5+˓jP=NRtz/Et|82ԒZ'O"%xМ#.Hk%_4dܚDaJqyO.g4W0K;t8Y6reZk~w$=GfޘYޠ≮GbiΠM^_:=dw&m| K0@-=q2\NG#ֆm5[]vJdQ6xqxWs@Y<ͥ>Yn!ǝLfˀ}(HOw=W!K걓S2.ܹV8x,{Jol[t_9[<סp0cw/}{y#՞jkspz&8:M;}:pj"Q{ >Y|5`b\7ߜEZѼ>ɋ1VQl>kj@'^abMjaa݊^Ǯ:Oߌw|։MyR @/c9Yfu*_aC}@GL6y{|41Q"C:Y5n|IUjOK^7<.];|e{/XgƱXCal_'&N·8} K+f'q֎c1y|1 tg ڟ>}9+y)7p/+$J9 ?L'43|I%tdˁZ/8$qo&-6Y3Pڝl  8^~֣glIx/yAؒ-ݯZp#;//^]dgx8&f֠L7wGƶ2}pד1V v|^*cL d7IW ^Szo<0ur&o%$R^qXˡ9Gz5TYc=4V ٗɍٱ6@9< //W~1"#? PԈ>o~0ȹr_'_=ȝaB!/e  yS.z뗚mKPDi9)^o6B)~Cls_Ơ'2gI.M o)\ѭu:H'&Nr54/)G\ДA³*+I>1w*Gq3[u\ n{zM%HD[x>Dѕ*a4Mc_L1oxWKYp<;s?u::l' ILdvZq[~{ꭓA ~<$/½{zJRpcHWiuZ^U#, \ZL#^`t!:xzhF8r`ϰӤgc7`Mmnr 6-\SNMA "z~nWqcRk}0GC!D~j{u r4ji,qƆ7#u̾׼%캝scFĮ73k(=u]uJfFn"Q0WȆ>YQͽ|ΖgrXЫINϏ&͸%Dh zX>p_w?<=zʈY^lO'bxF֫[ͧͧxǮn`'ku)CjJ*i ΃fv8>W4#AB[vq:vbù^q`w0z}\h),5GvbCdE}@c;kΈ`za/WPgU{{6OKOZgf> oz.G4i9O:>z^oouk(v(c0t$ЧD`7_4|k{>>pLK p쏬_|$h= nk\ui߅^r"Q6PSnMo$.=Ckrg"8_ۅ{bѰ3&$: 4Z㐦1ˊbCƠ>8w\g/3NTN{0gË;.|;Z);qō' SwռCA/G ,=GahNsg~\)-Ox{Ư5Nl?5sڦwvicLf| |ȿk\!CJ7T'lgfTYt]eDzﮮs -<_ c\ށFO3]üFNㇱbΗ"&ߘ˚p*L7_ F\IWDӔwz s>OW8m~NCZbU.410;ٳկz=Ef.$qGRwXC89>{Bas`{I;ap>.O|#*ߛ)9Vs/,Z"K3q|f~l2}bh,O";FG 70NJtO_j2FVձ@Yq^9y@+kJM4%rfzao-psbPQ6Y_^ +zeL ''oHȣޅ;.J7G}̥$~LGCAMxx(r,Nl VdwY^멉 5|lW$Pj[UvV7d{u$9 y!A#M4ւBmZ4 x=L}`ٽ 餾˻-Yޚ7vJky\(vͬZ=qc!Z;jѴ<;|Qu9̣MLZ12)ZޜˀoZ^kgObs= &u [^hm?grĔ [4̷M>BYsة!bDZXc-hʊ w^W{>ңa./CM\DR5 59N-m z=fVǓK0 t"֓㱣XM&rkbCk(su7_ajLkK|D}I4GgAO>2n?H O\j~I;m:H:H6@k8J/t|AGۤ(yQL1?a8ӳ kJoҧZZkzOcwgXtd-buz Qcl3``">Ez 98 GAx=@6 &#y+ߴ1PSbx{:nNa 6<߰ڄ=ׂ;VEzENSVLO5+˳6M.O&#֑//Jۋė edh'扵Ee;K888ivǐmy-\Y;q 4mŷ%G|6N?qw t8:uX./g"6%, 59rɠ2fA#~E\؛ \K !GN? ̟5 A}5nቋ&1AD)+[ƒш~Fp`"=HqmW;=дvf^eo+Oz+?ͽ|.xbόߜeƧ,{qV3f4X6(笍iغˎVXA LkIGyH{6 e>vr=3ŜZyl"wW_@М"=nvKs͐*Qep-HYCn;"O<' }'k"rZGz/#odolzwש&)''3}&ZHȟyRz/~ mI6R+/(]o ׀G/I''r%ȕK ~bڗmb\7Nl]#!ozg;I5@p9Hl>Jk'.CNY`C7rrr}_'7<,dcI]|28%Â4t& P&ͥ-~Ό,ZW]z[$.LiojVߨL hlb;5A0o^\1R2bBRӫZeXt>б^M/ &|=*Bc{Z^Jh,:7=Et0qMl^N:&>oncZ 6DY*&}M}3BSD^ذ9 3Z6Aiȏ3x:P@.>O&n3jvLN uOꄍ'O>.o1YwwBy_^}so]Z]m^ޛ}&FjmWZ -NmZV*]5%Ki rBΗ!.}v:JG g}a\{َ|ӣ9Moޭw&97+Hy >-Id伂\Zb!-D0ม1%n=AYr,Z&(thhLDȩh?' |I>.~al`q15y}3>џqJƑþ$?65B N?o_It'p|WMzӏpXqpd>s`;<1]wYNh(ΞPS_Ka߽\;\Wm_kt3Ϗ,FHo`8@yKJw7ׅcT3ٞ3k[_4GIL"8;38흓$MKGMc8q{=`ZH=iؽ?%G2Bj_Yio3)4#n jT9Uv%(̶lю{=ÒT%}Kh?Ҡ )p: >7gu g$ЖP 0Olνd8;GqVcknčp-UN0ZmN ӗlj˹ 7Ϙ\8rğJp'̶I},߷v{ɸ43U um-P3|?>>q "tc R@ qyCXhtp,p=dv~DKsSۡ>= 0pMZ ⿸ !0:4jbyx^QC:H,kBzXxvOP`;SkW)&4wguado= "ڰI~ }=kb'<\O̎;ևV۹4|P G̎uFi/ 3qq[,~=>T(C8}9jOpM$L>@^ kLDVPa&L}53]؅_"l8~:aM>n!SNwWE;xڲa'Ytidž}bJ-A/3:sqw ii ;'k.g?̓9LFa(Ӻ+PZU`Dqt`"8H~g\-?bKX<<6[ݭP6Ɵ,`y@9vxs>7 K;x۬ 6s]T|փ=$%F)|tkeX +ӾT^mGG4]_Lb=?<TQq IDATk0NZR:0bԍRa0Fp*3oWx)עp CN@DD?h{u_R8Ǚ;=?a k0{Q@c:Vf 2Gv5`Fj[#Ժ/aaƻ:3^s!Wq0ǖ3=nLPHP"ז qf*4#sXIlN$LsmaH<>1hӕ5g9=DѝgWH {B2F݋Ѿc3-5aN np8tz)X<0=\1HehcM,i}}򂋍UWy7hw 7/k8w< -ý{-Z"~\omc:TOt6pݡ.2pĐ;+yC @ P e3Z-IF) g4vr`GbC#Gbp燗搞Q07hnml. 5us`y0a%ẄޓIDNh s~`GV%'3XksNhИ~ߨEOL#L stM?:e|DoxsQv¿=89-kڦGSKjj:."a9Zq`r`2g/].ǁ H4.(|4+i| ϶uomOҍ})κ]sk&zЃ7TƲ^'LK1E3&j 1٭qE`˜ Eͬ7S,}phi!#=հe&?N a"L0@3lN\9Jhy]|/{'Xh&^՟}Op?Yۦ'>c9f} ~& qh0&mJMl~ o;,LEX {-[jآv=7봚Gɓg |:b {Zk(lͫ+7m ZY(Ā'[x/غaCƽ&<ef^MVs7qK4ٛO!.׮'A5`7!#y{yJ\xiHja9ςu9.lӁ[SCv-\ƒ#6NUig 3\ߣб r~ lr.ȁyc5zJX' EU,F,Ȍ>_cY/ ?Ҝ.864يay$K"GMN҇q2MɱhĉXNcq{ !u$ࡴ+"÷]n+t采e`q'qG{/=}XvZ72 pf߸?Ƈ =:psTOI^3X#g.Pk11;fS}z> [Z˽7+MoGQDr0hGMwcXpx#. G0=!ci{ H/Ըnى=f^]a҇͒%c|Uhxw,?oiL?3^x^.js|'k?C_,:|j%Цk>:``M7.lE,,"NC0FM[]V|.䛃8 -|ʗ.pX ٥a? ~qyl<7L+萈>.[AO=u:p>+j0lJ#f= "ou7<. p>~n’ x 7VY;nw{ {\DISh`PaL^251FskQFL,|`'94|=+k)cKȆK`_K ~1i ?,3نŹ怄t?Ycgh~IG"rc0{@t189O v?6"'>_ew10?< 9|}dr#x^L:\l0j=p>ΐ]ϺܥHb=\ɿ##}@|cffj?bO@5O= &ͬzB|3>a1T=>i c,z#4RXѕ _4q>v7fSk]ϼ u /r?Pio\nqن\*A2Zl?[-Tᐭo);86_c\'I<uQ7zW͙V*{F\p7^քH|o13ܤ?wgm\낙76_Ⰶ'O܉JC04w7 4 SV3p;6k;AsvWω#%!^O ޼aj^& = ۸o1a_!뮿2 sO'7v+…"һ[WO @^f^8G5 |xѱ o=;L 3)j 㺔Dag>C;pG4˜oHna|Y[c@[\h7J*2DJQwusAo wx@;Qy.Jr J悢o58KNpf`|92^agNc 86v.quN7vwll:?79:ȌpwI^+슨4XqJSlo|[\|9Eՠir,b30W=vUL.?F0Y8qu\91ypÎN\Cr9%hY{ԇ'>|Dy(ebYhkIV9fs$P9ͅKtFk5{|A/Ø|X;p-[2␸4|5k=3Uu%q 0-Obo"[ = O=q\(oa@ȿ8ť75.Г2؛6{l ZC|֭U8w}p-.Y(mp2#*LSb5d:1N_-k9'X񹧂CGrрqiSa듙 5|j9}ίiAC>ŭ/2ҀbUm^fXkWc* Bv8AL70=d{pCZ늞4EX9-sz }aE$%1]PFnkxf֜#=Gٶ7mo S D ziNѫsոՂu$/߼nh!|8O/V ptL[\'S?<&tzeLEW2(㳛,)Jܕ+ɫأֽ ?t<~d#w^DfOX0XUu| EG3Ee0" ucy4;65_K^l}aQGZ=Ldz4g<|{xe _]OS~X#{x̥y z[|G7{Fuy79D!4OGb vˇ%jpN\ÈKvWw~Xpi7"Ex Z{RmݫM ~kw,N;dd~}?E|53j/iӃăzhTJҌ;)_Gؤ\G?oL6q)' )1>n*CgN/92Uؒ- gK !n6+XzɑќÞ>|Qّ_T,խr~ͩsOd3y ҮO^=4ж\Vr2'sks_)Hlok; fp΍~Ǘrx6vstlx6wFjOb4_rp(t9ɿXV 3#92;]f_ԞrM,9kZPޯ^I*!fZsڟ0^5&or?ŗı~K`i DVN+GlM'My9q͟/LGcmwRwdҁ:<ž|6;0?5gvN9Mj'/Ǝ+ׁxiцzB֌ycXvx.fKBC3 .`#6 /&r (aX1֠<2lGq77p?.4 'oqdJ8Xt@[9Kq&cگ'z6 rN^ $89=+~{8dO= cv-YǾvĨptFqh82%:ZEM4 ݓq ήT vb~<7Ɓri݇4ՁĶQ\ouG::+/k!3~ j$$ۘ?oZw=QJ_a>31WͼdGrNm짶DUoX^gtCɛ=k|xvQ>A?$A/־\rL"'ka^Os\Vݵ$ a2y|먃:ϛix8Ĺ.WK$AppX~׍ 8Cl狃81ѯk}lnkZo&g9VÕhB}ܓk)75iZM8>xb5z4 U"`~gp^q4 vkrh ǫkj['7O"4)ɣäycݽ'&9>)l\&g,#NCBڑ›h}V^I}mcPOXs gL4B[>cV3~ ^ d1&* =U|,#%CC"^7\-~8!`G\b+6k;}~2T'-7[[6Nu WqpՐ7=UzB޼0#㱶Z/?Zp.q'Cx@ ?Y[*PkK`K<$3aln⁆Ur{8G(t4@6޼ЕŭŊI|m@uGbo;RVf3>Eؽ,MP;Ǟkd}$Qr5b:K.ZW@5 [rN,67$Q;gfle϶K,˛—!SXGvbqN&5=:plpm@oq=X~sX@}w!k4܏8Jc+4|<I7/N Br2pV%H=#y`0  -:a uNJ8v՟^kC=L %nUԊ}}><ɉ&c_Nlµ 72 "t?~ /x-:?[9y.Ir9 IDATܨ+uZ&Izzm'}~(r٬YiFZu7vJ5: 88\= +k0`s4|n[|?Fא4YG'N ~8mxq r15E$b2wG SWWh^Gl zmIBm 낭h@퍞$_xpZ-L'7ֻ#/sk:dq@>yˬg82lq.rW?Q Kp̢Zg9lw@K,)>k( ]:\ _h YzTR=-  |l<p?I(c v5UZ6s' cvgIo^0b[vʚ$O tiƳ˸ld0-_`pC3$j0L'2+)/pMhp軶τ>(n=V-}$6'v vz|1a~Xx?4u8xz;Y̚6@vْۋje%fd TDj5 kds ,d~ #Z5`bQh}TS| ǡwNLZ<+2N [GOz5q|ׇ.[e7kuc9g;fr5{OWji?N?|{j<\1lƣO9KDNP#qoY{Kk ?o0*}ӕɠY^k;z289yVvS17ǹ> %##Y*ZG7"zOO{Fhz`A>}q~ v|+kt#}zp;brR:mWG@{#'\ۓw#5\IZ?` e6q֨Lo̡k:`q$m,q9Qg8n\ٗVlz'}U>$cƶW&]]djne^5ut6v8-`y;/føNLU]p 26rf[Hĺr4܇<3X;Lz59M¡'3 pp^piW_cZۆjr968g-&<]1nD'Ȥ@ "lŲ~mPD^Duxo+)D S+g'w l>"s0+ګ]I7?oʪLOZ `1tz-uc@}#ki'֣_ 'Y3.G9"ǟȠeoNKLC{{z ;zp/!u r}ZC}_K 9>!¬͂ybq%e3qWtX3t۱MڋV?:Oƹz}7y&!h^oreqMPH\PA~J#$tnj.*pSB3Nj,zW#H;@/ b﷖GqN7[65v8FzM;Md钷װ .YI'Dq`9792XrxMua(oB(ji9Q}9?@Â=|5;^'?8#z'ȵP:5ǟZSw@kZJ Nwb>P{=BΈ6*O#+OY1\SJKFmӲdE2+w,~g`Y+}'@-o -Edi֫sʃXtO>dL4P'KMD?lEMSeY#O: 7 qΘW7CgbS`s9/ࡩmM1gI5d_5`Mcn DiNO bu5C"MOqיx{{o P.8=<~g&uG91_9 8:Al<~y9b4slU|5L01LrpCz/F} l 26Ws߰xɆZͧ o=kNǷEr9O_Ϧ{/vH3}fM8ٖy:X,ᛯ1a6蕶t?.GAN lŰE >@0^>Y?:\GsN>N 0U߯Y(Tf9cGt|cÏ尞 Z㣭QjVb|d9qЏS&Z.(zCƦ'u3-kva֑~9_HC\uUHԷĻ8cD6LoH'7c ILÉ}aűei )OM"{Y% 7yun|xbB<< ~p1^\8"li?Vo4`N3&'{Вǁť'DzxGs\Eu~mez,g>SG:WM g=UƓ@4e4Bz8TWB՗kAPfcѹ BSMaNcXk|uY|CֶNpomJd%>uboB]p&pZb5cEFuM_bP/~>|_DH_m7Ih5t1=_l;f`mQ=|p&NGgh7!$ؖSᐘIUQB}9}NccAƈ?86~OFɾor֗ݐN/6&C uuAXQϐG[;5g/k`Z݌O?7E;79bሶX84oD8|ؽF'kiNh휠ᰯ}.7?\Z ⬇ }L?; PIyZlMzK$< 8.=(X޷~͗ )X̞߬xLc5gGVå#K;coXjL,Б} F|K; W+d-Vt0Fڋ((ևLbaٰE}E5Q׆5T7Xfp3kq^ze Rrl}G2L&R:>+k \"<<<+d9wgy~N*OA'SiiڲWc+H; kb0 B]V_])#ޣwyjOfN)˅2zdeo=47gU@GQvWl>s_ kˁ/NsOK?7\>_#(ބ<I>rs&qubp)mދ}0[rC @~Dt#XXz]!>͓j 7/ěQXd4YSrD ;FWᤘ s4Fch} N,%ވxvjZ$f5_ɉ['%;+1ټ$lGGWyC#kZ_q/sik/~ڦ[Lp98ٞa9F3|7g\`:ࣨ+F[->5 dguk3ką|?y{R*}a*4/csM8g5_1% ٦|xY>U'`#+oICVn"6o2$ sk6U/DS5aH6ZFVjZ`7,|ߏi#9L[7[czXMzD|}%w0K$w-z6 SVb3 9ml4(}eK&{;^o.ןsc a^ƹo0Ak]1k F^m8?5._4R !M؄y~6=p'Zߵ簚* p5Ρ^ƧrFVK.YC"au31V'Oꮭ4\0pǓ\.)+ٟE]ӉYS]7N2tA!ДS{4çԳrL#DN8'}4;.u3\Ub`][v/ !>S7.oSDx em ]G -c{oikO_Dz5z)_꼇ќzMdy "ԭ^Ăf/ɖ.jR=|2 ׹3ɵbD̿_o/40Ş3~NfFMr);kǣ|#z5bzR58ò>5:򠃚- ![FlKӖL%'|yzHՔ>#jl.?ؑ|'Qؽ>u"ɗo!ʖ^ R S_i suzyT0D`2 k#Î*js#o%/MQ .́K룧SWiXt'kn_64֡HNl?! -;hѓXV]gZqÑ]5"VOα$5ȦY簚zWՊ5g_5N ;qr7_[ZTƅ~l=(܃q~>Ep{@{xįbu{E]$lܺȜ(́lX5r.o(?S'q t<NJy+\ob j,ŀMO+ssW7{D3xԎtH󱮷{v앿UCFzu9 Jzi/D<}ͯmOqɢ˧>}F#` 6v õ_.cN㛿D|j\ tud{/q۱Xkp5|+pK-&MuhQ70%5_"L|ZounQ۬nm5V*pU$Aw/':0s>Y`l=rG{M0u's_Эz~QDuAN:2~, GM߸#\CqH`m;d#:.MV` Z4D ~* ceL.$9w WV ^Ja6ni"ǜT1L!9:/dLDsYvw<}ѷFK#Sů!"J|"GzA- z}?\?㪕;H~<(b3mb_H3m[N'*}}%^&n*Hr?y9ࣆӿw.7.*5+#q0KݳqO"9_I8 {kAN_]gQp6Wrs|=Qos x3Mf=rb=8>}lB0$1#}gIg˹朇¸(꒧iz0b:sWBK US=ǚZևצ:1&;8o5*6`g`܋?[|/t܊'74H_;Iܘsٿ:X+6cYJ2?ֈHd8hy]a|x3rv7O8id'ïeDWϿ_ws ̇,;us←IhӴhu1 .ibC.= ˂s8cC}' ͂tBI8r:yboR ae ̓& ׆yِs2册`Z8g)h v:s`sB:ZC"p>FLqf9KicX3 gߜ=xjsg^d IDATi̢>P;3WO"x=6WY{jkmr(f/kZ]yv_N˸XQE#~2:8r9Z3sykǜxVJi#Yxx6 ^-8y0aCbF01樛 ?]/.kg|ʲ}\b4kh}gwōpaq PG!m]3ؽ#Hfs!>oىOP_*ΣΕA.SDMsd_2P|xNCks¥f{ZՕ}vy0'q=}Ac!biؗ㘝S>8g~ _12Rx0"spѳ37Bd3KK W뇠~M>X33Pz?@9gm5P-wp-{{Ic.0徛\ xW V=I˵ 15T;`W(gxI   ˆx< {'QG ^0;|NQ{4GbҵBy{z!8($6:[ucr} . /KLg8統*-kr7߽'HO|,r2N œ0"r{aF#R=4Ws~{l4$V` ۴F٠ڎ Ke؟&? C@.z 8ڃ!D>5'+u|B]8@yzA9\-#fYpF7)aV9+v׵f޳'^7v>)I@<ٳpݤo|v+1b+b;3}QJgԻa\&Loq8#}1W8ΛΏc!u$q/ԑq6n IFkspĬ'icԴX!`#_|P1'o^,٘ϩ7c ?GvqH%R0kfB냫m$`_)귴GHHݛaU⬘mr*1hA7;^}c|?<zcy/lWSxz'g!W5(ŋ{` Uͽ8\ˈѴ?rYQ+ңZIgz ,L={>8zJ3O!5 |]x zK+Wj Hy".OKrK_;v_gaҗDOfzZzEDQ]~8I5p%{&؏ >;u%.lƞ:o5gr93g}z~Ҿqsg܏Y` w5Z{~} o4poV{W{Z.fJ ; '{Eڗz#hqj.6UɴOq$?d﹙\@Ɖy] xm>c6󳲶.ˣ+uAj7r&Rc|hLdJ4}]_hެwGQ } 9|+&z\d_{ lwf^u79}\imin%Ԑ)JV.?aev8W}'SOa= ka~/8~B#7ѸfM?iAo`i7Ͳ/xGRoںOUgZ}&u P;ihHOB&߮hp?4GnksFx:zj&=0?1>ϔyq/>'Aچ43$-szsx.[F149ӣ ԶހǛ'Eyqx5=9B6OKuq>~c >3_

>J/Wh_Ӄk(`?5h\Q<;->ӡoEZj0ds: $}xbn_ 3g|~7ynt~%' 銞2Y"y{%[bs?@I;"G5>}=-3\?y,$+wtrb^'i./\&tr'w'or⿹,S-i0QI=u=Hu/̓s |~9M-^4BDN軿Z_ڂ׆Ҹhˠ?y5\D! Oݜw9|&5y8ϺWL?ϩN-kj]FPYfiCx_][Tv57G717_Nl4 U<㛩ӏ{ع 76x>^,^|@Η5z90Aa$MkZyztL(PƎ6>ц|`kR;hcc:À7{4M7B;5ó(׹fJW(r4IǿݝU:;$ #d 1o܌ Z?_51oܫu#ﻐ7K-ñRxM\\\_oӣ_;)nzwo2DOFDTgEӾVb6[CwUDr(J.;5'ax|n a|sb}/;\{akC|7Mi0|Sb.f tu!>ZJ,96cz|Q\[3Is]z{8s֟M^N +[r:^}\`k~g~<6si|snlB5<#|Ơr7]5^ܥWP\߾[WpooFu8yX`.YhsO td+abJ[\|!WRSf$ݘrR}K |cփ7X;QMįݱw›<*} |Y5~:[2!5#0e}KIE`A*rI/H~O|| &{xֳxZ0Tzf/NSeO3;HƧ'{5:@恗#92ܛj9B3Q%**DG'OqS;m'"xmf?eGј|qa9rGk|a/Bía<6cD,'a<y9w۶io y{^YfUG쎎%|Ͻw~Qp $,؜j#0"- . Fl"R8L 0h13t&Jo^xy(z3~`O 旁'?~cX/v.,Xm(>]6cB3atN[r7cZSCetc,3A>jN@8b''qw^ ˛9}kqf@5Ti}:6[y%xNNfoՊʽ[f= 0k<WrvZO-9^xs/K2P3=(?v8An.`lx}r) _;X.j?eJ݉C_p CL\Fzl\KHA:ᓫ@aV{50^ 0t'`ej.Cm4-}&]ZL]s}Fw9Mc"{ ,ښAXly:Iv#6&/D&V{ĩ;5Z sC?gcr^Ɂ5_ߌdd~K{1o,gUhWȘ=K틿uξ%B(yn5HΈGrye#a35=7$WD)\u-橊6E]xL<53?),zzOJ8?;o3~hosxXZQ{Л֢Ǹd8@Cz=Gx;|,r/d'N䚈o/\\hl9YG4o=j% ~ Sնg [hWW:t'Lݚz[ tk|b|je=bܸ͎X#v%Š3dT !aK85R}Q!yM|?<')ǻ?C~9a♏ fD`#݋>anT@?=7[#i0>`o ѽ2<c@|^k7?߼9r?NnjW3=r1O{D~jqxfx9`]ND[C7k{ GOM ڬeZq>rۓ[֟SGXA-~1d i?%8_#X s9) ͝ BAἢkx_%zX@s`c{ȭGhy/W>MZt wr+#I9Ս~GOSeCۏoAf\j^k42+Ftk)"xtmqBMitWEȝcA4]{,gK~r?~ߟ!X;I_Rb!Ϣh 4&1Vy8O!>?0 Qcm1_{AQؓ['$WrǴM͗؛> 2&}s-:RlNf1&{t鼃i^_cn,ifump;\jl#Jˇ;Ŧ7:!vތHr19s6?L<[Lf K4>6#s!~pb IDATy6K5Qs?bhC _5-UOhPf{'^(msm9P!d״KR ,Ӷ >]!TOG$*h "r$b,Wgߍ{4Xؒ#W5p̅g֌m9V{p=zVW{PCᶦLg$0=oϒ{G\}x_}G}?:ĭ@65dM#aYsmps`CΏO9 ړO^s{] $<8~:2߃s?ye;\E}0^iOlѩ_Si@"o8l|&x/V` =ln| tp60nrHIkbd6G 9a|p>QL?pɔxluތ{j 7M0~|=vܫCXY:!.ݜD/lVIfcgXӜѹӹyp=q`gC-;Go+7&?.(eMf,88vbn Iζ&@ .uV_|>wc=:IևuPq.{sԭ>0ͽe͌Nk Pk?p#"'ά`1kT`er-Zm>pqFa.6"4Ov|Rn>v>za+Uz3z>NCi<%ϫKT58i,G6ơos6%Ƈx̧q~M?x1ZO#v?t oJ!qX5yr4lQ9t̴=FM+'I ;^^|zDOX[oy~mCb#-`;db..w$O`!]}%'QߜϜ܎yxfۜ<5И<|`N`اt ula5y.yXkAөCoǀ`O!7uE qk=>\ѿ[`g/8=0o]\Y!mɒ@IJ?h$=ePoΨ1;sc-rm/|iJr:xa!'ge쬳\0F_1ɘڗ%X@Φ3]9LkeXdyo%/L;}Op,Ƒ5jKl?/$˽XKb:4"J.(EvC"W9lYD6]%5M0Yw6sG# L^Er̈́5G#{Y|V` ^[wh+s5ut l&='gI:=p3Н,uDv7H ob1+!Idj'=㇈ZfU¹ZO'GrY_jʘ*恿[ •,]_Ue8bJcQhlӑn\Vߴyeq8K'8vSKX[ׇwc&x43~`~bpO|V9c5{>Oq<MlwsBb[Y>Bl/2aW\b;۳t7!uZ.gAkP[ŃypyZzܗﰃyqLZnb Zhs@yc~Vb7|Ŵr?}=)p,9dR%7wY&u.[zRѢц/قY>Qmn Xz'ۙs0?:r9Ǡ쯯X;i',, .:L 2Er]Qw%cct}?]5OɃfX`:dlly v0ga|mDWu0q)1 \ۂQ Wϙ/PQ c>~2/ Uؒ*8o\4;?ET ?4pv:0{P|ν7a;{i$-ҵ䟪Qol^^I\zr.a` _lyc5v-7z=&0Af4jmE\&v~r9 "n$olְ=ro/UlQriv]үN$+卫iMj MKve,<ئNV/au5+(Y1sڼ{xO`$&xsxA=8ap:B3`Հ7 apZX4`ME H/ ٦/G(֚06Ü٢*6nbabMVShp4u'Xlhڌy&y.0Ces2jYp '6ҪHO}8ZfPvv4+˸d=R7PHpጪ1\P~-^3\;?[ s&V }1]/ǢvDƘ(FAk(/3y ֜Ϻwfr?7c@sW^^:%tLpm#P.睨FN V%fr8S1wG#;sL{6pmv˽ lڸK̸01S*Գz }뇮|:CuNxozv|9 u7ةK9kYܸrhFT+>LBy3r[Zo{>E]~3u>o:Y2op:̄f+̍],[6;=W|8~ ,ӥ /wub`!eQ' WxI"AO"]d|rA/RS\Ya9aYhשqZsuٔu᷏ ŤWuvڋ7nS'=٥,T_1 y{iakM"r}@lpԣ!{h q,9*=| ZJ[xFjcj;/Q|qo\:8'r9_0gӊ] IDrZj܁fN`#'zIءĖX(r^J=XGDZDC+d7Ur p1g4>J4#^.c6>-?0"G?|jV/68gc ᠸDwUi}bـ,=zZ^7 th~HJԥ/(f(wB$Z}o %r\;1'哞\\WoRz{@k c\lQ| h`~i'dt`ػu4s<|AxPPmuӃ)ղX h_8A澲Ꙗa Yi?O?R쾵Fn6\G{|n,?3'> 3$֑UYS\%RDÿ0_ EfI붆r{X,73cP6Vπr^u%|JW}c|5\˜|[Knl41I܂uI d?;|t0EW 6`f}x#X>djc5*)Ʌ" -QlqsSunŒ|օ"bg"58d/Ezzu+Irg9M:r#Z#fj2,;cu y\h8}cc5cg$6|~:ʹ+hT|d+UgL/ "#ymJ܍܊x KN5[<ŵ&!{Y1уhQe )uغdEG 3{Y!:F{'ٳ^6sML3J˜(f4m,D'<L#Q{=v'&Wb7wm}˜r6`<7嫉Xr3d矬Kҵ)ƻ RCv`fkgF:+ڠZN_ߙVm› 3xY?,V0wK̙U0 Ɖ~rM|쓊謐󆜽ԇ_yX׉P0W,uJFy4= aơ10xC9 #1ZzߵAx3vXm¨E.'uq1 7{`w Kr1/3̊N+7Mxl#~qeg5sb+f[ ! 7H%ʋN Øڜ^]d r$_RxOTOiŒ=4V̸2@ŽלXg3bua}ks^Ĺp0mOkvԁh9)JB q/l5LNt f88s( {r $wb.ϐ[ms15n[6?vi[q9#L<,b'{rT{zѳ޾Mߒ2)8DZδ)kͯوsv!5Y2* Ҳ80;lۛVKgϋ_ަ(#a $)i~)o8vkю֥Y=|kJ^sY7]s WïO-h6k)3ܧ&n:|>aS{=`iǩ\ʌ ~Z9q1pňn 93K[7Ʒsh*bk;xaY[By>1csh]jZ$z  =05ar/wr߽r'1䡪7Ϻ>;eŠ_}6'<[b4`(?[DyZwbK&p%V!qNMC=?a5ʔ?(px|]yrM(YJ?X<@iNłc>=ހ-޽Oai~ Ӄj$ ˏ\ghN`&>c\Q ׏L殦ؕs WRh0~^:֗˳$Ԩ}g<^3gA&VAp!׋s.i#;k3χf7ƅɓ:0'eth - `/X5 OAQ 6s:O~ ں˵ay.L'XO"o|{='~Ws_1>O{'aOb5k<ͪo+Ȅuye`^,% FDM\f.YkkYa o553fjm`j°:FoTjgbn 1tj} v\`ٞa Ciqnfi/ghsG;M kDyف~SP}H_Sa$r8g˱H{}.g?y#'#_e IDATj?nNsͣ"&7FFH-+QZ=2n67,Px=;Íܫ͘N]. q_9@| W5uD7yڡ8:FlJ#Yi]8>Oy ^9<}AأAqM. H/ gs <3 :Rz ݥ^#?d~ZFƽ,`e%k=7j gR]kؓ dfc;:؃puYB19 3φe9^=a5,LpB wx!􌏌>{p(n}H NA>gјK>wWp 2x_]=aBǓ>I񚛸T|szj&߼sYWO9|ڼg}}/2' _  n7 "efv/+gB C?'Ib5sh xrvyv`ʈz#_./BDYW)樳O?yz0= ?Z68`C#1%Nit?{uoͽoBq.Y3{12b&5pphF-3ѰZ d:Ŵ75/h<imMu܍ΰR~YlH 4LcCț?/u֦uj1B8c^Vlvp:Kۇ1whD|ι>UܩW>E =wqflhfl)?{N kXa<nfE9epM'#LJCg\;?\¤>wY8+9W]lV'e.-@/-Rz&n3$lxh .{Z6Aap.X^KP?5Id9&9x+ mšԸqr$W דX:@}M <לhcY.?5meecⱘ<ԕC>t[k)=gDl-VC`7]{g~σ!=tƋD1][S~lmRQR-,ۏ GL챟@O'lrxxj\GCr9_D4o/j6wx)AĊjŕwM^`&ϱ3kXrӉ3Nm;:"T|Y]C\Kݸ̄|@ǩ{%esGL?5pv ʽQj-S5|ZcE@[Dwpd7Lut2?􉮸j'9{g"hbn xrV4Ӗ*v[dBӶ/~AGy[d\EظZ_[n/nX [ŰXoQ~_&Ȫ$&-fɼ{ :^GljNs]˔)M781/,1wO>%Nʿ> o =_=0漲`UVsǜ8L G3ׇ q-<}"lHlM NI5CHwMOG^_!lR NP~jV O_/k MMy1萫be^tiZҞ_.e75ȳ\_`$3;;'i9ny>Ws9>LC|`}~-^FJĭ PPs=O /} 5N8O|zGA ӈqi}gX_.d)|EP<AOr[7а^S5|`փS6fXCK1ms%!iA&YĝW3Dk7;~:}VW'ӫ۞8>@'[|uK+i?ov!T}5أmǠs6y_0t||P|<Ձ="ɹṡ;X&b~r5>MOBI 㢱V7Kr8T޸:͠$G)Dg΃)WزiXqz|2*byP>E: ۯ:g_<> LJ]]z0~~&m4\Ǽ;^+wsU.MTsC%&}ބ8{ƕڌ1Kh/5t*Yu'~'ѺBNO-ۚUd1;rBC6'Ni,:<سr\ռÙ@,u4ɑ:b"ox>tñD-L;eA+()v~v;OſVCh쁲?qLp K]c;_ 9o~#ڸwbΟ١>)_G1e^>PQEMj뾐EaKtF;{kSWZ ?`OeڢLs`(Ϭ}[& ucw}3ʏmK,|_8pX>\&;8˞ϩՁ6Xhd/|m^=aO| ҫ<*YN{>WWd}~T4ؔo΀by遣 .xXޑ=uO a{j:Q "m tL*(}#ԼdQvkU>PnTSpZeGh xz6]Lp5uwYΛD^F᯻BdKݩlK}SBЭհxN*@s>16Nbe\,Xn-8M>kD0_ܟi2e#>:YӵNyOll8V$,D:kBzɇ뽀a8noa'ǼBş=m[.Ö@dG"sfG>S0fV5}AWҚy<+|ۚ}%g}[kQrC5Ph]@k|ZkQ g$͖}H#} 6qpZOpֶ`1hS\ٯw p BϦz5[gG8O k0 4@^u/z-ODzM? 3b10z< /aqi+hhoZ-t /vՓk.c!cjy; B~lD.zP]ac l٧8swzlFq^F(zS ?&@a;6Q*8W4NZ-s}@VӟaN~u 뾭H@^ͭSs{[9C$Q\Ė.UTqi?4`y+5f_ȮVS2뜶|&|Zn[rϒVzNѻ{I#G@e|kyw1s6Myoa1RfZ9܇Ye?si"cz6k5>.ᄄr$'O׹hDZ|CRH *;$Nޱqj}Fep$+\I:u(U}HoB^_sxj×Yθ>95&l Vzvr|')Wcf(=\%z8bUKRj>*0]Gld w xޏ9D B%l<_L{s,mYK8y!/\ z+Kdn&s.,W5W;!4CWH[3#!~ g8=) gsSPdaQ!"KM#rit"ï^0Gս4>~̧XM똜,p,@ gR{PDTޛlkQ^8IjΆP8`ثA?$SA"Bi^& 5O8H&xX/Pu-ͳm7,6CkоS¡7ySCeڳfi. _Bfvh#>ZI~5ooLzgE#{Yp8ֹ$hm6̻"V{$w9^7gm@ŗǎsd:;Wyp^Nt 8sd}ͳ;ƀ7(ߵ>I<miAX>ϞٽgJ¬92. b|Vc9-'[(wl=``k &eg\'%HXnkyr^ o7e ,Nknz,i(gA%X3;1~XU>8ȍ* *[i0x6#M,gs4\?{)/r^Nq (8g%2lam 撛NdNnMΦRYE% |hI@+z;8DmvɊA͞5SFt02f㲸 PJ h:3sKJ)rC l%A`A,#K/V[>SY,un!z穩9yϙF`:sVdC%~ﲿkOW0pq|Ȱ8kGWz#o|\8XBs̺nX,N-f;VПUQs~/풞!&[ 4i={,o<"j~Q_e tz!9Pyͳ\i./6]<&xȗPpcn]b~5L]A9ro~&B9K}|I36<`k1А@?N\jQ 2%%NNkܟ{ZnLt.خD c8\3]OAy[k>|.\\"pt[s缿[SR-p)^r0;k2,=؇<ݘt'*?x`cV%ȍ.+<휅7&w" ?csղʩ_hZs~^ #S-mN |@h4-9Qܚv;=Ē'-:rZO{=E8?D 3iW9Ž?xY>&hYf t Y8V s|jL[y 4$Lcׇ9d)M@/c_rrjB'ՙ ^`MSp}~uQrO$ Ozu'z~}ȏO?s*\_>bk'+5j(00Nx2q[M!DfYTD/kx@QefNx=3<4aZݓqgs4!ޣ+\qzZڣSrtԫ;zm b[T݆C~m!VJO9?q%uG=yؽc}oLmmEP1%c9thGʽPp˻G~p^n4'ŗ9I^xf#9`/j|KC]fÝLW҇3bm[WyR ?͛B(kB{4>fܞ0n~lMIN` b̽Yz[Ð%g]82'<?ܞdK|m&굟d9dvrmj vDOL)>BsXuSW5v0g-Ř[/a/;5/#XY^ GĜbp'0jnk~кn(kðSmJ8fʽIO9V\ݠՅkj4.eX?d6[SX8_'.u9{3y9zJf@''% |/=U擰~6*`VjC#!x#)o\?u|H~5V+QEr$xͷLgL78np&F/9: xł{@s_ oJŎy&많ݺLp~IEǀ\[iu]kW`|`գ<~veo}EŬOի+|Ֆ6;YꨜR;k{:zt^W1͎5`X $A2C[m>OuzȉE cwWVyм'?NK0ɀ"[ttyE-Cbο2Md IЎ\8]m5X0te J0󝡞'=׽aN6S IDAT+N{_ ۈuDø :ФaH(gou2ݽ/r_?r/>z f9AkWv8GZ⏮h0 ij>, 4.|s['=3'fb7gKUz8A_sܛv8 KOFbijh3+o}JŊDa{v¼'GdYO圩T*s*ꎾ]NmNtrvr9|ê6İy>#T arf\L$O}ĹߠH=Ts^D<62=/ԒxfU'k|"|wjo| e;3\ :쪟-{~5vGMOvg@Z]?tnGriB<9ёڣg@NJ"ssH6pn_3r꽆'_ns7zzpۭ,3;{JNb'8`aZNMc:W*e)|a}uz.|c"x_MOZ.%7 yI%={v z6L54=gw=xB.c1|`BgFЫ63=w;kÈ~jhgffs>1tc+ lÔ(vE)J7D{$9 \Q5>TNgi<3K*9elAt[\\V98;Ċ35EK-Vm{{o&p3lZj}>kID0YR)NN?8ŭur6a5M\?9R)~Źagɡ\yiz/7ۋ'`Pe7Y w4Kj ۇ/>ڿ+*`tT}˿ٻ45&6+[ącs=$υn۫gXU裡@C؜3'tNly'<#]_RGo0ė'Lp3̏Wo2-kb)ؚ3PN }㲡gl-TWMD,-H{Zq8h$; 3k{pþhl8}oߛ\hnӧEzd/pɔA9=Q>@ m[M1a}|Ϝ.+s 74:"_MuxSL}4C R%vxpJ̵Ygۍt/6-7|{n6)M[w%}܎#ƾBȮm'T<9yO7'Кc\茊/vMnQy 7'Z{syŸ :sKfk=v6~|ϊY`kU{O^'(uLTӺN,} IoY7"6%փtoiͼe)}x␋~hHB-\, ZY?#x4fn?ea8ݵf7uuv_Wja8!Yۭ99n9}4¼>J秷~YS6UWMW\o@`l rꆆgt |/rQ.vUFkPiuDQ~.T 3"6J k+h"=䆔Q~3_ip-a|ԩϮ̇n(y6# p6Y1N;3JgzD~H$N4!}2]ˌ/XhyS)93;yu8i7|ߛi֖2i63Z|zolڂ1? S3rW?m|t ,!bJrMR|VaQef>O0pwj){}%s`_>mt-4@浡cpIJTr_]'czYVձ耇 yjCb ͳXVtGѭD\KHG|2ǫ_b呇Ey<5-wm![eQgs-0 'ƙ#~!sHbmyrbMk,{||3vNMI Q(S7}gwΙb3[PR cq\~y|CMNzrȓܘz_*{J~$:'ÐۜGJcbi9=\Sec7eu9Ɣ|ꥍf3/5W_:\-i[wv5ɬkgbp ѱw\u{4㫹ub!t,SzӰڋSH N&c1bx7w;t3|}~>^r;z8y} G0ӽ?3$߯&rgG^@3ZpW//|sZ?קivIb>=La//+놻;Y?R`ׇP9̩~m=5~ق֡ S;|)ksfK{o?.`N_OڦS3R GSl4&gxQF02쓛 H<˥$is硜$Hg+OԎj]!57}9wFWfjs:C!Dqp8>*Nk[ki Y*<`/:n^ߥ7/k/[D(Zr[,}8L%ى?J7+MH0Z}ȡԣq=ԥ357B9t=XXr{=$ Eο<8G2SA#e.>. ~=$v%Z9el<F4_ G;7H8Nd>G_=MlZ}x2(s,Ct9m<6I^1-dnN8SVGޛ9c_; h޸eN(E 1U&k;Ji*uYiԛJvcZ]Tt_) qFcCPz9-V݃,:/F8>>gU=ƭh7Vޚd&[.8v=yӷ sz(o*S)sI}\́j 'Q{Cݿ7ƳnV'_N4r.wO({/:Jgӿ&ѱ%@OiO Pjw0̡qw N)ԀyP~Alܓ&Vr サrM@߃u΃u?zr9\7NFyp*fuY=BWǢQ#qM>ouu{솩]q\k7!B~uJutNkEph?Yycۍ e|0=W4}^2lPpb?۞1:vHfPzLaс5OZz|;3#S^_yC PWǎcI qnla?Q/|hI:u\~z8}X.s$*䐮 oh6>aYÝ;uNM3s {?Z|M/h^qp0}7$Y͎/uJwdp\~X_ȶ)yZϚ.ũNV]mQi$!"&6W:7%"Oc*Uzu;Eb6$o8OVlBJbS&9Т{C?u8 @ÜFˋrMkȶr8^eWY:t 3'n'p?t$|*4uS0eú3l[֠׃/Dd a]'ЖVl+*4j޾(sGLW@sU kD}_,[gN-(Q/. I#Gi#";$,7$$sSӰәps8\_&<spsFx@,O}5Qa,fE:FYS\m5'D[bIȼKK橙yGgPC`_-dwsl뚃Kr7;lh Pk9 a8(NJ)sq\9ȟvʓ#_/|OQ9MgT޼Ŋh-@[8''$ q|{뜢r P5uŘ8P'-|)'9;1 ~5֔p,k25kE wkAs`NFGk&QZw̶\Y `Dp8aiVv@gýv%ߤNmC̐u#>+l!/?eKgj ^w?|VCRӃjo X8Y|](O{HZڠp4f'^{}h8dp6H. xKDx7A/_u~ܲ/֊Ւh9`k_°LԴ]{^h_e M^DlQzrɯi64Tg89^<A$_|Ёb>8^KPEο| bp{k 2==, =ˆiy{g]YquK`&|0p^e䣱xmPGCp&uv[n,#JXsϡ x<澪Z#x| x=A {INW@9sχg}wїYFrs>ߐyކcu2݈CZ6锟Bv'L¡L y;H^{YZg+3=rXD8 P7z0fPkxl~x!GgxV6 Fopb&z%3PffI69O 8Quum ezNKCrKڳݘVd! N/ݸIt1CjnFXDq~H/dEP*˱fV) W-4LV 3KmXSD(hL-xյN Ĭ]!+ g-9\0,ϙ^SE;P+\ٓ"n8^yFf>zbySQ|LQL)KN8z瑘|5,{y@.(!53zI*&/Lic2<p~C[0aÛ/}'4g+CʽhnwN~3[-1]O =DKL #oLkF;s8aGB/>x{>$ܙ}x /R8H~Y߿| pS\BOm_܂.\YܝWgxӤgJ^˹7M" ^ĝMދCkrV.pHzjCɥ|uYQQóKVJ{[swm&kkL{N"WFb=\*9rYbqq\M, '39,_un!Q:->3 st\$/ys*}}R?$H%_XJco9a9`tlp­b>睼gM,5؞5WK*Ї;šX,08.ęmӺmO8:6vm_KvS'Sj fhZ<\-8磃p[_쀞e7]?)o&lfMT:3h=i36NEU,]oC/ɅśZ"μ~"͚tXe5FUiQp$FN1$rw/a0P>)CꙈc#-).3r_rj]jl{,(řS/q s,:(RCܜv-g8S#L~yvb$$$)ZcؤgpO]4g8VY%12=DzL278sEEN0N *R|1漈{r&hMORx L\1‡#T#P܏+1 dܸ" u\*̶]ְ<ظ8Qo5?XsMՋ*rt=#WKfsc>mXl|<7L5,OhGF{U;iQ2&~78\IQ(!)!.#VX队gF@F3X{qO-Qi_$dx+|m j.QW=W'Vܶ/>g9C`SsdqWdi+//yyjlhvo(=\h$Ty^t6<ĴWԂWs_c2p{ ZcCg0lap5hpbyㅆ}5P`ge_n΋ 0y1gI[7O?ӭ}_>93/͛= ۚF~uk^.8凢.Y\w3`H%lis~1Hz6<{lѡXCߚ˽!b23@-DA1UNV.Ov|i .`Fk$ ILP՜3C\I |邋8Y:ܫb7O#%y88nW/n5=5y+oP.nNpӞ$5\6s[;XK%Jfpq`Qvŗ8<~Ƭ`{ƪ6 '=zz{Z4ϒ=|l.~+8{qo"Տi ݚ0pyq8Iq..k5%qgD>uIpʹtP6IY8ջ /Ҍp8'HVr_wZG[p&'{Nq IDATܩ^ Srs2 Jq-|?:ą=9J/ODBJKcE^E-)x[,|W˩rֱKEǮfO[/J.AfeO)g*߳&R)z8WZ[!iѐgHWy~8_|\[jHl9C-ňpʦq1XGqj We{jHx;W𙳏8,?TO8›B|M]Mƛ=m>y蜖>g p8ܳkX0ˉY {zꜛ~izoGz_i8SwqkkW1̬:f2%8 }=ưao.<~uGjHqIZ_`}k'|䔞a/NtNwy׃Hhg2Wk'E3ٵރ\Ţ٩D~VGg{3K{Y3ԖrdNJ.ͩ~mIܥ9^9MO~pǧgcgSߵk9֚q 29'2NA<5uM ܧCV 6w[qyӜO)::sgI^ƛ;mg5廵n^49!f:T]>?e_ǿ<#俹Ƕ1[(Am๪6g燏+sA__kA{mef#g/m//5\Eϩ[&W퀼`I,(x8. SeWt_<0po&f3/oųB/v.ث7x#G n-{GdsXN{?1Iv(6Śvrg^Ii~',|=#9 wO,Yu|܋7xLJ/d_\Z9ʯ qG4'ׯNψf>sNYūKr$Y:zY 4ɫKf! +R3#Y(ש4kwyrM?X q:ang 9.˺: YdPGV=Y4G:S/b 3;8O90fƊjxV Z9NǙ [k3Y5g_78kpM Bovyvƭs"=:+[g8nG3}G0G%o-样ú0$tGXw[ꆨŻ_p6NrWT9rŒ.ioMp D0H=aH}gG½ g_nOA_y{z@Y=bz"[>qeDp1|4FX>^w(Ƶ~"y(س:'b} ҄iᾍ0gRdfCdWκy+B>߸E/rykDuLˀy9fri ;Qm8=5eƞufbW# o?`JQ5ِ.p*'S߭3N˺us DuD8Gku4p({11$w,P>xG]I1VLpk['xg-ej}j9r"'q7b 6VR~/>bEx.83S+l،u"5ӟ5ny{=C"Oa#9|q0=b}Fyp/OR}f^_u#ORM8Nw|Ø_qsNs:s}M ǎF/8{Ր1 u}w?%sY[3 A^}6ŭyk;(es)YM6LlN^>)pGd%w5n!Gg;q?Ψ)DU6l}Q[aaJʈZ9.8Gx WGzNvҶbf'mti"lM$9Ihk;+-705XR=T*~'@CJdvW|zN1 h{8~4_n4)-k)_@>)w<9y }ѫBqx+c99X`ַ|( zAJi't[CYו5=6k8zs&5)4i>uuEG8\轠 kGb1h?ٽg&$Y=sz"KXh;WsM<Ÿ#8;ټx7m~)~ݻϐ.8VZ~|?F$ T=KjOrfZ+ل\t M}uv\K&JF[ L`{wS*xµ‹.n0 :NEi.F%NAY<\{6.O?$XAiO=[G+D.OPcB k;]H~V`ҼZ8_ ZNڝXEFup,#K~8& Wxt/VrXwc<}eyg x>Wly;O?oyE4U)&~CX2}]W+fU"igkcGՂSr܏pc%|VM{F6'ZhTؔޝbtըiMd`_|pR{=)^Tl`!{4IF:Ǻx+QWs{ۺ&|"=b<F $3..^e>tA~(OOyΓ;qr]Y/9y8g@Cw"9Q&gyϦ.c4m6-uӼAlH0.o :BwdL 9}`mb^m 9%`<^ͷIB}PN Pn.ݛ$ %xM'X>|b:F<:owa Z1>d^c`HFEc 9x 2U)f̎\ϛ$G_Fc*/mܹ9 qcфNDw¥bQ0X×.`(99v6s'5s~O;~ja2Of8ެkW ?1.},Z"Ѿ.{ TJY_'+G{hZmG?uѽ5įvv#IrWhbE4y6Oxg.Շ':U8TG kfu*g5Tt\y|~8[B F5+'-mM19q 2;>I<9=8]]3cM-/M,u{p}3C8o[z._5)0PsB ~kѫD˳F_;fu]zSklrS|N֚x ?^̻<{pЏ{M=g;G ƈźո[FAч?oFD -E |nz㘊j bpȗ:}8Jg]; ~uv>rxj=rr;Ȏ)p=k O Vd_ͭ?ru` 9|~ƋO d%̲S,>8⇤y3uI|`@I1ʉyqK'AZ9'5_t?9h)bvCtoXꝘr5毠'iNPYYeU[Qob17pr E:`<zrd z.kڗglrgo .ZQl#}g6'}_'e8ˋxҳ=h̿ٳԁ$<}57qAI.1;o$˽B侁d{!nO fF'Qggn+3V$xPK53m_qo;j[ɬ>N7_rE<8 YU4OBkL2 6]Yb+G ܵppѤH{R/}=Vι'+ԇ+dV1{2{kĕG pooZ78f6礃 Wa;EOɼ& |uĞz?sw ?x F';Es@))m™7p0⌧d @~D;,2,ތZkzuhڻnTY忰9yΈas#}·>r[pr3=|j4e\~-SO)Sw~k5u)&` ~<=\;r4sԚORKx&`lwx3",=2=]]; P.$ -@dK?J\zz5(~1,4j>b7#z9wMkW>{Q.v<'1,8g>OJ S}]WfQ]vD ɏcϯ :sNj+{4h0L'XWIsyѶj\ד6ͽg`λV|p&phϮ۬Cn~4#wZSoh"Ե?,!8&2!}6F|P n#[Z|.Oe|Dq<D+|>J([3MI"Yӣ OFj psp{+~)X* ț u$:G'*J|>r;W_9lR| #{CI=_ KѢ8:8x]~Khy>gmi:NJDl~̵`pٿq-%xLzp\$ ]}_ܛL>'=sM]\}ƅ&GJﭡ`l f/S=q&^fp+~TM.2Huc!~|{@K7jo\STx4<z1>ax9ÖEzI7u ٸ2S wxNU-rszՈ +7矪Ӑ< xJ wpIv= ?]ߕHrq-8Rғrܾ9v}&y&\k#W9 Psdç+Jya\X^)/~Gbp0=B<nS@'r!o|}O5,i֮;zV[Mg -|iαݏ?ϿYi]$B2H;G;:ViǹNtNXp0G|Q.Poߪ_`i9.E;o:jH ,OZip0V< OEpgiK}'h̑CxgZ \W6 s\!6σ=$*Z܋;S?%T颹-NkM[T@YaQ'd?s}m[}O8}bw~>s> ]UȌ;e)E TbnR8X1 h}G'S)T6ӕ]Nx)碵xż7x0^_E?As'}$qpxg ,'VE:-΁ٹdy7ЖX>ϳ٩QCMҦμ"sL̓qGIL-N:iGvέ{Z\[Y֗GDﵭ$7*1 'OύpQ燂&^Cs6)r!z{XO.8 \W}vf5seC$u7<[NgNddKǃ3G+kODZ͇Y1s>))άskxkS|Ѹ78|uZ9NMϦ1Z_m!wAsmMӭ=u 6W |GwFi-dj.%,ˋM5@jP⳧m>|a.~5WQMe4< rM"ZёWgq5%ju@[NJM0p5dp?qb Pk.;xpntKsHkqn6~MYDs،!N˧ԳZW+vGUhm;eƳXmGsqgXg罸^71Zp k1h8⛟z<06՟{.Soǝ;5^4l&0N`"k|a+ c7;Mjp`0_bLr2GR8M&׳tuN"+Z .VK8WgcOhcç7?u}8<ǾE|V!/- 5dx&*eO9D/5@ؘ]Ʒ%X[/ 3ϽLϿm"p S4Wh:vk eҟKc19-#g6h˚t-1NT#`9ʬ~J >VAr`yNe6;lo=ovH.OӺ]f |p^?cHT}!Űׯ$M) Z2Sé" Y5&(jmr Y sHY^pD3fhhw#qNf@ 0 .|'}`R= tEq<0[k}wybwFk)dʷv|v~~fӬ=:k*Uvx8;x.p9#Uhn$GKrdJ2Fs{p$dʓ2ϩsܼŲ]Z{L r+4%O}q'cqރ!c7GKu9rCܘz~:ٶ<6=pq:ڇM0˓&u/Ge.-Z p>Fx Ǧ%&)虜м{X fz6N?fpƋCpӉq:Pb,MXD&b0uGsj_f4vAXqQ!.MĐj'L"Ly_s͆]LH9E%/4VYGbIy\LprQ[~Ib~Z|vz1.WV\-ngg2] Ey^xun<7״um~sXӰ^j +':ԌwXfG'~n+=.=_s1,qy3+w/v<`XlK̭լrƆ{~P'N#lq/sfU1!G`W\G6\ݩoUgѕ׮ivYQX"j/:NR__ G2ʦ6]O>qr&299}*k/x9#y _QM*ߧnř wl?0[ܱ(Le\K< |R-5$ĠK#<`9EKFmCV1 e%5݅y>x6N~Z6c=SjN_j'>Mٝ#M97N:2w__ W.󣜠'j]Z]?q%|mB5iqڪar.{m>:Fl\*>6]kk5/)ZB3M[[zL忦S861]Ng墇0[f!I_GiRya3ҼȨv[M:f+d)Ozyr[eV)[A6l-аZgqldzE,*ĖˮOCסCXjr_l^}Qw THXj8'{67p3{{~8F8jmӗ<ҕQd`Y%蒳 ݓ3P7# M@Yi>~YiJ(3x>~h-E=/m΀-.,Կk{$?:v?H4r9Zi.\w5Wi82S~+)\^RwL|= Yd&}#Z! "Yϩۋ^֥9hs'>(!9>9:s{f5ftoWއ`<Դ{`u@< ~~,Mv_(/B\谠b3M:nk& K)<hXW??WSCq] ̋&ڍmOYC$+)܏֚w5|&v9|876_źbM=@>~ϧul8׷xW8/Z vZ1D]T#k G8yc>t3Βz;:4#t,9'7}lN[snqr?1 ?#pg+}Ari5zo>0>mqgkx::N |x/|:mL>ɕ.`{x#W2o">2YB{A͹<lamڦ*ߓ ڦ(OKMNORM1%g=:q@_%$ps錍kE#T=3>OXvmH[!,"ٮFX,gOBx|OyZ \6H {<@f|{/#ܹ'm0zsskx5b* 7lP)$mɜMv_b)83͗V k0`_fJ@VCn</N:Ğr<9C*%#p'gV/¯oe nOٱ$N X6&tڟZd9Pa Y>zA6ɄqhXF4׃Ռ=|NG쓆2~sjlfx>g6yZ+~`qJ'X ssijwZ{qů=eZ" Āfmq`ve W{=xjc@y%N5B?<`ӔH P9p6KΘƜSipYa91m"1~% z Iqţy皴X_ӤX!))tp}.5&H6׍ϤϬ%gpCn(~!{^u5^]ްd]KRgDi;+ݟ #5EFճ7kBS#ɣO?ٙS?Rnv_k^MK"^ΊP7!.1ۊ۱em^@DWyq%kڠlN-qo:ЊZL_F~"žZWC c[}~{0Y_b5=hҖX]_[8}aYO+y|Nѯ>b5&s<) $$\Gϣa g3y֥İblhZ;u1Ճ96C6)sohts Ay̫Y.cs +,D~}~|Ѓ=o:>K3Y5LJ\6q~;roBfc"9ȭ5ޟ陾%OWVTo*yZ0 vg ,2Lh 8ipݱX&-6[6|Moݷ^MLo-q5Շho.W]!cxʉt{p^/ŁWGhZsiN='6gjxεjURl-"sϯ>bОzȻl-Ks݂qhhCnHAcLz0MZ^l`Ky#swƊkWC0Ny %ɳGcIRr:=6ynJ~F6#cut/766mM(V<fVg¹cMUnǍtՋx-g nDըk8,S-/ ,ÃYk.9];kc/ၻ:^İ 1%kPcNjNƦ/ђ>4w^hRH Û< ܆ru/aZ ` IDAT~c^Lv|V#ؑgOBX{q d%g$bkZڞXH7:ƱgC:nVtʹxKyx'h:Ԟb\K'Y:kOVXT8̹(j}qf,Nv, ɦ!e,/rz.c\ 21S0}^́PK^KuX]vyjs{CuY?|dnC7Wvc ;z#]-n^pA8^xw=?|\{_ a8پz u8bjpy24^\qVY6L#,7~?]/}o-ִ"4 BφO04֟zmo^^zy4p t4|o䟖D28_tCW.i 6Z&HvZN|d3n܌?3{=wޚ :9Scm𴼯EJ$sDy7:M2?%K4<ޔ1wX`Zp`ٽ*:Z߬F5c?/jН-$DU}ސO %-QrCi=>ebLH?:Ưӓ<7+Ǫ:x87=^ad8sV>3+427e YO_9p-cTN/;I^b}uk[&UMHqjYrW)Vc_+_3yV%>ŒW0x巾"=C*m7^hRs6@hSRt9ٷ. _{64v7{Q>5guZq)qljyDrzs ^u@WOKѤib[r"S{??S}sMho4m/7#zvxQ hH{М'Ik]zυ"%+ /~B؈|k q!~~0Ŀ{a`5}6>o^>#A,k.&6_VY~&KgQ/GkG}>e=(=LsçydǞץ:%xp3W}@Afʎٯssm_D_=#ufTDjcUᷩBߘp  Yir 9'_{~ݙjЦy1Nnߞ鶴^qL<|tt}JK|Ԑ/ nv~ђzMiB Wڅ:ıoѓƦf^/_ӻإ3suJ:9Df_O :5/}w+_qizj3eỎ{9nY?oӍK9 }!ٿ~֋9 A MGZb?Ws8sM ᯂ*'?LǴ^l=SӁ DЁɞ5<; IkqT;]8}K%멩": sb;8:фY }5A5\˸/zͷOl[ذr\ۊtRC 6={yOc49w_냬]6SLYh &ߚӋ8H]y`]OoNwPݪ/ڼlhj?}NϔdDo~HɅ`mC477~h*OZ 18w23^Fsd'q>jzvÏhw,lpք}ࢽc{l 8} #Is*ٝ?5{fj.3磷s {~ίf\ːZ.$ӟZXǫq'Qx?t,1mh^izZӲ/ƿ\ g{zV5 =f^ӗs~c_Lƭ_wgP_x۞o6śRki=1;F}6k3;~qco/y|!/oJY1n@zWDqc/"rpGAN^3?4M>mr6,|qRqx Is~lFO$u_x`@Tv$ƃNB:։p(Čo\Mkr&U^?y}XI? V;D\WO7=z4ҏhahx7)t!qǹ~ߚ7Soޯ^PnLbo“zEł kIx7 i⬕%1qՁ}BN`S9|F̽o`h (WĿ1՛{*OZ{WbS7_Byo:攒OtP4Wg~Cb+om}Ah=yj>/8EC |&ߑHeZ/(C_Xs<2*ۜc( e}57 gsW"voQO؏1>?Yܖ԰h a~S!,\+Aߘ?C*y5)_3'X{;اpy~_!56;fJ-x1<I֯ΛJ||VӴiYQsyZad8'y/`G7oy1AO;bƏ .cDRJI< $:x$Wq߾u$zM精]kS׃q7ctdy)r7{>ƙYp΍X]>ib>Z_[PܫF\VmSHd;¹~3w(l{c^~h5qvLye\gN?d{ׁ|١WzC!E>'"Hl" &y jY`X %a 3 |W\nn*_-4ݔ F&?sBҢ=}o'̉צrE $x*?~Wfn=/Q]OSGj%FYܴ|}83/?y˛̦pͺ}E.9^uhV(pF&9;jazxხ1ɌD'}?sxroZO|4&¡3K:Ϋ>y >c/Xv 30$y.s+ӳq!~1?%{Եޢ=魏^aL>}r2wk|ް gyjϭB:sk!כ{x>8GWkXza\32$8oݔ ֤9b0׏kPLB9 d\^f3k_I ~cͺ|1kKD+\r_!O; pa>9oskC! xc:}Kg= o oi˫Y{X׿會S_ dGqnI)J_y^?@3OzJVޒs_:f_e<«cVi2_{n[ǃcXjY# ='^'boZVͼwz{Mvpkm63=[[V ?dwR^RùX參#eKa7ĊKsK_"(ׯQf a?4|93KPe&}:Ϡp*&N{bm流{ώ/{v8 :~n\4,M7Hmvq\UW1X|}^|?KudZKj9%#U>ʯ{o`ea MD+~p^ tp ^sI_K{iHhzx%+8<6Cb,D׊J>jۢ5>K 0G˚r=]%SdM$` =]SL(_sĎS3km/<|"1еeA~n]_C wDzj8~iʍqu{I6_s~a,<;\k((@?r^.[k}aŨ[F Hq| rQ?B !< 6BSL [Wc(g'iK.?!rEv7~ ,IpxqdvbXs/=[<6^r5BIy4b>"~}/wҒ='^Q-˜dGy#7\nAÛ'{oB<{möjDJ#"胁QsV—48ƛBXѽm;>}(^mh}ohH+7YVj{% G_r[|exE}SjǙ!<6O*UBgjޘ8Sk yʶfv8å`5QlNcfYbMdݏEu4#X9 k32 6M카εXh.ӱj0.Zy.†msς7D8ܛ1 Q}|6 4,V?e\rH^[zAVcl\9;_`|Xmu+W|.m(ssv8%w5$O!I{=h\G&yb+֣o-Soggy =KR!ݽaǓƥF˞gZgo-5:30ד0H,e\čÜ='r[Srx>< 1 -{:Zm#P[ ፸Ju SҷϘn. _4׆m$*l!ci-k$:q۾pk%}̎jKlfl Ixrlg}+7h z.h ˘]{d?ay>ciNx55qNXB-|J=_͗6W;MKHZ!ͨLe]kPЉ%z5$8Ȱ7"}!à#Ö a9_^..Kol㰹B>\Y\H,>^Eسp8ZxMVk/Ձ8gR JW,xbb3ncu~%sZ|3aGyW~r̍g⟎٘s}bkgvoWXE&MM46y@ 8;w!-Im9b rOzAXyx$Ң]lNB߼RKjmN*8sP.;l/^!o> =-9OT$`'cˁ͵J~>) IDATfSUGzr/t|zvt\,'CTp;Dh`͋g8sqjy'6ur[mAN]/F[[u\(z'Nb/g)%f4p|0!6A(DXNR\߈Kv+Hr̍}Rf<3~9ϯ},4r\fn%%Ļ|yh1m`ẕ?u'5˾~%>A\WOf1ӈMkMޯщ.~Ol|[N05Y/6K|D1 S6zfRf|KY^gHS27`tQj8&iƞ 1Q<3& #d~=9 >}nQ~f~  #;́Gi^DzRك&aD W"p];Pl#~LݧFuA\JKN az< :lx.+>hy- {6D+858>R鵆~CŻq;ULΜbV/PCFÓU͖ d'Fa} ^#;኎wPN vu€?<#>S!!.#{: wm\BO^9LI}'w55W~ 6=x-8=1{uE=APO|v o1y_Z\"7ߘ;vhrzb7$0#ww؄Ç;Xjm\m{r=_fLRH< 4S4R_|XڟB`LYvWag}n֜{NQ[NxS?PQhpc~`ޘ kЕY_@j >(Q/ƺ-vU5w=bSSw`]f J\bu6Pu5& E]1hwj[8Kob5-=r :< 3'1! \7χpe7%24L`w #].}jh/=~rp-A>`bSxr^2O'NruG@O݇Χ'3h"ΆtJrV1I<ڿ?n;%1(o&w}s9;ԩ #/ަO'#À& ta|&<rƢcާ(^b$|k>Hgu2Vi".WS^[Z1yf"=ׯQܻ,CR2M @@|Q{r,_40/  u0 ɖMQWz@ B홰O/?ftCraB]춝Z x@Fg w m1Eoc ^ECh{ Aek XD<[rx&pfOmM_Xy_9&+eYHI䈛$ *M[dFY|zm`F/;Clz$x~j_RmN9R:l%=@ˌ&Gi~-6ȥvbM1B~>z4F}0'9cK8ىd=> 9,s@Հe=>qa\/&|)$DX%NΦ I9]Io.@߉{2񘾫wTcf=KK*Dś,L˟<7JNEkQ]ӗw ]~B<ƀRTD K{~q=J@(Mug'/Ҡ_ap'l11~,Ұ5>ߴ9GiǶUBf\s/.Y9 lcnK7۩r'K Z51#_ c3F3/t9x}'8ag62A =Z/fh?¾@zi44]7Fg '^nf=2gƶJ~cLJ6"I|L>!}=avTZ:o1zZϚ=X~W{⭳MmptL-_}89*}O&_=h}r s?3w B.4?y q_cr8<59j1PMe*#=蝯C`8g#q[0(RkKiPdO\XEn]hI Wr}GI/ADεZq 6rFYƛ.lu !5m=xG {8(!}n5G!qM3VgsϦ^bT-`s.3o/~B_H잡n ]])c{rf.rwzR+J'ȆCr{@|/)cZfcِyaI4W)5dX._l:y㌵:5Tnnf[Xky:78|%ېo&0ֈ;~1>RP^U,BOMY//5| |W91]cet=}dCٖ &°~&}2Z'yGMjS`qܓaZt@u92LvrX)5uMnĴ5z_bEo6va<ܟՃ_Q"|c-:j>܈}oDĥEi:ȋ8Xk." hl6mEe.}U4~H>2?(9ږ=}4=Sxz4Y_nS"s ÒM0/L~.gdSɱv`zBk0AQq=&rFMq,XF )^+_&- 7[@{7^ #%pcld  `u -:1#r~mFRף2Blv#\FM'~K0a~LaUC gXܰM"op Ѫqi} EWqqlNZSLjz$F956Ň:2=M̹68\鸔nρYIX= /2l{z50bgcoM<>v6؏F-vLf]c7GkvlW+6ׅۋ/8sV7>r6?gU I8ju\Ԝ_]::-D뭓…%8}}C}r? 6%5c359|zM?y,8Zؽ&?4`Bew9{tY b&B/4Oy #mqHkD.O^(CR4XtFzx#g$uH|xlv|Iv2,lAxҺ9m3S䍟sLW#p_Mo/|o`$' 4h!2lGC_IPbf̼(5dmC m\-㣥vFC-glKMW 1LVQe.cZ/k>={y/qF#ÜKALXImMdӑL7a@ %ɫ5ƆgS?@iI,AgM_; ^1cN"X׼^w #X4^O1 m6:Z~FsWaF_S<ŖG4.a6MM!3q.)qY4A[`pGAc yq}]`֜x`'5lX4OSAB3tŦPU2fe[!aٳ`B~֎|r=d 3,d_ K=,<@͟X =9c\4O1=W󃅳y{3prM~H>W8k0AxGcrJOxzlܣuu+typ{>.48یM@%EKxq}22`z/3Nټ$w]/Gɿ#=e"{Y'%c-߭ ⦇}^0XmExx5$=:]k% RXaw}`d;P8Jܙ\Šu|jzɟN|MMx?8Dp̰}uawYP<) l}v'-= zLC1|c9Z>8q>"65W@Ր]| &wPZ̟aoΙe(0}&GA O*}šh5a]}pE/ S6ΩZ]CѶy=x­zw(agekz!;qų%߫ih@Gu46b=;9% cA=w#Pڜ}7lh?_dAo ރ>ZL<1s*|c1k]͡ 9YA-a ۘc`M (ac0H6]VҥX&P|8zbNR=Y EMp/^_b+JˇSU|O=9+Z,Aܳ%h2"`hgkgq,Y{Ӹ]:ȏƜh}CMl;&&Fc>c\Dw Uj>,7p7=o}(:!~C+vCgMHNpXSZ%?elGxRۛO oc5'?]KnG#䵿j}ڰ Zpx qVND7kQ@L 2tp9[9&qw731lo*D4y[[z~xNY<>ZcGWdV𝯽2Jtn!j(jW0TT3`Z$;ql {hMk0:Qa kĞ"ki\ڤSiT40.(!-*R}ϜnDg OŚ.} VyI6G~j@ؓ^[]ܩ~7L X RHkE16b؛M<2oiߋ%O5#F_88mq+Bp(ͽ11\[BOT'! aNmVa KFfuc8__ }8{[Y['#XR{^60x,`G1S{OrV0 6|ᒵ1,lyx6? +v)3(dnkZa|qͧe9e_tGyAL_2Hl̅ 3r6A_sAL@$i\o6Z3~+^=[F=%ZoO`7|WؒOn$z;{V<͕3rה>z_:e$Gzy_zpNQ}yqڳEw$,|OXziƝx>xW]E¹X`ߢff|su:`񗗘= `d.ožGzԼtzCws·&8S; ҢS762\}qzP8(Z˱ތy{z8vO-&ʨЋsLu54%9ux\SF:öiZ/eKH!N_]PvMY_8{[_QgϑUh$,eµ3-_u 9$}LA_,ƐIIp~czX.* yu} h>oK7C r/Ňmv-a؜JYgţeMPPwpVNB˘pw^l8Cɧ~r"f{оT08<~MԁZ^XaGs=&k>`H2>ik'Y566)_Y|Kܙ=0z; iyxqJv+0'!Gp^,C_"k ; *?8p36j&\htx6mfj_+ o᲼ݼ:׋WRbFJ9u2-7;CdiJ&ɥ1|}vS3"P1`ۃF9c|V0\:1kcأC)#N )*,#׫!b7eAsYSQ?Қy~hg: 4_Dh#Ҽsvj IDAT)k{hroXNߞ~I.gh3i;/M`37[9nz56Yqԉ ) Om"6!ƚfe֦ONTsd܊n||?c#gja׫i6Ϻx< ^oY'q^oRn7b.0X }2k@`g|f!Kԍ3aְ&fcnz>Pԝ8g]ˡvpW8GqMϐqOcY8:eͳlf3{.d=y>3o8T|[Sm =|u wᬢ׾P!_ɈALhP]5ob_s24Q>oYcYw1͜G2Bq)s ?31n{~h :r,u-|1^l˪kO#)-@~ff?7q>sRs af~{ÿi'Dq/9biͤ#3aO ]/4ۣ0ھ͖ݮJL-.GX,)U_{h,7?Bl ,u~{яSo-uF@q o9 scgMG|nᚱ-zG蝍A3QzV*b.Į5re5޵pX6c\(8|yDTM%Ak֟hC`H0z5sދڴ bf#t-&Po@8%$ 8R2%5dDLw6H$f'֘H;N}!gq[4Wޔ_}GoXYo}sO_0= &ɣEr[&ďMp;vϓ /~{Fؿ`g-I-G D:Mh㏄DȮ>EcrNJ~$ot;]ofj+/q|M3wmNz9SȚΏN]xXePlgBs433cc!ѳ5>EiV:^>b˅ABgEx4\=x 79ݯtBCkA ?N4Y ВM.­'h|Jvyjj>a;)~3˶\HYOzy: v n1oeI£@Ba,K׬"vzFbHōGJlssz/_)pRE"34u7X]'EO-āyo&'cp?0![[m)hMѷ (]$u& o~kǶ+7_Fui.6/q} 9(Zac/U?_,OMө'5﷊0_˿8|[S0;JhbϹLo7}/^~1cc~uS1ėWrEFyfT:'5œ:3+̲c]9X,ҏV+qS^7K,躬Y%#5uZ>zӺNzT+zYcC`gNx8.i |ICz~&b kFҜ3Dr0qlgJ`6O ӸN|ӟZև~xmbِh߰kE_1xư k0=Xn{ܟ{֞\s}JGŜsܷjɾo|MNSIo:vƗOlfGU [׮TobzBrj"K_-`\&+'ɺOCpR2vzH:D՜ɗؐ]N3AMsG] R љ/)Qл>Вɖ098|KvmmıԃyҽjR[s?5h=?kG0MHoa&v{9 PMo6q\97(}٨+Jq}}P 'oHsKsOᱏ =e.זDw쵽|S?g suie?2sxzZD7D+ce4ϛ~A3z*4irAƿ<v<'>7 pzDpFu{%o?| Ntg?Y?g+I 5)c1 HL#6sDQfNqN.{\+Y{Q#?g5 :z̾9:+_nwVG]d$R@ӆ{9?c(4U~hPqe (6?u#Dx%AԨIBl^O VeQlwJ wx+!1\LչV!gٯ/"0W6W7KmJj$TOO<*ɪG#n80,i~)qx_ =O}Q]v|;F;Wsp|AN4GxA2eiMar ԥkIbi#d;fwsm6"9": r &Xyݖ' ę RnOy?;Y_Ys͞}SyzWy“8OusUϚL"a(Qy%9z;GK 5چn9$?MXX 4 c ⑨aSS><_IZߖ! _V9 q4վ8L=]l9g %e*$SSKHm M[h5}`@ !Xc6Chݳ 3L~xty5$;;kOS~jM.9c˝=R_->1[{qOO:"~tOK B3s9X0]W}G`ā8<$/ۋ|=GSk üL[>_JQwڵ|'|\qcL^lWkû妦D[ ZcNƐA+0O|c1dvԺ~MFPQ ۑ{y#i/[Aϡ bᅩl7~ '4-c?-fǒwvΑDb{~p쏽F\,S?d9zd]fB;&FA=~1, Xj5ƴ򒧚–ZfKDa>SYKOf"wjД`Z}c^-fim %>F38yL/]hs>/{hI(^&ۜ^qr޼%k0D%J'?YXKkN}M?0n/E=}W``Z_^Nt`\x]0y? Ƨ&z}xGGC;LގվͷرyH{o$A.Mvrޚ?~y%w [hc_>'}z$_G[K8S|1B[ڈfp ؚɏ _L!Ö$g~O77R6Sޘ&NUn;)g{:R[ܗd>]uR ś˸2/THح 7 =tH5b gȸ aW''`0{w/0x}B~V,}BǙ:c.X<[[,wcb<[sI㳞q9=N}ο &w@\f='ɡ6Aya htح 76c7 s˽rcl6M-yMr h8 5QR;qNfŭF>K>N1bh,6g{2Ax].c=vk([MxsL;W>]Xcc~{sr6h(-āxjgdhah}M/bGqίcȍb5b?1Y0L}jMbcO={OOQMhL_l[.3~6%:9IY?\}'=ƥ&3X$q4% ܃Nq&Fk'ϿI{rXs(5q̡ȬyEr)]Re F{3IHG5̴1^iK"-1ڽctս x7SpNtLohe/'Ug]W~ռXb}XIV;y_cs:!zqx-ɱ18iS#Gdž)! Sx 'uHK嘞0?zASkP.x<9۵mt/&#|$RPJҕEskNtr .1UMyݯ|zIm]uݏg߼a0/s̰П -'Էoczb |߾PsxAh{}]_(+%%_AG,[#i1T!o3 Wc#~n.Rjj?3M)ܗB/WI<6?k_o4Ӈ(\7M'pՓmϾk  JkZ8vxgfKY+[[J}+t°\~m>&%79γb@*(~my<<71횩7r1!{>?1ȿrrZtq;n0K8;KF kN :t惡7sOI0Up9pȐ_jB wT3'{pqY Z4/INߛ~\oj&ǣ<~x&',p'] |גX7uxsr*;dp}u0UfssfS`ĀCp2:跰[z™ Um>^x8[m}F _8wc\XA}~rǺnr@9D!I9̠'8Q:)}Ѹ ]fz&}20%.-АhbFξEN p”CI X芿V $OLmu0Mc`q1=89 {=ݩoR9&<>ZFN:a^7 G웂ԅ>uubnZDݜ"uĵ<秜2S"oxp-nsh`?]O:5sS>Y3~]<ёH@bnA<+^M1o_CH^u"i dH-2njt裇f6Vf\WBN`l llA$.uN9~Zxwp Đ p,n0$n}tg9Hm E|ݚgP !Ĵ>⿵fti@li+}<(\:"_~y/:tSy =}!)wLw wuz *$􄠣}e 龾q`my7v>8N OΞ7V۵#Ljo}i?A'ߧ~*eS{|3&+~V:l'©!.H`Rqk글tf/{x!O>z}8flջ̧/XZ>/>5!\?1''bnϵ~jnq=jx#_܊2QΏٵ XHkG ic!WxǀL-=^hiP'/FN>[YP#FNeob4{9c>cch|>Y*]p:T 7?(ޜ4_x9yN&|d9`h(/E Rdj/UzL{eCD%wj1Kcz6bi׊Ӛt,ƱfaLK#жKDi~ŹБ}/C11<ø=^{dz<)Feg&kV7}vϨ3'5gv`۫zM9zj=A}59? o!_PI "|! =m [â=>+Xo brh_.~vi_my-?=f~&6X%wl OO9s/ep[ xxfڣ#N:E\z"74Ť''˦>1\|r L'oh>1k0:>|woZY[xID0*;]/[3?M _}_v$KuKAh,sc/8LyQjzRw g>Knl ӗ t⼑ڨ)FwN\9az j?M[ /4#H&B֗۞hp#4_˚0 `3\Zacfɪ9E6sbRIDATP/׫M?1ƈ>/Vmo06,'x:>>7>fߛ/)7Gg&H<{Ǐa6n?9ܗfg'mFÜGFz/?4s?lsrI/n%pٙFqwvgշ{rH<\SkT":$`]V1b'}fMjL/\p#ǿx쩍{],S< ?Z.wr Cb7Wcmk0)Џ ƄZ[=sY.se3gsiOdJ1DDQ6Gh}8}uP&5d/M{;+7MN? jj^=-u/Hr]beX`3gյ6ӹ)mB$~>k{urWv%[Yoy$R%=rzKQ>?wd7E~.vV> î'KoMk~kȹ>܅ʶVESo/8myf >1E9c^G;ؗѸ{xC`AF`@ξgơ&z zGo4 (Mz:pyh}"޳1c&>bx_7cZp  ?*ހ(T~la$ ԟ=}!gi'wr~~1ge.{A kvj@ Cq9*VZIr%/Krc k?pe(Gj/ٺI%|bl}xw{V?(.z\clFuy|h6uɞ*j4O7G}x`}M>z㕫y e|5iWfJ?ӾW"Sad."$?2F{j61{,>!*3뉜ٱGy=߽tq"DsDoݴɎr|ꥸ}`S>]!clXAC工_ks~|ݕu5OLF03ΞM|̩A.{fA m}yƉ?}<2sOVJւy0&[ ^{/yzQ ьa$k&N =r ̦b}ՔᬟĴ':rv4g̱i~33 EO멽}v¡:оI$o%RTsGt=m'ӗ^y4ḳlV/.גlegmޠ//A2)li,7̹1r&z܇Y +9vkݙۧjߜ眴PrDTqᵫ,|}} t^ ʽ/j}ۛUIb@^Fm~T;/^=9=Flo%}_o#VIENDB`