@sinclair/typebox 0.23.3 → 0.24.0

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/typebox.js CHANGED
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  /*--------------------------------------------------------------------------
3
3
 
4
- TypeBox: JSON Schema Type Builder with Static Type Resolution for TypeScript
4
+ @sinclair/typebox
5
5
 
6
6
  The MIT License (MIT)
7
7
 
8
- Copyright (c) 2021 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
8
+ Copyright (c) 2022 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
9
9
 
10
10
  Permission is hereby granted, free of charge, to any person obtaining a copy
11
11
  of this software and associated documentation files (the "Software"), to deal
@@ -27,316 +27,303 @@ THE SOFTWARE.
27
27
 
28
28
  ---------------------------------------------------------------------------*/
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.Type = exports.TypeBuilder = exports.VoidKind = exports.UndefinedKind = exports.PromiseKind = exports.FunctionKind = exports.ConstructorKind = exports.RefKind = exports.AnyKind = exports.UnknownKind = exports.NullKind = exports.BooleanKind = exports.IntegerKind = exports.NumberKind = exports.StringKind = exports.LiteralKind = exports.EnumKind = exports.ArrayKind = exports.RecordKind = exports.ObjectKind = exports.TupleKind = exports.UnionKind = exports.IntersectKind = exports.KeyOfKind = exports.NamespaceKind = exports.ReadonlyModifier = exports.OptionalModifier = exports.ReadonlyOptionalModifier = void 0;
30
+ exports.Type = exports.TypeBuilder = exports.Modifier = exports.Kind = void 0;
31
31
  // --------------------------------------------------------------------------
32
- // Modifiers
32
+ // Symbols
33
33
  // --------------------------------------------------------------------------
34
- exports.ReadonlyOptionalModifier = Symbol('ReadonlyOptionalModifier');
35
- exports.OptionalModifier = Symbol('OptionalModifier');
36
- exports.ReadonlyModifier = Symbol('ReadonlyModifier');
37
- // --------------------------------------------------------------------------
38
- // Schema Standard
39
- // --------------------------------------------------------------------------
40
- exports.NamespaceKind = Symbol('NamespaceKind');
41
- exports.KeyOfKind = Symbol('KeyOfKind');
42
- exports.IntersectKind = Symbol('IntersectKind');
43
- exports.UnionKind = Symbol('UnionKind');
44
- exports.TupleKind = Symbol('TupleKind');
45
- exports.ObjectKind = Symbol('ObjectKind');
46
- exports.RecordKind = Symbol('RecordKind');
47
- exports.ArrayKind = Symbol('ArrayKind');
48
- exports.EnumKind = Symbol('EnumKind');
49
- exports.LiteralKind = Symbol('LiteralKind');
50
- exports.StringKind = Symbol('StringKind');
51
- exports.NumberKind = Symbol('NumberKind');
52
- exports.IntegerKind = Symbol('IntegerKind');
53
- exports.BooleanKind = Symbol('BooleanKind');
54
- exports.NullKind = Symbol('NullKind');
55
- exports.UnknownKind = Symbol('UnknownKind');
56
- exports.AnyKind = Symbol('AnyKind');
57
- exports.RefKind = Symbol('RefKind');
58
- // --------------------------------------------------------------------------
59
- // Extended Schema Types
60
- // --------------------------------------------------------------------------
61
- exports.ConstructorKind = Symbol('ConstructorKind');
62
- exports.FunctionKind = Symbol('FunctionKind');
63
- exports.PromiseKind = Symbol('PromiseKind');
64
- exports.UndefinedKind = Symbol('UndefinedKind');
65
- exports.VoidKind = Symbol('VoidKind');
66
- // --------------------------------------------------------------------------
67
- // Utility
68
- // --------------------------------------------------------------------------
69
- function isObject(object) {
70
- return typeof object === 'object' && object !== null && !Array.isArray(object);
71
- }
72
- function isArray(object) {
73
- return typeof object === 'object' && object !== null && Array.isArray(object);
74
- }
75
- function clone(object) {
76
- if (isObject(object))
77
- return Object.keys(object).reduce((acc, key) => ({ ...acc, [key]: clone(object[key]) }), {});
78
- if (isArray(object))
79
- return object.map((item) => clone(item));
80
- return object;
81
- }
34
+ exports.Kind = Symbol.for('TypeBox.Kind');
35
+ exports.Modifier = Symbol.for('TypeBox.Modifier');
82
36
  // --------------------------------------------------------------------------
