Skip to content

Commit

Permalink
Revision 0.32.0
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Nov 30, 2023
1 parent 573cdb1 commit 1950a1d
Show file tree
Hide file tree
Showing 376 changed files with 18,447 additions and 6,727 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
node: [16.x, 18.x, 20.x]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install Node
uses: actions/setup-node@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
node: [20.x]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install Node
uses: actions/setup-node@v3
with:
Expand Down
5 changes: 0 additions & 5 deletions benchmark/measurement/index.ts

This file was deleted.

97 changes: 97 additions & 0 deletions changelog/0.32.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
## [0.32.0](https://www.npmjs.com/package/@sinclair/typebox/v/0.32.0)

## Overview

Revision 0.32.0 is milestone revision. This revision carries out a complete modularization of `Type.*` and `Value.*`, as well as remodelling the TypeBox API to support selectively importing individual types. In addition to project restructuring, this revision also includes two new Types (`Const` and `Deref`) two new Value functions (`Clean` and `Default`) as well as many additional optimizations to type inference.

This is a significant revision for TypeBox. The updates in this revision should not break most users, however, many internal inference types that were previously exported on `typebox.ts` have been made private within module. Testing has been carried out to ensure the documented frontend for TypeBox is retained, however due to internal inference types being made fully private. Some users may experience some breakage.

A minor revision is required.

## Contents

