Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Nov 26, 2024
1 parent 258c013 commit b2960fe
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 17 deletions.
50 changes: 43 additions & 7 deletions example/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,49 @@
import { TypeSystem } from '@sinclair/typebox/system'
import { TypeCompiler } from '@sinclair/typebox/compiler'
import { Value, ValuePointer, ParseRegistry } from '@sinclair/typebox/value'
import { Value, ValuePointer } from '@sinclair/typebox/value'
import { Parse, StaticParseAsType } from '@sinclair/typebox/syntax'
import { Type, TypeGuard, Kind, Static, TSchema } from '@sinclair/typebox'

ParseRegistry.Set('Foo', (a, b, c) => c)
// -----------------------------------------------------------
// Create: Type
// -----------------------------------------------------------

console.time()
for (let i = 0; i < 1_000_000; i += 1) {
Value.Parse(['Convert', 'Assert', 'Clone'], Type.String(), 1)
}
console.timeEnd()
const T = Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number(),
})

type T = Static<typeof T>

console.log(T)

// -----------------------------------------------------------
// Parse: Type
// -----------------------------------------------------------

const S = Parse({ T }, `{ x: T, y: T, z: T }`)

type S = Static<typeof S>

// -----------------------------------------------------------
// Create: Value
// -----------------------------------------------------------

const V = Value.Create(T)

console.log(V)

// -----------------------------------------------------------
// Compile: Type
// -----------------------------------------------------------

const C = TypeCompiler.Compile(T)

console.log(C.Code())

// -----------------------------------------------------------
// Check: Value
// -----------------------------------------------------------

