@based/schema 5.0.3 → 5.0.4

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.js CHANGED
@@ -1,6 +1,39 @@
1
1
  import { hash } from '@based/hash';
2
2
  import { getPropType } from "./parse/utils.js";
3
3
  import { deepCopy } from '@based/utils';
4
+ function _makeEdgeTypes(newTypes, typeName, props, propPrefix) {
5
+ const putEdgeProps = (typeName, refPath, edgeProps) => newTypes[`_${typeName}:${refPath}`] = { props: edgeProps };
6
+ for (const propName in props) {
7
+ const prop = props[propName];
8
+ const propType = getPropType(prop);
9
+ const nextPropPrefix = propPrefix ? `${propPrefix}.${propName}` : propName;
10
+ if (propType === 'object') {
11
+ _makeEdgeTypes(newTypes, typeName, prop.props, nextPropPrefix);
12
+ }
13
+ else if (propType === 'reference') {
14
+ const edgeProps = {};
15
+ Object.keys(prop).filter((k) => k[0] === '$').forEach((k) => edgeProps[k] = prop[k]);
16
+ if (Object.keys(edgeProps).length > 0) {
17
+ putEdgeProps(typeName, nextPropPrefix, edgeProps);
18
+ }
19
+ }
20
+ else if (propType === 'references') {
21
+ const edgeProps = {};
22
+ Object.keys(prop.items).filter((k) => k[0] === '$').forEach((k) => edgeProps[k] = prop.items[k]);
23
+ if (Object.keys(edgeProps).length > 0) {
24
+ putEdgeProps(typeName, nextPropPrefix, edgeProps);
25
+ }
26
+ }
27
+ }
28
+ }
29
+ function makeEdgeTypes(types) {
30
+ const newTypes = {};
31
+ for (const typeName in types) {
32
+ const type = types[typeName];
33
+ _makeEdgeTypes(newTypes, typeName, type.props, '');
34
+ }
35
+ return newTypes;
36
+ }
4
37
  export const strictSchemaToDbSchema = (schema) => {
5
38
  // @ts-ignore
6
39
  let dbSchema = deepCopy(schema);
@@ -45,6 +78,10 @@ export const strictSchemaToDbSchema = (schema) => {
45
78
  };
46
79
  delete dbSchema.props;
47
80
  }
81
+ const edgeTypes = makeEdgeTypes(dbSchema.types);
82
+ for (const et in edgeTypes) {
83
+ dbSchema.types[et] = edgeTypes[et];
84
+ }
48
85
  // Assign typeIds
