@based/schema 5.0.4 → 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 +40 -6
- 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 +15 -7
- package/dist/def/typeIndexes.d.ts +1 -3
- package/dist/def/typeIndexes.js +0 -2
- package/dist/def/types.d.ts +5 -2
- 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 +17 -69
- package/dist/parse/utils.js +9 -10
- package/dist/types.d.ts +8 -30
- package/dist/types.js +0 -20
- package/package.json +4 -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 -145
package/dist/dbSchema.d.ts
CHANGED
package/dist/dbSchema.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { hash } from '@based/hash';
|
|
2
|
-
import { getPropType } from
|
|
2
|
+
import { getPropType } from './parse/utils.js';
|
|
3
3
|
import { deepCopy } from '@based/utils';
|
|
4
4
|
function _makeEdgeTypes(newTypes, typeName, props, propPrefix) {
|
|
5
|
-
const putEdgeProps = (
|
|
5
|
+
const putEdgeProps = (from, to, edgeProps) => (newTypes[`_${[from, to].sort().join(':')}`] = { props: edgeProps });
|
|
6
6
|
for (const propName in props) {
|
|
7
7
|
const prop = props[propName];
|
|
8
8
|
const propType = getPropType(prop);
|
|
@@ -12,16 +12,20 @@ function _makeEdgeTypes(newTypes, typeName, props, propPrefix) {
|
|
|
12
12
|
}
|
|
13
13
|
else if (propType === 'reference') {
|
|
14
14
|
const edgeProps = {};
|
|
15
|
-
Object.keys(prop)
|
|
15
|
+
Object.keys(prop)
|
|
16
|
+
.filter((k) => k[0] === '$')
|
|
17
|
+
.forEach((k) => (edgeProps[k] = prop[k]));
|
|
16
18
|
if (Object.keys(edgeProps).length > 0) {
|
|
17
|
-
putEdgeProps(typeName
|
|
19
|
+
putEdgeProps(`${typeName}.${nextPropPrefix}`, `${prop.ref}.${prop.prop}`, edgeProps);
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
else if (propType === 'references') {
|
|
21
23
|
const edgeProps = {};
|
|
22
|
-
Object.keys(prop.items)
|
|
24
|
+
Object.keys(prop.items)
|
|
25
|
+
.filter((k) => k[0] === '$')
|
|
26
|
+
.forEach((k) => (edgeProps[k] = prop.items[k]));
|
|
23
27
|
if (Object.keys(edgeProps).length > 0) {
|
|
24
|
-
putEdgeProps(typeName
|
|
28
|
+
putEdgeProps(`${typeName}.${nextPropPrefix}`, `${prop.items.ref}.${prop.items.prop}`, edgeProps);
|
|
25
29
|
}
|
|
26
30
|
}
|
|
27
31
|
}
|
|
@@ -79,8 +83,38 @@ export const strictSchemaToDbSchema = (schema) => {
|
|
|
79
83
|
delete dbSchema.props;
|
|
80
84
|
}
|
|
81
85
|
const edgeTypes = makeEdgeTypes(dbSchema.types);
|
|
86
|
+
// Create inverse props for reference(s)
|
|
82
87
|
for (const et in edgeTypes) {
|
|
83
88
|
dbSchema.types[et] = edgeTypes[et];
|
|
89
|
+
for (const key in edgeTypes[et].props) {
|
|
90
|
+
const prop = edgeTypes[et].props[key];
|
|
91
|
+
const propType = getPropType(prop);
|
|
92
|
+
let refProp;
|
|
93
|
+
if (propType === 'reference') {
|
|
94
|
+
refProp = prop;
|
|
95
|
+
}
|
|
96
|
+
else if (propType === 'references') {
|
|
97
|
+
refProp = prop.items;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
continue; // not a ref
|
|
101
|
+
}
|
|
102
|
+
const type = dbSchema.types[refProp.ref];
|
|
103
|
+
const inverseKey = `_${et}_${key}`;
|
|
104
|
+
dbSchema.types[refProp.ref] = {
|
|
105
|
+
...type,
|
|
106
|
+
props: {
|
|
107
|
+
...type.props,
|
|
108
|
+
[inverseKey]: {
|
|
109
|
+
items: {
|
|
110
|
+
ref: et,
|
|
111
|
+
prop: key,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
refProp.prop = inverseKey;
|
|
117
|
+
}
|
|
84
118
|
}
|
|
85
119
|
// Assign typeIds
|
|
86
120
|
for (const typeName in dbSchema.types) {
|
package/dist/def/addEdges.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { getPropType } from '../index.js';
|
|
1
|
+
import { getPropType, getValidator } from '../index.js';
|
|
2
2
|
import { DEFAULT_MAP } from './defaultMap.js';
|
|
3
3
|
import { fillEmptyMain } from './fillEmptyMain.js';
|
|
4
4
|
import { TYPE_INDEX_MAP, REFERENCES, REFERENCE, ENUM, NUMBER, } from './types.js';
|
|
5
5
|
import { getPropLen, isSeparate, parseMinMaxStep, sortMainProps, } from './utils.js';
|
|
6
|
-
import { defaultValidation, VALIDATION_MAP } from './validation.js';
|
|
7
6
|
export const addEdges = (prop, refProp) => {
|
|
8
7
|
const mainEdges = [];
|
|
9
8
|
for (const key in refProp) {
|
|
@@ -28,10 +27,11 @@ export const addEdges = (prop, refProp) => {
|
|
|
28
27
|
}
|
|
29
28
|
// add default
|
|
30
29
|
const edge = {
|
|
30
|
+
schema: edgeProp,
|
|
31
31
|
__isPropDef: true,
|
|
32
32
|
__isEdge: true,
|
|
33
33
|
prop: separate ? prop.edgesSeperateCnt : 0,
|
|
34
|
-
validation: edgeProp
|
|
34
|
+
validation: getValidator(edgeProp),
|
|
35
35
|
name: key,
|
|
36
36
|
typeIndex,
|
|
37
37
|
len,
|
|
@@ -44,13 +44,13 @@ export const addEdges = (prop, refProp) => {
|
|
|
44
44
|
mainEdges.push(edge);
|
|
45
45
|
}
|
|
46
46
|
if (edgeProp.max !== undefined) {
|
|
47
|
-
edge.max = parseMinMaxStep(edgeProp.max);
|
|
47
|
+
edgeProp.max = edge.max = parseMinMaxStep(edgeProp.max);
|
|
48
48
|
}
|
|
49
49
|
if (edgeProp.min !== undefined) {
|
|
50
|
-
edge.min = parseMinMaxStep(edgeProp.min);
|
|
50
|
+
edgeProp.min = edge.min = parseMinMaxStep(edgeProp.min);
|
|
51
51
|
}
|
|
52
52
|
if (edgeProp.step !== undefined) {
|
|
53
|
-
edge.step = parseMinMaxStep(edgeProp.step);
|
|
53
|
+
edgeProp.step = edge.step = parseMinMaxStep(edgeProp.step);
|
|
54
54
|
}
|
|
55
55
|
if (edge.typeIndex !== NUMBER && edge.step === undefined) {
|
|
56
56
|
edge.step = 1;
|
|
@@ -2,6 +2,7 @@ import { SchemaLocales, SchemaObject, StrictSchemaType } from '../types.js';
|
|
|
2
2
|
export declare const createEmptyDef: (typeName: string, type: StrictSchemaType | SchemaObject, locales: Partial<SchemaLocales>) => {
|
|
3
3
|
cnt: number;
|
|
4
4
|
blockCapacity: number;
|
|
5
|
+
capped: number;
|
|
5
6
|
insertOnly: boolean;
|
|
6
7
|
partial: boolean;
|
|
7
8
|
checksum: number;
|
package/dist/def/defaultMap.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
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,
|
|
1
|
+
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, } from './types.js';
|
|
2
2
|
export const DEFAULT_MAP = {
|
|
3
3
|
[NULL]: 0,
|
|
4
4
|
[OBJECT]: 0,
|
|
5
|
-
[WEAK_REFERENCE]: 0,
|
|
6
|
-
[WEAK_REFERENCES]: 0,
|
|
7
5
|
[ALIAS]: '',
|
|
8
6
|
[BINARY]: new Uint8Array(),
|
|
9
7
|
[BOOLEAN]: false,
|
package/dist/def/index.d.ts
CHANGED
package/dist/def/index.js
CHANGED
package/dist/def/typeDef.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isPropType, getPropType, } from '../index.js';
|
|
1
|
+
import { isPropType, getPropType, getValidator, } from '../index.js';
|
|
2
2
|
import { setByPath } from '@based/utils';
|
|
3
3
|
import { TYPE_INDEX_MAP, REFERENCES, REFERENCE, NUMBER, BLOCK_CAPACITY_MAX, BLOCK_CAPACITY_DEFAULT, BLOCK_CAPACITY_MIN, VECTOR, COLVEC, CARDINALITY, } from './types.js';
|
|
4
4
|
import { DEFAULT_MAP } from './defaultMap.js';
|
|
@@ -8,7 +8,6 @@ import { getPropLen, isSeparate, parseMinMaxStep, reorderProps, schemaVectorBase
|
|
|
8
8
|
import { addEdges } from './addEdges.js';
|
|
9
9
|
import { createEmptyDef } from './createEmptyDef.js';
|
|
10
10
|
import { fillEmptyMain, isZeroes } from './fillEmptyMain.js';
|
|
11
|
-
import { defaultValidation, VALIDATION_MAP } from './validation.js';
|
|
12
11
|
export const updateTypeDefs = (schema) => {
|
|
13
12
|
const schemaTypesParsed = {};
|
|
14
13
|
const schemaTypesParsedById = {};
|
|
@@ -53,7 +52,7 @@ export const updateTypeDefs = (schema) => {
|
|
|
53
52
|
// Update edgeNodeTypeId
|
|
54
53
|
if (!prop.edgeNodeTypeId) {
|
|
55
54
|
if (prop.edges) {
|
|
56
|
-
const edgeTypeName = `_${schema.type}
|
|
55
|
+
const edgeTypeName = `_${[`${schema.type}.${prop.path.join('.')}`, `${dstType.type}.${dstType.props[prop.inversePropName].path.join('.')}`].sort().join(':')}`;
|
|
57
56
|
const edgeType = schemaTypesParsed[edgeTypeName];
|
|
58
57
|
prop.edgeNodeTypeId = edgeType.id;
|
|
59
58
|
dstType.props[prop.inversePropName].edgeNodeTypeId = edgeType.id;
|
|
@@ -92,6 +91,14 @@ const createSchemaTypeDef = (typeName, type, locales, result = createEmptyDef(ty
|
|
|
92
91
|
typeName === '_root' ? BLOCK_CAPACITY_MAX : BLOCK_CAPACITY_DEFAULT;
|
|
93
92
|
}
|
|
94
93
|
}
|
|
94
|
+
if (result.capped == 0) {
|
|
95
|
+
if ('capped' in type) {
|
|
96
|
+
if (typeof type.capped !== 'number' || type.capped < 0) {
|
|
97
|
+
throw new Error('Invalid capped');
|
|
98
|
+
}
|
|
99
|
+
result.capped = type.capped;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
95
102
|
if (result.insertOnly == false && 'insertOnly' in type) {
|
|
96
103
|
result.insertOnly = !!type.insertOnly;
|
|
97
104
|
}
|
|
@@ -141,12 +148,13 @@ const createSchemaTypeDef = (typeName, type, locales, result = createEmptyDef(ty
|
|
|
141
148
|
const isseparate = isSeparate(schemaProp, len);
|
|
142
149
|
const typeIndex = TYPE_INDEX_MAP[propType];
|
|
143
150
|
const prop = {
|
|
151
|
+
schema: schemaProp,
|
|
144
152
|
typeIndex,
|
|
145
153
|
__isPropDef: true,
|
|
146
154
|
separate: isseparate,
|
|
147
155
|
path: propPath,
|
|
148
156
|
start: 0,
|
|
149
|
-
validation: schemaProp
|
|
157
|
+
validation: getValidator(schemaProp),
|
|
150
158
|
len,
|
|
151
159
|
default: schemaProp.default ?? DEFAULT_MAP[typeIndex],
|
|
152
160
|
prop: isseparate ? ++result.cnt : 0,
|
|
@@ -160,13 +168,13 @@ const createSchemaTypeDef = (typeName, type, locales, result = createEmptyDef(ty
|
|
|
160
168
|
}
|
|
161
169
|
}
|
|
162
170
|
if (schemaProp.max !== undefined) {
|
|
163
|
-
prop.max = parseMinMaxStep(schemaProp.max);
|
|
171
|
+
schemaProp.max = prop.max = parseMinMaxStep(schemaProp.max);
|
|
164
172
|
}
|
|
165
173
|
if (schemaProp.min !== undefined) {
|
|
166
|
-
prop.min = parseMinMaxStep(schemaProp.min);
|
|
174
|
+
schemaProp.min = prop.min = parseMinMaxStep(schemaProp.min);
|
|
167
175
|
}
|
|
168
176
|
if (schemaProp.step !== undefined) {
|
|
169
|
-
prop.step = parseMinMaxStep(schemaProp.step);
|
|
177
|
+
schemaProp.step = prop.step = parseMinMaxStep(schemaProp.step);
|
|
170
178
|
}
|
|
171
179
|
if (prop.typeIndex !== NUMBER && prop.step === undefined) {
|
|
172
180
|
prop.step = 1;
|
|
@@ -14,8 +14,6 @@ export declare const STRING = 11;
|
|
|
14
14
|
export declare const TEXT = 12;
|
|
15
15
|
export declare const REFERENCE = 13;
|
|
16
16
|
export declare const REFERENCES = 14;
|
|
17
|
-
export declare const WEAK_REFERENCE = 15;
|
|
18
|
-
export declare const WEAK_REFERENCES = 16;
|
|
19
17
|
export declare const MICRO_BUFFER = 17;
|
|
20
18
|
export declare const ALIAS = 18;
|
|
21
19
|
export declare const ALIASES = 19;
|
|
@@ -25,7 +23,7 @@ export declare const VECTOR = 27;
|
|
|
25
23
|
export declare const JSON = 28;
|
|
26
24
|
export declare const OBJECT = 29;
|
|
27
25
|
export declare const COLVEC = 30;
|
|
28
|
-
export type TypeIndex = typeof NULL | typeof TIMESTAMP | typeof NUMBER | typeof CARDINALITY | typeof INT8 | typeof UINT8 | typeof INT16 | typeof UINT16 | typeof INT32 | typeof UINT32 | typeof BOOLEAN | typeof ENUM | typeof STRING | typeof TEXT | typeof REFERENCE | typeof REFERENCES | typeof
|
|
26
|
+
export type TypeIndex = typeof NULL | typeof TIMESTAMP | typeof NUMBER | typeof CARDINALITY | typeof INT8 | typeof UINT8 | typeof INT16 | typeof UINT16 | typeof INT32 | typeof UINT32 | typeof BOOLEAN | typeof ENUM | typeof STRING | typeof TEXT | typeof REFERENCE | typeof REFERENCES | typeof MICRO_BUFFER | typeof ALIAS | typeof ALIASES | typeof BINARY | typeof ID | typeof VECTOR | typeof JSON | typeof OBJECT | typeof COLVEC;
|
|
29
27
|
export declare enum VectorBaseType {
|
|
30
28
|
Int8 = 1,
|
|
31
29
|
Uint8 = 2,
|
package/dist/def/typeIndexes.js
CHANGED
|
@@ -15,8 +15,6 @@ export const STRING = 11;
|
|
|
15
15
|
export const TEXT = 12;
|
|
16
16
|
export const REFERENCE = 13;
|
|
17
17
|
export const REFERENCES = 14;
|
|
18
|
-
export const WEAK_REFERENCE = 15;
|
|
19
|
-
export const WEAK_REFERENCES = 16;
|
|
20
18
|
export const MICRO_BUFFER = 17;
|
|
21
19
|
export const ALIAS = 18;
|
|
22
20
|
export const ALIASES = 19;
|
package/dist/def/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { LangCode, SchemaHooks, SchemaLocales, SchemaPropHooks } from '../index.js';
|
|
1
|
+
import type { LangCode, SchemaHooks, SchemaLocales, SchemaProp, SchemaPropHooks } from '../index.js';
|
|
2
2
|
import { Validation } from './validation.js';
|
|
3
3
|
import { TypeIndex, VectorBaseType } from './typeIndexes.js';
|
|
4
4
|
export * from './typeIndexes.js';
|
|
@@ -16,6 +16,7 @@ export declare const enum numberTypes {
|
|
|
16
16
|
export type InternalSchemaProp = keyof typeof TYPE_INDEX_MAP;
|
|
17
17
|
export type PropDef = {
|
|
18
18
|
__isPropDef: true;
|
|
19
|
+
schema: SchemaProp<true>;
|
|
19
20
|
prop: number;
|
|
20
21
|
typeIndex: TypeIndex;
|
|
21
22
|
separate: boolean;
|
|
@@ -61,6 +62,7 @@ export type PropDef = {
|
|
|
61
62
|
export type PropDefEdge = Partial<PropDef> & {
|
|
62
63
|
__isPropDef: true;
|
|
63
64
|
typeIndex: TypeIndex;
|
|
65
|
+
schema: SchemaProp<true>;
|
|
64
66
|
len: number;
|
|
65
67
|
prop: number;
|
|
66
68
|
name: string;
|
|
@@ -91,9 +93,10 @@ export type SchemaTypeDef = {
|
|
|
91
93
|
checksum: number;
|
|
92
94
|
type: string;
|
|
93
95
|
blockCapacity: number;
|
|
94
|
-
|
|
96
|
+
capped: number;
|
|
95
97
|
insertOnly: boolean;
|
|
96
98
|
partial: boolean;
|
|
99
|
+
mainLen: number;
|
|
97
100
|
buf: Uint8Array;
|
|
98
101
|
propNames: Uint8Array;
|
|
99
102
|
props: {
|
package/dist/def/types.js
CHANGED
|
@@ -77,6 +77,7 @@ for (const k in SIZE_MAP) {
|
|
|
77
77
|
}
|
|
78
78
|
export const REVERSE_TYPE_INDEX_MAP = reverseMap;
|
|
79
79
|
export const ID_FIELD_DEF = {
|
|
80
|
+
schema: null,
|
|
80
81
|
typeIndex: NULL,
|
|
81
82
|
separate: true,
|
|
82
83
|
path: ['id'],
|
|
@@ -88,6 +89,7 @@ export const ID_FIELD_DEF = {
|
|
|
88
89
|
__isPropDef: true,
|
|
89
90
|
};
|
|
90
91
|
export const EMPTY_MICRO_BUFFER = {
|
|
92
|
+
schema: null,
|
|
91
93
|
typeIndex: MICRO_BUFFER,
|
|
92
94
|
separate: true,
|
|
93
95
|
path: [''],
|
package/dist/def/validation.d.ts
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
|
-
import { TypeIndex
|
|
2
|
-
|
|
1
|
+
import { TypeIndex } from './types.js';
|
|
2
|
+
import { SchemaProp, StrictSchema } from '../types.js';
|
|
3
|
+
export type Validation = (payload: any, schema: SchemaProp<true>) => boolean | string;
|
|
3
4
|
export declare const VALIDATION_MAP: Record<TypeIndex, Validation>;
|
|
4
5
|
export declare const defaultValidation: () => boolean;
|
|
5
6
|
export declare const isValidId: (id: number) => boolean;
|
|
6
7
|
export declare const isValidString: (v: any) => boolean;
|
|
8
|
+
type ValidationErrors = {
|
|
9
|
+
path: string[];
|
|
10
|
+
value: unknown;
|
|
11
|
+
error: string;
|
|
12
|
+
}[];
|
|
13
|
+
export declare const getValidator: (prop: SchemaProp<true>) => Validation;
|
|
14
|
+
export declare function validate<S extends StrictSchema = StrictSchema>(schema: S, type: keyof S['types'], payload: unknown): {
|
|
15
|
+
valid: boolean;
|
|
16
|
+
errors: ValidationErrors;
|
|
17
|
+
};
|
|
18
|
+
export {};
|
|
7
19
|
//# sourceMappingURL=validation.d.ts.map
|
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,9 +46,6 @@ 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
|
},
|
|
@@ -124,35 +118,25 @@ export const isDefault = (val, prop, ctx) => {
|
|
|
124
118
|
if (prop.type === 'timestamp') {
|
|
125
119
|
val = convertToTimestamp(val);
|
|
126
120
|
}
|
|
127
|
-
const validation = prop
|
|
128
|
-
const
|
|
129
|
-
typeIndex,
|
|
130
|
-
__isPropDef: true,
|
|
131
|
-
start: 0,
|
|
132
|
-
path: [],
|
|
133
|
-
prop: 0,
|
|
134
|
-
len: 0,
|
|
135
|
-
separate: false,
|
|
136
|
-
enum: prop.enum,
|
|
137
|
-
validation,
|
|
138
|
-
default: DEFAULT_MAP[typeIndex],
|
|
121
|
+
const validation = getValidator(prop);
|
|
122
|
+
const tmpProp = Object.assign({}, prop, {
|
|
139
123
|
step: parseMinMaxStep((prop.step ?? typeIndex === NUMBER) ? 0 : 1),
|
|
140
124
|
max: parseMinMaxStep(prop.max),
|
|
141
125
|
min: parseMinMaxStep(prop.min),
|
|
142
|
-
};
|
|
126
|
+
});
|
|
143
127
|
if (prop.type === 'text') {
|
|
144
128
|
if (typeof val === 'object') {
|
|
145
129
|
for (const key in val) {
|
|
146
130
|
if (!ctx.schema.locales || !(key in ctx.schema.locales)) {
|
|
147
131
|
throw new Error(`Incorrect default for type "text" lang "${key}"`);
|
|
148
132
|
}
|
|
149
|
-
if (!validation(val[key],
|
|
133
|
+
if (!validation(val[key], tmpProp)) {
|
|
150
134
|
throw new Error(`Incorrect default for type "text" lang "${key}"`);
|
|
151
135
|
}
|
|
152
136
|
}
|
|
153
137
|
}
|
|
154
138
|
else {
|
|
155
|
-
if (!validation(val,
|
|
139
|
+
if (!validation(val, tmpProp)) {
|
|
156
140
|
throw new Error(`Incorrect default for type "text"`);
|
|
157
141
|
}
|
|
158
142
|
val = {};
|
|
@@ -162,7 +146,7 @@ export const isDefault = (val, prop, ctx) => {
|
|
|
162
146
|
}
|
|
163
147
|
return val;
|
|
164
148
|
}
|
|
165
|
-
if (!validation(val,
|
|
149
|
+
if (!validation(val, tmpProp)) {
|
|
166
150
|
throw new Error(`Incorrect default for type "${prop.type ?? 'enum'}"`);
|
|
167
151
|
}
|
|
168
152
|
if ('enum' in prop) {
|
|
@@ -190,7 +174,6 @@ p.vector = propParser({
|
|
|
190
174
|
if (;
|
|
297
|
-
ctx.inQuery = false;
|
|
298
|
-
ctx.isItems = false;
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
throw new Error(INVALID_VALUE);
|
|
302
|
-
}
|
|
303
|
-
},
|
|
304
|
-
}, {
|
|
305
|
-
default(val, prop) {
|
|
306
|
-
console.warn('TODO SET DEFAULT VALUE');
|
|
307
|
-
// if (typeof val === 'object') {
|
|
308
|
-
// throwErr(ERRORS.EXPECTED_PRIMITIVE, prop, 'default')
|
|
309
|
-
// }
|
|
310
|
-
},
|
|
311
|
-
});
|
|
312
264
|
p.references = propParser({
|
|
313
265
|
items(items, prop, ctx) {
|
|
314
266
|
expectObject(items);
|
|
@@ -383,11 +335,6 @@ p.text = propParser({
|
|
|
383
335
|
},
|
|
384
336
|
}, 0);
|
|
385
337
|
p.timestamp = propParser(STUB, {
|
|
386
|
-
display(val) {
|
|
387
|
-
expectString(val);
|
|
388
|
-
dateDisplaysSet ??= new Set(dateDisplays);
|
|
389
|
-
dateDisplaysSet.has(val);
|
|
390
|
-
},
|
|
391
338
|
min(val) {
|
|
392
339
|
if (typeof val !== 'string' && typeof val !== 'number') {
|
|
393
340
|
throw Error(INVALID_VALUE);
|
|
@@ -442,7 +389,6 @@ p.reference = propParser({
|
|
|
442
389
|
for (let i = 3; i < lvl; i += 2) {
|
|
443
390
|
prop += prop ? `.${path[i]}` : path[i];
|
|
444
391
|
}
|
|
445
|
-
targetProp.readOnly = true;
|
|
446
392
|
targetProp.items = {
|
|
447
393
|
ref,
|
|
448
394
|
prop,
|
|
@@ -480,13 +426,15 @@ p.reference = propParser({
|
|
|
480
426
|
if (edgeAllowed) {
|
|
481
427
|
let t = ctx.schema.types[prop.ref].props[prop.prop];
|
|
482
428
|
t = t.items || t;
|
|
483
|
-
if (t[key] && t !== prop) {
|
|
484
|
-
|
|
485
|
-
}
|
|
486
|
-
|
|
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);
|
|
487
434
|
const inType = ctx.type;
|
|
488
435
|
ctx.type = null;
|
|
489
436
|
p[edgePropType](val, ctx);
|
|
437
|
+
t[key] = prop[key];
|
|
490
438
|
ctx.type = inType;
|
|
491
439
|
return;
|
|
492
440
|
}
|
package/dist/parse/utils.js
CHANGED
|
@@ -15,16 +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
|
-
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return 'set';
|
|
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';
|
|
28
27
|
}
|
|
29
28
|
if ('props' in prop) {
|
|
30
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", "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,10 +16,6 @@ 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;
|
|
30
21
|
hooks?: SchemaPropHooks;
|
|
@@ -55,11 +46,7 @@ export type SchemaNumber = Prop<{
|
|
|
55
46
|
default?: number;
|
|
56
47
|
min?: number;
|
|
57
48
|
max?: number;
|
|
58
|
-
step?: number
|
|
59
|
-
display?: NumberDisplay;
|
|
60
|
-
history?: {
|
|
61
|
-
interval: 'year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second';
|
|
62
|
-
};
|
|
49
|
+
step?: number;
|
|
63
50
|
}>;
|
|
64
51
|
export type SchemaString = Prop<{
|
|
65
52
|
type: 'string';
|
|
@@ -121,14 +108,13 @@ export type SchemaColvec = Prop<{
|
|
|
121
108
|
*/
|
|
122
109
|
baseType?: SchemaVectorBaseType;
|
|
123
110
|
}>;
|
|
124
|
-
export type SchemaTimestamp = Prop<{
|
|
111
|
+
export type SchemaTimestamp<isStrict = false> = Prop<{
|
|
125
112
|
type: 'timestamp';
|
|
126
113
|
default?: number | Date | string;
|
|
127
114
|
on?: 'create' | 'update';
|
|
128
|
-
display?: DateDisplay;
|
|
129
115
|
min?: number | string;
|
|
130
116
|
max?: number | string;
|
|
131
|
-
step?: number
|
|
117
|
+
step?: isStrict extends true ? number : number | string;
|
|
132
118
|
}>;
|
|
133
119
|
export type SchemaReferenceOneWay = Prop<{
|
|
134
120
|
type?: 'reference';
|
|
@@ -144,9 +130,9 @@ export type SchemaReference = Prop<{
|
|
|
144
130
|
dependent?: boolean;
|
|
145
131
|
mime?: Mime;
|
|
146
132
|
}> & Record<`$${string}`, SchemaPropOneWay>;
|
|
147
|
-
export type SchemaObject = Prop<{
|
|
133
|
+
export type SchemaObject<isStrict = false> = Prop<{
|
|
148
134
|
type?: 'object';
|
|
149
|
-
props: SchemaProps
|
|
135
|
+
props: SchemaProps<isStrict>;
|
|
150
136
|
}>;
|
|
151
137
|
export type SchemaObjectOneWay = Prop<{
|
|
152
138
|
type?: 'object';
|
|
@@ -167,15 +153,7 @@ export type SchemaAlias = Omit<SchemaString, 'type'> & {
|
|
|
167
153
|
type: 'alias';
|
|
168
154
|
};
|
|
169
155
|
export type SchemaPropShorthand = 'timestamp' | 'binary' | 'boolean' | 'string' | 'alias' | 'text' | 'json' | 'cardinality' | NumberType | EnumItem[];
|
|
170
|
-
type
|
|
171
|
-
export type SchemaSet<ItemsType extends SetItems = SetItems> = Prop<{
|
|
172
|
-
type?: 'set';
|
|
173
|
-
default?: ItemsType extends {
|
|
174
|
-
default: any;
|
|
175
|
-
} ? ItemsType['default'][] : undefined;
|
|
176
|
-
items: ItemsType & NeverInItems;
|
|
177
|
-
}>;
|
|
178
|
-
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);
|
|
179
157
|
export type SchemaProp<isStrict = false> = SchemaReferencesWithQuery | SchemaReferenceWithQuery | NonRefSchemaProps<isStrict> | SchemaReferences | SchemaReference | SchemaObject | SchemaBinary;
|
|
180
158
|
export type SchemaPropOneWay<isStrict = false> = SchemaReferencesOneWay | SchemaReferenceOneWay | SchemaObjectOneWay | NonRefSchemaProps<isStrict>;
|
|
181
159
|
export type SchemaAnyProp = SchemaPropOneWay | SchemaProp;
|
|
@@ -214,6 +192,7 @@ type GenericSchemaType<isStrict = false> = {
|
|
|
214
192
|
hooks?: SchemaHooks;
|
|
215
193
|
id?: number;
|
|
216
194
|
blockCapacity?: number;
|
|
195
|
+
capped?: number;
|
|
217
196
|
insertOnly?: boolean;
|
|
218
197
|
partial?: boolean;
|
|
219
198
|
props: SchemaProps<isStrict>;
|
|
@@ -260,7 +239,6 @@ export type SchemaPropTypeMap = {
|
|
|
260
239
|
enum: SchemaEnum;
|
|
261
240
|
text: SchemaText;
|
|
262
241
|
json: SchemaJson;
|
|
263
|
-
set: SchemaSet;
|
|
264
242
|
binary: SchemaBinary;
|
|
265
243
|
cardinality: SchemaCardinality;
|
|
266
244
|
vector: SchemaVector;
|
package/dist/types.js
CHANGED
|
@@ -1,22 +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
|
-
'time',
|
|
18
|
-
'time-precise',
|
|
19
|
-
];
|
|
20
2
|
export const stringFormats = [
|
|
21
3
|
'alpha',
|
|
22
4
|
'alphaLocales',
|
|
@@ -89,8 +71,6 @@ export const stringFormats = [
|
|
|
89
71
|
'URL',
|
|
90
72
|
'UUID',
|
|
91
73
|
'VAT',
|
|
92
|
-
// TODO: for discussion
|
|
93
|
-
'multiline',
|
|
94
74
|
];
|
|
95
75
|
export const isPropType = (type, prop) => {
|
|
96
76
|
return getPropType(prop) === type;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@based/schema",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"README.md",
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"typescript": "^5.6.3"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@based/utils": "1.
|
|
35
|
-
"picocolors": "^1.1.0"
|
|
34
|
+
"@based/utils": "1.2.0",
|
|
35
|
+
"picocolors": "^1.1.0",
|
|
36
|
+
"validator": "^13.15.20"
|
|
36
37
|
}
|
|
37
38
|
}
|
package/dist/def/refSet.d.ts
DELETED
package/dist/def/refSet.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
const packOne = (nodeType, field) => ((nodeType & 0xffff) << 8) | (field & 0xff);
|
|
2
|
-
const packTwo = (a, b) => (a << 24) | (b & 0xffffff);
|
|
3
|
-
const makeTuple = (aType, aField, bType, bField) => {
|
|
4
|
-
const a = packOne(aType, aField);
|
|
5
|
-
const b = packOne(bType, bField);
|
|
6
|
-
return a < b ? packTwo(a, b) : packTwo(b, a);
|
|
7
|
-
};
|
|
8
|
-
export default class RefSet {
|
|
9
|
-
#s = new Set();
|
|
10
|
-
add(srcType, srcField, dstType, dstField) {
|
|
11
|
-
const t = makeTuple(srcType, srcField, dstType, dstField);
|
|
12
|
-
if (this.#s.has(t)) {
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
this.#s.add(t);
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
clear() {
|
|
19
|
-
this.#s.clear();
|
|
20
|
-
}
|
|
21
|
-
values() {
|
|
22
|
-
return this.#s.values();
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
//# sourceMappingURL=refSet.js.map
|
package/dist/def/selvaBuffer.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { ALIAS, ALIASES, BINARY, EMPTY_MICRO_BUFFER, CARDINALITY, MICRO_BUFFER, REFERENCE, REFERENCES, STRING, TEXT, VECTOR, WEAK_REFERENCE, WEAK_REFERENCES, JSON, COLVEC, VECTOR_BASE_TYPE_SIZE_MAP, } from './types.js';
|
|
2
|
-
import RefSet from './refSet.js';
|
|
3
|
-
const selvaFieldType = {
|
|
4
|
-
NULL: 0,
|
|
5
|
-
MICRO_BUFFER: 1,
|
|
6
|
-
STRING: 2,
|
|
7
|
-
TEXT: 3,
|
|
8
|
-
REFERENCE: 4,
|
|
9
|
-
REFERENCES: 5,
|
|
10
|
-
WEAK_REFERENCE: 6,
|
|
11
|
-
WEAK_REFERENCES: 7,
|
|
12
|
-
ALIAS: 8,
|
|
13
|
-
ALIASES: 9,
|
|
14
|
-
COLVEC: 10,
|
|
15
|
-
};
|
|
16
|
-
const selvaTypeMap = new Uint8Array(32); // 1.2x faster than JS array
|
|
17
|
-
selvaTypeMap[MICRO_BUFFER] = selvaFieldType.MICRO_BUFFER;
|
|
18
|
-
selvaTypeMap[VECTOR] = selvaFieldType.MICRO_BUFFER;
|
|
19
|
-
selvaTypeMap[BINARY] = selvaFieldType.STRING;
|
|
20
|
-
selvaTypeMap[CARDINALITY] = selvaFieldType.STRING;
|
|
21
|
-
selvaTypeMap[JSON] = selvaFieldType.STRING;
|
|
22
|
-
selvaTypeMap[STRING] = selvaFieldType.STRING;
|
|
23
|
-
selvaTypeMap[TEXT] = selvaFieldType.TEXT;
|
|
24
|
-
selvaTypeMap[REFERENCE] = selvaFieldType.REFERENCE;
|
|
25
|
-
selvaTypeMap[REFERENCES] = selvaFieldType.REFERENCES;
|
|
26
|
-
selvaTypeMap[WEAK_REFERENCE] = selvaFieldType.WEAK_REFERENCE;
|
|
27
|
-
selvaTypeMap[WEAK_REFERENCES] = selvaFieldType.WEAK_REFERENCES;
|
|
28
|
-
selvaTypeMap[ALIAS] = selvaFieldType.ALIAS;
|
|
29
|
-
selvaTypeMap[ALIASES] = selvaFieldType.ALIASES;
|
|
30
|
-
selvaTypeMap[COLVEC] = selvaFieldType.COLVEC;
|
|
31
|
-
const EDGE_FIELD_CONSTRAINT_FLAG_DEPENDENT = 0x01;
|
|
32
|
-
const EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP = 0x80;
|
|
33
|
-
function blockCapacity(blockCapacity) {
|
|
34
|
-
const buf = new Uint8Array(Uint32Array.BYTES_PER_ELEMENT);
|
|
35
|
-
const view = new DataView(buf.buffer);
|
|
36
|
-
view.setUint32(0, blockCapacity, true);
|
|
37
|
-
return buf;
|
|
38
|
-
}
|
|
39
|
-
function sepPropCount(props) {
|
|
40
|
-
return props.filter((prop) => prop.separate).length;
|
|
41
|
-
}
|
|
42
|
-
function makeEdgeConstraintFlags(refSet, nodeTypeId, prop, dstNodeTypeId, inverseProp) {
|
|
43
|
-
let flags = 0;
|
|
44
|
-
flags |= prop.dependent ? EDGE_FIELD_CONSTRAINT_FLAG_DEPENDENT : 0x00;
|
|
45
|
-
flags |=
|
|
46
|
-
prop.typeIndex === REFERENCE &&
|
|
47
|
-
inverseProp &&
|
|
48
|
-
inverseProp.typeIndex === REFERENCES
|
|
49
|
-
? EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP
|
|
50
|
-
: 0x00;
|
|
51
|
-
if (inverseProp) {
|
|
52
|
-
const x = refSet.add(nodeTypeId, prop.prop, dstNodeTypeId, inverseProp.prop);
|
|
53
|
-
flags |= x ? 0x00 : EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP;
|
|
54
|
-
}
|
|
55
|
-
return flags;
|
|
56
|
-
}
|
|
57
|
-
const propDefBuffer = (refSet, nodeTypeId, schema, prop) => {
|
|
58
|
-
const type = prop.typeIndex;
|
|
59
|
-
const selvaType = selvaTypeMap[type];
|
|
60
|
-
if (prop.len && (type === MICRO_BUFFER || type === VECTOR)) {
|
|
61
|
-
const buf = new Uint8Array(3);
|
|
62
|
-
const view = new DataView(buf.buffer);
|
|
63
|
-
buf[0] = selvaType;
|
|
64
|
-
view.setUint16(1, prop.len, true);
|
|
65
|
-
return [...buf];
|
|
66
|
-
}
|
|
67
|
-
else if (prop.len && type === COLVEC) {
|
|
68
|
-
const buf = new Uint8Array(5);
|
|
69
|
-
const view = new DataView(buf.buffer);
|
|
70
|
-
buf[0] = selvaType;
|
|
71
|
-
const baseSize = VECTOR_BASE_TYPE_SIZE_MAP[prop.vectorBaseType];
|
|
72
|
-
view.setUint16(1, prop.len / baseSize, true); // elements
|
|
73
|
-
view.setUint16(3, baseSize, true); // element size
|
|
74
|
-
return [...buf];
|
|
75
|
-
}
|
|
76
|
-
else if (type === REFERENCE || type === REFERENCES) {
|
|
77
|
-
const buf = new Uint8Array(7);
|
|
78
|
-
const view = new DataView(buf.buffer);
|
|
79
|
-
const dstType = schema[prop.inverseTypeName];
|
|
80
|
-
// @ts-ignore
|
|
81
|
-
buf[0] = selvaType + 2 * !!prop.__isEdge; // field type
|
|
82
|
-
buf[1] = makeEdgeConstraintFlags(refSet, nodeTypeId, prop, dstType.id, dstType.props[prop.inversePropName]); // flags
|
|
83
|
-
view.setUint16(2, dstType.id, true); // dst_node_type
|
|
84
|
-
if (prop.__isEdge) {
|
|
85
|
-
buf[4] = 0;
|
|
86
|
-
view.setUint16(5, 0, true);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
buf[4] = prop.inversePropNumber;
|
|
90
|
-
view.setUint16(5, prop.edgeNodeTypeId, true); // meta_node_type
|
|
91
|
-
}
|
|
92
|
-
return [...buf];
|
|
93
|
-
}
|
|
94
|
-
else if (type === STRING ||
|
|
95
|
-
type === BINARY ||
|
|
96
|
-
type === CARDINALITY ||
|
|
97
|
-
type === JSON) {
|
|
98
|
-
return [selvaType, prop.len < 50 ? prop.len : 0];
|
|
99
|
-
}
|
|
100
|
-
{
|
|
101
|
-
return [selvaType];
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
// TODO rewrite
|
|
105
|
-
export function schemaToSelvaBuffer(schema) {
|
|
106
|
-
const refSet = new RefSet();
|
|
107
|
-
return Object.values(schema).map((t) => {
|
|
108
|
-
const props = Object.values(t.props);
|
|
109
|
-
const rest = [];
|
|
110
|
-
const nrFields = 1 + sepPropCount(props);
|
|
111
|
-
let refFields = 0;
|
|
112
|
-
let virtualFields = 0;
|
|
113
|
-
if (nrFields >= 250) {
|
|
114
|
-
throw new Error('Too many fields');
|
|
115
|
-
}
|
|
116
|
-
for (const f of props) {
|
|
117
|
-
if (f.separate) {
|
|
118
|
-
if (f.typeIndex === REFERENCE || f.typeIndex === REFERENCES) {
|
|
119
|
-
refFields++;
|
|
120
|
-
}
|
|
121
|
-
else if (f.typeIndex === ALIAS ||
|
|
122
|
-
f.typeIndex === ALIASES ||
|
|
123
|
-
f.typeIndex === COLVEC) {
|
|
124
|
-
// We assume that these are always the last props!
|
|
125
|
-
virtualFields++;
|
|
126
|
-
}
|
|
127
|
-
rest.push(f);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
rest.sort((a, b) => a.prop - b.prop);
|
|
131
|
-
return Uint8Array.from([
|
|
132
|
-
...blockCapacity(t.blockCapacity), // u32 blockCapacity
|
|
133
|
-
nrFields, // u8 nrFields
|
|
134
|
-
1 + refFields, // u8 nrFixedFields
|
|
135
|
-
virtualFields, // u8 nrVirtualFields
|
|
136
|
-
0, // u8 spare1
|
|
137
|
-
...propDefBuffer(refSet, t.id, schema, {
|
|
138
|
-
...EMPTY_MICRO_BUFFER,
|
|
139
|
-
len: t.mainLen === 0 ? 1 : t.mainLen,
|
|
140
|
-
}),
|
|
141
|
-
...rest.map((f) => propDefBuffer(refSet, t.id, schema, f)).flat(1),
|
|
142
|
-
]).buffer;
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
//# sourceMappingURL=selvaBuffer.js.map
|