Skip to content

Commit

Permalink
Revision 0.31.27 (#671)
Browse files Browse the repository at this point in the history
* Clone Date and Uint8Array types

* Date Default is  Current Time

* Tests
  • Loading branch information
sinclairzx81 authored Nov 19, 2023
1 parent 06bd0b8 commit ea217cc
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 15 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sinclair/typebox",
"version": "0.31.26",
"version": "0.31.27",
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
"keywords": [
"typescript",
Expand Down
26 changes: 22 additions & 4 deletions src/typebox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,10 @@ export namespace ValueGuard {
export function IsBoolean(value: unknown): value is boolean {
return typeof value === 'boolean'
}
/** Returns true if this value is a Date object */
export function IsDate(value: unknown): value is Date {
return value instanceof globalThis.Date
}
/** Returns true if this value is null */
export function IsNull(value: unknown): value is null {
return value === null
Expand All @@ -1103,6 +1107,10 @@ export namespace ValueGuard {
export function IsString(value: unknown): value is string {
return typeof value === 'string'
}
/** Returns true if this value is a Uint8Array */
export function IsUint8Array(value: unknown): value is Uint8Array {
return value instanceof globalThis.Uint8Array
}
/** Returns true if this value is undefined */
export function IsUndefined(value: unknown): value is undefined {
return value === undefined
Expand Down Expand Up @@ -2287,19 +2295,29 @@ export namespace TypeExtends {
// --------------------------------------------------------------------------
/** Specialized Clone for Types */
export namespace TypeClone {
function ArrayType(value: unknown[]) {
return (value as any).map((value: unknown) => Visit(value as any))
}
function DateType(value: Date) {
return new Date(value.getTime())
}
function Uint8ArrayType(value: Uint8Array) {
return new Uint8Array(value)
}
function ObjectType(value: Record<keyof any, unknown>) {
const clonedProperties = Object.getOwnPropertyNames(value).reduce((acc, key) => ({ ...acc, [key]: Visit(value[key]) }), {})
const clonedSymbols = Object.getOwnPropertySymbols(value).reduce((acc, key) => ({ ...acc, [key]: Visit(value[key as any]) }), {})
return { ...clonedProperties, ...clonedSymbols }
}
function ArrayType(value: unknown[]) {
return (value as any).map((value: unknown) => Visit(value as any))
}
function Visit(value: unknown): any {
// prettier-ignore
return ValueGuard.IsArray(value) ? ArrayType(value) :
return (
ValueGuard.IsArray(value) ? ArrayType(value) :
ValueGuard.IsDate(value) ? DateType(value) :
ValueGuard.IsUint8Array(value) ? Uint8ArrayType(value) :
ValueGuard.IsObject(value) ? ObjectType(value) :
value
)
}
/** Clones a Rest */
export function Rest<T extends TSchema[]>(schemas: [...T]): T {
Expand Down
2 changes: 1 addition & 1 deletion src/value/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ function TDate(schema: Types.TDate, references: Types.TSchema[]): any {
} else if (schema.minimumTimestamp !== undefined) {
return new Date(schema.minimumTimestamp)
} else {
return new Date(0)
return new Date()
}
}
function TFunction(schema: Types.TFunction, references: Types.TSchema[]): any {
Expand Down
5 changes: 5 additions & 0 deletions test/runtime/assert/assert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ export namespace Assert {
export function NotEqual(actual: unknown, expect: unknown) {
return assert.notEqual(actual, expect)
}
/** Asserts a numeric value is within range of the expected */
export function InRange(value: number, expect: number, range: number) {
if (Math.abs(value - expect) <= range) return
throw Error('Expected value to be in range')
}
let nextIdOrdinal = 0
export function NextId() {
return `$id-${nextIdOrdinal++}`
Expand Down
10 changes: 5 additions & 5 deletions test/runtime/value/cast/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@ describe('value/cast/Date', () => {
it('Should upcast from string', () => {
const value = 'world'
const result = Value.Cast(T, value)
Assert.IsEqual(result, E)
Assert.InRange(result.getTime(), new Date().getTime(), 1000)
})
it('Should upcast from object', () => {
const value = {}
const result = Value.Cast(T, value)
Assert.IsEqual(result, E)
Assert.InRange(result.getTime(), new Date().getTime(), 1000)
})
it('Should upcast from array', () => {
const value = [1]
const result = Value.Cast(T, value)
Assert.IsEqual(result, E)
Assert.InRange(result.getTime(), new Date().getTime(), 1000)
})
it('Should upcast from undefined', () => {
const value = undefined
const result = Value.Cast(T, value)
Assert.IsEqual(result, E)
Assert.InRange(result.getTime(), new Date().getTime(), 1000)
})
it('Should upcast from null', () => {
const value = null
const result = Value.Cast(T, value)
Assert.IsEqual(result, E)
Assert.InRange(result.getTime(), new Date().getTime(), 1000)
})
it('Should preseve', () => {
const value = new Date(100)
Expand Down
30 changes: 30 additions & 0 deletions test/runtime/value/create/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Value } from '@sinclair/typebox/value'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../assert/index'

describe('value/create/Date', () => {
it('Should create value', () => {
const T = Type.Date()
const A = Value.Create(T)
const B = new Date()
Assert.InRange(A.getTime(), B.getTime(), 1000)
})
it('Should create default', () => {
const T = Type.Date({ default: new Date(1001) })
const A = Value.Create(T)
const B = new Date(1001)
Assert.IsEqual(A, B)
})
it('Should create value nested', () => {
const T = Type.Object({ value: Type.Date() })
const A = Value.Create(T)
const B = { value: new Date() }
Assert.InRange(A.value.getTime(), B.value.getTime(), 1000)
})
it('Should create default nested', () => {
const T = Type.Object({ value: Type.Date({ default: new Date(1001) }) })
const A = Value.Create(T)
const B = { value: new Date(1001) }
Assert.IsEqual(A, B)
})
})
1 change: 1 addition & 0 deletions test/runtime/value/create/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import './bigint'
import './boolean'
import './composite'
import './constructor'
import './date'
import './enum'
import './function'
import './integer'
Expand Down
8 changes: 8 additions & 0 deletions test/runtime/value/create/uint8array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ describe('value/create/Uint8Array', () => {
Assert.IsEqual(value.length, 4)
Assert.IsEqual([value[0], value[1], value[2], value[3]], [0, 0, 0, 0])
})
it('Should create value nested', () => {
const T = Type.Object({ value: Type.Uint8Array() })
Assert.IsEqual(Value.Create(T), { value: new Uint8Array() })
})
it('Should create default nested', () => {
const T = Type.Object({ value: Type.Date({ default: new Uint8Array([1, 2, 3, 4]) }) })
Assert.IsEqual(Value.Create(T), { value: new Uint8Array([1, 2, 3, 4]) })
})
})
4 changes: 2 additions & 2 deletions test/runtime/value/transform/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ describe('value/transform/Date', () => {
// --------------------------------------------------------
const T1 = Type.Transform(Type.Date())
.Decode((value) => 1)
.Encode((value) => new Date())
.Encode((value) => new Date(0))
it('Should decode mapped', () => {
const R = Encoder.Decode(T1, new Date())
const R = Encoder.Decode(T1, new Date(0))
Assert.IsEqual(R, 1)
})
it('Should encode mapped', () => {
Expand Down

0 comments on commit ea217cc

Please sign in to comment.