@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/compiler/compiler.d.ts +31 -0
- package/compiler/compiler.js +349 -0
- package/compiler/index.d.ts +1 -0
- package/compiler/index.js +40 -0
- package/license +1 -1
- package/package.json +6 -6
- package/readme.md +373 -358
- package/typebox.d.ts +315 -297
- package/typebox.js +247 -263
- package/value/check.d.ts +5 -0
- package/value/check.js +232 -0
- package/value/clone.d.ts +3 -0
- package/value/clone.js +94 -0
- package/value/create.d.ts +7 -0
- package/value/create.js +337 -0
- package/value/delta.d.ts +13 -0
- package/value/delta.js +191 -0
- package/value/index.d.ts +1 -0
- package/value/index.js +40 -0
- package/value/pointer.d.ts +12 -0
- package/value/pointer.js +110 -0
- package/value/reflect.d.ts +2 -0
- package/value/reflect.js +42 -0
- package/value/upcast.d.ts +4 -0
- package/value/upcast.js +247 -0
- package/value/value.d.ts +17 -0
- package/value/value.js +70 -0
package/typebox.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*--------------------------------------------------------------------------
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
@sinclair/typebox
|
|
5
5
|
|
|
6
6
|
The MIT License (MIT)
|
|
7
7
|
|
|
8
|
-
Copyright (c)
|
|
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.
|
|
30
|
+
exports.Type = exports.TypeBuilder = exports.Modifier = exports.Kind = void 0;
|
|
31
31
|
// --------------------------------------------------------------------------
|
|
32
|
-
//
|
|
32
|
+
// Symbols
|
|
33
33
|
// --------------------------------------------------------------------------
|
|
34
|
-
exports.
|
|
35
|
-
exports.
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
46
|
+
return { [exports.Modifier]: 'ReadonlyOptional', ...item };
|
|
93
47
|
}
|
|
94
|
-
/**
|
|
48
|
+
/** Creates a readonly property */
|
|
95
49
|
Readonly(item) {
|
|
96
|
-
return { ...item
|
|
50
|
+
return { [exports.Modifier]: 'Readonly', ...item };
|
|
97
51
|
}
|
|
98
|
-
/**
|
|
52
|
+
/** Creates a optional property */
|
|
99
53
|
Optional(item) {
|
|
100
|
-
return { ...item
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
/**
|
|
63
|
+
/** Creates a array type */
|
|
136
64
|
Array(items, options = {}) {
|
|
137
|
-
return this.
|
|
65
|
+
return this.Create({ ...options, [exports.Kind]: 'Array', type: 'array', items });
|
|
138
66
|
}
|
|
139
|
-
/**
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
/**
|
|
150
|
-
|
|
151
|
-
return this.
|
|
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
|
-
/**
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
/**
|
|
158
|
-
|
|
159
|
-
return this.
|
|
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
|
-
/**
|
|
87
|
+
/** Creates a integer type */
|
|
162
88
|
Integer(options = {}) {
|
|
163
|
-
return this.
|
|
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
|
-
/**
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
/**
|
|
170
|
-
|
|
171
|
-
return this.
|
|
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
|
-
/**
|
|
174
|
-
|
|
175
|
-
return this.
|
|
130
|
+
/** Creates a null type */
|
|
131
|
+
Null(options = {}) {
|
|
132
|
+
return this.Create({ ...options, [exports.Kind]: 'Null', type: 'null' });
|
|
176
133
|
}
|
|
177
|
-
/**
|
|
178
|
-
|
|
179
|
-
return this.
|
|
134
|
+
/** Creates a number type */
|
|
135
|
+
Number(options = {}) {
|
|
136
|
+
return this.Create({ ...options, [exports.Kind]: 'Number', type: 'number' });
|
|
180
137
|
}
|
|
181
|
-
/**
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
/**
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
|
212
|
-
property.
|
|
175
|
+
case 'Readonly':
|
|
176
|
+
property[exports.Modifier] = 'ReadonlyOptional';
|
|
213
177
|
break;
|
|
214
|
-
case
|
|
215
|
-
|
|
178
|
+
case 'Optional':
|
|
179
|
+
property[exports.Modifier] = 'Optional';
|
|
216
180
|
break;
|
|
217
181
|
default:
|
|
218
|
-
|
|
182
|
+
property[exports.Modifier] = 'Optional';
|
|
219
183
|
break;
|
|
220
184
|
}
|
|
221
185
|
}
|
|
222
|
-
return this.
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
|
236
|
-
property.
|
|
249
|
+
case 'Readonly':
|
|
250
|
+
property[exports.Modifier] = 'Readonly';
|
|
237
251
|
break;
|
|
238
|
-
case
|
|
239
|
-
property
|
|
252
|
+
case 'Optional':
|
|
253
|
+
delete property[exports.Modifier];
|
|
240
254
|
break;
|
|
241
255
|
default:
|
|
242
|
-
property
|
|
256
|
+
delete property[exports.Modifier];
|
|
243
257
|
break;
|
|
244
258
|
}
|
|
245
259
|
}
|
|
246
|
-
return this.
|
|
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
|
-
/**
|
|
275
|
-
|
|
276
|
-
return
|
|
262
|
+
/** Removes Kind and Modifier symbol property keys from this schema */
|
|
263
|
+
Strict(schema) {
|
|
264
|
+
return JSON.parse(JSON.stringify(schema));
|
|
277
265
|
}
|
|
278
|
-
/**
|
|
279
|
-
|
|
280
|
-
return this.
|
|
266
|
+
/** Creates a string type */
|
|
267
|
+
String(options = {}) {
|
|
268
|
+
return this.Create({ ...options, [exports.Kind]: 'String', type: 'string' });
|
|
281
269
|
}
|
|
282
|
-
/**
|
|
283
|
-
|
|
284
|
-
|
|
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
|
-
/**
|
|
278
|
+
/** Creates a undefined type */
|
|
287
279
|
Undefined(options = {}) {
|
|
288
|
-
return this.
|
|
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
|
-
/**
|
|
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.
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
|
|
296
|
-
return
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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 (
|
|
309
|
-
|
|
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
|
-
|
|
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();
|