83
37
  // TypeBuilder
84
38
  // --------------------------------------------------------------------------
39
+ let TypeOrdinal = 0;
85
40
  class TypeBuilder {
86
- schemas = new Map();
87
- /** `Standard` Modifies an object property to be both readonly and optional */
41
+ // ----------------------------------------------------------------------
42
+ // Modifiers
43
+ // ----------------------------------------------------------------------
44
+ /** Creates a readonly optional property */
88
45
  ReadonlyOptional(item) {
89
- return { ...item, modifier: exports.ReadonlyOptionalModifier };
46
+ return { [exports.Modifier]: 'ReadonlyOptional', ...item };
90
47
  }
91
- /** `Standard` Modifies an object property to be readonly */
48
+ /** Creates a readonly property */
92
49
  Readonly(item) {
93
- return { ...item, modifier: exports.ReadonlyModifier };
50
+ return { [exports.Modifier]: 'Readonly', ...item };
94
51
  }
95
- /** `Standard` Modifies an object property to be optional */
52
+ /** Creates a optional property */
96
53
  Optional(item) {
97
- return { ...item, modifier: exports.OptionalModifier };
98
- }
99
- /** `Standard` Creates a type type */
100
- Tuple(items, options = {}) {
101
- const additionalItems = false;
102
- const minItems = items.length;
103
- const maxItems = items.length;
104
- const schema = ((items.length > 0)
105
- ? { ...options, kind: exports.TupleKind, type: 'array', items, additionalItems, minItems, maxItems }
106
- : { ...options, kind: exports.TupleKind, type: 'array', minItems, maxItems });
107
- return this.Store(schema);
54
+ return { [exports.Modifier]: 'Optional', ...item };
108
55
  }
109
- /** `Standard` Creates an object type with the given properties */
110
- Object(properties, options = {}) {
111
- const property_names = Object.keys(properties);
112
- const optional = property_names.filter(name => {
113
- const candidate = properties[name];
114
- return (candidate.modifier &&
115
- (candidate.modifier === exports.OptionalModifier ||
116
- candidate.modifier === exports.ReadonlyOptionalModifier));
117
- });
118
- const required_names = property_names.filter(name => !optional.includes(name));
119
- const required = (required_names.length > 0) ? required_names : undefined;
120
- return this.Store(((required)
121
- ? { ...options, kind: exports.ObjectKind, type: 'object', properties, required }
122
- : { ...options, kind: exports.ObjectKind, type: 'object', properties }));
123
- }
124
- /** `Standard` Creates an intersect type. */
125
- Intersect(items, options = {}) {
126
- return this.Store({ ...options, kind: exports.IntersectKind, type: 'object', allOf: items });
127
- }
128
- /** `Standard` Creates a union type */
129
- Union(items, options = {}) {
130
- return this.Store({ ...options, kind: exports.UnionKind, anyOf: items });
56
+ // ----------------------------------------------------------------------
57
+ // Types
58
+ // ----------------------------------------------------------------------
59
+ /** Creates a any type */
60
+ Any(options = {}) {
61
+ return this.Create({ ...options, [exports.Kind]: 'Any' });
131
62
  }
132
- /** `Standard` Creates an array type */
63
+ /** Creates a array type */
133
64
  Array(items, options = {}) {
134
- return this.Store({ ...options, kind: exports.ArrayKind, type: 'array', items });
65
+ return this.Create({ ...options, [exports.Kind]: 'Array', type: 'array', items });
135
66
  }
136
- /** `Standard` Creates an enum type from a TypeScript enum */
137
- Enum(item, options = {}) {
138
- const values = Object.keys(item).filter(key => isNaN(key)).map(key => item[key]);
139
- const anyOf = values.map(value => typeof value === 'string' ? { type: 'string', const: value } : { type: 'number', const: value });
140
- return this.Store({ ...options, kind: exports.EnumKind, anyOf });
67
+ /** Creates a boolean type */
68
+ Boolean(options = {}) {
69
+ return this.Create({ ...options, [exports.Kind]: 'Boolean', type: 'boolean' });
141
70
  }
142
- /** `Standard` Creates a literal type. Supports string, number and boolean values only */
143
- Literal(value, options = {}) {
144
- return this.Store({ ...options, kind: exports.LiteralKind, const: value, type: typeof value });
71
+ /** Creates a constructor type */
72
+ Constructor(parameters, returns, options = {}) {
73
+ return this.Create({ ...options, [exports.Kind]: 'Constructor', type: 'constructor', parameters, returns });
145
74
  }
146
- /** `Standard` Creates a string type */
147
- String(options = {}) {
148
- return this.Store({ ...options, kind: exports.StringKind, type: 'string' });
75
+ /** Creates a enum type */
76
+ Enum(item, options = {}) {
77
+ const values = Object.keys(item)
78
+ .filter((key) => isNaN(key))
79
+ .map((key) => item[key]);
80
+ const anyOf = values.map((value) => (typeof value === 'string' ? { [exports.Kind]: 'Literal', type: 'string', const: value } : { [exports.Kind]: 'Literal', type: 'number', const: value }));
81
+ return this.Create({ ...options, [exports.Kind]: 'Union', anyOf });
149
82
  }
150
- /** `Standard` Creates a string type from a regular expression */
151
- RegEx(regex, options = {}) {
152
- return this.String({ ...options, pattern: regex.source });
83
+ /** Creates a function type */
84
+ Function(parameters, returns, options = {}) {
85
+ return this.Create({ ...options, [exports.Kind]: 'Function', type: 'function', parameters, returns });
153
86
  }
154
- /** `Standard` Creates a number type */
155
- Number(options = {}) {
156
- return this.Store({ ...options, kind: exports.NumberKind, type: 'number' });
157
- }
158
- /** `Standard` Creates an integer type */
87
+ /** Creates a integer type */
159
88
  Integer(options = {}) {
160
- return this.Store({ ...options, kind: exports.IntegerKind, type: 'integer' });
89
+ return this.Create({ ...options, [exports.Kind]: 'Integer', type: 'integer' });
90
+ }
91
+ /** Creates a intersect type. */
92
+ Intersect(objects, options = {}) {
93
+ const isOptional = (schema) => (schema[exports.Modifier] && schema[exports.Modifier] === 'Optional') || schema[exports.Modifier] === 'ReadonlyOptional';
94
+ const [required, optional] = [new Set(), new Set()];
95
+ for (const object of objects) {
96
+ for (const [key, schema] of Object.entries(object.properties)) {
97
+ if (isOptional(schema))
98
+ optional.add(key);
99
+ }
100
+ }
101
+ for (const object of objects) {
102
+ for (const key of Object.keys(object.properties)) {
103
+ if (!optional.has(key))
104
+ required.add(key);
105
+ }
106
+ }
107
+ const properties = {};
108
+ for (const object of objects) {
109
+ for (const [key, schema] of Object.entries(object.properties)) {
110
+ delete schema[exports.Modifier];
111
+ properties[key] = properties[key] === undefined ? schema : { [exports.Kind]: 'Union', anyOf: [properties[key], { ...schema }] };
112
+ }
113
+ }
114
+ if (required.size > 0) {
115
+ return this.Create({ ...options, [exports.Kind]: 'Object', type: 'object', properties, required: [...required] });
116
+ }
117
+ else {
118
+ return this.Create({ ...options, [exports.Kind]: 'Object', type: 'object', properties });
119
+ }
161
120
  }
162
- /** `Standard` Creates a boolean type */
163
- Boolean(options = {}) {
164
- return this.Store({ ...options, kind: exports.BooleanKind, type: 'boolean' });
121
+ /** Creates a keyof type */
122
+ KeyOf(object, options = {}) {
123
+ const items = Object.keys(object.properties).map((key) => this.Create({ ...options, [exports.Kind]: 'Literal', type: 'string', const: key }));
124
+ return this.Create({ ...options, [exports.Kind]: 'Union', anyOf: items });
165
125
  }
166
- /** `Standard` Creates a null type */
167
- Null(options = {}) {
168
- return this.Store({ ...options, kind: exports.NullKind, type: 'null' });
126
+ /** Creates a literal type. */
127
+ Literal(value, options = {}) {
128
+ return this.Create({ ...options, [exports.Kind]: 'Literal', const: value, type: typeof value });
169
129
  }
170
- /** `Standard` Creates an unknown type */
171
- Unknown(options = {}) {
172
- return this.Store({ ...options, kind: exports.UnknownKind });
130
+ /** Creates a null type */
131
+ Null(options = {}) {
132
+ return this.Create({ ...options, [exports.Kind]: 'Null', type: 'null' });
173
133
  }
174
- /** `Standard` Creates an any type */
175
- Any(options = {}) {
176
- return this.Store({ ...options, kind: exports.AnyKind });
134
+ /** Creates a number type */
135
+ Number(options = {}) {
136
+ return this.Create({ ...options, [exports.Kind]: 'Number', type: 'number' });
177
137
  }
178
- /** `Standard` Creates a record type */
179
- Record(key, value, options = {}) {
180
- const pattern = (() => {
181
- switch (key.kind) {
182
- case exports.UnionKind: return `^${key.anyOf.map((literal) => literal.const).join('|')}$`;
183
- case exports.KeyOfKind: return `^${key.enum.join('|')}$`;
184
- case exports.NumberKind: return '^(0|[1-9][0-9]*)$';
185
- case exports.StringKind: return key.pattern ? key.pattern : '^.*$';
186
- default: throw Error('Invalid Record Key');
187
- }
188
- })();
189
- return this.Store({ ...options, kind: exports.RecordKind, type: 'object', patternProperties: { [pattern]: value } });
138
+ /** Creates an object type with the given properties */
139
+ Object(properties, options = {}) {
140
+ const property_names = Object.keys(properties);
141
+ const optional = property_names.filter((name) => {
142
+ const property = properties[name];
143
+ const modifier = property[exports.Modifier];
144
+ return modifier && (modifier === 'Optional' || modifier === 'ReadonlyOptional');
145
+ });
146
+ const required = property_names.filter((name) => !optional.includes(name));
147
+ if (required.length > 0) {
148
+ return this.Create({ ...options, [exports.Kind]: 'Object', type: 'object', properties, required });
149
+ }
150
+ else {
151
+ return this.Create({ ...options, [exports.Kind]: 'Object', type: 'object', properties });
152
+ }
190
153
  }
191
- /** `Standard` Creates a keyof type from the given object */
192
- KeyOf(object, options = {}) {
193
- const source = this.Deref(object);
194
- const keys = Object.keys(source.properties);
195
- return this.Store({ ...options, kind: exports.KeyOfKind, type: 'string', enum: keys });
196
- }
197
- /** `Standard` Makes all properties in the given object type required */
198
- Required(object, options = {}) {
199
- const source = this.Deref(object);
200
- const schema = { ...clone(source), ...options };
201
- schema.required = Object.keys(schema.properties);
202
- for (const key of Object.keys(schema.properties)) {
203
- const property = schema.properties[key];
204
- switch (property.modifier) {
205
- case exports.ReadonlyOptionalModifier:
206
- property.modifier = exports.ReadonlyModifier;
154
+ /** Creates a new object whose properties are omitted from the given object */
155
+ Omit(schema, keys, options = {}) {
156
+ const next = { ...this.Clone(schema), ...options };
157
+ next.required = next.required ? next.required.filter((key) => !keys.includes(key)) : undefined;
158
+ for (const key of Object.keys(next.properties)) {
159
+ if (keys.includes(key))
160
+ delete next.properties[key];
161
+ }
162
+ return this.Create(next);
163
+ }
164
+ /** Creates an object type whose properties are all optional */
165
+ Partial(schema, options = {}) {
166
+ const next = { ...this.Clone(schema), ...options };
167
+ delete next.required;
168
+ for (const key of Object.keys(next.properties)) {
169
+ const property = next.properties[key];
170
+ const modifer = property[exports.Modifier];
171
+ switch (modifer) {
172
+ case 'ReadonlyOptional':
173
+ property[exports.Modifier] = 'ReadonlyOptional';
207
174
  break;
208
- case exports.ReadonlyModifier:
209
- property.modifier = exports.ReadonlyModifier;
175
+ case 'Readonly':
176
+ property[exports.Modifier] = 'ReadonlyOptional';
210
177
  break;
211
- case exports.OptionalModifier:
212
- delete property.modifier;
178
+ case 'Optional':
179
+ property[exports.Modifier] = 'Optional';
213
180
  break;
214
181
  default:
215
- delete property.modifier;
182
+ property[exports.Modifier] = 'Optional';
216
183
  break;
217
184
  }
218
185
  }
219
- return this.Store(schema);
220
- }
221
- /** `Standard` Makes all properties in the given object type optional */
222
- Partial(object, options = {}) {
223
- const source = this.Deref(object);
224
- const schema = { ...clone(source), ...options };
225
- delete schema.required;
226
- for (const key of Object.keys(schema.properties)) {
227
- const property = schema.properties[key];
228
- switch (property.modifier) {
229
- case exports.ReadonlyOptionalModifier:
230
- property.modifier = exports.ReadonlyOptionalModifier;
186
+ return this.Create(next);
187
+ }
188
+ /** Creates a new object whose properties are picked from the given object */
189
+ Pick(schema, keys, options = {}) {
190
+ const next = { ...this.Clone(schema), ...options };
191
+ next.required = next.required ? next.required.filter((key) => keys.includes(key)) : undefined;
192
+ for (const key of Object.keys(next.properties)) {
193
+ if (!keys.includes(key))
194
+ delete next.properties[key];
195
+ }
196
+ return this.Create(next);
197
+ }
198
+ /** Creates a promise type. This type cannot be represented in schema. */
199
+ Promise(item, options = {}) {
200
+ return this.Create({ ...options, [exports.Kind]: 'Promise', type: 'promise', item });
201
+ }
202
+ /** Creates a record type */
203
+ Record(key, value, options = {}) {
204
+ // If string literal union return TObject with properties extracted from union.
205
+ if (key[exports.Kind] === 'Union') {
206
+ return this.Object(key.anyOf.reduce((acc, literal) => {
207
+ return { ...acc, [literal.const]: value };
208
+ }, {}), { ...options });
209
+ }
210
+ // otherwise return TRecord with patternProperties
211
+ const pattern = key[exports.Kind] === 'Number' ? '^(0|[1-9][0-9]*)$' : key[exports.Kind] === 'String' && key.pattern ? key.pattern : '^.*$';
212
+ return this.Create({
213
+ ...options,
214
+ [exports.Kind]: 'Record',
215
+ type: 'object',
216
+ patternProperties: { [pattern]: value },
217
+ additionalProperties: false,
218
+ });
219
+ }
220
+ /** Creates a recursive object type */
221
+ Recursive(callback, options = {}) {
222
+ if (options.$id === undefined)
223
+ options.$id = `type-${TypeOrdinal++}`;
224
+ const self = callback({ [exports.Kind]: 'Self', $ref: `${options.$id}` });
225
+ self.$id = options.$id;
226
+ return this.Create({ ...options, ...self });
227
+ }
228
+ /** Creates a reference schema */
229
+ Ref(schema, options = {}) {
230
+ if (schema.$id === undefined)
231
+ throw Error('Cannot create reference schema as target schema as has no $id');
232
+ return this.Create({ ...options, [exports.Kind]: 'Ref', $ref: schema.$id });
233
+ }
234
+ /** Creates a string type from a regular expression */
235
+ RegEx(regex, options = {}) {
236
+ return this.Create({ ...options, [exports.Kind]: 'String', type: 'string', pattern: regex.source });
237
+ }
238
+ /** Creates an object type whose properties are all required */
239
+ Required(schema, options = {}) {
240
+ const next = { ...this.Clone(schema), ...options };
241
+ next.required = Object.keys(next.properties);
242
+ for (const key of Object.keys(next.properties)) {
243
+ const property = next.properties[key];
244
+ const modifier = property[exports.Modifier];
245
+ switch (modifier) {
246
+ case 'ReadonlyOptional':
247
+ property[exports.Modifier] = 'Readonly';
231
248
  break;
232
- case exports.ReadonlyModifier:
233
- property.modifier = exports.ReadonlyOptionalModifier;
249
+ case 'Readonly':
250
+ property[exports.Modifier] = 'Readonly';
234
251
  break;
235
- case exports.OptionalModifier:
236
- property.modifier = exports.OptionalModifier;
252
+ case 'Optional':
253
+ delete property[exports.Modifier];
237
254
  break;
238
255
  default:
239
- property.modifier = exports.OptionalModifier;
256
+ delete property[exports.Modifier];
240
257
  break;
241
258
  }
242
259
  }
243
- return this.Store(schema);
244
- }
245
- /** `Standard` Picks property keys from the given object type */
246
- Pick(object, keys, options = {}) {
247
- const source = this.Deref(object);
248
- const schema = { ...clone(source), ...options };
249
- schema.required = schema.required ? schema.required.filter((key) => keys.includes(key)) : undefined;
250
- for (const key of Object.keys(schema.properties)) {
251
- if (!keys.includes(key))
252
- delete schema.properties[key];
253
- }
254
- return this.Store(schema);
255
- }
256
- /** `Standard` Omits property keys from the given object type */
257
- Omit(object, keys, options = {}) {
258
- const source = this.Deref(object);
259
- const schema = { ...clone(source), ...options };
260
- schema.required = schema.required ? schema.required.filter((key) => !keys.includes(key)) : undefined;
261
- for (const key of Object.keys(schema.properties)) {
262
- if (keys.includes(key))
263
- delete schema.properties[key];
264
- }
265
- return this.Store(schema);
266
- }
267
- /** `Standard` Omits the `kind` and `modifier` properties from the underlying schema */
268
- Strict(schema, options = {}) {
269
- return JSON.parse(JSON.stringify({ ...options, ...schema }));
260
+ return this.Create(next);
270
261
  }
271
- /** `Extended` Creates a constructor type */
272
- Constructor(args, returns, options = {}) {
273
- return this.Store({ ...options, kind: exports.ConstructorKind, type: 'constructor', arguments: args, returns });
262
+ /** Removes Kind and Modifier symbol property keys from this schema */
263
+ Strict(schema) {
264
+ return JSON.parse(JSON.stringify(schema));
274
265
  }
275
- /** `Extended` Creates a function type */
276
- Function(args, returns, options = {}) {
277
- return this.Store({ ...options, kind: exports.FunctionKind, type: 'function', arguments: args, returns });
266
+ /** Creates a string type */
267
+ String(options = {}) {
268
+ return this.Create({ ...options, [exports.Kind]: 'String', type: 'string' });
278
269
  }
279
- /** `Extended` Creates a promise type */
280
- Promise(item, options = {}) {
281
- return this.Store({ ...options, type: 'promise', kind: exports.PromiseKind, item });
270
+ /** Creates a tuple type */
271
+ Tuple(items, options = {}) {
272
+ const additionalItems = false;
273
+ const minItems = items.length;
274
+ const maxItems = items.length;
275
+ const schema = (items.length > 0 ? { ...options, [exports.Kind]: 'Tuple', type: 'array', items, additionalItems, minItems, maxItems } : { ...options, [exports.Kind]: 'Tuple', type: 'array', minItems, maxItems });
276
+ return this.Create(schema);
282
277
  }
283
- /** `Extended` Creates a undefined type */
278
+ /** Creates a undefined type */
284
279
  Undefined(options = {}) {
285
- return this.Store({ ...options, type: 'undefined', kind: exports.UndefinedKind });
280
+ return this.Create({ ...options, [exports.Kind]: 'Undefined', type: 'object', specialized: 'Undefined' });
281
+ }
282
+ /** Creates a union type */
283
+ Union(items, options = {}) {
284
+ return this.Create({ ...options, [exports.Kind]: 'Union', anyOf: items });
286
285
  }
287
- /** `Extended` Creates a void type */
286
+ /** Creates a Uint8Array type */
287
+ Uint8Array(options = {}) {
288
+ return this.Create({ ...options, [exports.Kind]: 'Uint8Array', type: 'object', specialized: 'Uint8Array' });
289
+ }
290
+ /** Creates an unknown type */
291
+ Unknown(options = {}) {
292
+ return this.Create({ ...options, [exports.Kind]: 'Unknown' });
293
+ }
294
+ /** Creates a user defined schema that infers as type T */
295
+ Unsafe(options = {}) {
296
+ return this.Create({ ...options, [exports.Kind]: 'Unknown' });
297
+ }
298
+ /** Creates a void type */
288
299
  Void(options = {}) {
289
- return this.Store({ ...options, type: 'void', kind: exports.VoidKind });
290
- }
291
- /** `Standard` Creates a namespace for a set of related types */
292
- Namespace($defs, options = {}) {
293
- return this.Store({ ...options, kind: exports.NamespaceKind, $defs });
294
- }
295
- Ref(...args) {
296
- if (args.length === 2) {
297
- const namespace = args[0];
298
- const targetKey = args[1];
299
- if (namespace.$id === undefined)
300
- throw new Error(`Referenced namespace has no $id`);
301
- if (!this.schemas.has(namespace.$id))
302
- throw new Error(`Unable to locate namespace with $id '${namespace.$id}'`);
303
- return this.Store({ kind: exports.RefKind, $ref: `${namespace.$id}#/$defs/${targetKey}` });
300
+ return this.Create({ ...options, [exports.Kind]: 'Void', type: 'null' });
301
+ }
302
+ /** Use this function to return TSchema with static and params omitted */
303
+ Create(schema) {
304
+ return schema;
305
+ }
306
+ /** Clones the given value */
307
+ Clone(value) {
308
+ const isObject = (object) => typeof object === 'object' && object !== null && !Array.isArray(object);
309
+ const isArray = (object) => typeof object === 'object' && object !== null && Array.isArray(object);
310
+ if (isObject(value)) {
311
+ return Object.keys(value).reduce((acc, key) => ({
312
+ ...acc,
313
+ [key]: this.Clone(value[key]),
314
+ }), Object.getOwnPropertySymbols(value).reduce((acc, key) => ({
315
+ ...acc,
316
+ [key]: this.Clone(value[key]),
317
+ }), {}));
304
318
  }
305
- else if (args.length === 1) {
306
- const target = args[0];
307
- if (target.$id === undefined)
308
- throw new Error(`Referenced schema has no $id`);
309
- if (!this.schemas.has(target.$id))
310
- throw new Error(`Unable to locate schema with $id '${target.$id}'`);
311
- return this.Store({ kind: exports.RefKind, $ref: target.$id });
319
+ else if (isArray(value)) {
320
+ return value.map((item) => this.Clone(item));
312
321
  }
313
322
  else {
314
- throw new Error('Type.Ref: Invalid arguments');
323
+ return value;
315
324
  }
316
325
  }
317
- /** `Experimental` Creates a recursive type */
318
- Rec(callback, options = {}) {
319
- const $id = options.$id || '';
320
- const self = callback({ $ref: `${$id}#/$defs/self` });
321
- return this.Store({ ...options, $ref: `${$id}#/$defs/self`, $defs: { self } });
322
- }
323
- /** Conditionally stores and schema if it contains an $id and returns */
324
- Store(schema) {
325
- const $schema = schema;
326
- if (!$schema['$id'])
327
- return $schema;
328
- this.schemas.set($schema['$id'], $schema);
329
- return $schema;
330
- }
331
- /** Conditionally dereferences a schema if RefKind. Otherwise return argument */
332
- Deref(schema) {
333
- const $schema = schema;
334
- if ($schema['kind'] !== exports.RefKind)
335
- return schema;
336
- if (!this.schemas.has($schema['$ref']))
337
- throw Error(`Unable to locate schema with $id '${$schema['$ref']}'`);
338
- return this.Deref(this.schemas.get($schema['$ref']));
339
- }
340
326
  }
341
327
  exports.TypeBuilder = TypeBuilder;
328
+ /** JSON Schema Type Builder with Static Type Resolution for TypeScript */
342
329
  exports.Type = new TypeBuilder();
@@ -0,0 +1,5 @@
1
+ import * as Types from '../typebox';
2
+ export declare namespace CheckValue {
3
+ function Visit<T extends Types.TSchema>(schema: T, value: any): boolean;
4
+ function Check<T extends Types.TSchema>(schema: T, value: any): boolean;
5
+ }