@sinclair/typebox 0.20.2 → 0.20.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinclair/typebox",
3
- "version": "0.20.2",
3
+ "version": "0.20.6",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "json-schema",
@@ -23,14 +23,14 @@
23
23
  "test": "hammer task spec"
24
24
  },
25
25
  "devDependencies": {
26
- "@sinclair/hammer": "^0.12.1",
26
+ "@sinclair/hammer": "^0.15.7",
27
27
  "@types/chai": "^4.2.16",
28
28
  "@types/mocha": "^8.2.2",
29
29
  "@types/node": "^14.14.37",
30
30
  "ajv": "^8.6.2",
31
31
  "ajv-formats": "^2.0.2",
32
32
  "chai": "^4.3.4",
33
- "mocha": "^8.3.2",
34
- "typescript": "^4.3.5"
33
+ "mocha": "^9.1.2",
34
+ "typescript": "^4.5.2"
35
35
  }
36
36
  }
package/readme.md CHANGED
@@ -38,7 +38,7 @@ type T = Static<typeof T> // type T = string
38
38
 
39
39
  ## Overview
40
40
 
41
- TypeBox is a library that creates in-memory JSON Schema objects that can be statically resolved to TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox allows one to create a unified type that can be statically checked by the TypeScript compiler and runtime asserted using standard JSON Schema validation.
41
+ TypeBox is a library that builds in-memory JSON Schema objects that can be statically resolved to TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox allows one to create a unified type that can be statically checked by the TypeScript compiler and runtime asserted using standard JSON Schema validation.
42
42
 
43
43
  TypeBox can be used as a simple tool to build up complex schemas or integrated into RPC or REST services to help validate JSON data received over the wire. TypeBox does not provide any JSON schema validation. Please use libraries such as AJV to validate schemas built with this library.
44
44
 
@@ -59,6 +59,7 @@ License MIT
59
59
  - [Extended Types](#Extended-Types)
60
60
  - [Strict](#Strict)
61
61
  - [Validation](#Validation)
62
+ - [OpenAPI](#OpenAPI)
62
63
 
63
64
  <a name="Example"></a>
64
65
 
@@ -307,7 +308,7 @@ The following table outlines the TypeBox mappings between TypeScript and JSON sc
307
308
  │ Type.Number() │ │ y: { │
308
309
  │ ) │ │ type: 'number' │
309
310
  │ }) │ │ } │
310
- │ ) │ │ }
311
+ │ ) │ │ },
311
312
  │ │ │ required: ['x', 'y'] │
312
313
  │ │ │ } │
313
314
  │ │ │ │
@@ -383,7 +384,7 @@ TypeBox provides modifiers that can be applied to an objects properties. This al
383
384
 
384
385
  ### Options
385
386
 
386
- You can pass additional JSON schema properties on the last argument of any given type. The following are some examples.
387
+ You can pass additional JSON schema options on the last argument of any given type. The following are some examples.
387
388
 
388
389
  ```typescript
389
390
  // string must be an email
@@ -695,25 +696,25 @@ Referenced types can be added to AJV with the `ajv.addSchema(...)` function. The
695
696
  ```typescript
696
697
  //--------------------------------------------------------------------------------------------
697
698
  //
698
- // Common Types
699
+ // Shared Types
699
700
  //
700
701
  //--------------------------------------------------------------------------------------------
701
702
 
702
- const Common = Type.Box({
703
+ const Shared = Type.Box({
703
704
  UserId: Type.String({ format: 'uuid' }),
704
705
  Email: Type.String({ format: 'email' })
705
- }, { $id: 'Common' })
706
+ }, { $id: 'Shared' })
706
707
 
707
708
  //--------------------------------------------------------------------------------------------
708
709
  //
709
- // Setup AJV validator with the following options and formats
710
+ // Setup Validator and Register Shared Types
710
711
  //
711
712
  //--------------------------------------------------------------------------------------------
712
713
 
713
714
  const ajv = addFormats(new Ajv({}), [...])
714
715
  .addKeyword('kind')
715
716
  .addKeyword('modifier')
716
- .addSchema(Common) // <-- Register Common Types
717
+ .addSchema(Shared) // <-- Register Shared Types
717
718
 
718
719
  //--------------------------------------------------------------------------------------------
719
720
  //
@@ -722,8 +723,8 @@ const ajv = addFormats(new Ajv({}), [...])
722
723
  //--------------------------------------------------------------------------------------------
723
724
 
