@based/db 0.1.5 → 0.2.0

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 (120) hide show
  1. package/dist/lib/darwin_aarch64/include/cdefs.h +4 -0
  2. package/dist/lib/darwin_aarch64/include/selva/db.h +25 -5
  3. package/dist/lib/darwin_aarch64/include/selva/fields.h +34 -72
  4. package/dist/lib/darwin_aarch64/include/selva/selva_lang.h +7 -0
  5. package/dist/lib/darwin_aarch64/include/selva/types.h +9 -13
  6. package/dist/lib/darwin_aarch64/libdeflate.dylib +0 -0
  7. package/dist/lib/darwin_aarch64/libjemalloc_selva.2.dylib +0 -0
  8. package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
  9. package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
  10. package/dist/lib/darwin_aarch64/libnode-v24.node +0 -0
  11. package/dist/lib/darwin_aarch64/libnode-v25.node +0 -0
  12. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  13. package/dist/lib/linux_aarch64/include/cdefs.h +4 -0
  14. package/dist/lib/linux_aarch64/include/selva/db.h +25 -5
  15. package/dist/lib/linux_aarch64/include/selva/fields.h +34 -72
  16. package/dist/lib/linux_aarch64/include/selva/selva_lang.h +7 -0
  17. package/dist/lib/linux_aarch64/include/selva/types.h +9 -13
  18. package/dist/lib/linux_aarch64/libdeflate.so +0 -0
  19. package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
  20. package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
  21. package/dist/lib/linux_aarch64/libnode-v24.node +0 -0
  22. package/dist/lib/linux_aarch64/libnode-v25.node +0 -0
  23. package/dist/lib/linux_aarch64/libselva.so +0 -0
  24. package/dist/lib/linux_x86_64/include/cdefs.h +4 -0
  25. package/dist/lib/linux_x86_64/include/selva/db.h +25 -5
  26. package/dist/lib/linux_x86_64/include/selva/fields.h +34 -72
  27. package/dist/lib/linux_x86_64/include/selva/selva_lang.h +7 -0
  28. package/dist/lib/linux_x86_64/include/selva/types.h +9 -13
  29. package/dist/lib/linux_x86_64/libdeflate.so +0 -0
  30. package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
  31. package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
  32. package/dist/lib/linux_x86_64/libnode-v24.node +0 -0
  33. package/dist/lib/linux_x86_64/libnode-v25.node +0 -0
  34. package/dist/lib/linux_x86_64/libselva.so +0 -0
  35. package/dist/src/client/modify/Tmp.d.ts +0 -1
  36. package/dist/src/client/modify/Tmp.js +14 -9
  37. package/dist/src/client/modify/create/index.js +6 -5
  38. package/dist/src/client/modify/drain.js +6 -2
  39. package/dist/src/client/modify/edges/binary.js +3 -2
  40. package/dist/src/client/modify/edges/reference.js +2 -3
  41. package/dist/src/client/modify/edges/references.js +2 -3
  42. package/dist/src/client/modify/edges/separate.js +4 -1
  43. package/dist/src/client/modify/edges/string.js +2 -3
  44. package/dist/src/client/modify/error.d.ts +29 -0
  45. package/dist/src/client/modify/error.js +10 -0
  46. package/dist/src/client/modify/props/alias.js +1 -1
  47. package/dist/src/client/modify/props/binary.js +1 -1
  48. package/dist/src/client/modify/props/cardinality.js +1 -1
  49. package/dist/src/client/modify/props/fixed.js +13 -14
  50. package/dist/src/client/modify/props/reference.js +2 -2
  51. package/dist/src/client/modify/props/references.js +7 -7
  52. package/dist/src/client/modify/props/string.js +1 -1
  53. package/dist/src/client/modify/props/vector.js +1 -11
  54. package/dist/src/client/modify/types.d.ts +1 -0
  55. package/dist/src/client/modify/types.js +1 -0
  56. package/dist/src/client/modify/validate.d.ts +1 -1
  57. package/dist/src/client/modify/validate.js +4 -3
  58. package/dist/src/client/query/BasedDbQuery.d.ts +4 -4
  59. package/dist/src/client/query/BasedDbQuery.js +23 -12
  60. package/dist/src/client/query/BasedQueryResponse.d.ts +0 -1
  61. package/dist/src/client/query/BasedQueryResponse.js +0 -3
  62. package/dist/src/client/query/aggregates/aggregation.d.ts +1 -1
  63. package/dist/src/client/query/aggregates/aggregation.js +123 -51
  64. package/dist/src/client/query/display.js +14 -8
  65. package/dist/src/client/query/filter/createFixedFilterBuffer.js +59 -22
  66. package/dist/src/client/query/filter/createReferenceFilter.js +13 -13
  67. package/dist/src/client/query/filter/createVariableFilterBuffer.js +6 -3
  68. package/dist/src/client/query/filter/filter.js +8 -0
  69. package/dist/src/client/query/filter/primitiveFilter.js +4 -1
  70. package/dist/src/client/query/filter/{toBuffer.d.ts → toByteCode.d.ts} +3 -2
  71. package/dist/src/client/query/filter/{toBuffer.js → toByteCode.js} +46 -12
  72. package/dist/src/client/query/filter/types.d.ts +1 -0
  73. package/dist/src/client/query/filter/types.js +33 -5
  74. package/dist/src/client/query/include/toByteCode.d.ts +2 -2
  75. package/dist/src/client/query/include/toByteCode.js +1 -1
  76. package/dist/src/client/query/query.d.ts +1 -1
  77. package/dist/src/client/query/query.js +1 -1
  78. package/dist/src/client/query/queryDef.js +6 -2
  79. package/dist/src/client/query/registerQuery.js +5 -9
  80. package/dist/src/client/query/subscription/index.js +5 -0
  81. package/dist/src/client/query/subscription/toByteCode.d.ts +6 -0
  82. package/dist/src/client/query/subscription/toByteCode.js +139 -0
  83. package/dist/src/client/query/subscription/types.d.ts +6 -0
  84. package/dist/src/client/query/subscription/types.js +7 -9
  85. package/dist/src/client/query/toByteCode/aggregates.d.ts +2 -0
  86. package/dist/src/client/query/toByteCode/aggregates.js +60 -0
  87. package/dist/src/client/query/toByteCode/alias.d.ts +2 -0
  88. package/dist/src/client/query/toByteCode/alias.js +24 -0
  89. package/dist/src/client/query/toByteCode/default.d.ts +2 -2
  90. package/dist/src/client/query/toByteCode/default.js +21 -24
  91. package/dist/src/client/query/toByteCode/id.d.ts +2 -0
  92. package/dist/src/client/query/toByteCode/id.js +17 -0
  93. package/dist/src/client/query/toByteCode/ids.d.ts +2 -0
  94. package/dist/src/client/query/toByteCode/ids.js +52 -0
  95. package/dist/src/client/query/toByteCode/offsets.d.ts +35 -0
  96. package/dist/src/client/query/toByteCode/offsets.js +36 -0
  97. package/dist/src/client/query/toByteCode/reference.d.ts +2 -0
  98. package/dist/src/client/query/toByteCode/reference.js +12 -0
  99. package/dist/src/client/query/toByteCode/references.d.ts +2 -0
  100. package/dist/src/client/query/toByteCode/references.js +35 -0
  101. package/dist/src/client/query/toByteCode/toByteCode.d.ts +4 -2
  102. package/dist/src/client/query/toByteCode/toByteCode.js +62 -189
  103. package/dist/src/client/query/types.d.ts +24 -5
  104. package/dist/src/client/query/validation.d.ts +5 -1
  105. package/dist/src/client/query/validation.js +15 -3
  106. package/dist/src/client/string.js +1 -1
  107. package/dist/src/hooks.js +2 -29
  108. package/dist/src/index.d.ts +1 -0
  109. package/dist/src/index.js +1 -0
  110. package/dist/src/native.d.ts +8 -1
  111. package/dist/src/native.js +23 -2
  112. package/dist/src/server/index.d.ts +2 -0
  113. package/dist/src/server/index.js +11 -2
  114. package/dist/src/server/schema.js +3 -2
  115. package/dist/src/server/schemaSelvaBuffer.d.ts +4 -0
  116. package/dist/src/server/schemaSelvaBuffer.js +182 -0
  117. package/dist/src/server/subscription.d.ts +32 -0
  118. package/dist/src/server/subscription.js +275 -0
  119. package/dist/src/utils.js +2 -3
  120. package/package.json +5 -6
