schema-shield 1.0.4 → 1.1.0
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/README.md +419 -919
- package/dist/formats.d.ts.map +1 -1
- package/dist/index.d.ts +33 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1250 -391
- package/dist/index.min.js +2 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +1250 -391
- package/dist/keywords/array-keywords.d.ts.map +1 -1
- package/dist/keywords/number-keywords.d.ts.map +1 -1
- package/dist/keywords/object-keywords.d.ts +7 -1
- package/dist/keywords/object-keywords.d.ts.map +1 -1
- package/dist/keywords/other-keywords.d.ts +17 -1
- package/dist/keywords/other-keywords.d.ts.map +1 -1
- package/dist/keywords/string-keywords.d.ts.map +1 -1
- package/dist/utils/deep-freeze.d.ts.map +1 -1
- package/dist/utils/main-utils.d.ts +8 -4
- package/dist/utils/main-utils.d.ts.map +1 -1
- package/lib/formats.ts +36 -10
- package/lib/index.ts +1157 -155
- package/lib/keywords/array-keywords.ts +18 -3
- package/lib/keywords/number-keywords.ts +19 -5
- package/lib/keywords/object-keywords.ts +59 -61
- package/lib/keywords/other-keywords.ts +205 -192
- package/lib/keywords/string-keywords.ts +51 -8
- package/lib/types.ts +2 -2
- package/lib/utils/deep-freeze.ts +6 -4
- package/lib/utils/main-utils.ts +97 -42
- package/package.json +9 -10
package/lib/utils/main-utils.ts
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
import { CompiledSchema } from "../index";
|
|
1
|
+
import type { CompiledSchema } from "../index";
|
|
2
|
+
|
|
3
|
+
const hasOwnPropertyIntrinsic = Object.prototype.hasOwnProperty;
|
|
4
|
+
const hasOwnPropertyCall = Function.prototype.call.bind(
|
|
5
|
+
hasOwnPropertyIntrinsic
|
|
6
|
+
) as (target: any, key: PropertyKey) => boolean;
|
|
7
|
+
|
|
8
|
+
export function definePropertyOrThrow<T extends object>(
|
|
9
|
+
target: T,
|
|
10
|
+
key: PropertyKey,
|
|
11
|
+
descriptor: PropertyDescriptor
|
|
12
|
+
): T {
|
|
13
|
+
if (!Reflect.defineProperty(target, key, descriptor)) {
|
|
14
|
+
throw new TypeError(`Cannot define property "${String(key)}"`);
|
|
15
|
+
}
|
|
16
|
+
return target;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function hasOwn(target: any, key: PropertyKey): boolean {
|
|
20
|
+
return hasOwnPropertyCall(target, key);
|
|
21
|
+
}
|
|
2
22
|
|
|
3
23
|
interface ErrorTree {
|
|
4
24
|
message: string;
|
|
@@ -11,6 +31,7 @@ interface ErrorTree {
|
|
|
11
31
|
}
|
|
12
32
|
|
|
13
33
|
export class ValidationError extends Error {
|
|
34
|
+
code?: string;
|
|
14
35
|
message: string;
|
|
15
36
|
item?: string | number;
|
|
16
37
|
keyword: string;
|
|
@@ -20,51 +41,76 @@ export class ValidationError extends Error {
|
|
|
20
41
|
data?: any;
|
|
21
42
|
schema?: CompiledSchema;
|
|
22
43
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (typeof this.item !== "undefined") {
|
|
27
|
-
if (typeof this.item === "string" && this.item in this.schema) {
|
|
28
|
-
schemaPath += `/${this.item}`;
|
|
29
|
-
}
|
|
30
|
-
instancePath += `/${this.item}`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
this.instancePath = instancePath;
|
|
34
|
-
this.schemaPath = schemaPath;
|
|
35
|
-
|
|
36
|
-
// If there is no cause or the cause is not a ValidationError, return this
|
|
37
|
-
if (!this.cause || !(this.cause instanceof ValidationError)) {
|
|
38
|
-
return this;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return this.cause._getCause(schemaPath, instancePath);
|
|
44
|
+
constructor(message: string) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.message = message;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
getCause(): ValidationError {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
let current: ValidationError = this;
|
|
51
|
+
let schemaPointer = "#";
|
|
52
|
+
let instancePointer = "#";
|
|
53
|
+
const seen = new Set<ValidationError>();
|
|
54
|
+
|
|
55
|
+
while (!seen.has(current)) {
|
|
56
|
+
seen.add(current);
|
|
57
|
+
let schemaPath = `${schemaPointer}/${current.keyword}`;
|
|
58
|
+
let instancePath = instancePointer;
|
|
59
|
+
if (typeof current.item !== "undefined") {
|
|
60
|
+
if (
|
|
61
|
+
typeof current.item === "string" &&
|
|
62
|
+
current.schema &&
|
|
63
|
+
typeof current.schema === "object" &&
|
|
64
|
+
current.item in current.schema
|
|
65
|
+
) {
|
|
66
|
+
schemaPath += `/${escapeJsonPointerToken(current.item)}`;
|
|
67
|
+
}
|
|
68
|
+
instancePath += `/${escapeJsonPointerToken(current.item)}`;
|
|
69
|
+
}
|
|
70
|
+
current.schemaPath = schemaPath;
|
|
71
|
+
current.instancePath = instancePath;
|
|
72
|
+
|
|
73
|
+
if (
|
|
74
|
+
!(current.cause instanceof ValidationError) ||
|
|
75
|
+
seen.has(current.cause)
|
|
76
|
+
) {
|
|
77
|
+
return current;
|
|
78
|
+
}
|
|
79
|
+
schemaPointer = schemaPath;
|
|
80
|
+
instancePointer = instancePath;
|
|
81
|
+
current = current.cause;
|
|
60
82
|
}
|
|
61
|
-
|
|
62
|
-
return tree;
|
|
83
|
+
return current;
|
|
63
84
|
}
|
|
64
85
|
|
|
65
86
|
getTree(): ErrorTree {
|
|
66
87
|
this.getCause();
|
|
67
|
-
|
|
88
|
+
let current: ValidationError | undefined = this;
|
|
89
|
+
let root: ErrorTree | undefined;
|
|
90
|
+
let target: ErrorTree | undefined;
|
|
91
|
+
const seen = new Set<ValidationError>();
|
|
92
|
+
|
|
93
|
+
while (current && !seen.has(current)) {
|
|
94
|
+
seen.add(current);
|
|
95
|
+
const node: ErrorTree = {
|
|
96
|
+
message: current.message,
|
|
97
|
+
keyword: current.keyword,
|
|
98
|
+
item: current.item,
|
|
99
|
+
schemaPath: current.schemaPath,
|
|
100
|
+
instancePath: current.instancePath,
|
|
101
|
+
data: current.data
|
|
102
|
+
};
|
|
103
|
+
if (!root) {
|
|
104
|
+
root = node;
|
|
105
|
+
} else if (target) {
|
|
106
|
+
target.cause = node;
|
|
107
|
+
}
|
|
108
|
+
target = node;
|
|
109
|
+
current =
|
|
110
|
+
current.cause instanceof ValidationError ? current.cause : undefined;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return root!;
|
|
68
114
|
}
|
|
69
115
|
|
|
70
116
|
getPath() {
|
|
@@ -77,6 +123,7 @@ export class ValidationError extends Error {
|
|
|
77
123
|
}
|
|
78
124
|
|
|
79
125
|
export interface DefineErrorOptions {
|
|
126
|
+
code?: string;
|
|
80
127
|
item?: any; // Final item in the schemaPath
|
|
81
128
|
cause?: ValidationError | true; // Cause of the error
|
|
82
129
|
data?: any; // Data that caused the error
|
|
@@ -88,6 +135,7 @@ export interface DefineErrorFunction {
|
|
|
88
135
|
options?: DefineErrorOptions
|
|
89
136
|
): ValidationError | void | true;
|
|
90
137
|
}
|
|
138
|
+
|
|
91
139
|
const FAIL_FAST_DEFINE_ERROR: DefineErrorFunction = () => true;
|
|
92
140
|
|
|
93
141
|
export function getDefinedErrorFunctionForKey(
|
|
@@ -105,9 +153,12 @@ export function getDefinedErrorFunctionForKey(
|
|
|
105
153
|
|
|
106
154
|
const defineError: DefineErrorFunction = (message, options = {}) => {
|
|
107
155
|
KeywordError.message = message;
|
|
156
|
+
KeywordError.code = options.code;
|
|
108
157
|
KeywordError.item = options.item;
|
|
109
|
-
|
|
110
|
-
|
|
158
|
+
if (options.cause !== KeywordError) {
|
|
159
|
+
KeywordError.cause =
|
|
160
|
+
options.cause && options.cause !== true ? options.cause : undefined;
|
|
161
|
+
}
|
|
111
162
|
KeywordError.data = options.data;
|
|
112
163
|
return KeywordError;
|
|
113
164
|
};
|
|
@@ -118,6 +169,10 @@ export function getDefinedErrorFunctionForKey(
|
|
|
118
169
|
);
|
|
119
170
|
}
|
|
120
171
|
|
|
172
|
+
export function escapeJsonPointerToken(value: string | number): string {
|
|
173
|
+
return String(value).replace(/~/g, "~0").replace(/\//g, "~1");
|
|
174
|
+
}
|
|
175
|
+
|
|
121
176
|
export function getUTF16Length(str) {
|
|
122
177
|
let length = 0;
|
|
123
178
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -139,8 +194,8 @@ export function isCompiledSchema(subSchema: any): subSchema is CompiledSchema {
|
|
|
139
194
|
);
|
|
140
195
|
}
|
|
141
196
|
|
|
142
|
-
export function getNamedFunction<T>(name: string, fn: T): T {
|
|
143
|
-
return
|
|
197
|
+
export function getNamedFunction<T extends object>(name: string, fn: T): T {
|
|
198
|
+
return definePropertyOrThrow(fn, "name", { value: name });
|
|
144
199
|
}
|
|
145
200
|
|
|
146
201
|
export function resolvePath(root: any, path: string): any {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "schema-shield",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A fast library that protects your JSON schema from invalid data.",
|
|
5
5
|
"repository": "git@github.com:Masquerade-Circus/schema-shield.git",
|
|
6
6
|
"author": "Masquerade <christian@masquerade-circus.net>",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"module": "dist/index.mjs",
|
|
14
14
|
"unpkg": "dist/index.min.js",
|
|
15
15
|
"browser": "dist/index.min.js",
|
|
16
|
-
"types": "dist
|
|
16
|
+
"types": "dist/index.d.ts",
|
|
17
17
|
"exports": {
|
|
18
18
|
".": {
|
|
19
19
|
"types": "./dist/index.d.ts",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"User friendly"
|
|
67
67
|
],
|
|
68
68
|
"engines": {
|
|
69
|
-
"node": ">=
|
|
69
|
+
"node": ">=16.1.0"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"test": "mocha --bail --recursive --no-timeouts --forbid-only --exit --require ts-node/register --enable-source-maps tests/**/*.test.ts",
|
|
@@ -78,15 +78,10 @@
|
|
|
78
78
|
"release": "release-it --verbose",
|
|
79
79
|
"release-test": "release-it --dry-run --verbose"
|
|
80
80
|
},
|
|
81
|
-
"dependencies": {
|
|
82
|
-
"ts-node": "^10.9.1",
|
|
83
|
-
"tsc-prog": "^2.2.1",
|
|
84
|
-
"tslib": "^2.5.0",
|
|
85
|
-
"typescript": "^5.0.2"
|
|
86
|
-
},
|
|
87
81
|
"devDependencies": {
|
|
88
82
|
"@exodus/schemasafe": "^1.0.0",
|
|
89
83
|
"@release-it/conventional-changelog": "^5.1.1",
|
|
84
|
+
"@types/mocha": "^10.0.10",
|
|
90
85
|
"@typescript-eslint/eslint-plugin": "^5.56.0",
|
|
91
86
|
"@typescript-eslint/parser": "^5.56.0",
|
|
92
87
|
"ajv": "^8.12.0",
|
|
@@ -100,7 +95,11 @@
|
|
|
100
95
|
"nodemon": "^2.0.22",
|
|
101
96
|
"nyc": "^15.1.0",
|
|
102
97
|
"release-it": "^15.9.3",
|
|
103
|
-
"terser": "^5.16.6"
|
|
98
|
+
"terser": "^5.16.6",
|
|
99
|
+
"ts-node": "^10.9.1",
|
|
100
|
+
"tsc-prog": "^2.2.1",
|
|
101
|
+
"tslib": "^2.5.0",
|
|
102
|
+
"typescript": "^5.0.2"
|
|
104
103
|
},
|
|
105
104
|
"nyc": {
|
|
106
105
|
"exclude": [
|