@based/db 0.0.10 → 0.0.11
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/fields.h +8 -13
- 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/libnode-v22.8.0.node +0 -0
- package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
- package/dist/lib/darwin_aarch64/libxxhash.0.8.2.dylib +0 -0
- package/dist/lib/linux_aarch64/include/selva/fields.h +8 -13
- 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/fields.h +8 -13
- 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/index.d.ts +1 -1
- package/dist/src/client/index.js +3 -0
- package/dist/src/client/modify/cardinality.d.ts +1 -1
- package/dist/src/client/modify/cardinality.js +22 -30
- package/dist/src/client/query/BasedDbQuery.d.ts +2 -2
- package/dist/src/client/query/BasedDbQuery.js +18 -29
- package/dist/src/client/query/filter/filter.js +0 -4
- package/dist/src/client/query/include/walk.js +7 -3
- package/dist/src/client/query/queryDef.js +12 -7
- package/dist/src/client/query/registerQuery.js +2 -17
- package/dist/src/client/query/subscription/index.js +9 -3
- package/dist/src/client/query/thresholds.d.ts +3 -2
- package/dist/src/client/query/thresholds.js +3 -2
- package/dist/src/client/query/toBuffer.js +9 -0
- package/dist/src/client/query/types.d.ts +3 -1
- package/dist/src/client/query/types.js +3 -0
- package/dist/src/client/query/validation.d.ts +29 -16
- package/dist/src/client/query/validation.js +169 -59
- package/dist/src/server/csmt/tree.js +0 -1
- package/dist/src/server/index.d.ts +3 -1
- package/dist/src/server/index.js +3 -1
- package/dist/src/server/save.d.ts +1 -1
- package/dist/src/server/save.js +8 -2
- package/dist/src/server/start.js +7 -0
- package/package.json +2 -1
- package/dist/lib/darwin_aarch64/libxxhash.0.dylib +0 -0
- package/dist/lib/darwin_aarch64/libxxhash.dylib +0 -0
- package/dist/lib/linux_aarch64/libxxhash.so +0 -0
- package/dist/lib/linux_aarch64/libxxhash.so.0 +0 -0
- package/dist/lib/linux_x86_64/libxxhash.so +0 -0
- package/dist/lib/linux_x86_64/libxxhash.so.0 +0 -0
|
@@ -119,17 +119,6 @@ int selva_fields_set(
|
|
|
119
119
|
const struct SelvaFieldSchema *fs,
|
|
120
120
|
const void *value, size_t len);
|
|
121
121
|
|
|
122
|
-
/**
|
|
123
|
-
* Set field value with CRC.
|
|
124
|
-
*/
|
|
125
|
-
SELVA_EXPORT
|
|
126
|
-
int selva_fields_set_wcrc(
|
|
127
|
-
struct SelvaDb *db,
|
|
128
|
-
struct SelvaNode *node,
|
|
129
|
-
const struct SelvaFieldSchema *fs,
|
|
130
|
-
const void *value, size_t len,
|
|
131
|
-
uint32_t crc);
|
|
132
|
-
|
|
133
122
|
SELVA_EXPORT
|
|
134
123
|
int selva_fields_get_mutable_string(
|
|
135
124
|
struct SelvaNode *node,
|
|
@@ -160,6 +149,7 @@ int selva_fields_reference_set(
|
|
|
160
149
|
|
|
161
150
|
/**
|
|
162
151
|
* @param index 0 = first; -1 = last.
|
|
152
|
+
* @param reorder move the existing ref to `index` instead of returning EEXIST.
|
|
163
153
|
*/
|
|
164
154
|
SELVA_EXPORT
|
|
165
155
|
int selva_fields_references_insert(
|
|
@@ -243,7 +233,12 @@ int selva_fields_get_reference_meta_mutable_string(
|
|
|
243
233
|
* +------+------+--------+-----+
|
|
244
234
|
*/
|
|
245
235
|
SELVA_EXPORT
|
|
246
|
-
int selva_fields_set_string(
|
|
236
|
+
int selva_fields_set_string(
|
|
237
|
+
struct SelvaNode *node,
|
|
238
|
+
const struct SelvaFieldSchema *fs,
|
|
239
|
+
struct SelvaFieldInfo *nfo,
|
|
240
|
+
const char *str,
|
|
241
|
+
size_t len);
|
|
247
242
|
|
|
248
243
|
/**
|
|
249
244
|
* Set text field translation.
|
|
@@ -326,7 +321,7 @@ SELVA_EXPORT
|
|
|
326
321
|
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs);
|
|
327
322
|
|
|
328
323
|
/**
|
|
329
|
-
* Init fields of a node.
|
|
324
|
+
* Init the fields struct of a node or edge.
|
|
330
325
|
*/
|
|
331
326
|
SELVA_EXPORT
|
|
332
327
|
void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaFields *fields);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -119,17 +119,6 @@ int selva_fields_set(
|
|
|
119
119
|
const struct SelvaFieldSchema *fs,
|
|
120
120
|
const void *value, size_t len);
|
|
121
121
|
|
|
122
|
-
/**
|
|
123
|
-
* Set field value with CRC.
|
|
124
|
-
*/
|
|
125
|
-
SELVA_EXPORT
|
|
126
|
-
int selva_fields_set_wcrc(
|
|
127
|
-
struct SelvaDb *db,
|
|
128
|
-
struct SelvaNode *node,
|
|
129
|
-
const struct SelvaFieldSchema *fs,
|
|
130
|
-
const void *value, size_t len,
|
|
131
|
-
uint32_t crc);
|
|
132
|
-
|
|
133
122
|
SELVA_EXPORT
|
|
134
123
|
int selva_fields_get_mutable_string(
|
|
135
124
|
struct SelvaNode *node,
|
|
@@ -160,6 +149,7 @@ int selva_fields_reference_set(
|
|
|
160
149
|
|
|
161
150
|
/**
|
|
162
151
|
* @param index 0 = first; -1 = last.
|
|
152
|
+
* @param reorder move the existing ref to `index` instead of returning EEXIST.
|
|
163
153
|
*/
|
|
164
154
|
SELVA_EXPORT
|
|
165
155
|
int selva_fields_references_insert(
|
|
@@ -243,7 +233,12 @@ int selva_fields_get_reference_meta_mutable_string(
|
|
|
243
233
|
* +------+------+--------+-----+
|
|
244
234
|
*/
|
|
245
235
|
SELVA_EXPORT
|
|
246
|
-
int selva_fields_set_string(
|
|
236
|
+
int selva_fields_set_string(
|
|
237
|
+
struct SelvaNode *node,
|
|
238
|
+
const struct SelvaFieldSchema *fs,
|
|
239
|
+
struct SelvaFieldInfo *nfo,
|
|
240
|
+
const char *str,
|
|
241
|
+
size_t len);
|
|
247
242
|
|
|
248
243
|
/**
|
|
249
244
|
* Set text field translation.
|
|
@@ -326,7 +321,7 @@ SELVA_EXPORT
|
|
|
326
321
|
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs);
|
|
327
322
|
|
|
328
323
|
/**
|
|
329
|
-
* Init fields of a node.
|
|
324
|
+
* Init the fields struct of a node or edge.
|
|
330
325
|
*/
|
|
331
326
|
SELVA_EXPORT
|
|
332
327
|
void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaFields *fields);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -119,17 +119,6 @@ int selva_fields_set(
|
|
|
119
119
|
const struct SelvaFieldSchema *fs,
|
|
120
120
|
const void *value, size_t len);
|
|
121
121
|
|
|
122
|
-
/**
|
|
123
|
-
* Set field value with CRC.
|
|
124
|
-
*/
|
|
125
|
-
SELVA_EXPORT
|
|
126
|
-
int selva_fields_set_wcrc(
|
|
127
|
-
struct SelvaDb *db,
|
|
128
|
-
struct SelvaNode *node,
|
|
129
|
-
const struct SelvaFieldSchema *fs,
|
|
130
|
-
const void *value, size_t len,
|
|
131
|
-
uint32_t crc);
|
|
132
|
-
|
|
133
122
|
SELVA_EXPORT
|
|
134
123
|
int selva_fields_get_mutable_string(
|
|
135
124
|
struct SelvaNode *node,
|
|
@@ -160,6 +149,7 @@ int selva_fields_reference_set(
|
|
|
160
149
|
|
|
161
150
|
/**
|
|
162
151
|
* @param index 0 = first; -1 = last.
|
|
152
|
+
* @param reorder move the existing ref to `index` instead of returning EEXIST.
|
|
163
153
|
*/
|
|
164
154
|
SELVA_EXPORT
|
|
165
155
|
int selva_fields_references_insert(
|
|
@@ -243,7 +233,12 @@ int selva_fields_get_reference_meta_mutable_string(
|
|
|
243
233
|
* +------+------+--------+-----+
|
|
244
234
|
*/
|
|
245
235
|
SELVA_EXPORT
|
|
246
|
-
int selva_fields_set_string(
|
|
236
|
+
int selva_fields_set_string(
|
|
237
|
+
struct SelvaNode *node,
|
|
238
|
+
const struct SelvaFieldSchema *fs,
|
|
239
|
+
struct SelvaFieldInfo *nfo,
|
|
240
|
+
const char *str,
|
|
241
|
+
size_t len);
|
|
247
242
|
|
|
248
243
|
/**
|
|
249
244
|
* Set text field translation.
|
|
@@ -326,7 +321,7 @@ SELVA_EXPORT
|
|
|
326
321
|
void selva_fields_clear_references(struct SelvaDb *db, struct SelvaNode *node, const struct SelvaFieldSchema *fs);
|
|
327
322
|
|
|
328
323
|
/**
|
|
329
|
-
* Init fields of a node.
|
|
324
|
+
* Init the fields struct of a node or edge.
|
|
330
325
|
*/
|
|
331
326
|
SELVA_EXPORT
|
|
332
327
|
void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaFields *fields);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -47,7 +47,7 @@ export declare class DbClient {
|
|
|
47
47
|
};
|
|
48
48
|
create(type: string, obj?: CreateObj, opts?: ModifyOpts): ModifyRes;
|
|
49
49
|
copy(type: string, target: number | ModifyRes, objOrTransformFn?: Record<string, any> | ((item: Record<string, any>) => Promise<any>)): Promise<ModifyRes>;
|
|
50
|
-
query(type: string, id?: number | ModifyRes | (number | ModifyRes)[] | QueryByAliasObj | QueryByAliasObj[]): BasedDbQuery;
|
|
50
|
+
query(type: string, id?: number | ModifyRes | (number | ModifyRes)[] | QueryByAliasObj | QueryByAliasObj[] | Uint32Array): BasedDbQuery;
|
|
51
51
|
query(): BasedDbQuery;
|
|
52
52
|
update(type: string, id: number | ModifyRes, value: any, opts?: ModifyOpts): ModifyRes;
|
|
53
53
|
update(type: string, value: Record<string, any> & {
|
package/dist/src/client/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ModifyCtx } from '../../index.js';
|
|
2
2
|
import { SchemaTypeDef, PropDef } from '../../server/schema/types.js';
|
|
3
3
|
import { ModifyOp, ModifyErr } from './types.js';
|
|
4
|
-
export declare function writeHll(value: string | null | Buffer
|
|
4
|
+
export declare function writeHll(value: string | null | Buffer | Array<string | Buffer>, ctx: ModifyCtx, def: SchemaTypeDef, t: PropDef, parentId: number, modifyOp: ModifyOp): ModifyErr;
|
|
@@ -7,44 +7,36 @@ export function writeHll(value, ctx, def, t, parentId, modifyOp) {
|
|
|
7
7
|
return new ModifyError(t, value);
|
|
8
8
|
}
|
|
9
9
|
if (value === null) {
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
// if (ctx.len + 11 > ctx.max) {
|
|
13
|
-
// return RANGE_ERR
|
|
14
|
-
// }
|
|
15
|
-
// setCursor(ctx, def, t.prop, parentId, modifyOp)
|
|
16
|
-
// ctx.buf[ctx.len++] = DELETE
|
|
17
|
-
// }
|
|
10
|
+
// Future hll_reset frunction
|
|
11
|
+
return;
|
|
18
12
|
}
|
|
19
|
-
else if (Array.isArray(value)) {
|
|
20
|
-
|
|
21
|
-
// for (const key in value) {
|
|
22
|
-
// if (key === 'add') {
|
|
23
|
-
// // @ts-ignore
|
|
24
|
-
// const err = addHll(value[key], ctx, def, t, parentId, modifyOp, 1)
|
|
25
|
-
// if (err) {
|
|
26
|
-
// return err
|
|
27
|
-
// }
|
|
28
|
-
// } else {
|
|
29
|
-
// return new ModifyError(t, value)
|
|
30
|
-
// }
|
|
31
|
-
// }
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
return addHll(value, ctx, def, t, parentId, modifyOp);
|
|
13
|
+
else if (!Array.isArray(value)) {
|
|
14
|
+
value = [value];
|
|
35
15
|
}
|
|
16
|
+
const err = addHll(value, ctx, def, t, parentId, modifyOp);
|
|
36
17
|
}
|
|
37
18
|
function addHll(value, ctx, def, t, parentId, modifyOp) {
|
|
38
|
-
|
|
19
|
+
const len = value.length;
|
|
20
|
+
let size = 2 + len * 8;
|
|
39
21
|
if (ctx.len + size + 11 > ctx.max) {
|
|
40
22
|
return RANGE_ERR;
|
|
41
23
|
}
|
|
42
|
-
// console.log(`test JS original value = ${value}`)
|
|
43
24
|
setCursor(ctx, def, t.prop, t.typeIndex, parentId, modifyOp);
|
|
44
25
|
ctx.buf[ctx.len++] = modifyOp;
|
|
45
|
-
|
|
46
|
-
ctx.
|
|
47
|
-
|
|
48
|
-
|
|
26
|
+
ctx.buf.writeUint16LE(len, ctx.len);
|
|
27
|
+
ctx.len += 2;
|
|
28
|
+
for (let val of value) {
|
|
29
|
+
let b;
|
|
30
|
+
if (typeof val === 'string') {
|
|
31
|
+
b = Buffer.from(val);
|
|
32
|
+
}
|
|
33
|
+
else if (!(val instanceof Buffer)) {
|
|
34
|
+
b = val;
|
|
35
|
+
return new ModifyError(t, val);
|
|
36
|
+
}
|
|
37
|
+
const hash = xxHash64(b);
|
|
38
|
+
ctx.buf.writeBigUInt64LE(hash, ctx.len);
|
|
39
|
+
ctx.len += 8;
|
|
40
|
+
}
|
|
49
41
|
}
|
|
50
42
|
//# sourceMappingURL=cardinality.js.map
|
|
@@ -31,11 +31,11 @@ declare class GetPromise extends Promise<BasedQueryResponse> {
|
|
|
31
31
|
}
|
|
32
32
|
export declare class BasedDbQuery extends QueryBranch<BasedDbQuery> {
|
|
33
33
|
#private;
|
|
34
|
-
constructor(db: DbClient, type: string, id?: QueryByAliasObj | number | (QueryByAliasObj | number)[]);
|
|
34
|
+
constructor(db: DbClient, type: string, id?: QueryByAliasObj | number | Uint32Array | (QueryByAliasObj | number)[]);
|
|
35
35
|
id: number;
|
|
36
36
|
get(): GetPromise;
|
|
37
37
|
buffer: Buffer;
|
|
38
|
-
register():
|
|
38
|
+
register(): void;
|
|
39
39
|
i18n(locale: LangName): this;
|
|
40
40
|
subscribe(onData: OnData, onError?: OnError): import("./subscription/types.js").OnClose;
|
|
41
41
|
_getSync(dbCtxExternal: any): BasedQueryResponse;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { createQueryDef, QueryDefType,
|
|
1
|
+
import { createQueryDef, QueryDefType, filter, sort, defToBuffer, filterOr, convertFilter, isAlias, includeField, includeFields, } from './query.js';
|
|
2
2
|
import { BasedQueryResponse } from './BasedIterable.js';
|
|
3
3
|
import { createOrGetEdgeRefQueryDef, createOrGetRefQueryDef, } from './include/utils.js';
|
|
4
4
|
import { FilterBranch } from './filter/FilterBranch.js';
|
|
5
5
|
import { search, vectorSearch } from './search/index.js';
|
|
6
|
-
import { isValidId, checkMaxIdsPerQuery, checkTotalBufferSize, hasField, isValidAlias, } from './validation.js';
|
|
7
6
|
import native from '../../native.js';
|
|
8
7
|
import { REFERENCE, REFERENCES } from '../../server/schema/types.js';
|
|
9
8
|
import { subscribe } from './subscription/index.js';
|
|
@@ -140,10 +139,7 @@ export class QueryBranch {
|
|
|
140
139
|
});
|
|
141
140
|
}
|
|
142
141
|
else if (Array.isArray(f)) {
|
|
143
|
-
|
|
144
|
-
hasField(field);
|
|
145
|
-
includeField(this.def, field);
|
|
146
|
-
}
|
|
142
|
+
includeFields(this.def, f);
|
|
147
143
|
}
|
|
148
144
|
else if (f !== undefined) {
|
|
149
145
|
throw new Error('Invalid include statement: expected props, refs and edges (string or array) or function');
|
|
@@ -178,39 +174,33 @@ export class BasedDbQuery extends QueryBranch {
|
|
|
178
174
|
target.alias = id;
|
|
179
175
|
}
|
|
180
176
|
else {
|
|
181
|
-
if (Array.isArray(id)) {
|
|
182
|
-
checkMaxIdsPerQuery(id);
|
|
183
|
-
// const ids = id.filter((id) => typeof id === 'number')
|
|
184
|
-
// if (ids.length < id.length) {
|
|
185
|
-
// throw new Error(
|
|
186
|
-
// 'Seems that aliases are part of ids in qeury not supported yet...',
|
|
187
|
-
// )
|
|
188
|
-
// }
|
|
177
|
+
if (Array.isArray(id) || id instanceof Uint32Array) {
|
|
189
178
|
// TODO ADD MULTI ALIAS
|
|
190
179
|
// @ts-ignore
|
|
191
|
-
target.ids =
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
target.ids.sort();
|
|
180
|
+
target.ids = id;
|
|
181
|
+
// target.ids = new Uint32Array(id)
|
|
182
|
+
// target.ids.sort()
|
|
196
183
|
}
|
|
197
184
|
else {
|
|
198
|
-
isValidId(id);
|
|
199
185
|
target.id = id;
|
|
200
186
|
}
|
|
201
187
|
}
|
|
202
188
|
}
|
|
203
189
|
const def = createQueryDef(db, QueryDefType.Root, target);
|
|
204
|
-
if (isAlias(id)) {
|
|
205
|
-
isValidAlias(def, id);
|
|
206
|
-
}
|
|
207
190
|
super(db, def);
|
|
208
191
|
}
|
|
209
192
|
#getInternal = async (resolve, reject) => {
|
|
210
193
|
if (!this.def.include.stringFields.size && !this.def.references.size) {
|
|
211
|
-
|
|
194
|
+
includeField(this.def, '*');
|
|
195
|
+
}
|
|
196
|
+
let buf;
|
|
197
|
+
try {
|
|
198
|
+
buf = registerQuery(this);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
reject(err);
|
|
202
|
+
return;
|
|
212
203
|
}
|
|
213
|
-
const buf = registerQuery(this);
|
|
214
204
|
const d = performance.now();
|
|
215
205
|
const res = await this.db.hooks.getQueryBuf(buf);
|
|
216
206
|
if (res instanceof Error) {
|
|
@@ -227,7 +217,7 @@ export class BasedDbQuery extends QueryBranch {
|
|
|
227
217
|
}
|
|
228
218
|
buffer;
|
|
229
219
|
register() {
|
|
230
|
-
|
|
220
|
+
registerQuery(this);
|
|
231
221
|
}
|
|
232
222
|
i18n(locale) {
|
|
233
223
|
this.def.lang = langCodesMap.get(locale) ?? 0;
|
|
@@ -241,7 +231,7 @@ export class BasedDbQuery extends QueryBranch {
|
|
|
241
231
|
}
|
|
242
232
|
_getSync(dbCtxExternal) {
|
|
243
233
|
if (!this.def.include.stringFields.size && !this.def.references.size) {
|
|
244
|
-
|
|
234
|
+
includeField(this.def, '*');
|
|
245
235
|
}
|
|
246
236
|
const buf = registerQuery(this);
|
|
247
237
|
const d = performance.now();
|
|
@@ -250,10 +240,9 @@ export class BasedDbQuery extends QueryBranch {
|
|
|
250
240
|
}
|
|
251
241
|
toBuffer() {
|
|
252
242
|
if (!this.def.include.stringFields.size && !this.def.references.size) {
|
|
253
|
-
|
|
243
|
+
includeField(this.def, '*');
|
|
254
244
|
}
|
|
255
245
|
const b = defToBuffer(this.db, this.def);
|
|
256
|
-
checkTotalBufferSize(b);
|
|
257
246
|
return Buffer.concat(b);
|
|
258
247
|
}
|
|
259
248
|
}
|
|
@@ -2,7 +2,6 @@ import { isPropDef, ID_FIELD_DEF, TEXT, } from '../../../server/schema/schema.js
|
|
|
2
2
|
import { primitiveFilter } from './primitiveFilter.js';
|
|
3
3
|
import { toFilterCtx } from './types.js';
|
|
4
4
|
import { IsFilter } from './types.js';
|
|
5
|
-
import { hasField, checkOperator, checkValue } from '../validation.js';
|
|
6
5
|
import { langCodesMap } from '@based/schema';
|
|
7
6
|
const referencesFilter = (db, filter, schema, conditions, def) => {
|
|
8
7
|
const [fieldStr, ctx, value] = filter;
|
|
@@ -111,9 +110,6 @@ export const convertFilter = (field, operator, value, opts) => {
|
|
|
111
110
|
value = operator;
|
|
112
111
|
operator = '=';
|
|
113
112
|
}
|
|
114
|
-
hasField(field);
|
|
115
|
-
checkOperator(operator);
|
|
116
|
-
checkValue(value, operator);
|
|
117
113
|
if (operator === '!..') {
|
|
118
114
|
return [
|
|
119
115
|
[field, toFilterCtx('>', opts), value[1]],
|
|
@@ -2,8 +2,9 @@ import { isPropDef, REFERENCE, REFERENCES, TEXT, } from '../../../server/schema/
|
|
|
2
2
|
import { createQueryDef } from '../queryDef.js';
|
|
3
3
|
import { isRefDef, QueryDefType } from '../types.js';
|
|
4
4
|
import { getAllFieldFromObject, createOrGetRefQueryDef } from './utils.js';
|
|
5
|
-
import {
|
|
5
|
+
import { includeProp, includeAllProps, includeField } from './props.js';
|
|
6
6
|
import { langCodesMap } from '@based/schema';
|
|
7
|
+
import { includeDoesNotExist } from '../validation.js';
|
|
7
8
|
export const walkDefs = (db, def, f) => {
|
|
8
9
|
const prop = def.props[f];
|
|
9
10
|
const path = f.split('.');
|
|
@@ -28,7 +29,7 @@ export const walkDefs = (db, def, f) => {
|
|
|
28
29
|
else {
|
|
29
30
|
const f = path.slice(i + 1).join('.');
|
|
30
31
|
if (!includeProp(refDef, refDef.props[f])) {
|
|
31
|
-
|
|
32
|
+
includeField(refDef, f);
|
|
32
33
|
}
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
@@ -40,6 +41,9 @@ export const walkDefs = (db, def, f) => {
|
|
|
40
41
|
}
|
|
41
42
|
t = t[p];
|
|
42
43
|
if (!t) {
|
|
44
|
+
if (f != 'id') {
|
|
45
|
+
includeDoesNotExist(def, f);
|
|
46
|
+
}
|
|
43
47
|
return;
|
|
44
48
|
}
|
|
45
49
|
if (isPropDef(t) && t.typeIndex === TEXT) {
|
|
@@ -55,7 +59,7 @@ export const walkDefs = (db, def, f) => {
|
|
|
55
59
|
const refDef = createOrGetRefQueryDef(db, def, t);
|
|
56
60
|
const f = path.slice(i + 1).join('.');
|
|
57
61
|
if (!includeProp(refDef, refDef.props[f])) {
|
|
58
|
-
|
|
62
|
+
includeField(refDef, f);
|
|
59
63
|
}
|
|
60
64
|
return;
|
|
61
65
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { langCodesMap } from '@based/schema';
|
|
2
|
-
import {
|
|
2
|
+
import { DEF_RANGE_PROP_LIMIT, DEF_RANGE_REF_LIMIT } from './thresholds.js';
|
|
3
3
|
import { QueryDefType, } from './types.js';
|
|
4
|
+
import { validateId, validateIds, validateType } from './validation.js';
|
|
4
5
|
const createEmptySharedDef = () => {
|
|
5
6
|
const q = {
|
|
7
|
+
errors: [],
|
|
6
8
|
filter: { conditions: new Map(), size: 0 },
|
|
7
9
|
range: { offset: 0, limit: 0 },
|
|
8
10
|
lang: langCodesMap.get('none'),
|
|
@@ -35,21 +37,24 @@ export const createQueryDef = (db, type, target) => {
|
|
|
35
37
|
else {
|
|
36
38
|
const t = target;
|
|
37
39
|
const q = queryDef;
|
|
38
|
-
q.schema = db
|
|
40
|
+
q.schema = validateType(db, q, t.type);
|
|
39
41
|
q.props = q.schema.props;
|
|
40
42
|
q.type = type;
|
|
41
43
|
q.target = t;
|
|
42
44
|
if (type === QueryDefType.Root) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
if (t.id) {
|
|
46
|
+
t.id = validateId(q, t.id);
|
|
47
|
+
}
|
|
48
|
+
else if (t.ids) {
|
|
49
|
+
t.ids = validateIds(q, t.ids);
|
|
50
|
+
q.range.limit = t.ids.length;
|
|
46
51
|
}
|
|
47
52
|
else {
|
|
48
|
-
q.range.limit =
|
|
53
|
+
q.range.limit = DEF_RANGE_PROP_LIMIT;
|
|
49
54
|
}
|
|
50
55
|
}
|
|
51
56
|
else if (type === QueryDefType.References) {
|
|
52
|
-
q.range.limit =
|
|
57
|
+
q.range.limit = DEF_RANGE_REF_LIMIT;
|
|
53
58
|
}
|
|
54
59
|
return q;
|
|
55
60
|
}
|
|
@@ -1,29 +1,14 @@
|
|
|
1
1
|
import native from '../../native.js';
|
|
2
2
|
import { defToBuffer } from './toBuffer.js';
|
|
3
|
-
import {
|
|
3
|
+
import { handleErrors } from './validation.js';
|
|
4
4
|
export const registerQuery = (q) => {
|
|
5
|
-
// just add crc32 in the buffer
|
|
6
5
|
if (!q.id) {
|
|
7
6
|
const b = defToBuffer(q.db, q.def);
|
|
8
7
|
const buf = Buffer.concat(b);
|
|
9
8
|
let id = native.crc32(buf);
|
|
10
9
|
q.id = id;
|
|
11
|
-
// id = (id ^ q.def.schema.id) >>> 0
|
|
12
|
-
// typeId, crc32, len
|
|
13
|
-
// but want it to fit in a js number...
|
|
14
|
-
// use 2 bytes for len and just continue counting
|
|
15
|
-
// const x = Buffer.allocUnsafe(8)
|
|
16
|
-
// // const number
|
|
17
|
-
// x.writeUint16LE(q.def.schema.id, 0)
|
|
18
|
-
// x.writeUint32LE(id, 2)
|
|
19
|
-
// x.writeUint16LE(buf.byteLength, 6)
|
|
20
|
-
// // ------------------------
|
|
21
|
-
// console.log('-> CRC32', { id, x: new Uint8Array(x), y: x.readFloatLE(0) })
|
|
22
|
-
// do a test for
|
|
23
|
-
// console.log(id)
|
|
24
|
-
// id, len, type as id?
|
|
25
10
|
q.buffer = buf;
|
|
26
|
-
|
|
11
|
+
handleErrors(q.def);
|
|
27
12
|
return buf;
|
|
28
13
|
}
|
|
29
14
|
return q.buffer;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { includeField } from '../query.js';
|
|
2
2
|
import { registerQuery } from '../registerQuery.js';
|
|
3
3
|
import { runSubscription } from './run.js';
|
|
4
4
|
import { addSubscriptionMarkers, deleteSubscriptionMarkers } from './markers.js';
|
|
@@ -7,9 +7,15 @@ export * from './markers.js';
|
|
|
7
7
|
export const subscribe = (q, onData, onError) => {
|
|
8
8
|
let closed = false;
|
|
9
9
|
if (!q.def.include.stringFields.size && !q.def.references.size) {
|
|
10
|
-
|
|
10
|
+
includeField(q.def, '*');
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
registerQuery(q);
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
onError(err);
|
|
17
|
+
return () => q;
|
|
11
18
|
}
|
|
12
|
-
registerQuery(q);
|
|
13
19
|
if (!q.db.subscriptions.has(q.id)) {
|
|
14
20
|
const subscription = {
|
|
15
21
|
query: q,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const MAX_IDS_PER_QUERY = 1000000;
|
|
2
2
|
export declare const MAX_BUFFER_SIZE: number;
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const
|
|
3
|
+
export declare const DEF_RANGE_PROP_LIMIT = 1000;
|
|
4
|
+
export declare const DEF_RANGE_REF_LIMIT = 10000;
|
|
5
|
+
export declare const MAX_ID = 4294967295;
|
|
5
6
|
export declare const MIN_ID_VALUE = 1;
|
|
6
7
|
export declare const MAX_ID_VALUE: number;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Query thresholds
|
|
2
2
|
export const MAX_IDS_PER_QUERY = 1e6; // Max number of IDs that can be queried at once
|
|
3
3
|
export const MAX_BUFFER_SIZE = 5 * 1024 * 1024; // 5MB (max buffer size)
|
|
4
|
-
export const
|
|
5
|
-
export const
|
|
4
|
+
export const DEF_RANGE_PROP_LIMIT = 1e3;
|
|
5
|
+
export const DEF_RANGE_REF_LIMIT = 1e4;
|
|
6
|
+
export const MAX_ID = 4294967295;
|
|
6
7
|
// Data validation thresholds
|
|
7
8
|
export const MIN_ID_VALUE = 1; // Minimum allowed value for an ID (id array stared)
|
|
8
9
|
export const MAX_ID_VALUE = 2 ** 32 - 1; /// Maximum allowed value for an ID (Uint32)
|
|
@@ -28,10 +28,16 @@ const getAliasPropdef = (alias, path, def) => {
|
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
30
|
export function defToBuffer(db, def) {
|
|
31
|
+
// if (def.errors.length) {
|
|
32
|
+
// return []
|
|
33
|
+
// }
|
|
31
34
|
const result = [];
|
|
32
35
|
const include = includeToBuffer(db, def);
|
|
33
36
|
def.references.forEach((ref) => {
|
|
34
37
|
include.push(...defToBuffer(db, ref));
|
|
38
|
+
if (ref.errors) {
|
|
39
|
+
def.errors.push(...ref.errors);
|
|
40
|
+
}
|
|
35
41
|
});
|
|
36
42
|
let edges;
|
|
37
43
|
let edgesSize = 0;
|
|
@@ -39,6 +45,9 @@ export function defToBuffer(db, def) {
|
|
|
39
45
|
edges = includeToBuffer(db, def.edges);
|
|
40
46
|
def.edges.references.forEach((ref) => {
|
|
41
47
|
edges.push(...defToBuffer(db, ref));
|
|
48
|
+
if (ref.errors) {
|
|
49
|
+
def.errors.push(...ref.errors);
|
|
50
|
+
}
|
|
42
51
|
});
|
|
43
52
|
edgesSize = byteSize(edges);
|
|
44
53
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { LangCode } from '@based/schema';
|
|
2
2
|
import { PropDef, PropDefEdge, SchemaTypeDef } from '../../server/schema/schema.js';
|
|
3
3
|
import { FilterOpts } from './filter/types.js';
|
|
4
|
+
import { QueryError } from './validation.js';
|
|
4
5
|
export type MainIncludes = {
|
|
5
6
|
[start: string]: [number, PropDef];
|
|
6
7
|
};
|
|
@@ -54,6 +55,7 @@ export type QueryDefSort = {
|
|
|
54
55
|
order: 0 | 1;
|
|
55
56
|
};
|
|
56
57
|
export type QueryDefShared = {
|
|
58
|
+
errors: QueryError[];
|
|
57
59
|
lang: LangCode;
|
|
58
60
|
filter: QueryDefFilter;
|
|
59
61
|
search: null | QueryDefSearch;
|
|
@@ -97,4 +99,4 @@ export { QueryDefType };
|
|
|
97
99
|
export type QueryByAliasObj = {
|
|
98
100
|
[key: string]: string | QueryByAliasObj;
|
|
99
101
|
};
|
|
100
|
-
export declare const isAlias: (id: QueryByAliasObj | number | (QueryByAliasObj | number)[]) => id is QueryByAliasObj;
|
|
102
|
+
export declare const isAlias: (id: QueryByAliasObj | number | Uint32Array | (QueryByAliasObj | number)[]) => id is QueryByAliasObj;
|
|
@@ -10,6 +10,9 @@ export const isRefDef = (def) => {
|
|
|
10
10
|
};
|
|
11
11
|
export { QueryDefType };
|
|
12
12
|
export const isAlias = (id) => {
|
|
13
|
+
if (id instanceof Uint32Array) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
13
16
|
return typeof id === 'object' && id !== null && !Array.isArray(id);
|
|
14
17
|
};
|
|
15
18
|
//# sourceMappingURL=types.js.map
|
|
@@ -1,16 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export declare const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export declare const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
import { SchemaTypeDef } from '../../server/schema/types.js';
|
|
2
|
+
import { DbClient } from '../index.js';
|
|
3
|
+
import { QueryDef } from './types.js';
|
|
4
|
+
export type QueryError = {
|
|
5
|
+
code: number;
|
|
6
|
+
payload: any;
|
|
7
|
+
};
|
|
8
|
+
export declare const ERR_TARGET_INVAL_TYPE = 1;
|
|
9
|
+
export declare const ERR_TARGET_INVAL_ALIAS = 2;
|
|
10
|
+
export declare const ERR_TARGET_EXCEED_MAX_IDS = 3;
|
|
11
|
+
export declare const ERR_TARGET_INVAL_IDS = 4;
|
|
12
|
+
export declare const ERR_TARGET_INVAL_ID = 5;
|
|
13
|
+
export declare const ERR_INCLUDE_ENOENT = 6;
|
|
14
|
+
declare const messages: {
|
|
15
|
+
1: (p: any) => string;
|
|
16
|
+
2: (p: any) => string;
|
|
17
|
+
3: (p: any) => string;
|
|
18
|
+
4: (p: any) => string;
|
|
19
|
+
5: (p: any) => string;
|
|
20
|
+
6: (p: any) => string;
|
|
21
|
+
};
|
|
22
|
+
export type ErrorCode = keyof typeof messages;
|
|
23
|
+
export declare const validateType: (db: DbClient, def: QueryDef, type: string) => SchemaTypeDef;
|
|
24
|
+
export declare const includeDoesNotExist: (def: QueryDef, field: string) => void;
|
|
25
|
+
export declare const validateId: (def: QueryDef, id: any) => number;
|
|
26
|
+
export declare const validateIds: (def: QueryDef, ids: any) => Uint32Array;
|
|
27
|
+
export declare const handleErrors: (def: QueryDef) => void;
|
|
28
|
+
export declare const EMPTY_SCHEMA_DEF: SchemaTypeDef;
|
|
29
|
+
export {};
|
|
@@ -1,74 +1,184 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
1
|
+
import { MAX_ID, MAX_IDS_PER_QUERY } from './thresholds.js';
|
|
2
|
+
export const ERR_TARGET_INVAL_TYPE = 1;
|
|
3
|
+
export const ERR_TARGET_INVAL_ALIAS = 2;
|
|
4
|
+
export const ERR_TARGET_EXCEED_MAX_IDS = 3;
|
|
5
|
+
export const ERR_TARGET_INVAL_IDS = 4;
|
|
6
|
+
export const ERR_TARGET_INVAL_ID = 5;
|
|
7
|
+
export const ERR_INCLUDE_ENOENT = 6;
|
|
8
|
+
const messages = {
|
|
9
|
+
[ERR_TARGET_INVAL_TYPE]: (p) => `Type "${p}" does not exist`,
|
|
10
|
+
[ERR_TARGET_INVAL_ALIAS]: (p) => `Invalid alias "${p}"`,
|
|
11
|
+
[ERR_TARGET_EXCEED_MAX_IDS]: (p) => `Exceeds max ids ${~~(p.length / 1e3)}k (max ${MAX_IDS_PER_QUERY / 1e3}k)`,
|
|
12
|
+
[ERR_TARGET_INVAL_IDS]: (p) => `Ids should be of type array or Uint32Array with valid ids`,
|
|
13
|
+
[ERR_TARGET_INVAL_ID]: (p) => `Invalid id should be a number larger then 0 "${p}"`,
|
|
14
|
+
[ERR_INCLUDE_ENOENT]: (p) => `Included field does not exist "${p}"`,
|
|
16
15
|
};
|
|
17
|
-
export const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
export const validateType = (db, def, type) => {
|
|
17
|
+
const r = db.schemaTypesParsed[type];
|
|
18
|
+
if (!r) {
|
|
19
|
+
def.errors.push({
|
|
20
|
+
code: ERR_TARGET_INVAL_TYPE,
|
|
21
|
+
payload: type,
|
|
22
|
+
});
|
|
23
|
+
EMPTY_SCHEMA_DEF.locales = db.schema.locales;
|
|
24
|
+
return EMPTY_SCHEMA_DEF;
|
|
21
25
|
}
|
|
26
|
+
return r;
|
|
22
27
|
};
|
|
23
|
-
export const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
throw new Error(`The total buffer size exceeds the maximum threshold of ${MAX_BUFFER_SIZE} bytes.` +
|
|
29
|
-
`Crrent size is ${totalSize} bytes.`);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
28
|
+
export const includeDoesNotExist = (def, field) => {
|
|
29
|
+
def.errors.push({
|
|
30
|
+
code: ERR_INCLUDE_ENOENT,
|
|
31
|
+
payload: field,
|
|
32
|
+
});
|
|
32
33
|
};
|
|
33
|
-
export const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
export const validateId = (def, id) => {
|
|
35
|
+
if (typeof id != 'number' || id == 0 || id > MAX_ID) {
|
|
36
|
+
def.errors.push({
|
|
37
|
+
code: ERR_TARGET_INVAL_ID,
|
|
38
|
+
payload: id,
|
|
39
|
+
});
|
|
40
|
+
return 1;
|
|
38
41
|
}
|
|
42
|
+
return id;
|
|
39
43
|
};
|
|
40
|
-
export const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
44
|
+
export const validateIds = (def, ids) => {
|
|
45
|
+
if (!Array.isArray(ids) && !(ids instanceof Uint32Array)) {
|
|
46
|
+
def.errors.push({
|
|
47
|
+
code: ERR_TARGET_INVAL_IDS,
|
|
48
|
+
payload: ids,
|
|
49
|
+
});
|
|
50
|
+
return new Uint32Array([]);
|
|
46
51
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
if (ids.length > MAX_IDS_PER_QUERY) {
|
|
53
|
+
def.errors.push({
|
|
54
|
+
code: ERR_TARGET_EXCEED_MAX_IDS,
|
|
55
|
+
payload: ids,
|
|
56
|
+
});
|
|
57
|
+
return new Uint32Array([]);
|
|
53
58
|
}
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
if (Array.isArray(ids)) {
|
|
60
|
+
try {
|
|
61
|
+
ids = new Uint32Array(ids);
|
|
62
|
+
ids.sort();
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
def.errors.push({
|
|
66
|
+
code: ERR_TARGET_INVAL_IDS,
|
|
67
|
+
payload: ids,
|
|
68
|
+
});
|
|
69
|
+
return new Uint32Array([]);
|
|
70
|
+
}
|
|
56
71
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
72
|
+
// pretty heavy if it are a lot...
|
|
73
|
+
for (const id of ids) {
|
|
74
|
+
if (typeof id != 'number' || id == 0 || id > MAX_ID) {
|
|
75
|
+
def.errors.push({
|
|
76
|
+
code: ERR_TARGET_INVAL_IDS,
|
|
77
|
+
payload: ids,
|
|
78
|
+
});
|
|
79
|
+
return new Uint32Array([]);
|
|
80
|
+
}
|
|
64
81
|
}
|
|
82
|
+
return ids;
|
|
65
83
|
};
|
|
66
|
-
export const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
export const handleErrors = (def) => {
|
|
85
|
+
if (def.errors.length) {
|
|
86
|
+
let name = `Query\n`;
|
|
87
|
+
for (const err of def.errors) {
|
|
88
|
+
name += ` ${messages[err.code](err.payload)}\n`;
|
|
71
89
|
}
|
|
90
|
+
const err = new Error(name);
|
|
91
|
+
err.stack = '';
|
|
92
|
+
throw err;
|
|
72
93
|
}
|
|
73
94
|
};
|
|
95
|
+
export const EMPTY_SCHEMA_DEF = {
|
|
96
|
+
type: '_error',
|
|
97
|
+
cnt: 0,
|
|
98
|
+
checksum: 0,
|
|
99
|
+
total: 0,
|
|
100
|
+
lastId: 0,
|
|
101
|
+
blockCapacity: 0,
|
|
102
|
+
mainLen: 0,
|
|
103
|
+
buf: Buffer.from([]),
|
|
104
|
+
propNames: Buffer.from([]),
|
|
105
|
+
props: {},
|
|
106
|
+
locales: {},
|
|
107
|
+
reverseProps: {},
|
|
108
|
+
id: 0,
|
|
109
|
+
idUint8: new Uint8Array([0, 0]),
|
|
110
|
+
main: {},
|
|
111
|
+
separate: [],
|
|
112
|
+
tree: {},
|
|
113
|
+
hasStringProp: false,
|
|
114
|
+
stringPropsSize: 0,
|
|
115
|
+
stringPropsCurrent: Buffer.from([]),
|
|
116
|
+
stringProps: Buffer.from([]),
|
|
117
|
+
stringPropsLoop: [],
|
|
118
|
+
};
|
|
119
|
+
// import { ALIAS, PropDef, PropDefEdge } from '../../server/schema/types.js'
|
|
120
|
+
// import {
|
|
121
|
+
// MAX_IDS_PER_QUERY,
|
|
122
|
+
// MIN_ID_VALUE,
|
|
123
|
+
// MAX_ID_VALUE,
|
|
124
|
+
// MAX_BUFFER_SIZE,
|
|
125
|
+
// } from './thresholds.js'
|
|
126
|
+
// import { QueryByAliasObj, QueryDef } from './types.js'
|
|
127
|
+
// import { DbClient } from '../index.js'
|
|
128
|
+
// export const isValidId = (id: number): void => {
|
|
129
|
+
// if (typeof id != 'number') {
|
|
130
|
+
// throw new Error('Id has to be a number')
|
|
131
|
+
// } else if (id < MIN_ID_VALUE || id > MAX_ID_VALUE) {
|
|
132
|
+
// throw new Error(
|
|
133
|
+
// `Invalid Id: The Id should range between ${MIN_ID_VALUE} and ${MAX_ID_VALUE}.)`,
|
|
134
|
+
// )
|
|
135
|
+
// }
|
|
136
|
+
// }
|
|
137
|
+
// export const isValidType = (
|
|
138
|
+
// type: string,
|
|
139
|
+
// schema: DbClient['schemaTypesParsed'],
|
|
140
|
+
// ): void => {
|
|
141
|
+
// if (!schema[type]) {
|
|
142
|
+
// throw new Error(`Incorrect type provided to query "${type}"`)
|
|
143
|
+
// }
|
|
144
|
+
// }
|
|
145
|
+
// export const isValidAlias = (def: QueryDef, id: QueryByAliasObj) => {
|
|
146
|
+
// for (const key in id) {
|
|
147
|
+
// const prop = def.schema.props[key]
|
|
148
|
+
// if (!prop || prop.typeIndex !== ALIAS) {
|
|
149
|
+
// throw new Error(`Incorrect alias provided to query "${key}"`)
|
|
150
|
+
// }
|
|
151
|
+
// }
|
|
152
|
+
// }
|
|
153
|
+
// export const checkMaxIdsPerQuery = (
|
|
154
|
+
// ids: (number | QueryByAliasObj)[],
|
|
155
|
+
// ): void => {
|
|
156
|
+
// if (ids.length > MAX_IDS_PER_QUERY) {
|
|
157
|
+
// throw new Error(`The number of IDs cannot exceed ${MAX_IDS_PER_QUERY}.`)
|
|
158
|
+
// }
|
|
159
|
+
// }
|
|
160
|
+
// export const checkMaxBufferSize = (buf: Buffer): void => {
|
|
161
|
+
// if (buf.byteLength > MAX_BUFFER_SIZE) {
|
|
162
|
+
// throw new Error(
|
|
163
|
+
// `The buffer size exceeds the maximum threshold of ${MAX_BUFFER_SIZE} bytes.` +
|
|
164
|
+
// `Crrent size is ${buf.byteLength} bytes.`,
|
|
165
|
+
// )
|
|
166
|
+
// }
|
|
167
|
+
// }
|
|
168
|
+
// export const checkTotalBufferSize = (bufers: Buffer[]): void => {
|
|
169
|
+
// let totalSize = 0
|
|
170
|
+
// for (const buffer of bufers) {
|
|
171
|
+
// totalSize += buffer.byteLength
|
|
172
|
+
// if (totalSize > MAX_BUFFER_SIZE) {
|
|
173
|
+
// throw new Error(
|
|
174
|
+
// `The total buffer size exceeds the maximum threshold of ${MAX_BUFFER_SIZE} bytes.` +
|
|
175
|
+
// `Crrent size is ${totalSize} bytes.`,
|
|
176
|
+
// )
|
|
177
|
+
// }
|
|
178
|
+
// }
|
|
179
|
+
// }
|
|
180
|
+
// // ------------------------------
|
|
181
|
+
// export const includeDoesNotExist = (def: QueryDef, field: string) => {
|
|
182
|
+
// throw new Error(`Incorrect include field provided to query "${field}")`)
|
|
183
|
+
// }
|
|
74
184
|
//# sourceMappingURL=validation.js.map
|
|
@@ -3,6 +3,7 @@ import { SchemaTypeDef } from './schema/types.js';
|
|
|
3
3
|
import { createTree } from './csmt/index.js';
|
|
4
4
|
import { Worker, MessagePort } from 'node:worker_threads';
|
|
5
5
|
import { TransformFns } from './migrate/index.js';
|
|
6
|
+
import exitHook from 'exit-hook';
|
|
6
7
|
declare class SortIndex {
|
|
7
8
|
constructor(buf: Buffer, dbCtxExternal: any);
|
|
8
9
|
buf: Buffer;
|
|
@@ -48,6 +49,7 @@ export declare class DbServer {
|
|
|
48
49
|
queryQueue: Map<Function, Buffer>;
|
|
49
50
|
stopped: boolean;
|
|
50
51
|
onSchemaChange: OnSchemaChange;
|
|
52
|
+
unlistenExit: ReturnType<typeof exitHook>;
|
|
51
53
|
constructor({ path, maxModifySize, onSchemaChange, }: {
|
|
52
54
|
path: string;
|
|
53
55
|
maxModifySize?: number;
|
|
@@ -56,7 +58,7 @@ export declare class DbServer {
|
|
|
56
58
|
start(opts?: {
|
|
57
59
|
clean?: boolean;
|
|
58
60
|
}): Promise<void>;
|
|
59
|
-
save(): Promise<void>;
|
|
61
|
+
save(): void | Promise<void>;
|
|
60
62
|
createCsmtHashFun: () => {
|
|
61
63
|
update: (buf: Buffer) => any;
|
|
62
64
|
digest: (encoding?: BufferEncoding) => Buffer | string;
|
package/dist/src/server/index.js
CHANGED
|
@@ -82,6 +82,7 @@ export class DbServer {
|
|
|
82
82
|
queryQueue = new Map();
|
|
83
83
|
stopped;
|
|
84
84
|
onSchemaChange;
|
|
85
|
+
unlistenExit;
|
|
85
86
|
constructor({ path, maxModifySize = 100 * 1e3 * 1e3, onSchemaChange, }) {
|
|
86
87
|
this.maxModifySize = maxModifySize;
|
|
87
88
|
this.fileSystemPath = path;
|
|
@@ -432,6 +433,7 @@ export class DbServer {
|
|
|
432
433
|
}
|
|
433
434
|
this.stopped = true;
|
|
434
435
|
clearTimeout(this.cleanupTimer);
|
|
436
|
+
this.unlistenExit();
|
|
435
437
|
try {
|
|
436
438
|
if (!noSave) {
|
|
437
439
|
await this.save();
|
|
@@ -448,7 +450,7 @@ export class DbServer {
|
|
|
448
450
|
}
|
|
449
451
|
async destroy() {
|
|
450
452
|
await this.stop(true);
|
|
451
|
-
await rm(this.fileSystemPath, { recursive: true }).catch((err) => console.warn('Error removing dump folder', err.message));
|
|
453
|
+
await rm(this.fileSystemPath, { recursive: true }).catch((err) => console.warn('Error removing dump folder', this.fileSystemPath, err.message));
|
|
452
454
|
}
|
|
453
455
|
}
|
|
454
456
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { DbServer } from './index.js';
|
|
2
|
-
export declare function save(db: DbServer): Promise<void>;
|
|
2
|
+
export declare function save(db: DbServer, sync?: boolean): void | Promise<void>;
|
package/dist/src/server/save.js
CHANGED
|
@@ -2,10 +2,14 @@ import native from '../native.js';
|
|
|
2
2
|
import { writeFile } from 'node:fs/promises';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { destructureCsmtKey, foreachDirtyBlock } from './tree.js';
|
|
5
|
+
import { writeFileSync } from 'node:fs';
|
|
5
6
|
const WRITELOG_FILE = 'writelog.json';
|
|
6
7
|
const COMMON_SDB_FILE = 'common.sdb';
|
|
7
8
|
const block_sdb_file = (typeId, start, end) => `${typeId}_${start}_${end}.sdb`;
|
|
8
|
-
export
|
|
9
|
+
export function save(db, sync = false) {
|
|
10
|
+
if (!db.dirtyRanges.size) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
9
13
|
let err;
|
|
10
14
|
const ts = Date.now();
|
|
11
15
|
err = native.saveCommon(join(db.fileSystemPath, COMMON_SDB_FILE), db.dbCtxExternal);
|
|
@@ -61,6 +65,8 @@ export async function save(db) {
|
|
|
61
65
|
if (mtRoot) {
|
|
62
66
|
data.hash = mtRoot.hash.toString('hex');
|
|
63
67
|
}
|
|
64
|
-
|
|
68
|
+
const filePath = join(db.fileSystemPath, WRITELOG_FILE);
|
|
69
|
+
const content = JSON.stringify(data);
|
|
70
|
+
return sync ? writeFileSync(filePath, content) : writeFile(filePath, content);
|
|
65
71
|
}
|
|
66
72
|
//# sourceMappingURL=save.js.map
|
package/dist/src/server/start.js
CHANGED
|
@@ -6,7 +6,9 @@ import { join } from 'node:path';
|
|
|
6
6
|
import { createTree } from './csmt/index.js';
|
|
7
7
|
import { foreachBlock } from './tree.js';
|
|
8
8
|
import { availableParallelism } from 'node:os';
|
|
9
|
+
import exitHook from 'exit-hook';
|
|
9
10
|
import './worker.js';
|
|
11
|
+
import { save } from './save.js';
|
|
10
12
|
const SCHEMA_FILE = 'schema.json';
|
|
11
13
|
const WRITELOG_FILE = 'writelog.json';
|
|
12
14
|
export const DEFAULT_BLOCK_CAPACITY = 100_000;
|
|
@@ -82,5 +84,10 @@ export async function start(db, opts) {
|
|
|
82
84
|
while (i--) {
|
|
83
85
|
db.workers[i] = new DbWorker(address, db);
|
|
84
86
|
}
|
|
87
|
+
db.unlistenExit = exitHook((signal) => {
|
|
88
|
+
console.log(`Exiting with signal: ${signal}`);
|
|
89
|
+
save(db, true);
|
|
90
|
+
console.log('Successfully saved.');
|
|
91
|
+
});
|
|
85
92
|
}
|
|
86
93
|
//# sourceMappingURL=start.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@based/db",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"@based/schema": "5.0.0-alpha.3",
|
|
35
35
|
"@saulx/hash": "^3.0.0",
|
|
36
36
|
"@saulx/utils": "^4.3.2",
|
|
37
|
+
"exit-hook": "^4.0.0",
|
|
37
38
|
"picocolors": "^1.1.0"
|
|
38
39
|
},
|
|
39
40
|
"optionalDependencies": {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|