724
725
  const User = Type.Object({
725
- userId: Type.Ref(Common, 'UserId'),
726
- email: Type.Ref(Common, 'Email'),
726
+ userId: Type.Ref(Shared, 'UserId'),
727
+ email: Type.Ref(Shared, 'Email'),
727
728
  online: Type.Boolean()
728
729
  }, { additionalProperties: false })
729
730
 
@@ -741,4 +742,47 @@ const ok = ajv.validate(User, {
741
742
 
742
743
  ```
743
744
 
744
- Please refer to the official AJV [documentation](https://ajv.js.org/guide/getting-started.html) for more information on using this validator.
745
+ Please refer to the official AJV [documentation](https://ajv.js.org/guide/getting-started.html) for additional information.
746
+
747
+ ### OpenAPI
748
+
749
+ TypeBox can be used to create schemas for OpenAPI, however users should be aware of the various differences between the JSON Schema and OpenAPI specifications. Two common instances where OpenAPI diverges from the JSON Schema specification is OpenAPI's handling of `string enum` and `nullable`. The following shows how you can use TypeBox to construct these types.
750
+
751
+ ```typescript
752
+ import { Type, Static, TNull, TLiteral, TUnion, TSchema } from '@sinclair/typebox'
753
+
754
+ //--------------------------------------------------------------------------------------------
755
+ //
756
+ // Nullable<T>
757
+ //
758
+ //--------------------------------------------------------------------------------------------
759
+
760
+ function Nullable<T extends TSchema>(schema: T): TUnion<[T, TNull]> {
761
+ return { ...schema, nullable: true } as any
762
+ }
763
+
764
+ const T = Nullable(Type.String()) // const T = {
765
+ // type: 'string',
766
+ // nullable: true
767
+ // }
768
+
769
+ type T = Static<typeof T> // type T = string | null
770
+
771
+ //--------------------------------------------------------------------------------------------
772
+ //
773
+ // StringUnion<[...]>
774
+ //
775
+ //--------------------------------------------------------------------------------------------
776
+
777
+ type IntoStringUnion<T> = {[K in keyof T]: T[K] extends string ? TLiteral<T[K]>: never }
778
+
779
+ function StringUnion<T extends string[]>(values: [...T]): TUnion<IntoStringUnion<T>> {
780
+ return { enum: values } as any
781
+ }
782
+
783
+ const T = StringUnion(['A', 'B', 'C']) // const T = {
784
+ // enum: ['A', 'B', 'C']
785
+ // }
786
+
787
+ type T = Static<typeof T> // type T = 'A' | 'B' | 'C'
788
+ ```
package/typebox.d.ts CHANGED
@@ -60,10 +60,6 @@ export declare type NumberOptions = {
60
60
  export declare type IntersectOptions = {
61
61
  unevaluatedProperties?: boolean;
62
62
  } & CustomOptions;
63
- export declare type IndexedOptions = {
64
- minProperties?: number;
65
- maxProperties?: number;
66
- } & CustomOptions;
67
63
  export declare type ObjectOptions = {
68
64
  additionalProperties?: boolean;
69
65
  } & CustomOptions;
@@ -88,8 +84,8 @@ export declare type TBox<T extends TDefinitions> = {
88
84
  export declare type TTuple<T extends TSchema[]> = {
89
85
  kind: typeof TupleKind;
90
86
  type: 'array';
91
- items: [...T];
92
- additionalItems: false;
87
+ items?: [...T];
88
+ additionalItems?: false;
93
89
  minItems: number;
94
90
  maxItems: number;
95
91
  } & CustomOptions;
@@ -200,24 +196,24 @@ export declare type UnionToIntersect<U> = (U extends any ? (k: U) => void : neve
200
196
  export declare type ObjectPropertyKeys<T> = T extends TObject<infer U> ? PropertyKeys<U> : never;
201
197
  export declare type PropertyKeys<T extends TProperties> = keyof T;
202
198
  export declare type ReadonlyOptionalPropertyKeys<T extends TProperties> = {
203
- [K in keyof T]: T[K] extends TReadonlyOptional<infer U> ? K : never;
199
+ [K in keyof T]: T[K] extends TReadonlyOptional<TSchema> ? K : never;
204
200
  }[keyof T];
205
201
  export declare type ReadonlyPropertyKeys<T extends TProperties> = {
206
- [K in keyof T]: T[K] extends TReadonly<infer U> ? K : never;
202
+ [K in keyof T]: T[K] extends TReadonly<TSchema> ? K : never;
207
203
  }[keyof T];
208
204
  export declare type OptionalPropertyKeys<T extends TProperties> = {
209
- [K in keyof T]: T[K] extends TOptional<infer U> ? K : never;
205
+ [K in keyof T]: T[K] extends TOptional<TSchema> ? K : never;
210
206
  }[keyof T];
211
207
  export declare type RequiredPropertyKeys<T extends TProperties> = keyof Omit<T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>;
212
208
  export declare type ReduceModifiers<T extends object> = {
213
209
  [K in keyof T]: T[K];
214
210
  };
215
211
  export declare type StaticModifiers<T extends TProperties> = {
216
- readonly [K in ReadonlyOptionalPropertyKeys<T>]?: Static<T[K]>;
212
+ readonly [K in ReadonlyOptionalPropertyKeys<T>]?: T[K] extends TReadonlyOptional<infer U> ? Static<U> : never;
217
213
  } & {
218
- readonly [K in ReadonlyPropertyKeys<T>]: Static<T[K]>;
214
+ readonly [K in ReadonlyPropertyKeys<T>]: T[K] extends TReadonly<infer U> ? Static<U> : never;
219
215
  } & {
220
- [K in OptionalPropertyKeys<T>]?: Static<T[K]>;
216
+ [K in OptionalPropertyKeys<T>]?: T[K] extends TOptional<infer U> ? Static<U> : never;
221
217
  } & {
222
218
  [K in RequiredPropertyKeys<T>]: Static<T[K]>;
223
219
  };
@@ -240,12 +236,8 @@ export declare type StaticRecord<K extends TRecordKey, T extends TSchema> = K ex
240
236
  } : never : never;
241
237
  export declare type StaticArray<T extends TSchema> = Array<Static<T>>;
242
238
  export declare type StaticLiteral<T extends TValue> = T;
243
- export declare type StaticConstructor<T extends readonly TSchema[], U extends TSchema> = new (...args: [...{
244
- [K in keyof T]: Static<T[K]>;
245
- }]) => Static<U>;
246
- export declare type StaticFunction<T extends readonly TSchema[], U extends TSchema> = (...args: [...{
247
- [K in keyof T]: Static<T[K]>;
248
- }]) => Static<U>;
239
+ export declare type StaticConstructor<T extends readonly TSchema[], U extends TSchema> = new (...args: unknown[]) => Static<U>;
240
+ export declare type StaticFunction<T extends readonly TSchema[], U extends TSchema> = (...args: unknown[]) => Static<U>;
249
241
  export declare type StaticPromise<T extends TSchema> = Promise<Static<T>>;
250
242
  export declare type Static<T> = T extends TKeyOf<infer U> ? StaticKeyOf<U> : T extends TIntersect<infer U> ? StaticIntersect<U> : T extends TUnion<infer U> ? StaticUnion<U> : T extends TTuple<infer U> ? StaticTuple<U> : T extends TObject<infer U> ? StaticObject<U> : T extends TRecord<infer K, infer U> ? StaticRecord<K, U> : T extends TArray<infer U> ? StaticArray<U> : T extends TEnum<infer U> ? StaticEnum<U> : T extends TLiteral<infer U> ? StaticLiteral<U> : T extends TString ? string : T extends TNumber ? number : T extends TInteger ? number : T extends TBoolean ? boolean : T extends TNull ? null : T extends TUnknown ? unknown : T extends TAny ? any : T extends TConstructor<infer U, infer R> ? StaticConstructor<U, R> : T extends TFunction<infer U, infer R> ? StaticFunction<U, R> : T extends TPromise<infer U> ? StaticPromise<U> : T extends TUndefined ? undefined : T extends TVoid ? void : never;
251
243
  export declare class TypeBuilder {
package/typebox.js CHANGED
@@ -99,7 +99,9 @@ class TypeBuilder {
99
99
  const additionalItems = false;
100
100
  const minItems = items.length;
101
101
  const maxItems = items.length;
102
- return { ...options, kind: exports.TupleKind, type: 'array', items, additionalItems, minItems, maxItems };
102
+ return (items.length > 0)
103
+ ? { ...options, kind: exports.TupleKind, type: 'array', items, additionalItems, minItems, maxItems }
104
+ : { ...options, kind: exports.TupleKind, type: 'array', minItems, maxItems };
103
105
  }
104
106
  /** `STANDARD` Creates a `object` schema with the given properties. */
105
107
  Object(properties, options = {}) {