schema-shield 1.0.0 → 1.0.2
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 +38 -12
- package/dist/formats.d.ts.map +1 -1
- package/dist/index.d.ts +14 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1445 -447
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +1445 -447
- package/dist/keywords/array-keywords.d.ts.map +1 -1
- package/dist/keywords/object-keywords.d.ts.map +1 -1
- package/dist/keywords/other-keywords.d.ts.map +1 -1
- package/dist/keywords/string-keywords.d.ts.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/deep-freeze.d.ts +5 -0
- package/dist/utils/deep-freeze.d.ts.map +1 -0
- package/dist/utils/has-changed.d.ts +2 -0
- package/dist/utils/has-changed.d.ts.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/{utils.d.ts → utils/main-utils.d.ts} +3 -6
- package/dist/utils/main-utils.d.ts.map +1 -0
- package/dist/utils/pattern-matcher.d.ts +3 -0
- package/dist/utils/pattern-matcher.d.ts.map +1 -0
- package/lib/formats.ts +402 -84
- package/lib/index.ts +494 -46
- package/lib/keywords/array-keywords.ts +215 -21
- package/lib/keywords/number-keywords.ts +1 -1
- package/lib/keywords/object-keywords.ts +218 -113
- package/lib/keywords/other-keywords.ts +229 -76
- package/lib/keywords/string-keywords.ts +97 -7
- package/lib/types.ts +4 -5
- package/lib/utils/deep-freeze.ts +208 -0
- package/lib/utils/has-changed.ts +51 -0
- package/lib/utils/index.ts +4 -0
- package/lib/utils/main-utils.ts +190 -0
- package/lib/utils/pattern-matcher.ts +66 -0
- package/package.json +1 -1
- package/dist/utils.d.ts.map +0 -1
- package/lib/utils.ts +0 -362
|
@@ -1,26 +1,98 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isCompiledSchema } from "../utils/main-utils";
|
|
2
2
|
|
|
3
3
|
import { KeywordFunction } from "../index";
|
|
4
|
+
import { hasChanged } from "../utils/has-changed";
|
|
5
|
+
|
|
6
|
+
type BranchEntry =
|
|
7
|
+
| { kind: "validate"; validate: (data: any) => any }
|
|
8
|
+
| { kind: "alwaysValid" }
|
|
9
|
+
| { kind: "alwaysInvalid" }
|
|
10
|
+
| { kind: "literal"; value: any };
|
|
11
|
+
|
|
12
|
+
function toBranchEntry(item: any): BranchEntry {
|
|
13
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
14
|
+
if ("$validate" in item && typeof item.$validate === "function") {
|
|
15
|
+
return { kind: "validate", validate: item.$validate };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return { kind: "alwaysValid" };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (typeof item === "boolean") {
|
|
22
|
+
return { kind: item ? "alwaysValid" : "alwaysInvalid" };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return { kind: "literal", value: item };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getBranchEntries(schema: any, key: "allOf" | "anyOf" | "oneOf") {
|
|
29
|
+
const cacheKey = `_${key}BranchEntries`;
|
|
30
|
+
let entries = schema[cacheKey] as BranchEntry[] | undefined;
|
|
31
|
+
|
|
32
|
+
if (entries) {
|
|
33
|
+
return entries;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const source = schema[key] || [];
|
|
37
|
+
entries = [];
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < source.length; i++) {
|
|
40
|
+
entries.push(toBranchEntry(source[i]));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Object.defineProperty(schema, cacheKey, {
|
|
44
|
+
value: entries,
|
|
45
|
+
enumerable: false,
|
|
46
|
+
configurable: false,
|
|
47
|
+
writable: false
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return entries;
|
|
51
|
+
}
|
|
4
52
|
|
|
5
53
|
export const OtherKeywords: Record<string, KeywordFunction> = {
|
|
6
54
|
enum(schema, data, defineError) {
|
|
7
|
-
|
|
55
|
+
let enumCache = (schema as any)._enumCache as
|
|
56
|
+
| { primitiveSet: Set<any>; objectValues: any[] }
|
|
57
|
+
| undefined;
|
|
58
|
+
|
|
59
|
+
if (!enumCache) {
|
|
60
|
+
const primitiveSet = new Set<any>();
|
|
61
|
+
const objectValues: any[] = [];
|
|
62
|
+
const list = schema.enum;
|
|
63
|
+
|
|
64
|
+
for (let i = 0; i < list.length; i++) {
|
|
65
|
+
const enumItem = list[i];
|
|
66
|
+
if (enumItem !== null && typeof enumItem === "object") {
|
|
67
|
+
objectValues.push(enumItem);
|
|
68
|
+
} else {
|
|
69
|
+
primitiveSet.add(enumItem);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
8
72
|
|
|
9
|
-
|
|
10
|
-
|
|
73
|
+
enumCache = { primitiveSet, objectValues };
|
|
74
|
+
Object.defineProperty(schema, "_enumCache", {
|
|
75
|
+
value: enumCache,
|
|
76
|
+
enumerable: false,
|
|
77
|
+
configurable: false,
|
|
78
|
+
writable: false
|
|
79
|
+
});
|
|
80
|
+
}
|
|
11
81
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
82
|
+
if (
|
|
83
|
+
!(typeof data === "number" && Number.isNaN(data)) &&
|
|
84
|
+
enumCache.primitiveSet.has(data)
|
|
85
|
+
) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
15
88
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return;
|
|
89
|
+
if (data !== null && typeof data === "object") {
|
|
90
|
+
// Conservative exact-semantics path.
|
|
91
|
+
// Future opt-in optimization: structural hashing buckets for large enums.
|
|
92
|
+
for (let i = 0; i < enumCache.objectValues.length; i++) {
|
|
93
|
+
if (!hasChanged(enumCache.objectValues[i], data)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
24
96
|
}
|
|
25
97
|
}
|
|
26
98
|
|
|
@@ -28,25 +100,54 @@ export const OtherKeywords: Record<string, KeywordFunction> = {
|
|
|
28
100
|
},
|
|
29
101
|
|
|
30
102
|
allOf(schema, data, defineError) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
103
|
+
const branches = getBranchEntries(schema, "allOf");
|
|
104
|
+
|
|
105
|
+
if (branches.length === 1) {
|
|
106
|
+
const onlyBranch = branches[0];
|
|
107
|
+
|
|
108
|
+
if (onlyBranch.kind === "validate") {
|
|
109
|
+
const error = onlyBranch.validate(data);
|
|
110
|
+
if (error) {
|
|
111
|
+
return defineError("Value is not valid", { cause: error, data });
|
|
38
112
|
}
|
|
39
|
-
|
|
113
|
+
return;
|
|
40
114
|
}
|
|
41
115
|
|
|
42
|
-
if (
|
|
43
|
-
|
|
44
|
-
|
|
116
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
121
|
+
return defineError("Value is not valid", { data });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (data !== onlyBranch.value) {
|
|
125
|
+
return defineError("Value is not valid", { data });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
for (let i = 0; i < branches.length; i++) {
|
|
132
|
+
const branch = branches[i];
|
|
133
|
+
|
|
134
|
+
if (branch.kind === "validate") {
|
|
135
|
+
const error = branch.validate(data);
|
|
136
|
+
if (error) {
|
|
137
|
+
return defineError("Value is not valid", { cause: error, data });
|
|
45
138
|
}
|
|
46
139
|
continue;
|
|
47
140
|
}
|
|
48
141
|
|
|
49
|
-
if (
|
|
142
|
+
if (branch.kind === "alwaysValid") {
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (branch.kind === "alwaysInvalid") {
|
|
147
|
+
return defineError("Value is not valid", { data });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (data !== branch.value) {
|
|
50
151
|
return defineError("Value is not valid", { data });
|
|
51
152
|
}
|
|
52
153
|
}
|
|
@@ -55,26 +156,55 @@ export const OtherKeywords: Record<string, KeywordFunction> = {
|
|
|
55
156
|
},
|
|
56
157
|
|
|
57
158
|
anyOf(schema, data, defineError) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
159
|
+
const branches = getBranchEntries(schema, "anyOf");
|
|
160
|
+
|
|
161
|
+
if (branches.length === 1) {
|
|
162
|
+
const onlyBranch = branches[0];
|
|
163
|
+
|
|
164
|
+
if (onlyBranch.kind === "validate") {
|
|
165
|
+
const error = onlyBranch.validate(data);
|
|
166
|
+
if (!error) {
|
|
167
|
+
return;
|
|
66
168
|
}
|
|
169
|
+
return defineError("Value is not valid", { data });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
67
173
|
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
177
|
+
return defineError("Value is not valid", { data });
|
|
178
|
+
}
|
|
74
179
|
|
|
75
|
-
|
|
180
|
+
if (data === onlyBranch.value) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return defineError("Value is not valid", { data });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
for (let i = 0; i < branches.length; i++) {
|
|
188
|
+
const branch = branches[i];
|
|
189
|
+
|
|
190
|
+
if (branch.kind === "validate") {
|
|
191
|
+
const error = branch.validate(data);
|
|
192
|
+
if (!error) {
|
|
76
193
|
return;
|
|
77
194
|
}
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (branch.kind === "alwaysValid") {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (branch.kind === "alwaysInvalid") {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (data === branch.value) {
|
|
207
|
+
return;
|
|
78
208
|
}
|
|
79
209
|
}
|
|
80
210
|
|
|
@@ -82,41 +212,51 @@ export const OtherKeywords: Record<string, KeywordFunction> = {
|
|
|
82
212
|
},
|
|
83
213
|
|
|
84
214
|
oneOf(schema, data, defineError) {
|
|
85
|
-
const
|
|
86
|
-
let validCount = 0;
|
|
215
|
+
const branches = getBranchEntries(schema, "oneOf");
|
|
87
216
|
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
validCount++;
|
|
96
|
-
if (validCount > 1) {
|
|
97
|
-
return defineError("Value is not valid", { data });
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
validCount++;
|
|
103
|
-
if (validCount > 1) {
|
|
104
|
-
return defineError("Value is not valid", { data });
|
|
217
|
+
if (branches.length === 1) {
|
|
218
|
+
const onlyBranch = branches[0];
|
|
219
|
+
|
|
220
|
+
if (onlyBranch.kind === "validate") {
|
|
221
|
+
const error = onlyBranch.validate(data);
|
|
222
|
+
if (!error) {
|
|
223
|
+
return;
|
|
105
224
|
}
|
|
106
|
-
|
|
225
|
+
return defineError("Value is not valid", { data });
|
|
107
226
|
}
|
|
108
227
|
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
validCount++;
|
|
112
|
-
if (validCount > 1) {
|
|
113
|
-
return defineError("Value is not valid", { data });
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
continue;
|
|
228
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
229
|
+
return;
|
|
117
230
|
}
|
|
118
231
|
|
|
119
|
-
if (
|
|
232
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
233
|
+
return defineError("Value is not valid", { data });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (data === onlyBranch.value) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return defineError("Value is not valid", { data });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let validCount = 0;
|
|
244
|
+
|
|
245
|
+
for (let i = 0; i < branches.length; i++) {
|
|
246
|
+
const branch = branches[i];
|
|
247
|
+
let isValid = false;
|
|
248
|
+
|
|
249
|
+
if (branch.kind === "validate") {
|
|
250
|
+
isValid = !branch.validate(data);
|
|
251
|
+
} else if (branch.kind === "alwaysValid") {
|
|
252
|
+
isValid = true;
|
|
253
|
+
} else if (branch.kind === "alwaysInvalid") {
|
|
254
|
+
isValid = false;
|
|
255
|
+
} else {
|
|
256
|
+
isValid = data === branch.value;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (isValid) {
|
|
120
260
|
validCount++;
|
|
121
261
|
if (validCount > 1) {
|
|
122
262
|
return defineError("Value is not valid", { data });
|
|
@@ -137,8 +277,12 @@ export const OtherKeywords: Record<string, KeywordFunction> = {
|
|
|
137
277
|
}
|
|
138
278
|
|
|
139
279
|
if (
|
|
140
|
-
(
|
|
141
|
-
|
|
280
|
+
(data &&
|
|
281
|
+
typeof data === "object" &&
|
|
282
|
+
!Array.isArray(data) &&
|
|
283
|
+
schema.const &&
|
|
284
|
+
typeof schema.const === "object" &&
|
|
285
|
+
!Array.isArray(schema.const) &&
|
|
142
286
|
!hasChanged(data, schema.const)) ||
|
|
143
287
|
(Array.isArray(data) &&
|
|
144
288
|
Array.isArray(schema.const) &&
|
|
@@ -190,11 +334,15 @@ export const OtherKeywords: Record<string, KeywordFunction> = {
|
|
|
190
334
|
return;
|
|
191
335
|
}
|
|
192
336
|
|
|
193
|
-
if (
|
|
337
|
+
if (
|
|
338
|
+
schema.not &&
|
|
339
|
+
typeof schema.not === "object" &&
|
|
340
|
+
!Array.isArray(schema.not)
|
|
341
|
+
) {
|
|
194
342
|
if ("$validate" in schema.not) {
|
|
195
|
-
const error = schema.not.$validate(data);
|
|
343
|
+
const error = (schema.not as any).$validate(data);
|
|
196
344
|
if (!error) {
|
|
197
|
-
return defineError("Value is not valid", {
|
|
345
|
+
return defineError("Value is not valid", { data });
|
|
198
346
|
}
|
|
199
347
|
return;
|
|
200
348
|
}
|
|
@@ -206,6 +354,10 @@ export const OtherKeywords: Record<string, KeywordFunction> = {
|
|
|
206
354
|
|
|
207
355
|
$ref(schema, data, defineError, instance) {
|
|
208
356
|
if (schema._resolvedRef) {
|
|
357
|
+
if (schema.$validate !== schema._resolvedRef) {
|
|
358
|
+
schema.$validate = schema._resolvedRef;
|
|
359
|
+
}
|
|
360
|
+
|
|
209
361
|
return schema._resolvedRef(data);
|
|
210
362
|
}
|
|
211
363
|
|
|
@@ -225,6 +377,7 @@ export const OtherKeywords: Record<string, KeywordFunction> = {
|
|
|
225
377
|
}
|
|
226
378
|
|
|
227
379
|
schema._resolvedRef = targetSchema.$validate;
|
|
380
|
+
schema.$validate = schema._resolvedRef;
|
|
228
381
|
return schema._resolvedRef(data);
|
|
229
382
|
}
|
|
230
383
|
};
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { FormatFunction, KeywordFunction } from "../index";
|
|
2
|
+
import { compilePatternMatcher } from "../utils/pattern-matcher";
|
|
3
|
+
|
|
4
|
+
const PATTERN_MATCH_CACHE_LIMIT = 512;
|
|
5
|
+
const FORMAT_RESULT_CACHE_LIMIT = 512;
|
|
2
6
|
|
|
3
7
|
export const StringKeywords: Record<string, KeywordFunction> = {
|
|
4
8
|
minLength(schema, data, defineError) {
|
|
@@ -22,12 +26,24 @@ export const StringKeywords: Record<string, KeywordFunction> = {
|
|
|
22
26
|
return;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
let
|
|
26
|
-
|
|
29
|
+
let patternMatch = (schema as any)._patternMatch as
|
|
30
|
+
| ((value: string) => boolean)
|
|
31
|
+
| undefined;
|
|
32
|
+
|
|
33
|
+
let patternMatchCache = (schema as any)._patternMatchCache as
|
|
34
|
+
| Map<string, boolean>
|
|
35
|
+
| undefined;
|
|
36
|
+
|
|
37
|
+
if (!patternMatch) {
|
|
27
38
|
try {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
const compiled = compilePatternMatcher(schema.pattern);
|
|
40
|
+
patternMatch =
|
|
41
|
+
compiled instanceof RegExp
|
|
42
|
+
? (value: string) => compiled.test(value)
|
|
43
|
+
: compiled;
|
|
44
|
+
|
|
45
|
+
Object.defineProperty(schema, "_patternMatch", {
|
|
46
|
+
value: patternMatch,
|
|
31
47
|
enumerable: false,
|
|
32
48
|
configurable: false,
|
|
33
49
|
writable: false
|
|
@@ -40,7 +56,28 @@ export const StringKeywords: Record<string, KeywordFunction> = {
|
|
|
40
56
|
}
|
|
41
57
|
}
|
|
42
58
|
|
|
43
|
-
if (
|
|
59
|
+
if (!patternMatchCache) {
|
|
60
|
+
patternMatchCache = new Map<string, boolean>();
|
|
61
|
+
Object.defineProperty(schema, "_patternMatchCache", {
|
|
62
|
+
value: patternMatchCache,
|
|
63
|
+
enumerable: false,
|
|
64
|
+
configurable: false,
|
|
65
|
+
writable: false
|
|
66
|
+
});
|
|
67
|
+
} else if (patternMatchCache.has(data)) {
|
|
68
|
+
if (patternMatchCache.get(data)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return defineError("Value does not match the pattern", { data });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const isMatch = patternMatch(data);
|
|
76
|
+
if (patternMatchCache.size < PATTERN_MATCH_CACHE_LIMIT) {
|
|
77
|
+
patternMatchCache.set(data, isMatch);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (isMatch) {
|
|
44
81
|
return;
|
|
45
82
|
}
|
|
46
83
|
|
|
@@ -58,6 +95,12 @@ export const StringKeywords: Record<string, KeywordFunction> = {
|
|
|
58
95
|
| FormatFunction
|
|
59
96
|
| false
|
|
60
97
|
| undefined;
|
|
98
|
+
let formatResultCacheEnabled = (schema as any)._formatResultCacheEnabled as
|
|
99
|
+
| boolean
|
|
100
|
+
| undefined;
|
|
101
|
+
let formatResultCache = (schema as any)._formatResultCache as
|
|
102
|
+
| Map<string, boolean>
|
|
103
|
+
| undefined;
|
|
61
104
|
|
|
62
105
|
if (formatValidate === undefined) {
|
|
63
106
|
formatValidate = instance.getFormat(schema.format);
|
|
@@ -69,7 +112,54 @@ export const StringKeywords: Record<string, KeywordFunction> = {
|
|
|
69
112
|
});
|
|
70
113
|
}
|
|
71
114
|
|
|
72
|
-
if (!formatValidate
|
|
115
|
+
if (!formatValidate) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (formatResultCacheEnabled === undefined) {
|
|
120
|
+
formatResultCacheEnabled = instance.isDefaultFormatValidator(
|
|
121
|
+
schema.format,
|
|
122
|
+
formatValidate
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
Object.defineProperty(schema, "_formatResultCacheEnabled", {
|
|
126
|
+
value: formatResultCacheEnabled,
|
|
127
|
+
enumerable: false,
|
|
128
|
+
configurable: false,
|
|
129
|
+
writable: false
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!formatResultCacheEnabled) {
|
|
134
|
+
if (formatValidate(data)) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return defineError("Value does not match the format", { data });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!formatResultCache) {
|
|
142
|
+
formatResultCache = new Map<string, boolean>();
|
|
143
|
+
Object.defineProperty(schema, "_formatResultCache", {
|
|
144
|
+
value: formatResultCache,
|
|
145
|
+
enumerable: false,
|
|
146
|
+
configurable: false,
|
|
147
|
+
writable: false
|
|
148
|
+
});
|
|
149
|
+
} else if (formatResultCache.has(data)) {
|
|
150
|
+
if (formatResultCache.get(data)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return defineError("Value does not match the format", { data });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const isValid = formatValidate(data);
|
|
158
|
+
if (formatResultCache.size < FORMAT_RESULT_CACHE_LIMIT) {
|
|
159
|
+
formatResultCache.set(data, isValid);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (isValid) {
|
|
73
163
|
return;
|
|
74
164
|
}
|
|
75
165
|
|
package/lib/types.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { TypeFunction } from "./index";
|
|
2
|
-
import { isObject } from "./utils";
|
|
3
2
|
|
|
4
3
|
export const Types: Record<string, TypeFunction | false> = {
|
|
5
4
|
object(data) {
|
|
6
|
-
return
|
|
5
|
+
return data !== null && typeof data === "object" && !Array.isArray(data);
|
|
7
6
|
},
|
|
8
7
|
array(data) {
|
|
9
8
|
return Array.isArray(data);
|
|
@@ -27,11 +26,11 @@ export const Types: Record<string, TypeFunction | false> = {
|
|
|
27
26
|
// Not implemented yet
|
|
28
27
|
timestamp: false,
|
|
29
28
|
int8: false,
|
|
30
|
-
|
|
29
|
+
uint8: false,
|
|
31
30
|
int16: false,
|
|
32
|
-
|
|
31
|
+
uint16: false,
|
|
33
32
|
int32: false,
|
|
34
|
-
|
|
33
|
+
uint32: false,
|
|
35
34
|
float32: false,
|
|
36
35
|
float64: false
|
|
37
36
|
};
|