49
86
  for (const typeName in dbSchema.types) {
50
87
  if (!('id' in dbSchema.types[typeName])) {
@@ -48,13 +48,13 @@ function makeEdgeConstraintFlags(refSet, nodeTypeId, prop, dstNodeTypeId, invers
48
48
  inverseProp.typeIndex === REFERENCES
49
49
  ? EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP
50
50
  : 0x00;
51
- if (refSet) {
51
+ if (inverseProp) {
52
52
  const x = refSet.add(nodeTypeId, prop.prop, dstNodeTypeId, inverseProp.prop);
53
53
  flags |= x ? 0x00 : EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP;
54
54
  }
55
55
  return flags;
56
56
  }
57
- const propDefBuffer = (refSet, nodeTypeId, schema, prop, isEdge) => {
57
+ const propDefBuffer = (refSet, nodeTypeId, schema, prop) => {
58
58
  const type = prop.typeIndex;
59
59
  const selvaType = selvaTypeMap[type];
60
60
  if (prop.len && (type === MICRO_BUFFER || type === VECTOR)) {
@@ -74,41 +74,22 @@ const propDefBuffer = (refSet, nodeTypeId, schema, prop, isEdge) => {
74
74
  return [...buf];
75
75
  }
76
76
  else if (type === REFERENCE || type === REFERENCES) {
77
- const buf = new Uint8Array(9);
77
+ const buf = new Uint8Array(7);
78
78
  const view = new DataView(buf.buffer);
79
79
  const dstType = schema[prop.inverseTypeName];
80
- let eschema = [];
81
80
  // @ts-ignore
82
- buf[0] = selvaType + 2 * !!isEdge; // field type
81
+ buf[0] = selvaType + 2 * !!prop.__isEdge; // field type
83
82
  buf[1] = makeEdgeConstraintFlags(refSet, nodeTypeId, prop, dstType.id, dstType.props[prop.inversePropName]); // flags
84
83
  view.setUint16(2, dstType.id, true); // dst_node_type
85
- view.setUint32(5, 0, true); // schema_len
86
- if (!isEdge) {
84
+ if (prop.__isEdge) {
85
+ buf[4] = 0;
86
+ view.setUint16(5, 0, true);
87
+ }
88
+ else {
87
89
  buf[4] = prop.inversePropNumber;
88
- if (prop.edges) {
89
- const edgesS = Object.values(prop.edges);
90
- if (edgesS.length) {
91
- const props = edgesS
92
- .filter((v) => v.separate === true)
93
- .sort((a, b) => (a.prop > b.prop ? 1 : -1));
94
- const p = [
95
- {
96
- ...EMPTY_MICRO_BUFFER,
97
- len: prop.edgeMainLen || 1, // allow zero here... else useless padding
98
- __isEdgeDef: true,
99
- },
100
- // or handle this here...
101
- ...props,
102
- ];
103
- eschema = p
104
- .map((prop) => propDefBuffer(null, 0, schema, prop, true))
105
- .flat(1);
106
- eschema.unshift(0, 0, 0, 0, sepPropCount(p), 0, 0, 0);
107
- view.setUint32(5, eschema.length, true);
108
- }
109
- }
90
+ view.setUint16(5, prop.edgeNodeTypeId, true); // meta_node_type
110
91
  }
111
- return [...buf, ...eschema];
92
+ return [...buf];
112
93
  }
113
94
  else if (type === STRING ||
114
95
  type === BINARY ||
@@ -153,7 +134,7 @@ export function schemaToSelvaBuffer(schema) {
153
134
  1 + refFields, // u8 nrFixedFields
154
135
  virtualFields, // u8 nrVirtualFields
155
136
  0, // u8 spare1
156
- ...propDefBuffer(null, t.id, schema, {
137
+ ...propDefBuffer(refSet, t.id, schema, {
157
138
  ...EMPTY_MICRO_BUFFER,
158
139
  len: t.mainLen === 0 ? 1 : t.mainLen,
159
140
  }),
@@ -1,10 +1,10 @@
1
1
  import { isPropType, getPropType, } from '../index.js';
2
2
  import { setByPath } from '@based/utils';
3
- import { TYPE_INDEX_MAP, REFERENCES, REFERENCE, NUMBER, BLOCK_CAPACITY_MAX, BLOCK_CAPACITY_DEFAULT, BLOCK_CAPACITY_MIN, VECTOR, COLVEC, } from './types.js';
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';
5
5
  import { makeSeparateTextSort } from './makeSeparateTextSort.js';
6
6
  import { makeSeparateSort } from './makeSeparateSort.js';
7
- import { getPropLen, isSeparate, parseMinMaxStep, reorderProps, schemaVectorBaseTypeToEnum, sortMainProps, } from './utils.js';
7
+ import { getPropLen, isSeparate, parseMinMaxStep, reorderProps, schemaVectorBaseTypeToEnum, sortMainProps, cardinalityModeToEnum, } from './utils.js';
8
8
  import { addEdges } from './addEdges.js';
9
9
  import { createEmptyDef } from './createEmptyDef.js';
10
10
  import { fillEmptyMain, isZeroes } from './fillEmptyMain.js';
@@ -17,27 +17,58 @@ export const updateTypeDefs = (schema) => {
17
17
  if (!type.id) {
18
18
  throw new Error('NEED ID ON TYPE');
19
19
  }
20
- const def = createSchemaTypeDef(typeName, type, schemaTypesParsed, schema.locales ?? {
20
+ const def = createSchemaTypeDef(typeName, type, schema.locales ?? {
21
21
  en: {},
22
22
  });
23
23
  schemaTypesParsed[typeName] = def;
24
24
  schemaTypesParsedById[type.id] = def;
25
25
  }
26
- // Update inverseProps in references
27
26
  for (const schema of Object.values(schemaTypesParsed)) {
28
27
  for (const prop of Object.values(schema.props)) {
29
28
  if (prop.typeIndex === REFERENCE || prop.typeIndex === REFERENCES) {
29
+ // FIXME Now references in edgeType are missing __isEdge
30
+ // However, we can soon just delete weak refs
31
+ if (!prop.__isEdge && !prop.inversePropName) {
32
+ prop.__isEdge = true;
33
+ }
30
34
  if (!prop.__isEdge) {
35
+ // Update inverseProps in references
31
36
  const dstType = schemaTypesParsed[prop.inverseTypeName];
32
37
  prop.inverseTypeId = dstType.id;
33
38
  prop.inversePropNumber = dstType.props[prop.inversePropName].prop;
39
+ if (prop.edges) {
40
+ if (dstType.props[prop.inversePropName].edges) {
41
+ // this currently is not allowed, but might be
42
+ const mergedEdges = {
43
+ ...dstType.props[prop.inversePropName].edges,
44
+ ...prop.edges,
45
+ };
46
+ dstType.props[prop.inversePropName].edges = mergedEdges;
47
+ prop.edges = mergedEdges;
48
+ }
49
+ else {
50
+ dstType.props[prop.inversePropName].edges = prop.edges;
51
+ }
52
+ }
53
+ // Update edgeNodeTypeId
54
+ if (!prop.edgeNodeTypeId) {
55
+ if (prop.edges) {
56
+ const edgeTypeName = `_${schema.type}:${prop.path.join('.')}`;
57
+ const edgeType = schemaTypesParsed[edgeTypeName];
58
+ prop.edgeNodeTypeId = edgeType.id;
59
+ dstType.props[prop.inversePropName].edgeNodeTypeId = edgeType.id;
60
+ }
61
+ else {
62
+ prop.edgeNodeTypeId = 0;
63
+ }
64
+ }
34
65
  }
35
66
  }
36
67
  }
37
68
  }
38
69
  return { schemaTypesParsed, schemaTypesParsedById };
39
70
  };
40
- const createSchemaTypeDef = (typeName, type, parsed, locales, result = createEmptyDef(typeName, type, locales), path = [], top = true) => {
71
+ const createSchemaTypeDef = (typeName, type, locales, result = createEmptyDef(typeName, type, locales), path = [], top = true) => {
41
72
  if (top) {
42
73
  if (result.id == 0) {
43
74
  if ('id' in type) {
@@ -82,111 +113,120 @@ const createSchemaTypeDef = (typeName, type, parsed, locales, result = createEmp
82
113
  const propPath = [...path, key];
83
114
  const propType = getPropType(schemaProp);
84
115
  if (propType === 'object') {
85
- createSchemaTypeDef(typeName, schemaProp, parsed, locales, result, propPath, false);
86
- }
87
- else {
88
- const len = getPropLen(schemaProp);
89
- if (isPropType('string', schemaProp) ||
90
- isPropType('alias', schemaProp) ||
91
- isPropType('cardinality', schemaProp)) {
92
- if (typeof schemaProp === 'object') {
93
- if (!(schemaProp.maxBytes < 61) ||
94
- !('max' in schemaProp && schemaProp.max < 31)) {
95
- result.separateSortProps++;
96
- }
97
- }
98
- else {
116
+ createSchemaTypeDef(typeName, schemaProp, locales, result, propPath, false);
117
+ continue;
118
+ }
119
+ const len = getPropLen(schemaProp);
120
+ if (isPropType('string', schemaProp) ||
121
+ isPropType('alias', schemaProp) ||
122
+ isPropType('cardinality', schemaProp)) {
123
+ if (typeof schemaProp === 'object') {
124
+ if (!(schemaProp.maxBytes < 61) ||
125
+ !('max' in schemaProp && schemaProp.max < 31)) {
99
126
  result.separateSortProps++;
100
127
  }
101
128
  }
102
- else if (isPropType('text', schemaProp)) {
103
- result.separateSortText++;
129
+ else {
130
+ result.separateSortProps++;
104
131
  }
105
- else if (isPropType('colvec', schemaProp)) {
106
- if (!result.insertOnly) {
107
- throw new Error('colvec requires insertOnly');
108
- }
132
+ }
133
+ else if (isPropType('text', schemaProp)) {
134
+ result.separateSortText++;
135
+ }
136
+ else if (isPropType('colvec', schemaProp)) {
137
+ if (!result.insertOnly) {
138
+ throw new Error('colvec requires insertOnly');
109
139
  }
110
- const isseparate = isSeparate(schemaProp, len);
111
- const typeIndex = TYPE_INDEX_MAP[propType];
112
- const prop = {
113
- typeIndex,
114
- __isPropDef: true,
115
- separate: isseparate,
116
- path: propPath,
117
- start: 0,
118
- validation: schemaProp.validation ??
119
- VALIDATION_MAP[typeIndex] ??
120
- defaultValidation,
121
- len,
122
- default: schemaProp.default ?? DEFAULT_MAP[typeIndex],
123
- prop: isseparate ? ++result.cnt : 0,
124
- };
125
- if (schemaProp.max !== undefined) {
126
- prop.max = parseMinMaxStep(schemaProp.max);
127
- }
128
- if (schemaProp.min !== undefined) {
129
- prop.min = parseMinMaxStep(schemaProp.min);
130
- }
131
- if (schemaProp.step !== undefined) {
132
- prop.step = parseMinMaxStep(schemaProp.step);
133
- }
134
- if (prop.typeIndex !== NUMBER && prop.step === undefined) {
135
- prop.step = 1;
136
- }
137
- if (prop.typeIndex === VECTOR || prop.typeIndex === COLVEC) {
138
- prop.vectorBaseType = schemaVectorBaseTypeToEnum(schemaProp.baseType ?? 'number');
139
- }
140
- if (isPropType('enum', schemaProp)) {
141
- prop.enum = Array.isArray(schemaProp) ? schemaProp : schemaProp.enum;
142
- prop.reverseEnum = {};
143
- for (let i = 0; i < prop.enum.length; i++) {
144
- prop.reverseEnum[prop.enum[i]] = i;
145
- }
140
+ }
141
+ const isseparate = isSeparate(schemaProp, len);
142
+ const typeIndex = TYPE_INDEX_MAP[propType];
143
+ const prop = {
144
+ typeIndex,
145
+ __isPropDef: true,
146
+ separate: isseparate,
147
+ path: propPath,
148
+ start: 0,
149
+ validation: schemaProp.validation ?? VALIDATION_MAP[typeIndex] ?? defaultValidation,
150
+ len,
151
+ default: schemaProp.default ?? DEFAULT_MAP[typeIndex],
152
+ prop: isseparate ? ++result.cnt : 0,
153
+ };
154
+ if (schemaProp.hooks) {
155
+ result.propHooks ??= {};
156
+ for (const key in schemaProp.hooks) {
157
+ prop.hooks = schemaProp.hooks;
158
+ result.propHooks[key] ??= new Set();
159
+ result.propHooks[key].add(prop);
146
160
  }
147
- else if (isPropType('references', schemaProp)) {
148
- if (result.partial) {
149
- throw new Error('references is not supported with partial');
150
- }
151
- prop.inversePropName = schemaProp.items.prop;
152
- prop.inverseTypeName = schemaProp.items.ref;
153
- prop.dependent = schemaProp.items.dependent;
154
- addEdges(prop, schemaProp.items);
155
- }
156
- else if (isPropType('reference', schemaProp)) {
157
- if (result.partial) {
158
- throw new Error('reference is not supported with partial');
159
- }
160
- prop.inversePropName = schemaProp.prop;
161
- prop.inverseTypeName = schemaProp.ref;
162
- prop.dependent = schemaProp.dependent;
163
- addEdges(prop, schemaProp);
164
- }
165
- else if (typeof schemaProp === 'object') {
166
- if (isPropType('string', schemaProp) ||
167
- isPropType('text', schemaProp)) {
168
- prop.compression =
169
- 'compression' in schemaProp && schemaProp.compression === 'none'
170
- ? 0
171
- : 1;
161
+ }
162
+ if (schemaProp.max !== undefined) {
163
+ prop.max = parseMinMaxStep(schemaProp.max);
164
+ }
165
+ if (schemaProp.min !== undefined) {
166
+ prop.min = parseMinMaxStep(schemaProp.min);
167
+ }
168
+ if (schemaProp.step !== undefined) {
169
+ prop.step = parseMinMaxStep(schemaProp.step);
170
+ }
171
+ if (prop.typeIndex !== NUMBER && prop.step === undefined) {
172
+ prop.step = 1;
173
+ }
174
+ if (prop.typeIndex === VECTOR || prop.typeIndex === COLVEC) {
175
+ prop.vectorBaseType = schemaVectorBaseTypeToEnum(schemaProp.baseType ?? 'number');
176
+ }
177
+ if (prop.typeIndex === CARDINALITY) {
178
+ prop.cardinalityMode ??= cardinalityModeToEnum((schemaProp.mode ??= 'sparse'));
179
+ const prec = typeName == '_root' ? 14 : 8;
180
+ prop.cardinalityPrecision ??= schemaProp.precision ??= prec;
181
+ }
182
+ if (isPropType('enum', schemaProp)) {
183
+ prop.enum = Array.isArray(schemaProp) ? schemaProp : schemaProp.enum;
184
+ prop.reverseEnum = {};
185
+ for (let i = 0; i < prop.enum.length; i++) {
186
+ prop.reverseEnum[prop.enum[i]] = i;
187
+ }
188
+ }
189
+ else if (isPropType('references', schemaProp)) {
190
+ if (result.partial) {
191
+ throw new Error('references is not supported with partial');
192
+ }
193
+ prop.inversePropName = schemaProp.items.prop;
194
+ prop.inverseTypeName = schemaProp.items.ref;
195
+ prop.dependent = schemaProp.items.dependent;
196
+ addEdges(prop, schemaProp.items);
197
+ }
198
+ else if (isPropType('reference', schemaProp)) {
199
+ if (result.partial) {
200
+ throw new Error('reference is not supported with partial');
201
+ }
202
+ prop.inversePropName = schemaProp.prop;
203
+ prop.inverseTypeName = schemaProp.ref;
204
+ prop.dependent = schemaProp.dependent;
205
+ addEdges(prop, schemaProp);
206
+ }
207
+ else if (typeof schemaProp === 'object') {
208
+ if (isPropType('string', schemaProp) || isPropType('text', schemaProp)) {
209
+ prop.compression =
210
+ 'compression' in schemaProp && schemaProp.compression === 'none'
211
+ ? 0
212
+ : 1;
213
+ }
214
+ else if (isPropType('timestamp', schemaProp) && 'on' in schemaProp) {
215
+ if (schemaProp.on[0] === 'c') {
216
+ result.createTs ??= [];
217
+ result.createTs.push(prop);
172
218
  }
173
- else if (isPropType('timestamp', schemaProp) && 'on' in schemaProp) {
174
- if (schemaProp.on[0] === 'c') {
175
- result.createTs ??= [];
176
- result.createTs.push(prop);
177
- }
178
- else if (schemaProp.on[0] === 'u') {
179
- result.createTs ??= [];
180
- result.createTs.push(prop);
181
- result.updateTs ??= [];
182
- result.updateTs.push(prop);
183
- }
219
+ else if (schemaProp.on[0] === 'u') {
220
+ result.createTs ??= [];
221
+ result.createTs.push(prop);
222
+ result.updateTs ??= [];
223
+ result.updateTs.push(prop);
184
224
  }
185
225
  }
186
- result.props[propPath.join('.')] = prop;
187
- if (isseparate) {
188
- result.separate.push(prop);
189
- }
226
+ }
227
+ result.props[propPath.join('.')] = prop;
228
+ if (isseparate) {
229
+ result.separate.push(prop);
190
230
  }
191
231
  }
192
232
  if (top) {
@@ -1,4 +1,4 @@
1
- import type { LangCode, SchemaHooks, SchemaLocales } from '../index.js';
1
+ import type { LangCode, SchemaHooks, SchemaLocales, 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';
@@ -33,6 +33,9 @@ export type PropDef = {
33
33
  default: any;
34
34
  vectorBaseType?: VectorBaseType;
35
35
  vectorSize?: number;
36
+ cardinalityMode?: number;
37
+ cardinalityPrecision?: number;
38
+ edgeNodeTypeId?: number;
36
39
  edgeMainLen?: 0;
37
40
  hasDefaultEdges?: boolean;
38
41
  reverseEnum?: {
@@ -53,6 +56,7 @@ export type PropDef = {
53
56
  max?: any;
54
57
  min?: any;
55
58
  step?: any;
59
+ hooks?: SchemaPropHooks;
56
60
  };
57
61
  export type PropDefEdge = Partial<PropDef> & {
58
62
  __isPropDef: true;
@@ -86,7 +90,6 @@ export type SchemaTypeDef = {
86
90
  cnt: number;
87
91
  checksum: number;
88
92
  type: string;
89
- lastId: number;
90
93
  blockCapacity: number;
91
94
  mainLen: number;
92
95
  insertOnly: boolean;
@@ -128,6 +131,9 @@ export type SchemaTypeDef = {
128
131
  locales: Partial<SchemaLocales>;
129
132
  localeSize: number;
130
133
  hooks?: SchemaHooks;
134
+ propHooks?: {
135
+ [K in keyof SchemaPropHooks]: Set<PropDef>;
136
+ };
131
137
  };
132
138
  export declare const VECTOR_BASE_TYPE_SIZE_MAP: Record<VectorBaseType, number>;
133
139
  export declare const SIZE_MAP: Record<InternalSchemaProp, number>;
@@ -1,9 +1,10 @@
1
1
  import { PropDef, PropDefEdge, VectorBaseType } from './types.js';
2
- import { SchemaProp, SchemaVectorBaseType } from '../types.js';
2
+ import { SchemaProp, SchemaVectorBaseType, HLLRegisterRepresentation } from '../types.js';
3
3
  export declare function isSeparate(schemaProp: SchemaProp, len: number): boolean;
4
4
  export declare const propIsSigned: (prop: PropDef | PropDefEdge) => boolean;
5
5
  export declare const propIsNumerical: (prop: PropDef | PropDefEdge) => boolean;
6
6
  export declare const schemaVectorBaseTypeToEnum: (vector: SchemaVectorBaseType) => VectorBaseType;
7
+ export declare const cardinalityModeToEnum: (mode: HLLRegisterRepresentation) => number;
7
8
  export declare function getPropLen(schemaProp: SchemaProp): number;
8
9
  export declare const parseMinMaxStep: (val: any) => string | number;
9
10
  export declare const sortMainProps: (a: PropDef | PropDefEdge, b: PropDef | PropDefEdge) => 0 | 1 | -1;
package/dist/def/utils.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { INT16, INT32, INT8, UINT16, UINT32, UINT8, NUMBER, TIMESTAMP, SIZE_MAP, VECTOR_BASE_TYPE_SIZE_MAP, VectorBaseType, REVERSE_SIZE_MAP, REFERENCES, REFERENCE, ALIAS, ALIASES, COLVEC, } from './types.js';
2
- import { isPropType } from '../types.js';
2
+ import { isPropType, } from '../types.js';
3
3
  import { getPropType } from '../parse/utils.js';
4
4
  import { convertToTimestamp } from '@based/utils';
5
5
  export function isSeparate(schemaProp, len) {
@@ -50,6 +50,12 @@ export const schemaVectorBaseTypeToEnum = (vector) => {
50
50
  return VectorBaseType.Float64;
51
51
  }
52
52
  };
53
+ export const cardinalityModeToEnum = (mode) => {
54
+ if (mode === 'dense')
55
+ return 1;
56
+ else
57
+ 0;
58
+ };
53
59
  export function getPropLen(schemaProp) {
54
60
  let len = SIZE_MAP[getPropType(schemaProp)];
55
61
  if (isPropType('string', schemaProp) ||
@@ -58,6 +58,12 @@ const shared = {
58
58
  validation(val) {
59
59
  expectFunction(val);
60
60
  },
61
+ hooks(val, prop, ctx) {
62
+ expectObject(val);
63
+ for (const key in val) {
64
+ expectFunction(val[key]);
65
+ }
66
+ },
61
67
  };
62
68
  function propParser(required, optional, allowShorthand) {
63
69
  return (prop, ctx) => {
@@ -504,6 +510,18 @@ p.cardinality = propParser(STUB, {
504
510
  default(val, prop, ctx) {
505
511
  return isDefault(val, prop, ctx);
506
512
  },
513
+ mode(val, prop, ctx) {
514
+ if (!['dense', 'sparse'].includes(val)) {
515
+ throw Error(INVALID_VALUE);
516
+ }
517
+ p.mode = val;
518
+ },
519
+ precision(val, prop, ctx) {
520
+ if (val < 2 || val > 16) {
521
+ throw Error(INVALID_VALUE);
522
+ }
523
+ p.precision = val;
524
+ },
507
525
  }, 0);
508
526
  p.json = propParser(STUB, {
509
527
  default(val, prop, ctx) {
@@ -17,6 +17,11 @@ export const getPropType = (prop, props, key) => {
17
17
  }
18
18
  if ('items' in prop) {
19
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
+ });
20
25
  return 'references';
21
26
  }
22
27
  return 'set';
package/dist/types.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { LangName } from './lang.js';
2
2
  import type { Validation } from './def/validation.js';
3
3
  type Role = 'title' | 'source' | 'media' | string;
4
4
  export declare const numberDisplays: readonly ["short", "human", "ratio", "bytes", "euro", "dollar", "pound", "meter"];
5
- export declare const dateDisplays: readonly ["date", "date-time", "date-time-text", "date-time-human", "date-time-human-short", "time", "time-precise"];
5
+ export declare const dateDisplays: readonly ["date", "date-time", "date-time-text", "date-time-human", "time", "time-precise"];
6
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
7
  type DateDisplay = (typeof dateDisplays)[number];
8
8
  type NumberDisplay = (typeof numberDisplays)[number] | `round-${number}`;
@@ -27,6 +27,7 @@ type Prop<V extends PropValues> = {
27
27
  readOnly?: boolean;
28
28
  examples?: string[];
29
29
  validation?: Validation;
30
+ hooks?: SchemaPropHooks;
30
31
  } & V;
31
32
  type EnumItem = string | number | boolean;
32
33
  type NeverInItems = {
@@ -85,11 +86,12 @@ export type SchemaBoolean = Prop<{
85
86
  type: 'boolean';
86
87
  default?: boolean;
87
88
  }>;
89
+ export type HLLRegisterRepresentation = 'sparse' | 'dense';
88
90
  export type SchemaCardinality = Prop<{
89
91
  type: 'cardinality';
90
92
  maxBytes?: number;
91
- mime?: Mime;
92
- format?: NumberDisplay;
93
+ precision?: number;
94
+ mode?: HLLRegisterRepresentation;
93
95
  }>;
94
96
  type VectorDefaultType = Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;
95
97
  export type SchemaVectorBaseType = NumberType | 'float32' | 'float64';
@@ -195,6 +197,19 @@ export type SchemaHooks = {
195
197
  groupBy?: (query: BasedDbQuery, field: string) => void;
196
198
  aggregate?: (query: BasedDbQuery, fields: Set<string>) => void;
197
199
  };
200
+ export type SchemaPropHooks = {
201
+ create?: (value: any, payload: Record<string, any>) => any;
202
+ update?: (value: any, payload: Record<string, any>) => any;
203
+ read?: (value: any, result: Record<string, any>) => any;
204
+ aggregate?: (query: BasedDbQuery, fields: Set<string>) => void;
205
+ search?: (query: BasedDbQuery, fields: Set<string>) => void;
206
+ groupBy?: (query: BasedDbQuery, field: string) => void;
207
+ filter?: (query: BasedDbQuery, field: string, operator: Operator, value: any) => void;
208
+ include?: (query: BasedDbQuery, fields: Map<string, {
209
+ field: string;
210
+ opts?: any;
211
+ }>) => void;
212
+ };
198
213
  type GenericSchemaType<isStrict = false> = {
199
214
  hooks?: SchemaHooks;
200
215
  id?: number;
package/dist/types.js CHANGED
@@ -14,7 +14,6 @@ export const dateDisplays = [
14
14
  'date-time',
15
15
  'date-time-text',
16
16
  'date-time-human',
17
- 'date-time-human-short',
18
17
  'time',
19
18
  'time-precise',
20
19
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@based/schema",
3
- "version": "5.0.3",
3
+ "version": "5.0.4",
4
4
  "files": [
5
5
  "dist",
6
6
  "README.md",
@@ -15,6 +15,7 @@
15
15
  ".": "./dist/index.js"
16
16
  },
17
17
  "scripts": {
18
+ "clean": "rm -rf .node_modules ./dist ./tsconfig.tsbuildinfo",
18
19
  "build": "tsc",
19
20
  "watch": "tsc --watch",
20
21
  "test": "tsc && tsc $npm_config --noEmit && tsx --test $npm_config"
@@ -30,7 +31,7 @@
30
31
  "typescript": "^5.6.3"
31
32
  },
32
33
  "dependencies": {
33
- "@based/utils": "^1.0.0",
34
+ "@based/utils": "1.1.1",
34
35
  "picocolors": "^1.1.0"
35
36
  }
36
37
  }