@based/db 0.0.15 → 0.0.17
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/lib/darwin_aarch64/include/selva/db.h +3 -0
- package/dist/lib/darwin_aarch64/include/selva/fields.h +1 -2
- package/dist/lib/darwin_aarch64/include/selva/history.h +16 -1
- package/dist/lib/darwin_aarch64/include/selva/hll.h +2 -1
- package/dist/lib/darwin_aarch64/include/selva/types.h +4 -0
- package/dist/lib/darwin_aarch64/libnode-v20.11.1.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v20.18.1.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.13.0.node +0 -0
- package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
- package/dist/lib/linux_aarch64/include/selva/db.h +3 -0
- package/dist/lib/linux_aarch64/include/selva/fields.h +1 -2
- package/dist/lib/linux_aarch64/include/selva/history.h +16 -1
- package/dist/lib/linux_aarch64/include/selva/hll.h +2 -1
- package/dist/lib/linux_aarch64/include/selva/types.h +4 -0
- package/dist/lib/linux_aarch64/libnode-v20.11.1.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v20.18.1.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v22.13.0.node +0 -0
- package/dist/lib/linux_aarch64/libselva.so +0 -0
- package/dist/lib/linux_x86_64/include/selva/db.h +3 -0
- package/dist/lib/linux_x86_64/include/selva/fields.h +1 -2
- package/dist/lib/linux_x86_64/include/selva/history.h +16 -1
- package/dist/lib/linux_x86_64/include/selva/hll.h +2 -1
- package/dist/lib/linux_x86_64/include/selva/types.h +4 -0
- package/dist/lib/linux_x86_64/libnode-v20.11.1.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v20.18.1.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v22.13.0.node +0 -0
- package/dist/lib/linux_x86_64/libselva.so +0 -0
- package/dist/src/client/bitWise.js +1 -0
- package/dist/src/client/crc32.js +0 -276
- package/dist/src/client/modify/ModifyRes.d.ts +4 -2
- package/dist/src/client/modify/ModifyRes.js +11 -6
- package/dist/src/client/modify/alias.js +2 -2
- package/dist/src/client/modify/cardinality.js +14 -10
- package/dist/src/client/modify/create.js +8 -9
- package/dist/src/client/modify/references/reference.js +14 -7
- package/dist/src/client/modify/references/references.js +10 -4
- package/dist/src/client/modify/string.js +2 -2
- package/dist/src/client/modify/text.js +1 -1
- package/dist/src/client/modify/types.d.ts +3 -1
- package/dist/src/client/modify/types.js +2 -0
- package/dist/src/client/modify/update.js +1 -1
- package/dist/src/client/operations.d.ts +2 -2
- package/dist/src/client/operations.js +19 -3
- package/dist/src/client/query/BasedDbQuery.d.ts +5 -4
- package/dist/src/client/query/BasedDbQuery.js +28 -13
- package/dist/src/client/query/BasedIterable.js +3 -10
- package/dist/src/client/query/display.d.ts +6 -0
- package/dist/src/client/query/display.js +63 -4
- package/dist/src/client/query/filter/FilterBranch.js +8 -3
- package/dist/src/client/query/filter/convertFilter.d.ts +4 -0
- package/dist/src/client/query/filter/convertFilter.js +56 -0
- package/dist/src/client/query/filter/createFixedFilterBuffer.js +9 -8
- package/dist/src/client/query/filter/createReferenceFilter.js +5 -4
- package/dist/src/client/query/filter/createVariableFilterBuffer.js +6 -10
- package/dist/src/client/query/filter/filter.d.ts +1 -2
- package/dist/src/client/query/filter/filter.js +5 -56
- package/dist/src/client/query/filter/primitiveFilter.d.ts +2 -2
- package/dist/src/client/query/filter/primitiveFilter.js +5 -1
- package/dist/src/client/query/filter/toBuffer.js +1 -6
- package/dist/src/client/query/filter/types.d.ts +2 -1
- package/dist/src/client/query/filter/types.js +23 -12
- package/dist/src/client/query/include/props.js +14 -6
- package/dist/src/client/query/include/utils.js +2 -2
- package/dist/src/client/query/include/walk.js +1 -7
- package/dist/src/client/query/queryDef.d.ts +1 -1
- package/dist/src/client/query/queryDef.js +4 -3
- package/dist/src/client/query/read/read.js +21 -32
- package/dist/src/client/query/read/types.d.ts +4 -0
- package/dist/src/client/query/read/types.js +5 -0
- package/dist/src/client/query/registerQuery.js +1 -0
- package/dist/src/client/query/search/index.js +12 -6
- package/dist/src/client/query/sort.js +7 -6
- package/dist/src/client/query/thresholds.d.ts +0 -1
- package/dist/src/client/query/thresholds.js +0 -8
- package/dist/src/client/query/toBuffer.js +0 -3
- package/dist/src/client/query/types.d.ts +2 -0
- package/dist/src/client/query/validation.d.ts +39 -1
- package/dist/src/client/query/validation.js +299 -93
- package/dist/src/client/xxHash64.d.ts +1 -1
- package/dist/src/client/xxHash64.js +7 -2
- package/dist/src/index.d.ts +6 -1
- package/dist/src/index.js +31 -1
- package/dist/src/native.d.ts +3 -1
- package/dist/src/native.js +8 -2
- package/dist/src/server/index.d.ts +8 -6
- package/dist/src/server/index.js +56 -30
- package/dist/src/server/migrate/index.js +10 -2
- package/dist/src/server/migrate/worker.js +1 -1
- package/dist/src/server/schema/typeDef.js +35 -25
- package/dist/src/server/schema/types.d.ts +10 -5
- package/dist/src/server/schema/types.js +1 -1
- package/dist/src/server/schema/utils.d.ts +1 -0
- package/dist/src/server/schema/utils.js +18 -5
- package/package.json +5 -3
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import picocolors from 'picocolors';
|
|
2
|
+
import { ALIAS, BINARY, BOOLEAN, REFERENCE, REFERENCES, REVERSE_TYPE_INDEX_MAP, STRING, TEXT, TIMESTAMP, VECTOR, } from '../../server/schema/types.js';
|
|
3
|
+
import { propIsNumerical } from '../../server/schema/utils.js';
|
|
4
|
+
import { EQUAL, HAS, isNumerical, LIKE, operatorReverseMap, VECTOR_FNS, } from './filter/types.js';
|
|
5
|
+
import { MAX_ID, MAX_ID_VALUE, MAX_IDS_PER_QUERY, MIN_ID_VALUE, } from './thresholds.js';
|
|
6
|
+
import { displayTarget, safeStringify } from './display.js';
|
|
7
|
+
import { langCodesMap } from '@based/schema';
|
|
3
8
|
export const ERR_TARGET_INVAL_TYPE = 1;
|
|
4
9
|
export const ERR_TARGET_INVAL_ALIAS = 2;
|
|
5
10
|
export const ERR_TARGET_EXCEED_MAX_IDS = 3;
|
|
@@ -13,26 +18,178 @@ export const ERR_FILTER_INVALID_VAL = 10;
|
|
|
13
18
|
export const ERR_FILTER_INVALID_OPTS = 11;
|
|
14
19
|
export const ERR_FILTER_INVALID_LANG = 12;
|
|
15
20
|
export const ERR_INCLUDE_INVALID_LANG = 13;
|
|
21
|
+
export const ERR_SORT_ENOENT = 14;
|
|
22
|
+
export const ERR_SORT_TYPE = 15;
|
|
23
|
+
export const ERR_SORT_ORDER = 16;
|
|
24
|
+
export const ERR_SORT_WRONG_TARGET = 17;
|
|
25
|
+
export const ERR_RANGE_INVALID_OFFSET = 18;
|
|
26
|
+
export const ERR_RANGE_INVALID_LIMIT = 19;
|
|
27
|
+
export const ERR_INVALID_LANG = 20;
|
|
28
|
+
export const ERR_SEARCH_ENOENT = 21;
|
|
29
|
+
export const ERR_SEARCH_TYPE = 22;
|
|
30
|
+
export const ERR_SEARCH_INCORRECT_VALUE = 23;
|
|
31
|
+
export const ERR_SORT_LANG = 24;
|
|
16
32
|
const messages = {
|
|
17
33
|
[ERR_TARGET_INVAL_TYPE]: (p) => `Type "${p}" does not exist`,
|
|
18
34
|
[ERR_TARGET_INVAL_ALIAS]: (p) => {
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
v = JSON.stringify(p).replace(/"/g, '');
|
|
22
|
-
}
|
|
23
|
-
catch (err) {
|
|
24
|
-
v = '';
|
|
25
|
-
}
|
|
26
|
-
return `Invalid alias prodived to query "${v}"`;
|
|
35
|
+
return `Invalid alias prodived to query\n ${picocolors.italic(safeStringify(p, 100))}`;
|
|
27
36
|
},
|
|
28
37
|
[ERR_TARGET_EXCEED_MAX_IDS]: (p) => `Exceeds max ids ${~~(p.length / 1e3)}k (max ${MAX_IDS_PER_QUERY / 1e3}k)`,
|
|
29
|
-
[ERR_TARGET_INVAL_IDS]: (p) => `Ids should be of type array or Uint32Array with valid ids`,
|
|
38
|
+
[ERR_TARGET_INVAL_IDS]: (p) => `Ids should be of type array or Uint32Array with valid ids \n ${picocolors.italic(safeStringify(p, 100))}`,
|
|
30
39
|
[ERR_TARGET_INVAL_ID]: (p) => `Invalid id should be a number larger then 0 "${p}"`,
|
|
31
40
|
[ERR_INCLUDE_ENOENT]: (p) => `Include: field does not exist "${p}"`,
|
|
32
41
|
[ERR_INCLUDE_INVALID_LANG]: (p) => `Include: invalid lang "${p}"`,
|
|
33
42
|
[ERR_FILTER_ENOENT]: (p) => `Filter: field does not exist "${p}"`,
|
|
34
43
|
[ERR_FILTER_INVALID_LANG]: (p) => `Filter: invalid lang "${p}"`,
|
|
35
44
|
[ERR_FILTER_OP_ENOENT]: (p) => `Filter: invalid operator "${p}"`,
|
|
45
|
+
[ERR_FILTER_OP_FIELD]: (p) => `Cannot use operator "${operatorReverseMap[p[1].operation]}" on field "${p[0]}"`,
|
|
46
|
+
[ERR_FILTER_INVALID_OPTS]: (p) => {
|
|
47
|
+
return `Filter: Invalid opts "${safeStringify(p)}"`;
|
|
48
|
+
},
|
|
49
|
+
[ERR_FILTER_INVALID_VAL]: (p) => {
|
|
50
|
+
return `Filter: Invalid value ${p[0]} ${operatorReverseMap[p[1].operation]} "${safeStringify(p[2])}"`;
|
|
51
|
+
},
|
|
52
|
+
[ERR_SORT_ENOENT]: (p) => `Sort: field does not exist "${p}"`,
|
|
53
|
+
[ERR_SORT_WRONG_TARGET]: (p) => `Sort: incorrect qeury target "${displayTarget(p)}"`,
|
|
54
|
+
[ERR_SORT_ORDER]: (p) => `Sort: incorrect order option "${safeStringify(p.order)}" passed to sort "${p.field}"`,
|
|
55
|
+
[ERR_SORT_TYPE]: (p) => `Sort: cannot sort on type "${REVERSE_TYPE_INDEX_MAP[p.typeIndex]}" on field "${p.path.join('.')}"`,
|
|
56
|
+
[ERR_RANGE_INVALID_OFFSET]: (p) => `Range: incorrect offset "${safeStringify(p)}"`,
|
|
57
|
+
[ERR_RANGE_INVALID_LIMIT]: (p) => `Range: incorrect limit "${safeStringify(p)}"`,
|
|
58
|
+
[ERR_INVALID_LANG]: (p) => `Invalid locale "${p}"`,
|
|
59
|
+
[ERR_SEARCH_ENOENT]: (p) => `Search: field does not exist "${p}"`,
|
|
60
|
+
[ERR_SEARCH_TYPE]: (p) => `Search: incorrect type "${p.path.join('.')}"`,
|
|
61
|
+
[ERR_SEARCH_INCORRECT_VALUE]: (p) => `Search: incorrect query on field "${safeStringify(p)}"`,
|
|
62
|
+
[ERR_SORT_LANG]: (p) => `Sort: invalid lang`,
|
|
63
|
+
};
|
|
64
|
+
export const searchIncorrecQueryValue = (def, payload) => {
|
|
65
|
+
def.errors.push({ code: ERR_SEARCH_INCORRECT_VALUE, payload });
|
|
66
|
+
};
|
|
67
|
+
export const searchIncorrectType = (def, payload) => {
|
|
68
|
+
def.errors.push({ code: ERR_SEARCH_TYPE, payload });
|
|
69
|
+
};
|
|
70
|
+
export const searchDoesNotExist = (def, field, isVector) => {
|
|
71
|
+
def.errors.push({ code: ERR_SEARCH_ENOENT, payload: field });
|
|
72
|
+
if (isVector) {
|
|
73
|
+
return ERROR_VECTOR;
|
|
74
|
+
}
|
|
75
|
+
return ERROR_STRING;
|
|
76
|
+
};
|
|
77
|
+
export const validateRange = (def, offset, limit) => {
|
|
78
|
+
var r = false;
|
|
79
|
+
if (typeof offset !== 'number' || offset > MAX_ID || offset < 0) {
|
|
80
|
+
def.errors.push({ code: ERR_RANGE_INVALID_OFFSET, payload: offset });
|
|
81
|
+
r = true;
|
|
82
|
+
}
|
|
83
|
+
if (typeof limit !== 'number' || limit > MAX_ID || limit < 1) {
|
|
84
|
+
def.errors.push({ code: ERR_RANGE_INVALID_LIMIT, payload: limit });
|
|
85
|
+
r = true;
|
|
86
|
+
}
|
|
87
|
+
return r;
|
|
88
|
+
};
|
|
89
|
+
export const isValidId = (id) => {
|
|
90
|
+
if (typeof id != 'number' || id < MIN_ID_VALUE || id > MAX_ID_VALUE) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
};
|
|
95
|
+
export const isValidString = (v) => {
|
|
96
|
+
const isVal = typeof v === 'string' ||
|
|
97
|
+
v instanceof Buffer ||
|
|
98
|
+
ArrayBuffer.isView(v);
|
|
99
|
+
return isVal;
|
|
100
|
+
};
|
|
101
|
+
export const validateVal = (def, f, validate) => {
|
|
102
|
+
if (def.skipValidation) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
const value = f[2];
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
for (const v of value) {
|
|
108
|
+
if (!validate(v)) {
|
|
109
|
+
def.errors.push({ code: ERR_FILTER_INVALID_VAL, payload: f });
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else if (!validate(value)) {
|
|
115
|
+
def.errors.push({
|
|
116
|
+
code: ERR_FILTER_INVALID_VAL,
|
|
117
|
+
payload: f,
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
};
|
|
123
|
+
export const validateFilter = (def, prop, f) => {
|
|
124
|
+
if (def.skipValidation) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
const t = prop.typeIndex;
|
|
128
|
+
const op = f[1].operation;
|
|
129
|
+
if (t === REFERENCES || t === REFERENCE) {
|
|
130
|
+
if (op == LIKE) {
|
|
131
|
+
def.errors.push({ code: ERR_FILTER_OP_FIELD, payload: f });
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
if (t === REFERENCE && op != EQUAL) {
|
|
135
|
+
def.errors.push({
|
|
136
|
+
code: ERR_FILTER_OP_FIELD,
|
|
137
|
+
payload: f,
|
|
138
|
+
});
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
if (validateVal(def, f, isValidId)) {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (t === VECTOR) {
|
|
146
|
+
if (isNumerical(op) || op === HAS) {
|
|
147
|
+
def.errors.push({ code: ERR_FILTER_OP_FIELD, payload: f });
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
if (op === LIKE) {
|
|
151
|
+
const opts = f[1].opts;
|
|
152
|
+
if ((opts.fn && !VECTOR_FNS.includes(opts.fn)) ||
|
|
153
|
+
(opts.score != undefined && typeof opts.score !== 'number')) {
|
|
154
|
+
def.errors.push({ code: ERR_FILTER_INVALID_OPTS, payload: f });
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
if (validateVal(def, f, (v) => ArrayBuffer.isView(v) || v instanceof ArrayBuffer)) {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else if (t === TEXT || t === STRING || t === BINARY) {
|
|
163
|
+
if (isNumerical(op)) {
|
|
164
|
+
def.errors.push({ code: ERR_FILTER_OP_FIELD, payload: f });
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
if (op === LIKE) {
|
|
168
|
+
const opts = f[1].opts;
|
|
169
|
+
if (opts.score &&
|
|
170
|
+
(typeof opts.score !== 'number' || opts.score < 0 || opts.score > 255)) {
|
|
171
|
+
def.errors.push({ code: ERR_FILTER_INVALID_OPTS, payload: f });
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (validateVal(def, f, isValidString)) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (propIsNumerical(prop)) {
|
|
180
|
+
if (op !== EQUAL && !isNumerical(op)) {
|
|
181
|
+
def.errors.push({ code: ERR_FILTER_OP_FIELD, payload: f });
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
if (validateVal(def, f, (v) => t == TIMESTAMP || typeof v === 'number')) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else if (t === BOOLEAN && op !== EQUAL) {
|
|
189
|
+
def.errors.push({ code: ERR_FILTER_OP_FIELD, payload: f });
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return false;
|
|
36
193
|
};
|
|
37
194
|
export const validateType = (db, def, type) => {
|
|
38
195
|
const r = db.schemaTypesParsed[type];
|
|
@@ -76,6 +233,81 @@ export const includeLangDoesNotExist = (def, field) => {
|
|
|
76
233
|
payload: field,
|
|
77
234
|
});
|
|
78
235
|
};
|
|
236
|
+
export const validateLocale = (def, lang) => {
|
|
237
|
+
const schema = def.schema;
|
|
238
|
+
if (!(lang in schema.locales)) {
|
|
239
|
+
def.errors.push({
|
|
240
|
+
code: ERR_INVALID_LANG,
|
|
241
|
+
payload: lang,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
export const validateSort = (def, field, orderInput) => {
|
|
246
|
+
let propDef = def.props[field];
|
|
247
|
+
if (orderInput && orderInput !== 'asc' && orderInput !== 'desc') {
|
|
248
|
+
def.errors.push({
|
|
249
|
+
code: ERR_SORT_ORDER,
|
|
250
|
+
payload: { order: orderInput, field },
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const order = orderInput === 'asc' || orderInput === undefined ? 0 : 1;
|
|
254
|
+
// IF ! FIX
|
|
255
|
+
let lang = 0;
|
|
256
|
+
if (!propDef) {
|
|
257
|
+
let isText = false;
|
|
258
|
+
if (field.includes('.')) {
|
|
259
|
+
const path = field.split('.');
|
|
260
|
+
const x = path.slice(0, -1).join('.');
|
|
261
|
+
propDef = def.props[x];
|
|
262
|
+
if (propDef && propDef.typeIndex === TEXT) {
|
|
263
|
+
const k = path[path.length - 1];
|
|
264
|
+
lang = langCodesMap.get(k);
|
|
265
|
+
isText = true;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (!isText) {
|
|
269
|
+
def.errors.push({
|
|
270
|
+
code: ERR_SORT_ENOENT,
|
|
271
|
+
payload: field,
|
|
272
|
+
});
|
|
273
|
+
return {
|
|
274
|
+
prop: EMPTY_ALIAS_PROP_DEF,
|
|
275
|
+
order,
|
|
276
|
+
lang: def.lang,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const type = propDef.typeIndex;
|
|
281
|
+
if (type === REFERENCES || type === REFERENCE) {
|
|
282
|
+
def.errors.push({
|
|
283
|
+
code: ERR_SORT_TYPE,
|
|
284
|
+
payload: propDef,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
else if (type === TEXT) {
|
|
288
|
+
if (lang === 0) {
|
|
289
|
+
lang = def.lang ?? 0;
|
|
290
|
+
if (lang === 0) {
|
|
291
|
+
def.errors.push({
|
|
292
|
+
code: ERR_SORT_LANG,
|
|
293
|
+
payload: propDef,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
// add propDef LANG
|
|
299
|
+
if ('id' in def.target || 'alias' in def.target) {
|
|
300
|
+
def.errors.push({
|
|
301
|
+
code: ERR_SORT_WRONG_TARGET,
|
|
302
|
+
payload: def,
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
prop: propDef,
|
|
307
|
+
order,
|
|
308
|
+
lang,
|
|
309
|
+
};
|
|
310
|
+
};
|
|
79
311
|
export const validateAlias = (alias, path, def) => {
|
|
80
312
|
const schema = def.schema;
|
|
81
313
|
for (const k in alias) {
|
|
@@ -100,7 +332,10 @@ export const validateAlias = (alias, path, def) => {
|
|
|
100
332
|
return { value: '', def: EMPTY_ALIAS_PROP_DEF };
|
|
101
333
|
};
|
|
102
334
|
export const validateId = (def, id) => {
|
|
103
|
-
if (
|
|
335
|
+
if (def.skipValidation) {
|
|
336
|
+
return id;
|
|
337
|
+
}
|
|
338
|
+
if (!isValidId(id)) {
|
|
104
339
|
def.errors.push({
|
|
105
340
|
code: ERR_TARGET_INVAL_ID,
|
|
106
341
|
payload: id,
|
|
@@ -110,17 +345,18 @@ export const validateId = (def, id) => {
|
|
|
110
345
|
return id;
|
|
111
346
|
};
|
|
112
347
|
export const validateIds = (def, ids) => {
|
|
348
|
+
const origIds = ids;
|
|
113
349
|
if (!Array.isArray(ids) && !(ids instanceof Uint32Array)) {
|
|
114
350
|
def.errors.push({
|
|
115
351
|
code: ERR_TARGET_INVAL_IDS,
|
|
116
|
-
payload:
|
|
352
|
+
payload: origIds,
|
|
117
353
|
});
|
|
118
354
|
return new Uint32Array([]);
|
|
119
355
|
}
|
|
120
356
|
if (ids.length > MAX_IDS_PER_QUERY) {
|
|
121
357
|
def.errors.push({
|
|
122
358
|
code: ERR_TARGET_EXCEED_MAX_IDS,
|
|
123
|
-
payload:
|
|
359
|
+
payload: origIds,
|
|
124
360
|
});
|
|
125
361
|
return new Uint32Array([]);
|
|
126
362
|
}
|
|
@@ -132,17 +368,20 @@ export const validateIds = (def, ids) => {
|
|
|
132
368
|
catch (err) {
|
|
133
369
|
def.errors.push({
|
|
134
370
|
code: ERR_TARGET_INVAL_IDS,
|
|
135
|
-
payload:
|
|
371
|
+
payload: origIds,
|
|
136
372
|
});
|
|
137
373
|
return new Uint32Array([]);
|
|
138
374
|
}
|
|
139
375
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
376
|
+
if (def.skipValidation) {
|
|
377
|
+
return ids;
|
|
378
|
+
}
|
|
379
|
+
for (let i = 0; i < ids.length; i++) {
|
|
380
|
+
const id = ids[i];
|
|
381
|
+
if (typeof id !== 'number' || id == 0 || id > MAX_ID) {
|
|
143
382
|
def.errors.push({
|
|
144
383
|
code: ERR_TARGET_INVAL_IDS,
|
|
145
|
-
payload:
|
|
384
|
+
payload: origIds,
|
|
146
385
|
});
|
|
147
386
|
return new Uint32Array([]);
|
|
148
387
|
}
|
|
@@ -151,12 +390,17 @@ export const validateIds = (def, ids) => {
|
|
|
151
390
|
};
|
|
152
391
|
export const handleErrors = (def) => {
|
|
153
392
|
if (def.errors.length) {
|
|
154
|
-
let name = `
|
|
393
|
+
let name = picocolors.red(`QueryError[${displayTarget(def)}]\n`);
|
|
155
394
|
for (const err of def.errors) {
|
|
156
|
-
|
|
395
|
+
try {
|
|
396
|
+
name += ` ${messages[err.code](err.payload)}\n`;
|
|
397
|
+
}
|
|
398
|
+
catch (e) {
|
|
399
|
+
name += ` Cannot parse error:${err.code}\n`;
|
|
400
|
+
}
|
|
157
401
|
}
|
|
158
|
-
const err = new Error(
|
|
159
|
-
err.stack =
|
|
402
|
+
const err = new Error(`Query\n`);
|
|
403
|
+
err.stack = name;
|
|
160
404
|
throw err;
|
|
161
405
|
}
|
|
162
406
|
};
|
|
@@ -169,6 +413,24 @@ export const EMPTY_ALIAS_PROP_DEF = {
|
|
|
169
413
|
start: 0,
|
|
170
414
|
path: ['ERROR_ALIAS'],
|
|
171
415
|
};
|
|
416
|
+
export const ERROR_STRING = {
|
|
417
|
+
prop: 1,
|
|
418
|
+
typeIndex: STRING,
|
|
419
|
+
__isPropDef: true,
|
|
420
|
+
separate: true,
|
|
421
|
+
len: 0,
|
|
422
|
+
start: 0,
|
|
423
|
+
path: ['ERROR_STRING'],
|
|
424
|
+
};
|
|
425
|
+
export const ERROR_VECTOR = {
|
|
426
|
+
prop: 1,
|
|
427
|
+
typeIndex: VECTOR,
|
|
428
|
+
__isPropDef: true,
|
|
429
|
+
separate: true,
|
|
430
|
+
len: 0,
|
|
431
|
+
start: 0,
|
|
432
|
+
path: ['ERROR_VECTOR'],
|
|
433
|
+
};
|
|
172
434
|
export const EMPTY_SCHEMA_DEF = {
|
|
173
435
|
type: '_error',
|
|
174
436
|
cnt: 0,
|
|
@@ -187,75 +449,19 @@ export const EMPTY_SCHEMA_DEF = {
|
|
|
187
449
|
main: {},
|
|
188
450
|
separate: [],
|
|
189
451
|
tree: {},
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
452
|
+
hasSeperateSort: false,
|
|
453
|
+
seperateSort: {
|
|
454
|
+
size: 0,
|
|
455
|
+
buffer: Buffer.from([]),
|
|
456
|
+
bufferTmp: Buffer.from([]),
|
|
457
|
+
props: [],
|
|
458
|
+
},
|
|
459
|
+
hasSeperateTextSort: false,
|
|
460
|
+
seperateTextSort: {
|
|
461
|
+
size: 0,
|
|
462
|
+
buffer: Buffer.from([]),
|
|
463
|
+
bufferTmp: Buffer.from([]),
|
|
464
|
+
props: [],
|
|
465
|
+
},
|
|
195
466
|
};
|
|
196
|
-
// import { ALIAS, PropDef, PropDefEdge } from '../../server/schema/types.js'
|
|
197
|
-
// import {
|
|
198
|
-
// MAX_IDS_PER_QUERY,
|
|
199
|
-
// MIN_ID_VALUE,
|
|
200
|
-
// MAX_ID_VALUE,
|
|
201
|
-
// MAX_BUFFER_SIZE,
|
|
202
|
-
// } from './thresholds.js'
|
|
203
|
-
// import { QueryByAliasObj, QueryDef } from './types.js'
|
|
204
|
-
// import { DbClient } from '../index.js'
|
|
205
|
-
// export const isValidId = (id: number): void => {
|
|
206
|
-
// if (typeof id != 'number') {
|
|
207
|
-
// throw new Error('Id has to be a number')
|
|
208
|
-
// } else if (id < MIN_ID_VALUE || id > MAX_ID_VALUE) {
|
|
209
|
-
// throw new Error(
|
|
210
|
-
// `Invalid Id: The Id should range between ${MIN_ID_VALUE} and ${MAX_ID_VALUE}.)`,
|
|
211
|
-
// )
|
|
212
|
-
// }
|
|
213
|
-
// }
|
|
214
|
-
// export const isValidType = (
|
|
215
|
-
// type: string,
|
|
216
|
-
// schema: DbClient['schemaTypesParsed'],
|
|
217
|
-
// ): void => {
|
|
218
|
-
// if (!schema[type]) {
|
|
219
|
-
// throw new Error(`Incorrect type provided to query "${type}"`)
|
|
220
|
-
// }
|
|
221
|
-
// }
|
|
222
|
-
// export const isValidAlias = (def: QueryDef, id: QueryByAliasObj) => {
|
|
223
|
-
// for (const key in id) {
|
|
224
|
-
// const prop = def.schema.props[key]
|
|
225
|
-
// if (!prop || prop.typeIndex !== ALIAS) {
|
|
226
|
-
// throw new Error(`Incorrect alias provided to query "${key}"`)
|
|
227
|
-
// }
|
|
228
|
-
// }
|
|
229
|
-
// }
|
|
230
|
-
// export const checkMaxIdsPerQuery = (
|
|
231
|
-
// ids: (number | QueryByAliasObj)[],
|
|
232
|
-
// ): void => {
|
|
233
|
-
// if (ids.length > MAX_IDS_PER_QUERY) {
|
|
234
|
-
// throw new Error(`The number of IDs cannot exceed ${MAX_IDS_PER_QUERY}.`)
|
|
235
|
-
// }
|
|
236
|
-
// }
|
|
237
|
-
// export const checkMaxBufferSize = (buf: Buffer): void => {
|
|
238
|
-
// if (buf.byteLength > MAX_BUFFER_SIZE) {
|
|
239
|
-
// throw new Error(
|
|
240
|
-
// `The buffer size exceeds the maximum threshold of ${MAX_BUFFER_SIZE} bytes.` +
|
|
241
|
-
// `Crrent size is ${buf.byteLength} bytes.`,
|
|
242
|
-
// )
|
|
243
|
-
// }
|
|
244
|
-
// }
|
|
245
|
-
// export const checkTotalBufferSize = (bufers: Buffer[]): void => {
|
|
246
|
-
// let totalSize = 0
|
|
247
|
-
// for (const buffer of bufers) {
|
|
248
|
-
// totalSize += buffer.byteLength
|
|
249
|
-
// if (totalSize > MAX_BUFFER_SIZE) {
|
|
250
|
-
// throw new Error(
|
|
251
|
-
// `The total buffer size exceeds the maximum threshold of ${MAX_BUFFER_SIZE} bytes.` +
|
|
252
|
-
// `Crrent size is ${totalSize} bytes.`,
|
|
253
|
-
// )
|
|
254
|
-
// }
|
|
255
|
-
// }
|
|
256
|
-
// }
|
|
257
|
-
// // ------------------------------
|
|
258
|
-
// export const includeDoesNotExist = (def: QueryDef, field: string) => {
|
|
259
|
-
// throw new Error(`Incorrect include field provided to query "${field}")`)
|
|
260
|
-
// }
|
|
261
467
|
//# sourceMappingURL=validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const xxHash64: (buf: Buffer) =>
|
|
1
|
+
export declare const xxHash64: (buf: Buffer, target?: Buffer, index?: number) => Buffer;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import native from '../native.js';
|
|
2
|
-
export const xxHash64 = (buf) => {
|
|
3
|
-
|
|
2
|
+
export const xxHash64 = (buf, target, index) => {
|
|
3
|
+
if (!target) {
|
|
4
|
+
target = Buffer.allocUnsafe(8);
|
|
5
|
+
index = 0;
|
|
6
|
+
}
|
|
7
|
+
native.xxHash64(buf, target, index);
|
|
8
|
+
return target;
|
|
4
9
|
};
|
|
5
10
|
//# sourceMappingURL=xxHash64.js.map
|
package/dist/src/index.d.ts
CHANGED
|
@@ -7,14 +7,18 @@ export * from './client/modify/modify.js';
|
|
|
7
7
|
export { compress, decompress };
|
|
8
8
|
export { ModifyCtx };
|
|
9
9
|
export { DbClient, DbServer };
|
|
10
|
+
export { xxHash64 } from './client/xxHash64.js';
|
|
11
|
+
export { crc32 } from './client/crc32.js';
|
|
10
12
|
export declare class BasedDb {
|
|
13
|
+
#private;
|
|
11
14
|
client: DbClient;
|
|
12
15
|
server: DbServer;
|
|
13
16
|
fileSystemPath: string;
|
|
14
17
|
maxModifySize: number;
|
|
15
|
-
constructor(
|
|
18
|
+
constructor(opts: {
|
|
16
19
|
path: string;
|
|
17
20
|
maxModifySize?: number;
|
|
21
|
+
debug?: boolean;
|
|
18
22
|
});
|
|
19
23
|
create: DbClient['create'];
|
|
20
24
|
copy: DbClient['copy'];
|
|
@@ -31,4 +35,5 @@ export declare class BasedDb {
|
|
|
31
35
|
save: DbServer['save'];
|
|
32
36
|
migrateSchema: DbServer['migrateSchema'];
|
|
33
37
|
destroy(): Promise<void>;
|
|
38
|
+
wipe(): Promise<void>;
|
|
34
39
|
}
|
package/dist/src/index.js
CHANGED
|
@@ -2,17 +2,38 @@ import { compress, decompress } from './client/string.js';
|
|
|
2
2
|
import { ModifyCtx } from './client/operations.js';
|
|
3
3
|
import { DbServer } from './server/index.js';
|
|
4
4
|
import { DbClient } from './client/index.js';
|
|
5
|
+
import picocolors from 'picocolors';
|
|
5
6
|
export * from './server/schema/typeDef.js';
|
|
6
7
|
export * from './client/modify/modify.js';
|
|
7
8
|
export { compress, decompress };
|
|
8
9
|
export { ModifyCtx }; // TODO move this somewhere
|
|
9
10
|
export { DbClient, DbServer };
|
|
11
|
+
export { xxHash64 } from './client/xxHash64.js';
|
|
12
|
+
export { crc32 } from './client/crc32.js';
|
|
10
13
|
export class BasedDb {
|
|
11
14
|
client;
|
|
12
15
|
server;
|
|
13
16
|
fileSystemPath;
|
|
14
17
|
maxModifySize;
|
|
15
|
-
constructor(
|
|
18
|
+
constructor(opts) {
|
|
19
|
+
this.#init(opts);
|
|
20
|
+
if (opts.debug) {
|
|
21
|
+
for (const key in this) {
|
|
22
|
+
const fn = this[key];
|
|
23
|
+
if (typeof fn === 'function') {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
this[key] = function () {
|
|
26
|
+
const str = [`[${key}]`, ...arguments].join(' ');
|
|
27
|
+
console.info(picocolors.dim(str));
|
|
28
|
+
return fn.apply(this, arguments);
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
#init({ path, maxModifySize }) {
|
|
35
|
+
this.fileSystemPath = path;
|
|
36
|
+
this.maxModifySize = maxModifySize;
|
|
16
37
|
const server = new DbServer({
|
|
17
38
|
path,
|
|
18
39
|
maxModifySize,
|
|
@@ -91,5 +112,14 @@ export class BasedDb {
|
|
|
91
112
|
this.client.destroy();
|
|
92
113
|
return this.server.destroy();
|
|
93
114
|
}
|
|
115
|
+
async wipe() {
|
|
116
|
+
const opts = {
|
|
117
|
+
maxModifySize: this.maxModifySize,
|
|
118
|
+
path: this.fileSystemPath,
|
|
119
|
+
};
|
|
120
|
+
await this.destroy();
|
|
121
|
+
this.#init(opts);
|
|
122
|
+
await this.start({ clean: true });
|
|
123
|
+
}
|
|
94
124
|
}
|
|
95
125
|
//# sourceMappingURL=index.js.map
|
package/dist/src/native.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
declare const _default: {
|
|
2
|
+
historyAppend(history: any, typeId: number, nodeId: number): any;
|
|
3
|
+
historyCreate(pathname: string, mainLen: number): any;
|
|
2
4
|
workerCtxInit: () => void;
|
|
3
5
|
markMerkleBlock: (buf: Buffer) => any;
|
|
4
6
|
externalFromInt(address: BigInt): any;
|
|
@@ -24,6 +26,6 @@ declare const _default: {
|
|
|
24
26
|
crc32: (buf: Buffer) => any;
|
|
25
27
|
createSortIndex: (buf: Buffer, dbCtx: any) => any;
|
|
26
28
|
destroySortIndex: (buf: Buffer, dbCtx: any) => any;
|
|
27
|
-
xxHash64: (buf: Buffer) => any;
|
|
29
|
+
xxHash64: (buf: Buffer, target: Buffer, index: number) => any;
|
|
28
30
|
};
|
|
29
31
|
export default _default;
|
package/dist/src/native.js
CHANGED
|
@@ -3,6 +3,12 @@ import db from '../../basedDbNative.cjs';
|
|
|
3
3
|
var compressor = null;
|
|
4
4
|
var decompressor = null;
|
|
5
5
|
export default {
|
|
6
|
+
historyAppend(history, typeId, nodeId) {
|
|
7
|
+
return db.historyCreate(history, typeId, nodeId);
|
|
8
|
+
},
|
|
9
|
+
historyCreate(pathname, mainLen) {
|
|
10
|
+
return db.historyCreate(Buffer.from(pathname), mainLen + 16 - (mainLen % 16));
|
|
11
|
+
},
|
|
6
12
|
workerCtxInit: () => {
|
|
7
13
|
return db.workerCtxInit();
|
|
8
14
|
},
|
|
@@ -93,8 +99,8 @@ export default {
|
|
|
93
99
|
destroySortIndex: (buf, dbCtx) => {
|
|
94
100
|
return db.destroySortIndex(dbCtx, buf);
|
|
95
101
|
},
|
|
96
|
-
xxHash64: (buf) => {
|
|
97
|
-
return db.xxHash64(buf);
|
|
102
|
+
xxHash64: (buf, target, index) => {
|
|
103
|
+
return db.xxHash64(buf, target, index);
|
|
98
104
|
},
|
|
99
105
|
};
|
|
100
106
|
//# sourceMappingURL=native.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StrictSchema } from '@based/schema';
|
|
1
|
+
import { LangName, StrictSchema } from '@based/schema';
|
|
2
2
|
import { SchemaTypeDef } from './schema/types.js';
|
|
3
3
|
import { createTree } from './csmt/index.js';
|
|
4
4
|
import { Worker, MessagePort } from 'node:worker_threads';
|
|
@@ -67,19 +67,21 @@ export declare class DbServer {
|
|
|
67
67
|
sortIndexes: {
|
|
68
68
|
[type: number]: {
|
|
69
69
|
[field: number]: {
|
|
70
|
-
[start: number]:
|
|
70
|
+
[start: number]: {
|
|
71
|
+
[lang: number]: SortIndex;
|
|
72
|
+
};
|
|
71
73
|
};
|
|
72
74
|
};
|
|
73
75
|
};
|
|
74
76
|
cleanupTimer: NodeJS.Timeout;
|
|
75
77
|
cleanup(): void;
|
|
76
|
-
createSortIndex(type: string, field: string): SortIndex;
|
|
77
|
-
destroySortIndex(type: string, field: string): any;
|
|
78
|
-
getSortIndex(typeId: number, field: number, start: number): SortIndex;
|
|
78
|
+
createSortIndex(type: string, field: string, lang?: LangName): SortIndex;
|
|
79
|
+
destroySortIndex(type: string, field: string, lang?: LangName): any;
|
|
80
|
+
getSortIndex(typeId: number, field: number, start: number, lang: number): SortIndex;
|
|
79
81
|
migrateSchema(schema: StrictSchema, transform?: Record<string, (node: Record<string, any>) => Record<string, any> | [string, Record<string, any>]>): Promise<StrictSchema & {
|
|
80
82
|
lastId: number;
|
|
81
83
|
}>;
|
|
82
|
-
createSortIndexBuffer(typeId: number, field: number, start: number): SortIndex;
|
|
84
|
+
createSortIndexBuffer(typeId: number, field: number, start: number, lang: number): SortIndex;
|
|
83
85
|
updateMerkleTree(): void;
|
|
84
86
|
putSchema(strictSchema: StrictSchema, fromStart?: boolean, transformFns?: TransformFns): (StrictSchema & {
|
|
85
87
|
lastId: number;
|