@@ -63,4 +63,14 @@ export const handleError = (db, ctx, fn, args, e) => {
63
63
  }
64
64
  throw e;
65
65
  };
66
+ export const errors = {
67
+ NotExists: class extends Error {
68
+ constructor(id, schema) {
69
+ super(`Target ${schema.type}:${id} does not exist`);
70
+ }
71
+ },
72
+ };
73
+ export const errorMap = {
74
+ 1: errors.NotExists,
75
+ };
66
76
  //# sourceMappingURL=error.js.map
@@ -10,7 +10,7 @@ export const writeAlias = (ctx, def, val) => {
10
10
  deleteProp(ctx, def);
11
11
  return;
12
12
  }
13
- validate(def, val);
13
+ validate(val, def);
14
14
  const buf = ENCODER.encode(val);
15
15
  if (buf.byteLength === 0) {
16
16
  deleteProp(ctx, def);
@@ -38,7 +38,7 @@ export const writeBinary = (ctx, def, val, validated) => {
38
38
  throw [def, val];
39
39
  }
40
40
  if (!validated) {
41
- validate(def, buf);
41
+ validate(buf, def);
42
42
  }
43
43
  if (!buf.byteLength) {
44
44
  deleteProp(ctx, def);
@@ -10,7 +10,7 @@ import { writeBinary } from './binary.js';
10
10
  export const writeCardinalityRaw = (ctx, def, val, sizeFixBecauseEdgeIsDifferent = val.length) => {
11
11
  writeU32(ctx, sizeFixBecauseEdgeIsDifferent);
12
12
  for (const item of val) {
13
- validate(def, item);
13
+ validate(item, def);
14
14
  if (typeof item === 'string') {
15
15
  xxHash64(ENCODER.encode(item), ctx.array, ctx.index);
16
16
  ctx.index += 8;
@@ -1,5 +1,5 @@
1
1
  import { BINARY, BOOLEAN, ENUM, INT16, INT32, INT8, NUMBER, STRING, TIMESTAMP, UINT16, UINT32, UINT8, } from '@based/schema/def';
2
- import { convertToTimestamp, ENCODER } from '@based/utils';
2
+ import { convertToTimestamp, ENCODER, writeDoubleLE } from '@based/utils';
3
3
  import { getBuffer } from './binary.js';
4
4
  import { reserve } from '../resize.js';
5
5
  import { writeU16, writeU32, writeU64, writeU8, writeU8Array } from '../uint.js';
@@ -7,7 +7,7 @@ import { validate } from '../validate.js';
7
7
  const map = {};
8
8
  map[BINARY] = (ctx, val, def) => {
9
9
  val = getBuffer(val);
10
- validate(def, val);
10
+ validate(val, def);
11
11
  reserve(ctx, val.byteLength + 1);
12
12
  writeU8(ctx, val.byteLength);
13
13
  writeU8Array(ctx, val);
@@ -18,7 +18,7 @@ map[STRING] = (ctx, val, def) => {
18
18
  if (size + 1 > def.len) {
19
19
  throw [def, val, `max length of ${def.len - 1},`];
20
20
  }
21
- validate(def, val);
21
+ validate(val, def);
22
22
  reserve(ctx, size + 1);
23
23
  const fullSize = def.len - 1;
24
24
  ctx.array[ctx.index] = size;
@@ -30,12 +30,12 @@ map[STRING] = (ctx, val, def) => {
30
30
  };
31
31
  map[BOOLEAN] = (ctx, val, def) => {
32
32
  val ??= def.default;
33
- validate(def, val);
33
+ validate(val, def);
34
34
  reserve(ctx, 1);
35
35
  writeU8(ctx, val ? 1 : 0);
36
36
  };
37
37
  map[ENUM] = (ctx, val, def) => {
38
- validate(def, val);
38
+ validate(val, def);
39
39
  if (val === null) {
40
40
  reserve(ctx, 1);
41
41
  writeU8(ctx, def.default);
@@ -50,46 +50,45 @@ map[ENUM] = (ctx, val, def) => {
50
50
  };
51
51
  map[NUMBER] = (ctx, val, def) => {
52
52
  val ??= def.default;
53
- validate(def, val);
54
- const view = new DataView(ctx.array.buffer, ctx.array.byteOffset + ctx.index, 8);
53
+ validate(val, def);
55
54
  reserve(ctx, 8);
56
- view.setFloat64(0, val, true);
55
+ writeDoubleLE(ctx.array, val, ctx.array.byteOffset + ctx.index);
57
56
  ctx.index += 8;
58
57
  };
59
58
  map[TIMESTAMP] = (ctx, val, def) => {
60
59
  val ??= def.default;
61
60
  const parsedValue = convertToTimestamp(val);
62
- validate(def, parsedValue);
61
+ validate(parsedValue, def);
63
62
  reserve(ctx, 8);
64
63
  writeU64(ctx, parsedValue);
65
64
  };
66
65
  map[UINT32] = (ctx, val, def) => {
67
66
  val ??= def.default;
68
- validate(def, val);
67
+ validate(val, def);
69
68
  reserve(ctx, 4);
70
69
  writeU32(ctx, val);
71
70
  };
72
71
  map[UINT16] = (ctx, val, def) => {
73
72
  val ??= def.default;
74
- validate(def, val);
73
+ validate(val, def);
75
74
  reserve(ctx, 2);
76
75
  writeU16(ctx, val);
77
76
  };
78
77
  map[UINT8] = map[INT8] = (ctx, val, def) => {
79
78
  val ??= def.default;
80
- validate(def, val);
79
+ validate(val, def);
81
80
  reserve(ctx, 1);
82
81
  writeU8(ctx, val);
83
82
  };
84
83
  map[INT32] = (ctx, val, def) => {
85
84
  val ??= def.default;
86
- validate(def, val);
85
+ validate(val, def);
87
86
  reserve(ctx, 4);
88
87
  writeU32(ctx, val);
89
88
  };
90
89
  map[INT16] = (ctx, val, def) => {
91
90
  val ??= def.default;
92
- validate(def, val);
91
+ validate(val, def);
93
92
  reserve(ctx, 2);
94
93
  writeU16(ctx, val);
95
94
  };
@@ -19,7 +19,7 @@ export const writeReference = (ctx, def, val) => {
19
19
  return;
20
20
  }
21
21
  if (typeof val === 'number') {
22
- validate(def, val);
22
+ validate(val, def);
23
23
  if (def.hasDefaultEdges) {
24
24
  writeReferenceId(ctx, def, val, EDGE_NOINDEX_REALID);
25
25
  writeEdges(ctx, def, {}, true);
@@ -44,7 +44,7 @@ export const writeReference = (ctx, def, val) => {
44
44
  }
45
45
  }
46
46
  if (typeof val.id === 'number') {
47
- validate(def, val.id);
47
+ validate(val.id, def);
48
48
  if (!def.edges || val instanceof Tmp || val instanceof Promise) {
49
49
  writeReferenceId(ctx, def, val.id, NOEDGE_NOINDEX_REALID);
50
50
  }
@@ -41,7 +41,7 @@ const putReferences = (ctx, def, val, refOp) => {
41
41
  let index = 0;
42
42
  for (const id of val) {
43
43
  if (typeof id === 'number') {
44
- validate(def, id);
44
+ validate(id, def);
45
45
  writeU32(ctx, id);
46
46
  index++;
47
47
  continue;
@@ -50,7 +50,7 @@ const putReferences = (ctx, def, val, refOp) => {
50
50
  if (hasEdgeOrIndex(def, id)) {
51
51
  return index;
52
52
  }
53
- validate(def, id.id);
53
+ validate(id.id, def);
54
54
  writeU32(ctx, id.id);
55
55
  index++;
56
56
  continue;
@@ -78,7 +78,7 @@ const updateReferences = (ctx, def, val, index, length, refOp) => {
78
78
  }
79
79
  }
80
80
  if (typeof id === 'number') {
81
- validate(def, id);
81
+ validate(id, def);
82
82
  writeU8(ctx, NOEDGE_NOINDEX_REALID);
83
83
  writeU32(ctx, id);
84
84
  continue;
@@ -88,7 +88,7 @@ const updateReferences = (ctx, def, val, index, length, refOp) => {
88
88
  }
89
89
  if (typeof id.then === 'function') {
90
90
  if (id.id) {
91
- validate(def, id.id);
91
+ validate(id.id, def);
92
92
  writeU8(ctx, NOEDGE_NOINDEX_REALID);
93
93
  writeU32(ctx, id.id);
94
94
  continue;
@@ -101,7 +101,7 @@ const updateReferences = (ctx, def, val, index, length, refOp) => {
101
101
  throw id;
102
102
  }
103
103
  if (typeof id.id === 'number') {
104
- validate(def, id.id);
104
+ validate(id.id, def);
105
105
  writeReferenceObj(ctx, def, id.id, id, false);
106
106
  continue;
107
107
  }
@@ -110,7 +110,7 @@ const updateReferences = (ctx, def, val, index, length, refOp) => {
110
110
  }
111
111
  if (typeof id.id.then === 'function') {
112
112
  if (id.id.id) {
113
- validate(def, id.id.id);
113
+ validate(id.id.id, def);
114
114
  writeReferenceObj(ctx, def, id.id.id, id, false);
115
115
  continue;
116
116
  }
@@ -185,7 +185,7 @@ const deleteReferences = (ctx, def, val) => {
185
185
  writeU8(ctx, REF_OP_DELETE);
186
186
  for (const id of val) {
187
187
  if (typeof id === 'number') {
188
- validate(def, id);
188
+ validate(id, def);
189
189
  writeU32(ctx, id);
190
190
  continue;
191
191
  }
@@ -28,7 +28,7 @@ export const writeString = (ctx, def, val, lang) => {
28
28
  deleteString(ctx, def, lang);
29
29
  return;
30
30
  }
31
- validate(def, val);
31
+ validate(val, def);
32
32
  let size = isUint8 ? val.byteLength : ENCODER.encode(val).byteLength + 6;
33
33
  reserve(ctx, FULL_CURSOR_SIZE + 11 + size);
34
34
  writePropCursor(ctx, def);
@@ -8,7 +8,7 @@ export const writeVector = (ctx, def, val) => {
8
8
  deleteProp(ctx, def);
9
9
  return;
10
10
  }
11
- validate(def, val);
11
+ validate(val, def);
12
12
  if (val.byteLength === 0) {
13
13
  deleteProp(ctx, def);
14
14
  return;
@@ -34,15 +34,5 @@ export const writeVector = (ctx, def, val) => {
34
34
  ctx.array[ctx.index++] = 0;
35
35
  ctx.array.set(new Uint8Array(val.buffer).subarray(0, size), ctx.index - padding);
36
36
  ctx.index += size;
37
- // let size = Math.min(val.byteLength, def.len)
38
- // let padding = 0
39
- // if (ctx.index % 4 !== 0) {
40
- // padding = ctx.index % 4
41
- // size -= padding
42
- // }
43
- // writeU32(ctx, size + 4)
44
- // writeU8(ctx, padding)
45
- // writePadding(ctx, 3 - padding)
46
- // writeU8Array(ctx, new Uint8Array(val.buffer).subarray(0, size))
47
37
  };
48
38
  //# sourceMappingURL=vector.js.map
@@ -16,6 +16,7 @@ export declare const PADDING = 255;
16
16
  export declare const SWITCH_TYPE = 2;
17
17
  export declare const SWITCH_FIELD = 0;
18
18
  export declare const SWITCH_ID_CREATE = 9;
19
+ export declare const SWITCH_ID_CREATE_RING = 19;
19
20
  export declare const SWITCH_ID_CREATE_UNSAFE = 8;
20
21
  export declare const SWITCH_ID_UPDATE = 1;
21
22
  export declare const UPSERT = 17;
@@ -15,6 +15,7 @@ export const PADDING = 255;
15
15
  export const SWITCH_TYPE = 2;
16
16
  export const SWITCH_FIELD = 0;
17
17
  export const SWITCH_ID_CREATE = 9;
18
+ export const SWITCH_ID_CREATE_RING = 19;
18
19
  export const SWITCH_ID_CREATE_UNSAFE = 8;
19
20
  export const SWITCH_ID_UPDATE = 1;
20
21
  export const UPSERT = 17;
@@ -1,6 +1,6 @@
1
1
  import { PropDef, PropDefEdge } from '@based/schema/def';
2
2
  import { DbClient } from '../../index.js';
3
- export declare const validate: (def: PropDef | PropDefEdge, val: any) => void;
3
+ export declare const validate: (val: any, def: PropDef | PropDefEdge) => void;
4
4
  export declare const validatePayload: (payload: any) => void;
5
5
  export declare const validateId: (id: number) => void;
6
6
  export declare const getValidSchema: (db: DbClient, type: string) => import("@based/schema/def").SchemaTypeDef;
@@ -1,7 +1,8 @@
1
1
  import { isValidId } from '@based/schema/def';
2
- export const validate = (def, val) => {
3
- if (!def.validation(val, def)) {
4
- throw [def, val];
2
+ export const validate = (val, def) => {
3
+ const msg = def.validation(val, def.schema);
4
+ if (msg !== true) {
5
+ throw [def, val, msg];
5
6
  }
6
7
  };
7
8
  export const validatePayload = (payload) => {
@@ -24,9 +24,9 @@ export declare class QueryBranch<T> {
24
24
  search(query: string, ...fields: Search[]): T;
25
25
  search(query: ArrayBufferView, field: string, opts?: Omit<FilterOpts, 'lowerCase'>): T;
26
26
  groupBy(field: string, step?: StepInput): T;
27
- count(field?: string): T;
27
+ count(): T;
28
28
  sum(...fields: string[]): T;
29
- cardinality(field: string): T;
29
+ cardinality(...fields: string[]): T;
30
30
  stddev(...args: (string | aggFnOptions)[]): T;
31
31
  var(...args: (string | aggFnOptions)[]): T;
32
32
  avg(...fields: string[]): T;
@@ -52,9 +52,9 @@ export declare class BasedDbQuery extends QueryBranch<BasedDbQuery> {
52
52
  readSchema: ReaderSchema;
53
53
  constructor(db: DbClient, type: string, rawTarget?: QueryByAliasObj | number | Promise<number> | Uint32Array | (QueryByAliasObj | number)[], skipValidation?: boolean);
54
54
  reset(): void;
55
- id: number;
56
55
  get(): GetPromise;
57
- buffer: Uint8Array;
56
+ buffer?: Uint8Array;
57
+ subscriptionBuffer?: Uint8Array;
58
58
  register(): void;
59
59
  locale(locale: LangName, fallBack?: LangFallback): this;
60
60
  subscribe(onData: OnData, onError?: OnError): import("./subscription/types.js").OnClose;
@@ -129,16 +129,16 @@ export class QueryBranch {
129
129
  // @ts-ignore
130
130
  return this;
131
131
  }
132
- count(field = 'count') {
132
+ count() {
133
+ const fields = ['count'];
133
134
  if (this.queryCommands) {
134
135
  this.queryCommands.push({
135
136
  method: 'count',
136
- args: [field],
137
+ args: fields,
137
138
  });
138
139
  }
139
140
  else {
140
- const p = field.split('.');
141
- addAggregate(this, AggregateType.COUNT, p);
141
+ addAggregate(this, AggregateType.COUNT, fields);
142
142
  }
143
143
  // @ts-ignore
144
144
  return this;
@@ -159,18 +159,18 @@ export class QueryBranch {
159
159
  // @ts-ignore
160
160
  return this;
161
161
  }
162
- cardinality(field) {
163
- if (field.length === 0) {
162
+ cardinality(...fields) {
163
+ if (fields.length === 0) {
164
164
  throw new Error('Empty cardinality() called');
165
165
  }
166
166
  if (this.queryCommands) {
167
167
  this.queryCommands.push({
168
168
  method: 'cardinality',
169
- args: [field],
169
+ args: fields,
170
170
  });
171
171
  }
172
172
  else {
173
- addAggregate(this, AggregateType.CARDINALITY, [field]);
173
+ addAggregate(this, AggregateType.CARDINALITY, fields);
174
174
  }
175
175
  // @ts-ignore
176
176
  return this;
@@ -335,6 +335,18 @@ export class QueryBranch {
335
335
  // @ts-ignore
336
336
  return this;
337
337
  }
338
+ // first() {
339
+ // if (this.queryCommands) {
340
+ // this.queryCommands.push({ method: 'first', args: [] })
341
+ // } else {
342
+ // const offset = 0
343
+ // const limit = 1
344
+ // this.def.range.offset = offset
345
+ // this.def.range.limit = limit
346
+ // }
347
+ // // @ts-ignore
348
+ // return this
349
+ // }
338
350
  include(...fields) {
339
351
  if (this.queryCommands) {
340
352
  this.queryCommands.push({ method: 'include', args: fields });
@@ -408,7 +420,7 @@ export class BasedDbQuery extends QueryBranch {
408
420
  this.target = target;
409
421
  }
410
422
  reset() {
411
- this.id = undefined;
423
+ this.subscriptionBuffer = undefined;
412
424
  this.buffer = undefined;
413
425
  this.def = undefined;
414
426
  }
@@ -427,12 +439,12 @@ export class BasedDbQuery extends QueryBranch {
427
439
  reject(err);
428
440
  return;
429
441
  }
430
- const d = performance.now();
431
442
  await this.db.isModified();
432
443
  if (this.db.schema?.hash !== this.def.schemaChecksum) {
433
444
  this.reset();
434
445
  return this.#getInternal(resolve, reject);
435
446
  }
447
+ const d = performance.now();
436
448
  const res = await this.db.hooks.getQueryBuf(buf);
437
449
  if (res.byteLength === 1) {
438
450
  if (res[0] === 0) {
@@ -461,12 +473,11 @@ export class BasedDbQuery extends QueryBranch {
461
473
  resolve(new BasedQueryResponse(this.def, res, performance.now() - d));
462
474
  }
463
475
  };
464
- // if !id not initialized yet
465
- id;
466
476
  get() {
467
477
  return new GetPromise(this.#getInternal);
468
478
  }
469
479
  buffer;
480
+ subscriptionBuffer;
470
481
  register() {
471
482
  registerQuery(this);
472
483
  }
@@ -10,7 +10,6 @@ export declare class BasedQueryResponse {
10
10
  end: number;
11
11
  constructor(def: QueryDef, result: Uint8Array, execTime: number, end?: number);
12
12
  get id(): number;
13
- get queryId(): number;
14
13
  get version(): number;
15
14
  get size(): number;
16
15
  [inspect.custom](depth: number): string;
@@ -19,9 +19,6 @@ export class BasedQueryResponse {
19
19
  get id() {
20
20
  return readId(this.def.readSchema, this.result);
21
21
  }
22
- get queryId() {
23
- return this.def.queryId;
24
- }
25
22
  get version() {
26
23
  return readVersion(this.result);
27
24
  }
@@ -4,5 +4,5 @@ import { QueryBranch } from '../BasedDbQuery.js';
4
4
  import { AggregateType } from '@based/protocol/db-read';
5
5
  export declare const aggregateToBuffer: (aggregates: QueryDefAggregation) => Uint8Array;
6
6
  export declare const groupBy: (q: QueryBranch<any>, field: string, StepInput: StepInput) => void;
7
- export declare const addAggregate: (query: QueryBranch<any>, type: AggregateType, fields: string[], option?: aggFnOptions) => void;
7
+ export declare const addAggregate: (query: QueryBranch<any>, type: AggregateType, propNames: string[], option?: aggFnOptions) => void;
8
8
  export declare const isRootCountOnly: (def: QueryDef, filterSize: number) => boolean;
@@ -1,8 +1,8 @@
1
1
  import { writeUint16, writeInt16, writeUint32 } from '@based/utils';
2
2
  import { QueryDefType } from '../types.js';
3
3
  import { setMode } from './types.js';
4
- import { UINT32 } from '@based/schema/def';
5
- import { aggregationFieldDoesNotExist, validateStepRange, } from '../validation.js';
4
+ import { REFERENCE, REFERENCES, isPropDef, } from '@based/schema/def';
5
+ import { aggregationFieldDoesNotExist, validateStepRange, edgeNotImplemented, } from '../validation.js';
6
6
  import { aggregateTypeMap, Interval, } from '../aggregates/types.js';
7
7
  import { AggregateType } from '@based/protocol/db-read';
8
8
  export const aggregateToBuffer = (aggregates) => {
@@ -54,16 +54,19 @@ export const aggregateToBuffer = (aggregates) => {
54
54
  i += 2;
55
55
  writeUint16(aggBuffer, agg.accumulatorPos, i);
56
56
  i += 2;
57
+ aggBuffer[i] = agg.propDef.__isEdge ? 1 : 0;
58
+ i += 1;
57
59
  size += i - startI;
58
60
  }
59
61
  writeUint16(aggBuffer, size, sizeIndex);
60
62
  }
63
+ // console.log('aggBuffer', aggBuffer)
61
64
  return aggBuffer;
62
65
  };
63
66
  const ensureAggregate = (def) => {
64
67
  if (!def.aggregate) {
65
68
  def.aggregate = {
66
- size: 7,
69
+ size: 6, // groupBy + resultSize, accumulatorSize, mode,
67
70
  aggregates: new Map(),
68
71
  totalResultsSize: 0,
69
72
  totalAccumulatorSize: 0,
@@ -88,9 +91,11 @@ export const groupBy = (q, field, StepInput) => {
88
91
  groupByHook(q, field);
89
92
  def.schema.hooks.groupBy = groupByHook;
90
93
  }
91
- ensureAggregate(def);
94
+ if (!def.aggregate) {
95
+ ensureAggregate(def);
96
+ }
92
97
  if (!def.aggregate.groupBy) {
93
- def.aggregate.size += 12;
98
+ def.aggregate.size += 13; // field, srcPropType, start, len, stepType, stepRange, timezone
94
99
  }
95
100
  def.aggregate.groupBy = fieldDef;
96
101
  def.aggregate.groupBy.stepRange = undefined;
@@ -124,60 +129,127 @@ export const groupBy = (q, field, StepInput) => {
124
129
  def.aggregate.groupBy.display = StepInput?.display;
125
130
  }
126
131
  };
127
- export const addAggregate = (query, type, fields, option) => {
128
- const def = query.def;
129
- let hookFields;
130
- ensureAggregate(def);
131
- if (option?.mode) {
132
- def.aggregate.option = option;
133
- }
132
+ const updateAggregateDefs = (def, propDef, aggType) => {
134
133
  const aggregates = def.aggregate.aggregates;
135
- for (const field of fields) {
136
- const fieldDef = type === AggregateType.COUNT
137
- ? {
138
- prop: 255,
139
- path: [field],
140
- __isPropDef: true,
141
- len: 4,
142
- start: 0,
143
- typeIndex: UINT32,
144
- separate: true,
145
- validation: () => true,
146
- default: 0,
134
+ if (!aggregates.get(propDef.prop)) {
135
+ aggregates.set(propDef.prop, []);
136
+ def.aggregate.size += 3; // field + fieldAggSize
137
+ }
138
+ const aggregateField = aggregates.get(propDef.prop);
139
+ aggregateField.push({
140
+ type: aggType,
141
+ propDef: propDef,
142
+ resultPos: def.aggregate.totalResultsSize,
143
+ accumulatorPos: def.aggregate.totalAccumulatorSize,
144
+ isEdge: isEdge(propDef.path[0]),
145
+ });
146
+ const specificSizes = aggregateTypeMap.get(aggType);
147
+ if (specificSizes) {
148
+ def.aggregate.totalResultsSize += specificSizes.resultsSize;
149
+ def.aggregate.totalAccumulatorSize += specificSizes.accumulatorSize;
150
+ }
151
+ else {
152
+ def.aggregate.totalResultsSize += 8;
153
+ def.aggregate.totalAccumulatorSize += 8;
154
+ }
155
+ // needs to add an extra field WRITE TO
156
+ def.aggregate.size += 9; // aggType + propType + start + resultPos + accumulatorPos + isEdge
157
+ };
158
+ const isCount = (propString, aggType) => {
159
+ return propString === 'count' || aggType === AggregateType.COUNT;
160
+ };
161
+ const isEdge = (propString) => {
162
+ return propString.startsWith('$');
163
+ };
164
+ const isReferenceOrReferences = (typeIndex) => {
165
+ return typeIndex === REFERENCE || typeIndex === REFERENCES;
166
+ };
167
+ const getPropDefinition = (def, propName, type, resolvedPropDef) => {
168
+ if (isCount(propName, type)) {
169
+ return {
170
+ schema: null,
171
+ prop: 255,
172
+ path: [propName],
173
+ __isPropDef: true,
174
+ len: 4,
175
+ start: 0,
176
+ typeIndex: 1,
177
+ separate: true,
178
+ validation: () => true,
179
+ default: 0,
180
+ };
181
+ }
182
+ return resolvedPropDef || def.schema.props[propName];
183
+ };
184
+ const IN_RECURSION = Symbol('IN_RECURSION');
185
+ // process references, nested, edges
186
+ // return undefined if skip to recursive call (refs)
187
+ const processPropPath = (query, path, originalPropName, type) => {
188
+ let t = query.def.schema.tree;
189
+ for (let i = 0; i < path.length; i++) {
190
+ const propName = path[i];
191
+ if (isEdge(propName)) {
192
+ // @ts-ignore
193
+ const edgePropDef = query.def.target?.propDef?.edges[propName];
194
+ if (edgePropDef) {
195
+ return edgePropDef;
196
+ }
197
+ else {
198
+ edgeNotImplemented(query.def, propName);
199
+ return undefined;
147
200
  }
148
- : def.schema.props[field];
149
- if (!fieldDef) {
150
- aggregationFieldDoesNotExist(def, field);
151
201
  }
152
- if (fieldDef.hooks?.aggregate) {
153
- hookFields ??= new Set(fields);
154
- fieldDef.hooks.aggregate(query, hookFields);
202
+ if (!t) {
203
+ return undefined; // end
155
204
  }
156
- if (!aggregates.get(fieldDef.prop)) {
157
- aggregates.set(fieldDef.prop, []);
158
- def.aggregate.size += 3;
205
+ t = t[propName];
206
+ if (!t) {
207
+ return undefined; // path nor exist
159
208
  }
160
- const aggregateField = aggregates.get(fieldDef.prop);
161
- aggregateField.push({
162
- propDef: fieldDef,
163
- type,
164
- resultPos: def.aggregate.totalResultsSize,
165
- accumulatorPos: def.aggregate.totalAccumulatorSize,
166
- });
167
- const specificSizes = aggregateTypeMap.get(type);
168
- if (specificSizes) {
169
- def.aggregate.totalResultsSize += specificSizes.resultsSize;
170
- def.aggregate.totalAccumulatorSize += specificSizes.accumulatorSize;
209
+ if (isPropDef(t) && isReferenceOrReferences(t.typeIndex)) {
210
+ const remainingPath = path.slice(i + 1).join('.');
211
+ if (isEdge(remainingPath)) {
212
+ return t; // let the calling handle it
213
+ }
214
+ if (remainingPath) {
215
+ addAggregate(query, type, [remainingPath], query.def.aggregate.option);
216
+ }
217
+ return IN_RECURSION;
218
+ }
219
+ }
220
+ return isPropDef(t) ? t : undefined;
221
+ };
222
+ export const addAggregate = (query, type, propNames, option) => {
223
+ const def = query.def;
224
+ let hookPropNames;
225
+ ensureAggregate(def);
226
+ if (option?.mode) {
227
+ def.aggregate.option = option;
228
+ }
229
+ for (const propName of propNames) {
230
+ if (Array.isArray(propName)) {
231
+ addAggregate(query, type, propName, option);
171
232
  }
172
233
  else {
173
- def.aggregate.totalResultsSize += 8;
174
- def.aggregate.totalAccumulatorSize += 8;
234
+ const path = propName.split('.');
235
+ let resolvedPropDef = processPropPath(query, path, propName, type);
236
+ if (resolvedPropDef === IN_RECURSION) {
237
+ continue;
238
+ }
239
+ let propDef = getPropDefinition(def, propName, type, resolvedPropDef);
240
+ if (!propDef) {
241
+ aggregationFieldDoesNotExist(def, propName);
242
+ return;
243
+ }
244
+ if (propDef.hooks?.aggregate) {
245
+ hookPropNames ??= new Set(propNames);
246
+ propDef.hooks.aggregate(query, hookPropNames);
247
+ }
248
+ updateAggregateDefs(def, propDef, type);
249
+ if (def.schema.hooks?.aggregate) {
250
+ def.schema.hooks.aggregate(query, hookPropNames || new Set(propNames));
251
+ }
175
252
  }
176
- // needs to add an extra field WRITE TO
177
- def.aggregate.size += 8;
178
- }
179
- if (def.schema.hooks?.aggregate) {
180
- def.schema.hooks.aggregate(query, hookFields || new Set(fields));
181
253
  }
182
254
  };
183
255
  export const isRootCountOnly = (def, filterSize) => {