@based/db 0.0.8 → 0.0.9

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 (132) hide show
  1. package/README.md +425 -8
  2. package/dist/lib/darwin_aarch64/include/selva/db.h +12 -3
  3. package/dist/lib/darwin_aarch64/include/selva/fields.h +22 -11
  4. package/dist/lib/darwin_aarch64/include/selva/history.h +49 -0
  5. package/dist/lib/darwin_aarch64/include/selva/hll.h +21 -0
  6. package/dist/lib/darwin_aarch64/include/selva/sort.h +14 -0
  7. package/dist/lib/darwin_aarch64/include/selva/types.h +9 -2
  8. package/dist/lib/darwin_aarch64/include/selva/vector.h +22 -1
  9. package/dist/lib/darwin_aarch64/include/selva/xxhash64.h +23 -0
  10. package/dist/lib/darwin_aarch64/libnode-v20.11.1.node +0 -0
  11. package/dist/lib/darwin_aarch64/libnode-v20.18.1.node +0 -0
  12. package/dist/lib/darwin_aarch64/libnode-v22.13.0.node +0 -0
  13. package/dist/lib/darwin_aarch64/libnode-v22.8.0.node +0 -0
  14. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  15. package/dist/lib/linux_aarch64/include/selva/db.h +12 -3
  16. package/dist/lib/linux_aarch64/include/selva/fields.h +22 -11
  17. package/dist/lib/linux_aarch64/include/selva/history.h +49 -0
  18. package/dist/lib/linux_aarch64/include/selva/hll.h +21 -0
  19. package/dist/lib/linux_aarch64/include/selva/sort.h +14 -0
  20. package/dist/lib/linux_aarch64/include/selva/types.h +9 -2
  21. package/dist/lib/linux_aarch64/include/selva/vector.h +22 -1
  22. package/dist/lib/linux_aarch64/include/selva/xxhash64.h +23 -0
  23. package/dist/lib/linux_aarch64/libnode-v20.11.1.node +0 -0
  24. package/dist/lib/linux_aarch64/libnode-v20.18.1.node +0 -0
  25. package/dist/lib/linux_aarch64/libnode-v22.13.0.node +0 -0
  26. package/dist/lib/linux_aarch64/libselva.so +0 -0
  27. package/dist/lib/linux_x86_64/include/selva/db.h +12 -3
  28. package/dist/lib/linux_x86_64/include/selva/fields.h +22 -11
  29. package/dist/lib/linux_x86_64/include/selva/history.h +49 -0
  30. package/dist/lib/linux_x86_64/include/selva/hll.h +21 -0
  31. package/dist/lib/linux_x86_64/include/selva/sort.h +14 -0
  32. package/dist/lib/linux_x86_64/include/selva/types.h +9 -2
  33. package/dist/lib/linux_x86_64/include/selva/vector.h +22 -1
  34. package/dist/lib/linux_x86_64/include/selva/xxhash64.h +23 -0
  35. package/dist/lib/linux_x86_64/libnode-v20.11.1.node +0 -0
  36. package/dist/lib/linux_x86_64/libnode-v20.18.1.node +0 -0
  37. package/dist/lib/linux_x86_64/libnode-v22.13.0.node +0 -0
  38. package/dist/lib/linux_x86_64/libselva.so +0 -0
  39. package/dist/src/client/bitWise.js +21 -1
  40. package/dist/src/client/index.d.ts +11 -5
  41. package/dist/src/client/index.js +57 -11
  42. package/dist/src/client/modify/ModifyRes.d.ts +4 -1
  43. package/dist/src/client/modify/ModifyRes.js +8 -1
  44. package/dist/src/client/modify/alias.js +3 -3
  45. package/dist/src/client/modify/binary.js +5 -2
  46. package/dist/src/client/modify/cardinality.d.ts +4 -0
  47. package/dist/src/client/modify/cardinality.js +50 -0
  48. package/dist/src/client/modify/create copy.d.ts +5 -0
  49. package/dist/src/client/modify/create copy.js +112 -0
  50. package/dist/src/client/modify/create.d.ts +2 -1
  51. package/dist/src/client/modify/create.js +11 -7
  52. package/dist/src/client/modify/delete.d.ts +2 -0
  53. package/dist/src/client/modify/delete.js +37 -0
  54. package/dist/src/client/modify/expire.d.ts +3 -0
  55. package/dist/src/client/modify/expire.js +25 -0
  56. package/dist/src/client/modify/fixed.js +11 -1
  57. package/dist/src/client/modify/index.d.ts +1 -1
  58. package/dist/src/client/modify/index.js +1 -1
  59. package/dist/src/client/modify/json.d.ts +4 -0
  60. package/dist/src/client/modify/json.js +5 -0
  61. package/dist/src/client/modify/modify.js +11 -7
  62. package/dist/src/client/modify/references/edge.js +21 -6
  63. package/dist/src/client/modify/references/reference.js +2 -2
  64. package/dist/src/client/modify/references/references.d.ts +0 -1
  65. package/dist/src/client/modify/references/references.js +4 -4
  66. package/dist/src/client/modify/remove.d.ts +1 -2
  67. package/dist/src/client/modify/remove.js +9 -6
  68. package/dist/src/client/modify/setCursor.d.ts +1 -1
  69. package/dist/src/client/modify/setCursor.js +4 -1
  70. package/dist/src/client/modify/string.js +2 -2
  71. package/dist/src/client/modify/text.d.ts +2 -1
  72. package/dist/src/client/modify/text.js +13 -7
  73. package/dist/src/client/modify/types.d.ts +8 -1
  74. package/dist/src/client/modify/types.js +1 -0
  75. package/dist/src/client/modify/update.d.ts +2 -1
  76. package/dist/src/client/modify/update.js +9 -5
  77. package/dist/src/client/modify/upsert.d.ts +2 -1
  78. package/dist/src/client/modify/upsert.js +3 -3
  79. package/dist/src/client/modify/vector copy.d.ts +4 -0
  80. package/dist/src/client/modify/vector copy.js +46 -0
  81. package/dist/src/client/modify/vector.js +6 -4
  82. package/dist/src/client/query/BasedDbQuery.d.ts +4 -3
  83. package/dist/src/client/query/BasedDbQuery.js +39 -16
  84. package/dist/src/client/query/BasedIterable.js +3 -3
  85. package/dist/src/client/query/filter/FilterBranch.d.ts +2 -2
  86. package/dist/src/client/query/filter/FilterBranch.js +2 -2
  87. package/dist/src/client/query/filter/createFixedFilterBuffer.d.ts +3 -2
  88. package/dist/src/client/query/filter/createFixedFilterBuffer.js +14 -11
  89. package/dist/src/client/query/filter/createReferenceFilter.d.ts +2 -1
  90. package/dist/src/client/query/filter/createReferenceFilter.js +6 -5
  91. package/dist/src/client/query/filter/createVariableFilterBuffer.d.ts +2 -1
  92. package/dist/src/client/query/filter/createVariableFilterBuffer.js +61 -30
  93. package/dist/src/client/query/filter/filter.d.ts +2 -2
  94. package/dist/src/client/query/filter/filter.js +23 -21
  95. package/dist/src/client/query/filter/parseFilterValue.js +9 -64
  96. package/dist/src/client/query/filter/primitiveFilter.js +7 -11
  97. package/dist/src/client/query/filter/toBuffer.js +5 -7
  98. package/dist/src/client/query/filter/types.d.ts +51 -2
  99. package/dist/src/client/query/filter/types.js +114 -0
  100. package/dist/src/client/query/include/props.d.ts +2 -0
  101. package/dist/src/client/query/include/props.js +25 -6
  102. package/dist/src/client/query/include/toBuffer.js +21 -1
  103. package/dist/src/client/query/include/walk.js +17 -2
  104. package/dist/src/client/query/queryDef.js +1 -0
  105. package/dist/src/client/query/read/read.js +85 -21
  106. package/dist/src/client/query/search/index.d.ts +2 -0
  107. package/dist/src/client/query/search/index.js +79 -23
  108. package/dist/src/client/query/subscription/index.js +2 -2
  109. package/dist/src/client/query/subscription/markers.d.ts +1 -1
  110. package/dist/src/client/query/subscription/markers.js +2 -2
  111. package/dist/src/client/query/toBuffer.js +0 -4
  112. package/dist/src/client/query/types.d.ts +10 -0
  113. package/dist/src/client/query/validation.d.ts +3 -2
  114. package/dist/src/client/query/validation.js +17 -2
  115. package/dist/src/client/timestamp.d.ts +1 -0
  116. package/dist/src/client/timestamp.js +68 -0
  117. package/dist/src/client/xxHash64.d.ts +1 -0
  118. package/dist/src/client/xxHash64.js +5 -0
  119. package/dist/src/index.d.ts +4 -1
  120. package/dist/src/index.js +13 -3
  121. package/dist/src/native.d.ts +1 -0
  122. package/dist/src/native.js +4 -1
  123. package/dist/src/server/csmt/tree.js +12 -2
  124. package/dist/src/server/index.d.ts +12 -4
  125. package/dist/src/server/index.js +63 -17
  126. package/dist/src/server/migrate/worker.js +3 -3
  127. package/dist/src/server/schema/selvaBuffer.js +20 -11
  128. package/dist/src/server/schema/typeDef.d.ts +2 -2
  129. package/dist/src/server/schema/typeDef.js +14 -5
  130. package/dist/src/server/schema/types.d.ts +7 -2
  131. package/dist/src/server/schema/types.js +6 -3
  132. package/package.json +1 -1
