pax_global_header00006660000000000000000000000064143151222040014504gustar00rootroot0000000000000052 comment=6951beb708d64c9409c5cbd1f2a4446845ece25f typebox-0.24.44/000077500000000000000000000000001431512220400133515ustar00rootroot00000000000000typebox-0.24.44/.github/000077500000000000000000000000001431512220400147115ustar00rootroot00000000000000typebox-0.24.44/.github/.keep000066400000000000000000000000001431512220400156240ustar00rootroot00000000000000typebox-0.24.44/.github/workflows/000077500000000000000000000000001431512220400167465ustar00rootroot00000000000000typebox-0.24.44/.github/workflows/ci.yml000066400000000000000000000010321431512220400200600ustar00rootroot00000000000000name: GitHub CI on: [push, pull_request] jobs: TypeBox: runs-on: ${{ matrix.os }} strategy: matrix: node: [14.x, 16.x, 18.x] os: [ubuntu-latest, windows-latest, macOS-latest] steps: - uses: actions/checkout@v2 - name: Install Node uses: actions/setup-node@v1 with: node-version: ${{ matrix.node }} - name: Install Packages run: npm install - name: Build Library run: npm run build - name: Test Library run: npm run test typebox-0.24.44/.gitignore000066400000000000000000000000241431512220400153350ustar00rootroot00000000000000node_modules target typebox-0.24.44/.vscode/000077500000000000000000000000001431512220400147125ustar00rootroot00000000000000typebox-0.24.44/.vscode/settings.json000066400000000000000000000003031431512220400174410ustar00rootroot00000000000000{ "files.exclude": { "node_modules": true, "package-lock.json": true }, "typescript.tsdk": "node_modules\\typescript\\lib", "editor.suggest.showStatusBar": false }typebox-0.24.44/benchmark/000077500000000000000000000000001431512220400153035ustar00rootroot00000000000000typebox-0.24.44/benchmark/compression/000077500000000000000000000000001431512220400176445ustar00rootroot00000000000000typebox-0.24.44/benchmark/compression/index.ts000066400000000000000000000022521431512220400213240ustar00rootroot00000000000000import { shell } from '@sinclair/hammer' import { statSync, readdirSync } from 'fs' import { basename, extname } from 'path' export async function measure(test: string) { await shell(`hammer build benchmark/compression/module/${test}.ts --dist target/benchmark/compression`) const compiled = statSync(`target/benchmark/compression/${test}.js`) await shell(`hammer build benchmark/compression/module/${test}.ts --dist target/benchmark/compression --minify`) const minified = statSync(`target/benchmark/compression/${test}.js`) return { test: test.padEnd(20), compiled: `${Math.floor(compiled.size / 1000)} kb`.padStart(8), minified: `${Math.floor(minified.size / 1000)} kb`.padStart(8), ratio: compiled.size / minified.size, } } export async function compression() { const tests = readdirSync('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('-', '/')]: { Compiled: c.compiled, Minified: c.minified, Compression: `${c.ratio.toFixed(2)} x` } } }, {}) console.table(present) } typebox-0.24.44/benchmark/compression/module/000077500000000000000000000000001431512220400211315ustar00rootroot00000000000000typebox-0.24.44/benchmark/compression/module/typebox-compiler.ts000066400000000000000000000002221431512220400247770ustar00rootroot00000000000000import { TypeCompiler } from '@sinclair/typebox/compiler' import { Type } from '@sinclair/typebox' const T = TypeCompiler.Compile(Type.String()) typebox-0.24.44/benchmark/compression/module/typebox-conditional.ts000066400000000000000000000003001431512220400254650ustar00rootroot00000000000000import { Conditional } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' const T = Conditional.Extends(Type.String(), Type.String(), Type.String(), Type.String()) typebox-0.24.44/benchmark/compression/module/typebox-format.ts000066400000000000000000000001641431512220400244620ustar00rootroot00000000000000import { Format } from 'src/format' import { Type } from '@sinclair/typebox' Format.Set('custom', (value) => true) typebox-0.24.44/benchmark/compression/module/typebox-guard.ts000066400000000000000000000002111431512220400242650ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' const T = TypeGuard.TSchema(Type.String()) typebox-0.24.44/benchmark/compression/module/typebox-value.ts000066400000000000000000000002001431512220400242750ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' const T = Value.Create(Type.String()) typebox-0.24.44/benchmark/compression/module/typebox.ts000066400000000000000000000001021431512220400231640ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' const T = Type.String() typebox-0.24.44/benchmark/index.ts000066400000000000000000000001101431512220400167520ustar00rootroot00000000000000export * from './compression/index' export * from './measurement/index' typebox-0.24.44/benchmark/measurement/000077500000000000000000000000001431512220400176305ustar00rootroot00000000000000typebox-0.24.44/benchmark/measurement/index.ts000066400000000000000000000002701431512220400213060ustar00rootroot00000000000000import { shell } from '@sinclair/hammer' export async function measurement() { await shell(`hammer run benchmark/measurement/module/index.ts --dist target/benchmark/measurement`) } typebox-0.24.44/benchmark/measurement/module/000077500000000000000000000000001431512220400211155ustar00rootroot00000000000000typebox-0.24.44/benchmark/measurement/module/benchmark.ts000066400000000000000000000003741431512220400234230ustar00rootroot00000000000000export 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 } } } typebox-0.24.44/benchmark/measurement/module/cases.ts000066400000000000000000000056341431512220400225730ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' export namespace Cases { export const Number = Type.Number() export const String = Type.String() export const Boolean = Type.Boolean() export const Null = Type.Null() export const RegEx = Type.RegEx(/foo/, { default: 'foo' }) export const ObjectA = Type.Object({ p0: Type.String(), p1: Type.Number(), p2: Type.Number(), p3: Type.Array(Type.Number(), { minItems: 4 }), p4: Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number(), }), p5: Type.Object({ a: Type.String(), b: Type.String(), c: Type.String(), }), }) export const ObjectB = Type.Object(ObjectA.properties, { additionalProperties: false, }) export const Tuple = Type.Tuple([Type.String(), Type.Number(), Type.Boolean()]) export const 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 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: [] }, ], }, ], }, }, ) export const Vector4 = Type.Tuple([Type.Number(), Type.Number(), Type.Number(), Type.Number()]) export const 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 Literal_String = Type.Literal('foo') export const Literal_Number = Type.Literal(1) export const Literal_Boolean = Type.Literal(true) export const Array_Number = Type.Array(Type.Number(), { minItems: 16 }) export const Array_String = Type.Array(Type.String(), { minItems: 16 }) export const Array_Boolean = Type.Array(Type.Boolean(), { minItems: 16 }) export const Array_ObjectA = Type.Array(ObjectA, { minItems: 16 }) export const Array_ObjectB = Type.Array(ObjectB, { minItems: 16 }) export const Array_Tuple = Type.Array(Tuple, { minItems: 16 }) export const Array_Union = Type.Array(Union, { minItems: 16 }) export const Array_Recursive = Type.Array(Recursive, { minItems: 16 }) export const Array_Vector4 = Type.Array(Vector4, { minItems: 16 }) export const Array_Matrix4 = Type.Array(Matrix4, { minItems: 16 }) } typebox-0.24.44/benchmark/measurement/module/check.ts000066400000000000000000000023011431512220400225360ustar00rootroot00000000000000import { Cases } from './cases' import { Benchmark } from './benchmark' import { TypeCompiler } from '@sinclair/typebox/compiler' import { TypeGuard } from '@sinclair/typebox/guard' import { TSchema } 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.TSchema(schema)) throw Error('Invalid TypeBox schema') yield Measure(type, schema) } } } typebox-0.24.44/benchmark/measurement/module/compile.ts000066400000000000000000000033161431512220400231200ustar00rootroot00000000000000import { Cases } from './cases' import { Benchmark } from './benchmark' import { TypeCompiler } from '@sinclair/typebox/compiler' import { TypeGuard } from '@sinclair/typebox/guard' import { TSchema } 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 = 2000 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.TSchema(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 === 'Recursive' || type === 'Array_Recursive') continue yield Measure(type, schema) } } } typebox-0.24.44/benchmark/measurement/module/index.ts000066400000000000000000000023051431512220400225740ustar00rootroot00000000000000import { 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.padStart(16, ' ')]: { 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.padStart(16, ' ')]: { 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()]) typebox-0.24.44/benchmark/measurement/module/result.ts000066400000000000000000000003361431512220400230050ustar00rootroot00000000000000export type Result = { type: string ajv: { iterations: number completed: number } compiler: { iterations: number completed: number } value?: { iterations: number completed: number } } typebox-0.24.44/changelog.md000066400000000000000000000355361431512220400156360ustar00rootroot00000000000000## [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 equivelence 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` ## [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 iterable iterator errors found in a given value. ## [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.TString(T)) { const { type } = T // safe: type is 'string' } ``` ## [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) ## [0.23.3](https://www.npmjs.com/package/@sinclair/typebox/v/0.23.3) Updates: - Fix: Rename BoxKind to NamespaceKind ## [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)` ## [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 nessasary modifiers to the replication. ## [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). ## [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 }) ``` ## [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. ## [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. ## [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' }) ``` ## [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' } ``` ## [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(...)` ## [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. ## [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 oprands. ```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. ## [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` namespacing. 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. ## [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. Implementors 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 }) typebox-0.24.44/codegen/000077500000000000000000000000001431512220400147555ustar00rootroot00000000000000typebox-0.24.44/codegen/codegen.ts000066400000000000000000000034641431512220400167400ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/codegen The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '@sinclair/typebox' import { TypeBoxCodegen } from './typebox' import { TypeScriptCodeGen } from './typescript' export namespace CodeGen { /** Generates TypeScript type definitions from TypeBox types */ export function TypeScript(schema: TSchema, references: TSchema[] = []): string { return TypeScriptCodeGen.Generate(schema, references) } /** Generates TypeBox type definitions from TypeScript code */ export function TypeBox(code: string): string { return TypeBoxCodegen.Generate(code) } } typebox-0.24.44/codegen/index.ts000066400000000000000000000024631431512220400164410ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/codegen The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 './codegen' typebox-0.24.44/codegen/tsconfig.json000066400000000000000000000000751431512220400174660ustar00rootroot00000000000000{ "extends": "../tsconfig.json", "files": ["index.ts"] } typebox-0.24.44/codegen/typebox.ts000066400000000000000000000361261431512220400170270ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/codegen The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 ts from 'typescript' /** Generates TypeBox types from TypeScript interface and type definitions */ export namespace TypeBoxCodegen { function isReadonlyProperty(node: ts.PropertySignature): boolean { return node.modifiers !== undefined && node.modifiers.find((modifier) => modifier.getText() === 'readonly') !== undefined } function isOptionalProperty(node: ts.PropertySignature) { return node.questionToken !== undefined } function isExport(node: ts.InterfaceDeclaration | ts.TypeAliasDeclaration | ts.EnumDeclaration): boolean { return node.modifiers !== undefined && node.modifiers.find((modifier) => modifier.getText() === 'export') !== undefined } function* SourceFile(node: ts.SourceFile): IterableIterator { for (const next of node.getChildren()) { yield* Visit(next) } } function* PropertySignature(node: ts.PropertySignature): IterableIterator { const [readonly, optional] = [isReadonlyProperty(node), isOptionalProperty(node)] const type = Collect(node.type) if (readonly && optional) { return yield `${node.name.getText()}: Type.ReadonlyOptional(${type})` } else if (readonly) { return yield `${node.name.getText()}: Type.Readonly(${type})` } else if (optional) { return yield `${node.name.getText()}: Type.Optional(${type})` } else { return yield `${node.name.getText()}: ${type}` } } function* ArrayTypeNode(node: ts.ArrayTypeNode): IterableIterator { const type = Collect(node.elementType) yield `Type.Array(${type})` } function* TupleTypeNode(node: ts.TupleTypeNode): IterableIterator { const types = node.elements.map((type) => Collect(type)).join(',\n') yield `Type.Tuple([\n${types}\n])` } function* UnionTypeNode(node: ts.UnionTypeNode): IterableIterator { const types = node.types.map((type) => Collect(type)).join(',\n') yield `Type.Union([\n${types}\n])` } function* IntersectionTypeNode(node: ts.IntersectionTypeNode): IterableIterator { const types = node.types.map((type) => Collect(type)).join(',\n') yield `Type.Intersect([\n${types}\n])` } function* TypeOperatorNode(node: ts.TypeOperatorNode): IterableIterator { if (node.operator === ts.SyntaxKind.KeyOfKeyword) { const type = Collect(node.type) yield `Type.KeyOf(${type})` } } function* Parameter(node: ts.ParameterDeclaration): IterableIterator { yield Collect(node.type) } function* FunctionTypeNode(node: ts.FunctionTypeNode): IterableIterator { const parameters = node.parameters.map((param) => Collect(param)).join(', ') const returns = Collect(node.type) yield `Type.Function([${parameters}], ${returns})` } function* ConstructorTypeNode(node: ts.ConstructorTypeNode): IterableIterator { const parameters = node.parameters.map((param) => Collect(param)).join(', ') const returns = Collect(node.type) yield `Type.Constructor([${parameters}], ${returns})` } function* EnumDeclaration(node: ts.EnumDeclaration): IterableIterator { const exports = isExport(node) ? 'export ' : '' const name = node.name.getText() const members = node.members.map((member) => member.getText()).join(', ') const enumType = `${exports}enum ${name}Enum { ${members} }` const type = `${exports}const ${name} = Type.Enum(${name}Enum)` yield [enumType, '', type].join('\n') } function* InterfaceDeclaration(node: ts.InterfaceDeclaration): IterableIterator { useImports = true if (node.typeParameters) { useGenerics = true const exports = isExport(node) ? 'export ' : '' const constraints = node.typeParameters.map((param) => `${Collect(param)} extends TSchema`).join(', ') const parameters = node.typeParameters.map((param) => `${Collect(param)}: ${Collect(param)}`).join(', ') const names = node.typeParameters.map((param) => `${Collect(param)}`).join(', ') const members = node.members.map((member) => Collect(member)).join(',\n') const staticDeclaration = `${exports}type ${node.name.getText()}<${constraints}> = Static>>` const typeDeclaration = `${exports}const ${node.name.getText()} = <${constraints}>(${parameters}) => Type.Object({\n${members}\n})` yield `${staticDeclaration}\n${typeDeclaration}` } else { const exports = isExport(node) ? 'export ' : '' const members = node.members.map((member) => Collect(member)).join(',\n') const staticDeclaration = `${exports}type ${node.name.getText()} = Static` const typeDeclaration = `${exports}const ${node.name.getText()} = Type.Object({\n${members}\n})` yield `${staticDeclaration}\n${typeDeclaration}` } } function* TypeAliasDeclaration(node: ts.TypeAliasDeclaration): IterableIterator { useImports = true if (node.typeParameters) { useGenerics = true const exports = isExport(node) ? 'export ' : '' const constraints = node.typeParameters.map((param) => `${Collect(param)} extends TSchema`).join(', ') const parameters = node.typeParameters.map((param) => `${Collect(param)}: ${Collect(param)}`).join(', ') const names = node.typeParameters.map((param) => Collect(param)).join(', ') const type = Collect(node.type) const staticDeclaration = `${exports}type ${node.name.getText()}<${constraints}> = Static>>` const typeDeclaration = `${exports}const ${node.name.getText()} = <${constraints}>(${parameters}) => ${type}` yield `${staticDeclaration}\n${typeDeclaration}` } else { const exports = isExport(node) ? 'export ' : '' const type = Collect(node.type) const staticDeclaration = `${exports}type ${node.name.getText()} = Static` const typeDeclaration = `${exports}const ${node.name.getText()} = ${type}` yield `${staticDeclaration}\n${typeDeclaration}` } } function* TypeParameterDeclaration(node: ts.TypeParameterDeclaration): IterableIterator { yield node.name.getText() } function* ParenthesizedTypeNode(node: ts.ParenthesizedTypeNode): IterableIterator { yield Collect(node.type) } function* RestTypeNode(node: ts.RestTypeNode): IterableIterator { yield `Type.Rest()` } function* ConditionalTypeNode(node: ts.ConditionalTypeNode): IterableIterator { useConditional = true const checkType = Collect(node.checkType) const extendsType = Collect(node.extendsType) const trueType = Collect(node.trueType) const falseType = Collect(node.falseType) yield `Conditional.Extends(${checkType}, ${extendsType}, ${trueType}, ${falseType})` } function* TypeReferenceNode(node: ts.TypeReferenceNode): IterableIterator { const name = node.typeName.getText() const args = node.typeArguments ? `(${node.typeArguments.map((type) => Collect(type)).join(', ')})` : '' if (name === 'Array') { return yield `Type.Array${args}` } else if (name === 'Record') { return yield `Type.Record${args}` } else if (name === 'Partial') { return yield `Type.Partial${args}` } else if (name === 'Uint8Array') { return yield `Type.Uint8Array()` } else if (name === 'Required') { return yield `Type.Required${args}` } else if (name === 'Omit') { return yield `Type.Omit${args}` } else if (name === 'Pick') { return yield `Type.Pick${args}` } else if (name === 'Promise') { return yield `Type.Promise${args}` } else if (name === 'ReturnType') { return yield `Type.ReturnType${args}` } else if (name === 'InstanceType') { return yield `Type.InstanceType${args}` } else if (name === 'Parameters') { return yield `Type.Parameters${args}` } else if (name === 'ConstructorParameters') { return yield `Type.ConstructorParameters${args}` } else if (name === 'Exclude') { return yield `Conditional.Exclude${args}` } else if (name === 'Extract') { return yield `Conditional.Extract${args}` } else { return yield `${name}${args}` } } function* TypeLiteralNode(node: ts.TypeLiteralNode): IterableIterator { const members = node.members.map((member) => Collect(member)).join(',\n') yield `Type.Object({\n${members}\n})` } function* LiteralTypeNode(node: ts.LiteralTypeNode): IterableIterator { const text = node.getText() if (text === 'null') return yield `Type.Null()` yield `Type.Literal(${node.getText()})` } function* FunctionDeclaration(node: ts.FunctionDeclaration): IterableIterator { yield node.getText() } function* ClassDeclaration(node: ts.ClassDeclaration): IterableIterator { yield node.getText() } function Collect(node: ts.Node | undefined): string { return `${[...Visit(node)].join('')}` } function CollectNewLine(node: ts.Node | undefined): string { return [...Visit(node)].join('\n\n') } function* Visit(node: ts.Node | undefined): IterableIterator { if (node === undefined) return if (ts.isSourceFile(node)) { return yield* SourceFile(node) } else if (ts.isInterfaceDeclaration(node)) { return yield* InterfaceDeclaration(node) } else if (ts.isTypeAliasDeclaration(node)) { return yield* TypeAliasDeclaration(node) } else if (ts.isParameter(node)) { return yield* Parameter(node) } else if (ts.isFunctionTypeNode(node)) { return yield* FunctionTypeNode(node) } else if (ts.isConstructorTypeNode(node)) { return yield* ConstructorTypeNode(node) } else if (ts.isEnumDeclaration(node)) { return yield* EnumDeclaration(node) } else if (ts.isPropertySignature(node)) { return yield* PropertySignature(node) } else if (ts.isTypeReferenceNode(node)) { return yield* TypeReferenceNode(node) } else if (ts.isTypeLiteralNode(node)) { return yield* TypeLiteralNode(node) } else if (ts.isLiteralTypeNode(node)) { return yield* LiteralTypeNode(node) } else if (ts.isArrayTypeNode(node)) { return yield* ArrayTypeNode(node) } else if (ts.isTupleTypeNode(node)) { return yield* TupleTypeNode(node) } else if (ts.isIntersectionTypeNode(node)) { return yield* IntersectionTypeNode(node) } else if (ts.isUnionTypeNode(node)) { return yield* UnionTypeNode(node) } else if (ts.isTypeOperatorNode(node)) { return yield* TypeOperatorNode(node) } else if (ts.isTypeParameterDeclaration(node)) { return yield* TypeParameterDeclaration(node) } else if (ts.isParenthesizedTypeNode(node)) { return yield* ParenthesizedTypeNode(node) } else if (ts.isRestTypeNode(node)) { return yield* RestTypeNode(node) } else if (ts.isFunctionDeclaration(node)) { return yield* FunctionDeclaration(node) } else if (ts.isClassDeclaration(node)) { return yield* ClassDeclaration(node) } else if (ts.isConditionalTypeNode(node)) { return yield* ConditionalTypeNode(node) } else if (node.kind === ts.SyntaxKind.KeyOfKeyword) { return yield `Type.KeyOf()` } else if (node.kind === ts.SyntaxKind.NumberKeyword) { return yield `Type.Number()` } else if (node.kind === ts.SyntaxKind.StringKeyword) { return yield `Type.String()` } else if (node.kind === ts.SyntaxKind.BooleanKeyword) { return yield `Type.Boolean()` } else if (node.kind === ts.SyntaxKind.UndefinedKeyword) { return yield `Type.Undefined()` } else if (node.kind === ts.SyntaxKind.UnknownKeyword) { return yield `Type.Unknown()` } else if (node.kind === ts.SyntaxKind.AnyKeyword) { return yield `Type.Any()` } else if (node.kind === ts.SyntaxKind.NeverKeyword) { return yield `Type.Never()` } else if (node.kind === ts.SyntaxKind.NullKeyword) { return yield `Type.Null()` } else if (node.kind === ts.SyntaxKind.VoidKeyword) { return yield `Type.Void()` } else if (node.kind === ts.SyntaxKind.EndOfFileToken) { return } else if (node.kind === ts.SyntaxKind.SyntaxList) { for (const child of node.getChildren()) { yield* Visit(child) } return } else { console.log('Unhandled:', ts.SyntaxKind[node.kind]) return yield node.getText() } } function Format(input: string): string { function count(line: string, opens: string[]) { const codes = opens.map((open) => open.charCodeAt(0)) return line .split('') .map((char) => char.charCodeAt(0)) .reduce((acc, current) => { return codes.includes(current) ? acc + 1 : acc }, 0) } let indent = 0 const output: string[] = [] for (const line of input.split('\n').map((n) => n.trim())) { indent -= count(line, ['}', ']']) output.push(`${''.padStart(indent * 2, ' ')}${line}`) indent += count(line, ['{', '[']) } return output.join('\n') } let useImports = false let useConditional = false let useGenerics = false /** Generates TypeBox types from TypeScript interface and type definitions */ export function Generate(typescriptCode: string) { useImports = false useConditional = false useGenerics = false const source = ts.createSourceFile('code.ts', typescriptCode, ts.ScriptTarget.ESNext, true) const typeDeclarations = CollectNewLine(source) const importStatments: string[] = [] if (useImports) { if (useConditional) importStatments.push(`import { Conditional } from '@sinclair/typebox/conditional'`) if (useGenerics) importStatments.push(`import { Type, Static, TSchema } from '@sinclair/typebox'`) if (!useGenerics) importStatments.push(`import { Type, Static } from '@sinclair/typebox'`) } const imports = importStatments.join('\n') const types = Format(typeDeclarations) return [imports, '', types].join('\n') } } typebox-0.24.44/codegen/typescript.ts000066400000000000000000000153161431512220400175410ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/codegen The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 } from '@sinclair/typebox/guard' import * as Types from '@sinclair/typebox' export namespace TypeScriptCodeGen { function Any(schema: Types.TAny) { return 'any' } function Array(schema: Types.TArray) { const items = Visit(schema.items) return `Array<${items}>` } function Boolean(schema: Types.TBoolean) { return 'boolean' } function Constructor(schema: Types.TConstructor) { const params = schema.parameters.map((param) => Visit(param)).join(', ') const returns = Visit(schema.returns) return `new (${params}) => ${returns}` } function Function(schema: Types.TFunction) { const params = schema.parameters.map((param) => Visit(param)).join(', ') const returns = Visit(schema.returns) return `(${params}) => ${returns}` } function Integer(schema: Types.TInteger) { return 'number' } function Literal(schema: Types.TLiteral) { if (typeof schema.const === 'string') { return `'${schema.const}'` } else { return `${schema.const}` } } function Never(schema: Types.TNever) { return 'never' } function Null(schema: Types.TNull) { return 'null' } function String(schema: Types.TString) { return 'string' } function Number(schema: Types.TNumber) { return 'number' } function Object(schema: Types.TObject) { const properties: string = globalThis.Object.entries(schema.properties) .map(([key, value]) => { return `${key}: ${Visit(value)}` }) .join(',\n') return `{\n${properties}\n}` } function Promise(schema: Types.TPromise) { const item = Visit(schema.item) return `Promise<${item}>` } function Record(schema: Types.TRecord) { for (const [key, value] of globalThis.Object.entries(schema.patternProperties)) { const type = Visit(value) if (key === '^(0|[1-9][0-9]*)$') { return `Record` } else { return `Record` } } throw Error('TypeScriptCodeGen: Unreachable') } function Ref(schema: Types.TRef) { return schema.$ref } function Self(schema: Types.TSelf) { return schema.$ref } function Tuple(schema: Types.TTuple) { if (schema.items === undefined) return `[]` const items = schema.items.map((schema) => Visit(schema)).join(', ') return `[${items}]` } function UInt8Array(schema: Types.TUint8Array) { return `Uint8Array` } function Undefined(schema: Types.TUndefined) { return `undefined` } function Union(schema: Types.TUnion) { return schema.anyOf.map((schema) => Visit(schema)).join(' | ') } function Unknown(schema: Types.TUnknown) { return `unknown` } function Void(schema: Types.TVoid) { return `void` } function Visit(schema: Types.TSchema): string { if (TypeGuard.TAny(schema)) { return Any(schema) } else if (TypeGuard.TArray(schema)) { return Array(schema) } else if (TypeGuard.TBoolean(schema)) { return Boolean(schema) } else if (TypeGuard.TConstructor(schema)) { return Constructor(schema) } else if (TypeGuard.TFunction(schema)) { return Function(schema) } else if (TypeGuard.TInteger(schema)) { return Integer(schema) } else if (TypeGuard.TLiteral(schema)) { return Literal(schema) } else if (TypeGuard.TNever(schema)) { return Never(schema) } else if (TypeGuard.TNull(schema)) { return Null(schema) } else if (TypeGuard.TNumber(schema)) { return Number(schema) } else if (TypeGuard.TObject(schema)) { return Object(schema) } else if (TypeGuard.TPromise(schema)) { return Promise(schema) } else if (TypeGuard.TRecord(schema)) { return Record(schema) } else if (TypeGuard.TRef(schema)) { return Ref(schema) } else if (TypeGuard.TSelf(schema)) { return Self(schema) } else if (TypeGuard.TString(schema)) { return String(schema) } else if (TypeGuard.TTuple(schema)) { return Tuple(schema) } else if (TypeGuard.TUint8Array(schema)) { return UInt8Array(schema) } else if (TypeGuard.TUndefined(schema)) { return Undefined(schema) } else if (TypeGuard.TUnion(schema)) { return Union(schema) } else if (TypeGuard.TUnknown(schema)) { return Unknown(schema) } else if (TypeGuard.TVoid(schema)) { return Void(schema) } else { throw Error('TypeScriptCodeGen: Unknown type') } } function Format(input: string): string { function count(line: string, opens: string[]) { const codes = opens.map((open) => open.charCodeAt(0)) return line .split('') .map((char) => char.charCodeAt(0)) .reduce((acc, current) => { return codes.includes(current) ? acc + 1 : acc }, 0) } let indent = 0 const output: string[] = [] for (const line of input.split('\n').map((n) => n.trim())) { indent -= count(line, ['}']) output.push(`${''.padStart(indent * 2, ' ')}${line}`) indent += count(line, ['{']) } return output.join('\n') } /** Generates TypeScript code from TypeBox types */ export function Generate(schema: Types.TSchema, references: Types.TSchema[] = []) { const result: string[] = [] for (const reference of references) { result.push(`type ${reference.$id} = ${Format([...Visit(reference)].join(''))}`) } result.push(`type ${schema.$id || 'T'} = ${Format([...Visit(schema)].join(''))}`) return result.join('\n\n') } } typebox-0.24.44/example/000077500000000000000000000000001431512220400150045ustar00rootroot00000000000000typebox-0.24.44/example/index.ts000066400000000000000000000010011431512220400164530ustar00rootroot00000000000000import { CodeGen } from '@sinclair/typebox/codegen' import { TypeCompiler } from '@sinclair/typebox/compiler' import { Conditional } from '@sinclair/typebox/conditional' import { TypeGuard } from '@sinclair/typebox/guard' import { Format } from '@sinclair/typebox/format' import { Value, ValuePointer } from '@sinclair/typebox/value' import { Type, Static } from '@sinclair/typebox' const T = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() }) type T = Static console.log(T)typebox-0.24.44/hammer.mjs000066400000000000000000000054441431512220400153440ustar00rootroot00000000000000import { compression, measurement } from './benchmark' import { readFileSync } from 'fs' // ------------------------------------------------------------------------------- // Clean // ------------------------------------------------------------------------------- export async function clean() { 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 benchmark codegen') } // ------------------------------------------------------------------------------- // Start // ------------------------------------------------------------------------------- export async function start(example = 'index') { await shell(`hammer run example/${example}.ts --dist target/example/${example}`) } // ------------------------------------------------------------------------------- // Benchmark // ------------------------------------------------------------------------------- export async function benchmark() { await compression() await measurement() } // ------------------------------------------------------------------------------- // Test // ------------------------------------------------------------------------------- export async function test_static() { 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(target = 'target/build') { await test() await folder(target).delete() await shell(`tsc -p ./src/tsconfig.json --outDir ${target}`) await folder(target).add('package.json') await folder(target).add('readme.md') await folder(target).add('license') await shell(`cd ${target} && npm pack`) } // ------------------------------------------------------------- // Publish // ------------------------------------------------------------- export async function publish(otp, target = 'target/build') { const { version } = JSON.parse(readFileSync('package.json', 'utf8')) 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}`) }typebox-0.24.44/license000066400000000000000000000022561431512220400147230ustar00rootroot00000000000000TypeBox: JSON Schema Type Builder with Static Type Resolution for TypeScript The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.typebox-0.24.44/package-lock.json000066400000000000000000002657721431512220400166100ustar00rootroot00000000000000{ "name": "@sinclair/typebox", "version": "0.24.39", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox", "version": "0.24.39", "license": "MIT", "devDependencies": { "@sinclair/hammer": "^0.17.1", "@types/chai": "^4.3.3", "@types/mocha": "^9.1.1", "@types/node": "^18.7.13", "ajv": "^8.11.0", "ajv-formats": "^2.1.1", "chai": "^4.3.6", "mocha": "^9.2.2", "prettier": "^2.7.1", "typescript": "^4.8.2" } }, "node_modules/@esbuild/linux-loong64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.53.tgz", "integrity": "sha512-W2dAL6Bnyn4xa/QRSU3ilIK4EzD5wgYXKXJiS1HDF5vU3675qc2bvFyLwbUcdmssDveyndy7FbitrCoiV/eMLg==", "cpu": [ "loong64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/@sinclair/hammer": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/@sinclair/hammer/-/hammer-0.17.1.tgz", "integrity": "sha512-/M7KXwCaXdDmBJXQHpn1NWSTUg7Rmx6vzseVOax7IXhsBYj3vEGU5yt/Xh3XdRLVOEcyl4vGWgJ0pL9cmyrTJA==", "dev": true, "dependencies": { "@sinclair/hammer": "^0.17.0", "esbuild": "^0.14.53" }, "bin": { "hammer": "hammer" } }, "node_modules/@types/chai": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", "dev": true }, "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": "18.7.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz", "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==", "dev": true }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, "node_modules/ajv": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "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.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, "engines": { "node": ">=6" } }, "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/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "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/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, "engines": { "node": "*" } }, "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": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { "fill-range": "^7.0.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/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/chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" }, "engines": { "node": ">=4" } }, "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/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", "dev": true, "engines": { "node": "*" } }, "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/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "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/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/debug/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": 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/deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "dependencies": { "type-detect": "^4.0.0" }, "engines": { "node": ">=0.12" } }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, "engines": { "node": ">=0.3.1" } }, "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/esbuild": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.53.tgz", "integrity": "sha512-ohO33pUBQ64q6mmheX1mZ8mIXj8ivQY/L4oVuAshr+aJI+zLl+amrp3EodrUNDNYVrKJXGPfIHFGhO8slGRjuw==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" }, "engines": { "node": ">=12" }, "optionalDependencies": { "@esbuild/linux-loong64": "0.14.53", "esbuild-android-64": "0.14.53", "esbuild-android-arm64": "0.14.53", "esbuild-darwin-64": "0.14.53", "esbuild-darwin-arm64": "0.14.53", "esbuild-freebsd-64": "0.14.53", "esbuild-freebsd-arm64": "0.14.53", "esbuild-linux-32": "0.14.53", "esbuild-linux-64": "0.14.53", "esbuild-linux-arm": "0.14.53", "esbuild-linux-arm64": "0.14.53", "esbuild-linux-mips64le": "0.14.53", "esbuild-linux-ppc64le": "0.14.53", "esbuild-linux-riscv64": "0.14.53", "esbuild-linux-s390x": "0.14.53", "esbuild-netbsd-64": "0.14.53", "esbuild-openbsd-64": "0.14.53", "esbuild-sunos-64": "0.14.53", "esbuild-windows-32": "0.14.53", "esbuild-windows-64": "0.14.53", "esbuild-windows-arm64": "0.14.53" } }, "node_modules/esbuild-android-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.53.tgz", "integrity": "sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "android" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-android-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.53.tgz", "integrity": "sha512-PC7KaF1v0h/nWpvlU1UMN7dzB54cBH8qSsm7S9mkwFA1BXpaEOufCg8hdoEI1jep0KeO/rjZVWrsH8+q28T77A==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "android" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-darwin-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.53.tgz", "integrity": "sha512-gE7P5wlnkX4d4PKvLBUgmhZXvL7lzGRLri17/+CmmCzfncIgq8lOBvxGMiQ4xazplhxq+72TEohyFMZLFxuWvg==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "darwin" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-darwin-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.53.tgz", "integrity": "sha512-otJwDU3hnI15Q98PX4MJbknSZ/WSR1I45il7gcxcECXzfN4Mrpft5hBDHXNRnCh+5858uPXBXA1Vaz2jVWLaIA==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "darwin" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-freebsd-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.53.tgz", "integrity": "sha512-WkdJa8iyrGHyKiPF4lk0MiOF87Q2SkE+i+8D4Cazq3/iqmGPJ6u49je300MFi5I2eUsQCkaOWhpCVQMTKGww2w==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "freebsd" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-freebsd-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.53.tgz", "integrity": "sha512-9T7WwCuV30NAx0SyQpw8edbKvbKELnnm1FHg7gbSYaatH+c8WJW10g/OdM7JYnv7qkimw2ZTtSA+NokOLd2ydQ==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "freebsd" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-32": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.53.tgz", "integrity": "sha512-VGanLBg5en2LfGDgLEUxQko2lqsOS7MTEWUi8x91YmsHNyzJVT/WApbFFx3MQGhkf+XdimVhpyo5/G0PBY91zg==", "cpu": [ "ia32" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz", "integrity": "sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-arm": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz", "integrity": "sha512-/u81NGAVZMopbmzd21Nu/wvnKQK3pT4CrvQ8BTje1STXcQAGnfyKgQlj3m0j2BzYbvQxSy+TMck4TNV2onvoPA==", "cpu": [ "arm" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.53.tgz", "integrity": "sha512-GDmWITT+PMsjCA6/lByYk7NyFssW4Q6in32iPkpjZ/ytSyH+xeEx8q7HG3AhWH6heemEYEWpTll/eui3jwlSnw==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-mips64le": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.53.tgz", "integrity": "sha512-d6/XHIQW714gSSp6tOOX2UscedVobELvQlPMkInhx1NPz4ThZI9uNLQ4qQJHGBGKGfu+rtJsxM4NVHLhnNRdWQ==", "cpu": [ "mips64el" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-ppc64le": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.53.tgz", "integrity": "sha512-ndnJmniKPCB52m+r6BtHHLAOXw+xBCWIxNnedbIpuREOcbSU/AlyM/2dA3BmUQhsHdb4w3amD5U2s91TJ3MzzA==", "cpu": [ "ppc64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-riscv64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.53.tgz", "integrity": "sha512-yG2sVH+QSix6ct4lIzJj329iJF3MhloLE6/vKMQAAd26UVPVkhMFqFopY+9kCgYsdeWvXdPgmyOuKa48Y7+/EQ==", "cpu": [ "riscv64" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-linux-s390x": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.53.tgz", "integrity": "sha512-OCJlgdkB+XPYndHmw6uZT7jcYgzmx9K+28PVdOa/eLjdoYkeAFvH5hTwX4AXGLZLH09tpl4bVsEtvuyUldaNCg==", "cpu": [ "s390x" ], "dev": true, "optional": true, "os": [ "linux" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-netbsd-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.53.tgz", "integrity": "sha512-gp2SB+Efc7MhMdWV2+pmIs/Ja/Mi5rjw+wlDmmbIn68VGXBleNgiEZG+eV2SRS0kJEUyHNedDtwRIMzaohWedQ==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "netbsd" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-openbsd-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.53.tgz", "integrity": "sha512-eKQ30ZWe+WTZmteDYg8S+YjHV5s4iTxeSGhJKJajFfQx9TLZJvsJX0/paqwP51GicOUruFpSUAs2NCc0a4ivQQ==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "openbsd" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-sunos-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.53.tgz", "integrity": "sha512-OWLpS7a2FrIRukQqcgQqR1XKn0jSJoOdT+RlhAxUoEQM/IpytS3FXzCJM6xjUYtpO5GMY0EdZJp+ur2pYdm39g==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "sunos" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-windows-32": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.53.tgz", "integrity": "sha512-m14XyWQP5rwGW0tbEfp95U6A0wY0DYPInWBB7D69FAXUpBpBObRoGTKRv36lf2RWOdE4YO3TNvj37zhXjVL5xg==", "cpu": [ "ia32" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-windows-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.53.tgz", "integrity": "sha512-s9skQFF0I7zqnQ2K8S1xdLSfZFsPLuOGmSx57h2btSEswv0N0YodYvqLcJMrNMXh6EynOmWD7rz+0rWWbFpIHQ==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": ">=12" } }, "node_modules/esbuild-windows-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.53.tgz", "integrity": "sha512-E+5Gvb+ZWts+00T9II6wp2L3KG2r3iGxByqd/a1RmLmYWVsSVUjkvIxZuJ3hYTIbhLkH5PRwpldGTKYqVz0nzQ==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ "win32" ], "engines": { "node": ">=12" } }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "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/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/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "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/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "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/get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", "dev": true, "engines": { "node": "*" } }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "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": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true, "engines": { "node": ">=4.x" } }, "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/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "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/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/loupe": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", "dev": true, "dependencies": { "get-func-name": "^2.0.0" } }, "node_modules/minimatch": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": ">=10" } }, "node_modules/mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "4.2.1", "ms": "2.1.3", "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha" }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mochajs" } }, "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/nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "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/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { "wrappy": "1" } }, "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/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-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, "engines": { "node": "*" } }, "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.7.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "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.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "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/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/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "dependencies": { "randombytes": "^2.1.0" } }, "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/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/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-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/typescript": { "version": "4.8.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=4.2.0" } }, "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/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.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, "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/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "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/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" }, "engines": { "node": ">=10" } }, "node_modules/yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, "engines": { "node": ">=10" } }, "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": { "@esbuild/linux-loong64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.53.tgz", "integrity": "sha512-W2dAL6Bnyn4xa/QRSU3ilIK4EzD5wgYXKXJiS1HDF5vU3675qc2bvFyLwbUcdmssDveyndy7FbitrCoiV/eMLg==", "dev": true, "optional": true }, "@sinclair/hammer": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/@sinclair/hammer/-/hammer-0.17.1.tgz", "integrity": "sha512-/M7KXwCaXdDmBJXQHpn1NWSTUg7Rmx6vzseVOax7IXhsBYj3vEGU5yt/Xh3XdRLVOEcyl4vGWgJ0pL9cmyrTJA==", "dev": true, "requires": { "@sinclair/hammer": "^0.17.0", "esbuild": "^0.14.53" } }, "@types/chai": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", "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": "18.7.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.13.tgz", "integrity": "sha512-46yIhxSe5xEaJZXWdIBP7GU4HDTG8/eo0qd9atdiL+lFpA03y8KS+lkTN834TWJj5767GbWv4n/P6efyTFt1Dw==", "dev": true }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, "ajv": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", "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.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "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" } }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "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 }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "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": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { "fill-range": "^7.0.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 }, "camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, "chai": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", "type-detect": "^4.0.5" } }, "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" } } } }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", "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" } }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.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 }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, "debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "requires": { "ms": "2.1.2" }, "dependencies": { "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true } } }, "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 }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, "requires": { "type-detect": "^4.0.0" } }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "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 }, "esbuild": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.53.tgz", "integrity": "sha512-ohO33pUBQ64q6mmheX1mZ8mIXj8ivQY/L4oVuAshr+aJI+zLl+amrp3EodrUNDNYVrKJXGPfIHFGhO8slGRjuw==", "dev": true, "requires": { "@esbuild/linux-loong64": "0.14.53", "esbuild-android-64": "0.14.53", "esbuild-android-arm64": "0.14.53", "esbuild-darwin-64": "0.14.53", "esbuild-darwin-arm64": "0.14.53", "esbuild-freebsd-64": "0.14.53", "esbuild-freebsd-arm64": "0.14.53", "esbuild-linux-32": "0.14.53", "esbuild-linux-64": "0.14.53", "esbuild-linux-arm": "0.14.53", "esbuild-linux-arm64": "0.14.53", "esbuild-linux-mips64le": "0.14.53", "esbuild-linux-ppc64le": "0.14.53", "esbuild-linux-riscv64": "0.14.53", "esbuild-linux-s390x": "0.14.53", "esbuild-netbsd-64": "0.14.53", "esbuild-openbsd-64": "0.14.53", "esbuild-sunos-64": "0.14.53", "esbuild-windows-32": "0.14.53", "esbuild-windows-64": "0.14.53", "esbuild-windows-arm64": "0.14.53" } }, "esbuild-android-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.53.tgz", "integrity": "sha512-fIL93sOTnEU+NrTAVMIKiAw0YH22HWCAgg4N4Z6zov2t0kY9RAJ50zY9ZMCQ+RT6bnOfDt8gCTnt/RaSNA2yRA==", "dev": true, "optional": true }, "esbuild-android-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.53.tgz", "integrity": "sha512-PC7KaF1v0h/nWpvlU1UMN7dzB54cBH8qSsm7S9mkwFA1BXpaEOufCg8hdoEI1jep0KeO/rjZVWrsH8+q28T77A==", "dev": true, "optional": true }, "esbuild-darwin-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.53.tgz", "integrity": "sha512-gE7P5wlnkX4d4PKvLBUgmhZXvL7lzGRLri17/+CmmCzfncIgq8lOBvxGMiQ4xazplhxq+72TEohyFMZLFxuWvg==", "dev": true, "optional": true }, "esbuild-darwin-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.53.tgz", "integrity": "sha512-otJwDU3hnI15Q98PX4MJbknSZ/WSR1I45il7gcxcECXzfN4Mrpft5hBDHXNRnCh+5858uPXBXA1Vaz2jVWLaIA==", "dev": true, "optional": true }, "esbuild-freebsd-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.53.tgz", "integrity": "sha512-WkdJa8iyrGHyKiPF4lk0MiOF87Q2SkE+i+8D4Cazq3/iqmGPJ6u49je300MFi5I2eUsQCkaOWhpCVQMTKGww2w==", "dev": true, "optional": true }, "esbuild-freebsd-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.53.tgz", "integrity": "sha512-9T7WwCuV30NAx0SyQpw8edbKvbKELnnm1FHg7gbSYaatH+c8WJW10g/OdM7JYnv7qkimw2ZTtSA+NokOLd2ydQ==", "dev": true, "optional": true }, "esbuild-linux-32": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.53.tgz", "integrity": "sha512-VGanLBg5en2LfGDgLEUxQko2lqsOS7MTEWUi8x91YmsHNyzJVT/WApbFFx3MQGhkf+XdimVhpyo5/G0PBY91zg==", "dev": true, "optional": true }, "esbuild-linux-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.53.tgz", "integrity": "sha512-pP/FA55j/fzAV7N9DF31meAyjOH6Bjuo3aSKPh26+RW85ZEtbJv9nhoxmGTd9FOqjx59Tc1ZbrJabuiXlMwuZQ==", "dev": true, "optional": true }, "esbuild-linux-arm": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.53.tgz", "integrity": "sha512-/u81NGAVZMopbmzd21Nu/wvnKQK3pT4CrvQ8BTje1STXcQAGnfyKgQlj3m0j2BzYbvQxSy+TMck4TNV2onvoPA==", "dev": true, "optional": true }, "esbuild-linux-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.53.tgz", "integrity": "sha512-GDmWITT+PMsjCA6/lByYk7NyFssW4Q6in32iPkpjZ/ytSyH+xeEx8q7HG3AhWH6heemEYEWpTll/eui3jwlSnw==", "dev": true, "optional": true }, "esbuild-linux-mips64le": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.53.tgz", "integrity": "sha512-d6/XHIQW714gSSp6tOOX2UscedVobELvQlPMkInhx1NPz4ThZI9uNLQ4qQJHGBGKGfu+rtJsxM4NVHLhnNRdWQ==", "dev": true, "optional": true }, "esbuild-linux-ppc64le": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.53.tgz", "integrity": "sha512-ndnJmniKPCB52m+r6BtHHLAOXw+xBCWIxNnedbIpuREOcbSU/AlyM/2dA3BmUQhsHdb4w3amD5U2s91TJ3MzzA==", "dev": true, "optional": true }, "esbuild-linux-riscv64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.53.tgz", "integrity": "sha512-yG2sVH+QSix6ct4lIzJj329iJF3MhloLE6/vKMQAAd26UVPVkhMFqFopY+9kCgYsdeWvXdPgmyOuKa48Y7+/EQ==", "dev": true, "optional": true }, "esbuild-linux-s390x": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.53.tgz", "integrity": "sha512-OCJlgdkB+XPYndHmw6uZT7jcYgzmx9K+28PVdOa/eLjdoYkeAFvH5hTwX4AXGLZLH09tpl4bVsEtvuyUldaNCg==", "dev": true, "optional": true }, "esbuild-netbsd-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.53.tgz", "integrity": "sha512-gp2SB+Efc7MhMdWV2+pmIs/Ja/Mi5rjw+wlDmmbIn68VGXBleNgiEZG+eV2SRS0kJEUyHNedDtwRIMzaohWedQ==", "dev": true, "optional": true }, "esbuild-openbsd-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.53.tgz", "integrity": "sha512-eKQ30ZWe+WTZmteDYg8S+YjHV5s4iTxeSGhJKJajFfQx9TLZJvsJX0/paqwP51GicOUruFpSUAs2NCc0a4ivQQ==", "dev": true, "optional": true }, "esbuild-sunos-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.53.tgz", "integrity": "sha512-OWLpS7a2FrIRukQqcgQqR1XKn0jSJoOdT+RlhAxUoEQM/IpytS3FXzCJM6xjUYtpO5GMY0EdZJp+ur2pYdm39g==", "dev": true, "optional": true }, "esbuild-windows-32": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.53.tgz", "integrity": "sha512-m14XyWQP5rwGW0tbEfp95U6A0wY0DYPInWBB7D69FAXUpBpBObRoGTKRv36lf2RWOdE4YO3TNvj37zhXjVL5xg==", "dev": true, "optional": true }, "esbuild-windows-64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.53.tgz", "integrity": "sha512-s9skQFF0I7zqnQ2K8S1xdLSfZFsPLuOGmSx57h2btSEswv0N0YodYvqLcJMrNMXh6EynOmWD7rz+0rWWbFpIHQ==", "dev": true, "optional": true }, "esbuild-windows-arm64": { "version": "0.14.53", "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.53.tgz", "integrity": "sha512-E+5Gvb+ZWts+00T9II6wp2L3KG2r3iGxByqd/a1RmLmYWVsSVUjkvIxZuJ3hYTIbhLkH5PRwpldGTKYqVz0nzQ==", "dev": true, "optional": true }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "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 }, "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 }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "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 }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "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 }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", "dev": true }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "dependencies": { "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } } } }, "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" } }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, "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 }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" } }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "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 }, "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" } }, "loupe": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", "dev": true, "requires": { "get-func-name": "^2.0.0" } }, "minimatch": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, "mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "4.2.1", "ms": "2.1.3", "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "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 }, "nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, "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 }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "requires": { "wrappy": "1" } }, "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" } }, "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-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "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.7.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "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" } }, "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 }, "serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.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" } }, "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-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" } }, "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-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, "typescript": { "version": "4.8.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz", "integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==", "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" } }, "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.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, "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" } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, "yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "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 } } } typebox-0.24.44/package.json000066400000000000000000000017541431512220400156460ustar00rootroot00000000000000{ "name": "@sinclair/typebox", "version": "0.24.44", "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript", "keywords": [ "typescript", "json-schema", "validate", "typecheck" ], "author": "sinclairzx81", "license": "MIT", "main": "./typebox.js", "types": "./typebox.d.ts", "repository": { "type": "git", "url": "https://github.com/sinclairzx81/typebox" }, "scripts": { "clean": "hammer task clean", "format": "hammer task format", "start": "hammer task start", "test": "hammer task test", "benchmark": "hammer task benchmark", "build": "hammer task build", "publish": "hammer task publish" }, "devDependencies": { "@sinclair/hammer": "^0.17.1", "@types/chai": "^4.3.3", "@types/mocha": "^9.1.1", "@types/node": "^18.7.13", "ajv": "^8.11.0", "ajv-formats": "^2.1.1", "chai": "^4.3.6", "mocha": "^9.2.2", "prettier": "^2.7.1", "typescript": "^4.8.2" } } typebox-0.24.44/readme.md000066400000000000000000002306331431512220400151370ustar00rootroot00000000000000

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) [![GitHub CI](https://github.com/sinclairzx81/typebox/workflows/GitHub%20CI/badge.svg)](https://github.com/sinclairzx81/typebox/actions)
## Install Node ```bash $ npm install @sinclair/typebox --save ``` Deno and ESM ```typescript import { Static, Type } from 'https://esm.sh/@sinclair/typebox' ``` ## Example ```typescript import { Static, Type } from '@sinclair/typebox' const T = Type.String() // const T = { type: 'string' } type T = Static // type T = string ``` ## Overview TypeBox is a type builder library that creates in-memory JSON Schema objects that can be statically inferred as TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox enables one to create a unified type that can be statically checked by TypeScript and runtime asserted using standard JSON Schema validation. TypeBox is designed to enable JSON schema to compose with the same flexibility as TypeScript's type system. It can be used either as a simple tool to build up complex schemas 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) - [Standard](#types-standard) - [Modifiers](#types-modifiers) - [Options](#types-options) - [Extended](#types-extended) - [Reference](#types-reference) - [Recursive](#types-recursive) - [Generic](#types-generic) - [Conditional](#types-conditional) - [Unsafe](#types-unsafe) - [Guards](#types-guards) - [Strict](#types-strict) - [Values](#values) - [Create](#values-create) - [Clone](#values-clone) - [Check](#values-check) - [Cast](#values-cast) - [Equal](#values-equal) - [Diff](#values-diff) - [Patch](#values-patch) - [Errors](#values-errors) - [Pointer](#values-pointer) - [TypeCheck](#typecheck) - [Ajv](#typecheck-ajv) - [Compiler](#typecheck-compiler) - [Formats](#typecheck-formats) - [Benchmark](#benchmark) - [Compile](#benchmark-compile) - [Validate](#benchmark-validate) - [Compression](#benchmark-compression) - [Contribute](#contribute) ## Usage The following demonstrates TypeBox's general usage. ```typescript import { Static, Type } 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 // } //-------------------------------------------------------------------------------------------- // // ... then use the type both as JSON schema and as a TypeScript type. // //-------------------------------------------------------------------------------------------- function receive(value: T) { // ... as a Type if(JSON.validate(T, value)) { // ... as a Schema // ok... } } ``` ## Types TypeBox provides a set of functions that allow you to compose JSON Schema similar to how you would compose static types with TypeScript. Each function creates a JSON schema fragment which can compose into more complex types. The schemas produced by TypeBox can be passed directly to any JSON Schema compliant validator, or used to reflect runtime metadata for a type. ### Standard The following table lists the standard TypeBox types. ```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.RegEx(/foo/) │ type T = string │ const T = { │ │ │ │ type: 'string', │ │ │ │ pattern: 'foo' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ 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 │ properties: { │ │ }) │ } │ x: { │ │ │ │ type: 'number' │ │ │ │ }, │ │ │ │ y: { │ │ │ │ type: 'number' │ │ │ │ } │ │ │ │ }, │ │ │ │ required: ['x', 'y'] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ 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.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 │ type: 'object', │ │ x: Type.Number() │ } & { │ properties: { │ │ }), │ y: number │ x: { │ │ Type.Object({ │ } │ type: 'number' │ │ y: Type.Number() │ │ }, │ │ }) │ │ y: { │ │ ]) │ │ type: 'number' │ │ │ │ } │ │ │ │ }, │ │ │ │ required: ['x', 'y'] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Never() │ type T = never │ const T = { │ │ │ │ allOf: [{ │ │ │ │ type: 'boolean', │ │ │ │ const: false │ │ │ │ }, { │ │ │ │ type: 'boolean', │ │ │ │ const: true │ │ │ │ }] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ 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 │ properties: { │ │ Type.Number() | }> │ x: { │ │ ), │ │ type: 'number' │ │ y: Type.Optional( │ │ }, │ │ Type.Number() │ │ y: { │ │ ) │ │ type: 'number' │ │ }) │ │ } │ │ ) │ │ }, │ │ │ │ required: ['x', 'y'] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Pick( │ type T = Pick<{ │ const T = { │ │ Type.Object({ │ x: number, │ type: 'object', │ │ x: Type.Number(), │ y: number │ properties: { │ │ y: Type.Number() | }, 'x'> │ x: { │ │ }), ['x'] │ │ type: 'number' │ │ ) │ │ } │ │ │ │ }, │ │ │ │ required: ['x'] │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Omit( │ type T = Omit<{ │ const T = { │ │ Type.Object({ │ x: number, │ type: 'object', │ │ x: Type.Number(), │ y: number │ properties: { │ │ y: Type.Number() | }, 'x'> │ y: { │ │ }), ['x'] │ │ type: 'number' │ │ ) │ │ } │ │ │ │ }, │ │ │ │ required: ['y'] │ │ │ │ } │ │ │ │ │ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘ ``` ### Modifiers TypeBox provides modifiers that can be applied to an objects properties. This allows for `optional` and `readonly` to be applied to that property. The following table illustates how they map between TypeScript and JSON Schema. ```typescript ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐ │ TypeBox │ TypeScript │ JSON Schema │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Object({ │ type T = { │ const T = { │ │ name: Type.Optional( │ 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.ReadonlyOptional( │ readonly name?: string │ type: 'object', │ │ Type.String() │ } │ properties: { │ │ ) │ │ name: { │ │ }) │ │ type: 'string' │ │ │ │ } │ │ │ │ } │ │ │ │ } │ │ │ │ │ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘ ``` ### Options You can pass additional JSON schema options on the last argument of any given type. The following are some examples. ```typescript // string must be an email const T = Type.String({ format: 'email' }) // number must be a multiple of 2 const T = Type.Number({ multipleOf: 2 }) // array must have at least 5 integer values const T = Type.Array(Type.Integer(), { minItems: 5 }) ``` ### Extended In addition to JSON schema types, TypeBox provides several extended types that allow for the composition of `function` and `constructor` types. These additional types are not valid JSON Schema and will not validate using typical JSON Schema validation. However, these types can be used to frame JSON schema and describe callable interfaces that may receive JSON validated data. These types are as follows. ```typescript ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐ │ TypeBox │ TypeScript │ Extended Schema │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Constructor([ │ type T = new ( │ const T = { │ │ Type.String(), │ arg0: string, │ type: 'constructor' │ │ Type.Number() │ arg1: number │ parameters: [{ │ │ ], Type.Boolean()) │ ) => boolean │ type: 'string' │ │ │ │ }, { │ │ │ │ type: 'number' │ │ │ │ }], │ │ │ │ return: { │ │ │ │ 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' │ │ │ │ }], │ │ │ │ return: { │ │ │ │ type: 'boolean' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Uint8Array() │ type T = Uint8Array │ const T = { │ │ │ │ type: 'object', │ │ │ │ specialized: 'Uint8Array' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Promise( │ type T = Promise │ const T = { │ │ Type.String() │ │ type: 'promise', │ │ ) │ │ item: { │ │ │ │ type: 'string' │ │ │ │ } │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Undefined() │ type T = undefined │ const T = { │ │ │ │ type: 'object', │ │ │ │ specialized: 'Undefined' │ │ │ │ } │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Type.Void() │ type T = void │ const T = { │ │ │ │ type: 'null' │ │ │ │ } │ │ │ │ │ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘ ``` ### Reference Use `Type.Ref(...)` to create referenced types. The target type must specify an `$id`. ```typescript const T = Type.String({ $id: 'T' }) // const T = { // $id: 'T', // type: 'string' // } const R = Type.Ref(T) // const R = { // $ref: 'T' // } ``` ### Recursive Use `Type.Recursive(...)` to create recursive types. ```typescript const Node = Type.Recursive(Node => Type.Object({ // const Node = { id: Type.String(), // $id: 'Node', nodes: Type.Array(Node) // 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 is string .nodes[0].nodes[0] .id } ``` ### Generic Use functions to create generic types. The following creates a generic `Nullable` type. ```typescript import { Type, Static, TSchema } from '@sinclair/typebox' const Nullable = (type: T) => Type.Union([type, Type.Null()]) const T = Nullable(Type.String()) // const T = { // anyOf: [{ // type: 'string' // }, { // type: 'null' // }] // } type T = Static // type T = string | null const U = Nullable(Type.Number()) // const U = { // anyOf: [{ // type: 'number' // }, { // type: 'null' // }] // } type U = Static // type U = number | null ``` ### Conditional Use the conditional module to create [Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html). This module implements TypeScript's structural equivalence checks to enable TypeBox types to be conditionally inferred at runtime. This module also provides the [Extract](https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union) and [Exclude](https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers) utility types which are expressed as conditional types in TypeScript. The conditional module is provided as an optional import. ```typescript import { Conditional } from '@sinclair/typebox/conditional' ``` The following table shows the TypeBox mappings between TypeScript and JSON schema. ```typescript ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐ │ TypeBox │ TypeScript │ JSON Schema │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Conditional.Extends( │ type T = │ const T = { │ │ Type.String(), │ string extends number │ const: false, │ │ Type.Number(), │ true : false │ type: 'boolean' │ │ Type.Literal(true), │ │ } │ │ Type.Literal(false) │ │ │ │ ) │ │ │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Conditional.Extract( │ type T = Extract< │ const T = { │ │ Type.Union([ │ 'a' | 'b' | 'c', │ anyOf: [{ │ │ Type.Literal('a'), │ 'a' | 'f' │ const: 'a' │ │ Type.Literal('b'), │ > │ type: 'string' │ │ Type.Literal('c') │ │ }] │ │ ]), │ │ } │ │ Type.Union([ │ │ │ │ Type.Literal('a'), │ │ │ │ Type.Literal('f') │ │ │ │ ]) │ │ │ │ ) │ │ │ │ │ │ │ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤ │ const T = Conditional.Exclude( │ type T = Exclude< │ const T = { │ │ Type.Union([ │ 'a' | 'b' | 'c', │ anyOf: [{ │ │ Type.Literal('a'), │ 'a' │ const: 'b', │ │ Type.Literal('b'), │ > │ type: 'string' │ │ Type.Literal('c') │ │ }, { │ │ ]), │ │ const: 'c', │ │ Type.Union([ │ │ type: 'string' │ │ Type.Literal('a') │ │ }] │ │ ]) │ │ } │ │ ) │ │ │ │ │ │ │ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘ ``` ### Unsafe Use `Type.Unsafe(...)` to create custom schemas with user defined inference rules. ```typescript const T = Type.Unsafe({ type: 'number' }) // const T = { // type: 'number' // } type T = Static // type T = string ``` This function can be used to create custom schemas for validators that require specific schema representations. An example of this might be OpenAPI's `nullable` and `enum` schemas which are not provided by TypeBox. The following demonstrates using `Type.Unsafe(...)` to create these types. ```typescript import { Type, Static, TSchema } from '@sinclair/typebox' //-------------------------------------------------------------------------------------------- // // Nullable // //-------------------------------------------------------------------------------------------- function Nullable(schema: T) { return Type.Unsafe | null>({ ...schema, nullable: true }) } const T = Nullable(Type.String()) // const T = { // type: 'string', // nullable: true // } type T = Static // type T = string | null //-------------------------------------------------------------------------------------------- // // StringEnum // //-------------------------------------------------------------------------------------------- function StringEnum(values: [...T]) { return Type.Unsafe({ type: 'string', enum: values }) } const T = StringEnum(['A', 'B', 'C']) // const T = { // enum: ['A', 'B', 'C'] // } type T = Static // type T = 'A' | 'B' | 'C' ``` ### Guards Use the guard module to test if values are TypeBox types. ```typescript import { TypeGuard } from '@sinclair/typebox/guard' const T = Type.String() if(TypeGuard.TString(T)) { // T is TString } ``` ### Strict TypeBox schemas contain the `Kind` and `Modifier` symbol properties. These properties are provided to enable runtime type reflection on schemas, as well as helping TypeBox internally compose types. These properties are not strictly valid JSON schema; so in some cases it may be desirable to omit them. TypeBox provides a `Type.Strict()` function that will omit these properties if necessary. ```typescript const T = Type.Object({ // const T = { name: Type.Optional(Type.String()) // [Kind]: 'Object', }) // type: 'object', // properties: { // name: { // [Kind]: 'String', // type: 'string', // [Modifier]: 'Optional' // } // } // } const U = Type.Strict(T) // const U = { // type: 'object', // properties: { // name: { // type: 'string' // } // } // } ``` ## Values TypeBox includes an optional values module that can be used to perform common operations on JavaScript values. This module enables one to create, check and cast values from types. It also provides functionality to check equality, clone and diff and patch JavaScript values. The value module is provided as an optional import. ```typescript import { Value } from '@sinclair/typebox/value' ``` ### Create Use the Create function to create a value from a TypeBox 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 ``` ### Cast Use the Cast function to cast a value into a type. The cast function will retain as much information as possible from the original value. ```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 } ``` ### 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 } ) ``` ### Diff Use the Diff function to produce a sequence of edits to 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 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 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' // }] ``` ### 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) // const A = { x: 1, y: 0, z: 0 } ValuePointer.Set(A, '/y', 1) // const A = { x: 1, y: 1, z: 0 } ValuePointer.Set(A, '/z', 1) // const A = { x: 1, y: 1, z: 1 } ``` ## TypeCheck TypeBox is written to target JSON Schema Draft 6 and can be used with any Draft 6 compliant validator. TypeBox is developed and tested against Ajv and can be used in any application already making use of this validator. Additionally, TypeBox also provides an optional type compiler that can be used to attain improved compilation and validation performance for certain application types. ### Ajv The following example shows setting up Ajv to work with TypeBox. ```bash $ npm install ajv ajv-formats --save ``` ```typescript import { Type } from '@sinclair/typebox' import addFormats from 'ajv-formats' import Ajv from 'ajv' //-------------------------------------------------------------------------------------------- // // Setup Ajv validator with the following options and formats // //-------------------------------------------------------------------------------------------- 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' ]) //-------------------------------------------------------------------------------------------- // // Create a TypeBox type // //-------------------------------------------------------------------------------------------- const T = Type.Object({ x: Type.Number(), y: Type.Number(), z: Type.Number() }) //-------------------------------------------------------------------------------------------- // // Validate Data // //-------------------------------------------------------------------------------------------- const R = ajv.validate(T, { x: 1, y: 2, z: 3 }) // const R = true ``` ### Compiler TypeBox provides an optional high performance just-in-time (JIT) compiler and type checker that can be used in applications that require extremely fast validation. Note that this compiler is optimized for TypeBox types only where the schematics are known in advance. If defining custom types with `Type.Unsafe` please consider Ajv. The compiler module is provided as an optional import. ```typescript import { TypeCompiler } from '@sinclair/typebox/compiler' ``` Use the `Compile(...)` function to compile a type. ```typescript const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck> const R = C.Check({ x: 1, y: 2, z: 3 }) // const R = true ``` Validation errors can be read with the `Errors(...)` function. ```typescript const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck> const value = { } const errors = [...C.Errors(value)] // const errors = [{ // 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' // }] ``` Compiled routines can be inspected with the `.Code()` function. ```typescript const C = TypeCompiler.Compile(Type.String()) // const C: TypeCheck console.log(C.Code()) // return function check(value) { // return ( // (typeof value === 'string') // ) // } ``` ### Formats Use the format module to create user defined string formats. The format module is used by the Value and TypeCompiler modules only. If using Ajv, please refer to the official Ajv format documentation located [here](https://ajv.js.org/guide/formats.html). The format module is an optional import. ```typescript import { Format } from '@sinclair/typebox/format' ``` The following creates a `palindrome` string format. ```typescript Format.Set('palindrome', value => value === value.split('').reverse().join('')) ``` Once set, this format can then be used by the TypeCompiler and Value modules. ```typescript const T = Type.String({ format: 'palindrome' }) const A = TypeCompiler.Compile(T).Check('engine') // const A = false const B = Value.Check(T, 'kayak') // const B = true ``` ## 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.11.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. You can review this benchmark [here](https://github.com/sinclairzx81/typebox/blob/master/benchmark/measurement/module/compile.ts). ```typescript ┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┐ │ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │ ├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┤ │ Number │ 2000 │ ' 384 ms' │ ' 9 ms' │ ' 42.67 x' │ │ String │ 2000 │ ' 322 ms' │ ' 8 ms' │ ' 40.25 x' │ │ Boolean │ 2000 │ ' 310 ms' │ ' 6 ms' │ ' 51.67 x' │ │ Null │ 2000 │ ' 271 ms' │ ' 6 ms' │ ' 45.17 x' │ │ RegEx │ 2000 │ ' 491 ms' │ ' 12 ms' │ ' 40.92 x' │ │ ObjectA │ 2000 │ ' 2935 ms' │ ' 44 ms' │ ' 66.70 x' │ │ ObjectB │ 2000 │ ' 3076 ms' │ ' 30 ms' │ ' 102.53 x' │ │ Tuple │ 2000 │ ' 1274 ms' │ ' 22 ms' │ ' 57.91 x' │ │ Union │ 2000 │ ' 1281 ms' │ ' 22 ms' │ ' 58.23 x' │ │ Vector4 │ 2000 │ ' 1602 ms' │ ' 17 ms' │ ' 94.24 x' │ │ Matrix4 │ 2000 │ ' 959 ms' │ ' 10 ms' │ ' 95.90 x' │ │ Literal_String │ 2000 │ ' 337 ms' │ ' 6 ms' │ ' 56.17 x' │ │ Literal_Number │ 2000 │ ' 376 ms' │ ' 5 ms' │ ' 75.20 x' │ │ Literal_Boolean │ 2000 │ ' 370 ms' │ ' 5 ms' │ ' 74.00 x' │ │ Array_Number │ 2000 │ ' 733 ms' │ ' 9 ms' │ ' 81.44 x' │ │ Array_String │ 2000 │ ' 764 ms' │ ' 10 ms' │ ' 76.40 x' │ │ Array_Boolean │ 2000 │ ' 818 ms' │ ' 6 ms' │ ' 136.33 x' │ │ Array_ObjectA │ 2000 │ ' 3744 ms' │ ' 35 ms' │ ' 106.97 x' │ │ Array_ObjectB │ 2000 │ ' 3893 ms' │ ' 34 ms' │ ' 114.50 x' │ │ Array_Tuple │ 2000 │ ' 2229 ms' │ ' 16 ms' │ ' 139.31 x' │ │ Array_Union │ 2000 │ ' 1705 ms' │ ' 18 ms' │ ' 94.72 x' │ │ Array_Vector4 │ 2000 │ ' 2261 ms' │ ' 17 ms' │ ' 133.00 x' │ │ Array_Matrix4 │ 2000 │ ' 1574 ms' │ ' 14 ms' │ ' 112.43 x' │ └──────────────────┴────────────┴──────────────┴──────────────┴──────────────┘ ``` ### Validate This benchmark measures validation performance for varying types. You can review this benchmark [here](https://github.com/sinclairzx81/typebox/blob/master/benchmark/measurement/module/check.ts). ```typescript ┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┬──────────────┐ │ (index) │ Iterations │ ValueCheck │ Ajv │ TypeCompiler │ Performance │ ├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┼──────────────┤ │ Number │ 1000000 │ ' 37 ms' │ ' 5 ms' │ ' 5 ms' │ ' 1.00 x' │ │ String │ 1000000 │ ' 31 ms' │ ' 24 ms' │ ' 13 ms' │ ' 1.85 x' │ │ Boolean │ 1000000 │ ' 25 ms' │ ' 25 ms' │ ' 11 ms' │ ' 2.27 x' │ │ Null │ 1000000 │ ' 32 ms' │ ' 26 ms' │ ' 10 ms' │ ' 2.60 x' │ │ RegEx │ 1000000 │ ' 170 ms' │ ' 48 ms' │ ' 35 ms' │ ' 1.37 x' │ │ ObjectA │ 1000000 │ ' 564 ms' │ ' 36 ms' │ ' 23 ms' │ ' 1.57 x' │ │ ObjectB │ 1000000 │ ' 1000 ms' │ ' 56 ms' │ ' 40 ms' │ ' 1.40 x' │ │ Tuple │ 1000000 │ ' 125 ms' │ ' 27 ms' │ ' 13 ms' │ ' 2.08 x' │ │ Union │ 1000000 │ ' 316 ms' │ ' 27 ms' │ ' 14 ms' │ ' 1.93 x' │ │ Recursive │ 1000000 │ ' 3308 ms' │ ' 415 ms' │ ' 183 ms' │ ' 2.27 x' │ │ Vector4 │ 1000000 │ ' 135 ms' │ ' 27 ms' │ ' 12 ms' │ ' 2.25 x' │ │ Matrix4 │ 1000000 │ ' 658 ms' │ ' 44 ms' │ ' 30 ms' │ ' 1.47 x' │ │ Literal_String │ 1000000 │ ' 48 ms' │ ' 26 ms' │ ' 10 ms' │ ' 2.60 x' │ │ Literal_Number │ 1000000 │ ' 49 ms' │ ' 31 ms' │ ' 9 ms' │ ' 3.44 x' │ │ Literal_Boolean │ 1000000 │ ' 47 ms' │ ' 28 ms' │ ' 10 ms' │ ' 2.80 x' │ │ Array_Number │ 1000000 │ ' 418 ms' │ ' 38 ms' │ ' 17 ms' │ ' 2.24 x' │ │ Array_String │ 1000000 │ ' 466 ms' │ ' 35 ms' │ ' 22 ms' │ ' 1.59 x' │ │ Array_Boolean │ 1000000 │ ' 403 ms' │ ' 41 ms' │ ' 24 ms' │ ' 1.71 x' │ │ Array_ObjectA │ 1000000 │ ' 13596 ms' │ ' 2861 ms' │ ' 1759 ms' │ ' 1.63 x' │ │ Array_ObjectB │ 1000000 │ ' 15767 ms' │ ' 2798 ms' │ ' 1991 ms' │ ' 1.41 x' │ │ Array_Tuple │ 1000000 │ ' 1666 ms' │ ' 103 ms' │ ' 73 ms' │ ' 1.41 x' │ │ Array_Union │ 1000000 │ ' 4738 ms' │ ' 229 ms' │ ' 87 ms' │ ' 2.63 x' │ │ Array_Recursive │ 1000000 │ ' 56371 ms' │ ' 7315 ms' │ ' 2813 ms' │ ' 2.60 x' │ │ Array_Vector4 │ 1000000 │ ' 2180 ms' │ ' 106 ms' │ ' 53 ms' │ ' 2.00 x' │ │ Array_Matrix4 │ 1000000 │ ' 11795 ms' │ ' 384 ms' │ ' 313 ms' │ ' 1.23 x' │ └──────────────────┴────────────┴──────────────┴──────────────┴──────────────┴──────────────┘ ``` ### Compression The following table lists esbuild compiled and minified sizes for each TypeBox module. ```typescript ┌──────────────────────┬────────────┬────────────┬─────────────┐ │ (index) │ Compiled │ Minified │ Compression │ ├──────────────────────┼────────────┼────────────┼─────────────┤ │ typebox/compiler │ ' 49 kb' │ ' 24 kb' │ '2.00 x' │ │ typebox/conditional │ ' 42 kb' │ ' 17 kb' │ '2.46 x' │ │ typebox/format │ ' 0 kb' │ ' 0 kb' │ '2.66 x' │ │ typebox/guard │ ' 21 kb' │ ' 10 kb' │ '2.07 x' │ │ typebox/value │ ' 72 kb' │ ' 33 kb' │ '2.16 x' │ │ typebox │ ' 11 kb' │ ' 6 kb' │ '1.91 x' │ └──────────────────────┴────────────┴────────────┴─────────────┘ ``` ## Contribute TypeBox is open to community contribution. Please ensure you submit an open issue before submitting your pull request. The TypeBox project preferences open community discussion prior to accepting new features. typebox-0.24.44/src/000077500000000000000000000000001431512220400141405ustar00rootroot00000000000000typebox-0.24.44/src/compiler/000077500000000000000000000000001431512220400157525ustar00rootroot00000000000000typebox-0.24.44/src/compiler/compiler.ts000066400000000000000000000407211431512220400201400ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/compiler The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 { ValueErrors, ValueError } from '../errors/index' import { TypeGuard } from '../guard/index' import { Format } from '../format/index' import * as Types from '../typebox' // ------------------------------------------------------------------- // CheckFunction // ------------------------------------------------------------------- export type CheckFunction = (value: unknown) => boolean // ------------------------------------------------------------------- // TypeCheck // ------------------------------------------------------------------- export class TypeCheck { constructor(private readonly schema: T, private readonly references: Types.TSchema[], private readonly checkFunc: CheckFunction, private readonly code: string) {} /** Returns the generated validation code used to validate this type. */ public Code(): string { return this.code } /** Returns an iterator for each error in this value. */ public Errors(value: unknown): IterableIterator { return ValueErrors.Errors(this.schema, this.references, value) } /** Returns true if the value matches the given type. */ public Check(value: unknown): value is Types.Static { return this.checkFunc(value) } } // ------------------------------------------------------------------- // Property // ------------------------------------------------------------------- export namespace Property { function DollarSign(code: number) { return code === 36 } function Underscore(code: number) { return code === 95 } function Numeric(code: number) { return code >= 48 && code <= 57 } function Alpha(code: number) { return (code >= 65 && code <= 90) || (code >= 97 && code <= 122) } export function Check(propertyName: string) { if (propertyName.length === 0) return false { const code = propertyName.charCodeAt(0) if (!(DollarSign(code) || Underscore(code) || Alpha(code))) { return false } } for (let i = 1; i < propertyName.length; i++) { const code = propertyName.charCodeAt(i) if (!(DollarSign(code) || Underscore(code) || Alpha(code) || Numeric(code))) { return false } } return true } } // ------------------------------------------------------------------- // TypeCompiler // ------------------------------------------------------------------- export class TypeCompilerUnknownTypeError extends Error { constructor(public readonly schema: Types.TSchema) { super('TypeCompiler: Unknown type') } } /** Compiles Types for Runtime Type Checking */ export namespace TypeCompiler { // ------------------------------------------------------------------- // Types // ------------------------------------------------------------------- function* Any(schema: Types.TAny, value: string): IterableIterator { yield '(true)' } function* Array(schema: Types.TArray, value: string): IterableIterator { const expression = CreateExpression(schema.items, 'value') if (schema.minItems !== undefined) yield `(${value}.length >= ${schema.minItems})` if (schema.maxItems !== undefined) yield `(${value}.length <= ${schema.maxItems})` if (schema.uniqueItems !== undefined) yield `(new Set(${value}).size === ${value}.length)` yield `(Array.isArray(${value}) && ${value}.every(value => ${expression}))` } function* Boolean(schema: Types.TBoolean, value: string): IterableIterator { yield `(typeof ${value} === 'boolean')` } function* Constructor(schema: Types.TConstructor, value: string): IterableIterator { yield* Visit(schema.returns, `${value}.prototype`) } function* Function(schema: Types.TFunction, value: string): IterableIterator { yield `(typeof ${value} === 'function')` } function* Integer(schema: Types.TNumeric, value: string): IterableIterator { yield `(typeof ${value} === 'number' && Number.isInteger(${value}))` if (schema.multipleOf !== undefined) yield `(${value} % ${schema.multipleOf} === 0)` if (schema.exclusiveMinimum !== undefined) yield `(${value} > ${schema.exclusiveMinimum})` if (schema.exclusiveMaximum !== undefined) yield `(${value} < ${schema.exclusiveMaximum})` if (schema.minimum !== undefined) yield `(${value} >= ${schema.minimum})` if (schema.maximum !== undefined) yield `(${value} <= ${schema.maximum})` } function* Literal(schema: Types.TLiteral, value: string): IterableIterator { if (typeof schema.const === 'number' || typeof schema.const === 'boolean') { yield `(${value} === ${schema.const})` } else { yield `(${value} === '${schema.const}')` } } function* Never(schema: Types.TNull, value: string): IterableIterator { yield `(false)` } function* Null(schema: Types.TNull, value: string): IterableIterator { yield `(${value} === null)` } function* Number(schema: Types.TNumeric, value: string): IterableIterator { yield `(typeof ${value} === 'number')` if (schema.multipleOf !== undefined) yield `(${value} % ${schema.multipleOf} === 0)` if (schema.exclusiveMinimum !== undefined) yield `(${value} > ${schema.exclusiveMinimum})` if (schema.exclusiveMaximum !== undefined) yield `(${value} < ${schema.exclusiveMaximum})` if (schema.minimum !== undefined) yield `(${value} >= ${schema.minimum})` if (schema.maximum !== undefined) yield `(${value} <= ${schema.maximum})` } function* Object(schema: Types.TObject, value: string): IterableIterator { yield `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))` if (schema.minProperties !== undefined) yield `(Object.keys(${value}).length >= ${schema.minProperties})` if (schema.maxProperties !== undefined) yield `(Object.keys(${value}).length <= ${schema.maxProperties})` const propertyKeys = globalThis.Object.keys(schema.properties) if (schema.additionalProperties === false) { // Optimization: If the property key length matches the required keys length // then we only need check that the values property key length matches that // of the property key length. This is because exhaustive testing for values // will occur in subsequent property tests. if (schema.required && schema.required.length === propertyKeys.length) { yield `(Object.keys(${value}).length === ${propertyKeys.length})` } else { const keys = `[${propertyKeys.map((key) => `'${key}'`).join(', ')}]` yield `(Object.keys(${value}).every(key => ${keys}.includes(key)))` } } for (const propertyKey of propertyKeys) { const memberExpression = Property.Check(propertyKey) ? `${value}.${propertyKey}` : `${value}['${propertyKey}']` const propertySchema = schema.properties[propertyKey] if (schema.required && schema.required.includes(propertyKey)) { yield* Visit(propertySchema, memberExpression) } else { const expression = CreateExpression(propertySchema, memberExpression) yield `(${memberExpression} === undefined ? true : (${expression}))` } } } function* Promise(schema: Types.TPromise, value: string): IterableIterator { yield `(typeof value === 'object' && typeof ${value}.then === 'function')` } function* Record(schema: Types.TRecord, value: string): IterableIterator { yield `(typeof ${value} === 'object' && ${value} !== null && !Array.isArray(${value}))` const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0] const local = PushLocal(`new RegExp(/${keyPattern}/)`) yield `(Object.keys(${value}).every(key => ${local}.test(key)))` const expression = CreateExpression(valueSchema, 'value') yield `(Object.values(${value}).every(value => ${expression}))` } function* Ref(schema: Types.TRef, value: string): IterableIterator { // 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. Consider for refactor. if (names.has(schema.$ref)) return yield `(${CreateFunctionName(schema.$ref)}(${value}))` if (!referenceMap.has(schema.$ref)) throw Error(`TypeCompiler.Ref: Cannot de-reference schema with $id '${schema.$ref}'`) const reference = referenceMap.get(schema.$ref)! yield* Visit(reference, value) } function* Self(schema: Types.TSelf, value: string): IterableIterator { const func = CreateFunctionName(schema.$ref) yield `(${func}(${value}))` } function* String(schema: Types.TString, value: string): IterableIterator { yield `(typeof ${value} === 'string')` if (schema.minLength !== undefined) { yield `(${value}.length >= ${schema.minLength})` } if (schema.maxLength !== undefined) { yield `(${value}.length <= ${schema.maxLength})` } if (schema.pattern !== undefined) { const local = PushLocal(`new RegExp(/${schema.pattern}/);`) yield `(${local}.test(${value}))` } if (schema.format !== undefined) { yield `(format('${schema.format}', ${value}))` } } function* Tuple(schema: Types.TTuple, 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], `${value}[${i}]`) yield `(${expression})` } } function* Undefined(schema: Types.TUndefined, value: string): IterableIterator { yield `(${value} === undefined)` } function* Union(schema: Types.TUnion, value: string): IterableIterator { const expressions = schema.anyOf.map((schema: Types.TSchema) => CreateExpression(schema, value)) yield `(${expressions.join(' || ')})` } function* Uint8Array(schema: Types.TUint8Array, value: string): IterableIterator { yield `(${value} instanceof Uint8Array)` if (schema.maxByteLength) yield `(${value}.length <= ${schema.maxByteLength})` if (schema.minByteLength) yield `(${value}.length >= ${schema.minByteLength})` } function* Unknown(schema: Types.TUnknown, value: string): IterableIterator { yield '(true)' } function* Void(schema: Types.TVoid, value: string): IterableIterator { yield `(${value} === null)` } function* Visit(schema: T, value: string): IterableIterator { // Reference: Referenced schemas can originate from either additional schemas // or inline in the schema itself. Ideally the recursive path should align to // reference path. Consider for refactor. if (schema.$id && !names.has(schema.$id)) { names.add(schema.$id) const name = CreateFunctionName(schema.$id) const body = CreateFunction(name, schema, 'value') PushFunction(body) yield `(${name}(${value}))` return } const anySchema = schema as any switch (anySchema[Types.Kind]) { case 'Any': return yield* Any(anySchema, value) case 'Array': return yield* Array(anySchema, value) case 'Boolean': return yield* Boolean(anySchema, value) case 'Constructor': return yield* Constructor(anySchema, value) case 'Function': return yield* Function(anySchema, value) case 'Integer': return yield* Integer(anySchema, value) case 'Literal': return yield* Literal(anySchema, value) case 'Never': return yield* Never(anySchema, value) case 'Null': return yield* Null(anySchema, value) case 'Number': return yield* Number(anySchema, value) case 'Object': return yield* Object(anySchema, value) case 'Promise': return yield* Promise(anySchema, value) case 'Record': return yield* Record(anySchema, value) case 'Ref': return yield* Ref(anySchema, value) case 'Self': return yield* Self(anySchema, value) case 'String': return yield* String(anySchema, value) case 'Tuple': return yield* Tuple(anySchema, value) case 'Undefined': return yield* Undefined(anySchema, value) case 'Union': return yield* Union(anySchema, value) case 'Uint8Array': return yield* Uint8Array(anySchema, value) case 'Unknown': return yield* Unknown(anySchema, value) case 'Void': return yield* Void(anySchema, value) default: throw new TypeCompilerUnknownTypeError(schema) } } // ------------------------------------------------------------------- // Compile State // ------------------------------------------------------------------- const referenceMap = new Map() const locals = new Set() // local variables and functions const names = new Set() // cache of local functions function ResetCompiler() { referenceMap.clear() locals.clear() names.clear() } function AddReferences(schemas: Types.TSchema[] = []) { for (const schema of schemas) { if (!schema.$id) throw new Error(`TypeCompiler: Referenced schemas must specify an $id.`) if (referenceMap.has(schema.$id)) throw new Error(`TypeCompiler: Duplicate schema $id found for '${schema.$id}'`) referenceMap.set(schema.$id, schema) } } function CreateExpression(schema: Types.TSchema, value: string): string { return [...Visit(schema, value)].join(' && ') } function CreateFunctionName($id: string) { return `check_${$id.replace(/-/g, '_')}` } function CreateFunction(name: string, schema: Types.TSchema, value: string): string { const expression = [...Visit(schema, value)].map((condition) => ` ${condition}`).join(' &&\n') return `function ${name}(value) {\n return (\n${expression}\n )\n}` } function PushFunction(functionBody: string) { locals.add(functionBody) } function PushLocal(expression: string) { const local = `local_${locals.size}` locals.add(`const ${local} = ${expression}`) return local } function GetLocals() { return [...locals.values()] } // ------------------------------------------------------------------- // Compile // ------------------------------------------------------------------- function Build(schema: T, references: Types.TSchema[] = []): string { ResetCompiler() AddReferences(references) const check = CreateFunction('check', schema, 'value') const locals = GetLocals() return `${locals.join('\n')}\nreturn ${check}` } /** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */ export function Compile(schema: T, references: Types.TSchema[] = []): TypeCheck { TypeGuard.Assert(schema, references) const code = Build(schema, references) const func1 = globalThis.Function('format', code) const func2 = func1((format: string, value: string) => { if (!Format.Has(format)) return false const func = Format.Get(format)! return func(value) }) return new TypeCheck(schema, references, func2, code) } } typebox-0.24.44/src/compiler/index.ts000066400000000000000000000025621431512220400174360ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/compiler The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 } from '../errors/index' export * from './compiler' typebox-0.24.44/src/conditional/000077500000000000000000000000001431512220400164435ustar00rootroot00000000000000typebox-0.24.44/src/conditional/conditional.ts000066400000000000000000000122101431512220400213120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/conditional The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '../typebox' import { Structural, StructuralResult } from './structural' import { TypeGuard } from '../guard/index' // ------------------------------------------------------------------------ // Extends // ------------------------------------------------------------------------ export type TExtends = Types.Static extends Types.Static ? T : U // ------------------------------------------------------------------------ // Exclude // ------------------------------------------------------------------------ export interface TExclude extends Types.TUnion { static: Exclude, Types.Static> } // ------------------------------------------------------------------------ // Extract // ------------------------------------------------------------------------ export interface TExtract extends Types.TUnion { static: Extract, Types.Static> } /** Conditional Types */ export namespace Conditional { /** (Experimental) Creates a conditional expression type */ export function Extends(left: L, right: R, ok: T, fail: U): TExtends { switch (Structural.Check(left, right)) { case StructuralResult.Union: return Types.Type.Union([Clone(ok), Clone(fail)]) as any as TExtends case StructuralResult.True: return Clone(ok) case StructuralResult.False: return Clone(fail) } } /** (Experimental) Constructs a type by excluding from UnionType all union members that are assignable to ExcludedMembers. */ export function Exclude(unionType: T, excludedMembers: U, options: Types.SchemaOptions = {}): TExclude { const anyOf = unionType.anyOf .filter((schema) => { const check = Structural.Check(schema, excludedMembers) return !(check === StructuralResult.True || check === StructuralResult.Union) }) .map((schema) => Clone(schema)) return { ...options, [Types.Kind]: 'Union', anyOf } as any } /** (Experimental) Constructs a type by extracting from Type all union members that are assignable to Union. */ export function Extract(type: T, union: U, options: Types.SchemaOptions = {}): TExtract { if (TypeGuard.TUnion(type)) { const anyOf = type.anyOf.filter((schema: Types.TSchema) => Structural.Check(schema, union) === StructuralResult.True).map((schema: Types.TSchema) => Clone(schema)) return { ...options, [Types.Kind]: 'Union', anyOf } as any } else { const anyOf = union.anyOf.filter((schema) => Structural.Check(type, schema) === StructuralResult.True).map((schema) => Clone(schema)) return { ...options, [Types.Kind]: 'Union', anyOf } as any } } function Clone(value: any): any { const isObject = (object: any): object is Record => typeof object === 'object' && object !== null && !Array.isArray(object) const isArray = (object: any): object is any[] => typeof object === 'object' && object !== null && Array.isArray(object) if (isObject(value)) { return Object.keys(value).reduce( (acc, key) => ({ ...acc, [key]: Clone(value[key]), }), Object.getOwnPropertySymbols(value).reduce( (acc, key) => ({ ...acc, [key]: Clone(value[key]), }), {}, ), ) } else if (isArray(value)) { return value.map((item: any) => Clone(item)) } else { return value } } } typebox-0.24.44/src/conditional/index.ts000066400000000000000000000025301431512220400201220ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/conditional The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 './conditional' export * from './structural' typebox-0.24.44/src/conditional/structural.ts000066400000000000000000000553661431512220400212420ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/conditional The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '../typebox' import { TypeGuard } from '../guard' // -------------------------------------------------------------------------- // StructuralResult // -------------------------------------------------------------------------- export enum StructuralResult { Union, True, False, } // -------------------------------------------------------------------------- // Structural // -------------------------------------------------------------------------- /** Performs structural equivalence checks against TypeBox types. */ export namespace Structural { const referenceMap = new Map() // ------------------------------------------------------------------------ // Rules // ------------------------------------------------------------------------ function AnyOrUnknownRule(right: Types.TSchema) { // https://github.com/microsoft/TypeScript/issues/40049 if (right[Types.Kind] === 'Union' && right.anyOf.some((schema: Types.TSchema) => schema[Types.Kind] === 'Any' || schema[Types.Kind] === 'Unknown')) return true if (right[Types.Kind] === 'Unknown') return true if (right[Types.Kind] === 'Any') return true return false } function ObjectRightRule(left: Types.TAnySchema, right: Types.TObject) { // type A = boolean extends {} ? 1 : 2 // additionalProperties: false // type B = boolean extends object ? 1 : 2 // additionalProperties: true const additionalProperties = right.additionalProperties const propertyLength = globalThis.Object.keys(right.properties).length return additionalProperties === false && propertyLength === 0 } function UnionRightRule(left: Types.TAnySchema, right: Types.TUnion): StructuralResult { const result = right.anyOf.some((right: Types.TSchema) => Visit(left, right) !== StructuralResult.False) return result ? StructuralResult.True : StructuralResult.False } // ------------------------------------------------------------------------ // Records // ------------------------------------------------------------------------ function RecordPattern(schema: Types.TRecord) { return globalThis.Object.keys(schema.patternProperties)[0] as string } function RecordNumberOrStringKey(schema: Types.TRecord) { const pattern = RecordPattern(schema) return pattern === '^.*$' || pattern === '^(0|[1-9][0-9]*)$' } function RecordValue(schema: Types.TRecord) { const pattern = RecordPattern(schema) return schema.patternProperties[pattern] } function RecordKey(schema: Types.TRecord) { const pattern = RecordPattern(schema) if (pattern === '^.*$') { return Types.Type.String() } else if (pattern === '^(0|[1-9][0-9]*)$') { return Types.Type.Number() } else { const keys = pattern.slice(1, pattern.length - 1).split('|') const schemas = keys.map((key) => (isNaN(+key) ? Types.Type.Literal(key) : Types.Type.Literal(parseFloat(key)))) return Types.Type.Union(schemas) } } function PropertyMap(schema: Types.TObject | Types.TRecord) { const comparable = new Map() if (TypeGuard.TRecord(schema)) { const propertyPattern = RecordPattern(schema as Types.TRecord) if (propertyPattern === '^.*$' || propertyPattern === '^(0|[1-9][0-9]*)$') throw Error('Cannot extract record properties without property constraints') const propertySchema = schema.patternProperties[propertyPattern] as Types.TSchema const propertyKeys = propertyPattern.slice(1, propertyPattern.length - 1).split('|') propertyKeys.forEach((propertyKey) => { comparable.set(propertyKey, propertySchema) }) } else { globalThis.Object.entries(schema.properties).forEach(([propertyKey, propertySchema]) => { comparable.set(propertyKey, propertySchema as Types.TSchema) }) } return comparable } // ------------------------------------------------------------------------ // Indexable // ------------------------------------------------------------------------ function Indexable(left: Left, right: Types.TSchema): StructuralResult { if (TypeGuard.TUnion(right)) { return StructuralResult.False } else { return Visit(left, right) } } // ------------------------------------------------------------------------ // Checks // ------------------------------------------------------------------------ function Any(left: Types.TAny, right: Types.TSchema): StructuralResult { return AnyOrUnknownRule(right) ? StructuralResult.True : StructuralResult.Union } function Array(left: Types.TArray, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right)) { if (right.properties['length'] !== undefined && right.properties['length'][Types.Kind] === 'Number') return StructuralResult.True if (globalThis.Object.keys(right.properties).length === 0) return StructuralResult.True return StructuralResult.False } else if (!TypeGuard.TArray(right)) { return StructuralResult.False } else if (left.items === undefined && right.items !== undefined) { return StructuralResult.False } else if (left.items !== undefined && right.items === undefined) { return StructuralResult.False } else if (left.items === undefined && right.items === undefined) { return StructuralResult.False } else { const result = Visit(left.items, right.items) !== StructuralResult.False return result ? StructuralResult.True : StructuralResult.False } } function Boolean(left: Types.TBoolean, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right) && ObjectRightRule(left, right)) { return StructuralResult.True } else if (TypeGuard.TBoolean(right)) { return StructuralResult.True } else if (TypeGuard.TUnion(right)) { return UnionRightRule(left, right) } else { return StructuralResult.False } } function Constructor(left: Types.TConstructor, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right) && globalThis.Object.keys(right.properties).length === 0) { return StructuralResult.True } else if (!TypeGuard.TConstructor(right)) { return StructuralResult.False } else if (right.parameters.length < left.parameters.length) { return StructuralResult.False } else { if (Visit(left.returns, right.returns) === StructuralResult.False) { return StructuralResult.False } for (let i = 0; i < left.parameters.length; i++) { const result = Visit(right.parameters[i], left.parameters[i]) if (result === StructuralResult.False) return StructuralResult.False } return StructuralResult.True } } function Function(left: Types.TFunction, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right)) { if (right.properties['length'] !== undefined && right.properties['length'][Types.Kind] === 'Number') return StructuralResult.True if (globalThis.Object.keys(right.properties).length === 0) return StructuralResult.True return StructuralResult.False } else if (!TypeGuard.TFunction(right)) { return StructuralResult.False } else if (right.parameters.length < left.parameters.length) { return StructuralResult.False } else if (Visit(left.returns, right.returns) === StructuralResult.False) { return StructuralResult.False } else { for (let i = 0; i < left.parameters.length; i++) { const result = Visit(right.parameters[i], left.parameters[i]) if (result === StructuralResult.False) return StructuralResult.False } return StructuralResult.True } } function Integer(left: Types.TInteger, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right) && ObjectRightRule(left, right)) { return StructuralResult.True } else if (TypeGuard.TInteger(right) || TypeGuard.TNumber(right)) { return StructuralResult.True } else if (TypeGuard.TUnion(right)) { return UnionRightRule(left, right) } else { return StructuralResult.False } } function Literal(left: Types.TLiteral, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right) && ObjectRightRule(left, right)) { return StructuralResult.True } else if (TypeGuard.TRecord(right)) { if (typeof left.const === 'string') { return Indexable(left, RecordValue(right as Types.TRecord)) } else { return StructuralResult.False } } else if (TypeGuard.TLiteral(right) && left.const === right.const) { return StructuralResult.True } else if (TypeGuard.TString(right) && typeof left.const === 'string') { return StructuralResult.True } else if (TypeGuard.TNumber(right) && typeof left.const === 'number') { return StructuralResult.True } else if (TypeGuard.TInteger(right) && typeof left.const === 'number') { return StructuralResult.True } else if (TypeGuard.TBoolean(right) && typeof left.const === 'boolean') { return StructuralResult.True } else if (TypeGuard.TUnion(right)) { return UnionRightRule(left, right) } else { return StructuralResult.False } } function Number(left: Types.TNumber, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right) && ObjectRightRule(left, right)) { return StructuralResult.True } else if (TypeGuard.TNumber(right)) { return StructuralResult.True } else if (TypeGuard.TInteger(right)) { return StructuralResult.True } else if (TypeGuard.TUnion(right)) { return UnionRightRule(left, right) } else { return StructuralResult.False } } function Null(left: Types.TNull, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TNull(right)) { return StructuralResult.True } else if (TypeGuard.TUnion(right)) { return UnionRightRule(left, right) } else { return StructuralResult.False } } function Properties(left: Map, right: Map) { if (right.size > left.size) return StructuralResult.False if (![...right.keys()].every((rightKey) => left.has(rightKey))) return StructuralResult.False for (const rightKey of right.keys()) { const leftProp = left.get(rightKey)! const rightProp = right.get(rightKey)! if (Visit(leftProp, rightProp) === StructuralResult.False) { return StructuralResult.False } } return StructuralResult.True } function Object(left: Types.TObject, right: Types.TAnySchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right)) { return Properties(PropertyMap(left), PropertyMap(right)) } else if (TypeGuard.TRecord(right)) { if (!RecordNumberOrStringKey(right as Types.TRecord)) { return Properties(PropertyMap(left), PropertyMap(right)) } else { return StructuralResult.True } } else { return StructuralResult.False } } function Promise(left: Types.TPromise, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right)) { if (ObjectRightRule(left, right) || globalThis.Object.keys(right.properties).length === 0) { return StructuralResult.True } else { return StructuralResult.False } } else if (!TypeGuard.TPromise(right)) { return StructuralResult.False } else { const result = Visit(left.item, right.item) !== StructuralResult.False return result ? StructuralResult.True : StructuralResult.False } } function Record(left: Types.TRecord, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right)) { if (RecordPattern(left) === '^.*$' && right[Types.Hint] === 'Record') { return StructuralResult.True } else if (RecordPattern(left) === '^.*$') { return StructuralResult.False } else { return globalThis.Object.keys(right.properties).length === 0 ? StructuralResult.True : StructuralResult.False } } else if (TypeGuard.TRecord(right)) { if (!RecordNumberOrStringKey(left as Types.TRecord) && !RecordNumberOrStringKey(right as Types.TRecord)) { return Properties(PropertyMap(left), PropertyMap(right)) } else if (RecordNumberOrStringKey(left as Types.TRecord) && !RecordNumberOrStringKey(right as Types.TRecord)) { const leftKey = RecordKey(left as Types.TRecord) const rightKey = RecordKey(right as Types.TRecord) if (Visit(rightKey, leftKey) === StructuralResult.False) { return StructuralResult.False } else { return StructuralResult.True } } else { return StructuralResult.True } } else { return StructuralResult.False } } function Ref(left: Types.TRef, right: Types.TSchema): StructuralResult { if (!referenceMap.has(left.$ref)) throw Error(`Cannot locate referenced $id '${left.$ref}'`) const resolved = referenceMap.get(left.$ref)! return Visit(resolved, right) } function Self(left: Types.TSelf, right: Types.TSchema): StructuralResult { if (!referenceMap.has(left.$ref)) throw Error(`Cannot locate referenced self $id '${left.$ref}'`) const resolved = referenceMap.get(left.$ref)! return Visit(resolved, right) } function String(left: Types.TString, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right) && ObjectRightRule(left, right)) { return StructuralResult.True } else if (TypeGuard.TRecord(right)) { return Indexable(left, RecordValue(right)) } else if (TypeGuard.TString(right)) { return StructuralResult.True } else if (TypeGuard.TUnion(right)) { return UnionRightRule(left, right) } else { return StructuralResult.False } } function Tuple(left: Types.TTuple, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right)) { const result = ObjectRightRule(left, right) || globalThis.Object.keys(right.properties).length === 0 return result ? StructuralResult.True : StructuralResult.False } else if (TypeGuard.TRecord(right)) { return Indexable(left, RecordValue(right)) } else if (TypeGuard.TArray(right)) { if (right.items === undefined) { return StructuralResult.False } else if (TypeGuard.TUnion(right.items) && left.items) { const result = left.items.every((left: Types.TSchema) => UnionRightRule(left, right.items as Types.TUnion) !== StructuralResult.False) return result ? StructuralResult.True : StructuralResult.False } else if (TypeGuard.TAny(right.items)) { return StructuralResult.True } else { return StructuralResult.False } } if (!TypeGuard.TTuple(right)) return StructuralResult.False if (left.items === undefined && right.items === undefined) return StructuralResult.True if (left.items === undefined && right.items !== undefined) return StructuralResult.False if (left.items !== undefined && right.items === undefined) return StructuralResult.False if (left.items === undefined && right.items === undefined) return StructuralResult.True if (left.minItems !== right.minItems || left.maxItems !== right.maxItems) return StructuralResult.False for (let i = 0; i < left.items!.length; i++) { if (Visit(left.items![i], right.items![i]) === StructuralResult.False) return StructuralResult.False } return StructuralResult.True } function Uint8Array(left: Types.TUint8Array, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TObject(right) && ObjectRightRule(left, right)) { return StructuralResult.True } else if (TypeGuard.TRecord(right)) { return Indexable(left, RecordValue(right as Types.TRecord)) } else if (TypeGuard.TUint8Array(right)) { return StructuralResult.True } else if (TypeGuard.TUnion(right)) { return UnionRightRule(left, right) } else { return StructuralResult.False } } function Undefined(left: Types.TUndefined, right: Types.TSchema): StructuralResult { if (AnyOrUnknownRule(right)) { return StructuralResult.True } else if (TypeGuard.TUndefined(right)) { return StructuralResult.True } else if (TypeGuard.TVoid(right)) { return StructuralResult.True } else if (TypeGuard.TUnion(right)) { return UnionRightRule(left, right) } else { return StructuralResult.False } } function Union(left: Types.TUnion, right: Types.TSchema): StructuralResult { if (left.anyOf.some((left: Types.TSchema) => TypeGuard.TAny(left))) { return StructuralResult.Union } else if (TypeGuard.TUnion(right)) { const result = left.anyOf.every((left: Types.TSchema) => right.anyOf.some((right: Types.TSchema) => Visit(left, right) !== StructuralResult.False)) return result ? StructuralResult.True : StructuralResult.False } else { const result = left.anyOf.every((left: Types.TSchema) => Visit(left, right) !== StructuralResult.False) return result ? StructuralResult.True : StructuralResult.False } } function Unknown(left: Types.TUnknown, right: Types.TSchema): StructuralResult { if (TypeGuard.TUnion(right)) { const result = right.anyOf.some((right: Types.TSchema) => TypeGuard.TAny(right) || TypeGuard.TUnknown(right)) return result ? StructuralResult.True : StructuralResult.False } else if (TypeGuard.TAny(right)) { return StructuralResult.True } else if (TypeGuard.TUnknown(right)) { return StructuralResult.True } else { return StructuralResult.False } } function Void(left: Types.TVoid, right: Types.TSchema): StructuralResult { if (TypeGuard.TUnion(right)) { const result = right.anyOf.some((right: Types.TSchema) => TypeGuard.TAny(right) || TypeGuard.TUnknown(right)) return result ? StructuralResult.True : StructuralResult.False } else if (TypeGuard.TAny(right)) { return StructuralResult.True } else if (TypeGuard.TUnknown(right)) { return StructuralResult.True } else if (TypeGuard.TVoid(right)) { return StructuralResult.True } else { return StructuralResult.False } } let recursionDepth = 0 function Visit(left: Left, right: Types.TSchema): StructuralResult { recursionDepth += 1 if (recursionDepth >= 1000) return StructuralResult.True if (left.$id !== undefined) referenceMap.set(left.$id!, left) if (right.$id !== undefined) referenceMap.set(right.$id!, right) const resolvedRight = right[Types.Kind] === 'Self' ? referenceMap.get(right.$ref)! : right if (TypeGuard.TAny(left)) { return Any(left, resolvedRight) } else if (TypeGuard.TArray(left)) { return Array(left, resolvedRight) } else if (TypeGuard.TBoolean(left)) { return Boolean(left, resolvedRight) } else if (TypeGuard.TConstructor(left)) { return Constructor(left, resolvedRight) } else if (TypeGuard.TFunction(left)) { return Function(left, resolvedRight) } else if (TypeGuard.TInteger(left)) { return Integer(left, resolvedRight) } else if (TypeGuard.TLiteral(left)) { return Literal(left, resolvedRight) } else if (TypeGuard.TNull(left)) { return Null(left, resolvedRight) } else if (TypeGuard.TNumber(left)) { return Number(left, resolvedRight) } else if (TypeGuard.TObject(left)) { return Object(left, resolvedRight) } else if (TypeGuard.TPromise(left)) { return Promise(left, resolvedRight) } else if (TypeGuard.TRecord(left)) { return Record(left, resolvedRight) } else if (TypeGuard.TRef(left)) { return Ref(left, resolvedRight) } else if (TypeGuard.TSelf(left)) { return Self(left, resolvedRight) } else if (TypeGuard.TString(left)) { return String(left, resolvedRight) } else if (TypeGuard.TTuple(left)) { return Tuple(left, resolvedRight) } else if (TypeGuard.TUndefined(left)) { return Undefined(left, resolvedRight) } else if (TypeGuard.TUint8Array(left)) { return Uint8Array(left, resolvedRight) } else if (TypeGuard.TUnion(left)) { return Union(left, resolvedRight) } else if (TypeGuard.TUnknown(left)) { return Unknown(left, resolvedRight) } else if (TypeGuard.TVoid(left)) { return Void(left, resolvedRight) } else { throw Error(`Structural: Unknown left operand '${left[Types.Kind]}'`) } } /** Structurally tests if the left schema extends the right. */ export function Check(left: Types.TSchema, right: Types.TSchema): StructuralResult { referenceMap.clear() recursionDepth = 0 return Visit(left, right) } } typebox-0.24.44/src/errors/000077500000000000000000000000001431512220400154545ustar00rootroot00000000000000typebox-0.24.44/src/errors/errors.ts000066400000000000000000000460641431512220400173520ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/errors The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '../typebox' import { Format } from '../format/index' // ------------------------------------------------------------------- // ValueErrorType // ------------------------------------------------------------------- export enum ValueErrorType { Array, ArrayMinItems, ArrayMaxItems, ArrayUniqueItems, Boolean, Function, Integer, IntegerMultipleOf, IntegerExclusiveMinimum, IntegerExclusiveMaximum, IntegerMinimum, IntegerMaximum, Literal, Never, Null, Number, NumberMultipleOf, NumberExclusiveMinimum, NumberExclusiveMaximum, NumberMinumum, NumberMaximum, Object, ObjectMinProperties, ObjectMaxProperties, ObjectAdditionalProperties, Promise, RecordKeyNumeric, RecordKeyString, String, StringMinLength, StringMaxLength, StringPattern, StringFormatUnknown, StringFormat, TupleZeroLength, TupleLength, Undefined, Union, Uint8Array, Uint8ArrayMinByteLength, Uint8ArrayMaxByteLength, Void, } // ------------------------------------------------------------------- // ValueError // ------------------------------------------------------------------- export interface ValueError { type: ValueErrorType schema: Types.TSchema path: string value: unknown message: string } // ------------------------------------------------------------------- // ValueErrors // ------------------------------------------------------------------- export class ValueErrorsUnknownTypeError extends Error { constructor(public readonly schema: Types.TSchema) { super('ValueErrors: Unknown type') } } export namespace ValueErrors { function* Any(schema: Types.TAny, references: Types.TSchema[], path: string, value: any): IterableIterator {} function* Array(schema: Types.TArray, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!globalThis.Array.isArray(value)) { return yield { type: ValueErrorType.Array, schema, path, value, message: `Expected array` } } if (schema.minItems !== undefined && !(value.length >= schema.minItems)) { yield { type: ValueErrorType.ArrayMinItems, schema, path, value, message: `Expected array length to be greater or equal to ${schema.minItems}` } } if (schema.maxItems !== undefined && !(value.length <= schema.maxItems)) { yield { type: ValueErrorType.ArrayMinItems, schema, path, value, message: `Expected array length to be less or equal to ${schema.maxItems}` } } if (schema.uniqueItems === true && !(new Set(value).size === value.length)) { yield { type: ValueErrorType.ArrayUniqueItems, schema, path, value, message: `Expected array elements to be unique` } } for (let i = 0; i < value.length; i++) { yield* Visit(schema.items, references, `${path}/${i}`, value[i]) } } function* Boolean(schema: Types.TBoolean, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(typeof value === 'boolean')) { return yield { type: ValueErrorType.Boolean, schema, path, value, message: `Expected boolean` } } } function* Constructor(schema: Types.TConstructor, references: Types.TSchema[], path: string, value: any): IterableIterator { yield* Visit(schema.returns, references, path, value.prototype) } function* Function(schema: Types.TFunction, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(typeof value === 'function')) { return yield { type: ValueErrorType.Function, schema, path, value, message: `Expected function` } } } function* Integer(schema: Types.TNumeric, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(typeof value === 'number')) { return yield { type: ValueErrorType.Number, schema, path, value, message: `Expected number` } } if (!globalThis.Number.isInteger(value)) { yield { type: ValueErrorType.Integer, schema, path, value, message: `Expected integer` } } if (schema.multipleOf && !(value % schema.multipleOf === 0)) { yield { type: ValueErrorType.IntegerMultipleOf, schema, path, value, message: `Expected integer to be a multiple of ${schema.multipleOf}` } } if (schema.exclusiveMinimum && !(value > schema.exclusiveMinimum)) { yield { type: ValueErrorType.IntegerExclusiveMinimum, schema, path, value, message: `Expected integer to be greater than ${schema.exclusiveMinimum}` } } if (schema.exclusiveMaximum && !(value < schema.exclusiveMaximum)) { yield { type: ValueErrorType.IntegerExclusiveMaximum, schema, path, value, message: `Expected integer to be less than ${schema.exclusiveMaximum}` } } if (schema.minimum && !(value >= schema.minimum)) { yield { type: ValueErrorType.IntegerMinimum, schema, path, value, message: `Expected integer to be greater or equal to ${schema.minimum}` } } if (schema.maximum && !(value <= schema.maximum)) { yield { type: ValueErrorType.IntegerMaximum, schema, path, value, message: `Expected integer to be less or equal to ${schema.maximum}` } } } function* Literal(schema: Types.TLiteral, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(value === schema.const)) { const error = typeof schema.const === 'string' ? `'${schema.const}'` : schema.const return yield { type: ValueErrorType.Literal, schema, path, value, message: `Expected ${error}` } } } function* Never(schema: Types.TNever, references: Types.TSchema[], path: string, value: any): IterableIterator { yield { type: ValueErrorType.Never, schema, path, value, message: `Value cannot be validated` } } function* Null(schema: Types.TNull, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(value === null)) { return yield { type: ValueErrorType.Null, schema, path, value, message: `Expected null` } } } function* Number(schema: Types.TNumeric, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(typeof value === 'number')) { return yield { type: ValueErrorType.Number, schema, path, value, message: `Expected number` } } if (schema.multipleOf && !(value % schema.multipleOf === 0)) { yield { type: ValueErrorType.NumberMultipleOf, schema, path, value, message: `Expected number to be a multiple of ${schema.multipleOf}` } } if (schema.exclusiveMinimum && !(value > schema.exclusiveMinimum)) { yield { type: ValueErrorType.NumberExclusiveMinimum, schema, path, value, message: `Expected number to be greater than ${schema.exclusiveMinimum}` } } if (schema.exclusiveMaximum && !(value < schema.exclusiveMaximum)) { yield { type: ValueErrorType.NumberExclusiveMaximum, schema, path, value, message: `Expected number to be less than ${schema.exclusiveMaximum}` } } if (schema.minimum && !(value >= schema.minimum)) { yield { type: ValueErrorType.NumberMaximum, schema, path, value, message: `Expected number to be greater or equal to ${schema.minimum}` } } if (schema.maximum && !(value <= schema.maximum)) { yield { type: ValueErrorType.NumberMinumum, schema, path, value, message: `Expected number to be less or equal to ${schema.maximum}` } } } function* Object(schema: Types.TObject, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(typeof value === 'object' && value !== null && !globalThis.Array.isArray(value))) { return yield { type: ValueErrorType.Object, schema, path, value, message: `Expected object` } } if (schema.minProperties !== undefined && !(globalThis.Object.keys(value).length >= schema.minProperties)) { yield { type: ValueErrorType.ObjectMinProperties, schema, path, value, message: `Expected object to have at least ${schema.minProperties} properties` } } if (schema.maxProperties !== undefined && !(globalThis.Object.keys(value).length <= schema.maxProperties)) { yield { type: ValueErrorType.ObjectMaxProperties, schema, path, value, message: `Expected object to have less than ${schema.minProperties} properties` } } const propertyKeys = globalThis.Object.keys(schema.properties) if (schema.additionalProperties === false) { for (const propKey of globalThis.Object.keys(value)) { if (!propertyKeys.includes(propKey)) { yield { type: ValueErrorType.ObjectAdditionalProperties, schema, path: `${path}/${propKey}`, value: value[propKey], message: 'Unexpected property' } } } } for (const propertyKey of propertyKeys) { const propertySchema = schema.properties[propertyKey] if (schema.required && schema.required.includes(propertyKey)) { yield* Visit(propertySchema, references, `${path}/${propertyKey}`, value[propertyKey]) } else { if (value[propertyKey] !== undefined) { yield* Visit(propertySchema, references, `${path}/${propertyKey}`, value[propertyKey]) } } } } function* Promise(schema: Types.TPromise, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(typeof value === 'object' && typeof value.then === 'function')) { yield { type: ValueErrorType.Promise, schema, path, value, message: `Expected Promise` } } } function* Record(schema: Types.TRecord, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(typeof value === 'object' && value !== null && !globalThis.Array.isArray(value))) { return yield { type: ValueErrorType.Object, schema, path, value, message: `Expected object` } } const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0] const regex = new RegExp(keyPattern) if (!globalThis.Object.keys(value).every((key) => regex.test(key))) { const numeric = keyPattern === '^(0|[1-9][0-9]*)$' const type = numeric ? ValueErrorType.RecordKeyNumeric : ValueErrorType.RecordKeyString const message = numeric ? 'Expected all object property keys to be numeric' : 'Expected all object property keys to be strings' return yield { type, schema, path, value, message } } for (const [propKey, propValue] of globalThis.Object.entries(value)) { yield* Visit(valueSchema, references, `${path}/${propKey}`, propValue) } } function* Ref(schema: Types.TRef, references: Types.TSchema[], path: string, value: any): IterableIterator { const reference = references.find((reference) => reference.$id === schema.$ref) if (reference === undefined) throw new Error(`ValueErrors.Ref: Cannot find schema with $id '${schema.$ref}'.`) yield* Visit(reference, references, path, value) } function* Self(schema: Types.TSelf, references: Types.TSchema[], path: string, value: any): IterableIterator { const reference = references.find((reference) => reference.$id === schema.$ref) if (reference === undefined) throw new Error(`ValueErrors.Self: Cannot find schema with $id '${schema.$ref}'.`) yield* Visit(reference, references, path, value) } function* String(schema: Types.TString, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(typeof value === 'string')) { return yield { type: ValueErrorType.String, schema, path, value, message: 'Expected string' } } if (schema.minLength !== undefined && !(value.length >= schema.minLength)) { yield { type: ValueErrorType.StringMinLength, schema, path, value, message: `Expected string length greater or equal to ${schema.minLength}` } } if (schema.maxLength !== undefined && !(value.length <= schema.maxLength)) { yield { type: ValueErrorType.StringMaxLength, schema, path, value, message: `Expected string length less or equal to ${schema.maxLength}` } } if (schema.pattern !== undefined) { const regex = new RegExp(schema.pattern) if (!regex.test(value)) { yield { type: ValueErrorType.StringPattern, schema, path, value, message: `Expected string to match pattern ${schema.pattern}` } } } if (schema.format !== undefined) { if (!Format.Has(schema.format)) { yield { type: ValueErrorType.StringFormatUnknown, schema, path, value, message: `Unknown string format '${schema.format}'` } } else { const format = Format.Get(schema.format)! if (!format(value)) { yield { type: ValueErrorType.StringFormat, schema, path, value, message: `Expected string to match format '${schema.format}'` } } } } } function* Tuple(schema: Types.TTuple, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!globalThis.Array.isArray(value)) { return yield { type: ValueErrorType.Array, schema, path, value, message: 'Expected Array' } } if (schema.items === undefined && !(value.length === 0)) { return yield { type: ValueErrorType.TupleZeroLength, schema, path, value, message: 'Expected tuple to have 0 elements' } } if (!(value.length === schema.maxItems)) { yield { type: ValueErrorType.TupleLength, schema, path, value, message: `Expected tuple to have ${schema.maxItems} elements` } } if (!schema.items) { return } for (let i = 0; i < schema.items.length; i++) { yield* Visit(schema.items[i], references, `${path}/${i}`, value[i]) } } function* Undefined(schema: Types.TUndefined, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(value === undefined)) { yield { type: ValueErrorType.Undefined, schema, path, value, message: `Expected undefined` } } } function* Union(schema: Types.TUnion, references: Types.TSchema[], path: string, value: any): IterableIterator { const errors: ValueError[] = [] for (const inner of schema.anyOf) { const variantErrors = [...Visit(inner, references, path, value)] if (variantErrors.length === 0) return errors.push(...variantErrors) } for (const error of errors) { yield error } if (errors.length > 0) { yield { type: ValueErrorType.Union, schema, path, value, message: 'Expected value of union' } } } function* Uint8Array(schema: Types.TUint8Array, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(value instanceof globalThis.Uint8Array)) { return yield { type: ValueErrorType.Uint8Array, schema, path, value, message: `Expected Uint8Array` } } if (schema.maxByteLength && !(value.length <= schema.maxByteLength)) { yield { type: ValueErrorType.Uint8ArrayMaxByteLength, schema, path, value, message: `Expected Uint8Array to have a byte length less or equal to ${schema.maxByteLength}` } } if (schema.minByteLength && !(value.length >= schema.minByteLength)) { yield { type: ValueErrorType.Uint8ArrayMinByteLength, schema, path, value, message: `Expected Uint8Array to have a byte length greater or equal to ${schema.maxByteLength}` } } } function* Unknown(schema: Types.TUnknown, references: Types.TSchema[], path: string, value: any): IterableIterator {} function* Void(schema: Types.TVoid, references: Types.TSchema[], path: string, value: any): IterableIterator { if (!(value === null)) { return yield { type: ValueErrorType.Void, schema, path, value, message: `Expected null` } } } function* Visit(schema: T, references: Types.TSchema[], path: string, value: any): IterableIterator { const anyReferences = schema.$id === undefined ? references : [schema, ...references] const anySchema = schema as any switch (anySchema[Types.Kind]) { case 'Any': return yield* Any(anySchema, anyReferences, path, value) case 'Array': return yield* Array(anySchema, anyReferences, path, value) case 'Boolean': return yield* Boolean(anySchema, anyReferences, path, value) case 'Constructor': return yield* Constructor(anySchema, anyReferences, path, value) case 'Function': return yield* Function(anySchema, anyReferences, path, value) case 'Integer': return yield* Integer(anySchema, anyReferences, path, value) case 'Literal': return yield* Literal(anySchema, anyReferences, path, value) case 'Never': return yield* Never(anySchema, anyReferences, path, value) case 'Null': return yield* Null(anySchema, anyReferences, path, value) case 'Number': return yield* Number(anySchema, anyReferences, path, value) case 'Object': return yield* Object(anySchema, anyReferences, path, value) case 'Promise': return yield* Promise(anySchema, anyReferences, path, value) case 'Record': return yield* Record(anySchema, anyReferences, path, value) case 'Ref': return yield* Ref(anySchema, anyReferences, path, value) case 'Self': return yield* Self(anySchema, anyReferences, path, value) case 'String': return yield* String(anySchema, anyReferences, path, value) case 'Tuple': return yield* Tuple(anySchema, anyReferences, path, value) case 'Undefined': return yield* Undefined(anySchema, anyReferences, path, value) case 'Union': return yield* Union(anySchema, anyReferences, path, value) case 'Uint8Array': return yield* Uint8Array(anySchema, anyReferences, path, value) case 'Unknown': return yield* Unknown(anySchema, anyReferences, path, value) case 'Void': return yield* Void(anySchema, anyReferences, path, value) default: throw new ValueErrorsUnknownTypeError(schema) } } export function* Errors(schema: T, references: Types.TSchema[], value: any): IterableIterator { yield* Visit(schema, references, '', value) } } typebox-0.24.44/src/errors/index.ts000066400000000000000000000024611431512220400171360ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/errors The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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' typebox-0.24.44/src/format/000077500000000000000000000000001431512220400154305ustar00rootroot00000000000000typebox-0.24.44/src/format/format.ts000066400000000000000000000037561431512220400173030ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 FormatValidationFunction = (value: string) => boolean /** Shared string formats used by the TypeCompiler and Value modules */ export namespace Format { const formats = new Map() /** Clears all formats */ export function Clear() { return formats.clear() } /** Returns true if the string format exists */ export function Has(format: string) { return formats.has(format) } /** Sets a string format validation function */ export function Set(format: string, func: FormatValidationFunction) { formats.set(format, func) } /** Gets a string format validation function */ export function Get(format: string) { return formats.get(format) } } typebox-0.24.44/src/format/index.ts000066400000000000000000000024611431512220400171120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/format The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 './format' typebox-0.24.44/src/guard/000077500000000000000000000000001431512220400152425ustar00rootroot00000000000000typebox-0.24.44/src/guard/guard.ts000066400000000000000000000321301431512220400167130ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/guard The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, dTribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '../typebox' export class TypeGuardInvalidTypeError extends Error { constructor(public readonly schema: unknown) { super('TypeGuard: Invalid type') } } /** TypeGuard tests that values conform to a known TypeBox type specification */ export namespace TypeGuard { function IsObject(value: unknown): value is Record { return typeof value === 'object' && value !== null && !Array.isArray(value) } function IsArray(value: unknown): value is any[] { return typeof value === 'object' && value !== null && Array.isArray(value) } 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 (typeof value !== 'string') 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 IsString(value: unknown): value is string { return typeof value === 'string' } function IsNumber(value: unknown): value is number { return typeof value === 'number' } function IsBoolean(value: unknown): value is boolean { return typeof value === 'boolean' } function IsOptionalNumber(value: unknown): value is number | undefined { return value === undefined || (value !== undefined && IsNumber(value)) } function IsOptionalBoolean(value: unknown): value is boolean | undefined { return value === undefined || (value !== undefined && IsBoolean(value)) } function IsOptionalString(value: unknown): value is string | undefined { return value === undefined || (value !== undefined && IsString(value)) } function IsOptionalPattern(value: unknown): value is string | undefined { return value === undefined || (value !== undefined && IsString(value) && IsControlCharacterFree(value) && IsPattern(value)) } function IsOptionalFormat(value: unknown): value is string | undefined { return value === undefined || (value !== undefined && IsString(value) && IsControlCharacterFree(value)) } /** Returns true if the given schema is TAny */ export function TAny(schema: unknown): schema is Types.TAny { return IsObject(schema) && schema[Types.Kind] === 'Any' && IsOptionalString(schema.$id) } /** Returns true if the given schema is TArray */ export function TArray(schema: unknown): schema is Types.TArray { return ( IsObject(schema) && schema[Types.Kind] === 'Array' && schema.type === 'array' && IsOptionalString(schema.$id) && TSchema(schema.items) && IsOptionalNumber(schema.minItems) && IsOptionalNumber(schema.maxItems) && IsOptionalBoolean(schema.uniqueItems) ) } /** Returns true if the given schema is TBoolean */ export function TBoolean(schema: unknown): schema is Types.TBoolean { return IsObject(schema) && schema[Types.Kind] === 'Boolean' && schema.type === 'boolean' && IsOptionalString(schema.$id) } /** Returns true if the given schema is TConstructor */ export function TConstructor(schema: unknown): schema is Types.TConstructor { if (!(IsObject(schema) && schema[Types.Kind] === 'Constructor' && schema.type === 'constructor' && IsOptionalString(schema.$id) && IsArray(schema.parameters) && TSchema(schema.returns))) { return false } for (const parameter of schema.parameters) { if (!TSchema(parameter)) return false } return true } /** Returns true if the given schema is TFunction */ export function TFunction(schema: unknown): schema is Types.TFunction { if (!(IsObject(schema) && schema[Types.Kind] === 'Function' && schema.type === 'function' && IsOptionalString(schema.$id) && IsArray(schema.parameters) && TSchema(schema.returns))) { return false } for (const parameter of schema.parameters) { if (!TSchema(parameter)) return false } return true } /** Returns true if the given schema is TInteger */ export function TInteger(schema: unknown): schema is Types.TInteger { return ( IsObject(schema) && schema[Types.Kind] === 'Integer' && schema.type === 'integer' && IsOptionalString(schema.$id) && IsOptionalNumber(schema.multipleOf) && IsOptionalNumber(schema.minimum) && IsOptionalNumber(schema.maximum) && IsOptionalNumber(schema.exclusiveMinimum) && IsOptionalNumber(schema.exclusiveMaximum) ) } /** Returns true if the given schema is TLiteral */ export function TLiteral(schema: unknown): schema is Types.TLiteral { return IsObject(schema) && schema[Types.Kind] === 'Literal' && IsOptionalString(schema.$id) && (IsString(schema.const) || IsNumber(schema.const) || IsBoolean(schema.const)) } /** Returns true if the given schema is TNever */ export function TNever(schema: unknown): schema is Types.TNever { return ( IsObject(schema) && schema[Types.Kind] === 'Never' && IsArray(schema.allOf) && schema.allOf.length === 2 && IsObject(schema.allOf[0]) && IsString(schema.allOf[0].type) && schema.allOf[0].type === 'boolean' && schema.allOf[0].const === false && IsObject(schema.allOf[1]) && IsString(schema.allOf[1].type) && schema.allOf[1].type === 'boolean' && schema.allOf[1].const === true ) } /** Returns true if the given schema is TNull */ export function TNull(schema: unknown): schema is Types.TNull { return IsObject(schema) && schema[Types.Kind] === 'Null' && schema.type === 'null' && IsOptionalString(schema.$id) } /** Returns true if the given schema is TNumber */ export function TNumber(schema: unknown): schema is Types.TNumber { return ( IsObject(schema) && schema[Types.Kind] === 'Number' && schema.type === 'number' && IsOptionalString(schema.$id) && IsOptionalNumber(schema.multipleOf) && IsOptionalNumber(schema.minimum) && IsOptionalNumber(schema.maximum) && IsOptionalNumber(schema.exclusiveMinimum) && IsOptionalNumber(schema.exclusiveMaximum) ) } /** Returns true if the given schema is TObject */ export function TObject(schema: unknown): schema is Types.TObject { if ( !( IsObject(schema) && schema[Types.Kind] === 'Object' && schema.type === 'object' && IsOptionalString(schema.$id) && IsObject(schema.properties) && IsOptionalBoolean(schema.additionalProperties) && IsOptionalNumber(schema.minProperties) && IsOptionalNumber(schema.maxProperties) ) ) { return false } for (const [key, value] of Object.entries(schema.properties)) { if (!IsControlCharacterFree(key)) return false if (!TSchema(value)) return false } return true } /** Returns true if the given schema is TPromise */ export function TPromise(schema: unknown): schema is Types.TPromise { return IsObject(schema) && schema[Types.Kind] === 'Promise' && schema.type === 'promise' && IsOptionalString(schema.$id) && TSchema(schema.item) } /** Returns true if the given schema is TRecord */ export function TRecord(schema: unknown): schema is Types.TRecord { if (!(IsObject(schema) && schema[Types.Kind] === 'Record' && schema.type === 'object' && IsOptionalString(schema.$id) && schema.additionalProperties === false && IsObject(schema.patternProperties))) { return false } const keys = Object.keys(schema.patternProperties) if (keys.length !== 1) { return false } if (!IsPattern(keys[0])) { return false } if (!TSchema(schema.patternProperties[keys[0]])) { return false } return true } /** Returns true if the given schema is TSelf */ export function TSelf(schema: unknown): schema is Types.TSelf { return IsObject(schema) && schema[Types.Kind] === 'Self' && IsOptionalString(schema.$id) && IsString(schema.$ref) } /** Returns true if the given schema is TRef */ export function TRef(schema: unknown): schema is Types.TRef { return IsObject(schema) && schema[Types.Kind] === 'Ref' && IsOptionalString(schema.$id) && IsString(schema.$ref) } /** Returns true if the given schema is TString */ export function TString(schema: unknown): schema is Types.TString { return ( IsObject(schema) && schema[Types.Kind] === 'String' && schema.type === 'string' && IsOptionalString(schema.$id) && IsOptionalNumber(schema.minLength) && IsOptionalNumber(schema.maxLength) && IsOptionalPattern(schema.pattern) && IsOptionalFormat(schema.format) ) } /** Returns true if the given schema is TTuple */ export function TTuple(schema: unknown): schema is Types.TTuple { if (!(IsObject(schema) && schema[Types.Kind] === 'Tuple' && schema.type === 'array' && IsOptionalString(schema.$id) && IsNumber(schema.minItems) && IsNumber(schema.maxItems) && schema.minItems === schema.maxItems)) { return false } if (schema.items === undefined && schema.additionalItems === undefined && schema.minItems === 0) { return true } if (!IsArray(schema.items)) { return false } for (const inner of schema.items) { if (!TSchema(inner)) return false } return true } /** Returns true if the given schema is TUndefined */ export function TUndefined(schema: unknown): schema is Types.TUndefined { return IsObject(schema) && schema[Types.Kind] === 'Undefined' && schema.type === 'object' && IsOptionalString(schema.$id) && schema.specialized === 'Undefined' } /** Returns true if the given schema is TUnion */ export function TUnion(schema: unknown): schema is Types.TUnion { if (!(IsObject(schema) && schema[Types.Kind] === 'Union' && IsArray(schema.anyOf) && IsOptionalString(schema.$id))) { return false } for (const inner of schema.anyOf) { if (!TSchema(inner)) return false } return true } /** Returns true if the given schema is TUint8Array */ export function TUint8Array(schema: unknown): schema is Types.TUint8Array { return ( IsObject(schema) && schema[Types.Kind] === 'Uint8Array' && schema.type === 'object' && IsOptionalString(schema.$id) && schema.specialized === 'Uint8Array' && IsOptionalNumber(schema.minByteLength) && IsOptionalNumber(schema.maxByteLength) ) } /** Returns true if the given schema is TUnknown */ export function TUnknown(schema: unknown): schema is Types.TUnknown { return IsObject(schema) && schema[Types.Kind] === 'Unknown' && IsOptionalString(schema.$id) } /** Returns true if the given schema is TVoid */ export function TVoid(schema: unknown): schema is Types.TVoid { return IsObject(schema) && schema[Types.Kind] === 'Void' && schema.type === 'null' && IsOptionalString(schema.$id) } /** Returns true if the given schema is TSchema */ export function TSchema(schema: unknown): schema is Types.TSchema { return ( TAny(schema) || TArray(schema) || TBoolean(schema) || TConstructor(schema) || TFunction(schema) || TInteger(schema) || TLiteral(schema) || TNever(schema) || TNull(schema) || TNumber(schema) || TObject(schema) || TPromise(schema) || TRecord(schema) || TSelf(schema) || TRef(schema) || TString(schema) || TTuple(schema) || TUndefined(schema) || TUnion(schema) || TUint8Array(schema) || TUnknown(schema) || TVoid(schema) ) } /** Asserts if this schema and associated references are valid. */ export function Assert(schema: T, references: Types.TSchema[] = []) { if (!TSchema(schema)) throw new TypeGuardInvalidTypeError(schema) for (const schema of references) { if (!TSchema(schema)) throw new TypeGuardInvalidTypeError(schema) } } } typebox-0.24.44/src/guard/index.ts000066400000000000000000000024601431512220400167230ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/guards The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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' typebox-0.24.44/src/tsconfig.json000066400000000000000000000002431431512220400166460ustar00rootroot00000000000000{ "extends": "../tsconfig.json", "files": ["compiler/index.ts", "conditional/index.ts", "format/index.ts", "guard/index.ts", "value/index.ts", "typebox.ts"] } typebox-0.24.44/src/typebox.ts000066400000000000000000001074611431512220400162130ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ---------------------------------------------------------------------------*/ // -------------------------------------------------------------------------- // Symbols // -------------------------------------------------------------------------- export const Kind = Symbol.for('TypeBox.Kind') export const Hint = Symbol.for('TypeBox.Hint') export const Modifier = Symbol.for('TypeBox.Modifier') // -------------------------------------------------------------------------- // Modifiers // -------------------------------------------------------------------------- export type TModifier = TReadonlyOptional | TOptional | TReadonly export type TReadonly = T & { [Modifier]: 'Readonly' } export type TOptional = T & { [Modifier]: 'Optional' } export type TReadonlyOptional = T & { [Modifier]: 'ReadonlyOptional' } // -------------------------------------------------------------------------- // Schema // -------------------------------------------------------------------------- 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 [prop: string]: any } export interface TSchema extends SchemaOptions { [Kind]: string [Hint]?: string [Modifier]?: string params: unknown[] static: unknown } // -------------------------------------------------------------------------- // TAnySchema // -------------------------------------------------------------------------- export type TAnySchema = | TSchema | TAny | TArray | TBoolean | TConstructor | TEnum | TFunction | TInteger | TLiteral | TNull | TNumber | TObject | TPromise | TRecord | TSelf | TRef | TString | TTuple | TUndefined | TUnion | TUint8Array | TUnknown | TVoid // -------------------------------------------------------------------------- // TNumeric // -------------------------------------------------------------------------- export interface NumericOptions extends SchemaOptions { exclusiveMaximum?: number exclusiveMinimum?: number maximum?: number minimum?: number multipleOf?: number } export type TNumeric = TInteger | TNumber // -------------------------------------------------------------------------- // Any // -------------------------------------------------------------------------- export interface TAny extends TSchema { [Kind]: 'Any' static: any } // -------------------------------------------------------------------------- // Array // -------------------------------------------------------------------------- export interface ArrayOptions extends SchemaOptions { uniqueItems?: boolean minItems?: number maxItems?: number } export interface TArray extends TSchema, ArrayOptions { [Kind]: 'Array' static: Array> type: 'array' items: T } // -------------------------------------------------------------------------- // Boolean // -------------------------------------------------------------------------- export interface TBoolean extends TSchema { [Kind]: 'Boolean' static: boolean type: 'boolean' } // -------------------------------------------------------------------------- // Constructor // -------------------------------------------------------------------------- export type TConstructorParameters> = TTuple export type TInstanceType> = T['returns'] export type StaticContructorParameters = [...{ [K in keyof T]: T[K] extends TSchema ? Static : never }] export interface TConstructor extends TSchema { [Kind]: 'Constructor' static: new (...param: StaticContructorParameters) => Static type: 'constructor' parameters: T returns: U } // -------------------------------------------------------------------------- // Enum // -------------------------------------------------------------------------- export interface TEnumOption { type: 'number' | 'string' const: T } export interface TEnum = Record> extends TSchema { [Kind]: 'Union' static: T[keyof T] anyOf: TLiteral[] } // -------------------------------------------------------------------------- // Function // -------------------------------------------------------------------------- export type TParameters = TTuple export type TReturnType = T['returns'] export type StaticFunctionParameters = [...{ [K in keyof T]: T[K] extends TSchema ? Static : never }] export interface TFunction extends TSchema { [Kind]: 'Function' static: (...param: StaticFunctionParameters) => Static type: 'function' parameters: T returns: U } // -------------------------------------------------------------------------- // Integer // -------------------------------------------------------------------------- export interface TInteger extends TSchema, NumericOptions { [Kind]: 'Integer' static: number type: 'integer' } // -------------------------------------------------------------------------- // Intersect // -------------------------------------------------------------------------- export type IntersectReduce = T extends [infer A, ...infer B] ? IntersectReduce : I extends object ? I : {} // note: rename to IntersectStatic in next minor release export type IntersectEvaluate = { [K in keyof T]: T[K] extends TSchema ? Static : never } export type IntersectProperties = { [K in keyof T]: T[K] extends TObject ? P : {} } export interface TIntersect extends TObject { static: IntersectReduce> properties: IntersectReduce> } // -------------------------------------------------------------------------- // KeyOf: Implemented by way of Union> // -------------------------------------------------------------------------- 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] ? [] : [...UnionToTuple>, L] export type UnionStringLiteralToTuple = T extends TUnion ? { [I in keyof L]: L[I] extends TLiteral ? C : never } : never export type UnionLiteralsFromObject = { [K in ObjectPropertyKeys]: TLiteral } extends infer R ? UnionToTuple : never // export type TKeyOf = { [K in ObjectPropertyKeys]: TLiteral } extends infer R ? UnionToTuple : never export interface TKeyOf extends TUnion> {} // -------------------------------------------------------------------------- // Literal // -------------------------------------------------------------------------- export type TLiteralValue = string | number | boolean export interface TLiteral extends TSchema { [Kind]: 'Literal' static: T const: T } // -------------------------------------------------------------------------- // Never // -------------------------------------------------------------------------- export interface TNever extends TSchema { [Kind]: 'Never' static: never allOf: [{ type: 'boolean'; const: false }, { type: 'boolean'; const: true }] } // -------------------------------------------------------------------------- // Null // -------------------------------------------------------------------------- export interface TNull extends TSchema { [Kind]: 'Null' static: null type: 'null' } // -------------------------------------------------------------------------- // Number // -------------------------------------------------------------------------- export interface TNumber extends TSchema, NumericOptions { [Kind]: 'Number' static: number type: 'number' } // -------------------------------------------------------------------------- // Object // -------------------------------------------------------------------------- export type ReadonlyOptionalPropertyKeys = { [K in keyof T]: T[K] extends TReadonlyOptional ? K : never }[keyof T] export type ReadonlyPropertyKeys = { [K in keyof T]: T[K] extends TReadonly ? K : never }[keyof T] export type OptionalPropertyKeys = { [K in keyof T]: T[K] extends TOptional ? K : never }[keyof T] export type RequiredPropertyKeys = keyof Omit | ReadonlyPropertyKeys | OptionalPropertyKeys> export type PropertiesReduce = { readonly [K in ReadonlyOptionalPropertyKeys]?: Static } & { readonly [K in ReadonlyPropertyKeys]: Static } & { [K in OptionalPropertyKeys]?: Static } & { [K in RequiredPropertyKeys]: Static } extends infer R ? { [K in keyof R]: R[K] } : never export type TRecordProperties, T extends TSchema> = Static extends string ? { [X in Static]: T } : never export interface TProperties { [key: string]: TSchema } export type ObjectProperties = T extends TObject ? U : never export type ObjectPropertyKeys = T extends TObject ? keyof U : never export interface ObjectOptions extends SchemaOptions { additionalProperties?: boolean minProperties?: number maxProperties?: number } export interface TObject extends TSchema, ObjectOptions { [Kind]: 'Object' static: PropertiesReduce type: 'object' properties: T required?: string[] } // -------------------------------------------------------------------------- // Omit // -------------------------------------------------------------------------- export interface TOmit[]> extends TObject, ObjectOptions { static: Omit, Properties[number]> properties: T extends TObject ? Omit : never } // -------------------------------------------------------------------------- // Partial // -------------------------------------------------------------------------- export interface TPartial extends TObject { static: Partial> } // -------------------------------------------------------------------------- // Pick // -------------------------------------------------------------------------- // export interface TPick[]> extends TObject, ObjectOptions { // static: Pick, Properties[number]> // properties: ObjectProperties // } export type TPick[]> = TObject<{ [K in Properties[number]]: T['properties'][K] }> // -------------------------------------------------------------------------- // Promise // -------------------------------------------------------------------------- export interface TPromise extends TSchema { [Kind]: 'Promise' static: Promise> type: 'promise' item: TSchema } // -------------------------------------------------------------------------- // Record // -------------------------------------------------------------------------- export type TRecordKey = TString | TNumber | TUnion[]> export interface TRecord extends TSchema { [Kind]: 'Record' static: Record, Static> type: 'object' patternProperties: { [pattern: string]: T } additionalProperties: false } // -------------------------------------------------------------------------- // Rec // -------------------------------------------------------------------------- export interface TSelf extends TSchema { [Kind]: 'Self' static: this['params'][0] $ref: string } export type TRecursiveReduce = Static]> export interface TRecursive extends TSchema { static: TRecursiveReduce } // -------------------------------------------------------------------------- // Ref // -------------------------------------------------------------------------- export interface TRef extends TSchema { [Kind]: 'Ref' static: Static $ref: string } // -------------------------------------------------------------------------- // Required // -------------------------------------------------------------------------- export interface TRequired> extends TObject { static: Required> } // -------------------------------------------------------------------------- // String // -------------------------------------------------------------------------- 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' export interface StringOptions extends SchemaOptions { minLength?: number maxLength?: number pattern?: string format?: Format contentEncoding?: '7bit' | '8bit' | 'binary' | 'quoted-printable' | 'base64' contentMediaType?: string } export interface TString extends TSchema, StringOptions { [Kind]: 'String' static: string type: 'string' } // -------------------------------------------------------------------------- // Tuple // -------------------------------------------------------------------------- export type TupleToArray> = T extends TTuple ? R : never export interface TTuple extends TSchema { [Kind]: 'Tuple' static: { [K in keyof T]: T[K] extends TSchema ? Static : T[K] } type: 'array' items?: T additionalItems?: false minItems: number maxItems: number } // -------------------------------------------------------------------------- // Undefined // -------------------------------------------------------------------------- export interface TUndefined extends TSchema { [Kind]: 'Undefined' specialized: 'Undefined' static: undefined type: 'object' } // -------------------------------------------------------------------------- // Union // -------------------------------------------------------------------------- export interface TUnion extends TSchema { [Kind]: 'Union' static: { [K in keyof T]: T[K] extends TSchema ? Static : never }[number] anyOf: T } // ------------------------------------------------------------------------- // Uint8Array // ------------------------------------------------------------------------- export interface Uint8ArrayOptions extends SchemaOptions { maxByteLength?: number minByteLength?: number } export interface TUint8Array extends TSchema, Uint8ArrayOptions { [Kind]: 'Uint8Array' static: Uint8Array specialized: 'Uint8Array' type: 'object' } // -------------------------------------------------------------------------- // Unknown // -------------------------------------------------------------------------- export interface TUnknown extends TSchema { [Kind]: 'Unknown' static: unknown } // -------------------------------------------------------------------------- // Unsafe // -------------------------------------------------------------------------- export interface UnsafeOptions extends SchemaOptions { [Kind]?: string } export interface TUnsafe extends TSchema { [Kind]: string static: T } // -------------------------------------------------------------------------- // Void // -------------------------------------------------------------------------- export interface TVoid extends TSchema { [Kind]: 'Void' static: void type: 'null' } // -------------------------------------------------------------------------- // Static // -------------------------------------------------------------------------- /** Creates a static type from a TypeBox type */ export type Static = (T & { params: P })['static'] // -------------------------------------------------------------------------- // TypeBuilder // -------------------------------------------------------------------------- let TypeOrdinal = 0 export class TypeBuilder { // ---------------------------------------------------------------------- // Modifiers // ---------------------------------------------------------------------- /** Creates a readonly optional property */ public ReadonlyOptional(item: T): TReadonlyOptional { return { [Modifier]: 'ReadonlyOptional', ...item } } /** Creates a readonly property */ public Readonly(item: T): TReadonly { return { [Modifier]: 'Readonly', ...item } } /** Creates a optional property */ public Optional(item: T): TOptional { return { [Modifier]: 'Optional', ...item } } // ---------------------------------------------------------------------- // Types // ---------------------------------------------------------------------- /** Creates a any type */ public Any(options: SchemaOptions = {}): TAny { return this.Create({ ...options, [Kind]: 'Any' }) } /** Creates a array type */ public Array(items: T, options: ArrayOptions = {}): TArray { return this.Create({ ...options, [Kind]: 'Array', type: 'array', items }) } /** Creates a boolean type */ public Boolean(options: SchemaOptions = {}): TBoolean { return this.Create({ ...options, [Kind]: 'Boolean', type: 'boolean' }) } /** Creates a tuple type from this constructors parameters */ public ConstructorParameters>(schema: T, options: SchemaOptions = {}): TConstructorParameters { return this.Tuple([...schema.parameters], { ...options }) } /** Creates a constructor type */ public Constructor, U extends TSchema>(parameters: T, returns: U, options?: SchemaOptions): TConstructor, U> /** Creates a constructor type */ public Constructor(parameters: [...T], returns: U, options?: SchemaOptions): TConstructor /** Creates a constructor type */ public Constructor(parameters: any, returns: any, options: SchemaOptions = {}) { if (parameters[Kind] === 'Tuple') { const inner = parameters.items === undefined ? [] : parameters.items return this.Create({ ...options, [Kind]: 'Constructor', type: 'constructor', parameters: inner, returns }) } else if (globalThis.Array.isArray(parameters)) { return this.Create({ ...options, [Kind]: 'Constructor', type: 'constructor', parameters, returns }) } else { throw new Error('TypeBuilder.Constructor: Invalid parameters') } } /** Creates a enum type */ public Enum>(item: T, options: SchemaOptions = {}): TEnum { const values = Object.keys(item) .filter((key) => isNaN(key as any)) .map((key) => item[key]) as T[keyof T][] const anyOf = values.map((value) => (typeof value === 'string' ? { [Kind]: 'Literal', type: 'string' as const, const: value } : { [Kind]: 'Literal', type: 'number' as const, const: value })) return this.Create({ ...options, [Kind]: 'Union', [Hint]: 'Enum', anyOf }) } /** Creates a function type */ public Function, U extends TSchema>(parameters: T, returns: U, options?: SchemaOptions): TFunction, U> /** Creates a function type */ public Function(parameters: [...T], returns: U, options?: SchemaOptions): TFunction /** Creates a function type */ public Function(parameters: any, returns: any, options: SchemaOptions = {}) { if (parameters[Kind] === 'Tuple') { const inner = parameters.items === undefined ? [] : parameters.items return this.Create({ ...options, [Kind]: 'Function', type: 'function', parameters: inner, returns }) } else if (globalThis.Array.isArray(parameters)) { return this.Create({ ...options, [Kind]: 'Function', type: 'function', parameters, returns }) } else { throw new Error('TypeBuilder.Function: Invalid parameters') } } /** Creates a type from this constructors instance type */ public InstanceType>(schema: T, options: SchemaOptions = {}): TInstanceType { return { ...options, ...this.Clone(schema.returns) } } /** Creates a integer type */ public Integer(options: NumericOptions = {}): TInteger { return this.Create({ ...options, [Kind]: 'Integer', type: 'integer' }) } /** Creates a intersect type. */ public Intersect(objects: [...T], options: ObjectOptions = {}): TIntersect { const isOptional = (schema: TSchema) => (schema[Modifier] && schema[Modifier] === 'Optional') || schema[Modifier] === 'ReadonlyOptional' const [required, optional] = [new Set(), new Set()] for (const object of objects) { for (const [key, schema] of Object.entries(object.properties)) { if (isOptional(schema)) optional.add(key) } } for (const object of objects) { for (const key of Object.keys(object.properties)) { if (!optional.has(key)) required.add(key) } } const properties = {} as Record for (const object of objects) { for (const [key, schema] of Object.entries(object.properties)) { properties[key] = properties[key] === undefined ? schema : { [Kind]: 'Union', anyOf: [properties[key], { ...schema }] } } } if (required.size > 0) { return this.Create({ ...options, [Kind]: 'Object', type: 'object', properties, required: [...required] }) } else { return this.Create({ ...options, [Kind]: 'Object', type: 'object', properties }) } } /** Creates a keyof type */ public KeyOf(object: T, options: SchemaOptions = {}): TKeyOf { const items = Object.keys(object.properties).map((key) => this.Create({ ...options, [Kind]: 'Literal', type: 'string', const: key })) return this.Create({ ...options, [Kind]: 'Union', [Hint]: 'KeyOf', anyOf: items }) } /** Creates a literal type. */ public Literal(value: T, options: SchemaOptions = {}): TLiteral { return this.Create({ ...options, [Kind]: 'Literal', const: value, type: typeof value as 'string' | 'number' | 'boolean' }) } /** Creates a never type */ public Never(options: SchemaOptions = {}): TNever { return this.Create({ ...options, [Kind]: 'Never', allOf: [ { type: 'boolean', const: false }, { type: 'boolean', const: true }, ], }) } /** Creates a null type */ public Null(options: SchemaOptions = {}): TNull { return this.Create({ ...options, [Kind]: 'Null', type: 'null' }) } /** Creates a number type */ public Number(options: NumericOptions = {}): TNumber { return this.Create({ ...options, [Kind]: 'Number', type: 'number' }) } /** Creates an object type with the given properties */ public Object(properties: T, options: ObjectOptions = {}): TObject { const property_names = Object.keys(properties) const optional = property_names.filter((name) => { const property = properties[name] as TModifier const modifier = property[Modifier] return modifier && (modifier === 'Optional' || modifier === 'ReadonlyOptional') }) const required = property_names.filter((name) => !optional.includes(name)) if (required.length > 0) { return this.Create({ ...options, [Kind]: 'Object', type: 'object', properties, required }) } else { return this.Create({ ...options, [Kind]: 'Object', type: 'object', properties }) } } /** Creates a new object whose properties are omitted from the given object */ public Omit[]>>(schema: T, keys: K, options?: ObjectOptions): TOmit> /** Creates a new object whose properties are omitted from the given object */ public Omit[]>(schema: T, keys: [...K], options?: ObjectOptions): TOmit /** Creates a new object whose properties are omitted from the given object */ public Omit(schema: any, keys: any, options: ObjectOptions = {}) { const select: string[] = keys[Kind] === 'Union' ? keys.anyOf.map((schema: TLiteral) => schema.const) : keys const next = { ...this.Clone(schema), ...options, [Hint]: 'Omit' } if (next.required) { next.required = next.required.filter((key: string) => !select.includes(key as any)) if (next.required.length === 0) delete next.required } for (const key of Object.keys(next.properties)) { if (select.includes(key as any)) delete next.properties[key] } return this.Create(next) } /** Creates a tuple type from this functions parameters */ public Parameters>(schema: T, options: SchemaOptions = {}): TParameters { return Type.Tuple(schema.parameters, { ...options }) } /** Creates an object type whose properties are all optional */ public Partial(schema: T, options: ObjectOptions = {}): TPartial { const next = { ...this.Clone(schema), ...options, [Hint]: 'Partial' } delete next.required for (const key of Object.keys(next.properties)) { const property = next.properties[key] const modifer = property[Modifier] switch (modifer) { case 'ReadonlyOptional': property[Modifier] = 'ReadonlyOptional' break case 'Readonly': property[Modifier] = 'ReadonlyOptional' break case 'Optional': property[Modifier] = 'Optional' break default: property[Modifier] = 'Optional' break } } return this.Create(next) } /** Creates a object whose properties are picked from the given object */ public Pick[]>>(schema: T, keys: K, options?: ObjectOptions): TPick> /** Creates a object whose properties are picked from the given object */ public Pick[]>(schema: T, keys: [...K], options?: ObjectOptions): TPick /** Creates a object whose properties are picked from the given object */ public Pick[]>(schema: any, keys: any, options: ObjectOptions = {}) { const select: string[] = keys[Kind] === 'Union' ? keys.anyOf.map((schema: TLiteral) => schema.const) : keys const next = { ...this.Clone(schema), ...options, [Hint]: 'Pick' } if (next.required) { next.required = next.required.filter((key: any) => select.includes(key)) if (next.required.length === 0) delete next.required } for (const key of Object.keys(next.properties)) { if (!select.includes(key as any)) delete next.properties[key] } return this.Create(next) } /** Creates a promise type. This type cannot be represented in schema. */ public Promise(item: T, options: SchemaOptions = {}): TPromise { return this.Create({ ...options, [Kind]: 'Promise', type: 'promise', item }) } /** Creates an object whose properties are derived from the given string literal union. */ public Record, T extends TSchema>(key: K, schema: T, options?: ObjectOptions): TObject> /** Creates a record type */ public Record(key: K, schema: T, options?: ObjectOptions): TRecord /** Creates a record type */ public Record(key: any, value: any, options: ObjectOptions = {}) { // If string literal union return TObject with properties extracted from union. if (key[Kind] === 'Union') { return this.Object( key.anyOf.reduce((acc: any, literal: any) => { return { ...acc, [literal.const]: value } }, {}), { ...options, [Hint]: 'Record' }, ) } // otherwise return TRecord with patternProperties const pattern = key[Kind] === 'Number' ? '^(0|[1-9][0-9]*)$' : key[Kind] === 'String' && key.pattern ? key.pattern : '^.*$' return this.Create({ ...options, [Kind]: 'Record', type: 'object', patternProperties: { [pattern]: value }, additionalProperties: false, }) } /** Creates a recursive object type */ public Recursive(callback: (self: TSelf) => T, options: SchemaOptions = {}): TRecursive { if (options.$id === undefined) options.$id = `T${TypeOrdinal++}` const self = callback({ [Kind]: 'Self', $ref: `${options.$id}` } as any) self.$id = options.$id return this.Create({ ...options, ...self } as any) } /** Creates a reference schema */ public Ref(schema: T, options: SchemaOptions = {}): TRef { if (schema.$id === undefined) throw Error('TypeBuilder.Ref: Referenced schema must specify an $id') return this.Create({ ...options, [Kind]: 'Ref', $ref: schema.$id! }) } /** Creates a string type from a regular expression */ public RegEx(regex: RegExp, options: SchemaOptions = {}): TString { return this.Create({ ...options, [Kind]: 'String', type: 'string', pattern: regex.source }) } /** Creates an object type whose properties are all required */ public Required(schema: T, options: SchemaOptions = {}): TRequired { const next = { ...this.Clone(schema), ...options, [Hint]: 'Required' } next.required = Object.keys(next.properties) for (const key of Object.keys(next.properties)) { const property = next.properties[key] const modifier = property[Modifier] switch (modifier) { case 'ReadonlyOptional': property[Modifier] = 'Readonly' break case 'Readonly': property[Modifier] = 'Readonly' break case 'Optional': delete property[Modifier] break default: delete property[Modifier] break } } return this.Create(next) } /** Creates a type from this functions return type */ public ReturnType>(schema: T, options: SchemaOptions = {}): TReturnType { return { ...options, ...this.Clone(schema.returns) } } /** Removes Kind and Modifier symbol property keys from this schema */ public Strict(schema: T): T { return JSON.parse(JSON.stringify(schema)) } /** Creates a string type */ public String(options: StringOptions = {}): TString { return this.Create({ ...options, [Kind]: 'String', type: 'string' }) } /** Creates a tuple type */ public Tuple(items: [...T], options: SchemaOptions = {}): TTuple { const additionalItems = false const minItems = items.length const maxItems = items.length const schema = (items.length > 0 ? { ...options, [Kind]: 'Tuple', type: 'array', items, additionalItems, minItems, maxItems } : { ...options, [Kind]: 'Tuple', type: 'array', minItems, maxItems }) as any return this.Create(schema) } /** Creates a undefined type */ public Undefined(options: SchemaOptions = {}): TUndefined { return this.Create({ ...options, [Kind]: 'Undefined', type: 'object', specialized: 'Undefined' }) } /** Creates a union type */ public Union(items: [], options?: SchemaOptions): TNever public Union(items: [...T], options?: SchemaOptions): TUnion public Union(items: [...T], options: SchemaOptions = {}) { return items.length === 0 ? Type.Never({ ...options }) : this.Create({ ...options, [Kind]: 'Union', anyOf: items }) } /** Creates a Uint8Array type */ public Uint8Array(options: Uint8ArrayOptions = {}): TUint8Array { return this.Create({ ...options, [Kind]: 'Uint8Array', type: 'object', specialized: 'Uint8Array' }) } /** Creates an unknown type */ public Unknown(options: SchemaOptions = {}): TUnknown { return this.Create({ ...options, [Kind]: 'Unknown' }) } /** Creates a user defined schema that infers as type T */ public Unsafe(options: UnsafeOptions = {}): TUnsafe { return this.Create({ ...options, [Kind]: options[Kind] || 'Unsafe' }) } /** Creates a void type */ public Void(options: SchemaOptions = {}): TVoid { return this.Create({ ...options, [Kind]: 'Void', type: 'null' }) } /** Use this function to return TSchema with static and params omitted */ protected Create(schema: Omit): T { return schema as any } /** Clones the given value */ protected Clone(value: any): any { const isObject = (object: any): object is Record => typeof object === 'object' && object !== null && !Array.isArray(object) const isArray = (object: any): object is any[] => typeof object === 'object' && object !== null && Array.isArray(object) if (isObject(value)) { return Object.keys(value).reduce( (acc, key) => ({ ...acc, [key]: this.Clone(value[key]), }), Object.getOwnPropertySymbols(value).reduce( (acc, key) => ({ ...acc, [key]: this.Clone(value[key]), }), {}, ), ) } else if (isArray(value)) { return value.map((item: any) => this.Clone(item)) } else { return value } } } /** JSON Schema Type Builder with Static Type Resolution for TypeScript */ export const Type = new TypeBuilder() typebox-0.24.44/src/value/000077500000000000000000000000001431512220400152545ustar00rootroot00000000000000typebox-0.24.44/src/value/cast.ts000066400000000000000000000401661431512220400165650ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '../typebox' import { ValueCreate } from './create' import { ValueCheck } from './check' import { ValueClone } from './clone' namespace UnionValueCast { // ---------------------------------------------------------------------------------------------- // The following will score a schema against a value. For objects, the score is the tally of // points awarded for each property of the value. Property points are (1.0 / propertyCount) // to prevent large property counts biasing results. Properties that match literal values are // maximally awarded as literals are typically used as union discriminator fields. // ---------------------------------------------------------------------------------------------- function Score(schema: Types.TSchema, references: Types.TSchema[], value: any): number { if (schema[Types.Kind] === 'Object' && typeof value === 'object' && value !== null) { const object = schema as Types.TObject const keys = Object.keys(value) const entries = globalThis.Object.entries(object.properties) const [point, max] = [1 / entries.length, entries.length] return entries.reduce((acc, [key, schema]) => { const literal = schema[Types.Kind] === 'Literal' && schema.const === value[key] ? max : 0 const checks = ValueCheck.Check(schema, references, value[key]) ? point : 0 const exists = keys.includes(key) ? point : 0 return acc + (literal + checks + exists) }, 0) } else { return ValueCheck.Check(schema, references, value) ? 1 : 0 } } function Select(union: Types.TUnion, references: Types.TSchema[], value: any): Types.TSchema { let [select, best] = [union.anyOf[0], 0] for (const schema of union.anyOf) { const score = Score(schema, references, value) if (score > best) { select = schema best = score } } return select } export function Create(union: Types.TUnion, references: Types.TSchema[], value: any) { return ValueCheck.Check(union, references, value) ? ValueClone.Clone(value) : ValueCast.Cast(Select(union, references, value), references, value) } } // ----------------------------------------------------------- // Errors // ----------------------------------------------------------- export class ValueCastReferenceTypeError extends Error { constructor(public readonly schema: Types.TRef | Types.TSelf) { super(`ValueCast: Cannot locate referenced schema with $id '${schema.$ref}'`) } } export class ValueCastArrayUniqueItemsTypeError extends Error { constructor(public readonly schema: Types.TSchema, public readonly value: unknown) { super('ValueCast: Array cast produced invalid data due to uniqueItems constraint') } } export class ValueCastNeverTypeError extends Error { constructor(public readonly schema: Types.TSchema) { super('ValueCast: Never types cannot be cast') } } export class ValueCastRecursiveTypeError extends Error { constructor(public readonly schema: Types.TSchema) { super('ValueCast.Recursive: Cannot cast recursive schemas') } } export class ValueCastUnknownTypeError extends Error { constructor(public readonly schema: Types.TSchema) { super('ValueCast: Unknown type') } } export namespace ValueCast { // ----------------------------------------------------------- // Guards // ----------------------------------------------------------- function IsArray(value: unknown): value is unknown[] { return typeof value === 'object' && globalThis.Array.isArray(value) } function IsString(value: unknown): value is string { return typeof value === 'string' } function IsBoolean(value: unknown): value is boolean { return typeof value === 'boolean' } function IsBigInt(value: unknown): value is bigint { return typeof value === 'bigint' } function IsNumber(value: unknown): value is number { return typeof value === 'number' } 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 === 1n) || (IsString(value) && (value.toLowerCase() === 'true' || value === '1')) } function IsValueFalse(value: unknown): value is true { return value === false || (IsNumber(value) && value === 0) || (IsBigInt(value) && value === 0n) || (IsString(value) && (value.toLowerCase() === 'false' || value === '0')) } // ----------------------------------------------------------- // Convert // ----------------------------------------------------------- function TryConvertString(value: unknown) { return IsValueToString(value) ? value.toString() : value } function TryConvertNumber(value: unknown) { return IsStringNumeric(value) ? parseFloat(value) : IsValueTrue(value) ? 1 : value } function TryConvertInteger(value: unknown) { return IsStringNumeric(value) ? parseInt(value) : IsValueTrue(value) ? 1 : value } function TryConvertBoolean(value: unknown) { return IsValueTrue(value) ? true : IsValueFalse(value) ? false : value } // ----------------------------------------------------------- // Cast // ----------------------------------------------------------- function Any(schema: Types.TAny, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Array(schema: Types.TArray, references: Types.TSchema[], value: any): any { if (ValueCheck.Check(schema, references, value)) return ValueClone.Clone(value) const created = IsArray(value) ? ValueClone.Clone(value) : ValueCreate.Create(schema, references) const minimum = IsNumber(schema.minItems) && created.length < schema.minItems ? [...created, ...globalThis.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 (!ValueCheck.Check(schema, references, unique)) throw new ValueCastArrayUniqueItemsTypeError(schema, unique) return unique } function Boolean(schema: Types.TBoolean, references: Types.TSchema[], value: any): any { const conversion = TryConvertBoolean(value) return ValueCheck.Check(schema, references, conversion) ? conversion : ValueCreate.Create(schema, references) } function Constructor(schema: Types.TConstructor, references: Types.TSchema[], value: any): any { if (ValueCheck.Check(schema, references, value)) return ValueCreate.Create(schema, references) const required = new Set(schema.returns.required || []) const result = function () {} for (const [key, property] of globalThis.Object.entries(schema.returns.properties)) { if (!required.has(key) && value.prototype[key] === undefined) continue result.prototype[key] = Visit(property as Types.TSchema, references, value.prototype[key]) } return result } function Enum(schema: Types.TEnum, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Function(schema: Types.TFunction, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Integer(schema: Types.TInteger, references: Types.TSchema[], value: any): any { const conversion = TryConvertInteger(value) return ValueCheck.Check(schema, references, conversion) ? conversion : ValueCreate.Create(schema, references) } function Literal(schema: Types.TLiteral, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Never(schema: Types.TNever, references: Types.TSchema[], value: any): any { throw new ValueCastNeverTypeError(schema) } function Null(schema: Types.TNull, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Number(schema: Types.TNumber, references: Types.TSchema[], value: any): any { const conversion = TryConvertNumber(value) return ValueCheck.Check(schema, references, conversion) ? conversion : ValueCreate.Create(schema, references) } function Object(schema: Types.TObject, references: Types.TSchema[], value: any): any { if (ValueCheck.Check(schema, references, value)) return ValueClone.Clone(value) if (value === null || typeof value !== 'object') return ValueCreate.Create(schema, references) const required = new Set(schema.required || []) const result = {} as Record for (const [key, property] of globalThis.Object.entries(schema.properties)) { if (!required.has(key) && value[key] === undefined) continue result[key] = Visit(property, references, value[key]) } return result } function Promise(schema: Types.TSchema, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Record(schema: Types.TRecord, references: Types.TSchema[], value: any): any { if (ValueCheck.Check(schema, references, value)) return ValueClone.Clone(value) if (value === null || typeof value !== 'object' || globalThis.Array.isArray(value)) return ValueCreate.Create(schema, references) const subschemaKey = globalThis.Object.keys(schema.patternProperties)[0] const subschema = schema.patternProperties[subschemaKey] const result = {} as Record for (const [propKey, propValue] of globalThis.Object.entries(value)) { result[propKey] = Visit(subschema, references, propValue) } return result } function Recursive(schema: Types.TRecursive, references: Types.TSchema[], value: any): any { throw new ValueCastRecursiveTypeError(schema) } function Ref(schema: Types.TRef, references: Types.TSchema[], value: any): any { const reference = references.find((reference) => reference.$id === schema.$ref) if (reference === undefined) throw new ValueCastReferenceTypeError(schema) return Visit(reference, references, value) } function Self(schema: Types.TSelf, references: Types.TSchema[], value: any): any { const reference = references.find((reference) => reference.$id === schema.$ref) if (reference === undefined) throw new ValueCastReferenceTypeError(schema) return Visit(reference, references, value) } function String(schema: Types.TString, references: Types.TSchema[], value: any): any { const conversion = TryConvertString(value) return ValueCheck.Check(schema, references, conversion) ? conversion : ValueCreate.Create(schema, references) } function Tuple(schema: Types.TTuple, references: Types.TSchema[], value: any): any { if (ValueCheck.Check(schema, references, value)) return ValueClone.Clone(value) if (!globalThis.Array.isArray(value)) return ValueCreate.Create(schema, references) if (schema.items === undefined) return [] return schema.items.map((schema, index) => Visit(schema, references, value[index])) } function Undefined(schema: Types.TUndefined, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Union(schema: Types.TUnion, references: Types.TSchema[], value: any): any { return UnionValueCast.Create(schema, references, value) } function Uint8Array(schema: Types.TUint8Array, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Unknown(schema: Types.TUnknown, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } function Void(schema: Types.TVoid, references: Types.TSchema[], value: any): any { return ValueCheck.Check(schema, references, value) ? value : ValueCreate.Create(schema, references) } export function Visit(schema: Types.TSchema, references: Types.TSchema[], value: any): any { const anyReferences = schema.$id === undefined ? references : [schema, ...references] const anySchema = schema as any switch (schema[Types.Kind]) { case 'Any': return Any(anySchema, anyReferences, value) case 'Array': return Array(anySchema, anyReferences, value) case 'Boolean': return Boolean(anySchema, anyReferences, value) case 'Constructor': return Constructor(anySchema, anyReferences, value) case 'Enum': return Enum(anySchema, anyReferences, value) case 'Function': return Function(anySchema, anyReferences, value) case 'Integer': return Integer(anySchema, anyReferences, value) case 'Literal': return Literal(anySchema, anyReferences, value) case 'Never': return Never(anySchema, anyReferences, value) case 'Null': return Null(anySchema, anyReferences, value) case 'Number': return Number(anySchema, anyReferences, value) case 'Object': return Object(anySchema, anyReferences, value) case 'Promise': return Promise(anySchema, anyReferences, value) case 'Record': return Record(anySchema, anyReferences, value) case 'Rec': return Recursive(anySchema, anyReferences, value) case 'Ref': return Ref(anySchema, anyReferences, value) case 'Self': return Self(anySchema, anyReferences, value) case 'String': return String(anySchema, anyReferences, value) case 'Tuple': return Tuple(anySchema, anyReferences, value) case 'Undefined': return Undefined(anySchema, anyReferences, value) case 'Union': return Union(anySchema, anyReferences, value) case 'Uint8Array': return Uint8Array(anySchema, anyReferences, value) case 'Unknown': return Unknown(anySchema, anyReferences, value) case 'Void': return Void(anySchema, anyReferences, value) default: throw new ValueCastUnknownTypeError(anySchema) } } export function Cast(schema: T, references: [...R], value: any): Types.Static { return schema.$id === undefined ? Visit(schema, references, value) : Visit(schema, [schema, ...references], value) } } typebox-0.24.44/src/value/check.ts000066400000000000000000000277301431512220400167120ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '../typebox' import { Format } from '../format' export class ValueCheckUnknownTypeError extends Error { constructor(public readonly schema: Types.TSchema) { super('ValueCheck: Unknown type') } } export namespace ValueCheck { function Any(schema: Types.TAny, references: Types.TSchema[], value: any): boolean { return true } function Array(schema: Types.TArray, references: Types.TSchema[], value: any): boolean { if (!globalThis.Array.isArray(value)) { return false } if (schema.minItems !== undefined && !(value.length >= schema.minItems)) { return false } if (schema.maxItems !== undefined && !(value.length <= schema.maxItems)) { return false } if (schema.uniqueItems === true && !(new Set(value).size === value.length)) { return false } return value.every((val) => Visit(schema.items, references, val)) } function Boolean(schema: Types.TBoolean, references: Types.TSchema[], value: any): boolean { return typeof value === 'boolean' } function Constructor(schema: Types.TConstructor, references: Types.TSchema[], value: any): boolean { return Visit(schema.returns, references, value.prototype) } function Function(schema: Types.TFunction, references: Types.TSchema[], value: any): boolean { return typeof value === 'function' } function Integer(schema: Types.TNumeric, references: Types.TSchema[], value: any): boolean { if (!(typeof value === 'number')) { return false } if (!globalThis.Number.isInteger(value)) { return false } if (schema.multipleOf !== undefined && !(value % schema.multipleOf === 0)) { return false } if (schema.exclusiveMinimum !== undefined && !(value > schema.exclusiveMinimum)) { return false } if (schema.exclusiveMaximum !== undefined && !(value < schema.exclusiveMaximum)) { return false } if (schema.minimum !== undefined && !(value >= schema.minimum)) { return false } if (schema.maximum !== undefined && !(value <= schema.maximum)) { return false } return true } function Literal(schema: Types.TLiteral, references: Types.TSchema[], value: any): boolean { return value === schema.const } function Never(schema: Types.TNever, references: Types.TSchema[], value: any): boolean { return false } function Null(schema: Types.TNull, references: Types.TSchema[], value: any): boolean { return value === null } function Number(schema: Types.TNumeric, references: Types.TSchema[], value: any): boolean { if (!(typeof value === 'number')) { return false } if (schema.multipleOf && !(value % schema.multipleOf === 0)) { return false } if (schema.exclusiveMinimum && !(value > schema.exclusiveMinimum)) { return false } if (schema.exclusiveMaximum && !(value < schema.exclusiveMaximum)) { return false } if (schema.minimum && !(value >= schema.minimum)) { return false } if (schema.maximum && !(value <= schema.maximum)) { return false } return true } function Object(schema: Types.TObject, references: Types.TSchema[], value: any): boolean { if (!(typeof value === 'object' && value !== null && !globalThis.Array.isArray(value))) { return false } if (schema.minProperties !== undefined && !(globalThis.Object.keys(value).length >= schema.minProperties)) { return false } if (schema.maxProperties !== undefined && !(globalThis.Object.keys(value).length <= schema.maxProperties)) { return false } const propertyKeys = globalThis.Object.keys(schema.properties) if (schema.additionalProperties === false) { // optimization: If the property key length matches the required keys length // then we only need check that the values property key length matches that // of the property key length. This is because exhaustive testing for values // will occur in subsequent property tests. if (schema.required && schema.required.length === propertyKeys.length && !(globalThis.Object.keys(value).length === propertyKeys.length)) { return false } else { if (!globalThis.Object.keys(value).every((key) => propertyKeys.includes(key))) { return false } } } for (const propertyKey of propertyKeys) { const propertySchema = schema.properties[propertyKey] if (schema.required && schema.required.includes(propertyKey)) { if (!Visit(propertySchema, references, value[propertyKey])) { return false } } else { if (value[propertyKey] !== undefined) { if (!Visit(propertySchema, references, value[propertyKey])) { return false } } } } return true } function Promise(schema: Types.TPromise, references: Types.TSchema[], value: any): boolean { return typeof value === 'object' && typeof value.then === 'function' } function Record(schema: Types.TRecord, references: Types.TSchema[], value: any): boolean { if (!(typeof value === 'object' && value !== null && !globalThis.Array.isArray(value))) { return false } const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0] const regex = new RegExp(keyPattern) if (!globalThis.Object.keys(value).every((key) => regex.test(key))) { return false } for (const propValue of globalThis.Object.values(value)) { if (!Visit(valueSchema, references, propValue)) return false } return true } function Ref(schema: Types.TRef, references: Types.TSchema[], value: any): boolean { const reference = references.find((reference) => reference.$id === schema.$ref) if (reference === undefined) throw new Error(`ValueCheck.Ref: Cannot find schema with $id '${schema.$ref}'.`) return Visit(reference, references, value) } function Self(schema: Types.TSelf, references: Types.TSchema[], value: any): boolean { const reference = references.find((reference) => reference.$id === schema.$ref) if (reference === undefined) throw new Error(`ValueCheck.Self: Cannot find schema with $id '${schema.$ref}'.`) return Visit(reference, references, value) } function String(schema: Types.TString, references: Types.TSchema[], value: any): boolean { if (!(typeof value === 'string')) { return false } if (schema.minLength !== undefined) { if (!(value.length >= schema.minLength)) return false } if (schema.maxLength !== undefined) { if (!(value.length <= schema.maxLength)) return false } if (schema.pattern !== undefined) { const regex = new RegExp(schema.pattern) if (!regex.test(value)) return false } if (schema.format !== undefined) { if (!Format.Has(schema.format)) return false const func = Format.Get(schema.format)! return func(value) } return true } function Tuple(schema: Types.TTuple, references: Types.TSchema[], value: any): boolean { if (!globalThis.Array.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 Undefined(schema: Types.TUndefined, references: Types.TSchema[], value: any): boolean { return value === undefined } function Union(schema: Types.TUnion, references: Types.TSchema[], value: any): boolean { return schema.anyOf.some((inner) => Visit(inner, references, value)) } function Uint8Array(schema: Types.TUint8Array, references: Types.TSchema[], value: any): boolean { if (!(value instanceof globalThis.Uint8Array)) { return false } if (schema.maxByteLength && !(value.length <= schema.maxByteLength)) { return false } if (schema.minByteLength && !(value.length >= schema.minByteLength)) { return false } return true } function Unknown(schema: Types.TUnknown, references: Types.TSchema[], value: any): boolean { return true } function Void(schema: Types.TVoid, references: Types.TSchema[], value: any): boolean { return value === null } function Visit(schema: T, references: Types.TSchema[], value: any): boolean { const anyReferences = schema.$id === undefined ? references : [schema, ...references] const anySchema = schema as any switch (anySchema[Types.Kind]) { case 'Any': return Any(anySchema, anyReferences, value) case 'Array': return Array(anySchema, anyReferences, value) case 'Boolean': return Boolean(anySchema, anyReferences, value) case 'Constructor': return Constructor(anySchema, anyReferences, value) case 'Function': return Function(anySchema, anyReferences, value) case 'Integer': return Integer(anySchema, anyReferences, value) case 'Literal': return Literal(anySchema, anyReferences, value) case 'Never': return Never(anySchema, anyReferences, value) case 'Null': return Null(anySchema, anyReferences, value) case 'Number': return Number(anySchema, anyReferences, value) case 'Object': return Object(anySchema, anyReferences, value) case 'Promise': return Promise(anySchema, anyReferences, value) case 'Record': return Record(anySchema, anyReferences, value) case 'Ref': return Ref(anySchema, anyReferences, value) case 'Self': return Self(anySchema, anyReferences, value) case 'String': return String(anySchema, anyReferences, value) case 'Tuple': return Tuple(anySchema, anyReferences, value) case 'Undefined': return Undefined(anySchema, anyReferences, value) case 'Union': return Union(anySchema, anyReferences, value) case 'Uint8Array': return Uint8Array(anySchema, anyReferences, value) case 'Unknown': return Unknown(anySchema, anyReferences, value) case 'Void': return Void(anySchema, anyReferences, value) default: throw new ValueCheckUnknownTypeError(anySchema) } } // ------------------------------------------------------------------------- // Check // ------------------------------------------------------------------------- export function Check(schema: T, references: [...R], value: any): boolean { return schema.$id === undefined ? Visit(schema, references, value) : Visit(schema, [schema, ...references], value) } } typebox-0.24.44/src/value/clone.ts000066400000000000000000000043461431512220400167330ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 { Is, ObjectType, ArrayType, TypedArrayType, ValueType } from './is' export namespace ValueClone { function Object(value: ObjectType): any { const keys = [...globalThis.Object.keys(value), ...globalThis.Object.getOwnPropertySymbols(value)] return keys.reduce((acc, key) => ({ ...acc, [key]: Clone(value[key]) }), {}) } function Array(value: ArrayType): any { return value.map((element: any) => Clone(element)) } function TypedArray(value: TypedArrayType): any { return value.slice() } function Value(value: ValueType): any { return value } export function Clone(value: T): T { if (Is.Object(value)) { return Object(value) } else if (Is.Array(value)) { return Array(value) } else if (Is.TypedArray(value)) { return TypedArray(value) } else if (Is.Value(value)) { return Value(value) } else { throw new Error('ValueClone: Unable to clone value') } } } typebox-0.24.44/src/value/create.ts000066400000000000000000000266561431512220400171060ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '../typebox' export class ValueCreateUnknownTypeError extends Error { constructor(public readonly schema: Types.TSchema) { super('ValueCreate: Unknown type') } } export class ValueCreateNeverTypeError extends Error { constructor(public readonly schema: Types.TSchema) { super('ValueCreate: Never types cannot be created') } } export namespace ValueCreate { function Any(schema: Types.TAny, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { return {} } } function Array(schema: Types.TArray, references: Types.TSchema[]): any { if (schema.uniqueItems === true && schema.default === undefined) { throw new Error('ValueCreate.Array: Arrays with uniqueItems require a default value') } else if (schema.default !== undefined) { return schema.default } else if (schema.minItems !== undefined) { return globalThis.Array.from({ length: schema.minItems }).map((item) => { return ValueCreate.Create(schema.items, references) }) } else { return [] } } function Boolean(schema: Types.TBoolean, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { return false } } function Constructor(schema: Types.TConstructor, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { const value = ValueCreate.Create(schema.returns, references) as any if (typeof value === 'object' && !globalThis.Array.isArray(value)) { return class { constructor() { for (const [key, val] of globalThis.Object.entries(value)) { const self = this as any self[key] = val } } } } else { return class {} } } } function Enum(schema: Types.TEnum, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else if (schema.anyOf.length === 0) { throw new Error('ValueCreate.Enum: Cannot create default enum value as this enum has no items') } else { return schema.anyOf[0].const } } function Function(schema: Types.TFunction, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { return () => ValueCreate.Create(schema.returns, references) } } function Integer(schema: Types.TInteger, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else if (schema.minimum !== undefined) { return schema.minimum } else { return 0 } } function Literal(schema: Types.TLiteral, references: Types.TSchema[]): any { return schema.const } function Never(schema: Types.TNever, references: Types.TSchema[]): any { throw new ValueCreateNeverTypeError(schema) } function Null(schema: Types.TNull, references: Types.TSchema[]): any { return null } function Number(schema: Types.TNumber, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else if (schema.minimum !== undefined) { return schema.minimum } else { return 0 } } function Object(schema: Types.TObject, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { const required = new Set(schema.required) return ( schema.default || globalThis.Object.entries(schema.properties).reduce((acc, [key, schema]) => { return required.has(key) ? { ...acc, [key]: ValueCreate.Create(schema, references) } : { ...acc } }, {}) ) } } function Promise(schema: Types.TPromise, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { return globalThis.Promise.resolve(ValueCreate.Create(schema.item, references)) } } function Record(schema: Types.TRecord, references: Types.TSchema[]): any { const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0] if (schema.default !== undefined) { return schema.default } else if (!(keyPattern === '^.*$' || keyPattern === '^(0|[1-9][0-9]*)$')) { const propertyKeys = keyPattern.slice(1, keyPattern.length - 1).split('|') return propertyKeys.reduce((acc, key) => { return { ...acc, [key]: Create(valueSchema, references) } }, {}) } else { return {} } } function Recursive(schema: Types.TRecursive, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { throw new Error('ValueCreate.Recursive: Recursive types require a default value') } } function Ref(schema: Types.TRef, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { const reference = references.find((reference) => reference.$id === schema.$ref) if (reference === undefined) throw new Error(`ValueCreate.Ref: Cannot find schema with $id '${schema.$ref}'.`) return Visit(reference, references) } } function Self(schema: Types.TSelf, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { const reference = references.find((reference) => reference.$id === schema.$ref) if (reference === undefined) throw new Error(`ValueCreate.Self: Cannot locate schema with $id '${schema.$ref}'`) return Visit(reference, references) } } function String(schema: Types.TString, references: Types.TSchema[]): any { if (schema.pattern !== undefined) { if (schema.default === undefined) { throw new Error('ValueCreate.String: String types with patterns must specify a default value') } else { return schema.default } } else if (schema.format !== undefined) { if (schema.default === undefined) { throw new Error('ValueCreate.String: String types with formats must specify a default value') } else { return schema.default } } else { if (schema.default !== undefined) { return schema.default } else if (schema.minLength !== undefined) { return globalThis.Array.from({ length: schema.minLength }) .map(() => '.') .join('') } else { return '' } } } function Tuple(schema: Types.TTuple, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } if (schema.items === undefined) { return [] } else { return globalThis.Array.from({ length: schema.minItems }).map((_, index) => ValueCreate.Create((schema.items as any[])[index], references)) } } function Undefined(schema: Types.TUndefined, references: Types.TSchema[]): any { return undefined } function Union(schema: Types.TUnion, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else if (schema.anyOf.length === 0) { throw new Error('ValueCreate.Union: Cannot create Union with zero variants') } else { return ValueCreate.Create(schema.anyOf[0], references) } } function Uint8Array(schema: Types.TUint8Array, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else if (schema.minByteLength !== undefined) { return new globalThis.Uint8Array(schema.minByteLength) } else { return new globalThis.Uint8Array(0) } } function Unknown(schema: Types.TUnknown, references: Types.TSchema[]): any { if (schema.default !== undefined) { return schema.default } else { return {} } } function Void(schema: Types.TVoid, references: Types.TSchema[]): any { return null } /** Creates a value from the given schema. If the schema specifies a default value, then that value is returned. */ export function Visit(schema: T, references: Types.TSchema[]): Types.Static { const anyReferences = schema.$id === undefined ? references : [schema, ...references] const anySchema = schema as any switch (anySchema[Types.Kind]) { case 'Any': return Any(anySchema, anyReferences) case 'Array': return Array(anySchema, anyReferences) case 'Boolean': return Boolean(anySchema, anyReferences) case 'Constructor': return Constructor(anySchema, anyReferences) case 'Enum': return Enum(anySchema, anyReferences) case 'Function': return Function(anySchema, anyReferences) case 'Integer': return Integer(anySchema, anyReferences) case 'Literal': return Literal(anySchema, anyReferences) case 'Never': return Never(anySchema, anyReferences) case 'Null': return Null(anySchema, anyReferences) case 'Number': return Number(anySchema, anyReferences) case 'Object': return Object(anySchema, anyReferences) case 'Promise': return Promise(anySchema, anyReferences) case 'Record': return Record(anySchema, anyReferences) case 'Rec': return Recursive(anySchema, anyReferences) case 'Ref': return Ref(anySchema, anyReferences) case 'Self': return Self(anySchema, anyReferences) case 'String': return String(anySchema, anyReferences) case 'Tuple': return Tuple(anySchema, anyReferences) case 'Undefined': return Undefined(anySchema, anyReferences) case 'Union': return Union(anySchema, anyReferences) case 'Uint8Array': return Uint8Array(anySchema, anyReferences) case 'Unknown': return Unknown(anySchema, anyReferences) case 'Void': return Void(anySchema, anyReferences) default: throw new ValueCreateUnknownTypeError(anySchema) } } export function Create(schema: T, references: [...R]): Types.Static { return Visit(schema, references) } } typebox-0.24.44/src/value/delta.ts000066400000000000000000000150751431512220400167250ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 { Is, ObjectType, ArrayType, TypedArrayType, ValueType } from './is' import { ValueClone } from './clone' import { ValuePointer } from './pointer' export type Edit = Insert | Update | Delete export interface Insert { brand: T type: 'insert' path: string value: any } export interface Update { brand: T type: 'update' path: string value: any } export interface Delete { brand: T type: 'delete' path: string } export namespace ValueDelta { // --------------------------------------------------------------------- // Edits // --------------------------------------------------------------------- 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 } // --------------------------------------------------------------------- // Diff // --------------------------------------------------------------------- function* Object(path: string, current: ObjectType, next: unknown): IterableIterator> { if (!Is.Object(next)) return yield Update(path, next) const currentKeys = [...globalThis.Object.keys(current), ...globalThis.Object.getOwnPropertySymbols(current)] const nextKeys = [...globalThis.Object.keys(next), ...globalThis.Object.getOwnPropertySymbols(next)] for (const key of currentKeys) { if (typeof key === 'symbol') throw Error('ValueDelta: Cannot produce diff symbol keys') if (next[key] === undefined && nextKeys.includes(key)) yield Update(`${path}/${String(key)}`, undefined) } for (const key of nextKeys) { if (current[key] === undefined || next[key] === undefined) continue if (typeof key === 'symbol') throw Error('ValueDelta: Cannot produce diff symbol keys') yield* Visit(`${path}/${String(key)}`, current[key], next[key]) } for (const key of nextKeys) { if (typeof key === 'symbol') throw Error('ValueDelta: Cannot produce diff symbol keys') if (current[key] === undefined) yield Insert(`${path}/${String(key)}`, next[key]) } for (const key of currentKeys.reverse()) { if (typeof key === 'symbol') throw Error('ValueDelta: Cannot produce diff symbol keys') if (next[key] === undefined && !nextKeys.includes(key)) yield Delete(`${path}/${String(key)}`) } } function* Array(path: string, current: ArrayType, next: unknown): IterableIterator> { if (!Is.Array(next)) return yield Update(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 Insert(`${path}/${i}`, next[i]) } for (let i = current.length - 1; i >= 0; i--) { if (i < next.length) continue yield Delete(`${path}/${i}`) } } function* TypedArray(path: string, current: TypedArrayType, next: unknown): IterableIterator> { if (!Is.TypedArray(next) || current.length !== next.length || globalThis.Object.getPrototypeOf(current).constructor.name !== globalThis.Object.getPrototypeOf(next).constructor.name) return yield Update(path, next) for (let i = 0; i < Math.min(current.length, next.length); i++) { yield* Visit(`${path}/${i}`, current[i], next[i]) } } function* Value(path: string, current: ValueType, next: unknown): IterableIterator> { if (current === next) return yield Update(path, next) } function* Visit(path: string, current: unknown, next: unknown): IterableIterator> { if (Is.Object(current)) { return yield* Object(path, current, next) } else if (Is.Array(current)) { return yield* Array(path, current, next) } else if (Is.TypedArray(current)) { return yield* TypedArray(path, current, next) } else if (Is.Value(current)) { return yield* Value(path, current, next) } else { throw new Error('ValueDelta: Cannot produce edits for value') } } export function Diff(current: T, next: T): 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: T, edits: Edit[]): T { if (IsRootUpdate(edits)) { return ValueClone.Clone(edits[0].value) } if (IsIdentity(edits)) { return ValueClone.Clone(current) } const clone = ValueClone.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 } } typebox-0.24.44/src/value/equal.ts000066400000000000000000000055221431512220400167370ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 { Is, ObjectType, ArrayType, TypedArrayType, ValueType } from './is' export namespace ValueEqual { function Object(left: ObjectType, right: unknown): boolean { if (!Is.Object(right)) return false const leftKeys = [...globalThis.Object.keys(left), ...globalThis.Object.getOwnPropertySymbols(left)] const rightKeys = [...globalThis.Object.keys(right), ...globalThis.Object.getOwnPropertySymbols(right)] if (leftKeys.length !== rightKeys.length) return false return leftKeys.every((key) => Equal(left[key], right[key])) } function Array(left: ArrayType, right: unknown): any { if (!Is.Array(right) || left.length !== right.length) return false return left.every((value, index) => Equal(value, right[index])) } function TypedArray(left: TypedArrayType, right: unknown): any { if (!Is.TypedArray(right) || left.length !== right.length || globalThis.Object.getPrototypeOf(left).constructor.name !== globalThis.Object.getPrototypeOf(right).constructor.name) return false return left.every((value, index) => Equal(value, right[index])) } function Value(left: ValueType, right: unknown): any { return left === right } export function Equal(left: T, right: unknown): right is T { if (Is.Object(left)) { return Object(left, right) } else if (Is.TypedArray(left)) { return TypedArray(left, right) } else if (Is.Array(left)) { return Array(left, right) } else if (Is.Value(left)) { return Value(left, right) } else { throw new Error('ValueEquals: Unable to compare value') } } } typebox-0.24.44/src/value/index.ts000066400000000000000000000026061431512220400167370ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 } from '../errors/index' export * from './pointer' export * from './value' typebox-0.24.44/src/value/is.ts000066400000000000000000000046241431512220400162450ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 ValueType = null | undefined | Function | symbol | bigint | number | boolean | string export type ObjectType = Record export type TypedArrayType = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array export type ArrayType = unknown[] export namespace Is { export function Object(value: unknown): value is ObjectType { return value !== null && typeof value === 'object' && !globalThis.Array.isArray(value) && !ArrayBuffer.isView(value) } export function Array(value: unknown): value is ArrayType { return globalThis.Array.isArray(value) && !ArrayBuffer.isView(value) } export function Value(value: unknown): value is ValueType { return value === null || value === undefined || typeof value === 'function' || typeof value === 'symbol' || typeof value === 'bigint' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'string' } export function TypedArray(value: unknown): value is TypedArrayType { return ArrayBuffer.isView(value) } } typebox-0.24.44/src/value/pointer.ts000066400000000000000000000106071431512220400173100ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 class ValuePointerRootSetError extends Error { constructor(public readonly value: unknown, public readonly path: string, public readonly update: unknown) { super('ValuePointer: Cannot set root value') } } export class ValuePointerRootDeleteError extends Error { constructor(public readonly value: unknown, public readonly path: string) { super('ValuePointer: Cannot delete root value') } } /** ValuePointer performs mutable operations on values using RFC6901 Json Pointers */ export namespace ValuePointer { function Escape(component: string) { return component.indexOf('~') === -1 ? component : component.replace(/~1/g, '/').replace(/~0/g, '~') } /** Formats the given pointer into navigable key components */ 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 */ 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 */ 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 (globalThis.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 */ 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 globalThis.Object.getOwnPropertyNames(owner).includes(key) } /** Gets the value at the given pointer */ 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 } } typebox-0.24.44/src/value/value.ts000066400000000000000000000115451431512220400167460ustar00rootroot00000000000000/*-------------------------------------------------------------------------- @sinclair/typebox/value The MIT License (MIT) Copyright (c) 2022 Haydn Paterson (sinclair) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 '../typebox' import { ValueErrors, ValueError } from '../errors/index' import { ValueEqual } from './equal' import { ValueCast } from './cast' import { ValueClone } from './clone' import { ValueCreate } from './create' import { ValueCheck } from './check' import { ValueDelta, Edit } from './delta' export type { Edit } from './delta' /** Value performs immutable operations on values */ export namespace Value { /** Casts a value into a given type. The return value will retain as much information of the original value as possible. Cast will convert string, number and boolean values if a reasonable conversion is possible. */ export function Cast(schema: T, references: [...R], value: unknown): Types.Static /** Casts a value into a given type. The return value will retain as much information of the original value as possible. Cast will convert string, number and boolean values if a reasonable conversion is possible. */ export function Cast(schema: T, value: unknown): Types.Static export function Cast(...args: any[]) { const [schema, references, value] = args.length === 3 ? [args[0], args[1], args[2]] : [args[0], [], args[1]] return ValueCast.Cast(schema, references, value) } /** Creates a value from the given type */ export function Create(schema: T, references: [...R]): Types.Static /** Creates a value from the given type */ export function Create(schema: T): Types.Static export function Create(...args: any[]) { const [schema, references] = args.length === 2 ? [args[0], args[1]] : [args[0], []] return ValueCreate.Create(schema, references) } /** Returns true if the value matches the given type. */ export function Check(schema: T, references: [...R], value: unknown): value is Types.Static /** Returns true if the value matches the given type. */ export function Check(schema: T, value: unknown): value is Types.Static export function Check(...args: any[]) { const [schema, references, value] = args.length === 3 ? [args[0], args[1], args[2]] : [args[0], [], args[1]] return ValueCheck.Check(schema, references, value) } /** Returns an iterator for each error in this value. */ export function Errors(schema: T, references: [...R], value: unknown): IterableIterator /** Returns an iterator for each error in this value. */ export function Errors(schema: T, value: unknown): IterableIterator export function* Errors(...args: any[]) { const [schema, references, value] = args.length === 3 ? [args[0], args[1], args[2]] : [args[0], [], args[1]] yield* ValueErrors.Errors(schema, references, value) } /** Returns true if left and right values are structurally equal */ export function Equal(left: T, right: unknown): right is T { return ValueEqual.Equal(left, right) } /** Returns a structural clone of the given value */ export function Clone(value: T): T { return ValueClone.Clone(value) } /** Returns edits to transform the current value into the next value */ export function Diff(current: T, next: T): Edit[] { return ValueDelta.Diff(current, next) } /** Returns a new value with edits applied to the given value */ export function Patch(current: T, edits: Edit[]): T { return ValueDelta.Patch(current, edits) as T } } typebox-0.24.44/test/000077500000000000000000000000001431512220400143305ustar00rootroot00000000000000typebox-0.24.44/test/runtime/000077500000000000000000000000001431512220400160135ustar00rootroot00000000000000typebox-0.24.44/test/runtime/assert/000077500000000000000000000000001431512220400173145ustar00rootroot00000000000000typebox-0.24.44/test/runtime/assert/assert.ts000066400000000000000000000026671431512220400212000ustar00rootroot00000000000000import * as assert from 'assert' export namespace Assert { let port = 9000 /** Generates a new port used for host binding */ export function nextPort() { const next = port++ return next } export function equal(actual: unknown, expect: unknown) { return assert.equal(actual, expect) } export function notEqual(actual: unknown, expect: unknown) { return assert.notEqual(actual, expect) } export function deepEqual(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.deepEqual(actual, expect) } let nextIdOrdinal = 0 export function nextId() { return `nextID${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 isTypeOf(value: any, type: any) { if (typeof value === type) return throw Error(`Value is not typeof ${type}`) } export function isInstanceOf(value: any, constructor: any) { if (value instanceof constructor) return throw Error(`Value is not instance of ${constructor}`) } } typebox-0.24.44/test/runtime/assert/index.ts000066400000000000000000000000311431512220400207650ustar00rootroot00000000000000export * from './assert' typebox-0.24.44/test/runtime/compiler/000077500000000000000000000000001431512220400176255ustar00rootroot00000000000000typebox-0.24.44/test/runtime/compiler/any.ts000066400000000000000000000013331431512220400207640ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok } from './validate' describe('type/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) }) }) typebox-0.24.44/test/runtime/compiler/array.ts000066400000000000000000000056421431512220400213220ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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 intersection types when passing additionalProperties false', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.String() }) const C = Type.Intersect([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]) }) it('Should validate array with uniqueItems when items are references', () => { const T = Type.Array(Type.Object({ x: Type.Number(), y: Type.Number() }), { uniqueItems: true }) ok(T, [ { x: 0, y: 1 }, { x: 1, y: 0 }, ]) // references distinct }) it('Should not validate array with non uniqueItems', () => { const T = Type.Array(Type.Number(), { uniqueItems: true }) fail(T, [0, 0]) }) }) typebox-0.24.44/test/runtime/compiler/boolean.ts000066400000000000000000000014761431512220400216240ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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) }) }) typebox-0.24.44/test/runtime/compiler/enum.ts000066400000000000000000000022341431512220400211420ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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) }) }) typebox-0.24.44/test/runtime/compiler/index.ts000066400000000000000000000010251431512220400213020ustar00rootroot00000000000000import './any' import './array' import './boolean' import './enum' import './intersect' import './keyof' import './literal' import './modifier' import './never' 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 './regex' import './required' import './string' import './tuple' import './uint8array' import './union' import './unknown' import './void' typebox-0.24.44/test/runtime/compiler/intersect.ts000066400000000000000000000053431431512220400222020ustar00rootroot00000000000000import { Type, Static } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/compiler/Intersect', () => { it('Should intersect two objects', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Intersect([A, B], { additionalProperties: false }) ok(T, { a: 'hello', b: 42 }) }) it('Should intersect with partial', () => { const A = Type.Partial(Type.Object({ a: Type.Number() })) const B = Type.Partial(Type.Object({ b: Type.Number() })) const P = Type.Intersect([A, B], { additionalProperties: false }) ok(P, { a: 1, b: 2 }) // ok(P, { a: 1 }) // ok(P, { b: 1 }) // ok(P, {}) // fail(P, { c: 1 }) }) it('Should intersect with overlapping same type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.Number() }) const P = Type.Intersect([A, B]) ok(P, { a: 1 }) fail(P, { a: 'hello' }) fail(P, {}) }) it('Should intersect with overlapping varying type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.String() }) const T = Type.Intersect([A, B]) ok(T, { a: 1 }) ok(T, { a: 'hello' }) fail(T, {}) }) it('Should intersect 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.Intersect([A, B, C, D]) ok(T, { a: 1 }) ok(T, { a: 'hello' }) ok(T, { a: false }) ok(T, { a: null }) fail(T, { a: [] }) fail(T, {}) }) it('Should pick from intersected 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.Intersect([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 intersected 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.Intersect([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 intersect nested object properties', () => { const A = Type.Object({ x: Type.Object({ x: Type.Number() }) }) const B = Type.Object({ x: Type.Object({ x: Type.String() }) }) const T = Type.Intersect([A, B]) ok(T, { x: { x: 1 } }) ok(T, { x: { x: 'hello' } }) fail(T, { x: { x: false } }) }) }) typebox-0.24.44/test/runtime/compiler/keyof.ts000066400000000000000000000020141431512220400213070ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/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') }) }) typebox-0.24.44/test/runtime/compiler/literal.ts000066400000000000000000000021201431512220400216240ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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') }) }) typebox-0.24.44/test/runtime/compiler/modifier.ts000066400000000000000000000001271431512220400217730ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' describe('type/compiler/Modifier', () => {}) typebox-0.24.44/test/runtime/compiler/never.ts000066400000000000000000000014321431512220400213140ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { fail } from './validate' describe('type/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) }) }) typebox-0.24.44/test/runtime/compiler/null.ts000066400000000000000000000014271431512220400211530ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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) }) }) typebox-0.24.44/test/runtime/compiler/number.ts000066400000000000000000000014351431512220400214700ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/compiler/Number', () => { it('Should validate number', () => { 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) }) }) typebox-0.24.44/test/runtime/compiler/object.ts000066400000000000000000000062751431512220400214550ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/compiler/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, }) }) }) typebox-0.24.44/test/runtime/compiler/omit.ts000066400000000000000000000027511431512220400211520ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/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 }) }) }) typebox-0.24.44/test/runtime/compiler/optional.ts000066400000000000000000000012771431512220400220310ustar00rootroot00000000000000import { strictEqual } from 'assert' import { Type } from '@sinclair/typebox' import { ok } from './validate' describe('type/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) }) }) typebox-0.24.44/test/runtime/compiler/partial.ts000066400000000000000000000027161431512220400216370ustar00rootroot00000000000000import { Type, Modifier } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/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.ReadonlyOptional(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[Modifier], 'ReadonlyOptional') strictEqual(T.properties.y[Modifier], 'ReadonlyOptional') strictEqual(T.properties.z[Modifier], 'Optional') strictEqual(T.properties.w[Modifier], '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) }) }) typebox-0.24.44/test/runtime/compiler/pick.ts000066400000000000000000000030141431512220400211210ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/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 }) }) }) typebox-0.24.44/test/runtime/compiler/readonly-optional.ts000066400000000000000000000013351431512220400236370ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/compiler/ReadonlyOptional', () => { it('Should validate object with optional', () => { const T = Type.Object( { a: Type.ReadonlyOptional(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.ReadonlyOptional(Type.String()), b: Type.String(), }, { additionalProperties: false }, ) strictEqual(T.required!.includes('a'), false) }) }) typebox-0.24.44/test/runtime/compiler/readonly.ts000066400000000000000000000014111431512220400220070ustar00rootroot00000000000000import { deepStrictEqual, strictEqual } from 'assert' import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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) }) }) typebox-0.24.44/test/runtime/compiler/record.ts000066400000000000000000000061641431512220400214620ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/compiler/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 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()) 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()) 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()) 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()) fail(T, { '0': 1, '1': 2, '2': 3, '3': 4, a: 'hello' }) }) 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 should validate when specifying regular expressions', () => { const K = Type.RegEx(/^op_.*$/) const T = Type.Record(K, Type.Number()) ok(T, { op_a: 1, op_b: 2, op_c: 3, }) }) it('Should should not validate when specifying regular expressions and passing invalid property', () => { const K = Type.RegEx(/^op_.*$/) const T = Type.Record(K, Type.Number()) fail(T, { op_a: 1, op_b: 2, aop_c: 3, }) }) }) typebox-0.24.44/test/runtime/compiler/recursive.ts000066400000000000000000000034661431512220400222150ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' import { ok, fail } from './validate' describe('type/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.equal(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.equal(Node.$id === 'Node', true) }) it('Should validate recursive node type', () => { const Node = Type.Recursive((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ) ok(Node, { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, ], }) }) it('Should validate wrapped recursive node type', () => { const Node = Type.Tuple([ Type.Recursive((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ), ]) 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((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ), ]) fail(Node, [ { id: 'A', nodes: [ { id: 1, nodes: [] }, { id: 'C', nodes: [] }, ], }, ]) }) }) typebox-0.24.44/test/runtime/compiler/ref.ts000066400000000000000000000025621431512220400207560ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { Assert } from '../assert/index' describe('type/compiler/Ref', () => { 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) 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) 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: '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]) }) }) typebox-0.24.44/test/runtime/compiler/regex.ts000066400000000000000000000013751431512220400213150ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/compiler/RegEx', () => { it('Should validate numeric value', () => { const T = Type.RegEx(/[012345]/) ok(T, '0') ok(T, '1') ok(T, '2') ok(T, '3') ok(T, '4') ok(T, '5') }) it('Should validate true or false string value', () => { const T = Type.RegEx(/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 not validate failed regex test', () => { const T = Type.RegEx(/true|false/) fail(T, 'unknown') }) it('Should pass numeric 5 digit test', () => { const T = Type.RegEx(/[\d]{5}/) ok(T, '12345') }) }) typebox-0.24.44/test/runtime/compiler/required.ts000066400000000000000000000034671431512220400220270ustar00rootroot00000000000000import { Type, Modifier } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/compiler/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.ReadonlyOptional(Type.Number()), y: Type.Readonly(Type.Number()), z: Type.Optional(Type.Number()), w: Type.Number(), }) const T = Type.Required(A) strictEqual(T.properties.x[Modifier], 'Readonly') strictEqual(T.properties.y[Modifier], 'Readonly') strictEqual(T.properties.z[Modifier], undefined) strictEqual(T.properties.w[Modifier], 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') // }) }) typebox-0.24.44/test/runtime/compiler/string.ts000066400000000000000000000031411431512220400215020ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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 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') }) }) typebox-0.24.44/test/runtime/compiler/tuple.ts000066400000000000000000000035301431512220400213270ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { Assert } from '../assert' describe('type/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 }]) }) }) typebox-0.24.44/test/runtime/compiler/uint8array.ts000066400000000000000000000024011431512220400223000ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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)) }) }) typebox-0.24.44/test/runtime/compiler/union.ts000066400000000000000000000044041431512220400213270ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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 }) }) typebox-0.24.44/test/runtime/compiler/unknown.ts000066400000000000000000000013451431512220400216770ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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) }) }) typebox-0.24.44/test/runtime/compiler/validate.ts000066400000000000000000000101621431512220400217660ustar00rootroot00000000000000import { TypeCompiler } from '@sinclair/typebox/compiler' import { Value } from '@sinclair/typebox/value' import { TSchema } from '@sinclair/typebox' import { Format } from 'src/format' // ------------------------------------------------------------------------- // 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 // ------------------------------------------------------------------------- Format.Set('email', (value) => EMAIL.test(value)) Format.Set('uuid', (value) => UUID.test(value)) Format.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) { 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, additional: any[] = []) { const C = TypeCompiler.Compile(schema, additional) const result = C.Check(data) 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') } } typebox-0.24.44/test/runtime/compiler/void.ts000066400000000000000000000014231431512220400211360ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/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.Null() ok(T, null) }) it('Should not validate undefined', () => { const T = Type.Void() fail(T, undefined) }) }) typebox-0.24.44/test/runtime/conditional/000077500000000000000000000000001431512220400203165ustar00rootroot00000000000000typebox-0.24.44/test/runtime/conditional/any.ts000066400000000000000000000067711431512220400214700ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Any', () => { it('Should extend Any', () => { type T = any extends any ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = any extends unknown ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = any extends string ? 1 : 2 const R = Structural.Check(Type.Any(), Type.String()) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Boolean', () => { type T = any extends boolean ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Number', () => { type T = any extends number ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Number()) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Integer', () => { type T = any extends number ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Integer()) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Array 1', () => { type T = any extends Array ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Array 2', () => { type T = any extends Array ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Array(Type.String())) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Tuple', () => { type T = any extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Object 1', () => { type T = any extends object ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Object({})) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Object 2', () => { type T = any extends {} ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Object({})) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Object 3', () => { type T = any extends { a: number } ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Object({ a: Type.Number() })) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Union 1', () => { type T = any extends number | string ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Union 2', () => { type T = any extends any | number ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Union([Type.Any(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = any extends null ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Null()) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Undefined', () => { type T = any extends undefined ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Void', () => { type T = any extends void ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Void()) Assert.deepEqual(R, StructuralResult.Union) }) }) typebox-0.24.44/test/runtime/conditional/array.ts000066400000000000000000000274771431512220400220250ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Array', () => { // ---------------------------------------------- // Generic Varying // ---------------------------------------------- it('Should extend Array Varying 1', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array Varying 2', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array Varying 3', () => { type T = Array extends Array ? 1 : 2 // 1 const R = Structural.Check(Type.Array(Type.Any()), Type.Array(Type.String())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array Varying 4', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.Number()), Type.Array(Type.String())) Assert.deepEqual(R, StructuralResult.False) }) // ---------------------------------------------- // Any // ---------------------------------------------- it('Should extend Any', () => { type T = Array extends any ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = Array extends unknown ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = Array extends string ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = Array extends boolean ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = Array extends number ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = Array extends number ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 1', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array 2', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array 3', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Tuple', () => { type T = Array extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = Array extends object ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = Array extends {} ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 3', () => { type T = Array extends { a: number } ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Object({ a: Type.Number() })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 4', () => { type T = Array extends { length: '1' } ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Object({ length: Type.Literal('1') })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 5', () => { type T = Array extends { length: number } ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Object({ length: Type.Number() })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 1', () => { type T = Array extends number | string ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = Array extends any | number ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3', () => { type T = Array extends any | Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 4', () => { type T = Array extends any | Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 5', () => { type T = Array extends any | Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Union([Type.Any(), Type.Array(Type.String())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = Array extends null ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = Array extends undefined ? 1 : 2 const R = Structural.Check(Type.Array(Type.Any()), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) // ---------------------------------------------- // Constrained // ---------------------------------------------- it('Should extend constrained Any', () => { type T = Array extends any ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Unknown', () => { type T = Array extends unknown ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained String', () => { type T = Array extends string ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Boolean', () => { type T = Array extends boolean ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Number', () => { type T = Array extends number ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Integer', () => { type T = Array extends number ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Array 1', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Array 2', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Array 3', () => { type T = Array extends Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Tuple', () => { type T = Array extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Object 1', () => { type T = Array extends object ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Object 2', () => { type T = Array extends {} ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Object 3', () => { type T = Array extends { a: number } ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Object({ a: Type.Number() })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Object 4', () => { type T = Array extends { length: '1' } ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Object({ length: Type.Literal('1') })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Object 5', () => { type T = Array extends { length: number } ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Object({ length: Type.Number() })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Union 1', () => { type T = Array extends number | string ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Union([Type.Null(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Union 2', () => { type T = Array extends any | number ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Union([Type.Any(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Union 3', () => { type T = Array extends any | Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Union 4', () => { type T = Array extends any | Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Union 5', () => { type T = Array extends any | Array ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Union([Type.Any(), Type.Array(Type.String())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Null', () => { type T = Array extends null ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Undefined', () => { type T = Array extends undefined ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Void', () => { type T = Array extends void ? 1 : 2 const R = Structural.Check(Type.Array(Type.String()), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/boolean.ts000066400000000000000000000074071431512220400223150ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Boolean', () => { it('Should extend Any', () => { type T = boolean extends any ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = boolean extends string ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = boolean extends boolean ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Number', () => { type T = boolean extends number ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = boolean extends number ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array', () => { type T = boolean extends Array ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = boolean extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record', () => { type T = boolean extends Record ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = boolean extends {} ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = boolean extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = boolean extends object ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = boolean extends number | string ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = boolean extends any | number ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = boolean extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = boolean extends null ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = boolean extends undefined ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = boolean extends void ? 1 : 2 const R = Structural.Check(Type.Boolean(), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/constructor.ts000066400000000000000000000251731431512220400232630ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Constructor', () => { it('Should extend Function', () => { type T = (new () => number) extends () => number ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Function([], Type.Number())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Constructor 1', () => { type T = (new () => number) extends new () => number ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Constructor([], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 2', () => { type T = (new () => any) extends new () => number ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 3', () => { type T = (new () => number) extends new () => any ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 4', () => { type T = (new (a: number) => number) extends new () => any ? 1 : 2 const R = Structural.Check(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([], Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Constructor 5', () => { type T = (new (a: number | string) => number) extends new (a: number) => number ? 1 : 2 const R = Structural.Check(Type.Constructor([Type.Union([Type.Number(), Type.String()])], Type.Number()), Type.Constructor([Type.Number()], Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 6', () => { type T = (new (a: number) => number) extends new (a: number | string) => any ? 1 : 2 const R = Structural.Check(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([Type.Union([Type.Number(), Type.String()])], Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Constructor 7', () => { type T = (new (a: number, b: number) => number) extends new (a: number) => number ? 1 : 2 const R = Structural.Check(Type.Constructor([Type.Number(), Type.Number()], Type.Number()), Type.Constructor([Type.Number()], Type.Number())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Constructor 8', () => { type T = (new (a: number) => number) extends new (a: number, b: number) => number ? 1 : 2 const R = Structural.Check(Type.Constructor([Type.Number()], Type.Number()), Type.Constructor([Type.Number(), Type.Number()], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 9', () => { type T = (new () => number) extends new () => any ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Constructor([], Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 9', () => { type T = (new () => any) extends new () => number ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Any()), Type.Constructor([], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 10', () => { type T = (new () => Array) extends new () => object ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Array(Type.Any())), Type.Constructor([], Type.Object({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 11', () => { type T = (new () => Array) extends new () => object ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Array(Type.String())), Type.Constructor([], Type.Object({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 12', () => { type T = (new () => object) extends new () => Array ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Object({})), Type.Constructor([], Type.Array(Type.Any()))) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Constructor 13', () => { type T = (new (a: unknown) => number) extends new (a: any) => number ? 1 : 2 const R = Structural.Check(Type.Constructor([Type.Unknown()], Type.Number({})), Type.Constructor([Type.Any()], Type.Number({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 14', () => { type T = (new (a: any) => number) extends new (a: unknown) => number ? 1 : 2 const R = Structural.Check(Type.Constructor([Type.Any()], Type.Number({})), Type.Constructor([Type.Unknown()], Type.Number({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 15', () => { type T = (new () => any) extends new () => unknown ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Any({})), Type.Constructor([], Type.Unknown({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Constructor 16', () => { type T = (new () => unknown) extends new () => any ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Unknown({})), Type.Constructor([], Type.Any({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Any', () => { type T = (new () => number) extends any ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = (new () => number) extends string ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = (new () => number) extends boolean ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = (new () => number) extends number ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = (new () => number) extends number ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 1', () => { type T = (new () => number) extends Array ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 2', () => { type T = (new () => number) extends Array ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 3', () => { type T = (new () => number) extends Array ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = (new () => number) extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record', () => { type T = (() => number) extends Record ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = (new () => number) extends object ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = (new () => number) extends {} ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 3', () => { type T = (new () => number) extends { a: number } ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Object({ a: Type.Number() })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 4', () => { type T = (new () => number) extends { length: '1' } ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Object({ length: Type.Literal('1') })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = (new () => number) extends number | string ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Union([Type.Null(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = (new () => number) extends any | number ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3', () => { type T = (new () => number) extends any | Array ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 4', () => { type T = (new () => number) extends any | Array ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 5', () => { type T = (new () => number) extends any | Array ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.String())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = (new () => number) extends null ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = (new () => number) extends undefined ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = (new () => number) extends void ? 1 : 2 const R = Structural.Check(Type.Constructor([], Type.Number()), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/function.ts000066400000000000000000000243521431512220400225210ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Function', () => { it('Should extend Constructor 1', () => { type T = (() => number) extends new () => number ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Constructor([], Type.Number())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Function 1', () => { type T = (() => number) extends () => number ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Function([], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 2', () => { type T = (() => any) extends () => number ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Any()), Type.Function([], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 3', () => { type T = (() => number) extends () => any ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Any()), Type.Function([], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 4', () => { type T = ((a: number) => number) extends () => any ? 1 : 2 const R = Structural.Check(Type.Function([Type.Number()], Type.Number()), Type.Function([], Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Function 5', () => { type T = ((a: number | string) => number) extends (a: number) => number ? 1 : 2 const R = Structural.Check(Type.Function([Type.Union([Type.Number(), Type.String()])], Type.Number()), Type.Function([Type.Number()], Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 6', () => { type T = ((a: number) => number) extends (a: number | string) => any ? 1 : 2 const R = Structural.Check(Type.Function([Type.Number()], Type.Number()), Type.Function([Type.Union([Type.Number(), Type.String()])], Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Function 7', () => { type T = ((a: number, b: number) => number) extends (a: number) => number ? 1 : 2 const R = Structural.Check(Type.Function([Type.Number(), Type.Number()], Type.Number()), Type.Function([Type.Number()], Type.Number())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Function 8', () => { type T = ((a: number) => number) extends (a: number, b: number) => number ? 1 : 2 const R = Structural.Check(Type.Function([Type.Number()], Type.Number()), Type.Function([Type.Number(), Type.Number()], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 9', () => { type T = (() => number) extends () => any ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Function([], Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 9', () => { type T = (() => any) extends () => number ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Any()), Type.Function([], Type.Number())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 10', () => { type T = (() => Array) extends () => object ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Array(Type.Any())), Type.Function([], Type.Object({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 11', () => { type T = (() => Array) extends () => object ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Array(Type.String())), Type.Function([], Type.Object({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 12', () => { type T = (() => object) extends () => Array ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Object({})), Type.Function([], Type.Array(Type.Any()))) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Function 13', () => { type T = ((a: unknown) => number) extends (a: any) => number ? 1 : 2 const R = Structural.Check(Type.Function([Type.Unknown()], Type.Number({})), Type.Function([Type.Any()], Type.Number({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 14', () => { type T = ((a: any) => number) extends (a: unknown) => number ? 1 : 2 const R = Structural.Check(Type.Function([Type.Any()], Type.Number({})), Type.Function([Type.Unknown()], Type.Number({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 15', () => { type T = (() => any) extends () => unknown ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Any({})), Type.Function([], Type.Unknown({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Function 16', () => { type T = (() => unknown) extends () => any ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Unknown({})), Type.Function([], Type.Any({}))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Any', () => { type T = (() => number) extends any ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = (() => number) extends string ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = (() => number) extends boolean ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = (() => number) extends number ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = (() => number) extends number ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 1', () => { type T = (() => number) extends Array ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 2', () => { type T = (() => number) extends Array ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 3', () => { type T = (() => number) extends Array ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = (() => number) extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record', () => { type T = (() => number) extends Record ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = (() => number) extends object ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = (() => number) extends {} ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 3', () => { type T = (() => number) extends { a: number } ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Object({ a: Type.Number() })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 4', () => { type T = (() => number) extends { length: '1' } ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Object({ length: Type.Literal('1') })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 5', () => { type T = (() => number) extends { length: number } ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Object({ length: Type.Number() })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 1', () => { type T = (() => number) extends number | string ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Union([Type.Null(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = (() => number) extends any | number ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3', () => { type T = (() => number) extends any | Array ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 4', () => { type T = (() => number) extends any | Array ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.Any())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 5', () => { type T = (() => number) extends any | Array ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Union([Type.Any(), Type.Array(Type.String())])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = (() => number) extends null ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = (() => number) extends undefined ? 1 : 2 const R = Structural.Check(Type.Function([], Type.Number()), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/index.ts000066400000000000000000000005371431512220400220020ustar00rootroot00000000000000import './any' import './array' import './boolean' import './constructor' import './function' import './integer' import './literal' import './null' import './number' import './object' import './promise' import './record' import './string' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' typebox-0.24.44/test/runtime/conditional/integer.ts000066400000000000000000000076771431512220400223440ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Integer', () => { it('Should extend Any', () => { type T = number extends any ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = number extends unknown ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = number extends string ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = number extends boolean ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = number extends number ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Number()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Integer', () => { type T = number extends number ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Integer()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array', () => { type T = number extends Array ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = number extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record', () => { type T = number extends Record ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = number extends {} ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = number extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = number extends object ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = number extends number | string ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = number extends any | number ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = number extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = number extends null ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = number extends undefined ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = number extends undefined ? 1 : 2 const R = Structural.Check(Type.Integer(), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/literal.ts000066400000000000000000000301171431512220400223240ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Literal', () => { // ------------------------------------------------------------------- // String Literal // ------------------------------------------------------------------- it('Should extend Any (String)', () => { type T = 'hello' extends any ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown (String)', () => { type T = 'hello' extends unknown ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String (String)', () => { type T = 'hello' extends string ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.String()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Boolean (String)', () => { type T = 'hello' extends boolean ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number (String)', () => { type T = 'hello' extends number ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer (String)', () => { type T = 'hello' extends number ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array (String)', () => { type T = 'hello' extends Array ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple (String)', () => { type T = 'hello' extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1 (String)', () => { type T = 'hello' extends {} ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2 (String)', () => { type T = 'hello' extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3 (String)', () => { type T = 'hello' extends object ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1 (String)', () => { type T = 'hello' extends number | string ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2 (String)', () => { type T = 'hello' extends any | number ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3 (String)', () => { type T = 'hello' extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Null (String)', () => { type T = 'hello' extends null ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined (String)', () => { type T = 'hello' extends undefined ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) // ------------------------------------------------------------------- // Number Literal // ------------------------------------------------------------------- it('Should extend Any (Number)', () => { type T = 10 extends any ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown (Number)', () => { type T = 10 extends unknown ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String (Number)', () => { type T = 10 extends string ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean (Number)', () => { type T = 10 extends boolean ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number (Number)', () => { type T = 10 extends number ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Number()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Integer (Number)', () => { type T = 10 extends number ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Integer()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array (Number)', () => { type T = 10 extends Array ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple (Number)', () => { type T = 10 extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1 (Number)', () => { type T = 10 extends {} ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2 (Number)', () => { type T = 10 extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3 (Number)', () => { type T = 10 extends object ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1 (Number)', () => { type T = 10 extends number | string ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2 (Number)', () => { type T = 10 extends any | number ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3 (Number)', () => { type T = 10 extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null (Number)', () => { type T = 10 extends null ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined (Number)', () => { type T = 10 extends undefined ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) // ------------------------------------------------------------------- // Boolean Literal // ------------------------------------------------------------------- it('Should extend Any (Boolean)', () => { type T = true extends any ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown (Boolean)', () => { type T = true extends unknown ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String (Boolean)', () => { type T = true extends string ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean (Boolean)', () => { type T = true extends boolean ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Boolean()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Number (Boolean)', () => { type T = true extends number ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer (Boolean)', () => { type T = true extends number ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array (Boolean)', () => { type T = true extends Array ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple (Boolean)', () => { type T = true extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record 1', () => { type T = 'hello' extends Record ? 1 : 2 const R = Structural.Check(Type.Literal('hello'), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Record 2', () => { type T = 10 extends Record ? 1 : 2 const R = Structural.Check(Type.Literal(10), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record 3', () => { type T = true extends Record ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1 (Boolean)', () => { type T = true extends {} ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2 (Boolean)', () => { type T = true extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3 (Boolean)', () => { type T = true extends object ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1 (Boolean)', () => { type T = true extends number | string ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2 (Boolean)', () => { type T = true extends any | number ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3 (Boolean)', () => { type T = true extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null (Boolean)', () => { type T = true extends null ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined (Boolean)', () => { type T = true extends undefined ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = true extends void ? 1 : 2 const R = Structural.Check(Type.Literal(true), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/null.ts000066400000000000000000000075421431512220400216500ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Null', () => { it('Should extend Any', () => { type T = null extends any ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = null extends unknown ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = null extends string ? 1 : 2 const R = Structural.Check(Type.Null(), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = null extends boolean ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = null extends number ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = null extends number ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array', () => { type T = null extends Array ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = null extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record', () => { type T = null extends Record ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = null extends {} ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 2', () => { type T = null extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = null extends object ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = null extends number | string ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = null extends any | number ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = null extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Null', () => { type T = null extends null ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Null()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Undefined', () => { type T = null extends undefined ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = null extends void ? 1 : 2 const R = Structural.Check(Type.Null(), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/number.ts000066400000000000000000000076461431512220400221730ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Number', () => { it('Should extend Any', () => { type T = number extends any ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = number extends unknown ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = number extends string ? 1 : 2 const R = Structural.Check(Type.Number(), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = number extends boolean ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = number extends number ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Number()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Integer', () => { type T = number extends number ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Integer()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array', () => { type T = number extends Array ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = number extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record', () => { type T = number extends Record ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = number extends {} ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = number extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = number extends object ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = number extends number | string ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = number extends any | number ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = number extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = number extends null ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = number extends undefined ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = number extends void ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/object.ts000066400000000000000000000142531431512220400221410ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Object', () => { // ---------------------------------------------------------- // Record // ---------------------------------------------------------- it('Should extend Record 1', () => { 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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.True) }) 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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.True) }) // ---------------------------------------------------------- // Standard // ---------------------------------------------------------- it('Should extend Any', () => { type T = { a: number } extends any ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = { a: number } extends string ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = { a: number } extends boolean ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = { a: number } extends number ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = { a: number } extends number ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array', () => { type T = { a: number } extends Array ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = { a: number } extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = { a: number } extends {} ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = { a: number } extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Object({ a: Type.Literal(10) })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = { a: number } extends object ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 1', () => { type T = { a: number } extends number | string ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Union([Type.Null(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = { a: number } extends any | number ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = { a: number } extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Null', () => { type T = { a: number } extends null ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = { a: number } extends undefined ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = { a: number } extends void ? 1 : 2 const R = Structural.Check(Type.Object({ a: Type.Number() }), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/promise.ts000066400000000000000000000226061431512220400223520ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Promise', () => { // ---------------------------------------------- // Generic Varying // ---------------------------------------------- it('Should extend Promise Varying 1', () => { type T = Promise extends Promise ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Promise(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Promise Varying 2', () => { type T = Promise extends Promise ? 1 : 2 const R = Structural.Check(Type.Promise(Type.String()), Type.Promise(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Promise Varying 3', () => { type T = Promise extends Promise ? 1 : 2 // 1 const R = Structural.Check(Type.Promise(Type.Any()), Type.Promise(Type.String())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Promise Varying 4', () => { type T = Promise extends Promise ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Promise(Type.String())) Assert.deepEqual(R, StructuralResult.False) }) // ---------------------------------------------- // Any // ---------------------------------------------- it('Should extend Any', () => { type T = Promise extends any ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = Promise extends unknown ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = Promise extends string ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = Promise extends boolean ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = Promise extends number ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = Promise extends number ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array', () => { type T = Promise extends Array ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = Promise extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record', () => { type T = Promise extends Record ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = Promise extends {} ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = Promise extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = Promise extends object ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 1', () => { type T = Promise extends number | string ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = Promise extends any | number ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = Promise extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Null', () => { type T = Promise extends null ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = Promise extends undefined ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) // ---------------------------------------------- // Constrained // ---------------------------------------------- it('Should extend constrained Any', () => { type T = Promise extends any ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Unknown', () => { type T = Promise extends unknown ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained String', () => { type T = Promise extends string ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Boolean', () => { type T = Promise extends boolean ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Number', () => { type T = Promise extends number ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Any()), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Integer', () => { type T = Promise extends number ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Array', () => { type T = Promise extends Array ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Tuple', () => { type T = Promise extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Object 1', () => { type T = Promise extends {} ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Object 2', () => { type T = Promise extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Object 3', () => { type T = Promise extends object ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Union 1', () => { type T = Promise extends number | string ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Union 2', () => { type T = Promise extends any | number ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend constrained Union 2', () => { type T = Promise extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Null', () => { type T = Promise extends null ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend constrained Undefined', () => { type T = Promise extends undefined ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = Promise extends void ? 1 : 2 const R = Structural.Check(Type.Promise(Type.Number()), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/record.ts000066400000000000000000000202171431512220400221460ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.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 = Structural.Check(A, B) Assert.deepEqual(R, StructuralResult.True) }) // ------------------------------------------------------------------- // Standard // ------------------------------------------------------------------- it('Should extend Any', () => { type T = Record extends any ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = Record extends unknown ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = Record extends string ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = Record extends boolean ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = Record extends number ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = Record extends number ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 1', () => { type T = Record extends Array ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 2', () => { type T = Record extends Array ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Array(Type.String())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = Record extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = Record extends object ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = Record extends {} ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 3', () => { type T = Record extends { a: number } ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Object({ a: Type.Number() })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = Record extends number | string ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = Record extends any | number ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Union([Type.Any(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = Record extends null ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = Record extends undefined ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = Record extends void ? 1 : 2 const R = Structural.Check(Type.Record(Type.Number(), Type.Number()), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/string.ts000066400000000000000000000121411431512220400221730ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/String', () => { it('Should extend Any', () => { type T = string extends any ? 1 : 2 const R = Structural.Check(Type.String(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = string extends unknown ? 1 : 2 const R = Structural.Check(Type.String(), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = string extends string ? 1 : 2 const R = Structural.Check(Type.String(), Type.String()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Boolean', () => { type T = string extends boolean ? 1 : 2 const R = Structural.Check(Type.String(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = string extends number ? 1 : 2 const R = Structural.Check(Type.String(), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = string extends number ? 1 : 2 const R = Structural.Check(Type.String(), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array', () => { type T = string extends Array ? 1 : 2 const R = Structural.Check(Type.String(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = string extends [number, number] ? 1 : 2 const R = Structural.Check(Type.String(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record 1', () => { type T = string extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Record 2', () => { type T = string extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.Unknown())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Record 3', () => { type T = string extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.String())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Record 4', () => { type T = string extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.Number())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record 5', () => { type T = string extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.Union([Type.Number(), Type.String()]))) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record 6', () => { type T = string extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = string extends {} ? 1 : 2 const R = Structural.Check(Type.String(), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = string extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.String(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = string extends object ? 1 : 2 const R = Structural.Check(Type.String(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = number extends number | string ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = number extends any | number ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3', () => { type T = number extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = number extends null ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = number extends undefined ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = number extends void ? 1 : 2 const R = Structural.Check(Type.Number(), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/tuple.ts000066400000000000000000000203341431512220400220210ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Tuple', () => { it('Should extend Any', () => { type T = [string, number] extends any ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = [string, number] extends string ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = [string, number] extends boolean ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = [string, number] extends number ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = [string, number] extends number ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 1', () => { type T = [string, number] extends Array ? 1 : 2 // 1 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array 2', () => { type T = [string, number] extends Array ? 1 : 2 // 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.String())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 3', () => { type T = [string, number] extends Array ? 1 : 2 // 1 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Union([Type.String(), Type.Number()]))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Array 4', () => { type T = [string, number] extends Array ? 1 : 2 // 1 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Array(Type.Union([Type.String(), Type.Number(), Type.Boolean()]))) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Tuple 1', () => { type T = [string, number] extends [string, number] ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Tuple 2', () => { type T = [string, number] extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple 3', () => { type T = [string, any] extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Any()]), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple 4', () => { type T = [string, number] extends [string, any] ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Any()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Tuple 5', () => { type T = [string, unknown] extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Unknown()]), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple 6', () => { type T = [string, number] extends [string, unknown] ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([Type.String(), Type.Unknown()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Tuple 7', () => { type T = [] extends [string, number] ? 1 : 2 const R = Structural.Check(Type.Tuple([]), Type.Tuple([Type.String(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple 8', () => { type T = [string, number] extends [] ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Tuple([])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record 1', () => { type T = [string, number] extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Record 2', () => { type T = [string, number] extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.Unknown())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Record 3', () => { type T = [string, number] extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.String())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Record 4', () => { type T = [string, number] extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.Number())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record 5', () => { type T = [string, number] extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Record(Type.Number(), Type.Union([Type.Number(), Type.String()]))) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record 6', () => { type T = [string, number] extends Record ? 1 : 2 const R = Structural.Check(Type.String(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = [string, number] extends {} ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = [string, number] extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = [string, number] extends object ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Object({})) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 1', () => { type T = [string, number] extends number | string ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = [string, number] extends any | number ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = [string, number] extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Null', () => { type T = [string, number] extends null ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = [string, number] extends undefined ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = [string, number] extends void ? 1 : 2 const R = Structural.Check(Type.Tuple([Type.String(), Type.Number()]), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/uint8array.ts000066400000000000000000000100761431512220400230000ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Uint8Array', () => { it('Should extend Any', () => { type T = Uint8Array extends any ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = Uint8Array extends unknown ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = Uint8Array extends string ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = Uint8Array extends boolean ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = Uint8Array extends number ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = Uint8Array extends number ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array', () => { type T = Uint8Array extends Array ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = Uint8Array extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Record', () => { type T = Uint8Array extends Record ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Record(Type.Number(), Type.Any())) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 1', () => { type T = Uint8Array extends {} ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = Uint8Array extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = Uint8Array extends object ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = Uint8Array extends number | string ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = Uint8Array extends any | number ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3', () => { type T = Uint8Array extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Null', () => { type T = Uint8Array extends null ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = Uint8Array extends undefined ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = Uint8Array extends void ? 1 : 2 const R = Structural.Check(Type.Uint8Array(), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/undefined.ts000066400000000000000000000071371431512220400226370ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Undefined', () => { it('Should extend Any', () => { type T = undefined extends any ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = undefined extends string ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = undefined extends boolean ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = undefined extends number ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = undefined extends number ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array', () => { type T = undefined extends Array ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = undefined extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = undefined extends {} ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 2', () => { type T = undefined extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = undefined extends object ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = undefined extends number | string ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = undefined extends any | number ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = undefined extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Null', () => { type T = undefined extends null ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = undefined extends undefined ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Void', () => { type T = undefined extends void ? 1 : 2 const R = Structural.Check(Type.Undefined(), Type.Void()) Assert.deepEqual(R, StructuralResult.True) }) }) typebox-0.24.44/test/runtime/conditional/union.ts000066400000000000000000000133531431512220400220230ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Union', () => { it('Should extend Any', () => { type T = number | string extends any ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = number | string extends string ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = number | string extends boolean ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = number | string extends number ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = number | string extends number ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array', () => { type T = number | string extends Array ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = number | string extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = number | string extends {} ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Object({}, { additionalProperties: false })) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Object 2', () => { type T = number | string extends { a: 10 } ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Object({ a: Type.Literal(10) }, { additionalProperties: true })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = number | string extends object ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = number | string extends number | string ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 2', () => { type T = number | string extends any | number ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Any(), Type.Number()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3', () => { type T = number | string extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 4', () => { type T = any | boolean extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Union 5', () => { type T = any | string extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Union 6', () => { type T = any | {} extends {} ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Union 7', () => { type T = any extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Any(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.Union) }) it('Should extend Union 8', () => { type T = unknown | string extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Union([Type.Unknown(), Type.String()]), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 9', () => { type T = unknown extends boolean | number ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Union([Type.Boolean(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Null', () => { type T = number | string extends null ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = number | string extends undefined ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = number | string extends void ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void 2', () => { type T = number | string | void extends void ? 1 : 2 const R = Structural.Check(Type.Union([Type.Number(), Type.String()]), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/unknown.ts000066400000000000000000000101721431512220400223660ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Unknown', () => { it('Should extend Any', () => { type T = unknown extends any ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = unknown extends unknown ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = unknown extends string ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = unknown extends boolean ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = unknown extends number ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = unknown extends number ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 1', () => { type T = unknown extends Array ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 2', () => { type T = unknown extends Array ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Array(Type.String())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = unknown extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = unknown extends object ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 2', () => { type T = unknown extends {} ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = unknown extends { a: number } ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Object({ a: Type.Number() })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = unknown extends number | string ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = unknown extends any | number ? 1 : 2 // 1 const R = Structural.Check(Type.Unknown(), Type.Union([Type.Any(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3', () => { type T = unknown extends unknown | number ? 1 : 2 // 1 const R = Structural.Check(Type.Unknown(), Type.Union([Type.Unknown(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 4', () => { type T = unknown extends unknown | any ? 1 : 2 // 1 const R = Structural.Check(Type.Unknown(), Type.Union([Type.Unknown(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = unknown extends null ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = unknown extends undefined ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = unknown extends void ? 1 : 2 const R = Structural.Check(Type.Unknown(), Type.Void()) Assert.deepEqual(R, StructuralResult.False) }) }) typebox-0.24.44/test/runtime/conditional/void.ts000066400000000000000000000100041431512220400216220ustar00rootroot00000000000000import { Structural, StructuralResult } from '@sinclair/typebox/conditional' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('conditional/structural/Void', () => { it('Should extend Any', () => { type T = void extends any ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Any()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Unknown', () => { type T = void extends unknown ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Unknown()) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend String', () => { type T = void extends string ? 1 : 2 const R = Structural.Check(Type.Void(), Type.String()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Boolean', () => { type T = void extends boolean ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Boolean()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Number', () => { type T = void extends number ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Number()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Integer', () => { type T = void extends number ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Integer()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 1', () => { type T = void extends Array ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Array(Type.Any())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Array 2', () => { type T = void extends Array ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Array(Type.String())) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Tuple', () => { type T = void extends [number, number] ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Tuple([Type.Number(), Type.Number()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 1', () => { type T = void extends object ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 2', () => { type T = void extends {} ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Object({})) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Object 3', () => { type T = void extends { a: number } ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Object({ a: Type.Number() })) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 1', () => { type T = void extends number | string ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Union([Type.Number(), Type.String()])) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Union 2', () => { type T = void extends any | number ? 1 : 2 // 1 const R = Structural.Check(Type.Void(), Type.Union([Type.Any(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 3', () => { type T = void extends unknown | number ? 1 : 2 // 1 const R = Structural.Check(Type.Void(), Type.Union([Type.Unknown(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Union 4', () => { type T = void extends unknown | any ? 1 : 2 // 1 const R = Structural.Check(Type.Void(), Type.Union([Type.Unknown(), Type.String()])) Assert.deepEqual(R, StructuralResult.True) }) it('Should extend Null', () => { type T = void extends null ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Null()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Undefined', () => { type T = void extends undefined ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Undefined()) Assert.deepEqual(R, StructuralResult.False) }) it('Should extend Void', () => { type T = void extends void ? 1 : 2 const R = Structural.Check(Type.Void(), Type.Void()) Assert.deepEqual(R, StructuralResult.True) }) }) typebox-0.24.44/test/runtime/format/000077500000000000000000000000001431512220400173035ustar00rootroot00000000000000typebox-0.24.44/test/runtime/format/format.ts000066400000000000000000000012561431512220400211470ustar00rootroot00000000000000import { Format } from '@sinclair/typebox/format' import { Assert } from '../assert/index' describe('format/Format', () => { it('Should set format', () => { Format.Set('test#format1', () => true) }) it('Should get format', () => { Format.Set('test#format2', () => true) const format = Format.Get('test#format2') Assert.equal(typeof format, 'function') }) it('Should return true if exists', () => { Format.Set('test#format3', () => true) Assert.equal(Format.Has('test#format3'), true) }) it('Should clear formats', () => { Format.Set('test#format4', () => true) Format.Clear() Assert.equal(Format.Has('test#format4'), false) }) }) typebox-0.24.44/test/runtime/format/index.ts000066400000000000000000000000221431512220400207540ustar00rootroot00000000000000import './format' typebox-0.24.44/test/runtime/guard/000077500000000000000000000000001431512220400171155ustar00rootroot00000000000000typebox-0.24.44/test/runtime/guard/any.ts000066400000000000000000000010511431512220400202510ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TAny', () => { it('should guard for TAny', () => { const R = TypeGuard.TAny(Type.Any()) Assert.equal(R, true) }) it('should not guard for TAny', () => { const R = TypeGuard.TAny(null) Assert.equal(R, false) }) it('should not guard for TAny with invalid $id', () => { // @ts-ignore const R = TypeGuard.TAny(Type.Any({ $id: 1 })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/array.ts000066400000000000000000000032101431512220400205770ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TArray', () => { it('should guard for TArray', () => { const R = TypeGuard.TArray(Type.Array(Type.Number())) Assert.equal(R, true) }) it('should not guard for TArray', () => { const R = TypeGuard.TArray(null) Assert.equal(R, false) }) it('should guard for nested object TArray', () => { const R = TypeGuard.TArray( Type.Array( Type.Object({ x: Type.Number(), y: Type.Number(), }), ), ) Assert.equal(R, true) }) it('should not guard for nested object TArray', () => { const R = TypeGuard.TArray( Type.Array( Type.Object({ x: Type.Number(), y: {} as any, }), ), ) Assert.equal(R, false) }) it('should not guard for TArray with invalid $id', () => { // @ts-ignore const R = TypeGuard.TArray(Type.Array(Type.Number(), { $id: 1 })) Assert.equal(R, false) }) it('should not guard for TArray with invalid minItems', () => { // @ts-ignore const R = TypeGuard.TArray(Type.Array(Type.String(), { minItems: '1' })) Assert.equal(R, false) }) it('should not guard for TArray with invalid maxItems', () => { // @ts-ignore const R = TypeGuard.TArray(Type.Array(Type.String(), { maxItems: '1' })) Assert.equal(R, false) }) it('should not guard for TArray with invalid uniqueItems', () => { // @ts-ignore const R = TypeGuard.TArray(Type.Array(Type.String(), { uniqueItems: '1' })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/boolean.ts000066400000000000000000000011151431512220400211020ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TBoolean', () => { it('should guard for TBoolean', () => { const R = TypeGuard.TBoolean(Type.Boolean()) Assert.equal(R, true) }) it('should not guard for TBoolean', () => { const R = TypeGuard.TBoolean(null) Assert.equal(R, false) }) it('should not guard for TBoolean with invalid $id', () => { // @ts-ignore const R = TypeGuard.TBoolean(Type.Boolean({ $id: 1 })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/constructor.ts000066400000000000000000000026131431512220400220540ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TConstructor', () => { it('should guard for TConstructor', () => { const R = TypeGuard.TConstructor(Type.Constructor([], Type.Number())) Assert.equal(R, true) }) it('should not guard for TConstructor', () => { const R = TypeGuard.TConstructor(null) Assert.equal(R, false) }) it('should not guard for TConstructor with invalid $id', () => { // @ts-ignore const R = TypeGuard.TConstructor(Type.Constructor([], Type.Number(), { $id: 1 })) Assert.equal(R, false) }) it('should not guard for TConstructor with invalid Params', () => { const R = TypeGuard.TConstructor(Type.Constructor([{} as any, {} as any], Type.Number())) Assert.equal(R, false) }) it('should not guard for TConstructor with invalid Return', () => { const R = TypeGuard.TConstructor(Type.Constructor([], {} as any)) Assert.equal(R, false) }) it('should guard for TConstructor with empty TTuple', () => { const R = TypeGuard.TConstructor(Type.Constructor(Type.Tuple([]), Type.Number())) Assert.equal(R, true) }) it('should guard for TConstructor with array TTuple', () => { const R = TypeGuard.TConstructor(Type.Constructor(Type.Tuple([Type.Number(), Type.String()]), Type.Number())) Assert.equal(R, true) }) }) typebox-0.24.44/test/runtime/guard/function.ts000066400000000000000000000025141431512220400213140ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TFunction', () => { it('should guard for TFunction', () => { const R = TypeGuard.TFunction(Type.Function([], Type.Number())) Assert.equal(R, true) }) it('should not guard for TFunction', () => { const R = TypeGuard.TFunction(null) Assert.equal(R, false) }) it('should not guard for TFunction with invalid $id', () => { // @ts-ignore const R = TypeGuard.TFunction(Type.Function([], Type.Number(), { $id: 1 })) Assert.equal(R, false) }) it('should not guard for TFunction with invalid Params', () => { const R = TypeGuard.TFunction(Type.Function([{} as any, {} as any], Type.Number())) Assert.equal(R, false) }) it('should not guard for TFunction with invalid Return', () => { const R = TypeGuard.TFunction(Type.Function([], {} as any)) Assert.equal(R, false) }) it('should guard for TFunction with empty TTuple', () => { const R = TypeGuard.TFunction(Type.Function(Type.Tuple([]), Type.Number())) Assert.equal(R, true) }) it('should guard for TFunction with array TTuple', () => { const R = TypeGuard.TFunction(Type.Function(Type.Tuple([Type.Number(), Type.String()]), Type.Number())) Assert.equal(R, true) }) }) typebox-0.24.44/test/runtime/guard/index.ts000066400000000000000000000005761431512220400206040ustar00rootroot00000000000000import './any' import './array' import './boolean' import './constructor' import './function' import './integer' import './literal' import './null' import './number' import './object' import './promise' import './record' import './ref' import './self' import './string' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' typebox-0.24.44/test/runtime/guard/integer.ts000066400000000000000000000030051431512220400211200ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TInteger', () => { it('should guard for TInteger', () => { const R = TypeGuard.TInteger(Type.Integer()) Assert.equal(R, true) }) it('should not guard for TInteger', () => { const R = TypeGuard.TInteger(null) Assert.equal(R, false) }) it('should not guard for TInteger with invalid $id', () => { // @ts-ignore const R = TypeGuard.TInteger(Type.Integer({ $id: 1 })) Assert.equal(R, false) }) it('should not guard for TInteger with invalid multipleOf', () => { // @ts-ignore const R = TypeGuard.TInteger(Type.Integer({ multipleOf: '1' })) Assert.equal(R, false) }) it('should not guard for TInteger with invalid minimum', () => { // @ts-ignore const R = TypeGuard.TInteger(Type.Integer({ minimum: '1' })) Assert.equal(R, false) }) it('should not guard for TInteger with invalid maximum', () => { // @ts-ignore const R = TypeGuard.TInteger(Type.Integer({ maximum: '1' })) Assert.equal(R, false) }) it('should not guard for TInteger with invalid exclusiveMinimum', () => { // @ts-ignore const R = TypeGuard.TInteger(Type.Integer({ exclusiveMinimum: '1' })) Assert.equal(R, false) }) it('should not guard for TInteger with invalid exclusiveMaximum', () => { // @ts-ignore const R = TypeGuard.TInteger(Type.Integer({ exclusiveMaximum: '1' })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/literal.ts000066400000000000000000000020161431512220400211200ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TLiteral', () => { it('should guard for TLiteral of String', () => { const R = TypeGuard.TLiteral(Type.Literal('hello')) Assert.equal(R, true) }) it('should guard for TLiteral of Number', () => { const R = TypeGuard.TLiteral(Type.Literal(42)) Assert.equal(R, true) }) it('should guard for TLiteral of Boolean', () => { const R = TypeGuard.TLiteral(Type.Literal(true)) Assert.equal(R, true) }) it('should not guard for TLiteral of Null', () => { // @ts-ignore const R = TypeGuard.TLiteral(Type.Literal(null)) Assert.equal(R, false) }) it('should not guard for TLiteral', () => { const R = TypeGuard.TLiteral(null) Assert.equal(R, false) }) it('should not guard for TLiteral with invalid $id', () => { // @ts-ignore const R = TypeGuard.TLiteral(Type.Literal(42, { $id: 1 })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/null.ts000066400000000000000000000010621431512220400204360ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TNull', () => { it('should guard for TNull', () => { const R = TypeGuard.TNull(Type.Null()) Assert.equal(R, true) }) it('should not guard for TNull', () => { const R = TypeGuard.TNull(null) Assert.equal(R, false) }) it('should not guard for TNull with invalid $id', () => { // @ts-ignore const R = TypeGuard.TNull(Type.Null({ $id: 1 })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/number.ts000066400000000000000000000027551431512220400207660ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TNumber', () => { it('should guard for TNumber', () => { const R = TypeGuard.TNumber(Type.Number()) Assert.equal(R, true) }) it('should not guard for TNumber', () => { const R = TypeGuard.TNumber(null) Assert.equal(R, false) }) it('should not guard for TNumber with invalid $id', () => { // @ts-ignore const R = TypeGuard.TNumber(Type.Number({ $id: 1 })) Assert.equal(R, false) }) it('should not guard for TNumber with invalid multipleOf', () => { // @ts-ignore const R = TypeGuard.TNumber(Type.Number({ multipleOf: '1' })) Assert.equal(R, false) }) it('should not guard for TNumber with invalid minimum', () => { // @ts-ignore const R = TypeGuard.TNumber(Type.Number({ minimum: '1' })) Assert.equal(R, false) }) it('should not guard for TNumber with invalid maximum', () => { // @ts-ignore const R = TypeGuard.TNumber(Type.Number({ maximum: '1' })) Assert.equal(R, false) }) it('should not guard for TNumber with invalid exclusiveMinimum', () => { // @ts-ignore const R = TypeGuard.TNumber(Type.Number({ exclusiveMinimum: '1' })) Assert.equal(R, false) }) it('should not guard for TNumber with invalid exclusiveMaximum', () => { // @ts-ignore const R = TypeGuard.TNumber(Type.Number({ exclusiveMaximum: '1' })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/object.ts000066400000000000000000000041021431512220400207300ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TObject', () => { it('should guard for TObject', () => { const R = TypeGuard.TObject( Type.Object({ x: Type.Number(), y: Type.Number(), }), ) Assert.equal(R, true) }) it('should not guard for TObject', () => { const R = TypeGuard.TObject(null) Assert.equal(R, false) }) it('should not guard for TObject with escape characters in property key', () => { const R = TypeGuard.TObject( Type.Object({ 'hello\nworld': Type.Number(), }), ) Assert.equal(R, false) }) it('should not guard for TObject with invalid property values', () => { const R = TypeGuard.TObject( Type.Object({ x: Type.Number(), y: {} as any, }), ) Assert.equal(R, false) }) it('should not guard for TObject with invalid additionalProperties', () => { const R = TypeGuard.TObject( Type.Object( { x: Type.Number(), }, { // @ts-ignore additionalProperties: 'true', }, ), ) Assert.equal(R, false) }) it('should not guard for TObject with invalid $id', () => { const R = TypeGuard.TObject( Type.Object( { x: Type.Number(), }, { // @ts-ignore $id: 1, }, ), ) Assert.equal(R, false) }) it('should not guard for TObject with invalid minProperties', () => { const R = TypeGuard.TObject( Type.Object( { x: Type.Number(), }, { // @ts-ignore minProperties: '1', }, ), ) Assert.equal(R, false) }) it('should not guard for TObject with invalid maxProperties', () => { const R = TypeGuard.TObject( Type.Object( { x: Type.Number(), }, { // @ts-ignore maxProperties: '1', }, ), ) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/promise.ts000066400000000000000000000021461431512220400211460ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TPromise', () => { it('should guard for TPromise', () => { const R = TypeGuard.TPromise(Type.Promise(Type.Number())) Assert.equal(R, true) }) it('should not guard for TPromise', () => { const R = TypeGuard.TPromise(null) Assert.equal(R, false) }) it('should not guard for TPromise with invalid $id', () => { // @ts-ignore const R = TypeGuard.TPromise(Type.Promise(Type.Number(), { $id: 1 })) Assert.equal(R, false) }) it('should guard for TPromise with nested TObject', () => { const R = TypeGuard.TPromise( Type.Promise( Type.Object({ x: Type.Number(), y: Type.Number(), }), ), ) Assert.equal(R, true) }) it('should not guard for TPromise with nested TObject', () => { const R = TypeGuard.TPromise( Type.Promise( Type.Object({ x: Type.Number(), y: {} as any, }), ), ) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/record.ts000066400000000000000000000026261431512220400207510ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TRecord', () => { it('should guard for TRecord', () => { const R = TypeGuard.TRecord(Type.Record(Type.String(), Type.Number())) Assert.equal(R, true) }) it('should guard for TRecord with TObject value', () => { const R = TypeGuard.TRecord( Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: Type.Number(), }), ), ) Assert.equal(R, true) }) it('should not guard for TRecord', () => { const R = TypeGuard.TRecord(null) Assert.equal(R, false) }) it('should not guard for TRecord with invalid $id', () => { // @ts-ignore const R = TypeGuard.TRecord(Type.Record(Type.String(), Type.Number(), { $id: 1 })) Assert.equal(R, false) }) it('should not guard for TRecord with TObject value with invalid Property', () => { const R = TypeGuard.TRecord( Type.Record( Type.String(), Type.Object({ x: Type.Number(), y: {} as any, }), ), ) Assert.equal(R, false) }) it('should not guard for TRecord with invalid literal key', () => { const K = Type.Union([Type.Literal('hello\nworld')]) const R = TypeGuard.TRecord(Type.Record(K, Type.Number())) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/ref.ts000066400000000000000000000012231431512220400202370ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TRef', () => { it('should guard for TRef', () => { const T = Type.Number({ $id: 'T' }) const R = TypeGuard.TRef(Type.Ref(T)) Assert.equal(R, true) }) it('should not guard for TRef', () => { const R = TypeGuard.TRef(null) Assert.equal(R, false) }) it('should not guard for TRef with invalid $ref', () => { const T = Type.Number({ $id: 'T' }) const S = Type.Ref(T) // @ts-ignore S.$ref = 1 const R = TypeGuard.TRef(S) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/self.ts000066400000000000000000000011761431512220400204230ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TSelf', () => { it('should guard for TSelf', () => { Type.Recursive((Node) => { const R = TypeGuard.TSelf(Node) Assert.equal(R, true) return Type.Object({ nodes: Type.Array(Node) }) }) }) it('should guard for TSelf with invalid $ref', () => { Type.Recursive((Node) => { // @ts-ignore Node.$ref = 1 const R = TypeGuard.TSelf(Node) Assert.equal(R, false) return Type.Object({ nodes: Type.Array(Node) }) }) }) }) typebox-0.24.44/test/runtime/guard/string.ts000066400000000000000000000021501431512220400207710ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TString', () => { it('should guard for TString', () => { const R = TypeGuard.TString(Type.String()) Assert.equal(R, true) }) it('should not guard for TString', () => { const R = TypeGuard.TString(null) Assert.equal(R, false) }) it('should not guard for TString with invalid $id', () => { // @ts-ignore const R = TypeGuard.TString(Type.String({ $id: 1 })) Assert.equal(R, false) }) it('should not guard for TString with invalid minLength', () => { // @ts-ignore const R = TypeGuard.TString(Type.String({ minLength: '1' })) Assert.equal(R, false) }) it('should not guard for TString with invalid maxLength', () => { // @ts-ignore const R = TypeGuard.TString(Type.String({ maxLength: '1' })) Assert.equal(R, false) }) it('should not guard for TString with invalid pattern', () => { // @ts-ignore const R = TypeGuard.TString(Type.String({ pattern: 1 })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/tuple.ts000066400000000000000000000014371431512220400206230ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TTuple', () => { it('should guard for TTuple', () => { const R = TypeGuard.TTuple(Type.Tuple([Type.Number(), Type.Number()])) Assert.equal(R, true) }) it('should not guard for TTuple', () => { const R = TypeGuard.TTuple(null) Assert.equal(R, false) }) it('should not guard for TTuple with invalid $id', () => { // @ts-ignore const R = TypeGuard.TTuple(Type.Tuple([Type.Number(), Type.Number()], { $id: 1 })) Assert.equal(R, false) }) it('should not guard for TTuple with invalid Items', () => { const R = TypeGuard.TTuple(Type.Tuple([Type.Number(), {} as any])) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/uint8array.ts000066400000000000000000000020021431512220400215650ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TUint8Array', () => { it('should guard for TUint8Array', () => { const R = TypeGuard.TUint8Array(Type.Uint8Array()) Assert.equal(R, true) }) it('should not guard for TUint8Array', () => { const R = TypeGuard.TUint8Array(null) Assert.equal(R, false) }) it('should not guard for TUint8Array with invalid $id', () => { // @ts-ignore const R = TypeGuard.TUint8Array(Type.Uint8Array({ $id: 1 })) Assert.equal(R, false) }) it('should not guard for TUint8Array with invalid minByteLength', () => { // @ts-ignore const R = TypeGuard.TUint8Array(Type.Uint8Array({ minByteLength: '1' })) Assert.equal(R, false) }) it('should not guard for TUint8Array with invalid maxByteLength', () => { // @ts-ignore const R = TypeGuard.TUint8Array(Type.Uint8Array({ maxByteLength: '1' })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/undefined.ts000066400000000000000000000011371431512220400214300ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TUndefined', () => { it('should guard for TUndefined', () => { const R = TypeGuard.TUndefined(Type.Undefined()) Assert.equal(R, true) }) it('should not guard for TUndefined', () => { const R = TypeGuard.TUndefined(null) Assert.equal(R, false) }) it('should not guard for TUndefined with invalid $id', () => { // @ts-ignore const R = TypeGuard.TUndefined(Type.Undefined({ $id: 1 })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/union.ts000066400000000000000000000026651431512220400206260ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TUnion', () => { it('should guard for TUnion', () => { const R = TypeGuard.TUnion( Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ]), ) Assert.equal(R, true) }) it('should not guard for TUnion', () => { const R = TypeGuard.TUnion(null) Assert.equal(R, false) }) it('should guard for TUnion with invalid $id', () => { const R = TypeGuard.TUnion( Type.Union( [ Type.Object({ x: Type.Number(), }), Type.Object({ y: Type.Number(), }), ], { // @ts-ignore $id: 1, }, ), ) Assert.equal(R, false) }) it('should not guard for TUnion with invalid variant', () => { const R = TypeGuard.TUnion( Type.Union([ Type.Object({ x: Type.Number(), }), {} as any, ]), ) Assert.equal(R, false) }) it('should not guard for TUnion with invalid object variant', () => { const R = TypeGuard.TUnion( Type.Union([ Type.Object({ x: Type.Number(), }), Type.Object({ y: {} as any, }), ]), ) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/unknown.ts000066400000000000000000000011151431512220400211620ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TUnknown', () => { it('should guard for TUnknown', () => { const R = TypeGuard.TUnknown(Type.Unknown()) Assert.equal(R, true) }) it('should not guard for TUnknown', () => { const R = TypeGuard.TUnknown(null) Assert.equal(R, false) }) it('should not guard for TUnknown with invalid $id', () => { // @ts-ignore const R = TypeGuard.TUnknown(Type.Unknown({ $id: 1 })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/guard/void.ts000066400000000000000000000010621431512220400204250ustar00rootroot00000000000000import { TypeGuard } from '@sinclair/typebox/guard' import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' describe('type/guard/TVoid', () => { it('should guard for TVoid', () => { const R = TypeGuard.TVoid(Type.Void()) Assert.equal(R, true) }) it('should not guard for TVoid', () => { const R = TypeGuard.TVoid(null) Assert.equal(R, false) }) it('should not guard for TVoid with invalid $id', () => { // @ts-ignore const R = TypeGuard.TVoid(Type.Void({ $id: 1 })) Assert.equal(R, false) }) }) typebox-0.24.44/test/runtime/index.ts000066400000000000000000000002251431512220400174710ustar00rootroot00000000000000import './compiler/index' import './conditional/index' import './format/index' import './guard/index' import './schema/index' import './value/index' typebox-0.24.44/test/runtime/schema/000077500000000000000000000000001431512220400172535ustar00rootroot00000000000000typebox-0.24.44/test/runtime/schema/any.ts000066400000000000000000000013311431512220400204100ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/schema/array.ts000066400000000000000000000056371431512220400207540ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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 intersection types when passing additionalProperties false', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.String() }) const C = Type.Intersect([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]) }) it('Should validate array with uniqueItems when items are references', () => { const T = Type.Array(Type.Object({ x: Type.Number(), y: Type.Number() }), { uniqueItems: true }) ok(T, [ { x: 0, y: 1 }, { x: 1, y: 0 }, ]) // references distinct }) it('Should not validate array with non uniqueItems', () => { const T = Type.Array(Type.Number(), { uniqueItems: true }) fail(T, [0, 0]) }) }) typebox-0.24.44/test/runtime/schema/boolean.ts000066400000000000000000000014741431512220400212500ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/schema/enum.ts000066400000000000000000000022321431512220400205660ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/schema/index.ts000066400000000000000000000010211431512220400207240ustar00rootroot00000000000000import './any' import './array' import './boolean' import './enum' import './intersect' import './keyof' import './literal' import './modifier' import './never' 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 './regex' import './required' import './string' import './tuple' import './union' import './unknown' import './unsafe' import './void' typebox-0.24.44/test/runtime/schema/intersect.ts000066400000000000000000000060211431512220400216220ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Assert } from '../assert' import { ok, fail } from './validate' describe('type/schema/Intersect', () => { it('Should intersect two objects', () => { const A = Type.Object({ a: Type.String() }) const B = Type.Object({ b: Type.Number() }) const T = Type.Intersect([A, B], { additionalProperties: false }) ok(T, { a: 'hello', b: 42 }) }) it('Should intersect with partial', () => { const A = Type.Partial(Type.Object({ a: Type.Number() })) const B = Type.Partial(Type.Object({ b: Type.Number() })) const P = Type.Intersect([A, B], { additionalProperties: false }) ok(P, { a: 1, b: 2 }) ok(P, { a: 1 }) ok(P, { b: 1 }) ok(P, {}) fail(P, { c: 1 }) }) it('Should intersect with overlapping same type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.Number() }) const P = Type.Intersect([A, B]) ok(P, { a: 1 }) fail(P, { a: 'hello' }) fail(P, {}) }) it('Should intersect with overlapping varying type', () => { const A = Type.Object({ a: Type.Number() }) const B = Type.Object({ a: Type.String() }) const T = Type.Intersect([A, B]) ok(T, { a: 1 }) ok(T, { a: 'hello' }) fail(T, {}) }) it('Should intersect 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.Intersect([A, B, C, D]) ok(T, { a: 1 }) ok(T, { a: 'hello' }) ok(T, { a: false }) ok(T, { a: null }) fail(T, { a: [] }) fail(T, {}) }) it('Should pick from intersected 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.Intersect([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 intersected 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.Intersect([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 intersect nested object properties', () => { const A = Type.Object({ x: Type.Object({ x: Type.Number() }) }) const B = Type.Object({ x: Type.Object({ x: Type.String() }) }) const T = Type.Intersect([A, B]) ok(T, { x: { x: 1 } }) ok(T, { x: { x: 'hello' } }) fail(T, { x: { x: false } }) }) // todo: move to composition / type guard spec it('Should intersect and produce the same schema', () => { const T = Type.Object({ field: Type.Optional(Type.String()), }) const A = Type.Intersect([T]) const B = Type.Intersect([T]) Assert.deepEqual(A, B) }) }) typebox-0.24.44/test/runtime/schema/keyof.ts000066400000000000000000000020121431512220400207330ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/schema/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') }) }) typebox-0.24.44/test/runtime/schema/literal.ts000066400000000000000000000021161431512220400212570ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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') }) }) typebox-0.24.44/test/runtime/schema/modifier.ts000066400000000000000000000001251431512220400214170ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' describe('type/schema/Modifier', () => {}) typebox-0.24.44/test/runtime/schema/never.ts000066400000000000000000000014211431512220400207400ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { fail } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/schema/null.ts000066400000000000000000000014251431512220400205770ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/schema/number.ts000066400000000000000000000014331431512220400211140ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/Number', () => { it('Should validate number', () => { 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) }) }) typebox-0.24.44/test/runtime/schema/object.ts000066400000000000000000000062731431512220400211010ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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, }) }) }) typebox-0.24.44/test/runtime/schema/omit.ts000066400000000000000000000035301431512220400205740ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/schema/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.ReadonlyOptional(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 }) }) }) typebox-0.24.44/test/runtime/schema/optional.ts000066400000000000000000000012751431512220400214550ustar00rootroot00000000000000import { strictEqual } from 'assert' import { Type } from '@sinclair/typebox' import { ok } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/schema/partial.ts000066400000000000000000000027141431512220400212630ustar00rootroot00000000000000import { Type, Modifier } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/schema/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.ReadonlyOptional(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[Modifier], 'ReadonlyOptional') strictEqual(T.properties.y[Modifier], 'ReadonlyOptional') strictEqual(T.properties.z[Modifier], 'Optional') strictEqual(T.properties.w[Modifier], '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) }) }) typebox-0.24.44/test/runtime/schema/pick.ts000066400000000000000000000036001431512220400205500ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/schema/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 delete the required property if no required properties remain', () => { const A = Type.Object( { x: Type.Optional(Type.Number()), y: Type.ReadonlyOptional(Type.Number()), z: Type.Number(), }, { additionalProperties: false }, ) const T = Type.Pick(A, ['x', 'y']) 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.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 }) }) }) typebox-0.24.44/test/runtime/schema/readonly-optional.ts000066400000000000000000000013331431512220400232630ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/schema/ReadonlyOptional', () => { it('Should validate object with optional', () => { const T = Type.Object( { a: Type.ReadonlyOptional(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.ReadonlyOptional(Type.String()), b: Type.String(), }, { additionalProperties: false }, ) strictEqual(T.required!.includes('a'), false) }) }) typebox-0.24.44/test/runtime/schema/readonly.ts000066400000000000000000000014071431512220400214420ustar00rootroot00000000000000import { deepStrictEqual, strictEqual } from 'assert' import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/schema/record.ts000066400000000000000000000061621431512220400211060ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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 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()) 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()) 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()) 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()) fail(T, { '0': 1, '1': 2, '2': 3, '3': 4, a: 'hello' }) }) 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 should validate when specifying regular expressions', () => { const K = Type.RegEx(/^op_.*$/) const T = Type.Record(K, Type.Number()) ok(T, { op_a: 1, op_b: 2, op_c: 3, }) }) it('Should should not validate when specifying regular expressions and passing invalid property', () => { const K = Type.RegEx(/^op_.*$/) const T = Type.Record(K, Type.Number()) fail(T, { op_a: 1, op_b: 2, aop_c: 3, }) }) }) typebox-0.24.44/test/runtime/schema/recursive.ts000066400000000000000000000034641431512220400216410ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { Assert } from '../assert/index' import { ok, fail } from './validate' describe('type/schema/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.equal(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.equal(Node.$id === 'Node', true) }) it('Should validate recursive node type', () => { const Node = Type.Recursive((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ) ok(Node, { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, ], }) }) it('Should validate wrapped recursive node type', () => { const Node = Type.Tuple([ Type.Recursive((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ), ]) 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((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ), ]) fail(Node, [ { id: 'A', nodes: [ { id: 1, nodes: [] }, { id: 'C', nodes: [] }, ], }, ]) }) }) typebox-0.24.44/test/runtime/schema/ref.ts000066400000000000000000000025271431512220400204050ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { Assert } from '../assert/index' describe('type/schema/Ref', () => { 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) 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) 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: '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]) }) }) typebox-0.24.44/test/runtime/schema/regex.ts000066400000000000000000000013731431512220400207410ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/RegEx', () => { it('Should validate numeric value', () => { const T = Type.RegEx(/[012345]/) ok(T, '0') ok(T, '1') ok(T, '2') ok(T, '3') ok(T, '4') ok(T, '5') }) it('Should validate true or false string value', () => { const T = Type.RegEx(/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 not validate failed regex test', () => { const T = Type.RegEx(/true|false/) fail(T, 'unknown') }) it('Should pass numeric 5 digit test', () => { const T = Type.RegEx(/[\d]{5}/) ok(T, '12345') }) }) typebox-0.24.44/test/runtime/schema/required.ts000066400000000000000000000034541431512220400214510ustar00rootroot00000000000000import { Type, Modifier } from '@sinclair/typebox' import { ok, fail } from './validate' import { strictEqual } from 'assert' describe('type/schema/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.ReadonlyOptional(Type.Number()), y: Type.Readonly(Type.Number()), z: Type.Optional(Type.Number()), w: Type.Number(), }) const T = Type.Required(A) strictEqual(T.properties.x[Modifier], 'Readonly') strictEqual(T.properties.y[Modifier], 'Readonly') strictEqual(T.properties.z[Modifier], undefined) strictEqual(T.properties.w[Modifier], 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') // }) }) typebox-0.24.44/test/runtime/schema/string.ts000066400000000000000000000031371431512220400211350ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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') }) }) typebox-0.24.44/test/runtime/schema/tuple.ts000066400000000000000000000035261431512220400207620ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' import { Assert } from '../assert' describe('type/schema/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 }]) }) }) typebox-0.24.44/test/runtime/schema/union.ts000066400000000000000000000044021431512220400207530ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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 }) }) typebox-0.24.44/test/runtime/schema/unknown.ts000066400000000000000000000013431431512220400213230ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/schema/unsafe.ts000066400000000000000000000007141431512220400211060ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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 }) }) }) typebox-0.24.44/test/runtime/schema/validate.ts000066400000000000000000000042671431512220400214250ustar00rootroot00000000000000import { TSchema } from '@sinclair/typebox' import addFormats from 'ajv-formats' import Ajv, { AnySchema } from 'ajv/dist/2019' export function validator(additional: 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('kind') .addKeyword('modifier') .addSchema(additional) } export function ok(type: T, data: unknown, additional: AnySchema[] = []) { const ajv = validator(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 = validator(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') } } typebox-0.24.44/test/runtime/schema/void.ts000066400000000000000000000014211431512220400205620ustar00rootroot00000000000000import { Type } from '@sinclair/typebox' import { ok, fail } from './validate' describe('type/schema/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) }) }) typebox-0.24.44/test/runtime/value/000077500000000000000000000000001431512220400171275ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/cast/000077500000000000000000000000001431512220400200615ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/cast/any.ts000066400000000000000000000025401431512220400212210ustar00rootroot00000000000000import { 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.deepEqual(result, value) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from boolean', () => { const value = false const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should preserve', () => { const value = { a: 1, b: 2 } const result = Value.Cast(T, value) Assert.deepEqual(result, { a: 1, b: 2 }) }) }) typebox-0.24.44/test/runtime/value/cast/array.ts000066400000000000000000000113651431512220400215550ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, [1]) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve', () => { const value = [6, 7, 8] const result = Value.Cast(T, value) Assert.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(result, [1, 2, 3]) }) }) typebox-0.24.44/test/runtime/value/cast/boolean.ts000066400000000000000000000025211431512220400220500ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 0 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, true) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, true) }) }) typebox-0.24.44/test/runtime/value/cast/convert.ts000066400000000000000000000164021431512220400221140ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/convert/String', () => { it('Should convert string', () => { const value = 'hello' const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, 'hello') }) it('Should convert number #1', () => { const value = 42 const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, '42') }) it('Should convert number #2', () => { const value = 42n const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, '42') }) it('Should convert true', () => { const value = true const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, 'true') }) it('Should convert false', () => { const value = false const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, 'false') }) it('Should convert object', () => { const value = {} const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, '') }) it('Should convert array', () => { const value = [] as any[] const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, '') }) }) describe('value/convert/Number', () => { it('Should convert string #1', () => { const value = 'hello' const result = Value.Cast(Type.Number(), value) Assert.deepEqual(result, 0) }) it('Should convert string #2', () => { const value = '3.14' const result = Value.Cast(Type.Number(), value) Assert.deepEqual(result, 3.14) }) it('Should convert string #3', () => { const value = '-0' const result = Value.Cast(Type.Number(), value) Assert.deepEqual(result, 0) }) it('Should convert string #4', () => { const value = '-100' const result = Value.Cast(Type.Number(), value) Assert.deepEqual(result, -100) }) it('Should convert number', () => { const value = 42 const result = Value.Cast(Type.Number(), value) Assert.deepEqual(result, 42) }) it('Should convert true', () => { const value = true const result = Value.Cast(Type.Number(), value) Assert.deepEqual(result, 1) }) it('Should convert false', () => { const value = false const result = Value.Cast(Type.Number(), value) Assert.deepEqual(result, 0) }) it('Should convert object', () => { const value = {} const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, 0) }) it('Should convert array', () => { const value = [] as any[] const result = Value.Cast(Type.String(), value) Assert.deepEqual(result, 0) }) }) describe('value/convert/Integer', () => { it('Should convert string #1', () => { const value = 'hello' const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, 0) }) it('Should convert string #2', () => { const value = '3.14' const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, 3) }) it('Should convert string #3', () => { const value = '-0' const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, 0) }) it('Should convert string #4', () => { const value = '-100' const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, -100) }) it('Should convert number', () => { const value = 42 const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, 42) }) it('Should convert true', () => { const value = true const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, 1) }) it('Should convert false', () => { const value = false const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, 0) }) it('Should convert object', () => { const value = {} const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, 0) }) it('Should convert array', () => { const value = [] as any[] const result = Value.Cast(Type.Integer(), value) Assert.deepEqual(result, 0) }) }) describe('value/convert/Boolean', () => { it('Should convert string #1', () => { const value = 'hello' const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, false) }) it('Should convert string #2', () => { const value = 'true' const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, true) }) it('Should convert string #3', () => { const value = 'TRUE' const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, true) }) it('Should convert string #4', () => { const value = 'false' const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, false) }) it('Should convert string #5', () => { const value = '0' const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, false) }) it('Should convert string #6', () => { const value = '1' const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, true) }) it('Should convert string #7', () => { const value = '0' const result = Value.Cast(Type.Boolean({ default: true }), value) Assert.deepEqual(result, false) }) it('Should convert string #8', () => { const value = '1' const result = Value.Cast(Type.Boolean({ default: false }), value) Assert.deepEqual(result, true) }) it('Should convert string #8', () => { const value = '2' const result = Value.Cast(Type.Boolean({ default: true }), value) Assert.deepEqual(result, true) }) it('Should convert number #1', () => { const value = 0 const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, false) }) it('Should convert number #2', () => { const value = 1n const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, true) }) it('Should convert number #3', () => { const value = 1 const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, true) }) it('Should convert number #4', () => { const value = 2 const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, false) }) it('Should convert number #5', () => { const value = 0 const result = Value.Cast(Type.Boolean({ default: true }), value) Assert.deepEqual(result, false) }) it('Should convert number #6', () => { const value = 1 const result = Value.Cast(Type.Boolean({ default: false }), value) Assert.deepEqual(result, true) }) it('Should convert number #7', () => { const value = 2 const result = Value.Cast(Type.Boolean({ default: true }), value) Assert.deepEqual(result, true) }) it('Should convert true', () => { const value = true const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, true) }) it('Should convert false', () => { const value = false const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, false) }) it('Should convert object', () => { const value = {} const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, false) }) it('Should convert array', () => { const value = [] as any[] const result = Value.Cast(Type.Boolean(), value) Assert.deepEqual(result, false) }) }) typebox-0.24.44/test/runtime/value/cast/enum.ts000066400000000000000000000030161431512220400213750ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 123 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from enum A', () => { const value = Foo.A const result = Value.Cast(T, value) Assert.deepEqual(result, Foo.A) }) it('Should upcast from enum B', () => { const value = Foo.B const result = Value.Cast(T, value) Assert.deepEqual(result, Foo.B) }) }) typebox-0.24.44/test/runtime/value/cast/index.ts000066400000000000000000000006601431512220400215420ustar00rootroot00000000000000import './any' import './array' import './boolean' import './convert' import './enum' import './integer' import './intersect' import './keyof' import './literal' import './namespace' import './never' import './null' import './number' import './object' import './rec' import './record' import './regex' import './string' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' typebox-0.24.44/test/runtime/value/cast/integer.ts000066400000000000000000000023201431512220400220630ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, 1) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, 1) // conversion }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) }) typebox-0.24.44/test/runtime/value/cast/intersect.ts000066400000000000000000000040701431512220400224320ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Intersect', () => { 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.Intersect([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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = E const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast and preserve object', () => { const value = { x: 7, y: 8, z: 9 } const result = Value.Cast(T, value) Assert.deepEqual(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.deepEqual(result, { x: 0, y: 8, z: 9, a: 'a', b: 'b', c: 'c', }) }) }) typebox-0.24.44/test/runtime/value/cast/keyof.ts000066400000000000000000000026561431512220400215570ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve', () => { const value = 'y' const result = Value.Cast(T, value) Assert.deepEqual(result, 'y') }) }) typebox-0.24.44/test/runtime/value/cast/literal.ts000066400000000000000000000025341431512220400220710ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preseve', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.deepEqual(result, 'hello') }) }) typebox-0.24.44/test/runtime/value/cast/namespace.ts000066400000000000000000000000001431512220400223530ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/cast/never.ts000066400000000000000000000017601431512220400215540ustar00rootroot00000000000000import { 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)) }) }) typebox-0.24.44/test/runtime/value/cast/null.ts000066400000000000000000000025061431512220400214060ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preseve', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, null) }) }) typebox-0.24.44/test/runtime/value/cast/number.ts000066400000000000000000000025201431512220400217200ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, 1) }) it('Should upcast from boolean', () => { const value = true // convert const result = Value.Cast(T, value) Assert.deepEqual(result, 1) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preseve', () => { const value = 123 const result = Value.Cast(T, value) Assert.deepEqual(result, 123) }) }) typebox-0.24.44/test/runtime/value/cast/object.ts000066400000000000000000000050631431512220400217030ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = E const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(result, { x: 7, y: 8, z: 9, a: 'a', b: 'b', c: 'c', }) }) }) typebox-0.24.44/test/runtime/value/cast/rec.ts000066400000000000000000000046071431512220400212110ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/Recursive', () => { const T = Type.Recursive((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ) const E = { id: '', nodes: [] } it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from number', () => { const value = E const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(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.deepEqual(result, value) }) it('Should upcast from varying types', () => { const TypeA = Type.Recursive((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ) const TypeB = Type.Recursive((Self) => Type.Object({ id: Type.String(), name: Type.String({ default: 'test' }), nodes: Type.Array(Self), }), ) const ValueA = { id: 'A', nodes: [ { id: 'B', nodes: [] }, { id: 'C', nodes: [] }, { id: 'D', nodes: [] }, ], } const ValueB = Value.Cast(TypeB, ValueA) Assert.deepEqual(ValueB, { id: 'A', name: 'test', nodes: [ { id: 'B', name: 'test', nodes: [] }, { id: 'C', name: 'test', nodes: [] }, { id: 'D', name: 'test', nodes: [] }, ], }) }) }) typebox-0.24.44/test/runtime/value/cast/record.ts000066400000000000000000000037071431512220400217160ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = E const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(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.deepEqual(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.deepEqual(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 }, }) }) }) typebox-0.24.44/test/runtime/value/cast/regex.ts000066400000000000000000000025511431512220400215460ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/cast/RegEx', () => { const T = Type.RegEx(/foo/, { default: 'foo' }) const E = 'foo' it('Should upcast from string', () => { const value = 'hello' const result = Value.Cast(T, value) Assert.deepEqual(result, 'foo') }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve', () => { const value = 'foo' const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) }) typebox-0.24.44/test/runtime/value/cast/string.ts000066400000000000000000000025661431512220400217500ustar00rootroot00000000000000import { 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.deepEqual(result, 'hello') }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, '1') // conversion }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, 'true') // conversion }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve', () => { const value = 'foo' const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) }) typebox-0.24.44/test/runtime/value/cast/tuple.ts000066400000000000000000000040401431512220400215600ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, [1, '']) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve', () => { const value = [42, 'world'] const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast with empty', () => { const value = [] as any[] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should append with less than tuple length', () => { const value = [42] const result = Value.Cast(T, value) Assert.deepEqual(result, [42, '']) }) it('Should truncate with greater than tuple length', () => { const value = [42, '', true] const result = Value.Cast(T, value) Assert.deepEqual(result, [42, '']) }) it('Should preserve and patch invalid element', () => { const value = [{}, 'hello'] const result = Value.Cast(T, value) Assert.deepEqual(result, [0, 'hello']) }) }) typebox-0.24.44/test/runtime/value/cast/uint8array.ts000066400000000000000000000026611431512220400225440ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve', () => { const value = new Uint8Array([6, 7, 8, 9, 10]) const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) }) typebox-0.24.44/test/runtime/value/cast/undefined.ts000066400000000000000000000025371431512220400224010ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preseve', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, undefined) }) }) typebox-0.24.44/test/runtime/value/cast/union.ts000066400000000000000000000066041431512220400215670ustar00rootroot00000000000000import { 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.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve A', () => { const value = { type: 'A', x: 1, y: 2, z: 3 } const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should preserve B', () => { const value = { type: 'B', a: 'a', b: 'b', c: 'c' } const result = Value.Cast(T, value) Assert.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(result, { type: 'B', a: '', b: '', c: '' }) }) it('Should infer through heuristics #6', () => { const value = { x: 1 } const result = Value.Cast(T, value) Assert.deepEqual(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.deepEqual(result, { type: 'B', a: '', b: '', c: '' }) }) }) typebox-0.24.44/test/runtime/value/cast/unknown.ts000066400000000000000000000025531431512220400221350ustar00rootroot00000000000000import { 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.deepEqual(result, value) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from boolean', () => { const value = false const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, value) }) it('Should preserve', () => { const value = { a: 1, b: 2 } const result = Value.Cast(T, value) Assert.deepEqual(result, { a: 1, b: 2 }) }) }) typebox-0.24.44/test/runtime/value/cast/void.ts000066400000000000000000000025071431512220400213760ustar00rootroot00000000000000import { 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 = null it('Should upcast from string', () => { const value = 'world' const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from number', () => { const value = 1 const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from boolean', () => { const value = true const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from object', () => { const value = {} const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from array', () => { const value = [1] const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from undefined', () => { const value = undefined const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should upcast from null', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, E) }) it('Should preserve', () => { const value = null const result = Value.Cast(T, value) Assert.deepEqual(result, null) }) }) typebox-0.24.44/test/runtime/value/check/000077500000000000000000000000001431512220400202045ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/check/any.ts000066400000000000000000000022011431512220400213360ustar00rootroot00000000000000import { 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.equal(result, true) }) it('Should pass number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, true) }) }) typebox-0.24.44/test/runtime/value/check/array.ts000066400000000000000000000017551431512220400217020ustar00rootroot00000000000000import { 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.equal(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.equal(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.equal(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.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/boolean.ts000066400000000000000000000022171431512220400221750ustar00rootroot00000000000000import { 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.equal(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should pass boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/enum.ts000066400000000000000000000012451431512220400215220ustar00rootroot00000000000000import { 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.equal(result, true) }) it('Should pass enum option B', () => { const value = Foo.A const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail unknown value', () => { const value = 'unknown' const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/index.ts000066400000000000000000000006101431512220400216600ustar00rootroot00000000000000import './any' import './array' import './boolean' import './enum' import './integer' import './intersect' import './keyof' import './literal' import './never' import './null' import './number' import './object' import './rec' import './record' import './regex' import './string' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' typebox-0.24.44/test/runtime/value/check/integer.ts000066400000000000000000000007341431512220400222150ustar00rootroot00000000000000import { 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 pass integer', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail integer', () => { const value = 3.14 const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/intersect.ts000066400000000000000000000033501431512220400225550ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Intersect', () => { 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.Intersect([A, B]) it('Should pass intersect', () => { const value = { x: 1, y: 1, z: 1, a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.equal(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.equal(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.equal(result, false) }) it('Should fail intersect with primitive value', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(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.Intersect([A, B]) const value = { a: '1', b: '1', c: '1', } const result = Value.Check(T, value) Assert.equal(result, true) }) }) typebox-0.24.44/test/runtime/value/check/keyof.ts000066400000000000000000000015501431512220400216720ustar00rootroot00000000000000import { 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.equal(result, true) }) it('Should fail keyof', () => { const value = 'w' const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail keyof with undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail keyof with null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/literal.ts000066400000000000000000000014241431512220400222110ustar00rootroot00000000000000import { 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.equal(result, true) }) it('Should fail literal', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail literal with undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail literal with null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/never.ts000066400000000000000000000022141431512220400216720ustar00rootroot00000000000000import { 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.equal(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/null.ts000066400000000000000000000022111431512220400215220ustar00rootroot00000000000000import { 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.equal(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/number.ts000066400000000000000000000022151431512220400220440ustar00rootroot00000000000000import { 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 fail string', () => { const value = 'hello' const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should pass number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/object.ts000066400000000000000000000041371431512220400220270ustar00rootroot00000000000000import { 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.equal(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.equal(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.equal(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.equal(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.equal(result, true) }) it('Should fail object with null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail object with undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/rec.ts000066400000000000000000000031741431512220400213320ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/Recursive', () => { const T = Type.Recursive((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ) 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.equal(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.equal(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.equal(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.equal(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.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/record.ts000066400000000000000000000032611431512220400220340ustar00rootroot00000000000000import { 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.equal(result, true) }) 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.equal(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.equal(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.equal(result, true) }) }) typebox-0.24.44/test/runtime/value/check/regex.ts000066400000000000000000000007771431512220400217010ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/check/RegEx', () => { it('Should pass regex', () => { const T = Type.RegEx(/foo/) const value = 'foo' const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail regex', () => { const T = Type.RegEx(/foo/) const value = 'bar' const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/string.ts000066400000000000000000000022151431512220400220620ustar00rootroot00000000000000import { 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.equal(result, true) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/tuple.ts000066400000000000000000000022061431512220400217050ustar00rootroot00000000000000import { 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.equal(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.equal(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.equal(result, false) }) it('Should pass empty tuple', () => { const T = Type.Tuple([]) const value = [] as any[] const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail empty tuple', () => { const T = Type.Tuple([]) const value = [1] const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/uint8array.ts000066400000000000000000000016311431512220400226630ustar00rootroot00000000000000import { 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.equal(result, true) }) it('Should fail uint8array', () => { const T = Type.Uint8Array() const value = [0, 1, 2, 3] const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail uint8array with undefined', () => { const T = Type.Uint8Array() const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail uint8array with null', () => { const T = Type.Uint8Array() const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/undefined.ts000066400000000000000000000022231431512220400225140ustar00rootroot00000000000000import { 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.equal(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should pass undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/union.ts000066400000000000000000000037461431512220400217160ustar00rootroot00000000000000import { 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.equal(result, true) }) it('Should pass union B', () => { const value = { type: 'B', x: true, y: false } const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail union A', () => { const value = { type: 'A', x: true, y: false } const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail union B', () => { const value = { type: 'B', x: 1, y: 1 } const result = Value.Check(T, value) Assert.equal(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.equal(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.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/check/unknown.ts000066400000000000000000000022051431512220400222520ustar00rootroot00000000000000import { 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.equal(result, true) }) it('Should pass number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should pass array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, true) }) }) typebox-0.24.44/test/runtime/value/check/void.ts000066400000000000000000000022111431512220400215110ustar00rootroot00000000000000import { 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.equal(result, false) }) it('Should fail number', () => { const value = 1 const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail boolean', () => { const value = true const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should pass null', () => { const value = null const result = Value.Check(T, value) Assert.equal(result, true) }) it('Should fail undefined', () => { const value = undefined const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail object', () => { const value = { a: 1 } const result = Value.Check(T, value) Assert.equal(result, false) }) it('Should fail array', () => { const value = [1, 2] const result = Value.Check(T, value) Assert.equal(result, false) }) }) typebox-0.24.44/test/runtime/value/clone/000077500000000000000000000000001431512220400202275ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/clone/clone.ts000066400000000000000000000076311431512220400217060ustar00rootroot00000000000000import { 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.deepEqual(R, null) }) it('Should clone undefined', () => { const R = Value.Clone(undefined) Assert.deepEqual(R, undefined) }) it('Should clone number', () => { const R = Value.Clone(1) Assert.deepEqual(R, 1) }) it('Should clone bigint', () => { const R = Value.Clone(1n) Assert.deepEqual(R, 1n) }) it('Should clone boolean', () => { const R = Value.Clone(true) Assert.deepEqual(R, true) }) it('Should clone string', () => { const R = Value.Clone('hello') Assert.deepEqual(R, 'hello') }) it('Should clone symbol', () => { const S = Symbol('hello') const R = Value.Clone(S) Assert.deepEqual(R, S) }) // -------------------------------------------- // ObjectType // -------------------------------------------- it('Should clone object #1', () => { const V = { x: 1, y: 2, z: 3, } const R = Value.Clone(V) Assert.deepEqual(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.deepEqual(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.deepEqual(R, V) }) // -------------------------------------------- // ArrayType // -------------------------------------------- it('Should clone array #1', () => { const V = [1, 2, 3, 4] const R = Value.Clone(V) Assert.deepEqual(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.deepEqual(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.deepEqual(R, V) }) it('Should clone Int8Array', () => { const V = new Int8Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone Uint8Array', () => { const V = new Uint8Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone Uint8ClampedArray', () => { const V = new Uint8ClampedArray([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone Int16Array', () => { const V = new Int16Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone Uint16Array', () => { const V = new Uint16Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone Int32Array', () => { const V = new Int32Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone Uint32Array', () => { const V = new Int32Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone Float32Array', () => { const V = new Float32Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone Float64Array', () => { const V = new Float64Array([1, 2, 3, 4]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone BigInt64Array', () => { const V = new BigInt64Array([1n, 2n, 3n, 4n]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) it('Should clone BigUint64Array', () => { const V = new BigUint64Array([1n, 2n, 3n, 4n]) const R = Value.Clone(V) Assert.deepEqual(R, V) }) }) typebox-0.24.44/test/runtime/value/clone/index.ts000066400000000000000000000000211431512220400216770ustar00rootroot00000000000000import './clone' typebox-0.24.44/test/runtime/value/create/000077500000000000000000000000001431512220400203725ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/create/any.ts000066400000000000000000000006251431512220400215340ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), {}) }) it('Should create default', () => { const T = Type.Any({ default: 1 }) Assert.deepEqual(Value.Create(T), 1) }) }) typebox-0.24.44/test/runtime/value/create/array.ts000066400000000000000000000011371431512220400220620ustar00rootroot00000000000000import { 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.Array(Type.String()) Assert.deepEqual(Value.Create(T), []) }) it('Should create default', () => { const T = Type.Array(Type.String(), { default: ['1'] }) Assert.deepEqual(Value.Create(T), ['1']) }) it('Should create with minItems', () => { const T = Type.Array(Type.String(), { minItems: 4 }) Assert.deepEqual(Value.Create(T), ['', '', '', '']) }) }) typebox-0.24.44/test/runtime/value/create/boolean.ts000066400000000000000000000006461431512220400223670ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), false) }) it('Should create default', () => { const T = Type.Any({ default: true }) Assert.deepEqual(Value.Create(T), true) }) }) typebox-0.24.44/test/runtime/value/create/constructor.ts000066400000000000000000000015421431512220400233310ustar00rootroot00000000000000import { 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.deepEqual(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.deepEqual(R, 321) }) }) typebox-0.24.44/test/runtime/value/create/enum.ts000066400000000000000000000007741431512220400217160ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), Foo.A) }) it('Should create default', () => { enum Foo { A, B, } const T = Type.Enum(Foo, { default: Foo.B }) Assert.deepEqual(Value.Create(T), Foo.B) }) }) typebox-0.24.44/test/runtime/value/create/function.ts000066400000000000000000000010701431512220400225650ustar00rootroot00000000000000import { 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.deepEqual(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.deepEqual(R, 321) }) }) typebox-0.24.44/test/runtime/value/create/index.ts000066400000000000000000000006631431512220400220560ustar00rootroot00000000000000import './any' import './array' import './boolean' import './constructor' import './enum' import './function' import './integer' import './intersect' import './keyof' import './literal' import './never' import './null' import './number' import './object' import './rec' import './record' import './regex' import './string' import './tuple' import './uint8array' import './undefined' import './union' import './unknown' import './void' typebox-0.24.44/test/runtime/value/create/integer.ts000066400000000000000000000006401431512220400223770ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), 0) }) it('Should create default', () => { const T = Type.Integer({ default: 7 }) Assert.deepEqual(Value.Create(T), 7) }) }) typebox-0.24.44/test/runtime/value/create/intersect.ts000066400000000000000000000027711431512220400227510ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/Intersect', () => { 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.Intersect([A, B]) Assert.deepEqual(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.Intersect([A, B]) Assert.deepEqual(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.Intersect([A, B]) Assert.deepEqual(Value.Create(T), { x: 0, y: 0, z: 0, }) }) }) typebox-0.24.44/test/runtime/value/create/keyof.ts000066400000000000000000000011261431512220400220570ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), 'x') }) it('Should create default', () => { const T = Type.KeyOf( Type.Object({ x: Type.Number(), y: Type.Number(), }), { default: 'y' }, ) Assert.deepEqual(Value.Create(T), 'y') }) }) typebox-0.24.44/test/runtime/value/create/literal.ts000066400000000000000000000010561431512220400224000ustar00rootroot00000000000000import { Value } from '@sinclair/typebox/value' import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('value/create/KeyOf', () => { it('Should create literal string', () => { const T = Type.Literal('hello') Assert.deepEqual(Value.Create(T), 'hello') }) it('Should create literal number', () => { const T = Type.Literal(1) Assert.deepEqual(Value.Create(T), 1) }) it('Should create literal boolean', () => { const T = Type.Literal(true) Assert.deepEqual(Value.Create(T), true) }) }) typebox-0.24.44/test/runtime/value/create/never.ts000066400000000000000000000004351431512220400220630ustar00rootroot00000000000000import { 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)) }) }) typebox-0.24.44/test/runtime/value/create/null.ts000066400000000000000000000004361431512220400217170ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), null) }) }) typebox-0.24.44/test/runtime/value/create/number.ts000066400000000000000000000006351431512220400222360ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), 0) }) it('Should create default', () => { const T = Type.Number({ default: 7 }) Assert.deepEqual(Value.Create(T), 7) }) }) typebox-0.24.44/test/runtime/value/create/object.ts000066400000000000000000000032021431512220400222050ustar00rootroot00000000000000import { 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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(Value.Create(T), { x: 1, y: 2, z: 3, }) }) }) typebox-0.24.44/test/runtime/value/create/rec.ts000066400000000000000000000012631431512220400215150ustar00rootroot00000000000000import { 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((Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), ) Assert.deepEqual(Value.Create(T), { id: '', nodes: [], }) }) it('Should create default', () => { const T = Type.Recursive( (Self) => Type.Object({ id: Type.String(), nodes: Type.Array(Self), }), { default: 7 }, ) Assert.deepEqual(Value.Create(T), 7) }) }) typebox-0.24.44/test/runtime/value/create/record.ts000066400000000000000000000010061431512220400222150ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), {}) }) it('Should create default', () => { const T = Type.Record(Type.String(), Type.Object({}), { default: { x: {}, }, }) Assert.deepEqual(Value.Create(T), { x: {} }) }) }) typebox-0.24.44/test/runtime/value/create/regex.ts000066400000000000000000000007171431512220400220610ustar00rootroot00000000000000import { 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.RegEx(/foo/) Value.Create(T) }) }) it('Should create default', () => { const T = Type.RegEx(/foo/, { default: 'foo' }) Assert.deepEqual(Value.Create(T), 'foo') }) }) typebox-0.24.44/test/runtime/value/create/string.ts000066400000000000000000000006511431512220400222520ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), 0) }) it('Should create default', () => { const T = Type.String({ default: 'hello' }) Assert.deepEqual(Value.Create(T), 'hello') }) }) typebox-0.24.44/test/runtime/value/create/tuple.ts000066400000000000000000000016451431512220400221010ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), [0, '']) }) it('Should create default', () => { const T = Type.Tuple([Type.Number(), Type.String()], { default: [7, 'hello'] }) Assert.deepEqual(Value.Create(T), [7, 'hello']) }) it('Should create default elements', () => { const T = Type.Tuple([Type.Number({ default: 7 }), Type.String({ default: 'hello' })]) Assert.deepEqual(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.deepEqual(Value.Create(T), [32, 'world']) }) }) typebox-0.24.44/test/runtime/value/create/uint8array.ts000066400000000000000000000017051431512220400230530ustar00rootroot00000000000000import { 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.equal(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.equal(value.length, 4) Assert.deepEqual([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.equal(value.length, 4) Assert.deepEqual([value[0], value[1], value[2], value[3]], [0, 0, 0, 0]) }) }) typebox-0.24.44/test/runtime/value/create/undefined.ts000066400000000000000000000004551431512220400227070ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), undefined) }) }) typebox-0.24.44/test/runtime/value/create/union.ts000066400000000000000000000023061431512220400220730ustar00rootroot00000000000000import { 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.deepEqual(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.deepEqual(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.deepEqual(Value.Create(T), []) }) }) typebox-0.24.44/test/runtime/value/create/unknown.ts000066400000000000000000000006411431512220400224420ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), {}) }) it('Should create default', () => { const T = Type.Unknown({ default: 1 }) Assert.deepEqual(Value.Create(T), 1) }) }) typebox-0.24.44/test/runtime/value/create/void.ts000066400000000000000000000004361431512220400217060ustar00rootroot00000000000000import { 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.deepEqual(Value.Create(T), null) }) }) typebox-0.24.44/test/runtime/value/delta/000077500000000000000000000000001431512220400202205ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/delta/diff.ts000066400000000000000000000307541431512220400215110ustar00rootroot00000000000000import { 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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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('/z'), Delete('/y'), Delete('/x')] Assert.deepEqual(D, E) }) it('Should diff 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 E = [Update('/w', 2), Insert('/a', 2), Insert('/b', 2), Insert('/c', 2), Delete('/z'), Delete('/y'), Delete('/x')] Assert.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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 = [Update('/v/x', B.v.x), Insert('/v/w', B.v.w), Delete('/v/y')] Assert.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(D, E) }) it('Should diff NESTED ARRAY 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 E = [Update('/0/v/x', B[0].v.x), Insert('/0/v/w', B[0].v.w), Delete('/0/v/y')] Assert.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(D, E) }) }) typebox-0.24.44/test/runtime/value/delta/index.ts000066400000000000000000000000411431512220400216720ustar00rootroot00000000000000import './diff' import './patch' typebox-0.24.44/test/runtime/value/delta/patch.ts000066400000000000000000000302711431512220400216720ustar00rootroot00000000000000import { 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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(B, P) }) }) typebox-0.24.44/test/runtime/value/equal/000077500000000000000000000000001431512220400202365ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/equal/equal.ts000066400000000000000000000060561431512220400217240ustar00rootroot00000000000000import { 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.deepEqual(R, true) }) it('Should not equal null value', () => { const R = Value.Equal(null, 'null') Assert.deepEqual(R, false) }) it('Should equal undefined value', () => { const R = Value.Equal(undefined, undefined) Assert.deepEqual(R, true) }) it('Should not equal undefined value', () => { const R = Value.Equal(undefined, 'undefined') Assert.deepEqual(R, false) }) it('Should equal symbol value', () => { const S1 = Symbol.for('test') const S2 = Symbol.for('test') const R = Value.Equal(S1, S2) Assert.deepEqual(R, true) }) it('Should not equal symbol value', () => { const S1 = Symbol('test') const S2 = Symbol('test') const R = Value.Equal(S1, S2) Assert.deepEqual(R, false) }) it('Should equal string value', () => { const R = Value.Equal('hello', 'hello') Assert.deepEqual(R, true) }) it('Should not equal string value', () => { const R = Value.Equal('hello', 'world') Assert.deepEqual(R, false) }) it('Should equal number value', () => { const R = Value.Equal(1, 1) Assert.deepEqual(R, true) }) it('Should not equal number value', () => { const R = Value.Equal(1, 2) Assert.deepEqual(R, false) }) it('Should equal boolean value', () => { const R = Value.Equal(true, true) Assert.deepEqual(R, true) }) it('Should not equal boolean value', () => { const R = Value.Equal(true, false) Assert.deepEqual(R, false) }) it('Should equal array value', () => { const R = Value.Equal([0, 1, 2], [0, 1, 2]) Assert.deepEqual(R, true) }) it('Should not equal array value', () => { const R = Value.Equal([0, 1, 2], [0, 1, 3]) Assert.deepEqual(R, false) }) it('Should not equal array value with additional elements', () => { const R = Value.Equal([0, 1, 2], [0, 1, 2, 3]) Assert.deepEqual(R, false) }) it('Should equal object value', () => { const R = Value.Equal({ x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 3 }) Assert.deepEqual(R, true) }) it('Should not equal object value', () => { const R = Value.Equal({ x: 1, y: 2, z: 3 }, { x: 1, y: 2, z: 4 }) Assert.deepEqual(R, false) }) 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.deepEqual(R, false) }) it('Should equal typed array value', () => { const R = Value.Equal(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1, 2])) Assert.deepEqual(R, true) }) it('Should not equal typed array value', () => { const R = Value.Equal(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1, 3])) Assert.deepEqual(R, false) }) 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.deepEqual(R, false) }) }) typebox-0.24.44/test/runtime/value/equal/index.ts000066400000000000000000000000211431512220400217060ustar00rootroot00000000000000import './equal' typebox-0.24.44/test/runtime/value/index.ts000066400000000000000000000001711431512220400206050ustar00rootroot00000000000000import './cast' import './check' import './clone' import './create' import './delta' import './equal' import './pointer' typebox-0.24.44/test/runtime/value/pointer/000077500000000000000000000000001431512220400206075ustar00rootroot00000000000000typebox-0.24.44/test/runtime/value/pointer/index.ts000066400000000000000000000000231431512220400222610ustar00rootroot00000000000000import './pointer' typebox-0.24.44/test/runtime/value/pointer/pointer.ts000066400000000000000000000270521431512220400226450ustar00rootroot00000000000000import { 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.deepEqual(R, []) }) it('Should produce correct format #2', () => { const R = [...ValuePointer.Format('a')] Assert.deepEqual(R, ['a']) }) it('Should produce correct format #3', () => { const R = [...ValuePointer.Format('/')] Assert.deepEqual(R, ['']) }) it('Should produce correct format #4', () => { const R = [...ValuePointer.Format('/x')] Assert.deepEqual(R, ['x']) }) it('Should produce correct format #5', () => { const R = [...ValuePointer.Format('/x/')] Assert.deepEqual(R, ['x', '']) }) it('Should produce correct format #6', () => { const R = [...ValuePointer.Format('/x//')] Assert.deepEqual(R, ['x', '', '']) }) it('Should produce correct format #7', () => { const R = [...ValuePointer.Format('/x//y')] Assert.deepEqual(R, ['x', '', 'y']) }) it('Should produce correct format #8', () => { const R = [...ValuePointer.Format('/x//y/')] Assert.deepEqual(R, ['x', '', 'y', '']) }) it('Should produce correct format #9', () => { const R = [...ValuePointer.Format('/x/~0')] Assert.deepEqual(R, ['x', '~']) }) it('Should produce correct format #10', () => { const R = [...ValuePointer.Format('/x/~1')] Assert.deepEqual(R, ['x', '/']) }) it('Should produce correct format #11', () => { const R = [...ValuePointer.Format('/x/~0/')] Assert.deepEqual(R, ['x', '~', '']) }) it('Should produce correct format #12', () => { const R = [...ValuePointer.Format('/x/~1/')] Assert.deepEqual(R, ['x', '/', '']) }) it('Should produce correct format #13', () => { const R = [...ValuePointer.Format('/x/a~0b')] Assert.deepEqual(R, ['x', 'a~b']) }) it('Should produce correct format #14', () => { const R = [...ValuePointer.Format('/x/a~1b')] Assert.deepEqual(R, ['x', 'a/b']) }) it('Should produce correct format #15', () => { const R = [...ValuePointer.Format('/x/a~0b/')] Assert.deepEqual(R, ['x', 'a~b', '']) }) it('Should produce correct format #16', () => { const R = [...ValuePointer.Format('/x/a~1b/')] Assert.deepEqual(R, ['x', 'a/b', '']) }) it('Should produce correct format #17', () => { const R = [...ValuePointer.Format('/x/a~0b///y')] Assert.deepEqual(R, ['x', 'a~b', '', '', 'y']) }) it('Should produce correct format #18', () => { const R = [...ValuePointer.Format('/x/a~1b///y')] Assert.deepEqual(R, ['x', 'a/b', '', '', 'y']) }) it('Should produce correct format #19', () => { const R = [...ValuePointer.Format('/x/a~0b///')] Assert.deepEqual(R, ['x', 'a~b', '', '', '']) }) it('Should produce correct format #20', () => { const R = [...ValuePointer.Format('/x/a~1b///')] Assert.deepEqual(R, ['x', 'a/b', '', '', '']) }) //----------------------------------------------- // Get //----------------------------------------------- it('Should get array #1', () => { const V = [0, 1, 2, 3] Assert.deepEqual(ValuePointer.Get(V, ''), [0, 1, 2, 3]) Assert.deepEqual(ValuePointer.Get(V, '/'), undefined) Assert.deepEqual(ValuePointer.Get(V, '/0'), 0) Assert.deepEqual(ValuePointer.Get(V, '/1'), 1) Assert.deepEqual(ValuePointer.Get(V, '/2'), 2) Assert.deepEqual(ValuePointer.Get(V, '/3'), 3) }) it('Should get array #2', () => { const V = [{ x: 0 }, { x: 1 }, { x: 2 }, { x: 3 }] Assert.deepEqual(ValuePointer.Get(V, ''), [{ x: 0 }, { x: 1 }, { x: 2 }, { x: 3 }]) Assert.deepEqual(ValuePointer.Get(V, '/'), undefined) Assert.deepEqual(ValuePointer.Get(V, '/0'), { x: 0 }) Assert.deepEqual(ValuePointer.Get(V, '/1'), { x: 1 }) Assert.deepEqual(ValuePointer.Get(V, '/2'), { x: 2 }) Assert.deepEqual(ValuePointer.Get(V, '/3'), { x: 3 }) Assert.deepEqual(ValuePointer.Get(V, '/0/x'), 0) Assert.deepEqual(ValuePointer.Get(V, '/1/x'), 1) Assert.deepEqual(ValuePointer.Get(V, '/2/x'), 2) Assert.deepEqual(ValuePointer.Get(V, '/3/x'), 3) }) it('Should get object #1', () => { const V = { x: 0, y: 1, z: 2 } Assert.deepEqual(ValuePointer.Get(V, ''), { x: 0, y: 1, z: 2 }) Assert.deepEqual(ValuePointer.Get(V, '/'), undefined) Assert.deepEqual(ValuePointer.Get(V, '/x'), 0) Assert.deepEqual(ValuePointer.Get(V, '/y'), 1) Assert.deepEqual(ValuePointer.Get(V, '/z'), 2) }) it('Should get object #2', () => { const V = { x: { x: 0 }, y: { x: 1 }, z: { x: 2 } } Assert.deepEqual(ValuePointer.Get(V, ''), { x: { x: 0 }, y: { x: 1 }, z: { x: 2 } }) Assert.deepEqual(ValuePointer.Get(V, '/'), undefined) Assert.deepEqual(ValuePointer.Get(V, '/x'), { x: 0 }) Assert.deepEqual(ValuePointer.Get(V, '/y'), { x: 1 }) Assert.deepEqual(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.deepEqual(ValuePointer.Get(V, ''), { '': { x: -1 }, x: { '': { x: 1 } }, y: { '': { x: 2 } }, z: { '': { x: 3 } } }) Assert.deepEqual(ValuePointer.Get(V, '/'), { x: -1 }) Assert.deepEqual(ValuePointer.Get(V, '/x'), { '': { x: 1 } }) Assert.deepEqual(ValuePointer.Get(V, '/y'), { '': { x: 2 } }) Assert.deepEqual(ValuePointer.Get(V, '/z'), { '': { x: 3 } }) Assert.deepEqual(ValuePointer.Get(V, '/x/'), { x: 1 }) Assert.deepEqual(ValuePointer.Get(V, '/y/'), { x: 2 }) Assert.deepEqual(ValuePointer.Get(V, '/z/'), { x: 3 }) Assert.deepEqual(ValuePointer.Get(V, '/x//x'), 1) Assert.deepEqual(ValuePointer.Get(V, '/y//x'), 2) Assert.deepEqual(ValuePointer.Get(V, '/z//x'), 3) }) //----------------------------------------------- // Has //----------------------------------------------- it('Should return has true for undefined', () => { const V = undefined Assert.deepEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for null', () => { const V = null Assert.deepEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for object', () => { const V = {} Assert.deepEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for array', () => { const V: any[] = [] Assert.deepEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for string', () => { const V = 'hello' Assert.deepEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for number', () => { const V = 42 Assert.deepEqual(ValuePointer.Has(V, ''), true) }) it('Should return has true for boolean', () => { const V = false Assert.deepEqual(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.deepEqual(ValuePointer.Has(V, ''), true) Assert.deepEqual(ValuePointer.Has(V, '/'), true) Assert.deepEqual(ValuePointer.Has(V, '//x'), true) Assert.deepEqual(ValuePointer.Has(V, '//x/y'), true) Assert.deepEqual(ValuePointer.Has(V, '//x/y/z'), true) Assert.deepEqual(ValuePointer.Has(V, '/x'), true) Assert.deepEqual(ValuePointer.Has(V, '/y/x'), true) Assert.deepEqual(ValuePointer.Has(V, '/z'), true) Assert.deepEqual(ValuePointer.Has(V, '/z/0'), true) Assert.deepEqual(ValuePointer.Has(V, '/z/0/x'), true) Assert.deepEqual(ValuePointer.Has(V, '/z/1'), true) Assert.deepEqual(ValuePointer.Has(V, '/z/1/y'), true) Assert.deepEqual(ValuePointer.Has(V, '/x'), true) Assert.deepEqual(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.deepEqual(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.deepEqual(V, { x: 3, y: 4, z: 5 }) }) it('Should set object values recursively #1', () => { const V = {} ValuePointer.Set(V, '/x/y/z', 1) Assert.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(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.deepEqual(V, { x: { y: {} } }) }) it('Should delete owner', () => { const V = { x: { y: { z: 1 } } } ValuePointer.Delete(V, '/x/y') Assert.deepEqual(V, { x: {} }) }) it('Should not throw if deleting null property', () => { const V = { x: { y: null } } ValuePointer.Delete(V, '/x/y/z') Assert.deepEqual(V, { x: { y: null } }) }) //----------------------------------------------- // Escapes //----------------------------------------------- it('Should support get ~0 pointer escape', () => { const V = { x: { '~': { x: 1 } }, } Assert.deepEqual(ValuePointer.Get(V, '/x/~0'), { x: 1 }) }) it('Should support get ~1 pointer escape', () => { const V = { x: { '/': { x: 1 } }, } Assert.deepEqual(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.deepEqual(V, { x: { '~': { x: 2 } }, }) }) it('Should support set ~1 pointer escape', () => { const V = { x: { '/': { x: 1 } }, } ValuePointer.Set(V, '/x/~1', { x: 2 }) Assert.deepEqual(V, { x: { '/': { x: 2 } }, }) }) it('Should support delete ~0 pointer escape', () => { const V = { x: { '~': { x: 1 } }, } ValuePointer.Delete(V, '/x/~0') Assert.deepEqual(V, { x: {}, }) }) it('Should support delete ~1 pointer escape', () => { const V = { x: { '/': { x: 1 } }, } ValuePointer.Delete(V, '/x/~1') Assert.deepEqual(V, { x: {}, }) }) }) typebox-0.24.44/test/static/000077500000000000000000000000001431512220400156175ustar00rootroot00000000000000typebox-0.24.44/test/static/any.ts000066400000000000000000000001561431512220400167600ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Any()).ToInfer() typebox-0.24.44/test/static/array.ts000066400000000000000000000007501431512220400173070ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Array(Type.String())).ToInfer() Expect( Type.Array( Type.Object({ x: Type.Number(), y: Type.Boolean(), z: Type.String(), }), ), ).ToInfer< { x: number y: boolean z: string }[] >() Expect(Type.Array(Type.Array(Type.String()))).ToInfer() Expect(Type.Array(Type.Tuple([Type.String(), Type.Number()]))).ToInfer<[string, number][]>() typebox-0.24.44/test/static/assert.ts000066400000000000000000000003121431512220400174640ustar00rootroot00000000000000import { Static, TSchema } from '@sinclair/typebox' export function Expect(schema: T) { return { ToInfer: >() => {}, ToBe: () => {}, } } typebox-0.24.44/test/static/boolean.ts000066400000000000000000000001661431512220400176110ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Boolean()).ToInfer() typebox-0.24.44/test/static/enum.ts000066400000000000000000000002761431512220400171400ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' enum E { A, B = 'hello', C = 42, } const T = Type.Enum(E) Expect(T).ToBe>() // ? typebox-0.24.44/test/static/index.ts000066400000000000000000000012511431512220400172750ustar00rootroot00000000000000import './any' import './array' import './boolean' import './constructor-parameters' import './constructor' import './emum' import './function' import './instance-type' import './intersect' import './keyof' import './literal' import './modifier' import './namespace' import './never' 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 './regex' import './required' import './return-type' import './strict' import './string' import './tuple' import './union' import './unknown' typebox-0.24.44/test/static/intersect.ts000066400000000000000000000022731431512220400201730ustar00rootroot00000000000000import { Expect } from './assert' import { Type, TOptional, TString } 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).ToInfer< { 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.properties.A).ToBe>() Expect(T.properties.B).ToBe() } // 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: '' } // Expect(T).ToBe<{ A: string } & ({ B: string, } | { C: string })>() // } typebox-0.24.44/test/static/keyof.ts000066400000000000000000000015051431512220400173050ustar00rootroot00000000000000import { 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).ToInfer<'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).ToInfer<'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).ToInfer<'C'>() } { const T = Type.KeyOf( Type.Omit( Type.Object({ A: Type.Null(), B: Type.Null(), C: Type.Null(), }), ['A', 'B'], ), ) Expect(T).ToInfer<'C'>() } typebox-0.24.44/test/static/literal.ts000066400000000000000000000003211431512220400176170ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Literal('hello')).ToInfer<'hello'>() Expect(Type.Literal(true)).ToInfer() Expect(Type.Literal(42)).ToInfer<42>() typebox-0.24.44/test/static/modifier.ts000066400000000000000000000006061431512220400177670ustar00rootroot00000000000000import { Expect } from './assert' import { Type } 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).ToInfer<{ readonly A?: string readonly B: string C?: string D: string }>() } typebox-0.24.44/test/static/never.ts000066400000000000000000000002061431512220400173040ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { const T = Type.Never() Expect(T).ToInfer() } typebox-0.24.44/test/static/null.ts000066400000000000000000000001601431512220400171360ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Null()).ToInfer() typebox-0.24.44/test/static/number.ts000066400000000000000000000001641431512220400174600ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Number()).ToInfer() typebox-0.24.44/test/static/object.ts000066400000000000000000000014451431512220400174410ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' { const T = Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }) Expect(T).ToInfer<{ 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).ToInfer<{ A: { A: string B: string C: string } B: { A: string B: string C: string } C: { A: string B: string C: string } }>() } typebox-0.24.44/test/static/omit.ts000066400000000000000000000011121431512220400171320ustar00rootroot00000000000000import { 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).ToInfer<{ 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).ToInfer<{ C: string }>() } typebox-0.24.44/test/static/optional.ts000066400000000000000000000003461431512220400200170ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Object({ A: Type.Optional(Type.String()), }) type T = Static Expect(T).ToInfer<{ A?: string }>() } typebox-0.24.44/test/static/partial.ts000066400000000000000000000004771431512220400176330ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Partial( Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }), ) type T = Static Expect(T).ToInfer<{ A?: string B?: string C?: string }>() } typebox-0.24.44/test/static/pick.ts000066400000000000000000000011471431512220400171200ustar00rootroot00000000000000import { 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).ToInfer<{ 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).ToInfer<{ A: string B: string }>() } typebox-0.24.44/test/static/readonly-optional.ts000066400000000000000000000003311431512220400216240ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Object({ A: Type.ReadonlyOptional(Type.String()), }) Expect(T).ToInfer<{ readonly A?: string }>() } typebox-0.24.44/test/static/readonly.ts000066400000000000000000000003561431512220400200100ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Object({ A: Type.Readonly(Type.String()), }) type T = Static Expect(T).ToInfer<{ readonly A: string }>() } typebox-0.24.44/test/static/record.ts000066400000000000000000000030201431512220400174400ustar00rootroot00000000000000import { 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).ToInfer>() } { // type K = string const K = Type.RegEx(/foo|bar/) const T = Type.Record(K, Type.Number()) type T = Static Expect(T).ToInfer>() } { // type K = number const K = Type.Number() const T = Type.Record(K, Type.Number()) type T = Static Expect(T).ToInfer>() Expect(T).ToInfer>() } { // 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).ToInfer>() } { // 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).ToInfer>() } { // 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).ToInfer>() } typebox-0.24.44/test/static/recursive.ts000066400000000000000000000004371431512220400202020ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Recursive((Node) => Type.Object({ id: Type.String(), nodes: Type.Array(Node), }), ) type T = Static Expect(T).ToInfer() // ? how to test.... } typebox-0.24.44/test/static/ref.ts000066400000000000000000000004141431512220400167420ustar00rootroot00000000000000import { 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).ToInfer() Expect(R).ToInfer() } typebox-0.24.44/test/static/regex.ts000066400000000000000000000001701431512220400172770ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.RegEx(/foo/)).ToInfer() typebox-0.24.44/test/static/required.ts000066400000000000000000000006301431512220400200060ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' Expect(Type.RegEx(/foo/)).ToInfer() { 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).ToInfer<{ A: string B: string C: string }>() } typebox-0.24.44/test/static/return-type.ts000066400000000000000000000005361431512220400204710ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.ReturnType(Type.Function([], Type.String())) type T = Static Expect(T).ToInfer() } { const T = Type.ReturnType(Type.Function([Type.Number()], Type.Number())) type T = Static Expect(T).ToInfer() } typebox-0.24.44/test/static/strict.ts000066400000000000000000000004741431512220400175040ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Strict( Type.Object({ A: Type.String(), B: Type.String(), C: Type.String(), }), ) type T = Static Expect(T).ToInfer<{ A: string B: string C: string }>() } typebox-0.24.44/test/static/string.ts000066400000000000000000000001641431512220400174760ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.String()).ToInfer() typebox-0.24.44/test/static/tsconfig.json000066400000000000000000000001001431512220400203150ustar00rootroot00000000000000{ "extends": "../../tsconfig.json", "files": ["index.ts"] } typebox-0.24.44/test/static/tuple.ts000066400000000000000000000003561431512220400173240ustar00rootroot00000000000000import { Expect } from './assert' import { Type, Static } from '@sinclair/typebox' { const T = Type.Tuple([Type.Number(), Type.String(), Type.Boolean()]) type T = Static Expect(T).ToInfer<[number, string, boolean]>() } typebox-0.24.44/test/static/union.ts000066400000000000000000000021401431512220400173140ustar00rootroot00000000000000import { 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).ToInfer() } { 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).ToInfer< | { 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).ToInfer< | { A: string B: string } | { X: number Y: number } | ({ A: string B: string } & { X: number Y: number }) >() } { const T = Type.Union([]) Expect(T).ToInfer() } typebox-0.24.44/test/static/unknown.ts000066400000000000000000000001661431512220400176710ustar00rootroot00000000000000import { Expect } from './assert' import { Type } from '@sinclair/typebox' Expect(Type.Unknown()).ToInfer() typebox-0.24.44/tsconfig.json000066400000000000000000000013171431512220400160620ustar00rootroot00000000000000{ "compilerOptions": { "strict": true, "target": "ES2020", "module": "CommonJS", "moduleResolution": "node", "declaration": true, "baseUrl": ".", "paths": { "@sinclair/typebox/codegen": [ "codegen/index.ts" ], "@sinclair/typebox/compiler": [ "src/compiler/index.ts" ], "@sinclair/typebox/conditional": [ "src/conditional/index.ts" ], "@sinclair/typebox/format": [ "src/format/index.ts" ], "@sinclair/typebox/guard": [ "src/guard/index.ts" ], "@sinclair/typebox/value": [ "src/value/index.ts" ], "@sinclair/typebox": [ "src/typebox.ts" ], } } }typebox-0.24.44/typebox.png000066400000000000000000025432271431512220400155700ustar00rootroot00000000000000PNG  IHDRա pHYs  DtEXtFileC:\Users\relay\Desktop\sidewinder\build\assets\sidewinder.blend#ntEXtDate2022/07/02 14:34:32F?tEXtTime00:00:00:00T tEXtFrame000V% tEXtCameraCamerah tEXtSceneScene!]tEXtRenderTime00:06.19囈xtEXtcycles.ViewLayer.samples4096Kp$tEXtcycles.ViewLayer.total_time00:06.12D|%tEXtcycles.ViewLayer.render_time00:05.97q.tEXtcycles.ViewLayer.synchronization_time00:00.15u IDATxdd)ЙRT8Ha$`fXxŋ%C?_/Yn;믿a‡#bӟ~N܍mݥqB_v3=iތ]}HܛPX e[˿/~_p-tEl=^CMMCLƼs?9cCQ|>5g,>ש# 60>)γޯ6/ew__?~jE|ORzĨׯs>V#r[SΊ:'l}iC[Q,tU>o䗸9?=/d~ᣧw}6A|FT\)NOfb_?Ԍxcn?^8s@.`תȻ>[-3Q__ޟy{hJf~IuŜ\YKς>Xl7k>9NP\{f 7C&{d}΅_'>}{>XtXg掩HmkZsdWya}r(8 {|_y+uWޕZ?kv5 5Hi[m1|VK>G<|׿5U^> a~})/ۻ;*פpڵ1}[̡*zyG|>;tإnso o5Q9s#kK1'{wϝGg]y-~x0 fN0EϰjYmѳ.sk˚gEO7|9* ݵfiGn:LUjTWs>P8Wb)*М|֟WP#t2W5U[5py\!qdT<<;Gckh?N ?U(j.w3b|Fo1P=XO~ׅߟ1|M;y~!~3uO .mY]qB5N)݅j1=v6_yz6u/@jft6E)Ѽn295d}&v-z6^`θs6j$L_#<0=QQ[ȞuIvz9Q( ֪c go]GQ"*KϳUwJKSW`xj_9g^g0MOU7ӄr@S+sO!|\|v]1U2:+8j$W}g1;vr?3f&2P:{湋S3_kr)o,޹49=.~7cqJ6oCXѲ>7nqcgeɉ kr.9'6: ovū XS8Ʒ'8J+QsM<ߋ3wqZf#߻*+]h,Ƀ5dVxpU1P_ʝ:^: RC^B:7j큰5ԟg̀ \F5+UG9+Ca{γ(5?XfQ[fI,/J,ϬeaVi{ſ1ty$.W{>p")@y/e)eE+=9ܞ3EV4U{l'Q~ k7 iT DBH]Y5Hx5yK; \!G|IJyt+E~6У?yY,?K-~>'rNhVEh:Ʉ˿StVa^D{"]G`[J3^QAXpԚJf?kOaCU4, z8W9aCL'8[&7wYC)^M& UQ/-r$Io֡:q4>Ŝpbǵ\ωt|x]Ԧ88o֮7AWu"K#~6<#pCU죾QmmLbG~&\=ơH_EB0ɡX k✉Nruԟxӌ4V#@BCZ+oS,1y_7@E+{ Oh罀<$^9#RfAQc\b~ܓ;kkSgn]\~֙"v3+{jt[z9uүL/*,Wwȼsn? JwYw Jj]p@e{2xHכ1źUU2o/ꩾz 11UvcMUF)&9,tp֎3lYgordžcXgs<‡}zԭ⪚W #x9ط> 7Vqbjc}A g2oɄ"bbMP~.lej&gC}=B,忓{W=Pa2O~x^k)ؗQL/\|na5Mp3_Akfh?QpU7i?sp otwẓF 5W~l+Zb՜uAIvvwNǻ.kM/G&-?!;scF;F9{qǞg$9RwRzJ")t֬6۷bvͯ{]hn׳^0vGvI kz vzCD+5GbYɘ=f>I=|5xӷqŴks&&J{>u26C<r-[uM1=ꤏy>xͱșzzqn񹃝nIU/'?BLn▮ ůfc8JS -i<q}{/e zqսOoTc<1rosS3Snw峍Cv]Cz^qp& g۶9jjW#{e'4p:}fk6,u k#~|^Ob1z۝ګQؗ`gzOh+qoF\T>"+ϼJ#?Ϩ?Hb3(~fC:E*gAӄyfΣ6L1R7<Ω$ڼQS{>} ϙyeJI\bO.u$f~u`Gc7O\QI{sхS{McXsmmO?_|[Ͻ7@ӶHdE&KbOͧѧ2ۏɿ@ζ?׶ͨUZ> s͙qs@/Zp0u?jŋ{ ~خh^攳Ƙ kLݑcoK_9'MB&ŚiarddH`̷5{UN XAw?!e=|ԀZzfxg|r7Ns߸M5s;5Hڰ[Ze<C_ř^欆~%WGbWXf˪f`"46@/>mM -\{=ΣL{fyg\`+[d?iw:΃VEXkb//] x喷޷ɓ`Hq._Ʊv=q]K䉊2߷7{"5 TmT:w/5(_ъN?k6⿊/xsКޙPxt3M\b nwNEG<G8cՖ"~~ĂH|=v6qm3So$Ǫe(!6`asu;1KgOK3{s$a\[S9@޲Ek/P!he5gA(G[sTx+?bԭo|Ū twMN^0MbEGH/(xT{2\ựUX{{7@}xՖFαgnXNwM"Kɨc9.g|?wA+V~<>JҦj ֩.ick]s*ggk9vȹ3uj=(1Sטs%}[sioyl _W_Ntw_ >-b*gðx! k/p?u:XL[<,寯Z$6VU-۾t5+fB# ?N!lה=v@?]N>XIt`^u!6~9*s]B΁3[\7|ޛ>W/Wzşݯp8Ȫ8:6E v_zxxB>׃PÙEj-*tGh{f#Үl/HϳZ uDz],.rћ~+0`]kkמZo+_,6{Y5n(;d|Oʺ:_feX/sob7]'?=:+}#p]x K[1DT!?茦nzk`wki8fW对߼:e Lsg4e!WvX jw2Sكc|#_Uܴ҂߱=/?-br66FK~X|`s{/+ϭ ~Vo<-~LY+V,ZvD']s^c}USi|oIy?M9&лgk;:>#`su+*c7{,LE*Ϸ9{kSf;1c} S[x3[EZL}޵9zbOOsC=pG&shM\3oW?|M?Q[JgϽ\ Zyjfڋ=knw7eel=S+-f(|gV\ގ7vY*OsAB|mi߰ʷpZxE7_߱zb_GڜpV}}11; lv39oE9t ٙ\i? ~~(v{"V.tnk_p׀RSJRߺFZu$B~Ò ^Y=jgx1Uu鑽x e0̍=zRdKw״Vm왢,uծW;Z#i{דvtlɐϙ"^?nE\Z'๴>ɗ3> ܾ-rຣS3%k|s9nƚn}zkΈzwSw)qLؚp:gҿ` dcsYu<_h+* "t8\qk[6ZW8e^ez ٟb9G'u}*5o8ⅩudO)m~zWһu3b҈) ;/댧{r{[.Ssx5zW,VtoshKmwQ0ug9 3MƱ@{ꤾmEV~RSle<[L/qceKg MP3mԀ'Ԏ=0{/bm{-6yu~ͮ!ݿi3]Or_.fgz~y؏&0]/-s?s@JԲ9ԴKtW5t,l{4H7YjG^^g#f8ԟ9X}Zb=1jpNzT/{vePf>Ki|V7;|vνZ&Zf[{{4X6a WDb^+>_jdቭ Y~0`w}/3!)V~H޸uϽ'?S(~jح7,dz]ԛүck[s(nZf?wWsQsF~ư &uO_竴&?qԕi{j.k)eOBm|~)\ Τ+u­,ɭ͞wGDfw6{V-1=;+=J˺?ӸlHلzTe=kN\ ?Z[K"pj?˕wp5y{&Oʎ] FϋzGg vaJ>9lbrr}u`-rIQxv;`@v~s:=#YF&|&كXxתNjś:GSL0Kםq1iGYbp|wSl!>9=j}rc[H{s7Ot*[ap"_I}Zln糀[޵qƶ>pyD]E%뙢\e>9#\k ޞ*o-f/E:-8_[jFvm{4OP6}DoO]<cU}WkrU狿ag_̭9?EG:ľ>};㋲;Ƿ;xVLH9|b{#~d&>0jXocoLKWW>u06B~8K?dzВYͯ7KQue֮} #ټ43ﳖ+_1's]/gr;ط^ZNaFթV^V^k>s[kWW rG5w{5k=)}}Ztaݫ>u%8Vsb߹Fך}5ض[sPSg\?ki?skƸX}F|c{rYpvyX،3X]߹ܰ[OM}P޽x?r6VLLcWN[z['9]?yXڷ8?Zo};{VʺDv=>sYϛ=ӌ"γt{ĺp/>~W5iQe˫y>:+/{ߣk={G7e!.vtsv6|`_zrrszfֹ4x&-ϚqS/q-1kªcLo'>0caL]ߵnߺd6gٺ7sX97>9Xcfa|3o>cj~}kr& n}чFu`? D*!Y cvlr{G1 M{$?4zVkXZ&I>11eLm탿6Y!s!./>[߸ܩe3V|P3W0g45zǦ7ǺW%P]R˄79g~xk-/ۨ[{ƿZ˙Db`Zξs\oԵl48Zb?09lp70mb8kƤpg]5>Uksi.,Xu_b譸Zۢfc;f, ?W%p[;[1QDo]ež<ߗ_[U,q_9qׅ,ܙ}Z+?A-bFSϗe3ZrzeM8Ga\hVόz\֋Vw<='sӞ[Xo|>rVpȱ,1UNu~̄}ub'gcԹ{zhu}9̋xӔƀU:ߵqF_X2g[Xƻִ1g|4ytz]@XC/coWK$~yZ;sfyYSַqW3VĉgN栶7n=,V S1f_ڻޝ˟jNc5v jSo[b_Lr1&qpr;~$u,#`x2G1,ut'aWWl}b:}l#=uwکrzS]E\6MUqNdɏsS676rg8:y`Ԍ8'- ߯W,r{=ÿ(ZjcYDPݽDUȩ3[El+'3I֗>.$._+n>hwoKg]}2;ZHslͩ;W{Ʒbvx,Fۼ$1q7j'XB4tP}W q /Q ĩ}}j|m9s/άA3]6}Os;N}v/ow^ںPY9`?>g&([X +_lLm6۴R!vfcNkMCQk,Zjyƻ ^!yM /5KgR{f,&vjt#>{&?=ϪXycv.欒al̡c.h؏9K8jHZq&n["osVu9X*{7p9vɯNN5)~_3Q#K-b=b Ƶy/Wяݼ7-:y_L s!o1RXvu8{Eژ۱~VoW&slo_]K 18z1CWD?Z{h˘}fc]_W_a㐸tγRX=}[g}n]$`™w.0 |p$9 M럘 3c4}e-=|Ǻ/#׊yLFn"Nw}^kO9iKŠ3}1o9Wl:2P$.>^3'[Jy5|zof,giPuXiNo[{m'}r=n2{ 1}0\'~t ~YbiD0O+ u-+5}:+]XdO`q-|xRcV= y{5wcw O;u!o:cѵ-9TU yrLkN@úWI}9H)5|y\CqF+5\fxi3w>ވ# -3Umײyr%Fc o{  3 Ms^٪||fxu?#9̙{n:j>Y++vj^>ۊÇƙJ=?oíUؙO|t.5dm9PnT[y>DӹkkL/|߬m z- ~no[8[3\=U;t7=S85EqF–߫hY,bK|TyLy.< 3_Kןmeזּ6\u kNw^uY2k _.aUٯ0o-h^>E ̣nrʇc}j}r=s+7Jlg3TU{ڭm/>hTԺ^\m]^ius3G.>1yZ>N5>VZ(W uo߾Topyr)G7E#T+&:x`o^ys/a?hk&X_ycr|=D8;^Ŀ<[^䮵Ws8N~kĜw4w\/֣ӌ}5''{u]rϥUڰ"`s:ͣ~5fݗ=Sg?_s?1r\iDFwʼ"qeֈO͝5vyF,O߯!6|!է?WpF_".s>}9W`XW W\?XF{&9 '~9۟"[\,pYv "1;1;seJeh2ys/'un`aﬧ.c5Cclס|;f"fKhͳ.{y-qus>̠U~憹Zsq1s|nϵ糵BV:?᱗T97{{cZ|ע^`E՝~OzRbRDΞ:_΅YK/-(+{iTtwهjRs|j%KXk#/T{fe#F_y=zYzyƼ~z0^x# ćuJ{6˟^j_ [\{^_ځoen$\.0~ڡ/\pkbŒ[_)xKjǯD]?q1譁ur󎡷_|FKE޲]c1aGTT]c:[pk};~s~U0 r2矖8*^H?uJk3ț^ r~iz ᶢM_􋑧mȉsN욃Zb6X[oyjG$!/~p_؉^NCokٶYtoc0:ܟ窢[zכ^g&g -s߳^^<\Jjon>Nِgiݿo%._Ձ\jHjoYӔZ>.$5yղ+ʲ%/׳3>9^L^uW-s {gM̈+1v9٧>.6?Y~߱#˗_ IDATb>;7?ϨIYhSCZ3Mȣ6N.syhjdɒbChp*99G36{j%gxlGrY{$zkJΣb*yR*?7=olnCҪ ۏX"jj~^Zjgɭvx#a *Bz"?|r6q]̛H3gb"a],d] m Pk 7;Ւcdk1'Uc["37Z勎>xJɹhngcb/xQ}-{=7_c^<[<μG̎jQ/<փ]wD,8gy`p ˻>FjS%~Xr~:_$o{97Nĭ3c>Jޣ{xw>QOS51Ww̓C9,ɞpk!_[yg ($闯G>D{皟n,q[J+=y[r:/^V{فk˥sq1}DbV-9gWnqUBճ&C˞7>1}f.Q1uHuw/F+N++n؉G;jm >{=")|Cпkù#i~畱`s,q%{DqRw0~Sw|S >؈$,G{rY7/͏XkU)ح֟}}Z,}̑};Y81F&TM}\Q<^w-9ڬz^>3l-9#i\951[^]p_(M]m{/|)|[xViO¨}u'W畧ݼ'#qb{:"7֗1ma<5z{d,5;uŨqݕ8-2M_ Eb;˥6Va׹墕}/WxhJls33/p*FϮԋvџ؝3/vфxgm{* VWY?pɯ_LwVz^j%Fiתּ\03㉈1|8(-X<̱4p\[t}[n`.5.j236WV_4n{0}~ݧuj_ͭ#?-ok~ʇ[Զ0JY[x_I9bF3"f=`wW9g_-kzX`-T'މ9cye(qw[L='$H$R!8wu[Z5ګe }y|ͪ5&PpgI-)uȥ]QqzUo䩡ŽۧEĀe#!Yu&5~8[`[1@v[>+!S6۸'c}opj1Ӈ -˳@tfdMcoE.L3u/dYy7w3G<+=l孞f6ݪΘ9nˮE%᳏1n@8mR{)X׾s[uk|^~9'Y]gfhlr=9}o>%nTu5O"0;^kfIB76f3uv>Z9uNyNbOqX{c[3x5{-^1? 'kY(1&ƺ?ܬaмkcogג8ܝ߳Qquw3 UQ7ﵟx9׮+^I*65&VYs_VSyۧm?; 4*ޝ_-8M,GG6=${/5seFLGU>uZM}GxrYoĜŗ~X̱z?%}}=[C[߮ս1T#>wQwM)p @L^]3ݚЖOȴ{. B`/ͷV?Senb,ƣf|`mNm˯&VOEsck޿Vr~~ucj[3g{[$R}fhL*Cěǝ|߱+gW]> Mug;qp< r|h2*؍/Zգ_]pc}uQ:g.onUtfO;2t25:vUWi ʞc45fƳz9r-վQ/^ߵW:Zdk7_bM̠ǘ٪sgLk~j䙸1B)15} k~豴3͙>cOٹx6/=8]!Rsp`mlaVq!_[s޵8q\~k%s^;{8-}zKTyʳy;׽Nt44D oӪ6z[ xbG󨟱ŝÊ+J߭ ڢQu\k ^=hM:},F|%FbzhݺDON\ vOx- W?\]z`e˫^Zh;nf.➍cߺE<G_[ !uij>Hb^1ĒK$k꽰ҾVmgVwPNU6y7mQ1T$~bu5_mb`Y/' oK..AcmNP5gu/SE~M\zbm._?f}{ŚZԸth.[cZe#/t.<\ڴhǺY<YOywQO,}PfվSC[KlA5:'Οy-.oݽl'-t9fS>xZ*J'7r]k.n(}AeǷŻJU-֏Z_v/ lI=2} %/&v'J_i[\r1O:!w̡|J#}Y\1 Lg꽂=Ǯ}@IV>v]T#K]|j$I,N^fY廿nl/ĩE%cIGlcj=+ꨫݚ`>C sbWπ5Uy. ]ߗָQo#>?ei?j!7bu\sE^ָ{Jl&qrKLpRl<;#vܚa¡m;;ouVd}vobjozbE/m{M&0p[ #^\\9>~3 <ސ5'aӏ}מ>gRGw- z(9snGY}­=UDߚv{<;;1Ϫp?{h\ܨu)JI0YSWpamN v7a罹;20ٙjfG dXp_>q}ϰsA~rdm=`\Mm_΄OReGs2#/ߚa'3Sq3s÷6Vٚu %g*'+8Ϲbe|Rcs}f a[ss0gc졯9s0)-bj>zquZkfSjA^ŦURWܵu7y^OV31Fwp}eLrt~N γSJ|MV!q<;t7Bf󕰸}^j\%Ȏ?Ru^K \y]o+ _w>cͿj!_56u<^gy?Yy 9B o#[n~7XTqgKHߩ.!mtkӥܗg {xq^.S,&:_to?n*jin}ִbjTX}?9u|m jon7 %WZq,֠)w:dx+_գVϡuC-|Tub`͵5vk/Μhg eejrfoN{W@.[eYCSĄ^԰ҏw|6697 Q5ZRwj|WmFrڌ8{&o]3'Gm,K[xg ã^Bӏ SZgc|[ges:. ϙkaY*$[{/3[u%5_7T>_-x;5vt#]e~F'7?Og?Uk %{7sxZ*M؜Wdz=jc5_RhP9P%rvxuQ1UiꞓuW)"1X9ų>9c/&m=W$=o/N$5.5~18-S;< Rcet~UU/)O`Zp\ qtNHY;5$5SqⱮʹ?kSN- h2F 'uR㍵\h/Eʹ{ */X#5鷒sj K a5I?,x"?f>9z ~w-lN>_֒8L4zߤYowE3yi,\>k'WUٸ\[ߺ~7үίzGēKM\5iRfh^nɭ:a|i3^\9{د)~tzz6޽޿,qbOG0I"`e9җ6Fu~0ê%٧jSVϳς3}ӭ;_=Z5!|+S:{[y_,Uqv~7ǒw.{XSWn=iwP,gY='ݢKf w}"ɻ7匴]mrf jn>bߘrmW{|p i9(̒sxO?3ٯZX!ƏL w yu4ޙ~Afwb\q8o' 7~|{b9ҫn/؟Pt%~:3nό7k5 g^Y7po1zFG]_ど )u.hs`3HзǷ7eOXqU"^na>xe9ÿZr a$kk!6?j]dc5GJtku51~vgY6wڮ՚wgjFuOgiO?Iŷ{!l(\:ʚC{8=<+YSu"8 IDATҝ7w* ڗ'ػhu'os?F]\5l_ !\WՙHZZ'/ Xcr>)9kpө8sۤ=)li*>skԟU.Zv?kU{\q)mf?asO EyJ^\j2ڟtbsm=uO9'>-q]<_oͱV1537ib^+T ;t~-k֤74YY?Ln9ÿ\}Z]y8-kO?ޖ2g]\dOO#]=ow^:>}n/<ƇPGkr`^_+1_89Ö9T?r Gs,k[|_xS ,c9*@يXBwLTLdhz>êO_֗6{slVbo0|sW2Z>8^m+^k ϳ~:yǮuE9u#/u2s'/vhϥuVsڹ>RS39uMNlY<ƾ'>_uŽ7V|ƳUDѬךj%gEɼ5y^\)7&}}]́b9Ӳg(p~_vf ZR^,9Ln0_yU:?IQ_-ZźkEvŷ=>v1BO'Wpn4]嘰 687mGw~uX13 =ufs^ׯG=q(S{ro_sL4CPIh&Gc|ƛq_pp)9R`ǷIʈÂY_Fmr_~+SȱBtZ?`!Ϲ9}/ //u&LWf;ΙC:a]hY- صY7IbjsL뼜~~9'ezxvJ+y[ؾ88F.-1z{n5ANMy򔋷ixq:Zɜ=}GÎ4/:go4^>(Aq5uW h]sy2)`ז=gnvLbrgH֍8ظ4la c{6~\}pYq{! '^~4#~֬l'/2Jߜ:(nR[/UJn"Dnq1.9O1Gs_8|ŏٶ̻Z:к~lĻ_Y?::έ[ж̋ӳ_7:|]e2>Uj+o3WҰ9—mp`\+/Z{&:<-h]E+#ƬA/yb*j W9éej<|rdm wߌY+.nI%*z3 o'6_?Yx߼W3ƅYYgyk_ӹ^zK5ŗ?|ZCk,k@XUv %"E뿚׍[kٷ{pѠ-'#Vkm}yxVemWXR{,-{c]Ƶ ո}@7,FδIfp wSMoNQ IZ:/$, ofUW٥+1s_ryW5MZ}-o1,^mj^Xbg3Vl}9`cw^W,G[3ˊmS׀~|z5~k yc _>'~']jrxD~ra߾+/Mq+8Bgyrڣ:u?7rrck_Fj߯Ui\wmtֽgfRyԷΦ+ϱh;ϼ})14 :3 p/,B)_g͕#:u/ZȚ's7x~t7.fVyq.]<\?!hn/_ {gfA]\>p}ar2^Vp/iuɣN1>d=85sZzj\}8CvY1~=_ _!p5*k^MŁ,}bjoWh׶N}axV uayޘjm+bܸu(dO<lmjHM?QνUSZYZl qy+7)t6+]K>OؠYݩ{b~^%oŪw9[Oߝ}pL3{s:kqڊs>x_ruM5} /u½_aR˿CJmA<|4K/B~sjI>5f<}_fb1Xdna'97w;WIᛚF WjgOMY(9h.gWȬ>dnƓ=n9uf/ aWpr}[\#lqoeUOr$.+K|_|$\sl.ϱYMTƒ%} rcرwM>=4ff¯y9Hx;?}dzΘͺFW{XCn-(0#Z{K+/^tL9E@ؚ;9ʞؿg8ȫ܈c g,8ܜW9;c6xfuy|Ԧ0-%fwY*¯D+էjS:vSo_<VAe*[GgRwF~<6>ֱg| +>qi5d% ܣ qӧ%YZ>m5ӏzxƚ{qXi'aسs63x=!zq<4d_\.U`U_vn^.Y'_sɿ ֬Rڳf8݇X^[ޭMW׺~'>qfi\!7;k ӓ¤=XZTrn0wrv^k47Mqb_iֻ%^h'KW:D _ħg㤙[Ewb}g-֗\qɋ\sykշҸi=S+y:}qggCoZ=0^k?ǗW?'J|&>{S8V;Y7s0a`ٗZr1CLrka]7̛8sO Z+s:ɜ{6յ 9Xu9}wOj>[:0"iyƦF{٣Z"n 3gbr;?Xn1gmvNzx5 u/g-937u{ZX38^YsV9FC~&ڣcm<*4g:u'$7x6N^z?LNׯǹ-ΌG|K_+&/%U$W^~v_|kZ?ޣnaw*}/.QhWѣ ~)7YK~1}->.T}u=|O,uOlk<n.N|C7f})29}gկݠypfomw*}gb%D<-,hί3鼹'_7'ɛVu'b5nW{YCK i/5!LO7c/.ӐqZ9/I\8é_KyኻNloP=IƬ8_w}@W)2yhe^u!nj^3oz;,͖oS-1򨆘Q5nu݈ܯ|VWEu~3!: roF)׌/ԣ%do݋milago}1_UFK>OKը>y)g&UN={.>*_]5w˸ &zϝ3\|EIhO՚g0|1\G[mΩX]z:D֒C\7c{ k>rf^by%no"'kv?i'cs>\Õ_ 7'F^sa7/s[{?^zIw+ς/snx2V<}y11l0>\铳P"}s5M['~vFVWXp,`s翵1'Yo>3ivYP4{_Ml{+rg?8>f}׌grCOy]ns;s2y˳{l͂zkY8[bA33Y[|OK*Mw 욒Y+>ծXϻ\wcGl b^Kf_-ś{l{Ͽݯ kSyQz\y'lL+gX瑮sh;? mp=:պߞ5ЄeƴwxG&xON8瓻y8ˑ{l'/Ba<ڊ:A漆c(Ԃlِ.VFa_h9_Jg+귲NS36nEvqiH-̘{q+.GI[=rv9S{9R[XO{8[)+;֠m渟#c櫪4x6`GeY[.xgƫy 9 w2ܳ}jƣf7^vclRN9۷ƛr ݘfx:5`_Wg΍]v>[a|3gEY=|_22Յ!.|2*?Rl["?9j_Y~%4nqKy=gGG+jڈq/뷭9!|}$g :º#A"GV㈍y:=zgZE欬[|e_E^k <\{p+ż=Kx5Yo]bٿiG DqKXMwưűxֶg8=g^w'1 'y3ř8W9Ƀ몱9?z-fSı"\(Θg6qo ɥo:[6 &}r`RKDj{nxv584kG{=}wby ~4Pjܝ5uˊkv5iWkj'6jreZr>!"Z'sŖnežXfK:!Aω>kl{I:%t97+'1PW(a-%y:k6݋5 3G{;]S=ִV_qǿψZ/橮w{*#;;̩W͜[;˗~fUi%l5r{?9w9޹[-[۩)Ckg]'טJر/Nε@'h9u{5bf&ym 0_pE#jn0~=t;eE7nߺZ9h5n<+ᄥ*|g{ě<#3TaΠb55ο d=kptn"%Z민t% Ԯ&$Ͻ̝oh;s}d Auud~ًę9@_..}<9q~wޕgcK(zwryQr8Rدܿt#ߩw<]g,6u E?¥͜w/μfpt^׿晏M-y'7Wc{1׳}Ι 1g5ӿq~Ϙx}u#{r7־wɸ_qkܟ](m IDAT1Zs{%' zŨp'WF_`jV듽//$;۷)[.jK1_N?jH5>=ͯu? LdR;Ikd_!ha,c9ˡjuhՊ|;ă1#Z|9/~s>,ּN?N-s1ذ2o^~V^=3M^F ylb5WGKe¬D+LXxeݬ-Ojی$7"{ 騾A7}OK5#si׶kgʷ=$ڌZ`|צ_.b_q.ˑ7WV>Ӳ,Xr/ؙOE[U_ϯp8djMh#yCx1ZOU9O.\X}ڌ5?gbj/μvľF N6N.߈,S=$scf8|fĦ|'~}C'vI4оyOd\5x֊þ"EopeenZή(W.`UڠF$|˳1g9X4?/x|d ږx&+N\砟s^ԿsKEb`>x0'ٜ 4.mEA3^?7˞W}E\mOucUמ~Wk6%{벷6X5h\tOod޿GJI^M.s ~C/y:o~7<+uo[֨Zc;mո]gXZ/X1"oT1Қ<6ZUo LKxzP{loY֓7W_dO ҷX ^#GN?= ?3f}8缥>wZ9g9SSwΝ;3lfzYѡ7&g\9bNHqxy,3O-mkŬ*3k|uF4뽩=c1}}O/pt|4enX=uOk}}}ycMXN~M~c /|{?ݨj6]Zsү?ygQ~(%VK(0'}î:GNqu;J}Z'1kg ӺAkΩY_,ce%nj/r[T L.93Ag}sw 8V՗>6ڧ\3-3&.$~akEN-Wܙ9-[Ɵt Dylމe}iٚ<fH6 .:tYs}Ka}sw⡋59<}\VV yr,=r?ZՔkvV;GFM>}cm'aU=/pd\S wj=}| Vowu31wZ7Ш}y'rc9&ef3wM^=ש336z6F>>>r*?Uy'D/£aOxZ`< =w}?-+LHÃ\6[%{gA,G|f7y~Vдj92\=u3LZ343"׾ˮ= y ٯĮ>9<]|Y9w/[ek8YTuoH{֊GKC{-XZO渗kqyZP'~Dҽ.{_{ƒP#79%|1{z 0GbΙg!|bQViW}.S~r.x?sc=Y?$ú/N޳̗E cOZwWg߾/ ;8mwkxc}_mn{蝒o<Brc~s=s:CSne8oZc9l賗jpwhpK\}+gprU3s r?"'X5Lsr {z+ӚN TtDI Wݏ5y7rV>u3ew_si^/Xf"f_Fzц~k~1?/<̑~K|=˻MwϮGuf5yjWUoFT3;| %tef^-ެ渹xz;aE:C+1 !Ӊٟ8mP-{SIpg݅M^i' 9uZs3/+7X`IjFƮ޳/|n|޸\Q4kE>bTxv,b__קg 79{YE;39١ccI~{nl0xoAݹ|ZjNMoo w>r`ǁ8}m~\IZig/l|ﷀh11r)bp!|p:/Hyӗ-?ֽܯxS~kʗ|nFk;OFy3ae>#ڜƴ[ҷ{D"=I :gmy2w|sb}I9ˮ5UyHșsV`}-Y~]ƠZs˯6ˊS>N>󛓿Husz>S5: kyqy'FOM!f61ͷZ$w Qiυi~ĖD[ԙ )©o]=GP}:˷JVLk-Dm,84& Ʋ"7c1?Miu'?qO=rgTnzguğ}ͱejhm썃/ OloܟˎdҮႯC_~ɜ,pjf݁A9 '&t>kNg+Sac}g_VdxA^݉9;9ߖǷIy[7l U '>}6_GR+}ݲΝxkgʉB+m=yf{ƸC>{sNָmN_{kjo:+ln k9׶ǜ߼̟̈ +#v9 FQZξ3j^%x֘ÅgDTB}u }iAknuwU5,7 wHL앛lcm}hO݋_;Fј6 雜5付חgMtb_-RP KiN+m?q.#>Ϝ\1UgkU 6կ;Yv=6q&`gj|mo *o7m1>Rٛx'J/c>μ5_l's5mqY gc/bWsu֚#k=kuhO[rIk;}aiˇ^}6/WyzZejޞqp9h|@bfag}?+Ԭܫ7Ϧ':7|}^VmcI?SuzrZ=`Us':fd[cUxXY>׬E;{-M;?vΨ.<I?WMsؾLλtRǾʍkZ6Ɵ{mv[5uWZyf߯A <د75~CX[yϳ(֊g8ڼo #dywߑꙉM57`߯= _]3un,^Ivg|'g[؍W]{>V.rKAbXO~5`Ƭטܱ6Xp/}]|b3^׮c ُn疯1o4x<aAJ/Q/ri;kVxcJCsް']JKٕ|c+ L*BU54o'|v#b樋D_KLwq8\Z۸59WawoWc̱s^_7~'5ey;cnwjkL{<0^p 6#->KRe/6M8)>-?5LK.r&쫎91տ:kexk7B_as0/1-<wr*|\ 1Hiٛwy$ ti-CĨ9Z dY/ 9$Ǎ=MZ {?kcϧmЅi;Af7+'bR)ghՏ/P;to7UHN=KQ}Q6crj]?<'UKd}l=2y}Zg#z~XWڡ,;": 3h";ųg GOAig=γ=R;z~?7@LptY~xmFdښ̿07V;Ͼ9fB־ sZ'kz7i='3rNLL|w319s43xNOn毌}?E;:lNMٿnaCC򔮘ut/g9Vy83~×ܛYl~蓳1"ŸZXI󄯪n;3l1R IDAT!ԼlFQ#i-xpK>oGߧy{#X?iuzmvU_ݨ߻#Ҽdaef^Jy#k 7sҰzHLٱ^i,ھC}kM}w7Pܹk _.Tgkq#|flm$8??֣N￟Yjhh9$w:y}Gi׉o:yKoފzfW_ϞDl.9k://QkOlnƪ־?}3c惱NCVͣ qًվuWrWk͛;pjZ4\'cw9ܿB?Ǫ|wX,}i{wMyJLg~O^ڂRyZXળGŔ<}9swZƌj=ȭОpK=÷9;+qx3wϹ|{-ae9Mt].ݎV㝑÷/gZ,Ef/xhVڀeɣΘ۪$oPYXuq/&!1ƃg+~}~b:n>bՑgqzAެbslp.ޡۺpGd.' ιcO>%FS3N?p,guoXsh.9s7WVoU_%wr3o]cGY TrU39=J{uW|u sצ%?9orbt`]A)³2!\i'5wFR__jEjխ߽rR69 .:Гcψ{kc3,6} )_'VB8f6u+ENެaӃM)yp: ;:vVk;ߚ{w"G&8(_O_~W#oƨ>Xksums|cv& Zolk>9z9J^9ϭx/KCwϏ#pʟwsUlm볿pn3޽mYu S _/[z@YjCD5`Okq̾b^2-Yuw]Ӹ?:кwn.ϻ>Yw9FwdySkӟŸy9;hEZD]%wyWBr{i>ʧX~Zk}Lj(Xz+ߢ7b<@L_bXt5{߀wB?zÚy'gMd-bq,ͳ{߹.Oמ}.{qX]u|oĭM?M%*u-r6U?^ՄnH09=~|vfߵ:M7O{{ė٧ˡmc}$M'F[ 9t +%w^Cʊkd>u|KmZU 0sHYAڈ;|],Itti_ޜ}`}<9Oti}^w5f\95 Fq`x=Mg=1)/C[ |qv_}y_5hftC5;4we׌WybŮɜ=\rNSqjF̆3*ђ\rvZץ)]ot:7Υdu//˩٬׹}qkjk,Dqg ꫟'G6=}l,\@_ KP=tyi=͡m_xfF 1_a?7`6?1piZ }uϳzi/-K=Qyuvwk6z9d3P,A,sk}{޳y|NdNt1m}3vQx5"ߍS=6 u]K >eNWz.M;:rڷ~{]-Žp NjJ|q/-ЀcyDz7WbX XԿ =C{o{wKHeq/GOjc/r,Z̚@$}Þg\]gjg[wu97yOΈaG gsHj8|FgVˎ5X#\¶1|'.9Om_VMZ+Sg<'ÿyZbcv0y[~m;_׃j7G80q^_WZkֻf3cO ,dW2c>s[-T`7(7/q/<7>+/;Q_P3>?Uu&m4h UF$Xb3sk؟xat˜ĘI\[m|bQu"~rSJڊ{9ͻk,N(r3 Wu {7/uc]!'(n!1UM9B_7H{ ƨ/jb+,k91ky6|ˉ^n'-1sS&ƉK$\^k>5|&ک<`NN:>uEqyw/Z1S%Sm/W=ˁW{CNq+sJ84#,/x,/Kߜ~I.5? Yþj.3_vʛzE|GMKx;h~~۷o\wS#O?]tǍLcswvQblt[}W'7߬l-cN|bõ \(v`&Rh?l23{g3-|8wv6$(K}Ǜ O\kb˟|U_ ؃5N}. [ =o]}o̞e^jys/eu}uup%\|I9O1~r8(UIUa*~ݑߖh)=[E@b_yܝd 8]BqOywixW K,} tz}NG=#v>/)k#WroM|zϸڌun-tZZ ?Pa{k-ʷoky]{j.WN{1>bOr; #Ӳ~'u˫9I.gRFյRR @KE>x}s Y]5w>QPRg2;G>:?վ9%{1_9>{σӌlin9?7>ϐv:XcG.{L)ulԕjS)Ykټ).7 ycImutsK\\ČS+zܕg/9l;}s03Eȗ?;.?9+xƇgLstYn?ͱ{<򛋕|lXusM {Fpּ/Üg_3h4yS}Cײv<F=ƜMrؿ!9Twdj[Som;YWS \bomƛat9ך+~l.MC,s_{˜syG^rf~-SO!CbrGuQb}_`rwcخ51]bu kM CSתtAƏc1^8~U 4lU|;V|esz}j\o.uaW wվ `f³%_'n[3n\͗ocNUouxGks&op[.)j/,uv֕<1O33nL_-^UISh_<~.uW7uik;N˘O|j:@9 k#qI[i8=Ik_9[/q'=Uۙ?g-~+s;A߹ [hxqYzΣ[}{>FK/ NΪ{lu7w`ogF~/cqI.Gk/"ldr=k/ =wI\}}9:~{{T5Ss!vo/9nx]϶E^^w,pMli2gHz`[l*_:ں'oݬ3lc ?.xfZNCltT92Y/jC>1Z*+:\~y.ʿ\mO1~*<`ĕg5'g'k _wߙ')zQVHj{3]9>3m7s;F«i>SYtyXh ?pՖC4껎7q3O뮉3gVCp;+7sН^6;ŊYUO Tkd}c/m+X5u/JՀ^N`oskW޺ҲuiO>ĭj5#}u 8~qBr}aNCڳ O j&. zvn[kўe#.Y{o=#?.*:Qq|Ν.< )ŕ59U͏ySYmmWDu&Ҧ@辴ʣ11=4ZN 8]m߯͝cjshj"~&'ʥ_᮷' ڕPrsx װau@|SOԱ>Eeobƴ`M97.?I<2\dscL \!劣h ?ww|ݛq!؀O&@bwWezsγf Қ9<=|hU}YU{寃8 }V䌳wy_uK:5"گƋ/RkCz۹QY}i%3 [ϙ͖˽{ 98&Π[ X@k\ywY9"&qOΙFV:^Es*N"iK{+rϧ:+Ejp־|댻|8ͩ?V7 [ʿ7%ܗ1;<3k<Ċi7)r}<7,5vhtvqFFܦu/s׆w[PbpM_gk.b:11'w3^ipgW)C/s :Kr$?9'ba,ԙ)wP0Cu5a]GskbKPHUVWhW[̸\X}K ?>mO-ܹOx8+.z^NSdWmx0X+G㯜5#9+-5,J7??!غHK ~2vKo#/mƫ [p}|+~kMZRkC5+?@{~cYL@I IDAT$wȓG{Gܘ{Gٹ(8F֞5Y)e uI@R*YZ?eDa猵&-X6wfeLS<TӱܤĬ:kڭn; ;~5Oxd26 N}$os#Md{_`;Cf~qiXX 9poz9Tuڻ Wf?381R҆?am۾ZYϻ=^A/e3G^$*}|رkGW~PFt:pod-Yda9 ٜCN.}qz5,'>::{l7:怣u#>L#laA2؉:Gh~䚨g_ `++if9חZd.\Ԭ=\M_9Yؼ5fazmiۿ &_Vao'U<OG=H&}}q:c=\ͦ^߶#]jOԗ14#}o~nj_2/Z{sMܛ3Psz~lϥ3#w~h(6EyƻZVWuƔ_zf7~ϬԿu|?ZKz ː|nmM;b78_.:wv`K #'jY@ 2}`0S#~bEޛGu99XwRMtm !+fWu}Cqxb]|_8vӋQĉ߹0,}VzѸצ1XO["܆Z Vz8R?ŭ )3Ĩ6Ʃ`ΆqMc]5;B`i/^˃mbh#~lǵ>LKp;\t]s}T6ٳj걾DݣNe~ё]凌{ zý?|co$6Rk&_u#xs9a \9_~^Tqm75 14y rr'uWh 3ZKlE>nuEJ•PsԜTeV;W}h|u)xzZs™Bڔغ?Fo?iIcu-؝'xXr/oA|rC ub5JyDSB[㔗mGmc%6/n&W_K ̒b]#rscοba }-Eђ43}Łe'on!u$:ڗLأ!_b[502:<)@& Π2!zk> :~gVK&enb:imlX*O{?fOJUBg9$u]G8zenkr=:ݬ?/S+qPN{`αp|D5ٖ֘f֏>B2N`pao(}\5{] /מ͌D^=m'>Z뇏Gn/5|ci¶{O||0,ŗ\aD8yЗͅ`_2&v?ywTaf@Z?G{Lnp;gw֚C 7J|odՈSYխYֶ} t_`v駐%)?ӟb$$=Et@*b2/$9̾8 %k~9v̶'>؁v1f)_}Qe(XSkfm\= G~]yn/8ͭsFTŘ^'F`KVj&e/Ӵvą(^=6>MǼGXV.xmҖ3uawo[7Y嬹j<ש7G\|Ǖģr֛D}g:߮{Bv'tM 8dNm1'p3o~42rߚIs!λ_7a!Ć 09Z-|+K>3Fװ#Ξ׽?C˿rC61FpPG+xX֘:4M%;"@5/MI\5.|zr//Riw-61(q) Z7:8N*r:4}ƨ8ur=icB<5˧-5g?wU JnpYGHlb@GNޥx(kǺdyϽAJfёGЌ>\)@#㖱{eFԘ%Ie&-3-y91|/:QuQ\qⓇ5購ꮝ>}/gbt;:TՀF9Y;Y;o>mbh`p|KG17Kgxp ב4MեNNa3zY;sW$_xAG;R ;9?ݚ^={iH{rc⭝T\xslk}j{ӏ 1I|Z^"u(r0ʹOP!,S-dž&I9k6Q7G*_%s|co`5_|ͲnLK,s6gAX39˵?  ][a"0.y_v0vDCҸlMQˠuk-r2W.'wsz|Q+Je?KܞSC26;@'ìW<-8K_}P3[3y؊+]4dR*+31k[kb7ipeUvF3qaU:8Kuh;]|J7p~ӛq8A`hI>*5{?#iZqbUzpAJ|gɘEHqžjԭªo>z.;uc825z%pT $lܚc>|u}| ?ȓ4=A}o;I79#0Y@2i_^7:jm^fFRҤ1B75t47);@o ^ N_u=n\ZlIAͨz{+:F`c0GB3ph M{X^]AAdH5Pulb10YGGݘ4I֤7Sx];(C>'ؓ#F xpe0k=[8~3l$ίdὼI.p3WKW<]g^>yȩf9%zٮ=8ذw|CAD3_o^3#]dSS^|-]7һdlrcaȇ?M?\/qglcʑqM,yܵJ t4X,yrKOzŸ4|_mZ:nsؓYM|N+~AUzUN>L%:}99ֳ5h3t(;4X,l<3:űiդ7'Ga-buT3Eli cJ; ҂"/;UlnbyӬ.ٮgGj>Ÿ9Tw>{yQ967QWA맣` vN.ތDH'auju%~ /V]3tcYxk7o.}\ɠ\efި9#i:\O[Î5Pg˙r|v cdL~B͡V]'Q'ϭS^p{lNo69^~Ш(7̻F5k|rc:I;i~uq{vppp$EaLJ -VٗJ]SfS[xR&'u߽T'{z7E:uh F<-J;X>^[#8(/a-M1| l9ޑ&q⿄eccgUѨ7<έ>E˷a|su^`*IѶ\×_}'`]ؼ^ة'VUI`W>u9ux{v3fF,0¥}1m_Of%3U͞rq]{y\ؿi3(9yk}Ƒghgy?Oy}c];[ѶQO #xsU~짮՞ ESo0~>8R -CPjz'~ruq5R by@^+ \}aŕ~ uߘ͓9޼'?Ȥ,geyfYWBfwl`cM쾇^tWq5!*iP\sZf aUvvGl܌Q<͜.`c85͸7m] ?OP:'躹3yV<g0R_M xlt^@*'28 *33{9]WMCUX+vw=X_k}O_%?_"TKkهx1'6Y= Krᕇ5CLkMbHY4_5_}yw.8}1g(udRzś _"K囒Kv!G&隧sz›ߌ u|鈋yַu}c֘ .W}uY;E=|^Q߿__j*|sF|CX$D٣7G^o~y$..p7p ۗsŞ5.;?b՚8fZqCv{$_ {Wqvm/|.5??W:]#'uƶdd,fݵ<ҷ6q~Թ1x_[y?4a}8sq}NC3739'0Gmab_8{;^c`2~br.G1ٗomrm((oȉ-86n(^f#=fs<̓Jhi"ϺG֘]\ SAUr1waF<|5#}nzSHzObh]Α}'A" X4вWw=RX$jkЫK3S#.(25.S>{}*L[@/\XJ_@>*Hf5Sx5c}^x]6g2gqT4_ 9cUKCrsJU7kM/ӇָNL< -^xQ+|e~[۞Ųʱ mGLP1Ɩi]ӷ>^ǽLjZ:zimۼ>: Ž[z;g=qw}ï?c{Jo_FݜO9OC7k"h)uⴽ(;;:ɑ 6I|˻3舛- }S=: #{K{Ƹw97wI,g~?Gۜ;&kj~J9>?5~ Um0zN[zOղmy4:ffiO5cκE֙US{?0P|bp^zz>QP&0ܻ8K;FޜY93]=e|oMb͡rig7> _/{W,>C?t~y޲׻70ok}.7Ov ;5h3_a=}o}\<}V}6`+l] rbQOֿVwy.O}>J7;y,k'b%^VOJ7H~/K;k~s;g>Gqmm#>v&g~8gh.m-||?5 SãMȥ]_ۓ8zue^^,z--9pv0o6*_j{H/w^ڳu/ݚ_Ҫp<(%oqYڸ}.k[7:pƜqo#u϶{NJ>ͯ&\jf \67ͅ[ji\~ݧxsu,΀Ƿ+//NM۞{syvűgxT0%<źϼq7>l֡OC6'bBg %k W.,R:$# IDAT4dsp֌^4(՗(GX\1yNO@7ma=ፂى&6w·mbϚeny\7riŷ!+=#u ɻ/pl^}mcdN#}uO`5e%ޚكS 6rwo˽K =IJ5rO_Yj_9 =>nWJ&(-^{D'=6(ʹq\ g+)fz-{*R]gx ;LaKw;oyK) o*5gSG6.vsϤ9^_~hyꨚ-6z?s<G{x tDrki)muNo-5)?X?O582$? shd7GLcG`T16hz|?ѥpJonƭS{{Qq'tN):"*w?3f+1,"'5||Kc1jDsV`?f3WSi+ ;m؊K4җvYJ% ~wArxJ!܅:D:/Չ (5Pš8)ρ;6uf /*=|`^rk7?VuOy $ϳS7+aSm[iq:(71qNJ_-{UyC^5yc135pL"b/>}Mn{nA,Nx ̬F8Ξb KkC̎gx6ޜb>?0qgӤ©A TujJMHy^ͼ,ꎊN,_ّ^WZCޜ-Vc0d j8qЪ 0=3Ckf(2{@̎7MFSKՅ|e>||=a?g\JTW>!y^3RGg=+0 Ck@j*\y)oky~Mc^ZZ:tT- Jp`V#ozoe޳'}=^)\kom2w>i;9Ȍ2x͟saۅ|\ ;π H'c^m7;?=Ė1Yj]i n{_B4Z09ī e_cNy7kc|g]\=*Vsx®ﵕ/m-.=hzL: L\dş([rg,÷(qaeޣVғ_oOO=ȜW kw,>}?{cCĜNRo~hcwϐ ~Rew]L''S}wE9=[s^viyn^'/N)>wpI81m!)_9qꭱ&|x ,|@W1{!֞xB:1ֽac]`s!^ݳHRwy16.fwދtY#+D R0:B YǶ[o{pq6cc7OmƸg>m6;{ǔQ};ބ[WzBq/yd֖ŷ9wOߍV9؎F>snm{(6x(|X/_q$&eҽ8Du$7fμV3&2.6r!rUݭ 'g:rc]>rP8$P^ZrYÇF稳vWc'"6[bO_]g4[?āo`h #gsN '~W+t=rc[vq`n9aaݏXP'1ywڸ{-ŷ&BaI8,_FXq쌱ׯ__5U@~cXuMn^g¿0{㴻gV1`32g0m^0"ƽSwn^ì}ϥn|Q5ˑػWۿmky՟ȘHoo xb]oLqUr/[%P}{fו/[s?4 e c1ex3kMpAcw>/b+>i}t²{&?yr58sf|'gf}&Y, *^`<X}w3Of8shf&TױG..E[q} ?y3/,Gϭ{qokH*wUȃNRs'_L{~ 5oةh|ϔ4f|31u}7OͪA,i& zuхvzFb\~sw-[ZuCSyϊY4i\Rywdsm}O^a|_}/5X/po'jrcwd:*C އ6>@iЦGG=E8a<}tTω XիJsյf[4_';F&>W@}s֣[s tTJZDtqi7?܆>iC$v} P#{Xd^bV狦o\[{KC|Fo9+&Grsu$ws#ωC!fOl,~{  dwY6y`'{mٶ x|;N.s߹X{/DŜ_\N=̯/y"~10*o m ꋽlYcYu ?oW~Yv\;6ZvKfMbc.>UR+'~avfܯ^c4w׷&~zۼgrؿUdž}{ 楡K{nVHi6>P/}z!)iw~f;xMKދ éũeN={ac]MaS^yzz`TƂzn9?{!7Jw8_ r$GbwOX3^ˋqߺcs4~͢>o;yUx.Ce.O+C؛kT]{SǖC,\jtBzKA*wo,33IX} # c6^wNL7g<:&f COe-&6}~ox;6_ ~+{Zѐ5{KRۖdŸ:y~i63$s{.?n#AT~Y3og#"|u/1 za pRx,sljYe.OG#^|lMd`>܅-qY {N+w5g?pG 08aVS7~O2Q|s(_,>꩹rmx9/g|lsX{溱Zɭm{Ǻ63q ֛q;QD6$|?ov~9rC͡oهk:_} k+żGYp#ivb-wԹ^;ۨ[Q:Q8fpwPLsMwiw9/՛Й P߽ݚ:`1ZaelH"SC@~rAG$w+# dV9_mɡɷǶ9 SSM |۶~YPCg~Yk^]P0] z3{cb^?kbpO@t03[ִ;gΙ>0'BRdкdG2fO[󎩶}׭C^ml w?9O0g쮅@l^OՃzSCo-88o6}fu\,99;%֌s īg:Km۶s=5g\l!p,QsvȔa9ƥF(tV{v]"G>+K^0X΅!/w᩾><`׾Lդey ;wl2wis4řnT'=kcÚkdVI[ gڝScx/k# i␸ebә=^=K68\=8Zo Yx[A(X s c AWFMݏ(%*N;DVq*쒱MD=8z}`V8Pw9{><oġt⨃x޿0kSCm]Vz>? %q5YgbamS(8y76޻j^N^+5=KCCr;ǫ㶹&(ώיnMrFPڼ 1^]-͵ڙ]ڸ1jf>Sao<={+7?\&^­Fb[6 Wslʶb|"V=?fq\叠΋آ:$}K@/^)V-x*+M{(cyW]36*y9G/wzz}\G7ҷ~h63gf˹X=>bsCe}{f^.I yfuP~LU]go~f3k ;58|bx<`{qDf_`΃ctC̫ǘҤ7Jb,ﶹ9=ZSý4l y+_{{}ꩃIEHħ-<`Y'0}M\ yJ r=Zts_Уoob6sըw;7M]Q|ha`({Vluao. <^lGL<ƾw9=ys[cr_1u<́M;cR4mͻqqӖH_2{|ITĮ9OJ{hYb O_K6)KCYg+y؞7\ǰF=)={Ϙwv?5zo>=}'۞Rxk2.> 翘X{gkk;kyz^5/W_q6^=+dxzTmkvά^ ]ke{wZl+^4.kiQ/{-m`ؼډplN۬uj3oWsQ14TdvS0/`^He~ sRKTǖ ucyxR+Hsh;qYc0R;#ڜKC{T.7Y.{6/" qκF'аu`'n?{, Ƽ#k`Ԯ O{cXG>~f쑖a'V\d0kLl5^lX#͝{28c+CyBA߾~cOs7amg} )<wC{Wg%]ߋ}}s|lgNxjvӐƂPΥ.B3\r p11K}7oU)\'<~$6ֹm>Fګ}2uf^Ҙ IDATO~m-Ixq*)sa鲎.QϞl]]֩y]/ͩ˼ڝ$02i`M=_`8ŏ%&tG=99bl.d?e=ԩ~8^uЙ\8NyظǞ{u8}.mI9נ%iߤRg]qkc'&_v7N3 #oD7YhD޵43wW^)-7Ɣzky[9i[;[bQ]K49Uwִ\(.,=V/53Л jU3y wXGD̛Cg-^>/=~ioa\#9`oP/{|O\EC^w:cC;'r;o|r/r=B{ahMo^tX¿4|iLi:Ւ>̟gt%j.s? j~&.W틌֢|=[ U;F;mo9wo\3;0h|p57 |޵߳ݵ\ymCYv HTZZY[PS??sɗ΃: WBm ~5{q1=!`:7[ۺثt #OO69Ͼ!Vl>*W%1zʵ<`6>Ot (' qX/zqHf{66fp|C-w^fUky柃{Ks./2_cxsa/ܜXgyc0k^roϤ}̛S/oDf̧x?FĿkLv?yo6{۾"ܽOo%I܇[7b3_b2w{9Gk3x [Ueisl#<ǐ?_+-zm, e#^M6SBoJmn/{}$+&.+2᜛s{g ToxWN"Y\`n53M(r~c8&e+] mju{nCTRY&\0}Yݎ'<~h1[ĄxK͕3]cy4YxH1oĤ,}{}a`c_)2gs\m{96p qe|r6&xG;Fs޼1g1;O;+ͷc9[vqQymrfZr8juUX)}du?]θҊӷϰSxqy` ֲ}`_ bycn\>;W߯@8UL3I !B3:A &WLN~}oĐ;ۄ13OӘ[8avVo#b{<[<8+Gl54uXf0m 훺{gdؚ<5ғqYMH6S>0\WLu15{Nu}H% P9c_ͣ=#/=39>}I=k]<{VuOԬrƘq?÷ɱ .&^{*(1-9o],u6yE=3m8}8o{w~m֩>m ]<9ҟ(px&OvjY``rk?XO5} &t=Ԇ#e5M'v'Yk )O/ʳSg?|w'sf-"3Ʊw==3NMoc/_ݗ;PX9eV-]SƪXqox3a59Z69k/~y wؕwt7Uwnh{LXϾKCGTǵ57 }]c3ĺNs02-F%~8OCgly#o|;׃q}wr8!'U\RwoPɳޥԥf۹{@s]1uyߘiұR9\3^jprok㌩yU[}Էg։iu%ٸ\}Pa+vߘ ǎ Ma~gbtz^\ky-nՎ~]ɽkoFnʇ>p\7Av=x^yIGK%&'gb7?qmOg_؇;Qy1KAM7~ $3Cs 9` & C2dU#g{<#Aqysjsb ưeDXXRB1ĠT>/_uUC$<̓7?/eƌ=Gb/F|h36sYMg{a͹F{675~)U>5YmOdYyrw ko:o8l{8v}'IlN1kʈ1_?Y.F>j8^fG윗+r0ۡoz֯A}7MՐ%䲇s:nSQk9$1׶PվcXEۼ 'fG9RA훯i]m\hȂ|qg} ^k`nlI~z'7>u8W'ƾ<h:vָ;Sga+kmG~b놘#gkp͗O~«$9dfN0V)/{}3Iat3[ 7tJ캇tcG ]5 UcO?PT6t} j\+xlA6êVpj882͡]{;zLq{O>6UUs[7~bٚ7^U^١{-Ι[ߏjcΘ9?TIͬOQ: 92%:cnKqF/c4MBtsSmFm&qjN~}KJba1lSOYF2{cW sߚ Zo<{m؊^1 ,cN"L "ң,q>ؿpƫC v-w镏NȋUCv|t{J?f5quԮW9b޿9qܑF\;:3՗~|K1|3^6Lpu,S"ך/n-[,d+6XW;Svǫ9}ٴvrG ^yu?}]E Ķ`чw月nsx{cXo|qpWhdⳘ"U.IOjF]5uF=ۺY@zcv2gkOS9 n|Jl;orۿl2Mڴd-,fϗ1H5.=Sb\pmF6[FO6NF⻦ڧyr~ĴwMMYT:GH!b`yS5ОGk!S1 ;o4iqc/f+|Ew'>95mmKw,ܠj5߱Lݛc?g#KK͑imʯC+mԟ3=V|2Z~Xq{r_GBUWy&Odе/+<+ϘJzxu,8핚05CSЖB}x8L7~ku?a_j'&,SW#ݷ`L}Ɗq1OZ3VNcqlNL>/ͻar?#؋M͙\ԥ}asOѰL/{Me,*}}Șl ?oꬹI9œb?v6Y ޴Eǒ͍A~?v^<mSaV$.`gweb¿q9ccG|+Xm{(x_11$>b֗6(]o{᥅jΞG{O[X5Jco k||+hkGi'u?Z`2X+>Qǐ'w ,+w:*&ͼ!Ka|pJ_Yb/d4k؞iKWg8-*mX^b_J%0g _ıϬ}o6ls{NsknZ/g>%irRުc>g~ba {14׶b٘`uWKx؁xgf´;z1[6~;4R.緛4Nj4ޞlm/N{|6\('qe.`+MlP- Em""fs+ ;ez^w]Kgj39xQZj&vӀ9lsl=`ךt~FOy}4.A\gXL1}Sx3ޚO̜΍9|ρ6150x1~+{_qUvXbqX#f;9=^yGMg?Ջ%鍜?ͅ;﹀Awح1mϽJ5x9k=HJ3yo|]9s*%_v^;&iϺeEuy{dūIXѮNӞ 꾅 n9z\𯖌 };~lvԏco6yӝRYX',WOe҇ kֶ^uoU]qw-GO?SCI IDATky`bI7>׸o׎_t\׬xsOɱ)-Uk1uD/@<ҌTӻCМN/ɯ}&hC弹wk(^U57&8{W\u] [?x'Y8Kޤ8zA:]߶XfoۆS&. 8l_ xDHqfQ$>t#+њQJnEZ%g;<79R[Imva'qCg֞}YN}¥NU^=/1\ǧ؝GZx19EMA>^;Gh[k5{j?0k}OjU+N0_ZH&%qoJaGC9Վ-y!Ԣ_$C&qD3O̎>sS5^:uؑ]8r-~~l[OQPgΊ˵4}-:jn[O/B^^oN7>&i椦3ݘtnS[jk ߘ8_mJ֐y e'-Բ,YTÊo +9Oh]g @mxQz[#$'0|n!ι*pY:e}hh7re.q ˧|*]DGOMyױ',w6uk979u_;/p|#~V#8Zҹ}OLtˉ4T2yj,]':*`V:xiaڱ]EOWGhWy~aQ?9ၗȧ PU .-"DNbOx+\sxlp9kOnʼn?yٵCYg}^7RuέG8wKhT]-ZT| ވOGxq]oJsVU9kG߫gLwՎcn0kG\r=Os"x6ҟ>C*w͜w1 _a>ab3}86nNM<ޗ3Ƈv|hw|pʩ'\c߫&1(0N҆w4k6tv-DCCʌ^a9Fɟo$I*rh`E߄iWG\{O_ ܹO$mk:y;t,g^`ì1F{ꌾ͊~W=ݱj O\[>+@p<֣kN=?qS?Xuu.ͧW0,tJTDQ_.-| }x_:lxT|gp򐓿RC^Zq޹|zOͬMŅ_F75fSj:S_wkj\ |Lqbװ|uO7jCw,8%~ u|$3C\i;]8Ĥ'nfOP:MIB{~Pv-,ysh.7]<:7:k~cV1ccƯڨ]-\p%Y4dX 7H31*$8pFlY+|]X0 #* N =X.zʮhǯZkU_p Pv4s:_5q]owāwa&vp<?j,Ṋ҃k_:tX/ڏ]h/(2ν?FF?2ھf0,=%$O f}/?/,e+K15Cl:Ft6cwfUp|Muܡ1W!Aa_ ޼ g;m|ЋI)GI?јaߵ$[tX5Z<%ƟAS;vrY{i5uS|Z}7_9]=J}4Bg'3ǡO6s|ǝ(u-) tIMZ7po4=K.͠^5g\4QUsqg5Z@V,eqx]vIk'&S.xf.1;UnQGszFl>}HVmQB_=hߘJ~9_8>lÜ\:NFڱi?>7+ ;m@Z83kaa>w-2f#TJ*]-x k-5V>l8;A=U`Jх&o;/+ciw |IX=0GWuEwH?X>v^ޮQwG\_/^$>j= gLW-Lb{4̓OZ eu^ D}5\:y+SVLX=h%[v⛡K !:r8뙧j7l10qfuKIﹾ8aZG;o'5|g<׮u-Cv]F\Bo]/ڻXE\>42Ф?N}:;pz\ ~"%,e`^瞾ei/"eQc{_jVYALSۄ*q[/ Lۺҫ2SawW_Go ȧj@㭿S{y+n܈궫mw/BԹNgR0wwϋ +ДI=>P~xoo^՘g|Ϯmߚ9bDh^r+'g?=*&ſ>U} ϥ<Z0]Ժ\WBQWZZMޒ3iӹ8Ԯ;[8ǔ~I|Eowz+vDGo§6+?9iY_zo\Z桲;9.M;xj8{+8s^[g~WWQelAѶ$3Qݺ>9EݽrF\ytDnvɞ|*uZivټ454rj\kScs!!rALڈoMxn-s֬9Sڥn_ɣc m7l_JHt?k ]OsF񳛿[{I߱! qD z{zKMy%_480p#[KHvۛPDֶp.h>1Уt~ŘkZ0_} Qn*g~u3= O͓j<shw 0ғ-٥n chՄ۸A6pu.}/:|#NEib =!/qRϰ"ysw&֫ Lu=K뭓jז3 s'/g{]'ƜK yiOMr((}d"$oq˒AILSkQlYqKyS;>i.V.SGƹ;>: g'Y>= wLke =}s'319wsҞ5RC8to_鯱zVڨ#8X]gGݫE]<}R,<|4zԨ?rsO*}} c7.jJ;W&gZalZ{sHq~JomJ+y~s#Ѣ 闭Zz33Zh}Kݓ\ U5tms]mFwDN$im,|Uwjڎ$>=t=rQzWA/rlK`0`{nM/EƐw[ӫ)f\r k<(5C{ _6u˖,i}Q$%~R1zvprGFTNjSTBos:=$`(FV@%N_7x-Wjc;˾ˏ/N򥟟OYPGpwg/S]|Y{X+Y絾]ՒX!]rKuU6:/=+WbFʨK*lbљW. F[kKwpL=B>[?8˄Ansܿ%^65HN'G+>ϩ:xڵ\m[ʸ~С^IcFi.s桔o-ŷ5}0:z%mr)&mn&R?-@}X WHzz١R5g4im򳫮۹~u7_L ]sjדd_\~ukI{%DŽFg"K %E|jrzfHDXrqj5peEK}|6X3gAܸ,ǝ59|W9Vѓ'KlsP7!ZiLjךZ~w\pL#(3[ruTC-@-ɃUZE>->>""3;8Lڞ3¡<0p6*ޮ[Oooĭ[-i,6!>Wza%&+G]_gjMu{sۜ'BvW5:=uvc{ ͯ(ydo zKh/s/57.ϠUŁz33a]syc}3O3suO5ԒOGq4Er\lk}j%wmsy G0OSqjV'h7uZlȓS<#tFNbVvcb?4K;sWTNN<3pnz8w΁aOVz >ss_37f; W!ӜIk3ْ>kj^ĵcCƧ]\^_`ieWyG3;ᵎ`'[(cBHLX‘s(MDΜ'EOz\=l|OXol䙼7u ɐ͢7"^<'\w|, .$GMp??Ap=M]>4\]3Ϯ vP#1\+<1 䘚y&'gv᰷Ν|W633V Ǝ㻿`}^Lџl(XŴ/wcO爏?G]gz}O:=^fakX|~?A(myF1ȥ:JׂǞ>x¹o?kk?,isʂ3u>㋨C@|g8>'OqH5Im?́BWM^v@^ypBWPW\aD8S^E~׽|w^O"}& C+7p3şd\[h9nۜ`7l? ^̔B~~Ԣ>׻xJGseQx)%]m;V4OIw3 7ps]n:\6RqC=ij$ YNp8Z'4SEpI3)T|^2StU])ϻx f@b{.[FDv=#!1 @>˸kuMDĎvks΋ZI~0bD5'qV7A軣mÒσhvl^mj[;zRcgO ub{^g̣nR3F'ݴu.?WBf4CNQ܏,R>uڽU^6Oor1nCSPN{sFuڗo0>\}\<W>WUG[j>^/>dm/iwH,9ɮ\Y'843;YL( i,<6+?%}jeԹWZͼ]3*(|] ?ۨͯ31[0bw۞~fX IDAT{_QO[ѬKg%W*hm}kԽ/K޴V^i >cOh^E;TWZ4dޝ\97/S6R}'bx쌧dY??'LvډA[#^IJ??etRשc9We{^ 5rp|.)lSXVp"~d+PIyN+o \'Wv~p=k63wWOg\HtNpe{v#-@Fxskͩ5Qo뾂΍eu\Z¾h:/G~4F`wE~Ϊl`N!r4|. :;$zi9E=A+q֔?gc&V\Gd +"}Ss`wf-1c^;+=k:L.2K\2V?E%mk͐=3&ԖQ?.>W{{W^*ըX6W:Z:#jμh{F ,/gBSXkhٯwr[Ow9ǯpeM85O%QwOL*&?A%  {Pgz8 lC5ѐ?mpmJN-In]9[K,-4zYeg숏Eά!t\u֙L~m|, k =(v8Q|]#sL|heN`q%b)BKA@.:lOu jg4nמzfZDuoR^je:PzwPF>ǖ}ߑwNNiy5}&^9҇S5CMLB`tȍf@.:X;}pZ뛑zTHSF;/TGJ-~>q*ӳB=ٿa7kGNpixtlv!ĨAglRK\-J?V$C)llypp\Jɠ!O]:NroroΦ˼Y9. #F+th3uKZK1iKkC]u:b˟'kuw=ugma{3®b'W٪Kׇ_.>vi3W(o;ϟJG0]=:g HexE$:}DfP/N|:Ypϭ# go>穈 mR`+gEG>b /{5߀L̕8F yoA?~m,/mAߣ1ҋq/U"zN>vi+c*}e~ٜd럎+S°dғ|pm_ϵZ;;zޙc͚dg]>w`Y||̡mIЬ䘰G(.)j-c3օ_ܛܙ&{k>EZ֯x|Pܗq<|5/0 kg!}mO}Fz:4z:y|'ⓣY6,(sڞ|2I C}<Ҙ;^>:9 GI'Ze߾ofեڸ7tkPd9+0e]ǮHڋSpIC5-[ lࠡnnk%r hz_~>.}.P6?)\tM5̶CL6[:SBe;1i߼s9f^kM(uZ Sv3#;/2'^[g8o  x9Kv6f唐)Vt.Z'z振|po4/k)UkguS} OnvaГu܉OJ~r4҇yFLqoz|(">1s/nq=BGiV;xcT:gs?S_->OoF{-]NK770*Q$gZ[WoGANyC ;*F5শl^h<8wO$c(SW|d+\egM`uOJK;:R1SxD4gB]ک"X5"-) --gFQ.<;Y|Rn-p'ʐ{eg'#|.vLŨ[Nr]3Vܳ rqV듂2+4zvxk 0q^^H7_ژJ>. 7gЮcDǹ>A_s]_+D4L2^~V6=9YpZc&W+NQ%ܯeN]J]b®âj!b{l͉)yKNfwN#,gC_ Hm\[< j|xO\Ǟ#_Wyn׎O{i~ j;sPo%<)zS[ zxsٸ,k>79sk._I=ɩ=mp\b^ny735ϾONm'.qӾA)8 ޫo!% (!o\5oIDg|b_4 Cњ+䨏Uc Ϛ,_lv~=-fW>r[Jc\ñgfNp uxFG)I!&_ޭ䨁SUi Yoo'G0i?v-zh63izv:u hAj7o>`؝|#'̽8yw!W-Ao y,gDxM/!g8`u9aTnU$RXųAϹkS}z?2а^G{ӾcwĔ[e*WMo@# n :?|W<[Gy=rR;8\+xT,q}aRCO`+Ӗ!h5c[ V{N`yJ3e;ϺꎨFJyylN`7&/ڪMڛ3x熻ok] <9iV2ơ߹Oʭ?u=1z츦8)rGwܳTH-<$患{d1긥!οR_8^\9uH=tW[O<Ϛ\'7YD\_9 g4WxҾ6N殶YI۷Y5 s@ 6y5/-4d #h}_ܩzޜ0O:Ww/i'ģ{<;mVS˧YTfqMޚYKy܂oo'lrpGYvׯ)&-Jz;i,|:K\sI|f:蜾G 4ѽT~toף\=n?`K}߻^MҽRShj>9`34p:.^FƇ>Y>u~Ȭ󢭈hC+$ݿtVRscԛe=ou^ڞe76zl٧ҹ&^*dTω줋=vr5B[-%o[;yۿ-@"=|oϩa>ۜ;q N5ڍ~Wű\ZQlYh>}9S^5kQ;{_Rmw3cOWCա O=) uބuahv>[?ھⶦǜ}TwꜾ  RV[%OYZtUGg O51Io<&ن<孀}a\_K!꠆W:ӏihYLӀ&a]⪨">lq]La{_?d}fv'8"]ҵY>3K?jo hzsI>Go&o$wW^^iObi7wjhi[zx%^ֹ므zү{GOMHOܚ_"un*|WB_WW!!%kR磙Bl @&Nyҟuq$.92\}q>^g!Or.L{8jςϑ|OĚ4?KM;bBG^v⻻iXCKS=Zgw~Yl'_h8aG^sKeoוv Ñkc7d9Tu1f-]1}. Z;nSug=4N.XC)PS%0o/1à 3|;7arrf ԙy[pIO+qY~8Q3-5\,tldT{`;  g\a({?h'[ȻwnOZZ_wN\qA^\JЛʟJ{QlJ8{ykj^F@0r4sչyV֣\soΨz_\ :ݿ0,d %qsi@ Og^k}o!RK@5gm4\k-óuxWRU)>ًE‰"mzC+,M㳶d[0c:uN(5P>9:Ӌi*LMίMwTfl^z]Gkȝg4C,dz<)ؚkW{GW]blԩ.ΒM/ƻKϝż=\؉Έ[iM}5a|RF3/l[~'g(g.ymΎ[,0Z}uywz:J 7l𴓇yf<;Z:aZffygӞts OlV{szհNôo#l@Z~a6{v=to,hD@dLbRX1TEn14kN%~X}寅Qaw<6oo%}2WrG˄9aj-ph=lbMfq%N֥xeGvb#[䱶khߖ⮥Ԣ@ʧrnp̡yc/)2}J9nIoN=̱B2k'b@˜ZKv e:USK}T]%B¶1"tUԩy9'^0Hg/DzBM}l`\R0 7gL<~aV|dhi/يS?PVa3,5-?vtE;DƩL;WE?qzwT;| W~!3A~by~#qI:#3 !88vQxH-lphOMC,QVb:{xg)QO7ߩ<ȳQq|1)ƓSg>=ygE0_ ,l׏u/RZ+ \x(o=휄#';<1=;ퟁ<]HQj诃t_?65a$nkgcFF=+>j_XcN̂Ģg,ȥ"fDXMIei:BSvc~ &cz?mq%=fWod:7q_,zcΩ V-K]rH#B?Mz azk5c)~tGz幵䛏AUz[<;߈=_Pdm8kGɯW_qЍ<3]gegݾ~+;O/~yQKrKW~j +AtS=r֯yӎm0DBNF.i m0]wzUGjK{܇ tPY? ԻP-EQ=aT,a;ԑ9ez9Soț_4O6Sкs+S;G|~3#5yZ?h3B[7ߎܹ8U,3U~F#'|e:CK.<|>/\v.W'm#ֺ~⎦/,5YyYw N1ӗ]S.5e m|G.r\U_KhQW;boUT^r~SR*WV7i]^L/6O?J:;>5AvGW Cƻy~90OOsk?wd|-+^jf*ֽyFܑ`l;=o{Fzr<Bq8/L✹0CSGXjΘ덹W[Xsن8s`笽>9Hfyq;s"/q3ُ՞}aC3s@e*r~+5CfbjQoAC7-S̓:t&<ڱ[.z}`ëӛS8=G߳G\؋JЁE)FN8WemU GJ♣ϛ#Mő: Ċw@|j"/l>ĝKaгvW:cTKJsj1xڳ)CXPj( ߅j5119},bNU"ѕCu l o=q|AŇv'?]jh݋ӋrmeA^u*<ӕy: eEH IDATpc֏4𫿬s 1qZ؞}fd>[:&۹+h? ^4ز~0d-[ެ:EM9.1cF`{+h4YCz/AӾu-lx_''Iʗcu{?|z8Klιu^ip|9~1\q23R[kb~直d{.'IGݳs檸g&%r`yW+Dv#\rc?j,hÚžG#o,1'6p>nKGWMB`4W+q9.T:V\U/ch&>9UZuT(kY&{H4~1Y᪁yTќesw'c9`?0SR^5'|ٟ9Ub_N 7>ꢷSPĨI1sGUL6xi?qie^x=}iuMJxD8\| kSh֗E~r. G8>Zɑ&ZRM3E#bı霶j[\Wp8})[8 /ƽ3/Abn`f`W܊/=|k?$'Um<֬)1aAu^?ay㭹_Swrq*XU9lSMxUIY3U:Fn>Zm^yrNrwFWgp!ڻ]z%aT>9'̫c ڲՄve&׮NC%Qi%5LQgv8gg|s45&Vghýu?OU/bSCy}4<^Tom#~ýum]GJJs]M|,{Fg|ݙŚƾ3to0A޹TL aM<^7Wℵs~fS Q1ĤO6=: GnXҗxls~Ŀ0*n||}G;wx%ի5qήykyL~h:C>9'p_xxnǖV^r ݽ7Ȑ,.P:+\ 9/946. {ic=Ŗqx75|Fվ5D sa=_<#8y#B22ܸS;3?h_5λ}l\ש).kͼ:7R3bE_X3|cn<$k%Chp;\VQܬ[=K^v7fҢ67we:՝ z'm#gy^\![ﳶ90ݕGc7ߕ3:705AG%(?(Z7srlg*7TIմSY>0oM_H;ȫe?QKs[C 7x&ޠy -p, `SKooE~;}PWzZef15tN@&6+7p_?ؓWӻ\G^NY铝gA'F{Ѡk}^f~$S_QEG~޲Ol==T%_ư݊ro {1FCMTl`3=Wc{PrfO;ujq=> FiՎv˾;P=/w㮏ܟ8J?Uz!H뜋y]yUVO.ݿiC;k6a碼˸au yGߓs~ϒ^^ӗJ)V7w1 g,} o:զpprq{|kV\Ԇ?5s?S.?}km̶0zxOX׆$jA\tg3?>Gâ/J5z~ó( h):Jos!N-ɬ! :c|Lۜ%3>(_R B+LEz}y桜ox}:\|_/T|O䂁%=j9\5_yA{^<6CO~f’Qi6}XKՉ,osqm>n9NU5ljgġL;8'i9s朶8?q;1MϝW;Cp;V>['Syߝk:staɃ[oL9oΈѵ ] 5>^Lwb޹Źuj'_NVq^P!\.-qMGNn whs-}4UOZoGY+>YWCz.yt]SKy#Sͦ98աV$5zOoM7,uk|.̇) |t}bAgUmk'ZViȗ;7]K~J~JuyrUu2#n$*84KZ%[:?\uig4D9>+هJW2y.c98#ϗ{g]agN|޷W +{Z&^W̮_:Gkn J5SOWr6L1'b,R;QN{ZmTsΝ4n7vgVSEiܺ:rh +#g2-㇋"h֢n4p2Q,zKkO>#G.|`]q|s 7G1ia ыWNoq u S14K :Uo"w@ tnkwQ <ˉd0[]yH򳛿zNk@?9j=ѓ?ci'q9t۹9wuklo 'tU?q{_vε7ϝOoYb=v Ë:Sv7:o$Z(#fA]m%O,Z cF.԰ԴvF/۵8g=oL|tйY"W)][˥/NOO:j8;g$p[tCAgGon1J掵Pӡ|;F$Yy4u= tT[KRGCMV#T=0,vJE/xK=4֤ w '>#N䕞^:S DG^=5{€w$_-K*\zyvoډ&.ycL>Gz%-N?.K-uu&mꔞ;ңA,ZlߌuxnqZ Wשn!{}):ёݿWgOqA~׶ΑuvEeV{Gg[{"E3d_*S1۞3|:-gî9S;qct]{dV̯:)450xP_5vG~~cO?z?wQy)T$G::r*|WskY]+÷>3qӦ^|8<^df'Mg /OڋUwNQXjr9̅!v߿ px/bg.}Ǎ<5+w8vވ"M#fw|g@mԨK -KďC{1#T9:z#9v/(Hb#.jNwlv BaOl (8Oqxb)z^U^QwQmwY'mcG|3O27?s31oNyڅzFv w><]k7Ԁ&CVG֩g˿Ѷ5gu55fZC;>pǾ?QIٺ\/mY2&^.b;3FK9;krNVkmE4|s=ᶯS.}lU<>WTڞ8n<ɲ+ SpMls-N]sKM;S_.}BOe>ͮ|QZ=nӟzzhKjǎ*P֞YC]yל1 C_)v%,cƂ\p=9k}#plz2wwa}hAй{։PMnkPOs4CuRc5JJЗM$Hidջ=Ir|@W8Ũ=I+G^S(Ofn:g^[UԪ,9]@r?q ғJγlYjQ3) ,s@>r뫠ɬ^]\|Ӹ>Q3\ !gǎoz'iCZEL>l Խ[Z,1LR@\|T(uy?؞kh{qG |,POF9~=Cn?ݥ7Իk|vJmL ,Zpܝ۟sg.g:4>ѬZ)[bޒ^ދ֫p [˺=_ùȝ9ל':ByvqW_'k!9cr9 u)fsɊ7! =sǹw;+% n馶(X_*bYXCT޴BF&'EjWL/+ǧ]zeL}߆}+9}m^Mx޹w _y8ZT[߾2wھA>u\4'[y j,K9<uLjYyx\A΄GCK>zc>ܻvl2՛[c:wY msKx:”<Ԫ2~H]Z|@eo!9;=nNz9лw?ҽ1Ky {f0yHN]/W.֜;a[h$ώ_ |%W*_e˭}Uމ6&QtYw!z\:3k7^9 ;FLʣg)ǶՔ޶u&?FċG= e)~pO4mFw_rZiߜ9) N[bwMߘ(|cjvoݻ5*LG=c v]{sNb+Dq`h]#ݓkGRר-k0G:ԔL, -GkP>xB7* =u|l̤9[Ʃww n[q(Զ5K5.fBL4lyvuFLwnl8JM٩3k3bҪjֶ_.zx5EwZ;I?}%V9,km N1f8d׽&| %r;ۘ#j=Brg ?qlߘ4a3._O8kD+l.40-j{`O w{{IowN_ʂY<@Yy_6g:{?ab]Exzivծ<i:O;ds.Lڜ=N_ͳN] ]uK8YvqgR@N:;fr4+Уꌯ:;GqeK vL8;mܟ><ȸᨆ[{1 ϢiP9E>E#6?8Ze:僋. S1~ӉnM :?n,h-.HyK-~k61}s'^9n|v&癕Y, ^Ĉ㞝GoALNK o*+j/c,3Iý5a9;q-4ؙUSqPҝq8Ռs55۸BRqu]>-Y29ÁGҤ6९Y{ OvJ޻E-B_QW 9_v?itk[Ϟ4=sro&Rǔ9XNR, לkv9_5jn-=(xuRsls}N =97}6[isgnz;="Gdy0#z}b`%/_;ߍsW7QAQzB{5&g.jeZ;+OԪӋKf⼼/|vՃV4/sOkД:+Ʀ65R/ ZcMMUѩE>b͝#<3&PuW~j:SWyZ׮%L߾3+J+^6WIY?5iy2&*W?o]hS#;8ų&!r9;ׯs_Q> {oÆGbOo*i:Q+ygl?tFS>nz5pnjҙRxFRk9Rs|k,ьصoe{ g^0lEU-w=u ELb|:~ \ ',rg=׽ OT<'_e;ۃ3W{G5J@ 9n}ggzy/:+>Sv O<vwG{ڪJNo"NX]A101@N*͹D]˵Z_ bWCS' ݳTqLOi>-;4?_#LlLŌg]rwzk |D\ާy`sw6H$v buN7#;;H=pdwu=-s=$d|'`F]g~n; vN֌BMw8Toi?=SK=ٜj~}7hf?ĥy{&&cWѧ3:٧MKAZN.(-Vcz[o.iƩ gCm@9߾4s∟~l;XN,pS}uy3t߯];Sv'3U?Ky5 IDAT7w(8$ڻ},eϜTAm6p [*ěOf7gѹ237ވ欪YUkC5ߌNxs?\+ë )gh\Z1|o* cr_|y[~~~'z}̣L|fr~yΦ,}j0;+OtxU0sgۘuuH~1kH6Fm8-b~bι신'/pL7N?|t[}ng'[8g? Mkj4>d'G,wf 'ˮfsõ}/IԚb|rn 7V[5=k?k׺mWAO{f92qP'AY;φDV'1ؑOO=_}l[CA\U$W,>ƫ~"Ă߶q֘:'w4'xr9k=Ѹ"3nEKr8,6] ]cY/؀ϺpkЫO9gL9WyB45;2c7`?vuμ7ms}S{Zg3{m#o'Yfj8oֳٗv7BN6ts`*P{ix|SW9zq%NTtΠ4Oj#ޚSEF 8ϐ01wNg?u.۵ęyL'q&gScpu{.χ70b;3^%xξcw`X,={M"C7lۏru})gYP =n( w/sm G,mol {6aZ>=89.egCifqsd{3(XQu7ikoɥ3g)"VpRz(N?3ۼe;cPG 0DXs6)Ԃ񋡩<joX{͂Lݏ/+Th!aA$/ι[r 9s mIs)7=(k#y:!߼-C"}8iՕyy繞 ?ƕ{cX9ש}[h1ONv+RB{ƹ]#fmHc7Ou<`iob&z\7''n`B~>?[Prw,c s?[# ?-ƪ licO1'/8t1I<5ĜC?urݞf~,yCX\:pD3J Rv L~Mgpg7hؚHZD:z=}Xה+*E}8uWٵ]"=$Y;܋}bN^63u̵qٻUD[:.oQ4qPw2a0߉ڽ vU?jG{wOBKPƯRзɯgo\zbFEn[e>$nmѱyh+)=捑0eOSo;B}$!hrI^N@ͺlSc|bo~>r=zV_w Lj4{Mwp,7|aL݌e5kgN=:hRa!z n|jS.WXfbo6f uUV^ܞkB{C>1y#ƽsbԕZ׹W,{UqGݧGJ@y"<qar5zxiqOLq_%FNZALG3 ^RM-[mm[q̀kɻ}.U+}m?7Άm>0>.ㄽԆ@9>jhp!ޟEra<3{&: ެ˴gbk؉;N^r'o3t8M޶ bef?ؾ7ͶÕy}o؞Cq&f+ >ğ|kw=CZSaWS.4av9;Z1wFg{.Әhew|!6[({B~>H =\Oܓ=TX]O6<ڵ& r!s/C7;{]]|ŕЮ .Re@81=b`i|S9o|aN^pX[Vo||yG3V)ǰ`h=CMW]&;~y=?^(_y+n`~ 'O(L$~N!'K-㕳bԉh8QakH`.F䐽u.6]vr#IyP>^vBbGX} ΉIP74س9oO icsMι&O`7&]aZ /1:{$UtΝc`54 tJ0͎з Wߥ s?}?y}z&V`{q}^3"N_:~Y\S+7A]wỰ"r;oeY35_Wunܩd<*G3c~3m 2 ŵȌlv[I<>y+g,eݶ+{#2qII%!u~j\0s 3nƴxkA'Grr~yjqE\1Vnz0F1*bM%eN\!|ǚPbm]a?V|o4v~;]b8< :Y҅h~}ԢcfmMq}X7"u-{5ǧ618 qٽ:G NmOЈ='jrM쌱ggRk~'8g}^oR|0e=#fpb3ri^\x1ĸÌMny,]l ^1ٛm4_[k?9簶^9k%ferVxs6{&{V״>u-kgq}{cFͱkէA{6^ 36ge7'.'__<9~E7=RC3sdS''M-jʍ6jt&rƜms,u2q vu0\9p 1?قC On] 3kgT10c"8@4wB=!\SK2Yv{O`Rӎk@ Zii R>갞g5Ď]I5>RcǕa[?0:=? ʁld0b{gֶpU{xv?st5V+e,@'\[FfUO"YM3yXϜgh:MX.0x#ۼR.\6VvhC3`9u۝iK3f5cz3&MyD33ާ&ld{OyXvrOg9|V@utz#6+1{ @|UL=s?')p暱t8mDd^Јnww>1jދҕ9pE~uBk|阼9Vl1ӻ/8ev}m<9O3c9:ossFWlVwgDnp#9++mwiwǾrׇ1ks!\øКvs ;›ծ4ZXBW F>5af#G9m.J1a^3۴x=m|V8h>ky*wF/V/8|sKtW{m*v@c&VU Vo"aӞԥ]{W>O^Kz-Z3GǨ geaW;g)KuF;YF^m\֙-f}U d.GQ;ز SUffo1 F͓(9$6':#+3G?vͳ6T!/iԿM[g0pe'/;ro|̉zO)ZSsw΁u&>]#s͛Mt.B|T0:V>=ϕεnVRcű+n䊾qOtsjߜ'C4% 6bاƱq| ZcKW9C^K .ny'Фf|͡v1|gwE~}Γ|l԰4fk58E6g}'ucw/:[1XC[LVWL'/$}3DZ{7W-r{}ѺR[ëh 3^P_0OY 2 9qj97~wo'&gޘ pp?@ Oy^/Ǜs]EԀ碞>^9S9R=VfI͆a:"[CE<66g?1ޙwR=kѯ|rHzbO\ucgX`}h'5|'~`[kj^ >1z0v1Gb|{=u`OO o[/Hꋑ&νXլ:O.;ZN[ YsCwZ[_tnr:Y *23녧/0ޟ$ Gџ0O:ǵJ6m]=}-Pr<=Wk6y1`?T17(A,ՏN[9'^޼lk_ኍYs'; ؞T-/UX6"8 o|GM{8Ur=@z(r^.8 /=㗀U#frT?J~~Yo5){]41D&<-K wy|rέ&rO͐~_/P);Ŷ gyШ%xpǍ1yUs ;_—JY.Z: ( ؞)?Y |Ow+㣱~1â:z vxϺzg)e^'ԯoƇ#rscLPsl9/zye)gy6u~bdi$X0韀ߎ}'(w<< ަֽ j+k>%tb3/ʬ˛] 6o{ |=v3'3^p{j}:CA}gVFfbΜZX(ӷcVbcO }f|sڬMxA{||;Kb/v%U yNܱE=۸~^9{5'y'Z3Ƀ5WFV<ĕ_c+ƽ㣖k;qT,gƜɢH5k^f]/f8ˑuڜgvNq7Z?6 AȜ[28U筅ʹ6f+.6f\ۯ@־q_?lysr%<3g}XJm ]g='cuqKr}g-s3nhcip{rU50dܮݍOsyњiBWng{3 [!VNҳwC)@]jݘ"״lJc򈙏bļrs-1ֽ5kƱug~kFޛg_(;f#w"͚\O-lr1շ%z*kݵ.:&2=~}ycQs=MM-;9&ZWWҼKX ؆O-ʺn` ss?h' g^r4ɽc [ ZGgIîiٰZGi5?`pĨw*~$zyW|Ra{o?[߭cj,ڜ~Vǟ|AsL3>g$Q=_Ƌ^memd`?6}}+oЕ9ߑ3ߜXkR;Ee5ڸ7rĿM4u]1Z ź{ #6=fD\%矯#Ft}7JĥS[k]Ѷ]-q ܟ,ZgM\0牟^қWe;>qցag̈UuWP8Ca\x;Tm'l{mƳ>ej7jkNj&G57ߩb3a"9cK-GWӎ{ ٮ2OGU&bctlHq#x l{s"gy-0q/g>:?'K7є\}!(im>9&gzv\9sc w^뼈8:>|˾G&h'`L̕9pu]ρeqls -9Scuk 0=w^ȝųֽ _=}LjG^k:Ъͷ+~b ĸ:bAfk5b֓\9o78]kSQX2k/}~tmNY貉1著iX\>׻e;:Qw]u}7PMb;n].lr?OvϟN T,kke\9o<9|Q^V 0YS/~Ed]%g}SǸV>9쯮O{ȫA@#ø0Ck;7"hkqc6?b1v5ĮW'μ163yb9=ݼAm\U~AX0 ؓc+{o{'4?q>z8.Gz~ܛ;]keüq\jSۓY|T.i1J贅?\ ^ͱ_Ϙf- SŮy9˜缈o,uX]6 5/C'F~?UȞa+Қp3ESAWnp_WZ3/9|"qm;席Wdoȡ>czsZ+;SYCǖ}-jϭ=\7kܺ}[|Xk?w4`}˯*;cǮ"ݿvp'W5v`5rwuؼX(W۪Zpǹͪu(ѭXhm&q Lw$nK.֥ƖEۜ?Qu ,Qg.CIJgj_y:rJٹ5{yI/<)yיկ"ؘZ9;xO 9oMOA_;%%w<+\^\\p}'5xc}bm=;nDxzx[UET|gr5Xl>0ܓQ~m K3ݯÖ':y7 ǫ.9ـ!Fr,Ċ7Fϥr"۬游˟NTo87^}Ͻd'Ƶw3z|ͳ;9k\M}gyf9hc;ws`_Yùrkjz;\g_i6}_̅9cg=X\`:Ovp9=yDG5bDm2amf3vɗQ"iաpgndc""hbyb`kw 55NkOfƈi/ml摫O~#a1W]R7v"жـy3[M?s14r:7.rwoq?q"Wh?TxHWjI0Fo>sl@8ɑ{=@9Y 5a,6s/˯;ͤ\OpEkA'vͨ؃Vb=CԠvຨϼ0\5U ӷO#h5e i5K.zBeDT$,76eީd%$+3>pjbޘk | NsFFnO >{5͚) 71W~g0s ̌<3륷r;:,"j.- s|*f3Wu5$$n|_iM~k,|>#Ϋ.փNEqҖ՗Iދ7Cq~jm4v̭n\7V z^'wuByswb51+IU)csLWbb1o ]h}I׭xk{rE<3I;v|A7.يqas|پpx go_!7*p.:,s\ϘyFoNV^|[`{jE⢋|d/msz+VvŽvp~,/{?uT|0s=uYSEx+=%vszg~2wR;t/?:]L1q:~1;ﴏp=9-^O} fkZѻxSzݣO,5sl.fyz~N?*\nw6 㼗FO+ᡜc}You! UkZڨdMqϛ-ek%ufn`r( }w{ot5PGVsnYd<;'X L=q~4`nm'dpƴ2>;n^fQyڐU"Ǒs?ձa:[gm mڜ"Sv KbjׇYƑw_n#sii=ƚ {g-G7b&f4NN11lڝw<1r]:ڕy~l;̋k:~}#}2Z"7R[CJ7nj-l4}3q3׽_qN;_մ _icqj\jcN4;ĸv>!\=KciMk~W_wZcM+39cX5OފopQĒ/5OgJf$"cQϞk/e5FgЬOg&wXg_Ld9BL=s͚]- z :%9HT{r!V9q惡k/\c;ԑ?{@]&`+1丿)>GصΚԍ/xC^~j?îeqNM+vGC^_8;j7GXcVtN/58=we6qo^!朒Y}`w85g 7Յ\?Lzc RӜ޿{[=/kAwccH{4'hǽ8/q;Gb~o U#_<:sϞΝ3_vXWMh{U{s͞MMf1+R<.ms}ۆ& alhn9;#o'k[tiOj;"F׭W^.L?G-!+_QDsOo4tnKby$,[};*~!WFW_Zom<{0sPnOMkk,7yKuh>/m>9{[57e$cv\ծibdsI,t%>RC&ׅz鱷Xݫ=nGUSGY!^yn/eqZ~pΑr=2#u#`-C ܑ^;EC\0^G//F^!9?_O^?Mٽ7bOj?9^]mR:{~bȟ vbC[xx.Eoj>cI 8OVbgQ, _ ux^gfboEpԴs~pbz&=,Ya YovW+Mz4-"IOw@] λj}Z]=Vtא;ee? j\y)?鱩 IDAT'OZ{>296cڰ.O]o2^9󧣧EƉ6n㩉REhɺ90KkeY=@aU_Pd5g=:Wg~*:#D\{WyPouV!:mhug0'76|T3Nvzl=O=69عw/:䣁#\zj MXj:9q܌b5l. 8ßH cQ$ى[=ع -}XŠù2Ċ#XM~ڂOQvploE.- Ct:zz;9K9M?=5%ȹugu ,s:۳Iyy>{ O0`[[>cYan\ s~ϺrJA_S5.IԈO<ԭ(wj*VZ 7q@,ڼ'R6P,7zƲҒ7z}v9l?Ə|$ȿ'-^ ֺr5& 5RGGfaKC02<9傡:o4v|ƪ݉WcU){(f =}cLG98Oh-D]|ŽΚ7BϿ?uSCЬ}i-bӫGx}l\vQ5m_impfzǟ"mڤsk=߽7綵,}vE=~o//}OXVUH]-$ȓs.\&#k?>~~=O`glJiLh˹׵s"_z  8ڗ&bRWMXbجW/'d8fR7ڃ|qp_v-y4Jvx5sC>7j+oxy=fft+G._kI+>hڇb^yՏλbu~bU6T [UjfBXz 3[O ~1a裹_iV"7f28B| jhDzkvwC?SkO|4n%Eyh|gFu3,uCXD-ӌϧ6t=Y5\gkK-*\z&G_gZoh׏c'qo' ԥ# ! CzxnǾ`s88NYݱތ՚ZAeX;wj^&\f}z#Nħ'Sg8=ZZa}<ȖҔ5ͺɱ_O`^Hs.AF)kctͧ`[Ϝ=<ˡ>{Թ =z}?B'mk/d}'>q3j7Ybٵ׭g{;·> 0y":8Nq ;5qrXz;''7o'1YvGg (l35mM\A|43N|8D Q<>LaH^SĦ?6x8x 6řkˀuַ>W\7gNku?5u7cYϸ"ÐqFEԇ^-.[yɨ+3/z<Ƚ ܬ͸S9w?y>AcCR6n>穟?_'L^EZB=t^aО^>F}-l׷y|A566v q%^,6` ~|Uר}WL RXz1yggiMO@{ywDKsYR3d힙7uysܳ&Zo^'3x~_gկ~W0|K sbOvM{gz!Cmo2jvǚ1}mX6߹;ۥ17{-ujt,u=bU"@{on9gB|[[k]v0Klš lAS֚w+Q yg=58Y3;w*eMy')Z9uùgWVDU0~|{7Yeh2o,e 6NSYu'|xY~Laڕx(Dko ~g]~~,;hyξ>1[;o`쉳EāAK>c}?qco,xM,57^O Ð=pl3 ''@O[_ԱNo}/FM6-ƹCrh͌Y<9#giiɍ/Hcc_&CL{KRξ &5x"Gy;sey$=Zr O"|Q607[kMs8w*flY;FekߜK=#Km"Y;ͰY<~is뇏ı>fƼ>/`)ț렎uq vXDѫ"v/]CH;qu|ឥl:OBW#wSQuv0ְc^X<7Ϟ /Sߠ.'}Ӈbұ1fGk%%w?> xs | Ӵ/Fʱ UFiʒږ>GI9cϽ'l5o#}_p-@ZEsĤ |]%;n=eM85)XX;ԺG33&W-3|Qdk(9 ]53gS]]zWOr16;k Y oئk^"GtsYqӶΤj]Tt:>₟Ĉ 枟Gk|+_?~~~>~/`aHJ]@Kn4.[pte?_oBXHfiE]bSϙx7rosBQGj'S<*|8ƬM[}:OwZRT>/-\NLt,#4{bBpJO Fޮ%>NzkWo}I+8fΊrQ͛ÈX=E`D5bl ^N'0PoKqZW=#}*E0Vvy>ɵ і)s~lpZ\4&XouJ6$w2;:y3&{y7OVZ/{8crO:l%v[3~Yzi1N(}m:`?7ؿiʹt4cũt 1&ًs{0x&?Ͻx=>CR/}7c٧3aNgV&&e&d*0֘Uͥyk8Yq_-K??ڷHnDLE 0Q}_xtK(g՟m9q-ŜA7Γ37[W81ĦP/NN33[sl'ul'c y>x*H}wbpS#5 yd"Փ_kG,>#yqS-Ǔޚ:XzÍ1c .kX4<`N}^[s  >.rM^R&#_PɯND΋yՄ=y5aG|BOekY_N)]1ya笱= 57y{u? wʟ7y^0ī˽ v~tn|L٣yӗk? C~8dQ &9C~Ѓ_MgY#/j܀+FέgűF8'ߢ,nZ0 }A@mww||}GCj=ڙ:m+MSεF<~W?1{V^˽+)z.jF|DcOwֽ 1vfdϹ#k0<\op>7ɜ WU|ڭS9+{?g-y679>mb~1ĽO˵{fQ?~}^uޯOG+U/ϻuX.e}bW? }()] --yh\҃Ԝj\&}z׹09>y*{K/g=aH Fs2cA.3imt'1Γ5Q ʶXgc1،s68>C!Wt׈o?FM6&|fK?C?mDËG㣾zwE>>O.o%uZm]O}`qϸelFsRGZu ߨEO;BuC>Lt]=bBtYzqNkӱ(S+=N'vᄟg5~gA^]_krhܤXU.]@:PA7Ak cؑ5m] s 8~~q}Ao.md>NxM݄G;9a՛8|rkOz|7y7Ewq}6h<@6j 3]qnV lN__uk+~6K-N'":H9xqDB_/ƞ U> V(qک}^_'"_7~~//. q_mAPfz"ę#/76~w77?1{~|}5{1YK|۹}Su+GkǶx^zR5m(KnOe ׎=߯y]MǽL|n;wŞuֵcƑ|st챳O_jO|{t=ֹK'{?oquyiscgW4gŲz#96Fm⢛ZNͿsy'}kl;)T nh'$tۍ=84X#ѥfj~F}731_j; N?|[E/9gLZ\)_N.2bS~!Vɝ~cj}Fߎ[/a]19t^/?zϽǼ_bFϼgoݟէD4|#wi{ML+o|WSG޽/ ԛp<z99qFcܚo7w'fN}Ҫm.l3[ 8H޾qxбk?}05>$cETذ_pv:T!IS jfq[I xyiq%ο\&lbQxs.y`V҉˓`&uE5Gh_ԿPrhp1~!{r!'۳󼀚Ϲ77dFp'Lٱo@Z=V?;gkcn=kk3';#QSwQۻ[|~q sϬR~'L\cPo9^B}hUgO%5S]ĶU?:x0ׅ8~"58k1g*/;y9u`bbڂ`gwdi.sCkޢ#>c$VSk7^8<2GqШ:Ғ·=jM][ˈ1bCp nVPykID(}/{<_L{l!r~\ה_Bx3ymR`yu&?  ŵu zۋ{438g^6yY5_; gy5|`3էBoЕ9'Ufc|< 'NZiy+|]w%1u4\N@w].VyzǛ/})wM[⚬W Z xV[KaVǷ =w;q摃}x=sx|0p0auL6=޿Q{ /q&<{Gn,Qd5WzA|ڝ'$r͸y42rﺦs}/ܹ/_I4W\9lZ`G E'P"f_䦍!:]8kLEa;#pTܺ yӶ }h)l\z_fa},ߨY3:Ѓ$KQ bg/yմ0U&_'SSׂgl>}KZ5V^g%K=|c>Xjl_loo IDATC*080tPo[Á Şz3:_x"sGMfF}ϯwom%ص|kjƦOWb_+YJݓa+df'MV)r 穡9օx9x5O6h~2oX]2؜/=vL?kN ^}zA'kD_;cG,J5V;OlO4 cY`-_,Ǧa_ WLn>[oJ%IꔰQye~ڢOȡfOyK_f4)ݝYO3.ecGNkȸj\y^8<Cr^۫@voQe $| ^ΙF//~7I>=)n>F_}A| O'/Ǐ@OFݤqt3*n`|oǯʯ|~wܠmU@sԞq>-E *\8Q`}96lt6Ɛ_.1/rXhգTZ´jX7q`Bmh~S3w3{{K|w2ဓ7 JC [ OTwS#$6/W! WionmVy> ""# 2;]}?XXe_e_U  $* P*C1e&Zw&{d;[-'fcO&ok$aʺb ^u?S8kyS}d1nk% uiB1gaF ԹںC=X=B}`zzzO7{TtS=̶.mN}UKgW_il3JZSnWϨKݧnP^ k?H'/~}7{z X}eY8c߱5m m qs1]4s=;gkNy3>uMUVmeSp/g`gX~A .ozs{?xғ~:_<]C^pXSNPx0zox/v9Ko;o7'?E LIm}l[\ a&{[OyӎO~{ۿ? JS"?'bW Z}8賎L2bv|ᒩ4eޝq|hdTZkVl! ]Tj1VJ3VŜ=K.$s$$kT;![&k_[O/gL峦i(okL}ޱyv֎yַ[r7nHn!=qc 3~^/g7j͏]]u8ϑ}/Ʊ5T׫sZ&šWCgWC|gܭxlA4aj+0vw&Oں֙7!g''䅧;f= }lc}M~O`ߊҹ%lZc7:cʑSk"~Ո!gzkՒŦv[-ZC5Ofysw䩷z2x"U.m ߬!}1m_40{X*3_xS[,[?X&gI#먯O@5™mkyղ5FMu/վ'ƚ-=,Ugg: ={}]G*pXJ6ذ[kE7{uOLo'EYΉ5~ {0ŗ 7H~;V 5$8Dž8l@̟ /;ʼnϵ?8kè=+QZf\}[}pF_>C<^xQUo2z{\JS^p~_O'>Ø_w_|fxKUv93S=|h䕆/_;^_9/ۃx{w|5^{[ɑ/џO3>cz`@"IԆaKd;l=r3b3DH]u{igoz0S˪sɭK?UOzb/%N~7cDBL=ݮ'z|I!?5W ;kQ,kFLqלk8VXk|~|z 0-)<Qk-+؃]ռ&5ח}mj םX]2(Zu$Vk&n3ׂvzWs/ \+~u8g^DCSU}d=bM@ͯyaNڵ1Y^6<Σ}wtN߽KV[Rw,>X0}&5nj) +aѾnE;W CV釮e:-X?*um8996Kߊ,Mg?x(:[r%oe<68n/3n c:OZ_j{k&f\L[[||~ #Z<xvO18+ƽ8;q&9O98O5ͮqoL93HFo_i IN6霞W%6#GҷR_Nyy['h9q>34$O3'gѹr2mcPy䌰B;x ]̘f~)|p+'-^zbѵJiO$XRxcpyud9Xu;oO4 s/Ny`-(#ƫ#" 9- qS~総eOPz&Ie^Zw6ؤZo%; ~Ǘ]~񖷾x<&3/ǟo~[/{]obDD纮X6)gb?x/_<:}>>'S/ن=4TO:&y"^هѳ`o{VOt^®לȽҵ$^Pŧvl+ >`n}xR 1Nl1sHg:t3ƹ RҊ1Rn?Ǭwkq's3I4O=cY}9<90sM9fQǐV/ƙ.rٸVg(Quڝg=y=v1}St_ϼUwԩz$(ׁ}F3kNj3oheїQ5;yy2oaI:>.L|4~x}wryVL&>0lOfߙ|;qڜT=&1NJ\zu\ú)z)$wUYnbtRzsfϹ{֕UΊiML18C^Xw] ]O{;J:ڏqEH Ki\|N} _dZYsuI?\gi)1@:)rz[}hysgo2/^ UyI7uu;sf0ėəW~wW~k|ύxqNuxEUo{k뉿`G 7׿`\qV _W-g>~ի̧t3M˝q$S׽u+_3;Oa=اO s`=o]Lֵ󴱏59yj®-Ջe _c Ƶڸ1֢OZs_5uƍ=xqT̲zSWXL3 yA ?CMe/B[0bĪK܌ƨ ƺDj{|m~g¦ΠҏUNQ3-|ħ˙iH|cw-}D0ݨ\,y * _SPak=uCoN'AtY(64_({ͣ}fYCq˘Rc;k/d۽29{yѧֳk flJeT#;yk]{*k|}T S>fscF),Nt4^;Z۞9z@>,&^XFߡxIx16hJɄ{i>m;f7O\d#f&^Wk3?czcI_JgY>v1oy'շ~whbIw|nZ˟oMVWο-1vf979 S>[m5c/x7>0Rrc?GzĥWVUAuLM!99vqq17ZH3=>q4(k7/1giYT怞d\'i8 Uh}o5]kNff{ˁ=8%sV5Md]7^O WzYu;ŰgVڲ6jM?VF]w㋷0sԖ|Ӡ]̹Ucj Vz#ڼ>HSgDZG|Ay]9_pZCc/ EVglCӞ/-O|}#YNyO29ѐ1uc3rM.5c~ȑ*Z5W)kB>Oα@U*:3.5o;kNb eLl,{νt͙s->WD>m~dNʶ6qխ[{h0'W>}Ĺ7sBg\W\%]1v>~H@|/+~9Z.݄a3B%M/&κ-%扽'}ԝ];ߠ졠G3 $ Ѳ7a޽:_W,:P)7/ػy7]_(}X6 ;Q'0 ;wGYi۱d}USi]V}(vs7d A_9 >vmj}\j4XتKKg>zT+<[}q=E5;藹ř]M1k_ v8[{@ 8z2>~s7FWk]9 g?]Ѷu9Sa$LجigoaJ>5u_O|)g-GǍX[g=b҄l]R Cp3ב0̅fLrk3񦩓=Dmc}߾Rzud~<6{y;Փm1+>/mL]l?|{,|x'r<=0&r8XgNtpM17zٟ񎷿x SOGWC#sN){W>9>׼x>{Q[T]:1<5>6p`c`tJZ+~a:JV 8_m'{8o2<!"܅y2 Ѥ;OZ[0Տس>~Ʊ7ϞӺ82OFE!k=W90ݬw9 ]7k<0/7n^ !#vx}cW|5bҳofȾeϫկԢ^uV|^s٧YQ޸Ɲ댽9Ior& 0G]`8ҚaZIo9Z-_4zQg`+:1M_k>y&gS<=^=*zWc3Z ȷL"̧a7.eQ_rAW Gi)mK16 dǹp%O=CEޟ:~%/9^Wgի®fDoGES>я[z_ɷ?5 83'uܐe]7e o kt?u/ˏO}S7MhE1%GEcV{"[ g>AXf1o[ p8f>Ɯ93 rZ9|3ƙlHl[™kVg)2V@yCFИۚ1+^su~ z ?։5׽5OYo,+dCYlpNz-58ueLqog7EMr >C@ jƟ 'orܸpS9[Ͷra`g m=lc`/ӹP#^.fqyܐc͗ŗG:Oawl4jUOY_Fɑe䵷4tYO޹^8byVw۱?x.\ǹk}ra$}Ƒ胥Y58GU|假'~~xk^}/'xu1(>5.ӎ(`y}o/Q8'm Pֳ&I2|c~Y%{<1? woOo:^W|+/W]Wb <+zc~'e_x|K_:>W:_ʗKgrK◆h^rio]]',ycU}L3YWlz7'M #769uY«.u-9c$ꎢ'α(F9Ճi~{&Ac:;liZ\<ۼ'kqc>ݭqM:OWz͗3">OJ{GʱVp6WYrᑳ s:Motuw60 Y0)9 3zA$O=gȝ.7r0}>"69i5.c,&vgCAEcb7gdfLoHL/^&kfFX`a?s͚]Ϙy}s7nCuN3U{kmuWMiؿ%B랥z@∽ iW_q92olVLqO|pJM~AW2;|8,⬄8+6T~jsXlO:gF^5sf\Fl[or&gc?g`}v?|#0bdRy{5omnΰrݛ]24 HAͼŢq1VԾ#ovϘk/ז1AQos:ŝےĵQ=ܝGhS Iua \i_O̥i -`E9>Yk-1N;A͙z]_Ƶ|;+⋷03"sMՃΓWUNZī[3kqՋaL3V!x6.Cc24VyZkaAxƸ LGO7^_zB뚯}_YW߻{ߪ/^WoI>= g^ Ԟ/>moWg#x^Hm|Q/_֪Z5=ѧ9X>~`6_W7MǛ=OWIGwZ#\miDZgU:;?g=+w]:>sٞK[^1;7+7)J[qM# ht{g^=IgKv}_ڋzcs|ػ'} <'OXGq׮z`mܜ k.[cqY5>aj?mhjt->s;sHsHC䚱 ɟ !Df>員)wkޜp<Ձ}pO'2ws`<#ξ;K 5vhՇwB ?H(~̣U$W&̜K{Vchd~I>~~x|Adn$0Y8{~\9SEݼ 6QDWJNq݇39k \{{ji\kcO=S#u䪮\[kbWllk8|ڙɇ~`栀>`uL4QwuYֶx'rʼnfh,H" 1p`{,+gu dkڒ7_5b1_Vn1 tÞ=`Զu3c'~Liþr$. c{Wٴ~QV7؝R:sΓWo<-{Uq噯۾Uʿ(r;+ZXqp-I9{czMV}_[=\͝=y* fI \lǶ4t-5xsvS7~s-rN8uP"v;3y`.Kɸ|اh}Új[@o91G,8L{ HKڨ].kv5kSZniYs>8[l7&cԆ>i{EG/Ōj5Sg(HF2[]/ V'm!%/u/Q0Zyr}aXgc9-{qUݬ+ioWYsw:p3d|kauYĻ]>Ccg]}_U$_w<%j=1M޵3WִWLS]ΫCr8CIMǟ1^ L5ŭopZm͋g5}gO1&lsoN O63nTba]G!/-%{ rlϙ$)^{\+/-4h|tb~Y~総ƫP!,j]`ʛh2g XAC?t|9S9η{?H +<-[ ^-Wn%*ov?Y?ovF<f~3??ɷd=x5UG5Bo2_;WO&a/ȇLJ|=>W2́/n+NPӆigj&{m b3/3'ϽFx,k&5Pi\)Rw;;'{Wus8-+u]gPX=νdu֖hPղ:aC!; a/~uO{2Ǣzr>kLX^Kg{Ԗkor<Iovc81}KA=ԙ=űg^q lk3ϸZm:)Kʌ˼+:c*/ʰCMWHXԫ APyէߙp1=3b+=4n1u,xqq>rTsol"n̡fOy4Wų;>}f~,͑OkW~/)mnDhZ&{57sk΁a\(cu&|n ^sx 9Sp;spI?Ƞw7YEʹ\tKD)߹\=]yQ5fS^ 3Kg qŖ wsMgĚ:uASS÷_ySw:I$sbi:.NƼr ][f ٜxلc&3wYU ?a]m3[i/D૸s}WsݿKƤ3GnFƉs?樾6 ϵ{i4s46\ l'-׶ l՜{sys7;|zI;nr Tpc]-qűL;ڏs]-![ň]b/9O|b|ǯx+_y<3>}qD}=z*mpd*~a2'/UlRGogE#\Syf|<>"Fp =)HX7O~GoxC=֕}D bX'}@YSyc?s?O:\~j>Sz9k <2{K C=7xM1\;>a f-3kO[׮ٜ/fj.SB[rщ9w{ʃ:_\3u4&*Kel\x.۷x/sZu5:y{@cscZj:} ?X6s'xrkdFoG㾟#s^t_'3fε#;ym]s179vs__ormSC+ZGg_6{f΁}u<8 q2\B93ծNzuQl?_;·HMI`pןq_`&1n(Ak繟+z`N6'^ qś+[Sx=_#MŃϜpiy?k4zx{"f~\źw.ƗC '0;>M4inC#<39лWũЫ^Y_b6s8;PCLhQM?댉5,4͚j\}pɌzBZ=c>xRw5.{5~o/ʽn39oB/и jwƷuU]n?RO1W>/fA{b[CVz;퐟ys't7qW,\)psݜWikjr\>0; ĸ|Yv8õ\O|Ǔ k$*<Ƃcmڼ#N}:Z枱smg~I#MS=hd7Vo$+j\r>`ٶĕKTD{\YI eG.gKկxEr:^%<ɟ|b5{۪?4U >ޚ|7u'k=IϞ'!H`i|/$ O^+#_ }/m< xg>w?>=Y~\Q)J|dROrV|[_o|?ЇOOHcyb/T{$ }c7x`3Twchɋ/!q g=+^}G?í R_"3ywuҴzb٪XEءeF@x[9MoDx\7K[ 8c9,5t1YaSXg)\qYW^ YsF>8^жb UBîŖ!fĤ&F Ku$}>c5{ŧ3Sѐj$~ǔvr=AuON1r&F bW_;ju@Jccńlp&(|>8ĻHEϼ,ʗuՌGZO<L~=98|prs\5j&tRG; yZb'js_Z㚧Kfό9 c5|y\Ә=!83Ga3i#36`ޮ=D'_f~G0s`wc̳牃cUީNy3Z;1Nwr30W.+q'Mas<`  OĢ< Zz򭵽_k-'kfʟSffqUVc~8qIȹaąƼco[{T_O{K_ׇ|])njX2rUI,P)?]cψv ұ&<øɘklΗ>n)Ա n0"'HKqp '?ǯo7&PQfΡj4=7yRPKćx';_ǃ|jm@G~+S1ij.?ZU`g\F7>^|GJ5/7J>x"0[_?o}k-ǿx L\"ٹs֝2*zc՞y[u|;w;sUUљkr%*%Ή9DlPw:\I1瘺oxdb2g:om2~In00Gi+ۼ51#_叨X +YWSzw`0ΐG\ϸT_x7Q5siһ6;փhrg?FuN9@+*G;*?dX8ei kvuQz<?/3(O{Qb1ҖH6,rex(pU|׹Я!w [6y `5Լ}̀yA)+Zd|QkMmj!>r/vf9ikК3ix\cʁ1ͱ ò.\Gr{17svn)mFo/a[eτ+ޅoIYZۙQKX:Cjj{M/9RMX򅝁ic >LM@h[OE'vS8X1SOW3MLٖDmɴqcPbadn=9]>^',^Z)@s7>4&θ |r`7ό%}˘XMX}Ʋ61bak_iD3󏞛nS~,uiMLɓ]@SAPu$K_3pX|sLW~Űo,`(Ǯa6wq{ՃN'i j@Ѯ9Y(Ӥwr ta}?F< (A3ŤzQg^Μ.eVN3+欭pjg쾟aQ+^%pۘj\W]hwdVyn1{vg-^>yeY' &W7!& 4<'\c:pv& ̜=8Ґ \&rNܭ||ZsjKlԡY츱eprNo}khOΖSofGY~m3>y(=_8aX?DsGQRvsѻo;V3;x 81bu:ԭ:ֿiP$E^kqhs'P__ >M@刟kw-I%בW~!ΘqW 0gtܹ |؋ 6նbrmЇ6+ srS>42ombk5f{*msc]{Ӿc+E(6*<Öt3O`&0*o_p+~ ?y(^M׾x3U>g97}W56Wa';~_W*w''XТ9O05TL,3VL;8kST7#csg{:hWqg4@Ccw?{W}xͫ_}uxO|8qӺu& lC}k_Ӄ_/'o8>|׻o1ۃ_RN:g>Y?@ыW^w~T 8y'_8cu]3 >{Zv|5+HZ#&1 r3i~zўæ/{RX;P濠e +#'vDӀfl|16'k;1EsrF")U-뻼] U܏F3mNcƨ !~i OIjufmˁ5q"io-G,x6OYnv9M̛vkl,݃ K&}zM7}m \/o~s"eA!18}֚dqq+> g L̉7n!n9n,&vr 6yxkrQvΣmgo^;el[pqk;ЮOIw vެ $ zBwZo -S5sm9Ɓur }خ8 (پr45dDg{=" l{*QkjI;c}q%y{}:G67+uk^r0>(p_X12g1rϬoNQ觱گ|ӎ=3_5d{Mh)nsslΎ3G4}}8l|79;ezgXYEg üiTת3ǵ|\/rˈ<{z@kMNḫ48 aU}jr`t;=%&NY^rӞu\ڛx99ߵCV/_Ea kZlg97Ƕ$?Қڙw]ՙ8m޵q݇"8^M9:]NiBuVimWWx<=:^e=={xӟ~<&^Ft}_xBLx| )Bg:w~;>>O~Ǘ So9S{\_uR:ӻۆRkg+!M\c8|Xnַ2La|+ү-c$εCXaai 3e@bY5]gSgPzk:X11ZVٸ[q'C=s*?$QBE;zʔZ'z<)1ޏpmx淼%_?I.tD_?>A'cs /]J( \{N<*$gS7f0eUNj㕁}G"?ji#9UcSOlǃ@3}𸑠y0YQn]˵L 7gȰ5FUFƞl3W{81%Ȼ=Zy1y>gz/C )c^;]81773ºӭzi1&=}3'~G3V|cPիy䬅ĄFWϷ_ˆ[M3 E;fsоbwO}/WiK[_ka[o̬Mq٘Mm"b{=-ZmH9Z0=CS9-h$re7?qFwS/~׏|G[paf6H_c_ +f̃ߗ>]yg|__=\Oϣo{LnL!™Km3V[DbU/whĸ^qm"}έj_֐s(c(wk_-U8ZKG#T~5Lι^<'Vpsn|b(ƤpOĀNDI\Ϋ>}2A [vN<$=2W곦[yO!Vq&j=,}dqSNx#ć||-ಟh?ʓ~6E<1O-_|/"{<-'+j#>GI( c%3?_yvW|ⓟ8ulyEr\ÞqUZUxgDc&\I4ϘXsNL8>Ξx0>1#;3qɰ:v3߲# f҄lD%"mv5clw UY7(/k 7rݾ}?2ʵ}gNlܞXS+쌙ghkuB囉=0v׹G,Z\$fbώt_7jO9u^黵IQ@3R "X( ӑA9ç>}Re(AbI_D2ɵU{efw^Z{UW31+:s#AՖŽԵʎ:Arm3;?% C=pp:^3Ȕ؄z30uy*615[,!}aX,z孨oZIZ⊩ ftT䁯sg_KXe g~XuګkZ3ջ5V mYW8rF={SWN"jil[r2#G{t)]w/x '=IC!c+G][)1e ?3?T>ЃwvЏ׿q?^WŞAz(IS3zqoA,?An\ݸ'μڇ~y{L3APU\- ;^|u@$3gҝ |}ǎ*HrMωG?t.}]ߠl _n#eWy3; ws(WL!x: ٚPu9zX/uZ\;w'=|^ˮk9u,qhi6'k]cɮg5'L{'o5LOM=vE~ŕm.Jc>kn)r9unQg*o8B ޏqHH^\rfΥ_1y/E1־"JUԈ2؜7HiI[9ϚVʁyI,<]a'hg f|9*˿ \ĨLXy2`sγhyS/F[co94!I7MϨl䬽=|>y˖:2Oq+Ceb’%'.5sp5jA:Lr!_sV9{ lr`7vmKs3{lfqS+9 6G:>iל:>s3Wkc5vX &=kNg7AlŜ̍gZAc5/umPV=]yR7 wv8yf/G&Xl:5lE| pFNC댦-nמX Q\:VAΠY؊q[C_YV56:p[1*Ӵ@rf<`>XBťōppj7ψ*8W_ʫčkT\RѬsM^=e W9E@;cG6c'3wXw=ˆu#{68 +aCfZuY'Fa=T6癱 -~i,#[lP9S/XHuE3%L9眑(&w7fpOGZq<ܟsU䏠Tv/rƆ-?tV!M'm<1!ϑXQc}H} 5j}-/<\ J}5>~֟(Ģ'_{[|wO~/' `= q{YOծ?q?>#<_㉾{C=ʗ'.>F:VVΊr5q<1?ނuM+ (dpJy\)bbcTgD꽊a鼴 "c)> Ř?>//$~;q =9?#OgF, cPۺyR{^+~>||&>4O:^W=@7Y|ـ@xެk$mOCW0:縲'|B]T`.o~ew;>5Ebyv 8g&6PGeGθ9X<6dV8Vk%l+=8d\f8_IS z>=tZ/:\'.3X9w.lFtNz "0->9}EڳHP2rւ_Xk˸煴yl.?<|(MUW+ENֱ} p{acwyfZ=۹\_ˏqy!Z}'G㿉v{Ӛx<ѳ^k5Wka Ƭ=.׳Zr>fY_|k6E63bsL`,˲xsjuFX#|#)W7^%5Mu-q>kJJ4U:COOCOOa'q ?۟#_W퍸%?Ulqدp DA'?Xr[g`gfb~͈*cKr߈g Y5Ye'ٻ)}d w{xv|@;#>,&Gkh0y>厧~kˎַ{"ۃ&C^W}\p՞9x1pin2@1x'b;?h+GvusLθYjXVr~l"J[SuăjHޑ~sMs%\G'T^G64cר*R(9Ԗ]ɛы $^9)yW.8Q{JnԓyyZtS',z9}ƛcv_=\cl&Io\t&]LoϾz8<󘻶amZWKLXA]֣ٜe@{3>_7J=\ڙ'~A5țga kg&6Xywi7=sZ;b;3r$mhf][ϜKqSg˗9޿/zm!poXwIpEa/M\qኋQ]ܺ_a64Yq!<-}Esu-+=YY(kֹrfv_ږ:y?!O]ǺΙƹu2&>pckxFye7uNf#[C::Ӹ*#֚'+nݱ'=?/5Con_q%{)gKޘWTwYӬň)ܮ|Usxs/sK^Xڧc}3GkS.UW/Jˡ99o@\TcizRܓ~m}@zǤgi(3~ %:1s?\ '{9Nz+N<(w*->-W[iƓ3=^/:~iO?8>ԃpM]/|!JQ={u/]o4Ow߿=~>8r^Yf1Y;_+1<1İW~[_Z3|ş2Rk- 쭝կsxFb1GH2&AX'97/҇OGߣoFCd{2Aԣe^IԨf^g'VŽշʧ]la5{rw]HS_cdz}3ϵX:+ɼuev-\1XSf՞6~obٵvaWy3uYyNӃYmOpZXynz|OS3i1YuSLÐіy&MV@V/, 6cvnpg9LZ`ᑳ3seLj {}(&~c4dɻx@:Mv]C R J͍=4۹"ߊIC6¬hs>zx5TIu&90.t̡_kLLݾ4X0sz):oUȳ^|%j߉cmMAO~]Ù?#~ccDu˿皘*qN1C"'Ö5UY`#}1̮ TPľ1;Ib9N|'ntrn*`ck״'ٽV G[ΟO6g3W8F^Ox+^qUY[*ÌvsdPpXc|83=:|+>#;.G'/H|gx'WOc`K-y2W9z)uPO7YIu(z$e3h33/qeJoʥQa㕖cJKUJ8M$0mI]r5@>=-\_WOKr$ݫ5\y@|=TD]l\ ش$Q1c]9˵WZRF黆fnTsB IDATfqb!IGH-=0}]X%n5gqglțlxRD.S[:kr+[51|7޼RSæ}c3>y: &1=o_gq6lc_<17tqD~8ө&[f;cp,~Zgmv&7aUI`I'GO7C` Þm^b+Ȩka)֕94 &GQy*Nh缳c#+eL]ZkRR;ؾfOw9 :mqS]<;(6uDZ}>3^ۡr9ʘyΪlV3uc>/ jˬ8kvmrݎ}t>%w~}~-L 3'97}}Iqg]W'L`Kv}Y3+sI˷Us;G[?.c3l,NLߕxԕ '^_yӏm]/x3O<.PYCFߒps{l=tOt}u?O}b{Go~pY'>uRx0yR|pҺ괾Cj6Int!37u˲NYcK{rqJي"dXqLsG ]v}#<X,pdĆF0y|#D鷿kx3=q kG@>*J;8~s%/9^|<>8S~ΙF2c)73x]=ˤK7\Qx7yqT[vX.3F [L`F­orUZoKr[sM(ːgnc!g;=(DqsEZ=+^?"|%Lџn gczWD6Lo֥0KSyP`ajpN61*M?a E8bXk؇pWsGL= 43HpկlO<ɩA ~mmh4s$AgƧn/_Лx1q(ؐK™DZuOZ;7MǝwyS'lΘgxܕp)nVd{ك?}xޛq_}8zc-( ?_2ֹ5co-UUvXc4"kh$_am,2>m3GH垛b  X-kze>1<~|{r|_?O?woM'+|$8ڪܡD6noO~ wg?xӋb,F.^7c(݉]ƫ&I`gfEȌYVu_PsSe`yXy: g窨^^#sg`z^rdZ6I 5\oeR~-?A81žԫ39}<Ük7V`:D1ǚqNsuêbF7xf xV瓑N7jQCIWcR٘k`zlr+3R:KKs_w=y}{Z7\S<@UF;G_ee?r_˹umpo.m:^v8m:Rˇ͵av vzwk|'̹WNj`_b!GɗgtvZ5gդVvQ'=_c"VnϚVW!pxm#^L _94LUz'XZcY3ދBy[zZ4>Pvb#s'箵l+. nC+6,XK yǖ]b'' X}?c..ē-9d^)r1.kakajT+\+fw8F (]zyΚK[˟Ku]Fry'WT~?iG̛G)wqGEa !go⃏ ^ڝU?0ˎčs]| #+0N;s-1yFb,=5-u՟ƴof'3"urڈbO}}su%h)Wűb S~N|p \ǹ<+^Op|C:9~%9\7|1rMnۏW_`Wrd|ٓ4n_ jÝv7 |٣a;bgM@.&MS™/r6+Jwfez_D$9O1|>6䫮㱖}/+ϟwxQYjg}{|;g?ON3E]QsmfBHփc?1W=9:/k%֫U캭k8]S/@:xV>}+YaiS;J[0]$ÑQ2~^_\|xrDva9kVd "c6ގcuʉݼa\yVyn}{ĸ7,⪮X{f}2zYPsVÉo 8㜍>sG(̌~~3α(*^R뺞;'EC[_?u=+My*l;o/?$I $Õ]%3F0;BHMXC-p/|bPsKBwK{<AEe=L9aҺq[ˍ]7S%qK( G0zC?cOڜ1}Y+-e͋wյv-zmTO;3_:u/Ξ6/gŊ6ws:~zqaiDg\^KjJ#Uμ̩Žٺ6lsb[vHΝebWZoH }59GqrxYw_7H Y|kԡ!eTLkI8sr=_ijHHykWbRScPߐKO뉠z)ģ:C[]ou>5y3(rKj/8Al@tȆPGaշlҌ*'Q<訦a䉿CPPrMWG+{<;뮗wē}l<ٿ?Gǃ> oup>1X(i -| sH7}cb'2?xj|D  PURipt{U#A0Vy 37|ㅒJcY7q> Υ4+O/}$\>NS ~>O_7a>=YrZg(uh6cpМs/fW] puWj,.÷0f:_DhK 9rmV,ļ6+2F}C6z<'1į;a̩ݺ-:byGS _˕)69Vc?{L%xK|_5z^cOek]\ƯټZ*Lfl)~~8G +=NCuUwaͳO 3W[u:u,c`Pkjzg옲[sQ:}CO®^۵ _.CxL'm^. c}:&Q'Wh[] ETº],HXQc]#.dLBn}ߨ&5|l>V);y3B_ٵ8l̵͘P}k62.^>BܪM*6d&N"z@7na/ku3W-<\_F]=xӧƝ<68kwQ}eo8yU;m z9MPh3v hS-Y0j89JGCxl%S{qɾGk0t:0|g h/Xs/)W*‘ŗH :r;ֹGǧS8^oz OQZ {J@;'Q!_oǓ~$ck>t3|x0G8]k&r<=xWUNduo?<}#KЌ_=8oA6'<5ӷM D'4<65#>./_O''HȘXw/7!?=_IOzZ9VYXx?q7 Ioϋyv|K_<_'?5D!Zy{;ӣA>dcO 9Z+/qa<01+:Wf|v=Wƥ\+L|u9f|u`4eWkOV]0ADɰDg>:7|ڵ\7Ιp2?\9nV^W\uƜqK~5:Ϙw"Ou<@n+ӂS cر96Yڋ#Y_CUPX~4{xuկyPvI0}.5I&s&a=r"Cj={WRg{V~~}s8\S P}YoǍ8bs=GTYehf=Fgm,C,hPӬgLwf\mQW~d \> Ϻx^*?E7,y{K_)-,3˸τݺ)01[뮗׏~ǧӃjďd0OҒȵ0(O38vi}}0Lg1ǰOۈi`vnmCė< -aN^눸”V[ubi;[qد"ϋ=qCQe}v ۟̆.zYCac+%+8qkfO2ns&5yb9ǃq.!#CSODY"ϐ Lsm039ޑ( 6N.YŜ{7jh^.ZY[M}WNknqW׾rvL_}l[sԖ F|k9䔛y窨sn1by:W{8fy8 \/P[SǍ-GHDzK#5 3\f (a/\;.lx}Ʋg3v?Ck!Nsrd4U3bs<=W ~,"ڀ>{~peg/Z׃$hOŒ:y $ְ6߰v*Ȝ5k~M;o|%8q(cٳG>[YnaH[?ENMteC Ҹu܏na~ 躧N!R9NIO8E%sA;ra\ۓ= 㦵`9/җ9ÑqqXlׄd'b_g;xk`MB̓F|:x2K,gLbc 'Lz承;_-o~s>ԣt!l9"ԁ!))D׋G|~LJ?47~@ 7Ay5yiCq2 yuԾԹ޶>x Y9]y ޞUD64oǁ挞nMLg P+5Q]oniu(ss+yEs[< 5/M"4 Sǿ &xo㉸ou}m|W妶'9{X֡;f4_ IDATFO0[/>~O/}/_?'G^Q샨f?ېڈdTWfLޝNly&~Xi9,e=_k3ȕ\#>tY<*- HN7WQҌ"%\sόyw-s*w]uV>&qPvhcV6^,=@z{SGyss ?qdg/_X2c(UC1v2͓0^^:ܗs(o@;0rTc!=k q[rcʐt\G)7m7u}}5o_}2M)~}\z35mX>zp//,9Zyzqiw mܧ=ؖ,pcuP) - yZc,jJrCXJ`룰XDW6~!ݖ0B/ݥ<wދGTq/{bY>~eTkN1':^{1[Y?q cŔ%f"~c73_=(/G_{;_[.]k]CGdz拷axKh]<{{t {C?RLm֌̧n!/=kuM8Ocldqc:l1:ȁY,99F^brT4^ѕ'd^i~,q]Tjd͟<8?yj`-:vVM!^!_' Uӹ!;_r>vLH_(Ǖy"w]ѯx/1l\v>ǥ/Ӟ㕯xk<9xb%>L!3K!}Iu~ ;<|O5GǐZ:x;i|?|[ǻ?~8Oq5>k |/rXA\^ [| V44f ~鲥 nb3tp~\+|=8xWl.nr+y9${?٦.k9Fÿc;qV&'g 5+X{WȣIBb W>L+_W71?_|rXWzg^g)M)@I=ǯo'?;?^:28jKcύubS\rqĦsȞRo}X;yQN6輼*ΨG`|io9cMZ/_xKZq8w—U5V'#f[~Vsq.k<^s8Uy3Y-F38SoXgVWeWȎx[uc,i\I^1srg}|e\2Wb,#H0N{Eqk+&s!Jڳl> x~OH?X4E3vv5&fs՞mqŬ,5/},bkԘ9'7v|ǽ:1 ;}fc 랣ݎ&k,Kܪ3Xm3FP+Oj6r>3qls樝qtV`hK$Mvq9Χx\,~E)%)׃Yc\;Q䝂!;bnp \;{b/`.ێ)Iaq^IM}~ H=jS{ڜZlbpU~O>Mn͡4c\Q h6Q\|aRGa;bEo kjzu-ripj2׮ik 2%};(@H>٣pG{nmyG[_zT:\fLQL=.@,-jˊT_V_G@<[*cI@1Fـ 0k|KS O|`wZ"fNl}c\q-Ut5')>˿Pc^-Dۺ5w*MzB|o{'K_R}o+6'VZ>k{1=CGVһM=Y\^1^Wl28}CiZ!Dnja?f\62O)vJƹcw/k&0q8^y 8XΖ}/ r[=*P{]xbNj_e]^w;2oN})W(.h 5ӟO6xU|0׾z~]:/<S?Vy_% f ՟N?e59VVt쿰V\Gď1XMޑeC^@ϿX@ EGjac؟xGv־zYZ}T-_޳X:ADdZ=ZڍwG_Nu]n##g&4 6_oث=󙿅MMجXKD35n|Տ:'q~ cqvA]nOfnq!PHY/L<8LUNRzqFyj$;O8)ou~1uyeYWT,Qvջk~1ծqt1rX;@'7d\ΡG3vs`f h7pr zliC@&Xn2ngL1O_X\\sqp}*=}<9_W?'G{.;ye9 ۹E2ѝ\u^h)'lU _eiϗC`>|Nz^3)z~ \ח )K(4C.{_UTc_~畫V>TKӨ5Cȡ3}ⷮtn7f񄾠-d^C7 s ȵQucWjš2j_:g뀣FU( H9O`Oh׿xAIOzqc~iƏ>fa;J7I?'Ux?ӫrzT5;דuz90bRghzc/&34H K{f\gѐF ]|MrOlKJ.WΠYCJ,Nu4م5\Έ4ݕ|V$ ߼R|$Kf C@}?d;x ?{ =`k={o|{;O+czh|Q<Տ(hHР&lZ SKNjT8}\%vֹhoV}j\8cGc"Μׁ~{,]l{ Ƅcv29E/ ͵svMS =-'v?'gW_{#3Nl =[qmTC|5nɽvZzLjm5t.;oq2uu \]߳q挐1;#)G<_\]z[zi!jf[-d6z \:ƣ}?O:&5?<;3~XpN31lR9;9:牄n'FRPBz ӝa Wc+z`h`nAs];nԘ?FT-uSW2Eҏ˧ y]{^3qpc}ho\=^uޞT[8,=u}&q*96h zF\]܉55oEȚw@^kT$K[iwŌ:'x~ %>= ,oOgc^O˾'|KWzoO~铱3_meIuՐ+,zūqy-o~[Ⓥ||8r QZY^5c)[2%%/KP|%`EL~{G YsL_ +scXh*j˜k{X쌲ћ^V^g3dnz&e8c"DW9!] <ũJ$)f\"b`>̮#WYduq1O1}6ӵk;ccߖ.oWe1'պr_ bݏK-꛾!b0Y'Wp\S0GY;kxN6}9f]g^bhxI^s/sD,s/QQ1\u"Bw-oXĊgf&/mmlX3277[/zYuQg.%E"[;3zd,{g( PS8Y(=N Ph _SOJ̰6;B(» jkw p\<}tvcs.ͥjlaW493oj'tJ#\5s;܂6&W&|JmHe;z:0PgQuXIJ|=O:_V|wo% %>z,ju?1gnvjOY>rO=x >4/w*7@}4UOMj ,OO):3guo5ᬉi*=*0a ܥ#a;6 [ŎF$?L +|")X<=.+dK1䃿J9^#s+V=S!ACy&#_6Пs5o{җOW=8reWW:0wo#:?:==[_;>O'ߟ5Wux5U}N<l6ZzT-&ёv ٦H}WlȾȩ>gL&1w{pC^ΰ\ Út^ߵ+|r {_ﱹQ~erqǺ:sQ]EMĨkj,_jǾR$>ES5bnEb@+m>^mЎaYoqܬXԤxO3GTˤK"^Z3Z_ڠ:sF^\o Squ}ZkehXy j1zo|?q;7ky+Ҹ=ף z6U^8g{yw\qjN{Z?W0|&BafAwUR~9w>׸cy! zv?~c9cP1e[ l(qlNY[SCyD1j3_VO*άް9k%e̒#Or? ׮Ms/ɵc;`ȱrha*Z=W3ິ$,$#}B `Ϧqov~AUam̛?/?x^q5>~ٿv< a]9!}~RՑ هxR/}xw|<}z۸^bI+Ե+k P+찫 _} L2<[xՇO?o S49-@]`;Eլ4֌^d]!fز^~R{'p>A3_տ'qoV/tQ{g bkl,x$N=9^%H>!*B)_|J=Dg?gۃq6sx3i>6zQUUWEuO<^ߎOG˿W,HP3m=9/; Scq}Na"2չg]"7x:{ԏ=b,@9X'Xaob-ߵV7E옪UqڜW'N vl=/2,L" Y(km#{ˊZ6μ|?ڪHU%ZkBEkֹ9{ϴلU8Yx}|\#`mc(o |_ "9}f^ {~%ܣJP=͝ ?qQ䉟(<;|bz\'4F>km3 rvm9iu6F޾g-ׄ<^Q^m,w>  F\ܬ8Qa1 =#rrlv=EN1=Ou]i ɥ]v\^gw3̃]s#Xq{.Vͼ{EznjuʂeCb|ThޚYB3<+<1ȭJQ~y l"|K6k*vduilsin 0ߜqIqk0: 9 [P4+|ܶc/;w4X"Saj|e'`Ou`^/p֌}~1|bag/Kr#ۊ<'Q5Kj`+'VjaSvQf_e+ī^dz~YXSOaʶ2z~S{㋟d^#<4ī=xq ?AW'ݹ>q^~rsTL-c)Qٍ<%(nԩ{ &i`4꼍\W[}$Z65u,<ڭ_+OO(0 5 IDATUO]z"4?Wqׯ}kp7{'jg#sQ_MKU[fĐQ~>9{^|R ?k23s μ}Hsmb!}OSȜȻ,{tWS5Ee+->.wNo1>/=U>v\.1[rWM/.Zl)5>q bO+&臐L*90˞9qj)u0ڮ-}Ckb_#Mq+PZb׸ޮJSf^ac~ea'v؃\ڳORn6q @=W3_\kiF[> OXp޳R+aճ)Zqy/:zN0[__jzT bi"֟2 _t89H9;7אS~lh gxҟ%EB&^s8\3&Y ~Ă{Yħ}Ⱦ;jssq0o=7%sF/OnLٸng:1Z \/~)zt<;o';P#CMjՖ}|~!{_G>;|2$/~/y2'Sፙ/f5ЖA#V zל:΍x˖m尶[]ׇyy&"'Wʣ'(t-j5"G7;9z^X=S8nvZ6{> |?>o?wƧlۃ#>l1Mt9'AbCFV=tEO{Z|{x{ǏcOxb_ƃ !}#Mps9RTO//N|A;6Ƴ͸ij?4Y̞u6$1gW,Sι|n58sXsDT?16ϽyQ짎!4\v}ڗՙh>?gsyʝyQ0յcAmڻk6cAG!$\%XuYN]E\'A4S׃RBϞ+k56@dױ#!/&]u'' .yŅ\üfR?? \87"B! ad =as=} ukksiȥ=uv\\rg@S%^=k6̷C@^G ɹlgO mC>c샜}{rw{ұj֥m7SKn|ø^ S/7ƱijƉsO=Y圸'CsٹF(<jRw1?Ü=H#*'ź}خd?~b5{tkfc`Z[Ŭ1,(>h_F^;;0#a=c+;XYb.A=|kz |=F]A*+#~5>?xsKBkYgvpη7%Emx|s;ӟ,|0{G5>z}ۃ<'>Dݯ{}=>q+T>vvHx%o|oK|$>i&߳[ۻōuG0Wv_ }_%Xs0П_pS {Q%W)շͥ UԈf҈%Ev8?Ձ h$A !!$*UIޟ =k{ϻp\Kw9ɕ1sڐM9^9A9kxl8v`gKD/}pO.3:3מk 7'_~VK.XIoqEƾqsmzn&wWGQr"p|s O̯#OsMnIb_~A) y|s[ܧ:nuq :.Nv\C|79sv=6WÑr7\Њ\'R5Kv8@I3WyQ@>1qi?[mڵZ]g;JxM *p]1ucz+q$`!7ئ7)Wq1'`j AO{DSuߧ8ƩU䶍>n?>LEY;eY Sԣ:G8~'v\z嫜:21ޜjā9zHRS?2eֳ:xcf>;o ^f^$}ztu5q:v7]`?ᚰ[ٸy}ܛ yCY/\!ޘ韵<eB_F_v%Myd۹/3c2~Wc^WO=da^l>* +yY\]lrMU16rW#DUK`D|[\g$T 5s1jcw}p`boWkӾi<H}_CAK_o/O׃ߡ?¯/ysƒRPZ<,V+ S_?yگ˿ˮO٫~Ey#Q^ž:gōANgHE$h2y >|yγY7cϷ .8h{0>DZˏV5.+{k,{Nqq k[1ޭ{,Rp9}$O]b|sem N#w+p罐̵c3 UMFzn$@936/'6(ǜٹW|%Jho w"]\O%y`M;&" HbF#ô>\ٟ`1Oܠs %1$ȽѶ5`o?[~`.sԹdUP>3˨%CƔMcOݳD1BC¢Q7=O~6i"mf UiNٿ\.}SqQ87j/1}(cSE7!9EcnI\"ְȕ0qmrFEfF(grf{zr=CpCxN':9_`h/mJ^бFNEsca8ozaˡFN$r!C6;zєxi8 yqФ7̘>y3 Ֆb5q`Od3Pn@kS r=f  EɧH>V؂#7&\~nĖv,w/A-kMł7V+׿oVč)9b۾Q+W5B`|WpG~g>s+L<79#zĝOk.+xqwxv`#ЬbLqjŅvBPfp=cXyrzsش:{ ;ʐO+?@ڄ,.< `iE,b:gG1CF㓡EfkĖv&=b}ߜ˸Ľg^f/kM&<35f8W䌭(+j5J.w|%Ͻ",3P$!3 ~-6 y h "D e؆?=`nɤ3q{ҍڄ-;s`cGQo_>S(~>ybAծk|K}ŽK25,=i,F.w-B_#~Rυn%;X͟x%I֦pVLq8\SA%5k9sWY?R3mF.:16g9 ]<hA\X6U_uC:zذ%TG:?\jH}\S:sS76+ie.'7qEa#{찝< stW oόB9#rkPc~AA} I/PG7VibbCȊ*7 iO}|ӟO_ugr}O9T#@e|pΜ"2^IqM45aKO߻W;za(h]uY'P K|$A{ϐUq1~`z%gNk>lo^nMwMڻas ķ , 䎾 Gx꜋p3י8+Ҿq~gO߯_>Pէ^4Xd4{Minp(Mp !Ԡ?׿Y2Zw 9wmFJѬCI.x9HC0G}Ʊ GWMbpZ[IŪG0񗵉X:]3-ia_-}Ӛ596sfGZ=LmO>|gv4F ٭m{&E<[q\Dg&c0frqXXc3<>'1M[Sj]vWÉr1,}&_C]'f];ԛ}+ޚ&9g|Yu݈<ʭ4ߐ}Qvawg\޴&^bcs X7zǗ!1iOikofOwE`BNf[:ϝ A7)o}aȂqEl&|Ņf2EބfJ3XF33=;Z?U 6oh]k{z7X٢H}DM<\a^yƸzL믙~#?0oaY%Gn+|\mέfy/{&nQlsR(9?zZzM]j'0k8?m`OZkU'vA?ǒ)E>c;W˿Ѹ㜶%yM<~ȏ}Insle6sۜu'+}$tpfMyOe x`:g} ćvgztUlڣ{aEEt[lvʔJ9Ӻ^b,q0|G?a7k1c28vl`zlaIs 8^ f==-1N2U gn2>aȹwdK[fݭqx8ӌx! ޶[? i;ۍ&ASە`?3&OTB2tB1X/I'x[dW:^tB^ R7D11_N6Kd:/&WyO]8NE}@ ;WfƏZxEݱ򫘺&XKsqr8[=sˑ]9 -z8cQۡ=KOM_j3c ޱ>w4Ϻeփi1Ⱦ9;FwݍxJtĹy2ʯL<8`X:be/V$Nki׾?3ɤO+.W7zcKns0oQ2<7R]byd4p%o)-Elv۴%5?,3VF5-\Nj?zndC 'q?x,rB ƪG\$KLJ` IDATo0\۸/A$ xWE!8ъÄڊMN8~ss]r 0 L>?zeYZ>''b[! ǟs|._y_g8&$j`ؿ6yy'cX+lmc|<3'fliQ4eDܽ.mvkwl\v-Lk9Fl=&gId,}UعwܖoyJF+uvMb,$Ľc`5L ,hƟ972sbL986'ط(ܮSe0E;7:^y x㱵t`G>jv딓<"nM xd=4dyPج>`51ctDAc>939nGaC#fF&tF5<_M΅κ^lSOp+FJ\A챃#--I +d9dX},* 8:؈b4/BxfvvaͻB Ez$뜘 &n{tǷ8<ljl5C ~;V\MUYZofKe&1Z)w+}>}0x{v;۲q1SSi*wO cE^'2K>O /}0x"Γ~w2JWiO\R5L۴̘8eׂx.c"G?!dv^y:pACF]`WrrA=XڕokZ~^X*~_溔 g|>V"Tߺ3n՛$r[NSj | xc}+~[v=>_v,q1lW9Gppyl E^Bμ`Xs9!UB2ܱ5yLCloqHl%'ߝ>3 j[pl]O~ʑy|,Wq`-uREPo>-pKAxw/Jk1㤼vݘ3?fɜw$4EbL_|r^cCzVƕ߱>7 \8HLћZ5}cQHsgxȽ[Aa)m [WNj=3 g;։+-?ѧOؓٴ!~zV7@s];~MSQ Uw,W74 )>wZ Vѯ.z)Aŗ~A0NɾT$?cD˟H_E""%3_/05wL¯5=W?'_GNs}h;p`&FTνty$lٮqj'Pph?ǵhg\;N؇.S\ C8v#_wb' r.!5ӻXOl&;q"J(Q]Y=muȹG+|f;:Y}708w?; }/Q k|g[#.`_[8tG Q˦1-N+ؗ.՝_=L^3d4KNllq]xA9uđqLKKŀ%;_szj_ѐ:ΌE" !hǭ&,'}{CR:y& +9NLdԓU:L|xw<->ފ6r }đllc\\"O|d+2Y6,ǫf4ލg__J)c)0s߁I3~0^ó}lK"8sKo{/<.uD1Ŕ8sz}%pOLs]̅9g8&cx4sm ]mG9NȒgH?^#P^ s`N\ʥeBx<.oNr~U,;rW6񂟇8?0fL>D*gHO? gz|8>wM7 }Qo~sw ѝ&NŔ"VgX`eDZNFxZ /[ؙ&2Xo>l;4 Dlb㙏]@\מ3$ᯁGy"̚b,kҰ}vO]%rYnxk_.@b?y:~'JE`?CdZPbK va}go}活v@sW0T-q3QGn''_6O[\޿q0`(0"KicEڕ7ǧe;!_:݄ĉy&17Ǡ2bG!$L4BHbs}ԉbG,zut j̗]9ֱxg%뎋2̖#%Q=3½{ Bca1'殹_XSb~ڱ_3+1ǥB\2E_5rS肎yt_s>G~_&]3v'_:2 _z7U0n2as|2bɏm'8[|( ݵr]Muꮘgr+v䉋e_U\:  C̣[Mozׁ7zZ7ZC7;Snz؇7hU P&iB~q*+D5uwB\Ajrc@k?iͅM^e uY_vZw;ܡ k[y|/zt#׍7-w9{ǓO~7xOy>),OS/rEpkxL$)l>!iѧEoN E΀s ܼ3xrܸt|cy0>\Hvw\Y~S\ԫ`qonz,1Ҷ/"WO 59`W܅x^v8{A$}RWUEPlL[G&)1:xo0p)1VҊ%s\Aak&1\ha_jre 3n~ ɦ܇2N Fȱs߈s.R= G&)F\O\&;/EnI0OPɕ:o}Kpm'+ȦL}d}x<>҃ G<ڢ OHl^i<4d4p|dÔd_YUAg"˱X dH?P,ȍGrFs؈Oll~(B'Hp;D>YQ5@M?yn m*|&ÀSI#2֠/ڽ6aمk$@>S$+}pZO*M6iA H]K=vcsn}uݞK ɘF|4Ŵޘt^᜸iηܻM=3X9l63Sd`9g?0-R[cpJ!8_w&O#3ܸa'M}kbbx{тE}2ܵAμ_=}xfcpKԞj fPJ ]m*3/3Jo/?==_|~>~nFi(}?&N5_(kbhᜱFL Dh ^],SqXLWMA\F3q.>uIo[vkQIcT{ru ^6GTx5^|c_˾֟Ңv}uTn2ʡ9sq|]zT)V\5^~~~SO/yK^ˆN tl_6W@/ă=(ߍ90튫p\ vd {ǖ>2c)ceW6r @#M☾"\q#?Yg}8g4KF&r]pӇsx`i-sh lk>95VCl̽82GrcmQnٹS.>8Rg;Zؐcש [s+wQyvHg7ĘT^uJ\5ޥ[sy?XNÂ8 leZx4A7 \'s] g>f"UCA?~X_c:[Sln[c9*Z)st^0Ǯw1kw>Y?<3R{l߲}Q}0>gC&.C\=6#\i|q"`6XV@Y,Vl>>ex:yk(u׊G|>D؋G _$t`k.[jln#6:@ǚ|0i>-T0H-ǿNMabdFٽ9E kb .q[b}cޱM!Rر$FB9ٔ~TJ(Al'-,fzъ|׻ޡsfc? :0 rf ռv#u>Y*K;#ġ鈤 hn[*gsɜ>u2w;&p^prܿN;NB j8\koiDjt^{z`S;3cGB->c66 ݔ1R,92p3ӃM>eFT"-õ=ꍹ)Cq׿p=vRSOsn?s>ȩ{b{﫰 ṉɷ+qW'[qM _֭Z8?ĝ~۞G[:suVZنѮg>N}+w'O8s [Wyt=.#}1(rs07 }p"u ~2W8.Q>ߴ}g{E Ȣ 0ccMqt0ib .k<՗^L4͋֫D ga"Ky+~.Vi ?1nA5[C]Y7 SEWAd Jȱ?Ǚ+N&@6+' x:[vקyhtj'<=LLI=յD>lvgx$Cp7nf:N݌c z`EpŎx޺y ɧ%N,n;u۱No縭As1HzD,?36䉇>-k_肘}7^4K_h3X}K>#˓P O2c$hNǀmɄ)Pt47|ScB\(]K^XբLy+꩚.yU Y eD/ d9g╯8~o=x}GG]6sY\̹_qD; F;A=•t߱#.ȭf4 S?MS+33rHkԢ]f5l2B/M,؈ҥ7qNhx8Vo(84nĉS1Vb.qFKs^Yp='{u.1I3p]9ȗq᳽6$7 IDAT'׸g. Ck^?j<d]Giā߿mlGηGg[ackx깾\%m [L}+1k#n~gբӄ5)M1cb&?ϗv!츌I})l:rOwEpR#y}/.~ :hͿ,sa&}3QSy_~2Ok;V('['df.ϘQxN|1ysu_V,;\O,&% |y▹Sa g~w5IRN>\˦Iu9_]MyNO.y;6j),LS`#ouZ6dR:q9RS]^Hv# `&ZjLAǞ-S׳x=qĒی#|8gͮ\ek,#Qp8~gݮAl17bj@u߸˚ Nl9{䥩5H>ąm=1E8oI<!~81Ke>cC-i{-Gx?Ė>}'O[1ff224yHsպm|lln\fO/Y1 |8×<8yLꝸcנ؅ck vQ|uVĿX9g#-N'vS _0ƹi*t_0;&\QF4 vugLl32u D 35RL ]ώmo0xS¼C~NO^ϑhZqzyaSSc@:R Sc89M5IRh0ma@݋jn΍Vz_8217͞xⵝD똽V覇M9L(&E7@z7⸑'`Z lSu8Kpqه6Uqaĸ%f 렛 P} 3.=5oPU{xG>_b}?`%Haˋd_41#yp~SYY]x..Lwy. ?vM5@px.qN?%A^E`p;r%̬]l|B/ +Z1]ͩdgڍ?a R#byO~;7ū(44̧1͏8` CfzInaSE(K^:,2 V ̰w'i[t-"7x냩sLnPjqr_p66k,Le[}0DGP =M/-6ۇFY-kر!5H9}a[Q`'r>8b3;rz`m-uݵAOSe@!Xhf15I^ Fb{ԹQrkQWh֪%UVLYhIRb.I8J1y5)Bg/Q^oYMj`qoYeyqߌ)? |sSx$(\d<:{i4|R+Wx>K\@ڧJ[D%NXIzg< _8~7~?ܷb>x(F?;oHP+ٕsqnQ1 N6m[ցpguΨ\E:pC@|ݒc3UbĽrw\WbO:0#>=g X5zVc~;,O%n֏5G/U>ɚFj#X-?KuFկOd(e uqɖ8׃??]'?#?rߥKx6kybH%p~Ko|kǏ'z1GձkCMKjge_,$P,y5qaQ\|c.](tCk,)EA]:2_KSø,wҒ_#} ^\M^)ɫsCXXAPZ%tPHzMj>q*疥5U V5bR{)煞B0α|:؎v+SE ף1QO֎>ܼ`yF\Co#}td+esn9eM=Xq `]1'7'dO۫7xOnB;rO:_$Z?7oJM~D#b;ݒ@% kLݳ.']+8BO`%/~7Y|TKx"`&FƑ1rjLw9H o8؇v(8ΑIWdwc<nHB7ތBu?rNx/~c}tNNNʱ'!SCi4~UIqٽc߲~s/Nm+|קKxDgw]Cđ6Ou\odes(j+*>Í. [`{n86sͼ[:C~;7ԯ>_$8(q7NF ;P=&X07쉷ׯHS?[>+JՁ}Pkq7.\f=q(|8k<ѥ'мMcOs>y.U|'?]oJ;a")v#slU|>JuX*ꓟ>|'ͬcK<)D#JAҕ>$W]JqٟK>5~zI}k.r ;"w>iBҗ 7o_G~=/_^_jC/.|)՜ b;G; [Z8#=/XF]|=N\ls=3hrƉ?ۯwh_|p녤,;|JݔaNاٷ]’!q}Q~z n= OC.WGlB> vM'Wz~+c^P1HY1՚mS}ϐ _>{\ەGSwk|>XЫ): ?XJ߁X:/JL/^J±@;沖Mh]Q'\~>p$6»5b+_CHღԋ=‘)|p:ɥ/.XjjVc'3gsK'a$B׸̼sn䍡U|Tۊer]\ LW39€3}?R@?2AoXV0vne(Ɇd—o^8;dǜ=i̲jR̚0NCȲXhO>^i )\c.͖H5Sw"n΋$ CgjΘ:n7*9'} N霂:'+ynu)OW[po9wɦzdlC}YI[1/Aˍu- dtZXoVsdŁ|%xD|$dlL5,OG ͻp-?ounyMe_谩uC?Cu#7-+CI.QWd u ń B)L$fo~O?[͍=+_zؾ~l r&Gjp}21Ү źcDκ6PK)z:ƒ}/dUDYZp!,L+F JjL8 XS_UJ@+E^Nj`*9ʘ$G bq6^5{ZR*'hoyNb'u_ Kj /yp 񵮽e|}[z맟>>'f,qȘl _#oZM)ν?U#=w4W859M<5b"?fO, ۉQV*߶nPS&Έ:"/klwS/5tic8yVr<0W1$OpgDPrg!u\%T !FK|Ex’FDlvfR'P\[M7ugMuOe8yMAчo iԖNmc_nG&mOҺ\)ktU< ?NJ cHB{|=e}(X 17Ǧ8?/ͮ+AJ-sJ 9\Eb<SHv}އEf$  bP 5~sgGWf3N [+7*-(KŇ,h1lu SlM&_3?0/dݕavZtM BcfE裏HzC/d,gI 5q76pZb#`O?s|j?7/2>E{֞?pBZxA.q !KOC16d ]0\";T 3.=Dz(b~vsm3eWl]vKHj }o<>/>pO׼xʦ #1'V3[MS |_OUcS9q(>#~c'hڵfÊѠe mHȅG3<>|LL| |jo)͒qmٝ5*jV91ۉcun=VRU{^%>& 7 SӦW.7q.67+~3ڬ7~}SK .Ԥẕ]AW{'5׽u#|¥l&ߴĠ<~ri|U%'_7/}ǯ8~?}M u[1?ϬM%ObꁬՀk|=\Q#Vߩ8oI ƒktW|jws w=c/So[p}è >=6W*AFmr0oOy i2gM>Ĕ>Z<|}ҵ5pڮ1`}l诺ot5K`(gF:)&7'MՉ.'ct\¦62p![b/fNgȞ'닫7.>ةf](ň{9 8l|-X~ })5aԨG]ux3O}\+KSGf$6^#8y\aȻ3/cyBsڗ2%W~!5Qd1n;_c=q.PH{B2v `>x #8ʶ.ߨ 'sCIqHw"d+o 2g~s,wp7&n,7gؑw%Il /8~s/9-zw7y+^Q7_ q.L78Wg,Đ<)jQ8\UG'5:ptxyhݿۗ-fZR]X3d BDqrwGLdu3أg5x{s}cX|75YWmCfJՎDXYN5vv ׼ǻۏ/|M 6YpPx'eziNl2u7U"y}\o 0TªNM!%\ѥi;6FZOlϜ*a0úq7OqsI~4Cs8"i5͍ R<_5p8ĎtC-?C{#O7ytS~կy,XW_>>?}cMߞmY$vzP (+Ԁy=gvDWuLr eNtzZ6nfg#Y0/z{s{=\r۠G'Ct-Xh]m$Ye%.8=سɦ&;v3?ɝ[E ߵA9i拵y'<{R̖.,Ol}e \(ʼnM=~|"l(`#LL|)lg{jST $߾iԵ.va"jjױG3§L,۷MwA{z#OD>İP>EGW[ل;-394՝b0 8'c!ꎅ#TF7JHJ,9槲ME'e쥁a8v>֧igO\%1 Ĺ\3Y3lM:W(ђ{0CdvB썈ߩ_`}s1GL/>3Qvك;"h}ޠ9]h״) ~H=) (b/__o;>x[rQU_ ȇ?r|SZ2yŘ3%W%nb¶ {}A Uy18C z 8Qv굲&Ϙu7{FLy{j;vagdlۦ!)ZZ[8ц\^&[3|¯TfY{BIOfmou㏛/yKLk̓ߎ.jj#v|+??گ/dXo&b:&nٗ?ķl!+ήz6cɯ+7NxhSBCSO7bƂ&ɦ˔XpK d\=N.3nm7Vx.gG&_@Ϙ' ǖ5Y$c@:xsxyE~l wMׁXWϧpT:N{3Oz I&>Xs̒ Q7/".3:f)1ad߬GS$x iw$r 9ƫͺ1=$զ9\d!0&1e?ɁFNvk]u}Ơ>lWd Y\BYjLO78eƤ s|"Hl2Hv|>!cQyB8|8bukLۣ;7|-ȩ6HvKO~uSm;{hʲ >2}4:KӱC >8Y> 9>x)%_t2\EHV/~W"3qr?Euz>tți-8Z'_'W"ѧ H  xވY=S%oy[AO|x*Hqo;YBSu $ks<}j_%UzS9]챋+e48s-JMX `߉eqeE&IC$*E@DykU?=FUTգ-%(B(!H,Q@M&t|挹V}7yZ+bƌ9=P iC\$C}ɕogCǪH`#N[F_\?xE6#Olc@n5SC[<< x><~׽x+xWɨL䪏˸aHꍱFl7}~*K_>z;w׏?~l:gyݷ?>9|o4Q̩ʴV Y|Kn~ Gu|^0cE>S,7uƊ"{_fߜ=JJ ɑɻtRԺˌz~7ѸsIA>y\u(,C?Kc]saN9UCP)^[D,Z.Dh;V+cޜzi,úN:6vcp[gq\}shT7Ry;.}k+ܔL /Ck=uRb;Q/2KG1nŔ뒑 XKSc!._Hĕɋ5>͡eOg&&p{'=+rK\`ǬYv.Jć;ʼn >c>SLmrJj=e!:k杶0W+՟ZÙv_6>B=>1׵ڥ߱FD$4k^q2 r3/@s\yu)Gkŗ ׶dڤ`oq95t,^@8 6bk!]KĬW\-ADӟW=pU!pKܧў̩5.:xkRd;j;!fvw/܏S_TgӒb̉m:8ߣc>Һ/e3:سyqQuhYằ~䧎w?t^+e^51On4L?kFgnںPnRH|c&& Z萦>/ҽ2 M*q:/IjJApz=ƚMp@ehs)՟kWJ>k_[yENئO㭝uV]4\{r Ė9[߮)hc-<4%枵4 \Y'6Wlɝ5~퓯SGas61<cztd9?G-Z*DcΛvYu]8Yzc+1hɌW98h֣kSƎ%`_W\SKժ=O>a.U ?1v33~_ւ1qYƢ'߈==cHjwU{j3_z`ɱͽM~R]ڧ'{om-gwz>Ӥxw\ ~>LF.]D<:k1[bTx+۸ )_HX켘ǖyb}FJ|+]t\\OP堿S*I>f:_. \pg ^L3.nڒ /͹403ܘ5CK;v)W1oٱQtX23bϼx$ S[c.t,1Qk1VdubL]_s[٣yNޫg~. `Q~٪C%|5_́MM`n .j<@b[e;׼aqn X5u?p+pHKN ~s%=ʼn-۹9w0u͵5̳mU{۝M p+[;-,[wzWzɟInw/ˎ^`fɯwO=#H-q^}Ds)O=~}?җO{|xX\'/yCkFv~?ns3R)+a #a8;sG)OŽ\y71wןs&+Z]_k=[0HV=$|a.bȩUi*7z$s zwհrb;33RG"D?h󰛱>ϓ/L`ivMeY"?E$ fQ!3b}~Ş5\c6 vxЦj+v< f|E NӖ}lc5S T)Ouŀ;G/s^Փyu%_?񉽤m3,Y8@  >'LNp,81Z9. FBX/OaL}[<%FTlYlBj>bV[$jnΝK *l>yl}3\c1#63lcl]~8U|1So8׬<ΕܩrrV(&ŗt-6o)ܧw:W쓇N[j3:F\֣>ռ.ғbv \hW,0w2?9߽,dOG{pxs~ף?k\ 1V30SSc*wsGOg3B`Wz5؞X.ԍ>Mw;#kP/z ]t(w27!η>>?s/87}k֏O0G$[4;+!>aVyxg>ǫG_W_Տ~ڷMSKk\5ԛe#`JhZ !D†Vwy64֌n?<lj'pSͭYwG{*4coD {d&o 5p3u^kyuG }pTxתU?xw_D߅g.F1!:ReM902ڪ ]*chȞY9@AY9놟=nf2|dֳv*酷j;s}8&vs99Sýp ~\l"F?}^=wzkpOZWɶ-\.lҋU{L op ^G 17.߰OuV-":׮h0h\2$Z21gi81a<ؤ^Oa1YsQS3&]3g5#}rƧ\v\ [th;_f?k'#g[c8^_!3gG7{1G-;).^s`0Wehwǫ^oyRYzgU5xba4ײMZ?Oы== oz_JD-Wޥ]_u vP ?Ngj*$^gncgB'o(x °o>(¢\Cb0f٦ǭ?9d&QKf]C:0.uΙA7dިdrM" osŻcs{bŋ__V?g?[?|]밾<@R͛~>=u-uW_ֹ׵ ZVﺻEK#F&2׃Mh'_۰{IKW6Yׇb>tabLuJgqgW;h/UO- ?z>@Z5X6 _XԜT#n)me⻤s]"|ĄvN`ٖ~فȶMn1w=cO;}u819gŰOn֖u 5QKR6xkgM`\ZQU$frSԦ7#օxl:~j)pG[-Mәצ{>39UOj=aϲh9@꠴|‰Y6H J?_.}FH sN.c.yI}=k՚E[uFlpN_nYogu!lWrygs=vk6I|s df:'z+m8-:x̅=V'V7VP*+n6@.;2f'?ם0Kizs.y§/a-:ILD#X7et(B-<+HaNnPw0с#ß/ZY<7_K?lN^7nxxYx{z׃Wu 4IOzT'}?7{^|Ͼ@'/}~|Br]?טsVzpoA$?& 3j\<2Wq^Q6Њɿ)߉SuMյZCl+jqIQq_=}".`_lyԧM_8^ p<_sġ9xUh\η}|<LJ>XFַtJὯnHY*#պ~ \4I{Ú^[0؜Cʼnq>f㥡Hσ$y'v昘o _ty€Vs|N#6zX~?G2ej&_ 5V3}*mm7cfVBpl[r.BE S-3\gpњ_y39ϼeNɧ6Hq=%{fQı6|QW>`'>z~]A~d ezh?k׃A\bcz: W"Sng02͸pfko 6x;.';VU3O@3 3XMSOBsD?Fl29M'q)!/Չ~=%^3u_W`edf6V>`DON]$'M,s8 h|'B^j3IzFN}Mst* Ucjz[㛹 |YGup9 *:k|f9u'Gۢ _t%;-G4M^0W@-&߲Ӽ _4y6:k&rᘻFӽ ӚXǷzWȋ5lvkI+# tiBH<ԡܵg6jn:BJ[`SLum]gue]Ilm{~kӞxlZ:^eV2*{1Sf/ßq3\PS;.ƭ^H1-,>]˸Y©#-dN;O<{>kV^o} >sp`ؼ6y &q|)ou>z7%z? pW<>R\y8aZm_}t5N#*˲pv`ZDsXg8bX6}aH(ѕ:3ܥtqgvm9־Yl^w|KOCzNl3g}-yuOsQ# 01ًAؙ҆#¥} 9wi5muO."i[eS"K߽YG1wuS`e&΂eX>?#??x?ku-oя?ϨߖWqQ^ՙ_ɥ}dp)xgTzV޷׾ï9zC|#?@pGȘڏ|k(r.9YF󸅨ۀoLgV7u^\5d¿G!kasγcb[-}~lVoR w\׽ǯ??u<}NZhK4=|58Y_sUO ]K1=r&o87fu _3ц.-˱Jlf\ъ-75j2;_'s&pq þDC&Ƽ,AFV{~6a]R\Rt ҫ"FT!&O?_ķ]W͑5_4ײr95'b3Vޜe# e㟚]P%>ȾK\xȓ\ NAũ>g{{<57eG-_ _*g7c D_#|3ub{GebQvjÉP:`眓˘|aN;cH ojdc׻k1S\RU'1 K?Fz"%Oڜn7X-.c_zG6r&/6_&/u|7ީ*ݠIOȯ }yۼgXg/`O-=iuW/Gǿ˿TἬu OQ# S;kK{GGjNXb͹{.)qFhWKMs|Z7Ϗho$x gtMqmGs<8jzIU5sΟIo`g}_>h꟨ۼ-$ﲋ~f3a&|2i`O3+j+8>HwxWnW;I;`쁏w!2['{{./W8ibKՓhS5ޟタIH/pWq&پ= Yfߴ+c #6YDC|&94UkHG/#5'>ؙob]SeUgE(toڦ`2(e¹&x8=Iwڄaa{mFqqx6m!(K{%I3׋h%6p3 %qu4C1up}:Ś>;M1 B _|N~;q 4i53rpyί} G?=Ӭ(8{`q9,.@'~ % ݯ7AHaֺ|Iy 81ه?'8q4dg욖!˼³nK̊7f!d.yzn ms.;u2g-|3rbw/oSWWY6.Jp-*ָb|+i&q~E*o8f\3fe|3&6B?$ù9} X`yz;aBLqNέk)=S~RNSS Fuşrvp8 1CQt|bI|- L.8໎Z7\5n+(شg#7": :܍k;O,D\wVǞisqe-=1c9y>$Nu/3t.W6=(>. >x|=x~~/!R7~G?'s oo|Q'?ɺbCjˇ&[ᶎtt_xKx8~nWz=YzR~1/R-kH#xȞyd鄷}.9/?+&( ̬;6d0|>#, eVOs^Q7\&} _o)upM$yrRcO~~o|_ۿovۼf5  o_вo4Eo+]_M;O?.hy *>VؘZHsztb_ ZVLpН"Xgɿo_!t~vUrT<ݣdT+TU fՀYsO VTZcΘ:^KuG%>>0h|^gL#G̎*Xǩ/5^5]D/ekܘڮm v]`#뉙ضc&֚uN+-.lşOœ\9g}Ύ1wbOLf0Qx: I -OI/QD^4yW'״3Ok\0{9K>Zw͞n$&{n8 .O挓&_UWD̙͘8swی}M\y(͚kYg5y_K/9}/;ᑝ]^Hr}]kzz߶h Wb*Q"fyt9^>9{#cu\-71 c!`?L|craS>`2_sdkΕx;=xŀm`ܼ!;pbO-σG-ma]{.b\P|z ~b Lz_n ;?O?9^W_xG^*g%K?4'{`ֽXuo~[>In6K9#C9{#>zٌ6Wup|_;u>@qM]URM@ƴ~A_Ԝ3J% tL:L=%J/{:"}o.[~_nIbcP+=`]5u4 4u׬&׻ 6Z9f':q̉K}9#ksq OG3^.fa.W5ȣ?L-Br B5ʩ{4?|Θg|p{ނ᳖k7:LJPA34ܜ/kucw=;|;”IWO+/bk}DpߞS?q<z"kFp _pY_x{̬%cG;ZxgNgWLAD3'of6w3>v/LIJ^ IDAT VZTV+.Ǐ׍%:;q:m;[%wj16q.Rõy7V&{kafSz$S9y8gD[3udƕZTfcAH_yRStfSR]2<ۿN_r雳Ϝ15CԆ-{z>|| oCԷNyꇗ$UZ{s[8_Ꙗ<t Mk鹉 vnͼ)l΋Vo n4gH>|~ZiK$6^s7w?8 xؓ*A hMhȻ\[kvB1vGTu» |k_g?{|G??2?O$r[#2Ԛ+gX4SutҼ."." 犇ăYq6Ķ%[s(\ ^T]j{7 ɟqH!(V-xGmi=y__~_?謹˵}]rnz?xғ݃>[UF8n X;)F7#u;1Q[12>E%b3c&Fx%8IYT1bYRZzq3.dv\}s]X󵗜Ivϡcc{)Z7׊1L%|s'`ygN絞pM>|g}ɕύjl818k5>˪b4.=bӢ&-{c;Vx3ק{$y7ZЅ%ػ[f"jS9B4)?i㦮L;{{hqMTz-(Iz鉟]n$GjK_~"h 'I=H ւM}/.,(p^;9U9z&^chLRvn(750w;fccع rO }ÇGeǏvj|3k7O n7-΃7%um31=˿?R򖷾>x};oy(]R'V]rQ9̇nuYq 4_1FW ǐ7ȵR=: ֋CoEL +p{Q Jwl@>[6嫸?MN`W^Vw`\8_斳A?v3?z7M:ZױOʯxj:-ui-{b}9ySՔ=䥎muwkM/>8e[ۋo{#[>؍U9`nB'M'.sr54u$Olsc NL=\}.qL}v&_JLfror71>p̾Ǭx j^FZ2og{ϜKc1=3vM"1?ºkI|9%u^S%xR6ݮsr!>bkk2$Rr6XPtMFTN'S1icrxU;ɟv'`"om芝Ίnμ7r|^>7eyrK r23Z:n<}z=ʮ}\}Y-]H e˵x)|9S0yw MXgZqO~ʏ{!+uqe%3'?%k('~ȣ?]#?nFW G֦;pu Zj! Wж0Clu~ Yk?}jw~9T7hn7d#Q[^pG&l lފibEA@?4`zkMDw1Mjʞ9uJKD{|+;rkuVܾ 8 ?O'Ι.ZGs DcE(/:km[M$[z~_qNp1g\?yXDڇ:Gw<7 _-+鵜`r>ALYmڵLe^}ڋ`=ZukV^a[6,xk|379f71a_xS˭O+ZΖlxp^<:4?VGis9qW/F"=3Y'yNs}F9˜O(Z(9v \_>禃i%Fp1c i@k(N- CxC_74e$f8/_$OF\;1.rl;9"C5549=kB}ϝ]~.~|w]繤Ve5^~H)/z .CƥSFwQ'yXeC>WM=`.uvbk]l+f$F( պg +k)ׂbX9 Hqck!::s|Ρ}'?|3oy+Dü J~1Mxl,<?w/L结bm_ٔcӨ/\Iw ZSbS{"\WkIOt,q}=APvE'>suGX缯nyQTO?}x/>Z77FOCq.ja(ucOY3r. /w{ַWd3 -B~ޑ#L#eQx(:jλ؀"v,<5)vpV`E ){D8;~uRŀzy%/9߫3t&%9v=iy3}GCɏ;uWAruE{'WSnxw>tsQ~bM qŌ A|ou-W17paH#X;lqyrPg|{^~-CN1͖ۏhB՚ZTyX/ лWW#^%g2(G>s=>\/&O|1C:w4b?涶sv^!25sS~.%mm'g]14HԙYiz37y}zlen7{o>yq^ yDK3gep+=w=e 7f?G|wX,6ۭ;|'if 9''wwռu˳}ǩMp1kMPb/`2On3~ǀs* υk >1֝zvL0E G:),_5wAsAOĉ'Ϝ_lUZ?qoլ\ҋ[PC57|հj)G[ΖE88/x3q./p@Z FyZSroDlx2w9Oao#_O'GpԊ286s=)9~xWݡXiF̱?YX:D{`{R:͊i]̩S}ֹ;u #"S =ھo.+rQ&P\ۉKjڼ:04itKFVWOO^M MjH̸Gj&Fsv~_OYN96Oy.w\7MwaWoY@j׭[ۺֹ(Z3qaMCOVN#}bv?y^5`G.SO+x;N70treNe+^kD_vrS~i\/f{aiGsQw}'~q(G#>X_avaψofʗ0iur 1<5䌞$frf؂"b d Gxi^ea]zHR{7-Pc+5 tsq9\#q?̩k9m^Z6fZLw2vw5k!'҃滫}!g+cyke k-ްusr?Y{dͪLs^8}.X} O滵9ؚl^G]y|/5=̼^9^~pE#'hhƅ+3[?~ I__ȅsxf4w;'Q = 챱O^1qgݛSD2DP-7..v^bsh4mp 9o n NpݷcV4e{ڇ`;XbY +Z}e[|9#q79={ib9l}L fWy-킉I^9/(HHb7PDa#ڂc|ǟ׏//+z+8C18%#ԍ |ӏǃ/}/~QL| qch:XaiXˢ%d>N9u$Az>^bV,%˾?kw7z/R| gRccǟώ|1_p<~0y_׃j=3ncV~՚ {k>eU>?mV$d{?P<[>iT?9›ys[x7[s&/ѱgz~\c!bhzdn>-q~i3-8Ŧ^`\ga{gjW|%w_9ӞѸcӏwtzW aԒ3 w+T _u[vk/ ᎝ƒ.T07W,Ŏ.+ Xbt0ksuފ;tǦxACxQ}|KiGm^5\Uɻluq6CIS4gMh'UNy&crW;A9Zw}gGtp||Qy}F2Z:1a9n8GYWO}t/}Fgf7U5͛ۙ9OrS@7p.Xjw'^gZ>}9^o{[zի{'wߋSeV ,D\V$YB^=\z~OGKCyOTXVUcG$:9wϏXSVdǫB$*}uɁ)b_kl:qW֭5oMp/q|>w|~|ۿDZ*ulZ-h&pt;8 _۸|Z6]g'אzHlFzg0vztw^%+;mȂ齧sTO/fuƱV \]Z乸6ԓhֳG;sFsz컅g>gݯp akNbs5ctl <_ Y\c9%|Nxb~~CGSຈ{"\G͕4dt6qP.' IDATolpX>4fN\؉_rYWU6׾ƗsE=;~,Y;ޘ{L++ɟݯY 9|\;-}05|ti^:k^.g .P%4E9rTo4^dzz+Ȍ}\wy+赯ZS*T1W"-}7TAkҗ|qF3GC>O_??:^Wo߫>n7[_ǃ. 1O_?x |kO}}C݁'շS|o]ĥlmTx*۵eGGb>xfFtv)?~3}qLS_ <.Fs]{ % }<||_:~?ԏ殑972Cɚog"ӻ?MEjT(^Q򧷔3`DacYILZ( ғ+_ܴ24GJ _fW=Ey;/+ r'\ZumVaI~QPa=9uW5^Jʘ2vʽ0:( =ۙ=|΢@ٖk`0 kfUկ w e,ޚ'[/{/[[[GM<Qo'^^iIkQbٿ{߽fsl4:Ǚk]Ēü~뤚+ ]cKFDǶxA_s9dgrOƜ,73ʓ[_L<{mĭخkbvNzxN wcOo3Z#u7+'i8߽kҷ?ػ[6y#KEf2Oigi &|_o,Ǧ#v ו؂vR &_زc}5$oe6>h,V3>kZk];&֫3nm_p1YO^lNS j1s& 㞱w;X]]+k] .iCȩ)g|hO-DUsj\q}ݹR+zpGkf1]c[|'Y+侃-ukv ߽ɕ98skyvzLzp8[?UR/]cb!I7ΐhϓLB :~vg.sNH | >:3:&&~{4/ګ}Np&3wXkBwǖᯅnB/)[֚0|M_<ow=A=_roWo{˿+Ǐď4ki^)^P |k |׻u|~*:qWH}fm|j[ydMUI9zO3߭ߙQ_~̗|ٵVqG%{Tu{OO;0̹eJ]ϵt>bAz\JԂջo 9%|Y· 5엞Uِ[}X557p5tn5Bq=Tke1M{"ou MN_񴎎[raS6k{ŐFzv/ іG_IzON'^zu!])-W/[71vKW0t+:[0wUldpO{0yXu_}OnL5EmL`ehsrq+j\16k(4=7ZEOf,c:)19VhyK-f^)bƘᑰ?,sæiaDjY=3hLFGճvڭ/:9{b# r办|#q[S?jr^kElz#~{' ?[kl\۹>,|=71"zx%)XRھmυ~H6vosNsgsFsHsv1Gщ%w+8<oqb>֘q% ]]g"2+*lcg>Rj`|W@37Wږ>9Oɴg?q'@h"u_#~3,d{8;vO^$Ҵg笃Gu5{Iݾ+‡, ]`X}4 iL9xiL~k_sb%kW:Ńz7Z'\ F,\`Zμ%fѦ}f'~W|-=mY:yGz_s1[@W2#77T<MyL;{7~o?>TU7| ^.4g9_qJS l7O pܙ)G̾S{T[K}'}Y'kr.60aW{M̪:K Gl̶V'זkmp$z昵%:/\+W>ǹ;܌>sH=3s@veG^e^7Wi-Ɔi({?6S m+'{]C'uŮubnJd]i<8q4I_OŸ%$v9sUpkFŗ3Hn-r`8qڢelYƹ`#\he|:-/f?pk <^kyZcϱDcbϋ99YO< 7ݚ_n!'CZ(:?isy$I\+t'sp m;Y{~ϞjfNKS`ֺ\;$k'vq\`cĞg>w7z]|+'Ԁ#qOuV`Wmb'XԦz<{Ll<S޶{;6`^HښkͿ}m On 7>U wnܵ&+X{&`W3ۼwgfxZ3vO AD=ȥ9Og'-G̜I@/ۘV|x _-s('3'n["15xr+=m9xnЏ&PBz"W 3GK-5&'־NQ~_pn8:"os8׈6 )k9B,dQ&Sq[6dqS2!8캭SUcÜr{ymQbr4Kc-zxWw^u+Ovyj~Z8v2DIWC-w(z3Lnsu̽k5ien1HR54ILA1e69;i˹#cZ&ʒMgƕWleAf\cʂ|,3|_9gȗ% vƒ8J5jN9"7O"Y K&̕Xߜ=<rHYu3g7 9Wsk^9t8(&%r%!!zXP.D.qCJm%-ϐ;wc_([WEAA9 ġz3,TsgnJ94w]r;~Z= qYurݲl$Ok7:•yyyY-57Վ" |>/oD,l)4/D|@Tï`z_K;|wqէiP|z/vlj>Ci.^w?}./Lo",yp|уBrů yk;㺇8g?^~||9ӇFa]0BOcFVm1}{|ǗKDƬ\EPk0*Qǂܫ/Բs6b'g0<^,22:8L(`qS߈gV213/T2q8)c VcI\ьqu1|W?>9yp?4&F.~՗9kZnmun}S[s_׹1&iE9k?c>&ip1c8nC`|7D s`'Ofh_>'jh[ms-쪷4|{.J}s1cku$W4iT."G#S?k$o%EŰΘN=8M%o]XvޟrSRv?l5|Xrk+v軮5{)=1Wnyq8gc|_^>ѥ*jM`^xvg Yv\-#HyĻg. }1mj/sϙ .],+"5E (`9I,3.v eQbNDAtλ +nωoGx%ew.!/yks}Qxz\ ˲k8a V_kV1Y˖,1vS]SPpgJ(rNG!Fi 63NqE g;?r9wv!#& z3cC︵N+h&ov9f?}OK uu51UVa+;ܴjX܃7&83Lesb %<=.:pxqaH/`K>b- ]CWz'?y|~/?ǃy?'hH| >؏HNrDUEǛu?(^~Sw*tO[e |-CSKkp-{pbƆZ6 ]ȃ?K^~o:^}ո.#P͜ycNxYEG3^~O_sT߿[ߏ789׌/^{z3yƫܵn~!S4FO96q2e<|Mo96RA郌SKMio ɏca[c\LwY=†mжf8ޑ/qqd^ #e\^o1}S#%;ҺZ5x>d_Sʵb[Bdk԰B 'ܭYI9O{F[:2ijz~:s<Ӟ]TX9[ݣ$|Ǜ8w\Ik,ttP-LM5?Xy3Ԇ(`]++2 $Z%d8{fC>59}|;:$8cQEUOk2GVpB !V /vI~5k'F9~zZoF٧4ƶ),i=c>fc>ֳv}giwƗt v;1n,v_|; =rԜuqj"זygpL~u\+I:i-S[_|]ѷU1$H^н9?=y5kU-|z)>2n]5~Ë l'8,^zr59,[ᵿc7=:` WzGy`s׹w➻rfO;3_3lyuF9Wfo߽ͫqeZ;kw6+  n aya5>4͑zdx\3/_{p 1z‹h|`]Ilf5kSyLƝquE'vcXO3m Xz9ucض<&ZJDWޙK}/_cduIfZ5^P]>cl'ePe,e6&~lݚx?s:t>7L$ɳ*;Y7ipFžw"w-lrm3~SϰX̑=]yp,CZWVyyo#Ǜ}ʏz&țTY?9gu&FJY0 ;4__G/yK2W 7{JN1sis6쁙 _qv?Q]b\wN tc#[ŝ:ʼ~@m2Ȣc^vWت.#rAoִ|%ƕF3~ku.}hPOu帘?wq_ @s ?x(']gGpyŗqbs/{9R9h)x]+_s Py0}wu;~3v %CaZnBJ܌S\L?uNrBOV[:[=&<nNeJE[Z~ɻ8NQ \ _;yw'.G1v 75Lޱغ+~4u5*`J>Ew؏5ܮZfIqya7!/s;`6yϽkf;aƴY3kxX oU..&UqҚBսXf=s]9+5f%^1msZp6FM–uk;?G9uUQyF9sؖ/}`Vcsz⏽R{k{}h9{?|hk}AXw97҇jِLhc_&`o_V$gmҊ{ù:qğnqW5뛎ns; VcMo75/1|8v@Ul~bV2Fa%M\7ŀ6s-~WAAY^zHy<7yNjͤC-0njgF&a9˕,e(4PH,{Ջ\Ż !&~oց|u|%_.^y.ݧTk9CHvkG'r|^ԧ~>tqS1.{p?C=Lst+Z"HGNeޛ3- N̚W/ y棷#B\`ZUl<-V XGSu##lUG~^m8Q܅JaEZ'k2oMƭx3igiDYIA'RɑS骯3Ho\-ɻĀf3W/rNڳ5'K:EӅm]qq}rkaX({Z\x~(sc1y>NNGp/O5kw~l$rͯkXӵ{Z&k1;&x_rt|aA [ˍMw/8x`M: дKb=;_O}'_S_ߛ-D^n=njÚX3,sVΥ~5uˠ('RGwC}e̯ẟvrjV9o<1乩Xkq޽'Ac-Rj͕N-okZ(rKd's| ;kHp oe6Mϵ1Ҳb{ݠmh+,Ɨcj17#cc=UwO|+/]ps ި![?P=u@ܾqhw||YW7V˨Sl/6v_K.G3>L.֞5_N{\9`5eifP6{inԕHַZY>U nIbu:)jWbu,T.T?n}Bskہ8Û䓇Y^SGC~3Ι8|b;l*nkCl%F<=Y<܀W-k+Bkf{#1b֔=H,l4wU[ 11Ce1j#wޑ<_}iְ?7Z9ƌVKlb_*jb'5>n~=%^Ħz;1j® 56M9kwNm}i˚IuQKNhljʩt!5oj:W9Ώ}gƾmngu+ނ²p^uE_ڭ+n,Fcsh\@vla P5klvWpQKJ ._ ֒%&:[̝׻>;pN saw UB̌{I`yO_Z{-,|8:N>pGW _[g#8[*Wۡ\g"u fBJ_w元u^q-ͪSCb;F\짶;wr81fcuY+{k&N:<`͵ϵdf.^WVy{9}g8 &>%!fI0M̀,L+(؇ÚI,G 8ddw:ҚFo%iT3 +O`.){δC p+"asĶe+X3?99VFzZcU+6r\1aMuI{믘$- i^0\s7Z:8YtV\.6Ѝƕ? 㺧TOഭqVLuoc3z&ؚQ<8!5y<^aa܋&Y'9ɀcL¦{HL=ONZuů\LiucOjݜ: ^vk'OZ+1Wד,1R9bHq 5H5$K;do"~Ȗ5$bzx~]+[TA+#{&;1p|(QG'$7p4dl{?{w}s?Ǜb{<;zp|aH#9gZcTK-0#?H{_Wo{ێߟ8>gd iͱzL wBxW _EƗGg?b|Q)9΋4uJ %*82}xw/~=l-W{3NnoeE#3gz*Oq/\F]jGX⑏'p×z~Xq'WNǵbd` cŸP!Sg{}s #{FKCSkY ;Y9# |qp3|-j^%\J15/<JBO-mNo ? `c]Ǵj[6i/qqZ[Ԋ:Y~NJY["h5S.)\09ƞlͅC69+_+qa [zzZ;d=\ODҧ{c+֯|-1U\j\s]Nyf4NuElʮ.3Pk4k ~gaZ;q~>eGłuӥ y7,fN{kq;{<g \^RsL2>.>Ĭe1]~޻(b=jjy0yiF1M5sbe1럺\>c!8|%5 WSg=ns}j8p"x\u'kt'CCΤn9ӗl~gk@ފ '\j>?ՎlK%^Psʅ?^⫈j@^wS]W`_LTMiO'gYC/l?Wg-߼*i .f-2sConZֶzAԸQ{Nz6njSOɫĂcQ*}srMCf;cXb 8q܍7s''Flt͌S|̓5H6) !>s ~- Gs ̪q*MĘ3v`)L#7Skq[CśQs6OVss 3&R{+M;-!}m}NǫZ󊮳HIY(k\^u3Qo\z kzVRéՉq}ؙgY+X.~Yk̐+׃C&N ϵBc8쨜@zS {js,[&GmSF|ik^n=Ow#&~%4{p!jbw/wbUT5oIy/lh[\FS/[CiR33[{|9 Z.X3~ʋεX~C5]DŽ8b V.8f.h=Fîyle7ss#o㴔|ԛsN˸|u̚\qWT;/p?nvqz6V;6gWRy->#.R|o轾{V}72Gu (!fϣl/yXO=K3CZٳN{˖9c~=iُ:kByln֩lƁ>Xw3t跨mwr_Ÿ,1Av˽1ܴz]˽r5c0x/ߌױVc_g 'z*3uW>9 \==|#@.Ls8bfS1/edNuҙ/-/JwϚݲdZ![|ϲƎ皩f6sINHsuWʹ$Q+[L`(v<ߏ=Yk"uM;qg? ZU}ȗJZqr>4_cKJo v#k ?!:Ѿ GQY1mmDoAXY0}\9U몑 Ƃ8+#a`T:UZNsxpM1qJ}3ow9ᦂ:e;wxQx5cޞt#A ulX+9wo7o}[Wg?9c 'EwmўKM^܉E ?mߖ/8{w>yMƼP?=ys;zfm\wBsb2<(xk??>xޗ׿1櫞Cʋ~x~eczh=dtp'q)N| QP1v/rW52915uzbw g{Y&{v&ycX'gy.{΋\Gu~߈ r9c \s9=%"u'x=v;{]9؃AyT?>gʎ>7f^fn}1q+o/&qwB~5yY2 8=mO9|X%~b>9Ơ`#6~zo\׹簄'l!kualƮ_þGg̣~މݗiOjR]3>9]|t{ _3k9N tqU9<əMbزaHyosLp[޵,f܌+# 3uoL{.>-db+:=gy_k euwlx9Vc-e@^w)ƳAn*Y w̅89yт9V}ja=U\iny\Ia.b*nŊo>'di;9;`Vg⇧*SAW/z[Ŭ^K/aٗ߀S|飾+g93jJV<b o񚧆[~m`d|߭UߤZka} u?%;M٧Y+!Țg37|U3ϙv֧j2sk~*0v@VL5r^gl&f8-Z5/dz ܨ#]q7sf~;+kz|\%6Ed,_}<'gq'F/7БZX_|[Ϸk{v󀯯yNO_˿뻎}=5q[^{AeֲR[;#˜kuL#?ǫ[gn@xK^1∯)/I8k?ktm%:㧞FЇ9w%*3ȓgs_.ŒCŝ–=>Wi Y]zg6Va~o\-|Ca̡Y5xݶ9eƸúj*Cla6,l6YVٸNÞޓDLSߜYsŜd9 &Wvv 7ՠ}<cJ=>1k@7f3Acg<[ U>w{޷AKN:ψjE?Oǝ!vgBi-:}ZG1ǫmFb7nhVWk?ěo5g_C?B[{z+my(yV߻gMz&7;_W, Ys/7nvni'_s󻭌^ N/d\~o+woUcB͝}8W'Nu {D?Bl HMdggս*qYOruվx?}\чԖ?1ƙ'б`/Z<󸆋!v׋#Ӟ>sq)d~9|̧>ӿ߯> Ӟ_Jvco=Lj'&ƱoƮqޓ?Y \2EVo<8+1s.W@e/m s q^}U켗G<g}#Ϡ⧝xes +_{œ3$6|̭_W'Tq39ْ`?_']¢(<W'QSw{j2͵}-z>ۓRPqG,`Gd.7=J‘cZgAn[ZK ]Š9z4sygQML9q,;Zs/Ԍm `xcԹfC9.Y<κr{գG57~f|:Z׾x$HEy%??&jMk^{]dj$8?zPTigao7z@*qr1Y g4sL<8cbJv<~ p!8|*HfwMgԓNO]_;pŅ@­aŸvf+f `( #][ôGM̠'AFvtO|pEUH=P< շgD&۴~pK4v'%=x#$eHTEG#Ğ!O}+o_Ó,b/~|KϏw='s_Oά#Qz|\5i{#?֛W3_;3_p&~ 鱁wǃ?_x8~*?ۏWs\-;ڬ5%iig<\YC"Gt0$r^\<@]'_cZx$q$X'_ב _πb;0qX7ck BKCB^Sk՞;wֲ]t,Eԫ mldMVhg\qXscIM>K&ƞ_/Tp%3b0gjOW{q`U90c\;D#o߶MOA3?v̌˫_L%6#w}loC9͵|ĭUB1 *'q<Υ&'漮1T[m3P?dYדRR\-^*ffc]$=3>WpYțqgL^]9oyc+H Z /㺟7? l=>:ԹbXLIbsY WcG13W>xs;ƥ/d0P=u#uh_3m+wLj3Cc[`sgaPYWđ i!n3'q;o@egLn3b?#?<(֑Bn獼D̖g] PQV_g|d<7 VcYk 1~,=ُ>58`-.h>L^z gM_% a/O8 GO<ȦꇛT--rO;xrzˊos@ZsYj7l2 V]6]Yȸ6dhx)vN-M*͘yzt ɛn5=:_8 E / e>1lPWWs)Ey#|ы^{|xq9~W~?w@,_,GSLyUɚ:n o?/ēO__wk⣻/x 'Owէ(Ԑ@jc΁t7mhwp>$?7zɍ^nO<ǟ{}=?ǓO[c8Fts1ӣ9sO _z\ JGp.k7{93&/>Ѱ8gQ0E=){e$'O1&LcX;3ܓckw`Gً3_]y'5ź"'~j8;6n$.ٺFG6wf/WZνqw80RNvf_R~le=A]8K X7k\f.~xuhǑ<_̐W=Q= q' ]\^fMZ(eĪ{z1VL~9=[;ؽ?ΦzuruDyi֐\31Uߌ-]mMԐ|;9KZ.F吻Y浘9];'h\Z:nǁfr+O{96g#%3k󇕘NC4v-q%bwb.9;~1?1Tu<(<ybbng3b:sK/3FcX/"c R~0a}mWB5CP׎#C2O+l{̓Xy-_1;.W: *gCy}>rYgιw }b3z^Z&6yB*j;c=p7"{Ey)_g%C-Lg}%1᥸ b3/:b2C>jkEu؍*K9՜KHZc3җo >`VbNJQ'?.&̣ӌIƤeuسm#6ݯc?ޒwG7z;67CbhG em-ցt8>lyr>Qǿ/|Tн+?yUrji\MM "l{ 3Wcb1fF"d _ue/;vo?KK?Ϯ8!d GVٷE{>t}]ᗱ6'SO=y||G>~Q'T|h`XՏ^5o>p|ijw!D~]S 䎔{cnƠ.`'~mr-L*>؋30eBhpIR#2f&|Z91dzoz1?i3sՇ۳J3eN|o:hmUkEMҹqfy.{L"f`+V>Rzg3sO,v#xb|V[ɭ?91~fse [aG亹sd]GUUʕ~nˊCY#Bq=Fc{w9oA㘈Muۣ\X~T\[%8__5H-G6X'!>vg1za^ޔ{<\3cG&\7ejoh/>8G[R=.jxd jf137ߙjqL~'?cCTo0{3[56IKʋs3mSp3`Է66c;t8E[}Dn1zғx@uf LOirGPƛS|C>ud>_7gqjbVb>ND.Xߏ:+Q-{_3sgRz\Ws&8<5LzA[3vƖNA<+~7[rN,>>L.ΘԖ@31FJ\>#v]^cbl+/zշ V9i?q֕TCz38y]A5b]:ި؝OsꫳsmQx,<ȻT\*u&GY2u{qut+L(jĹ$?m;4TWp|!tWd92svz`2_Ҥ=3ŰG^ܛXtgO_Xhc[uTch|ib>Wr%5;zȺ)V=ڪ̐y'|Ue!ѮEajroqX+dh,Kz3mp02v:o+~V#ZuOi  =2&퉘{ubX+^E]/VucߛG\u|׵E(:k"jv5>c^sds>u58.⸹02GT*Nc*SB?ߕWNiE͚2qnfOÌg|vic{c<|^7ԛ踫<8}1PCJ[k>+}ΤJ\+_<պq.U?rY(g}G9ƹV\cr=]g^東goWRK5Hve Bפ&^l͡ ƠZsͅ"Z>**{yki>)[˾>5]^9v=^8R\k5#ڞm_|IxB&&#&o8sN=/L9C~){b}#Hka_\Sd{Kþ&\-9cr Hf<۹M:ᓮg67C/Q"1`кaCִ1riWvuWo懏E?d=~ȁu\gq/ =x ]y>虿M궿.4p>ۢ1 9\K)[^T$3ןzhwSnuokC{Jnj rךyssҿ! Q:9]rlmrgS:o߳QYҽ|E^72|ㅕxNe?|#bic7g|e?s.Skj#O7#Ҙ]auXy>cZllnk|x9򁹗/ƺoi3>hw/Z9~'+7W.x,mÇ-c8^O>mگk^Ou-qύCNM+fWpq}bi9ճ A0g| yxzcDFES`Y_֏r-ҼD/{,XI$gA9o ^{a=V1UlZ$[)UڏqJayV=hd=qayWJ2bmlV끹og=_`pg.0sKmI38kߛtM<;o= 89![S]Q'OַZ3!kIy6Ɂ?NLō|6 s&{:熮~@5c?N4UvK'hĪu5ϧu}{_ܨ*KR?uږϢwƬwتas晎;"K8y*C,|Us鲄kDVSǝ=H1|3~a׿^ܼH/e U- ?s|p/=~?wg60/"[?8͙T(.-_O>__>r|_E3}jſ.H?2|?b\/|ҷ4\WK۬7sֺ΀V~s^gBuxNk<`JW ߱\M}|#^\{9&]rȍڜ sݭˮ\bLޚ9s^jW 9s͕dH8o`A͐.& uWJ,\#?s֞Ĥej|ljg܎#3>>#Lv3.{Wly3/'ϡL=3=F˾6ԇ's4D>3mؽ&g`͐v[{g>q@8o6c zȘu$Pƾ΍55`'IbGxזBk\M6΋ʽb};\Ar5C,kxȔa܄ Us_y?*<岔K0a¬|T2m`33Jܰ5fl[гeq&|E?yVA5]sI$!=첵 tQz>KQ ; ?&X(.6旿{},Nٮp^V#q;xZ>YfHERYlրhS֗!i O MHa;|$1Znx2~'} _8Ϳ?__<^?p<+|G^1b.# }5uLN>կ|>s<~+pS[}G~qQ?'4v0 -}+ g4:i~k)V]rݩ2w/df݁M1C'kɛ5w_ jsMy~(Ը70L3_.&}՜=]wNK`Ń v]9MreӼlnuy#:V;8wrg85G|n>%rk zM: ϟٱ9*->Y Gxsaȯ=qW%{On'9U>llK])@8c7`wڹb=LT40鐇c߈K`\#>hz~60;O1_w.\eCR'vϦ#ŲS <9N9amx9gj>>׼Y97\_gף=qm0>eb>yjkה[ uP,}%XW{?~Y_+m}c~3S:F#Yjvs/h3g鬾j̚ ̋pj'xg5'2`la̋QsYwmO_?r΋M_!_*^[ g ksm ^|t2T5!ŵr&Skj xII}RT_q1U^"n_h0eYZaf??d+jƀwo\~A?Gwk%uuy"//v ô^\X2xgm]3WvZ53v5Pbɡ?z$O.r⚱u}]:!~ P3ĝ'.Ok@wHklSGjۜ)gZNpWMKb?U'gqc9~abX{/Lcw1#{51)dqgrrYϡ59{_sMq~8彧uO<Ϯ>˧dWWR2rS2j8m/1,Pߟ<,fB""b-><.̈ז"}s&W?j%hS\75gcZp:Ƒõ>l,/ l]|>n74+9/_OG'?vbڼ@TJ.Y;E`3vbhyW-s߹qvLNͰZ4 !_Mv WGm^gjEl zĬ&;;þM mB/ 1x{J]ѴjBpe KSm?5o7motn#Hɀ+bCD#Ʀ@t_ )*TRIR6IAJv%/mٕeP!1H[{u)7k͵y֚͘cε><v[E!q]Ӳ{[Si4&/ԩހɱ41 s#;kNqrd$'NNjś'F޼PU>^{L~3.vl ŨoMjŎz 8x'sG6_xeNXfAũT86_gub?o+1'1O]pxډK6nl813Ԃy϶CO }[Hv\E<RY3 wwq 5<_$2*s6!O'fRf)wV֍,~\$^{C7|#<֋w?u}NDlC1k}Wr?_}wGSZ]I`/\+/|O}ooM/wJMkYn0|ӘG /(_?pOyCuXGɞ_u1Sn=!fp4.#?'jm/Mc!K:ltS5&e^{[rȍȄ]Xc_uoʛ=/`U=usvhYxD,~xxGq_ӌǞ1j0qc;?Ȧͣ<ѧm[d0ޞH5<\;1fd@^s;!OD^3ATjF] {ݍ׋v9"먇-oI1(iey9HI,UJr.kv<&ݏŋ uٱa5:h-.`]y f SFZ눍68Q8i-] hÇѧz=m#Oݜc]3MXf[B5myOXVeg@X>}pS¸ XNG楛G16cZM=ETlW#4Z罁15`EaVm>5AS?dyDď}ihm3L?<"5on{3}wn˼=k0yIQ .&#n85i"xOCM'kwJ+^Sif0qQ0&/d?->[s̋O >+oFÿmvcH' +)>Bd9qZ?9wf+x{G~=u`>k8R/Ӄ/` ]ɖo߲ӼAuelN~ 8< mdk@gηۿgWg_@xqj}οNnt| tgٶ>0K߶ܔa7Y)CGv/>[:oi6VS?;׃/r?;&"u\/oo^}-ʽl8W/0|f`rJӵ֜)9Jz-ǵ=Q5r˪yP?ja313n߱FmhGg;@qdyy̥SX"$vz3>Wp v^;.xqbw]96hk_x$6%ȗcL}l {$>Mj27- \Kٰnw^e5J8tnƏ wcMf~IίrSRNqw=ï }oG;n.ת=MZ%V΅7ؤ%c[.}{,`bofXH4#H 'Fѯz<0j<YnKl5]Xc> T06ή#^`Dϵza4Uéڜ3G;?Ϻ>cn#v>&q/c|Ϲ~`IB=-/q:[okv񛾙x pSB(M%9WI_񫶕 [qاl_kXϲzdgw}W{e;imڙO6J45 1#&#6sеu{}C+4hwXdMM6YwIﰢI 5OטB}s( :qJ0xך}, í^|nvO 07簈PIxX}%k}yzSU'ökt ϶ [zfu.1s#Њ>23FbϖbZ3#dlhqGkmk3}E|>ov\Q] vg-E8n>kȰgO~ģt|XըPC~?}}}ҷ}_oS_֕GUBĎ,!*@MߌǮWk틘?\5IćX_+9sn̹=!yB//~Սr7?kv+4.`w_-pLܨM)t]ǙgauSk i{?:zWxp7]4#1RlsDy |9]/2݆Q3*ɕ IDAT75,1gn6հ"zǖjԯ!ޟA2}t^xpCآKYx0:G)׊*ƞx:r }iVĊ{،JK,/Of̓fl'?_SLdW}~Vlo;q0;ueOMٛksMp1Gwsdeu6OY*`/}:#]YjZ%qbѧVU6Sk M+XӜw> ~FAv .1kTDǘv@M|2Nk LjeDG8}lHw^ЇjT3b@cwt~eۯʧo?P|3#n۟_e]__$~B4 Dd:PSZj-oEkVz?f=k*5ZlU+7 7ԾM/;M\u>}H3_0Ӌ][bH>&.̑qӏ? >255@͗k:ٛQwη9y{MaC3E‡Z=׏]d;0x[>K]":m)"q,1F:eaD?1ϲGvѻ~pqcsEyt|a$Chl `Sjn#>|AL6'G_9aE03}2 \sokJjQpեI{m'.\sP i%5"{B# ֚+=6če,ݕo> \cy:\a*q9eG-Ok0qo80X0e: 1ZasyԦ#\|"Oo~p9Z&rtCI?PU;ޮVpKc5&YJk?b,R,,GR ]6|3;F:4-}dG:)pڶ<,^ o3ґoBNu:5GlPOlr6Y9^ oΞ_߯dMKGdk2;ypHӇJm)mrL _ηTK= $oض/#6<}M|6QE}E:.`1>=7%/Xʔ9&3[83>kx;q\t<:rXyINIj<1d%}' u/Q\ORbOatܻF}NM/2!ފ GˮV5ŎhR7n6Θ7a%9en`FDeܻ[ܢ_e:m{}>')n<>q>GEW~_r͊!˿~W~Yzr 9 =yٱrwpTGU$CZ5\ ҈Wy}9ݞ)u>ZSOӔ/$V9)FI7=|o][DN6r13}]WF]ksm7iX&n3/:=1>7K:9/$o#wzHm&Ƭ%ĊSpUU*5uPR`~Yz[q(\f9#]pC/sz>#euA# O=ѥ=_wܳ?biNƊ,=How-v-1X~5t7}Y=s#5sq02\$IJEδ=5KQpC@V$7U`R ^܃s 8#B汽 a?~M؁|ٓ{W)\9Ċ'&DDsg>XXd;NG`Z"2U,Pf,8cǼEǟ1Ͷ{Rw6ב)LܮD_Ej\u:$;I_zSqy7۵8m-ۺ$xw9&[Bc7s0;!~b3!sA\' t]F;A.$#7qZz KCu׸^ N6ڨ=gMr# w"ć<،#.O$ 4(yls h21c0%G9,˶'Ĉ}NŚ'SY_t+F0v~۲N܂,seԼ}>/1郬1ybrF]3Ղ .-,:ν~GN9+D 8k٦n*Ĕsw -'DZe}mϹL88\#q=cCȑYӮH9/j xy5JQ/rubp= (]jg%WaX7ԨģU ֹ\'G)P[a+U*]@`Js-vMC &}l3Nc+ʼnzg5:)JC7~r17 hw÷sƱ12d1Yq<ɅF'q3lm`M{lhcoL1)5ɧ9`c` 5{ΩOb"G@ 'UؙC<ﰊX%qȍ]P!}"G'F_l" 9˦9D5,){dGsS^qegOs|Zw]vA_r8KlbW0e*f>v^c?{x g{,co-6H.cNɶ [i9tZHPW!rr42AnF,1<:qNp}ιhb<1&vĥQv9{<#S`4/\^Ep,l! L: ]&@jL؉%)}gFi 3Zr5]!4o,NiXxXki8K5I%t{ķrZF$@EXA[x-V挣?^kC<ai}^%yplXh6Ac ,Nɧ%]r>s,NtA>qd'aAYuU{_ j˶|E(qpoț9ռ/m59J, kѵ*Jʋ]j#9=>чۣ4fl3EqBg?kc;Y>0Xy9XrO>q0,M=NtcXc,Ԯy y&}㞋mR5/u \o|Ծ~{4G"~n^my<Ņ9b՛1x ưZC8ɣn5fޢ5u`ͅ|7>Gq 8ǯE pK/a>|$_QsS/XA!ƊKUKyz.DZKm%#тe:YB)cp^v?P' 7dwe^2X@y|#u& W~-̘u(Oj9{<,u,AJ9,$Cg}d_)F;lf>2\3"kZa"Om߷Z1"~|Pmgܤ _$䔬uI(zϝi#9ƛsVd@ţ+`v}$/phFCf]k۴XeP"c^." SwV'>yϨuulx͹>܂?GkcgN :!=">y\wy+>>VMR9aH^vH,1 _teKƭ)mCrdK Fε0xFpnĚ,]d%6z?Jv9}dzL<^B2wl8.>t>^1=lt!l3V`_T(27XKX!oţ5b>5XV*Վnmx%cM#<~ GkWVA$cyBqt;BRzi<5;Ɯy18.~o|iN~+2 #poc'*q9 (E9.1x=)cTM}sJ<وSt=ϲnéO&91(B*Ȝ؋}ݶ_mk۟5\JyD5"/0_C?v{jƇ]qўF\_wyU.B %"W;  Um V}>mv{>Mbu5V"is# p~$ ?Y67!z/q˯n>UN,_Q!o0rnU$^Im{ެTL^Ǡ+_)\ˁ\p}0܏ݚi8)Jԉ,W\./@;Vנe&/aܶMFgRW~Â=X,7~U>_{qrbPwR Ym=UQN4wnFŵ^Q2cEx=z.vʣ|wmjgף]ݶsr#Ķ:F~k+`_|J1m&mNykn!}m,1dCLgli7o2Ŕw-9e65/#v|꒗_~52g3t8O}(qp!1U.<-ϞZ1:eX$Ɖ|g/a*|0Nx-Zȍ]11- =iWx-Lôg<ӐKuۗ~~>?s~w sa!'UɁuW ,ym(ؑSf}uCplT >r37/vȍ@Zzk{ɻ8d.-Zi4e)#FWѧ`D_=w*rYF5NPnMJ^W|jVIKAOޓ^1/86_ݵb >6C)4]gȖgSJ* $B("p۫``0]e )R2G9mg轤 ڝ87֯/#G. $KX*hV} {f:tlZU/|=wtsĨ7=,v'7KH"oκfc1>'WbEYhSzhX96„_cO6. ?F-ܵ4zxx#cN;O96>N-SqJ<'.qʪlTN@ g×yﱁ8}\"O,鵎~$⻑0ozqAE9eWޙo.'浦cc5Oyab($80WgKb^m.'63.|:u ~vmI}E*3_?<7ɧh@2w|sˑN>؛C[Pc2wկ~|OD t~앷ݞ_kG\bslb`.y1:֭С@G?M$~?;?{_oU&uk΋[qOm5]mK 靧? 770?xXw>H<|q2PԮT;{ڼb&"[ dfj]ؖJLd3#<;o@)wǍ?yRçڊI-0ޟLm&O'!n Ѽ5|tTo/=~ʷ,}/=nq-|rlSp([p7Gd?Y\<ǶkgsMuRgN$q"8va9㑑n{˲`kcl }~;1lCq}bnɎت`.=ƤgG1z$׾mr>A 9gl'@xG߾5} &սF- j`28U6i͜O| =_ IDATP'1=g>Ŵe~g][XByU~7\>ӧMȮ}lfxnEy|ŗS->8qzN+sSm ̘rׁln$+OLWP:-I˰wx R{.W q|$v&sƱJyt76#0Θ.blF<0ʿ~Q#/''Sѯk ux8w&ڏh:7xD$1"Ïjp\ $&aAL.~^D,bTp@chCV(>ʣh;sgyID+N5%1QX16:bTom#]1GȈ#]iRcmyNetzG6 SXS.V^坜59`8L/9Noa%x\sg|c(vR2n/q7mF-}dzyyYrN E޾&OxThU(lfuZ\Cb3vl Vs!cM\>3O,Ȼoo~s;oh_A} # ʍ[>Jn~ ) z?Hˆe܀|{{ٟ'>۳;@Ady:7_F:HV|yjM #~׵Bg/;7b͸1y@C:9l8Yp 3.ĐoٟKcN)EY _84)'ltvSh' FS_Ow\{ of CWGvKL+8pfsMVza&g,tW@_twt`| j|O'&(G~ۜH5@9ҐߟOFp'[=>xC]č]|ɚ%cR d.sғG6ʛ}>>'ƍoխa"o~9+|N`aX.yg &(?UJrGFy0~$WԣTD͕ڨ%O[-`#"y#[616g^ B'J˜cL))90H0Tk]l]K3<` kI.pp@3}/-d>\X-y(BN]o6[\.1eӮq |0]^19_Y5VNѻ'/NJE:%IWVJmFpݧL=+v$PaO[E+|B lʑ>Wۉ inZB<NޟrGp0tKj=j5vNϜ}M-<~W>i$ldciqKwan~Dt61Ϙ!OlbFO4|gmm[k6}#9<73کc,\ݬ#Hv;"Ks;hq=]1d8`1 cfl?™`z<yk ?3> >˸}1^{ w,"w"g/ql.ZWvwq{M/>~ vSRFM`yͶrϜ<2?sCO[`ΩmuH,tqDևsP3Xecic)Fs{O9Gc_ĸj 'u=n,R' X$ gO޻fȎgo`#SrK\@HC'ӿG.[c/<^84mwf^X,\[ދ񞻮{뭙L^QNДM&4~@oenx^ 6}$+Vf71#񿎡 O#䓘W{Oc&72TaVλkw<ˬQx$ҵ"3zۜ lylY.r8 l^&@ _T%a]'憾[㓡 2af,2 {95MqYn,p+ <׍G)TW~Q2mv /x/H߬I^}#p_\蒷$w6Ⱥ]2k,/@ J5YO6~ x9 ;v#>%;W=8?WN[-C6^!|_rZ%>A8^x˿<݃wls a˯}Wլ/j B̘{cKDGx=r0?*anZm>0X^-Q%pWd*1n.'W9g\,],rč{ŤoE oUÕNnF|s|_lm\:wqNJbm_#ӵy oaz퐭5Ą{(©)feĈYd>"ݹE|@c,,`0 P #K̥x|<2>=q~ņcD]Zd-v> Z2Ns&~GSmN_dBR!d`w37XO|w cO?c[ǩ[cg`Omj=JXSaۉא%b康M]=k7_K;mm[|MSlZMNmxLθ&|< {ޔ@SK8- B<K"qpb 0(@\dM5nWz|u_Hm1pbNG]*'&.U(9۶W&rMYжl3[VQ1W|E+2զpě'LעYώ5!;LGw-A c6ZD?d,We ^7 ~C/}~|nQ_{z= Tg+5]ɹzRʻ4ȥ&O o|a.mxeȐ@Zs˙Yb$IJ~PȾMdZk:YCs!E075|%_C 1+0x}llXZ$5Ġwsy [WB2Yy wEE`p>$1ӵEP=\ 4x=z*G]?16?<ϸR3O=-2ƚi{5ؠGa R[a\gm T6TsFod575&^U/.X843jyO,W%?t#XɁ:^][$%}Ũ>q3(}hcĵ<;4ud|jw27^@>'W5kZ6STr{!rswS< Z`ŎX͕˘O |K\Λ.6Cp$V)>c=%ǥlfc.&FnO!|m /s1< cjaIZɓ2vy+҇Wz Y tOcq_`%-}Ɂ1vS[aulT~=A'sڶbl/˵ 78X62?6A`# mY{s Xw AypqÝ9ikiu'nZ1Ae εI^™79E0,ײފl;Icaey!Jtc_d5,3K;'F^ԇ}0dy0${Pli A9p`յlOl|j ҇T uaʧ&m@XZzƶgؑ}|AwKVӄ666Atqb;x^wtɁY󝗹#.M^5sp>zgL\4H+Hl˦9RJ+&K/M׀[؜stv]=b^?hwK5-RI97|}V_}nk_{cԯ / /p?[ jvmMej-< ~~'ol̺!Yݗ_fa//׏__['ǝ^|'O_CX ׺O% YetZܼOe0ןX~8uۿ91WW|\_mvy'!z^YIڨӒ+"a2v \XiUF_98;odkԫZuC/r)BMͼjɳ#='H\1!hu:0<5 \G\ū3g|`&:`1~̬Z*ClW~.b0M<0Q[?K&:svI.A/3L];901|~/yhveaCԸȁ)9J~b>4_9|G+Pmïk|0 &bxɛ/C?idaK j=r-cLH|-rWV%Xr4?md$1F<~r+<5BO)ߊ;stT *WU:k:9Feê>RgN`uPWU>=1y!i$$沽wi'( [tjZ$٥3ʬ'v'^3t䎎2 Zgko9sq#,8[ ö/pL#k"E3ew|7q1͜6m2݃B~.qD _98"1kb9 [5J=Z|ܹ/Y9ɝZ|Qp ghwm-,iUp\2,CXI0Λqn@L')Vu"|gټx_〩UM,XODb9/˥|tx E'go[ʧR8)o) 㳩 7/u|30Mʬd.ms/7A=u^/|Oi]/'}6?2>ugɴn+peoc^)0 F䆞_ \3_k|UX h/o?_q~M ?|s9@7A< Q?O>#?r{n.v;( pso_o}'&P}{,A=[?~幮^\|{:\xЧ n}u~p_LFǧa( ^NFWko^jz|É]̘X|ԢcО?֒=l1. =$ y89 5ekAXuxǵf>"v#:髧v|7%hȳtK4L MWTl큹IΡykp<׵E5xt [l'+4Ljzu 5;F: } iZ:]yz\ys4 y'vb9ճѧKLʒFcxHa ІۖB{Юg?ɒiZ;~L=WOyzJ!9:aAja˱F6yƳkoV{dx7rK~U(VA1&&iu©,<q "\7{b(P3H%|lSȮzeFJj2z>ك͕zo'/g1+Lj O})&N[osDs3U[k%v' ;^Ŧ 93VPfoT|bw.M5M|Ћ}}GbdQ/ON`8Yְ#869EWJvpFjϛp01:ZHG+*M8ŬbK=^1;O\b2疟~{;[8ؓWyI͒۲+@cwk.˶M_j<\l8|7:zdqڣ HĎ~ԝu>>q+6WاnQ\+cqSg}`h!:zna}?|6yQR^ 2~X-r/ n ps9kxJ|/9dر%w Fz(zU!uq]|su49G* o_'sߋWof]o?~~ ׀ovV n[?S/߾{_RL|;ߩxHK"ӵi\3{WOQNyހIV>@-W,皸@}ÞZ&>A>zpL ҳY?~Bͣ.AA. t6@u'mMvXw_qȱ9X$zS½џrOaO,4}%p8P'k=qI+WĊ?nRRY*'b2&_|筮F:M쎆~%fîT;Fm 11F %E69E{u&ydxgɎm{Z9dOLTo3fO fs..ιذ IDAT ;ql.|N›P=h0iYZC_FLE~]+7 Iy/ҷnb%n̒s8 M;?:ԄkocowmZbW38)赿kOoQv5OUsj'1~@T²{ )ƕy~S_zqcUj,[?ir_o,Yg nd^\>{ư:N'AΕP3FU :z4?j91]S Xρ0Χs2W5T^',XQȥ;4YGHϺUAmu5d6?G|T/}aaÓKm #l&;r{졎 W3NXqGzN|MԦ#?; fC^%XSɜNF@=@|1n_0݆ >-O1 6}lXIɣPrōki- /[[M^؄oD+^bEej}R҇~O١K[qn` Q ’M)uWߪOp,gZ8kRj̶-eΰдc>ܱ9\q412}OW6>4ٵYz#Farj>\ؕ*g +W3J n7X֚#{Z%_ )$g 2hG1)7|9eҏ&.7 _q`3rMZ E}Ses`WwwXn}fmm Gэ .TS^e>'zWY?6ֿ؊KGX5>,\e Vsz \#p9[{BWs8{<n#2lhg#MŚ>kLvNL,6cox"-qӣaatIyP50v?N}㔡o?2=ziY{[Sa_p`C[$ =9w\l1m1k#:8dCiq##dZ޾UorL}*{ņ]dW1)5Z cMztn~]Iu+hs#kdW3>cr>92 &;]Z;/-OV=__֯Bŏϼ󒭜vnBaC 0k7q/qO^umZÃO9W~L/`%@@SC8bg>\g՛𺶱] >(/rF woӾg\tMI~PQ"_͇}ի}uFk#k2 |!f}]yy\:7̰9/__LXG\| z#a7-9oSMnu~4G -u׸_Ї{_W]ͱQKC _;zQ{|~]3-S_QPL7Jhtοk~Uۗy4W^ 9޻_/$c/׃J|sXm\y\/9uym|q擦'wi҈:Yyu<5ڒ;i^q%Щ6RO|'#upQv.e EaϳuO;Ͻhm|K1ghm LW~68b_yF}'j&=y߃Bf𐺨c} 7O.9^ol8 M?r(VV5fͳYcctИ~G/˒1H#|2j]3:oO~@aT \ .< Ӗ] |ڡs1/Mkjsp?]VT *){sx{L>'6Ykzbկ}Ğ(CC[b.U,~^I:[f4<1ٴa}҃U~~pk~'O|ئ xؗ|#Ճ!v{6sOM!cF1/ @|қD/5v!8yb(/j).ypf1hD > ʡ=~]s ?C9~bb&odil,KzS1sDezNɴI,ή%bk.{6 qiر̬==yap"^{5{5vw! f9:Fe,w˞cWEo^^N>U¯AO$K2ִwp> y"}r)F;nyܘpVo+֝ qԺ'$Q5<ǸlO# kf>Fˬ0b T?Z&Sc~^mWZ7}V| sصm2[&{OcYtM,176>lNtʽ0Vy͟[8CkޅtY@vֻ$uV.$eDr}~v}M:_! /y>n6<Ȕh``k/&o,Ʀdnǚt{7~~nHկn41BU)W _ؼ|ow|;nem@|c_?$nH]&݋2.QrS^H CvoJEŌCI/s͂K8g9 dU,!yj+uD}\F[ic5W-kꦌq56O-xt,iG ^P~ 𝗬 u=i/Sdu >ųp=dQqQ+yΛT>9%< pr "e({pk_s> wyVps5-+no˒ZlFoin钑N5Gq6rC]]|kw]5A^i^Ek7,[\Z9 KRJtfl{[̯zשL_c":=רF-1n]pxpMI;q{9K>˖3x y&~$MK\tkrFVq4|'1N{s9BSt'l_윛6HW`d)~;B0$͖A< kJҭuΉ[ũF +>7ewɌmbb'f3,^JL$~ga鮽q:^# \颱b^9 HIR.;T ocs#nW9W}gQA)ifcqQb|ЖPoa"c296>plq,ɭ$ "!-[b+ʺxQF-_Ƌ,׸-eQ2߰#W ͱ*`vMj%'7*db;1"Pp~(Җ "R<|RH_i='؊I\?FVZCqԘZ0GGZd`61<7^EPV<#^텾f.\r.=nnU-OtEGb${6G升|vS)໷1yϛ?0ؘS%ŢEGٞ뺗lѿP%'K&R7xCX2ku%+/mow:{o/Cznso塜\)ܼe\o*fPoRU(wmQCZFkt-srP:oOnr Ya*mxc$NuK51]vB7*OSK U֫9R+炞75s!tĶ ! 5ƢZ~uw'%bol0ijNJ#\mCo32t?˧ٟ!y .mch&}ᔾM?9!7G(F`8/Z^G1Z6Z\`>N_Ilص5\\t9RASc݂IZ5nIL&|Ik=iŭ!ȏ`4btTֶK+Ұ8w܂|9pϙ5֊W>Ɂ>c8c/C.8Lq0l< hG-b+ 7J*O^;$!)GЊޣt2A*#<&7|b˳Aѥ/kŴ~A|6yg Vh ty40oNV~ih?cMLaS AmOW v֩7\c;k JĐ =5(v3YOō\JVyϚ&Dղq/ zu0Ȯ ~{hGCg]N4jt?g9,îK,P2Smv܏M!VI<*-1}Ro3KVEEmM}\ElP[\мgL'7όw-]s@ 5ʥoe8`;^>O"߲Y7j>c67>WaB>=&jy%i^L />ݚ+*?_-u](7nOƠs{=y퓟?_ĚK4s[@FM4tH|㥮qlV浛e<2+z=9Jر'95.<\rX u@u^o+m5V O'xT=#ڪo}Px9R){g{t5h@0A3&H`8T3_RJq c9U/>r qه=*kP/|L#ؐt;kY6Od!bq[o6^d.SRb9}_?mO\S:gGl<־HڭΞeڽF ǿ[#Q󹷣ks̄QZ{_}|ܮg~U%.ֲ5q[^=ݻR=\~W Yo%3Ҷ pm뺔ua2וS9SEͿ6_ZU#0q?mlp1>$/yOj-1lQ:Dሄ~y%/% OO?txg ~j~<޹we_hկ/~Iqok2F)^繣5|JX#l9DOO@,=\c "OŇiY]rB+X8;97Oҝ|^zL1-:GsWlZҔ6~w/%y Ȯ:+P$#ǽ8L޼,>Ven1x Ul=7]qDT熟+߹٨hX|Sעl;OǚoZ |J+=,qW{̮-ԩu睺 Ft .G;sӧȓ>Y+B7C4b-Lmj0ӏ'Wk^mhl/v9ć-c1 50>3\+?c;fab 'pYf3a0˙c?ms-&5G? WU3s=J3O W}kU~OysyNs,>3gbnenV WaS8}Hӕ}~5ڜ~eʷEM3{RO/?8s69˿g$ܸ:Q1{WSsQFbEr]};.E)sn 3q&1=LqϜiw GЦoj޹wChg(51n;gkfJ_u}\Ŕlu!`Ƃqo1Ԯ_UK_w1HOEW/5?(L IDATy#FOC.pc?o6 %ڸN´co W?717Ղ'8[yB[Ù/ w9y=ka&~i+_35u703rg#՟'0ӳ~ow?2OIIHQxL vmj0 fotx͛T3gϼ;'Ɛ0G?- .ݫ. a|GO yLн;?ď(ϏOơpn giYwЗrN9 -g>o~/d~K'}{uZ~_w~tDm>xސPIYkxPIfݶ+s:TuEup<^^ԴcO-b 9%|% hQ¯ϋ`k%^}`7?ג1̕ڈ]භ| g(̹H孙 CeTw&̻Enu򦭒}}-r\{ޜ98pCg8L#+ȚS[2yuW/}Bޛ5{.qP#Ohh=ږ/9aHW&vL\=AcVc1PmlƜΘaisһ$*ߋh&PCwE*ML$}-$xމ609sE;C\ڛ͟ >nh_\8U HTuY霯#漬նU=T׺WcsPrU˸ _(d}&J^@{M͔[km<;sV%#*vUh8Ի u$qW? c/&oWQ3)N>?8Ͽ;~{x曆)~꯮ .!OOϔJRv_K3AqgL.C|!u8W$ƀrW-?Mh[+y;/~Y;f=S]#\݋6yl{bjP*=範E/?/ʉGf?H1ϳ&YSG,Q,0a輵KL_ۓ t2Zܧ1Iw?;qk{9Ϋ뾜!rd Q|@"&|> Tܜ5^ɚbgG6S[W ŧpbqĸ-bY +'*N}7!y1=};YM!ԺwdvDlջ#Fuiwwq8CZVO|7ߺ#PWiՐObu_̣&gr/P /~?^Rpwk7+{mgbsfrs\Vu^?.q?g:5Ħ=D>|kp\W ^f!(5M[]T{`~Wlgu6!4ѡoղyni=(s;Z-?~ހ`~$7Ps/Y<6n jln[X#BM76,(Mm3OkZzsQ9wǬC>V3thFOCnXkN=9Y5219}R3 5;u\}kK>擣BF㳈Q4u.- T{/rتiK3y3{nzWwk}MR)'Am#fg%y4(Igs=Rr߫+~Kü;DNlyP4Dp]vvOlL $\jHD'T]X-b*=ikG i{}SKEֽ/%76ޗ6k_j6ׁWswtokћ}l̜x׵K{ض n0ʁcGfk+}n U//.}G x`kg/+g<'?ST@w 9߾[xZ` U:6B9~-~g)(CL܌%x/x "Z#yw~L/~.pW/COwMݻ7+2/xuVH\6^=X:jd_{fg1upwֽ~c׽9 iCț1C{38;]hfzSu{=bx/zެ}?3?2~W棉w/^V?*QZTܱ^t(-kh?֞wfq`q=PaQ;ˑ:^f&Gckc۽dEay>Os݁Cdn$zaϘΏ w3ne]_ z%ɬhyĖq&N>cf^XՐdk)Wj=3\69vx]:O< 5kާr'=m'T\>?rݬi"F ;+}F+NgsDYf,/>w>U|FdUm,A,u}[yM\oOz?m'' Mkr57u笱gu;?e?gyȓ}J֤O.s/9&̭ca}>#7>A e3{=.n$+s3oU9|qj|G:[_%^N#4 O8y&jSvns$6qgL5qp3y]gN8 [Qv;>?9*9$[ߊ>lYjC $W}J>jІ+{sSIs߻a $kMM?c3"ǻ'O滤Q=4կ9e/+%.%p9/#( =2;S &5GVx3|j1jn9IEj&q~(u`ۜy3VW9a,2.8)Oyxի_}|~_dzTt~/}>?w?.O "aέ; ΖUۨii*oA ^4khjg.BW.ژcPĺvkܮG<{m/{3glN6}mk[avH14kʳ-KM#ydnΑ3׹ҋA#6睵o̡Ua9D1ruٶ[s#\W>T7>%͸7mrSx!8IR{6O6vkf-SG9Cs=cnSav߽{H#7:O}3< 7ء^ ѿ=v?%9&OЮ3O+r֏^FM;),'F~mWP,gsp_S&g z:Ѭ_$#da2K̙]qk}EлoԻE؂B̽*}-=^1w1ʭf_](hiꆦGromm y!yGu5xK˸V4޸gOwġ`8U1&\H-*'6+[ؽeZo-z):3mp/\8ײc \5i۠P?Κ<ŀxyvgfļUsYzV҃y͗xK^r؏^_U _/.yZ gG>|Xe:> /|ZEN1UT}aw&^ʨ"WǢr7O h o'Z)֜~8GIkn񀮩m[ǝ`뀇xsgm1}c+]Ÿ΀v797M=kñbpg6 Uw2Qo?ӆ}]O ;ߌtfgڮ31wooL5\wG*4e[ŗ&Q7L \~ XlMMt6u˜⃟:˓q7䅨6rYd C³NibNu}9918\akx*>5L+q_yUviw#5UzNӊ337йf?H>4>c#^C=}YCq\ >e,z7r%OpMymgڜ˷N3X 5>^#Mm'AW s2uEĞ9+8Xkޘ~cYk69a4ы8opxs9u w^-Y☱q6Rv9ud}y:\Ƴy /\')~8cm|_a^/.8\e@(ɟt˹5>lY1?$03c2S&'Vmˎ7{Ρ:1Os3iRnΓ _r_x|\_s>׎ds߼l^gwv>ky~Q ǠzA`̥5rK~7=珌zp1(6Mz]V?Xg=Ǘbc3{o`n;?'"QJO1{_^/`hUOosG?ky-^@%yakx3^1SB'Rmy쳾TU5W|jg؃Jvfm){t"9Kr6c@y"ruLWb54 n :9L2d`o:9[x ^z$@C43nnⅳ<9ǟ_W-A)9K;vSshs=S 3u=$?ca1gܝΞ3yM{d05&7S|l VoǺ/DܴϜՓ3g"Ibcfޔ;69n3;h1ıזx Ǩ߹ Us:O;;>tZ[Leiȇ0x]1WF玍G3;R;6cܪ\kGd98;}'kcL?54>67 k[ 7?s2 z!wCsk< < ⚢lAaa]={ϩ/c֞O>?~/ַKUp2z7W>!W[3oj`p<ÁIuM|n皜v ay-c9 mI!ݲs߱RCÌ 1V--7u5V{|\z$a2`AY7ˎĨ?8^>F07xi͋ rRZȔo?&ʧ~KZ"p }R0HM!wbS1ad E bS`' k b#Lk -_71O\tj7g̼yWn%Sv*no礫a-y"z肋j-9-g[/w@Yp&~l@\ˎAO 38\{Gې:1iKetvC<\P|3Nm>{&&SuQ3>)I*|y`sT_u5-8saeȕ13 IDATiG_\a u3 #:bF4;[!JQN+XcSO| }a^9vz5A'_bi#~֌˹.M_HdU3:n6nb n}V/x-Ę䤹w0Gk&5o{cf=Swg|1O|rgsؚe_uKA{I¿1d 3?5a 26s>,ē\pQkvwޑBa0<34.ߗ`@jmLqKؼLf-߹N!@;{I6?E'fpqs\[Lg\1+'"&5^젩:!dB>n ]xQ}]=[|՗c=4ˑC5NFU=vl 9ij>wҝb'zfGڱ kj>9_&x;_k?^B;{is? 4"zBO?BݾQ'1:+9\[$3,YrY{Vi+͙,M\K~D_yZ"Tb4JlO?nsG^qoLbSso?_<(8ޑ[yp#F7K_usW//20 |cc+,ě8V;HfoWx3(cەr]g{2tʩO{B}k{p^0" 꼄QTPM5y~N!JVN]7 Ϊɰ3~0}<1pMS~n3ceZCs??V|zJ5%uc\]zV沇%)c.iwvs7>_Uرg{n\k+]~ڮ= 6XmշsB6p=g`Drjuw]>q&Bjp\~<יw=/׾1ru n$8@zJ6||_G'v\Í,iŒ.&0/{/yKŲgO}SqHs3xub?gvCPfȜ7bŅWNj//8^9$HʶޏG[~syI:U|WŞ?u,TDMf{P>8i˶N_}L璑:Ԅڜ N|վn͚^ө*rpdKwC-7;A5#})ڙpgTbԧ>xlѥ>c2YJcexz8ymya9L0&%,9'.aմ^p9{r]T*N׹:_֙ᦦ;2Sn,;+oz _k۞ekΰg7Άg\wd=y>ccH^:ǖor05/1qp=[Xϸ=[۩ן7:V.>גxiPu9 U>cnOk] ){rL˺kβGct?m^ =NӷTOK:B99tk/s]'ifTCuOhƃ3tqk>f@-utOgLj8^dоЬrck&cs<]gZo}`OߌiU-{ȄW^f^0sm^g]'.qwϦZ3uS+W<r3N3JpՒu6^yj0KO&0s닃ǧ>kw?׺dl"|]"u:__?>Ώ; tw],~rSsOc ])J<9 Ӂ:cƯ~*&#@\b`$>sJ}wϜ^b=ES ll<=5 Жvjwԫ.|bO{p3>t TdܮDm[Wr=p7Y@.C:KN1WZ|_몓x8g$k {:mb0Gn] s [Wl'jC9J; {<‰1j&Yu.?~RUzw7YFQݫ灳0R-s 1Ʋ7^{g3zYs_'srO\SG&.5OOlٱ%:&&#ˇ!gn.Y=v1?5 qbT-wKwcqHp3I;(?{Z}A3|W.so7gLv́{1gN=c69 Şsݝ,shsrGí>֌PPժ;{QW |zg3g8{eM۾3߈M39j>ƹ?_QZw^-sȲ(XbqN_bkw+^Z]Ws(7`&6q˷5 zU ?g5:b!b\U[R@0\JϞc{f.{=՜\1f s}ձDqO#&m{<(}UذeϫSy^y_Yc~=o>?-\ə?*Kmr%_L--!G>nh>?~4~,Y҂a/\ܟO8ݗmj)'C0KM5랱'NδsC+Ͼ>5dl+Kpb&:[!Ns;x7k:epf0p*wab/Üb'̕ڏ17'4`U/cV=?S  |t=uiͤM/Nlv*9|| Iw>k6q}kwL\J,?mDv6O9._ho9Vc5Oh'[cw3]1agY6 4ƝQw6)OT9ĶćekZ|k)3h&WCzP"kyVӧW,>gm>fu:Ϝ,աEʱa% Xf'8}N{ts/𰇣b9>2b>׫O 0XuFm3[x /b|TϻD/R*r6:w՚cr-850Dn-kP8^r 6 1Ι FhQ䜟̳GcmIz}S?A~"/+3Lef엽UWw+xoB#=%rSGwϚ1 g,z0k9{MB ߌM?\ cCX+hQ+l-6\F}`}ⲷQ_v[Y{W, |w:^e>-~3]ulW^f0ΨsG~|;|ny,z 'pXg).+~`;{+ns劔O }&aXoyL?'ye|7=k1h9Ekua5'kXb93Gcd~/vΆqSMw5J<1հ*O3ds\+Y2箉A3^- ΄bS=M]42g0c'qu(6ؽlŁ0~qXˋ;DU@ޯ|jX]zǡs֓€9mL΅I7r_wzkϘ3r&vz]tdvrnj7/`q`+V-x8;iWͧ^'k|"z<ĥ鿄~ u0Sg,su%M=>xuf#K88}YS iumg'c)1zSksLƉ94yh{jg\x5Lj/0lal.d*NOP!mrw~tl_T[E}n3x|]x?1"6KƜC^.;95dڜX~R{ӟsȋXni ? m6!O~ǧ}zHV/zg=xϦFWOa͚ea3{k_/eeTw۟Nʛ)I{3 [|2xNcq%řmj^]p}ɚGU8gp 3rgN#V]?1۾¶/o8}.֏_/~QO\sg=8r#! @|'?y_};qS['cvhK|ڇAyu{<˹6GtNƋY]1Ϟוvg8\Cgb绋6l5÷;o?X=qq˾ɐ?`pW5-bYFsc_J}gtgOʆݶȡwwy+Y\HSRqQcn~ 7%pƦ*!]ն S57{1׹vO-~Jz:l\xcZJv}0]j Vlիf͛@r8ɏy:wv+vq$UxNդ?}ڝeZ1tN;=q^i5.ƚKnig=;46H>cӞ*ǒC~o(&>SD&7לs_$c[&$z^H[qEj8i@yf7ekT9].g%(؋ `*Җ1#K&N\Q<5yGi}#?J [}]Ź0W?w_5^=~~̕ms8VMf IDATqI|r#Ē~_au}Jxߗ 펑]x 5fϺVj+u1n4V0Sg2,m;=s|9!5W̼U^[pO#x<.s3܉Ic]3>~o,]x{MWuyOm}Bm|_{X7K1?:~/=FTXn3&-s}p$V]/Sڵ1r. C3JpQיoɘc6~b;h=;M$z;I{yc9uЕJ6nhS\f|T+MĥkU?s`rckmי<|lre )|l9WĶa~uvHNjb\;s̼JsLkɹ陈mG ?bS531!5=1>r#ݤ sf錕>1yaϺag߻3DN9mM\i;3>a{wψGܮ+53g!BL\ٳF(5[-Zd?ySZ/l9\UCj.OP}iajSb@O:_?ܭ(C_"_}. i|<^L_x7g#&FZ=(4=?{jG)k7#JJ<K;[}83=%1HkQDx+vS=S->O5 0k;޺uF'Z Ha\a ]M,{saMsba߫yodO-i9}2Y̑#~G-WQ3sRijJM:g|8r cVrrsaЬxh@u6 uIdИ-9 YU?W6<\}D#bK1gk߱Wog^#uKo\Y :?+˕z$-ʞ;,;>9>6 []{b]3)~|ٰ}m{ή]{3O܉![ǕmawZ1~'àŜ?nTCМ:pj.XgC#Xr8ksi >Ijm\Z'l9Z ![jh̋Eǽq:w7rșSZ&g9+M-CK=\ s<|`C {W9`Ԛ;]z}?Wj9,/U9\'Dt݄JWNxVsr99Aq ;4ɋ>1\m1ˉwؚ cp7X蒯Yzruʕ[gىB8F[Ib'W!/kx7GڃY$H ޘ<vnq?sXE^e 4\Kzn*?7ujٴ8+l`i7­s]Z_3vbNZץwk2s;uM-羁AT`'\WGl:M!:y=uC8JK8BOrz2 K؛.$\~cv?Knr02>XԫsMuG8-ԄqDz]gƌ,RMq>[zFc{Ht|/ToSWQcgES^scASk\LsҺklĆ/|\W]}׭TdU5Dɲc*oK![ZUqQWܦ]Z!t줭e㝣X^{O=3_gg=֚3Mo|GnT26~OykGQW]=d?5GEUOQxGy0<Έe#^xw,$%-zIe\`<w~3g_9gMħP s_\@u276Uč93{+ Z8yߋ^-o<^d }kZȔ_U?᛾x$8py>&h݅y<~ht=̈Uw?> Z}A|ۢ{"n,rO_x2s̾Q_x2<;|f5Gy-{`T8Øn-K_N\Y>ӎm-u+.hЇ}ILm޹ۡ3&{q6UwhI~ۻgkڧu :zeo_Mv|.8|V]u=TMJ+HOÞu vykՀK|x۫nIP.]ygAo. ]獀k\\]묹vɮgl;X1֞l_;|ɔsuز+'ݤ8_s#D:fc/߉GooǷ[e/=?r54/G?[, mo{_ߔ S[]'OLƆUŴgƯuȕADX#g?9:azxkq/q$~u $C /f(la R\X*wˀqa*iur_l$d** Cˤ!avzދe/;[_g}ɋ?L+/qr$}>7{'^#B~wۿ}{xEǛ뻎/{՗O}3~LJ>v캪bGnMZz=s纓+rdLa#3i&'u0zFE>$.݈m;宺\`5gF!lW/|k*ey 0֯gn;q?D589Aqgy^ȧ}Oִwlݕssb5Ol2#cygb^룻WbڙLgpUNQ>άfj 8 59Zé6Ԥm>k:!~k(~ƞ~fnx"G3W6c%^BֽId_qw\n]ICا.k+<=z9)͛<9jkMs)m6UsjzyZ8bb!r{]4_yjwFL |:'p)H+'c٠(!4{{ʓwĀϚOT~f:Y]콚FXßc4'U>Y>sNKxk'G(-KGcb$Ә:䒳"?".#W8j.u="8aD|G=;zƻu|}-o|c cE?_}Ǻ~hZ G>sV:2?')7Hk)}0E1|3KhoA}]U?W~L2cKu^d.ue|7~|E Kz9Wٺͱft?==kbG>EĴZ*O吏RS&W[]0?2KO;^Wx~0 D8ǷF7/| W5Qk}^sJƆ%/Oŋ&{CLmwgyw~7_y ĺ&+)=jNu /..뎹^Zց9)o}Y*t5νMqu3y+LkdKɷyw̭2QpԂ3!"}̒_zngQ5z.n'ͣqj~9~^_OsJ͡>n۪s钨)z$Ļ6fYkMDd?x|Q^.w϶m]WNZWK=gb>Ѹ(o_S5^.sL;:7owys= Ԡ k+7~?'>A=1;9Ws^7EUR?9E$߇<9MQ֕):oq~g s[y!!g?0|Z̕[FjVͿ+#zJp! vUFj;E+IT\ R!'$ag\&LMcM9 hD' wY{}{{ks{{6x@s_ ox/| _O O>./#㭘?gӟx ㎿|`W2."^U&kVp& @tFE( z?w‡f=BywP4YH?r :N4_exլmB@Ns`gh*sR@%ڄUaɜ06wlǣy.kOsD'>i{mZk(zS}R镝!GY)qTn3k()E߾[~wƧba\w5w}{ޫO1~YLr%I ꈜ:LR\hbΰ)R++4Ws]HgLYgGX[ 64Oq%c!r7--OdBz_qIh=Z_$'-dq8cJLV+ttb1bփK'8޳`_ tcں1[1GN]gU>0oRDgWσ;:u.3c :ry?<9UOclb;=qǺ{7F?yc][s>?Ƭbygs߱+uLqg8s3׳Vϳc}{vu6v{p؜=&kcV=371gBf5~b:&%š};g0\<Č֝pwQ\ Anr6ψ;q~G_wN7G`^iT18YX #ʶu>Ѱ3^v;HlRaZ+8_(6֝}btfW#w8\gP&=~쓎؞Yg6j{#//kFg|3 IDAT qlQ"o{l}Z1Ɛ>!9:67{F$M u$--rYsBFYLO\kܫ?~Z(%3\cQF).|-\<N1{]4z5@SIT^Z̃YWs"^a]y? _^q '`:(|Z`(.X+MM)>I{\s-nO|">>=1x0E}Ưn߈{ɇpO9U}lP҆. cr*eg䏽jc5rȚ18q%8Nz#t:*OEzW 206ƜG͘njgkM`f~fsc>B>̗~=+(#sss\kqWZ3{ $c/}WGNǒ'֌ႛǀ5\15vn=;}bN|R@ʓp݋7x<=)aYged 5cx|^crecEgmcΜ;{(a*28:Nzηrv~(NuNu.d:dxlwߏulѬ:Ǻbdi$tikm57L}w*~Oݶ|Ϝ^3g=;G;6fsy%5ULKT$l.N(ǔKc䩢'58_5m[$Id]rqY9=&=9[gxqNW̊eo|Ů\c(Q3\γՎHs8_vvvu7Z&:3OZ&;~ɈDD^]kZsq_:֜5)ѩ‡G_8{L{ww9 [s{d̋ֈ}vyW\wnN&e\05*0Z#9#Ns\p "&ij-MK#5gӢAZ;8\w[K(8y:58Vzm}M~q2 ȗ&Ί5&<X=vH \'7xyy[o'?gCC~g~z> ?H;O[%C@ @un-^Uu^vݳ n83^EF6<9܋"-W'-=>*cG_m?׼A6ނ ߼cx09<6ۖUm>8uVĜJ$, $_n{5B E{}n~pvUWo>V߇ x!m؎% jV`~3g\@$  zb|0^q?^;&Fq^ @uՍvR3 7ώ|lW4,aSƙf.a\ڜ.L'K秖A)g!ROjӌR{5g5X\y #|ȨŶF<䮝]_[M(jOr͙%{U8|$.Ou}ӳ M=39d9̷SgPjLuN{j?P7{6,}d7DIrKpygxaPF9cݽ(Q_m,3#gpRù[c}Gy>K\_ǚexP5#,va"muXy;nᄒ66+&M's M.>6`p9|Q-؞y/&OgcxkmWl(篂)ς:cz1&O,=xr)68桌o1KjAԗ~z3w]9>ض)#qѥg^cc;: 0puޞyYtټXӕL#Ê)a^⪞f>9c͍Yq>2pcYC:l~Y9WjXgۙ1.U\# B"̝㊇1elR:&S$c~sy=kkhޱFmAN0ϨXscG j,T*Weu=zJ}lęg S~=H?vkz o7m;]xqkڛrYK3+눈[r:}zдmϹ9q.?{ғؾo;jP?׿\("3|a ao=11wnO]!;cgБ=%CL]Yj8F/Wɞak,^0+dEJ ﰗ֖6\MqW‹'& 󇒈kfGF?gJ1X_|5^:vUqK.ÿ?2L:P"6oc{>F OtjU%p/~z;xO:[QĔ:S\=f|$jtc)oS3\⶯MׂaL<{םtneCYڳ=:f$Ǧs%Y,91{c]+Qy3S؊ f;>csՉѢj&yȴ un?kV)+I#-uL.sl=FJ}jwU1Bpךy$1yܝv6s2s&>HyrݑT)Gi:@lֈ\E86:c8ӱ<:kt>o}a+_=vNVۍÊ=Ě?[E^u׳. 9қS"ǻ>9W=.k鶞59A?>7.>1YP1s8>nQv⽟/)*Oy'<=>^{6u&'ɓ;o=xi׊/5`3Ƴm3k8JQs⾝~ :Z̫,<"y"]#ly:Ȩs`#ZF˻ޓfvAqoc8[kM3W t!-8sgN iNߏ9&s3u(]opO؜b8^s-.`Lɑɞ17G1C9S{3H.}\أ/@k~G?~"tk,Zm$5v~Qe\u׽p{؞msᏗQCdƜ}sl<9#o$Zpkw?6Fq+ffq"?ԛ``9nbY?ɪ}~Lqz3?l אN c5+m c錥{nǡk&MV6q*O".%"3sg}37\wn{,ٰ7# #\]cjwϬdq8J4g ܃ܧZfZz{2ӽ=Rkt>k]q>Y=-ӬU HRW>e zϬQZY:8ܒq9et} G۶j޳q̧0k}6Y%qX߹:Ϫ5y&e{԰'"#*k:zmN7cVՍ!H[aTW6ct\>hD;hO7rM92k09Yg`= q8|V]oEwk>Η~!àdtLw~g\ؾu:<4k.=)yV;L3A`<>9{ߛ, f̀,Osx6߈gQ=/&Ȉ6l|9@0,aAQ{=YӞj9z\Gq#V}PUAXIREŕmXLϐi34E4y(3s[>3sd@"`pKkƎz47mqh_4wLC;=N,^ĪWf갊f?ʋbV3,~[1R'_6 ^](LǨg *3/-CĦw߽ʿ__>n\mpro'>Uc !* _xq*b}0+ /!}G }u8=6fbވMT@p 0y{eD6G57sc8'fOfkH&_i❠d3 Nzxn@ݸ. _ۯ6?Q:~m*>xd^e5kεyv>T"Ú=j~f8quiQ5F:=1aco0k91*}&s);6m5CwZ8km:y?u\+i_H\ƥ\c+Ef~f٧< ~l3x0gq_{6uF.,OVϻqZSd@#bp|X!.19?5yQ<0 7j^e-{TZge.#ڞǼ\>cL'U4Z8q6w%Y5lZ0 n=H{6fhV1ʅ)w>'bk{pbOւmMyduqVd~6#FEϭ̱ k}yB5\h[wu͊ssy?BlM|eN<`~bW,3sZ{xXԹeu`c 1k?GNl磎ȵqk]h\Y{O[%]l#F1=k p^бGo3k; `9:q3/ Rs5wyMjl5ƅyﱱo^s2\mlRt>sbG pLrg;!ZS.U< 3xf؎8n5{^=E Q.בLf%_ڤšCtԵ;ܪ1KfcA |`b嘃XClG=$ԷVlqpM>bM?H_?r+"t8escu\}$ghKBc'm]׏)b!ŐC_1, 5(_YK.YҞ&$:ȅx/Zctc;)LM^eRJN@F \͉5y ]拝++x|KkqJx3M؀xhGWtݷbѼ҉yJ>LNDMVn++9{ .`{#Q^~r)wԅ\+%TtTf'?Dk=֜\} ~tqN胼VsX6qejghGcּ+HI{}lc|?Gx{ƕW颜rR13IϠbPE1/rlu|c-ỵR+>5\x@|/|uߌcw q+.%}e|xqɛ.sLxk88`g 0q|y@O c<)e;tc:f]I\6Ee<% +ݣg{ɳ[bκmyѼ|t?ẅ́Gys9Id<~afMܣ'ߠ_5޺QW>zGDk;3*96^z5gwυ#޹z< a b[= z&cV*p9(A T6c{X>}!a}D^~2YOu=HmN'ȥ[ -ym~4'CMWԉas5{n+IgtUcBS M3|3rjhkvbSٶC@,\g<~cT,PAQ3=֍inc7+ah]S#7=Vߓ׸2'|Ens6XS, IDATAnsxq)T?8srdaYSk<=G0<)y6:ou)Rᄇ{έWIP~ \aZݮ$N|Ӟ;[<mFt(zYgN%#e͋Ĩ|$93j[78Kr1oⳗ>ϫz<ǥA 1KK䏙.߶?z;߱yۮxHqқ`s. 8=)btœ}sK^ǫ^/^m¼"oz[Oo}_#~``ҳ~G-qE`9M!;sƖlF ~G:kim1 9:OZQA: ?q{+^mls17MjZ-0 O[؞rœ╨ <ݺ9 77Os1>x:X Hgι{xiϻcINRM[ |wʌqk~or5X>t fh>;q-`}3/⩅'aLra ˖Ż#Vރ5.ds֞0X3wm}rc2:>;ζ5灯}?8^{>yxﱮ;L1qg**>X`L#!J 1y+.O0浂:]XQu,>]?ӧp|^lǡ^G;kM >mSc$ֹ51Ζuq]lcZWc+3(r7dk)ϗ>^c33Ly<8]ܺt[[~(ױx¥sjHVgY۩/Q$v{'qU+/h\뱏!2וNzx0c/<ֱ\"/YK 0Fެ-N_l;~]A="bn=">G^܏Nʁ-.u9ɒ~v}?~l\9ʼ踘XY=6]xO!As6w(R3v$Qu7->דZom3kC,k.FO `.pa ([bS}|q..|c?oϫPsڣ/x/~Q_NK^/.v^Uw=O>nnǶ^a۔'יּy¾asL m/ TνKV?ˠs M["΢86G'y@r">~{um}cŸ1GjbG뵦# >nzKlp|\uՕC՟9".0T]g_}Sn7uQ6pւ^ב'58'Y{p \^>խ'Lckp)riǹ$@fNj(AY끭m+@ƫg11yÉW݁G.Ö\Tp rt cs+|i0 udu֘Gl5c*AgsynY1oϗ}ÿ=.ǮQ#f}y(+?8||u^:yݧ5hte߃Ιk܃>|2C<\s֩ObV,6DZ0:־]Lm\!?'o}x۶o[r8xC&爣 ]so}>| }VsGɱ?m6&>b ^9{nX>w\s9u:nu6νu:vIyD&Dٰx8p B{Ϛ_H4v_#\b\Ft.,wsv"X=cG/1dҼ'gϜ7u.a.f '% R2^eb9 -}}K@v8qTUϽ 79:Z۔1{{ּVUKXY1me1/>fp;[s.Npg\2j| L9y_ S,qd=s,9VB5 ,T&ĊYq<֐M_$yowhp"_Gi>kz55y 4vz:ojC/8ty|JE۝w9^=d)sэ3x;߶=ynWŧ~+C``/خxvwW?k{?xYG"ϋ+8?~;ۓȑG~Ũ$ϻo} 1jЦP_&o- %lyu>p`ފ^6-by:<Nƪ /ܞԧm78G?0FP"Ϣj&~Cc?^Mz<^_Fz=VcOO&׿]wߣWyxk}ݷs瞻oVt׶/|:w⡣|Z, )Tb;/;O$C-1IaN81^]0 0ul_c"'cOgݯcomn=f^]6!' f?c#z[ExtJ]rΞ 'qoXjc;5usc~cxy8/\8X׸U xn3x l^m}vk׹rd~c=w!3"oX(`5ǼZ]11=ng|sT->MoCM'Nzp.sm@w)};`6&Ѻ%I{Zoc5t0wLxi;iM}vsxom7vr iU5γKo̊'k'g'<{%cins̴}EXw8cf[ةiohsX1Λs >|˜Sovs&{W(Gڝ ȽkZ[!jÎuok)l.y3Oɼ ɝbs4əPXDl{fmΑ\=k"K_͋a~MyR1P@'WЯ+{ܴIT$op⼏W3>\( 0\7ny_"^ W ([f{sq>jH71kǒGǦml#O)Io_X;2.o 9auQfNs|/\$u$u<%h=w8zC~)`Ty']a0;;GvqϱYcY5αK齵 ZEwו\3vis]*  d;s!s_(bc<'Sָbont^;u6}׹SyL?cw-^ZHeMEϝ:s[c9X6 [Nx[pb}vkϝkǃAyܡy3{+=g|x?lq[vtwE$ o;|=O fJc3? X粝n[v(i%g WPGvqa7^vTi1} ϓN|K?}| E޸cmv8}2|f^lxi|`*F%(J!dy9g YJ'/+/*aWo 6'XΜ2s>'&σ#*NGf='+֪QTbN +ΝUWe0[PbRXw5\Dqnh--{G(j=3;9O[{J-~q_1l3G[n흧ƙ8&:=Rfso;:qDu>LATrX~\3-d˂[1z)Ȓ_#/˿}O|uNb8M_Ƕ7/lwq[om"ȧnſ /`$>Q\SDFkܸTp~:mz׻u$l%* M#XuZx?V/ ^]̫>''}co4_Ƨ]g|Īk{fl{c ';𻏶-!<5`, zLu7+ۗ2"1ˢ:#>׃dž>VKDzm>'e0WzNr5`g_8NcFy<ˠ^zmk]:i;A~IlЎs?Yw?nYϳݮbډ-aN3߼_7-{uŜ3Ύ6zHH4Ƴt$vƼkoO~甘9>!_\+̧c|!3bv,2?zO8 j8gSϕ Nwj(}YsKⲍv5{hl25Hq 44>cԶ:>Нm_<)"mcyxX1 kڭdzsg|[4 kp}c}/x?Ab9d4/8k#Cd#Oyyל1]3@u3̵x{ uL6컻j&էΣJ?mp+jgOϚ[aյf(Qns ]X=fTN7呿9}^cxZS_vű)&|rp'iW?{0&K}Y_1j^4Q`M߾}R}+V{mb6>=4c9.V}b3sg-w7s ~ SF8@ɣ%/>O;u50h*ޫqmo>=!^狐:_t'uyJƫ~?=Ϗz#>΅PJWY!!LJli>n2}akN|}yr%k:V.Ŧծ$yT6F85uǓu~ϓ#1GGڱz<;}q`7+'P'G]1y2MpրϚR|Z>S+k,j^g=EQGTuFNL3VwƩxpgNkZy֐:)vzj`>m>bhr]o49Dyv"oHskNsU{sC*^E^tX̓͸t ߀ Ib~7DQB .ܮ{ዶEXDs7߹ޞ+/`A^Y^}3ۧZ"}Z9M00`..لq,<ì3T"00P&eZ$rft#B/?5qAֆ8ھ!yic$xw~m{߷}Co+#x+ަIˬ\j%gED\ /x;oܾ邤Yb YH^G vFr> Xz4<⡥>ࢾs .v sLX݇9&&tn'rȋps3=HkܚVyRkolRRQ9N 21F92#c'mύCƌ8-߳]+m11~_-|#n'T:d|lϚ=ojG^gNu !ʛa# IDATI7 9S_ډgɎVFN]2c=[uf(w`i(sq<]cGY{# ?o;elqkxyv>ci=u Ø5ߺOiﰛ#Y_xv2~ p0I{=.3ߞc/4,ܝ Fj 1d׳bŵֲhp`lIkYaA`Ȩ|z|!m!lۯ\0c59{ˇ&4xt_"&1٧W$>rr?|G3aXk{| t8ͧ5VqFh=iR#0 j1̷8M?8k1ec\#iRjFnü#'tɝ;"uLz'V-i53%0rZ>{X=rLWD[Uڊ|Kk Ωڊ8f1`&9 6{oqƞsrIJF{Xnf|u7IF[. ׾[MpH6NrM_/gg?oT^ؓV?ŇߡGTz@]iTW}/2{zU>mߊ˰I¿O?#:|.9G N ~3yy A,oz>L{k5wY.j-M]}xG11M,xs7׎p*rvGwDz ^t&Zr61kDzڼa)X `5ǜyq1{$.sH…} "[idmYcN8z^%#6(cv§}@yN㺘7'ucmcLhZQX3pMyl Q1 a:lsŹh8eڷɐ2Ɯݮ-yÙRUgxTh['M&.%n/.kOQU힉9f'o?/V І1gYtNDZgy¸n7~8vcnۍÎa +>E?vZ<~n?ژ슋4Jj*<ڸUѧ'dN95ݟ,Ι1`UqA"+Ht"˳} JFvsw{o4yRYDU1Y|Wm fm}r~z{^l{m̲8|}v˶J|eXͭpxs4t9aE`=k7Ҳ]mdm}m翍OF_}.zN/6gqerf1F̓ G#Xi}jWaYŠ92DZ8.evV]KD>n#Gdm| `_6V W~g ̹r=yd7m>E].euU+\zz=vghn:Jx9p}yшW0`]d~_.As:?j7mWc-L+@nx~=[Xuz۞gmo-Xu~+zBP:F9c<!FyׅrV_3*-]w޵}~[owm]K X/jzo|}uOGM)߻O^>%AT;J G|]yU?{뷧>iap(1ȥO7ș#&ߞɕyfy E_m1W.|; C>asЁ=xnprhj_9]җАZmM֎t:Զw9jjnS{z-1m/>,Mk~FS]_>:lY\pc`z>kvaEb䊅su:h@ͧ~ky^bF0yupɱq<˸co*N#;g{t6btq7,Z3'u:sT}&q\5>,9O2=6)3%bHlo6Yϙ9Nm6ޥqƝy77(ص9ȹ: `XˁK&8ُ^-0EA̾D.-ъ7w] vkm5q}=}&schO.q%:aw0EGWT\>ö~t*k5V1|gX!@5n>gήv"]=fipc8g}qO ~cnaF{mNyZ#LsLmtM{`59kq>}_JHZ Y1bsaqcA왃]NGW-3bsچD=H9%Ӗ|:Fq>dWD&pE2ODwW<銸7+P)n-R7xn7ys@iWlX3>%monqQxE`OۛxCM#U>o7>xp$Z:GgbkߵƪZP02zm.jfsiumn[Z9uk4&ss^ TNj5qOowsw / 61ao>P(R~ QK1Pr@[??Z4SkXBG C}< sHδ\~$6S6=mZ"_sbmHLP~cȽÍ%bLΑZl=ɝLjOt&7e`5ЫۙڈvvEM>C$}zs;O7cf }_xeX/Ό.;{B>^SN_;sqg2vrEޜ7fZJWDG+1qp'vcݵa~^Ou=2|,5lLr,w{bܸf/e}awlص 'd=l,"_ xmqN3gyl{ؒ'N0Fe+Ed=|pǤa3m̶bcjgOck|cc"Bg0vLgTExNE:X8ɷr=kslY/\#iNj?40V| f[#l;嘧c`fo[jq09D,N'YL假:شguP[&$_yO>70^VV:ZaV36W<:_du&Q99Чg[,{{6bcAމ|"-g[wҌ-YsX;pU&nR[ߟKo^1Yыa3(luҟvl>fvOd;\#q68^ ;l)T2箉99-z{i_p̼p( ~՚meɒ Ӭ:bo}XLG#tx;UuEz!:, +=uޒ̶Ix1i>ϱѧA^ l.f3fg ]#l92;!`?ˌ1g#"e=d3^k~,Fu/=bŽrTӚ_u|QIkWke 1g^ʉsq dmkuۼf蹩|}^_8bt8'7#r}gCwi%W{9u^agsrL_rWԣ@k8"|͹y|ǝw5boA9xso@}iX ݾ2hB|MC;|{蜬@hC!Q4ؖ01x:r#Wj0^mιb=e`֓Yݾ6d:N7s_c`/cw;m)ZgK?+ۘ#m@ p3'9LֽvxG|`@- QLQ#k<-B='G>(ٻ6ƪDy|&#1H;=4 H0uzeLq6ڹ 8Xxqe͉v~cՑ:?-MƬq>qNw8zWhyWr:#d#XSupm+rg.rx=kRG3>?0@#OzkֱA)k"5n[><}^+C/e֗Fn4{| ˡ5$mUs`&PL(5;sIG˷ڇm6cL+ȣ|3ƫKz9\: -Njd.O_ئ:k o5ԣU.a3#1H{ ol+ʲ!j`s#^MxOݨC"B?G>Hox^YnۥqQuu/?QU#Y1Whڞm06Њ>Y+Ϸn[-vn`>^K3FnK|-ML̗>Qy|]Ĉ8X_jƷcSqr:fǤ?5i9{\8^=;K=۬FnrG(do#gb*7XG{fMg>t)k!O<;۴Ƣ%)(GFYR#\ ۜ/yzW}$Yq̺Fv욍c95upw|KXxȼ혚8Gl5Bϝo"Ss8;'ۙ63+؎gϣ2^Dq;Zu9{jN "7t؏Y,-ugɝ{Y֘s]Lc%oD;ng?kuo+[fG晖gIt2'}_O`NǛ6#c;9IVyg>1~b<T`mvp`)WUܭ5XȋcM.[ظqm>Mҡ5Ie-e}oZú-םPc,,|x>aF^ca*MnbamN9gL\pfEdԗg v1wV/NП1Qp59ڶ q6pZ }={fMoSAZ]=Vi>Fm=T ]siT{Sg=k+TG?™۵8Nsc ^`0]i5cX;"?~x%/qE'y=+w!Pcf1q<)~&1 29;>4c.`F^q~*l鯱ur{S-{0P;+@z/qis9Mx5ry{[ lw8c?m3cm7 #-S~?B#ncg`N[[z N#;9&nzN[9g@-I3m/V1QTWhek]|'?g IDATmbȯy`j>ouENfS662&> ^ǎNv}dp?cMc~ئ=ݵq 8+p.`|M8v/XŁ-ë֎#CcO܊F,5\Gcw)g>qoDX!s>Ny0'T?+*'$[mŸJhMOۣӝb]b_H%S&>$n;lc? ;6Hj my9?ޘYWÀb3갛G'dήh ޹5ucfx(?ڷMSN豏<%+?;=q ~dWPIG5r?"~~.]to?|ccWCk$k%]4ݓuEprBصGM|gV~dZC03޼5HApo}/h}j,uB@S^guY{y^P =Ĺnq?7oח}?u={'?otypyA/[DbAᓐ| /}j{ s\Aۧ`d`ım9Q$ 7OI먱mK6؍YzIԸ&'5S&e[/υsXSd?/B}~BYfzƷ|ptyR.ϸ</]oO@< G9x'n932F+|W$I#-sIDK!]ULQ Q5EtA<6`Q+>BX-281N߲ܘ۶7LlMglj 1ԋa9gi9g|PT5ּMZ0Ok8m&o91t<%;w;84b>:u DyLwyKZ08#jZ OpfMFˊح5MN1dM¦}6C{=nħ%.R$36pEzݱ. pq3ƔO\1N+y󙱦MXo铱{<_3^ddgу|7~xl8`idm[fa,e^X/sYOٝ7v|ӣ#,EM1q_9ujRNC>hؘ\wC/tա6v~9O9Pɣ64K>pz]P5qc}Mn"s[ola+(Mm[bnn8u}9&<:69vOEt̮myR}:ؓm8ɌKlj<;,HG~ƈmƾ{mO73'KAok_ScU}e(8""_Ss$rąRZj`(~Oع+.m+X?,*5y;JB&"msw_~MAGPs~/A9+{ﻼ5֧D:iÜ|/c|vɟy\cW!]ېCz6*;Fo-ǍJ焠|ɹSՁF\+U|^ST+?8{i1TՂM>k_vؓzd5&{zǕ,6eG.[q_{+=$nO8 ErƛG2wccz jԈ Wm5!Wɻe߶YH?b, =0@!祐f'kus?8 +1܇Ly,N5.By'1#.^9.g5v9!o[\ 7$B6@^܈7̘0Ĝq&7~CzOIݹmUH=+;dy6ƞИk϶bu]:&piW S'5zu(℃b0oMmXXosMukP'_8U]tɃM&lƻ:y$!V-p{,urH by#SG$yZf=gi0sbev=sh:Ϋ(J^\)vI8>^۹KKחJ{kȦUquH&gO;^'-|5Ǩ`uHT\LnP=v-8OGW}87LjVZΜ: 6!kJOO^S*#Le cPq*ޓO|/裏>r#K^?wZe{-qu^H9~f*kQL_w\z y_•]3ܬ%엌=_-N裏]+ty߻]%O~~͘katm>6 ҝlغX©kW8uXv_Z2>7ugیaObfc ͝eX#^>83'ƙ>-1r #gv'fl%CV~%V 8WY]qU!'fGc^Sac,oin6aH=c/[Xågq8Wgu ƔNYXkQLؠM|g1qťlI?r?Z͞<_|<ִ8=6;r-#/_OaXiau+slhܐG쀧|c>^-Eb>e~9} }Ź/qg^-K˶G,yWi8aF(c[Hw ]Zg98c] %+êlpJU{oKǾW@:9]7Au=E&~S5yol+zt?Gك.8pQpLK{ё g~Lgn27FUq䜚f~:cx`?iBM.u7CsOK.Dlp@Uq5䫠Or #KO=qmvCkcMWر߮yNĤwK[5q8\(q*>ցwhGf/Sڇn#ZԦ쓻 .ˮQ |T\SL3Y^SyrYXT{縫?ީEbqd8!f#kl[J -vS, ,Ǒw]u㹔w t{sS^*Lqqp~s>)e>Yɟb{lueۘ#GaKMLdC_'e\7wQpk.uj򡮳x+^CX7,aHE׮ܜԕ=1xw'5]n7=\E/>o֍w=nϽ>aNQ-)k3QkZ{g,ʍ[S6N4\q;wկ>jZB]CGpGZo~>{VlX*9Wez{3.-a,1>Ui>y;;C:^C ><c=$rA5=r-|Ч P8jxbꖽX'h;VNIwПɭv]%jI*5oQc0-;kpwҔ kO6E^ b㱎1(ĔPqӸfq!~Zho7Sy*X$ek ׽uwI7>#u^yܞ]oyu {ŝ>5/WͫG‘% da~K_:[i5E 8jr0~!-?-dCى_Asb1J]À5!!b•?/}~}/ׯx<)2W|\ŲL?:a*6\]*u3/o|.M=O={jC!q*QAQ-܈ur뮻,yהKx;5 A6clnv?x!f<A11֔5öb vt]0z3&ß Y7a99gn]i<82|x)86ǺWrΓG 1:2ݹ i)s|㧾mk)Q[0C/vf;w t 1{b;,'E>!D?%^^/|s/`ߟ 2v B5QnpCA$O(*݊[ʧHlsl'6v( hf,œG2irp 3>_frZ }c{ ?q=J'ep"U5N3pGOi%ͭ&i Q:q=卂\-"ŗ?^CT\.+o|+_\ޫ\J'tb2l9#_էu f|{{?|?ǯrlJ\vIs֘OY)EqS)Rb,em[5 Njڜ<+z/\c T7>|y{wǟxu=~\JksGփF_i5_ Go%ـ@~܊#ͨM9p黺c5$VXˀb{}~gGR BGõfgML<\ј1_ GN“҉SDz#'Snی[F -59|!՗n4ͭ)âks.=64Ϸ8coOdOQL73Oι'7;pa-/9S_Z?Ѯ◜~ŏ1m3>6'kZEisD]-*Os\,ss8D7nrO{GC=|t\A`{WzOzy_8[,3pTe(>ɴ}w]G@bgnԤnէyV9RW)IG?[_n"!S+PXoy cGONc YFeXJ[zD5gmbƼ겾HVZ=~g>Ws GvoX/%5)5BO 9J1U"SG~>[~-w/F}o7t.n?屺D䏉)=~mݨsEtԻ_#_jR݀FlUg :Z'w0-R'CԳ0Hߩx20n?גz)M923"rlh~kN IDATb]eym`+&fp},s=C,g=:Zp&zfz^'vNQ$~ fh϶{ss#FC0O^pwA}sY}N9^Akp|r׵!^bEvw0dn_PD@&Hn'4/$͋ sJ^yXG |sƍ>B>yrZ|771yf싡1 ~Omoە_pcXLƓᚾ2&SfK|s߆qO8Kㅥ%45[l&>dg] `u桍x;6[f>A#y1NFr)gO=VQ's}15}=+grm\,OU#=O;~b[[$H.qz3v\l(b7c|7;2N:T8ڷu?_g./{ˤZl[0B9_7_'N K}s*jկu$3Ikԡ TG*x_G}nWȿMaDqgsp%j۟2 j:hmux:Xש9G3S;}"FWimA 'fkn$''O򀯒2.z:;q(=&4uno&o8sѢ( {=KODG>r^?mny|Uc77_לpwO҈ÏKq04ig{6 )82+kaG$L=X!߸57kڪYI-F.YAi2k8 n˶>-ލƞOsN'.-|TY.]VfZȍ,V|T Pm#si>?cL1g#&^$y>ܥ;{=نy1[vg=f/:{ϭsm_FQ#}4~ hGtyL^ F@[-~&6v]ؚe$؁1hޢ%'l,/2c?}e|c"k5!r1n6۾M2K>W1ƅ>v`O,cԤSSsϋUxwjqYjO&cnYm(̏w5.iJcv#4 _Rg;Xo+pwb?E^)Tg_ޢ\tm6(}.UɅF0 dK܌+nDh{ި=g(FsM 7yxM>S~S7;TcxG@oD7vq}]S SHݯM~pB}gcD>]pe7%sw(fe\tTˏ.D#0Gu7^n~anLzsaCy⛎[7d gF[#i< lO@Ư}|#ץ{.L ^ 01"K_Ը1ZXqs@;L'o._t1^ {1ĉ1Slȟ^q+xc6q;mͱN~fAs-ugzY^=H7YEC'ٵy<6)UcnkFéLs 3ҝT@[{:e#?f$S͢}cĴzq"NsO-CΕvoeۢ4 Igk [bӱ\lSF+އaxVp;1ξ:ː4mOq8&hismC;X3sSsM=l(Z7&vѧ\uHL#>x2d~ vp4nI;WR\S!~DlgF͍З,qm^5sfLؗ/ozӛ./y ؜z/ ?ʑaSEW5K+ͫ'uEWBI3V){t1Jm/]v#olx'-LPs#Kr2qiDR2*TMC1Ⱦi5%q- E1JcGf"} /]-;,8{q+S3.x>AmHG<)0!6Du8ʴng/G:E_Z>|B0g~aX`cbK?[bGv\Q8e8cq/;8xm?7oꖾ[m 4Jb[e k X"c8pc<˯-:9a09pcWi{nϥ!1vVr2Pc-tybgxDyzO Y'o{X3ӢT:s^Q,k<{0!~̹t]ҖhjotylGN3F򍼔ful籸z;'`fsnq#K; d3O`>y%ki8%ď,qcKD܃3 ]͹D -`d~aFPɉ>r[cBo<8˘>cw˲?|ٴaq=uyl^wHXw*p}C%#1~FA]#6Cjr6[}d;MbƋ]o5 ѱ`u>kFtXD.;ǥ&,׼b3{tifyd1&z)8LɝL;lM╟Bclh^&+>w[٨I[20z៛ |# >+rZ(G{.wsF?8g|Ԟ%MgUOh}=(9׽GA۵W50/˯C&Wmܠ.y,^ǹGr5-rfU;EKqMn&֫! 0W,Md@\{ԫJ'^ysCP9y3tkr׍OnN飼[\nm.9nw!91H|!2K?u){u;=n`#> xmbѡq~c<LŇ^\F M.O & y̱ gNj![qfm]J#~'&.ݾw8k#cӵ7fIgSn;',['T2-BL\ė}9Ȅmdм+f{:8+;~=v9S7x{$=dٛ'y$`cG$?C͋^xסfO=yOn@SWyOG.^[<UvcO2vm5 DpR»ȯWXm9:l'iZF#;_y6wx8ss|h۹FH _n3>6W0O3#>yc&$^?2bCYڔ0ћS?`>=0>Ǖm%.BA۩8i_! [@ %(y1A70{V519Me;6 ^Gl|>n^"Bcfevg[<93V{%!IRՕA~q~Xsc9eIy껄lsgnL~g+yя s̞a=歿Lx&!q4zt켙Adũ(v,dwz1Ħqoޤ|“/-s?u2Ce;cOqpI=qߘf_˃~\裍,8'-^Zcշ E`w aYrsqGFOqx)9U.Sߪg?!F6_8Ʀ]V7Yb-j-jId܇9^1}"r$\fc\;\֎?Iu}ccojmD**pg71Hm-^yf Nbq_rq)t%Ozq5srEl[&lLc"\8Ө?q9t-PM/}u1iƧ¨5_{&} ~RHe31c_t gt~c |8iG VNGxLǒۊO)&|c#xx|q_{r!MSs_^~wW0_\4./n!c1W$|?\E}{OUkX!{Zj Gnc.y|R2AZжGnŋCh'(8vۦ-^6K*dz|㺮9t־8ӪCy 1j@|uv#.*)<y#nr:׻VN;^tFvXoE>k8sD?u\dW+e5|!T#9LNl.`{#ݍXJ&6);`Ĕ-@ / 0:^t 농pN] upLƉyEw97pV|D?t"-%c6(Vr~bbuGvgk8qrOcCes똦L> 0[ ,5TY[aԓO}vHx<[M#2O{z6Bیqエ'2>Ζip/8 Y|c~2۷Uy36s)Œ\._:0-K{DA<99>c 5ٹZɸ'ḠĒYoJ},j%Oď5_TQ(kѩ+ВX-h&/rF"\]pa=A}VbZ2 _eW ,DtH\vw+ɏ&H<. 4t,9륉-y8t$9d?+1;ŷyV,?"ʟȳ.lɻxG[n%vLpKOb21ms\mˍqMp?QZ-t^ǹfي#<!(.+j7EҠ"Σ+%ʨ q3R;_f}[ a,>A}*}.Lzڄį)8^r eԧ_B˽{LEn2|GϺw}ߺ˗kC1Fe]vķ^Wˮ;vNmَ&*N˱Hlӵ88Ÿy=b捫A73jWUG>-ZPwmg>5@O+%5{=.>w ~_/Y.6<Ɛ_͊kƺ>IX%k? ؋o"HO}>gP'*naG~57o6 ^S13gY4%'*i9 =k<ޮ]5>5ȶ_L7Fpշ:T~j|,kCQ=Ce9WSS"k/kʠq=W7[*X_s2╌5r; e`(njߘsR IDATgR1ƞQSB]`;x]cDűⴰ<}pumybW׿\l#]t?-vFi˦< S{j|M'{a<Ďq6ꋽ Fwy(#7a+<wn@Y1T`V{y-q'ޙMNcQ&ɡmL [ pnZM6s+hU~Xy'ζ'i6{ȹw5qu0fg7u}@7~nr/崍?=-oD4^[>o['p ˠѥpb#j""%FzZϸfbϞ>'LXpÁFn|Ri2FSb%A2(e0}Go5^ }=-x p&5h6U|P, RmbaF)#Nbvg8"5n命/'J_|=< $ sy†vţL" <4q)R,_Au9ǟ9N "M+gs3^`=| TTtpp~m ߨlȔ^9Wϯpw^|px@En_|^vW}Bݤˮe 5,/] /$ԗ7Gp?2/`灜Osw5XC?S=F#I|aMGլ}4ixd"wb٧8p*H_7$ re?`l5QlRFN"b@#kcR}r+lda/RyxE<':[?Guw9h;ؔP vk8māTz ai-08?˙GG}G>.zq|BJ2X7̦l#/-7A(?)F8lfƶD)0Io~n9q~C~b%|x`?mufC쉭3_`Ky+Wmma V-|L\x7S|σyڙOM[08cIMpK!ktWvyrg }}bNZpi#c9cZ86O}>S15?=?r1ogDZur5$>e(y,]2s[4bnbbUǼKk^@V9-1%{i.Qg\\ CO6.x-n``q1rRڅ߼A<~%%p N`b 9r 'I74r(]^jO~4j뾆̍siY"~o@jXzato=j7>j#E!ě \8Ši?#w`UݲG|zNyd!ď]^JC0[ldvƈyM뎜7ؤcx2t}%^pcҋo Y䔱.;{@Ь8/)r&hmX9d$.Dm%؁/%&ߌ#/f7W[5;9͛S/ґ 9K^˳N_W7)~G~^Psy~r8ğ7XW=P52RVNݔs?񉿸oUݹ1ōwpynT4pTZ5z>WV\xq]Q57UGx 0_| 4ύlCĚeÊ[hyTkObϞqzz|+yq*ܲ][8qp8\/62CԕFdW16pW.ԸgCmEX2y,unIVP}%ND?a}krít_Oէ%iC79ώ9 ^) 8Osi_Nrsݨ'7In.!'@.u`#zig `2!5N=s ܈_2JsZ)wDLYu.Bwm}a+^ձZAu𤶉5v%gcNMA%l՗օz$M2HnCX;s|Gwh:g満vA;{m&pTO,^h#dk vyI\4`dA~ʦ]0|ض=m6ϧ'XNGwę*ܦ%'w8b2vJL9Λ3úf\Ydƴڐ '/A(8Z2;c±,iba;fbSX1ѵ:F+^y[.rдṂx&"G"1uaw]핾eGmU-Můݖ}8wQ<*s҂>7&o6]7SiYrua/i 1v5sޅIjG؎e[uCzn!B$a^LOYrz$ ~7bP݊s'X|BV /]tE@n%r9{9׀eNX`.*8;xz_z|ymO}"2LGe c{6}0WS|tZUtbT / +.“6=ƨ>Ưc^d]By3v+E<ahν8~ù_>w./O,qe׫2^Dq~//jo|C{T+:XÊ/~ַCG>UVT!W򬺁P}Ky(2 ^<^7nZ~}nK)׼Fa9ȡ a?ϝ6N,C}giM\Zzyn#WcYuv ?sWFt2I971 UlV lȍ]q(CAEs0ȱńGU/Sm_k Nk-IW ?,#dxo5osfYFZUSJ}D[M`̃\y,z dj78~va|#>pҘ7!=ήM8TDv.L3v_p@&7h߈Ͳܮy]ih?w2K.iuɺfTaI+ϖ>k <q޳\Ŭ~ke`3vrtGj,yeXm.ƹ7b/| S=s?Wb2[o2擗ue* U<0l'3&8kreOXQMU׌qSqw9پxzmqFy3cҧ:kV9_rNOvhyHuU-#5emc{#A0se\ /(^T89SKEf˪R 6Xm`yቁuϯ=Ogy9#$TY/p9(sS#Hؘ%5}0*/|y˨u"Vn|*/+@=x?e(F2.މOlbGO=`[{1 :?~_&.\ؼ.LR1:~m'kMnn6sw 㠵ޙD [s}cO?0sGƃo|\~g~zjxRt3&s?~G:OrΘ99\ Ԥx~㖬ϏuzNƂ78翫?2oU||j9nT,r( :1ve‘Z Iwa\O 9X]?IϚ`XG7MRY [rn3ͼ8rكn3XA;j\y`s6}ָL2:669nD}xe;1"И_=>=k{/ YW9^$D-D5J6m[Gv!r<}u=^_8{/`Q4?׸0 F] Y;vɞk>{y#Z6`N!w\;k\աC2)Z[6`;|e\g}x~ofnG霴HLtmUctx;8]y5M3OyzׇupOn䄜w?o,S&9>8l?7yxux~AYvP{w1@sؓj̙0򣟖ʷ!l_1vi[VuJEɹ`w=j/pL_]G?ď qE~"51UN @&}gxsaoGO,C^מp75`$,K?"j2$>w/M⊟~" aWyGu̾`>^?I9vM@r' TH1Ҭ3 ˾j.29ņjPrECcR~eyڜ R-~8:وb\\jnvՍ|փ&`L؃S󝻉 m( ZAzsO}eǕ=K7/aŷ|) ^s|Dyεt%؊Q͠j_yV>DWr|x-4tyڲVʗE|C(;\?]/{.ouՋfq =OӗnuU.z˿}ofϛw~w/G~מ|?uF.//%q5s/GG+lݜMOסQor%ku@YiG6d=0L.u8c^6]PByX{>PCK%>kmY鯱f?usqRQr<|b&蕿֮37!ZVu E5.x=b'lmW*t5"Ź&Ư7/1sSct5sr]\ھoeO=+,5 ɑC 36YE>-Y⽖=i/5y7{%:_ƊrMbKO~pŇq yLeJڹ-z\+Z= 0EnNѧt!_A_ t2]>a1TQ߼[)/x/1&V8FbzG?}3>bGlěWxvxc@ܨz so=͉3QG}k0V҉_aB;Xdhǹ@+Zz?Nc}ZcLJüy%oZj?m3Wr=fNXiQx`  {+ف>ނw7.s]C/x?|>nd+uMx˶+Fc]ٓAG1ӋaGx,LqCWyT0_* 6dၯm㪾ƮqD+&qQ\c(.bf`!vi[#mM4S<;_zkWqPsߝZn:k˷9$jO}ӗ?}l0¹i wn>^5I<%j?|IǁuO|p_T-0 |P4:5z _yWmSJ8E0c_ J>嫛@ů&֭$"7v=i⤑]T#oe_rwLz|ټK~ ylT5rxY `7?S/zuM׿ w׾'A4 կ~埿g//| V)8sԋO~] _BLIk]3Q:“cie(m3ǭKp:Pc?`JG<3zx9e-~щ'e(2X׿2\OGG،zoKcx”cF: IDATop*|/6CFs5h(ͺp/\bcm)'Kk<\Lٺ>+]͏ベt;q8&6\=2:e8M87קSO _u*<]{?D.\%ѡHstVNW9(?uB,t& |VDo+o*؆vj 钱i(IJqvtcs1x[,k1XYvrL-٣]tbθɣG؛Cl8-w3[<؆k:R}MOanZ23v-^Z,i,>iĹNV_{hڣsuan>轓5G&kh4&G`kdlzZˈ-%_%]:ǽD,zhb+z|mĻ~-oykUF}b][)8~EMu#5`׹ϋCeǃC֪D4\+=I}>ai>fex|OsPlt|YQF#b;~kq63te pמfA^:,G$ؾ{D#.\{_qם+RG~x__}̹v8:~x|zO;aR,rC4u~x[_MU6bբ!C *{>䫵{<7Ls_#{N:LqӖxn[.Qش׌cǺח/K8%Z(kT闼ʔksF4j}bW/6gR\xg:8(^g$F/?IڪW̊4'[K{Z>hQs #GnSt앀u]~65s۹{֪r5c.sŲHjU^Ɯ5Ygޚ\_ǜ51ɗIJR#'fc/O߭_=ŔV(g;KzTs5X+S_uJQ*2='"x&8ZXՎ23^}(.o=u l`~x1cSypǯe,a]=A{#9ڽTzd:?! eq\ylPZ:?o&{=-ZG{͝X}_EBKR5|̈́pbcs1+ėi_?L:,8Uc{|>95qa[6tɓ؞n;vP.(C3M^x`EqZQ?<N:} S?-u? ?_⽆^;>PϧȪ4;z =>k: 8+mo=z޷GXZA|oWbN~|JT FJ_ׁ{Vl n oٵy Ofl)5Ε=mǠv_\~ATc.\*͞yai\'o v235+J=|WK+froFRO1Xb֌/_[0 ƽZ&cLڤ\`eulDĮ5f Xό%V{t{_pwY9$fl2by?~xw(ђ'=ۏ7sz+y|-WNzƽ+f}y3|wx[oMiS{Gכ2lg X[?=ZMi-jZNG>gBհ$,΁sY&.btS#xLn>_s%*_]*6ZMg4Kj'}$H9]nbHγF]*8~k_Ba=T7k߯k{t! ^{3zPƯg>]>/uZBMrE&#S'1^0z1+$8rg$hػf^̷2!pW!{y4|}:ȍM/pem>*uK,)Û[ 3G/ 1G[3]|T4{\ChyfgdE.{EZ]1]7Gnjmqͷz$'smY]{? ">|@U6 =&ι,ГIvQh!kqL-eQ+εCFw0^ZldZDǫ(η^ )B]r/z| ^p/.c?-IQue"\xxӟv_|87'>qWG: ߵNY$O_zpz;x>ԗ uvI~Mze!׵[F5R˺k 'v1ݖrhse=g2ԴBusdrM9^s\:;ϊdyd5D=Q`Υ վ>#M*ku坜gfǜsCo\6-~r]Cem nzaK3.vlp]B,'06g1ivLSc\]k_GQp(8ȁ:ux0R>>x>Xes`+a\c456k4= }u+KjOFs+`^G\JC\\[ß+^q#TD!r-,GWsdVjyt޿?.iZ _bj>oUy74.$y/eL7b #c rT>x9w벭0ɺ?s -0v kHN ;$9½o c՞Vqfb9I?֫N/}/:O3/Dבt!'{%4irZ$Vtٸ]Yx/k *y^km b Ђ7Ϝ,wM4_-X:l\SK|#muo,#]kb_!kUOVuMA) VF7&\_>t>-6ƽNqwߘÕ %t`UE-Vo:YȻi|+ln-;W%1{Mc#bλ?ǽ܍ЬݞzgOM>y16<5<~]nOϹB/Z ;yP/ׯ9 i[\!HA栆2}J2ț5^npnVٟOu V8q94vmʿ9^/=nWzG,N$]7ս>[$۔G})~?,mJ8]B^^USەEZ x6DYTho8dF*d͙ iJz! k6++<#x;}.p+yù0§Od>8ңcWݔ<- hMxuK@(52]kOuFʇ)m7[%L@][tSnxoTZy{E z;[0WBVS&g8{NWr-W w}b:lܩO՜9$7Ū5c875w^vF1 ӌkfğ8RrթIs”5}$zgxqG|YW<.D^;3b:x'jb3z\lγrhsӚ{vB$).vDgf0|9O<0&xpسa}3nz±p4zXTZJQg"=Tx}&K'Ǘ dv~wDϚןiC˞4y&;s_kFf~X'C\49:s!Ó6Έv]b{#쾞ݧ7};1Iչm4r~.quv_ΗNM\*ynE8jNlP5>fǎ ke&zzf} 9][tϺ8G76[[nVo38W^U_[?OzƉӆ815F]3Ԯ߮yqõ\s\\̉^FВP9GNk.^ᨹ) Gb ǯ1aR :YZ'91 Ox_Ϳy[n:p9w]'~q:o)LG?~u2>_u=aѫTO$?v#K>u#rUXW:o(s>?X?W*61o/kbi.nFܲtRq\3όoidk:|-I|}faS<εZ/<Ҳ 4Dsf=ؘ&N{_3=/l_'CR|6fGsc y 2:D&f8J}x+;#1XՓh\bW31Ot 4왱M׵fͽ5Dş =g o\oP%q3O05(9]OSlɎ}Y_#vp4Z1cOב8Ʊ皯Iϳs@}Vb˹9iĿ`>u?>>y==qf\3t8/>Ȟ%>GVzZ uD}4$.}{M|)G>k6{\tr5h]g+f01ə}"kO 5t'?fvdffaNcNLl7y&&֨F/1=Oi'g0| YCЮLpf%m&|`͔1oElZyVў;/om>ă1Kr,[{:FciHV^7P2ܫVӘuo(&Obu$qs7׿>[[oMx"+p=s;a8ǒXl >cƔClD,inƟ1ɇm +R XL5 EjȖ[uθ鏌L˪ܴ}{^=˾ē?X<(kUS"]֊PO ?{|^ k6f@N!6dgPc-`8'sh~{ѥ R⽖AɭZv-kfi3O9(n Gu#;}c=y?{8ʸc♋wev{8\~ 146_p1lؽ7{0s;*Y#_wmdLf27|hŠ=_'{x%5,y'G暃qO:j:?4wqMSqܹ`ヨ~./{?zE}1~j~"G?GK"*hpKZ"l8:N:d:sHwK8`mv*s5<ҼJŲ乮h0#X^ύ<*K:Ȭ=O^Cl#Wlɵ֣Aԟ-d.˼NMgπLp4`z;Rhj%6sZ W'61ꤰss$4<`2'hb}{^k$>"iq]=o*W,|4^6kZ*yz)ȵʶcnҺo򄣒c &s6Bۥ̠ZܸcMKkz!EOb\V5{F~x9e}\-1p]jM+ݐK1ZnzGNud)v zuS51nml˯{|+o.Z jɱ{Ϗ?pO]ޟ/ssqcK _W9[sQXj+CK]$Wۼ K Gq\QqNj^;~$@-ˋպ+3}6 x_c*ɚq] c{ $@Gᬯan ^% a4:z ^! 61C׀xC{4o9U0aDPO\kgh3by֑s/DFf&G9|wܥ_ƣ3Ɨ\{ hYЉQk_bXwᕭ!33VU#yOk䢚Jl Ot? L_μ lhɯ u$.Cn iJFaZ@&\m"0xx<8:vXXg5}L`4ym`U:W Yqf%6}.)ARCw0bds+8}19՗`unscI˸wʛZ[~ۣkjhr8g1ˌ/CćL1ϟF \1 }Fzݔ|-M{K~zХFXŦPp`ck0Bk0Jl,7~L=؂LI׹Y=X/{c.ֹuٙGڮ^8{ǮhˌǴ Amɑ0<$Rn#R'{cK]U/CjKF~ڟiq9*0'i 98Z"^q=:?`ޥ{Xjr͙' H]5FG]yͿ-u^˰3:%g'F qa"g0`'NeIkιw4֌|ͥe?";D{8`{UlT Uar/w+ 6U*|&wU]uG}ztT/{8#ZS9㬃O$'8 Ø 39w|{u2DJ̃N.PQ$1xln⸄ c ~ n|w5yByetƸ#^siÔYansp`B5 'Sk^-]G>5F6O c=e)-YE-m(Gٜ˟w7,IJx[zɧ=h1}taE4gQw%/Bkc~O_׹nܩfCL̵򾓋eC4W VG2 r-QaH5k)z5fRY͙EEe:3#=3jZ5=[{y_f->'ٶ4M:Ȉm9Vc+{iyBFIxُ{qޯspwe| =Xڃclj+=i2wnl fO5N һy~@f5†csϳ7K(|7Έ=\l)Ħv|4s&$zqi}p!O獯Pza`&kpJ sfߒ:uqdwr|lƅXcco xӠ q+v]g~8:ד:c|-̌}mƍ`=s73^HOuiߎR1&|x6ߪ{Dz@W/G  r/1w;q8H?θg yϟm) j յB`\W/{7% J۩SJeշ>sxykx_;P2ϟ<=hgIb 7k(_nGsEhdYÓ qY66) W{ {t8FlsIϢ>y5>?<^ ՟oFEL3]Ryھ_8fc\ɩN}7X.!.CB94[j1_-V}.9=Kc!bOkStj 1ʐ.i7yM譁C|8 ČncHc#ucc^y7qoi?3n e}iN-\n̪s&5±$G;9WЕ7Ѡ`L&.5ܸ;LE=3/>0Mߡ}:UBH8Q4<_UtE!q>+GMyJƟk szBzuooҞ.im ۳|XlGv>CS/mKΨ쬐c/s 6n}:ƥ }ڜ[ֆ48l_qxjś1cvh*?z^9l֞MFĄA~sx7 TUcv̌t=G2} JWJ qY˘i}gWim| X32\Fq:bs{ѹz꾅9:lמz3& wiG8;ui$;{xyps_?f |}9}9-S#yY'H3?3Wt}F'{yY%׉ )ba˞}$vƒͼcoy^º}C`֘:vfyݭ5zpg8Nhݞ΅15~GJMk\r=3?Wo#뤏8]Yg.p!A}q }gH|7c^%'sxFnngS$q~ )a- m7R UH_POz,EPs-Z7|a^ԯ,Y>BR׌h k] Œ?@#2s{=_l3 3e7>BohJr=G|OOM??@+!>\}'|w__/㠰PW8^{ !+G*;6Hn*N~OxP+g8{BS5Y[gƀ[:i=X_FGy)u+(ٍ#W,g=aIy޹v|1p31?LmIfp 7\7<#}l߸3v9)R21+o"3sF;c_5ה<,ְK6cϸU8?gWΩbZ֙qn\> _etk,۱ &b0_MߌG #w~Z g%{DzFײ&/e ك:EJNݣı'?'&j?;|ϟ/OL|̱r}y_k!~zz Gކ3ϹR>,ԟgSf MqQ'g}}ve?Ƀ䯂jiT|e>s#HuIjX:^C}Qk¸5HSXu&=*K9Q"K o\Lp# Ӝ-%ebuɝ?W;Ճ[ƍ ٴ_-}\w|y3*@U:CeRy+'z;V7#ğr7\!MM:%:0ݖ\}>Ya|>[>գ+85m'0[zzգݸnl`l7u|c.?*%_ӟ~կ>^o>~<8.7'f8r.=B9,56I(ڿ5g^">yj*dF#w3ӿk3WGDW_¯9%/9Ǐٟ'?y 0ބǝϸS6~!&ճqNΤvyg$<u<3j{u <@iѬSx+>t?Ga8#Vq5wz2{⚲uI\?d >>~qҾAk5byG_?(a융BǠ_̤,mY.ܼas >9f,uiy%x'e8𡧏ܛk\{bx _o29&̝36fNMEX۵^vr^G39+m{AXufÅ&pԷz?#=aĬ'Mũ?-kVw̋#)Om뜧]> wX WH/3w$ǟ\׈ Kv'D5c=kbεó8PHl$ssR#0d mh#ϟ:l>5jч.q}9GPѱM:!q͠ϧE삲G]  sly į}{=ssz3~q,\tÉ-5" #a괦{*iFdD#b|,OXmU-t{Odܗr7u &t&2_.ֵ(hV^{p<œS\YwMYI`7ޓ%[|sn⻖\f@e=s^8vᚸ+|N9C1EZV^l4d5C &|ͺ+]Kb(0"y%ԧ("HL m.,GD_ZyZxYGq?$.9fbkՕV2ka7曮f2n@8+|5́pS_U7_vS|@e)P#ףeP{ 4|QRH1e} D0?ӌ|?c?~<99WD>C>YR졺W8|~/n~/jy)k\k}zmϗԟY%l_YYp\ά^J8 9-.p^ncww'~ }<ǫ5yۄ0fHN>Oo|㛎__=ԧř#5`*=M7ۿx_7k#sYt6O s`fmcmW 9c;1=$тjvm'WbGO8@Va 63*Ygǰf(eʐǷ*{]H\4f9ϒ9cs]0:f؛,L+9heϗIz 7>/-wL }^)w!FֳQcW1=U8cg^\ggf|R54^HN'O_֙(]b{XϵWXys&snL- q^u;fפ+̻=ՎS3˜{WT:`_=b:.m?5#3憋On輔?O;Os/~ m5ͩu|!2'FYc$'ɟ:◚ Xptkcxo8z5CYtNG:оQ$OQ=< ,0l$M%ӑ<خ!7 ?Wdcs<͕Q>G ),kQ%Mη|m538}KC̘q>XNB4 c2l(\jA!=8_#proVP:]xN#XquDwy?c 7+{'?dzlWgOe-ql٣oz=_ @?3cS0! IDATыGdC _|dc:P7$J_7_57~7/ÔK0ӣwu5+^{_g>x7kW>g_KqM_u]]46gLS0~6]hY%gs1xLWXVt9W~0 lup%1CI+UNβtpg*vFϱ ~36+GɃ~M-O&Ub[+|~Tt:oS0ubp'ڙ\ 6!CfLܪ5s&6r͞>ҧi'a%Wҹ'$^Glцa6Ĺ1Tw1R|>l;6})j#}|`V7%G51.1Uǟ^?&s1=>c™֓!9'v[pB􅑜/kx 4L|urpxLImWGpl yUT yyN/ 5J+5]n|>LWl z#e3?\C{W=$GF,gK#1]4;܊E7dŸ;jTS=>8(9Q#XaLkXŏ?CW?hqN sF݉K++n=N=g_9stЙ.I?{2}ppM]ØC0*fZk1u80N'Qֹ9>0Ϛ+e ՀYبCC3GoAʙ> zZ֓F\G}o㖛T-՛=OOym׿%Gz?yE۩uu J5@Tw׾z(61W̩O!1˦|w{97^uV7_ZuqYs殾Q/RaiPvկ?T3&[h=֥{e55+-3ws56֮ٱpV-k'*.<3"F0+Y_<+woSsmGp T=~~uu3 M&Bu"F}+ uX/<_zMn YboM>zk^3|ALӊ_;b).լ',y粢ԃѭ:ƍl|58yS[+;wXݗ7~G:?}YgGblڛuzdqL +u~E ֗&g07_s||s&~zP}i| =\>lVﶾF ~mp4'o|U Nj9 ۈchpxӜ:/ٶ6\6s8\^pxqbRK݋n Ns09'vسpė8$~}y Uzk\ŸyѾ艾D>>{p|Ipfоutwr^:ɞ#g[b ƚ۳N%O_}d1F3s~2%Z,.y |r[brI9{]N.K>˓M>/d7u4- \,VSob3(m[W=ۗ;WFgޞOM9Ϟ8ٸp*?̙MՕ-p]68@K)_{0[>a$?}/~UWEN]Ig^4}p,f\7+cЏizg8h~ f?e;4EUpᲪbDhL|1ɗ,sQ3@~+ +g>Y zbW瓟[ێ+ oW~¯b# 5M7s l=y ||w?ؒ?,׶}W~5X{kM+zSoyӏ~C!lmj@e!ڒ;xz: }buAYȶ&X׬`\?q~!h@fwO?wo[o>2Ցq^z1WypW~kQRSfSNo|[=~t󯂉+l򧇪W*[qS_K6USE=K6 =ZFfǦWlv-'=f-Az}֍ҡa uvZΎ/Nq@+py4l}t%Ϣ8`] Ofs"N$Mpyu6b'x[DS,OZo8l53Vd}y͢aw1b |׌=6g ^\#b7YL_ _g9'U0ewpƺ=W<3;>Xf_a<]_(F{OfOoת6Чs&͙g3\Er%t"xF\XkvD &|\p4e8}9nD0'IJ1 Iq,G%#>[o#"L}vƲC/BF^km,",?4ӵZa9磐n?0gN*YĶ=s:ONkpv>⦚vқ<ßε3ZUlƶ:6&g9:q_9Y/^49)m>~$Oc.NNq8 ;5`"}{ܾO.k`It 6 U'gṺ7]C֙'v(_Gїd>&Ed9s`in|`T9U •ܙˠƯ]_ ᾶ 9y'(ξkzV7uy>zUwc?3QxVn(0ι? hVmO|-Nj^#W~ u#nz=tFHnT$i}TZ7ꪃfms(WRz'=pGdp%=sMig}}} OzS+Hx/yەJ·ǿGWWn1=aD/27{^Uzr;:Ғ^Cم#U=}+㵯wzP8{*ȵVw_5)_Br×=c O `y3X{~B\k@5C^`³F>@p$D~s騺ʬ}Ǎ*b;xG1'ofA9׺)^Ub`JУޯs-T5N:lm,5`3z9?O]h3h<M~sPχ}8]u~c=_Ϲ½뀋&"JE5q6F9qhXq7uIx2>p!:K{e[8OvhcγPF|1ll.\] b^׊EGղUc@BQE=bf:jJu]Pz &{= ADlњEo`}nt_XEWm:޼ɷ;O'Wk_tX2ViW~_}sHʙ5DžOđ|N>cx%WdMօ2c f?95B8"xuaPĕhξT兕HJ ׎s(n\ 9<00UXO}YF8zh# keU'sh= 4t|υWvn_:?)erԦű!h/{q"i:Ǒj931)(qW9騅1/OX{z\eFslNs'I;{Q*4r6j >x}=zkw<u3A8tyԫY}:YO[Fox땁{r#PO?Щ[!|H\R9s Tf%s8Tu :R԰Ъp>ӟW !3Et-0]碤J:?L n,K?dٹj.VZ[*W-NJ97KG}M~EYIn'~Ų/,#?Jzh7f%y\sB{۩9GpW\8ǒGmriXɅEQ_諫ķ4g Jhx mu&l kGckp]ڕst l=|nޏNf|ም}1)6/ϢCGS;{<biSry\ѐ~\b= vŮyv%G&цmv}t8373y1Zut_ ?hO1ت+KŌ-<%sr3& cVkωؘl\>䧈`][>,Os <,19Լ.*0h( !w273DY3_{C1<9ܝ8iU&WfpbҼcu1\ >k;gl:;VsWg[t^r;=(8厙R$5f_jlKpׄ}cu9u?v|t Sucm4oPGW-:e'K NHm'uI5؈{h1w{H=eze{ΚOl07w n_|Xܘe?k9]X0|69G=puxƒNh1 ~za}9ht䛐ΑtrD?J?ǯWի/?Q@Ks:bXmKGwmt_s|^ ?G 3~}lږS(qPK"L7,g`9ZoX1q_vpu=T__ÆC=|5{+{W (ي$>bR@1JFtYX(Wy]~*ֿ=[jJj}rCX1E_Tzh .0ޚ&vqO:kC>o;^lJJ-k&ҹ"{k`ݵw ֵ~Dc Ccc YK5BVֱ3~-rFS₿'U>03͕|&w|g犏:ۉk* ;!O\ .pM35^Hj}K]㚺>,33ެ3ؤb392ӪEp{>[9 {=,v,g}[( ';uTbp…-pOꊌ2܄>t~CkXv\f!GoĘ/,=€ l-^|&ywrKKF ]׬smmg@{'Mha<'=ۯ8?:{Z#wO܃#p9:{|>ci}lJf[T&&|EPMCt Rz=-4CO8Zwh+}GfT&v͙=k M'/o ԫnկ\fr⿭n/;zT7gvpM^p ;2*zgfbr"clD4uiP%_l]sxLf#?{:§_cXeœWޤʼny4zOq-s:m[ɍp=8Ŕu͵=Ρ n1պ ySٮy+K gfчSe8fg '&{{)8qk>Xs㋟@s7gNVwic/ cft CW-+{7k+e0t3\Kt%2̼:i$&̱gNYϬ|8u=Wc>kL{d IDATnxEK^ W W~5 ǻC4F(2M*uz#l ~d'Dn^٨/;>_w&&zO;ny7]~[S/V _䧎׽{.8Yq>l{v>3,ٟN7_C^Q-eN> 591gN:ZȌh CA< |u([ghm~k2PWJc}}|w|wW}o8v}U,\Gքb󚚽Շ}h~xc Gx XGřs.D{PSL7rG/+QSɹW!'9.po\kXۮDZ:\vyV վs^>#:G{]9hHݼA~=y<۵&WfqM1}?qƭ6ʕ|zTg|%0sButeL1cG> &ĖGq= Mozzww;췺yRexIzTy׻?2o0"~){0F 35^/A0?OK #h)?E0{dCг[9nֿǦnhȵ*Ws5uƹ ͞놤SO׻8;qS - B%]7tޕ7U:D'7Ǫ0@<0g>>]K-+R?0U$=\Nn[޺ #G7\M=3Whž_d 60c¬6tnlhgrO 66* #|Y||rܒNWUO>vs=?ơyWoƎ5$"ΓccF4e鷰Y -W'I8LudzNCvʵprqQu_1s]Kٹ)=r6lϙ,΁^FGn|^w#Cn"6u#GZ4 >f.ɿL)ϫjw_q724&nD/ 8 j.g6rY&m9X$`! kr[+Ğsl^>@uf]17|S!H]ƪŽs5mc C"*:syެlVr:w Rg1j~\霮[FfK`^>EBtuUʱJ1 LVE{BbJgcml9W#@B؋QXC\\r/KʶmJWqz>k,еЪ+H,?ң7b+Ki&.)ªs]1Pnl]{~ŝs6yXQ0˯z4ba/嫰2}2#6V+xgA1j&v\,+SQZ =|Cl0/{s{!}y@:+VdyJKx);'bzlj\$<t}?G yw{G js^EqlǾw\`+)sεngО곗Kgi++K rWϊa/^WGۿu.`[zkn[l7HZnΏv 5ud=>%C_Ba2np;3=ZƁ;OU36c|uܓo6 o[kk}&CSWs8}ssRRHF==OϿvϽ8BPczk`12sEl]yt:Lu&mѹ㐗QCin0{{xf1{/K<, 9>5`mMW]J[ݜ/ja^[^Hp=F>mn,&ِ 9yXWtk_Gx5(~Ն󪥰[}r{Fծ8+?fc9.Jb޼*tlqVyQ^ثZ­ٜU%b[慖ٜ8CpJn9Şp|oOX6b&ozrdI61;pZ¹c%NΑeOs7d6 u"3R땚8^6 ꑼ-84L5nHOj2% [Oc.&s|y9cw|l1?cI"jcxucc,f&zmh RYǷ3wx{OƟǟ,&h"k\]('^|9|_|t|:>,o~qM8],>s׏+k_Ŗrbej)^ W{^r?U?f^O 'f櫟W3I`y`E+vmyϒj唇9Ӑ`q$.<_w' $4i/SCsS'?)߈~(N7Zj]}QʯOV1b3U0 QnQ_?(Ts ֵ׏u~z+HL`˶b4^~mjpG31{wb,5rFCS5 zsuFug˹s<5GDc;咟uz|og8㮡sS{ɿT@?ʊu#y}?\z.py;* N-u]Vڃ߹ylcw d~a5˜goisk5qɾGj\{em^cٻm^[cc+Whŧ59vΕּG&1}X];c؋ga1%vIr)vN>%_O³#ADB mj?bFhglUGv^1싼۱C^gx{2pU_BZ_o}şi=wuw& mδ WOWğqo7+1>ǓO~!2HSo£o>h.{{pfOu깎 |>v+>s H^jQ Ӛjp`+ [p)''*O^;=XˣzGQk6\6 F+cG?:c >v"/Ļ>]kQgU\0uٞu&&/"[p|}س}qvlqlrDg|ӖT/p{Ź{*6|z,p.#SWз6O|I00fڹg$71A5kuɉm'i} !tTcqʱmi6{n /v>m}]u˥h &W9v˨}:ΰcs:'X5->u2#sq=O&gu~Z 5$Aqp5&vlCNѷ%: 3w7^sgKM9龾8`7'ݱQv!=;q`->;s[qdo đvcMrʆq=q3n:kf:/>p*9O%%X[M {և͑6bmwsq>'#gq?^wq[\}DӳlpԨN9Xc&-x+~p?/ L[εCp|.V#)~1ڈujy3̱r5G$'`RSþ~inqB9a} }m37:Gt.9׋g9#VL_9kuk͵v_ٮTd/5h.kJԦʆ4R5±?Z[5<%u/?QwѬhyWUvq_۵uuG6u#ru[hEq4YRY>ma糚7sr.sEҀ'o߳s::F[5hD#H<[Q+ٗ//9ECCWTs#$OVq_5 Ԍeݯ9Ĺwf>1yK & S71ay>y+~<,<,u˺1`j b=1g:897;zfONq0_6Tj#W8.YwO{ρmm=IkFǝXuy԰D:cߗݵoc~i3/^vlmvXh=7kpS+A$> cF@R mԿ4U[!ږqC9ۍ3榙kaխƙzL!'VƑ|_6J7{pݺcx2M7+.V]v@"VfM d}F PXWN3!yn^Z7k\w~.8W5>Ň_H?^ IDATkzLFr3iaa 3YnұK<{5Ó0e~!]ӀsrKOEv[bFӫ|vSG f Z^Y˿+k^gǟW>ip㿫q1Sx/b`X1?{ޮZ+eYLtqS@Jk+U '>b/ ď3\'nAc\ƴ$c=AM~yP~f9*Ѕlf_!,p_9GЖלijf6g'60/{׋/=m`ALjg3g&k欁q?s?||׿|*MQ WNh6-9F3i9v 6֌Xl|g Wx{k|2~ɶnJKq[ѩ~'\ ǩ&h}騞WXV}Ą||>g L6ͳ44kseCcv5X FR:<;bͻosrVrcSp SGl{ |kG 4=&vSE=:Z:Šwu'6&ƼVuj*u]q7ZwldzFZ?T9oɾȝȝ;7=YמU?4{#oç?TS>,OoȟB͸;׽Ww?H<\^rD O$Y9F/G̼-8*K'k,կo7ƛW(Fd$ʲ<8p,o=+p^vVֵμ 0j)r|4jue?yl!=ϸv"<3>*LߞfﱛK̭fӕ+ss :vܱbԿrN ']r%mW: OsTKQψ}+)qۼ(P?:{LxY9~nʫ=jxyiv/E_~S#s^'V|j'>>|o>د} lb|yǝ}gU{>h|DW%G<a)uTZ6^zLMЭr X3i\zej ЗWTNc䇌]UMq]ΫǣڌO×Wikǖ}I gcZvm]6q}3y#vYjcq/[?>u+yF_3^"8߹?I~sUk\(Vs{>ծW}( ӸsWw!jav Nm ͍K˙qc~g=>c݃buv<='oϕk..3|_Ý70#]]V%! GOSsݗɸO6ιSFMԾXK-d:ȇimΚ/KMrxy^ ڸbՈ5T:i_0Rw_͋#K3< .~x:kǾqz*S~|Q? vy8fGڹVLu}ϧ ^<vr/MXR+>sfLCvs\d QXw-GŞ5yM7Hcj+4hO>׷jR!iCRn{4˹%oqϾgvhgf5ĝ`uUe 肯rRSc FZP}F.<3=8c=҆=’y=㜸Y9y\v.I!{w>NH,/|G\3iC '6t4lU\O& amdNK('nS-ƨ#Aq.9}G~ǯ_}Y%ŹGsV>,?OO~Ǐk_xG"j}u7"8j)>XLQZ"El6؆,Q { x֒+7b\p 3Qo{h_Ku:Ξ77*B|T=3΅S>2KbW-{\kxݻ66+[ =նjҜ/)4Qmm5?̭\sE ގS53`xW1}}}dRS 9칗ͯ]>;9L?]k ,S|]wᏟ`g_tUWNqP>$. 3c~ƨg [ !n^s-M y݆s0_ Wm}֟&tP__v,ob;|p/&O}? k#W Dx>X+vp 뺐6xԉ6u2v#an}ڋ^]XX qX`Cācp[3͌~03傮C#3vsvfU>qpø6׸+wei&q;s8` _A8拞擯T7Usia5_A3Y~ݏٟ;>,/>f%cfWϕ^Wꗎw<@|bO>Ԓc=S_>w&9&}yӱʟ5SZjbV_#ӌk2F;q>m¦=MM(p oתĞ7Xp+z£Јbi"J^}ힹt,ڟM~ꫥZsW7ac=W䕓ᙾ"ZvbJO+7YwF11z31Wrh9s:sl.gƞl\UC1+?Xܓ$nu?b#]#6rGG^ M=+БI/0eSы9QO "3|g7\93zϸqbJ\~I̓s).ɾڭ[zz[KE\sFC#>77v^`N^# +{~GCJO!`_ire$dM.5g3(/J\O٭k@^g'QAla#NYǴEm"Rxx&ĀŘպ'瀊:cػ9;e@EmGA!^ {·>xo>yy}GVX>9Jn#{<O?>u|k_|>J!yKw69f<\U$cbu#?I[(dF G^_þ]'Iqh~q皦`yy;5z/?I/rc@:ԥO>zXf[_<OwZ}'p |5/㙣x׵+Yޛb˾W0aM soiIg܈c]̐Y oyC_Z>kbC̢r߱KU4֘i\Y6ʼrwQ;vOZg ^x? kٚB>0>u[BOK<'oa/q»_[De-;9li2Z3qMek_-~VjUbf,k3ʻS}K.C@$sbH:c0(*/P[ ClHNUevHtbZOS4siצ2z>/2,;y_^Qy,w>۹otWfщZyN[lZ?ܐ]@rz6&\4mha/f^/dUoӛ~bs_#w7ͤTOy+WդO!@Yue/ջZW,|[58 &nç*gb Odx"ǚKM3(KrӀ=?584R38YyX#aIJZ~ԥ^(Ǡգ79u7}ad dqʏQ/q[`brLծ|+k׵.lU?½&SH'P!' :ьƧO=:۽c]S:?$+񶷿l<#>ħ֧CG,91ws;m;0I ӨPC8oqyf KZR3y0cO+MMllOL3xsco'/9G9'v,m3Xq+ ov>}_(zgv[q> =z͸23k9gu=c s[\uی﵋/vC9%4jUkf6[͙_gO3bM=#c^&}Tk{GیK;5%~8cyX\_\V4_Dvtl,})lYڈQCa6[k3qĊY~8e}9qu9̞uC?΅c͋sܹf6{n;$>Jn s[B>iQe>m5WΌ[^lY#qNzL %>c;ϸPVOlbL\R23 9O~մאic3)9I;c/*#{f3Ce5oXf43Pb?|G@J8ޗu491C2װe=9isH_3뤊x9llE\sֱ-okrEq鎖 IDAT>rlI\1&(sO<[aO 3^[ {yQV}iʯ^|Sq_e>s0>su4#|z/uV ,['_,~(Yg`F)|3)33r'?=o{mĹ$~Y!*'+c¬=cͱϜwD5%OQx oC׎x/Wzޢ_ >Tn={6>Oo|#'q}FgW.+wzAsu9^CS]{2l#40[-Q+ąNmvjF~g("pLO.p,޹ғeg罩kMnuјQo:V''ƨc:X˹ZR=Y{kжs7W.U 9=uGl` C]Re8ݮYNAO w%_t:#=޸w&锔 g;w`]pu;G:=|1981Uxp}dNx}YwM==~MԠ;|aLi:KM!q\q{q k^w~|={y -HG6bg] ]&2]`r<º@2p]3/g Z-baVkar'Opؒ0t&6IwKkZl2PA>g)ɪ}}rְ;$sL{iz]Oە=|=ԩ'8yz8}Lm''YᅲnFz7,|…~nzOYvK+^W~8|ǎG>mT+UU^eKSد|p O,4Oc]=A{0yC :a, ͺ1jl*K˜O9Hz OfqI3-` bI';\9:N^ zGj}ችuםk7sOX3{]Yߦњ&iD%*jC-ԗ|:^|5SHNRM 1)\O '{rR^eC80`otd%z W7_iLd?ŋZ9QVNppxw9;/_vvnw芫3Yk]Y_sq>Z0?,\|`hsz;_kG-Nj9FUgLϷC 5ڱ@}3_N0[K5cf,{d4_AYxOV|~i  zboŪ=xGhд b몸a:× a}m/NGn} &mpvhzFO3kؼɱ}s]{ͪx)x\Hg+}< Q3L1sҏM[V#V-̻tf1XXZQ:#^Qn'~V~hXGcj|n7FjGSp4iy:^݄kNMyD\k+GթJW]ũiz>F>LUiίx!.*BgC[gwaW*zXkKblZYy[pžcgWk93?,0,%d'bΥ}䜃55Mè}RثӶ(80EW5&8僋xnOL{bcXq ؕkWQ3EiLh5>d+FuM &1)ܵklA~Oq_WSgJ/#O8Wx|?r?}Yd+=;,dfEaqy?kT'׿_~T'#Ţd-yGuJo:gѓ$ [K탳>jw >OD#oV{,8\wYQ^䨀W6muXz69xyjb|_{p>`!'Ƕw s٦58mKk·fvFz;T\,F\! K`Kɜ|ڜ69:1b$t4⫒aI^ӭzL˝g1È;rV:AzO?Xw媏޶oJk\_ I^+0/}\:c\˕W¸ލM^Vm>Y^7 4Sy̞vz@D3'ͼ1;mŁ: V[tB03:8;s:8}̙oo&~$}m])g>0 cw.gZQ(Hի+vgu!u0_+or}&s "7a01Wu\Y|싓:֙S{Ƶ=vu9r7Ԉ D7OBYq8x>ZO^߱_=kOti0̇+yA d-ZnngW/bi0O~;O(/}i>) 6ڲg -?O곏K{ &(gQx.ٌ30Κe <1W8qJ'vշf/r(qЗ|;Ky9"iz7|<ǣo}[?u7n<Kf4HK[?;9y.0pG?ׂ"w`Bҝ7Z;bi\`!o|g8ff`1<: Eݡn':iڵ1U1ӒT9xնW;>'[97m(fkɦ`uƵ׶[&XGmڛ4hgΕ gsͳ(ĕ^w^9 ;w5e ŭƪ}c^)bu`yX?bxVޏߵ͵4`SC=c\rv߾73}]]sʻc\ꋾ8ikgale٫ϫf!wc`o9-WfpQ1oWs+?}}ҭzt->h 80ϡf_/5 b!6kcϽ3U҄|˛Nyƹfkph;ejckv骜j4ּ ٕq?""vvř\ccvi5+8и:S꾌GL|/ԙ*cS:EWk aUbzGfjuU9>;gUmH4- oSgتL4rgϸSDu-[I[ +q g.,ŏΘ}Hܴ fk|{?j]z^Dmh%>|ͼ唛L=s9/5< X'h\O<>x|_W*do]RMQWUyG=~ w90QlYSmm:7~t«&&y)[l]׳mIV󻠌Vl ׋Փ0\Cn~+A3{xg}T^xI<w~=~%/كdubюt=+IK=˘x;~xO>O}^<ӟO? 0M/F 3}֮'ـDoI4nkAϚQR k'|l(_b8cc{0e|a&'Qvy{YЕƵW=6m@NzirT: <~} 9gȰWW +HWgp+y6Ӷk? \8i Ө)f춵sٱO'4ܒ;GvVӖVb֞k9)9C_"wVƘOcvZ}>y~Z{~~ψeq];qΕ\ۥ:c{C2~-u&ה:o \An*'[jp}i g֝ӵ57|ml8=Ń1yW\5U;1<}:Ǎɩk?LWׅ_5L˚;QBwΕkI^&ԕR紙wXlxהyрK>*h5,/?sf*]b/m9 ;45M qis)m}=@SGĚ ۥs3-s3c'Ɨ 1}Yd&ȁA>غVZF(c7GL-=?k5h&ߴG2\o-oB?WOo{[}ාwqw ['Oox=8|o/|g;iyf (?_zyE\]]Ikb&1yk_+z460YXVU{85_U&5:zsPpMܘG9L k >v|sjË _x/|.ܖ )pwy77x^vxLj5z#:la`T}.{2TD|G|L̵FSgEta}gNy}>9P?3:WQM7Coŗv|cOo&lUʉo8sM Gc1]Cq4={LrqwbPÞsplNzWs>=!ϳgA8ù֢uqFҝD:\Ԩ4k_kԚ¡&iwO~iS׼N;qe99+njC2H{%$ԪbJ> 3ϊ7c\s2+1hrc0+ljr&9sL{.9H%|Ki-.fwqXۮ?-tvlZI:.i=Wr_z/K:Z}6Ga+y{nw;\?Cܛd&H|v,j}Gs%^\͊g]wbųfw.kq)Hs (ڌGC8ڙZ|,v5WmלSt_O5[sq6㼑G~9Ֆuѽq0EŜkqQ1>pE͗Ga*̊g+@6aoșHrMX4ωz *.mɷne&/#6*@I&(|]ivc6YF=n:/7G&Vo'Y~c~ϵ| qݪg꥾CVOu~3k JmF$ ~ZؚM0kTT@ӮrMB]vA9^]Ce,6Y0Tټu ɋL1,/^U\?ԧ@#'wsc 9Ȇ? D{"/?=+\p\cClŗETo?b_<1'[lWE~|{Fbvn_>ƹǓ!OtO=t|WdxOxo{x*& Bcw+װ,Iy-3WE_W='|;Lx> '0SG]OGFms“5bgPu٫"P5oz gְYSz//U[W9+\Xsv}I/OnGпaﭳ'j\ץTObNܱ͜SyK|`:%unCĘ_O~_n;|֥Aı ~fGW;)\[ԐIp񛇹?iώoX|Kc#9͵l8}{f0+z߱_~M|#?7ۯ垟8)x`=\O.r-}rs1{AR>ut.s^ 8eӷC-x,6"_zo1bߴ| q}zX[t ɣb]+0옮6ؘV}˺s=fܐpu];;νQt>zH^;PmSLjw WgԨ`stVrUjo=ȰOE+x35xF醫|𛠸ۙ#L S#ɍOjs;YeY1w_Y"OC"AQVS_"z߃ɛh4q$=؁-d[ҷ]_EG}+:wYL}=qO2_V8gf$9:k`8G-`VVՇۭz\_[ŜbͣE IDATK kԮћ5YޒoĕzXz䉪? ~6>D>x<z[z|0'CdlȈLs]>Dک{^~'>-oy?O>tCG 6x*FZci^_H U{X$e#k?F;|=Q1M?9512# sО4&n_51y8v=~OKay%/o~sSAhm=mSY_m<*ZJwjdqS>zg͉^B73Wإއ?qaf$n|Jǰ//LI1w\v˜]wj 9Ů٦ek]WUy E:Ô icjBv4%i=߀} rNyI =x3Pf'R.rۻS͝uu_=*Kȫd}O+<1yhPW?W"{}Wo)Ishɩ7ŜiuݭK9{6غx޵x9 ʅMm\~J>j iq{CzTd}ݙasG}:g4!{tUMBs}cA?s7b.c>:Lst-V_ܞ{Ԇ#ǜ~'>unXͩ/6U[Z2vFE9`23ON>n%\ ++~Gʷً [ Xm|?3}^@QZzUS|֏wվs}ǭţ{Uẅu 뫈ɳiԧ.*G##ƊuV0j&!^\(m 8I˨!l}|DA:tk>qɯv֣k*ĺFՇգM_Hqz5502An&NO|5B3|k_?h'n KR/f?|9x;7?/O>Ь{_bWR*:US+#&^4tqxeO+>|9xoУ7"H2)֩= )u~ΑD{: w6pݟG? GMSG}T\Nyÿ:P((0XB7qE2y쉳gmNܔ9U;1r&{ij:O={Lx)^yg }'IY[8w9%\u r92΄^EmX7+xU;.ʳQʿ+~iLۻ͵z}:8ZG`9G+wײs0yšz@? s[ݯ]׿jn3̣.){'1R)3u$+W%vq-[:͊)w!׈6 Y}qasGk 1N9j&_C^y/fH{`5CR 'u]3q+~/k|IUeUAQ (*%#ʭV? r/(TP E(u^9׌X{g>k5%"Ow/{/ׅ]ǶU|^32#E/1B>Oκ#p~,9I͐E3=c!Y8U箹Vy]@u2zp7؇UM~KSL]k @ɛ׍Y#{=gzA?ىU V.}ϻ뎿ȏxIiNL2oӎ luᚿķ/>>vuS#ZW6尪j~ؾU-{̅)ב^/SAS` Z1 [$j?erKo-fO=/L|x8SO=RMQk|'~|?VO QQ _2!E/6%o% ;)LH;}82718!H0<㩟cݱ3QLTWD1 'so6gmGɨ۱pjmm~J>bm0iG.mD 1xsQ{\jqR{'->KYǫķ. ?7<|yO]zůB7ǪRT EK]Cw\H̷?~YK_R͹?w*v+h8#\*!=7.[yd^g|=͠b2j(9p:4l%s`?}|Է/ҖD=.կ~|)t!Vkvɘ,\\|[c|/._]}&Iy[zjnjHgC_lrULpi!.C᤯94M]kľ O?9E_xw:%g<XC5s(O{9ݚ x=sK>GЂRi?4@ 3uLcbD1P/fU0gy̘ssfKNwT> w}iS>m"71k0,n:` 48*`kٙGZ.Vl'>vS0ˌ>HxXT=}<'^=~>g}Fyf [{{+1<*ͨ-Jj:Ɔ%mW ݅=oW{f.KId;Q|.>'XY?s.օ˽ϵSJyx_K f!~r>˷ύ$9X2sA<|gφ· )|AKwG (9z*{~X\MןV߾#.o\ȭk Gd7M߬ _?\?`!ؤ"S{nY?ȃr?qW vGJ=Xhu"_bG{y+^qyu_ =càXw%ַzoe}#W3בJ\sۣD z;ro1̑[s {lFA'HUڙ__Eb.!f{'n-8J CܟlG[mr.XSǚܧ$%獫yjz@ϓ"oڃ8gק")9r9syÿqמo9A՜ #⹣uX]EϱNg[؃<<19'8ǔu)<'%ů+N␇ ڃ_ݒm|ĽR8y]yZwʏټp=η?sը+trY.&o8Q.2Al16[l#μ̈́1A^˗-vCL]3`ApƥNѕwMc⼔Ȓ}V\[>?v%5#pg_M9.zZV^BDt+}'}jx)9=d>x'3L,c/@DG?ɉ<-[z7ϼ:[LKykk3n+^#uˌc{kOw6m .:9[:O0Hx&͖y/ ?m5Xm%L+qr{=.6<\w/P})šWȃ1>]G㽜R\Ei).}3` h&:^m \xj!k߹w|{b؟|b NwDuQqkX7(៼n{F`N3M6w86g5sƷopʺ#+쁎F9 V>s^Ѯ}p\d'΁I2#.KLmb`jbG䧽z[>\9U]>nsG\@oя~u!w w,N1YqO)q!7O<\_8:]/|a}YHrezg-5q0{ `yVەea|!O2ZC/o-fjU@hKf3gD+ ſ*4>Pc}s}|vMEra[TsN|z@c ]gyx{{4эn0qĵC?+ʓMth풲hɻ(u5ќu6Lv^{8yC2_Mf=}t׋XIpVPi g;va-i-meX8?Hrλ'`)Q[bčco3)3cRJRs2@8ZÝm@9Lpl5?գ`}193sN{Ж-=RS٧-|D>9pWsxzm}K\'3Ȧ ccO^v91>gΚ8c\G&p2~3M>wN%{͖D~ kb_̃ 3a}oG#'p|Ml'׸6nq6*#p"$~?27~JN]Dz '-c~ߚ۱L`1;Zd'vh{Psnf Z6kdױ!w[cP}8>ʎi'ǚvT8qh繕cܮ߁&`҂r} )!Bnㄙ.'~ƊWluj_n"z̺etdǰkclh8k7g`n71Npu&6z(nqױyU+뜍珂 (f IDAT֠vIDuRXڵc/`US9 ka{Tg 3ޱz>6w̍}tvK<3cօJ&=ŔdCZ. ?}k\;_^WK#~ovL#@)_Z'Bk'Q>DAc)viR˾/#m1yWz//efh }=G~{;rY#Û 1zDiK_wօOo|>˅?T5M<*J̹㔼x [r|X }|NdĤiq CÉ4oi}IuΚ\8sP!eck̈NI9fm}orp0O✪C82N6բL\非;9cߌY^кϻp)vAr8Ĵ [+Occ|o{蹚:7t>fSwZb3-7:m\_Vvjь]1z[$G̲{F}k\bGKs~c &=j9x.|#yX7,tCc-1FAZM9ƞs7 ޘV9`;؁Ϧ\-uV'} R{m3OL~{|SӃI<ߚ˖L.X1}$<[' </g.oxﺼկ֗Fh-HDa`ԔUK q^;Ei;/Y!ܚ;0y4^yMyM<:p#Mrc~hEdʺ+nZ}7/zы=x=~}O{q|tQbz;7>y_|_ʺoq>e~F- .1M|l襧gR-\'{,c=_M^>{ɵ82qX2}L%!m0D2:$?cz]cZ0 |Af޻3t'.;Js F1C+#qY~kn~^OӐ!]6s<8υ(bFx|fY`L_səx\C'1Vmeavl,#p2֠ﭰ:\؞ĞԊm35oY>`?<ē>|⑙1 <6O&BvX3 $:&C؜F=\/ne<>Wk]+K0H%=N jbїAXujbhNs7-Ã簏,˟}1l _գkz-/$'± I&]&drI֧=팫c#c7Vq Sb?m3J _u'wģ8Lj6i3q#:;e 5fuס\lܓ謃(*XՎ-Adƨl0H=7cɜReL,q(/.9;@}8CzY]|"\>W,|al]SO>*v\q`1۲2?tw4{L~moGsN=\aC r^fuH/ ִ/$=L:l>踋;V(fxodL9x5ygG X~TE7Tx#תCR C⏤ť0h'>~_w_^_< YvʷzX5y]^(W]˧ 'LIv Uxp:%wWGOa,|W9.cwTR5P|%R&Ȯ^#^םRw=ϗ i"pPiPlZ{h~2?:3-9Q;.i^͵dǁpӟcK,Gl\94˓[汍_}u{[גY|{X^_z3٦\, O\3}ތ8"[*bUT ڬIKN,O]gy91Rp%/Ǻ~??9=pn*%!Ȯ>e>=s\Pਇku^|MkƁrsXsL5];kν'9=b;sɁYpuc^ew;u?)o94/"B&HU9/l˂ sX, dn(OBGyl>*C+ sLh!wz˧m]ʝ,ѵ|3V] qΉ,6 rXӹG 6I^wǞ7=#? 'u+03)yŸD=m;4.~GN]'cEZI{̹=)- V[~K2,-Qg?dsvpP\ `? &7iy8 Ơ NyJt7/Yq1;=F;*PHNrZP `I 16&O<&>*GHuj1@y0VqnS" C>cpp|=p1^{elwcsnڷ$.ڗݰCm75;9ĕlˌy#E39Ž,>GgjOx, q}=uL +*`x\s֬~er/~lcIƦ.&^f}؜b8^1nV|sTχOEEC8|Þ;׍;J8;Z u.V<3h&|`KSg]t d'Af0!2rE ,#cAj-@F:vFn&E ~Õ>` Wp2aNۼ\ϲ_YRmk;ic#N}6 ]v3Sd1Ӹf{rN{.//ȶgȜ|MD@`{pVlH_tis o^XDsZG6]m$ r0WXv`،8•Zg>m,g*.o 0o 䟾e5G̹]Dy:G qw$iM])S ӴҁB.8Ce|X@kF #)<~W u-=Kֻf0&X }V]Ԛ2Gng5̉jդXeFlwZ c峟{_˃/xP L⏫Y7 ryA]pɷտVw򎺳O|_ hōzIU˂;y #\\6eKK>M+Nb ^9VVdlٽw᣾o{[/߻/ǨY/sZcǟ~C<}ȇu?v^?C?퓲I􉣩>OGcg-`C>=!rָհyV)z AXfG.Wg|HyZzpg_G0WmT؄իnĥ<XsLJ୧\-?J1\22#C[}|?'.c+jgȰ<=rj|pzuNn#1eMo'yS⚸g: z> Q{\o@e'p6k,E~v(w7Lzl;&y'һ}>J1cO#-qdsr5+ݵCp;{X6[\X4Mh[f:a|%N[ܠ:^Pb?O9t;[ `5ܢqD1}doQ'#\o<f}Y}8 Ir1|a+G6[bYŇ+>jXyЩu@yG?皜` v|QfpNMZbݙ+> a}|pmjGo1s|uc9y߽x~is`o_kcϕټ.(Lv`m0s9v]#3_"l LH Kz[ +Ӟ!]-х yvM=4G0z;k p5ǔ]Cje4~n|/~B'FK_y宼y_]~7^w?cx28E;6A= e+6qV..}!Oꛏ;#9o1:sߣ%'e2Ԛʼ%Y[7$|jas%m=ۖ%^):?@K&ʳx->eq|@ldqSG7)K dхs,ѹc˱ۺĖ~kn3?kG9};y `朵:>6ϟ<kӃ7gt>>x1k[ϸsOt.x朱V?&Frb-XDs}iJ'82ab?;hGo?`[F7Naj2@X_%عnyrc/+Ep1x,$.=CczYs>~Ý~).sܖ,scK<'y%:9W;K,5|1(O}&=+NLƷ8 ͔~| !FM/\L78)7le742\emg GU` s Emwׅ?)#P˧?뎿G}oo\#BY96~{O?֚XSp{RU oOMlelW`/֡]a[:!#"sepqf~#Ɂ^:ˣ n>W9|I 6sfR,s[b،\{m6ׇ-qKj1&aqg+óz=W'ߍg댇=di1A$9պe96Z-ھJa08ӧc9Yyϱ&}џUY/'i3_Fk\J;YS+ż%Ms>5awO[d1/z>r4^I|⩩bk Nr_kpu2C[2"Y΃1%>=9iCmb3Nƺ8P 1H" $I<"Z85i l^\}uR ɄbC& 9%qj[BZhЇ$~?jl3~x1 vXo ez8cǵ~ dM'_pCm'r͉S%YPl>uQ:1d|M6d>nOՂ| 0^ivR& \C!S[zd+><^\%Y|<1ǚ57~‘%'"7@7olp&4]8ĭcd L"X݊ld@sG:a̓[_h.h>$mVc⬇bZiy^-y!Rf'(Q^Ic}L{8OuN>{$ `2w7]}5x.g/_ ֿ IDATZAkq/CŐ"4)՗򕯼/G`?я^>_]]nF*ʉZk"I>zUvyɄуED%Dae")b>w(>Xw//;!1 q%Q6ON^|dγ\%<;3;_uEq}L%_繌R'/sܕ"#&xm>tGH| )|욙:s3N =%)?;)ostԠl9k܎̼;!u\r>ASOq;cՒwiW>K+#UʫU0gĻ{09^3b@) iG95pO. 9]w"Oldc0{!ȂOo:ȷk>7r>mUZ`"}8eT֕Yɮp?$TyvM,ksTˆ0{1oɾ|̳ߣMH!~O {-9N`ێ]ycL:Vº(:MQ \\D*f0]f1:* 'Xt/پx(OkK[>k5ǵpS݂|626zdWb6*ﳾa9D󢀖>12p&/&gN2,{_`K+ԡ~ߝAVsˌ9R};vy),Ɲ]|15 TW~F5HaE _ ZǵrĖ|O&6ثyAYp6pOբs,cQsxmYԊ̊W'3vp\BƮХYe~+3|by2w6Qݫ&V-U9S]P(Lk*FO 闺&hO5o ItX3K<\΋|/\EOK>Nk{?O㽄=-)ly}8U!?y_',@-²(Q⇖ 9!gfl67<ѩyy{ .1G>ymauwO-Gibx? _>z$ṽK.D~FK^xYƔPpgtC_8eB__#V]@Ù^)H??b\ݬ#̺X>Cdgi &VZbXBVjй.ii,=MG1=ux?FѢIǼ19#.w ]ꢜesǡu7g8,fV\%%-10g^[-V,J"Ox/.iRCѓp.K?'"4 gb>S W%QٯQseTG337 q% e3=kbxڿm7z2:7Q(+e]{W}^ˏdYxVx{v+R]sqg})-sgқkȦ>rjTާPWdDiI v-tb+(HvüqUmyXR ]lY0qbF>yօ2D1ẗ^%E˴Cq^=1&q<| gzCÑ9HR([|򉭒>x:ϭqF_9TYo{@A(xF4|$H4lcƖX BfKc^^!ǣL.!17qq' 5>8.#5_]q35fPU Vy37JōI(їmbIp$#O˹_>َ;广jEh?cŮxeٺvDл6pڥ)pyk^}y_ky]-j5K^oT%wtwyE},^KmrwmK&hK /ϫJuW'a:9PqC:n65 o.K^nG8X_u@} 3eW1_]{Oח|v/._՗l<[u$քU.z|+°(mO<y/1-f~o} HYBx} bğ8HXud –, 9Q^%L c/d<89u }`GL\XuBSk}VKD7Oqgm 'OZ[⑏`KEُԶ%'kkHuwz79?~^9~|k_H18gw?˗2q+ <3}b&<z腗nɟǜ;م'$GZ$ 1EV峟}яO_ϪQgRSx_bhg-K)pnjn^0  y\<Uĕ =9 =_<:pZ[8cXWIL#c`̱މ>r( qpj`Q hZmGL"[-'%rrHw'AѸ߭<0[ o#cy7E;8WZG:׿j>|`ҐEX˪mc|8#ǂqa>\CŹ-VLGxg~tyZi¡-z| wœ2)@u(uz6y;ߜ/ uL *kNv7?/]=e!<u0$lL]pè=u./__MoGo*J]eR\бO}&Wv Lۑ3<֏ZOmo}K/??<8.lR6Gdmh*J.>s&_Qw}4_ZXWb+j_1yՕ?dS}ez5isrWzc5 h_Qv@(g11Eײ,bR]*>^o;޳Z]0[Đnu#U#/3||7u oH sN5!L;5_"gGxt H[|3WDc'6z /|+S/^;5"4R H}]V4\yw<9GoV/ܶыO{C{F.ċ0<4@oRolq 2=Nf;odB05S狭_|n`R.zO٨NӦȂ9l |/GEt 6uuD׍u3*yb:arH<z )Z=ɩߔVU|ƶc⦶Gc>vpO^C5lhIH9 [N+ !{晧?䡈Qz3DzU~g&WaD&|NcKd?]]Q.9u\rG]MPmrx<t:Đ1`#F(|&7rḖwL_pW[*$] .TΌ_;E<998L_gz)Ac\ 6x, r}0zؑGO7ӦxAlh 跏kP̝9ëkðÙ>|y%Юř1suk3hW[[K}v\䣏ƹ g~8C$kYb/Ղ'ۍӶ@gLu ~tyILz`3cm}bdޖ?-܉61yp9wf#_ z]TO|D #'4p!}ܣ 1'.r;c'[ <gn>|`< }Gў< j3uQ:0I /M{(x7ccunr |:؁ɑS}s/~׽7.Zuಃչp\/8jه/ŗ]O淼ݧ.[g=~KJ."9C\jmv\aȖxL=djC屦z(09o}.~}oG}abl+#)JL>*,*^Sso؃S_bLcz~6M=95>2^DpEhUM/SdgS;4q$1I1r:~;^ UgoIN> 6%iM;QvNrۧ"gy{p35t!)~AX2_£P:M>[<78Oؔ#=?;VF;Ofi>o[QT8T]³϶! ᅬ7ֆߠ=}l]o.?5Pu`ᚱ]3Y-]rh6q\uRD  B77-g50%tlK׃+53>`2O|?79 |Z+ qhAUQqcM.usp񷪻`O+O{ͱ_pG|/o}_x_˅u~ ><}c_SL~wIJsMo_Mv}4% 6Rl9p1`CK=u~b.x[-W*;r܈?]YqS5=U 1*Ɓ\U2qhoqIb҉bDq8>0ގ{߈;q-Lj.?mD݆4<[1>p똘'}:6]ō0.A8,e_/X?+qor8sT1ۧ}0_9u[f2*9mncj(sMӧ6zNk%A=#3!GfG-j"ɮ.h/wkm.P :xfh~tetq#N%İ?7t̝/^}5z_{՗^(Ƈ sЭ$Iƚ a0/8/u~?zׯg&<&9QY+hcߟ}#7񍗟]!+kҼV57uα 'Uأuo-(Y삣%ޚ?$ rd烖96昋O;W¹7 i /&'<`/}drNߍ3m~ɻv;6jaccȼ"RuMqk?+3?>hX1nJ\|\Yp|$XqSxYZu#CO2yr:&O0+ N ӴϕHlҳy¦Gb޾(t$6U =">)_6H8,:_'Θ&`G pb'~&Oblʈ']6dspU#G8iH,>Zcƺ*yB~?I)s;<' *S9?Noˮ˦c56 7Ȍ{AE+̏mǾ1"ܑGCǃ74yN?6裣-Ϻ~^_|M})C/|Hqqlr&VUt̥/g۬k;k?\7_>[կ|ER^b/-UCZK^%/yGޣ/]k45b[=r|swcm//RwMc\(gQ9g|fYsյ3:Op_nuvm#u#Rg\^?ui`$q/d͇Es{Fޜ>''~\kgÃ>4hNyt:C^9Wd362ŁX.5G0g>} l0$[;0V`"- p&G~cGi[]$Gˍ Of3B_s\qpA22qXlg.B̿8ڕIz!Ýּ_ϕ[bMHN=59g5N@Ga^ f8]{6mD\9q\FDY) KC;a;MƳ\g[pǭ,Reć'&~C/z7W`G|^ٴmqry߁o.a{\u}DW~Kn vPX,Yb1ԜC4;'U _5 *|I ;ݩ#S˒V3~0M`J߱`aug*O>o`*82#O jozW,`4|!9bP`퐥&pNȖxk fbIT='-Y#w> J:ēGtp\l|bw6$Ѣ>p(VDOxY^sy/3FDŽgx|MnEzT Wygыz/b+^/ y塇^s(nJ>jcJŖ~K^z??/oyӛ/?>O|lET[cC3h?,(g ̣QkU]vSf-=7~vs#v?>rBjjZm7 b8qTCȉOw/z?Vֿܗgօe>sfL{b'Ǵes]B]UHb'rrrp˚QWG5D%c檐}Cy}ִRzl>sqzq70˭!鼌atG??#,BSQ{[ ]3O_~5~~>??Po@RŹUȜ(Qj;m]7Ô s%S; K޹ ܮ97d11wVAAE{h/鲶;u昺_6678rǍk Ci!6jyq\Ǒ%bř# 䠆W1<2 ι=-:A=?&_:^U+f޼wy=[?ξ^>o'61O< k#cEn_n60|-vsѸp`&^579?qi_k@aߓʑ9]^}'Yb m^|.z+xn}M*boT]0i,#Km_Tǘ͡>umym$. ُߊoUY#:}NԚxkR&<8%o~ lyA'>.<Dr!LеN5ћ<I$IXҨZxb&&:9ag9LVuU=E[g~bq4 wNۗJFٶZ"gvEγ>sxnVuw9`"?Ede=kﰫr(|!7A?b?Hr[5n8}o$9o[돲Oʛè%?NS~dMx 8g,W9=U|5ﵓ3&*\;6X6$~yba,E\w ޠ+>#&J3jxW Z9VI=M{WumQVj˗*b{8̡sEĬ9t8x()eLتV?1o߇ȞX~#}~ƧwOphw'2ﲒk娯 bO0|1OQ[e+6?}YĀ p%\lLT _OG'YoƧss^/Tw=YB=)<5E uˊscŵ܃6')r}@S_mUcY#\O+⩚_8=S`I߁]Sc|YkOM=gM2?=렞]SY&WT<[?9.Fg5ݶO嚲ssY$4``<>v'&įXx/6{ͣ>%^{s/K?Y܋]/0ܤ3FNsz5T|ՓK[_|,B>Դ޹̻(DF/ X-ҵa$f?$5ZamHʲW:|zɻHICs`yQm0'_D{xynŷG (%`b%3=k3㊚WAm| 9 d- G>|%Dž}~zk_WWvt>*+;ՕlO `,;cV 9Li^qOVMֆ撲m;yAՕ5M{_wpe=+}S~#Ϟ׾曁Wпۿo}?F o#oMRψp _h7}"؟yxSכNwf&SH`ga'Z??˿K?_dq2#HqWT[?.?]sT+K 89bSq_D-k¸SƷwT&.*gۥ'69کf/YaSɕ1gXʘz5ܾ!%?X2p"q_|H5G*@{>&S{,c{Lg.<2F\c>gw2U,RO}^`$<_;~:85nL[\yКډ^ˠ!'Lی󞬉9/I"xxƪ:O?{}oJeu\F1.O|b2?cYO.{y:ؼʉ3ヨjl%7up[Y͛1Uʳx]'ݟ9FΚmyy?Tkst}JmWbd&'>$W;(ȕ#@JeBw᧳7.J.ፘ\5OJx@db1ʔjrWuvk,mb~Y-'N0s..vxלs=78庱S>ew!pצF\bL؋co=G'[yOm1-c\>}Lضqu[1?}moτ~{xvY ޥ_}m˭_]Cm.}̖G~ޘ u'̅&]u*KPRe߿79@jcBn0q*=}c ɓθӆn-ξlJ?1j cit(Rێ:{|kXܫO9s`1yE,Z YvmH_:[6QйN,_~o7GXeM%g8sO~Z9sa)~af5B>_/G?~Wo/o_/LERΒNk5'YSbgoeoK!bGmz~O{^SCّ?U'ޮ'g4%Gpmpz(۞>8l`K=x#~,/+7ڙ׼`-ӽ53OQtoQ]Κvj!=|Ϳݜ7yk9<7\SMgWYgnt}r)˩>HMT#Svru \Bꀬƀ=::o|WG2>l˚PKs랕VpCݹSVyCxg/Hn,bUjGC{u[? K!ٲa/_ͦd0oݓM> L%(~J{J13ϴ}O,rbf]Y>f5^Wakl+u,U^6l}N\S熵.YӇHSVM: ޡGMpկٴ?z}7g%qh,fTqUD+y{>m=3a']PO[EYux3k#Ȟ Q9<{-n#7l㬝H1F}VV Ʈ=~!t9rgK+H.J9S}jͽsV5mHPbg|#EU<o"&X`32nڝKʹO}qM.3.bw}O>8-יw{kgR1H<;lM3t<|Ya2ysp M^<@˙uiܜLZZM u1 06ċEu.|vJ8rroHSG~so}W=Zln5[VkC :d-jq3tK>WiWJAFuor6u~#b,97l_OFgo??V5As&MveD7KNkOFXB$E6NK^̗{z7_o'%}QDAלU> $"oz'?y֒7Dƒ'i uS,#Mu*ܝXs :P~'^f{u'YP^'U{͘H,gY-@nzy^3>D5={ͱG }[0 ׮ƺulboo ;!3]>By޹\`fsM>zM;;5ޑi1OB'PS.ghvvv`Zǜ}bLEXxX{x6sS=iwO>rN9CcSK$u7+}.þgU߈ \hCM;{nN,{ ru,>Z͙ܙ򈭺 o [MW 9W;NJpi②u|P?:Ko'+~4_k?_ۏF`zzÅXU3H`kw||O=t>~ko ߿O/A޿ooM 3C0_XvicDS߯r]L#),Rw#8kH밄e}i*כrG|cϲ&۔b!b6S֖umݹbΚBI;fsڅݙ`뚾;F1JyEJ"O=R?R;=Ǥ^|b$>Nv|!1x,2>e""ᰟ=WpcKcfW6S=w֤)\|yi;Dݹjۿ˗'n鶀`5^u4 u#޼f~|ơ[W;;&fkqYo_?ub1QgufRj^o!d?BpawFO-pT,V.zk|fs?U]yxkQZ#3wh<"mTz~O> .^is53u1I3+3~#.X< W؈dHK\];7]ĀC Q!$MۇWUO=pa t֨f G?o oiꍹf4wkY\Ꚙز''ow}x.u"q[51jqhS¥O@1D1ԙono* \jANر7Fe^)-Pyy1CVOxd˫{ʞu^=UCoʒ_Ӟ*Ӯ"+>ll7Z9hɇadG;\J11օ-2bO\1 %|&>?0s3q7y |An7mO_ay.~yyJ{4:\,1YZ"&o u ֎.1uxy|}o??#W;ov́Vz!Eungli|` ?o//Y7QRW34YceO9K}ӟ+o z7kry"V_c87o,sOUkb~Y,mrTܶBϘjv5k&1fd/T%ITqw'*~3[O1Ӂ%?ٱ&~gL{oz?ͯ9`gK>֍ {M"}ƛ~~F7|ɓ={q~)>+L#G=/wq9Ѣ n:㲝N5{3?ӲؖڙGV eL՞㎘۷y߸,$+l;渚XY>pӦ }Eg&{R49󜑯yw?5λΊ˸[>pϣԺԏ:܈wKsI?㣢<'<#&s^uUgN" s̘:bXr,; @[w $@|܋lZ+1/J5c˶(Qêy`x/rSgןE(GOE_Lpl1cN$v_.OA,.iqn3zs%wqf{7>9ԳhkN^e>:@ݾ|^Y<\sp;z،4-ڹgBܸ"cSk ~-2U!!wWUM;ϞG֑,{Vw $27]?}ԊɁtQWjBuHlxL;{˜GqBK ڼb3n`ꀶ!vxQO҆Pcp9Y[aY/9/L_AM/?bgl~YG׋=yvWTRr~;o.]s kfdr+ں>nԑAaɉ%?7r|3o?o?S??coM4}9rΕ^ν&%F,?aX_oď/}+_7(7QGoܞiZ ٪n5̕ʞXۇ_8pGǪ[6kGAO걓6f2_8Uck*y1NR+gieF({5v~g}뛙A\ÀM rbȘp Uozɋ.dtJ\^xX m]s vIϞr NΡb_a8UI67XywK3(#ͬ}"K1rƋ2833ZUs+3Sshtw:8E;xқ_/jFk0yKE\C WPg ԃ1檘}؟v{c>HYVlJyαm+暀 rTMSguwco v8)x97Mó/G}lz,kHL__s,kX58p?NLwV9CkH=b2]m۸g 2v|oF1;4Z.;81tN$~ssGoJjT6b'^_sڷmޙg}vup_X]x__ab_v7Lm0|چq{ڢTF{keڔ9hS>a +׎t0uC]/o&["pn.mԞθaʭ9%G}{^cƍF~:]Nim[3󙷿շ?'oGm+7 "'cg_^Q厳hoB7?'W}0_[̀OK[YaWknM9OS$A\c/a@Xr+R$ [#y<Xs ބöT&>k՝knN.xiM( 'Z^nkA[ʻ-rUY9JhWqn9=[?k腩u`Cs*J[S=gc>|}cƚ=ʃ'Ŝ7׭{D_i>=͡N]ȭ'.{*iM枞{q'ܸ5IZs㘳q`fa7OքgZRWZ"*"O9l15V37wWHo_?>+"~Fׯm*Q8%>gy%%˺WU}+ [9k>URce׀ o^@>5gи[=6I<=W~rX)şl~2S=ȗbuHsZ_@U.⌕Oq'z-?r6ǛgciyG}oßOߊ7[㪥Wq3zD劍Nu!~fl@5l\[cW0ar=yۿLߌѶrkFK}Z1Z|\ܥmcx}6yvr\4^9kv\眬uA_19-vwm7nr7:OAH}Yay>u 43ҙݼ^5gZ_文L/޼O"bfF}3K<XsYy`#Klkւ]]9g|Q|3׌oN=Bv fSi;jqUZ~+ɠ?zAK T>s"m~zbN[sV9OKIsX :_pԖOEn_a8ka8e{FdBZRļc.&)Wmk(Y&]kA2@۹W˛'rk(rL N3Q(kydO<0 g>hE?F`ǵRݱOpP؊֊{By5bsM{.y7t&DZgF5:ؗŚsD+m {m׬[\*!zK=ܬkPr gǬo\gƫ#<ۋu"(LS5 >^1v\܇^klxe/NJ KߜGWtw!gNj>bov IDATž_U% T 8w~P8/LܺSRTx>ƏǏ,?o]Q|"'hUMPTt*|/޼/xo}04O =دHo<>G{?݈a1ٳ]SƵWăY5-bYq9[Ju,CZJTXRnTU/Z_Pz߲}%ψFc/wDq|ou!h<U_fvwtʷ㧿rsyf9tpdq4<|pw;yfMlŔ9 S+~u_XMdgkr6eC~c̡ {DG~y&|ڵ#OƩ+}k4{~M 1Sb<uH⼉H0ko;i'k}[]2~;ӂP[w~NnԭIh3g%ڸ>bIhl 2fN߬uL{}r}מ*zrYC۔o+}ܜU7yxc\g=_ʣn(Ů:cJ \_D-^7%1}z.b=gz7/;h/ʒ0ї|W{yqzC7Sa۵N0U38gs*|#wY'~C>zp׶rdE90gTj/}Ko;{~$~Gw'SE%gɛP~ ~W՗O$2 Z)H9,_͚Ƀ|Ͼ|!sa{lw-ids.VNt9g>fzEnkX1cߴbQY^.XW.T^Wѧy&/Ҙ{^kL};mW>nmFݺ[!N%vG4L1SVY +@lXG)c}`v.X` ] -=C1zj8$0^ 9={>&VdJ\fEl{3Uc. mOwսXFw/Naצag!'&mgoq_?H̝Wɵz7ʤfDsn%^0c c]g|eeaQ 40k%.d9|ܳ亚%yINB&oFw/'kc/}hnN[Cܣ\O+:&s5ZzߜֲjЉ(ţnc+9s>e45(#rkN=YX)v;{++FvCMڻ׉#x0'6W$x^b G̽ og?9cvQHPk"ٲhej&`窯z/j/g~s?5*_HW/9_~>?'FLhSor4Uzͤ~J-ܘ\ t;.um's\QS\[f4orWE=ayJfu5,|&&{'VIdjfǐSϊkPy~"cGĈmͳuX>y:?s>}r|x9O3\9v:{4r@4w+xsȶsUGՇy7 JՆ>(8>`) 37W'vbf^ %uyN u%vkM 4ynW:4vǫs k֞披dKqfqJ=RGQgnT1}}]Tn"5o5}O: Dbl3x*^@qW30fˎn,_?Z̫\~+h{9˜Yz^qJ͗؈f{-j2.spEu%6TqHk }Ï\TWn3O23{3ʂY}P&F'%93kBLE;(^ڷزNn q9cL<{yr̫.32(aր|Zr f>rq2ƈ(g\O-L'GQY:Mܔⴭ:4\rT;05/>aMmwmرiW7nr6O6jZXo*Ϳ>>sG.0o^cnx՞'^}Mo|/_ n>X}om_]Z?}?˖#_Jܾ:gi߳YWX/0TׂڱdLd[gi/- 6jϵ!̭?e{غogNm wی^[ck^|գ]|o M#rעqamڔS0mэSu3XO۠IMy镃Y[[q԰(y' K{BtZ⑷$K:/~ǼW]L$AJr.ug:(|8 ֭1SeUWo%3&O٢׼NUO~c9򜼾سUپB7TՒ/go回."];g9bGΥ{Z&Z{⧯ݏלd'w)rՙD43l_gaYp+2 ?pd\SGѷ\gяg\VhyoL}3th3V)H}} d= ўs7C [@rh|ϼnzE?_oMnC\krc09_k=tPi]5Y'Ƨ_iMi؜ &gwds]_?>SJfz?5nƩK.^\gAf /xljM@^aU1Eş7k.Tc۷վ3e}O}.~G=Y^)-?dجneQo|R7awkVЎ\6Yje g-f s"|]lE}#ƾ'8Y?`&Zn <FR&eYL8$p{Fz[3βS+6}j!~r_vن <bu3=\ƙqGėݧ9MYy*Vxx8?ba^=J[3ٳqrqݐ=|윻ڑ6"%8**W&3nbvA'*OmZ[M%/|zbwMDk#5 G=QL~yڙhyXo,ڭ!|2o"Z9ͭYiіYVn );qmo! !vѳ%i焷u2/?NzaZDϙ˷c6v uO{1>0<.3㫪T=y0Oւs~ ̟6{ı7Zw|s_:𱌟cŎaL&!}Xc1MhɉoJc+*;Ykا|bFg}X?\SsضsW` .vpܟSz]'q97[Mc>NyP=c8a×3)6/b8n,$Xkk\ڶ8dSD*7NПϺa<#W׵:cǔƧo~~ 1ަ20s66w9>g1&.έ[\$-!QqXI~ղC *N5sN~0mg;15nW8.{/XIJgѾvO@O7kqͻd@3j^0Żq!f߼te.%6MpWY\]Ӈ^N? ^:NQYpSpb1=XOw}MP~lqcsENn}J9^d9-^lAhVا=Xs^}1m﹃gN3/ϡT \&Nۆ-6bu,{h 5ڔ !YO~<`Yj3GI#rwx< 9{=6Ѝ7WB:ĩKݧoԸ0 Lwubȷf/Ϛv{RNV8b/ 軝)vͤqKҽ/ q bЩev$63g9NbNĩeA0yN_dHlbb7iK||)IZQoݷ]] Ϝ]r> k5ކ{?k1w溎v}kN}}#͗vj[a),ƃ 0#okv7B##I4%v,5֔_?O{pUśc:ٻO[q} s@J?yW>sQkZebwlˮId>YWi[KK/b§qNK:˿W_S}71ڵCw}j7vF0SyfKKF3l^׷78'8I+y&P?/&deƶSYtzje :Xh*gݟpb"F9=}<vu>oN1m{uCRcHۏ8@y%_?[ͣ=oWqͧ|b!?T:y֦4u ^:zՕɩI+fEK}?:?k7Bz#X|,y.m NͱY rlqX*$ҿGhrlളI%\""\IǕwfZ_m._ߓ}{f_2w(rKo;Oa*=4 :q,׏Yop`BMn}g1IĖϫ5o>+uISU \. b̫nrv͉}~26{u.f/sUig?+'TҎ&2}sBLlňП1}`Hs85hqooͯm\Y#3<)[bc]ϪF[;ndD9oFrxW?rgTqOu%ÝiK61yfi+;Lħ<]O)Tg{{<1g|ڽv#v䵹ŧb>o-b}bָpb-[M{&nOO9} goi)a羸OA쯱s:1s 9-j W99zagJjs /?kz?>k|:rrv+RF]Yi_vb ͇^u_qwin=s؍7yˮwʌ3IAe3Դ"Wmk'& IDATmsf7/ŧCbj ɏWũ#ôdس|cϞni Mrw lס?iGa8;<]ݡըLfJ!y&pU󘄱'\]l4_9%$`M;v[5>S0ny7]?Z ڧd/F^sկ ^ȉtg6Ө:"nKr>ǜ1`}H'/~Z7/\SgVХ%n49cj}Đۼe*b;2jd[溹f0+Ϯo˘X͸c}S~Ofc+Z&@k70;n5K[uk)z^r׵'^9kYXjCnzzԉgTfnrs~1ĺ'Ě rIcc/6qyreu7{;b=_L*g8V ] 1i٨\Hl۾0ewe{7׬.عߵVE=^Nk G{N/c9Sr&N-*mJy6j1ZՍ}ߘ)'EiMO8^p if7=nk嗟 sydx̥}b:؊XocF\Ϝg'>SL*Lg1Y-=wu[?^jM,9L-1D8X}.V8'@Udy5Q{ZJyk/+>^ViƟvOyY^jY#Om/MU_WX wGͭ%>`ƪŚw3v[׊u}k{56߈L\~S,A~K}|ͽ9k {OT<6n`},#YSK?qGZoHo΋K/K|Yyfq+\{=CI$͔62My!k[Y:{Ny;gn/+?߳G}0`[9.Zƒwj;{ `ڳWcD',]6v,t| gy>IqQ뉯Μ,bVr*y\t_]~T0qw썟j(yns̳8oz{{3òi^3VXӧxԒΧ^䞉x%kIǠ;C XW8#CIڔ_r_Җ<K_tb$gyӸlc\UVqٶ֮b֑. _A!c{"3Oѹ@ cQGwr{,[SX'N嶕}ddWNCӋ%{k:Ӈ E8 9X |]Z{o xXAf@27\752k`cni iO$o~d+vwU1`Yw|Y{1QN6ODz;c{lKL1,͎-UO/2Y{5>HG?[_$r/}mGUO,7{~x;vmJ}V8 7kyݟ\^ԅ;=è_/o3=jrλeƬ=1 O_(RN{y<*SsNt+5Վ0֤C>Y9"p3(+sqe^wąXʞNNmD3/*q16r=˃uW:G_'Q b{$ ֭۬I)G^a5(9Tbݫ>}mqjc?s#kqX3qΧIR؈\Ђ\\O䎤3ǽ԰Ebr_6~BJ1S[~TVc7񌓛7$oubv0qӾ}Z|cf֚:eS$ ^vܸ52o^監[7LwY-͵+YWyzR݈ubd E=}],[z2K3wC}"p4uX_Ө3ͣMɶք%1=Foi^Yo99!AkS򜩟=̜ش{8zTy=hUK>slta36bs6S5Ҙoc`>/YIJCMNU][7r1ùmU6c?$gLxZbM޲UN+G;Ĩs(祄vbjn΅NFRrk1ε8t֥L_۱M;fr)ɻyʫolWܜ#13]3c6geŐk.g/İ1:_@^MYc>Cm6[]<v$=܋K3voJFcK׬e |X~ڳ|_b;c֣RlĊWN`]6v1> 3=~%4ǒvMcc"H,Y6z"(;dzγ;y̳f4*Z"lb)08Bds)kOi&νk{kQͣ>XQw&.хm{uy'r ['vb# %iMOcq$;ǜxsq$-1J{ؖk>j  )ۣ_Yve<}41j͸HH˼7s%w3lYkWHlfNYW&8nYCZUj%W_/l=z-tOH`|cꦏ*~*~޸Q+z:\O[GڿhKHhW/B(3Oa;H@Uw{u:`in,jֻܗu9i\Eʹ|KUCBY7r>诐3N掫_]ZckE쯽<<5ǪQvϐ3CQ/i*V߷u}C^2~^ҪiU-u$;ٌm9}BNL$N벧& 2iЊzՖ3Z~Kvk;SSi}O֥}u<[ ֫'^؎X1+p\;ݸWG+^[4_ߗ1MCru76}<.HWvm1gӯU?pR/9+<{sW{vkUgk3?9Ɛkɻ7')Ĺ҈-G^QKi:Ԩy\65G*_L|c˱a8$Ϙ`_eW/[~AصĪ<߈͗{&r4[g^0sK,Zq1+~Ͻ >w!]=uʞ4?\z>gg>yx-}BWz[XJv(%^G՚GlG_\iSc0s f|sow:w15뿪=A7oZb,k_WzZUkʽgwuhN-t%)os8d>ܧx^ۚźמǷo.?ؿFO\6V9Ŋ{}௦ f[oz)G]W ڗN<;ĊIieGŒs%:o~77mn%R? Vaa*w)DmLվܺg:Sط-z fڜ~dˌy9y>+ubU&?(6-{d Q7sixE63}n}&ѯ>6gعUNT>. ng_nu ȝ5x~`s7Xa6< |@khT3\C݀vvn[_GGzem~޳O~5Sj[5mGԚ綦6]7];P;m=q_7Bv>s4_Gy8۫9Zע156p+i+9;U]Ê[]YjOqU/_1|WߛИ<*gG 5Ff[mY}oƺKk"kn]tyqsߓ֗\C"Α#_κ6&kưlx=鷏N{y u&ˇeU0o<+~o[uWWڝ\5Kվz9bkHb2L(lynQqao e,CcV!jў5_Ԟ[{ ȏf:q!z5Oov\]{s O>-yrqXϺH Ӹަ3}5[/jD6Gwbݑ>]?I9qWkNLDzhS!<;/{^,ݗc9|-S++ɇ*/쓈b3WWLY\Ι#Kg"j/ygYމ\z%6V5|fTMQ8f%=#kF~o :従bnho*Y/֍'}'yO{,rp}s>j;ZgV+دzþ4&;5ά<ԳЇF|'xkS=Ϛ ʼn[}T ЍiUWÙ+)gbǯjӝ/||<޸X8'&.njV EmW 1zwcn9s ߳61 0^=33i,9R1ߕc巧1/3:C bFvd>\rӿBo[#*fϸ<3r,|_q%ްgmw|U~_d=g$y[9{kVp9X^cYvb;~Λ NR;Zr+tਅk{wnfwrfAҧnqw^ZxHy>/fzp|ke˹r}ke}-1́,V+yL؃:Sǽ9E`w~"ف?ꗻslC' {)n$ܵz}uuP!c1rϐ~j h9;`nN LҼwz߻c-wI~99I8~¢j/1j38;L4kgnݧEBjސǿt\k/ ZN e65 \-ĩ|cVGxѦ0z+/ArleLc9nX*+ުzKB,|ɫ>)V㉱ց?93WfF/kQ$H/ր@jB[{V|4=Ԃ,zy+kMo^YVoصMD5:g\{¼>9uo}v.r4`k_gqch?_V6zCMW P[zo㩇OPs`3Ub5 73Nݬ+*Y2 8K#vpZԾ:85Πsٻ{?ն58s&1e=whk-ZijgSO^\r31άĶ M:R_=}p/n}̫!OʏS yr)amHy=v]HĽSM=':<;uy7o4vl!fgb W̰T̗=V2oW E,<M=i(ɑ}vԶbŸsF)@g <9}1o, ]Gs0|RZ)X6uO6G4g5poLKK\skNO勓Y:ȹVLl̓/c_-H{q͕|ޜrR_Ѷ<7sڜ]xAlQ]?(XXE=#"|-\VP6Ytm==ƠzbU;wٿbBmOnu&ߺ+0xwCo~՞W`u}!g_niX3~GFC֓gvmq>ާ'LWpSR#`{.hY[k;gSK wg,i{骽JM5@?B\s;K0糷>3,]S+To P@e+\͝`o}6O_!{Q6Uϸ+|͛_m^MՍ6k;٢?f<>Ď_:ls}gxصT3J}U&ۛeO2_O]g:ck䴇ҭ*2j HA+OTӪX-8vu2Sgu*"q1>g]5la_MMuк}u7>ř~0Ԃd[U|axƭA_} zxᾖy_,nEcEiܠK¬GPz?qz.f'{sZP{m+?W/\sN? ]%z5}u^Ak}_8}Ǯ|%>q׹f-j|xL|8wjb:G?0V;7|7y{.zc_Kgm"u';O~;X7*:'NM<}/S>+-L~0suLpuwA.Ck;=yT.O5Lιh_+cs띚'=U獏h/Հ?l`/׸18q}YYcW~ a7fM7.w !:ϓBpKY;I>ᵁ"W|M`o,_[{mz~a) 5;_V4XMGAiٍN̻cXkNnu0C|}٧w{+1gc򵯎ZJl}j? yOv?p{{7ZS͊==='jsz~iyc'|^m\?5VX>7 VhJceC!~A{9[JY hzowEGc|j^'ZOԬ;r[s&Z`ZJ(8֦5~S E3̵\=kSc*ح\;?g׆ߑ}i{ܝ՚"l\,4E>Y 꾗 {ʷNgˏifB '۶ޜ~3w-=y5B0UȳSoվ]:qg{Qcf|\sskЋW-خofi2DG(w[yi^_K d▗@twZ2g_gpB}غe-98@ۜ;s2n=Z+'~mbRO۱8m*დ= V9Nj_ᵺk{0u3-z8ZGʼn7֬~onՓYY|6&݅_UkÅ5v9?GwAO&tKګi=rwnsz, |^/jgBkoL.8[L}Z`t iU}j>v勂<wWVpPv5|ӻ+k@/z{hO仿x!NY?VUa`\퀲j:6nx57N&Y,=Xbw."CuHMnwߓwn;aտqD[!=?6[& 3nD3=K'kh|^WMS1|h{ ꍡeؚo:K-}5gtElM彜B=ݫy{_mLw5žz[ٞ2ub.d-/Fl U>{jk-}8+wW9#.F* }s5O`bBzy7%VuX5\G5njyNk4m$?3M| ݟMb͡3P18R ׽vyJ~Z;[;~d"2?~3%gu[5%nl].uQC92>sXܪ!O N~WڛKɩ:ΓsM=I1#eMݮc)u^| PlO8QYgN[i۷*_i N ƌ`EoYkbUeOgh/ݞMk;]pϮ}T{S3rO 7d}],gY﹜/+.ZD g>_|}j~|f_U Ĭ':bԽ O<ցξxy[u'ֽoE_!Nbk::ާS{uMӫu,c]{+WsUj+w6h`ŸH/2nmڙ/x[{jwV9tg/}]u:7 %V=ό;GXt]Cpƛ_<+P!Zw?XG'ڊ}WvFF9z27jyQWVv%Nǹ3q~#q}`3cNANzg<{kz?/43ޮ)f5A_`uKlFb"I㕱Nư;1VmsT,D{Nnqjع cV ?}ïAZr+o4Sz^vs[՜z啾eOlz~;\;M$<{k3M|8YwzRB^~D5}.̞SHYkBV|Rzvoˋu.cB1ap /lu||{LZ/ܾc\siu#zyiV};qzE,9Z[N=1I{{ l>}_K,y7EuvIsw&yyoժhȟ~Ws:E7M;6֖>z='NOׂw>Ƶ@Hid@)&qZt;Ħb}A/}O~DVlUFw"Yݷ^{֛s1gmkf.71vK#{H]53Wƌk_ |^Ŧ`Kc߷،M<7׎B-rO*f@猻c\<8~NJymrrϐG|sOL^.><'VԕS119/w^jl;6xkJ[˜Ɠc.qmxjXēpk75U5ݚ]^g-_:́F>_qkT\z=8yvϾ{z8˜L+QΗ9q%?}Wڪm CM >Ì>@Yb xB 1׎߮c﷠Ԫ:ԓx6e+{}b՞zgk.)L ~?<8ZiV߯K|sO' ~ R{TfYmkлğf1NR^ulş3:ORUg /|p5l3ÛԘ~Z5_g Ť,I Zղ9jMoe+b'5{<345s}/m_|/]O`nGT/%-{~8:ynݱчׯ~x2nfI<>ًO~9\c K,82˲Y@Za`{s׊K!Zz/b3,k߸(9ٷnx;5zE؜w/+~+X[1_1_] cb+-zw&~}5{4:ԀUY~Pks| gl(RS<ժh\wOxuE\Τf^bX&/&bw{d9_mέqVʵ©pwiCQXRϜ'nW p]] {e7aML*سuzewИ5i8: 珚^^fۥ֜s~`_|,1_fpVkgjg7x~@@ Wgưօu6cYns3!sr/EHދSϢ=8jj_կ笯y#v=Xϗ7ukUc=y櫮t9zjeR6`z>qDr~:ؿXbL,ൈsVOEQ ~cŕѴz77KvR/(6ݟMbUjnWYZQ_s;1+'㡘4.>]ی78gOiEM]'MOHy_GX4ڂwY6ɩƚMi퀺gĿܟ؉L>Dcߌ9ǟc=S'`5߉x/H&>('ػMbo=)̡Ʊ>c/cy;/lK_s>ξ&ijϸyR{f!v8Z|ق<9XEp6%Z_ 9<|_1\mL'̈͟80/j;"͑C\jfO w}͞^`'ǞMtW.?wAl]kC5hU#q뱔ᚳUc֍q{Կ5RΦDxsw5=wf =3h Yԓ\u?+x3ÉOV͌+uΞu=/'0o-YhNi; q+]i[X-G6xSy}3_ m89Vv: 6fU~6> ?,S%=౴R5^gT?9sZor?n^jw.X5#ўl޳9޳8p[ 87D6^YG(t"n /1f+_߮.ᷧ3omSzU52Upɼ6qhYM-Jm^wqeמ`;̔s6@kw|͙\'{юzYsu~U}_Ҵ?#Z);\x{f,_MWC,Z#{3I ի3\#?{0}>1^{dY㓧5u.m3'UD791W;}e`3׫_RKk9_ntdyoԲ|jhA瞳x,͹y-k?97yn`]X%>w >>+[?F fIR;e_APELWSǡ,.NBTs7G{.oS,޺9k9k>ur>_u?9i?5ތo>N۫&58 ٿXZ|Pn㳞=еĊޚ Oڗ?bQR3ƕYhW3^[ 5_k\{g'8,z҉0Q%_c{?wqJ=CZgEӺxl IDATV4ݘCݢ\.s]:ePZdz%O^rU^w/reMe.;Gՙ}԰b`xl'ނz Wo*8acCRhYhνY PS|٪qB\]~=xb.^w/OmjaѭXcɡ1m{F9wd1,,(gl+U/hIFx䫋mcG_$߾bx9ãB$v9WpXoh+"- _:&˹b V}}֧_-WS?SHbbͯ>X)Izm^q8g}}rQ Zw9[5=kѿ*u[5i r;}f#?-? 'YO9 +oIS/N| #~?Bm㞱=~nst\Tuv=xh[hv}:= ̭u_mmy/SkqN5fk,G{կ}u^wߜ?_*ˇBxV6YS>6]Pa ELkHmR:UE]z9<8m3,"j/zͣd2BUתܹϤh-}@NZ8SC5]_>Z sϋBFc#Ë~zu&9A)kD`=\6{nkw/9υxa s^h4Vs`C# ͏uUs6zr ss%߈_o+՟|;;Spl5;3I9L5I]4zZx,,g_uu~}j% c.Y -qVs_B1v,H{-Xw~sԲ<ݺ]\E}r>y srN d-YWw&񩧘b∭ b<z糔 _}-}_j$^6_-Vk>m搗6wk}"uγêmڿξs~D޸:c6W_~k1jrebU[_q.Hk_>7v'y֛Xߡwl_K<㌡ǚ[ֽ8G{Nzʺ3LKk`3^̝~`a_3&G]&pw^?C";6|=Y.l+ I 5od:(uWjgUGu{C^wo#NV'O5bgY*D̍5j EVZ˜ 'w+W1vIXµ0rO#}!} 0y)b/X>Qfvkmn~݇8f>wb Ϛ&Ljkh/N͹?9Ym^}f;ݱkTmد~|?֠zrR+̡?m{Gk_(W9g}r=/62IysQg-1?]f~u޺sYv?J>?{/̏x{뼋h$oH8&bJZLz˿s:_G+U3q-~̼rn`_3|׋&f{^9 cNw{_+.1_4ƦΞ&~;-܍Kg\7_x,_YM=XZ4ؾGcN\yNOKH̚\Zܸmc+kaM{ǐ8;08X\cSvt|o}:~cxy>utc*:ե;_~[c#,bo#wcW6z:S7VWإܷݧ3Em+wlk|G\ξg9y?ƚl,b+}pFwc>k}㈻7 W=RYUG?~WƦ u'-zep.s&kW:7^-m ɿ?:AY܅|:_1r$0kLw_#{xQG{q "߉g zx3x~VԴ!cf/syxnL_{|rroΊjioc8s]ok%r~ugWeWIvBbԘ4;v奞6Qʽz{SGHf[nVWU+Kyu??fաrG9X>zBZ?yY.Г1,">^_}X̰}VqZCcתګͳή]S`J=>5\=_5i,ZsϪm?+vw;0g Qruffnȼ'FL=u&Ώ~V qV3cӏ'fx3[BY1V?_հco}=׍C}}T Fx{GNm[/Ah8dž&,NHƏVS5u6ocGQchV/ʼn|UGݧue/e G=9jl߈%VnǷ8[]W:r׹.u$%[w54>!#\*F|T ™>>g%xczNsPsȄ8ђ_PkS-%O -8sjZ̫pFW~>l.a/۵ ˕5x(jO.|⻹-ϼd/nm1ڣKcgUUZiq3ƽ{k>@˙oR{yŋO]yku\SZOY+>OUy䤕o6Sm#ϥ9l>j6<Dl?ϸ:Z59;9UhUil\5Wk\(%~ӫ>ygw$t /r{N˿[mڤY}jϡ)Wk }i$S?~[@S8ޞz=EN_oLst趧'q|<%$vr/2}Yuǭ󹱦 XgU:7$7Y8'vb캉bOMH>vCc43{kqٍ֯ȋźGe5`^g=_V?Ywb~/^r?-z:>YZ~w,kǟ)b3}m ]G벇n ά;Xω]]m]9:ϭq}YX|RvL\Uט|ɸf>ܥWy tS`w Ł%С_];7،k\O5'N`h.~$vxqc̏uzسne>o+o75@ b+v݇dm^ {:U.V~ߔVnUsr%}k[~cZviwkzڍ05G]mȟMh_71Ũ$pĴ8_=k_e3y~ew2km|^aymbro~}v9쮭quIe̛hlg'<{ڎnl|2d'Skp:U383w^c˗3ѥOLjϳ&uԘ;9.o3?$zgmY k,wWQ q96W=xxL;Q+nS_FOۧC bZ ϦSVk޻ҥwzYq?ǗuNM⮾OOmfy9Wu1O~~_iA_y{68s|k$,=[,PcoۈןUQ_V1|.GL v6 ܨKgy_ύkVƦpnYد_bZUzCs׭v!/rO[9G2;2O9D_>J'~Wq֒>{?U8}1TL.sڢOj n&n,Zبߓ܄\ۿvem H=uGlJ-kTW|rsg=du'V z%z;k:kW{|K>O<->6ְ Z5[\徛՘f!2y:1Zs|qM:hS /ZqC3_<췼ەLc5س#ڛ)&=r҂C{dq*.ּ߮a>vQymjl0$Nƪu u6plDup uV5Pb\]Wl*u.bZz./|~OOlwmg߱2Km!x`->)=MswlQp:F,}!;g-~KϳD_Z_ğsyN}?_MҷUc 6LwNvG=m.4Z/:c3/59 WF ''jbKcW^csfα? :b9x|ƍa<+n`W?;i4TM9BO*Z7>U3XK,u5*G^__1yq MjKg3ݘ­يϜ|r@egl3~R,=]M5fY:B5 죬w/qRyL;do2_}(eM~j竜+Tc~=k<#W|W 8F}rػ}yx݅Cl  Li$k?S,}{4۩8c }"d޾_|`L0SA/=qrx{v[^ZڌW@w1m ܵLXr{[q叼7vϞZ V>I^m'[+wrg ⰼ韌4_s75U`ſ=kΌ\׻SvreOd?kFmYjJ?3uf}a:w ښ^fX7/僿Ӌ~ŗ'ׂ7W׳|6c^+kщsϗ'}S|NO~NKMqTҍUا̅+sx9z~ IDAT㇍Z68kZ/}geR1(N?}rޘb9/!p+YW :`Ïkξ,&C25zOAC$:ZZ`&MzӺ;gIϱ+$߳ppFnX9W3G SW= ýL|8hMwFެGlsJ_]kŶ5rj7RU.fD/ M|$m9dzͷ%(Է_WfG?^l%׽+wgmY{Xѹ]SF^t֚3Ϯ36@y}&1^ ]S:v|$qgݚ8|9ݥI_wh'gNLe݇q8&?D݀myϥk@Ӹ4EdafZS#Z@u4۳pI=AҊ>b%VΙwOѵy*Vj.skFo;VyK3?kéRֽ'嫛rsH^GJ+?q'4H85ݯܛ b $5Zgė]qg>E⹢XtO` _C3q^sgu?qWU7(4v9~6Qe?-+zN4zBXGk{b豗g\9/;okO۹_ 5ɳ|vۉs g&$~K^ sԴwˏ/܌XiotνՇwAeMjk?:h2ƪgN <7 t@[5NdZ'|ͧ>M6{ne>5{fTr8,!=3__Q,wF;bB-/g-ky1$Ŀ~':*y[hmyYW3^[OOcήsk_Ϟ5|m`ܞFr_7fz2tYx-GosygYkbkbbȻ5ޫ*!~cj$t?Ϯ~ÊCK[A4|f*9oC]KP(cK.9m;7{^]hƥK}a5ד.rĭJjS; 6" X֑ӧlߧgu8ŸL^]~]y601rfpksjg@]pSsZcDpgn+a 14b_hOEz}69~&֑OkL[sbť.>_YMMᘽNZu9&T_K^s~z{ZF/$\`;G{䥯"9M'$:2{Nm=J <sim>CYzM3qA"soxn%v"'{~KRoט?k}y7'Xl\+7g2|>!(Eĺ8[3;Rmc*[MQS쥵s*nl#\c1Dkkv{~V>ۍk^^z;B{C͚|fcJ*[u6^O}i|@όw(߸1yŎ>xSu}[=m Sk0[:nyr$~NaH ݘFO x=k$jE}kX;n|'b"g\W6y̥&ҕw.oع̬|nVy_K*qX~K".θ1KXZ֙ 1gM-]{ #gp3}'<1okLxKNt-wjI,Y8n|wܞUu9q0X;!GLn>Ħ߽qċ֊_}+/cdJ'>?pgr/Fi/շ5'l{m ks `~'K3bY{n _Y/Ԥ_׊ןwV<{x'ư_z5 .Wj7_8ŪWr XZs_9^VuSûj8 5g6Ԩi'Nh/o u >C*dm? pGڔ"bw$aT/ޞ0+c aFZ1 -)so3@ S#U1>5Xsޙ_7+ի,PZۉos^#MVկ5lg6Q< /oFbrʫv!K//*X>,@ Nrԗo\;>9ul]|ЂtqS:-Ҋ7/y`rFwj26wjyB-ߢd?{N-~ Ĩ}wdNhŚZ0{nCWگ7Gx7k_AMf,rcNү/4QYAZ~QldӧϠ*&O3 |3694__xjVA\z}oi,.<%s_)PrLn4xG+4ߚ_5#}ܬg}ljk'̑{>[bցRO KmSkd3/ >[5{g ,=6Z#[:~|S,OV_imڭ/:,\FkFXrsN}}^ V.v{s9|Wk,cqZ/jY/=MU V߸[//>8oݟ/zG /1֡O^ikѯY[;ppp#222ywNo{sh}JO[g"s`g5Te^59Gg7޸S}m4'5^`c:hSQB݊5|m#v^kVwq9VlOε~˦r}0_w_~~CgzsF{$kWݏ[)8g5}zSH{=6d 5qnua) Ss5)bj{_ڎnaoز_OצQY>gεOe/X[kfA C.cĕ?ט{|M4W`ISHu7x zm 5:1F19{ruιew|+lȹ~}v7l!VkwXXsa.d+nR}8vd1{.EU[վb՚&ͥFbadJƥ1.9KAcמ|'{stx㎭xc_rm[YSNS0 DyB4+_vmGlS˞&s UGsuH9{l l_سb!89.lnr{sFČY \5=o]ɿuf?Z;5bzv(_9Gsv:Pļ#}[}WXV+smՓ/0 3bxv83*?|OXZ%vD/ d{{pGU qrm|6V=.s c]CLs<._$&JM۞kD0o|1z|)D®x1Mp΃8kr.t*h7o f:*6bx;Ù yc<zbՖ\̹o=ɓ9a:b=s? :`Cl*~츷[E*'\5=Үo3z0FeXF\| nMl n%C.hAb/6[G]k紅\l>LG3 xJYe1SӁqǒ;c[a.\Ւ5t][T7CŸW]g,Ѹ{U9o,={1ر6qՓz/^T9utr3ۇڽy&w=r"=s f~|6| 93p{shc6{yX{%jqC9+̩Rӆ;^{AX*7}.[.@88<*f!VsԽdng>aȓd%N;9D x|{}}nDL `o~S/z.O{Ocϴ?O6Ĥ2 >}gvR8b=c\c6\سv5ͱȧ#dRQ>]@ex 1r1f<3=3{2 XcO |,ts;sQTѽg539r 0{* xm^f𕖲Q[8>V^8oج>q;iMф<¼uV3yb&ۊsp6ʹуDm\760Y Xׯogo܆p$Gȯ11]|ھ͑܃jG__z#8Cێ+O]?RMōl7pb776kfU ) YE~:ĭ{psÇZ}rSH Q[7}`ɵ篘>Bct6c'8m^"2xn>yy.T\s?vk_ȴwBəY o{ɹX՗'s:m֝hX~ Ie'~l=jr:W'6eﻱ a%9gVwnQW9k\e{9k__H@!w*^ۙspO+fޘ!c!u6"U0cVƗW;?k:o?~q2y4ל"antgUꕸa ;9 WrG cmИߌ8uDbmsL2:ZS-oRa^7IlED>3\i{9|z+fMwnc$i)Zlf9=7 ]{ma12*h׿m'F5{g#omgbܿ؏nckͱ׀}'wM,kL߼z^3ù#f"ƈw9|760ѡn^u GĿ}x0kj15NosIٯj#Iw-ã6Hk^mk8rݯCok` y8bO-+/xf}݃'~07kbg[XS_޸oy3ڙXl{6Lھw FxW]~ԴrwȖxof5l_^wB%:&GQCsfķ=~kרձ*7V kYauA{o|'hoj1&']C@Uzv jw}8ΓYS5b+3q>bPvָ_Q>Fc/'kG$缱0Ϙzx~yŻwU+vZlkѧ'zﱽC]v8Ը >z[if]@;9/ Co\-Μ@Cб.us/WKn @%K~b ?9J܄'p_ZSy c9~z;\arX}m7rG`c}YoH~7y'_%>ELQ"7_ɱ{nPe"ܷkh0DZB<7O#α]>m9ڽyr?AN=> .K]-'\ǿݜE ,-_LL7Z_\Il粆a]W ;V\mcox[K|#%Qc`zaK#~r'.Om 8!'3-=Cs N[ͬC X"o~xSR:Oȃ?1tG>76֙ r_d4n|3  M̎.|߆͕.;/͘dY^ش*;g;0^_wUyTw@gcr$fq۵&0!;Y`7wNmj?U//%NKq'$Ӣ*) ^$GSb3교QB~`.octX7]~xֿWi^sEc%(d_AxCs'/iiCpNesKN6ķ~pe97}IeA77zRSԹ1"Sӑc9jOOkܶs}ĻNͧxNk$?6xi&Գxy;xsd皣ґ+A F"CƉ;p(;!pͯRn8ZN\=_w S_З1 ?r"ϩC6^9!3yM9&a@$&..T0yb339.QXV{ggk3Gք?Y4%Д66ru7ur9*J_.\J֭9y_Ky '~㳖#6n ~qOxPtcxpqnlqͻ99-̃o:_0 v51Wz-Qpqmp46Ǯ܀".9ѧyǟ׼̊Dl}<߰JANZ]i[DeFg͐ka?Y@)|- |.jk 1ny0^g.0_[3gΈ~g|i_?r1_SW0P[ ;Q9:|UkaC`kgH%%3at+|20bٳP* la3mS/`/ٱk]u~jB+AӇo/]7m?=P׻>3<·Pmx8\s=o~c+׆kN60ßUWbɵkyshϸIq5uDvO‚ r2lRyTTokKu"Ogǥ;|N2*ݜG bJ]ã;gmC#vlz@\J;]JɷzZ9(xkMcV׹{x¶uﶋO;߹õY;/[/'a7ՓbTwΌI9I&OLCvp+Q} J_ز'\V&<0Xjpߚ:iȃur Lo^Ӈ8͕qD=SpS͘pSrcuIĜq1OJOqƿ~7g C kM]uo@'BҜL}OF1/<2O9ZgK䭜j/61;{_v^k?>[&+.9÷o$phWY9o̵5#:=oYܮc9_}95sx9{wՄ6g9y895oɵris@l9jC=o>POqH0{(awkU{_8-!vr~r2W|SJiA̿Rvq;2c/;WWVX.'IŠuo:t 5Do5dOrY}Lٟ֓.yŕ8r5ZGZ_~ŤuRk?F΃mA>zj[ .ocvç 9$l{S:^Os$*t޷q_||.3<Ƨl_vMvMo^@K9 z+yN'Ͽ%P$[SV6Ƹ&k1䜅X`^=; s(}~'cpOm&8uy8?;Y{SdJqn{i _.z^їs={?2"ӟֹCڅaGl$8g|f߹2~]?ј#xgc)'_ˮno;6O3_tXMjy ^ZpLĘۜ}? q龚Ü/pm)|O_!0V9֜0K7]xy r9'wAn=^7^ˎg=w yl?8r3n_ԓ,r_v9(6?-릻ɪ uOcS.Rn^/.ie@rk 8?ux뤿2lI T%xzfڜY7%EشǢjz9hX|B՟r }?$r<\O^Uʬڒ Yկ\ָ ?HT<"mv;TF,S^9 tFg8váq$FO6qY ;\Tb+qWg,GeAjNCrmNho[WqyuַhR#}r񬷝uiʩ~w$|c>|&K_(=#%#JW{=K (]r+K5|o޸_ǪR,c["jr5RED?uŹ< ciɑ-471'1Ԛa~Hl̙ujxڿ{]Κ&zM_؞cܞ?G 9ЀY{7%8 k8Շ@X_܋bQ{P5*}~u"~n<0N,ΑVW}h5=Er=\VLVɃC^ `JGWAd:|!G;?.vS}[y3>nˋM- |.Sx3kքoý6s;mv}^%>x63Yh^l=Wd!&q2$"n;F2`#ESh;[{`cY',sְh..}gܐgl{g~xat/cbwc\oڜU>g7/~ψU wXڜ߾ʛwE7=iG2S0&QC{-sVeb[370v;,sUR\qP3 =gb+ 6rQ.7=Oh@@ Mep QSp#͍e=gz4Mgob!ޤƉy͠go}h#4:ܛ={c}Ό;8? =c#N ZWg0rŤZ'\ص-RaU1"kd}gd8?y78ƃ5V>3^:"=Fǹqui!7C{i Q 5֌ß7L=߬|Xu#6..N,9>wb‡?ob>"΢9g4ZGuF=}1.^_ _K'|%e9yz:Oo5rq/לt6Dy2>p[`MUX `99VSK;sz?F{&1E ' b]bwyn|F?O}:w>9=Q~bR?Z?v1o8l.acPs}c?'7ۚק_.yseϲ{:͠U` /?Olojڈc/[k_jأ%nl~|_<]sTo2A$ugl\#D`fp_SSщXΠ?i9~oaN-Df^~_Q550yĖF"~N'Qv}f>ߙбmmE*u]5G(ֿ=y|AN~V>kΨ9g S SCZ 61:QmyԱ}[ಟ" vb,f_]ˍ/+/|Ψ`^~z߲qu|u>ŏf5ÌfԼ,xj%fۿJp^J|/˟%cߜ# 7rٌ7=xv充.毽2sրy\{qsN$ Rv3o6sPKm}˿KE 6\]w/X28[~;Cf ?Csoll墘2jS{qPG;-A'T `?ӺU)݇G^8Y) OfœlƲ3h8d?y qk_~4k%{o75k&'G'}j؉;1-جS AV %gة=W!DJD91 yEwʇƪ$usVaƓ',NM) ?K=g=|{ .Ijol[ꭢns߳_s5atSgF|#(Ξs=IXؚ Q3m$zɅXfqk{z?{8yY[ 8l;:+'wst`fC!\ gOo^3U'-'z9s5+_"=TZRQo>7hzoU~MQδw=Դqr.ersy7YƩ=}y}TJg䝖%р?MO)\q~^)%3U|ciK"<Ws|< ݼ{s!xKSCZ| Oe+Wej4һy/}A/|8{υ::x/H}al^wmjg7.4DǪttGɞ#wO/QruUO&:wӰ0ʁھ+{е[7^$oNFw3h `w4(rp}1'Q,&~b/`zU&|h<1Ծ,lh<8 U'?:׬{zU`8AoEa=P oN!_yqSUO>wy̑®Zi1guE#+^;k)/u1&N_S>.f/[ir7+elLfcwԛ='˕G}oq&JhcdZLg_m}cK9bYX+䑏pupS{A}ĩ $VI%V _9 }̔1hMvkѯ 6\a5u8lu,Sk W1< ΏsԪg shΟ7F}ym'rDD2=ƛcbx+?o:DiL|Wy "'_wQ5ug>{_ӟTՔMe* o9'-jDH9CM|VG:'B~%|[+slzMj[vʃʅb߱NGOf憭 l⭉5_LO7=*4b^.9fMZX0\96&NW Ijgfd_.u|jmŮȟXL tușJg"%V y_/]g0_Xu1βozʹw,^b[&f:q7 93W? ν;v?=̫ߜۧ] V*u #m}0fpe@T7OƁa "6ƽXc^,:?*[^<7k.0FS|{~3϶vÜ·\6,n,O 0њ[hjc+;Pssaclɋ"Zckzvπ'tcu/󅍍f KMٟO{c}\XW7DKo]ʿnYokupVwXW7]e(bg9Ӫq&v--we,M:ᝳV_q7!G1[ݝCTGi^wN:UeƎ5HXpnk}?Tָh9ӷ; cy=?)Sz.~|y:jsVsAj ZN?'b.ry\ ?rcy=͑[gnы;do䗓&mq̎kF<#pzǕ[}S)K= g}>÷J:}缹:uqv"\d55ɜVy٪A:}smky -Z:/wa0OZ?48M|gFK=1'a&ad#cگOqy3ϣrum=1 b)O[vp }98WYoq.9O K }Ő̻.<{;eG6 a{^;+[o7ҳuMtU+&Vw X_SO1"^̶o} &ƺbñs޹K2=5ܽxxG5o=e8eo>؟[9*2t,1\GPMI{,?/ZCgfqRSp3v^i쾉![;p˶[n^c]oNjgN\п9sLb^#Yܶk#xl|N|cSg {Nc_6e8]s8f8;9Ԧ U݋[܇Uc~3ٶVڝ}j;1ؽ[˳]?g}w1Ĉuc\3mXvc;N=[:+`soq6oQU46)+#I:~Xuy~֛ZbCAn[u5<3_ג'શmbڻ-U'aM[`guxBw9h6M0K\+}@2z$h!iSkπk3K>es/2A`4N;]0_I.g;n'&Qn3_`90?3(/n|fS̘O2ߴ[ZR'EiO-NHm955wOy[< 9;ssM<>pw-.9Y>5V~0>bޱg8\2+|\}PoD~K'1yJ7H078pb  ̢b@ w߇eL; ~g!$\7~2>,i+Խ枈aw+|~o_E,xj}~g{ɚn"o xuӫO} ڵ}oPkqo}Ycۭk/M8ξLС#zG9ȟ1?3cuss'a&n^[CB㒹bWl]U')k3^mgz>_ MLʝ>|{[78ǜFGK1ãه;/v4#+P~s t>lT}3$|0uVf;:m $[l¶_ 6w;7sFͬg`7%fbKΫ"8v5Kk ")>f5073ʖYҷ+d]7/˽Ɯ=3&cpezQS{檞}!cw].zc{*H߿sgswwh[Xw]bƂc]2g^q3~lk ^l>)ۜ]y?9occ΁7=!6ckÌmsm}Nbq*OA:$ac>o}`͸ėoOhqb~Sթ9hE֜g^3oB乖xeO7݋#.u0a&޽6'7Ol1)?j%œ*{a̭g,>$C8fl+G׭/+m^c>x}gp7 ٘1)!N;ƵqV7,µ c%+~Ȅ;{"Q(w7&p3uk{:1o-a]sLjҧÖ!fxy/kĸoN}vq_?2ֿI;b4M ѳu:o\֡mp1̍ODNw T7%;FmsmYF?驶eնGGsW^c]C#zOѯ#>ͱh6i7^83?eGyR5;?e%>ekA*84G;OlI-N# k.þvok?lӱ\+6_yjo∳ݿ<9ןricBΣA-"\we)\'\>}0c8r2kS gތ{X98l6sqF،j`8ybQR}m[q7=9G|r+m+xG4>iv|bNڪr)C{}ɑγsdCU93Wվܹ4/ݯܭ8bmYO؋67{:ka@{ 8H5oNVr,x,}rz駿0l߸vs_/!&s=|\]G =c?p˰|o++mzlj3+&z9>`OqTriڙՋԲ6W*Bų6ּ?q9^=r_<1cv9cڔf\]\/wqp7k\%B3`.F1/ܯEkK쯤`Yr*u~1(Wm2ؤ@H<*׵mA 7{b~smY>5#䖢>8M?,im8cۚz;Z =|uog,gqej3ިcC6:5>qOmK`ؾ1Y̻lp<'?*Mju]1Ɓ_?XĚK{/y܃:_Ν5dk-^~\n]ǏT43+酬< ųt#?u“ .约&1iZ~pP5;_v_yt+nW! rM!C\ƆSݵ`g|c{JxD9Y0\ض1q- #hOГf2רZC~,H.˱(3eHyɐpƒk^oU{Sy< <5jNk6uqpnkr3TҞٸ#38i yANض{>Jkmp5{M?\X˩OsꨶU]SNcPuSa"o/kk^R oo]3}LFyr=Coˏ5ӈcrn7qbmĹ7'{|_qe~cRևֿ7nwqۑkC[y&⢣[kak[:+Xgg!ɱɎsQ3 }1ϩs28 Y[3 @n,q0Xrx`-[`T &$@Ф2O~CD[Fl{u2FP@gMeHY[c̯mI^:{^#6r=k93XbO|l?9[qCw}o<\=0rksssg>E6TZ:_S$upaL_rLΦ:A.bfl^[$b/V^0Oc6 m)7knufuV婘'oM7{=:1 ."o<k9|ځ]F<0H1(Sk֎*}j#hˌ&q5%谞t֫Cw/'aGwD9o3O$ߛ'OjNi`O=Զ19w_R}b{zqaXs"n.똜\H[W_݄%.9s ?V;{:GץxևA1?Pܜ!l;{2; _غf /6Z^6Cl5Z38sI/%/ÙXcs¬IbǐeBo\kÍ̮4 )Ԟޝ' ${:H>m\3ź< ޜīO{zBŎe }`Cۺ7#'~o>XgƱg{wSJۋk6s-;51.TW:*^Ÿ{fe}֓4G*x{>#4ͻ9:xg0_g$U = %Ҽl1F K_#XfmbkqulܶUy>Engq8*J F '_oM}%39>w [[ IDAT4j,3wR<<~&m-ݻN2ʡwyT5w5#ջU,kqf޶MG/Ϻz!I_4"}<^%qq7Tl]6u.hN{g׊=M3 N,4n~yͱm.Y"^50snkܜ%6Xv˞cXWwgto;nN>?+M&zƃKl$4%M|]P>fP/is0 3qEs_mh )^8c[M,ROTqIJr#]9?1_>l_WA9rǸj&]h֖wg^5kWN Ț17o8mƃhZk4]5{0G6!?ýҙonCN/Gٓ>.pur`sNɇfrsxvle=_&y qr24r>E eZ_/g]T(L.1W[۱m$9Vs 盏DKSkj>2o+uon~Pgm/Ƹk&gecwb:\6.sovyc xD{7ӷs&iōV|  ZGm[uJJWou HKl}Y+k~ζ lWoR+6ywb:px#yW|+ߜtaC{8x_˵xڝa7嶉LJ6p> ̓8; 9-$9vpłc8شkq@99˛w7v;ׇ,, ߫ý3wT[v&j',W֧yk=3jy=rd@_Wׇ{Jom< 8ṸvcZA1CG^5N̎Hߴc8[9w~yCS&p g5Q>86Dq63maƷ''k3_#`wv&{s s'䌟CmEOvCC^gYË5wcsr9yZ۬7n^oPT&4[v-K3I8Ǯ>}|R8TJ>s6zmZ䱇_~xg0~c _\s27˓@9<+f|+8؃wxXby;/q%2f4e C.`0wV'ջ[ol9HAy5ufB L_$)xbs/m]-b#ZvS_'nz}!  w 꼹,==Ք)rϜ<: ?!;֜x;}j߮^\眠{Mzԁ6?x6;x?mpUARyem,~̕ށruڄ+_dˈ7zϾ-,֐qٹ _6TCHY7u|LŒWt>7x?/]?CT[F`ġO [_1Qy8'_d{{v`#1$|g__a)ra\/??rh>p Sr6 y[Qs!* co|'f$%[c5 9?rs#k$Q4B'.a-W~8gx] ~}ڿ5b//?|xO?/u6GDKp_a).-|7ft r&؏Ɯ!~9bw >%>ch] 4~b:kyU\=) S>&y^D :eAiΈuV8]0Ar8ٲf-냣xޯhMlߙ/L_'LlϫC~su5e ף. $LgSc"^w]+]/a]Us;/6v״73uQ6XV}{?:kvu k| DjiN2ok7>H1,?3csvգށ+oZ^(h>b{ki.y{oͩ.{޳8CM/[7QoIoQ\2A46.gonV.t ݡHtҷhIݨ>nAcQr[Cl@@4JTA֧>cԜ{swQꭷ1{ͽkMܶv0q]cn?eqÃ1f5DI>{MsaVk+$ҒX6G{p<*Ͻ=wɢ9^8c9̅,cEٽ'q*-{6۵7xy}bnlyܘ@Z<>gNi瘊{Nxn:*~ #1,\p\O'߱r{fMu80ܨ7!ض_{<~uݗey36g9慔>z2"KUg}Z\{cћx\0dTTcyW{}{3yӟ~>v,bse{hG1*/yRsujmڸjw z'/2〉/{k99>.ʿc1:67׽|?Ǘ~}×wKJa >Xnīպhtls@2|s,_PluLVWA>;Gx{9Zs\O7ks8s/;cط >Xr7ֵxf]1N%~Ɣ,Z>ŵOygaw0o^m$BS>GS1tS1pPO)(omȒơquAt 5S+6ygH f^ʩ7x1ڊgu_U+̟W }(9Y!'Q[>)NW?hf&TR,}=O=0 ֜..ܮxs^WM+I2g}WR ;1<9ך(qb'6[_fu~XT'''Ǹ˺_TKn>0Ob$h0>֝ep!JX·1us?uqg}`1VAc\9ũgZΫOusZA\}2y]ә=~ۂ2Ή~}eW*ʉ pŝԹ4mT9EGZk{M{ kg:k֮iL]kÓ|s.?~+s6O#P- 9_֟DEeL! '^<_d덅@a 2}V}OY-S}\}=~\>O]WU=Ie1سc^cM uF]C|TyXw''=+6\y3.;QfVɝܰ*GPb4a^hĚE_m09p,|^B5a,`8 .{O~0']8CUy1tő? dzbYW ~0{0nS華8>ArT.Cyq{.{˟ɟP0,H! uو:F\.cHuIִPzdpWQ6x|f7ݔS=NsZC6ۖG2gAcԑ]W}h/Ŝ6cr fv1dϴ1}6e@\1ц\HG43qDS7a)KKTǣc ߙ u:*)w ^y倞Q]euogyqAo'=W>s)O=؍_>ԃss"_3|eX9+]p=k(Xu4|v/Ÿ۵Iur*+`>iʘhwN7;D\OY~ 6IB]kG1enen>O.}מbs\:i0c,p}->G=gBy[,<϶ZܜVM<}<M^慽IAGsq ?L/M\u{->\|yO0b/kggaJϜ`KcbXU9_!yr=3V`]%/xH~,"Ld|߶O֫g"yGŬmO9 <—Qڦ~Θ[.#+e||ZU:x^Wyd? b }qg7˺qQ+Q'9O~h$ΨI;>`cm, cı#l4\u^>_ۘչ`SӜʋnkuU>)qszP(1W: ?{/|+/?#*_=ۆm~关䇻<=ՂuSNᤝš<Q_Zo̙bͬNNJP/ :Ɉ[p3n6g|7a{bEy夳;>sL?Z>1Z`#e%H\c0+nhc+8ktVOε9My7cp׏ycqvx{l|5.)~1s Pg ئ$/\Pyo!1bnu,LwA"D$^ .mǩ]3׭ _1Xcz2V!3VX/Q1v?HQA_Uu pfRV8u~bg5:оiEqjJq0ˍ 9@=*9kmr.N.bs=Q'P^3rwNϬow 3ͭn1܈+6@H>C+v8*5 {%8P3r\`8Jw%ҽj7~xQ8]o#̨PW@r3wp.CCC/w+*^h+#yO$mew,k'^,1Γ,=f\+ WwДx<9y}? {X7e/z3h]k+Lدvr/1VqcL 0`T+(Uɉuֿ5ǹr>U3G&[|6C9w힗6\[8pzD=Wլ:,:ܻc[mϳ̡ym9Giîlt9#Gqʰ_ 0>lɩ8 IDATCzNny})2VXV̽rU,|#raݓ]rO71)\Y\;ja*♲eb]\!U~/q̓>U g]稛n1ĘWS3?ޱgNSk[xˮgNŚym጑w0e{gLe6{TFU=P_uo[XPwuq6dm{ŚVY>m鏜񂋱BN΋9߹W\pD>_N̥+u׬$1a4oeuKD(|3v;Gyچ@;9;>9x1gǷp{[Wk}@0A׈wZZ8Fbɻr(gPڀr~pOqb{+}őcOyCQ\nبևxuQb|Ӷ8puddt'if.\kkrl#GsAl{%G@@+?__VH7a-u{^m} ~inmc6KyG㪝#79)޻_=k#yڐzJflӬM~KcPC?l:9C79oi4cC΄RZq;+~Fg6欟3iC^/&};qDI,y:O9yo(dQ^cLJosN?}319*F!v=7wZw$]ygD~&v}S$6MRmo;nəӵ/2vme'QT cMy/Ø R]>؁#+5I`fiXwGnճd͉}W\3>90FY>RAޮrO{ke 3mX\;;eb,89lZYW#jc}4}w(ֲCJ)'_,ΧjonO= Bfv8l-]f̬:ouh$'xy*Ĕ c$>c௜j}oLH3i]3+zUi{gg-G-5aqG]us yb9N5?tsn"}kލЇp'bXc<苧csfNVO#v'(׃~']Q|lRUnPs)mM lsڨz՗G?qw\g~u>\s"o̕;/QP[oN,'la$E|2ՙhoc/MOWzyr:T# ?ׄ[Wg("qi!]ggxNS {,ڶu(W7ǸYW,/D-|Ƒ<-ܦ]o*?犻 ;\1c?Θ>6Á 4}J.< μ7Is8<,fW)u^x(*䓀s!2NE v0<#5}svQ?SXbnQn z̡ )$hG_]0s]ytۀ^.Tmg3'Kui.(*~inw.iMxk@Ƿ$q}ap>/ʼn.{Uc융dAwGca[ax82:X@)61yDRǽ> c4IXx!cL|7Jc9O ഡ:{1\"{0]\k[ߌ>pM=ۭ;ݸi'%o\l2Wg\ T|Sݱ]󘗳`Mk>MyC_sln>9Oas4o1+۝sHh=h;Ư Vjz(,kqUs$i| 8yse9fsk+؝99k og:eS:Gfs׹z$gk7}7sE:x$b הc.m;`5a7}S7uwmD&%s6_lM/6k`/=Fc&C](3F57Ġ2r;c ,GM^ϩ'Zݠ8 7a 9ݬ_]mu`W-g>(m'>ꍕD^q{Xš˸)n\U۾m릤]9)} 8/.Wzm,Jkł3kW568gur}JC&#Ck7+}Z K`Տ1"go-7.:yvOCt<<98fU|`>ik`r6k;0(Xrl'ŔIeH{q:U:֦yN1.'Ҧ|v~;|NF•;> V>/cJyY5501ξ;7tbKچi$12_ \tԏHo}ݡGeL8W(||y2KdВjEܜqp:?OR,z V#4!Pǽ Uc ˑg/6-gWny_5$m۵b`?5uAa߄[8b0[sVY&*sfF]<\sߜKnŇ97>SEZ݋Ƕ4j>߽]G=<pk0擘3gvL3Ϗͅ vq_[M_97~j2~nu<ʡ=I[o[8J\zsk9r83I DWu'g=}@:͘MLtPL5':gte'k{5뙲$mw! X]L^`7ƙǼ1~w/9X7928rOOviv*Ě[_HmvG7BLz!&\ƍ,iw0;Nwkk_ɉ!9]xc\n]Yo\әC_dEy᪸;Wݞ˴r㘾y D ty Pc&8&҆Cq?L+)d^GL>kbh>p5UfJ{X(\kb(aULQ3)g|٩GǗ?t JjO^adҁE 92#oθA1VUk*4ϻ[S)C2ynǞk: GӚ{ǸK+O!cښXı2zA4s{Xk~{dr Gv Я~cb;7d8q֓Uﮚu! g_v1j@o=L҆`tu1BI_f\Ӯ;~uy3QGZ<2/Ɉ'9&4y_܆ ^*Ӎq71wPL5٩˹kto}V=-`JUOF S;M>v 1wGu̜>7#^1}kwm7w듖zk1fTNX+75۷Q!zO9GSIqG.yQ{U\Ky#gڛjn>'nQ,&oxߊ=_5o{ |( ǽm){; A>fob͏^- ~ꑵ5qٶuUq3ީ̍7D19na%i*_>VJ6( bB ޔMLBӆ̸G̉5LFCL ~rf m̷F[&9W!v@^ٞMrW_gbz=tUkP3G͞ܬsg\c<]r̙[c0[nt!~)$. 4S+U \1'f'ּ@x8d2]Og\|ŗN|&en0:RȺҫ6=qo/Pݏ$o| j9뱗@F&$ WKz4s^o.g9#}u2 2}*FWiG4*H6\qo#/[;z=șC4\@nvr8 7$ޘT;۴\ QfNuL{%>ձ"'{ύa K8d ԳfM|-Qz'ccf8F[T5XvhOzt1ef)_INb+N5GGX^](hNiO\hsarOp',_̌+t8蹸s?1S MbӅ3ei?1|ƘI& kWd{CBi`'is?9H0ߣG\H? Oe|Iv$ Rʥduk1]p#py8xEz}k0OYf88عW6]|9GGo[ތɿlll}esʜ 83y]^<o? ^UE 1sxDWs Wf sx+\˹o<~}۴bK}S?]&r:g6!p5܍6 էf}`QG~N_;'ߌ~/}"'Xi0Y=}ŧ>BmLg>pZK(=G OA11jNZ+y?k}h7O9?-ğ6eiWz 9܁rrsg]XeXl])c?'9mLw{>'u}^_ê&b"s}{%gf:`Z7sNְ(@ۑ|b3@mϺLM3** g?`݂p}>G/qy^y|Mp_׋#:Dv-B+%n~\=<19ݵs {";d'fU#rd?/|?_~7K>;QIπ;_ _btatp,U߯> iWP:}.Ka 1vT;g*VqK}r~iZ YẈ.VX)ZG}= D o5??>.,ޝy )9zX=W~zuG?<+b>яN܃q|) y<"u?뎼9c$gƴ#/]<&O_<Չ; 䞜BS֔vb} }O9#39s̃KJ<{Mqծ$v0ҋk|6gsəp2n p 55M]QX`f~PW9ԝ͸5񝵺tj}b:oFy>ZQ̾l\kxO~}mSyw=}\~GY߱mk>T/>X=ɋrʬ_V5ƽq]X|r#_[8&C9EMuqzDuccy+1-.ϾuOb/Yژ?I-Ȅ-CY?„Q&-g&kT>~wfnb`TcM,qܺ^q5wgCZeLukuLCSN~73>\gLDCw3n(c/TS\9?cc핇=rmPO_Z 3 \ӷ{Yw^yʚc~vm% N}N>){岅Ƞ*OGKG|gZ@wǬM]bӅr >Q|lX}D& Vˬ]~?{6Z˽/?~Woty{s0 IDAT>wySr\xyz'\ r_}_rR1N}\+ |r۹BX>>gꋋKेًPЃk&5E߿Of~wf.l$}YYگ qg\Lc?Ir-sUs*9GёCf; 1zBuܳ{<>O^_>pb\B<1*vqP$oO|/ Ͽ/<~S՜ȗUƞE80E ;&u6܁q\ .o/O&g<b00ByauϵJ|b:&pD\@]1-EiWKW*Cc8_%͍T 1rqG_?>i$"e. pxDO%Ї?/ūO}$”bg17m!TQ B&_Un\+O|ʑ7Y{b1Ī\'y3OҍW;/Zj^]P:2炩Ur=3c'=)ы\^]g_y#S;ty!wgW@7aǯ$uWկW rpa=;tI>җ~c\{Yzf|;:kWMڈl?>ؔ"vWլώ oz/7o_>ϖ\ qE/|a\|J[%9;??kpӗ~(fBbOhzYʏ\zɩ!3 o|]˽O|RpqQ= !ײΥ8*/8!?g)'emBO`VVa<1=c7i>X;xhD}A|[ŪgӧSy]c-[s8ڜ>57Zj9/>U1D2|İ_ʌ c+q̌Yҧ8-Xc0Wby/TkTiOУ,\mMIbl0>iq;TܭXT=1i4Yym3c4$14P:\c&WP,O^>˲1[\ؚ"syl38-εY[T ăꦔͨq`-K; מ+X&9[Kaxd&4]\uo,_7ҝ@~1r0[XʥnY 3V8b%v\>7n5j$Gįp<йvNyL8׆֎ k12C7{`~3+O}ꬭs;&\ϵxw:xStdr.oS |^:sO\O?|+Eƍ̥{Z1`|jq!Q\0/|>/ >ץ6́8V :j= c&iiʕM;^|ܶf_xDC2=VڀUxoe5۠__9_{_O__,B&HEK4z…o}Uqyx5Ʈxs]ד|jm bs_ʽK-^tw^^\/{.T{i.h3!8yگ]>ɿ5ۗf]yq A, 95z_ʋ;|b`֝.[1Jg)0|^%tys/<2j1]|&g&Y r]>b;8^93^ߺ b^lPf|8& d-9Od޹{A^6,>c9&ϲQ'6z8>IJ8j/ {32k"w*1君Ey9#}wp_by [)ryg?rX̥}bŤWPOAںTnnw+v=z3V'ґ>,Uuq'IEf5O<wֳf#zV9ȥ&љ}"CE0 ~b%|-'>KkXu5Ü&XB6|Q+TgN {fƛzӔoھyra&ΙXKn\eږ^ՅytԋU`e(nY~A.~jGiSی<_vywS.KMhowĂz0cꎩ=[|ݧ~B~s92;yBHq%.1?EY1/􌪷s`ܫw#{qrV~7tJG=7dǞ3k,gmPg\]x}'s^% &;e1Rna}U13y5y=fl;ϭ:f u[^uE!;y .k{|VabHt_^ ?j-gܖog(к4HT >ֱ|NN[]#e{/HYgyO^~:a_;u+VZ'}Ի6nj=1<S7e0O3p 윾mő6U rʫڐ?@gkaH#״̈́>r0sYJWeTzFb9GGܹ^&x<%l4wG;6n8 촙?37ssd'm\|7'G@yK#"S^~3Oxs"(VNT?Ȳgޕ2:7 12NV~hY\09/>)Oq9sN>a"5w[o/j(311:DQ@[64]ǃQe6WwKĬ%^ 8.)/p8>-|})|Ṇ1g +ɱƓX&%|GGz&֡Eo7\b"e|tA}Lr̵]=kq%Q#_,܇v͟b/{+bzZ|([X8}vI`jΪ4u|:/"9W"BV~[ǫ@y%^LY^ rO˰8Ώ|#* L,Ze=*οWpvy򓟒Z69mG+j W~+^>{s`1W=xo,>OU x{\^=3̹r0z6 -W7 e@+uMkH5B,v1r:_qDdiDcN܈mگqb)Oȧraics/X`66spf<穃9Oy\IθQ.7[y5<$Ioqiqqg93y8)Vys8sI&9MW}q1#!~?܇WpdW ?R6ip^Q>D;i&? @?Cxh1a͒˙8S6.:ia;^8fTrO09c7n}&&6\j<٥To]'snnؙKNgynO̷őobջ73uܬ'>w⌭Xk(C<>=æl;jÙ_ytY3X#ڛ;}PelՖm\uD_yu,'GQsS WO >}|Ou\~nSƣqfnO]͵Kqxٻ>_={z$\9j/gOIV^x|2knpc'u!<9;|A*A^+(2&OKyX. \/q֓b'|}oz<u>'} (9oo:~_AdWR' )/\>x^?<߿|}_-+f9^~;maTW.[?1MG{#㮬hq)$:ِ/~|Kc e1᜿n@[2{X$P:-| B ^:ł9hՔt{%]0}uznFVѐٞ<6sҜwŗ|%H+^\Kg{Wqsыyx>&D<8"|qy>੉5tֽݢ]8Fn o\G*Eg^:V=^\n.y$`ZMMӊ6tʻ)'|sW\|~yK_q{Y?j<}k_pK^z<%E>v-߰#`W/zB 2o{ߝ]!MZc#?~7c?\ &lmjt͵G׿#xpW:K[:{W#(O>ThKa7=>NP:q-~>=meI"|aMcigD ~NJkzt+$;n#%teLt31]3dX2{;cXO)̍0Nq7_pqzm h+}0b7$VK7.hN8س} %nQy\>ߛnC4/pp򭽚y_1瞇z>@_g8׏gV=فAZ]31}qlФ9k;Ff_}J}+r#x0VTiA~1ӽ7aI;_|Ŀ/ֶU?ٺ@x|7:#zܸWu0M }8VqWk/:1 pycB>0?P\jp뛫/5}:=XWO\ssoW}a|C6ǎ1=jZ}~+nƟyFG~&k%[Gbl}'oĮodտ<%ԃn/siMx˧?Zc>GuW8!ˈ^pḈ=/>!^xsAv 58c>-\;KGmyŸ9291^+?L2_c_yV^o wpjy\UIS7Y㧯vӞ Ԇ[nZ8(Y1ܯ6|Yfle+s[G}\U|ܲ͵ ^1,hݽipόGYu3ƴۖGl%#}6ǎ_n;]X6gtɓLÇM9{ uZ'rfXE˚䕏4.|'' $.u)'<"]_ ?*bk'+HoW }7I$zƓ|3F>E\1GrMy } pWxcN^DŽX'vϭW;9f4AKD cDO|⽗7 BW:xt ͹i`2C\7紩r;yQ̭uS~\ū6pEoW;ѪWbe )`+;ǔ=+gtH >,aܾ%9"#WD>9-4s.r8|5m|F`sk{%'ugbe myNЇmX7/KC:^,^)ܯǍǓ̡jAَXǶۚt PǠﺫd{C#0νGBŇc^`X7ιmOhX~|=Iݠg=\^Wիxuwzc ?>:NulhC/e ķpwo&xFb7-ʿwIH0u;%Mdn`Ӧ69g\6kό vM9y"}t_){6s_@y!S?PRD^-co(gr;Sؒ;$;@LAV~%6c5;`&1Z}ur[qf֦Rqml&7Or\!'1=_4<7y'6 !՗<2SvX#Ƶ\nbϑߴ#G9 aH]ͼ'y9> šό.gb|xwm]x؇5=lg-|jnDrzOIb-WkZ16"֡xn81<7|]3b6>a';فd?؛9zDVyO_P!|u#iu׍Ov?Ws}M}{+07zW"4 h`q6kuO3.o|2oxb~+ke AʞWgl=IV+Bdĸܚڒy&(8-Wot)Ň_:7g;rJdut!1c}QWJs'<woz.ϊo΃.q=3,{ohn <댕UD4e|)Fmg}Ψ"1~B_ͯȷ *C9}ˏg}bGQ朶 pqn>ϼO.d1]ޢ!Ⱦ{O/ȱQ^ٵ_81;Vɟo~ B19yJUJl,H 7=ޙڍ)ʿ6+WvgD3WM,MsV&S&|f gګRyt>p>g>tF9W^u{];-qLc|׻fka>mg%mD^a&QP+8뵘e_\OLm׆,N\r}Pշk/YNu]Ϙ&#k^)g^5E\MrY}baw2q^o%x=uID9Vvse^k~qHƜLŶi1mCۄ{,(M`ˉa"ˉR^|+Ƒ%ȕsyc:ӛuoa̴sbXzy&~a$ e``ġ>cX}g0a}M}OU |U5};ԝ3~|RxיRyֈ:Vķqc4,pc[X[p/ʹ9c;|vk7W䄟g]U2Ͻg3z+xBLߟz{}R'xMXwmv:=z go<9~GQFK]ܕ_;}\@/>qK^Ҹyg(̟UDCAWbƗēh!Ǔp=)nuۘO[bKf/SZvS7t~s╜}ӇI߲>/GMk"|rҘE#/^>Ÿqq3Mx o?3g>gvg,979sa-Ħ5q:Lux8'FRw͹[ @\3s[yڙ#x uqN~b\|B~<&1k4F1cPs؍ek1p.uʐ= qxZݎ7]u@7C&Z.& srθ]ek?َAt|$,\,9;yyi|`=)(C/#Ϳ?W5'c-m2OfA=5/ul[1GS=~|7fLKG/?/pۗ7r@ ;{u'Mܥo7w^;}_$=vG{_lC<C̓Wv;LؾPΔč\G.ؔꙧ 9\r[뽲,"f1sz(0vVnyriCַͿ?X]ê i_˝?E+3m 8Avm̷ w'VY+!s>gyf?n1yQ@C}/r8F,1&؛0❉㪽k,pUN!Q] rs(Lb0%r*|;58[UAXV»gu#wݓ4 9o998 iRG;Oںy6cZ8VNѼ]Ϲbk p)i3 m;qYALݽ2X^Xy/6-z/rX<1>{z}R^aɓ2i?֛Y9Ü8#5sžbĹ{׾0ފaN߽9~gֻ5}{{ CD1 @?:F?8Hk`NM_]bG ![bsG ;EKJ0[q9m _mׅ:0վ͉ n|s(.qX}ut#!s~oG<{~EMv7WS_@k!!tvorGM?@ ԑ p>AR):`El–Xs5u7,nt7.w/FN~ w[an?f{S4~nϬ|iI3řhDWe^VF<}N@!WHW{9e\[uYGZޱwLJ]{ZWo`l밬z<w 983E!ȒmH.Ŏau[h~xl^/Zo qPZsp{ 9=ۙ^,sݎ@מ, ~"GPZ-[q}EFw]`g;LjroZb,1DitqA;&>!@[]T'G/؉Ѡc G[\yo#q < b("O>;5_l[>MI.SW=?qk]`yboyǹ\=`,'f^+<ˣmYgza(BR8> O|vmxn̓-c?c/xAk Z1Mܖ҇o}L5V;PqZ(0O=hkzTDil+9ؾ馛7Kva ͅ;8W\E``[oy! Ü3{y^;jOڃq1dؐ~+^\wŀ(!& Ob'۟ꎽ/&6a4I'h_C'l/0wq=Kcw:JAT+G U9]l.XC|C$z>ڇo?' G(Uܼh/.=֚[2֓?(Ǡ= {dEK*qs)ʝ|][ׅ=)z ȁhٳL5M;拌؟[wu}!P1a;}_`|;aPuM:(Ul^K/~oBF .7qt8?>yTs;{~_o|.39a4V#:.J|e9]_l%Ta+A/{i]?F>#e|'>WomX]~"ٷZ~Q%fֳQZ#]p,cjX& I:Nd~7,q4D*8T9ϧ8g }j.|y S^Ma1\axcC,~"OlGyuiGcy;XIsXO[|,* X7,T%G~b[c1jrdnq#w*؎afږ\u۱:xG8&f1O2fҖS`}n'.xk2;g}Z$7>~ß9ˮm@E<>{&E׃"yBA(3}dh?!͗v}{n%>ҒQ.|)Mqށv75k)$F~︌U횦{Yb8d<#s<\ɺ(` \r|}>MOXOA1J1k>`F}2{.iN#FB8M 7-WaD,?>f Ҩz-d-UUC8/6庣n݀mcŇWtxONyk]tѺ@Rs$?xo)5fC6w8[An/iS_q>tP|5ޓJ6Z?6ɀ "1gOT?sn~7%nեb{D}$xe牮p%&Ʋ/Oחƫ^y,4BJ#sՌѴ&ve.S}宻_~>ʶ IDATa1T8WQɪ&N.$ZߛK.LV/x>g>(T_r~L1k#?Vou3wlbI{Qy@c]it?7ިό².PKr[GK ȅtNT śvV} [p?3G~ү0gwM#/s및 }pĶ;.fQkXCԉs"˜>]cyP̣,Qm1>5@~ԹNK_Vu E}rozXxq8# xKbGsT ܧU ͎O<${E9,#q;6|eNjԥP#n9Y}gOM0㲹 Br>c lݎq5oQEԐ2GP|Öqww]y/9\! knӱgarw$0j -2yI7xc̢ c (<}Fv>q\29OHygfU+p`c{/ZLl q,꓍U<9zB2qy9_G9}~Ձ.?A_c2W+|3e(O@ӵY?&;_E{ݳ.6B $1cؖZ5qw/b/8"~;9O 9Mz8斡o !o-ַVMk1/)!? N;p&ޢ/ b)2zԋK/|yXx=.;ɸ{9x=2rdr7s˖YKJ.1I^=Bȇ;~>;XRox bJZ1zn׾nωoD!,c]*|A򢬆)8k2װYEPs? k_hfv:9fƅ.e1`ɓs޵wo޾TyX3O;8:@:o/˶/?4j}Wl/^^wmsbj1 1b wno>I={EBsM=^>PǶ3ה L8+rQtMgmzb6j6-yc|c]2_uL]z_%ۏ>hpy_Y"gs6cC X'kױ>uY?d]Si1u^4b>G\ie~O;.]ֱƟJ;M٦፞=}2e.B;خ>},=:񿰉=༒[c~@Lz}/eOU.za7<Îג#ɴDg ?=00tRu<ѕYxXj?g$tjo˳GԞ/}tuYr<}be~Z#?㴠S<mb>p>kMҙ~8v?8ŭ3d+g%?cGs?t.u>8O>x0%c=Wi \){mE2q5\837u)l|ѝ! a\SHeF՞|xd.(Y ~Mlcs#~ZsyQV/tD?l%\/[&ޓб{أ7&)v7復 twPD98/x ɧ2k]jMLW;Jju3?G/"g>ޡn%^,=.,sph8EQu>ψ׸kͱ _z& Zu)=M0q E}춏ېMaBW36|ƞᎫOn[qE+kQ[ow^C:f(ƒw6ا]$&lrM#&Vuey.qx@rMА3ꄑTJ[Mlӥ bR.ؔ/KuQ귶'4FLo=.޳FGxm\9"㣖;p&}rqƱg_;q|hpK|H\֯jwKypKFGHDa -̘scŐsQ$ #NE`tFoC+FhGy c`|u(jk/YќLA0R.0>33p?ю9{}R{Gxb rd#*h\|XNaǎ&=>tzIVâc'qi̠d|{rK^is8,$!(Uw8/~ʮ9%[߳ZBt>ky.t֏v["=6SCQ#@@u\dG]XqT[[o8_*..˜_Lԝt)@ &'E1ZùFT =Bi}Ye-)?ic?Zl.(S?S۵=j{K^m} YQ`)5z?wn(wH:$&3?`~σ~-x5awJw.X~7Y-;?ǣʏѫ.xX}}c>6S󦏜>ĸ-k~8Ywrro2{\p,UB;[qLlzaZ|LS0p|TuBgߜwA?'}_x߽>}{v+GL<Pf|M g7:Do+92lj53W EvrXTgո'c>0sdliO)շxa-^ɼ;m7a+P~m2VXvKf*Gԑ[˼_6npu#_x`-%6¤Z, c%y|w9g'c}&3IvZ&+'_} ӣ q]|57Yo:ulel6U!yJs抵OU)ct# kl+g^ z#~Q3 <Zd |c:RyF\WvIJrL6],%慗kɲ/Y,2~O$^ʅ ߭>(%^杣W"`p-h|u6]H-Gc4wm?n}omwsd4LMˌ#z?xQɪY_ՇIݍvO]T-$wZw~P-k…>÷#Fp193׾qz|5~_җmpW=וJYw7ƺX$f񀨫ڻe÷"-qʟrbFWK~ᢟl_{eP$^]}!o)-_3KZ8Yd Iג ,cj! xٟ|#`;+]瀕-CxqTȺe01y"&Ъ<[V'3qs2K<۝Y +zVMT-?h`7})3|Oq9͸+9{OO[͟^k|4\X;c3cwZm_//zO+G_^uPfvr@.Oo~Hw#4Q`OM3P BW_z}FH9q=,Z<%qONv,LOJ>zyÑQyOwYSCqcczG:ZohݍcSXE)Er8q /~]b״͊3%OUt]?:Kש V\rd.>r;L>?d},8wOεǬc`ix#гu*`ObF=?|2MKst<贈m³⠾ڽ_rq.839z E°!vut9:Z8V/tG)@}}-ݟ_ܔ[E\]* }uE] W3:0LǞ^ 9'PùEiDT"_Vz=OYqߚEfkVQ!tCW1+?ΖFݦsB#ZyE<\:?ƻJXǒz6s#rĖ9-~+#Zr WE\c֥rKN=RO 5^HǏ>ŕB㹰c_bI .rQx+gȥqf Z%빶D U+13-ñ;m(<1&m: ol?JF C݈({ܺq_ VJ9e{C{]Sz #yޠ@oa~Û4}K[u 4!D1iħ|za t8bW+%sZE˸:\}ړd78≏ĤlaTUR XEϔw5b1Rgz[yku{rEeѾXZ8ovk*bUb|ao3P'_J?7iw:T ?بeZ2,׾GHXRs s3bcH-kb<g_>Sխ%wwn~w~O>Kb/@pU_9`ŇjXq\<[~=9%:Q/\>/A|S R$\c_f/r$/7` ]_7gޤ?t(ʧ~"=1!$o%\puxϸY,Ā&6P1y& Пr,y8xO$&dp{ή,'@p81C:$QL"~2VEkv?tsᵺUΉ>sc]ˌ!}ɻt{,~^t .}iY&5?_ds±DG}F1 zjVࢧ]Ab|rM1guP-:zW~iCFc'lv[ɝrFv%9 ltӟkDG!K<"Uo"gQW1/Y`}b}qnF08I+si wj. u9WO|]8,G(OL3$.}k&M>^.nѺG.բ%Wc\ m#^aٌei0`Rqro4 vt|t2lsO~fQhw/|rjo?bOcrZ[ْ7/l eƼRxcȜ.R2ŤL(_8]Q"PΟn#KouB s!z3<7mC;M^c_Q:3r_"eKʚn)"x|˭nꢦﶺJqŸo%k?od@^4%{DwF~t?'C4k@aGcq]:^%USpog@u 5W Vi7Tcov)q֥ov <J_O̝s̰|r]$'kcg&`WWs5\YyM6 UbV%@­poR?mk  qv`>!K^uگFR#..6.ʟ*}WxԞYpĜ5>G;|/"s={\nGu\.)Ut|}O||߶WnO>>[gb9#hb_>wTIPj4|؟1]fs>3|#O/yz&C+Sr9 d|ghI]d|ľfZ<|gOߩly;꒶dH8vNcY:`K8\8ǵf6pF]o]q,<{ =/I+9WJgktym#!,}} F}*nyJlwwd/zdL?%C>oXGӹXeO_yaIfSCCLp*-v]468Co0 uimtN'<6ZϹyA͠M`wC֭y8ڿO^PT$‘$s2o~il3. 81$;A"E%QD~ RNJ\|.Rl?QN{kYc7~cĪv$q p.#f6 IDAT OrT#+YVV\>q KKL#ܙ zdhC(3:cq |c=!ul&> \A%:rsYp}_2lcؠ9YgqIm;>ݾaƃ>g[ֹ}@@sRyǟZQex3v=.GL/G^N_=\X &xjHHw=QNI7~1꣋ ̱cc >,E\E ]cJB޸cL$0?T#I<' s:ޑ`-䄭CNDsL ]ydX!9^x6e4OsMw~Wo.$>yKDR^p'K?O/(ltAuq*{'1cTS@HF3iH`4(^؁c^Ul#Ę>&;Slj,} G#KHԼ[ 7~@nWE="B_ty oOj5ƾ4\Lx+-e{ _;z}{\_}#HKB̵j0%^+h\ڪ\aݱ߻}ӟE?.Κw}p5r|Mwםǐ؍/( c&g;lK}8碮VW7Y*iƎudߊn2sO#|ƞ8\K#.d^Z4hћԗ113ET.)W)}PM?:SЊSt//_eoV%q1Z|\ ZL%_ʠQPWS7m&]꫷G?/088~ } ?Np*!l%a"? >}q!ĥk=>bæ1#CG\sxF}#߼]y|[T S} n䋋|}h-;1.1+yX4𛻖Ӭ ..q$>V@zq(Yw$I+f@|,);$ĄEJg?sY~.>_c5N)0~hbB8t|ƽ9.=69pGGhmß=e_e_g{֘p1GƝ?`g]߷j'Xxi!S7Ƌ{@},ۚU[ksĻkDgkɞyvi+B4U*N?%0ٜw猝-2Sҫ#g~n]P!=2}b.%nq C;.cÝC<ϪF;?.<:9.}egƮG|1{`&GyLKW=Oliȅ=i31REl]otчe:5MzjU^1 Ecli_8`J& "<2zLW?P/d29Rn¤{=reo#FEBrxcR?p{.TxnFNM{H;>۸0yOq[svz7o{3z> n;?yvsױ|?n~x0{[bj'on77{q !,fNF$.G""_HDq\3}.E.38)p}$V _}UQLQ?t lrb)=)Y9Ųk>GX.ͱi :.Z1(!g3t|LN 3k> /~׋qc#OS`S?ƹ?֝ٯ|.w}a2:pJ4**%>vc՜;#V<2D&-YM {$Oj>/=9,ykz,G8j}j8e3,<ҕpwE<y\EsCzꒃ1}120医=>63r/I,D#(Qaf_dFPčNwC1^=n-M 8!K{Ygn,}wÑ_J˙!Pe5z\N֯:>vs/>챏ȅ[}&'zzJ9Klخ<15*E >=|GfgSes]w1;`|+N44bXr*Fuc# 79rIcx~ _!+*WUd%UŰj< 4gb A L F"?)|1-\)k3]Q3ݷHÕ,|CdIydWno{;xOl;y+>|>Ly>~ݝI̟,=|+;n]B?t޶8jxlH.X X#+[:~Gz,p2.D zyx[ח %rA$#8yT ~v+ē\}1 ?6U~P,Vjė;TAYSP޼X:"~G@ oLh2WKwU(u/|U[8~ɨ3pK/1(Ұ [ڥM](-NB K̓푏zT9vձ\b>ZeɾQW\y=^z{t;SWTsŵHQ{*_ZƵlw,}㈮%2lN S{ij:hܕ<H{d$< ;x{ {{N۷c8\}%urMΝ(M$PLtZ6rĵibDžփ4nlv0M-\o,e3̃rG*|}s2֥%ds>vNў }be >EفpuylaZ.nڲ&AMܫjs/A7Xi Rw|:5~݁ap^V~J:h4d)Jr%ĘڇaadHb>vAGvbLCGm%h+䊏lDpSV<䟖2{{=~b}AxW$үiA'ڴgGwȂ{&XgeY]ٹ'eNjg=\ 5n OcaFE9I'kú$|08w* #<:/bKJ}탙zqF]+¸ ¥fB @1ӆ͐2(L?Ρ.|od.ᑛC$H>P1 KBc+`T]Θ_q{n޾统}3}dG4ʹȼGl?/n5y|_S}O)|yc7om{+^= g T6"·>\L*lAbs])'MUn 9!DOZGB=s/axi1g vgl gD[uKR@D=6l)d1Ț/>s+*` ^>cS>ˈnad&ƃ}T \+ZC}/t* ZR EI^arq|gny-\__U;_Xxײ\W!|ޏʟ\sFV|4M>p{K_Voa}53 R6H=T |3WZw 6_rX3Ί) Nlge=zXrJšCvO."ZL2i~lft\ UX]}îd.xsZ|1acUVD}bikns@g5,Ak$ /'7d ]\É`~xl ő:g/xU" ל9/jc9",6pGp>aH>|郊뺏'39^rƕήNG8 >]>uwYl*b _qcL;ְ$V8r˼36fX-=nMO/^|01-ڥOrN#"BeWaq6PRKȨ^~\!ثglK0j 3bQ;z_ႎ%ziix{퟿}[վTҗҥk#\0Է~] -\P筯̿^_˜ ]<'G`!8|ℏx:y{u浯~OZoɫ~!;|]UXr(Kpĺh/].}!֪jWGܜS_6w"X,{ߵpt9Y1bi'#K'>I/ۮ/hҾ.E. -yd=8{_mzu3838+)¾S9يc;cs|FWAj56!1_z[zˎ'Xf<1Zs^{'Sg" "N9Lb˪ae!s878R:F3TqwdqG>{!!Ɖ'r@1a҇ydSypS7[ѧc)c9LSr_߬M'>acqD43t`vi躾y 8c\ jq{hY66}V# +أNs1>v g! d3v<1 ].~ f=`2qֱ̜Ho(ⳜG4 8yy.v,GZ50+1utBj≯4g G|}]_'a?wiw~!v*W UZ['ii̺xC1u~6C.{8mb[ab1ylę Lf#\G삡ydQ\t)F~25_֚F]_u* e~Y Zp 'lcfPTǺ}48bh+R^'?{8N-s&؅Z;P3CR IDATmgsd6ƼN\̱l;ϏvA[y8:Tq QGݎ9hg:N7`2^>6]pC"qm@h_dGbؗ=Nlzh.O=k @)I4PŋYŧXn~"[L4|~L]`V|?wp /vaPyR|f̉8s=8QcӅz(P-xv8 Oze3w~EFc":5l#O {} {+%YcX-~$s^;G1sǶ!( |_G5mZܗXS89u)狭G}v?ُك/n)G 7ڴu+Y/`sָ}J] +C^ugyag8Е"M} ^9\^,5rط3Z&CTxV/}VåEں#`4z]y }ݴe7tgNwa=~-p?Ǘn[nOϦOۮ {te*Rvkբ w:'Hj4(3'{1<c5_&+9ۆ|{=zOn5/9$c<6*B=WBOiP/θke~n\|ga~#3'C"`k_]u%\'lz2_HVӫ39?+|{h}4B [&CcʯC8pxrq_/?;>ьw"':WF?tcy#6޺دxEN:6޻+eyAY}PqSVμ$Gd.w&$X}N֦ǜq'2' =?/#~қZ9G!dLlzp\9Š_G|t.;ka=jX9“ۈxIH;E&.|16<2։X쎲/c|a/8p"*dԏ\vX%ؠ~$S'L0ǹlƦrqy7W[C(w 9h=>G2A`8Z#6dق}A'O䴽kNXC7.6(9>jl#;{|كus/?m33u.#wID>>uN{9׎™9۽IўeB|& qmu8y‘}fX޸Z [u8|G۪r9}&R/٣f+Ȍ/=Ѻ]8 Xíg0ΩgStmBX|h}PFe1yW!ʁxxGZ:>P>buL^*wV ޿~{[޺/ەv@@ǖp/C>y01j|i*׾vv7o__T"2*oKu蘣} Cs;-VCx#=><2jR\# Tu Z[⚟-_@źB+uuW׽u -9_~tR4[y2'/E٨"vU SU#W\!` l;k!E o'8˞"u)J;֜\eO\O ʼnvvƔЉns+n%bDƘZ$' x; _?h{`U{vvP߅9G_KuW}ۊ7#I:V3(ؤn`ε8ѹ>zQ-K+}V\/p8>^>NGhwD^Ioj;stI)WHj;s ༨_ǜ5*:̣;6.ᦧ$Gǹq.~NVO8#J9c3n{Xn}d{uݦ+_ﺌ/>qDpG}jz·bE<}7 >Xz˺wY&jU0r6}3W? gtX#?lq%ȴ,*[GNO..qԊLmWN /[󡋞>>beQD (mKڀ=9Yx.} Gr?qcW/0zwn؞mhDs,ĝ^/k\XkZY>^~Ms6v~T̜2y#53t])kw+楗ڧCu_( cDFᏯAJO+YfC?M beyȋ\ [Vb ݈Xc7yM$:zs \₥T|WǢ\qU]8E帿H?"[erte]|ws%>l'W7תZpGnk\xÔl~mW^AdZY^@ؿ / )IR{.qiN>Ϛl<n?sƗWw=P޾ [c?߻=!~v۬2G?3ũԋ Y3^9u|##sMKRG4>zŴе`}3>gc>yǦ& }y{*4ڀsq0|ȻN6b9Ɛ%l096˟<:O8 ]mx{d_SU l^\VGj;{b:a5Q\#`dT}̪HmbK{SF"J#C&/`/^jЈkq'töA9؜ 0-›ORN/s#sMA;ְclE #?2Vc.pCkXxbXg闭%26;?1{ЅM1|KvTE)r.1۷ھoܮï}|.cf}f] ^spogv|ݓY,S;S/Gk߲c G\P/gdA]S3F^\zo̥u!jɸ%-0'Eƈz'` a>Q]( fG68X/}ʅf9QVEzQ6ϲάIƣks0@v2\C4Y\;CG^/ cT FDWvG#kAd_jj&:̷V 3 q2_7jg~u]gڥu1q*7&5}jjL=ЂձEhnz_~. %rO _qf:'e_ݭljg|ӷG3^',Eb{lj.E)f!W/:f,'qr Gq}d{@N >cNccP\6F~Ñaˆj¢vN$<&P+;u1!@59u@X=2υG>K^#zq.b%/A~̵%eU<я|t{{]wY"5l᠏Oh/xL]~xE:&u,.p0CX_]ok<Hy#<\|?+v_$"XxFԳDF}*[Ԭ2O uc>kH}금\5_5s.VfZ3r|-,QW%˞tJ ^{c(U/b/4!o#&}Xw)|{pzN:Y==^%]}U'U.f.ؤ)1IFa9aڦ.glP8ږ.kGp/JV`H_xƟm'k+ھяֲ;$2#Zyˬ!:[88AEsǓ O viTfLNj;38o?ۍq_>G$Ԟ,@E/˯~/~ks ou&E46׾5:zd'\`M=&_Gm=H-V3sd^\>&ۑSdGNsî&cOu[0g|y97̜ķPu}lշ6hf.k==zS,ܑ^T(﫪3#3 `((FXjRTh|)Sh~N:1&Vms!((̓@ֳ:W{{ z|ν0v bUXvn2הDj=\1{db͵7{?َ^@)4v}|?^Q]}ʺ }?X[xl#ikRɫb L1km.[$nӵky:7ݾ3֬ kKDZ z'Y&/>[;lO~_L(? ?`Cv qS'\7p=l97􋿠Ԥ.t2}w&q;`|'b7ei.˧YY>Չp:q'9N=V'u1׉sY6˓~akq\#\g )wbS] !+PS#?ewޱǣkaN캨Y;g? 'G\=d% 9kޞ{ mcm+q>Lf8qƙ5yŜ8Q;ɢcыq❘*bs,a)\w3╿_N J۱KE9oo_Y|媫\,7Cc"ű'߼יE'?묳忽k93N韣INݚJCǽ뉲{>KJY=岝TXwOT0VTZ-h(]| {@E &a-}jȘCOY-z9;mmqo-/d6|< ng|,>3FO_wĴ_ux [n;YIg]î%Sw;[$#@4`[z`c}~l;fU^Kߪym^粅ֹZ5ƆAwQ"nh:d_ڍt]nq<]ۤ).Unc,j#8 aAX޾5˜vrmDz\%E4ۇqަvl9P G'צ{έ ?+Os5Gm?iXVcm_">]W-X1vL8+Nm殝ƣ :&Sdh{g =VX(gq(y0.r,ewk\#,3F Nm IDATmR\&|t<ֹcK6m-p ܨh|SµOqdr]?Ygc^{%@ɉO8~y^p ex\U~uX&䘷"tꊿˮbtR#L㞨Y B0MW Qr^qiFfi^i8^IJnNqR"ku0?/qUss`Lr=Nku|(bTNh0U'or'>D9!)뜿lrfi}6K`ww_uײ!#*7d:YkC=G|҆\gI#g H"pH>⢜W㪫lJ}k[OypT ZO~ĉ WB^wo]v8YrwѾ|͏gYp-y,yv6X1XjU\Oqaէoc[<͠bqYS.EDl 6w?K?+)፟tpa9zܶctms8pv8e5iz01)\*u~zQU$on>s=Ibm7vܺv4Ӌ۷(#VEm̕B6SqYm͜;u{,jε-IVG}'~[[;svn"_.bL琍I^| w7qcصx6N΂낌o`+0Yͮonw[w&/իU=~Ƿٶ,9z|ME 6|<& ҩJBg^ڮl<`ÛVۦ)>:/lK5|Ds2|ZW!Ĉ|r֯p͗ެr Tؼ g ɇ Wfy36ě{ֹ'=ϡ睧Cq4`6zazP/07dQq|_V|,cdʱ)y`WSF Eu&6oÖ}%emю9/}}JPpRӚ_ 9!oΓ'%CYmM͗7Gƕ\/wsr.וkKu  F.Aͤug<7t?'c N0N> !cY,)c|D7Nq691GYbLv)~џZR-˸ Rasy>6ȺvŶ>6b@1c?q\i.t[ch[׾*{Q0jMP+[m<Ɨ~+Ƿsa/cn~,+Xt'ZWsaTq_ʹێQlgu1~>^pW;O㻷4Xޘ]ƘuƱ\PQu-+gLd3ΆSs1u,ckR:#vQlaz+ Z7g<'=V u.ֲtLna`T~^MScpVEMO\A8>;ϛNjx~#~x_@E>㹶҄^yV3xefSY~rj|sk7j@e |U|'pR_q%N?|.-78-FNF}BT'Z"fq:{։ 7۲+& O1ZhZm lg^zs'ޠ58dFɣ&^ذިJ6芯-qF3oir'‹.L bYxSV*dY'X׹.Yi`fJ'd6<$N~1k$I=FqS&Z .SN>uyi\B~:9 $ 8Ar0{"ƺeL 0x,? Ĕ{KE\&?r ܻ'NޝV/7oË&c8s4̗g>Y[?NTۙ`srxƋ%u27Ǹl' 9 'w>'wϽ`#Z'NtGuosaq񛗗%8 ;)׿6D,SKzqu('aqsӏ߻wcqGV ȹwqbѕo~[N,?tJ}#ܰ^&eRøX-)m..-u| #0rx`[cl[[z3{:ֵsy<9&sZ>σ1&zoN~լs -sQ=n`qD+_o\DN1P]1/5P2J\փaƲzrR>c?aIB EJq,M%g&5 P! _n~yk V[1=Ek捞 d 1*X쥞A@""9p0mI}oRxZAM עAx9&zju"q̋Y4=f~1,a3|ʟ37t;̻NL.]q6yɘ]oKo;zv=qyɸl|Vp6s5Jfz?̒U~ p-уGr'p{}J# .NZu%&87|+҆xawX1}DZ  '.9̜+΀:1{C/(=80D1yp˛"&/1l\xo4e(ǂWUp`Q\?* Jd~%s[n:F(0ŗ>49y6}Rl0i|w&'bTv!Z{0a^Xqx"Äye3. Z1 {1cX~aUc,߽X2pŦ t흟/z_~'pe͹z >I:j C|̉Rq3G?R#*w4Kr["w ҲvYGUsbFiXG~Mc؍c+_s>~zOun[]޶/e:r"S6֋K?r~r=^5g@X*r=5"qtylW=J9 sX6C]e'Ӝå? Ajt[˒ȽJN\%dgW1b33Ӭʫ0Cjz'V =8HVi< m:V;N f.D1nKĚ1X9HôO'r$q\R\%Wd1\WĒ|[o8#m79obamQzEh|%H;1ޱzf[ǫ7RW!<#'* woo&H1,cזHB BsŚqk{36VPm\rfE?ƛv"\~ϝ8eV|XAr|V? F]9zR5l'x<^y87?ύ{mö4vdʌV@j}Ry̸^{@X88{o`F޸Mz"֡f W_xLόi 4<9Szy}8#ɫgѨzsڣ4x,8V.?˙q%]! #5z7~|VM[1JRy؞7bn`8eq##W&EOX 3wx#7ŏ82duz.z>HG ,xs1'zINYw16mFژvIlF^t\u.>#`G>&GF1IS%.rk:3<(\qY;sU u {\R')uF-]E Q/p]H [vc|7ܰ"'ߴ<->cTI:}qM#Ex9~ F)ߊ+jq>ro"h}]AQ~e˱>s]ԁ7_S qܲb0Q7U>1R{ڈUcd~@wT䢆}2c3xKglG6GjaXȧf8;N>q`MuBIFODz>5}dq8-j cXj_1Çƭ{B5E}F|8[U,[ڊK3|ڇQ}i_c /ޒNH1ӈ`b<ƽYo[0 D+䉚 pN%l;P}ǐA 'n0OƴNq;p62;Xmfs@$J74z<)4lKDZKsu1zpڍ|{~Pl[Za?a1>1w\ېSotݥsl$}RS7+R5uzL',3(¨u3JW%r/.]5V98XS>6G6| aed_>c{z|5^*?7 9/·'1p];2V?+l!wLDXq< T'@ZX70m_C<>mȁf^s2P ^ο\0!]!Enbƣ.3ܯ[rwu卽=Dh} :_>J Xɼ\VR9?NH&dL{>f-~J P:CT W@]vSQx7kf_/vDŽT7!HBH"DS2A:iX J<䐎9x |ӧ F&9o|Cs8?,]+i@-L3DIGYA1L#\^HG<1TCYMыiAo;J7ϸ!''ν޻\?y|śƌ!ې_=~ыZߗɕ_\Ȟi`=8c_\ "}׊1s]<8!w-gwsܱ\TJ#!^'ǯo/9ˏN,'cQxX9tLƝuS=]0}WvW钵{)M&c^Gh`Vhƞ$k/)0`-mr珹ejX!!vo[Fr(mC:)Ό5#kn+Yzc2s[adjdq 8oscڟ4j֖wXKH<aA1`,|VG@ѝMG \y],J'd-yJȓ!FcxĊYj1哯*mwqiC)eH9]EJ<`-$`F1X7-4{Q[YFo{ؒZۆ9NLMan]XhF"bRX r0:k_bH|l?d?m {&p S8g[P:i;Er!Bd-ĐB}%_ՋgǏJ跿OǕ y$Pef1x|ݣԃƜp%wȵ[_ވv9{-O3:,r*/S:5`}Nȯt?? # Y(j.p6ǻuwl3zٯ+y&YK[8̨}#w=2MY;zJ.Ȝ^X:Dj[,G`{@\@HhLpvKcAutF< yI(ߋCf[93bq:>>qgyE13,{eav*O<4N0r@ `mORq0(铡=bh; c|i +hLwG]&38?Nax7 4L ?@uz-S0*zDiƾlٹzyF}p*8>/~: p7QPY)S9nk&=iafR c_Y4sqxL1w$=>M15q71߾Ȱ9 [͝9 ݱBǪQݷbqSk?k>$\c/sc {x`0O޽b&Y7 -7rW_sYq/>o&s`h!)@}3_Q87K`xLtLV`[䤵QFe؇zi VQI0rAÑcy/m0v {}gj+^-?9m1}_Ytʓ`p cEa)&IݫCIВ8KsN Sh6ΈVgQ=#GҴWv ?ҒSư>)NN[ 5&5ŚG-F b"|ww'xΉNɚ}-W]yZ >zsH/C Ye%lbd^y')waaYiK;PM}mw6|Zı!u ߯w zG%ع6;c=1sSłJF}oPc r ѐy,ctڭ6a;y:ɐAsܒ*ِ @ץ1Vծ}Ӽ <ݜBus:"D=ҋ_-4ۊ^]/c݅ Z۶d6 7kAg ۶i0Ko9Qc_dvS?W-][slͤ_ݕO ';msƭ~: (T=e?VAǁ605M<ɛ Y֘uK)!TZ Y&V'Px~P$pQYx=tzbZQ|G0)}Gs'q<%/C \1Kqo) SkN C[}{Ȳb?ظu(19{sjZ`~:X8ۘ}Rɇ54~=͝OΘiŬsfU+uOVUٵc zí9X◾1WJuѣ;W1zQN^07qSǗ'r?yk| b³Yz皹Ȇq O'?;緖C$VeJG{E52 >"5lfՄ)s:d啎GG~9}B͚gm$ [ 6aLqE/_L*@׹6oۿvq <#Szī|Y~<޸9b`{`mN3'd}֖KS3ٍN#G ;. D$-ƽH$O(=gB&{Ɍ?8>WA!qR{oz>G⚹P2Ƕwo s߂k כPy,11ĵmXOzpkc,a4◓ϜyQ~8⑂nim۩ QZ,֜3gkY0?e՛ x:p6ȰYeČj+#ƴV!7{dԛG =u,ɼ\̕'~,S_z|O?('ט҃ZX` %^иaύ|LN"~}dlL OS58^/@B`mhi=Wqߗ8psW܄ˀ.d0QVK]Lw/z3/L̒˴ w0'M7%nyAk`؈21+Dah)R;gCc5o_[* i9;/s3Kƾ/ďpDL7Ɩ(?/T;8 rh8Ekw\0Rr3hxX'f.~Ԟ+~_岸2g=;WtDe GB{['xHobls`/|<8ܸ^|,w#pc0? OS = *-&[}1=mkw$jYm|ۺX|k oĝ@-514œ۶!2.ncO| qH&ye|o>8&pD+%}C㩯<-1pn=.Dzm9#VV~EZofFDEÌuLTl SycW9s##`r?; rl1I|r+G SX kb[4þ qD􉓨A0gD wz{yG,waHtF=kI}O~˝߮gqũkuNM16mgJJm)IM6wԔ^܅'1 4}C۬ͮ"q/9a0Xb[$q7:'cGGώpȣZ}5d!ƣt r1+&K=^Jq {,34!<e36堞 j? f=E~g{֚7zL昹2~Nq7<^^nq3|K}٘q<5qRd>ϸ]m|F72z흋l9Ǫg};} 6glg.ֻ~U*=xr ژьw$#w7V=q^sf~'1C֧(kT6h n)̄ aSq좏vȓ= 1vb3F姈p-gDzl_?ba'IcVGNH2Ƕv-~g2 +Pٔ9}-{l<-ެOٌ7~ c&cm5Ad諿(CB*ތa>sヮ컓Y%{v Ɩm1/k0y?l /琘rkBۯclg$cא`k3﹚.#ze8vLԣ{m޺mo=}[x7pܗɘ0۾:Hm{ ~!Q5l7Z[~#՟EajZ׃ur}nja7`YIw=mGX_qK/_1|9LN+ݷ\t]m2yJY4Z{pn=V=#,ꉛ-kQ 0;u>PQj\2~Gͱ/,_ʗydks>qrW,WqM,i`?7h#p7GX(G+o(oxԺn;0@52)5VP9w}飜g ݯ)0 \UW\WUZzYˉ'=) b3"f"FL4" i.Ȗzhv.akBH|l[n8t _X~qNО!n~_N:$=wV'>GXq .>{7G>L_}AYcѼ6:!Θμ} c{rti^/c[f\e˷1\xm\t}g1č u|z,dW6[1v;Gu}=+ӟeyP&֝9'&=]{>]c.,W-^ 7n#Pc p{<$mj m&A;705BR&nI-%rF#Dv>b ygaE9L+Gc31 r؏]`03G?²;.&eӸ<&^!cړDkIİI֎[C͉I,ѧZّc ,NŨĭso;+\*m$2`;ԹdY k3S--޲Ke}e/i`<-^8ە/Nscƙu}clx;GF-D0A[NˮBa6k2lR/3NﱣyݦNSIn;s] = foպϸ`W;[< IDAT[bi\ʡFn}Facpy,ݮZ/11# X.c >}"ZRq R;NMźNrcz9O1?3^g?9MQx# ^'Bnu^~ߟGZ([|J:r˜٪+E`\AMCGO]6WkTCd|G>Q]]X] F’!#p) Q#u{~UӛȪCJG~bjQ/R5*d8;'^aK zka!:7D#n<'o+0w]yՕ~<ZzCbUcSqFP5^Ͽ_K_O}rN9J_2}X|g~7Ŋl%kLNg"JN=64qL 'b4R&Q+R\y&'y05HF mD)sh2-]c?2hli_h#ID1{9w~r/='QϞ/Œ4@<?X>X>s_E/~~"x[Ε@L&#b_3 py<8a1"XWwW?Btr_jQ_,|bǯ)!1i|.N6r ;Ut6Py=[NkcV l &XrS8YP(NdsdS3?‡E҅~޴M͘T{wvLl#к lƫAz-Kx'6zlZch,iX~罷-c7\7ٺ@4qL3ncOKq|zp x{SJ0fC,7OdwYK70G:mjl}:h1.>΁mqw3ݾǴ6]1%6*Ҝ h=24u1 s0Ӧ=\Ymknɂ=>E/6\؆ۅ(ZPw!o8dX.&hoc!کh =i}^"z]x_oؕy\z,DCg)*AP֜+7t}cu\YdcQ up*d+T}Yاqtyds3s|l6YhX>Ñ`||fؘWI.whsg˲$gǴ><39zMj /ɱUvJL}ڏRV=ui~As4>>F1˼EYzm{ O2c;/yW[\l7H+*+Ҋ7l=[D{ۺnc^~\َ7iIY6|:bþYvY]M<7:<~a q5Sco,Ue߾'${K* èq% :c>x^΋1γ]~ɧ"PA&AnOMKwIGb-8x!M}xWB.hP=j~+8iH飿ޜяnZ.߹;񝉷ؼO}30Wܜ}QX8ZEm!k_/j\-t~O_~ri-ψ۩<8;q+0 jBp6a)yyCʤ{뮕;[A).=yW{죆V>:J1PĆ1u /),bp2FsO:mz_L^yU˅^zۭ#ݛĠ&1/0fM5h%9O>M7-37Nu~߹/96:nppu%:GOH䤞)=1}-߈@th#bCDUTcՉ;W/'K'gyB LNim'L'Aڸ!uo :AM#=Wo^wucܯySN=EǟC?NQ?67xS:ɿ⅟j'S)Mg[?х ܩu? OMϽʿ0ퟺk_tƈY IK1p/kc|֠vwl>vmQrS^s|+ɑq]a|7hչl}vu΃#6c6mm.DnXîfũ=cؿύEύl IX)6>-85ݴK#wsbN~SgY֢i:m5u1=#,$`۪agf}ak踊~|x@lzn1m;'.ݱeX̱>9^~p6{iGvz3n`a/8'GU\o(BHA=dWc!kXb3K:nF٘?>*טfFfk>҇Lv+^a.2Z7unlj;n7ّ1TQS|7h7՗}w ߾9}=qCkW(N+6o SDFFu|jb,cȮ0Njv Z䃰v)sf`cF[o]>{uqO_{![t?k|, yyZ~]w=.)lZf[ +&z]l+D+@9~b+cdH,l !~4=6aJaaS8=|xg>S˚N^aZ ><0x/G*>cd~ \"BVCVTRm8 jk60?\6@}&ȁ?rY;G=:sc2GcL=vEV?~#S6pEҲI)f Zq\;.A`ŝc0b$n46DSVÞ!U-'lgygzBxDظٷ{?>m-XVB{ ; ػM$湟36ljk}Q`$C0擏+;%丷΁9:'-kEgޛc%f&;6r?Fs0v>އlkA֯bn/P0k9{2[>_6%P 4|zFU~~ủc;5㻷ŽT+94KPw*TjOC1z>k_6wĿaj,ƶ+{z&<Ƽxlߴ{<{:PN6Ey͕JEt 0ؚORu4G>| NQpt &MxяI/l-o_@009fKoSK|:JҾ ޺GB+1]}˭`=8 YE+׵>枴pi/in'!1g4oWZ,CCK"DH5z?%+5x3o1Vo8Wzco09cr*~1ļЅ}c+>vB\N0*D_Rߦ)VcnIՇy ] Qpk&,S\Ts<׼mz]sCc<ӣ(05f.4fBf0d69Z{l5ۨa1B@O3Jq=Ɔliv# i5l嗠s?ZAg c0-]m"bgNG5G!0Cf0[X7/>߾d>[쭷CɅzϙu\h܄I}楕,EUg3=}ozh!y"3Ym1߯!붎eR><%"4Ɍ簜;6GKg軌h1;.ؽszlS6?A_Xhp[hlƵx)-fmAT62ۺGo,.6Ѽ`m"鏟mܧ>)ɱ0aq@d6D7A̭9{o.N!tDYz^h}|o0gΘ枱喥?vsͱ1-~ZpYa1zu1zpWފہ~m2o#ŒՎ.03j&rcR|7}Ն_I.bmm-__`FO51s(@U4m}r:sbJMBXGm>}eYc-æc1߇g{:_mG쟧,羟uKmۖ5nqZ6`аusyڑzodç DW7r&U$fyO|uF̦PU$F2Cl36ē Õ}eL- =r+ư'slnnV惝tExؖO{bøZYہF߭p\W2q}BumX=Bp~Bpxp,@$<1ٞO!5z3m<ǩ:Ut;X@l4n[ ̫8{2MNA9=FsY}'Af?< kAj<+Ϙvy^\*{dֿx{lq3sk7cB' Y6y?<}`gCJdxu̱.o7-/|Yaqĕ1#㻯f^xA|i>%u.\wgm=kCPIwC|썏x{ |)o^dY'-XpH?ߣ7G` Yo-DO1w[wk3M׼f$xxe̕jάg/9&}bn1yEL'>y`7w3|ɘ8׽O 2ύS\,?Z޲!>q"mJGw'rGF3-s ,5Zc:^:*f͢N{Z (s!.* ҀXp<}l8Uu0T:6]Y5?}s+I)m=.ܐYc)Fٖ~_>7?g̉mtp6]kf6.`K5l|ڞ^ 9u|l3:g&~eLͶG''l{0۲63:Fuh_v'm~%Pȇ}<^+uyL|ƿ8Ecc7x.b1MI`jTo]ugg }܃_UOT$p]!\SxD^==v"sǚby7M ᆜ팛zsKn}*Sرqw}̻¨yxnp|;J"Ǝ^IִI{ݻ?( D!hGj"jObD<G$iUJ*mHkc mMRtv~Ƙ99wo }cqkss?ϓ2vvtOy kRg#_]-rc<ڬssVr{_UuběSxb;~u]\yJUy*~3J$\[gmҕuĊwo,O;ҾI߀%ve>#^QeLx%wKcȌM]LqQܨc=A8:;0[s ^]K 8*\mZ14}RtoY]Baq7 ُmkL.]x:R]8gxsܜ6Ux(uaF':^ 2^[WV cf/Ss U?zxd ע:7Nb}?sv]܉l@ȭ_.\j,kc[[ʞMƴe?#ԕ=U:WR杂+1uks4LQ)qhgl_f IDATs4߰e1uڊy5<  ٯJwYrqo}Ĩk;g ^'][ ?ɃQ=ٗL5zw39oc[` 1[sl's̷})>x,^Gr E4M#YJAw?݋Zrt՞%+V`: R]kor;3mO3Ԏm3Zr {SDiu`ɟg{3m SbXoT'y [v|zۍO^g}5uԄ>a젝35ڌog6c)_?}S[9< ppLۦ:o}LvmG:?v7n{9ƶ]\90Q#7gK?bN9(TV9Ik e-1{FhWLZ?}Fÿ?B̈́Cb/_~ߵW:W,/u6VIXOh̡z=s.t\y+&g^8b82;϶Cw|%&R& 3e cbz缁ga0P wuHq΅{́kUokLW1r*+ YWHU,pIX߲2+'qGMbd#1Xk°'&kM^F]1kDYZX\rdgU\zgַT[rٿ{7`BC,eoS٨:*??V4m^b+<}H1wb;cF`;\X r~=g`f3U Yg9 y6u9 ك}5JJ]|m­L gz 7k+1w{m0^_kû ֲyi33![Gg]_ kz kqL{ͭ}Ƨ{*<*x~~dp~kTOKSOpr9T)}~Ϯs]c4-U{ȫܵ3ثAgeGt:a޸&cC,jkھ -j~HAiS$6ydxyoک=Gg~Ɖ#jp=lH~ךB̼ևNʋUZ)_X^7Ү\~UDfaKZ3'e޹z8gp vXlcܟ({ȂP gsCMR9}g)u.qnt+~A~{/s c;DZŻޞQtT9C|}Qn:_͏/˻^r\rU5ƨi~Z}wG|:4ngh BHX%e>mC ^;ɳC:. ܺpNUUɍOLƕ>ksOi.~86mRA9C}yܘC2}?姄њ{5csb[)O L ܑXӔq ?N\ ?9U|:y?x k~bcy6oR3t]5xfolzS8cϑDGk_/vt}؆=Q׳m;j`/{HkJ]֢8tm^G)k[Йg{饣. mWͷ讥XcO;⪰Arzlήe30t?t.^[//eڟz7{TgzşLڌ7_Ϥgsҟ1~~a;czrKS6d9h Wuebdc[skIŦjӒ{*\>%~*&/?ҩa.F4vI^[-Q o_ybxִ9AWBZܹ> GBs+)_nmk}}CƓ13H {.]&Fh쯹؜'O-6>@X:iGK k/uѻmr =kbn\培::ΐڒ{=MO?Gh>ñ~p<N6'[Y3}u?~N%Rw^N]9!8SWS;W}1z;kT/g 0k`W5'w+&曱W=i p隇n۞y\IG7XcS&NJ>kJV\wqko/!}͉5!7mԳ\}k4ƓJHVՊf(n8\-Ա咟41ǿ߭1f֥|/pec޳_Sg?-L~.rko|z| ̹#&Ƕ}mH5z7l䇃eMr1hӪ]_s)!y5Rܺ3^-HXt_ԗX1Jk/WeY׷_g`FA$w36tcu}XϚC{ﱱ4V|3OML%{v%!q?\>}`һ7zϠjl5g+&W;Tkn ٍ&R_q}8u̙ab.Nӓq]+8[m`X}@qӆ%kĜ5ERzv ݇{N ;==P' qOAE1*%qE⳨ͷM\n}+;.Āg)Ŗmbb>;q֨}#+W ;87e f_~M|u^>#_2`ϲ$XtLԤO?ut;'im9E[a*fZrx}k3FJ֤MXHm%V6JCm4kؒ{ֈcF+ߜq$5ԧļy{:ڪ5-uX>b|_ ]} .uHN|sbgcmk).u/kuxth˘cd!;{Iv59/其ٞ9n^JƝY'9=am2D5$DeĠ;抨11veՑ/ w|A,aqf}jr;5Xbw.iL?rڽ%>qJnm#>eۍN?QZYMySWr N}~E݇ۗ$y+3L8O'r0V*g7~y78p u6w;lkZECsǩ 1ϾV)YhKxGRo_?h/VxȚ8ιTS{qIп??+dXdTz1[~d6bMӮOܲQ?v1]ֻK|Eqp!y-ȳٓά dG~m`ĝej lO?c]9H.xϜ5?\ɩݾf;e|V}pǰ/,¹]O) _"`ݛSIԙ5C_]*pa:ύvte9 *{rNvl/&ϔfKm8sc9k%S r)jQ]L/쎳nw=#k.?jLFkݷ]c2n\.2pi{6^scO%$ַP/yA?ѻJc嶻Ww 㩡oZy(ew|؝C~6߽ϟ+ y  Wж' 16ܾwwv6޾'ko.c;KYt'ѳ)qNmxZGOwNE|2"r\,a7'8%Y7117"ow\ok'+c>͵|~KyPA9%gńAM;sjW-Wʟ;ƽ}LyfRy1=5afجG >tWzvr1m?7r8h&[ժ?er~lbxg!]ߎ͸ԉWYxv}`f_,3O3d$dq C^]7{j9#ӖzcolBɝhd?=y[\1W(k:S Ȭ=mxv3®bpeۻ9Sw=Dʻ7ww1⼣]!>f{'5roq^7\O|sT/gruN39MyՏ& Ob6~kU=A-{~Z y,y1YRm|cSҋ_XV,PšcjC饾"PSoYtOc/g쫕濽i}Ḃ+qβE<Nj͚R9͟21Q浊{//)xb{.9=a,g4'2fS/X}J+njdkL8~Ξsn?ɥd7RSהGs>6k/"B]74A9%@rU -ֿo}~]#~wz_HM?,Oó/ 3Vſ:o| ]E}~qTZӨ^w+i3 1̞xz#՜m]w7oXɓz9G(ZN8mTn|XA`͉gjtWesƭzia~ Itz5l\$6c2?)܈ߍM~<l 3ʥ=OVe{+[V^p蹼gneW}Fxe@k$]Yw;v+~=t6~5}`D.8kQvu~ kg/W⏿ pcuLOX{u[62p̫bu_XW~~M^tz׽Uc gi?k(mO%=_9Gg~cJ Ų ]d[%ե6̆٫ˡ{28>ɺ߳4=7RزVLgOu*?cJuѾ6/77sFd 3[L5c[7wph1ˡ#uGY9zO?1p{wU8c[`gnH{f-yȥgbWY5*vЉM)/Xسsm~yNe`~SJ|鑩pLp"_{^UiamIWDDZ.9mHG=qu:ul0 IDAT/sZrTjŦ=ubGjNkB'^_7#E-ȧ=͸Q⌬yoacdن߮m}/&m͘}O=n7b<X<.SmbRsjR3^k&N]T(cS~UZacqއy`س!߄YIߒ霺۵u9N\Pnk_eLBr-<&.vڏ%{oY9,׏7[6_^CnOK~eⰭ=lP C/Er. 7#>WLYg}&b,e}| Cpg3DWw}V]0:dOkf;#jDn7~H-"Hv/1{4+FiOyq9{y[9=k+ulc/TR>چ-e}E sxɬ [.&޻؈]{GSk142a^klױT$=K\NiO.Fٜ+6͞\-_ٗ {A+CXywxXStrOnsscm4Y#'[ЦmFʛlүϜHmLF:dN<{}Jl,M{.p<ӏ9uay؝5QFV/ugufc_?~_̟$|Zj|lxMG9cp2;~*<V]^߿|OgHbSOQ`xwڕԊr"1]Aڿĩ'fz]Ty#.?@g}m:^.?by;yKA᩾{fԽ}9?cIه9ns`X)ѫ|7Ƴ N Z%gzg'끷j|[R2eOvM;F-11껲sY0"=3O$qH:WwkȺ[r3t7GO90cɓzb>}=<Hȹ2jKAgǔݨ1EC5lLHyh1Hw_i2\7~ga\K~? qT8e'1,m#f&<Գ _9^N: ^lTo} C̋ٹdA~1qeK،.F3zIog [|YJt[úk^7ͼIcx^}oG}ƥXz |~dO>2#y[w%t?rPS_g98 pb?&>G}}{,,͠.$yWmssׇ@2J9ۥwLFڵ!t^-|;Px9еo5c`]\S%12O'' WxlS~`ا9ꡒ1>3Ξ3OjLsj 1}Vwsö^4+竮Zԟk39>F䄵9e,5x֣=Xec^w'~FM3g [ưek?' 0qbk3NL^iy4}svkkk^t4]Wi=֞޶~zg/'W_-0]}΃/|+t2RZ֥.kg ШlvS;FŽ{%uZ/j–h,vrY['i.gh\qGr&W N-xnc̏/HcCZoe1~kuڵʌklgO1ǜ0F^9fO}'Ov^a~g< ߴ䕧Ϧږ!KxckLV ks?~XQYo}^N' opS̘­^5^o 3coy޽:S_`\߼D`W̵LC7gYGJu2J<|wvO>'yJi)}m7~?;u^i, rh̄a?oǏ?]ͯm=+Ϥ{&=Oy*ݼv9z ߃/EoƇ?g?o~>h׏~b_/_׊jфPkIbO=[w_S`roo)x{p5S._wF9:Ħߺ&pvJbOs=ͥ`|CUpzONub>}HWTVo,/{/f7͸>o珴'g!6ֽ|E\%uq$s~c{G2Pr<~ƒ߶+ m;g<4qgiO'=kzWQxw>X͉%ֳ}9:~~5OcnXl+v^6ɑ{C?N}-kߘ{}&ڞ|ub^x%0|/Z{ZlEZqAc">y}Oz_g(ǒwO> mo&ܳ^_#GpY;:K nϺc{َ؉{&xCb)#ma_n|;oX *vlxʟ&3vŵw2ޟ}qa?k__ŏ3} /3 ַ3?sϏo n:UL GaOVME~?ιaW{͏?)a~f=j1lZ;c^[I6gu% ?~}o=uLʹ{g8=_mȞ 7ӌ񝓽Xt={./_lZ )mv;}Z W qW{fYڱs9>>#bՊ^N=f G[ݳ5meOu-Ni\wdvWT^i8|qfD,`83г}'U xj%CsǙOS5}Ủ~Ss/xĐ,4/|vͷc)Y\\fMa{#C:\6J*{b]k<]m ɍ-ucΜ{rzss7w3#o|g7.=dݱmi&l٬ecү͵Ccty.+!][jXV=^1k+˚M)FI 8Ŭx !y'j'\}yHmR<|2'a[[9RLxpMwbe߼3fkjx6mgNO|ŗ G C0sPwĘk&@\w-|'2=i K{s<0#ܼYWgN[XYƜ_g1{'{UU显n|!]]}5[cu7SOX_VΠl{!!5}}F93qًy}:6F,k%V;nz^͌Ilƀeב愸#bXL ќ;|Yg{sYu6u,ky&T 5;l>~g倃臕y֭yN=r3f֗t=U3P F CknFYQ'':JzwkGV=SV*w^~7/ p̩?d'qiq殼#*>m֎F]?x1cQ[ڼOyYC2Aa|Hh=/{VQ7ǽ'1ok@޲_3]ka[iCͪOl[lb&8HelKV߁_>+|/[6y/5Y3{kZɻƵ㑮Y{c#?{w7_?׊>^:cWDc8_z>0bg.9ĚB> Xu1tGCN/yPu4q3߉:f`+fpe|9K=;/ldDgZ%ݲjG׶;x9=2UZ~m"~ǝyz^Ɉeg Ɗkw޿:;Vwss_M\/+}?`m%mRscRnmX83NێA>剭2Y{խ=\`L}}YB.yܦ|osI;-e;Z'Ռ܈եqgJ >Jv΂ߕX߈/NxmJ| ~ w-CLђ՘0`ngys}V93 ѧu'7xdb|n"qqdQ{ޫ}]m}+e&ѫO=u+pG콒ߍ!$c܍[~Bwz.[ՉG(T2^uSww 9_u_dZ[}V􌟄g>l2gcV8+>cyVNs`̾E!|7fPׇz{u{>*e< ^Ix/*C?cΡdK4os0.sw6o q/K%7 3μRMoݘ{5fϘ3O>s/G}&xxFPs)[P< _/RC6\^ >FyE߿ތ.<ɋcW̷1#f*<f aÀ0沇;èZ3>$(@،I \鯛_ٰq/ۇ6'kBמSG~c}/K>ߘj :07{lfSw(VmFƞk˱RYHmƐs'w'0y+ 3q})@Zk_~9[zՀzys˅$D>N}ī'NQPՍu+jszmgu$K^e<=o.f0EלFcYGz^ yxm{o9GS? gp̱HS 㲍XwSޯ$۸ops>kF;z&eo)C%6|G {YGr'fƑ<ċ=/\:_Y|ڍ3Ҝ泒-%̓F~} \>ǡ>~v/RBr4[֖MN K{ȴ5.fLq6š$1­o73ufͷ#2URitl*=ꑧkky +S5rM!NLG}ml~n-a{%}JlX~"5˼v5̜9'INΡݜɿq}/rnh21'lrcVbwc >k$NNualr<ƍ׬ҬƁǦsk u|{1_uqJjcUz/?{m~ľb JtI|HǓ}K2W-'qz;$h؋8- lj۠Yv- (?s$[Rkcۖ'4wוzt: 9y\2Nnl^M5[Ŷ4u&0XͅQ;~ _7<[if.b!>c+Nx{|s}v#x6&)>11/\̝\LzJ'l=nez2#Oehrz@ĒZ|۰ r 创g@mcs?HG3hqelג3\]L |pן6gom1`UU睃].y"5:ȃO>ONmK8t3~ yRػ 6شJg`K. uɱb5x1v%Wܙ\ 4<7nmfqюu-tכPsqoc:<"jD0ݬ[;i= Bmq_ 2?ګ=6=2k~pgRC'e?bgǝ3E ׾ qV\c sk L'{X6{-g4.{#7;ˑ2e7yo'gs#'oس4Wqϛ4ft\ʲO~'vqL.̸[ø7q!' ^9kGZW^_O/*Eok?6GFX]5kZSo<1;G[3.܋3|ou}foxbJ\ x5hN$6i3D?cC 0w]=ʮ?8޹LJ<}nθ΁n߁a9_K`s0XX>87W'7<_ko5֚6saO:RLf~9zs1͇-v\Iz[~@]gܰ:cq+u7gU5r {^}W5nK,423#e+f嵞X㴹G~3Wf=w00wJݒgi3yP/wM ,rzv] ԩTJ?#Y4kA\hVQ܍^yz;_7Ħ~tH\D]{֋̧M.'P}G]VH]69zΟk1aqɁ-^l} R[k5>Y̕ڔrϸm냷97εj~.SU%j^օ3ƢkzvcyF>kqKiOOΜ1=Τ%sؿvOøӝ u8%_Gb)]:J:Kj~ ^6Sd4G&ySk׽4fս=Kڴl߱?=~]=|o4ݳZej.3cKs=Œyd}Oqu,r{9QJs($G`)>~|fg(,a{؊:kI{}&>?' Os9yY1݅{t/SZhwg-;6΀8cY(-C؈leyÉm9-'c*ᯄ#4_JuphaǛvTN~ krQ/iR3g8G/77Zgq9KR8)~jӽ~||.5L~_yXgTq9-kӏM/{uι2jl̞I\Vվ_gy5OqMk\|:;;wr(66eJW)7͞Aزfg=kdomnjeaӨkJR,S+=}&e{8U<[κVg[q'|0Z4Eޭe=|CQջvex_g/iwhV@(3E~2M6<ȭTׇtQgL> 79 f}Ʋ{ZЊ:kG^#&TkU <5c{]F2E*_155=YXS]RbϢط|YM,4;f,6nf]1C~$8HX3MFH׏deHŁbPb'L/k26s/"5nt &1&S}^̳VZ'$'}Ӱzκj>eŽbxʢM]d6پ#+nXϚlϛwϝ٧Un%vkY3 b*xXXA`%Y^Ү0c䢪ڶ=gy<}=-qٿ'uP˰k Ӯσ 'ycmg-Gb+;yӯsFZǓ5zU!yTbG}!Gז5Y,8QȘsGijm&mZۃr{v{企#]̡}Lf%64=.1ϱ1 Zf=[ҳ)gc_Ïvlqȝۼ` m=Y]{OC~娮w,z9{xyX'rHŒ55VWimdžd點M_Ӯe b'/{cN[yTKhG8rH }+ꑏYS qwሱ9`Gbά}3"שxb6u4.s]Ή=E]I.֬WqAQح={`2W|G⬥{n\Ԗ2㱻/zMo分I3h5zZǨaNk<{ou7j(1gt? O,cK/#C'.Xև.7\z,+|/Ð>ϕvm)c/cYgms?iRuG6漷W\{F$;lⳞ'ܓ I/.0c-t#D3Z7ӆw쾇O$8'mW>KHT?fp/}8s݇8ԉ~'.ч?*E;ƽþjuˇg+CIQ1y#SWXyT3/r3,6Wo|Tkc:`Nn;?u/h ~宣9x#_0ɡX# W10⒫xfOvl<܃ZѼӳ/O[_)ξHWsby,5S3sFeOxx.m7F~O.p,a.+>bm)| 9?g!ڛ;=0:d٧ݵem΂=Ȳ]F,1/YĊ}~9: \8eX~ƕkg]bw 8A5|J{^In.>̍$ɳmrnsp+kN߻1֮Z9Sg5qڶǦTs\Eki\''qKeb܊jÎ^BS2b??k&~mm};37lGc߱N-p>^srZkg؞YpNzT6k} 9׽7S*zq]uzg RyWдO5wF;fYiG}߹kpsnA 1[4GE!AAO%'y4O|ʣLz2ދ#U?yھ2d?֟9KgX768:N~,mH{(ĈN#mrǿ)WbYcѳ{m-'w #71I=OD<Ƕ>gߝW}yeu.O޶혽|J)+\&C(f{Q9Ş:\pоyg$x;Wr-MUu0gw,taƴxPe7pHq >U1߯4M\cϚcH_A3m0~ۼ7ڽE<ѵgl(PZAyCbAvl3beMK梮pynrrĕp#97~7HS'|<ݓ J+>[=YO>$?M`]k%|:8QUΑ:흯k޵yn"+3˓ ~y^Wq}/].c5l:oǝ 'Q޸+w OP-߮|z3_bdo^p7N8O2Ǘ~9ҏ'xݜe֐1#}Y3};$w}Ը暩,k6@kYcbSq,xҾץ]f7y'= BߏI[ÓSf)g_;s<53?}//R]{XWfc-1\]~)y`xM -y{n渲gʛ;y Îx.ܾelybő!qۉO :;]$VJ!|CyHC 끪k6AQNTu͙%ƹ/ ɵì:^Ϩf13*Yy6;~8s>ى;zsTXHRI*^rbRy&GX-kzݥ sǛ[Ҟ*ٌ)̺zfp۩|֧^Xk WN%s(#Ni,sׇbN5ōqgJ޲yෆIe6k%}8=ϰ{y >L[ן[߳Xg6tΙ>HSS'g˾-Ŏ͜X}&Dq֮Ե!wcT">'tN"ab*n@Lӯ&y"r #~@j%1SZHrf-攃"Gh72 M'ٗҤOK '&#[zcSS1r[2^8HْG[Rbԃ Ľ3~DŽcӗqؓyޘ!;68%|siw/{}Hx+o(XO~vZMOP 5][zzm_-g I^ 5K|W@sؔȥNĢˉ.i7q]0;gNσmama6w_$2syaiV/ԯ*Ybk3λ\:_ųy^\L^yfɃlCrGs=e4^C\ygs CG컵yAL'Y/E7߾"|bg)L񘐽S5_u넵"YL}|$&6NJ^X|˚7f2:n~8y}סMx13Fۄ.B*<]w<ԋIm_gM6[a'q1z~>ޘ~c/ 27ޘQh,`9[5N<6q9++-ۼH9i6yeu'u5W{l`cf ]cÖ5Qhy>؈ۜ|?g(W#[]wwSpF>Y w  =gud[̜ Z-Dv݌+v);ߏg؍w1ecC<~:[JMOE&K870!;1kv4Xҥmw/333\/R]cgU`vFnuYs q{ccפ[/fml5 [:Xwy8m<Kԝo911%dԯƵu2bd>+>jwبڈ?1# "Re1L~]SqLsfJIkk폙V?P7{9RxК@ȁٯg}–wVk~`9J{$ IDATXY\nϋ1˭d~$1_6:~j>Ƿ7G)V ou޸/Nn[n:/I+)qr+/OIկM.wM|ӂ|7= _sT ?5Nl\4OS.}FвW6`xY:r qn#Ҷ?89/~sҿf 퉙O=c鷆R#<˷0?@)˚Hy9Kkf^ĥ^yTcncHqNӟMk\iX/yR[pW}}f-rM8]Η֗iɩݗkߙΕ9{|) JV'%9wQc?ũ+~w<ݯHĨϟOWξ>9Vhm%FjջNqo\rL?ty>֗GwB[2;c|/s62Oד/9ҷZ`J{~gm?gbFΝsAISνgxԖuO~QO<1^93_S[yNe.\.so[{*;gXv"יk߱v? w߼=͙o=%:_'X:b#sW ˫ձ9r);[stV4 +6@yJBĝRp}+92$g 5ki'މM?Ts- Co_pv\<xAwܶM9 c,#Y?0pnr4f5ݣa{PoA-yOinpY4 /OޮvSzP7$F|=y?;n`j_eҁ1S-ƒxz7nG1 }/s;ElSb9ݟ2ߚbRϼwqsþ+{c{O^lrZx#4DZյU'R].c]mO!q1581_ohzer1NK~y)z[\h N":'O4շ?z0+F|!gBjX\>7çg ??,6G}g+z溏3GLͮ3`&}m}k^ܢqڣrG*Yq}BOQ=ߵuOB5˟y.6mXv$N[b_K[,>uy4/޸SSb'_ƒK=~  :Z,"[XV3Lo{ #VN)l9O+`ͮ䢶8}Q߸l܊|Jkʹe^?GgP RTfٿ Kt<ӧQ&:eL=`u͙vAtNugpc=/ĘXe)V n>spSc޲Ar஻w Ra؉Z71#c}˪p<>Dd\R(_<9FmO} SN{y GY,``GУGǐ6X\xBwּ˫gۗx}$ƕ#_ssǛi?w>;ݹOg'bP -b+S-!{QEyR+3~5ѷX1J۾?s%skr~j䮧WY;5͙UFR[v|ͺ|XJ2h2}HџvqkB>ޒӰ>;yо!FkgO/6͸2k+ɺ_\߸gNu"(dnb扦/_K>AIյ3CM69__um^gmX{5}{_qjrGOT1xM83??1֟jF\ 2OŖ+>}N29_m=YK68_+$6P7EVYu~9N#N7O׾%YCke`?Ō'V]gSf\ݘ= Sx[9k}ܱ|_faѯ̴u9j a|:_w'jʽC՟Mw?qo~X rc'O|b<_tbȗS_ţy3O`B[-Qx9ʌٯo_6~c«5]{~[O<SlĐr쫪 O[~>uȽ6ܕʇk_ډO/O*/&vU3֖8/2j8qd0b,v)?oJ(8e ةҙEtёo߱uc\:X#{֭??ӼZX]ю[>}G9i\7ZcX|f<3cSŵ`兏55zb3 &խi?8Sw+tP}FOXk.{;&>['ȬA|kbԾ;x5?s;}\_;>_{(/WbObx7%'K{_|K:|'F-6\FBGG^gOx4Zw6?kcbR'}l~3Og3"%=Ǜ'J+wu 񳧎 L|5Wxbgq?Ɣ<뵏}(Kǎ1G|npstNԑ_l &__Y+bCǿutfևhyu߸J{@>uyT{$+s7`XlgYXŋ}ڍZ\|bw?$=[+=+WcP\eTM'(U-o w_>f8>c8:V>wl`Nc\U}w)u^׆GR@}yu[8c-%zXdM6tWo;vwkuX72q~P󙣏g#D޲+^"l昛Rk?ҟzrf̒oXS7gpv ƴ3>krɃgy 1fOǵy0RG;x'cY7Vg<ʜD ]^_KkoOq7g~ȱ:Y7yp#❶}ȝ~u}⒯:6}J_㭹}ؿRxcY1uDN m3Ne'rcΫW|֓3k>+ѿn)[~Xe]#ù?fX|/vbspAk,D81{KLη/rDΪ/~>* 'V?wA.G;S~ *zYMvA(%ݏ{;/J3:/&99٣swUuY8׶*YW/QYWÿYofZ{v_f/R6%[\f焾cNys۟l&>dS7fNGľ1_뛖S+rS#f=;K km8λ;,κybֆ˗xcİyڵGߘu7'1_n{/{->9`Er{Scp<|O?92ƩK_sb&OϞa*Q_{vIcrj+8'<@\i-83mpת?t)ìeMm~T> GqtgX2:ĺ=+͕k=O9~aݍ7ƺG"͓~_};~]H؎9\/ޘGY 6+?45p]rߩ;+`CޥNpnWxEYr5JpkJOP/ {KNwdKqwoשEp|p{ZƋ }v˨^$oĢصu{QpR~(ų̋w'm" 崪R{vpa-|yd7G)yWCO' I"C1\Z߽orԬmW}bs'96}g{+xK#ܴV}yTchOWj}_ j[N'H'>Ҹ y{N7o{:iq9腸&]/.rr^;.o;|MjwN39D⣅~תμ4[~F5jX{Ҽ~#}]NJi3dO'yՑ}阵1/[rʹ}{&fʟ9{vmcoK#oݲwdLI>qyӖ#sɗc,%1GXlCe?͑~".iܒi%ċ!/`KcK#wpQɧ1[7YӓiojW`[:] C 9؞,E{Izio)U {u+$6Fb;;.y&g8&/M \׸~>7e.gz\// wakWx+?i ȵoy>X|_/Ub,k)XEݚn^*?<矖3}ʙ>{M;5w|?{V_+/rϝ3!\ޓXV Y_}p2y΍?}:=%qDxʝyC؇y FR_׷䡙^b|xۉ=֘-ZK?_su+ן>u`9]ck W?q_[k%uNY;ͫjDG{}X9y!s~P߲mo5Ucf_zOʎWRHop/̸w3gkjμYM F^ٻնZf1jqOn qgg߮:-#^;%i3rG/cU%C5|]s`u۹}+AbwRWV_0_Ǟŝؾ$A_~"ISxήfIl(#Ӹd\0/=#8_pky<=cr+}=_x鱮_p0͏`b5^H*ɑn{ݹ9߽˱y]yO^SykS<~1[819/9~{bIX]Sޏ!3;%1kJr˟d'-Fr-F拼8/.]玃Akl;nMid-`s56>Z̹>qw@;} iSu26Qv_9~c.HI~l^6ך܁|h/zs|u o7 kg=־jxbԍq+>}V^sfY~9G-vk:7o4=`:J\pb.G7W<5׻VFgo1l?Gݼ{ўo+-1G88`RGGҒpXGXnQ$}FZʧ(:dĂop/ŽotDN_kOVruӛ1s{~1|%.7}bgϢǘd_bo6r5OxȕS$c_?ucMx-5׹oMXty?6׺|9&sW.7zprz,\E^ոWyƗg{wgL }j>;sKfR5T"*~T~GԚngBp/3f="7ҚI^|Tl7[_9fZ}m[͗O?v3څ{!n9E=wf$Pyړw05h>#X{掴]k1{`%a"ui9ͷۯ7ك轛3x3ܽ{a?u R37lrf |V+'z oK>V^vdaGO,gcwfڐ9Y$묊VL~2wF}YcgӮZuت.?z2M_ԫֺ>V 5*Rks9Jrhv Zyh#ť/x̫geĹrïj<+sěOL]Ζ͛Қ+GO\g37qcË~}ʊuw?!Tv_zbv^\@/{8Fl;?Ct߿0uF\덿w5o"nmO u{=rXv5yYsqN'-c*`3$l ,?Iվ#cP?ع]|ԱU1h {6|63Źuxd`tOp|3]>6%($얜o6 C|UxO?ؿ8| zƩ߶M9/^ Z_rמ$s$'zE^AfO_^1빞Ǭ}OYLuWopG?q߽> e~dj/bH>8i _:_ T9kfΟ~&5Uv3v>;9Z\ \O^sO}!o֨=g/(h|x}bC+a4,`^|?iYIsj\>D2RؾAѓ}u{׹RPlmM;p%޾*<1t^6,蹂7LrcǜU M*<Yq1Jy`;=io˓g[6cr9K^ӗUn<'\u׫L&_C?L9`?ӷ9c_Y_q#tx8YS^ۗһKyHNyR rA?/6mؙY}ة'zsy;{z3[c7'b}a׏reߩ?uدϼ9vI:w!|&>!NoKi87򟭺ո[а wv{LD\c~6/g*S+_*?3[`m\`oϐ$EhXXgV};wLީ{;Y27~zt2ɻO|ˋQƦ^wP5nif[7>f޴_ϝ9%{sY]?q?Y+G]cXtkrSܫӶ6ry,}Gxmk;{gݽ0<]=k|5mto'~mNngxTU9Gq4ſyU$߱*U{5^+wWsZ7zr.XlyXR.7ZV%9W]uu[[Y|W3q4/~q+m׈M~zsu(hWy(Ί//.mqt,yKlr{qbc?/k5(63%x3{c1ue/FҢ~)@%؃YCø/i/wg+8s!ǚʌ"+I5їWqdH?/gm`3N{m*}drɅW1sg;Wze3KnC=5T89}Gf^֚!O { Yd_5!lAߊw+mgS8Dk}=9ĜP֑K];JowlόXCLns3g#)yI_εĽكk,n GU%;" :=MYzr˘H?8}b6vɖ)>uw +g 6=b0kdw\W ɦ_]9onعO1uv^gPWVuĈ%oq__֛(G^ < X;kr_ <:Axu\xdO`ю'\I I|=k|PyTO/GUneYݿ/j½EZ{z?o˟Zm`-Q3`@.L6 9&#e!6?<\!ɫ{ݟF3 E:_,~̹}wSlJb?"fyָwPkd$1rC'BX#RLJR9Uc^I c_[ .B.T8!}v>hOGBl1sؙW[.kȳoj/:vR=ٳs򭸶Hًq}_RLdO=Xr5wLom1O_թ1G_ùF)ǹ~P%>ʓc.:PY byg9:3.zїd`kz,V.]+9zؾg p`kn9t0{ý`H5;腼j4ջY\yYs>Zَv@i.:uXӻS^Ϭ:'vQW K]e-wc\s }Ӽ{l~+0y<+H DW>U`ˏdF(lo x8?SAO˭yϼZgɹԙE㹻[qUϺ{'xw#[*~Y.f/x꫞9g~aA:;]M^"KؼEDFu]~c$zVϲIrM]A N,<q|햻zr᩟c?V~v4W~Ŭ'Kz&dՋR8W|+ ^:u˧M\ 4ǿ9mWo\ .9+ӏ=WLboLQA؃o{a7Tͽ? 7,LMm͙dgY4oĿwr~Wwͫ~f@Z|f5VOɁaEfB֎oۓJsSVɑC/m3gsgŚƿ$5u?fr3 v性H[~Qjprg//cz&mJ>qNww_ce=v֑2y$mϓe?K^{i[go晻lΫ ,1}TI@4Wv7U4OGGq-y L lASyk7^5( rg|x85H5/w߼R={OCmKf_eg}r6T[5hkg_ _iO4u~?d~}ScX[ϙ}yً5W{n/ދ}XCYo| 髚`ҡJqe=cwؓ#njNuE:.~Pj17do,ms^>kNDot3.fMޯUe4WNRIL~en2ޑ8Qwֱ;Ӡ0(KĽ*?@̾L+MG{^v>f^-ocM^VQ{Kăǧ:`|i׹gr>=Lr~+u*\! ;q6u7O,wY:?8]{C˺?ys1Axkuv>oG0d fp3rx]7u'eԛ;+cԕXg޵0w+Uj#K{uɵ㍛'>i"c۞8T~^ke.;W.#׸<"@c?UDŽۘsT2v=&2Ys!{Zz ƀcjK=43A4nϵœjbY/mw ǚ/kFދ^n|eM\yi;K )NL?~9Z+yJbuq1/S9۰=9U2U=)wKvxG҇@ Օ+0.:])Ϩ>.?f~X--^I\bW.u؈H^*S7O|bƱ]UFʧGvƓ{QpPr˝_,H\x{4q+B8 qֶ#/'~;%)̹b58>^Wj%=|m}~!P5Ϣޠ.rȏqow_ݿ՝kE&g"Oޙ{^ɻؙ𪄔\#DtIJ~}VgW{&c/AqCVZK̑Kn$N\a!C xkUU5o kH 9?5ͭ>'ܻڃJD8kWig[oR\g糠5} } Y?2{Xh%svoX;j%EW*;9曃S\4$g#=}C\:?,k+Iݽ jt)Gי!Fs=c.o)XWN3͑7RJ=5kaڬ^ǝs]?\::>6knTH=]wbMAמ<w`l؛=Ԟni>9~mƕra?,qg; n5%6S֛<j5\J/g~wXk))yj䆳0w[驗hCl8[Û.]no,^9{Gss؇qs?9wg;dKfrZu6ʳUԵN؉C,m}Y^,~3wycȖ&^l'O^$|HYVLJZ89e̜#3'oj6d.f}u h:<=?=(۪VfZ3Oqk+g =8ȏ 1q2-_7nUr#gygWw5M7>I`pw,zݿ hi!ZΟ(t޿w؝W9Ϯv=!Փq =jɫ. oXJ'6sTҝq 4FjZjf'-1ZOցhȜy8o {u,w"ܺ89{rC$=_>^U»&4酫; Θ="٣XrfsT{)>/Nc/kga͢SE3b%ƺvP3GCUGǖUgꞳRfu\D޻Ϟ{>|ׁ{9.˟4Ϋ\7L<((fړD]y+߫}.Gug|.K~kՕ* s;C>Q̜[drus6šX棓7ݨh!/_oMC;s,)=vNyn34,h_'/~:fQvs͞*F;SܯHqsG5Wsغ\gSuwLB IDAT9ӷ-:5yӂ,CO[˙M]ys2؃__{Mv~.M̒sWyF8|Hqt Ϝ,GgeG͸5l=c _Fu-m~uq1ǝ,suu3{cȯ,ĥ(3r j:\289[Y]}߹| w{K7223s[gyXyH&gc)fxZc>7q<:ʦ:5Zw> }sɎyNge?b'oQ|kfw/IdCya;~6v 9}'׃yW g'gu [ zw܉1:Ev޶y8{^ln.cr=#k7:\ɑ6ƾC(O1c3r=69iw|qW1]>pŷ%6I9uO53^\N_`So-}M=#OJǮişk>!+U++&&ؗ Sm7r|W _W91TkFfw|TʡSՃ4Cz96L>sd>g͜x+gzX}&'̎O|ׇGim9ӻ>}7gb_ 38}/Yx$y'_R#N5< bZ3-=o(|”|Hikb;s04w%'dU˗kKRDE'w~v x^^ɷ'ʧ70'Yf̙{Gk#Wg +㯟GqsjUEב9ԳP;!Oo]i>T{.lr͟]QhX9M'!:Ƿ)iin{e޽kp̿k5#.x}H^uz bɱ!Qcc`'f \^_b=Ed8'o#~0'{_Wes4pW.6ԪһNsڋq(kGS1=Dxkj'V0w3\p\izsgo哈cz!~xWGo^u+O)/ArԾ7(9cG:J^i!p/(}Sƞ䗯⻷z VuW;7OkVXte=5qe=={ary7>h^{=DL;uvxƑ`2__c?j}{iR~d#9&߫wx@:ZϘ1eg%b?߰kl␙;]غ=˧_8i~kɷWuψNoyqdX<r^&~H}AYG9 Áx~|k(3?m\>bXxq91Gu`c=g2מs0yi{OG8tbkCKdgV=+~##,GכY3<>Jm5==_.r"Sp3>9#Dvn{H~'.ukJySw8RΉ@FH;zI|{\AR|X^gJI<BISo g1M|۰ļoRN]`W0ߵ]iImvܼߑX̽b ޿{?;0L̙ڙkwx}SW[ޛDW\W`==Wx_f_r?酥~DӴwS/Te.oȯxNsuSW&8u^QpG3)_c :dsc\6xubO+ݰ ]u_V~C}VW/9 XӼUk.Xs[Lƕo3GzOtnݘ GEuȄG中#[N|@UϹ`׿3fj}s|mOGb|9'z2<}}%gzrfNŶϷϹKy8.{E=f?-V߉^hW;V~-]vDjFm|Zɤu;y2mvb\ٱT]LSk8]rט;6=ɧ86q1_x$[yo~|Qy;v9RrgMyKʘRӇy%8)LKRa i_┍׳!wj%B->G:j<߹Įճ@<|*oyv,sĴwk1|9}QZ&=/cORh,#?q^Vd?'OJe1~Ǩ"ᗏ{./Jw1ܿsa, {n9R}ױ^s~^(id_/ȫ]M梛_#>3'59|w z8?Sӿqs~үH0?jeV3'w"~䯾|F%^)TU1OYS}Θbۛ~rۑ-/OmxP+)bj5ߍkS<5Fwz?kW.Bͺ0vrw@)ψ~dErOGO[3axL𩭞XpD {x/wpx@E?{jj[ŻO.7C8|ܣ%7.7R|{o0*Ka9zJD­]ۇ[_vp2dm2\%'= t\=K ۗ9J՞c]jU1>3 \5{)R_?)mWuKy= Csss[::=u-4a7*Y.!.?Wluwz̹*ߟt ZõpupKqNwiO`ԕ90qTrȧL}C`9=)W.V3tpSY|Y6c3/P=׼On >澲5KFOʹ3|Uךvɮ\p\5ζ9ƵmXžR7>L3sT= YY5Jߴϔ:ZݼƌM̓ל=WLGd' fpJ$qEr.|ȵKO˅1lNh>1| \] wg7Yz󙇽wR/mapΨb,cU?[ yԏ|,cN[w.9pO^+|z~%Vy㮒r]rWn;$1yѫ>`ۧf\c1\ C?r^SwsRh;T#3A%GJy~U{ϲx9uʚGHZw gnWOO()qiJ!g05Y4u?g3/ \TʳZreOedι59x uxzzd~ѯ,f\t#ϼ=wn os ό1hggfBqSfV"g?pg=YXy漶/uƢg>xW40v%;fM.§_-Z,{<&WFHqHrZa~'~oZ62}K{G[5O.wfqk! >ag>ZGܕ|r +_՗9;1Ϟj'6wSEx;=$bxw^GaxkLߓsճ·9:NϏ}|%3 <2kWƗ3 ;3(wKǾW)w6[{uHcdna~X|˷^Iunpn7u҇$D쪷9Ņ/_#c6?$~xsO.>_YrH{n9;*K^],>F+d`x$fJN^\>J8bG;c|y]C<<=?9$Xniw} p$O/?%+F킐!|`_~h\}Uڑg= #+t^yNlz!VnU--|H%\}^daUgJ\!N)2("ܼ=N𯐷_Eb|ONm^`Ȼwߩ.䡗<'p?̴ͧ{_J3bڀn,| |^?[CG:ݳ9+q'n9?UJ(W/3Oz1 Fn p/_b>pɝ<ٍS~9pI/61`3$zw% qݒW;u^s *|dy #1CQ}9vȕxtyG|״vz6\o+wcC_^Y?\ΘjG]38w}_^ ?gN:|\or.`mD?C?3p]޲:-i_V6s۫-8#Ynpc^+{u%$GDsY̰+OgOoݺK[3-FC\L9f;sf{Nk늝iyv[gtwSk:ŷȺF=NOuݧoL8QT9Y2w_[ٕ0suEP{r k0pUژ3EdZUsZ޾˜:k[k{'Ngkf%ً:ֱvl}M˵ggɁ}9+WnoF70r:woRuϒThשYkΙ2ϛ}][\ YP?ݓz6xEfĹn,J쇟s.1gsς푫|kqH ׀~C*n3u@y`ݵʿt9g- [Gyy )=gwM" )@;I8~1T/bl6\;%WdɫwlsGnP_͚\z^I s Az'=bY!z~׬Y5N>s' :Ӡ׾!.?܅wrw;90x.O>|c>鬅]`ȗFSmYX?=ߘ~<ޱc50&`>_ uEϓ*<0Cy8G/zk.Ž'j~]u,;Wwy @e9NbOMelƒtt;q)_cNȋyw=7Lr#y}w}wB1wX|owߏԛghka+鞑`5w<(b^zirrjZ67;gg^nMps3S~%~2omq7^\'\iϘW;L\S߳,+oX6+WbwYƉ&|O)>N/l qٛ#kkwo.)/yvωwߺ%+җyı5b 0|_F?+g֒7ùbV ;XE'ӊxk6gH *Xl5r=5?sjgy`۟Y5:}~m+V>da#wV>iogfeuCHtkz2+Hk0{ gWΨ{F;x 96dukoz^V=|9+pv)Xrymk}1rnn=!k+'F\G]^=S}G?< ;XFd~OI9wa^t}7i|O};8wk-fU|>W`?kFd[~ IDAT9{ 3gU]kR7^?ye_>ly|oL<3xk~pz}U"^^ebYo}){XROoS_ѱܿ7o9ӗf8$W'_lZTaObouU?uFnɻ!SWf=!f,?F_0ݿ>eI[G{8dz cCc\5bem_4|GdjɦHL'?1oq^ŜȖK<6c+ +>gYtSn|,򻴵wAva9tRo^>kq>6(@_gbȀ]οhrUr#/Nc[U~ś땅[2910?5p)Y?ľosI&?Yl(~wC~!Qz:_f\AW7Jw.>z{_cWy(2zSe/sbx0-17G{jy4Rqkm88\qWf49d_[=9"nbY>f01UL?VM+gΣڃRYY<'~_7&|۹6̨,+֢1}s=krn׿!&g_5't:˜f|OX_J~hJ.P׌VZ(L>vifnܩlWz7eѽm|W6s/~~1}neqn_Ǹ۴g:^_E7foqsxt!r}}]r1ow~1__=wue___ 0, D/5 %6֕"\}MO\Raީ3d94AǷᄉOl*;F_l}U{'/ݧʽ+q8}/rw w8&~}F@r9G3z͟Ssb9 Yk$ϜGZnNosިX:_T/g/`^66+_\ŬxzFKTSin9+jqqyoY/^JX]R^mg/O9nwW.Hۗ^5gl^n&u ƺHAN8[rժ!uꡱʾ{4|~S>{r%UӮO >qjS{OGW(ffxb33sOL G.1~cqudpJWWQg>ʲ2փa1 :5\{+# 5l~Igrf?ݗe=Cӱ_qe[5z `tN5⳾yX}?|*{LXzЭ EיrmoqT@9{]߼wŮS9H*'y̑Ts5 әßO"%Zܧ?-7wU;_T#ՙ 9Y_3{kzɉ-^}k=u:03ߛߛ#/3YϘī?ǧy.5/xy{," ;+Ҧ^x4SQ|o2_$)+/__V/ pJl\Űb@4vep\j&Ԧw ߻.j'D_Z9Z]KVCUӮ=28(Ys}pm/|uCEK~f \SCۏyim 꽿FyBNBzϞ~x /-ƹ\e9oN_fv3Vw3Ԓ5O 9|S\kű>u,&:[ĪWMkژd? CI| }cs&q85к/5֡܈ճG`8~~}]fKWUcZƼ%{uj}`@Hd"~sJz\?Q_U#c˷y&Ǿ" [\WOt||ޯx++;W/mҭWj1ǨAY&Ct׋7z}7δ]/X,H+K(-_gyV9cN?ۿ=NܥUO;!}+ws|2}uq}O5:1 o5wr[K_y%/s矽ˋO=؝ԫuG;3:T8UP _H5g6&ij3 OV>,mwBX^zk2\Y玘XĹ϶ӆ|Wv'rlos8e *.Ā㪺 ֵpPEs$μMuWO_b d?{lo?pad_~d$\KKcwڝTM˗\xck$뮚9NsyRyC׮L۫wͮ/òքK;+G ;N|8?7s`{֮W^!z~PjO|ya`5Ā0⫐0>aڒ9#!ra'>9밙9ӯmQJ:KLxOjcyx /-@wm=ᇍHH=7Wg1K9s8\bg'}Wy{ho~jP\K| L.-1Hdœ_~mSyEPQÞϼRܫ?YQ> F_IvS"~wz#K]=#|QǛF`SzRܻ^~k'S.Nh-$lzcrz]vw *Z.geԀf稘8[k/s[ɒ뼞YlyUx?sQ/=&OL$1ޭk վ>8yfAO{#1\MN}xi__ĢԿ~N잗%meaQdI?Y >90ՐaZcu{lpk.0Fb/IwƏJo|b[X3ϚR(}?nǾC'W⳶5|>vqջ~cf?܋?m&ꛚ$R֪36\ ,r('gfڽSr`_:mvIjdž^gǾ1|٫;щF(ǒ>+pܣ< :ֶ엟˼ޕěK^i }]S&=|^l.U5#6Z/8}6C>h'_J$)*V.nSN~Jcmڎt _40qӟa=‹$MN } Hc) zc|] ϞsRi>yAm(8~K5lBnKٹ_qE#,;N5҇Nh6an JάKgSqQ1k#z7l&J 7Pl|-}װS1leϞ-y6y|S=~pX k>7Ҏj8s<'GeG³c}e8w0KpŔ) Ch/׺9gbc+U7ߎ]rZYsrȅ[o3-.ŵ⾖yo`ο'pւqlKvbC2y3+9Gq?=w0.sv6Re}rC|ܷ<7m؃Kuj4[k'vGf}#zkxc+m1ŵWy)o)-7gϳ`ܕsW'^V%i^pNHS%ӗ:ZF#%jGqZ/gwTQ(;󎻔5Ca+&tulN#sËԝ_vR?rBkLƔm?[K]bGK;+^e tS93st,FS&yV2WvzkymHlUǒ{86+[g [W?DWko WJXr~ԑVv?ݓv|G2;7780SmӮ,MiLwr{.}xSfYI{``|_k׶]$SCc$m^st?mϞbۇWٲr/"pg-~yCG.n;`Yg׮p/~ټ݃9R:MZƣ[#P55A?i_E8;_6#&^_ DŲwbfXVhm8 w'0jaeM6!ZtuO`c(%hG/4=GIԀc߳x+fqum[{MqEsɁ/`dNt{7?ڌ3v}R}UUnUCOE\w;~Ǽso^F4p+=ӍKL/ʴe,vk.6iKN W}uf0sW3UK;|r|a?+X}?.)c'RaLby/alW'O덖G{otfmt9y=hD 5[y;gs[o]tAl`=୐iMYUGJ}ƾ2^_wr1Hz3{bt/ Y1bg qĕXcX۱wKvqƚÓ[YeGHχ:K^+~i7m.jdf ѯU\)}^ٯ/t5N]3Eb?7O%е뛳Thmu1I~Y%{dxz|z;Qz&e°^;6ľLO'tKzfs~OڏUsơfϐWOSI^y> KwdNI s:޷w8l桮kPeM]́.6`g4m/os7g]X8^iŲߡݞ7NKþaeo q⽡'MvsSMΔb!K{_m3/S]ypX .^_>lø>032Qʱ<'>rjH!%\M;lǞxrXӗ_˻د/_L^0}m/L{.Ct)%g2Gow,\`7_zuMs_\P>b1Q؇ud>lHzu/q`?uw`;wF N|a8hwsX8;k}E'UG7?!+3l\O}νM [ ߾fK E;R:Wlo__N㕙/1&%]W|jS}rGC)8hJ1̫YdjˋƋ)ϲ>c#osu˥XӞt+^,պ:3bu =*BCve&daA Uan} /6%yiɡLB}gd>BX2cy9CJ,e\!FRL_Vӗ=C>qYp{3ck?{V-P %xQ܃\nuAJ =P,/,ßAՎ5}7|} 5e_FNQfW=5s?mYg~g v$<]MGjcG.kxeylO״ F IDATkJ:Ec{sf/a eן|r?͹>=k:ߧ=}o-`3|o %6My"{szz(CW[Y 1ײ@9,ݤ4FNs`MOw-<9aFƼ9O{;]#yܿ6fyLo<~yCz߻3i'>mDy4z6T%&fOgxbW{  '\ʢb$fql/εק|Hzj,cj^!/^Te]Iα,ё#iKj}r* xEj.lsB:tޗ]~(}0Ƿođw>ڝ yM|JHsɡ/N?R_Qۮbx~C,iAlajZɫ}![.[mW~],{c_e"`Nal,TNd切Ƈ#T1WVE3(46jgzl'~aN%ϡrr/uCXߎbKmNκ{F5n\ɗX_,?y%O]q-ʵ3\ZěK>5׮g1ѽxTiYwcG.gn s*Õ(|pf!`7μ0q.ށC)YzXSO[3ԙX W%}9{ް$uiw_8 /HVxMv}J/=sxG>cZv-s5\Bs ՗R7Îx/ϱܩ?-YrM#&x xqk>lz͜ŬZHo\mV 1qwj{*a#yK_!i+{սdf_ LoF?U.Bu}M&θ Lj+}'cɛ/0Zľp] ySrX_}<ϼɬcUۊwٛ5X};4[^g? yѓ{碛5xml=@o4vpMS`fǸ*lo^$4f<~>n _%xK䮘;G⧇#c._6\أk#i!y 7q_9U?|uNgnl0=W>O/OR5#K& ǿW3~x5?ݦa1 +_Ov2F{֎X(y=1߽L*sm덟tc:u. ?v\/Z:o®O,(mڑةF+>G8rcW%&neX` O1>Wɵv}N`{tC O fgS}=wmĠ##w.r֡ȢkN^.scˁחOgLmZmăM{%gYcԞ)_=UE:#Wyq+pT-aG?-?zEY K=u{.MswmӎnMگrwu|:c -&IOrc]4UŗJ82xkdاF}emKbgU1,w9ǂ;MloĔm%lwY(i rg^KF,X^\WuxZ߹t歘W\;WyCqXoQ}^\+̪z}b2}>OMOy2~%mx0\کt܃cxںD>̗KW޽ξm5簱H8Ļ~y߄SGͯ<&G[̯_IM,ՑwA<?h,̉nތX e {45ӹyXնr0O@' 8$QO:V\91ϓAu`}o|b=sbU K\65^9^1`ݗ4&J?҇MoL!Kx+Uvb?m}+[[;vYvx=a+vgZ1;Iꘒ#s]~kiĞ;sߛvv3t3?M$CsP :Ϟ&aR1SVϳưC_1?A2vwNNm'C)ݘƧr3%1$qȪiDzw~'Méͣ&t0\g}㯽vm["~1 B߅YS[wu/(n{ϝcI^iIXc+ [9#ɝ}O[{Sz69:_Aq8yvSxl(GAa6+\ȌO]f(!x$?|҇>9}!ϧMMl<29poxqSRՇ䕾xVbR(=Å=9R`.~ƻvc~^5OGl( 3Ӯ憃{lTOr߿U^s[ S~Hb3qzc)oKLZ DO4yQ lĬ6'\sz}]Y!ńx& aͷJ؈Rl9p'.9^zrg^lúx[1_1U;1HB5/+إr?c\ƽ4B8+z}b/{q'߶)]seܗVվOPo]>loKիs^)ps^*o^Eɫ]d5>O &_;(Rn%z?3fzg|˙X15s̙\=Lw+~*paMoYpyT2m"lŵ İۙr95̹ U31\dWA:d+=xw>Ń]Ḙےaeu~pg$qT&+zEw7O >H] Jb}^y2a{{UќHl3'WI ;zk{jYAe(cx}-&o?^Ƕc\Q~ɰj8dgќr˥s>lrM;s߼eM^t["Lʽl_+q{\+澹gvwEo9s9jq6^A+fWrf6䚏@VPٵʓsb_ڑO k%G$//=x%CL6~-q،.fbqmyqF+qοseV?Ωcn•|֩[[VLdUm-1̕67U1ʙ;?O"Gr~^&gԶ/}hmkm*>F@r;:ᬘ~Vc}Fw/WTZ0i_'ZM nIoo)f@)٦]!Y ɵ&фUPY;Ign:XE MgwU  ?}O7Cgm_mbRLs&,x=g Z^}; qY68uحG-n ~ubȚj  ?bW <cr ;(=8{romHmokؿ2__Ly'f%ڹ=)sE_=ؙZS%Pѝ^dIck¥Ø\^=^z鷜$3cۈ}W;udI;9 6~KB3~uF x"|WC |O+h}!j'yE֛Xtk/C?1&ہ3Vl&@幀m*>5/kjj1V=ԧåΆaQ2"_sx\{zhAk*)gC-~m:mtyjN^ĸ26Kzr9m6Ϸ6xKt/V>G%/8iSG!cf.F|PgELշ$c~ma+ *v+K/dN,3ή}w=UKr[y/19`_5_#ie9њ9mEy~9*fm6t~'ج_?/l;_r`cz^7֚x/[cn|폇7ϒLGbTWv<;.uvq0;-} f/* ` %8*H+X)6lnS/MwFB3Af$lj?>wiS~kN=}p7ON(ӏv/'̅_Rpݵ'̜3>9?u/u(O{S_;,K TXO@GP&7Ȩ܃<#䟰_/^k-KV?93gr/V? Ҽ1z3zb]@vtشa}-2ΜJrUUC4eH=i3_|B;\oۅ]5a^3h{Ǿ[NM_=,V1_;]ýfQ{_õ<}T}]@Zz>9Đ֨$b*Uܮz_6Awm30]u)?\ky_k?=|RCbk6] ZoڑOLSs|8_|zYb1\}ڕP)?we*{2ͣ|`m+iWXJ=,1K~@kh+I\3Hxchigz5[Hu~AOG֜ʷ[CھtpO uѝ NkH| ٻowk=S؜'S0ӶXXv>=Q+`u>xkUgN+* _Ac똦*}ǁq9fڛGsm}]s}4^ج5+M~uޘ?k֏-׻w|ױ߹`ɗƽAyzZbjܫ/mr 7tMB6lƠ'6c#v֧V}a̍:=o>;g,_[q݉߶ ~bL:FH%l p [tO9 9& p1|;8ߊE|hgJ*tujj:nkGh c4WG/\*V}c}}pXfh&# mB6ˤOrXՆJĨ;'[_%̏԰g!=L}$O4L>ŰЙ߽ҜSswNO֒|/=߳/+trBkYw婝7dr/~GMc),C6aΜuWRSZbV½aЬزm@ri$V$6Y[7\ȜqӨٽb- .]?vu:v f bZ:k㱞LTt-kZ!b~ <^u[掝! 3ŰGߗ J}cɕ-;6'^[a XwJ]Cz F\JkH&g\ޘETzu܃\?ubL⧾~ zsc9z/v#9U1ew'+f0gRO, W{̗1r1:Os`I^u%YC≹֞e gղ4"Ř 8y~=4{R{A'RM8JząMWX)1rsȌ)`61;~o\ӧQ>KBouȋU1^k/o"HIP.S/Vůt_YE7&GR1}5d욵zM~}HJҮNLzThΉ9܄u|=OpmXuؔKѝt}'U/vWI}k;DZ15{2+3Ğ9;~͇3fo٬ /kjX<}$ƈE7S?.? rwOW8ߝ#c<9:3Z3V}U=vmg,{2ͺK\ w(m]W7jz`=rY۳~hZZ{$ue}}caok`^/r H{9سa.2-X:qbK;Zؖ`!052;P73\Ã/q`W/vk0̧uWxdےbaoߝM_>q\RfKeYeE+m([f,B<+)>%zXتg-N雚/)mpElW9MeK6PKMmm/IJ0T.sLG}@K|[vr2$GռϝH]ⰹJ:R?fޓJlc[4baM IDATמWfCnq b.P^wAqo"{|c}a%}|ƈAb8XŸ^8;gcTg~=tKLX:֚}G/|o|92'(r2cV3~.McT}r%`PYԗyYyqWOz)'}%ZOj\i0ǸC CKb}}lrk~x8kǘ^M:Lc;ȓA7Qf2Ku,bB&1X-n#p`O-}, W{9kz.GawcۨJ~H~T܂)-d=k;@~;jDr6_͸˹v& X$xc7k4p<kn꫆Funȿn=y +ؚgG料%ץ'{r5~dJO!՛cg]V>wƤ$^ ALx9Х_Z&VR ĥϺ]Kwo+k}N?6/|wke|&Ɯ15VnDZ7ݶW+ص_fWNgr'm}b慨) \Z74|/a:3kT2޺›S=+-^;޳<*5Sʕ8x]K ~ʴ-yҗ~0x"w@|Fe-ƙCbϓ2Xd88(޼bw`eҖe1Okb<{}y2}7}4ZX.D/ʿ-ʟҚ)}ة7%ӻsC&ϋɁ^bV㓧oozM {\;/kHHƾLw"c+iFvfXct_`>Tŕ^k!BWs%=`Cۚ'DO)}|ns.apz"׮3TGqzLNX)ոq`}%޸Ëuf]|G 6=p/&9{ǐHlJur*I,%{Ў_~cAZ;˩dr]L.9}%0ŕ|wmُo>syՑėmpT~4Opܗy}6+sJlky.i#I=ȟ`Ҏ^`$}3({.7qk',L֣~{%D4˕{mb`ԟ碯~4qioUܜ1{o}Z]î/Wdmͫ6WUk]֝[n,jǩ3sɳ!}kݾ;Ԛe19w `/m߭ 3BV XWWgpPþ03k*}!+nx>l6{ L֋ 9{ꍜ8goͫ!C9XsM}֔OZDov{ї8y3usLo|c}jsV7,ıkL۹}b}SS-Ͽ nѵ9%:\kqKdL|\\:֮d)Jb?{'<\>I6.wό^;ױU;WS4ȹpHx>[>L쁨n2LDkR;GYx?_~Lľ޿8A§N=kmdn}*XgW^։r|]#`ʿ_8_vc#Z悇Zw ~`)A?^sq|bPg_r_.lz9t{\'U {v{oU/%&rߵi>,_}$Dgd''Nk;ua+/`W|Bof߫eͰ޳ĦnqFc8 }Ե5D/5Ĥo#~MdM>y2xCk`1|ؿu 5.:_ً~v+{ yKfs~dž8 ~sd,AٙArY[b_~lж}j|_'z9k=Ȫiܙɮ:=ߐ>9F :<3cߚϘCSƚs&VⱩgdD@t+߱k@)6 |YڃE+KR9_'A f_q8:~cyqc\zﵷ /?qk{ KO$~w@\r}~Uʗ{9)VU˱??.tY[K9&bq`fVY7#}1 5*S)G]][& rsyr GþxSy_%ׇ9-Lվz Lu{S3esjys9Xu%tJWfsu۵n/{_R fr޳0^1elߚ@pW`k~`Kج& '~'ʽy%RΪiXOHZî/yՑ:Z{Is|$y؂KL+oS%g~76#ŋe{_qukU!G_/׸u`[׭UXhNĂ0w=YN\>ry5Pg y*~=Bl ۆ|o%^\V勣q`Y60%%zb|5߹Y">Yԧ69txK X3+|-O)܅ݬrjMLκߛM,ּU\o'E}lGS_-'Z7bMšMl{rv5^)\_ӳk7/{f݇ZZҝwrjǞq}r!g~k{k mp<ԕ~ukE-L?Wǡl4_웇=W.Kb;97 2ѓ$&M5f>}^>WG|gOvlJy _f h6v,іJ{:ySC\>ru\3pbY9 =ǞE(3]~eDtMc7o&)CKz㫼 gV^qEmMwc<|?uv`?}w.ŝНV~{ù_?5srɑfl|AۜvW<֕yN Squͨ|Qk2ϣgEÑ_αW[6>/{+ҦǵÜ?rC?U\>b.|Z}g&ETO_m&{䬾5,=ݫlCYj1}6jۿls",LٛUOGl:w1XI5IM+OV/2l8g;HkW.CEk[ˉ[Qڊ`?sJ3Jrc'o|o9(cȩ<5U݉=vNwq0Wl3軞 H~:-Ġm~b)WطzIxƵy%X {oc 2>=)K*Ҏ~qqi Y?uw-!s4s 6HŸ1v-#ŊmPZ{WWvt39%+9rQ6Ȯ}o>S6ܛK)sr=cL덕1ƶ}t|qrg/ko+ ~2Dݚƺ>ߵKxH^ÙÅ'5/}Oq>$^֡ y&YV]/13ygn*!N;8uGyoGVL ³0kh +%{pCWzn }m>Ƨ͍r&˸)˩2=,f@3S3ѧ])v~rႏoΜk?{"֟\z +xÕF=29(m[Aα;N{Qu7k^H@嚺y_{v/;"Sz^>m8`PA8{ycoGiWR2ga[&3+7~tGNƈr+jw5o<>5G_U\sw|aiSW6W+컗9'ѿx3g؜\{R>$qеqڨ]foS"V͵rev?\{ǹ>1H2/_2jS~P+|u}h>iט׆ϕuhKy`dgqSb >|v:棘}f778Pr7.6cWZhG7^&% K^\tq/W2:W_~{ b_0i ?Uy}q\`|y1ŗ+nk]K] r߸9AZ+fאw4>qoO,5/>93 ɇĭUPUѧzΒý2ޮ?AY僳Ã&^M>%7%Y]Wԋ&W?|GV,o^?֏'}E3eYiY&=kӇYajc}]aMA{;ga.e|;cF4Ʋg,{{w4X]cܑIu7ۉ=_(|ʺ&Ovb^E g87 1Eu#צ?uӓ8/ ?||9ۓ6X/Ƶ'iǮ MnB^fV6k2{9ܛ3oXmg%ܛMXFjk='hcu?`I_|]!7|lۘ4'?D`rYG&|'R#㵃|ŭ.'6uSܽlƣoo>r8loɹr3^:^3[IR2uԪ/~͡=׻w03bWTQ372uyO 6yy}q=u}҆%/~f\4ḅs^)wk<;K˧ٵ}dme/3\&Eb%F=}K;75i&w,z2^:i8|{W*[٤ o>C?5ˣ][5o׊_L߾ g/Ǚ 9qZF^o5^p޽F?mjrH~JL0muϣls_+ŬwZ1K+gdNf㿋ˍWn${ 1KCL bqu7~vĶ0+Vڭ[ O9"N /_{}͵-mqb+5d+̓E|ж'F-zֻ~v$89F'}+{1^HWL:OaX16 '3U2&iϚ,n g(Oy"8bC~8<}Tc'Omi2mr5.d$Xf`kG_`zۻ/.{յ(Qj` /t5=<n~p8s%g_%ͥ=aY޽oCItq_2k~:W=<|}3Op'uQ_>mbRz8.Rx8iKro,rwbƯvr$~T kYҼ`1yFqA9هLUa/kNzbГ[p 1ǶaIn8 sC)HάnU?T~ڏ}&!GszSg.cəג`k'?&G_f{s` fCV\xĐxq7o,Kᓿkw5VtzFb^/.kjck %;347W̧Ft[4Rn]m?{`}%fBϦe>gYy=r.c,쉲ZXk_WysvS|֗5Z{U\7'jS3N= Gh<֚HTS Wk{l|m}lS\|~%vb5iM㥄[zY#'W=qϜu3?Ƚ<@*֧o|ü6PjT}}ms-}b?ϕ۸37uvFW[k7jV}u<[.'s1٧c՜ X4\kkcoLmRΦqD<51W;1)|c{׎+'0;C|=O>ƙ~V7j{cy{1kh//%G\ޏ_|yӧVjdM[a9?֟{0'SK 1;ԆH^i_KhO,2۾q9/9pW 1TDK[J F10.iJ=nXO}+dk}orҊ }77w7z)uǮyy:G-5ۚFؾ%W[.M=?0Xoёw4RRV*nݿj/|rLc^1PPelM}-[M̴^W?6=DGr`Az]jڼ*ZB{VXkW:V{=JNcԫ[\:!oAOߣě[I =̓⳩M(~u>~s.{bf.1:JHgѼ\,+wzsxpon ip@jJȚ9ק'qo3 Z{gg oZon5T+k>~SVwyG2J) ފo}V>gV`gW}ɿz77/_G{K0NIGޚ>kVqvah3܀잫@<5ށ/;P] 97ߙ8@t%=L`럣?{>~\;3'zȜk>g&?qoCl]%9{P <\=ܝGgy‚? *W_Sk][?$f-wr_]ñ6u͗E1Zt~{ֽq_9jd]q彪xl_<o/Xsj\gf>J]:Sg]9#̊Mqs$ͷ1xъ_.&Fk>b  w G2N~ڟ^a7Zf$| NKR_qwָ>x|^r5qj\Z2g?i n=~nu}kjlj9'ən:X=wD-*س2 >+5}u9CtZc"Wk\?sOuc,')8RF̼jוo,\Ncfԑc|ke/pRߖ}Z7y@}%h_,c&u+݇8O <*-+1H`8}pis,_˚ٙQT 7ӟm{sQGϱm}R?˞ :ֹ>{/Z_hX#>3O$62˚?tůPOjr9 O,㲻#.:on诅Ѯ (c):_qœs^Ԭ3frXNuN59ؖ4X>㝧R~/QWi=Cj{Oy3o-4Vtk+yuJ{s@΄oc;sfkõ[`?5Cw#^dϳ 5NZ.7oVZoȭkSKsbc>;EâbbNr}>ջa{j$'sZ=?aNy{?&w1-⁋[<$W%}w7zOsϽ~bz8 .'5Ē{{XS;G8w⣁sgPyersfb2 {ᄇsdzlŽ7oZx̫lrrmDw7uhoLNW'k8;94ޗ58b'q?e>g۟3}bȉ3R޽vK1XZ|j?WtF/jwKn՘5|k8`߶rwf8fܿ{Iގwbcb=YwFpKލ{ۘ9#e/-srK+Wp7hW;IIhgej̭puɵ_3VezsK V.Ĺ9"9~u1S.gEl/Z fƩwN͙'gs5>*:pXgmX0svd[\{Vո5엽AKMf/ۓ9%v9Gfrf.prDP;YvkkOޛɜš0zv_37G<|B;֚\׸k=hG0_"J\g~߹9׋|jVw9O 곟s/[kLϘ}R>7IBivOC9yu·#h!#5SχX?_B+؉+ |Wc{\q'+~A_6+8S#9;sZu~gJ{νgǸ.n^;1V_9H<%l]=8mk:;3泇N9Wy3 `}^Kw{ rZ_V_|I~זNyb!k)y|y,}rNEJNjs}: YHvb-}3`|ñNXĽ粦8{Rl7USj;>+15_ְjP~Ͻ{ gծ8K7Hk9^ݜ89O/nXV Wgݜ=jiic~ك+v_>&Vuz[V XwX9 ֟^s\ԻwW>{/ؾh*)Ƙ"9W?#Gqĩ#?ֺ兩jR[+9'W>>+9whCb|ӇY:z;^䫿:koךF}V{aD+4U\[ccBVV~;oM c|zRcޙ#_+S fL_}ěW=k8\Vr)ƌbKsm+sfKegaZzfk98!j7+C.Y+Q{߫=c,s;wwjy^bose^k!c{5]/ժSnδs~KGR-9uHμJs7wp#-us>:WzWFkw65$7EٽPcɯ௷WǙ؏yn= ͬSVL~ee;je=}C\rl\X̖w2_fOB⸩a a|2?̵g4l"ݗaEW?YExtqm|̭ d䟆j3JjHoDk-yLwk]&د3'D|O_{ϥbnRt߹}ӫ=?'`댾o*j)^Xsja>8K}KG-mI>~awk1RCyry{pk:3%,QX=݀֜R }2#>z5ŵVݟ7_nr9[>\7g?F;Q~i4~y{Pޛڑ5'~kbG1qǾ7~9Yez3OZǿwJ>/{crsnK{j#8k3fhgre9ޜ5gs'ט-KmDY=zoN>ڗj]罗Zo|>2~z"cQCfsq)iCW26+4~&5?j?Z?+}Av6h9zBZv差x]川9.VLgw8_uP|a۟]smguzl@ ;=kgx3Z琝n{{?V5:Y{wqͺE7w&?lάcg镾39=Fv._'2w]>Y{r՝!r;h9H9CC=- oir ^aL҂ӿpsWS>6_}z 󊿆<{ˤZ^5gد fvmS[`/|fbj|JospTYi2O[u$R3C5UxO)_^by:?5Hz1w::ɞR;7Z,jg.땻Kyw2%/4Eh-±OnwZw#4;׋}{dZ&ƞ\v<[>16{~]GDx_}\Mލrln'W7X5Sy0d52QTp&^.53Q9 7gRv'8uf+˜OMsX9ļ}to{ SK{5.LFs[O~Ϥu8wZqiϳZ_\s5>lsDTo͒+/)b_~y2o/_߿gK{`[/S+Uܝh#z/5ihYvF}3ڨRwe?ģ{YO?SC7Oa0< BuVb{o/b},dL/u=$:0m]Jpcbɽhxo/~vU <>V6f?_3'Z]s7/W'ⱬ%W mé֫c4^r|Q]ѼSؽ!ՠ9NjKr3X!6wv:s'ݗeǙiS}QEk&/Rsy nN>Oخoq2אoz/F:VެQմēϯGcv1GC2m=Vu2.|jdu'oì/usΑ3X=ǜwq3?wH;7Lk;g"p}P35_S8yoƼzbW۞|r"LjbS氉/aq;}rNqv-|5̉X7Zo\>Cm8K>y#Ulw[p/7 9{$|xrbԫ|_̂?\R^j,ESICdflNj=,ӐZI>8fo0=5=`r*]׋U~ncܲ3|{5[sz#9 yeOo.fjzĹ'&/9J%3ؘ>:V-ϸ*=9o1_a|%[M?1xu}7a鯦 g5sjak^M]cO1K`j:rG*f^z~{=8}ʥ^ތ{485:'sJj IDATbjm|ۚ$/N_]ə\^R{拼cětՏ_;8s^^;lSusY3ט>jgU|rmA@%@Ka1CNU/s^}%=:6!1=Jj5s}ѱM U0\u|w?ݶ:P.<[+Ϭ'ɧfsAʣ?ŧ~r&5yjkSلޛϚͺܪh㹇:pGHzr v8uZKώzPNqxd{ְÝ0*1stg#9ؠz]o!AdM̅{?@#wI_uFtհY'ڼe38+|}18| CU/k zL{Oi [w^c~be{VF>J%ު=?}vϖé;XqXr~,?jԞVkGTpkrFbJ; [;H>$'^Nc]YoizH~ŠQgs9s|k1RCNK??9e/jnܮ;-f|/ֱ_3b:s垱7Zz/vN۟ft-Mg/k@H g\ZuFs4޳!ɼXaoMEDߓK(#^k}Ӧޛ7F٥>/gre$ڸٷ`=$opYXW_y'g_zOW`h3W:}\/ 9y<l'/XrSRgO2Y:e̮G_7 _ylE,-Jg=wտ+_?bPO r!x28{M&t͞X5ŊϞ0'Guuߜ_^p|Nwvr/osn~n79ζ=z]eV^?35 pzߝ8,:jZ'G?#WϞu_L~]rջYN^:`uzxʩak&vx;ߡ.Gxsy6/6%pn:U䤎`ysK>|>ib]_5ϗ&1sְ`Vq5'yu9GkQj,_5~9HljyybrUޣ%/{][- 0?}r_Z/neܫɫX{x&; zjj19]o-9[i5?}km؎Q9j./ΈIX8kmߟM|^:?}O([^X~on.M_OJg *[qGsA{v3%ݐ+37& :qXѸ8\rFl!{5~~!^ WhWjb/_,8nY9xl~kÓ+>-5{jW&OO?5G}`Ԅ#Ok>?7L׻cid﹉9vi:/uy#>:O ?v[aqjR q/msۇjf~sR8MqGJc75z(F+9s'8kkS3\-n?|uXWr&61򵢩RXWZ~uljee1~ٵZ9' 3L5UCr }S1hh1_䈬x~갷JT.}Wڇ'^Q,GF:jc}μj[{cs{9Å6tlZ3ƎUX}(Ad 5 XYo3& 1i7^ u},π95_B9}_b9y*;>;U wPgd?z=mo8EVc~qi]{䋛zN+Nk].?=/Nn[v;ľ1y?v֗^_=#ۼ˫]oN-y #_smׯdEgљc}Qo|A1'h&bɚĚ`S}@W5.gk'wT5:}|f{gOSSl:\3ZgCOR.Y}s?_O<=UOf%cYQ&<7IMSͣj![[S#E#ZJb%?{i}ޗi3N_=:5sO󊁟`vދAKtZ}E\gԾ_YݳA9uag;׀5ޛ̞"ws6'/rw>v?Zp=$ΉK/yKk;#x5ϣy0fe|j+v=$v]/,Oߴ#omзu9 ҿU_6W;ÚJ@o49HZڷN.m X=ٙpGfRxUkj5u@_VnT ?lOy؟{}BV|f>3#_mqN.˜Ñm k-,?9UWz}ռX)^ WV/O|c9=o~~jZvޜ8~ɟ7jwS7_}Ϳn]|c3-i W[c^=kͷ~Gp01h>+rqqDٳ97jǒ~z/qlASC<;껓6=Ux1֮^h#j =0k*ҿ+S4]*3ŁmQ;jŜU=7U_xzX=MNBQ)jr ^Zɹ͓=oli&?{L=ŭsKӞNG5z?g<:j73U}'W1suZ'Q !!K_~ JSCzն=PmGa|ݶOqYsgHScݓ b~HQm]:ج7Ns=P Cr'&j8_Q"O;gyk_o}.sZPe9m_k6O-0:gf.fFyW?kw;!XuE9p?hŃU}r湒yf[󬯏?1o34eYpלn~Q"y}X/OY&(uKe>Sy>s'T=/Mzc8Dp$5nW^nX1k2#4ll߇z?;oҗ"+C4|@WJE*M/r; ĿS׃֮W_ ԉś405nh;W3s_k%r_95x<7ԓy|vԹ;*;VS>VߞYZ9[[-կ=7קQ6%3sbpyk9S",ZA ϲ9NHUcӪ;kn֜}aq=3R%.>+]ɍjq\/t"U&˟WL{fK9{njצ ;F.7ru.r# zf'3KNr}nԃfG5o[|!-W΁S9%gyj~5g \|en)}1y`Ֆ,juezc. ,s=ڻ-5;{iw5fH_zto_̌dΖ~"{,Ǭt6w祐oĜFN91kNiɽ=|{8xog"\f53~yִ_Z^s%!g1RO wem3;0yZ^Üc^; O?CjLs[<3?E1|JKmoy]߻~bܝ^!as._Lɕӹa c|wmH<ՁavºԌӷe_gg>wwWׇ֚PJd҂<{ ̠9KPL u>ow?Sg-ba[nW<᯹ =jPbH=\%5=om1r65js徰9#*&ȃw̶ z' a8kN5Zc]<8gSP#cuVb}pSXeCkY^3h=0j?3xsxy5gެ=XM5-֛#>w].أyno6ֹ=nNKoP^=`jsʿLV?ꑣ>zM q.<}YrsNy0Uc{ojem=Ţf>9wܪbo|yZrׁ!ΙPu/~+zjϓf>s46MngjfWگ&qbH!mN{8Ce0an:9/ƪe+1;/qj;6:Փ~a9hړ\E%W/1ֱգ<;,-Nt!*>e`-G1mNTΙws*{-X}8ۑϒ j3Ƣ?.bf_iogstN_ןX>E^;~]p^g!מϓW OU{"ׯ[̅ߢחO~2y|YUgph1<^_?9:=Y^Vdɹg_V׺~u ^~b Ru"+xyUr&rrNJю}rR>qnOYYWroy.|>K[y9zkqn{W"yN:8u,hu>nK᫧2`r]]?Wqӫ{ê#\+S`o~x*ō}3{=e?13|m-z-j^˺3N/V^3_wB>Č9ݮc[pxC'Xﯺ6쥳hr{t͕|l |_Pz1dͽY7wFZi$7>~$>/“9la^VV1 \`1˭:wӶ,j%窵{7>ϒy.= ܫ 3eՋsSOMj62qYby s?rcĪ5?w,G/Mr˷f<6s+?fo}՜/Y.dg8=jC%L>;χ`o]'BW%/?3#fwD2Z[j|a'W%0vMnS1'Ǒ<`*/v{{+Q̫$jT fOGӒg`5^\sy/7wC.ʳMR~#gok'W|qy! 50_~^y&=҇g~&U9Դ6iqל7T^ם=/3}]Ժeu)嫗+^mNe=eݿ/iɶ/P17.eSj{8ڡqL>żmTysSԬxujs2Oy6kyhZ}[zzrZYS8}sσ?.Ư ־jܜÎNk™(ثc]c^zgF͝'YhOm%vi {&$[Oͺڟĭ5dNjGu󶰭skIzR~rcYce=$jf:vRRos_^s [سlݓ;}y z3q^;}gw0{8gzy(9cD%VG}4sŢcgxrW{8;w05Kͪp[gjNy}_qq3+?Ws-'{~j=͜w,RDoQٶ xfq@r6{O>?Ygh_'[f7yR=7'>9i>CzAkF֏L bמ|gom[~sjUOiZt?{wwt_+mEolGI?IsI~?۷S5kP\[#yͨy_fXFTdvel9x[WGXXͫK>CG'?Sxr%ٜ<oܸ}1bέkg::r#5^h.I}&5ǵ?_C9s:\6+k'9j/#_18C4M_ -[(e:¡~4#+:>{:}(ļ[܌QO Ӝ38&ӏ7;KZŲz|:=|ֲttYK93_?kuxU.01U~xmr^MъC\bșWllnk5hR&WSwj/~PRqsS)owY y}/p);Kճ:u>l.?xjW뵇S]up#}8瀓|ۮv^abk)8}m2W}bܯڜ#ଗeMټs5|^w.Ntq-I}52.Ca s,Mueem^YKygi9IR''G`<}s Xw*jvʇv}n'>\]woEWٺG_˷w33 e^K]X3Rf4%ejYhlk%y}*g_joPdv~U /Ipw_tm].A@W@`&b|Q'Vڲ7oxDhlM҉=׺cw}W̳M\Va,?pm+%\L2}sC;|5F\3;zdkQE.}@i$$JVwmKl9gD+1waYZm.O ⅾ[Rֺ{|Dݪ \{هuCNssi>_lK'0KZ~Cu|=*qoSyܳsS*FjuS׺SڈK:;tO;`Q3cl¡˭Gs~֚īU+ ǪM^- NGj.k]>w#>1)۳ycM6}'omޜ2 gK7V-ue]'@_L$YުtsF >ӧ1w1ۀ73P;3A3>8Fg/KKlL%yk踲NXW>ZniͿox1?J_곬J߸s_]c^m <'׵>Ki֞~;<|q9|t*fyԨM_<#-{94ۃ!ϚX1Đ^HW6~f&'6բ/z{cXkg:y!c~~/{Ɔֺ{Y{@pGwۊ)LճNYwW{9g-7hZюCv]ݵ ^z>Lrƍu{A>9f5l<3Ή5W̉ÞZ_.P|*QT9_ե93]qYќsއuk5SrgNJs3aj`nd[Qtb<}k_|#}1p=}tOiW^,yTr ԙǙo}^kwhC ՗g˼ֹ's2ںz=-=suTy olBHI>ssz9,id=ωgJARS;8^3C؎<]vW7“|W F >6-6ŤuyK칔]K7L:~@2g}Nq 䧞!xf߿勿Rvf<7jtg3\8 xk3W o %Ԉ-G vzne~XOjyk Ĥ1: ~jSce];uFO^W"pS^Q7UvWO{n`eM\x1qʂZqR/{B6.jO|=DKJZe7=ӗz /uK{ y`_V=ypՇW_5Sݚ]o<A^u JyVԧ/2~N-o?m`HXkj}K⬩u M{raGr19XKr֥_ ζj'r}5ɉU {Ub%9Jk&#!9Zۮ7[Vg*Yj=E,68]yZ{;7bktJcs*f!퓺oo!<<NU:җ׸n?{ZoNo,tɉ6Z7^P<޼55<=|i~ɡQg={=oNWq7z;9}ԟjE$ `6ބ6 '}ϼX1ʼn蝯աImZkb?&5gJ&+,{h]jsze79rH5s_',ymS/}">z^~jE\Cv{Y{F: 5>+XΫu6CKo r>$y)_Qڧg=?({Aɸsoᬑwd? _G-۳tyWY1&XkYuՑg5>l$մs>/^ކ\y|3}xq5^@8/K-9{e _;{dJۛӲ9//_٣󐜜{%b I/9<rol+_3&篺$M~mlw4u=&zwy;{JlXASyX_bϠeF?w}=SQ9SSyCK9ckVRC^G /Ad_?rwꕇrhkBkuGف>XONkti/шgy_⪾ulxh?-Up%GLT8ֱU}= igY$Ҩ>skoO,{z ՘=kc>mGoL׈z3/b; c5޵i~نv[ lQ5`c7ZNG"tͱm5Ce>~K{o}hn ?ӣogqSǷV8uӷ$7N.w9~~~`3>A_zjn޵[Ɠ u{J-3ne9(}g3K%1߶?򰍛Rs4FnK=|9_zHRXYR#k[\~;}q_,kZjկg\*j̜uj`^X?ozR߽H쨙gd% {<#cuR#f'eکK[-̥_z2u?bsqo͙Z=տПEMu g;;5c}Qkpȿ.^Or#1'I -^;zVYrUyj]f L)9X:7cעs*'Fv>kQ:n9v}mG ,WssԽ9gP'9󓰮zoBj)1Z9̐mo:RKF_'iZ}5=gYyG|'xmOa˹ֻOb;Ucr}GO>PxΧ5'Fڜ|ѥf]37g{O_sS;Zk8CK5gΎ nzU}8ć[@:K>YX >?koR3jc8髑#sگ53z-7593j3$΢zUjrokrX;;ycmmyv{g_b_$K{ ߾߅/s]yZ/^7/{x9~^}Sss79gi*EMq4߰|dPAv%Ԟy5F9MS YFXbs[_C^ ގez&{9Z]|)|bjK{2ZsW";Cۈϩse ^ϋZq DX?q'kY`qUìsb]o^4C`Umj-|cYzU+Pp/BuF9ػd78i&yrPsuV_gfwW'c{εy܅15e^M&&}q7>waq>x9qmwRޭ[M;oӛ˷5ѽw/XΔ}{uO^GX+S[lYW4o@ΙDfh=~Wsgs_9 ` %:[wޠ}RD?Zƾ }os}rlY|~_:%RucSur,ХbSyť֢._~`j/uHgk8gbkZK͵>/j2r9Eq_\\v=T~T"u7}1oEK;5^m؃3Q[Gm'sc8NѮNWb_<~H\kw<&3:}s!p4G׃yMyħ8gc LxݼFr W&?hǞ79so\^۵ܩr~̰߹;_~t0rG"y9XuQ~-hR8r@-aދ!6^Y~W睚/v|qFÖoμeoi|:? b">k |_*V}FRxb{W}\%2|޹q351ӽf7^J5MӋU&T+BV'k\h\zƯE{F{\?+~z,Rj>4YzڽycS,LA"?fwo%fϛ>>+cOX ;Շ3Vi%Ǟľ飱U̩6n_i3ez٧{qrڿۋ{|5,|g̅Pʟb׈S%|Kl$z~s͕=?8kjPSmZ;U̯N_i߶V㙨 "}b #ߚ~'%'u3/ZkG٥m~ch=hj#6_j='nvuezw/ĝ527gA05b}hӃ'N_[dssδ/Mg%!.ަ|irE̫%v.p,w?5 : Uܭ=y8$߼s3/VΪgq̀Gw=;T ӝuȳ}6Oo'_c~s~+xTZ5'Us>蹷SqoJ|U2w;J͞5O=w]3\dk`P jUO^?N-9^s=qWyY,8C@WUC w*lْGހ|}!sowtYKX1"/.==, ߱OɣiwyR~ۛ{U"U3ܕr16+:X87sν0>X:} wY6umS\^Jݿ>`Ѝ}(t|V5% 1YcsA vtS-W썜(3Nls'ƛyǒ[YĩazcM]Z :W,/rp ?w3N\e1,pݷβ%wi⊹Q^O}j ܨ>afm(_NnHYӶCO܋ϙlߺ+\7WO @J6iVg쇓QZw޼B_ݽ~% 'N)yמ,}N^tkI;a S 5~Z)ɋ;D㓣Y`c4񩟜yym7ڒ{Ssqr7yNNKN}w{x6L yd,mgy xsS _QoO5nףTwK, 'ffy×w?p^sY5_rwwӽq"ޜo ^<#בRцm(vďDO?;<\}~[:.xsx3O*d#'F~Iz.c8ޘ/~m"n IDAT&cļ9sNɬ[}9%ןw2̳8{jچs6$Jpڵ)5v= 2z03=um%\gi_'_>|ĵF{ֱeOϧ֤+s],1o ><}W~J;A?R佌_lν GRc;3sU%.uH{&*vA?>0-]OԢ}cgM7ِTRn)E4-s0VS/ '6ꖃՕA>{lOq??[K Ig4SI.t\v`.S Q=h}ceNy$ Sjk9;pK@|8H1 Ӧrr6rs0(ޞ V'4Gӯz6C[E.nfxsv=&M#;q7N.).<? ǀ7f}7$ǣX r?ۆPt8k1S[zb^{E|7q}rޑcۣ[ wU[-Y嚞g>\--by汮<\O7X$c:ý+wlqHkfs"V-?b;X7ʹq8;~UR,܄g%v?ƭ`S^/>49Ψ2f| 7Ŝt(8YSc#Ƭ-~ ߞŴ\i-.Wym6>Nny[Fmbօ.ȣ2}&7!ౙ_E v# L7oC\Nl;gOmJw͸~'Su7fc]_ &q׾w3uƵemԂ>%_֊}OքԐ9}zg!2:mഈĜs?w/'^<8x?O@IkI6 թyG=>˾6oJ,3!Ԯk_̙uwU;Au.'nf֘'𹰁ѷs hYXv}ƾsPC9_cԪ<|^ose=ڐݘnwmH]N%~X=~c3L k :{91}_>$\WT7W&wOweqo6oJ8g<21p+S7cmqZ ܛM-,-S.(eXאoΕXs!ygL*y q,OV{9ٿ+MY^RϨGbbY*|HұV&9>.cyΒ=խ*@bEo:uVmP_W}w-c(ےȚ/3z \]9tz#'ؑҺs\>|"ޱnZ{G?HcmXϸwmk/䫊8mlrK!]\uN< 9{1y?0rO;fj̠Gw`n0ƲFG7?w?$ Jk)qr|m6 0]s~I}Lju"g,>{x|cyD_-)2;akC~biϛF~aMU=Sf oM@|Ojbo<쁾]'q rGLƳg _.(kZ<+<6]| N7VҊ{3h .b<^smc㗕 A_)GRu0޼1m?)N%;|r՘>ur^7k ?.01+~֢ԖHw=%:O j[CO^^nÝzE]o `yoΊkrx+s4zNe~ގ?u26yQmeވnOrѵk'+*} q@K9_5y{>B#{jZKc=ioSKyqdO+|m|kj]ٴس{͗~YxWʅUl߽ۺ:~Ž#ZuLdi15vɋ_Nus]2כK>mJ|yfI=Ѯ^=%8CIkut{}Ѳcme. ;%=@}&8}`e O/9y+AT*>\ggċojI0|cٿy2O]Oӗ1~}7Ӑx$9n;9lqɛ6۷#~c&oFqD?xg}^;vW1+ڈ'UM]%h5}go 8/j֌`3/6{EoF*9fI~|]YG?39=k]͐$xc|l/pʧħe X{%|wJ!"/{V>uc?侧x|ͻ[^e9bxy$@rsg $ 켋VY'۱e=g)c=-_/Gڭ]L֪ӆ>5>W33 \Ǧv$vuu28:y6AbZ ܩ/3/(p'ֻ;57Qڕڹ*:{lkv%8e NNo0zf)-3J;)09Z@ғ{B_E>,|# 93swSpOy,-^y8DžѮ$0%CkW1o `_̌eWl)M: L~ԑ<Wq0sgb~{}yC}6Lx9Ժ˔rV\ߘnes9k 3~/ۡbCg<RUG=q蹗ýR{Pt~s5'/:+yjcb#{?ۻsĹԑvGP'=mjכvlɣ/ySq'?I$|sΆ:2sh甉o":x9]k'V1bw"~lŋ} կS83˵ VG}r;9g8//'fr7]_ޅ=c q=.a8jzf3{c+:{Ү,omڌ}9[}eĘG^A^>j|uzAXd:3h?kOQE;n~.1|pgo!~d{ָγJ@;GWI2̃o8N^3![v ́ YP?ho r5Ǔxyeu~c %6[ͽƖgZ+Ӈβ~̛_u1ZO#~w:Y>HwZϡ_D-j^&_my ɾĘ6\eȓ5 >[ˋaodև_Og%ӧLXʱ~y/gPdMwrzq惏d:{bg SP_q^\o/n1owPɅ>Yt0~v'Fmp'N|̫/2>eX5hWbuH9s4kŹWٶ?2ü<+v}k}a Ɖmz$`uo9>Z79^);NEml~ >hZ_%)WLujغtn'M\bQ6R3}`X yfUY5Wދt8?vvlzkcr=eM<^1 k.?u%Cǒ7r3L^`c㮟>N}So\́lI'z0G׮ėkg#.~r6~#gkuqr);gDM̘:b!+uqSqώX÷كQ&cӿN@ryO̻}m3ļKҏֻ×qn3xaL"ERm˝G}ϜOۋ7Ntű3f_uuMA{ѹ?^椭Epao};q_ 63ګTy_1[~Ws[5ӵ;α\ӊӽ? YoصoUxǯnеۛ8_Csaٌ@zu-9C]EOsK|S>Il$f,Yx) uSX(. b%\Yy] ^_) o?wg>CM5xNeˉL%/尬+x=?z\Ӷ[9k.[F&ω=OQ h:]z|֖*wo7݋]>6Ok]W惦MuWoܹkXqvvd {ӻ2=h׶JjyGr!{eeL 9}Чl ܶky`y{˗P93c}ru-+W<%)L gM t;8-n}o.yҿʘ+'Q|-H f2(ߎY{cʼ4/Erq*S9;},;fj KiBCL[{Ë?Y6Jc~!=fL"Sn}*PoݓZɴ_Gh΄776(\g4_AkTذ.;M;jk_[;e\KّgxY=,N_zjcXc''3|F'j%V<пj)~-1zm4*cS7N5.N)5;T.m׽Ha˲<"AT|>mRN]\-Zkp^1 IDATəس|Ù9:v3}=g:[rR~)'kGNHMRy`e緮yv>D.bӺ*aN֊>m*,7ޗޫ|Jpr/B}؈o&g)V֘7yOv9ĨӵƹӭD̕>9،?_8kxn|䓽+tkʹCwx"fwדOL@~|ںsLԮԍ_q5W>&O=Yw?jֳ9Þ}Joc;\rxه瞼+i :"*߈\|e5̯{1iK1Ńm;a;b5S᜞D;߶2|E O?^gn/Vׇmٮ{Uz5x"^:'v}ɉljbO˺B+3^3hVr^,gu5YQ8ا~+Nk.k0go}_9~%e֌=|yُ2{7N_rd.~&~vy]25{ALrAMSЮ?Tz0K ':po"`߁3TM7#x%qY5YXf73_6τ|yy^R߰kX,߹gֈ dhCm\}o;zh@qL>.gԞZ)r{SЙK7m_:8Μ5o|4/1S}?ѬeI;(c損nkX$pF`kAa3V VR{mW.k`gE⿩OЎ[#:v?r2Ory+ oKm78_`|;NT>}H߷ܻoq1{7To:ww_g_I5n˭:(A|_1vuR5=꽻6`߻ '&鹺:x/ɗL_wNE׏2¼㝆|Yuȋ5tkGP͵f'ן[q_R{c}/Y]?w 7%c? eu*coΗp]&:F>_ܛsh|vS{F#nǍiOZí39?=p{}{kIuԿA|gk`S\I=3ױXTA $wE]2NLsW7z6o߃UOۆxzm?q:Xqe.k)foӛ n:߿3Ut 7698״3GZɷ.z"3zu9OQզ.fp@HW[B]n;-rȃ|O,SxskGjǢ[NUMϱ=|`6<7q,v:S.̳lĺ8/߮m:UV]i) A''90&6^W9Œgvy(= ։Xs+ _t?ΙyR'?o's^~Z_ױ hKjsi҉'Iԩ7WYĀz޵es&C/ۜ#CRO5!/uڿ|Hs3p9_vk;+qZӖ^ϜFvfm6 ?QW] ׽m:qrmln]M,x$Ux&w8N.1!%C]S=}~뿸bsWg}b:O#?W8[׽j+[IKm{hZXvkK)KGk"]^8gC,kfjܹ {XkKf\W:=mJۗN^;JquL&_q7@1 bn2-}[_ῶHg4PXx+vRDe`qlkt+5A=-b6438X954˶_9zOZ|\Ng|_Y;kg09UmYq| abZ˲۳^s$segsHf.o) )8hrvAۍ$ԍo$<_߄Wq% rY[̼qOb$|/¤-gw=+ n$kǿRǎYg kKsM\*ޤm}GeزN~}اSs1_̷[0!'f"tyZ*s+]q+jNm;u_JU y{\*oo}/Wᦹ ;ZkB1 ̪Kưxgz[xX׏_mя9X׮O)7uk|$ymb3ؾk/3#rY{!g{ϛ[4}}rX302~W~ P/Y_3"O;I9WDW?3z:Gνcf4g>U1ў{uҗ.ؼyygZƶeyZ1tV'%Vnm+gW]0WG/]Kp:מ[Z9'5]*xِW=ЯzƼNLkGc6xÐ~ub/tɭ=D+'sk<ђ|ŕʩ8T`OC\o]ﯤiz2[C#rv?d^%>l_ o3/t?]\S\9&N}ޟk ֳ} 5Nvz^|'^9}II-8NhZRq ?#{}c8zϵr_ {Њ85s2DH7׎ 5ni~̍cftol ׮xhB?_б$"z b,  c=-fEאؾdnLmQwhK|rB%;{)nw)0XϪpəy}8'y!Aj=}???k|ӾK~جU8lgQWd{0փ)KY>/ y]u}uW<暸Lg<%س_9>/6W`½U6<_%Ngm#>5D$ٱhogknmʝ8o6?AgZ2sX D>`_Y{^);݊¬d=;ԕgYCs(?~CΉ853wN2F[_J_5brGڜ|wNk!+i>6xs;`>fP5yv7{ǚg<'A 23VYHz=̫uruh΢9!@̆wCh.!֔vk!~s'ɧMLF}|[}k ?yY>eUpS!N__f?b ˾i3&>SOl~|c >l/ų_}yeİ2.krvb޾#W+dsyf"\^"G}W e.4s&'?T9_~92l{R-T-ewl'M޻heCd!yAI͹|źjSԀYƢ>b~_9˓{`gVF%#GNޗϽ|kx<뾺됗S~+ÑSD=}ya{MUcof=~⒓x~b탸~'^}U<|@lUek8fvif`P!WH|)ӏ]aZk\YrfS'X0ʶG'6PM5|7}Eb\tBsX{sn_!vfn?zZ_2sf)2'%c(_՝0}K:cܲOXbXrs%ͣҟ槌!gak}ʝ#}n'r={pu#&oR#s7μ{g5W>rڮ^"2aIsb/O@Z=89?b߀3S5ȷ2ҟm[ԋegu_\&W׋&7A33KH}{({ k~^ǟ؏zgmp;왃uqogr d ք;pGȕ{XO}Yk3\>}7KL3ӳy@5o<&=o}Hkw-7e9#zԳuYl^V9G(6s-m=}rj"6 9k3_,wĞɛm\;ܝb?3{xӟ: =?w%{=9x;~wC1}Yُ"5_ƽZ2Ѫ_>qr6fNjϘ~ X9ٳ2a__i `tD-*>(%wЍG onv`N|c٨ߕkEӖY7FmO:W!|C2KEߜ/`p6$~Տ\ir5GGi#9'pO"(yS\ruP=u_n*b{V9%Ǯ>$ԗ_6&<~5וmxdesG]Ϳu 4^Ҟv֓M_6y~HZƽz_j;epm`L/O>b'M9zjo2+^O^8,qpGfgD!!8ŧDյȲ%5ȃ?,ᘚWv}OYNJ.q8s9F&~xgY`.]:4]ؽmSZ^6B$ۓ! =97ybE?"*Z6.e3'^2Q7 IDAT]yXs'W;gg9]y{5dVGfc SΌvVrF6tF\㟻!6bAYQ68K'7ۻJ;zv?1gNĘW8Πg&bΩ YnGQ2mY3nrb|攫<%{q-S\`g& _ 8~g.MZg&P~}n3`7vYJ v{;vsOO>dtlʻR[A$o1⾾0L~↽cve]?N=b?%g}ٰ/㱳Vt^w+';.<s>ͫ.9ny+K :I}@_vW!q`]ԓ{rJ8;;p)9ősŵg?|Ŧ wv~=9Z+w{DZ+w._^ tz~F.H@ɉ9wo7GP}֦4}]X3Z Wc;Zfz߾ipޚ RflEx\7lo?wϓ9Nɗi_N}OO~>}͑(rlwr(Ab:n؝ޘׂÙkrmp7NᷳmD]+1Ngj&c8^ةU݃͞ՕFEG2<B,Z@؃7F{ٻYvl>/y婨VO/_cȱ*U'|Q_=}僂g#|Hmo}dF>xW7Ni~`l&kqgK7^? As'=wO 9g~rR:جe\)O8 Łb2-D6̫VG9 <5L9~Wcj o>0XGAp9cKN"/&^eoD^O ́c弱~ `\w^.}_6x\ضc~:=+Oq63|IRff˨_|xvR}\ m-u+aJpr5U{0,웧gsیLQW>s,ۻ/:еSzWs/Nwghj?8lAQ%>7E* 7/XL}k_r_\v~kf>myS{|t/yj u)L{bcԵ,Qg o{k>v/U|}|:4VjKgW o7gM5N??u5adczMڕVKCb3b5ٳOLq󔵑qW~YzƴZv&a?\eH?氆'~qoV>2>6㴋DOڭ}hcb د5JaW"qH1nP=arϜ_5:`.lt}yk÷#u5cas67/q򊝏ÈO{?u7c*ԡе5NuT)nVbR>0>m`CLں[>piS~ s?λnn˹킿d]>fYh9^<+e{ў=xuFvrM~e!ZLCv:ήx1!w.~R~뀋3Zt;/- ^m]Mf7N1SWĠxϝdYXX~r%:< "[x/දس&K̗fkFR<ةRl*_=dl׶ud 7?N|܃ɡ} 6kI5ZO_\3Yd^c#GՑu_̳ ޼m-Ny^kNqJf/|O[1;fɿs VO 4=59vb}^nk`xe' {$sY3758 A!'~ͭ[n?IC`,qk7mϟ g\ɯH:;nux}r@ EK9YX;άIűz^Wb3W7uȻ܋/z<oMX+*L#8zq:Һ8Scg]}U<1~f6; GohSTO'FnmbOnz{"ȿ [Ϣ8̏=|}j{V)Xkz*_,Ή{vw~ܿZ_ڷ-!Dw6{XV6c|J-3Ew\9O`?7Ӝz73y!uu>cX`n Ov$)7Gbx֒?cd{ɱ}2[ܳeßṟDŇ;q׌<+|_ڐ>kOmVoqm ؎.X\36w9.-vQ(3:ky=Ӯkn~?I\&9xo"db>Skx3s%̃2J`g~?@1Wwo֪$j|?ʸ<哏֋O{y=ݧ\>uouaWBjޒp~ۯww|qff.UjGs23q߱8rS۱9s'pf-9Ћ7:xw@ I[?] Z_n/[%!=c?`k3x_{li:qSU?3*Wӫ.xv Ts(6:rGl-to>9X[z<|pL{~֐9 5.8MSZj'J߸ubO֞~%gbx%1-V0ֵM=gX;rX3fV}˻+wmxU+v}lPF/fV1ڶټ%UG_t?u9 \6ϋy t?xM3ÞQl|4o w;ZxŚpa﫞X큝cZ^qU NZA\_u`ͫb+\G+oL5 huq`7?.Xz'7S3f~\Wqƺ581cN[s߫Nv893 xq9{nڗ~δ`In.m'nnϴ٬<7:5NXDI, 5Y.8~bCW"z&$Ěݲ C.5G`vy=xj47.4Y'PuB&p#%ᣔ#u #ߎ_Me])o^ d@?9:dY:q6wv 49>&JQ7y/ ?u?LX<7\}Gqc[KeKc^<6grsg,s.'|P#&s߼nFꛧCϾɻ"W #mbsIk\o&1۩mɳuZ]<'01n1My4=]Fx# [C 9ĮqM4M>{~lskM ӕQ_{;tzZ66>\ {YXZGEڱvލs ls4yU7AG_eyg_XXf &~_Pɜ򼼆:߰0;DzHQkrV/ڜ[cW#'R}m[m)/zm92mՖym?|MG%3umc l6lK lZN֟.M=}3_sg|o $5.kGbsw{Զ.}Ύ@ԩU\-ֲ1f߯`}|zYg!Z׏<,R_6ެ4{c]lȳ#(=:j|rl}6 qК#o30DpFK&?uB^}ϰ( 8n.EZO4~.:A/&'u腯Edvgck&b \>3%q}( =r|yðy0M\:0Wj /cj|i3HtQ{ ۴r4Vluy&`phM5U>|%}\\g4/Hqon{..?\ts^?#|p /k[ov[&i.z|NLjopu}r.ȱqH|ʹy"t;.Yimva~Cݓ>bև5>Lo/w1C$kk= {Bg?v|2>.[39껔\6}cv0Bs8ʶE(y 1D@F8Y/=ѥm]/XS9O8. tWAPb0!saCvJenYhYvx~_a&z| sCT!_P9kfd0m% ].L@?J6 z͓MxG _^tlDp?X>^BE7kgAb%l1ޣ_ߍyX-z^t]M[p@z)0SӮA2-v9dD?i5 u\ -A(9}oz|e.ק1n$X|އ&ix*Cq/CxIDAT{|/~wvyoqu/u{k ׾8j|7ϻ~]fugû˩y8us?g 7_Nj=9e1vڟv#/~vٌ#1^O?͟ǎ{N慘(IENDB`