@based/db 0.1.1 → 0.1.3-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/lib/darwin_aarch64/include/selva/hll.h +2 -0
  2. package/dist/lib/darwin_aarch64/include/selva/membar.h +9 -0
  3. package/dist/lib/darwin_aarch64/libdeflate.dylib +0 -0
  4. package/dist/lib/darwin_aarch64/libjemalloc_selva.2.dylib +0 -0
  5. package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
  6. package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
  7. package/dist/lib/darwin_aarch64/libnode-v24.node +0 -0
  8. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  9. package/dist/lib/darwin_aarch64/libxxhash.dylib +0 -0
  10. package/dist/lib/linux_aarch64/include/selva/hll.h +2 -0
  11. package/dist/lib/linux_aarch64/include/selva/membar.h +9 -0
  12. package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
  13. package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
  14. package/dist/lib/linux_aarch64/libnode-v24.node +0 -0
  15. package/dist/lib/linux_aarch64/libselva.so +0 -0
  16. package/dist/lib/linux_x86_64/include/selva/hll.h +2 -0
  17. package/dist/lib/linux_x86_64/include/selva/membar.h +9 -0
  18. package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
  19. package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
  20. package/dist/lib/linux_x86_64/libnode-v24.node +0 -0
  21. package/dist/lib/linux_x86_64/libselva.so +0 -0
  22. package/dist/src/client/index.d.ts +1 -2
  23. package/dist/src/client/modify/Ctx.js +1 -1
  24. package/dist/src/client/modify/cursor.d.ts +1 -1
  25. package/dist/src/client/modify/cursor.js +2 -2
  26. package/dist/src/client/modify/error.js +0 -2
  27. package/dist/src/client/modify/props/binary.js +2 -1
  28. package/dist/src/client/modify/props/cardinality.js +7 -0
  29. package/dist/src/client/modify/props/object.d.ts +2 -0
  30. package/dist/src/client/modify/props/object.js +50 -17
  31. package/dist/src/client/query/BasedQueryResponse.js +3 -8
  32. package/dist/src/client/query/display.js +9 -16
  33. package/dist/src/client/query/include/toByteCode.js +14 -10
  34. package/dist/src/client/query/queryDefToReadSchema.js +7 -2
  35. package/dist/src/client/query/registerQuery.js +4 -3
  36. package/dist/src/client/query/types.d.ts +1 -0
  37. package/dist/src/client/query/validation.js +4 -1
  38. package/dist/src/client/setLocalClientSchema.d.ts +1 -1
  39. package/dist/src/hooks.d.ts +1 -2
  40. package/dist/src/native.d.ts +2 -0
  41. package/dist/src/native.js +7 -1
  42. package/dist/src/server/index.d.ts +1 -2
  43. package/dist/src/server/index.js +2 -3
  44. package/dist/src/server/migrate/index.d.ts +1 -2
  45. package/dist/src/server/migrate/worker.js +31 -25
  46. package/dist/src/server/schema.d.ts +7 -3
  47. package/dist/src/server/schema.js +7 -56
  48. package/dist/src/server/workers/DbWorker.js +19 -5
  49. package/dist/src/shared/DbBase.d.ts +1 -1
  50. package/dist/src/shared/Emitter.d.ts +1 -1
  51. package/package.json +4 -4
  52. package/dist/src/schema.d.ts +0 -6
  53. package/dist/src/schema.js +0 -2
@@ -13,6 +13,8 @@
13
13
  SELVA_EXPORT
14
14
  void hll_init(struct selva_string *hllss, uint8_t precision, bool is_sparse);
15
15
  SELVA_EXPORT
16
+ void hll_init_like(struct selva_string *hlla, struct selva_string *hllb);
17
+ SELVA_EXPORT
16
18
  void hll_add(struct selva_string *hllss, uint64_t element);
17
19
  SELVA_EXPORT
18
20
  uint8_t *hll_count(struct selva_string *hllss);
@@ -4,6 +4,15 @@
4
4
  */
5
5
  #include "selva/_export.h"
6
6
 
7
+ /*
8
+ * When you run threads on different cores on Graviton it doesn't guarantee that
9
+ * a write in one thread is seen in the other one immediately.
10
+ * https://github.com/aws/aws-graviton-getting-started/blob/main/optimizing.md#ordering-issues
11
+ *
12
+ * This is also true on the Apple M arch:
13
+ * https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code
14
+ */
15
+
7
16
  /**
8
17
  * Read memory barrier.
9
18
  * Call this function before read in case another thread has potentially
@@ -13,6 +13,8 @@
13
13
  SELVA_EXPORT
14
14
  void hll_init(struct selva_string *hllss, uint8_t precision, bool is_sparse);
15
15
  SELVA_EXPORT
16
+ void hll_init_like(struct selva_string *hlla, struct selva_string *hllb);
17
+ SELVA_EXPORT
16
18
  void hll_add(struct selva_string *hllss, uint64_t element);
17
19
  SELVA_EXPORT
18
20
  uint8_t *hll_count(struct selva_string *hllss);
@@ -4,6 +4,15 @@
4
4
  */
5
5
  #include "selva/_export.h"
6
6
 
7
+ /*
8
+ * When you run threads on different cores on Graviton it doesn't guarantee that
9
+ * a write in one thread is seen in the other one immediately.
10
+ * https://github.com/aws/aws-graviton-getting-started/blob/main/optimizing.md#ordering-issues
11
+ *
12
+ * This is also true on the Apple M arch:
13
+ * https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code
14
+ */
15
+
7
16
  /**
8
17
  * Read memory barrier.
9
18
  * Call this function before read in case another thread has potentially
Binary file
@@ -13,6 +13,8 @@
13
13
  SELVA_EXPORT
14
14
  void hll_init(struct selva_string *hllss, uint8_t precision, bool is_sparse);
15
15
  SELVA_EXPORT
16
+ void hll_init_like(struct selva_string *hlla, struct selva_string *hllb);
17
+ SELVA_EXPORT
16
18
  void hll_add(struct selva_string *hllss, uint64_t element);
17
19
  SELVA_EXPORT
18
20
  uint8_t *hll_count(struct selva_string *hllss);
@@ -4,6 +4,15 @@
4
4
  */
