@based/schema 5.0.0-alpha.2 → 5.0.0-alpha.20

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.
@@ -0,0 +1,203 @@
1
+ import { isPropType, getPropType, } from '../index.js';
2
+ import { setByPath } from '@saulx/utils';
3
+ import { TYPE_INDEX_MAP, REFERENCES, REFERENCE, NUMBER, } from './types.js';
4
+ import { DEFAULT_MAP } from './defaultMap.js';
5
+ import { makeSeparateTextSort } from './makeSeparateTextSort.js';
6
+ import { makeSeparateSort } from './makeSeparateSort.js';
7
+ import { getPropLen, isSeparate, parseMinMaxStep } from './utils.js';
8
+ import { addEdges } from './addEdges.js';
9
+ import { createEmptyDef } from './createEmptyDef.js';
10
+ import { fillEmptyMain, isZeroes } from './fillEmptyMain.js';
11
+ import { defaultValidation, VALIDATION_MAP } from './validation.js';
12
+ export const DEFAULT_BLOCK_CAPACITY = 100_000;
13
+ export const updateTypeDefs = (schema) => {
14
+ const schemaTypesParsed = {};
15
+ const schemaTypesParsedById = {};
16
+ for (const field in schemaTypesParsed) {
17
+ if (field in schema.types) {
18
+ continue;
19
+ }
20
+ const id = schemaTypesParsed[field].id;
21
+ delete schemaTypesParsed[field];
22
+ delete schemaTypesParsedById[id];
23
+ }
24
+ for (const field in schema.types) {
25
+ const type = schema.types[field];
26
+ if (!type.id) {
27
+ throw new Error('NEED ID ON TYPE');
28
+ }
29
+ const def = createSchemaTypeDef(field, type, schemaTypesParsed, schema.locales ?? {
30
+ en: {},
31
+ });
32
+ def.blockCapacity = field === '_root' ? 2147483647 : DEFAULT_BLOCK_CAPACITY;
33
+ schemaTypesParsed[field] = def;
34
+ schemaTypesParsedById[type.id] = def;
35
+ }
36
+ return { schemaTypesParsed, schemaTypesParsedById };
37
+ };
38
+ export const createSchemaTypeDef = (typeName, type, parsed, locales, result = createEmptyDef(typeName, type, locales), path = [], top = true) => {
39
+ if (result.id == 0 && top) {
40
+ if ('id' in type) {
41
+ result.id = type.id;
42
+ }
43
+ else {
44
+ throw new Error(`Invalid schema type id ${result.type}`);
45
+ }
46
+ }
47
+ result.locales = locales;
48
+ result.localeSize = Object.keys(locales).length;
49
+ result.idUint8[0] = result.id & 255;
50
+ result.idUint8[1] = result.id >> 8;
51
+ const target = type.props;
52
+ for (const key in target) {
53
+ // Create prop def
54
+ const schemaProp = target[key];
55
+ const propPath = [...path, key];
56
+ const propType = getPropType(schemaProp);
57
+ if (propType === 'object') {
58
+ createSchemaTypeDef(typeName, schemaProp, parsed, locales, result, propPath, false);
59
+ }
60
+ else {
61
+ const len = getPropLen(schemaProp);
62
+ if (isPropType('string', schemaProp) ||
63
+ isPropType('alias', schemaProp) ||
64
+ isPropType('cardinality', schemaProp)) {
65
+ if (typeof schemaProp === 'object') {
66
+ if (!(schemaProp.maxBytes < 61) ||
67
+ !('max' in schemaProp && schemaProp.max < 31)) {
68
+ result.separateSortProps++;
69
+ }
70
+ }
71
+ else {
72
+ result.separateSortProps++;
73
+ }
74
+ }
75
+ else if (isPropType('text', schemaProp)) {
76
+ result.separateSortText++;
77
+ }
78
+ const isseparate = isSeparate(schemaProp, len);
79
+ const typeIndex = TYPE_INDEX_MAP[propType];
80
+ const prop = {
81
+ typeIndex,
82
+ __isPropDef: true,
83
+ separate: isseparate,
84
+ path: propPath,
85
+ start: 0,
86
+ validation: schemaProp.validation ??
87
+ VALIDATION_MAP[typeIndex] ??
88
+ defaultValidation,
89
+ len,
90
+ default: schemaProp.default ?? DEFAULT_MAP[typeIndex],
91
+ prop: isseparate ? ++result.cnt : 0,
92
+ };
93
+ if (schemaProp.max !== undefined) {
94
+ prop.max = parseMinMaxStep(schemaProp.max);
95
+ }
96
+ if (schemaProp.min !== undefined) {
97
+ prop.min = parseMinMaxStep(schemaProp.min);
98
+ }
99
+ if (schemaProp.step !== undefined) {
100
+ prop.step = parseMinMaxStep(schemaProp.step);
101
+ }
102
+ if (prop.typeIndex !== NUMBER && prop.step === undefined) {
103
+ prop.step = 1;
104
+ }
105
+ if (isPropType('enum', schemaProp)) {
106
+ prop.enum = Array.isArray(schemaProp) ? schemaProp : schemaProp.enum;
107
+ prop.reverseEnum = {};
108
+ for (let i = 0; i < prop.enum.length; i++) {
109
+ prop.reverseEnum[prop.enum[i]] = i;
110
+ }
111
+ }
112
+ else if (isPropType('references', schemaProp)) {
113
+ prop.inversePropName = schemaProp.items.prop;
114
+ prop.inverseTypeName = schemaProp.items.ref;
115
+ prop.dependent = schemaProp.items.dependent;
116
+ addEdges(prop, schemaProp.items);
117
+ }
118
+ else if (isPropType('reference', schemaProp)) {
119
+ prop.inversePropName = schemaProp.prop;
120
+ prop.inverseTypeName = schemaProp.ref;
121
+ prop.dependent = schemaProp.dependent;
122
+ addEdges(prop, schemaProp);
123
+ }
124
+ else if (typeof schemaProp === 'object') {
125
+ if (isPropType('string', schemaProp) ||
126
+ isPropType('text', schemaProp)) {
127
+ prop.compression =
128
+ 'compression' in schemaProp && schemaProp.compression === 'none'
129
+ ? 0
130
+ : 1;
131
+ }
132
+ else if (isPropType('timestamp', schemaProp) && 'on' in schemaProp) {
133
+ if (schemaProp.on[0] === 'c') {
134
+ result.createTs ??= [];
135
+ result.createTs.push(prop);
136
+ }
137
+ else if (schemaProp.on[0] === 'u') {
138
+ result.createTs ??= [];
139
+ result.createTs.push(prop);
140
+ result.updateTs ??= [];
141
+ result.updateTs.push(prop);
142
+ }
143
+ }
144
+ }
145
+ result.props[propPath.join('.')] = prop;
146
+ if (isseparate) {
147
+ result.separate.push(prop);
148
+ }
149
+ }
150
+ }
151
+ if (top) {
152
+ // Put top level together
153
+ const vals = Object.values(result.props);
154
+ vals.sort((a, b) => {
155
+ if (b.separate &&
156
+ (a.typeIndex === REFERENCES || a.typeIndex === REFERENCE)) {
157
+ return -1;
158
+ }
159
+ return a.prop - b.prop;
160
+ });
161
+ let lastProp = 0;
162
+ for (const p of vals) {
163
+ if (p.separate) {
164
+ p.prop = ++lastProp;
165
+ }
166
+ }
167
+ let len = 2;
168
+ for (const f of vals) {
169
+ if (f.separate) {
170
+ len += 2;
171
+ setByPath(result.tree, f.path, f);
172
+ }
173
+ else {
174
+ if (!result.mainLen) {
175
+ len += 2;
176
+ }
177
+ len += 1;
178
+ f.start = result.mainLen;
179
+ result.mainLen += f.len;
180
+ setByPath(result.tree, f.path, f);
181
+ }
182
+ }
183
+ result.mainEmpty = fillEmptyMain(vals, result.mainLen);
184
+ result.mainEmptyAllZeroes = isZeroes(result.mainEmpty);
185
+ if (result.separateSortText > 0) {
186
+ makeSeparateTextSort(result);
187
+ }
188
+ if (result.separateSortProps > 0) {
189
+ makeSeparateSort(result);
190
+ }
191
+ for (const p in result.props) {
192
+ const x = result.props[p];
193
+ if (!x.separate) {
194
+ result.main[x.start] = x;
195
+ }
196
+ else {
197
+ result.reverseProps[x.prop] = x;
198
+ }
199
+ }
200
+ }
201
+ return result;
202
+ };
203
+ //# sourceMappingURL=typeDef.js.map
@@ -0,0 +1,179 @@
1
+ import type { LangCode, SchemaLocales } from '../index.js';
2
+ import { Validation } from './validation.js';
3
+ export declare const NULL = 0;
4
+ export declare const TIMESTAMP = 1;
5
+ export declare const NUMBER = 4;
6
+ export declare const CARDINALITY = 5;
7
+ export declare const INT8 = 20;
8
+ export declare const UINT8 = 6;
9
+ export declare const INT16 = 21;
10
+ export declare const UINT16 = 22;
11
+ export declare const INT32 = 23;
12
+ export declare const UINT32 = 7;
13
+ export declare const BOOLEAN = 9;
14
+ export declare const ENUM = 10;
15
+ export declare const STRING = 11;
16
+ export declare const TEXT = 12;
17
+ export declare const REFERENCE = 13;
18
+ export declare const REFERENCES = 14;
19
+ export declare const WEAK_REFERENCE = 15;
20
+ export declare const WEAK_REFERENCES = 16;
21
+ export declare const MICRO_BUFFER = 17;
22
+ export declare const ALIAS = 18;
23
+ export declare const ALIASES = 19;
24
+ export declare const BINARY = 25;
25
+ export declare const ID = 26;
26
+ export declare const VECTOR = 27;
27
+ export declare const JSON = 28;
28
+ export declare const OBJECT = 29;
29
+ export declare const TYPE_INDEX_MAP: {
30
+ alias: number;
31
+ aliases: number;
32
+ microbuffer: number;
33
+ references: number;
34
+ reference: number;
35
+ timestamp: number;
36
+ boolean: number;
37
+ number: number;
38
+ string: number;
39
+ text: number;
40
+ uint16: number;
41
+ uint32: number;
42
+ int16: number;
43
+ int32: number;
44
+ uint8: number;
45
+ enum: number;
46
+ int8: number;
47
+ id: number;
48
+ binary: number;
49
+ vector: number;
50
+ cardinality: number;
51
+ json: number;
52
+ object: number;
53
+ };
54
+ export declare const enum numberTypes {
55
+ number = 4,
56
+ uint16 = 22,
57
+ uint32 = 7,
58
+ int16 = 21,
59
+ int32 = 23,
60
+ uint8 = 6,
61
+ int8 = 20,
62
+ cardinality = 5
63
+ }
64
+ export declare function isNumberType(type: TypeIndex): boolean;
65
+ export type InternalSchemaProp = keyof typeof TYPE_INDEX_MAP;
66
+ export type TypeIndex = (typeof TYPE_INDEX_MAP)[InternalSchemaProp];
67
+ export type PropDef = {
68
+ __isPropDef: true;
69
+ prop: number;
70
+ typeIndex: TypeIndex;
71
+ separate: boolean;
72
+ path: string[];
73
+ start: number;
74
+ len: number;
75
+ inverseTypeName?: string;
76
+ inversePropName?: string;
77
+ compression?: 0 | 1;
78
+ inverseTypeId?: number;
79
+ inversePropNumber?: number;
80
+ enum?: any[];
81
+ dependent?: boolean;
82
+ validation: Validation;
83
+ default: any;
84
+ edgeMainLen?: 0;
85
+ reverseEnum?: {
86
+ [key: string]: number;
87
+ };
88
+ edgesSeperateCnt?: number;
89
+ edges?: {
90
+ [key: string]: PropDefEdge;
91
+ };
92
+ reverseSeperateEdges?: {
93
+ [prop: string]: PropDefEdge;
94
+ };
95
+ reverseMainEdges?: {
96
+ [start: string]: PropDefEdge;
97
+ };
98
+ edgeMainEmpty?: Uint8Array;
99
+ __isEdge?: boolean;
100
+ max?: any;
101
+ min?: any;
102
+ step?: any;
103
+ };
104
+ export type PropDefEdge = Partial<PropDef> & {
105
+ __isPropDef: true;
106
+ typeIndex: TypeIndex;
107
+ len: number;
108
+ prop: number;
109
+ name: string;
110
+ edgesTotalLen?: number;
111
+ __isEdge: true;
112
+ };
113
+ export type PropDefAggregate = Partial<PropDef> & {
114
+ __isPropDef: true;
115
+ typeIndex: TypeIndex;
116
+ len: number;
117
+ prop: number;
118
+ name: string;
119
+ };
120
+ export type SchemaPropTree = {
121
+ [key: string]: SchemaPropTree | PropDef;
122
+ };
123
+ export type SchemaSortUndefinedHandler = {
124
+ size: number;
125
+ buffer: Uint8Array;
126
+ bufferTmp: Uint8Array;
127
+ props: PropDef[];
128
+ };
129
+ export type SchemaTypeDef = {
130
+ cnt: number;
131
+ checksum: number;
132
+ type: string;
133
+ lastId: number;
134
+ blockCapacity: number;
135
+ mainLen: number;
136
+ buf: Uint8Array;
137
+ propNames: Uint8Array;
138
+ props: {
139
+ [path: string]: PropDef;
140
+ };
141
+ reverseProps: {
142
+ [field: string]: PropDef;
143
+ };
144
+ id: number;
145
+ idUint8: Uint8Array;
146
+ separate: PropDef[];
147
+ main: {
148
+ [start: string]: PropDef;
149
+ };
150
+ mainEmpty: Uint8Array;
151
+ mainEmptyAllZeroes: boolean;
152
+ tree: SchemaPropTree;
153
+ separateSortProps: number;
154
+ separateSortText: number;
155
+ hasSeperateSort: boolean;
156
+ seperateSort: SchemaSortUndefinedHandler;
157
+ hasSeperateTextSort: boolean;
158
+ seperateTextSort: SchemaSortUndefinedHandler & {
159
+ noUndefined: Uint8Array;
160
+ localeStringToIndex: Map<string, Uint8Array>;
161
+ localeToIndex: Map<LangCode, number>;
162
+ };
163
+ createTs?: PropDef[];
164
+ updateTs?: PropDef[];
165
+ locales: Partial<SchemaLocales>;
166
+ localeSize: number;
167
+ };
168
+ export declare const SIZE_MAP: Record<InternalSchemaProp, number>;
169
+ export declare const REVERSE_SIZE_MAP: Record<TypeIndex, number>;
170
+ export declare const REVERSE_TYPE_INDEX_MAP: Record<TypeIndex, InternalSchemaProp>;
171
+ export declare const ID_FIELD_DEF: PropDef;
172
+ export declare const EMPTY_MICRO_BUFFER: PropDef;
173
+ export declare const getPropTypeName: (propType: TypeIndex) => InternalSchemaProp;
174
+ export declare const isPropDef: (prop: any) => prop is PropDef;
175
+ export type SchemaTypesParsed = {
176
+ [key: string]: SchemaTypeDef;
177
+ };
178
+ export type SchemaTypesParsedById = Record<number, SchemaTypeDef>;
179
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,132 @@
1
+ // WARN: The following type codes are used in js and zig but selva has its own typing.
2
+ export const NULL = 0;
3
+ export const TIMESTAMP = 1;
4
+ export const NUMBER = 4;
5
+ export const CARDINALITY = 5;
6
+ export const INT8 = 20;
7
+ export const UINT8 = 6;
8
+ export const INT16 = 21;
9
+ export const UINT16 = 22;
10
+ export const INT32 = 23;
11
+ export const UINT32 = 7;
12
+ export const BOOLEAN = 9;
13
+ export const ENUM = 10;
14
+ export const STRING = 11;
15
+ export const TEXT = 12;
16
+ export const REFERENCE = 13;
17
+ export const REFERENCES = 14;
18
+ export const WEAK_REFERENCE = 15;
19
+ export const WEAK_REFERENCES = 16;
20
+ export const MICRO_BUFFER = 17;
21
+ export const ALIAS = 18;
22
+ export const ALIASES = 19;
23
+ export const BINARY = 25;
24
+ export const ID = 26;
25
+ export const VECTOR = 27;
26
+ export const JSON = 28;
27
+ export const OBJECT = 29;
28
+ export const TYPE_INDEX_MAP = {
29
+ alias: ALIAS,
30
+ aliases: ALIASES,
31
+ microbuffer: MICRO_BUFFER,
32
+ references: REFERENCES,
33
+ reference: REFERENCE,
34
+ timestamp: TIMESTAMP,
35
+ boolean: BOOLEAN,
36
+ number: NUMBER,
37
+ string: STRING,
38
+ text: TEXT,
39
+ uint16: UINT16,
40
+ uint32: UINT32,
41
+ int16: INT16,
42
+ int32: INT32,
43
+ uint8: UINT8,
44
+ enum: ENUM,
45
+ int8: INT8,
46
+ id: NULL,
47
+ binary: BINARY,
48
+ vector: VECTOR,
49
+ cardinality: CARDINALITY,
50
+ json: JSON,
51
+ object: OBJECT,
52
+ };
53
+ const numberTypeValues = [
54
+ NUMBER,
55
+ UINT16,
56
+ UINT32,
57
+ INT16,
58
+ INT32,
59
+ UINT8,
60
+ INT8,
61
+ CARDINALITY,
62
+ ];
63
+ export function isNumberType(type) {
64
+ return numberTypeValues.includes(type);
65
+ }
66
+ export const SIZE_MAP = {
67
+ timestamp: 8, // 64bit
68
+ // double-precision 64-bit binary format IEEE 754 value
69
+ number: 8, // 64bit
70
+ int8: 1,
71
+ uint8: 1,
72
+ int16: 2,
73
+ uint16: 2,
74
+ int32: 4,
75
+ uint32: 4,
76
+ boolean: 1,
77
+ reference: 0, // separate
78
+ enum: 1, // enum
79
+ string: 0, // separate
80
+ text: 0, // separate
81
+ cardinality: 0, // separate
82
+ references: 0, // separate
83
+ microbuffer: 0, // separate
84
+ alias: 0,
85
+ aliases: 0,
86
+ id: 4,
87
+ binary: 0,
88
+ vector: 0, // separate
89
+ json: 0,
90
+ object: 0,
91
+ };
92
+ const reverseMap = {};
93
+ for (const k in TYPE_INDEX_MAP) {
94
+ reverseMap[TYPE_INDEX_MAP[k]] = k;
95
+ }
96
+ export const REVERSE_SIZE_MAP = {};
97
+ for (const k in SIZE_MAP) {
98
+ REVERSE_SIZE_MAP[TYPE_INDEX_MAP[k]] = SIZE_MAP[k];
99
+ }
100
+ export const REVERSE_TYPE_INDEX_MAP = reverseMap;
101
+ export const ID_FIELD_DEF = {
102
+ typeIndex: TYPE_INDEX_MAP['id'],
103
+ separate: true,
104
+ path: ['id'],
105
+ start: 0,
106
+ prop: 255,
107
+ default: 0,
108
+ len: 4,
109
+ validation: () => true,
110
+ __isPropDef: true,
111
+ };
112
+ export const EMPTY_MICRO_BUFFER = {
113
+ typeIndex: TYPE_INDEX_MAP['microbuffer'],
114
+ separate: true,
115
+ path: [''],
116
+ start: 0,
117
+ default: undefined,
118
+ prop: 0,
119
+ len: 1,
120
+ validation: () => true,
121
+ __isPropDef: true,
122
+ };
123
+ export const getPropTypeName = (propType) => {
124
+ return REVERSE_TYPE_INDEX_MAP[propType];
125
+ };
126
+ export const isPropDef = (prop) => {
127
+ if ('__isPropDef' in prop && prop.__isPropDef === true) {
128
+ return true;
129
+ }
130
+ return false;
131
+ };
132
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,8 @@
1
+ import { PropDef, PropDefEdge } from './types.js';
2
+ import { SchemaProp } from '../types.js';
3
+ export declare function isSeparate(schemaProp: SchemaProp, len: number): boolean;
4
+ export declare const propIsSigned: (prop: PropDef | PropDefEdge) => boolean;
5
+ export declare const propIsNumerical: (prop: PropDef | PropDefEdge) => boolean;
6
+ export declare function getPropLen(schemaProp: SchemaProp): any;
7
+ export declare const parseMinMaxStep: (val: any) => string | number;
8
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1,59 @@
1
+ import { INT16, INT32, INT8, UINT16, UINT32, UINT8, NUMBER, TIMESTAMP, SIZE_MAP, } from './types.js';
2
+ import { isPropType } from '../types.js';
3
+ import { getPropType } from '../parse/utils.js';
4
+ import { convertToTimestamp } from '@saulx/utils';
5
+ export function isSeparate(schemaProp, len) {
6
+ return len === 0 || isPropType('vector', schemaProp);
7
+ }
8
+ export const propIsSigned = (prop) => {
9
+ const t = prop.typeIndex;
10
+ if (t === INT16 || t === INT32 || t === INT8) {
11
+ return true;
12
+ }
13
+ return false;
14
+ };
15
+ export const propIsNumerical = (prop) => {
16
+ const t = prop.typeIndex;
17
+ if (t === INT16 ||
18
+ t === INT32 ||
19
+ t === INT8 ||
20
+ t === UINT8 ||
21
+ t === UINT16 ||
22
+ t === UINT32 ||
23
+ t === NUMBER ||
24
+ t === TIMESTAMP) {
25
+ return true;
26
+ }
27
+ return false;
28
+ };
29
+ export function getPropLen(schemaProp) {
30
+ let len = SIZE_MAP[getPropType(schemaProp)];
31
+ if (isPropType('string', schemaProp) ||
32
+ isPropType('alias', schemaProp) ||
33
+ isPropType('cardinality', schemaProp)) {
34
+ if (typeof schemaProp === 'object') {
35
+ if (schemaProp.maxBytes < 61) {
36
+ len = schemaProp.maxBytes + 1;
37
+ }
38
+ else if ('max' in schemaProp && schemaProp.max < 31) {
39
+ len = schemaProp.max * 2 + 1;
40
+ }
41
+ }
42
+ }
43
+ else if (isPropType('vector', schemaProp)) {
44
+ len = 4 * schemaProp.size;
45
+ }
46
+ return len;
47
+ }
48
+ export const parseMinMaxStep = (val) => {
49
+ if (typeof val === 'number') {
50
+ return val;
51
+ }
52
+ if (typeof val === 'string') {
53
+ if (!val.includes('now')) {
54
+ return convertToTimestamp(val);
55
+ }
56
+ return val;
57
+ }
58
+ };
59
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1,7 @@
1
+ import { TypeIndex, PropDef, PropDefEdge } from './types.js';
2
+ export type Validation = (payload: any, prop: PropDef | PropDefEdge) => boolean;
3
+ export declare const VALIDATION_MAP: Record<TypeIndex, Validation>;
4
+ export declare const defaultValidation: () => boolean;
5
+ export declare const isValidId: (id: number) => boolean;
6
+ export declare const isValidString: (v: any) => boolean;
7
+ //# sourceMappingURL=validation.d.ts.map