@based/schema 4.1.0 → 5.0.0-alpha.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 +152 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/lang.d.ts +152 -0
- package/dist/lang.js +149 -0
- package/dist/mermaid.d.ts +3 -0
- package/dist/mermaid.js +24 -0
- package/dist/parse/assert.d.ts +1 -1
- package/dist/parse/assert.js +2 -2
- package/dist/parse/errors.d.ts +2 -0
- package/dist/parse/errors.js +2 -0
- package/dist/parse/index.d.ts +5 -4
- package/dist/parse/index.js +43 -41
- package/dist/parse/props.js +160 -68
- package/dist/parse/utils.d.ts +2 -2
- package/dist/parse/utils.js +11 -2
- package/dist/types.d.ts +66 -23
- package/dist/types.js +93 -0
- package/package.json +4 -3
- package/dist/parsePayload/index.d.ts +0 -3
- package/dist/parsePayload/index.js +0 -2
- package/dist/parseSchema/assert.d.ts +0 -6
- package/dist/parseSchema/assert.js +0 -27
- package/dist/parseSchema/errors.d.ts +0 -19
- package/dist/parseSchema/errors.js +0 -19
- package/dist/parseSchema/index.d.ts +0 -20
- package/dist/parseSchema/index.js +0 -132
- package/dist/parseSchema/props.d.ts +0 -7
- package/dist/parseSchema/props.js +0 -256
- package/dist/parseSchema/utils.d.ts +0 -3
- package/dist/parseSchema/utils.js +0 -29
- package/dist/src/compat/index.d.ts +0 -6
- package/dist/src/compat/index.js +0 -217
- package/dist/src/compat/oldSchemaType.d.ts +0 -93
- package/dist/src/compat/oldSchemaType.js +0 -2
- package/dist/src/display/index.d.ts +0 -2
- package/dist/src/display/index.js +0 -16
- package/dist/src/display/number.d.ts +0 -4
- package/dist/src/display/number.js +0 -97
- package/dist/src/display/string.d.ts +0 -5
- package/dist/src/display/string.js +0 -26
- package/dist/src/display/timestamp.d.ts +0 -5
- package/dist/src/display/timestamp.js +0 -134
- package/dist/src/error.d.ts +0 -21
- package/dist/src/error.js +0 -23
- package/dist/src/index.d.ts +0 -6
- package/dist/src/index.js +0 -7
- package/dist/src/languages.d.ts +0 -188
- package/dist/src/languages.js +0 -188
- package/dist/src/set/fields/array.d.ts +0 -2
- package/dist/src/set/fields/array.js +0 -119
- package/dist/src/set/fields/index.d.ts +0 -3
- package/dist/src/set/fields/index.js +0 -85
- package/dist/src/set/fields/number.d.ts +0 -4
- package/dist/src/set/fields/number.js +0 -123
- package/dist/src/set/fields/object.d.ts +0 -3
- package/dist/src/set/fields/object.js +0 -28
- package/dist/src/set/fields/references.d.ts +0 -3
- package/dist/src/set/fields/references.js +0 -136
- package/dist/src/set/fields/set.d.ts +0 -2
- package/dist/src/set/fields/set.js +0 -59
- package/dist/src/set/fields/string.d.ts +0 -3
- package/dist/src/set/fields/string.js +0 -289
- package/dist/src/set/index.d.ts +0 -3
- package/dist/src/set/index.js +0 -205
- package/dist/src/set/isValidId.d.ts +0 -2
- package/dist/src/set/isValidId.js +0 -17
- package/dist/src/types.d.ts +0 -205
- package/dist/src/types.js +0 -113
- package/dist/src/updateSchema.d.ts +0 -2
- package/dist/src/updateSchema.js +0 -12
- package/dist/src/validateSchema/basedSchemaTypeValidator.d.ts +0 -3
- package/dist/src/validateSchema/basedSchemaTypeValidator.js +0 -45
- package/dist/src/validateSchema/fieldValidators.d.ts +0 -27
- package/dist/src/validateSchema/fieldValidators.js +0 -360
- package/dist/src/validateSchema/index.d.ts +0 -17
- package/dist/src/validateSchema/index.js +0 -109
- package/dist/src/validateSchema/utils.d.ts +0 -25
- package/dist/src/validateSchema/utils.js +0 -61
- package/dist/src/walker/args.d.ts +0 -36
- package/dist/src/walker/args.js +0 -158
- package/dist/src/walker/index.d.ts +0 -6
- package/dist/src/walker/index.js +0 -31
- package/dist/src/walker/parse.d.ts +0 -3
- package/dist/src/walker/parse.js +0 -182
- package/dist/src/walker/types.d.ts +0 -45
- package/dist/src/walker/types.js +0 -7
- package/dist/test/array.d.ts +0 -1
- package/dist/test/array.js +0 -342
- package/dist/test/compat.d.ts +0 -1
- package/dist/test/compat.js +0 -97
- package/dist/test/data/newSchemas.d.ts +0 -2
- package/dist/test/data/newSchemas.js +0 -489
- package/dist/test/data/oldSchemas.d.ts +0 -2
- package/dist/test/data/oldSchemas.js +0 -5058
- package/dist/test/display.d.ts +0 -1
- package/dist/test/display.js +0 -103
- package/dist/test/json.d.ts +0 -1
- package/dist/test/json.js +0 -40
- package/dist/test/number.d.ts +0 -1
- package/dist/test/number.js +0 -374
- package/dist/test/reference.d.ts +0 -1
- package/dist/test/reference.js +0 -188
- package/dist/test/rest.d.ts +0 -1
- package/dist/test/rest.js +0 -168
- package/dist/test/set.d.ts +0 -1
- package/dist/test/set.js +0 -95
- package/dist/test/string.d.ts +0 -1
- package/dist/test/string.js +0 -120
- package/dist/test/text.d.ts +0 -1
- package/dist/test/text.js +0 -324
- package/dist/test/utils/index.d.ts +0 -11
- package/dist/test/utils/index.js +0 -17
- package/dist/test/validateSchema/basic.d.ts +0 -1
- package/dist/test/validateSchema/basic.js +0 -94
- package/dist/test/validateSchema/fields.d.ts +0 -1
- package/dist/test/validateSchema/fields.js +0 -436
- package/dist/test/validateSchema/languages.d.ts +0 -1
- package/dist/test/validateSchema/languages.js +0 -124
- package/dist/test/validateSchema/realWorld.d.ts +0 -1
- package/dist/test/validateSchema/realWorld.js +0 -13
- package/dist/test/walker.d.ts +0 -1
- package/dist/test/walker.js +0 -289
package/dist/parse/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { INVALID_VALUE, UNKNOWN_PROP } from './errors.js';
|
|
1
|
+
import { INVALID_KEY, INVALID_VALUE, UNKNOWN_PROP } from './errors.js';
|
|
2
2
|
import { getPropType } from './utils.js';
|
|
3
3
|
import propParsers from './props.js';
|
|
4
4
|
import pc from 'picocolors';
|
|
@@ -8,33 +8,55 @@ export class SchemaParser {
|
|
|
8
8
|
constructor(schema) {
|
|
9
9
|
this.schema = schema;
|
|
10
10
|
}
|
|
11
|
+
isItems;
|
|
11
12
|
inQuery;
|
|
12
13
|
schema;
|
|
13
14
|
type;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
this.parseProps(type.props, type);
|
|
17
|
-
}
|
|
15
|
+
path = [];
|
|
16
|
+
lvl = 0;
|
|
18
17
|
parseTypes() {
|
|
18
|
+
this.path[this.lvl++] = 'types';
|
|
19
19
|
const { types } = this.schema;
|
|
20
20
|
expectObject(types);
|
|
21
21
|
for (const type in types) {
|
|
22
|
-
this.
|
|
22
|
+
this.lvl++;
|
|
23
|
+
if (type[0] === '_') {
|
|
24
|
+
throw new Error(INVALID_KEY);
|
|
25
|
+
}
|
|
26
|
+
this.path[this.lvl] = type;
|
|
27
|
+
expectObject(types[type]);
|
|
28
|
+
if (!('props' in types[type])) {
|
|
29
|
+
types[type] = { props: types[type] };
|
|
30
|
+
}
|
|
31
|
+
this.lvl--;
|
|
32
|
+
}
|
|
33
|
+
for (const type in types) {
|
|
34
|
+
this.path[this.lvl++] = type;
|
|
35
|
+
this.parseProps(types[type].props, types[type]);
|
|
36
|
+
this.lvl--;
|
|
23
37
|
}
|
|
38
|
+
this.lvl--;
|
|
24
39
|
}
|
|
25
40
|
parseProps(props, schemaType = null) {
|
|
41
|
+
this.path[this.lvl++] = 'props';
|
|
26
42
|
expectObject(props);
|
|
27
43
|
this.type = schemaType;
|
|
28
44
|
for (const key in props) {
|
|
45
|
+
if (key[0] === '_') {
|
|
46
|
+
throw new Error(INVALID_KEY);
|
|
47
|
+
}
|
|
29
48
|
const prop = props[key];
|
|
30
|
-
const type = getPropType(prop);
|
|
49
|
+
const type = getPropType(prop, props, key);
|
|
50
|
+
this.path[this.lvl++] = key;
|
|
31
51
|
if (type in propParsers) {
|
|
32
52
|
propParsers[type](prop, this);
|
|
33
53
|
}
|
|
34
54
|
else {
|
|
35
55
|
throw Error(INVALID_VALUE);
|
|
36
56
|
}
|
|
57
|
+
this.lvl--;
|
|
37
58
|
}
|
|
59
|
+
this.lvl--;
|
|
38
60
|
}
|
|
39
61
|
parseLocales() {
|
|
40
62
|
const { locales } = this.schema;
|
|
@@ -60,17 +82,18 @@ export class SchemaParser {
|
|
|
60
82
|
}
|
|
61
83
|
parse() {
|
|
62
84
|
expectObject(this.schema);
|
|
85
|
+
// always do types first because it removes props shorthand
|
|
86
|
+
if ('types' in this.schema) {
|
|
87
|
+
this.parseTypes();
|
|
88
|
+
}
|
|
63
89
|
for (const key in this.schema) {
|
|
64
|
-
if (key === '
|
|
65
|
-
this.parseTypes();
|
|
66
|
-
}
|
|
67
|
-
else if (key === 'props') {
|
|
90
|
+
if (key === 'props') {
|
|
68
91
|
this.parseProps(this.schema.props);
|
|
69
92
|
}
|
|
70
93
|
else if (key === 'locales') {
|
|
71
94
|
this.parseLocales();
|
|
72
95
|
}
|
|
73
|
-
else {
|
|
96
|
+
else if (key !== 'types') {
|
|
74
97
|
throw Error(UNKNOWN_PROP);
|
|
75
98
|
}
|
|
76
99
|
}
|
|
@@ -83,7 +106,7 @@ export const print = (schema, path) => {
|
|
|
83
106
|
const v = obj[key];
|
|
84
107
|
const padding = ' '.repeat(lvl);
|
|
85
108
|
const prefix = key === Object.keys(obj)[0] ? '' : `${padding}...\n`;
|
|
86
|
-
if (lvl === depth) {
|
|
109
|
+
if (lvl === depth && lvl !== 0) {
|
|
87
110
|
const err = key in obj
|
|
88
111
|
? `${key}: ${typeof v === 'object' && v !== null && !Array.isArray(v) ? `{..}` : JSON.stringify(v)}`
|
|
89
112
|
: key;
|
|
@@ -94,39 +117,18 @@ export const print = (schema, path) => {
|
|
|
94
117
|
});
|
|
95
118
|
return lines.join('\n');
|
|
96
119
|
};
|
|
97
|
-
export const debug = (schema) => {
|
|
98
|
-
let curr;
|
|
99
|
-
const proxy = (obj, path = []) => {
|
|
100
|
-
const copy = {};
|
|
101
|
-
return new Proxy(obj, {
|
|
102
|
-
get(_, key) {
|
|
103
|
-
const v = obj[key];
|
|
104
|
-
curr = [...path, key];
|
|
105
|
-
if (typeof v !== 'object' || v === null) {
|
|
106
|
-
return v;
|
|
107
|
-
}
|
|
108
|
-
copy[key] ??= proxy(obj[key], curr);
|
|
109
|
-
return copy[key];
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
};
|
|
113
|
-
const parser = new SchemaParser(proxy(schema));
|
|
114
|
-
try {
|
|
115
|
-
parser.parse();
|
|
116
|
-
}
|
|
117
|
-
catch (e) {
|
|
118
|
-
e.message += '\n\n' + print(schema, curr) + '\n';
|
|
119
|
-
e.cause = curr;
|
|
120
|
-
throw e;
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
120
|
export const parse = (schema) => {
|
|
121
|
+
const parser = new SchemaParser(schema);
|
|
124
122
|
try {
|
|
125
|
-
|
|
123
|
+
parser.parse();
|
|
124
|
+
// @ts-ignore
|
|
126
125
|
return { schema };
|
|
127
126
|
}
|
|
128
127
|
catch (e) {
|
|
129
|
-
|
|
128
|
+
const cause = parser.path.slice(0, Math.min(4, parser.lvl) + 1);
|
|
129
|
+
e.message += '\n\n' + print(schema, cause) + '\n';
|
|
130
|
+
e.cause = cause;
|
|
131
|
+
throw e;
|
|
130
132
|
}
|
|
131
133
|
};
|
|
132
134
|
//# sourceMappingURL=index.js.map
|
package/dist/parse/props.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
import { stringFormats, dateDisplays, numberDisplays, } from '../types.js';
|
|
1
2
|
import { expectBoolean, expectFunction, expectObject, expectString, expectNumber, } from './assert.js';
|
|
2
|
-
import { EXPECTED_ARR, EXPECTED_DATE, EXPECTED_OBJ, EXPECTED_PRIMITIVE, EXPECTED_VALUE_IN_ENUM, INVALID_VALUE, MIN_MAX, OUT_OF_RANGE, TEXT_REQUIRES_LOCALES, TYPE_MISMATCH, UNKNOWN_PROP, } from './errors.js';
|
|
3
|
+
import { EXPECTED_ARR, EXPECTED_DATE, EXPECTED_OBJ, EXPECTED_PRIMITIVE, EXPECTED_VALUE_IN_ENUM, INVALID_VALUE, MIN_MAX, MISSING_TYPE, OUT_OF_RANGE, TEXT_REQUIRES_LOCALES, TYPE_MISMATCH, UNKNOWN_PROP, NOT_ALLOWED_IN_ITEMS, } from './errors.js';
|
|
3
4
|
import { getPropType } from './utils.js';
|
|
5
|
+
let stringFormatsSet;
|
|
6
|
+
let numberDisplaysSet;
|
|
7
|
+
let dateDisplaysSet;
|
|
4
8
|
const STUB = {};
|
|
5
9
|
const shared = {
|
|
6
10
|
type() { },
|
|
7
|
-
|
|
11
|
+
role(val) {
|
|
12
|
+
expectString(val);
|
|
13
|
+
},
|
|
14
|
+
required(val, _prop, ctx) {
|
|
15
|
+
if (ctx.isItems) {
|
|
16
|
+
throw new Error(NOT_ALLOWED_IN_ITEMS);
|
|
17
|
+
}
|
|
8
18
|
expectBoolean(val);
|
|
9
19
|
},
|
|
10
20
|
query(val) {
|
|
@@ -28,6 +38,10 @@ const shared = {
|
|
|
28
38
|
throw Error(TYPE_MISMATCH);
|
|
29
39
|
}
|
|
30
40
|
},
|
|
41
|
+
title(val) { },
|
|
42
|
+
description(val) { },
|
|
43
|
+
readOnly(val) { },
|
|
44
|
+
examples(val) { },
|
|
31
45
|
};
|
|
32
46
|
function propParser(required, optional, allowShorthand) {
|
|
33
47
|
return (prop, ctx) => {
|
|
@@ -46,15 +60,21 @@ function propParser(required, optional, allowShorthand) {
|
|
|
46
60
|
throw Error(EXPECTED_OBJ);
|
|
47
61
|
}
|
|
48
62
|
for (const key in required) {
|
|
49
|
-
|
|
63
|
+
ctx.path[ctx.lvl] = key;
|
|
64
|
+
const changed = required[key](prop[key], prop, ctx);
|
|
65
|
+
if (changed !== undefined) {
|
|
66
|
+
prop[key] = changed;
|
|
67
|
+
}
|
|
50
68
|
}
|
|
51
69
|
for (const key in prop) {
|
|
70
|
+
ctx.path[ctx.lvl] = key;
|
|
52
71
|
const val = prop[key];
|
|
72
|
+
let changed;
|
|
53
73
|
if (key in optional) {
|
|
54
|
-
optional[key](val, prop, ctx);
|
|
74
|
+
changed = optional[key](val, prop, ctx);
|
|
55
75
|
}
|
|
56
76
|
else if (key in shared) {
|
|
57
|
-
shared[key](val, prop, ctx);
|
|
77
|
+
changed = shared[key](val, prop, ctx);
|
|
58
78
|
}
|
|
59
79
|
else if (!(key in required)) {
|
|
60
80
|
if (key[0] === '$' && 'ref' in prop) {
|
|
@@ -64,15 +84,13 @@ function propParser(required, optional, allowShorthand) {
|
|
|
64
84
|
throw Error(UNKNOWN_PROP);
|
|
65
85
|
}
|
|
66
86
|
}
|
|
87
|
+
if (changed !== undefined) {
|
|
88
|
+
prop[key] = changed;
|
|
89
|
+
}
|
|
67
90
|
}
|
|
68
91
|
};
|
|
69
92
|
}
|
|
70
93
|
const p = {};
|
|
71
|
-
p.alias = propParser(STUB, {
|
|
72
|
-
default(val) {
|
|
73
|
-
expectString(val);
|
|
74
|
-
},
|
|
75
|
-
}, 0);
|
|
76
94
|
p.boolean = propParser(STUB, {
|
|
77
95
|
default(val) {
|
|
78
96
|
expectBoolean(val);
|
|
@@ -100,6 +118,11 @@ p.enum = propParser({
|
|
|
100
118
|
},
|
|
101
119
|
}, 1);
|
|
102
120
|
const numberOpts = {
|
|
121
|
+
display(val) {
|
|
122
|
+
expectString(val);
|
|
123
|
+
numberDisplaysSet ??= new Set(numberDisplays);
|
|
124
|
+
numberDisplaysSet.has(val);
|
|
125
|
+
},
|
|
103
126
|
min(val) {
|
|
104
127
|
expectNumber(val);
|
|
105
128
|
},
|
|
@@ -144,63 +167,6 @@ p.object = propParser({
|
|
|
144
167
|
console.warn('TODO object default value');
|
|
145
168
|
},
|
|
146
169
|
});
|
|
147
|
-
p.reference = propParser({
|
|
148
|
-
ref(ref, _prop, { schema }) {
|
|
149
|
-
schema.types[ref].props;
|
|
150
|
-
},
|
|
151
|
-
prop(propKey, prop, { schema, type, inQuery }) {
|
|
152
|
-
const propAllowed = type && !inQuery;
|
|
153
|
-
if (propAllowed) {
|
|
154
|
-
expectString(propKey);
|
|
155
|
-
const propPath = propKey.split('.');
|
|
156
|
-
let targetProp = schema.types[prop.ref];
|
|
157
|
-
for (const key of propPath) {
|
|
158
|
-
targetProp = targetProp.props[key];
|
|
159
|
-
}
|
|
160
|
-
if ('items' in targetProp) {
|
|
161
|
-
targetProp = targetProp.items;
|
|
162
|
-
}
|
|
163
|
-
if ('ref' in targetProp && 'prop' in targetProp) {
|
|
164
|
-
const inversePath = targetProp.prop.split('.');
|
|
165
|
-
let inverseProp = schema.types[targetProp.ref];
|
|
166
|
-
for (const key of inversePath) {
|
|
167
|
-
inverseProp = inverseProp.props[key];
|
|
168
|
-
}
|
|
169
|
-
if ('items' in inverseProp) {
|
|
170
|
-
inverseProp = inverseProp.items;
|
|
171
|
-
}
|
|
172
|
-
if (inverseProp === prop) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
throw Error(INVALID_VALUE);
|
|
177
|
-
}
|
|
178
|
-
if (propKey !== undefined) {
|
|
179
|
-
throw Error('ref prop not supported on root or edge p');
|
|
180
|
-
}
|
|
181
|
-
},
|
|
182
|
-
}, {
|
|
183
|
-
default(val) {
|
|
184
|
-
expectString(val);
|
|
185
|
-
},
|
|
186
|
-
edge(val, prop, ctx, key) {
|
|
187
|
-
const edgeAllowed = ctx.type && !ctx.inQuery;
|
|
188
|
-
if (edgeAllowed) {
|
|
189
|
-
let t = ctx.schema.types[prop.ref].props[prop.prop];
|
|
190
|
-
t = t.items || t;
|
|
191
|
-
if (t[key]) {
|
|
192
|
-
throw Error('Edge can not be defined on both props');
|
|
193
|
-
}
|
|
194
|
-
const edgePropType = getPropType(val);
|
|
195
|
-
const inType = ctx.type;
|
|
196
|
-
ctx.type = null;
|
|
197
|
-
p[edgePropType](val, ctx);
|
|
198
|
-
ctx.type = inType;
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
throw Error('ref edge not supported on root or edge p');
|
|
202
|
-
},
|
|
203
|
-
});
|
|
204
170
|
p.set = propParser({
|
|
205
171
|
items(items, prop, ctx) {
|
|
206
172
|
expectObject(items);
|
|
@@ -210,8 +176,10 @@ p.set = propParser({
|
|
|
210
176
|
itemsType === 'timestamp' ||
|
|
211
177
|
itemsType === 'boolean') {
|
|
212
178
|
ctx.inQuery = 'query' in prop;
|
|
179
|
+
ctx.isItems = true;
|
|
213
180
|
p[itemsType](items, ctx);
|
|
214
181
|
ctx.inQuery = false;
|
|
182
|
+
ctx.isItems = false;
|
|
215
183
|
}
|
|
216
184
|
else {
|
|
217
185
|
throw new Error(INVALID_VALUE);
|
|
@@ -231,8 +199,10 @@ p.references = propParser({
|
|
|
231
199
|
const itemsType = getPropType(items);
|
|
232
200
|
if (itemsType === 'reference') {
|
|
233
201
|
ctx.inQuery = 'query' in prop;
|
|
202
|
+
ctx.isItems = true;
|
|
234
203
|
p[itemsType](items, ctx);
|
|
235
204
|
ctx.inQuery = false;
|
|
205
|
+
ctx.isItems = false;
|
|
236
206
|
}
|
|
237
207
|
else {
|
|
238
208
|
throw new Error(INVALID_VALUE);
|
|
@@ -246,13 +216,34 @@ p.references = propParser({
|
|
|
246
216
|
// }
|
|
247
217
|
},
|
|
248
218
|
});
|
|
249
|
-
|
|
219
|
+
const binaryOpts = {
|
|
250
220
|
default(val) {
|
|
251
221
|
expectString(val);
|
|
252
222
|
},
|
|
223
|
+
format(val) {
|
|
224
|
+
expectString(val);
|
|
225
|
+
stringFormatsSet ??= new Set(stringFormats);
|
|
226
|
+
stringFormatsSet.has(val);
|
|
227
|
+
},
|
|
228
|
+
mime(val) {
|
|
229
|
+
if (Array.isArray(val)) {
|
|
230
|
+
val.forEach(expectString);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
expectString(val);
|
|
234
|
+
}
|
|
235
|
+
},
|
|
253
236
|
maxBytes(val) {
|
|
254
237
|
expectNumber(val);
|
|
255
238
|
},
|
|
239
|
+
compression(val) {
|
|
240
|
+
// return the actualy string!
|
|
241
|
+
return val;
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
p.binary = propParser(STUB, binaryOpts, 0);
|
|
245
|
+
p.string = propParser(STUB, {
|
|
246
|
+
...binaryOpts,
|
|
256
247
|
min(val) {
|
|
257
248
|
expectNumber(val);
|
|
258
249
|
},
|
|
@@ -275,6 +266,11 @@ p.text = propParser({
|
|
|
275
266
|
},
|
|
276
267
|
}, 0);
|
|
277
268
|
p.timestamp = propParser(STUB, {
|
|
269
|
+
display(val) {
|
|
270
|
+
expectString(val);
|
|
271
|
+
dateDisplaysSet ??= new Set(dateDisplays);
|
|
272
|
+
dateDisplaysSet.has(val);
|
|
273
|
+
},
|
|
278
274
|
default(val) {
|
|
279
275
|
if (typeof val !== 'number' && !(val instanceof Date)) {
|
|
280
276
|
throw Error(EXPECTED_DATE);
|
|
@@ -286,5 +282,101 @@ p.timestamp = propParser(STUB, {
|
|
|
286
282
|
}
|
|
287
283
|
},
|
|
288
284
|
}, 0);
|
|
285
|
+
p.reference = propParser({
|
|
286
|
+
ref(ref, _prop, { schema }) {
|
|
287
|
+
if (!schema.types[ref]?.props) {
|
|
288
|
+
throw Error(MISSING_TYPE);
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
prop(propKey, prop, { schema, type, inQuery, path }) {
|
|
292
|
+
const propAllowed = type && !inQuery;
|
|
293
|
+
if (propAllowed) {
|
|
294
|
+
expectString(propKey);
|
|
295
|
+
const propPath = propKey.split('.');
|
|
296
|
+
let targetProp = schema.types[prop.ref];
|
|
297
|
+
expectObject(targetProp, 'expected type');
|
|
298
|
+
let create;
|
|
299
|
+
for (const key of propPath) {
|
|
300
|
+
if (!targetProp.props[key]) {
|
|
301
|
+
create = true;
|
|
302
|
+
targetProp.props[key] = {};
|
|
303
|
+
}
|
|
304
|
+
targetProp = targetProp.props[key];
|
|
305
|
+
}
|
|
306
|
+
if (create) {
|
|
307
|
+
const ref = path[1];
|
|
308
|
+
let prop = '';
|
|
309
|
+
for (let i = 3; i < path.length - 1; i += 2) {
|
|
310
|
+
prop += prop ? `.${path[i]}` : path[i];
|
|
311
|
+
}
|
|
312
|
+
targetProp.readOnly = true;
|
|
313
|
+
targetProp.items = {
|
|
314
|
+
ref,
|
|
315
|
+
prop,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
if ('items' in targetProp) {
|
|
319
|
+
targetProp = targetProp.items;
|
|
320
|
+
}
|
|
321
|
+
if ('ref' in targetProp && 'prop' in targetProp) {
|
|
322
|
+
const inversePath = targetProp.prop.split('.');
|
|
323
|
+
let inverseProp = schema.types[targetProp.ref];
|
|
324
|
+
for (const key of inversePath) {
|
|
325
|
+
inverseProp = inverseProp.props[key];
|
|
326
|
+
}
|
|
327
|
+
if (inverseProp && 'items' in inverseProp) {
|
|
328
|
+
inverseProp = inverseProp.items;
|
|
329
|
+
}
|
|
330
|
+
if (prop === inverseProp) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
throw Error('expected inverse property');
|
|
335
|
+
}
|
|
336
|
+
if (propKey !== undefined) {
|
|
337
|
+
throw Error('ref prop not supported on root or edge p');
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
}, {
|
|
341
|
+
mime: binaryOpts.mime,
|
|
342
|
+
default(val) {
|
|
343
|
+
expectString(val);
|
|
344
|
+
},
|
|
345
|
+
edge(val, prop, ctx, key) {
|
|
346
|
+
const edgeAllowed = ctx.type && !ctx.inQuery;
|
|
347
|
+
if (edgeAllowed) {
|
|
348
|
+
let t = ctx.schema.types[prop.ref].props[prop.prop];
|
|
349
|
+
t = t.items || t;
|
|
350
|
+
if (t[key] && t !== prop) {
|
|
351
|
+
throw Error('Edge can not be defined on both props');
|
|
352
|
+
}
|
|
353
|
+
const edgePropType = getPropType(val);
|
|
354
|
+
const inType = ctx.type;
|
|
355
|
+
ctx.type = null;
|
|
356
|
+
p[edgePropType](val, ctx);
|
|
357
|
+
ctx.type = inType;
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
throw Error('ref edge not supported on root or edge property');
|
|
361
|
+
},
|
|
362
|
+
dependent(val, prop, ctx, key) {
|
|
363
|
+
expectBoolean(val);
|
|
364
|
+
const dependentAllowed = ctx.type && !ctx.inQuery;
|
|
365
|
+
if (!dependentAllowed) {
|
|
366
|
+
throw Error('ref dependency not supported on root or edge property');
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
});
|
|
370
|
+
p.alias = propParser(STUB, {
|
|
371
|
+
default(val) {
|
|
372
|
+
expectString(val);
|
|
373
|
+
},
|
|
374
|
+
format: binaryOpts.format,
|
|
375
|
+
}, 0);
|
|
376
|
+
p.hll = propParser(STUB, {
|
|
377
|
+
default(val) {
|
|
378
|
+
expectNumber(val);
|
|
379
|
+
},
|
|
380
|
+
}, 0);
|
|
289
381
|
export default p;
|
|
290
382
|
//# sourceMappingURL=props.js.map
|
package/dist/parse/utils.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { SchemaAnyProp, SchemaPropTypes } from '../types.js';
|
|
2
|
-
export declare const getPropType: (prop: SchemaAnyProp) => SchemaPropTypes;
|
|
1
|
+
import { SchemaAnyProp, SchemaProps, SchemaPropTypes } from '../types.js';
|
|
2
|
+
export declare const getPropType: (prop: SchemaAnyProp, props?: SchemaProps, key?: string) => SchemaPropTypes;
|
|
3
3
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/parse/utils.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { INVALID_TYPE, MISSING_TYPE } from './errors.js';
|
|
2
|
-
export const getPropType = (prop) => {
|
|
2
|
+
export const getPropType = (prop, props, key) => {
|
|
3
3
|
if (typeof prop === 'string') {
|
|
4
|
+
if (props) {
|
|
5
|
+
props[key] = { type: prop };
|
|
6
|
+
}
|
|
4
7
|
return prop;
|
|
5
8
|
}
|
|
6
9
|
if ('type' in prop) {
|
|
@@ -21,7 +24,13 @@ export const getPropType = (prop) => {
|
|
|
21
24
|
if ('props' in prop) {
|
|
22
25
|
return 'object';
|
|
23
26
|
}
|
|
24
|
-
if ('enum' in prop
|
|
27
|
+
if ('enum' in prop) {
|
|
28
|
+
return 'enum';
|
|
29
|
+
}
|
|
30
|
+
if (Array.isArray(prop)) {
|
|
31
|
+
if (props) {
|
|
32
|
+
props[key] = { enum: prop };
|
|
33
|
+
}
|
|
25
34
|
return 'enum';
|
|
26
35
|
}
|
|
27
36
|
throw Error(MISSING_TYPE);
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
import { LangName } from './lang.js';
|
|
2
|
+
type Role = 'title' | 'source' | 'media' | string;
|
|
3
|
+
export declare const numberDisplays: readonly ["short", "human", "ratio", "bytes", "euro", "dollar", "pound", "meter"];
|
|
4
|
+
export declare const dateDisplays: readonly ["date", "date-time", "date-time-text", "date-time-human", "time", "time-precise"];
|
|
5
|
+
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", "passportNumber", "port", "postalCode", "postalCodeLocales", "python", "RFC3339", "rgbColor", "rust", "semVer", "slug", "strongPassword", "surrogatePair", "taxID", "typescript", "uppercase", "URL", "UUID", "VAT", "multiline"];
|
|
6
|
+
type DateDisplay = (typeof dateDisplays)[number];
|
|
7
|
+
type NumberDisplay = (typeof numberDisplays)[number] | `round-${number}`;
|
|
8
|
+
type StringFormat = (typeof stringFormats)[number];
|
|
9
|
+
type MimeString = 'text/html' | 'text/plain' | 'text/markdown' | 'image/png' | 'image/jpeg' | 'video/mp4' | 'video/quicktime' | 'image/*' | 'video/*' | 'audio/*' | '*/*' | `${string}/${string}`;
|
|
10
|
+
type Mime = MimeString | MimeString[];
|
|
1
11
|
type Letter = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z';
|
|
12
|
+
type AllowedKey = `${Letter}${string}`;
|
|
2
13
|
type QueryFn = Function;
|
|
3
14
|
type PropValues = {
|
|
4
15
|
type?: string;
|
|
@@ -6,19 +17,25 @@ type PropValues = {
|
|
|
6
17
|
};
|
|
7
18
|
type Prop<V extends PropValues> = {
|
|
8
19
|
required?: boolean;
|
|
9
|
-
|
|
10
|
-
description?: Record<string, string>;
|
|
20
|
+
title?: string | Record<string, string>;
|
|
21
|
+
description?: string | Record<string, string>;
|
|
11
22
|
path?: string;
|
|
12
23
|
query?: QueryFn;
|
|
24
|
+
role?: Role;
|
|
25
|
+
readOnly?: boolean;
|
|
26
|
+
examples?: string[];
|
|
13
27
|
} & V;
|
|
14
28
|
type EnumItem = string | number | boolean;
|
|
29
|
+
type NeverInItems = {
|
|
30
|
+
required?: never;
|
|
31
|
+
};
|
|
15
32
|
export type SchemaReferences = Prop<{
|
|
16
33
|
type?: 'references';
|
|
17
|
-
items: SchemaReference;
|
|
34
|
+
items: SchemaReference & NeverInItems;
|
|
18
35
|
}>;
|
|
19
36
|
export type SchemaReferencesOneWay = Prop<{
|
|
20
37
|
type?: 'references';
|
|
21
|
-
items: SchemaReferenceOneWay;
|
|
38
|
+
items: SchemaReferenceOneWay & NeverInItems;
|
|
22
39
|
}>;
|
|
23
40
|
export type SchemaText = Prop<{
|
|
24
41
|
type: 'text';
|
|
@@ -31,6 +48,7 @@ export type SchemaNumber = Prop<{
|
|
|
31
48
|
min?: number;
|
|
32
49
|
max?: number;
|
|
33
50
|
step?: number | 'any';
|
|
51
|
+
display?: NumberDisplay;
|
|
34
52
|
}>;
|
|
35
53
|
export type SchemaString = Prop<{
|
|
36
54
|
type: 'string';
|
|
@@ -38,31 +56,44 @@ export type SchemaString = Prop<{
|
|
|
38
56
|
maxBytes?: number;
|
|
39
57
|
max?: number;
|
|
40
58
|
min?: number;
|
|
59
|
+
mime?: Mime;
|
|
60
|
+
format?: StringFormat;
|
|
61
|
+
compression?: 'none' | 'deflate';
|
|
41
62
|
}>;
|
|
42
63
|
export type SchemaBinary = Prop<{
|
|
43
64
|
type: 'binary';
|
|
44
65
|
default?: ArrayBuffer;
|
|
45
66
|
maxBytes?: number;
|
|
67
|
+
mime?: Mime;
|
|
68
|
+
format?: StringFormat;
|
|
46
69
|
}>;
|
|
47
70
|
export type SchemaBoolean = Prop<{
|
|
48
71
|
type: 'boolean';
|
|
49
72
|
default?: boolean;
|
|
50
73
|
}>;
|
|
74
|
+
export type SchemaHll = Prop<{
|
|
75
|
+
type: 'hll';
|
|
76
|
+
default?: number;
|
|
77
|
+
}>;
|
|
51
78
|
export type SchemaTimestamp = Prop<{
|
|
52
79
|
type: 'timestamp';
|
|
53
80
|
default?: number | Date;
|
|
54
81
|
on?: 'create' | 'update';
|
|
82
|
+
display?: DateDisplay;
|
|
55
83
|
}>;
|
|
56
84
|
export type SchemaReferenceOneWay = Prop<{
|
|
57
85
|
type?: 'reference';
|
|
58
86
|
default?: string;
|
|
59
87
|
ref: string;
|
|
88
|
+
mime?: Mime;
|
|
60
89
|
}>;
|
|
61
90
|
export type SchemaReference = Prop<{
|
|
62
91
|
type?: 'reference';
|
|
63
92
|
default?: string;
|
|
64
93
|
ref: string;
|
|
65
94
|
prop: string;
|
|
95
|
+
dependent?: boolean;
|
|
96
|
+
mime?: Mime;
|
|
66
97
|
}> & Record<`$${string}`, SchemaPropOneWay>;
|
|
67
98
|
export type SchemaObject = Prop<{
|
|
68
99
|
type?: 'object';
|
|
@@ -83,43 +114,54 @@ export type SchemaEnum = Prop<{
|
|
|
83
114
|
default?: EnumItem;
|
|
84
115
|
enum: EnumItem[];
|
|
85
116
|
}>;
|
|
86
|
-
export type SchemaAlias = SchemaString & {
|
|
117
|
+
export type SchemaAlias = Omit<SchemaString, 'type'> & {
|
|
87
118
|
type: 'alias';
|
|
88
119
|
};
|
|
89
|
-
export type SchemaPropShorthand = 'timestamp' | 'boolean' | 'string' | 'alias' | 'text' | NumberType | EnumItem[];
|
|
90
|
-
type SetItems =
|
|
120
|
+
export type SchemaPropShorthand = 'timestamp' | 'binary' | 'boolean' | 'string' | 'alias' | 'text' | 'hll' | NumberType | EnumItem[];
|
|
121
|
+
type SetItems<isStrict = false> = SchemaTimestamp | SchemaBoolean | SchemaNumber | SchemaString | SchemaEnum | (isStrict extends true ? never : 'timestamp' | 'binary' | 'boolean' | 'string' | NumberType | EnumItem[]);
|
|
91
122
|
export type SchemaSet<ItemsType extends SetItems = SetItems> = Prop<{
|
|
92
123
|
type?: 'set';
|
|
93
124
|
default?: ItemsType extends {
|
|
94
125
|
default: any;
|
|
95
126
|
} ? ItemsType['default'][] : undefined;
|
|
96
|
-
items: ItemsType;
|
|
127
|
+
items: ItemsType & NeverInItems;
|
|
97
128
|
}>;
|
|
98
|
-
type NonRefSchemaProps =
|
|
99
|
-
export type SchemaProp = SchemaReferencesWithQuery | SchemaReferenceWithQuery | NonRefSchemaProps | SchemaReferences | SchemaReference | SchemaObject | SchemaBinary;
|
|
100
|
-
export type SchemaPropOneWay = SchemaReferencesOneWay | SchemaReferenceOneWay | SchemaObjectOneWay | NonRefSchemaProps
|
|
129
|
+
type NonRefSchemaProps<isStrict = false> = SchemaTimestamp | SchemaBoolean | SchemaNumber | SchemaString | SchemaAlias | SchemaText | SchemaEnum | SchemaBinary | SchemaHll | (isStrict extends true ? SchemaSet<SetItems<true>> : SchemaPropShorthand | SchemaSet);
|
|
130
|
+
export type SchemaProp<isStrict = false> = SchemaReferencesWithQuery | SchemaReferenceWithQuery | NonRefSchemaProps<isStrict> | SchemaReferences | SchemaReference | SchemaObject | SchemaBinary;
|
|
131
|
+
export type SchemaPropOneWay<isStrict = false> = SchemaReferencesOneWay | SchemaReferenceOneWay | SchemaObjectOneWay | NonRefSchemaProps<isStrict>;
|
|
101
132
|
export type SchemaAnyProp = SchemaPropOneWay | SchemaProp;
|
|
102
133
|
export type SchemaHook = string | Function;
|
|
103
|
-
export type SchemaProps = Record<
|
|
104
|
-
|
|
134
|
+
export type SchemaProps<isStrict = false> = Record<AllowedKey, SchemaProp<isStrict>> & {
|
|
135
|
+
id?: never;
|
|
136
|
+
};
|
|
137
|
+
type GenericSchemaType<isStrict = false> = {
|
|
105
138
|
hooks?: {
|
|
106
139
|
create?: SchemaHook;
|
|
107
140
|
update?: SchemaHook;
|
|
108
141
|
delete?: SchemaHook;
|
|
109
142
|
};
|
|
110
143
|
id?: number;
|
|
111
|
-
props: SchemaProps
|
|
144
|
+
props: SchemaProps<isStrict>;
|
|
145
|
+
};
|
|
146
|
+
export type StrictSchemaType = GenericSchemaType<true>;
|
|
147
|
+
export type SchemaType<isStrict = false> = isStrict extends true ? StrictSchemaType : StrictSchemaType | GenericSchemaType<false> | (SchemaProps & {
|
|
148
|
+
props?: never;
|
|
149
|
+
});
|
|
150
|
+
export type SchemaTypeName = AllowedKey;
|
|
151
|
+
export type SchemaTypes<isStrict = false> = Record<SchemaTypeName, SchemaType<isStrict>>;
|
|
152
|
+
export type SchemaPropsOneWay<isStrict = false> = Record<AllowedKey, SchemaPropOneWay<isStrict>> & {
|
|
153
|
+
id?: never;
|
|
112
154
|
};
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
props?: SchemaPropsOneWay;
|
|
118
|
-
locales?: SchemaLocales;
|
|
155
|
+
type GenericSchema<isStrict = false> = {
|
|
156
|
+
types?: SchemaTypes<isStrict>;
|
|
157
|
+
props?: SchemaPropsOneWay<isStrict>;
|
|
158
|
+
locales?: Partial<SchemaLocales>;
|
|
119
159
|
};
|
|
120
|
-
export type
|
|
160
|
+
export type StrictSchema = GenericSchema<true>;
|
|
161
|
+
export type Schema = GenericSchema<false> | StrictSchema;
|
|
162
|
+
export type SchemaLocales = Record<LangName, {
|
|
121
163
|
required?: boolean;
|
|
122
|
-
fallback?:
|
|
164
|
+
fallback?: LangName[];
|
|
123
165
|
}>;
|
|
124
166
|
export type SchemaPropTypeMap = {
|
|
125
167
|
references: SchemaReferences;
|
|
@@ -133,8 +175,9 @@ export type SchemaPropTypeMap = {
|
|
|
133
175
|
text: SchemaText;
|
|
134
176
|
set: SchemaSet;
|
|
135
177
|
binary: SchemaBinary;
|
|
178
|
+
hll: SchemaHll;
|
|
136
179
|
} & Record<NumberType, SchemaNumber>;
|
|
137
180
|
export type SchemaPropTypes = keyof SchemaPropTypeMap;
|
|
138
|
-
export declare const isPropType: <T extends
|
|
181
|
+
export declare const isPropType: <T extends SchemaPropTypes>(type: T, prop: SchemaProp) => prop is SchemaPropTypeMap[T];
|
|
139
182
|
export {};
|
|
140
183
|
//# sourceMappingURL=types.d.ts.map
|