@@ -1,4 +1,6 @@
1
- import { STRING } from '../../../server/schema/types.js';
1
+ import { langCodesMap } from '@based/schema';
2
+ import { STRING, TEXT, VECTOR } from '../../../server/schema/types.js';
3
+ import { getVectorFn } from '../filter/types.js';
2
4
  const makeSize = (nr, u8 = false) => {
3
5
  if (u8) {
4
6
  const size = Buffer.allocUnsafe(1);
@@ -9,10 +11,31 @@ const makeSize = (nr, u8 = false) => {
9
11
  size.writeUint16LE(nr);
10
12
  return size;
11
13
  };
14
+ // vector
15
+ export const vectorSearch = (def, q, field, opts) => {
16
+ const prop = def.props[field];
17
+ if (!prop) {
18
+ throw new Error(`Cannot find prop ${field}`);
19
+ }
20
+ if (prop.typeIndex !== VECTOR) {
21
+ throw new Error('Can only search trough strings / text');
22
+ }
23
+ // [isVec] [q len] [q len] [field] [fn] [score] [score] [score] [score] [q..]
24
+ let size = 9;
25
+ const vec = Buffer.from(q.buffer);
26
+ size += vec.byteLength;
27
+ def.search = {
28
+ size: size,
29
+ prop: prop.prop,
30
+ query: vec,
31
+ isVector: true,
32
+ opts,
33
+ };
34
+ };
12
35
  export const search = (def, q, s) => {
36
+ const bufs = [];
13
37
  let blocks = 0;
14
38
  const x = q.toLowerCase().trim().split(' ');
15
- const bufs = [];
16
39
  for (const s of x) {
17
40
  if (s) {
18
41
  const b = Buffer.from(s);
@@ -23,9 +46,10 @@ export const search = (def, q, s) => {
23
46
  bufs.unshift(makeSize(blocks, true));
24
47
  const query = Buffer.concat(bufs);
25
48
  def.search = {
26
- size: query.byteLength + 2,
49
+ size: query.byteLength + 3,
27
50
  query,
28
51
  fields: [],
52
+ isVector: false,
29
53
  };
30
54
  if (typeof s === 'string') {
31
55
  s = [s];
@@ -35,7 +59,7 @@ export const search = (def, q, s) => {
35
59
  for (const k in def.props) {
36
60
  const prop = def.props[k];
37
61
  // if title / name / headline add ROLE:
38
- if (prop.typeIndex === STRING) {
62
+ if (prop.typeIndex === STRING || prop.typeIndex === TEXT) {
39
63
  s[k] = k === 'title' || k === 'name' || k === 'headline' ? 0 : 2;
40
64
  }
41
65
  }
@@ -48,35 +72,67 @@ export const search = (def, q, s) => {
48
72
  s = x;
49
73
  }
50
74
  for (const key in s) {
51
- const prop = def.props[key];
75
+ let prop = def.props[key];
76
+ let lang = def.lang;
52
77
  if (!prop) {
53
- throw new Error('field ' + key + ' does not exist on type');
78
+ if (key.includes('.')) {
79
+ const k = key.split('.');
80
+ prop = def.props[k.slice(0, -1).join('.')];
81
+ if (prop && prop.typeIndex === TEXT) {
82
+ lang = langCodesMap.get(k[k.length - 1]);
83
+ }
84
+ else {
85
+ throw new Error('field ' + key + ' does not exist on type');
86
+ }
87
+ }
88
+ else {
89
+ throw new Error('field ' + key + ' does not exist on type');
90
+ }
54
91
  }
55
- if (prop.typeIndex !== STRING) {
56
- throw new Error('Can only search trough strings');
92
+ if (prop.typeIndex !== STRING && prop.typeIndex !== TEXT) {
93
+ throw new Error('Can only search trough strings / text');
57
94
  }
58
- def.search.size += 4;
95
+ def.search.size += 5;
59
96
  def.search.fields.push({
60
97
  weight: s[key],
98
+ lang,
61
99
  field: prop.prop,
62
- start: prop.start ?? 0,
100
+ start: prop.start ?? 0, // also need lang ofc if you have start
63
101
  });
64
102
  }
65
103
  };
66
104
  export const searchToBuffer = (search) => {
67
- const result = Buffer.allocUnsafe(search.size);
68
- result.writeUint16LE(search.query.byteLength, 0);
69
- result.set(search.query, 2);
70
- const offset = search.query.byteLength + 2;
71
- search.fields.sort((a, b) => {
72
- return a.weight - b.weight;
73
- });
74
- for (let i = 0; i < search.fields.length * 4; i += 4) {
75
- const f = search.fields[i / 4];
76
- result[i + offset] = f.field;
77
- result[i + 1 + offset] = f.weight;
78
- result.writeUInt16LE(f.start, i + 2 + offset);
105
+ if (search.isVector) {
106
+ // [isVec] [q len] [q len] [field] [fn] [score] [score] [score] [score] [q..]
107
+ const result = Buffer.allocUnsafe(search.size);
108
+ result[0] = 1; // search.isVector 1
109
+ result.writeUint16LE(search.query.byteLength, 1);
110
+ result[3] = search.prop;
111
+ result[4] = getVectorFn(search.opts.fn);
112
+ result.set(Buffer.from(new Float32Array([search.opts.score ?? 0.5]).buffer), 5);
113
+ result.set(search.query, 9);
114
+ return result;
115
+ }
116
+ else {
117
+ const result = Buffer.allocUnsafe(search.size);
118
+ result[0] = 0; // search.isVector 0
119
+ result.writeUint16LE(search.query.byteLength, 1);
120
+ result.set(search.query, 3);
121
+ const offset = search.query.byteLength + 3;
122
+ // @ts-ignore
123
+ search.fields.sort((a, b) => {
124
+ return a.weight - b.weight;
125
+ });
126
+ // @ts-ignore
127
+ for (let i = 0; i < search.fields.length * 5; i += 5) {
128
+ // @ts-ignore
129
+ const f = search.fields[i / 5];
130
+ result[i + offset] = f.field;
131
+ result[i + 1 + offset] = f.weight;
132
+ result.writeUInt16LE(f.start, i + 2 + offset);
133
+ result[i + 4 + offset] = f.lang;
134
+ }
135
+ return result;
79
136
  }
80
- return result;
81
137
  };
82
138
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  import { includeFields } from '../query.js';
2
2
  import { registerQuery } from '../registerQuery.js';
3
3
  import { runSubscription } from './run.js';
4
- import { addSubscriptionMarkers, removeSubscriptionMarkers } from './markers.js';
4
+ import { addSubscriptionMarkers, deleteSubscriptionMarkers } from './markers.js';
5
5
  export * from './types.js';
6
6
  export * from './markers.js';
7
7
  export const subscribe = (q, onData, onError) => {
@@ -35,7 +35,7 @@ export const subscribe = (q, onData, onError) => {
35
35
  sub.subs.delete(fn);
36
36
  if (sub.subs.size === 0) {
37
37
  q.db.subscriptions.delete(q.id);
38
- removeSubscriptionMarkers(q);
38
+ deleteSubscriptionMarkers(q);
39
39
  }
40
40
  closed = true;
41
41
  return q;
@@ -7,4 +7,4 @@ export declare const checkSubscriptionMarkers: (db: DbClient, m: SubscriptionMar
7
7
  export declare const createSubscriptionMarkerMap: () => SubscriptionMarkerMap;
8
8
  export declare const addSubscriptionMarkers: (q: BasedDbQuery, subscription: Subscription) => void;
9
9
  export declare const resetSubscriptionMarkers: (db: DbClient) => void;
10
- export declare const removeSubscriptionMarkers: (q: BasedDbQuery) => void;
10
+ export declare const deleteSubscriptionMarkers: (q: BasedDbQuery) => void;
@@ -206,8 +206,8 @@ export const resetSubscriptionMarkers = (db) => {
206
206
  }
207
207
  }
208
208
  };
209
- export const removeSubscriptionMarkers = (q) => {
209
+ export const deleteSubscriptionMarkers = (q) => {
210
210
  // derp
211
- console.log('remove markers!');
211
+ console.log('delete markers!');
212
212
  };
213
213
  //# sourceMappingURL=markers.js.map
@@ -223,10 +223,6 @@ export function defToBuffer(db, def) {
223
223
  metaEdgeBuffer.writeUint16LE(edgesSize, 1);
224
224
  result.push(metaEdgeBuffer, ...edges);
225
225
  }
226
- // 8 byte crc 32
227
- if (def.type === QueryDefType.Root) {
228
- result.push(Buffer.from([def.lang]));
229
- }
230
226
  return result;
231
227
  }
232
228
  //# sourceMappingURL=toBuffer.js.map
@@ -1,5 +1,6 @@
1
1
  import { LangCode } from '@based/schema';
2
2
  import { PropDef, PropDefEdge, SchemaTypeDef } from '../../server/schema/schema.js';
3
+ import { FilterOpts } from './filter/types.js';
3
4
  export type MainIncludes = {
4
5
  [start: string]: [number, PropDef];
5
6
  };
@@ -34,11 +35,19 @@ export type QueryDefFilter = {
34
35
  export type QueryDefSearch = {
35
36
  size: number;
36
37
  query: Buffer;
38
+ isVector: false;
37
39
  fields: {
38
40
  weight: number;
39
41
  field: number;
40
42
  start: number;
43
+ lang: LangCode;
41
44
  }[];
45
+ } | {
46
+ size: number;
47
+ query: Buffer;
48
+ prop: number;
49
+ isVector: true;
50
+ opts: FilterOpts;
42
51
  };
43
52
  export type QueryDefSort = {
44
53
  prop: PropDefEdge | PropDef;
@@ -55,6 +64,7 @@ export type QueryDefShared = {
55
64
  limit: number;
56
65
  };
57
66
  include: {
67
+ langTextFields: Map<number, Set<LangCode>>;
58
68
  stringFields: Set<string>;
59
69
  props: Set<number>;
60
70
  propsRead: {
@@ -1,6 +1,6 @@
1
1
  import { PropDef, PropDefEdge } from '../../server/schema/types.js';
2
- import { Operator } from './filter/operators.js';
3
- import { QueryByAliasObj } from './types.js';
2
+ import { Operator } from './filter/types.js';
3
+ import { QueryByAliasObj, QueryDef } from './types.js';
4
4
  export declare const isValidId: (id: number) => void;
5
5
  export declare const checkMaxIdsPerQuery: (ids: (number | QueryByAliasObj)[]) => void;
6
6
  export declare const checkMaxBufferSize: (buf: Buffer) => void;
@@ -10,6 +10,7 @@ export declare const hasFields: (fields: {
10
10
  } | {
11
11
  [path: string]: PropDef;
12
12
  }) => void;
13
+ export declare const isValidAlias: (def: QueryDef, id: QueryByAliasObj) => void;
13
14
  export declare const hasField: (field: string) => void;
14
15
  export declare const checkOperator: (operator: Operator | boolean) => void;
15
16
  export declare const checkValue: (value: any, operator: Operator) => void;
@@ -1,5 +1,6 @@
1
+ import { ALIAS } from '../../server/schema/types.js';
1
2
  import { MAX_IDS_PER_QUERY, MIN_ID_VALUE, MAX_ID_VALUE, MAX_BUFFER_SIZE, } from './thresholds.js';
2
- import { validOperators } from './filter/operators.js';
3
+ import { validOperators } from './filter/types.js';
3
4
  export const isValidId = (id) => {
4
5
  if (typeof id != 'number') {
5
6
  throw new Error('Id has to be a number');
@@ -29,12 +30,24 @@ export const checkTotalBufferSize = (bufers) => {
29
30
  }
30
31
  }
31
32
  };
32
- export const hasFields = (fields) => {
33
+ export const hasFields = (
34
+ // get schema see if it actualy has the value (can find it on def)
35
+ fields) => {
33
36
  if (Object.keys(fields).length === 0) {
34
37
  throw new Error('No fields available to include');
35
38
  }
36
39
  };
40
+ export const isValidAlias = (def, id) => {
41
+ for (const key in id) {
42
+ const prop = def.schema.props[key];
43
+ if (!prop || prop.typeIndex !== ALIAS) {
44
+ throw new Error(`Incorrect alias provided for query "${key}"`);
45
+ }
46
+ }
47
+ };
48
+ // also wrong
37
49
  export const hasField = (field) => {
50
+ // get schema see if it actualy has the value (can find it on def)
38
51
  if (!field) {
39
52
  throw new Error(`Invalid field: ${field}`);
40
53
  }
@@ -43,6 +56,7 @@ export const hasField = (field) => {
43
56
  }
44
57
  };
45
58
  export const checkOperator = (operator) => {
59
+ // pass schema value (def) and complete for each prop + operator combination
46
60
  if (operator !== undefined &&
47
61
  typeof operator !== 'boolean' &&
48
62
  !validOperators.includes(operator)) {
@@ -50,6 +64,7 @@ export const checkOperator = (operator) => {
50
64
  }
51
65
  };
52
66
  export const checkValue = (value, operator) => {
67
+ // pass schema value (def) and complete for each prop + operator combination
53
68
  if (operator === '..' || operator === '!..') {
54
69
  if (!Array.isArray(value) || value.length !== 2) {
55
70
  throw new Error(`Invalid value for operator ${operator}: expected an array with two elements`);
@@ -0,0 +1 @@
1
+ export declare const convertToTimestamp: (value: string | Date | number) => number;
@@ -0,0 +1,68 @@
1
+ const timeToNumber = (ex) => {
2
+ if (ex === 's') {
3
+ return 1000;
4
+ }
5
+ if (ex === 'm') {
6
+ return 1000 * 60;
7
+ }
8
+ if (ex === 'h') {
9
+ return 1000 * 60 * 60;
10
+ }
11
+ if (ex === 'd') {
12
+ return 1000 * 60 * 60 * 24;
13
+ }
14
+ if (ex === 'y') {
15
+ return 31556952000;
16
+ }
17
+ return 1;
18
+ };
19
+ export const convertToTimestamp = (value) => {
20
+ if (value instanceof Date) {
21
+ return value.valueOf();
22
+ }
23
+ if (typeof value === 'string') {
24
+ if (value === 'now') {
25
+ return Date.now();
26
+ }
27
+ // MAKE THIS INTO A UTIL
28
+ const y = value.replace(/([+-])/g, ' $1 ');
29
+ const arr = y.split(/ +/);
30
+ let newValue = 0;
31
+ let now;
32
+ let op = 1;
33
+ for (const seg of arr) {
34
+ if (seg === '-') {
35
+ op = -1;
36
+ }
37
+ else if (seg === '+') {
38
+ op = 1;
39
+ }
40
+ else {
41
+ var v = 0;
42
+ if (seg === 'now') {
43
+ if (!now) {
44
+ now = Date.now();
45
+ }
46
+ v = now;
47
+ }
48
+ else if (/[smhdy]$/.test(seg)) {
49
+ const ex = seg[seg.length - 1];
50
+ const number = parseInt(seg, 10);
51
+ v = number * timeToNumber(ex);
52
+ }
53
+ else if (seg) {
54
+ v = new Date(seg).valueOf();
55
+ }
56
+ if (op === -1) {
57
+ newValue -= v;
58
+ }
59
+ else {
60
+ newValue += v;
61
+ }
62
+ }
63
+ }
64
+ return newValue;
65
+ }
66
+ return value;
67
+ };
68
+ //# sourceMappingURL=timestamp.js.map
@@ -0,0 +1 @@
1
+ export declare const xxHash64: (buf: Buffer) => any;
@@ -0,0 +1,5 @@
1
+ import native from '../native.js';
2
+ export const xxHash64 = (buf) => {
3
+ return native.xxHash64(buf);
4
+ };
5
+ //# sourceMappingURL=xxHash64.js.map
@@ -17,9 +17,12 @@ export declare class BasedDb {
17
17
  maxModifySize?: number;
18
18
  });
19
19
  create: DbClient['create'];
20
+ copy: DbClient['copy'];
20
21
  update: DbClient['update'];
21
22
  upsert: DbClient['upsert'];
22
- remove: DbClient['remove'];
23
+ delete: DbClient['delete'];
24
+ expire: DbClient['expire'];
25
+ remove: DbClient['delete'];
23
26
  query: DbClient['query'];
24
27
  putSchema: DbClient['putSchema'];
25
28
  drain: DbClient['drain'];
package/dist/src/index.js CHANGED
@@ -27,9 +27,9 @@ export class BasedDb {
27
27
  return Promise.resolve(server.putSchema(schema, fromStart));
28
28
  },
29
29
  flushModify(buf) {
30
- server.modify(buf);
30
+ const offsets = server.modify(buf);
31
31
  return Promise.resolve({
32
- offsets: {},
32
+ offsets,
33
33
  });
34
34
  },
35
35
  getQueryBuf(buf) {
@@ -44,14 +44,24 @@ export class BasedDb {
44
44
  create = function () {
45
45
  return this.client.create.apply(this.client, arguments);
46
46
  };
47
+ copy = function () {
48
+ return this.client.copy.apply(this.client, arguments);
49
+ };
47
50
  update = function () {
48
51
  return this.client.update.apply(this.client, arguments);
49
52
  };
50
53
  upsert = function () {
51
54
  return this.client.upsert.apply(this.client, arguments);
52
55
  };
56
+ delete = function () {
57
+ return this.client.delete.apply(this.client, arguments);
58
+ };
59
+ expire = function () {
60
+ return this.client.expire.apply(this.client, arguments);
61
+ };
53
62
  remove = function () {
54
- return this.client.remove.apply(this.client, arguments);
63
+ console.warn('WARNING: db.remove() is deprecated. Use db.delete() instead');
64
+ return this.client.delete.apply(this.client, arguments);
55
65
  };
56
66
  query = function () {
57
67
  return this.client.query.apply(this.client, arguments);
@@ -24,5 +24,6 @@ declare const _default: {
24
24
  crc32: (buf: Buffer) => any;
25
25
  createSortIndex: (buf: Buffer, dbCtx: any) => any;
26
26
  destroySortIndex: (buf: Buffer, dbCtx: any) => any;
27
+ xxHash64: (buf: Buffer) => any;
27
28
  };
28
29
  export default _default;
@@ -92,6 +92,9 @@ export default {
92
92
  },
93
93
  destroySortIndex: (buf, dbCtx) => {
94
94
  return db.destroySortIndex(dbCtx, buf);
95
- }
95
+ },
96
+ xxHash64: (buf) => {
97
+ return db.xxHash64(buf);
98
+ },
96
99
  };
97
100
  //# sourceMappingURL=native.js.map
@@ -3,6 +3,7 @@ import { distance, min, max } from './tree-utils.js';
3
3
  import membershipProof from './memebership-proof.js';
4
4
  export function createTree(createHash) {
5
5
  let root = null;
6
+ const emptyHash = genHash(Buffer.from(''));
6
7
  function genHash(s) {
7
8
  return createHash().update(s).digest();
8
9
  }
@@ -12,7 +13,7 @@ export function createTree(createHash) {
12
13
  function createNode(left, right) {
13
14
  const hash = left && right
14
15
  ? genNodeHash(left.hash, right.hash)
15
- : genHash(Buffer.from(''));
16
+ : emptyHash;
16
17
  return {
17
18
  hash,
18
19
  key: max(left, right),
@@ -80,7 +81,16 @@ export function createTree(createHash) {
80
81
  const left = node.left;
81
82
  const right = node.right;
82
83
  if (!left || !right) {
83
- throw new Error('The tree is broken');
84
+ console.log(node, k);
85
+ if (node.data) {
86
+ if (node.key === k) {
87
+ return null;
88
+ }
89
+ throw new Error(`k=${k} does not exist`);
90
+ }
91
+ else {
92
+ throw new Error('The tree is broken');
93
+ }
84
94
  }
85
95
  if (checkForLeaf(left, k) || checkForLeaf(right, k)) {
86
96
  if (left.key === k) {
@@ -3,6 +3,12 @@ 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
+ declare class SortIndex {
7
+ constructor(buf: Buffer, dbCtxExternal: any);
8
+ buf: Buffer;
9
+ idx: any;
10
+ cnt: number;
11
+ }
6
12
  export declare class DbWorker {
7
13
  constructor(address: BigInt, db: DbServer);
8
14
  db: DbServer;
@@ -59,17 +65,19 @@ export declare class DbServer {
59
65
  sortIndexes: {
60
66
  [type: number]: {
61
67
  [field: number]: {
62
- [start: number]: any;
68
+ [start: number]: SortIndex;
63
69
  };
64
70
  };
65
71
  };
66
- createSortIndex(type: string, field: string): any;
72
+ cleanupTimer: NodeJS.Timeout;
73
+ cleanup(): void;
74
+ createSortIndex(type: string, field: string): SortIndex;
67
75
  destroySortIndex(type: string, field: string): any;
68
- hasSortIndex(typeId: number, field: number, start: number): boolean;
76
+ getSortIndex(typeId: number, field: number, start: number): SortIndex;
69
77
  migrateSchema(schema: StrictSchema, transform?: Record<string, (node: Record<string, any>) => Record<string, any> | [string, Record<string, any>]>): Promise<StrictSchema & {
70
78
  lastId: number;
71
79
  }>;
72
- createSortIndexBuffer(typeId: number, field: number, start: number): any;
80
+ createSortIndexBuffer(typeId: number, field: number, start: number): SortIndex;
73
81
  updateMerkleTree(): void;
74
82
  putSchema(strictSchema: StrictSchema, fromStart?: boolean, transformFns?: TransformFns): (StrictSchema & {
75
83
  lastId: number;
@@ -16,6 +16,15 @@ const SCHEMA_FILE = 'schema.json';
16
16
  const __filename = fileURLToPath(import.meta.url);
17
17
  const __dirname = dirname(__filename);
18
18
  const workerPath = join(__dirname, 'worker.js');
19
+ class SortIndex {
20
+ constructor(buf, dbCtxExternal) {
21
+ this.buf = buf;
22
+ this.idx = native.createSortIndex(buf, dbCtxExternal);
23
+ }
24
+ buf;
25
+ idx;
26
+ cnt = 0;
27
+ }
19
28
  export class DbWorker {
20
29
  constructor(address, db) {
21
30
  const { port1, port2 } = new MessageChannel();
@@ -91,6 +100,35 @@ export class DbServer {
91
100
  return this.csmtHashFun;
92
101
  };
93
102
  sortIndexes;
103
+ cleanupTimer;
104
+ cleanup() {
105
+ if (!this.cleanupTimer) {
106
+ // amount accessed
107
+ // current mem available
108
+ this.cleanupTimer = global.setTimeout(() => {
109
+ this.cleanupTimer = null;
110
+ let remaining;
111
+ for (const type in this.sortIndexes) {
112
+ for (const field in this.sortIndexes[type]) {
113
+ for (const start in this.sortIndexes[type][field]) {
114
+ const sortIndex = this.sortIndexes[type][field][start];
115
+ sortIndex.cnt /= 2;
116
+ if (sortIndex.cnt < 1) {
117
+ native.destroySortIndex(sortIndex.buf, this.dbCtxExternal);
118
+ delete this.sortIndexes[type][field][start];
119
+ }
120
+ else {
121
+ remaining = true;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ if (remaining) {
127
+ this.cleanup();
128
+ }
129
+ }, 60e3);
130
+ }
131
+ }
94
132
  createSortIndex(type, field) {
95
133
  const t = this.schemaTypesParsed[type];
96
134
  const prop = t.props[field];
@@ -113,7 +151,7 @@ export class DbServer {
113
151
  buf.writeUint16LE(prop.start, 3);
114
152
  buf.writeUint16LE(prop.len, 5);
115
153
  buf[7] = prop.typeIndex;
116
- sortIndex = native.createSortIndex(buf, this.dbCtxExternal);
154
+ sortIndex = new SortIndex(buf, this.dbCtxExternal);
117
155
  fields[prop.start] = sortIndex;
118
156
  return sortIndex;
119
157
  }
@@ -138,7 +176,7 @@ export class DbServer {
138
176
  delete fields[prop.start];
139
177
  }
140
178
  }
141
- hasSortIndex(typeId, field, start) {
179
+ getSortIndex(typeId, field, start) {
142
180
  let types = this.sortIndexes[typeId];
143
181
  if (!types) {
144
182
  types = this.sortIndexes[typeId] = {};
@@ -147,11 +185,7 @@ export class DbServer {
147
185
  if (!fields) {
148
186
  fields = types[field] = {};
149
187
  }
150
- let sortIndex = fields[start];
151
- if (sortIndex) {
152
- return true;
153
- }
154
- return false;
188
+ return fields[start];
155
189
  }
156
190
  migrateSchema(schema, transform) {
157
191
  return migrate(this, schema, transform);
@@ -185,7 +219,7 @@ export class DbServer {
185
219
  buf.writeUint16LE(prop.len, 5);
186
220
  buf[7] = prop.typeIndex;
187
221
  // put in modify stuff
188
- const sortIndex = native.createSortIndex(buf, this.dbCtxExternal);
222
+ const sortIndex = new SortIndex(buf, this.dbCtxExternal);
189
223
  const types = this.sortIndexes[typeId];
190
224
  const fields = types[field];
191
225
  fields[start] = sortIndex;
@@ -279,7 +313,7 @@ export class DbServer {
279
313
  }
280
314
  if (strictSchema.props) {
281
315
  // insert a root node
282
- const data = [2, 1, 0, 0, 0, 9, 1, 0, 0, 0, 7, 1, 0, 1];
316
+ const data = [2, 1, 0, 0, 0, 17, 9, 1, 0, 0, 0, 7, 1, 0, 1];
283
317
  const blockKey = makeCsmtKey(1, 1);
284
318
  const buf = Buffer.alloc(data.length + 2 + 8 + 4);
285
319
  // add content
@@ -353,14 +387,18 @@ export class DbServer {
353
387
  const sort = buf.slice(s + 2, s + 2 + sortLen);
354
388
  const field = sort[1];
355
389
  const start = sort.readUint16LE(2 + 1);
356
- if (!this.hasSortIndex(typeId, field, start)) {
390
+ let sortIndex = this.getSortIndex(typeId, field, start);
391
+ if (!sortIndex) {
357
392
  if (this.processingQueries) {
358
393
  return new Promise((resolve) => {
359
394
  this.queryQueue.set(resolve, buf);
360
395
  });
361
396
  }
362
- this.createSortIndexBuffer(typeId, field, start);
397
+ sortIndex = this.createSortIndexBuffer(typeId, field, start);
363
398
  }
399
+ // increment
400
+ sortIndex.cnt++;
401
+ this.cleanup();
364
402
  }
365
403
  }
366
404
  else if (queryType == 1) {
@@ -392,13 +430,21 @@ export class DbServer {
392
430
  if (this.stopped) {
393
431
  return;
394
432
  }
395
- if (!noSave) {
396
- await this.save();
433
+ this.stopped = true;
434
+ clearTimeout(this.cleanupTimer);
435
+ try {
436
+ if (!noSave) {
437
+ await this.save();
438
+ }
439
+ await Promise.all(this.workers.map(({ worker }) => worker.terminate()));
440
+ this.workers = [];
441
+ native.stop(this.dbCtxExternal);
442
+ await setTimeout();
443
+ }
444
+ catch (e) {
445
+ this.stopped = false;
446
+ throw e;
397
447
  }
398
- await Promise.all(this.workers.map(({ worker }) => worker.terminate()));
399
- this.workers = [];
400
- native.stop(this.dbCtxExternal);
401
- await setTimeout();
402
448
  }
403
449
  async destroy() {
404
450
  await this.stop(true);