@sinclair/typebox 0.25.9 → 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.d.ts +1 -1
- package/compiler/compiler.js +36 -27
- package/conditional/conditional.d.ts +1 -1
- package/conditional/structural.js +2 -2
- package/custom/custom.d.ts +8 -8
- package/custom/custom.js +5 -5
- package/errors/errors.js +14 -4
- package/format/format.d.ts +6 -6
- package/format/format.js +5 -5
- package/guard/guard.d.ts +2 -2
- package/guard/guard.js +4 -4
- 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 +5 -4
- package/readme.md +82 -64
- package/typebox.d.ts +36 -36
- package/value/cast.js +2 -2
- package/value/check.js +15 -5
- package/value/create.js +3 -3
- package/value/delta.d.ts +4 -4
- package/value/index.d.ts +1 -0
- package/value/index.js +6 -1
- package/value/is.d.ts +4 -4
- package/value/value.d.ts +4 -3
- package/value/value.js +12 -11
package/compiler/compiler.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ValueError } from '../errors/index';
|
|
2
2
|
import * as Types from '../typebox';
|
|
3
|
-
export
|
|
3
|
+
export type CheckFunction = (value: unknown) => boolean;
|
|
4
4
|
export declare class TypeCheck<T extends Types.TSchema> {
|
|
5
5
|
private readonly schema;
|
|
6
6
|
private readonly references;
|
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')`;
|
|
@@ -237,11 +238,11 @@ var TypeCompiler;
|
|
|
237
238
|
// Reference: If we have seen this reference before we can just yield and return
|
|
238
239
|
// the function call. If this isn't the case we defer to visit to generate and
|
|
239
240
|
// set the function for subsequent passes. Consider for refactor.
|
|
240
|
-
if (
|
|
241
|
+
if (state_local_function_names.has(schema.$ref))
|
|
241
242
|
return yield `(${CreateFunctionName(schema.$ref)}(${value}))`;
|
|
242
|
-
if (!
|
|
243
|
+
if (!state_reference_map.has(schema.$ref))
|
|
243
244
|
throw Error(`TypeCompiler.Ref: Cannot de-reference schema with $id '${schema.$ref}'`);
|
|
244
|
-
const reference =
|
|
245
|
+
const reference = state_reference_map.get(schema.$ref);
|
|
245
246
|
yield* Visit(reference, value);
|
|
246
247
|
}
|
|
247
248
|
function* Self(schema, value) {
|
|
@@ -292,15 +293,17 @@ var TypeCompiler;
|
|
|
292
293
|
function* Void(schema, value) {
|
|
293
294
|
yield `(${value} === null)`;
|
|
294
295
|
}
|
|
295
|
-
function*
|
|
296
|
-
|
|
296
|
+
function* UserDefined(schema, value) {
|
|
297
|
+
const schema_key = `schema_key_${state_remote_custom_types.size}`;
|
|
298
|
+
state_remote_custom_types.set(schema_key, schema);
|
|
299
|
+
yield `(custom('${schema[Types.Kind]}', '${schema_key}', ${value}))`;
|
|
297
300
|
}
|
|
298
301
|
function* Visit(schema, value) {
|
|
299
302
|
// Reference: Referenced schemas can originate from either additional schemas
|
|
300
303
|
// or inline in the schema itself. Ideally the recursive path should align to
|
|
301
304
|
// reference path. Consider for refactor.
|
|
302
|
-
if (schema.$id && !
|
|
303
|
-
|
|
305
|
+
if (schema.$id && !state_local_function_names.has(schema.$id)) {
|
|
306
|
+
state_local_function_names.add(schema.$id);
|
|
304
307
|
const name = CreateFunctionName(schema.$id);
|
|
305
308
|
const body = CreateFunction(name, schema, 'value');
|
|
306
309
|
PushFunction(body);
|
|
@@ -358,27 +361,29 @@ var TypeCompiler;
|
|
|
358
361
|
default:
|
|
359
362
|
if (!index_4.Custom.Has(anySchema[Types.Kind]))
|
|
360
363
|
throw new TypeCompilerUnknownTypeError(schema);
|
|
361
|
-
return yield*
|
|
364
|
+
return yield* UserDefined(anySchema, value);
|
|
362
365
|
}
|
|
363
366
|
}
|
|
364
367
|
// -------------------------------------------------------------------
|
|
365
|
-
//
|
|
368
|
+
// Compiler State
|
|
366
369
|
// -------------------------------------------------------------------
|
|
367
|
-
const
|
|
368
|
-
const
|
|
369
|
-
const
|
|
370
|
+
const state_reference_map = new Map(); // tracks schemas with identifiers
|
|
371
|
+
const state_local_variables = new Set(); // local variables and functions
|
|
372
|
+
const state_local_function_names = new Set(); // local function names used call ref validators
|
|
373
|
+
const state_remote_custom_types = new Map(); // remote custom types used during compilation
|
|
370
374
|
function ResetCompiler() {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
375
|
+
state_reference_map.clear();
|
|
376
|
+
state_local_variables.clear();
|
|
377
|
+
state_local_function_names.clear();
|
|
378
|
+
state_remote_custom_types.clear();
|
|
374
379
|
}
|
|
375
380
|
function AddReferences(schemas = []) {
|
|
376
381
|
for (const schema of schemas) {
|
|
377
382
|
if (!schema.$id)
|
|
378
383
|
throw new Error(`TypeCompiler: Referenced schemas must specify an $id.`);
|
|
379
|
-
if (
|
|
384
|
+
if (state_reference_map.has(schema.$id))
|
|
380
385
|
throw new Error(`TypeCompiler: Duplicate schema $id found for '${schema.$id}'`);
|
|
381
|
-
|
|
386
|
+
state_reference_map.set(schema.$id, schema);
|
|
382
387
|
}
|
|
383
388
|
}
|
|
384
389
|
function CreateExpression(schema, value) {
|
|
@@ -392,15 +397,15 @@ var TypeCompiler;
|
|
|
392
397
|
return `function ${name}(value) {\n return (\n${expression}\n )\n}`;
|
|
393
398
|
}
|
|
394
399
|
function PushFunction(functionBody) {
|
|
395
|
-
|
|
400
|
+
state_local_variables.add(functionBody);
|
|
396
401
|
}
|
|
397
402
|
function PushLocal(expression) {
|
|
398
|
-
const local = `local_${
|
|
399
|
-
|
|
403
|
+
const local = `local_${state_local_variables.size}`;
|
|
404
|
+
state_local_variables.add(`const ${local} = ${expression}`);
|
|
400
405
|
return local;
|
|
401
406
|
}
|
|
402
407
|
function GetLocals() {
|
|
403
|
-
return [...
|
|
408
|
+
return [...state_local_variables.values()];
|
|
404
409
|
}
|
|
405
410
|
// -------------------------------------------------------------------
|
|
406
411
|
// Compile
|
|
@@ -416,17 +421,21 @@ var TypeCompiler;
|
|
|
416
421
|
function Compile(schema, references = []) {
|
|
417
422
|
index_2.TypeGuard.Assert(schema, references);
|
|
418
423
|
const code = Build(schema, references);
|
|
419
|
-
const
|
|
420
|
-
const
|
|
421
|
-
|
|
424
|
+
const custom_schemas = new Map(state_remote_custom_types);
|
|
425
|
+
const compiledFunction = globalThis.Function('custom', 'format', 'hash', code);
|
|
426
|
+
const checkFunction = compiledFunction((kind, schema_key, value) => {
|
|
427
|
+
if (!index_4.Custom.Has(kind) || !custom_schemas.has(schema_key))
|
|
422
428
|
return false;
|
|
429
|
+
const schema = custom_schemas.get(schema_key);
|
|
423
430
|
const func = index_4.Custom.Get(kind);
|
|
424
|
-
return func(value);
|
|
431
|
+
return func(schema, value);
|
|
425
432
|
}, (format, value) => {
|
|
426
433
|
if (!index_3.Format.Has(format))
|
|
427
434
|
return false;
|
|
428
435
|
const func = index_3.Format.Get(format);
|
|
429
436
|
return func(value);
|
|
437
|
+
}, (value) => {
|
|
438
|
+
return index_5.ValueHash.Create(value);
|
|
430
439
|
});
|
|
431
440
|
return new TypeCheck(schema, references, checkFunction, code);
|
|
432
441
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as Types from '../typebox';
|
|
2
|
-
export
|
|
2
|
+
export type TExtends<L extends Types.TSchema, R extends Types.TSchema, T extends Types.TSchema, U extends Types.TSchema> = Types.Static<L> extends Types.Static<R> ? T : U;
|
|
3
3
|
export interface TExclude<T extends Types.TUnion, U extends Types.TUnion> extends Types.TUnion<any[]> {
|
|
4
4
|
static: Exclude<Types.Static<T, this['params']>, Types.Static<U, this['params']>>;
|
|
5
5
|
}
|
|
@@ -57,7 +57,7 @@ var Structural;
|
|
|
57
57
|
return true;
|
|
58
58
|
if (guard_1.TypeGuard.TAny(right))
|
|
59
59
|
return true;
|
|
60
|
-
if (guard_1.TypeGuard.
|
|
60
|
+
if (guard_1.TypeGuard.TUserDefined(right))
|
|
61
61
|
throw Error(`Structural: Cannot structurally compare custom type '${right[Types.Kind]}'`);
|
|
62
62
|
return false;
|
|
63
63
|
}
|
|
@@ -668,7 +668,7 @@ var Structural;
|
|
|
668
668
|
else if (guard_1.TypeGuard.TVoid(left)) {
|
|
669
669
|
return Void(left, resolvedRight);
|
|
670
670
|
}
|
|
671
|
-
else if (guard_1.TypeGuard.
|
|
671
|
+
else if (guard_1.TypeGuard.TUserDefined(left)) {
|
|
672
672
|
throw Error(`Structural: Cannot structurally compare custom type '${left[Types.Kind]}'`);
|
|
673
673
|
}
|
|
674
674
|
else {
|
package/custom/custom.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export
|
|
2
|
-
/** Provides functions to create
|
|
1
|
+
export type CustomValidationFunction<TSchema> = (schema: TSchema, value: unknown) => boolean;
|
|
2
|
+
/** Provides functions to create user defined types */
|
|
3
3
|
export declare namespace Custom {
|
|
4
|
-
/** Clears all
|
|
4
|
+
/** Clears all user defined types */
|
|
5
5
|
function Clear(): void;
|
|
6
|
-
/** Returns true if this
|
|
6
|
+
/** Returns true if this user defined type exists */
|
|
7
7
|
function Has(kind: string): boolean;
|
|
8
|
-
/** Sets a validation function for a
|
|
9
|
-
function Set(kind: string, func: CustomValidationFunction): void;
|
|
10
|
-
/** Gets a custom validation function */
|
|
11
|
-
function Get(kind: string): CustomValidationFunction | undefined;
|
|
8
|
+
/** Sets a validation function for a user defined type */
|
|
9
|
+
function Set<TSchema = unknown>(kind: string, func: CustomValidationFunction<TSchema>): void;
|
|
10
|
+
/** Gets a custom validation function for a user defined type */
|
|
11
|
+
function Get(kind: string): CustomValidationFunction<any> | undefined;
|
|
12
12
|
}
|
package/custom/custom.js
CHANGED
|
@@ -28,26 +28,26 @@ THE SOFTWARE.
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
30
|
exports.Custom = void 0;
|
|
31
|
-
/** Provides functions to create
|
|
31
|
+
/** Provides functions to create user defined types */
|
|
32
32
|
var Custom;
|
|
33
33
|
(function (Custom) {
|
|
34
34
|
const customs = new Map();
|
|
35
|
-
/** Clears all
|
|
35
|
+
/** Clears all user defined types */
|
|
36
36
|
function Clear() {
|
|
37
37
|
return customs.clear();
|
|
38
38
|
}
|
|
39
39
|
Custom.Clear = Clear;
|
|
40
|
-
/** Returns true if this
|
|
40
|
+
/** Returns true if this user defined type exists */
|
|
41
41
|
function Has(kind) {
|
|
42
42
|
return customs.has(kind);
|
|
43
43
|
}
|
|
44
44
|
Custom.Has = Has;
|
|
45
|
-
/** Sets a validation function for a
|
|
45
|
+
/** Sets a validation function for a user defined type */
|
|
46
46
|
function Set(kind, func) {
|
|
47
47
|
customs.set(kind, func);
|
|
48
48
|
}
|
|
49
49
|
Custom.Set = Set;
|
|
50
|
-
/** Gets a custom validation function */
|
|
50
|
+
/** Gets a custom validation function for a user defined type */
|
|
51
51
|
function Get(kind) {
|
|
52
52
|
return customs.get(kind);
|
|
53
53
|
}
|
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++) {
|
|
@@ -367,9 +377,9 @@ var ValueErrors;
|
|
|
367
377
|
return yield { type: ValueErrorType.Void, schema, path, value, message: `Expected null` };
|
|
368
378
|
}
|
|
369
379
|
}
|
|
370
|
-
function*
|
|
380
|
+
function* UserDefined(schema, references, path, value) {
|
|
371
381
|
const func = index_2.Custom.Get(schema[Types.Kind]);
|
|
372
|
-
if (!func(value)) {
|
|
382
|
+
if (!func(schema, value)) {
|
|
373
383
|
return yield { type: ValueErrorType.Custom, schema, path, value, message: `Expected kind ${schema[Types.Kind]}` };
|
|
374
384
|
}
|
|
375
385
|
}
|
|
@@ -426,7 +436,7 @@ var ValueErrors;
|
|
|
426
436
|
default:
|
|
427
437
|
if (!index_2.Custom.Has(anySchema[Types.Kind]))
|
|
428
438
|
throw new ValueErrorsUnknownTypeError(schema);
|
|
429
|
-
return yield*
|
|
439
|
+
return yield* UserDefined(anySchema, anyReferences, path, value);
|
|
430
440
|
}
|
|
431
441
|
}
|
|
432
442
|
function* Errors(schema, references, value) {
|
package/format/format.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export
|
|
2
|
-
/** Provides functions to create
|
|
1
|
+
export type FormatValidationFunction = (value: string) => boolean;
|
|
2
|
+
/** Provides functions to create user defined string formats */
|
|
3
3
|
export declare namespace Format {
|
|
4
|
-
/** Clears all formats */
|
|
4
|
+
/** Clears all user defined string formats */
|
|
5
5
|
function Clear(): void;
|
|
6
|
-
/** Returns true if the string format exists */
|
|
6
|
+
/** Returns true if the user defined string format exists */
|
|
7
7
|
function Has(format: string): boolean;
|
|
8
|
-
/** Sets a string format
|
|
8
|
+
/** Sets a validation function for a user defined string format */
|
|
9
9
|
function Set(format: string, func: FormatValidationFunction): void;
|
|
10
|
-
/** Gets a string format
|
|
10
|
+
/** Gets a validation function for a user defined string format */
|
|
11
11
|
function Get(format: string): FormatValidationFunction | undefined;
|
|
12
12
|
}
|
package/format/format.js
CHANGED
|
@@ -28,26 +28,26 @@ THE SOFTWARE.
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
30
|
exports.Format = void 0;
|
|
31
|
-
/** Provides functions to create
|
|
31
|
+
/** Provides functions to create user defined string formats */
|
|
32
32
|
var Format;
|
|
33
33
|
(function (Format) {
|
|
34
34
|
const formats = new Map();
|
|
35
|
-
/** Clears all formats */
|
|
35
|
+
/** Clears all user defined string formats */
|
|
36
36
|
function Clear() {
|
|
37
37
|
return formats.clear();
|
|
38
38
|
}
|
|
39
39
|
Format.Clear = Clear;
|
|
40
|
-
/** Returns true if the string format exists */
|
|
40
|
+
/** Returns true if the user defined string format exists */
|
|
41
41
|
function Has(format) {
|
|
42
42
|
return formats.has(format);
|
|
43
43
|
}
|
|
44
44
|
Format.Has = Has;
|
|
45
|
-
/** Sets a string format
|
|
45
|
+
/** Sets a validation function for a user defined string format */
|
|
46
46
|
function Set(format, func) {
|
|
47
47
|
formats.set(format, func);
|
|
48
48
|
}
|
|
49
49
|
Format.Set = Set;
|
|
50
|
-
/** Gets a string format
|
|
50
|
+
/** Gets a validation function for a user defined string format */
|
|
51
51
|
function Get(format) {
|
|
52
52
|
return formats.get(format);
|
|
53
53
|
}
|
package/guard/guard.d.ts
CHANGED
|
@@ -51,8 +51,8 @@ export declare namespace TypeGuard {
|
|
|
51
51
|
function TUnknown(schema: unknown): schema is Types.TUnknown;
|
|
52
52
|
/** Returns true if the given schema is TVoid */
|
|
53
53
|
function TVoid(schema: unknown): schema is Types.TVoid;
|
|
54
|
-
/** Returns true if the given schema is a registered
|
|
55
|
-
function
|
|
54
|
+
/** Returns true if the given schema is a registered user defined type */
|
|
55
|
+
function TUserDefined(schema: unknown): schema is Types.TSchema;
|
|
56
56
|
/** Returns true if the given schema is TSchema */
|
|
57
57
|
function TSchema(schema: unknown): schema is Types.TSchema;
|
|
58
58
|
/** Asserts if this schema and associated references are valid. */
|
package/guard/guard.js
CHANGED
|
@@ -394,11 +394,11 @@ var TypeGuard;
|
|
|
394
394
|
IsOptionalString(schema.$id));
|
|
395
395
|
}
|
|
396
396
|
TypeGuard.TVoid = TVoid;
|
|
397
|
-
/** Returns true if the given schema is a registered
|
|
398
|
-
function
|
|
397
|
+
/** Returns true if the given schema is a registered user defined type */
|
|
398
|
+
function TUserDefined(schema) {
|
|
399
399
|
return IsObject(schema) && IsString(schema[Types.Kind]) && index_1.Custom.Has(schema[Types.Kind]);
|
|
400
400
|
}
|
|
401
|
-
TypeGuard.
|
|
401
|
+
TypeGuard.TUserDefined = TUserDefined;
|
|
402
402
|
/** Returns true if the given schema is TSchema */
|
|
403
403
|
function TSchema(schema) {
|
|
404
404
|
return (TAny(schema) ||
|
|
@@ -424,7 +424,7 @@ var TypeGuard;
|
|
|
424
424
|
TUint8Array(schema) ||
|
|
425
425
|
TUnknown(schema) ||
|
|
426
426
|
TVoid(schema) ||
|
|
427
|
-
|
|
427
|
+
TUserDefined(schema));
|
|
428
428
|
}
|
|
429
429
|
TypeGuard.TSchema = TSchema;
|
|
430
430
|
/** Asserts if this schema and associated references are valid. */
|
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
|
},
|
|
@@ -39,12 +40,12 @@
|
|
|
39
40
|
"@sinclair/hammer": "^0.17.1",
|
|
40
41
|
"@types/chai": "^4.3.3",
|
|
41
42
|
"@types/mocha": "^9.1.1",
|
|
42
|
-
"@types/node": "^18.
|
|
43
|
-
"ajv": "^8.11.
|
|
43
|
+
"@types/node": "^18.11.9",
|
|
44
|
+
"ajv": "^8.11.2",
|
|
44
45
|
"ajv-formats": "^2.1.1",
|
|
45
46
|
"chai": "^4.3.6",
|
|
46
47
|
"mocha": "^9.2.2",
|
|
47
48
|
"prettier": "^2.7.1",
|
|
48
|
-
"typescript": "^4.
|
|
49
|
+
"typescript": "^4.9.3"
|
|
49
50
|
}
|
|
50
51
|
}
|