@sinclair/typebox 0.23.5 → 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,319 +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;
87
- constructor() {
88
- this.schemas = new Map();
89
- }
90
- /** `Standard` Modifies an object property to be both readonly and optional */
41
+ // ----------------------------------------------------------------------
42
+ // Modifiers
43
+ // ----------------------------------------------------------------------
44
+ /** Creates a readonly optional property */
91
45
  ReadonlyOptional(item) {
92
- return { ...item, modifier: exports.ReadonlyOptionalModifier };
46
+ return { [exports.Modifier]: 'ReadonlyOptional', ...item };
93
47
  }
94
- /** `Standard` Modifies an object property to be readonly */
48
+ /** Creates a readonly property */
95
49
  Readonly(item) {
96
- return { ...item, modifier: exports.ReadonlyModifier };
50
+ return { [exports.Modifier]: 'Readonly', ...item };
97
51
  }
98
- /** `Standard` Modifies an object property to be optional */
52
+ /** Creates a optional property */
99
53
  Optional(item) {
100
- return { ...item, modifier: exports.OptionalModifier };
101
- }
102
- /** `Standard` Creates a type type */
103
- Tuple(items, options = {}) {
104
- const additionalItems = false;
105
- const minItems = items.length;
106
- const maxItems = items.length;
107
- const schema = ((items.length > 0)
108
- ? { ...options, kind: exports.TupleKind, type: 'array', items, additionalItems, minItems, maxItems }
109
- : { ...options, kind: exports.TupleKind, type: 'array', minItems, maxItems });
110
- return this.Store(schema);
54
+ return { [exports.Modifier]: 'Optional', ...item };
111
55
  }
112
- /** `Standard` Creates an object type with the given properties */
113
- Object(properties, options = {}) {
114
- const property_names = Object.keys(properties);
115
- const optional = property_names.filter(name => {
116
- const candidate = properties[name];
117
- return (candidate.modifier &&
118
- (candidate.modifier === exports.OptionalModifier ||
119
- candidate.modifier === exports.ReadonlyOptionalModifier));
120
- });
121
- const required_names = property_names.filter(name => !optional.includes(name));
122
- const required = (required_names.length > 0) ? required_names : undefined;
123
- return this.Store(((required)
124
- ? { ...options, kind: exports.ObjectKind, type: 'object', properties, required }
125
- : { ...options, kind: exports.ObjectKind, type: 'object', properties }));
126
- }
127
- /** `Standard` Creates an intersect type. */
128
- Intersect(items, options = {}) {
129
- return this.Store({ ...options, kind: exports.IntersectKind, type: 'object', allOf: items });
130
- }
131
- /** `Standard` Creates a union type */
132
- Union(items, options = {}) {
133
- 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' });
134
62
  }
135
- /** `Standard` Creates an array type */
63
+ /** Creates a array type */
136
64
  Array(items, options = {}) {
137
- return this.Store({ ...options, kind: exports.ArrayKind, type: 'array', items });
65
+ return this.Create({ ...options, [exports.Kind]: 'Array', type: 'array', items });
138
66
  }
139
- /** `Standard` Creates an enum type from a TypeScript enum */
140
- Enum(item, options = {}) {
141
- const values = Object.keys(item).filter(key => isNaN(key)).map(key => item[key]);
142
- const anyOf = values.map(value => typeof value === 'string' ? { type: 'string', const: value } : { type: 'number', const: value });
143
- return this.Store({ ...options, kind: exports.EnumKind, anyOf });
144
- }
145
- /** `Standard` Creates a literal type. Supports string, number and boolean values only */
146
- Literal(value, options = {}) {
147
- return this.Store({ ...options, kind: exports.LiteralKind, const: value, type: typeof value });
67
+ /** Creates a boolean type */
68
+ Boolean(options = {}) {
69
+ return this.Create({ ...options, [exports.Kind]: 'Boolean', type: 'boolean' });
148
70
  }
149
- /** `Standard` Creates a string type */
150
- String(options = {}) {
151
- return this.Store({ ...options, kind: exports.StringKind, type: 'string' });
71
+ /** Creates a constructor type */
72
+ Constructor(parameters, returns, options = {}) {
73
+ return this.Create({ ...options, [exports.Kind]: 'Constructor', type: 'constructor', parameters, returns });
152
74
  }
153
- /** `Standard` Creates a string type from a regular expression */
154
- RegEx(regex, options = {}) {
155
- return this.String({ ...options, pattern: regex.source });
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 });
156
82
  }