5
5
  #include "selva/_export.h"
6
6
 
7
+ /*
8
+ * When you run threads on different cores on Graviton it doesn't guarantee that
9
+ * a write in one thread is seen in the other one immediately.
10
+ * https://github.com/aws/aws-graviton-getting-started/blob/main/optimizing.md#ordering-issues
11
+ *
12
+ * This is also true on the Apple M arch:
13
+ * https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code
14
+ */
15
+
7
16
  /**
8
17
  * Read memory barrier.
9
18
  * Call this function before read in case another thread has potentially
Binary file
@@ -1,9 +1,8 @@
1
- import { MigrateFns, Schema } from '@based/schema';
1
+ import { MigrateFns, Schema, SchemaChecksum } from '@based/schema';
2
2
  import { BasedDbQuery, QueryByAliasObj } from './query/BasedDbQuery.js';
3
3
  import { SubStore } from './query/subscription/index.js';
4
4
  import { DbShared } from '../shared/DbBase.js';
5
5
  import { DbClientHooks } from '../hooks.js';
6
- import { SchemaChecksum } from '../schema.js';
7
6
  import { ModifyOpts } from './modify/types.js';
8
7
  import { Ctx } from './modify/Ctx.js';
9
8
  type DbClientOpts = {
@@ -3,7 +3,7 @@ export class Ctx {
3
3
  constructor(schemaChecksum, array) {
4
4
  this.array = array;
5
5
  this.max = array.buffer.maxByteLength - 4; // dataLen
6
- this.size = array.buffer.byteLength - this.max;
6
+ this.size = array.buffer.byteLength - 4;
7
7
  writeUint64(array, schemaChecksum, 0);
8
8
  }
9
9
  id;
@@ -5,6 +5,6 @@ export declare const PROP_CURSOR_SIZE = 3;
5
5
  export declare const NODE_CURSOR_SIZE = 5;
6
6
  export declare const FULL_CURSOR_SIZE: number;
7
7
  export declare const writeTypeCursor: (ctx: Ctx) => void;
8
- export declare const writePropCursor: (ctx: Ctx, def: PropDef) => void;
8
+ export declare const writePropCursor: (ctx: Ctx, def: PropDef, typeIndex?: import("@based/schema/prop-types").TypeIndex) => void;
9
9
  export declare const writeMainCursor: (ctx: Ctx) => void;
10
10
  export declare const writeNodeCursor: (ctx: Ctx) => void;
@@ -16,11 +16,11 @@ export const writeTypeCursor = (ctx) => {
16
16
  ctx.cursor.id = null;
17
17
  }
18
18
  };
19
- export const writePropCursor = (ctx, def) => {
19
+ export const writePropCursor = (ctx, def, typeIndex = def.typeIndex) => {
20
20
  if (def.prop !== ctx.cursor.prop) {
21
21
  ctx.array[ctx.index] = SWITCH_FIELD;
22
22
  ctx.array[ctx.index + 1] = def.prop;
23
- ctx.array[ctx.index + 2] = def.typeIndex;
23
+ ctx.array[ctx.index + 2] = typeIndex;
24
24
  ctx.index += 3;
25
25
  ctx.cursor.prop = def.prop;
26
26
  }
@@ -47,8 +47,6 @@ export const handleError = (db, ctx, fn, args, e) => {
47
47
  return fn.apply(null, args);
48
48
  }
49
49
  if (typeof e.then === 'function') {
50
- if (e.id)
51
- process.exit();
52
50
  return e.then((id) => {
53
51
  if (!(e instanceof Tmp)) {
54
52
  e.id = id;
@@ -1,6 +1,7 @@
1
1
  import { writeU16, writeU32, writeU8, writeU8Array } from '../uint.js';
2
2
  import { PROP_CURSOR_SIZE, writePropCursor } from '../cursor.js';
3
3
  import { validate } from '../validate.js';
4
+ import { BINARY } from '@based/schema/def';
4
5
  import native from '../../../native.js';
5
6
  import { reserve } from '../resize.js';
6
7
  import { deleteProp } from './delete.js';
@@ -45,7 +46,7 @@ export const writeBinary = (ctx, def, val, validated) => {
45
46
  }
46
47
  const size = buf.byteLength + 6;
47
48
  reserve(ctx, PROP_CURSOR_SIZE + size + 11);
48
- writePropCursor(ctx, def);
49
+ writePropCursor(ctx, def, BINARY);
49
50
  writeU8(ctx, ctx.operation);
50
51
  writeBinaryRaw(ctx, buf);
51
52
  };
@@ -6,6 +6,7 @@ import { ENCODER } from '@based/utils';
6
6
  import { reserve } from '../resize.js';
7
7
  import { PROP_CURSOR_SIZE, writePropCursor } from '../cursor.js';
8
8
  import { CREATE } from '../types.js';
9
+ import { writeBinary } from './binary.js';
9
10
  export const writeCardinalityRaw = (ctx, def, val, sizeFixBecauseEdgeIsDifferent = val.length) => {
10
11
  writeU32(ctx, sizeFixBecauseEdgeIsDifferent);
11
12
  for (const item of val) {
@@ -27,6 +28,10 @@ export const writeCardinality = (ctx, def, val) => {
27
28
  deleteProp(ctx, def);
28
29
  return;
29
30
  }
31
+ if (val instanceof Uint8Array && val.byteLength !== 8) {
32
+ writeBinary(ctx, def, val, true);
33
+ return;
34
+ }
30
35
  if (!Array.isArray(val)) {
31
36
  val = [val];
32
37
  }
@@ -37,6 +42,8 @@ export const writeCardinality = (ctx, def, val) => {
37
42
  reserve(ctx, PROP_CURSOR_SIZE + size + 1);
38
43
  writePropCursor(ctx, def);
39
44
  writeU8(ctx, ctx.operation);
45
+ writeU8(ctx, def.cardinalityMode);
46
+ writeU8(ctx, def.cardinalityPrecision);
40
47
  writeCardinalityRaw(ctx, def, val);
41
48
  if (ctx.operation === CREATE) {
42
49
  ctx.schema.separateSort.bufferTmp[def.prop] = 2;
@@ -1,3 +1,5 @@
1
1
  import { SchemaTypeDef } from '@based/schema/def';
2
2
  import { Ctx } from '../Ctx.js';
3
+ export declare const writeObjectSafe: (ctx: Ctx, tree: SchemaTypeDef["tree"], obj: Record<string, any>) => void;
4
+ export declare const writeObjectUnsafe: (ctx: Ctx, tree: SchemaTypeDef["tree"], obj: Record<string, any>) => void;
3
5
  export declare const writeObject: (ctx: Ctx, tree: SchemaTypeDef["tree"], obj: Record<string, any>) => void;
@@ -2,7 +2,21 @@ import { isPropDef } from '@based/schema/def';
2
2
  import { writeSeparate } from './separate.js';
3
3
  import { writeMainValue } from './main.js';
4
4
  import { writeIncrement } from './increment.js';
5
- export const writeObject = (ctx, tree, obj) => {
5
+ const writeProp = (ctx, def, val) => {
6
+ if (def.separate) {
7
+ writeSeparate(ctx, def, val);
8
+ }
9
+ else if (ctx.overwrite) {
10
+ writeMainValue(ctx, def, val);
11
+ }
12
+ else if (typeof val === 'object' && val !== null) {
13
+ writeIncrement(ctx, def, val);
14
+ }
15
+ else {
16
+ ctx.main.set(def, val);
17
+ }
18
+ };
19
+ export const writeObjectSafe = (ctx, tree, obj) => {
6
20
  for (const key in obj) {
7
21
  const val = obj[key];
8
22
  if (val === undefined) {
@@ -10,28 +24,47 @@ export const writeObject = (ctx, tree, obj) => {
10
24
  }
11
25
  const def = tree[key];
12
26
  if (def === undefined) {
13
- if (ctx.unsafe) {
14
- continue;
15
- }
16
- throw [tree, key];
27
+ throw [def, val];
17
28
  }
18
- if (!isPropDef(def)) {
19
- writeObject(ctx, def, val);
20
- continue;
29
+ if (isPropDef(def)) {
30
+ writeProp(ctx, def, val);
21
31
  }
22
- if (def.separate) {
23
- writeSeparate(ctx, def, val);
24
- continue;
32
+ else {
33
+ writeObjectSafe(ctx, def, val);
25
34
  }
26
- if (ctx.overwrite) {
27
- writeMainValue(ctx, def, val);
35
+ }
36
+ };
37
+ export const writeObjectUnsafe = (ctx, tree, obj) => {
38
+ for (const key in obj) {
39
+ const def = tree[key];
40
+ const val = obj[key];
41
+ if (def === undefined || val === undefined) {
28
42
  continue;
29
43
  }
30
- if (typeof val === 'object' && val !== null) {
31
- writeIncrement(ctx, def, val);
32
- continue;
44
+ if (isPropDef(def)) {
45
+ const index = ctx.index;
46
+ try {
47
+ writeProp(ctx, def, val);
48
+ }
49
+ catch (e) {
50
+ if (Array.isArray(e)) {
51
+ ctx.index = index;
52
+ continue;
53
+ }
54
+ throw e;
55
+ }
33
56
  }
34
- ctx.main.set(def, val);
57
+ else {
58
+ writeObjectUnsafe(ctx, def, val);
59
+ }
60
+ }
61
+ };
62
+ export const writeObject = (ctx, tree, obj) => {
63
+ if (ctx.unsafe) {
64
+ writeObjectUnsafe(ctx, tree, obj);
65
+ }
66
+ else {
67
+ writeObjectSafe(ctx, tree, obj);
35
68
  }
36
69
  };
37
70
  //# sourceMappingURL=object.js.map
@@ -3,11 +3,8 @@ import picocolors from 'picocolors';
3
3
  import { debug } from './query.js';
4
4
  import { size, time, inspectData, defHasId, displayTarget } from './display.js';
5
5
  import { readFloatLE, readUint32 } from '@based/utils';
6
- import { resultToObject, readProps, readId, } from '@based/protocol/db-read';
6
+ import { resultToObject, readProps, readId, readChecksum, readVersion, } from '@based/protocol/db-read';
7
7
  export { time, size, inspectData };
8
- const BITS_FOR_BYTE_LEN = 21;
9
- const FACTOR = 2 ** BITS_FOR_BYTE_LEN;
10
- const MASK_B = FACTOR - 1;
11
8
  export class BasedQueryResponse {
12
9
  result;
13
10
  def;
@@ -26,7 +23,7 @@ export class BasedQueryResponse {
26
23
  return this.def.queryId;
27
24
  }
28
25
  get version() {
29
- return (this.checksum >>> 0) * FACTOR + (this.result.byteLength & MASK_B);
26
+ return readVersion(this.result);
30
27
  }
31
28
  get size() {
32
29
  return this.result.length;
@@ -106,9 +103,7 @@ export class BasedQueryResponse {
106
103
  return arr;
107
104
  }
108
105
  get checksum() {
109
- const result = this.result;
110
- const offset = result.byteLength - 4;
111
- return readUint32(result, offset);
106
+ return readChecksum(this.result);
112
107
  }
113
108
  get length() {
114
109
  const l = readUint32(this.result, 0);
@@ -1,7 +1,6 @@
1
1
  import picocolors from 'picocolors';
2
2
  import { BINARY, CARDINALITY, NUMBER, REFERENCE, REFERENCES, STRING, TEXT, TIMESTAMP, } from '@based/schema/def';
3
3
  import { ENCODER } from '@based/utils';
4
- import { AggregateType } from '@based/protocol/db-read';
5
4
  const decimals = (v) => ~~(v * 100) / 100;
6
5
  const sizeCalc = (size) => {
7
6
  if (size > 1e6) {
@@ -160,10 +159,7 @@ const inspectObject = (object, q, path, level, isLast, isFirst, isObject, depth)
160
159
  if (typeof v === 'number') {
161
160
  if (q.aggregate) {
162
161
  str += printNumber(v);
163
- // TBD: replace comptime const enum and reverse map it
164
- const [[__, akv], _] = q.aggregate.aggregates;
165
- const aggType = akv[0].type;
166
- str += picocolors.italic(picocolors.dim(` ${AggregateType[aggType].toLowerCase()}`));
162
+ str += picocolors.italic(picocolors.dim(` ${k.toLowerCase()}`));
167
163
  str += ',\n';
168
164
  }
169
165
  else {
@@ -179,9 +175,7 @@ const inspectObject = (object, q, path, level, isLast, isFirst, isObject, depth)
179
175
  if (def.typeIndex === REFERENCES) {
180
176
  if (q.aggregate) {
181
177
  str += printNumber(v);
182
- const [[__, akv], _] = q.aggregate.aggregates;
183
- const aggType = akv[0].type;
184
- str += picocolors.italic(picocolors.dim(` ${AggregateType[aggType].toLowerCase()}`));
178
+ str += picocolors.italic(picocolors.dim(` ${k.toLowerCase()}`));
185
179
  }
186
180
  else {
187
181
  str += inspectData(v, q.references.get(def.prop), level + 2, false, depth);
@@ -194,9 +188,7 @@ const inspectObject = (object, q, path, level, isLast, isFirst, isObject, depth)
194
188
  else {
195
189
  if (q.aggregate) {
196
190
  str += printNumber(v);
197
- const [[__, akv], _] = q.aggregate.aggregates;
198
- const aggType = akv[0].type;
199
- str += picocolors.italic(picocolors.dim(` ${AggregateType[aggType].toLowerCase()}`));
191
+ str += picocolors.italic(picocolors.dim(` ${k.toLowerCase()}`));
200
192
  }
201
193
  else {
202
194
  str += inspectObject(v, q.references.get(def.prop), '', level + 2, false, false, true, depth);
@@ -240,22 +232,23 @@ const inspectObject = (object, q, path, level, isLast, isFirst, isObject, depth)
240
232
  if (typeof v === 'number') {
241
233
  if (q.aggregate) {
242
234
  str += printNumber(v);
243
- const [[__, akv], _] = q.aggregate.aggregates;
244
- const aggType = akv[0].type;
245
- str += picocolors.italic(picocolors.dim(` ${AggregateType[aggType].toLowerCase()}`));
235
+ str += picocolors.italic(picocolors.dim(` ${k.toLowerCase()}`));
246
236
  }
247
237
  else {
248
238
  str += printNumber(v);
249
239
  }
250
240
  }
251
241
  else if (typeof v === 'object' && v) {
252
- inspectObject(v, q, key, level + 2, false, false, true, depth) + '';
242
+ str +=
243
+ inspectObject(v, q, key, level + 2, false, false, true, depth) + '';
253
244
  }
254
245
  else {
255
246
  str += v;
256
247
  }
257
248
  }
258
- if (def?.typeIndex !== REFERENCE && def?.typeIndex !== REFERENCES) {
249
+ if (def?.typeIndex !== REFERENCE &&
250
+ def?.typeIndex !== REFERENCES &&
251
+ typeof v !== 'object') {
259
252
  str += ',\n';
260
253
  }
261
254
  }
@@ -1,4 +1,4 @@
1
- import { MICRO_BUFFER, STRING, TEXT, JSON } from '@based/schema/def';
1
+ import { MICRO_BUFFER, STRING, TEXT, JSON, BINARY } from '@based/schema/def';
2
2
  import { QueryDefType } from '../types.js';
3
3
  import { walkDefs } from './walk.js';
4
4
  import { langCodesMap } from '@based/schema';
@@ -76,6 +76,7 @@ export const includeToBuffer = (db, def) => {
76
76
  }
77
77
  if (propSize) {
78
78
  for (const [prop, propDef] of def.include.props.entries()) {
79
+ const typeIndex = propDef.opts?.raw ? BINARY : propDef.def.typeIndex;
79
80
  if (propDef.opts?.meta) {
80
81
  if (propDef.opts.codes) {
81
82
  if (propDef.opts.codes.has(0)) {
@@ -84,7 +85,7 @@ export const includeToBuffer = (db, def) => {
84
85
  const buf = new Uint8Array(4);
85
86
  buf[0] = 6 /* includeOp.META */;