console.log(C.Check(V))
9 changes: 5 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -1325,25 +1325,26 @@ const B = Value.Encode(Type.String(), 42) // throw
### Parse
Use the Parse function to parse a value. The Parse function will internally call a sequence of Value operations in order to parse the value.
Use the Parse function to process a value. The Parse function will call a specific sequence of Value functions (operations) to process the value.
```typescript
const R = Value.Parse(Type.String(), 'hello') // const R: string = "hello"

const E = Value.Parse(Type.String(), undefined) // throws AssertError
```
The default sequence of Value operations is `Clone` `Clean`, `Default`, `Convert`, `Assert` and `Decode`. You can override this sequence in the following way.
The specific sequence of Value operations is `Clone` `Clean`, `Default`, `Convert`, `Assert` and `Decode`. You can specify user defined sequences in the following way.
```typescript
// Will only Assert the value a String
// Same as calling the Assert() function

const E = Value.Parse(['Assert'], Type.String(), 12345)

// Will Convert first, then Assert.
// Same as calling the Convert() then Assert() functions.

const S = Value.Parse(['Convert', 'Assert'], Type.String(), 12345)
```
When specifying user defined sequences, the return type of Parse will be unknown.
<a name='values-equal'></a>
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ export class TypeCheck<T extends TSchema> {
public Code(): string {
return this.code
}
/** Returns the schema type used to validate */
public Schema(): T {
return this.schema
}
/** Returns reference types used to validate */
public References(): TSchema[] {
return this.references
}
/** Returns an iterator for each error in this value. */
public Errors(value: unknown): ValueErrorIterator {
return Errors(this.schema, this.references, value)
Expand Down
9 changes: 5 additions & 4 deletions src/value/parse/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,15 @@ function ParseValue<Type extends TSchema, Result extends StaticDecode<Type> = St
// ------------------------------------------------------------------
// Parse
// ------------------------------------------------------------------
/** Parses a value using the specified operations. */
export function Parse<Type extends TSchema, Output = StaticDecode<Type>, Result extends Output = Output>(operations: TParseOperation[], schema: Type, references: TSchema[], value: unknown): Result
/** Parses a value using the specified operations. */
export function Parse<Type extends TSchema, Output = StaticDecode<Type>, Result extends Output = Output>(operations: TParseOperation[], schema: Type, value: unknown): Result

/** Parses a value using the default parse pipeline. Will throws an `AssertError` if invalid. */
export function Parse<Type extends TSchema, Output = StaticDecode<Type>, Result extends Output = Output>(schema: Type, references: TSchema[], value: unknown): Result
/** Parses a value using the default parse pipeline. Will throws an `AssertError` if invalid. */
export function Parse<Type extends TSchema, Output = StaticDecode<Type>, Result extends Output = Output>(schema: Type, value: unknown): Result
/** Parses a value using the specified operations. */
export function Parse<Type extends TSchema>(operations: TParseOperation[], schema: Type, references: TSchema[], value: unknown): unknown
/** Parses a value using the specified operations. */
export function Parse<Type extends TSchema>(operations: TParseOperation[], schema: Type, value: unknown): unknown
/** Parses a value */
export function Parse(...args: any[]): unknown {
// prettier-ignore
Expand Down
20 changes: 20 additions & 0 deletions test/runtime/compiler/__members.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { TypeCompiler } from '@sinclair/typebox/compiler'
import { Type, TypeGuard, ValueGuard } from '@sinclair/typebox'
import { Assert } from '../assert/index'

describe('compiler/TypeCheckMembers', () => {
it('Should return Schema', () => {
const A = TypeCompiler.Compile(Type.Number(), [Type.String(), Type.Boolean()])
Assert.IsTrue(TypeGuard.IsNumber(A.Schema()))
})
it('Should return References', () => {
const A = TypeCompiler.Compile(Type.Number(), [Type.String(), Type.Boolean()])
Assert.IsTrue(TypeGuard.IsNumber(A.Schema()))
Assert.IsTrue(TypeGuard.IsString(A.References()[0]))
Assert.IsTrue(TypeGuard.IsBoolean(A.References()[1]))
})
it('Should return Code', () => {
const A = TypeCompiler.Compile(Type.Number(), [Type.String(), Type.Boolean()])
Assert.IsTrue(ValueGuard.IsString(A.Code()))
})
})
1 change: 1 addition & 0 deletions test/runtime/compiler/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import './__members'
import './any'
import './array'
import './async-iterator'
Expand Down
39 changes: 37 additions & 2 deletions test/runtime/value/parse/parse.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Value, AssertError } from '@sinclair/typebox/value'
import { Type } from '@sinclair/typebox'
import { Value, AssertError, ParseRegistry } from '@sinclair/typebox/value'
import { Type, TypeGuard } from '@sinclair/typebox'
import { Assert } from '../../assert/index'

// prettier-ignore
Expand Down Expand Up @@ -87,4 +87,39 @@ describe('value/Parse', () => {
const X = Value.Parse(T, 'world')
Assert.IsEqual(X, 'hello')
})
// ----------------------------------------------------------------
// Operations
// ----------------------------------------------------------------
it('Should run operations 1', () => {
const A = Type.Object({ x: Type.Number() })
const I = { x: 1 }
const O = Value.Parse([], A, I)
Assert.IsTrue(I === O)
})
it('Should run operations 2', () => {
const A = Type.Object({ x: Type.Number() })
const I = { x: 1 }
const O = Value.Parse(['Clone'], A, I)
Assert.IsTrue(I !== O)
})
it('Should run operations 3', () => {
ParseRegistry.Set('Intercept', ( schema, references, value) => { throw 1 })
const A = Type.Object({ x: Type.Number() })
Assert.Throws(() => Value.Parse(['Intercept'], A, null))
ParseRegistry.Delete('Intercept')
const F = ParseRegistry.Get('Intercept')
Assert.IsEqual(F, undefined)
})
it('Should run operations 4', () => {
ParseRegistry.Set('Intercept', ( schema, references, value) => {
Assert.IsEqual(value, 12345)
Assert.IsTrue(TypeGuard.IsNumber(schema))
Assert.IsTrue(TypeGuard.IsString(references[0]))
})
Value.Parse(['Intercept'], Type.Number(), [Type.String()], 12345)
ParseRegistry.Delete('Intercept')
})
it('Should run operations 5', () => {
Assert.Throws(() => Value.Parse(['Intercept'], Type.String(), null))
})
})

0 comments on commit b2960fe

Please sign in to comment.