@sinclair/typebox 0.25.10 → 0.25.11
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.js +6 -3
- package/errors/errors.js +11 -1
- package/hash/hash.d.ts +8 -0
- package/hash/hash.js +183 -0
- package/hash/index.d.ts +1 -0
- package/hash/index.js +44 -0
- package/package.json +2 -1
- package/readme.md +64 -50
- package/value/check.js +11 -1
- package/value/index.d.ts +1 -0
- package/value/index.js +6 -1
- package/value/value.d.ts +4 -3
- package/value/value.js +12 -11
package/compiler/compiler.js
CHANGED
|
@@ -32,6 +32,7 @@ const index_1 = require("../errors/index");
|
|
|
32
32
|
const index_2 = require("../guard/index");
|
|
33
33
|
const index_3 = require("../format/index");
|
|
34
34
|
const index_4 = require("../custom/index");
|
|
35
|
+
const index_5 = require("../hash/index");
|
|
35
36
|
const Types = require("../typebox");
|
|
36
37
|
// -------------------------------------------------------------------
|
|
37
38
|
// TypeCheck
|
|
@@ -117,13 +118,13 @@ var TypeCompiler;
|
|
|
117
118
|
}
|
|
118
119
|
function* Array(schema, value) {
|
|
119
120
|
const expression = CreateExpression(schema.items, 'value');
|
|
121
|
+
yield `(Array.isArray(${value}) && ${value}.every(value => ${expression}))`;
|
|
120
122
|
if (IsNumber(schema.minItems))
|
|
121
123
|
yield `(${value}.length >= ${schema.minItems})`;
|
|
122
124
|
if (IsNumber(schema.maxItems))
|
|
123
125
|
yield `(${value}.length <= ${schema.maxItems})`;
|
|
124
126
|
if (schema.uniqueItems === true)
|
|
125
|
-
yield `(new Set(${value}).
|
|
126
|
-
yield `(Array.isArray(${value}) && ${value}.every(value => ${expression}))`;
|
|
127
|
+
yield `((function() { const set = new Set(); for(const element of ${value}) { const hashed = hash(element); if(set.has(hashed)) { return false } else { set.add(hashed) } } return true })())`;
|
|
127
128
|
}
|
|
128
129
|
function* Boolean(schema, value) {
|
|
129
130
|
yield `(typeof ${value} === 'boolean')`;
|
|
@@ -421,7 +422,7 @@ var TypeCompiler;
|
|
|
421
422
|
index_2.TypeGuard.Assert(schema, references);
|
|
422
423
|
const code = Build(schema, references);
|
|
423
424
|
const custom_schemas = new Map(state_remote_custom_types);
|
|
424
|
-
const compiledFunction = globalThis.Function('custom', 'format', code);
|
|
425
|
+
const compiledFunction = globalThis.Function('custom', 'format', 'hash', code);
|
|
425
426
|
const checkFunction = compiledFunction((kind, schema_key, value) => {
|
|
426
427
|
if (!index_4.Custom.Has(kind) || !custom_schemas.has(schema_key))
|
|
427
428
|
return false;
|
|
@@ -433,6 +434,8 @@ var TypeCompiler;
|
|
|
433
434
|
return false;
|
|
434
435
|
const func = index_3.Format.Get(format);
|
|
435
436
|
return func(value);
|
|
437
|
+
}, (value) => {
|
|
438
|
+
return index_5.ValueHash.Create(value);
|
|
436
439
|
});
|
|
437
440
|
return new TypeCheck(schema, references, checkFunction, code);
|
|
438
441
|
}
|
package/errors/errors.js
CHANGED
|
@@ -31,6 +31,7 @@ exports.ValueErrors = exports.ValueErrorsUnknownTypeError = exports.ValueErrorTy
|
|
|
31
31
|
const Types = require("../typebox");
|
|
32
32
|
const index_1 = require("../format/index");
|
|
33
33
|
const index_2 = require("../custom/index");
|
|
34
|
+
const index_3 = require("../hash/index");
|
|
34
35
|
// -------------------------------------------------------------------
|
|
35
36
|
// ValueErrorType
|
|
36
37
|
// -------------------------------------------------------------------
|
|
@@ -113,7 +114,16 @@ var ValueErrors;
|
|
|
113
114
|
if (IsNumber(schema.maxItems) && !(value.length <= schema.maxItems)) {
|
|
114
115
|
yield { type: ValueErrorType.ArrayMinItems, schema, path, value, message: `Expected array length to be less or equal to ${schema.maxItems}` };
|
|
115
116
|
}
|
|
116
|
-
|
|
117
|
+
// prettier-ignore
|
|
118
|
+
if (schema.uniqueItems === true && !((function () { const set = new Set(); for (const element of value) {
|
|
119
|
+
const hashed = index_3.ValueHash.Create(element);
|
|
120
|
+
if (set.has(hashed)) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
set.add(hashed);
|
|
125
|
+
}
|
|
126
|
+
} return true; })())) {
|
|
117
127
|
yield { type: ValueErrorType.ArrayUniqueItems, schema, path, value, message: `Expected array elements to be unique` };
|
|
118
128
|
}
|
|
119
129
|
for (let i = 0; i < value.length; i++) {
|
package/hash/hash.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class ValueHashError extends Error {
|
|
2
|
+
readonly value: unknown;
|
|
3
|
+
constructor(value: unknown);
|
|
4
|
+
}
|
|
5
|
+
export declare namespace ValueHash {
|
|
6
|
+
/** Creates a FNV1A-64 non cryptographic hash of the given value */
|
|
7
|
+
function Create(value: unknown): bigint;
|
|
8
|
+
}
|
package/hash/hash.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*--------------------------------------------------------------------------
|
|
3
|
+
|
|
4
|
+
@sinclair/typebox/hash
|
|
5
|
+
|
|
6
|
+
The MIT License (MIT)
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2022 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in
|
|
18
|
+
all copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
26
|
+
THE SOFTWARE.
|
|
27
|
+
|
|
28
|
+
---------------------------------------------------------------------------*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.ValueHash = exports.ValueHashError = void 0;
|
|
31
|
+
class ValueHashError extends Error {
|
|
32
|
+
constructor(value) {
|
|
33
|
+
super(`Hash: Unable to hash value`);
|
|
34
|
+
this.value = value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.ValueHashError = ValueHashError;
|
|
38
|
+
var ValueHash;
|
|
39
|
+
(function (ValueHash) {
|
|
40
|
+
let ByteMarker;
|
|
41
|
+
(function (ByteMarker) {
|
|
42
|
+
ByteMarker[ByteMarker["Undefined"] = 0] = "Undefined";
|
|
43
|
+
ByteMarker[ByteMarker["Null"] = 1] = "Null";
|
|
44
|
+
ByteMarker[ByteMarker["Boolean"] = 2] = "Boolean";
|
|
45
|
+
ByteMarker[ByteMarker["Number"] = 3] = "Number";
|
|
46
|
+
ByteMarker[ByteMarker["String"] = 4] = "String";
|
|
47
|
+
ByteMarker[ByteMarker["Object"] = 5] = "Object";
|
|
48
|
+
ByteMarker[ByteMarker["Array"] = 6] = "Array";
|
|
49
|
+
ByteMarker[ByteMarker["Date"] = 7] = "Date";
|
|
50
|
+
ByteMarker[ByteMarker["Uint8Array"] = 8] = "Uint8Array";
|
|
51
|
+
})(ByteMarker || (ByteMarker = {}));
|
|
52
|
+
// ----------------------------------------------------
|
|
53
|
+
// State
|
|
54
|
+
// ----------------------------------------------------
|
|
55
|
+
let Hash = 14695981039346656037n;
|
|
56
|
+
const [Prime, Size] = [1099511628211n, 2n ** 64n];
|
|
57
|
+
const Bytes = globalThis.Array.from({ length: 256 }).map((_, i) => globalThis.BigInt(i));
|
|
58
|
+
const F64 = new globalThis.Float64Array(1);
|
|
59
|
+
const F64In = new globalThis.DataView(F64.buffer);
|
|
60
|
+
const F64Out = new globalThis.Uint8Array(F64.buffer);
|
|
61
|
+
// ----------------------------------------------------
|
|
62
|
+
// Guards
|
|
63
|
+
// ----------------------------------------------------
|
|
64
|
+
function IsDate(value) {
|
|
65
|
+
return value instanceof globalThis.Date;
|
|
66
|
+
}
|
|
67
|
+
function IsUint8Array(value) {
|
|
68
|
+
return value instanceof globalThis.Uint8Array;
|
|
69
|
+
}
|
|
70
|
+
function IsArray(value) {
|
|
71
|
+
return globalThis.Array.isArray(value);
|
|
72
|
+
}
|
|
73
|
+
function IsBoolean(value) {
|
|
74
|
+
return typeof value === 'boolean';
|
|
75
|
+
}
|
|
76
|
+
function IsNull(value) {
|
|
77
|
+
return value === null;
|
|
78
|
+
}
|
|
79
|
+
function IsNumber(value) {
|
|
80
|
+
return typeof value === 'number';
|
|
81
|
+
}
|
|
82
|
+
function IsObject(value) {
|
|
83
|
+
return typeof value === 'object' && value !== null && !IsArray(value) && !IsDate(value) && !IsUint8Array(value);
|
|
84
|
+
}
|
|
85
|
+
function IsString(value) {
|
|
86
|
+
return typeof value === 'string';
|
|
87
|
+
}
|
|
88
|
+
function IsUndefined(value) {
|
|
89
|
+
return value === undefined;
|
|
90
|
+
}
|
|
91
|
+
// ----------------------------------------------------
|
|
92
|
+
// Encoding
|
|
93
|
+
// ----------------------------------------------------
|
|
94
|
+
function Array(value) {
|
|
95
|
+
Fnv1A64(ByteMarker.Array);
|
|
96
|
+
for (const item of value) {
|
|
97
|
+
Visit(item);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function Boolean(value) {
|
|
101
|
+
Fnv1A64(ByteMarker.Boolean);
|
|
102
|
+
Fnv1A64(value ? 1 : 0);
|
|
103
|
+
}
|
|
104
|
+
function Date(value) {
|
|
105
|
+
Fnv1A64(ByteMarker.Date);
|
|
106
|
+
Visit(value.getTime());
|
|
107
|
+
}
|
|
108
|
+
function Null(value) {
|
|
109
|
+
Fnv1A64(ByteMarker.Null);
|
|
110
|
+
}
|
|
111
|
+
function Number(value) {
|
|
112
|
+
Fnv1A64(ByteMarker.Number);
|
|
113
|
+
F64In.setFloat64(0, value);
|
|
114
|
+
for (const byte of F64Out) {
|
|
115
|
+
Fnv1A64(byte);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function Object(value) {
|
|
119
|
+
Fnv1A64(ByteMarker.Object);
|
|
120
|
+
for (const key of globalThis.Object.keys(value).sort()) {
|
|
121
|
+
Visit(key);
|
|
122
|
+
Visit(value[key]);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function String(value) {
|
|
126
|
+
Fnv1A64(ByteMarker.String);
|
|
127
|
+
for (let i = 0; i < value.length; i++) {
|
|
128
|
+
Fnv1A64(value.charCodeAt(i));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function Uint8Array(value) {
|
|
132
|
+
Fnv1A64(ByteMarker.Uint8Array);
|
|
133
|
+
for (let i = 0; i < value.length; i++) {
|
|
134
|
+
Fnv1A64(value[i]);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function Undefined(value) {
|
|
138
|
+
return Fnv1A64(ByteMarker.Undefined);
|
|
139
|
+
}
|
|
140
|
+
function Visit(value) {
|
|
141
|
+
if (IsArray(value)) {
|
|
142
|
+
Array(value);
|
|
143
|
+
}
|
|
144
|
+
else if (IsBoolean(value)) {
|
|
145
|
+
Boolean(value);
|
|
146
|
+
}
|
|
147
|
+
else if (IsDate(value)) {
|
|
148
|
+
Date(value);
|
|
149
|
+
}
|
|
150
|
+
else if (IsNull(value)) {
|
|
151
|
+
Null(value);
|
|
152
|
+
}
|
|
153
|
+
else if (IsNumber(value)) {
|
|
154
|
+
Number(value);
|
|
155
|
+
}
|
|
156
|
+
else if (IsObject(value)) {
|
|
157
|
+
Object(value);
|
|
158
|
+
}
|
|
159
|
+
else if (IsString(value)) {
|
|
160
|
+
String(value);
|
|
161
|
+
}
|
|
162
|
+
else if (IsUint8Array(value)) {
|
|
163
|
+
Uint8Array(value);
|
|
164
|
+
}
|
|
165
|
+
else if (IsUndefined(value)) {
|
|
166
|
+
Undefined(value);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
throw new ValueHashError(value);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function Fnv1A64(byte) {
|
|
173
|
+
Hash = Hash ^ Bytes[byte];
|
|
174
|
+
Hash = (Hash * Prime) % Size;
|
|
175
|
+
}
|
|
176
|
+
/** Creates a FNV1A-64 non cryptographic hash of the given value */
|
|
177
|
+
function Create(value) {
|
|
178
|
+
Hash = 14695981039346656037n;
|
|
179
|
+
Visit(value);
|
|
180
|
+
return Hash;
|
|
181
|
+
}
|
|
182
|
+
ValueHash.Create = Create;
|
|
183
|
+
})(ValueHash = exports.ValueHash || (exports.ValueHash = {}));
|
package/hash/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './hash';
|
package/hash/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*--------------------------------------------------------------------------
|
|
3
|
+
|
|
4
|
+
@sinclair/typebox/hash
|
|
5
|
+
|
|
6
|
+
The MIT License (MIT)
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2022 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in
|
|
18
|
+
all copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
26
|
+
THE SOFTWARE.
|
|
27
|
+
|
|
28
|
+
---------------------------------------------------------------------------*/
|
|
29
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
32
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
33
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
34
|
+
}
|
|
35
|
+
Object.defineProperty(o, k2, desc);
|
|
36
|
+
}) : (function(o, m, k, k2) {
|
|
37
|
+
if (k2 === undefined) k2 = k;
|
|
38
|
+
o[k2] = m[k];
|
|
39
|
+
}));
|
|
40
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
41
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
__exportStar(require("./hash"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sinclair/typebox",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.11",
|
|
4
4
|
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"./errors": "./errors/index.js",
|
|
20
20
|
"./format": "./format/index.js",
|
|
21
21
|
"./guard": "./guard/index.js",
|
|
22
|
+
"./hash": "./hash/index.js",
|
|
22
23
|
"./value": "./value/index.js",
|
|
23
24
|
".": "./typebox.js"
|
|
24
25
|
},
|
package/readme.md
CHANGED
|
@@ -90,6 +90,7 @@ License MIT
|
|
|
90
90
|
- [Check](#values-check)
|
|
91
91
|
- [Cast](#values-cast)
|
|
92
92
|
- [Equal](#values-equal)
|
|
93
|
+
- [Hash](#values-hash)
|
|
93
94
|
- [Diff](#values-diff)
|
|
94
95
|
- [Patch](#values-patch)
|
|
95
96
|
- [Errors](#values-errors)
|
|
@@ -843,6 +844,18 @@ const R = Value.Equal( // const R = true
|
|
|
843
844
|
)
|
|
844
845
|
```
|
|
845
846
|
|
|
847
|
+
<a name='values-hash'></a>
|
|
848
|
+
|
|
849
|
+
### Hash
|
|
850
|
+
|
|
851
|
+
Use the Hash function to create a [FNV1A-64](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) non cryptographic hash of a value.
|
|
852
|
+
|
|
853
|
+
```typescript
|
|
854
|
+
const A = Value.Hash({ x: 1, y: 2, z: 3 }) // const A = 2910466848807138541n
|
|
855
|
+
|
|
856
|
+
const B = Value.Hash({ x: 1, y: 4, z: 3 }) // const B = 1418369778807423581n
|
|
857
|
+
```
|
|
858
|
+
|
|
846
859
|
<a name='values-diff'></a>
|
|
847
860
|
|
|
848
861
|
### Diff
|
|
@@ -1192,29 +1205,29 @@ This benchmark measures compilation performance for varying types. You can revie
|
|
|
1192
1205
|
┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
|
|
1193
1206
|
│ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │
|
|
1194
1207
|
├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
|
|
1195
|
-
│ Number │ 2000 │ '
|
|
1196
|
-
│ String │ 2000 │ '
|
|
1197
|
-
│ Boolean │ 2000 │ '
|
|
1198
|
-
│ Null │ 2000 │ '
|
|
1199
|
-
│ RegEx │ 2000 │ '
|
|
1200
|
-
│ ObjectA │ 2000 │ '
|
|
1201
|
-
│ ObjectB │ 2000 │ '
|
|
1202
|
-
│ Tuple │ 2000 │ '
|
|
1203
|
-
│ Union │ 2000 │ '
|
|
1204
|
-
│ Vector4 │ 2000 │ '
|
|
1205
|
-
│ Matrix4 │ 2000 │ '
|
|
1206
|
-
│ Literal_String │ 2000 │ '
|
|
1207
|
-
│ Literal_Number │ 2000 │ '
|
|
1208
|
-
│ Literal_Boolean │ 2000 │ '
|
|
1209
|
-
│ Array_Number │ 2000 │ '
|
|
1210
|
-
│ Array_String │ 2000 │ '
|
|
1211
|
-
│ Array_Boolean │ 2000 │ '
|
|
1212
|
-
│ Array_ObjectA │ 2000 │ '
|
|
1213
|
-
│ Array_ObjectB │ 2000 │ '
|
|
1214
|
-
│ Array_Tuple │ 2000 │ '
|
|
1215
|
-
│ Array_Union │ 2000 │ '
|
|
1216
|
-
│ Array_Vector4 │ 2000 │ '
|
|
1217
|
-
│ Array_Matrix4 │ 2000 │ '
|
|
1208
|
+
│ Number │ 2000 │ ' 415 ms' │ ' 14 ms' │ ' 29.64 x' │
|
|
1209
|
+
│ String │ 2000 │ ' 335 ms' │ ' 12 ms' │ ' 27.92 x' │
|
|
1210
|
+
│ Boolean │ 2000 │ ' 295 ms' │ ' 13 ms' │ ' 22.69 x' │
|
|
1211
|
+
│ Null │ 2000 │ ' 255 ms' │ ' 8 ms' │ ' 31.88 x' │
|
|
1212
|
+
│ RegEx │ 2000 │ ' 482 ms' │ ' 17 ms' │ ' 28.35 x' │
|
|
1213
|
+
│ ObjectA │ 2000 │ ' 2700 ms' │ ' 55 ms' │ ' 49.09 x' │
|
|
1214
|
+
│ ObjectB │ 2000 │ ' 2871 ms' │ ' 36 ms' │ ' 79.75 x' │
|
|
1215
|
+
│ Tuple │ 2000 │ ' 1229 ms' │ ' 22 ms' │ ' 55.86 x' │
|
|
1216
|
+
│ Union │ 2000 │ ' 1216 ms' │ ' 26 ms' │ ' 46.77 x' │
|
|
1217
|
+
│ Vector4 │ 2000 │ ' 1575 ms' │ ' 25 ms' │ ' 63.00 x' │
|
|
1218
|
+
│ Matrix4 │ 2000 │ ' 908 ms' │ ' 13 ms' │ ' 69.85 x' │
|
|
1219
|
+
│ Literal_String │ 2000 │ ' 353 ms' │ ' 9 ms' │ ' 39.22 x' │
|
|
1220
|
+
│ Literal_Number │ 2000 │ ' 371 ms' │ ' 7 ms' │ ' 53.00 x' │
|
|
1221
|
+
│ Literal_Boolean │ 2000 │ ' 361 ms' │ ' 8 ms' │ ' 45.13 x' │
|
|
1222
|
+
│ Array_Number │ 2000 │ ' 694 ms' │ ' 7 ms' │ ' 99.14 x' │
|
|
1223
|
+
│ Array_String │ 2000 │ ' 778 ms' │ ' 8 ms' │ ' 97.25 x' │
|
|
1224
|
+
│ Array_Boolean │ 2000 │ ' 735 ms' │ ' 7 ms' │ ' 105.00 x' │
|
|
1225
|
+
│ Array_ObjectA │ 2000 │ ' 3732 ms' │ ' 44 ms' │ ' 84.82 x' │
|
|
1226
|
+
│ Array_ObjectB │ 2000 │ ' 3624 ms' │ ' 40 ms' │ ' 90.60 x' │
|
|
1227
|
+
│ Array_Tuple │ 2000 │ ' 2101 ms' │ ' 15 ms' │ ' 140.07 x' │
|
|
1228
|
+
│ Array_Union │ 2000 │ ' 1480 ms' │ ' 25 ms' │ ' 59.20 x' │
|
|
1229
|
+
│ Array_Vector4 │ 2000 │ ' 2175 ms' │ ' 18 ms' │ ' 120.83 x' │
|
|
1230
|
+
│ Array_Matrix4 │ 2000 │ ' 1516 ms' │ ' 13 ms' │ ' 116.62 x' │
|
|
1218
1231
|
└──────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
|
|
1219
1232
|
```
|
|
1220
1233
|
|
|
@@ -1228,31 +1241,31 @@ This benchmark measures validation performance for varying types. You can review
|
|
|
1228
1241
|
┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
|
|
1229
1242
|
│ (index) │ Iterations │ ValueCheck │ Ajv │ TypeCompiler │ Performance │
|
|
1230
1243
|
├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
|
|
1231
|
-
│ Number │ 1000000 │ '
|
|
1232
|
-
│ String │ 1000000 │ '
|
|
1233
|
-
│ Boolean │ 1000000 │ '
|
|
1234
|
-
│ Null │ 1000000 │ '
|
|
1235
|
-
│ RegEx │ 1000000 │ '
|
|
1236
|
-
│ ObjectA │ 1000000 │ '
|
|
1237
|
-
│ ObjectB │ 1000000 │ '
|
|
1238
|
-
│ Tuple │ 1000000 │ '
|
|
1239
|
-
│ Union │ 1000000 │ '
|
|
1240
|
-
│ Recursive │ 1000000 │ '
|
|
1241
|
-
│ Vector4 │ 1000000 │ '
|
|
1242
|
-
│ Matrix4 │ 1000000 │ '
|
|
1243
|
-
│ Literal_String │ 1000000 │ '
|
|
1244
|
-
│ Literal_Number │ 1000000 │ '
|
|
1245
|
-
│ Literal_Boolean │ 1000000 │ '
|
|
1246
|
-
│ Array_Number │ 1000000 │ '
|
|
1247
|
-
│ Array_String │ 1000000 │ '
|
|
1248
|
-
│ Array_Boolean │ 1000000 │ '
|
|
1249
|
-
│ Array_ObjectA │ 1000000 │ '
|
|
1250
|
-
│ Array_ObjectB │ 1000000 │ '
|
|
1251
|
-
│ Array_Tuple │ 1000000 │ '
|
|
1252
|
-
│ Array_Union │ 1000000 │ '
|
|
1253
|
-
│ Array_Recursive │ 1000000 │ '
|
|
1254
|
-
│ Array_Vector4 │ 1000000 │ '
|
|
1255
|
-
│ Array_Matrix4 │ 1000000 │ '
|
|
1244
|
+
│ Number │ 1000000 │ ' 28 ms' │ ' 6 ms' │ ' 5 ms' │ ' 1.20 x' │
|
|
1245
|
+
│ String │ 1000000 │ ' 22 ms' │ ' 21 ms' │ ' 13 ms' │ ' 1.62 x' │
|
|
1246
|
+
│ Boolean │ 1000000 │ ' 22 ms' │ ' 21 ms' │ ' 11 ms' │ ' 1.91 x' │
|
|
1247
|
+
│ Null │ 1000000 │ ' 25 ms' │ ' 20 ms' │ ' 11 ms' │ ' 1.82 x' │
|
|
1248
|
+
│ RegEx │ 1000000 │ ' 167 ms' │ ' 48 ms' │ ' 38 ms' │ ' 1.26 x' │
|
|
1249
|
+
│ ObjectA │ 1000000 │ ' 591 ms' │ ' 36 ms' │ ' 22 ms' │ ' 1.64 x' │
|
|
1250
|
+
│ ObjectB │ 1000000 │ ' 1168 ms' │ ' 61 ms' │ ' 37 ms' │ ' 1.65 x' │
|
|
1251
|
+
│ Tuple │ 1000000 │ ' 127 ms' │ ' 24 ms' │ ' 14 ms' │ ' 1.71 x' │
|
|
1252
|
+
│ Union │ 1000000 │ ' 340 ms' │ ' 26 ms' │ ' 16 ms' │ ' 1.63 x' │
|
|
1253
|
+
│ Recursive │ 1000000 │ ' 3174 ms' │ ' 432 ms' │ ' 100 ms' │ ' 4.32 x' │
|
|
1254
|
+
│ Vector4 │ 1000000 │ ' 142 ms' │ ' 24 ms' │ ' 12 ms' │ ' 2.00 x' │
|
|
1255
|
+
│ Matrix4 │ 1000000 │ ' 577 ms' │ ' 40 ms' │ ' 28 ms' │ ' 1.43 x' │
|
|
1256
|
+
│ Literal_String │ 1000000 │ ' 47 ms' │ ' 19 ms' │ ' 10 ms' │ ' 1.90 x' │
|
|
1257
|
+
│ Literal_Number │ 1000000 │ ' 47 ms' │ ' 19 ms' │ ' 9 ms' │ ' 2.11 x' │
|
|
1258
|
+
│ Literal_Boolean │ 1000000 │ ' 45 ms' │ ' 19 ms' │ ' 11 ms' │ ' 1.73 x' │
|
|
1259
|
+
│ Array_Number │ 1000000 │ ' 432 ms' │ ' 33 ms' │ ' 19 ms' │ ' 1.74 x' │
|
|
1260
|
+
│ Array_String │ 1000000 │ ' 462 ms' │ ' 32 ms' │ ' 22 ms' │ ' 1.45 x' │
|
|
1261
|
+
│ Array_Boolean │ 1000000 │ ' 455 ms' │ ' 32 ms' │ ' 26 ms' │ ' 1.23 x' │
|
|
1262
|
+
│ Array_ObjectA │ 1000000 │ ' 14595 ms' │ ' 2306 ms' │ ' 1496 ms' │ ' 1.54 x' │
|
|
1263
|
+
│ Array_ObjectB │ 1000000 │ ' 17310 ms' │ ' 2625 ms' │ ' 2105 ms' │ ' 1.25 x' │
|
|
1264
|
+
│ Array_Tuple │ 1000000 │ ' 1794 ms' │ ' 97 ms' │ ' 66 ms' │ ' 1.47 x' │
|
|
1265
|
+
│ Array_Union │ 1000000 │ ' 5085 ms' │ ' 246 ms' │ ' 91 ms' │ ' 2.70 x' │
|
|
1266
|
+
│ Array_Recursive │ 1000000 │ ' 59747 ms' │ ' 7866 ms' │ ' 1136 ms' │ ' 6.92 x' │
|
|
1267
|
+
│ Array_Vector4 │ 1000000 │ ' 2375 ms' │ ' 99 ms' │ ' 48 ms' │ ' 2.06 x' │
|
|
1268
|
+
│ Array_Matrix4 │ 1000000 │ ' 13115 ms' │ ' 385 ms' │ ' 246 ms' │ ' 1.57 x' │
|
|
1256
1269
|
└──────────────────┴────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
|
|
1257
1270
|
```
|
|
1258
1271
|
|
|
@@ -1266,12 +1279,13 @@ The following table lists esbuild compiled and minified sizes for each TypeBox m
|
|
|
1266
1279
|
┌──────────────────────┬────────────┬────────────┬─────────────┐
|
|
1267
1280
|
│ (index) │ Compiled │ Minified │ Compression │
|
|
1268
1281
|
├──────────────────────┼────────────┼────────────┼─────────────┤
|
|
1269
|
-
│ typebox/compiler │ '
|
|
1282
|
+
│ typebox/compiler │ ' 61 kb' │ ' 30 kb' │ '2.03 x' │
|
|
1270
1283
|
│ typebox/conditional │ ' 45 kb' │ ' 18 kb' │ '2.44 x' │
|
|
1271
1284
|
│ typebox/custom │ ' 0 kb' │ ' 0 kb' │ '2.61 x' │
|
|
1272
1285
|
│ typebox/format │ ' 0 kb' │ ' 0 kb' │ '2.66 x' │
|
|
1273
1286
|
│ typebox/guard │ ' 23 kb' │ ' 11 kb' │ '2.07 x' │
|
|
1274
|
-
│ typebox/
|
|
1287
|
+
│ typebox/hash │ ' 4 kb' │ ' 1 kb' │ '2.27 x' │
|
|
1288
|
+
│ typebox/value │ ' 85 kb' │ ' 39 kb' │ '2.16 x' │
|
|
1275
1289
|
│ typebox │ ' 12 kb' │ ' 6 kb' │ '1.89 x' │
|
|
1276
1290
|
└──────────────────────┴────────────┴────────────┴─────────────┘
|
|
1277
1291
|
```
|
package/value/check.js
CHANGED
|
@@ -31,6 +31,7 @@ exports.ValueCheck = exports.ValueCheckUnknownTypeError = void 0;
|
|
|
31
31
|
const Types = require("../typebox");
|
|
32
32
|
const index_1 = require("../format/index");
|
|
33
33
|
const index_2 = require("../custom/index");
|
|
34
|
+
const index_3 = require("../hash/index");
|
|
34
35
|
class ValueCheckUnknownTypeError extends Error {
|
|
35
36
|
constructor(schema) {
|
|
36
37
|
super(`ValueCheck: ${schema[Types.Kind] ? `Unknown type '${schema[Types.Kind]}'` : 'Unknown type'}`);
|
|
@@ -56,7 +57,16 @@ var ValueCheck;
|
|
|
56
57
|
if (IsNumber(schema.maxItems) && !(value.length <= schema.maxItems)) {
|
|
57
58
|
return false;
|
|
58
59
|
}
|
|
59
|
-
|
|
60
|
+
// prettier-ignore
|
|
61
|
+
if (schema.uniqueItems === true && !((function () { const set = new Set(); for (const element of value) {
|
|
62
|
+
const hashed = index_3.ValueHash.Create(element);
|
|
63
|
+
if (set.has(hashed)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
set.add(hashed);
|
|
68
|
+
}
|
|
69
|
+
} return true; })())) {
|
|
60
70
|
return false;
|
|
61
71
|
}
|
|
62
72
|
return value.every((val) => Visit(schema.items, references, val));
|
package/value/index.d.ts
CHANGED
package/value/index.js
CHANGED
|
@@ -41,8 +41,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
41
41
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
42
42
|
};
|
|
43
43
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
-
exports.ValueErrorType = void 0;
|
|
44
|
+
exports.Delete = exports.Update = exports.Insert = exports.Edit = exports.ValueErrorType = void 0;
|
|
45
45
|
var index_1 = require("../errors/index");
|
|
46
46
|
Object.defineProperty(exports, "ValueErrorType", { enumerable: true, get: function () { return index_1.ValueErrorType; } });
|
|
47
|
+
var delta_1 = require("./delta");
|
|
48
|
+
Object.defineProperty(exports, "Edit", { enumerable: true, get: function () { return delta_1.Edit; } });
|
|
49
|
+
Object.defineProperty(exports, "Insert", { enumerable: true, get: function () { return delta_1.Insert; } });
|
|
50
|
+
Object.defineProperty(exports, "Update", { enumerable: true, get: function () { return delta_1.Update; } });
|
|
51
|
+
Object.defineProperty(exports, "Delete", { enumerable: true, get: function () { return delta_1.Delete; } });
|
|
47
52
|
__exportStar(require("./pointer"), exports);
|
|
48
53
|
__exportStar(require("./value"), exports);
|
package/value/value.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as Types from '../typebox';
|
|
2
2
|
import { ValueError } from '../errors/index';
|
|
3
3
|
import { Edit } from './delta';
|
|
4
|
-
export { Edit, Insert, Update, Delete } from './delta';
|
|
5
4
|
/** Provides functions to perform structural updates to JavaScript values */
|
|
6
5
|
export declare namespace Value {
|
|
7
6
|
/** Casts a value into a given type. The return value will retain as much information of the original value as possible. Cast will convert string, number and boolean values if a reasonable conversion is possible. */
|
|
@@ -16,16 +15,18 @@ export declare namespace Value {
|
|
|
16
15
|
function Check<T extends Types.TSchema, R extends Types.TSchema[]>(schema: T, references: [...R], value: unknown): value is Types.Static<T>;
|
|
17
16
|
/** Returns true if the value matches the given type. */
|
|
18
17
|
function Check<T extends Types.TSchema>(schema: T, value: unknown): value is Types.Static<T>;
|
|
18
|
+
/** Returns a structural clone of the given value */
|
|
19
|
+
function Clone<T>(value: T): T;
|
|
19
20
|
/** Returns an iterator for each error in this value. */
|
|
20
21
|
function Errors<T extends Types.TSchema, R extends Types.TSchema[]>(schema: T, references: [...R], value: unknown): IterableIterator<ValueError>;
|
|
21
22
|
/** Returns an iterator for each error in this value. */
|
|
22
23
|
function Errors<T extends Types.TSchema>(schema: T, value: unknown): IterableIterator<ValueError>;
|
|
23
24
|
/** Returns true if left and right values are structurally equal */
|
|
24
25
|
function Equal<T>(left: T, right: unknown): right is T;
|
|
25
|
-
/** Returns a structural clone of the given value */
|
|
26
|
-
function Clone<T>(value: T): T;
|
|
27
26
|
/** Returns edits to transform the current value into the next value */
|
|
28
27
|
function Diff(current: unknown, next: unknown): Edit[];
|
|
28
|
+
/** Returns a FNV1A-64 non cryptographic hash of the given value */
|
|
29
|
+
function Hash(value: unknown): bigint;
|
|
29
30
|
/** Returns a new value with edits applied to the given value */
|
|
30
31
|
function Patch<T = any>(current: unknown, edits: Edit[]): T;
|
|
31
32
|
}
|
package/value/value.js
CHANGED
|
@@ -27,19 +27,15 @@ THE SOFTWARE.
|
|
|
27
27
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.Value =
|
|
30
|
+
exports.Value = void 0;
|
|
31
31
|
const index_1 = require("../errors/index");
|
|
32
|
+
const index_2 = require("../hash/index");
|
|
32
33
|
const equal_1 = require("./equal");
|
|
33
34
|
const cast_1 = require("./cast");
|
|
34
35
|
const clone_1 = require("./clone");
|
|
35
36
|
const create_1 = require("./create");
|
|
36
37
|
const check_1 = require("./check");
|
|
37
38
|
const delta_1 = require("./delta");
|
|
38
|
-
var delta_2 = require("./delta");
|
|
39
|
-
Object.defineProperty(exports, "Edit", { enumerable: true, get: function () { return delta_2.Edit; } });
|
|
40
|
-
Object.defineProperty(exports, "Insert", { enumerable: true, get: function () { return delta_2.Insert; } });
|
|
41
|
-
Object.defineProperty(exports, "Update", { enumerable: true, get: function () { return delta_2.Update; } });
|
|
42
|
-
Object.defineProperty(exports, "Delete", { enumerable: true, get: function () { return delta_2.Delete; } });
|
|
43
39
|
/** Provides functions to perform structural updates to JavaScript values */
|
|
44
40
|
var Value;
|
|
45
41
|
(function (Value) {
|
|
@@ -58,6 +54,11 @@ var Value;
|
|
|
58
54
|
return check_1.ValueCheck.Check(schema, references, value);
|
|
59
55
|
}
|
|
60
56
|
Value.Check = Check;
|
|
57
|
+
/** Returns a structural clone of the given value */
|
|
58
|
+
function Clone(value) {
|
|
59
|
+
return clone_1.ValueClone.Clone(value);
|
|
60
|
+
}
|
|
61
|
+
Value.Clone = Clone;
|
|
61
62
|
function* Errors(...args) {
|
|
62
63
|
const [schema, references, value] = args.length === 3 ? [args[0], args[1], args[2]] : [args[0], [], args[1]];
|
|
63
64
|
yield* index_1.ValueErrors.Errors(schema, references, value);
|
|
@@ -68,16 +69,16 @@ var Value;
|
|
|
68
69
|
return equal_1.ValueEqual.Equal(left, right);
|
|
69
70
|
}
|
|
70
71
|
Value.Equal = Equal;
|
|
71
|
-
/** Returns a structural clone of the given value */
|
|
72
|
-
function Clone(value) {
|
|
73
|
-
return clone_1.ValueClone.Clone(value);
|
|
74
|
-
}
|
|
75
|
-
Value.Clone = Clone;
|
|
76
72
|
/** Returns edits to transform the current value into the next value */
|
|
77
73
|
function Diff(current, next) {
|
|
78
74
|
return delta_1.ValueDelta.Diff(current, next);
|
|
79
75
|
}
|
|
80
76
|
Value.Diff = Diff;
|
|
77
|
+
/** Returns a FNV1A-64 non cryptographic hash of the given value */
|
|
78
|
+
function Hash(value) {
|
|
79
|
+
return index_2.ValueHash.Create(value);
|
|
80
|
+
}
|
|
81
|
+
Value.Hash = Hash;
|
|
81
82
|
/** Returns a new value with edits applied to the given value */
|
|
82
83
|
function Patch(current, edits) {
|
|
83
84
|
return delta_1.ValueDelta.Patch(current, edits);
|