157
- /** `Standard` Creates a number type */
158
- Number(options = {}) {
159
- return this.Store({ ...options, kind: exports.NumberKind, type: 'number' });
83
+ /** Creates a function type */
84
+ Function(parameters, returns, options = {}) {
85
+ return this.Create({ ...options, [exports.Kind]: 'Function', type: 'function', parameters, returns });
160
86
  }
161
- /** `Standard` Creates an integer type */
87
+ /** Creates a integer type */
162
88
  Integer(options = {}) {
163
- 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
+ }
164
120
  }
165
- /** `Standard` Creates a boolean type */
166
- Boolean(options = {}) {
167
- 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 });
168
125
  }
169
- /** `Standard` Creates a null type */
170
- Null(options = {}) {
171
- 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 });
172
129
  }
173
- /** `Standard` Creates an unknown type */
174
- Unknown(options = {}) {
175
- 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' });
176
133
  }
177
- /** `Standard` Creates an any type */
178
- Any(options = {}) {
179
- 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' });
180
137
  }
181
- /** `Standard` Creates a record type */
182
- Record(key, value, options = {}) {
183
- const pattern = (() => {
184
- switch (key.kind) {
185
- case exports.UnionKind: return `^${key.anyOf.map((literal) => literal.const).join('|')}$`;
186
- case exports.KeyOfKind: return `^${key.enum.join('|')}$`;
187
- case exports.NumberKind: return '^(0|[1-9][0-9]*)$';
188
- case exports.StringKind: return key.pattern ? key.pattern : '^.*$';
189
- default: throw Error('Invalid Record Key');
190
- }
191
- })();
192
- 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
+ }
193
153
  }
194
- /** `Standard` Creates a keyof type from the given object */
195
- KeyOf(object, options = {}) {
196
- const source = this.Deref(object);
197
- const keys = Object.keys(source.properties);
198
- return this.Store({ ...options, kind: exports.KeyOfKind, type: 'string', enum: keys });
199
- }
200
- /** `Standard` Makes all properties in the given object type required */
201
- Required(object, options = {}) {
202
- const source = this.Deref(object);
203
- const schema = { ...clone(source), ...options };
204
- schema.required = Object.keys(schema.properties);
205
- for (const key of Object.keys(schema.properties)) {
206
- const property = schema.properties[key];
207
- switch (property.modifier) {
208
- case exports.ReadonlyOptionalModifier:
209
- 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';
210
174
  break;
211
- case exports.ReadonlyModifier:
212
- property.modifier = exports.ReadonlyModifier;
175
+ case 'Readonly':
176
+ property[exports.Modifier] = 'ReadonlyOptional';
213
177
  break;
214
- case exports.OptionalModifier:
215
- delete property.modifier;
178
+ case 'Optional':
179
+ property[exports.Modifier] = 'Optional';
216
180
  break;
217
181
  default:
218
- delete property.modifier;
182
+ property[exports.Modifier] = 'Optional';
219
183
  break;
220
184
  }
221
185
  }
222
- return this.Store(schema);
223
- }
224
- /** `Standard` Makes all properties in the given object type optional */
225
- Partial(object, options = {}) {
226
- const source = this.Deref(object);
227
- const schema = { ...clone(source), ...options };
228
- delete schema.required;
229
- for (const key of Object.keys(schema.properties)) {
230
- const property = schema.properties[key];
231
- switch (property.modifier) {
232
- case exports.ReadonlyOptionalModifier:
233
- 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';
234
248
  break;
235
- case exports.ReadonlyModifier:
236
- property.modifier = exports.ReadonlyOptionalModifier;
249
+ case 'Readonly':
250
+ property[exports.Modifier] = 'Readonly';
237
251
  break;
238
- case exports.OptionalModifier:
239
- property.modifier = exports.OptionalModifier;
252
+ case 'Optional':
253
+ delete property[exports.Modifier];
240
254
  break;
241
255
  default:
242
- property.modifier = exports.OptionalModifier;
256
+ delete property[exports.Modifier];
243
257
  break;
244
258
  }
245
259
  }
246
- return this.Store(schema);
247
- }
248
- /** `Standard` Picks property keys from the given object type */
249
- Pick(object, keys, options = {}) {
250
- const source = this.Deref(object);
251
- const schema = { ...clone(source), ...options };
252
- schema.required = schema.required ? schema.required.filter((key) => keys.includes(key)) : undefined;
253
- for (const key of Object.keys(schema.properties)) {
254
- if (!keys.includes(key))
255
- delete schema.properties[key];
256
- }
257
- return this.Store(schema);
258
- }
259
- /** `Standard` Omits property keys from the given object type */
260
- Omit(object, keys, options = {}) {
261
- const source = this.Deref(object);
262
- const schema = { ...clone(source), ...options };
263
- schema.required = schema.required ? schema.required.filter((key) => !keys.includes(key)) : undefined;
264
- for (const key of Object.keys(schema.properties)) {
265
- if (keys.includes(key))
266
- delete schema.properties[key];
267
- }
268
- return this.Store(schema);
269
- }
270
- /** `Standard` Omits the `kind` and `modifier` properties from the underlying schema */
271
- Strict(schema, options = {}) {
272
- return JSON.parse(JSON.stringify({ ...options, ...schema }));
260
+ return this.Create(next);
273
261
  }
