schema-shield 1.0.0 → 1.0.1
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
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
export function deepFreeze(
|
|
2
|
+
obj: any,
|
|
3
|
+
freezeClassInstances: boolean = false,
|
|
4
|
+
seen = new WeakSet()
|
|
5
|
+
): any {
|
|
6
|
+
if (
|
|
7
|
+
obj === null ||
|
|
8
|
+
typeof obj !== "object" ||
|
|
9
|
+
seen.has(obj) ||
|
|
10
|
+
Object.isFrozen(obj)
|
|
11
|
+
) {
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
seen.add(obj);
|
|
16
|
+
|
|
17
|
+
if (Array.isArray(obj)) {
|
|
18
|
+
for (let i = 0, l = obj.length; i < l; i++) {
|
|
19
|
+
deepFreeze(obj[i], freezeClassInstances, seen);
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
const props = Reflect.ownKeys(obj);
|
|
23
|
+
for (let i = 0, l = props.length; i < l; i++) {
|
|
24
|
+
deepFreeze(obj[props[i]], freezeClassInstances, seen);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// If the object is an instance of a class (not a plain object or array) we need to freeze the prototype
|
|
28
|
+
if (freezeClassInstances) {
|
|
29
|
+
const proto = Object.getPrototypeOf(obj);
|
|
30
|
+
if (proto && proto !== Object.prototype) {
|
|
31
|
+
deepFreeze(proto, freezeClassInstances, seen);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
Object.freeze(obj);
|
|
37
|
+
|
|
38
|
+
return obj;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isPlainObject(value: any): boolean {
|
|
42
|
+
if (!value || typeof value !== "object") {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const proto = Object.getPrototypeOf(value);
|
|
47
|
+
return proto === Object.prototype || proto === null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { isPlainObject };
|
|
51
|
+
|
|
52
|
+
function canUseStructuredClone(value: any): boolean {
|
|
53
|
+
if (typeof structuredClone !== "function") {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (typeof Buffer !== "undefined" && value instanceof Buffer) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
Array.isArray(value) ||
|
|
63
|
+
isPlainObject(value) ||
|
|
64
|
+
value instanceof Date ||
|
|
65
|
+
value instanceof RegExp ||
|
|
66
|
+
value instanceof Map ||
|
|
67
|
+
value instanceof Set ||
|
|
68
|
+
value instanceof ArrayBuffer ||
|
|
69
|
+
ArrayBuffer.isView(value)
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function deepCloneUnfreeze<T>(
|
|
74
|
+
obj: T,
|
|
75
|
+
cloneClassInstances = false,
|
|
76
|
+
seen = new WeakMap()
|
|
77
|
+
): T {
|
|
78
|
+
if (typeof obj === "undefined" || obj === null || typeof obj !== "object") {
|
|
79
|
+
return obj;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const source = obj as any;
|
|
83
|
+
|
|
84
|
+
if (seen.has(source)) {
|
|
85
|
+
return seen.get(source);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (canUseStructuredClone(source)) {
|
|
89
|
+
const cloned = structuredClone(source);
|
|
90
|
+
seen.set(source, cloned);
|
|
91
|
+
return cloned;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let clone: any;
|
|
95
|
+
|
|
96
|
+
switch (true) {
|
|
97
|
+
case Array.isArray(source): {
|
|
98
|
+
clone = [];
|
|
99
|
+
seen.set(source, clone);
|
|
100
|
+
for (let i = 0, l = source.length; i < l; i++) {
|
|
101
|
+
clone[i] = deepCloneUnfreeze(source[i], cloneClassInstances, seen);
|
|
102
|
+
}
|
|
103
|
+
return clone;
|
|
104
|
+
}
|
|
105
|
+
case source instanceof Date: {
|
|
106
|
+
clone = new Date(source.getTime());
|
|
107
|
+
seen.set(source, clone);
|
|
108
|
+
return clone;
|
|
109
|
+
}
|
|
110
|
+
case source instanceof RegExp: {
|
|
111
|
+
clone = new RegExp(source.source, source.flags);
|
|
112
|
+
seen.set(source, clone);
|
|
113
|
+
return clone;
|
|
114
|
+
}
|
|
115
|
+
case source instanceof Map: {
|
|
116
|
+
clone = new Map();
|
|
117
|
+
seen.set(source, clone);
|
|
118
|
+
for (const [key, value] of source.entries()) {
|
|
119
|
+
clone.set(
|
|
120
|
+
deepCloneUnfreeze(key, cloneClassInstances, seen),
|
|
121
|
+
deepCloneUnfreeze(value, cloneClassInstances, seen)
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
return clone;
|
|
125
|
+
}
|
|
126
|
+
case source instanceof Set: {
|
|
127
|
+
clone = new Set();
|
|
128
|
+
seen.set(source, clone);
|
|
129
|
+
for (const value of source.values()) {
|
|
130
|
+
clone.add(deepCloneUnfreeze(value, cloneClassInstances, seen));
|
|
131
|
+
}
|
|
132
|
+
return clone;
|
|
133
|
+
}
|
|
134
|
+
case source instanceof ArrayBuffer: {
|
|
135
|
+
clone = source.slice(0);
|
|
136
|
+
seen.set(source, clone);
|
|
137
|
+
return clone;
|
|
138
|
+
}
|
|
139
|
+
// TypedArrays and DataView
|
|
140
|
+
case ArrayBuffer.isView(source): {
|
|
141
|
+
clone = new source.constructor(source.buffer.slice(0));
|
|
142
|
+
seen.set(source, clone);
|
|
143
|
+
return clone;
|
|
144
|
+
}
|
|
145
|
+
// Node.js Buffer
|
|
146
|
+
case typeof Buffer !== "undefined" && source instanceof Buffer: {
|
|
147
|
+
clone = Buffer.from(source);
|
|
148
|
+
seen.set(source, clone);
|
|
149
|
+
return clone;
|
|
150
|
+
}
|
|
151
|
+
case source instanceof Error: {
|
|
152
|
+
clone = new source.constructor(source.message);
|
|
153
|
+
seen.set(source, clone);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
// Non clonable objects
|
|
157
|
+
case source instanceof Promise ||
|
|
158
|
+
source instanceof WeakMap ||
|
|
159
|
+
source instanceof WeakSet: {
|
|
160
|
+
clone = source;
|
|
161
|
+
seen.set(source, clone);
|
|
162
|
+
return clone;
|
|
163
|
+
}
|
|
164
|
+
// Instance of a class
|
|
165
|
+
case source.constructor && source.constructor !== Object: {
|
|
166
|
+
if (!cloneClassInstances) {
|
|
167
|
+
clone = source;
|
|
168
|
+
seen.set(source, clone);
|
|
169
|
+
return clone;
|
|
170
|
+
}
|
|
171
|
+
clone = Object.create(Object.getPrototypeOf(source));
|
|
172
|
+
seen.set(source, clone);
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Plain objects
|
|
177
|
+
default: {
|
|
178
|
+
clone = {};
|
|
179
|
+
seen.set(source, clone);
|
|
180
|
+
|
|
181
|
+
const keys = Reflect.ownKeys(source);
|
|
182
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
183
|
+
const key = keys[i];
|
|
184
|
+
clone[key as string] = deepCloneUnfreeze(
|
|
185
|
+
source[key as string],
|
|
186
|
+
cloneClassInstances,
|
|
187
|
+
seen
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
return clone;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
195
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
196
|
+
const descriptor = descriptors[key as string];
|
|
197
|
+
if ("value" in descriptor) {
|
|
198
|
+
descriptor.value = deepCloneUnfreeze(
|
|
199
|
+
descriptor.value,
|
|
200
|
+
cloneClassInstances,
|
|
201
|
+
seen
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
Object.defineProperty(clone, key, descriptor);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return clone;
|
|
208
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Utility function to check if dependencies have changed recursively
|
|
2
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
3
|
+
export function hasChanged(prev: any, current: any) {
|
|
4
|
+
if (Object.is(prev, current)) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (Array.isArray(prev)) {
|
|
9
|
+
if (Array.isArray(current) === false) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (prev.length !== current.length) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
for (let i = 0; i < current.length; i++) {
|
|
18
|
+
if (hasChanged(prev[i], current[i])) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (typeof prev === "object" && prev !== null) {
|
|
27
|
+
if (typeof current !== "object" || current === null) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
for (const key in current) {
|
|
32
|
+
if (hasChanged(prev[key], current[key])) {
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const key in prev) {
|
|
38
|
+
if (key in current) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (hasChanged(prev[key], undefined)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { CompiledSchema } from "../index";
|
|
2
|
+
|
|
3
|
+
interface ErrorTree {
|
|
4
|
+
message: string;
|
|
5
|
+
keyword: string;
|
|
6
|
+
item?: string | number;
|
|
7
|
+
schemaPath: string;
|
|
8
|
+
instancePath: string;
|
|
9
|
+
data?: any;
|
|
10
|
+
cause?: ErrorTree;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class ValidationError extends Error {
|
|
14
|
+
message: string;
|
|
15
|
+
item?: string | number;
|
|
16
|
+
keyword: string;
|
|
17
|
+
cause?: ValidationError;
|
|
18
|
+
schemaPath: string = "";
|
|
19
|
+
instancePath: string = "";
|
|
20
|
+
data?: any;
|
|
21
|
+
schema?: CompiledSchema;
|
|
22
|
+
|
|
23
|
+
private _getCause(pointer = "#", instancePointer = "#"): ValidationError {
|
|
24
|
+
let schemaPath = `${pointer}/${this.keyword}`;
|
|
25
|
+
let instancePath = `${instancePointer}`;
|
|
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);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getCause(): ValidationError {
|
|
45
|
+
return this._getCause();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private _getTree(): ErrorTree {
|
|
49
|
+
const tree: ErrorTree = {
|
|
50
|
+
message: this.message,
|
|
51
|
+
keyword: this.keyword,
|
|
52
|
+
item: this.item,
|
|
53
|
+
schemaPath: this.schemaPath,
|
|
54
|
+
instancePath: this.instancePath,
|
|
55
|
+
data: this.data
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
if (this.cause) {
|
|
59
|
+
tree.cause = this.cause._getTree();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return tree;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
getTree(): ErrorTree {
|
|
66
|
+
this.getCause();
|
|
67
|
+
return this._getTree();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
getPath() {
|
|
71
|
+
const cause = this.getCause();
|
|
72
|
+
return {
|
|
73
|
+
schemaPath: cause.schemaPath,
|
|
74
|
+
instancePath: cause.instancePath
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface DefineErrorOptions {
|
|
80
|
+
item?: any; // Final item in the schemaPath
|
|
81
|
+
cause?: ValidationError | true; // Cause of the error
|
|
82
|
+
data?: any; // Data that caused the error
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface DefineErrorFunction {
|
|
86
|
+
(
|
|
87
|
+
message: string,
|
|
88
|
+
options?: DefineErrorOptions
|
|
89
|
+
): ValidationError | void | true;
|
|
90
|
+
}
|
|
91
|
+
const FAIL_FAST_DEFINE_ERROR: DefineErrorFunction = () => true;
|
|
92
|
+
|
|
93
|
+
export function getDefinedErrorFunctionForKey(
|
|
94
|
+
key: string,
|
|
95
|
+
schema: CompiledSchema,
|
|
96
|
+
failFast: boolean
|
|
97
|
+
) {
|
|
98
|
+
if (failFast) {
|
|
99
|
+
return FAIL_FAST_DEFINE_ERROR;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const KeywordError = new ValidationError(`Invalid ${key}`);
|
|
103
|
+
KeywordError.keyword = key;
|
|
104
|
+
KeywordError.schema = schema;
|
|
105
|
+
|
|
106
|
+
const defineError: DefineErrorFunction = (message, options = {}) => {
|
|
107
|
+
KeywordError.message = message;
|
|
108
|
+
KeywordError.item = options.item;
|
|
109
|
+
KeywordError.cause =
|
|
110
|
+
options.cause && options.cause !== true ? options.cause : undefined;
|
|
111
|
+
KeywordError.data = options.data;
|
|
112
|
+
return KeywordError;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return getNamedFunction<DefineErrorFunction>(
|
|
116
|
+
`defineError_${key}`,
|
|
117
|
+
defineError
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function getUTF16Length(str) {
|
|
122
|
+
let length = 0;
|
|
123
|
+
for (let i = 0; i < str.length; i++) {
|
|
124
|
+
const codePoint = str.codePointAt(i);
|
|
125
|
+
if (codePoint > 0xffff) {
|
|
126
|
+
i++;
|
|
127
|
+
}
|
|
128
|
+
length++;
|
|
129
|
+
}
|
|
130
|
+
return length;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function isCompiledSchema(subSchema: any): subSchema is CompiledSchema {
|
|
134
|
+
return (
|
|
135
|
+
!!subSchema &&
|
|
136
|
+
typeof subSchema === "object" &&
|
|
137
|
+
!Array.isArray(subSchema) &&
|
|
138
|
+
"$validate" in subSchema
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function getNamedFunction<T>(name: string, fn: T): T {
|
|
143
|
+
return Object.defineProperty(fn, "name", { value: name });
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function resolvePath(root: any, path: string): any {
|
|
147
|
+
if (!path || path === "#") {
|
|
148
|
+
return root;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// JSON Pointer
|
|
152
|
+
if (path.startsWith("#/")) {
|
|
153
|
+
const parts = path.split("/").slice(1);
|
|
154
|
+
let current = root;
|
|
155
|
+
|
|
156
|
+
for (const part of parts) {
|
|
157
|
+
const decodedUriPart = decodeURIComponent(part);
|
|
158
|
+
const key = decodedUriPart.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
159
|
+
|
|
160
|
+
if (current && typeof current === "object" && key in current) {
|
|
161
|
+
current = current[key];
|
|
162
|
+
} else {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return current;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Simple lookup by definition name (non-standard, but useful)
|
|
170
|
+
if (!path.includes("#")) {
|
|
171
|
+
if (root.definitions && root.definitions[path]) {
|
|
172
|
+
return root.definitions[path];
|
|
173
|
+
}
|
|
174
|
+
if (root.defs && root.defs[path]) {
|
|
175
|
+
return root.defs[path];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (root.$id && typeof root.$id === "string") {
|
|
179
|
+
if (root.$id === path || root.$id.endsWith("/" + path)) {
|
|
180
|
+
return root;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function areCloseEnough(a: number, b: number, epsilon = 1e-15): boolean {
|
|
189
|
+
return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
|
|
190
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const REGEX_META_CHARS = /[\\.^$*+?()[\]{}|]/;
|
|
2
|
+
|
|
3
|
+
function hasRegexMeta(value: string) {
|
|
4
|
+
return REGEX_META_CHARS.test(value);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const PATTERN_CACHE = new Map<string, CompiledPatternMatcher>();
|
|
8
|
+
|
|
9
|
+
export type CompiledPatternMatcher = RegExp | ((value: string) => boolean);
|
|
10
|
+
|
|
11
|
+
export function compilePatternMatcher(pattern: string): CompiledPatternMatcher {
|
|
12
|
+
const cached = PATTERN_CACHE.get(pattern);
|
|
13
|
+
if (cached) {
|
|
14
|
+
return cached;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let compiled: CompiledPatternMatcher;
|
|
18
|
+
|
|
19
|
+
if (pattern.length === 0) {
|
|
20
|
+
compiled = (_value: string) => true;
|
|
21
|
+
} else if (!hasRegexMeta(pattern)) {
|
|
22
|
+
compiled = (value: string) => value.includes(pattern);
|
|
23
|
+
} else {
|
|
24
|
+
const patternLength = pattern.length;
|
|
25
|
+
|
|
26
|
+
if (patternLength >= 2 && pattern[0] === "^" && pattern[patternLength - 1] === "$") {
|
|
27
|
+
const inner = pattern.slice(1, -1);
|
|
28
|
+
if (!hasRegexMeta(inner)) {
|
|
29
|
+
if (inner.length === 0) {
|
|
30
|
+
compiled = (value: string) => value.length === 0;
|
|
31
|
+
} else {
|
|
32
|
+
compiled = (value: string) => value === inner;
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
compiled = new RegExp(pattern, "u");
|
|
36
|
+
}
|
|
37
|
+
} else if (pattern[0] === "^") {
|
|
38
|
+
const inner = pattern.slice(1);
|
|
39
|
+
if (!hasRegexMeta(inner)) {
|
|
40
|
+
if (inner.length === 0) {
|
|
41
|
+
compiled = (_value: string) => true;
|
|
42
|
+
} else {
|
|
43
|
+
compiled = (value: string) => value.startsWith(inner);
|
|
44
|
+
}
|
|
45
|
+
} else {
|
|
46
|
+
compiled = new RegExp(pattern, "u");
|
|
47
|
+
}
|
|
48
|
+
} else if (pattern[patternLength - 1] === "$") {
|
|
49
|
+
const inner = pattern.slice(0, -1);
|
|
50
|
+
if (!hasRegexMeta(inner)) {
|
|
51
|
+
if (inner.length === 0) {
|
|
52
|
+
compiled = (_value: string) => true;
|
|
53
|
+
} else {
|
|
54
|
+
compiled = (value: string) => value.endsWith(inner);
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
compiled = new RegExp(pattern, "u");
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
compiled = new RegExp(pattern, "u");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
PATTERN_CACHE.set(pattern, compiled);
|
|
65
|
+
return compiled;
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "schema-shield",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
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>",
|
package/dist/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,UAAU,SAAS;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,UAAU,EAAE,MAAM,CAAM;IACxB,YAAY,EAAE,MAAM,CAAM;IAC1B,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB,OAAO,CAAC,SAAS;IAqBjB,QAAQ,IAAI,eAAe;IAI3B,OAAO,CAAC,QAAQ;IAiBhB,OAAO,IAAI,SAAS;IAKpB,OAAO;;;;CAOR;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAC1C,eAAe,GACf,IAAI,GACJ,IAAI,CAAC;CACV;AAGD,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,OAAO,uBAuBlB;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,WAwCjD;AAED,wBAAgB,QAAQ,CAAC,IAAI,KAAA,WAE5B;AAED,wBAAgB,cAAc,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,EAAE,OAAO,SAAQ,WAEnD;AAED,wBAAgB,cAAc,CAAC,GAAG,KAAA,UAUjC;AAED,wBAAgB,SAAS,CAAC,CAAC,EACzB,GAAG,EAAE,CAAC,EACN,mBAAmB,UAAQ,EAC3B,IAAI,uBAAgB,GACnB,CAAC,CA6HH;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,GAAG,SAAS,IAAI,cAAc,CAE5E;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAE1D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,GAAG,CAwCxD"}
|