86
87
  buf[1] = prop;
87
- buf[2] = propDef.def.typeIndex;
88
+ buf[2] = typeIndex;
88
89
  buf[3] = langCodesMap.get(code);
89
90
  result.push(buf);
90
91
  }
@@ -94,7 +95,7 @@ export const includeToBuffer = (db, def) => {
94
95
  const buf = new Uint8Array(4);
95
96
  buf[0] = 6 /* includeOp.META */;
96
97
  buf[1] = prop;
97
- buf[2] = propDef.def.typeIndex;
98
+ buf[2] = typeIndex;
98
99
  buf[3] = code;
99
100
  result.push(buf);
100
101
  }
@@ -104,21 +105,20 @@ export const includeToBuffer = (db, def) => {
104
105
  const buf = new Uint8Array(4);
105
106
  buf[0] = 6 /* includeOp.META */;
106
107
  buf[1] = prop;
107
- buf[2] = propDef.def.typeIndex;
108
+ buf[2] = typeIndex;
108
109
  buf[3] = 0;
109
110
  result.push(buf);
110
111
  }
111
112
  }
112
113
  if (propDef.opts?.meta !== 'only') {
113
114
  const hasEnd = propDef.opts?.end;
114
- const t = propDef.def.typeIndex;
115
- if (t === TEXT) {
115
+ if (typeIndex === TEXT) {
116
116
  const codes = propDef.opts.codes;
117
117
  if (codes.has(0)) {
118
118
  const b = new Uint8Array(hasEnd ? 12 : 4);
119
119
  b[0] = 1 /* includeOp.DEFAULT */;
120
120
  b[1] = prop;
121
- b[2] = propDef.def.typeIndex;
121
+ b[2] = typeIndex;
122
122
  if (hasEnd) {
123
123
  b[3] = 8; // opts len
124
124
  b[4] = 0; // lang code
@@ -139,7 +139,7 @@ export const includeToBuffer = (db, def) => {
139
139
  const b = new Uint8Array(7 + (endCode ? 5 : 0) + fallBackSize);
140
140
  b[0] = 1 /* includeOp.DEFAULT */;
141
141
  b[1] = prop;
142
- b[2] = propDef.def.typeIndex;
142
+ b[2] = typeIndex;
143
143
  let i = 0;
144
144
  if (endCode) {
145
145
  b[3] = fallBackSize + 8; // opts
@@ -169,10 +169,14 @@ export const includeToBuffer = (db, def) => {
169
169
  const buf = new Uint8Array(hasEnd ? 9 : 4);
170
170
  buf[0] = 1 /* includeOp.DEFAULT */;
171
171
  buf[1] = prop;
172
- buf[2] = propDef.def.typeIndex;
172
+ buf[2] = typeIndex;
173
173
  if (hasEnd) {
174
174
  buf[3] = 5; // opts len
175
- buf[4] = propDef.opts?.bytes || (t !== JSON && t !== STRING) ? 0 : 1;
175
+ buf[4] =
176
+ propDef.opts?.bytes ||
177
+ (typeIndex !== JSON && typeIndex !== STRING)
178
+ ? 0
179
+ : 1;
176
180
  writeUint32(buf, getEnd(propDef.opts), 5);
177
181
  }
178
182
  else {
@@ -1,11 +1,11 @@
1
1
  // import type { IncludeOpts, QueryDef, Target } from '@based/db'
2
2
  import { inverseLangMap, langCodesMap } from '@based/schema';
3
- import { COLVEC, ENUM, TEXT, VECTOR, } from '@based/schema/def';
3
+ import { COLVEC, ENUM, TEXT, VECTOR, BINARY, CARDINALITY, } from '@based/schema/def';
4
4
  import { ReaderMeta, ReaderSchemaEnum, } from '@based/protocol/db-read';
5
5
  const createReaderPropDef = (p, locales, opts) => {
6
6
  const readerPropDef = {
7
7
  path: p.__isEdge ? p.path.slice(1) : p.path,
8
- typeIndex: p.typeIndex,
8
+ typeIndex: opts?.raw ? BINARY : p.typeIndex,
9
9
  readBy: 0,
10
10
  };
11
11
  if (opts?.meta) {
@@ -19,6 +19,10 @@ const createReaderPropDef = (p, locales, opts) => {
19
19
  readerPropDef.vectorBaseType = p.vectorBaseType;
20
20
  readerPropDef.len = p.len;
21
21
  }
22
+ if (p.typeIndex === CARDINALITY) {
23
+ readerPropDef.cardinalityMode = p.cardinalityMode;
24
+ readerPropDef.cardinalityPrecision = p.cardinalityPrecision;
25
+ }
22
26
  if (p.typeIndex === TEXT) {
23
27
  if (opts.codes.has(0)) {
24
28
  readerPropDef.locales = locales;
@@ -51,6 +55,7 @@ export const convertToReaderSchema = (q, locales) => {
51
55
  const readerSchema = {
52
56
  readId: 0,
53
57
  props: {},
58
+ search: false,
54
59
  main: { len: 0, props: {} },
55
60
  refs: {},
56
61
  type: isEdge
@@ -15,11 +15,9 @@ export const registerQuery = (q) => {
15
15
  q.target, q.skipValidation);
16
16
  def.schemaChecksum = q.db.schema?.hash || 0;
17
17
  q.def = def;
18
- // proposal:
19
18
  for (const command of commands) {
20
19
  q[command.method](...command.args);
21
20
  }
22
- // locale first...
23
21
  if (!q.def.include.stringFields.size && !q.def.references.size) {
24
22
  includeField(q.def, { field: '*' });
25
23
  }
@@ -32,10 +30,13 @@ export const registerQuery = (q) => {
32
30
  q.buffer = buf;
33
31
  // console.log('--------------------------------------------------')
34
32
  // console.dir(convertToReaderSchema(q.def), { depth: 100 })
35
- // console.log(deSerializeSchema(serialize(convertToReaderSchema(q.def))))
33
+ // const c = convertToReaderSchema(q.def)
34
+ // const s = serialize(c)
35
+ // console.log(deSerializeSchema(s))
36
36
  // q.def.readSchema = deSerializeSchema(
37
37
  // serialize(convertToReaderSchema(q.def)),
38
38
  // )
39
+ // console.log('--------------------------------------------------')
39
40
  q.def.readSchema = convertToReaderSchema(q.def);
40
41
  handleErrors(q.def);
41
42
  return buf;
@@ -13,6 +13,7 @@ export type IncludeOpts = {
13
13
  codes?: Set<LangCode>;
14
14
  fallBacks?: LangCode[];
15
15
  localeFromDef?: LangCode;
16
+ raw?: true;
16
17
  };
17
18
  export type IncludeField = {
18
19
  field: string;
@@ -352,7 +352,10 @@ export const validateAlias = (def, alias, path) => {
352
352
  if (typeof alias[k] === 'string') {
353
353
  const p = path ? `${path}.${k}` : k;
354
354
  const prop = schema.props[p];
355
- if (prop.typeIndex === ALIAS) {
355
+ if (!prop) {
356
+ // def.errors.push({ code: ERR_TARGET_INVAL_ALIAS, payload: def })
357
+ }
358
+ else if (prop.typeIndex === ALIAS) {
356
359
  return { def: prop, value: alias[k] };
357
360
  }
358
361
  }
@@ -1,3 +1,3 @@
1
+ import { DbSchema } from '@based/schema';
1
2
  import { DbClient } from '../index.js';
2
- import { DbSchema } from '../schema.js';
3
3
  export declare const setLocalClientSchema: (client: DbClient, schema: DbSchema) => DbSchema;
@@ -1,8 +1,7 @@
1
- import { StrictSchema, MigrateFns } from '@based/schema';
1
+ import { StrictSchema, MigrateFns, DbSchema, SchemaChecksum } from '@based/schema';
2
2
  import { BasedDbQuery } from './client/query/BasedDbQuery.js';
3
3
  import { OnClose, OnData, OnError } from './client/query/subscription/types.js';
4
4
  import { DbServer } from './server/index.js';
5
- import { DbSchema, SchemaChecksum } from './schema.js';
6
5
  export type DbClientHooks = {
7
6
  setSchema(schema: StrictSchema, transformFns?: MigrateFns): Promise<SchemaChecksum>;
8
7
  flushModify(buf: Uint8Array): Promise<{
@@ -16,6 +16,8 @@ declare const native: {
16
16
  updateSchemaType: (prefix: number, buf: Uint8Array, dbCtx: any) => any;
17
17
  getTypeInfo: (typeId: number, dbCtx: any) => any;
18
18
  getNodeRangeHash: (typeId: number, start: number, end: number, bufOut: Uint8Array, dbCtx: any) => any;
19
+ createCompressor(): any;
20
+ compressRaw: (compressor: any, buf: Uint8Array, offset: number, stringSize: number) => any;
19
21
  compress: (buf: Uint8Array, offset: number, stringSize: number) => any;
20
22
  decompress: (input: Uint8Array, output: Uint8Array, offset: number, len: number) => any;
21
23
  crc32: (buf: Uint8Array) => any;
@@ -74,6 +74,12 @@ const native = {
74
74
  getNodeRangeHash: (typeId, start, end, bufOut, dbCtx) => {
75
75
  return db.getNodeRangeHash(typeId, start, end, bufOut, dbCtx);
76
76
  },
77
+ createCompressor() {
78
+ return db.createCompressor();
79
+ },
80
+ compressRaw: (compressor, buf, offset, stringSize) => {
81
+ return db.compress(compressor, buf, offset, stringSize);
82
+ },
77
83
  compress: (buf, offset, stringSize) => {
78
84
  return db.compress(compressor, buf, offset, stringSize);
79
85
  },
@@ -106,7 +112,7 @@ const native = {
106
112
  },
107
113
  colvecTest: (dbCtx, typeId, field, nodeId, len) => {
108
114
  return db.colvecTest(dbCtx, typeId, field, nodeId, len);
109
- }
115
+ },
110
116
  };
111
117
  global.__basedDb__native__ = native;
112
118
  export default native;
@@ -1,8 +1,7 @@
1
- import { LangName, MigrateFns, StrictSchema } from '@based/schema';
1
+ import { StrictSchema, LangName, MigrateFns, SchemaChecksum } from '@based/schema';
2
2
  import { StartOpts } from './start.js';
3
3
  import { VerifTree } from './tree.js';
4
4
  import exitHook from 'exit-hook';
5
- import { SchemaChecksum } from '../schema.js';
6
5
  import { IoWorker } from './IoWorker.js';
7
6
  import { QueryWorker } from './QueryWorker.js';
8
7
  import { DbShared } from '../shared/DbBase.js';
@@ -1,6 +1,6 @@
1
1
  import native from '../native.js';
2
2
  import { rm } from 'node:fs/promises';
3
- import { langCodesMap } from '@based/schema';
3
+ import { langCodesMap, strictSchemaToDbSchema } from '@based/schema';
4
4
  import { ID_FIELD_DEF } from '@based/schema/def';
5
5
  import { start } from './start.js';
6
6
  import { destructureTreeKey, makeTreeKeyFromNodeId } from './tree.js';
@@ -10,7 +10,6 @@ import { migrate } from './migrate/index.js';
10
10
  import { debugServer } from '../utils.js';
11
11
  import { readUint16, readUint32, readUint64, writeUint32 } from '@based/utils';
12
12
  import { QueryType } from '../client/query/types.js';
13
- import { strictSchemaToDbSchema } from './schema.js';
14
13
  import { DbShared } from '../shared/DbBase.js';
15
14
  import { setNativeSchema, setSchemaOnServer, writeSchemaFile, } from './schema.js';
16
15
  import { resizeModifyDirtyRanges } from './resizeModifyDirtyRanges.js';
@@ -263,8 +262,8 @@ export class DbServer extends DbShared {
263
262
  return this.schema.hash;
264
263
  }
265
264
  setSchemaOnServer(this, schema);
265
+ setNativeSchema(this, schema);
266
266
  await writeSchemaFile(this, schema);
267
- await setNativeSchema(this, schema);
268
267
  process.nextTick(() => {
269
268
  this.emit('schema', this.schema);
270
269
  });
@@ -1,6 +1,5 @@
1
1
  import { DbServer } from '../index.js';
2
- import { DbSchema } from '../../schema.js';
3
- import { MigrateFns } from '@based/schema';
2
+ import { DbSchema, MigrateFns } from '@based/schema';
4
3
  export type MigrateRange = {
5
4
  typeId: number;
6
5
  start: number;
@@ -1,7 +1,7 @@
1
1
  import { isMainThread, receiveMessageOnPort, workerData, } from 'node:worker_threads';
2
2
  import native from '../../native.js';
3
3
  import { BasedDb } from '../../index.js';
4
- import { REFERENCE, REFERENCES } from '@based/schema/def';
4
+ import { CARDINALITY, REFERENCE, REFERENCES } from '@based/schema/def';
5
5
  import { setSchemaOnServer } from '../schema.js';
6
6
  import { setToSleep } from './utils.js';
7
7
  import { setLocalClientSchema } from '../../client/setLocalClientSchema.js';
@@ -27,28 +27,36 @@ else if (workerData?.isDbMigrateWorker) {
27
27
  const map = {};
28
28
  for (const type in fromDb.server.schemaTypesParsed) {
29
29
  const { id, props } = fromDb.server.schemaTypesParsed[type];
30
- const include = Object.keys(props);
31
- let i = include.length;
32
- while (i--) {
33
- const path = include[i];
34
- if (props[path].typeIndex === REFERENCE ||
35
- props[path].typeIndex === REFERENCES) {
36
- include[i] = `${path}.id`;
37
- if (props[path].edges) {
38
- for (const key in props[path].edges) {
39
- const prop = props[path].edges[key];
40
- if (prop.typeIndex === REFERENCE ||
41
- prop.typeIndex === REFERENCES) {
30
+ const include = [];
31
+ const includeRaw = [];
32
+ for (const path in props) {
33
+ const prop = props[path];
34
+ if (prop.typeIndex === REFERENCE || prop.typeIndex === REFERENCES) {
35
+ include.push(`${path}.id`);
36
+ if (prop.edges) {
37
+ for (const key in prop.edges) {
38
+ const edge = prop.edges[key];
39
+ if (edge.typeIndex === REFERENCE ||
40
+ edge.typeIndex === REFERENCES) {
42
41
  include.push(`${path}.${key}.id`);
43
42
  }
43
+ else if (edge.typeIndex === CARDINALITY) {
44
+ includeRaw.push(`${path}.${key}`);
45
+ }
44
46
  else {
45
47
  include.push(`${path}.${key}`);
46
48
  }
47
49
  }
48
50
  }
49
51
  }
52
+ else if (prop.typeIndex === CARDINALITY) {
53
+ includeRaw.push(path);
54
+ }
55
+ else {
56
+ include.push(path);
57
+ }
50
58
  }
51
- map[id] = { type, include };
59
+ map[id] = { type, include, includeRaw };
52
60
  }
53
61
  for (const type in transformFns) {
54
62
  const fnOrNull = transformFns[type];
@@ -58,14 +66,17 @@ else if (workerData?.isDbMigrateWorker) {
58
66
  let msg;
59
67
  while ((msg = receiveMessageOnPort(channel))) {
60
68
  const leafData = msg.message;
61
- const { type, include } = map[leafData.typeId];
69
+ const { type, include, includeRaw } = map[leafData.typeId];
62
70
  const typeTransformFn = transformFns[type];
71
+ const query = fromDb
72
+ .query(type)
73
+ .range(leafData.start - 1, leafData.end)
74
+ .include(include);
75
+ for (const rawProp of includeRaw) {
76
+ query.include(rawProp, { raw: true });
77
+ }
78
+ const nodes = query._getSync(fromCtx);
63
79
  if (typeTransformFn) {
64
- const nodes = fromDb
65
- .query(type)
66
- .include(include)
67
- .range(leafData.start - 1, leafData.end)
68
- ._getSync(fromCtx);
69
80
  for (const node of nodes) {
70
81
  const res = typeTransformFn(node);
71
82
  if (res === null) {
@@ -80,11 +91,6 @@ else if (workerData?.isDbMigrateWorker) {
80
91
  }
81
92
  }
82
93
  else if (type in toDb.server.schemaTypesParsed) {
83
- const nodes = fromDb
84
- .query(type)
85
- .include(include)
86
- .range(leafData.start - 1, leafData.end)
87
- ._getSync(fromCtx);
88
94
  for (const node of nodes) {
89
95
  toDb.create(type, node, { unsafe: true });
90
96
  }
@@ -1,7 +1,11 @@
1
- import { StrictSchema } from '@based/schema';
1
+ import { DbSchema } from '@based/schema';
2
2
  import { DbServer } from './index.js';
3
- import { DbSchema } from '../schema.js';
4
3
  export declare const setSchemaOnServer: (server: DbServer, schema: DbSchema) => void;
5
4
  export declare const writeSchemaFile: (server: DbServer, schema: DbSchema) => Promise<void>;
5
+ /**
6
+ * Set schema used in native code.
7
+ * This function should be only called when a new schema is set to an empty DB
8
+ * instance. If a `common.sdb` file is loaded then calling this function isn't
9
+ * necessary because `common.sdb` already contains the required schema.
10
+ */
6
11
  export declare const setNativeSchema: (server: DbServer, schema: DbSchema) => void;
7
- export declare const strictSchemaToDbSchema: (schema: StrictSchema) => DbSchema;
@@ -1,12 +1,10 @@
1
1
  import { schemaToSelvaBuffer, updateTypeDefs } from '@based/schema/def';
2
- import { deepCopy } from '@based/utils';
3
- import { getPropType, serialize } from '@based/schema';
2
+ import { serialize } from '@based/schema';
4
3
  import { join } from 'node:path';
5
4
  import { writeFile } from 'node:fs/promises';
6
5
  import native from '../native.js';
7
6
  import { SCHEMA_FILE } from '../types.js';
8
7
  import { saveSync } from './save.js';
9
- import { hash } from '@based/hash';
10
8
  import { writeCreate } from '../client/modify/create/index.js';
11
9
  import { Ctx } from '../client/modify/Ctx.js';
12
10
  import { consume } from '../client/modify/drain.js';
@@ -27,6 +25,12 @@ export const writeSchemaFile = async (server, schema) => {
27
25
  }
28
26
  }
29
27
  };
28
+ /**
29
+ * Set schema used in native code.
30
+ * This function should be only called when a new schema is set to an empty DB
31
+ * instance. If a `common.sdb` file is loaded then calling this function isn't
32
+ * necessary because `common.sdb` already contains the required schema.
33
+ */
30
34
  export const setNativeSchema = (server, schema) => {
31
35
  const types = Object.keys(server.schemaTypesParsed);
32
36
  const s = schemaToSelvaBuffer(server.schemaTypesParsed);
@@ -52,57 +56,4 @@ export const setNativeSchema = (server, schema) => {
52
56
  saveSync(server, { skipDirtyCheck: true });
53
57
  }
54
58
  };
55
- export const strictSchemaToDbSchema = (schema) => {
56
- // @ts-ignore
57
- let dbSchema = deepCopy(schema);
58
- // reserve 1 for root (even if you dont have it)
59
- dbSchema.lastId = 1;
60
- if (dbSchema.props) {
61
- for (const key in dbSchema.props) {
62
- const prop = dbSchema.props[key];
63
- const propType = getPropType(prop);
64
- let refProp;
65
- if (propType === 'reference') {
66
- refProp = prop;
67
- }
68
- else if (propType === 'references') {
69
- refProp = prop.items;
70
- prop.items = refProp;
71
- }
72
- if (refProp) {
73
- const type = dbSchema.types[refProp.ref];
74
- const inverseKey = '_' + key;
75
- dbSchema.types[refProp.ref] = {
76
- ...type,
77
- props: {
78
- ...type.props,
79
- [inverseKey]: {
80
- items: {
81
- ref: '_root',
82
- prop: key,
83
- },
84
- },
85
- },
86
- };
87
- refProp.prop = inverseKey;
88
- }
89
- }
90
- dbSchema.types ??= {};
91
- // @ts-ignore This creates an internal type to use for root props
92
- dbSchema.types._root = {
93
- id: 1,
94
- props: dbSchema.props,
95
- };
96
- delete dbSchema.props;
97
- }
98
- for (const field in dbSchema.types) {
99
- if (!('id' in dbSchema.types[field])) {
100
- dbSchema.lastId++;
101
- dbSchema.types[field].id = dbSchema.lastId;
102
- }
103
- }
104
- const { hash: _, ...rest } = dbSchema;
105
- dbSchema.hash = hash(rest);
106
- return dbSchema;
107
- };
108
59
  //# sourceMappingURL=schema.js.map
@@ -18,14 +18,19 @@ export class DbWorker {
18
18
  },
19
19
  transferList: [port2],
20
20
  });
21
- this.readyPromise = new Promise((resolve) => {
21
+ this.readyPromise = new Promise((resolve, reject) => {
22
22
  const onReady = (msg) => {
23
23
  if (msg?.status === 'READY') {
24
24
  // TODO Also call native.destroyThreadCtx() somewhere
25
25
  this.#threadId = msg.threadId;
26
- native.createThreadCtx(db.dbCtxExternal, this.#threadId);
27
- this.worker.off('message', onReady);
28
- resolve(true);
26
+ try {
27
+ native.createThreadCtx(db.dbCtxExternal, this.#threadId);
28
+ this.worker.off('message', onReady);
29
+ resolve(true);
30
+ }
31
+ catch (e) {
32
+ reject(e);
33
+ }
29
34
  }
30
35
  };
31
36
  this.worker.on('message', onReady);
@@ -58,8 +63,17 @@ export class DbWorker {
58
63
  resolvers = [];
59
64
  readyPromise;
60
65
  async terminate() {
61
- // TODO do we want to force this.worker.terminate() after a timeout?
66
+ // worker.terminate() is known to cause crashes but this is the best we can
67
+ // do if the thread won't exit voluntarily.
68
+ const tim = setTimeout(() => this.worker.terminate(), 5e3);
69
+ const p = new Promise((resolve) => {
70
+ this.worker.on('exit', () => {
71
+ clearTimeout(tim);
72
+ resolve();
73
+ });
74
+ });
62
75
  await this.call(0n);
76
+ return p;
63
77
  }
64
78
  callback = (resolve) => {
65
79
  this.resolvers.push(resolve);
@@ -1,5 +1,5 @@
1
1
  import { SchemaTypeDef } from '@based/schema/def';
2
- import { DbSchema } from '../schema.js';
2
+ import { DbSchema } from '@based/schema';
3
3
  import { Emitter } from './Emitter.js';
4
4
  export type EventMap = {
5
5
  schema: DbSchema;
@@ -1,4 +1,4 @@
1
- import { DbSchema } from '../schema.js';
1
+ import { DbSchema } from "@based/schema";
2
2
  export type EventMap = {
3
3
  schema: DbSchema;
4
4
  info: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@based/db",
3
- "version": "0.1.1",
3
+ "version": "0.1.3-alpha.1",
4
4
  "type": "module",
5
5
  "main": "./dist/src/index.js",
6
6
  "scripts": {
@@ -22,7 +22,7 @@
22
22
  "test-fast-linux_aarch64-schema": "podman run --rm -v \"$PWD/../..:/usr/src/based-db\" based-db-clibs-build-linux_aarch64 sh -c '\\. \"/usr/local/nvm/nvm.sh\"; cd /usr/src/based-db/packages/db; npm run test-fast schemadebug'",
23
23
  "test-fast-linux_aarch64": "podman run --rm -v \"$PWD/../..:/usr/src/based-db\" based-db-clibs-build-linux_aarch64 sh -c '\\. \"/usr/local/nvm/nvm.sh\"; cd /usr/src/based-db/packages/db; npm run test-fast'",
24
24
  "test-fast-linux_aarch64-gdb": "podman run --rm -v \"$PWD/../..:/usr/src/based-db\" based-db-clibs-build-linux_aarch64 sh -c '\\. \"/usr/local/nvm/nvm.sh\"; cd /usr/src/based-db/packages/db; LOCPATH=../locale/locale-x86_64-gnu/locale gdb -ex run --args node ./scripts/test.js'",
25
- "test-fast-linux_aarch64-valgrind": "podman run --rm -v \"$PWD/../..:/usr/src/based-db\" based-db-clibs-build-linux_aarch64 sh -c '\\. \"/usr/local/nvm/nvm.sh\"; cd /usr/src/based-db/packages/db; LOCPATH=../locale/locale-aarch64-gnu/locale valgrind --leak-check=full node ./scripts/test.js references:update2'",
25
+ "test-fast-linux_aarch64-valgrind": "podman run --rm -v \"$PWD/../..:/usr/src/based-db\" based-db-clibs-build-linux_aarch64 sh -c '\\. \"/usr/local/nvm/nvm.sh\"; cd /usr/src/based-db/packages/db; LOCPATH=../locale/locale-aarch64-gnu/locale valgrind --leak-check=full node ./scripts/test.js'",
26
26
  "test-vector": "podman run --rm -v \"$PWD/../..:/usr/src/based-db\" based-db-clibs-build-linux_aarch64 sh -c '\\. \"/usr/local/nvm/nvm.sh\"; cd /usr/src/based-db/packages/db; npm run test-fast -- mem.js'",
27
27
  "test-zig": "npm run build-zig && tsc && npm run test-fast",
28
28
  "test-zig-debug": "npm run build-zig -- debug && tsc && LOCPATH=../locale/locale-x86_64-gnu/locale ./scripts/lldb-node ./scripts/test.js",
@@ -43,8 +43,8 @@
43
43
  "dependencies": {
44
44
  "@based/hash": "1.0.0",
45
45
  "@based/schema": "^5.0.2",
46
- "@based/utils": "^1.0.0",
47
- "@based/protocol": "^0.0.3",
46
+ "@based/utils": "^1.1.0",
47
+ "@based/protocol": "^0.0.4",
48
48
  "exit-hook": "^4.0.0",
49
49
  "picocolors": "^1.1.0"
50
50
  },
@@ -1,6 +0,0 @@
1
- import { StrictSchema } from '@based/schema';
2
- export type DbSchema = StrictSchema & {
3
- lastId: number;
4
- hash: number;
5
- };
6
- export type SchemaChecksum = number;
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=schema.js.map