ascertain 0.14.39 → 0.15.0-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/LICENSE +21 -0
- package/README.md +51 -10
- package/build/index.cjs +221 -58
- package/build/index.cjs.map +1 -1
- package/build/index.d.ts +65 -34
- package/build/index.js +210 -56
- package/build/index.js.map +1 -1
- package/package.json +22 -12
- package/src/index.js +0 -201
package/src/index.js
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
class AssertError {
|
|
2
|
-
constructor(value, expected, path, subject = 'value') {
|
|
3
|
-
this.value = value;
|
|
4
|
-
this.expected = expected;
|
|
5
|
-
this.path = path;
|
|
6
|
-
this.subject = subject;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
toString() {
|
|
10
|
-
return `Invalid ${this.subject} ${JSON.stringify(this.value)} specified by path ${this.path} expected ${this.expected}`;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function findFirstError(array, map) {
|
|
15
|
-
for (let i = 0; i < array.length; i++) {
|
|
16
|
-
const error = map(array[i], i);
|
|
17
|
-
if (error) {
|
|
18
|
-
return error;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function findNotError(array, map) {
|
|
25
|
-
const errors = [];
|
|
26
|
-
for (let i = 0; i < array.length; i++) {
|
|
27
|
-
const error = map(array[i], i);
|
|
28
|
-
if (!error) {
|
|
29
|
-
return false;
|
|
30
|
-
} else {
|
|
31
|
-
errors.push(error);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return errors.reduce((result, error) => {
|
|
35
|
-
return new AssertError(result.value, [result.expected, error.expected].join(' or '), result.path, result.string);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function Optional(schema) {
|
|
40
|
-
this.schema = schema;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function And(schema) {
|
|
44
|
-
this.schema = schema;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function Or(schema) {
|
|
48
|
-
this.schema = schema;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export const optional = (schema) => {
|
|
52
|
-
return new Optional(schema);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export const and = (...schema) => {
|
|
56
|
-
return new And(schema);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export const or = (...schema) => {
|
|
60
|
-
return new Or(schema);
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const $keys = Symbol.for('@@keys');
|
|
64
|
-
export const $values = Symbol.for('@@values');
|
|
65
|
-
|
|
66
|
-
export const fromBase64 =
|
|
67
|
-
typeof Buffer === 'undefined' ? (value) => atob(value) : (value) => Buffer.from(value, 'base64').toString('utf-8');
|
|
68
|
-
|
|
69
|
-
const MULTIPLIERS = {
|
|
70
|
-
ms: 1,
|
|
71
|
-
s: 1000,
|
|
72
|
-
m: 60000,
|
|
73
|
-
h: 3600000,
|
|
74
|
-
d: 86400000,
|
|
75
|
-
w: 604800000,
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
export const as = {
|
|
79
|
-
string: (value) => {
|
|
80
|
-
return typeof value === 'string' ? value : undefined;
|
|
81
|
-
},
|
|
82
|
-
number: (value) => {
|
|
83
|
-
const result = parseFloat(value);
|
|
84
|
-
return Number.isFinite(result) ? result : undefined;
|
|
85
|
-
},
|
|
86
|
-
date: (value) => {
|
|
87
|
-
const result = Date.parse(value);
|
|
88
|
-
return Number.isFinite(result) ? new Date(result) : undefined;
|
|
89
|
-
},
|
|
90
|
-
time: (value) => {
|
|
91
|
-
const matches = value?.match(/^(\d+)(ms|s|m|h|d|w)?$/);
|
|
92
|
-
if (matches) {
|
|
93
|
-
const [_, amount, unit = 'ms'] = matches;
|
|
94
|
-
return parseInt(amount, 10) * MULTIPLIERS[unit];
|
|
95
|
-
}
|
|
96
|
-
return undefined;
|
|
97
|
-
},
|
|
98
|
-
boolean: (value) => (/^(0|1|true|false|enabled|disabled)$/i.test(value) ? /^(1|true|enabled)$/i.test(value) : undefined),
|
|
99
|
-
array: (value, delimiter) => value?.split(delimiter) ?? undefined,
|
|
100
|
-
json: (value) => {
|
|
101
|
-
try {
|
|
102
|
-
return JSON.parse(value);
|
|
103
|
-
} catch (e) {
|
|
104
|
-
return undefined;
|
|
105
|
-
}
|
|
106
|
-
},
|
|
107
|
-
base64: (value) => {
|
|
108
|
-
try {
|
|
109
|
-
return fromBase64(value);
|
|
110
|
-
} catch (e) {
|
|
111
|
-
return undefined;
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
function certain(target, schema, path, optional) {
|
|
117
|
-
if (schema === null || typeof schema === 'undefined') {
|
|
118
|
-
return new AssertError(schema, 'any value', path, 'schema value');
|
|
119
|
-
}
|
|
120
|
-
if (schema instanceof Optional) {
|
|
121
|
-
return certain(target, schema.schema, path, true);
|
|
122
|
-
}
|
|
123
|
-
const isValue = target !== null && typeof target !== 'undefined';
|
|
124
|
-
if (!isValue && optional) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
if (schema instanceof Or) {
|
|
128
|
-
if (!schema.schema.length) {
|
|
129
|
-
return new AssertError(target, 'values', path, 'OR schema');
|
|
130
|
-
}
|
|
131
|
-
return findNotError(schema.schema, (schema) => certain(target, schema, path));
|
|
132
|
-
}
|
|
133
|
-
if (schema instanceof And) {
|
|
134
|
-
if (!schema.schema.length) {
|
|
135
|
-
return new AssertError(target, 'values', path, 'AND schema');
|
|
136
|
-
}
|
|
137
|
-
return findFirstError(schema.schema, (schema) => certain(target, schema, path));
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (typeof schema === 'function') {
|
|
141
|
-
if (!isValue) {
|
|
142
|
-
return new AssertError(target, schema.name, path);
|
|
143
|
-
}
|
|
144
|
-
if (typeof target === 'object' && !(target instanceof schema)) {
|
|
145
|
-
return new AssertError(target, schema.name, path);
|
|
146
|
-
}
|
|
147
|
-
if (typeof target !== 'object' && target.constructor !== schema) {
|
|
148
|
-
return new AssertError(target, schema.name, path);
|
|
149
|
-
}
|
|
150
|
-
} else if (Array.isArray(schema)) {
|
|
151
|
-
if (!Array.isArray(target)) {
|
|
152
|
-
return new AssertError(target, schema.constructor.name, path);
|
|
153
|
-
}
|
|
154
|
-
return findFirstError(target, (value, idx) => {
|
|
155
|
-
return findNotError(schema, (itemSchemaType) => certain(value, itemSchemaType, `${path}.${idx}`));
|
|
156
|
-
});
|
|
157
|
-
} else if (typeof schema === 'object') {
|
|
158
|
-
if (schema instanceof RegExp) {
|
|
159
|
-
if (!schema.test('' + target)) {
|
|
160
|
-
return new AssertError(target, `matching /${schema.source}/`, path);
|
|
161
|
-
}
|
|
162
|
-
} else {
|
|
163
|
-
if (typeof target !== 'object') {
|
|
164
|
-
return new AssertError(target, schema.constructor.name, path);
|
|
165
|
-
}
|
|
166
|
-
if (target === null) {
|
|
167
|
-
return new AssertError(target, 'an object', path);
|
|
168
|
-
}
|
|
169
|
-
if ($keys in schema) {
|
|
170
|
-
const targetKeys = Object.keys(target);
|
|
171
|
-
const assertError = findFirstError(targetKeys, (targetKey) =>
|
|
172
|
-
certain(targetKey, schema[$keys], `${path}.${targetKey}`)
|
|
173
|
-
);
|
|
174
|
-
if (assertError) {
|
|
175
|
-
return assertError;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if ($values in schema) {
|
|
179
|
-
const targetKeys = Object.keys(target);
|
|
180
|
-
const assertError = findFirstError(targetKeys, (targetKey) =>
|
|
181
|
-
certain(target[targetKey], schema[$values], `${path}.${targetKey}`)
|
|
182
|
-
);
|
|
183
|
-
if (assertError) {
|
|
184
|
-
return assertError;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return findFirstError(Object.keys(schema), (key) => certain(target[key], schema[key], `${path}.${key}`));
|
|
188
|
-
}
|
|
189
|
-
} else if (target !== schema) {
|
|
190
|
-
return new AssertError(target, schema, path);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export const ascertain = (schema, data, rootName = '[root]') => {
|
|
195
|
-
const result = certain(data, schema, rootName);
|
|
196
|
-
if (result instanceof AssertError) {
|
|
197
|
-
throw new TypeError(result.toString());
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export default ascertain;
|