274
- /** `Extended` Creates a constructor type */
275
- Constructor(args, returns, options = {}) {
276
- 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));
277
265
  }
278
- /** `Extended` Creates a function type */
279
- Function(args, returns, options = {}) {
280
- 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' });
281
269
  }
282
- /** `Extended` Creates a promise type */
283
- Promise(item, options = {}) {
284
- 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);
285
277
  }
286
- /** `Extended` Creates a undefined type */
278
+ /** Creates a undefined type */
287
279
  Undefined(options = {}) {
288
- 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 });
289
285
  }
290
- /** `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 */
291
299
  Void(options = {}) {
292
- return this.Store({ ...options, type: 'void', kind: exports.VoidKind });
293
- }
294
- /** `Standard` Creates a namespace for a set of related types */
295
- Namespace($defs, options = {}) {
296
- return this.Store({ ...options, kind: exports.NamespaceKind, $defs });
297
- }
298
- Ref(...args) {
299
- if (args.length === 2) {
300
- const namespace = args[0];
301
- const targetKey = args[1];
302
- if (namespace.$id === undefined)
303
- throw new Error(`Referenced namespace has no $id`);
304
- if (!this.schemas.has(namespace.$id))
305
- throw new Error(`Unable to locate namespace with $id '${namespace.$id}'`);
306
- 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
+ }), {}));
307
318
  }
308
- else if (args.length === 1) {
309
- const target = args[0];
310
- if (target.$id === undefined)
311
- throw new Error(`Referenced schema has no $id`);
312
- if (!this.schemas.has(target.$id))
313
- throw new Error(`Unable to locate schema with $id '${target.$id}'`);
314
- return this.Store({ kind: exports.RefKind, $ref: target.$id });
319
+ else if (isArray(value)) {
320
+ return value.map((item) => this.Clone(item));
315
321
  }
316
322
  else {
317
- throw new Error('Type.Ref: Invalid arguments');
323
+ return value;
318
324
  }
319
325
  }
320
- /** `Experimental` Creates a recursive type */
321
- Rec(callback, options = {}) {
322
- const $id = options.$id || '';
323
- const self = callback({ $ref: `${$id}#/$defs/self` });
324
- return this.Store({ ...options, $ref: `${$id}#/$defs/self`, $defs: { self } });
325
- }
326
- /** Conditionally stores and schema if it contains an $id and returns */
327
- Store(schema) {
328
- const $schema = schema;
329
- if (!$schema['$id'])
330
- return $schema;
331
- this.schemas.set($schema['$id'], $schema);
332
- return $schema;
333
- }
334
- /** Conditionally dereferences a schema if RefKind. Otherwise return argument */
335
- Deref(schema) {
336
- const $schema = schema;
337
- if ($schema['kind'] !== exports.RefKind)
338
- return schema;
339
- if (!this.schemas.has($schema['$ref']))
340
- throw Error(`Unable to locate schema with $id '${$schema['$ref']}'`);
341
- return this.Deref(this.schemas.get($schema['$ref']));
342
- }
343
326
  }
344
327
  exports.TypeBuilder = TypeBuilder;
328
+ /** JSON Schema Type Builder with Static Type Resolution for TypeScript */
345
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
+ }