@sinclair/typebox 0.24.2 → 0.24.3

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.
@@ -8,18 +8,16 @@ export declare class TypeCheckAssertError extends Error {
8
8
  export declare class TypeCheck<T extends Types.TSchema> {
9
9
  private readonly schema;
10
10
  private readonly checkFunc;
11
- constructor(schema: T, checkFunc: CheckFunction);
11
+ private readonly code;
12
+ constructor(schema: T, checkFunc: CheckFunction, code: string);
13
+ /** Returns the compiled validation code used to check this type. */
14
+ Code(): string;
12
15
  /** Returns true if the value is valid. */
13
16
  Check(value: unknown): value is Types.Static<T>;
14
17
  /** Asserts the given value and throws a TypeCheckAssertError if invalid. */
15
18
  Assert(value: unknown): void;
16
19
  }
17
20
  export declare namespace TypeCompiler {
18
- interface Condition {
19
- schema: Types.TSchema;
20
- expr: string;
21
- path: string;
22
- }
23
- /** Compiles a type into validation function */
21
+ /** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
24
22
  function Compile<T extends Types.TSchema>(schema: T, additional?: Types.TSchema[]): TypeCheck<T>;
25
23
  }
@@ -45,9 +45,15 @@ exports.TypeCheckAssertError = TypeCheckAssertError;
45
45
  class TypeCheck {
46
46
  schema;
47
47
  checkFunc;
48
- constructor(schema, checkFunc) {
48
+ code;
49
+ constructor(schema, checkFunc, code) {
49
50
  this.schema = schema;
50
51
  this.checkFunc = checkFunc;
52
+ this.code = code;
53
+ }
54
+ /** Returns the compiled validation code used to check this type. */
55
+ Code() {
56
+ return this.code;
51
57
  }
52
58
  /** Returns true if the value is valid. */
53
59
  Check(value) {
@@ -55,9 +61,6 @@ class TypeCheck {
55
61
  }
56
62
  /** Asserts the given value and throws a TypeCheckAssertError if invalid. */
57
63
  Assert(value) {
58
- // The return type for this function should be 'asserts value is Static<T>' but due
59
- // to a limitation in TypeScript, this currently isn't possible. See issue below.
60
- // https://github.com/microsoft/TypeScript/issues/36931
61
64
  if (!this.checkFunc(value))
62
65
  throw new TypeCheckAssertError(this.schema, value);
63
66
  }
@@ -68,74 +71,68 @@ exports.TypeCheck = TypeCheck;
68
71
  // -------------------------------------------------------------------
69
72
  var TypeCompiler;
70
73
  (function (TypeCompiler) {
71
- // -------------------------------------------------------------------
72
- // Condition
73
- // -------------------------------------------------------------------
74
- function CreateCondition(schema, path, expr) {
75
- return { schema, path, expr };
76
- }
77
74
  // -------------------------------------------------------------------
78
75
  // Schemas
79
76
  // -------------------------------------------------------------------
80
77
  function* Any(schema, path) {
81
- yield CreateCondition(schema, path, '(true)');
78
+ yield '(true)';
82
79
  }
83
80
  function* Array(schema, path) {
84
- const expr = [...Visit(schema.items, `value`)].map((condition) => condition.expr).join(' && ');
85
- yield CreateCondition(schema, path, `(Array.isArray(${path}) && ${path}.every(value => ${expr}))`);
81
+ const expr = [...Visit(schema.items, `value`)].map((condition) => condition).join(' && ');
82
+ yield `(Array.isArray(${path}) && ${path}.every(value => ${expr}))`;
86
83
  }
87
84
  function* Boolean(schema, path) {
88
- yield CreateCondition(schema, path, `(typeof ${path} === 'boolean')`);
85
+ yield `(typeof ${path} === 'boolean')`;
89
86
  }
90
87
  function* Constructor(schema, path) {
91
88
  yield* Visit(schema.yields, path);
92
89
  }
93
90
  function* Function(schema, path) {
94
- yield CreateCondition(schema, path, `(typeof ${path} === 'function')`);
91
+ yield `(typeof ${path} === 'function')`;
95
92
  }
96
93
  function* Integer(schema, path) {
97
- yield CreateCondition(schema, path, `(typeof ${path} === 'number' && Number.isInteger(${path}))`);
94
+ yield `(typeof ${path} === 'number' && Number.isInteger(${path}))`;
98
95
  if (schema.multipleOf)
99
- yield CreateCondition(schema, path, `(${path} % ${schema.multipleOf} === 0)`);
96
+ yield `(${path} % ${schema.multipleOf} === 0)`;
100
97
  if (schema.exclusiveMinimum)
101
- yield CreateCondition(schema, path, `(${path} < ${schema.exclusiveMinimum})`);
98
+ yield `(${path} < ${schema.exclusiveMinimum})`;
102
99
  if (schema.exclusiveMaximum)
103
- yield CreateCondition(schema, path, `(${path} < ${schema.exclusiveMaximum})`);
100
+ yield `(${path} < ${schema.exclusiveMaximum})`;
104
101
  if (schema.minimum)
105
- yield CreateCondition(schema, path, `(${path} >= ${schema.minimum})`);
102
+ yield `(${path} >= ${schema.minimum})`;
106
103
  if (schema.maximum)
107
- yield CreateCondition(schema, path, `(${path} <= ${schema.maximum})`);
104
+ yield `(${path} <= ${schema.maximum})`;
108
105
  }
109
106
  function* Literal(schema, path) {
110
107
  if (typeof schema.const === 'string') {
111
- yield CreateCondition(schema, path, `(${path} === '${schema.const}')`);
108
+ yield `(${path} === '${schema.const}')`;
112
109
  }
113
110
  else {
114
- yield CreateCondition(schema, path, `(${path} === ${schema.const})`);
111
+ yield `(${path} === ${schema.const})`;
115
112
  }
116
113
  }
117
114
  function* Null(schema, path) {
118
- yield CreateCondition(schema, path, `(${path} === null)`);
115
+ yield `(${path} === null)`;
119
116
  }
120
117
  function* Number(schema, path) {
121
- yield CreateCondition(schema, path, `(typeof ${path} === 'number')`);
118
+ yield `(typeof ${path} === 'number')`;
122
119
  if (schema.multipleOf)
123
- yield CreateCondition(schema, path, `(${path} % ${schema.multipleOf} === 0)`);
120
+ yield `(${path} % ${schema.multipleOf} === 0)`;
124
121
  if (schema.exclusiveMinimum)
125
- yield CreateCondition(schema, path, `(${path} < ${schema.exclusiveMinimum})`);
122
+ yield `(${path} < ${schema.exclusiveMinimum})`;
126
123
  if (schema.exclusiveMaximum)
127
- yield CreateCondition(schema, path, `(${path} < ${schema.exclusiveMaximum})`);
124
+ yield `(${path} < ${schema.exclusiveMaximum})`;
128
125
  if (schema.minimum)
129
- yield CreateCondition(schema, path, `(${path} >= ${schema.minimum})`);
126
+ yield `(${path} >= ${schema.minimum})`;
130
127
  if (schema.maximum)
131
- yield CreateCondition(schema, path, `(${path} <= ${schema.maximum})`);
128
+ yield `(${path} <= ${schema.maximum})`;
132
129
  }
133
130
  function* Object(schema, path) {
134
- yield CreateCondition(schema, path, `(typeof ${path} === 'object' && ${path} !== null && !Array.isArray(${path}))`);
131
+ yield `(typeof ${path} === 'object' && ${path} !== null && !Array.isArray(${path}))`;
135
132
  if (schema.minProperties !== undefined)
136
- yield CreateCondition(schema, path, `(Object.keys(${path}).length >= ${schema.minProperties})`);
133
+ yield `(Object.keys(${path}).length >= ${schema.minProperties})`;
137
134
  if (schema.maxProperties !== undefined)
138
- yield CreateCondition(schema, path, `(Object.keys(${path}).length <= ${schema.maxProperties})`);
135
+ yield `(Object.keys(${path}).length <= ${schema.maxProperties})`;
139
136
  const propertyKeys = globalThis.Object.keys(schema.properties);
140
137
  if (schema.additionalProperties === false) {
141
138
  // optimization: If the property key length matches the required keys length
@@ -143,11 +140,11 @@ var TypeCompiler;
143
140
  // of the property key length. This is because exhaustive testing for values
144
141
  // will occur in subsequent property tests.
145
142
  if (schema.required && schema.required.length === propertyKeys.length) {
146
- yield CreateCondition(schema, path, `(Object.keys(${path}).length === ${propertyKeys.length})`);
143
+ yield `(Object.keys(${path}).length === ${propertyKeys.length})`;
147
144
  }
148
145
  else {
149
146
  const keys = `[${propertyKeys.map((key) => `'${key}'`).join(', ')}]`;
150
- yield CreateCondition(schema, path, `(Object.keys(${path}).every(key => ${keys}.includes(key)))`);
147
+ yield `(Object.keys(${path}).every(key => ${keys}.includes(key)))`;
151
148
  }
152
149
  }
153
150
  for (const propertyKey of propertyKeys) {
@@ -156,21 +153,21 @@ var TypeCompiler;
156
153
  yield* Visit(propertySchema, `${path}.${propertyKey}`);
157
154
  }
158
155
  else {
159
- const expr = [...Visit(propertySchema, `${path}.${propertyKey}`)].map((condition) => condition.expr).join(' && ');
160
- yield CreateCondition(schema, `${path}.${propertyKey}`, `(${path}.${propertyKey} === undefined ? true : (${expr}))`);
156
+ const expr = [...Visit(propertySchema, `${path}.${propertyKey}`)].map((condition) => condition).join(' && ');
157
+ yield `(${path}.${propertyKey} === undefined ? true : (${expr}))`;
161
158
  }
162
159
  }
163
160
  }
164
161
  function* Promise(schema, path) {
165
- yield CreateCondition(schema, path, `(typeof value === 'object' && typeof ${path}.then === 'function')`);
162
+ yield `(typeof value === 'object' && typeof ${path}.then === 'function')`;
166
163
  }
167
164
  function* Record(schema, path) {
168
- yield CreateCondition(schema, path, `(typeof ${path} === 'object' && ${path} !== null && !Array.isArray(${path}))`);
165
+ yield `(typeof ${path} === 'object' && ${path} !== null && !Array.isArray(${path}))`;
169
166
  const [keyPattern, valueSchema] = globalThis.Object.entries(schema.patternProperties)[0];
170
167
  const local = PushLocal(`const local = new RegExp(/${keyPattern}/)`);
171
- yield CreateCondition(schema, path, `(Object.keys(${path}).every(key => ${local}.test(key)))`);
172
- const expr = [...Visit(valueSchema, 'value')].map((cond) => cond.expr).join(' && ');
173
- yield CreateCondition(schema, path, `(Object.values(${path}).every(value => ${expr}))`);
168
+ yield `(Object.keys(${path}).every(key => ${local}.test(key)))`;
169
+ const expr = [...Visit(valueSchema, 'value')].map((condition) => condition).join(' && ');
170
+ yield `(Object.values(${path}).every(value => ${expr}))`;
174
171
  }
175
172
  function* Ref(schema, path) {
176
173
  // reference: referenced schemas can originate from either additional
@@ -185,48 +182,48 @@ var TypeCompiler;
185
182
  PushLocal(body);
186
183
  }
187
184
  const func = CreateFunctionName(schema.$ref);
188
- yield CreateCondition(schema, path, `(${func}(${path}))`);
185
+ yield `(${func}(${path}))`;
189
186
  }
190
187
  function* Self(schema, path) {
191
188
  const func = CreateFunctionName(schema.$ref);
192
- yield CreateCondition(schema, path, `(${func}(${path}))`);
189
+ yield `(${func}(${path}))`;
193
190
  }
194
191
  function* String(schema, path) {
195
- yield CreateCondition(schema, path, `(typeof ${path} === 'string')`);
192
+ yield `(typeof ${path} === 'string')`;
196
193
  if (schema.pattern !== undefined) {
197
194
  const local = PushLocal(`const local = new RegExp('${schema.pattern}');`);
198
- yield CreateCondition(schema, path, `(${local}.test(${path}))`);
195
+ yield `(${local}.test(${path}))`;
199
196
  }
200
197
  }
201
198
  function* Tuple(schema, path) {
202
- yield CreateCondition(schema, path, `(Array.isArray(${path}))`);
199
+ yield `(Array.isArray(${path}))`;
203
200
  if (schema.items === undefined)
204
- return yield CreateCondition(schema, path, `(${path}.length === 0)`);
205
- yield CreateCondition(schema, path, `(${path}.length === ${schema.maxItems})`);
201
+ return yield `(${path}.length === 0)`;
202
+ yield `(${path}.length === ${schema.maxItems})`;
206
203
  for (let i = 0; i < schema.items.length; i++) {
207
- const expr = [...Visit(schema.items[i], `${path}[${i}]`)].map((condition) => condition.expr).join(' && ');
208
- yield CreateCondition(schema, path, `(${expr})`);
204
+ const expr = [...Visit(schema.items[i], `${path}[${i}]`)].map((condition) => condition).join(' && ');
205
+ yield `(${expr})`;
209
206
  }
210
207
  }
211
208
  function* Undefined(schema, path) {
212
- yield CreateCondition(schema, path, `${path} === undefined`);
209
+ yield `${path} === undefined`;
213
210
  }
214
211
  function* Union(schema, path) {
215
- const exprs = schema.anyOf.map((schema) => [...Visit(schema, path)].map((cond) => cond.expr).join(' && '));
216
- yield CreateCondition(schema, path, `(${exprs.join(' || ')})`);
212
+ const exprs = schema.anyOf.map((schema) => [...Visit(schema, path)].map((condition) => condition).join(' && '));
213
+ yield `(${exprs.join(' || ')})`;
217
214
  }
218
215
  function* Uint8Array(schema, path) {
219
- yield CreateCondition(schema, path, `(${path} instanceof Uint8Array)`);
216
+ yield `(${path} instanceof Uint8Array)`;
220
217
  if (schema.maxByteLength)
221
- yield CreateCondition(schema, path, `(${path}.length <= ${schema.maxByteLength})`);
218
+ yield `(${path}.length <= ${schema.maxByteLength})`;
222
219
  if (schema.minByteLength)
223
- yield CreateCondition(schema, path, `(${path}.length >= ${schema.minByteLength})`);
220
+ yield `(${path}.length >= ${schema.minByteLength})`;
224
221
  }
225
222
  function* Unknown(schema, path) {
226
- yield CreateCondition(schema, path, '(true)');
223
+ yield '(true)';
227
224
  }
228
225
  function* Void(schema, path) {
229
- yield CreateCondition(schema, path, `(${path} === null)`);
226
+ yield `(${path} === null)`;
230
227
  }
231
228
  function* Visit(schema, path) {
232
229
  // reference: referenced schemas can originate from either additional
@@ -238,7 +235,7 @@ var TypeCompiler;
238
235
  const name = CreateFunctionName(schema.$id);
239
236
  const body = CreateFunction(name, conditions);
240
237
  PushLocal(body);
241
- yield CreateCondition(schema, path, `(${name}(${path}))`);
238
+ yield `(${name}(${path}))`;
242
239
  return;
243
240
  }
244
241
  const anySchema = schema;
@@ -324,11 +321,11 @@ var TypeCompiler;
324
321
  return `check_${$id.replace(/-/g, '_')}`;
325
322
  }
326
323
  function CreateFunction(name, conditions) {
327
- const statements = conditions.map((condition, index) => ` if(!${condition.expr}) { return false }`);
328
- return `function ${name}(value) {\n${statements.join('\n')}\n return true\n}`;
324
+ const expression = conditions.map((condition) => ` ${condition}`).join(' &&\n');
325
+ return `function ${name}(value) {\n return (\n${expression}\n )\n}`;
329
326
  }
330
327
  // -------------------------------------------------------------------
331
- // Compiler
328
+ // Compile
332
329
  // -------------------------------------------------------------------
333
330
  function Build(schema, additional = []) {
334
331
  ClearLocals();
@@ -337,11 +334,11 @@ var TypeCompiler;
337
334
  const locals = GetLocals();
338
335
  return `${locals.join('\n')}\nreturn ${CreateFunction('check', conditions)}`;
339
336
  }
340
- /** Compiles a type into validation function */
337
+ /** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
341
338
  function Compile(schema, additional = []) {
342
339
  const code = Build(schema, additional);
343
340
  const func = globalThis.Function(code);
344
- return new TypeCheck(schema, func());
341
+ return new TypeCheck(schema, func(), code);
345
342
  }
346
343
  TypeCompiler.Compile = Compile;
347
344
  })(TypeCompiler = exports.TypeCompiler || (exports.TypeCompiler = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinclair/typebox",
3
- "version": "0.24.2",
3
+ "version": "0.24.3",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "json-schema",