@based/schema 5.0.4-alpha.1 → 5.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/dist/dbSchema.d.ts +1 -1
- package/dist/dbSchema.js +72 -1
- package/dist/def/addEdges.js +6 -6
- package/dist/def/createEmptyDef.d.ts +1 -0
- package/dist/def/createEmptyDef.js +1 -0
- package/dist/def/defaultMap.js +1 -3
- package/dist/def/index.d.ts +0 -1
- package/dist/def/index.js +0 -1
- package/dist/def/typeDef.js +149 -106
- package/dist/def/typeIndexes.d.ts +1 -3
- package/dist/def/typeIndexes.js +0 -2
- package/dist/def/types.d.ts +10 -3
- package/dist/def/types.js +2 -0
- package/dist/def/validation.d.ts +14 -2
- package/dist/def/validation.js +174 -21
- package/dist/infer.d.ts +1 -1
- package/dist/parse/props.js +23 -69
- package/dist/parse/utils.js +9 -5
- package/dist/types.d.ts +22 -30
- package/dist/types.js +0 -21
- package/package.json +5 -3
- package/dist/def/refSet.d.ts +0 -7
- package/dist/def/refSet.js +0 -25
- package/dist/def/selvaBuffer.d.ts +0 -5
- package/dist/def/selvaBuffer.js +0 -164
package/dist/def/validation.js
CHANGED
|
@@ -1,13 +1,86 @@
|
|
|
1
1
|
import { convertToTimestamp } from '@based/utils';
|
|
2
|
-
import { ALIAS, BINARY, JSON, BOOLEAN, CARDINALITY, TIMESTAMP, INT16, INT32, INT8, UINT8, UINT16, UINT32, NUMBER, ENUM, ID, MICRO_BUFFER, REFERENCE, REFERENCES, STRING, TEXT, ALIASES, VECTOR, COLVEC,
|
|
3
|
-
import { MAX_ID, MIN_ID } from '../types.js';
|
|
2
|
+
import { ALIAS, BINARY, JSON, BOOLEAN, CARDINALITY, TIMESTAMP, INT16, INT32, INT8, UINT8, UINT16, UINT32, NUMBER, ENUM, ID, MICRO_BUFFER, REFERENCE, REFERENCES, STRING, TEXT, ALIASES, VECTOR, COLVEC, NULL, OBJECT, TYPE_INDEX_MAP, } from './types.js';
|
|
3
|
+
import { MAX_ID, MIN_ID, } from '../types.js';
|
|
4
|
+
import v from 'validator';
|
|
5
|
+
import { getPropType } from '../parse/index.js';
|
|
4
6
|
const EPSILON = 1e-9; // Small tolerance for floating point comparisons
|
|
7
|
+
const validators = {
|
|
8
|
+
email: v.isEmail,
|
|
9
|
+
URL: v.isURL,
|
|
10
|
+
MACAddress: v.isMACAddress,
|
|
11
|
+
IP: v.isIP,
|
|
12
|
+
IPRange: v.isIPRange,
|
|
13
|
+
FQDN: v.isFQDN,
|
|
14
|
+
IBAN: v.isIBAN,
|
|
15
|
+
BIC: v.isBIC,
|
|
16
|
+
alpha: v.isAlpha,
|
|
17
|
+
alphaLocales: v.isAlphaLocales,
|
|
18
|
+
alphanumeric: v.isAlphanumeric,
|
|
19
|
+
alphanumericLocales: v.isAlphanumericLocales,
|
|
20
|
+
passportNumber: v.isPassportNumber,
|
|
21
|
+
port: v.isPort,
|
|
22
|
+
lowercase: v.isLowercase,
|
|
23
|
+
uppercase: v.isUppercase,
|
|
24
|
+
ascii: v.isAscii,
|
|
25
|
+
semVer: v.isSemVer,
|
|
26
|
+
surrogatePair: v.isSurrogatePair,
|
|
27
|
+
IMEI: v.isIMEI,
|
|
28
|
+
hexadecimal: v.isHexadecimal,
|
|
29
|
+
octal: v.isOctal,
|
|
30
|
+
hexColor: v.isHexColor,
|
|
31
|
+
rgbColor: v.isRgbColor,
|
|
32
|
+
HSL: v.isHSL,
|
|
33
|
+
ISRC: v.isISRC,
|
|
34
|
+
MD5: v.isMD5,
|
|
35
|
+
JWT: v.isJWT,
|
|
36
|
+
UUID: v.isUUID,
|
|
37
|
+
luhnNumber: v.isLuhnNumber,
|
|
38
|
+
creditCard: v.isCreditCard,
|
|
39
|
+
identityCard: v.isIdentityCard,
|
|
40
|
+
EAN: v.isEAN,
|
|
41
|
+
ISIN: v.isISIN,
|
|
42
|
+
ISBN: v.isISBN,
|
|
43
|
+
ISSN: v.isISSN,
|
|
44
|
+
mobilePhone: v.isMobilePhone,
|
|
45
|
+
mobilePhoneLocales: v.isMobilePhoneLocales,
|
|
46
|
+
postalCode: v.isPostalCode,
|
|
47
|
+
postalCodeLocales: v.isPostalCodeLocales,
|
|
48
|
+
ethereumAddress: v.isEthereumAddress,
|
|
49
|
+
currency: v.isCurrency,
|
|
50
|
+
btcAddress: v.isBtcAddress,
|
|
51
|
+
ISO6391: v.isISO6391,
|
|
52
|
+
ISO8601: v.isISO8601,
|
|
53
|
+
RFC3339: v.isRFC3339,
|
|
54
|
+
ISO31661Alpha2: v.isISO31661Alpha2,
|
|
55
|
+
ISO31661Alpha3: v.isISO31661Alpha3,
|
|
56
|
+
ISO4217: v.isISO4217,
|
|
57
|
+
base32: v.isBase32,
|
|
58
|
+
base58: v.isBase58,
|
|
59
|
+
base64: v.isBase64,
|
|
60
|
+
dataURI: v.isDataURI,
|
|
61
|
+
magnetURI: v.isMagnetURI,
|
|
62
|
+
mimeType: v.isMimeType,
|
|
63
|
+
latLong: v.isLatLong,
|
|
64
|
+
slug: v.isSlug,
|
|
65
|
+
password: v.isStrongPassword,
|
|
66
|
+
taxID: v.isTaxID,
|
|
67
|
+
licensePlate: v.isLicensePlate,
|
|
68
|
+
VAT: v.isVAT,
|
|
69
|
+
code: () => true,
|
|
70
|
+
javascript: () => true,
|
|
71
|
+
typescript: () => true,
|
|
72
|
+
python: () => true,
|
|
73
|
+
rust: () => true,
|
|
74
|
+
css: () => true,
|
|
75
|
+
html: () => true,
|
|
76
|
+
json: () => true,
|
|
77
|
+
markdown: () => true,
|
|
78
|
+
clike: () => true,
|
|
79
|
+
};
|
|
5
80
|
export const VALIDATION_MAP = {
|
|
6
81
|
[NULL]: () => true,
|
|
7
82
|
[OBJECT]: () => true,
|
|
8
83
|
[COLVEC]: () => true,
|
|
9
|
-
[WEAK_REFERENCE]: () => true,
|
|
10
|
-
[WEAK_REFERENCES]: () => true,
|
|
11
84
|
[ALIAS]: (value) => {
|
|
12
85
|
if (typeof value !== 'string') {
|
|
13
86
|
return false;
|
|
@@ -31,7 +104,9 @@ export const VALIDATION_MAP = {
|
|
|
31
104
|
(val instanceof Uint8Array && val.byteLength === 8));
|
|
32
105
|
},
|
|
33
106
|
[TIMESTAMP]: (value, t) => {
|
|
34
|
-
if (typeof value !== 'number' ||
|
|
107
|
+
if (typeof value !== 'number' ||
|
|
108
|
+
(t.step && value % t.step !== 0) ||
|
|
109
|
+
isNaN(value)) {
|
|
35
110
|
return false;
|
|
36
111
|
}
|
|
37
112
|
if (t.min !== undefined) {
|
|
@@ -57,7 +132,9 @@ export const VALIDATION_MAP = {
|
|
|
57
132
|
return true;
|
|
58
133
|
},
|
|
59
134
|
[INT16]: (value, t) => {
|
|
60
|
-
if (typeof value !== 'number' ||
|
|
135
|
+
if (typeof value !== 'number' ||
|
|
136
|
+
(t.step && value % t.step !== 0) ||
|
|
137
|
+
isNaN(value)) {
|
|
61
138
|
return false;
|
|
62
139
|
}
|
|
63
140
|
if (value > 32767 || value < -32768) {
|
|
@@ -72,7 +149,9 @@ export const VALIDATION_MAP = {
|
|
|
72
149
|
return true;
|
|
73
150
|
},
|
|
74
151
|
[INT32]: (value, t) => {
|
|
75
|
-
if (typeof value !== 'number' ||
|
|
152
|
+
if (typeof value !== 'number' ||
|
|
153
|
+
(t.step && value % t.step !== 0) ||
|
|
154
|
+
isNaN(value)) {
|
|
76
155
|
return false;
|
|
77
156
|
}
|
|
78
157
|
if (value > 2147483647 || value < -2147483648) {
|
|
@@ -88,7 +167,9 @@ export const VALIDATION_MAP = {
|
|
|
88
167
|
},
|
|
89
168
|
[INT8]: (value, t) => {
|
|
90
169
|
// use % for steps size
|
|
91
|
-
if (typeof value !== 'number' ||
|
|
170
|
+
if (typeof value !== 'number' ||
|
|
171
|
+
(t.step && value % t.step !== 0) ||
|
|
172
|
+
isNaN(value)) {
|
|
92
173
|
return false;
|
|
93
174
|
}
|
|
94
175
|
if (value > 127 || value < -128) {
|
|
@@ -103,7 +184,9 @@ export const VALIDATION_MAP = {
|
|
|
103
184
|
return true;
|
|
104
185
|
},
|
|
105
186
|
[UINT8]: (value, t) => {
|
|
106
|
-
if (typeof value !== 'number' ||
|
|
187
|
+
if (typeof value !== 'number' ||
|
|
188
|
+
(t.step && value % t.step !== 0) ||
|
|
189
|
+
isNaN(value)) {
|
|
107
190
|
return false;
|
|
108
191
|
}
|
|
109
192
|
if (value > 255 || value < 0) {
|
|
@@ -118,7 +201,9 @@ export const VALIDATION_MAP = {
|
|
|
118
201
|
return true;
|
|
119
202
|
},
|
|
120
203
|
[UINT16]: (value, t) => {
|
|
121
|
-
if (typeof value !== 'number' ||
|
|
204
|
+
if (typeof value !== 'number' ||
|
|
205
|
+
(t.step && value % t.step !== 0) ||
|
|
206
|
+
isNaN(value)) {
|
|
122
207
|
return false;
|
|
123
208
|
}
|
|
124
209
|
if (value > 65535 || value < 0) {
|
|
@@ -133,7 +218,9 @@ export const VALIDATION_MAP = {
|
|
|
133
218
|
return true;
|
|
134
219
|
},
|
|
135
220
|
[UINT32]: (value, t) => {
|
|
136
|
-
if (typeof value !== 'number' ||
|
|
221
|
+
if (typeof value !== 'number' ||
|
|
222
|
+
(t.step && value % t.step !== 0) ||
|
|
223
|
+
isNaN(value)) {
|
|
137
224
|
return false;
|
|
138
225
|
}
|
|
139
226
|
if (value > 4294967295 || value < 0) {
|
|
@@ -165,11 +252,11 @@ export const VALIDATION_MAP = {
|
|
|
165
252
|
}
|
|
166
253
|
return true;
|
|
167
254
|
},
|
|
168
|
-
[ENUM]: (value,
|
|
255
|
+
[ENUM]: (value, t) => {
|
|
169
256
|
if (value === null) {
|
|
170
257
|
return true;
|
|
171
258
|
}
|
|
172
|
-
const arr =
|
|
259
|
+
const arr = t.enum;
|
|
173
260
|
for (let i = 0; i < arr.length; i++) {
|
|
174
261
|
if (value === arr[i]) {
|
|
175
262
|
return true;
|
|
@@ -211,18 +298,22 @@ export const VALIDATION_MAP = {
|
|
|
211
298
|
}
|
|
212
299
|
return true;
|
|
213
300
|
},
|
|
214
|
-
[STRING]: (
|
|
215
|
-
|
|
216
|
-
|
|
301
|
+
[STRING]: (v, t) => {
|
|
302
|
+
if (v instanceof Uint8Array) {
|
|
303
|
+
return !!v[1];
|
|
304
|
+
}
|
|
305
|
+
if (typeof v !== 'string') {
|
|
217
306
|
return false;
|
|
218
307
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (typeof value !== 'string' && !(value instanceof Uint8Array)) {
|
|
308
|
+
if (t.max !== undefined && v.length > t.max) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
if (t.min !== undefined && v.length < t.min) {
|
|
224
312
|
return false;
|
|
225
313
|
}
|
|
314
|
+
if (t.format !== undefined && t.format in validators) {
|
|
315
|
+
return validators[t.format](v);
|
|
316
|
+
}
|
|
226
317
|
return true;
|
|
227
318
|
},
|
|
228
319
|
[ALIASES]: (value) => {
|
|
@@ -244,7 +335,9 @@ export const VALIDATION_MAP = {
|
|
|
244
335
|
}
|
|
245
336
|
return true;
|
|
246
337
|
},
|
|
338
|
+
[TEXT]: null,
|
|
247
339
|
};
|
|
340
|
+
VALIDATION_MAP[TEXT] = VALIDATION_MAP[STRING];
|
|
248
341
|
export const defaultValidation = () => true;
|
|
249
342
|
export const isValidId = (id) => {
|
|
250
343
|
if (typeof id != 'number' || id < MIN_ID || id > MAX_ID) {
|
|
@@ -258,4 +351,64 @@ export const isValidString = (v) => {
|
|
|
258
351
|
ArrayBuffer.isView(v);
|
|
259
352
|
return isVal;
|
|
260
353
|
};
|
|
354
|
+
const validateObj = (value, props, errors, path, required) => {
|
|
355
|
+
if (!props) {
|
|
356
|
+
errors.push({ path, value, error: 'Unexpected property' });
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
if (value === null || typeof value !== 'object') {
|
|
360
|
+
if (required) {
|
|
361
|
+
errors.push({ path, value, error: 'Missing required value' });
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
for (const key in value) {
|
|
367
|
+
if (!(key in props)) {
|
|
368
|
+
errors.push({
|
|
369
|
+
path: [...path, key],
|
|
370
|
+
value: value[key],
|
|
371
|
+
error: 'Unexpected property',
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
for (const key in props) {
|
|
377
|
+
const val = value?.[key];
|
|
378
|
+
const prop = props[key];
|
|
379
|
+
if ('props' in prop) {
|
|
380
|
+
validateObj(val, prop.props, errors, [...path, key], prop.required);
|
|
381
|
+
}
|
|
382
|
+
else if (val !== undefined) {
|
|
383
|
+
const test = getValidator(prop);
|
|
384
|
+
const msg = test(val, prop);
|
|
385
|
+
if (msg !== true) {
|
|
386
|
+
errors.push({
|
|
387
|
+
path: [...path, key],
|
|
388
|
+
value: val,
|
|
389
|
+
error: typeof msg === 'string' ? msg : 'Invalid value',
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
export const getValidator = (prop) => {
|
|
396
|
+
const validator = VALIDATION_MAP[TYPE_INDEX_MAP[getPropType(prop)]] ?? defaultValidation;
|
|
397
|
+
const custom = prop.validation;
|
|
398
|
+
if (custom) {
|
|
399
|
+
return (a, b) => {
|
|
400
|
+
const msg = custom(a, b);
|
|
401
|
+
return msg === true ? validator(a, b) : msg;
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
return validator;
|
|
405
|
+
};
|
|
406
|
+
export function validate(schema, type, payload) {
|
|
407
|
+
const errors = [];
|
|
408
|
+
validateObj(payload, schema?.types?.[type]?.props, errors, [], true);
|
|
409
|
+
return {
|
|
410
|
+
valid: !errors.length,
|
|
411
|
+
errors,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
261
414
|
//# sourceMappingURL=validation.js.map
|
package/dist/infer.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ type InferSchemaTypes<T> = {
|
|
|
66
66
|
type InferSchema<T extends Schema> = T extends {
|
|
67
67
|
types: infer Types;
|
|
68
68
|
} ? Types extends Record<string, any> ? InferSchemaTypes<Types> : never : never;
|
|
69
|
-
export type Infer<T> = InferSchema<T>;
|
|
69
|
+
export type Infer<T extends Schema> = InferSchema<T>;
|
|
70
70
|
export declare const infer: <T extends {
|
|
71
71
|
types: Record<string, any>;
|
|
72
72
|
}>(schema: T) => InferSchema<T>;
|
package/dist/parse/props.js
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { convertToTimestamp } from '@based/utils';
|
|
2
2
|
import { NUMBER, TYPE_INDEX_MAP } from '../def/types.js';
|
|
3
|
-
import {
|
|
4
|
-
import { stringFormats,
|
|
3
|
+
import { getValidator } from '../def/validation.js';
|
|
4
|
+
import { stringFormats, } from '../types.js';
|
|
5
5
|
import { expectBoolean, expectFunction, expectNumber, expectObject, expectString, } from './assert.js';
|
|
6
6
|
import { EXPECTED_ARR, EXPECTED_OBJ, EXPECTED_PRIMITIVE, INVALID_VALUE, MIN_MAX, MISSING_TYPE, TEXT_REQUIRES_LOCALES, TYPE_MISMATCH, UNKNOWN_PROP, NOT_ALLOWED_IN_ITEMS, } from './errors.js';
|
|
7
7
|
import { getPropType } from './utils.js';
|
|
8
|
-
import { DEFAULT_MAP } from '../def/defaultMap.js';
|
|
9
8
|
import { parseMinMaxStep } from '../def/utils.js';
|
|
10
9
|
let stringFormatsSet;
|
|
11
|
-
let numberDisplaysSet;
|
|
12
|
-
let dateDisplaysSet;
|
|
13
10
|
const STUB = {};
|
|
14
11
|
const shared = {
|
|
15
12
|
type() { },
|
|
@@ -49,15 +46,18 @@ const shared = {
|
|
|
49
46
|
description(val) {
|
|
50
47
|
expectString(val);
|
|
51
48
|
},
|
|
52
|
-
readOnly(val) {
|
|
53
|
-
expectBoolean(val);
|
|
54
|
-
},
|
|
55
49
|
examples(val) {
|
|
56
50
|
expectString(val);
|
|
57
51
|
},
|
|
58
52
|
validation(val) {
|
|
59
53
|
expectFunction(val);
|
|
60
54
|
},
|
|
55
|
+
hooks(val, prop, ctx) {
|
|
56
|
+
expectObject(val);
|
|
57
|
+
for (const key in val) {
|
|
58
|
+
expectFunction(val[key]);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
61
|
};
|
|
62
62
|
function propParser(required, optional, allowShorthand) {
|
|
63
63
|
return (prop, ctx) => {
|
|
@@ -118,35 +118,25 @@ export const isDefault = (val, prop, ctx) => {
|
|
|
118
118
|
if (prop.type === 'timestamp') {
|
|
119
119
|
val = convertToTimestamp(val);
|
|
120
120
|
}
|
|
121
|
-
const validation = prop
|
|
122
|
-
const
|
|
123
|
-
typeIndex,
|
|
124
|
-
__isPropDef: true,
|
|
125
|
-
start: 0,
|
|
126
|
-
path: [],
|
|
127
|
-
prop: 0,
|
|
128
|
-
len: 0,
|
|
129
|
-
separate: false,
|
|
130
|
-
enum: prop.enum,
|
|
131
|
-
validation,
|
|
132
|
-
default: DEFAULT_MAP[typeIndex],
|
|
121
|
+
const validation = getValidator(prop);
|
|
122
|
+
const tmpProp = Object.assign({}, prop, {
|
|
133
123
|
step: parseMinMaxStep((prop.step ?? typeIndex === NUMBER) ? 0 : 1),
|
|
134
124
|
max: parseMinMaxStep(prop.max),
|
|
135
125
|
min: parseMinMaxStep(prop.min),
|
|
136
|
-
};
|
|
126
|
+
});
|
|
137
127
|
if (prop.type === 'text') {
|
|
138
128
|
if (typeof val === 'object') {
|
|
139
129
|
for (const key in val) {
|
|
140
130
|
if (!ctx.schema.locales || !(key in ctx.schema.locales)) {
|
|
141
131
|
throw new Error(`Incorrect default for type "text" lang "${key}"`);
|
|
142
132
|
}
|
|
143
|
-
if (!validation(val[key],
|
|
133
|
+
if (!validation(val[key], tmpProp)) {
|
|
144
134
|
throw new Error(`Incorrect default for type "text" lang "${key}"`);
|
|
145
135
|
}
|
|
146
136
|
}
|
|
147
137
|
}
|
|
148
138
|
else {
|
|
149
|
-
if (!validation(val,
|
|
139
|
+
if (!validation(val, tmpProp)) {
|
|
150
140
|
throw new Error(`Incorrect default for type "text"`);
|
|
151
141
|
}
|
|
152
142
|
val = {};
|
|
@@ -156,7 +146,7 @@ export const isDefault = (val, prop, ctx) => {
|
|
|
156
146
|
}
|
|
157
147
|
return val;
|
|
158
148
|
}
|
|
159
|
-
if (!validation(val,
|
|
149
|
+
if (!validation(val, tmpProp)) {
|
|
160
150
|
throw new Error(`Incorrect default for type "${prop.type ?? 'enum'}"`);
|
|
161
151
|
}
|
|
162
152
|
if ('enum' in prop) {
|
|
@@ -184,7 +174,6 @@ p.vector = propParser({
|
|
|
184
174
|
if (;
|
|
291
|
-
ctx.inQuery = false;
|
|
292
|
-
ctx.isItems = false;
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
295
|
-
throw new Error(INVALID_VALUE);
|
|
296
|
-
}
|
|
297
|
-
},
|
|
298
|
-
}, {
|
|
299
|
-
default(val, prop) {
|
|
300
|
-
console.warn('TODO SET DEFAULT VALUE');
|
|
301
|
-
// if (typeof val === 'object') {
|
|
302
|
-
// throwErr(ERRORS.EXPECTED_PRIMITIVE, prop, 'default')
|
|
303
|
-
// }
|
|
304
|
-
},
|
|
305
|
-
});
|
|
306
264
|
p.references = propParser({
|
|
307
265
|
items(items, prop, ctx) {
|
|
308
266
|
expectObject(items);
|
|
@@ -377,11 +335,6 @@ p.text = propParser({
|
|
|
377
335
|
},
|
|
378
336
|
}, 0);
|
|
379
337
|
p.timestamp = propParser(STUB, {
|
|
380
|
-
display(val) {
|
|
381
|
-
expectString(val);
|
|
382
|
-
dateDisplaysSet ??= new Set(dateDisplays);
|
|
383
|
-
dateDisplaysSet.has(val);
|
|
384
|
-
},
|
|
385
338
|
min(val) {
|
|
386
339
|
if (typeof val !== 'string' && typeof val !== 'number') {
|
|
387
340
|
throw Error(INVALID_VALUE);
|
|
@@ -436,7 +389,6 @@ p.reference = propParser({
|
|
|
436
389
|
for (let i = 3; i < lvl; i += 2) {
|
|
437
390
|
prop += prop ? `.${path[i]}` : path[i];
|
|
438
391
|
}
|
|
439
|
-
targetProp.readOnly = true;
|
|
440
392
|
targetProp.items = {
|
|
441
393
|
ref,
|
|
442
394
|
prop,
|
|
@@ -474,13 +426,15 @@ p.reference = propParser({
|
|
|
474
426
|
if (edgeAllowed) {
|
|
475
427
|
let t = ctx.schema.types[prop.ref].props[prop.prop];
|
|
476
428
|
t = t.items || t;
|
|
477
|
-
if (t[key] && t !== prop) {
|
|
478
|
-
|
|
479
|
-
}
|
|
480
|
-
|
|
429
|
+
// if (t[key] && t !== prop) {
|
|
430
|
+
// throw Error('Edge can not be defined on both props')
|
|
431
|
+
// }
|
|
432
|
+
// @ts-ignore
|
|
433
|
+
const edgePropType = getPropType(val, prop, key);
|
|
481
434
|
const inType = ctx.type;
|
|
482
435
|
ctx.type = null;
|
|
483
436
|
p[edgePropType](val, ctx);
|
|
437
|
+
t[key] = prop[key];
|
|
484
438
|
ctx.type = inType;
|
|
485
439
|
return;
|
|
486
440
|
}
|
package/dist/parse/utils.js
CHANGED
|
@@ -15,11 +15,15 @@ export const getPropType = (prop, props, key) => {
|
|
|
15
15
|
if ('ref' in prop) {
|
|
16
16
|
return 'reference';
|
|
17
17
|
}
|
|
18
|
-
if ('items' in prop) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
if ('items' in prop && getPropType(prop.items) === 'reference') {
|
|
19
|
+
Object.keys(prop.items)
|
|
20
|
+
.filter((v) => v[0] === '$')
|
|
21
|
+
.forEach((v) => {
|
|
22
|
+
if (typeof prop.items[v] === 'string') {
|
|
23
|
+
prop.items[v] = { type: prop.items[v] };
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return 'references';
|
|
23
27
|
}
|
|
24
28
|
if ('props' in prop) {
|
|
25
29
|
return 'object';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import type { LangName } from './lang.js';
|
|
2
2
|
import type { Validation } from './def/validation.js';
|
|
3
|
-
|
|
4
|
-
export declare const numberDisplays: readonly ["short", "human", "ratio", "bytes", "euro", "dollar", "pound", "meter"];
|
|
5
|
-
export declare const dateDisplays: readonly ["date", "date-time", "date-time-text", "date-time-human", "date-time-human-short", "time", "time-precise"];
|
|
6
|
-
export declare const stringFormats: readonly ["alpha", "alphaLocales", "alphanumeric", "alphanumericLocales", "ascii", "base32", "base58", "base64", "BIC", "btcAddress", "clike", "code", "creditCard", "css", "currency", "dataURI", "EAN", "email", "ethereumAddress", "FQDN", "hexadecimal", "hexColor", "HSL", "html", "IBAN", "identityCard", "IMEI", "IP", "IPRange", "ISBN", "ISIN", "ISO31661Alpha2", "ISO31661Alpha3", "ISO4217", "ISO6391", "ISO8601", "ISRC", "ISSN", "javascript", "json", "JWT", "latLong", "licensePlate", "lowercase", "luhnNumber", "MACAddress", "magnetURI", "markdown", "MD5", "mimeType", "mobilePhone", "mobilePhoneLocales", "octal", "password", "passportNumber", "port", "postalCode", "postalCodeLocales", "python", "RFC3339", "rgbColor", "rust", "semVer", "slug", "surrogatePair", "taxID", "typescript", "uppercase", "URL", "UUID", "VAT", "multiline"];
|
|
7
|
-
type DateDisplay = (typeof dateDisplays)[number];
|
|
8
|
-
type NumberDisplay = (typeof numberDisplays)[number] | `round-${number}`;
|
|
3
|
+
export declare const stringFormats: readonly ["alpha", "alphaLocales", "alphanumeric", "alphanumericLocales", "ascii", "base32", "base58", "base64", "BIC", "btcAddress", "clike", "code", "creditCard", "css", "currency", "dataURI", "EAN", "email", "ethereumAddress", "FQDN", "hexadecimal", "hexColor", "HSL", "html", "IBAN", "identityCard", "IMEI", "IP", "IPRange", "ISBN", "ISIN", "ISO31661Alpha2", "ISO31661Alpha3", "ISO4217", "ISO6391", "ISO8601", "ISRC", "ISSN", "javascript", "json", "JWT", "latLong", "licensePlate", "lowercase", "luhnNumber", "MACAddress", "magnetURI", "markdown", "MD5", "mimeType", "mobilePhone", "mobilePhoneLocales", "octal", "password", "passportNumber", "port", "postalCode", "postalCodeLocales", "python", "RFC3339", "rgbColor", "rust", "semVer", "slug", "surrogatePair", "taxID", "typescript", "uppercase", "URL", "UUID", "VAT"];
|
|
9
4
|
type StringFormat = (typeof stringFormats)[number];
|
|
10
5
|
type MimeString = 'text/html' | 'text/plain' | 'text/markdown' | 'image/png' | 'image/jpeg' | 'video/mp4' | 'video/quicktime' | 'image/*' | 'video/*' | 'audio/*' | '*/*' | `${string}/${string}`;
|
|
11
6
|
type Mime = MimeString | MimeString[];
|
|
@@ -21,12 +16,9 @@ type Prop<V extends PropValues> = {
|
|
|
21
16
|
required?: boolean;
|
|
22
17
|
title?: string | Record<string, string>;
|
|
23
18
|
description?: string | Record<string, string>;
|
|
24
|
-
path?: string;
|
|
25
|
-
query?: QueryFn;
|
|
26
|
-
role?: Role;
|
|
27
|
-
readOnly?: boolean;
|
|
28
19
|
examples?: string[];
|
|
29
20
|
validation?: Validation;
|
|
21
|
+
hooks?: SchemaPropHooks;
|
|
30
22
|
} & V;
|
|
31
23
|
type EnumItem = string | number | boolean;
|
|
32
24
|
type NeverInItems = {
|
|
@@ -54,11 +46,7 @@ export type SchemaNumber = Prop<{
|
|
|
54
46
|
default?: number;
|
|
55
47
|
min?: number;
|
|
56
48
|
max?: number;
|
|
57
|
-
step?: number
|
|
58
|
-
display?: NumberDisplay;
|
|
59
|
-
history?: {
|
|
60
|
-
interval: 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second';
|
|
61
|
-
};
|
|
49
|
+
step?: number;
|
|
62
50
|
}>;
|
|
63
51
|
export type SchemaString = Prop<{
|
|
64
52
|
type: 'string';
|
|
@@ -120,14 +108,13 @@ export type SchemaColvec = Prop<{
|
|
|
120
108
|
*/
|
|
121
109
|
baseType?: SchemaVectorBaseType;
|
|
122
110
|
}>;
|
|
123
|
-
export type SchemaTimestamp = Prop<{
|
|
111
|
+
export type SchemaTimestamp<isStrict = false> = Prop<{
|
|
124
112
|
type: 'timestamp';
|
|
125
113
|
default?: number | Date | string;
|
|
126
114
|
on?: 'create' | 'update';
|
|
127
|
-
display?: DateDisplay;
|
|
128
115
|
min?: number | string;
|
|
129
116
|
max?: number | string;
|
|
130
|
-
step?: number
|
|
117
|
+
step?: isStrict extends true ? number : number | string;
|
|
131
118
|
}>;
|
|
132
119
|
export type SchemaReferenceOneWay = Prop<{
|
|
133
120
|
type?: 'reference';
|
|
@@ -143,9 +130,9 @@ export type SchemaReference = Prop<{
|
|
|
143
130
|
dependent?: boolean;
|
|
144
131
|
mime?: Mime;
|
|
145
132
|
}> & Record<`$${string}`, SchemaPropOneWay>;
|
|
146
|
-
export type SchemaObject = Prop<{
|
|
133
|
+
export type SchemaObject<isStrict = false> = Prop<{
|
|
147
134
|
type?: 'object';
|
|
148
|
-
props: SchemaProps
|
|
135
|
+
props: SchemaProps<isStrict>;
|
|
149
136
|
}>;
|
|
150
137
|
export type SchemaObjectOneWay = Prop<{
|
|
151
138
|
type?: 'object';
|
|
@@ -166,15 +153,7 @@ export type SchemaAlias = Omit<SchemaString, 'type'> & {
|
|
|
166
153
|
type: 'alias';
|
|
167
154
|
};
|
|
168
155
|
export type SchemaPropShorthand = 'timestamp' | 'binary' | 'boolean' | 'string' | 'alias' | 'text' | 'json' | 'cardinality' | NumberType | EnumItem[];
|
|
169
|
-
type
|
|
170
|
-
export type SchemaSet<ItemsType extends SetItems = SetItems> = Prop<{
|
|
171
|
-
type?: 'set';
|
|
172
|
-
default?: ItemsType extends {
|
|
173
|
-
default: any;
|
|
174
|
-
} ? ItemsType['default'][] : undefined;
|
|
175
|
-
items: ItemsType & NeverInItems;
|
|
176
|
-
}>;
|
|
177
|
-
type NonRefSchemaProps<isStrict = false> = SchemaTimestamp | SchemaBoolean | SchemaNumber | SchemaString | SchemaAlias | SchemaText | SchemaEnum | SchemaJson | SchemaBinary | SchemaCardinality | SchemaVector | SchemaColvec | (isStrict extends true ? SchemaSet<SetItems<true>> : SchemaPropShorthand | SchemaSet);
|
|
156
|
+
type NonRefSchemaProps<isStrict = false> = SchemaTimestamp<isStrict> | SchemaBoolean | SchemaNumber | SchemaString | SchemaAlias | SchemaText | SchemaEnum | SchemaJson | SchemaBinary | SchemaCardinality | SchemaVector | SchemaColvec | (isStrict extends true ? never : SchemaPropShorthand);
|
|
178
157
|
export type SchemaProp<isStrict = false> = SchemaReferencesWithQuery | SchemaReferenceWithQuery | NonRefSchemaProps<isStrict> | SchemaReferences | SchemaReference | SchemaObject | SchemaBinary;
|
|
179
158
|
export type SchemaPropOneWay<isStrict = false> = SchemaReferencesOneWay | SchemaReferenceOneWay | SchemaObjectOneWay | NonRefSchemaProps<isStrict>;
|
|
180
159
|
export type SchemaAnyProp = SchemaPropOneWay | SchemaProp;
|
|
@@ -196,10 +175,24 @@ export type SchemaHooks = {
|
|
|
196
175
|
groupBy?: (query: BasedDbQuery, field: string) => void;
|
|
197
176
|
aggregate?: (query: BasedDbQuery, fields: Set<string>) => void;
|
|
198
177
|
};
|
|
178
|
+
export type SchemaPropHooks = {
|
|
179
|
+
create?: (value: any, payload: Record<string, any>) => any;
|
|
180
|
+
update?: (value: any, payload: Record<string, any>) => any;
|
|
181
|
+
read?: (value: any, result: Record<string, any>) => any;
|
|
182
|
+
aggregate?: (query: BasedDbQuery, fields: Set<string>) => void;
|
|
183
|
+
search?: (query: BasedDbQuery, fields: Set<string>) => void;
|
|
184
|
+
groupBy?: (query: BasedDbQuery, field: string) => void;
|
|
185
|
+
filter?: (query: BasedDbQuery, field: string, operator: Operator, value: any) => void;
|
|
186
|
+
include?: (query: BasedDbQuery, fields: Map<string, {
|
|
187
|
+
field: string;
|
|
188
|
+
opts?: any;
|
|
189
|
+
}>) => void;
|
|
190
|
+
};
|
|
199
191
|
type GenericSchemaType<isStrict = false> = {
|
|
200
192
|
hooks?: SchemaHooks;
|
|
201
193
|
id?: number;
|
|
202
194
|
blockCapacity?: number;
|
|
195
|
+
capped?: number;
|
|
203
196
|
insertOnly?: boolean;
|
|
204
197
|
partial?: boolean;
|
|
205
198
|
props: SchemaProps<isStrict>;
|
|
@@ -246,7 +239,6 @@ export type SchemaPropTypeMap = {
|
|
|
246
239
|
enum: SchemaEnum;
|
|
247
240
|
text: SchemaText;
|
|
248
241
|
json: SchemaJson;
|
|
249
|
-
set: SchemaSet;
|
|
250
242
|
binary: SchemaBinary;
|
|
251
243
|
cardinality: SchemaCardinality;
|
|
252
244
|
vector: SchemaVector;
|
package/dist/types.js
CHANGED
|
@@ -1,23 +1,4 @@
|
|
|
1
1
|
import { getPropType } from './parse/utils.js';
|
|
2
|
-
export const numberDisplays = [
|
|
3
|
-
'short',
|
|
4
|
-
'human',
|
|
5
|
-
'ratio',
|
|
6
|
-
'bytes',
|
|
7
|
-
'euro',
|
|
8
|
-
'dollar',
|
|
9
|
-
'pound',
|
|
10
|
-
'meter',
|
|
11
|
-
];
|
|
12
|
-
export const dateDisplays = [
|
|
13
|
-
'date',
|
|
14
|
-
'date-time',
|
|
15
|
-
'date-time-text',
|
|
16
|
-
'date-time-human',
|
|
17
|
-
'date-time-human-short',
|
|
18
|
-
'time',
|
|
19
|
-
'time-precise',
|
|
20
|
-
];
|
|
21
2
|
export const stringFormats = [
|
|
22
3
|
'alpha',
|
|
23
4
|
'alphaLocales',
|
|
@@ -90,8 +71,6 @@ export const stringFormats = [
|
|
|
90
71
|
'URL',
|
|
91
72
|
'UUID',
|
|
92
73
|
'VAT',
|
|
93
|
-
// TODO: for discussion
|
|
94
|
-
'multiline',
|
|
95
74
|
];
|
|
96
75
|
export const isPropType = (type, prop) => {
|
|
97
76
|
return getPropType(prop) === type;
|