@sinclair/typebox 0.23.4 → 0.24.1
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 +25 -0
- package/compiler/compiler.js +347 -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 +377 -361
- package/typebox.d.ts +306 -296
- package/typebox.js +247 -260
- 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,316 +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
|
-
|
|
41
|
+
// ----------------------------------------------------------------------
|
|
42
|
+
// Modifiers
|
|
43
|
+
// ----------------------------------------------------------------------
|
|
44
|
+
/** Creates a readonly optional property */
|
|
88
45
|
ReadonlyOptional(item) {
|
|
89
|
-
return { ...item
|
|
46
|
+
return { [exports.Modifier]: 'ReadonlyOptional', ...item };
|
|
90
47
|
}
|
|
91
|
-
/**
|
|
48
|
+
/** Creates a readonly property */
|
|
92
49
|
Readonly(item) {
|
|
93
|
-
return { ...item
|
|
50
|
+
return { [exports.Modifier]: 'Readonly', ...item };
|
|
94
51
|
}
|
|
95
|
-
/**
|
|
52
|
+
/** Creates a optional property */
|
|
96
53
|
Optional(item) {
|
|
97
|
-
return { ...item
|
|
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
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
/**
|
|
63
|
+
/** Creates a array type */
|
|
133
64
|
Array(items, options = {}) {
|
|
134
|
-
return this.
|
|
65
|
+
return this.Create({ ...options, [exports.Kind]: 'Array', type: 'array', items });
|
|
135
66
|
}
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
/**
|
|
143
|
-
|
|
144
|
-
return this.
|
|
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
|
-
/**
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
/**
|
|
151
|
-
|
|
152
|
-
return this.
|
|
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
|
-
/**
|
|
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.
|
|
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
|
-
/**
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
/**
|
|
167
|
-
|
|
168
|
-
return this.
|
|
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
|
-
/**
|
|
171
|
-
|
|
172
|
-
return this.
|
|
130
|
+
/** Creates a null type */
|
|
131
|
+
Null(options = {}) {
|
|
132
|
+
return this.Create({ ...options, [exports.Kind]: 'Null', type: 'null' });
|
|
173
133
|
}
|
|
174
|
-
/**
|
|
175
|
-
|
|
176
|
-
return this.
|
|
134
|
+
/** Creates a number type */
|
|
135
|
+
Number(options = {}) {
|
|
136
|
+
return this.Create({ ...options, [exports.Kind]: 'Number', type: 'number' });
|
|
177
137
|
}
|
|
178
|
-
/**
|
|
179
|
-
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
/**
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
|
209
|
-
property.
|
|
175
|
+
case 'Readonly':
|
|
176
|
+
property[exports.Modifier] = 'ReadonlyOptional';
|
|
210
177
|
break;
|
|
211
|
-
case
|
|
212
|
-
|
|
178
|
+
case 'Optional':
|
|
179
|
+
property[exports.Modifier] = 'Optional';
|
|
213
180
|
break;
|
|
214
181
|
default:
|
|
215
|
-
|
|
182
|
+
property[exports.Modifier] = 'Optional';
|
|
216
183
|
break;
|
|
217
184
|
}
|
|
218
185
|
}
|
|
219
|
-
return this.
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
|
233
|
-
property.
|
|
249
|
+
case 'Readonly':
|
|
250
|
+
property[exports.Modifier] = 'Readonly';
|
|
234
251
|
break;
|
|
235
|
-
case
|
|
236
|
-
property
|
|
252
|
+
case 'Optional':
|
|
253
|
+
delete property[exports.Modifier];
|
|
237
254
|
break;
|
|
238
255
|
default:
|
|
239
|
-
property
|
|
256
|
+
delete property[exports.Modifier];
|
|
240
257
|
break;
|
|
241
258
|
}
|
|
242
259
|
}
|
|
243
|
-
return this.
|
|
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
|
-
/**
|
|
272
|
-
|
|
273
|
-
return
|
|
262
|
+
/** Removes Kind and Modifier symbol property keys from this schema */
|
|
263
|
+
Strict(schema) {
|
|
264
|
+
return JSON.parse(JSON.stringify(schema));
|
|
274
265
|
}
|
|
275
|
-
/**
|
|
276
|
-
|
|
277
|
-
return this.
|
|
266
|
+
/** Creates a string type */
|
|
267
|
+
String(options = {}) {
|
|
268
|
+
return this.Create({ ...options, [exports.Kind]: 'String', type: 'string' });
|
|
278
269
|
}
|
|
279
|
-
/**
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
/**
|
|
278
|
+
/** Creates a undefined type */
|
|
284
279
|
Undefined(options = {}) {
|
|
285
|
-
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 });
|
|
286
285
|
}
|
|
287
|
-
/**
|
|
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.
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
|
|
293
|
-
return
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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 (
|
|
306
|
-
|
|
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
|
-
|
|
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();
|