- Enhancements
- [Modularization](#Modularization)
- [Types](#Modularization-Types)
- [Values](#Modularization-Values)
- [Bundle Size](#Modularization-Bundle-Size)
- [Types](#Types)
- [Const](#Const)
- [Deref](#Deref)
- [Values](#Values)
- [Clean](#Clean)
- [Default](#Default)
- Deprecations
- [RegExp](#RegExp)
- [TypeSystem Format](#TypeSystemFormat)
- [TypeSystem Type](#TypeSystemType)
- Breaking
- [JsonTypeBuilder and JavaScriptTypeBuilder](#JsonTypeBuilder-and-JavaScriptTypeBuilder)
- [TypeSystemPolicy](#TypeSystemPolicy)

## Modularization

Revision 0.32.0 carries out a complete restructuring of TypeBox's internals to modularize the type system. These updates enable for the following.

- Enable bundlers to properly tree-shake TypeBox's type system.
- Enable additional options for integrators re-exporting TypeBox's interface.
- Further optimize bundle sizes for Value and TypeCompiler.
- Improve maintainability of the type system.
- Make nessasarily provisions for ESM publishing.

### Types

Revision 0.32.0 now exposes `Type.*` as a default export as well as enables all types to be selectively imported. When importing selective types, bundlers may be able to tree-shake unused types. The following imports are now supported.

```typescript
import { Type, type Static } from '@sinclair/typebox' // classic
import Type, { type Static } from '@sinclair/typebox' // modern
import { Object, String, Number, ... } from '@sinclair/typebox' // selective
```
### Values
Revision 0.32.0 carries out modularization of `Value.*`. Individual Value functions can not be imported directly without specifying the sub module path.
```typescript
import { Value } from '@sinclair/typebox/value' // classic
import Value from '@sinclair/typebox/value' // modern
import { Check, Clone, Cast } from '@sinclair/typebox/value' // selective
```
### Bundle Size
The modularization in 0.32.0 has enabled significant bundle size optimizations across Value, TypeCompiler, Errors and System sub modules.
Revision 0.31.0
```
┌──────────────────────┬────────────┬────────────┬─────────────┐
│ (index) │ CompiledMinifiedCompression
├──────────────────────┼────────────┼────────────┼─────────────┤
typebox/compiler'163.6 kb'' 71.6 kb''2.28 x'
typebox/errors'113.3 kb'' 50.1 kb''2.26 x'
typebox/system' 83.9 kb'' 37.5 kb''2.24 x'
typebox/value'191.1 kb'' 82.3 kb''2.32 x'
typebox' 73.8 kb'' 32.3 kb''2.29 x'
└──────────────────────┴────────────┴────────────┴─────────────┘
```

Revision 0.32.0

```
┌──────────────────────┬────────────┬────────────┬─────────────┐
│ (index) │ Compiled │ Minified │ Compression │
├──────────────────────┼────────────┼────────────┼─────────────┤
│ typebox/compiler │ '109.3 kb' │ ' 48.5 kb' │ '2.25 x' │
│ typebox/errors │ ' 54.8 kb' │ ' 24.9 kb' │ '2.20 x' │
│ typebox/system │ ' 12.1 kb' │ ' 6.1 kb' │ '1.98 x' │
│ typebox/type │ ' 77.8 kb' │ ' 32.8 kb' │ '2.37 x' │
│ typebox/value │ '143.7 kb' │ ' 61.2 kb' │ '2.35 x' │
│ typebox │ ' 77.9 kb' │ ' 32.8 kb' │ '2.37 x' │
└──────────────────────┴────────────┴────────────┴─────────────┘
```
6 changes: 3 additions & 3 deletions examples/collections/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import { TypeCheck, TypeCompiler, ValueError } from '@sinclair/typebox/compiler'
import { TSchema, Static, TypeBoxError } from '@sinclair/typebox'
import { TSchema, Static } from '@sinclair/typebox'
import { Value } from '@sinclair/typebox/value'

// ----------------------------------------------------------------
// TypeArrayError
// ----------------------------------------------------------------
export class TypeArrayError extends TypeBoxError {
export class TypeArrayError extends Error {
constructor(message: string) {
super(`${message}`)
}
}
export class TypeArrayLengthError extends TypeBoxError {
export class TypeArrayLengthError extends Error {
constructor() {
super('arrayLength not a number')
}
Expand Down
6 changes: 3 additions & 3 deletions examples/collections/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import { TypeCheck, TypeCompiler, ValueError } from '@sinclair/typebox/compiler'
import { TSchema, Static, TypeBoxError } from '@sinclair/typebox'
import { TSchema, Static } from '@sinclair/typebox'
import { Value } from '@sinclair/typebox/value'

// ----------------------------------------------------------------
// TypeMapKeyError
// ----------------------------------------------------------------
export class TypeMapKeyError extends TypeBoxError {
export class TypeMapKeyError extends Error {
constructor(message: string) {
super(`${message} for key`)
}
}
export class TypeMapValueError extends TypeBoxError {
export class TypeMapValueError extends Error {
constructor(key: unknown, message: string) {
super(`${message} for key ${JSON.stringify(key)}`)
}
Expand Down
4 changes: 2 additions & 2 deletions examples/collections/set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import { TypeCheck, TypeCompiler, ValueError } from '@sinclair/typebox/compiler'
import { TSchema, Static, TypeBoxError } from '@sinclair/typebox'
import { TSchema, Static } from '@sinclair/typebox'
import { Value } from '@sinclair/typebox/value'

// ----------------------------------------------------------------
// Errors
// ----------------------------------------------------------------
export class TypeSetError extends TypeBoxError {
export class TypeSetError extends Error {
constructor(message: string) {
super(`${message}`)
}
Expand Down
3 changes: 1 addition & 2 deletions examples/prototypes/evaluate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import {
TTuple,
TProperties,
TIntersect,
IntersectType,
TUnion,
TNever
} from '@sinclair/typebox'
Expand Down Expand Up @@ -75,7 +74,7 @@ export type TEvaluateArray<T extends TSchema[]> = T extends [infer L, ...infer
[]
// prettier-ignore
export type TEvaluate<T extends TSchema> =
T extends TIntersect<infer S> ? IntersectType<TEvaluateIntersectRest<S>> :
T extends TIntersect<infer S> ? TIntersect<TEvaluateIntersectRest<S>> :
T extends TUnion<infer S> ? TUnion<TEvaluateArray<S>> :
T extends TConstructor<infer P, infer R> ? TConstructor<TEvaluateArray<P>, TEvaluate<R>> :
T extends TFunction<infer P, infer R> ? TFunction<TEvaluateArray<P>, TEvaluate<R>> :
Expand Down
1 change: 0 additions & 1 deletion examples/prototypes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

export * from './const'
export * from './evaluate'
export * from './partial-deep'
export * from './union-enum'
Expand Down
9 changes: 5 additions & 4 deletions examples/prototypes/partial-deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,18 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import { TypeGuard, Type, TSchema, TIntersect, TUnion, TObject, TPartial, TProperties, AssertRest, AssertType, Evaluate } from '@sinclair/typebox'
import { TypeGuard, Type, TSchema, TIntersect, TUnion, TObject, TPartial, TProperties, Evaluate } from '@sinclair/typebox'

// -------------------------------------------------------------------------------------
// TDeepPartial
// -------------------------------------------------------------------------------------
export type TPartialDeepProperties<T extends TProperties> = {
[K in keyof T]: TPartial<T[K]>
}
export type TPartialDeepRest<T extends TSchema[]> = T extends [infer L, ...infer R]
? [TPartial<AssertType<L>>, ...TPartialDeepRest<AssertRest<R>>]
: []
export type TPartialDeepRest<T extends TSchema[]> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? [TPartial<L>, ...TPartialDeepRest<R>]
: []
export type TPartialDeep<T extends TSchema> =
T extends TIntersect<infer S> ? TIntersect<TPartialDeepRest<S>> :
T extends TUnion<infer S> ? TUnion<TPartialDeepRest<S>> :
Expand Down
23 changes: 6 additions & 17 deletions examples/typedef/typedef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,10 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import { TypeSystemErrorFunction, DefaultErrorFunction } from '@sinclair/typebox/system'
import * as Types from '@sinclair/typebox'
import * as Types from '@sinclair/typebox/type/index.mjs'

// --------------------------------------------------------------------------
// Utility Types
// --------------------------------------------------------------------------
export type Assert<T, U> = T extends U ? T : never
export type Base = { m: string, t: string }
export type Base16 = { m: 'F', t: '01', '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9', '9': 'A', 'A': 'B', 'B': 'C', 'C': 'D', 'D': 'E', 'E': 'F', 'F': '0' }
export type Base10 = { m: '9', t: '01', '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9', '9': '0' }
export type Reverse<T extends string> = T extends `${infer L}${infer R}` ? `${Reverse<R>}${L}` : T
export type Tick<T extends string, B extends Base> = T extends keyof B ? B[T] : never
export type Next<T extends string, B extends Base> = T extends Assert<B, Base>['m'] ? Assert<B, Base>['t'] : T extends `${infer L}${infer R}` ? L extends Assert<B, Base>['m'] ? `${Assert<Tick<L, B>, string>}${Next<R, B>}` : `${Assert<Tick<L, B>, string>}${R}` : never
export type Increment<T extends string, B extends Base = Base10> = Reverse<Next<Reverse<T>, B>>
// --------------------------------------------------------------------------
// SchemaOptions
// Metadata
// --------------------------------------------------------------------------
export interface Metadata {
[name: string]: any
Expand All @@ -65,8 +54,8 @@ export interface TBoolean extends Types.TSchema {
// --------------------------------------------------------------------------
// TUnion
// --------------------------------------------------------------------------
type InferUnion<T extends TStruct[], D extends string, Index = string> = T extends [infer L, ...infer R]
? Types.Evaluate<{ [_ in D]: Index } & Types.Static<Types.AssertType<L>>> | InferUnion<Types.AssertRest<R>, D, Increment<Types.Assert<Index, string>>>
export type InferUnion<T extends TStruct[], D extends string, Index = string> = T extends [infer L, ...infer R]
? Types.Evaluate<{ [_ in D]: Index } & Types.Static<Types.AssertType<L>>> | InferUnion<Types.AssertRest<R>, D, Types.Increment<Types.Assert<Index, string>>>
: never

export interface TUnion<T extends TStruct[] = TStruct[], D extends string = string> extends Types.TSchema {
Expand Down Expand Up @@ -177,7 +166,7 @@ export interface StructMetadata extends Metadata {
}
export interface TStruct<T extends TFields = TFields> extends Types.TSchema, StructMetadata {
[Types.Kind]: 'TypeDef:Struct'
static: Types.PropertiesReduce<T, this['params']>
static: Types.ObjectResolve<T, this['params']>
optionalProperties: { [K in Types.Assert<OptionalKeys<T>, keyof T>]: T[K] }
properties: { [K in Types.Assert<RequiredKeys<T>, keyof T>]: T[K] }
}
Expand Down Expand Up @@ -240,7 +229,7 @@ export namespace TimestampFormat {
// --------------------------------------------------------------------------
// ValueCheck
// --------------------------------------------------------------------------
export class ValueCheckError extends Types.TypeBoxError {
export class ValueCheckError extends Error {
constructor(public readonly schema: Types.TSchema) {
super('Unknown type')
}
Expand Down
26 changes: 22 additions & 4 deletions hammer.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { compression, measurement } from './benchmark'
import { compression, measurement } from './task/benchmark'
import { convertToCommonJs } from './task/build'
import { readFileSync } from 'fs'

// -------------------------------------------------------------------------------
// Clean
// -------------------------------------------------------------------------------
export async function clean() {
await folder('node_modules/typebox').delete()
await folder('target').delete()
}
// -------------------------------------------------------------------------------
// Format
// -------------------------------------------------------------------------------
export async function format() {
await shell('prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write src test examples/index.ts benchmark')
await shell('prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write src test task examples/index.ts')
}
// -------------------------------------------------------------------------------
// Start
Expand Down Expand Up @@ -56,15 +58,31 @@ export async function test(filter = '') {
// -------------------------------------------------------------------------------
// Build
// -------------------------------------------------------------------------------
export async function build_esm(target = 'target/build/esm') {
await shell(`tsc -p ./src/tsconfig.json --outDir ${target} --target ESNext --module ESNext --declaration`)
}
export async function build_cjs(target = 'target/build/cjs') {
await shell(`tsc -p ./src/tsconfig.json --outDir ${target} -target ES2020 --module CommonJS`)
convertToCommonJs(target)
}
export async function build(target = 'target/build') {
await test()
await folder(target).delete()
await shell(`tsc -p ./src/tsconfig.json --outDir ${target}`)
await test()
await build_cjs(`${target}/cjs`)
await build_esm(`${target}/esm`)
await folder(target).add('package.json')
await folder(target).add('readme.md')
await folder(target).add('license')
await shell(`cd ${target} && npm pack`)
}
// -------------------------------------------------------------------------------
// Install
// -------------------------------------------------------------------------------
export async function install_local(target = 'target/typebox') {
await clean()
await build(target)
await folder('node_modules').add(target)
}
// -------------------------------------------------------------
// Publish
// -------------------------------------------------------------
Expand Down
Loading

0 comments on commit 1950a1d

Please sign in to comment.