schema-shield 1.0.5 → 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 +400 -1050
- 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 +1247 -392
- package/dist/index.min.js +2 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +1247 -392
- 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 +7 -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 +91 -47
- package/package.json +8 -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;
|
|
@@ -25,56 +46,71 @@ export class ValidationError extends Error {
|
|
|
25
46
|
this.message = message;
|
|
26
47
|
}
|
|
27
48
|
|
|
28
|
-
|
|
29
|
-
let
|
|
30
|
-
let
|
|
31
|
-
|
|
49
|
+
getCause(): ValidationError {
|
|
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
|
+
|
|
32
73
|
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
typeof this.schema === "object" &&
|
|
36
|
-
this.item in this.schema
|
|
74
|
+
!(current.cause instanceof ValidationError) ||
|
|
75
|
+
seen.has(current.cause)
|
|
37
76
|
) {
|
|
38
|
-
|
|
77
|
+
return current;
|
|
39
78
|
}
|
|
40
|
-
|
|
79
|
+
schemaPointer = schemaPath;
|
|
80
|
+
instancePointer = instancePath;
|
|
81
|
+
current = current.cause;
|
|
41
82
|
}
|
|
42
|
-
|
|
43
|
-
this.instancePath = instancePath;
|
|
44
|
-
this.schemaPath = schemaPath;
|
|
45
|
-
|
|
46
|
-
// If there is no cause or the cause is not a ValidationError, return this
|
|
47
|
-
if (!this.cause || !(this.cause instanceof ValidationError)) {
|
|
48
|
-
return this;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return this.cause._getCause(schemaPath, instancePath);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
getCause(): ValidationError {
|
|
55
|
-
return this._getCause();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
private _getTree(): ErrorTree {
|
|
59
|
-
const tree: ErrorTree = {
|
|
60
|
-
message: this.message,
|
|
61
|
-
keyword: this.keyword,
|
|
62
|
-
item: this.item,
|
|
63
|
-
schemaPath: this.schemaPath,
|
|
64
|
-
instancePath: this.instancePath,
|
|
65
|
-
data: this.data
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
if (this.cause) {
|
|
69
|
-
tree.cause = this.cause._getTree();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return tree;
|
|
83
|
+
return current;
|
|
73
84
|
}
|
|
74
85
|
|
|
75
86
|
getTree(): ErrorTree {
|
|
76
87
|
this.getCause();
|
|
77
|
-
|
|
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!;
|
|
78
114
|
}
|
|
79
115
|
|
|
80
116
|
getPath() {
|
|
@@ -87,6 +123,7 @@ export class ValidationError extends Error {
|
|
|
87
123
|
}
|
|
88
124
|
|
|
89
125
|
export interface DefineErrorOptions {
|
|
126
|
+
code?: string;
|
|
90
127
|
item?: any; // Final item in the schemaPath
|
|
91
128
|
cause?: ValidationError | true; // Cause of the error
|
|
92
129
|
data?: any; // Data that caused the error
|
|
@@ -116,9 +153,12 @@ export function getDefinedErrorFunctionForKey(
|
|
|
116
153
|
|
|
117
154
|
const defineError: DefineErrorFunction = (message, options = {}) => {
|
|
118
155
|
KeywordError.message = message;
|
|
156
|
+
KeywordError.code = options.code;
|
|
119
157
|
KeywordError.item = options.item;
|
|
120
|
-
|
|
121
|
-
|
|
158
|
+
if (options.cause !== KeywordError) {
|
|
159
|
+
KeywordError.cause =
|
|
160
|
+
options.cause && options.cause !== true ? options.cause : undefined;
|
|
161
|
+
}
|
|
122
162
|
KeywordError.data = options.data;
|
|
123
163
|
return KeywordError;
|
|
124
164
|
};
|
|
@@ -129,6 +169,10 @@ export function getDefinedErrorFunctionForKey(
|
|
|
129
169
|
);
|
|
130
170
|
}
|
|
131
171
|
|
|
172
|
+
export function escapeJsonPointerToken(value: string | number): string {
|
|
173
|
+
return String(value).replace(/~/g, "~0").replace(/\//g, "~1");
|
|
174
|
+
}
|
|
175
|
+
|
|
132
176
|
export function getUTF16Length(str) {
|
|
133
177
|
let length = 0;
|
|
134
178
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -150,8 +194,8 @@ export function isCompiledSchema(subSchema: any): subSchema is CompiledSchema {
|
|
|
150
194
|
);
|
|
151
195
|
}
|
|
152
196
|
|
|
153
|
-
export function getNamedFunction<T>(name: string, fn: T): T {
|
|
154
|
-
return
|
|
197
|
+
export function getNamedFunction<T extends object>(name: string, fn: T): T {
|
|
198
|
+
return definePropertyOrThrow(fn, "name", { value: name });
|
|
155
199
|
}
|
|
156
200
|
|
|
157
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,12 +78,6 @@
|
|
|
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",
|
|
@@ -101,7 +95,11 @@
|
|
|
101
95
|
"nodemon": "^2.0.22",
|
|
102
96
|
"nyc": "^15.1.0",
|
|
103
97
|
"release-it": "^15.9.3",
|
|
104
|
-
"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"
|
|
105
103
|
},
|
|
106
104
|
"nyc": {
|
|
107
105
|
"exclude": [
|