@sinclair/typebox 0.25.10 → 0.25.12

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.
@@ -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}).size === ${value}.length)`;
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
- if (schema.uniqueItems === true && !(new Set(value).size === value.length)) {
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 = globalThis.BigInt('14695981039346656037');
56
+ const [Prime, Size] = [globalThis.BigInt('1099511628211'), globalThis.BigInt('2') ** globalThis.BigInt('64')];
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 = globalThis.BigInt('14695981039346656037');
179
+ Visit(value);
180
+ return Hash;
181
+ }
182
+ ValueHash.Create = Create;
183
+ })(ValueHash = exports.ValueHash || (exports.ValueHash = {}));
@@ -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.10",
3
+ "version": "0.25.12",
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 │ ' 414 ms' │ ' 14 ms' │ ' 29.57 x' │
1196
- │ String │ 2000 │ ' 326 ms' │ ' 12 ms' │ ' 27.17 x' │
1197
- │ Boolean │ 2000 │ ' 301 ms' │ ' 11 ms' │ ' 27.36 x' │
1198
- │ Null │ 2000 │ ' 253 ms' │ ' 8 ms' │ ' 31.63 x' │
1199
- │ RegEx │ 2000 │ ' 480 ms' │ ' 18 ms' │ ' 26.67 x' │
1200
- │ ObjectA │ 2000 │ ' 2704 ms' │ ' 53 ms' │ ' 51.02 x' │
1201
- │ ObjectB │ 2000 │ ' 2846 ms' │ ' 35 ms' │ ' 81.31 x' │
1202
- │ Tuple │ 2000 │ ' 1244 ms' │ ' 23 ms' │ ' 54.09 x' │
1203
- │ Union │ 2000 │ ' 1222 ms' │ ' 26 ms' │ ' 47.00 x' │
1204
- │ Vector4 │ 2000 │ ' 1522 ms' │ ' 22 ms' │ ' 69.18 x' │
1205
- │ Matrix4 │ 2000 │ ' 830 ms' │ ' 10 ms' │ ' 83.00 x' │
1206
- │ Literal_String │ 2000 │ ' 348 ms' │ ' 9 ms' │ ' 38.67 x' │
1207
- │ Literal_Number │ 2000 │ ' 356 ms' │ ' 9 ms' │ ' 39.56 x' │
1208
- │ Literal_Boolean │ 2000 │ ' 353 ms' │ ' 6 ms' │ ' 58.83 x' │
1209
- │ Array_Number │ 2000 │ ' 686 ms' │ ' 11 ms' │ ' 62.36 x' │
1210
- │ Array_String │ 2000 │ ' 722 ms' │ ' 11 ms' │ ' 65.64 x' │
1211
- │ Array_Boolean │ 2000 │ ' 724 ms' │ ' 9 ms' │ ' 80.44 x' │
1212
- │ Array_ObjectA │ 2000 │ ' 3706 ms' │ ' 36 ms' │ ' 102.94 x' │
1213
- │ Array_ObjectB │ 2000 │ ' 3678 ms' │ ' 38 ms' │ ' 96.79 x' │
1214
- │ Array_Tuple │ 2000 │ ' 2217 ms' │ ' 23 ms' │ ' 96.39 x' │
1215
- │ Array_Union │ 2000 │ ' 1654 ms' │ ' 24 ms' │ ' 68.92 x' │
1216
- │ Array_Vector4 │ 2000 │ ' 2283 ms' │ ' 20 ms' │ ' 114.15 x' │
1217
- │ Array_Matrix4 │ 2000 │ ' 1567 ms' │ ' 19 ms' │ ' 82.47 x' │
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 │ ' 33 ms' │ ' 6 ms' │ ' 5 ms' │ ' 1.20 x' │
1232
- │ String │ 1000000 │ ' 26 ms' │ ' 24 ms' │ ' 12 ms' │ ' 2.00 x' │
1233
- │ Boolean │ 1000000 │ ' 24 ms' │ ' 22 ms' │ ' 11 ms' │ ' 2.00 x' │
1234
- │ Null │ 1000000 │ ' 28 ms' │ ' 24 ms' │ ' 11 ms' │ ' 2.18 x' │
1235
- │ RegEx │ 1000000 │ ' 171 ms' │ ' 56 ms' │ ' 41 ms' │ ' 1.37 x' │
1236
- │ ObjectA │ 1000000 │ ' 614 ms' │ ' 42 ms' │ ' 24 ms' │ ' 1.75 x' │
1237
- │ ObjectB │ 1000000 │ ' 1109 ms' │ ' 59 ms' │ ' 45 ms' │ ' 1.31 x' │
1238
- │ Tuple │ 1000000 │ ' 122 ms' │ ' 25 ms' │ ' 13 ms' │ ' 1.92 x' │
1239
- │ Union │ 1000000 │ ' 316 ms' │ ' 26 ms' │ ' 16 ms' │ ' 1.63 x' │
1240
- │ Recursive │ 1000000 │ ' 3219 ms' │ ' 453 ms' │ ' 128 ms' │ ' 3.54 x' │
1241
- │ Vector4 │ 1000000 │ ' 145 ms' │ ' 26 ms' │ ' 13 ms' │ ' 2.00 x' │
1242
- │ Matrix4 │ 1000000 │ ' 537 ms' │ ' 42 ms' │ ' 28 ms' │ ' 1.50 x' │
1243
- │ Literal_String │ 1000000 │ ' 51 ms' │ ' 21 ms' │ ' 11 ms' │ ' 1.91 x' │
1244
- │ Literal_Number │ 1000000 │ ' 48 ms' │ ' 20 ms' │ ' 11 ms' │ ' 1.82 x' │
1245
- │ Literal_Boolean │ 1000000 │ ' 49 ms' │ ' 20 ms' │ ' 11 ms' │ ' 1.82 x' │
1246
- │ Array_Number │ 1000000 │ ' 438 ms' │ ' 35 ms' │ ' 19 ms' │ ' 1.84 x' │
1247
- │ Array_String │ 1000000 │ ' 468 ms' │ ' 33 ms' │ ' 23 ms' │ ' 1.43 x' │
1248
- │ Array_Boolean │ 1000000 │ ' 448 ms' │ ' 36 ms' │ ' 29 ms' │ ' 1.24 x' │
1249
- │ Array_ObjectA │ 1000000 │ ' 13904 ms' │ ' 2536 ms' │ ' 1530 ms' │ ' 1.66 x' │
1250
- │ Array_ObjectB │ 1000000 │ ' 16188 ms' │ ' 2724 ms' │ ' 1834 ms' │ ' 1.49 x' │
1251
- │ Array_Tuple │ 1000000 │ ' 1725 ms' │ ' 98 ms' │ ' 64 ms' │ ' 1.53 x' │
1252
- │ Array_Union │ 1000000 │ ' 4762 ms' │ ' 237 ms' │ ' 87 ms' │ ' 2.72 x' │
1253
- │ Array_Recursive │ 1000000 │ ' 54754 ms' │ ' 7707 ms' │ ' 1152 ms' │ ' 6.69 x' │
1254
- │ Array_Vector4 │ 1000000 │ ' 2485 ms' │ ' 100 ms' │ ' 48 ms' │ ' 2.08 x' │
1255
- │ Array_Matrix4 │ 1000000 │ ' 13116 ms' │ ' 387 ms' │ ' 232 ms' │ ' 1.67 x' │
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 │ ' 56 kb' │ ' 28 kb' │ '2.01 x' │
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/value │ ' 80 kb' │ ' 37 kb' │ '2.16 x' │
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/cast.js CHANGED
@@ -146,10 +146,10 @@ var ValueCast;
146
146
  return IsBigInt(value) || IsBoolean(value) || IsNumber(value);
147
147
  }
148
148
  function IsValueTrue(value) {
149
- return value === true || (IsNumber(value) && value === 1) || (IsBigInt(value) && value === 1n) || (IsString(value) && (value.toLowerCase() === 'true' || value === '1'));
149
+ return value === true || (IsNumber(value) && value === 1) || (IsBigInt(value) && value === globalThis.BigInt('1')) || (IsString(value) && (value.toLowerCase() === 'true' || value === '1'));
150
150
  }
151
151
  function IsValueFalse(value) {
152
- return value === false || (IsNumber(value) && value === 0) || (IsBigInt(value) && value === 0n) || (IsString(value) && (value.toLowerCase() === 'false' || value === '0'));
152
+ return value === false || (IsNumber(value) && value === 0) || (IsBigInt(value) && value === globalThis.BigInt('0')) || (IsString(value) && (value.toLowerCase() === 'false' || value === '0'));
153
153
  }
154
154
  // ----------------------------------------------------------------------------------------------
155
155
  // Convert
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
- if (schema.uniqueItems === true && !(new Set(value).size === value.length)) {
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
@@ -1,3 +1,4 @@
1
1
  export { ValueError, ValueErrorType } from '../errors/index';
2
+ export { Edit, Insert, Update, Delete } from './delta';
2
3
  export * from './pointer';
3
4
  export * from './value';
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 = exports.Delete = exports.Update = exports.Insert = exports.Edit = void 0;
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);