@based/schema 5.0.4 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { StrictSchema } from "./types.js";
1
+ import { StrictSchema } from './types.js';
2
2
  export type DbSchema = StrictSchema & {
3
3
  lastId: number;
4
4
  hash: number;
package/dist/dbSchema.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { hash } from '@based/hash';
2
- import { getPropType } from "./parse/utils.js";
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 = (typeName, refPath, edgeProps) => newTypes[`_${typeName}:${refPath}`] = { props: edgeProps };
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).filter((k) => k[0] === '$').forEach((k) => edgeProps[k] = prop[k]);
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, nextPropPrefix, edgeProps);
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).filter((k) => k[0] === '$').forEach((k) => edgeProps[k] = prop.items[k]);
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, nextPropPrefix, edgeProps);
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) {
@@ -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.validation ?? VALIDATION_MAP[typeIndex] ?? defaultValidation,
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;
@@ -3,6 +3,7 @@ export const createEmptyDef = (typeName, type, locales) => {
3
3
  return {
4
4
  cnt: 0,
5
5
  blockCapacity: 0,
6
+ capped: 0,
6
7
  insertOnly: false,
7
8
  partial: false,
8
9
  checksum: hashObjectIgnoreKeyOrder(type),
@@ -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, WEAK_REFERENCE, WEAK_REFERENCES, NULL, OBJECT, } from './types.js';
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,
@@ -1,7 +1,6 @@
1
1
  export * from './types.js';
2
2
  export * from './typeDef.js';
3
3
  export * from './utils.js';
4
- export * from './selvaBuffer.js';
5
4
  export * from './createEmptyDef.js';
6
5
  export * from './defaultMap.js';
7
6
  export * from './validation.js';
package/dist/def/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
  export * from './types.js';
3
3
  export * from './typeDef.js';
4
4
  export * from './utils.js';
5
- export * from './selvaBuffer.js';
6
5
  export * from './createEmptyDef.js';
7
6
  export * from './defaultMap.js';
8
7
  export * from './validation.js';
@@ -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}:${prop.path.join('.')}`;
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.validation ?? VALIDATION_MAP[typeIndex] ?? defaultValidation,
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 WEAK_REFERENCE | typeof WEAK_REFERENCES | typeof MICRO_BUFFER | typeof ALIAS | typeof ALIASES | typeof BINARY | typeof ID | typeof VECTOR | typeof JSON | typeof OBJECT | typeof COLVEC;
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,
@@ -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;
@@ -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
- mainLen: number;
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: [''],
@@ -1,7 +1,19 @@
1
- import { TypeIndex, PropDef, PropDefEdge } from './types.js';
2
- export type Validation = (payload: any, prop: PropDef | PropDefEdge) => boolean;
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
@@ -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, WEAK_REFERENCE, WEAK_REFERENCES, NULL, OBJECT, } from './types.js';
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' || value % t.step !== 0) {
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' || value % t.step !== 0) {
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' || value % t.step !== 0) {
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' || value % t.step !== 0) {
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' || value % t.step !== 0) {
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' || value % t.step !== 0) {
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' || value % t.step !== 0) {
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, prop) => {
255
+ [ENUM]: (value, t) => {
169
256
  if (value === null) {
170
257
  return true;
171
258
  }
172
- const arr = prop.enum;
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]: (value, t) => {
215
- // add max etc all here - make a ref to the original SCHEMA on DEF
216
- if (typeof value !== 'string' && !(value instanceof Uint8Array)) {
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
- return true;
220
- },
221
- [TEXT]: (value, t) => {
222
- // add max etc all here - make a ref to the original SCHEMA on DEF
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,113 @@ 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
+ if ('items' in prop) {
385
+ if (typeof val !== 'object' || val === null) {
386
+ errors.push({
387
+ path: [...path, key],
388
+ value: val,
389
+ error: 'Invalid value',
390
+ });
391
+ }
392
+ let arr = val;
393
+ if (!Array.isArray(val)) {
394
+ arr = [];
395
+ for (const i in val) {
396
+ if (i === 'add') {
397
+ arr.push(...val.add);
398
+ }
399
+ else if (i === 'update') {
400
+ arr.push(...val.update);
401
+ }
402
+ else if (i === 'delete') {
403
+ arr.push(...val.delete);
404
+ }
405
+ else {
406
+ arr = [];
407
+ break;
408
+ }
409
+ }
410
+ if (!arr.length) {
411
+ errors.push({
412
+ path: [...path, key],
413
+ value: arr,
414
+ error: 'Invalid value',
415
+ });
416
+ }
417
+ }
418
+ for (const val of arr) {
419
+ const msg = typeof val === 'object' ? test(val?.id, prop) : test(val, prop);
420
+ if (msg !== true) {
421
+ errors.push({
422
+ path: [...path, key],
423
+ value: val,
424
+ error: typeof msg === 'string' ? msg : 'Invalid value',
425
+ });
426
+ }
427
+ }
428
+ }
429
+ else {
430
+ const msg = getPropType(prop) === 'reference' && typeof val === 'object'
431
+ ? test(val?.id, prop)
432
+ : test(val, prop);
433
+ if (msg !== true) {
434
+ errors.push({
435
+ path: [...path, key],
436
+ value: val,
437
+ error: typeof msg === 'string' ? msg : 'Invalid value',
438
+ });
439
+ }
440
+ }
441
+ }
442
+ }
443
+ };
444
+ export const getValidator = (prop) => {
445
+ const validator = VALIDATION_MAP[TYPE_INDEX_MAP[getPropType(prop)]] ?? defaultValidation;
446
+ const custom = prop.validation;
447
+ if (custom) {
448
+ return (a, b) => {
449
+ const msg = custom(a, b);
450
+ return msg === true ? validator(a, b) : msg;
451
+ };
452
+ }
453
+ return validator;
454
+ };
455
+ export function validate(schema, type, payload) {
456
+ const errors = [];
457
+ validateObj(payload, schema?.types?.[type]?.props, errors, [], true);
458
+ return {
459
+ valid: !errors.length,
460
+ errors,
461
+ };
462
+ }
261
463
  //# 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>;
@@ -1,15 +1,12 @@
1
1
  import { convertToTimestamp } from '@based/utils';
2
2
  import { NUMBER, TYPE_INDEX_MAP } from '../def/types.js';
3
- import { VALIDATION_MAP } from '../def/validation.js';
4
- import { stringFormats, dateDisplays, numberDisplays, } from '../types.js';
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.validation || VALIDATION_MAP[typeIndex];
128
- const propDef = {
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], propDef)) {
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, propDef)) {
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, propDef)) {
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 (![
191
175
  'number',
192
176
  'int8',
193
- ,
194
177
  'uint8',
195
178
  'int16',
196
179
  'uint16',
@@ -248,21 +231,16 @@ p.enum = propParser({
248
231
  },
249
232
  }, 1);
250
233
  const numberOpts = {
251
- display(val) {
252
- expectString(val);
253
- numberDisplaysSet ??= new Set(numberDisplays);
254
- numberDisplaysSet.has(val);
255
- },
256
- min(val) {
234
+ min(val, prop, ctx, key) {
257
235
  expectNumber(val);
258
236
  },
259
- max(val, prop) {
237
+ max(val, prop, ctx, key) {
260
238
  expectNumber(val);
261
239
  if (prop.min > val) {
262
240
  throw Error(MIN_MAX);
263
241
  }
264
242
  },
265
- step(val) {
243
+ step(val, prop, ctx, key) {
266
244
  if (typeof val !== 'number' && val !== 'any') {
267
245
  throw Error(INVALID_VALUE);
268
246
  }
@@ -283,32 +261,6 @@ p.object = propParser({
283
261
  ctx.parseProps(val, ctx.type);
284
262
  },
285
263
  }, {});
286
- p.set = propParser({
287
- items(items, prop, ctx) {
288
- expectObject(items);
289
- const itemsType = getPropType(items);
290
- if (itemsType === 'string' ||
291
- itemsType === 'number' ||
292
- itemsType === 'timestamp' ||
293
- itemsType === 'boolean') {
294
- ctx.inQuery = 'query' in prop;
295
- ctx.isItems = true;
296
- p[itemsType](items, ctx);
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
- throw Error('Edge can not be defined on both props');
485
- }
486
- const edgePropType = getPropType(val);
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
  }
@@ -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
- if (getPropType(prop.items) === 'reference') {
20
- Object.keys(prop.items).filter((v) => v[0] === '$').forEach((v) => {
21
- if (typeof prop.items[v] === 'string') {
22
- prop.items[v] = { type: prop.items[v] };
23
- }
24
- });
25
- return 'references';
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
- type Role = 'title' | 'source' | 'media' | string;
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 | 'any';
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 | 'any' | string;
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 SetItems<isStrict = false> = SchemaTimestamp | SchemaBoolean | SchemaNumber | SchemaString | SchemaEnum | (isStrict extends true ? never : 'timestamp' | 'binary' | 'boolean' | 'string' | NumberType | EnumItem[]);
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.4",
3
+ "version": "5.1.1",
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.1.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
  }
@@ -1,7 +0,0 @@
1
- export default class RefSet {
2
- #private;
3
- add(srcType: number, srcField: number, dstType: number, dstField: number): boolean;
4
- clear(): void;
5
- values(): SetIterator<number>;
6
- }
7
- //# sourceMappingURL=refSet.d.ts.map
@@ -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
@@ -1,5 +0,0 @@
1
- import { SchemaTypeDef } from './types.js';
2
- export declare function schemaToSelvaBuffer(schema: {
3
- [key: string]: SchemaTypeDef;
4
- }): ArrayBuffer[];
5
- //# sourceMappingURL=selvaBuffer.d.ts.map
@@ -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