@based/db 0.0.20 → 0.0.21

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 (99) hide show
  1. package/basedDbNative.cjs +6 -2
  2. package/dist/lib/darwin_aarch64/include/selva/db.h +3 -3
  3. package/dist/lib/darwin_aarch64/include/selva/fast_memcmp.h +18 -0
  4. package/dist/lib/darwin_aarch64/include/selva/fields.h +3 -0
  5. package/dist/lib/darwin_aarch64/libdeflate.dylib +0 -0
  6. package/dist/lib/darwin_aarch64/libjemalloc_selva.2.dylib +0 -0
  7. package/dist/lib/darwin_aarch64/libnode-v20.node +0 -0
  8. package/dist/lib/darwin_aarch64/libnode-v21.node +0 -0
  9. package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
  10. package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
  11. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  12. package/dist/lib/linux_aarch64/include/selva/db.h +3 -3
  13. package/dist/lib/linux_aarch64/include/selva/fast_memcmp.h +18 -0
  14. package/dist/lib/linux_aarch64/include/selva/fields.h +3 -0
  15. package/dist/lib/linux_aarch64/libnode-v20.node +0 -0
  16. package/dist/lib/linux_aarch64/libnode-v21.node +0 -0
  17. package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
  18. package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
  19. package/dist/lib/linux_aarch64/libselva.so +0 -0
  20. package/dist/lib/linux_x86_64/include/selva/db.h +3 -3
  21. package/dist/lib/linux_x86_64/include/selva/fast_memcmp.h +18 -0
  22. package/dist/lib/linux_x86_64/include/selva/fields.h +3 -0
  23. package/dist/lib/linux_x86_64/libnode-v20.node +0 -0
  24. package/dist/lib/linux_x86_64/libnode-v21.node +0 -0
  25. package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
  26. package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
  27. package/dist/lib/linux_x86_64/libselva.so +0 -0
  28. package/dist/src/client/bitWise.js +0 -1
  29. package/dist/src/client/crc32.d.ts +1 -1
  30. package/dist/src/client/modify/alias.js +3 -3
  31. package/dist/src/client/modify/binary.d.ts +1 -1
  32. package/dist/src/client/modify/binary.js +7 -6
  33. package/dist/src/client/modify/cardinality.d.ts +3 -1
  34. package/dist/src/client/modify/cardinality.js +8 -4
  35. package/dist/src/client/modify/create.js +41 -5
  36. package/dist/src/client/modify/delete.js +9 -8
  37. package/dist/src/client/modify/expire.js +1 -1
  38. package/dist/src/client/modify/modify.js +3 -3
  39. package/dist/src/client/modify/references/edge.js +15 -1
  40. package/dist/src/client/modify/setCursor.js +0 -2
  41. package/dist/src/client/modify/string.d.ts +1 -1
  42. package/dist/src/client/modify/string.js +5 -3
  43. package/dist/src/client/modify/text.d.ts +1 -1
  44. package/dist/src/client/modify/text.js +52 -9
  45. package/dist/src/client/modify/types.d.ts +5 -1
  46. package/dist/src/client/modify/types.js +2 -1
  47. package/dist/src/client/modify/vector.js +4 -4
  48. package/dist/src/client/query/filter/convertFilter.js +3 -1
  49. package/dist/src/client/query/filter/createFixedFilterBuffer.js +1 -1
  50. package/dist/src/client/query/filter/createVariableFilterBuffer.js +10 -4
  51. package/dist/src/client/query/filter/parseFilterValue.js +13 -4
  52. package/dist/src/client/query/filter/primitiveFilter.js +13 -3
  53. package/dist/src/client/query/filter/toBuffer.js +13 -3
  54. package/dist/src/client/query/filter/types.d.ts +5 -3
  55. package/dist/src/client/query/filter/types.js +12 -0
  56. package/dist/src/client/query/read/read.js +7 -1
  57. package/dist/src/client/query/search/index.js +25 -19
  58. package/dist/src/client/query/serialize.d.ts +4 -0
  59. package/dist/src/client/query/serialize.js +26 -0
  60. package/dist/src/client/query/sort.d.ts +1 -1
  61. package/dist/src/client/query/sort.js +5 -5
  62. package/dist/src/client/query/subscription/run.js +1 -1
  63. package/dist/src/client/query/types.d.ts +6 -2
  64. package/dist/src/client/query/validation.js +14 -32
  65. package/dist/src/client/string.d.ts +2 -2
  66. package/dist/src/client/string.js +32 -29
  67. package/dist/src/client/tmpBuffer.d.ts +3 -0
  68. package/dist/src/client/tmpBuffer.js +20 -0
  69. package/dist/src/client/xxHash64.d.ts +1 -1
  70. package/dist/src/client/xxHash64.js +1 -1
  71. package/dist/src/index.d.ts +2 -0
  72. package/dist/src/index.js +2 -0
  73. package/dist/src/native.d.ts +14 -13
  74. package/dist/src/native.js +41 -25
  75. package/dist/src/server/csmt/draw-dot.js +2 -1
  76. package/dist/src/server/csmt/memebership-proof.d.ts +1 -1
  77. package/dist/src/server/csmt/tree.d.ts +2 -1
  78. package/dist/src/server/csmt/tree.js +10 -9
  79. package/dist/src/server/csmt/types.d.ts +4 -3
  80. package/dist/src/server/index.d.ts +5 -4
  81. package/dist/src/server/index.js +5 -6
  82. package/dist/src/server/save.js +4 -3
  83. package/dist/src/server/start.d.ts +1 -0
  84. package/dist/src/server/start.js +43 -16
  85. package/dist/src/server/tree.d.ts +1 -1
  86. package/dist/src/server/tree.js +17 -2
  87. package/dist/src/server/worker.js +2 -1
  88. package/dist/src/utils.d.ts +4 -0
  89. package/dist/src/utils.js +84 -0
  90. package/package.json +3 -3
  91. package/dist/lib/darwin_aarch64/libnode-v20.11.1.node +0 -0
  92. package/dist/lib/darwin_aarch64/libnode-v20.18.1.node +0 -0
  93. package/dist/lib/darwin_aarch64/libnode-v22.13.0.node +0 -0
  94. package/dist/lib/linux_aarch64/libnode-v20.11.1.node +0 -0
  95. package/dist/lib/linux_aarch64/libnode-v20.18.1.node +0 -0
  96. package/dist/lib/linux_aarch64/libnode-v22.13.0.node +0 -0
  97. package/dist/lib/linux_x86_64/libnode-v20.11.1.node +0 -0
  98. package/dist/lib/linux_x86_64/libnode-v20.18.1.node +0 -0
  99. package/dist/lib/linux_x86_64/libnode-v22.13.0.node +0 -0
@@ -1,24 +1,67 @@
1
1
  import { langCodesMap } from '@based/schema';
2
- import { CREATE } from './types.js';
2
+ import { CREATE, UPDATE, RANGE_ERR, DELETE, } from './types.js';
3
3
  import { writeString } from './string.js';
4
- export function writeText(value, ctx, def, t, res, modifyOp) {
4
+ import { ModifyError } from './ModifyRes.js';
5
+ import { setCursor } from './setCursor.js';
6
+ export function writeText(value, ctx, def, t, res, parentId, modifyOp) {
7
+ const isBuffer = value instanceof Uint8Array;
8
+ if (typeof value !== 'string' &&
9
+ value !== null &&
10
+ !isBuffer &&
11
+ value &&
12
+ typeof value !== 'object') {
13
+ return new ModifyError(t, value);
14
+ }
15
+ // const len = value?.length
16
+ // think about this
17
+ if (value === null && !res.locale) {
18
+ if (modifyOp === UPDATE) {
19
+ if (ctx.len + 11 /* SIZE.DEFAULT_CURSOR */ + 1 > ctx.max) {
20
+ return RANGE_ERR;
21
+ }
22
+ setCursor(ctx, def, t.prop, t.typeIndex, parentId, modifyOp);
23
+ ctx.buf[ctx.len++] = DELETE;
24
+ }
25
+ return;
26
+ }
5
27
  // todo proper fallback as well
6
- if (value && typeof value !== 'object') {
7
- const err = writeString(res.locale ?? langCodesMap.get('en'), value, ctx, def, t, res.tmpId, modifyOp);
28
+ if ((value && typeof value !== 'object') || value === null) {
29
+ const locale = res.locale ?? langCodesMap.get('en'); // TODO: Add def lang option...
30
+ if (value == null) {
31
+ // @ts-ignore
32
+ value = '';
33
+ }
34
+ // @ts-ignore
35
+ const err = writeString(res.locale, value, ctx, def, t, res.tmpId, modifyOp);
8
36
  if (modifyOp === CREATE) {
9
- def.seperateTextSort.bufferTmp[t.prop * def.localeSize] = 2;
10
- ctx.hasSortText++;
37
+ const index = t.prop * (def.localeSize + 1);
38
+ const langIndex = def.seperateTextSort.localeToIndex.get(locale);
39
+ def.seperateTextSort.bufferTmp[index] -= 1;
40
+ def.seperateTextSort.bufferTmp[index + langIndex] = 0;
41
+ ctx.hasSortText += 1;
11
42
  }
12
43
  return err;
13
44
  }
14
45
  else {
46
+ // @ts-ignore
15
47
  for (const lang in value) {
16
- const langCode = langCodesMap.get(lang) || langCodesMap.get('en'); // TODO use proper fallback
17
- const s = value[lang];
18
- const err = writeString(langCode, s, ctx, def, t, res.tmpId, modifyOp);
48
+ const langC = def.seperateTextSort.localeStringToIndex.get(lang);
49
+ if (!langC) {
50
+ return new ModifyError(t, lang, 'Invalid locale');
51
+ }
52
+ let s = value[lang];
53
+ if (s == null) {
54
+ // @ts-ignore
55
+ s = '';
56
+ }
57
+ const err = writeString(langC[1], s, ctx, def, t, res.tmpId, modifyOp);
19
58
  if (err) {
20
59
  return err;
21
60
  }
61
+ const index = t.prop * (1 + def.localeSize);
62
+ def.seperateTextSort.bufferTmp[index] -= 1;
63
+ def.seperateTextSort.bufferTmp[index + langC[0]] = 0;
64
+ ctx.hasSortText += 1;
22
65
  }
23
66
  }
24
67
  }
@@ -3,7 +3,8 @@ import { ModifyError } from './ModifyRes.js';
3
3
  export declare const CREATE = 3;
4
4
  export declare const UPDATE = 6;
5
5
  export declare const DELETE = 11;
6
- export declare const MERGE_MAIN = 4;
6
+ export declare const DELETE_SORT_INDEX = 4;
7
+ export declare const DELETE_NODE = 10;
7
8
  export declare const RANGE_ERR = 1;
8
9
  export declare const INCREMENT = 12;
9
10
  export declare const DECREMENT = 13;
@@ -14,6 +15,9 @@ export declare const SWITCH_TYPE = 2;
14
15
  export declare const SWITCH_FIELD = 0;
15
16
  export declare const SWITCH_ID_CREATE = 9;
16
17
  export declare const SWITCH_ID_UPDATE = 1;
18
+ export declare const enum SIZE {
19
+ DEFAULT_CURSOR = 11
20
+ }
17
21
  export type ModifyErr = typeof RANGE_ERR | ModifyError | void;
18
22
  export type ModifyOp = typeof CREATE | typeof UPDATE | typeof INCREMENT | typeof EXPIRE;
19
23
  export type ModifyOpts = {
@@ -1,7 +1,8 @@
1
1
  export const CREATE = 3;
2
2
  export const UPDATE = 6;
3
3
  export const DELETE = 11;
4
- export const MERGE_MAIN = 4;
4
+ export const DELETE_SORT_INDEX = 4;
5
+ export const DELETE_NODE = 10;
5
6
  export const RANGE_ERR = 1;
6
7
  export const INCREMENT = 12;
7
8
  export const DECREMENT = 13;
@@ -1,4 +1,4 @@
1
- import { UPDATE, RANGE_ERR, DELETE } from './types.js';
1
+ import { UPDATE, RANGE_ERR, DELETE, } from './types.js';
2
2
  import { ModifyError } from './ModifyRes.js';
3
3
  import { setCursor } from './setCursor.js';
4
4
  function write(value, ctx, fieldSize) {
@@ -9,7 +9,7 @@ function write(value, ctx, fieldSize) {
9
9
  ctx.buf[ctx.len++] = tmp >>>= 8;
10
10
  ctx.buf[ctx.len++] = tmp >>>= 8;
11
11
  ctx.buf[ctx.len++] = tmp >>>= 8;
12
- Buffer.from(value.buffer).copy(ctx.buf, ctx.len, 0, size);
12
+ ctx.buf.set(new Uint8Array(value.buffer).subarray(0, size), ctx.len);
13
13
  ctx.len += size;
14
14
  }
15
15
  export function writeVector(value, ctx, schema, t, parentId, modifyOp) {
@@ -25,7 +25,7 @@ export function writeVector(value, ctx, schema, t, parentId, modifyOp) {
25
25
  }
26
26
  if (size === 0) {
27
27
  if (modifyOp === UPDATE) {
28
- if (ctx.len + 11 > ctx.max) {
28
+ if (ctx.len + 11 /* SIZE.DEFAULT_CURSOR */ + 1 > ctx.max) {
29
29
  // TODO ???
30
30
  return RANGE_ERR;
31
31
  }
@@ -34,7 +34,7 @@ export function writeVector(value, ctx, schema, t, parentId, modifyOp) {
34
34
  }
35
35
  }
36
36
  else {
37
- if (ctx.len + 15 + size > ctx.max) {
37
+ if (ctx.len + 11 /* SIZE.DEFAULT_CURSOR */ + 5 + size > ctx.max) {
38
38
  // TODO ???
39
39
  return RANGE_ERR;
40
40
  }
@@ -15,7 +15,9 @@ export const convertFilter = (def, field, operator, value, opts) => {
15
15
  value = operator;
16
16
  operator = '=';
17
17
  }
18
- if (value === '' || value === undefined) {
18
+ if (!(operator === 'exists' || operator === '!exists') &&
19
+ (value === '' || value === undefined)) {
20
+ // not great...
19
21
  return;
20
22
  }
21
23
  if (operator === '!..') {
@@ -20,7 +20,7 @@ export const writeFixed = (prop, buf, value, size, offset) => {
20
20
  const size = buf.write(value, offset + 1, 'utf8');
21
21
  buf[offset] = size;
22
22
  }
23
- else if (value instanceof Buffer) {
23
+ else if (value instanceof Uint8Array) {
24
24
  buf.set(value, offset);
25
25
  }
26
26
  else {
@@ -2,7 +2,7 @@ import { ALIAS, TEXT, VECTOR } from '@based/schema/def';
2
2
  import { EQUAL, EQUAL_CRC32, HAS, HAS_TO_LOWER_CASE, LIKE, MODE_DEFAULT_VAR, MODE_OR_VAR, getVectorFn, } from './types.js';
3
3
  import { createFixedFilterBuffer } from './createFixedFilterBuffer.js';
4
4
  import { crc32 } from '../../crc32.js';
5
- const DEFAULT_SCORE = Buffer.from(new Float32Array([0.5]).buffer);
5
+ const DEFAULT_SCORE = new Uint8Array(new Float32Array([0.5]).buffer);
6
6
  const parseValue = (value, prop, ctx, lang) => {
7
7
  let val = value;
8
8
  if (ctx.operation === HAS_TO_LOWER_CASE && typeof val === 'string') {
@@ -12,11 +12,17 @@ const parseValue = (value, prop, ctx, lang) => {
12
12
  if (!(val instanceof ArrayBuffer)) {
13
13
  throw new Error('Vector should be an arrayBuffer');
14
14
  }
15
- let fn = getVectorFn(ctx.opts.fn);
15
+ const vector = new Uint8Array(val);
16
+ let fn = new Uint8Array([getVectorFn(ctx.opts.fn)]);
16
17
  const score = ctx.opts.score
17
- ? Buffer.from(new Float32Array([ctx.opts.score]).buffer)
18
+ ? new Uint8Array(new Float32Array([ctx.opts.score]).buffer)
18
19
  : DEFAULT_SCORE;
19
- val = Buffer.concat([Buffer.from(val), Buffer.from([fn]), score]);
20
+ const buf = new Uint8Array(vector.byteLength + fn.byteLength + score.byteLength);
21
+ let off = 0;
22
+ off += (buf.set(new Uint8Array(vector), off), vector.byteLength);
23
+ off += (buf.set(fn, off), fn.byteLength);
24
+ buf.set(score, off);
25
+ val = buf;
20
26
  }
21
27
  if (val instanceof Uint8Array ||
22
28
  typeof value === 'string' ||
@@ -1,6 +1,7 @@
1
1
  import { TIMESTAMP, CREATED, UPDATED, ENUM, BOOLEAN, STRING, BINARY, TEXT, } from '@based/schema/def';
2
2
  import { crc32 } from '../../crc32.js';
3
3
  import { convertToTimestamp } from '../../timestamp.js';
4
+ const ENCODER = new TextEncoder();
4
5
  // -------------------------------------------
5
6
  // conditions normal
6
7
  // field, [size 2]
@@ -18,10 +19,18 @@ export const parseFilterValue = (prop, value) => {
18
19
  if (prop.typeIndex === BINARY ||
19
20
  prop.typeIndex === STRING ||
20
21
  prop.typeIndex === TEXT) {
21
- const b = value instanceof Buffer ? value : Buffer.from(value);
22
- const buf = Buffer.allocUnsafe(8);
23
- buf.writeUint32LE(crc32(b), 0);
24
- buf.writeUint32LE(b.byteLength, 4);
22
+ const b = value instanceof Uint8Array ? value : ENCODER.encode(value);
23
+ const buf = new Uint8Array(8);
24
+ let crc = crc32(b);
25
+ buf[0] = crc;
26
+ buf[1] = crc >>>= 8;
27
+ buf[2] = crc >>>= 8;
28
+ buf[3] = crc >>>= 8;
29
+ let len = b.byteLength;
30
+ buf[4] = len;
31
+ buf[5] = len >>>= 8;
32
+ buf[6] = len >>>= 8;
33
+ buf[7] = len >>>= 8;
25
34
  return buf;
26
35
  }
27
36
  else if (prop.typeIndex === BOOLEAN) {
@@ -1,5 +1,5 @@
1
1
  import { CARDINALITY, REFERENCE, REFERENCES, REVERSE_SIZE_MAP, } from '@based/schema/def';
2
- import { EQUAL, isNumerical } from './types.js';
2
+ import { EQUAL, EXISTS, isNumerical, TYPE_NEGATE } from './types.js';
3
3
  import { createVariableFilterBuffer } from './createVariableFilterBuffer.js';
4
4
  import { createFixedFilterBuffer } from './createFixedFilterBuffer.js';
5
5
  import { createReferenceFilter } from './createReferenceFilter.js';
@@ -9,10 +9,20 @@ export const primitiveFilter = (def, prop, filter, conditions, lang) => {
9
9
  return;
10
10
  }
11
11
  let [, ctx, value] = filter;
12
- const fieldIndexChar = prop.prop;
13
12
  let buf;
14
- let size = 0;
13
+ const fieldIndexChar = prop.prop;
15
14
  const bufferMap = prop.__isEdge ? conditions.edges : conditions.conditions;
15
+ if (ctx.operation === EXISTS) {
16
+ if (!conditions.exists) {
17
+ conditions.exists = [];
18
+ }
19
+ conditions.exists.push({
20
+ prop: prop,
21
+ negate: filter[1].type === TYPE_NEGATE,
22
+ });
23
+ return 4;
24
+ }
25
+ let size = 0;
16
26
  const isArray = Array.isArray(value);
17
27
  if (isArray && value.length === 1) {
18
28
  value = value[0];
@@ -1,4 +1,4 @@
1
- import { META_EDGE, META_OR_BRANCH, META_REFERENCE } from './types.js';
1
+ import { META_EDGE, META_EXISTS, META_OR_BRANCH, META_REFERENCE, TYPE_DEFAULT, TYPE_NEGATE, } from './types.js';
2
2
  // or
3
3
  // [meta = 253] [size 2] [next 4]
4
4
  // -------------------------------------------
@@ -17,7 +17,6 @@ import { META_EDGE, META_OR_BRANCH, META_REFERENCE } from './types.js';
17
17
  const writeConditions = (result, k, offset, conditions) => {
18
18
  let lastWritten = offset;
19
19
  result[lastWritten] = k;
20
- // result[lasWritten + 1] = typeIndex
21
20
  lastWritten++;
22
21
  const sizeIndex = lastWritten;
23
22
  lastWritten += 2;
@@ -27,7 +26,6 @@ const writeConditions = (result, k, offset, conditions) => {
27
26
  result.set(condition, lastWritten);
28
27
  lastWritten += condition.byteLength;
29
28
  }
30
- // make this u32
31
29
  result.writeUint16LE(conditionSize, sizeIndex);
32
30
  return lastWritten - offset;
33
31
  };
@@ -76,6 +74,18 @@ export const fillConditionsBuffer = (result, conditions, offset) => {
76
74
  result.writeUint32LE(lastWritten, orJumpIndex + 2);
77
75
  lastWritten += size;
78
76
  }
77
+ if (conditions.exists) {
78
+ for (const exists of conditions.exists) {
79
+ result[lastWritten] = META_EXISTS;
80
+ lastWritten++;
81
+ result[lastWritten] = exists.prop.prop;
82
+ lastWritten++;
83
+ result[lastWritten] = exists.negate ? TYPE_NEGATE : TYPE_DEFAULT;
84
+ lastWritten++;
85
+ result[lastWritten] = exists.prop.typeIndex;
86
+ lastWritten++;
87
+ }
88
+ }
79
89
  return lastWritten - offset;
80
90
  };
81
91
  // TODO convert to UINT8ARRAY
@@ -4,7 +4,7 @@ export type Filter = [fieldStr: string, ctx: FilterCtx, value: any];
4
4
  export type FilterBranchFn = (filterBranch: FilterBranch) => void;
5
5
  export type FilterAst = (Filter | FilterAst)[];
6
6
  export declare const IsFilter: (f: FilterAst) => f is Filter;
7
- export type Operator = '=' | 'has' | '!has' | '<' | '>' | '!=' | 'like' | '>=' | '<=' | '..' | '!..' | 'like';
7
+ export type Operator = '=' | 'has' | '!has' | '<' | '>' | '!=' | 'like' | '>=' | '<=' | '..' | '!..' | 'like' | 'exists' | '!exists';
8
8
  export declare const VECTOR_FNS: string[];
9
9
  export type FilterOpts<O = Operator> = {
10
10
  lowerCase?: boolean;
@@ -27,7 +27,8 @@ export declare const HAS_TO_LOWER_CASE = 13;
27
27
  export declare const STARTS_WITH_LOWER_CASE = 14;
28
28
  export declare const ENDS_WITH_LOWER_CASE = 15;
29
29
  export declare const LIKE = 18;
30
- export type OPERATOR = typeof EQUAL | typeof HAS | typeof ENDS_WITH | typeof STARTS_WITH | typeof GREATER_THAN | typeof SMALLER_THAN | typeof GREATER_THAN_INCLUSIVE | typeof SMALLER_THAN_INCLUSIVE | typeof RANGE | typeof RANGE_EXCLUDE | typeof EQUAL_LOWER_CASE | typeof HAS_TO_LOWER_CASE | typeof STARTS_WITH_LOWER_CASE | typeof ENDS_WITH_LOWER_CASE | typeof LIKE | typeof EQUAL_CRC32;
30
+ export declare const EXISTS = 19;
31
+ export type OPERATOR = typeof EQUAL | typeof HAS | typeof ENDS_WITH | typeof STARTS_WITH | typeof GREATER_THAN | typeof SMALLER_THAN | typeof GREATER_THAN_INCLUSIVE | typeof SMALLER_THAN_INCLUSIVE | typeof RANGE | typeof RANGE_EXCLUDE | typeof EQUAL_LOWER_CASE | typeof HAS_TO_LOWER_CASE | typeof STARTS_WITH_LOWER_CASE | typeof ENDS_WITH_LOWER_CASE | typeof LIKE | typeof EQUAL_CRC32 | typeof EXISTS;
31
32
  export declare const isNumerical: (op: OPERATOR) => boolean;
32
33
  export declare const TYPE_NEGATE = 1;
33
34
  export declare const TYPE_DEFAULT = 2;
@@ -39,10 +40,11 @@ export declare const MODE_AND_FIXED = 3;
39
40
  export declare const MODE_DEFAULT_VAR = 4;
40
41
  export declare const MODE_REFERENCE = 5;
41
42
  export type FILTER_MODE = typeof MODE_DEFAULT | typeof MODE_OR_FIXED | typeof MODE_OR_VAR | typeof MODE_AND_FIXED | typeof MODE_DEFAULT_VAR | typeof MODE_REFERENCE;
43
+ export declare const META_EXISTS = 251;
42
44
  export declare const META_EDGE = 252;
43
45
  export declare const META_OR_BRANCH = 253;
44
46
  export declare const META_REFERENCE = 254;
45
- export type FILTER_META = typeof META_EDGE | typeof META_OR_BRANCH | typeof META_REFERENCE;
47
+ export type FILTER_META = typeof META_EDGE | typeof META_OR_BRANCH | typeof META_REFERENCE | typeof META_EXISTS;
46
48
  export type FilterCtx = {
47
49
  operation: OPERATOR;
48
50
  type: FILTER_TYPE;
@@ -34,6 +34,9 @@ export const STARTS_WITH_LOWER_CASE = 14;
34
34
  export const ENDS_WITH_LOWER_CASE = 15;
35
35
  export const LIKE = 18;
36
36
  // -------------------------------------------
37
+ // only valid for seperate fields
38
+ export const EXISTS = 19;
39
+ // -------------------------------------------
37
40
  export const isNumerical = (op) => {
38
41
  if (op === GREATER_THAN ||
39
42
  op === SMALLER_THAN ||
@@ -59,6 +62,7 @@ export const MODE_DEFAULT_VAR = 4;
59
62
  export const MODE_REFERENCE = 5;
60
63
  // -------------------------------------------
61
64
  // Meta
65
+ export const META_EXISTS = 251;
62
66
  export const META_EDGE = 252;
63
67
  export const META_OR_BRANCH = 253;
64
68
  export const META_REFERENCE = 254;
@@ -88,6 +92,13 @@ export const toFilterCtx = (def, op, opts = {}) => {
88
92
  opts,
89
93
  };
90
94
  }
95
+ if (op === 'exists' || op === '!exists') {
96
+ return {
97
+ operation: EXISTS,
98
+ type: op === '!exists' ? TYPE_NEGATE : TYPE_DEFAULT,
99
+ opts,
100
+ };
101
+ }
91
102
  if (op === 'has' || op === '!has') {
92
103
  return {
93
104
  operation: opts.lowerCase ? HAS_TO_LOWER_CASE : HAS,
@@ -129,5 +140,6 @@ export const operatorReverseMap = {
129
140
  [ENDS_WITH_LOWER_CASE]: 'endsWith (lowerCase)',
130
141
  [LIKE]: 'like',
131
142
  [EQUAL_CRC32]: '= (crc32)',
143
+ [EXISTS]: 'exists',
132
144
  };
133
145
  //# sourceMappingURL=types.js.map
@@ -234,6 +234,12 @@ export const readAllFields = (q, result, offset, end, item, id) => {
234
234
  }
235
235
  i += size + 4;
236
236
  }
237
+ else if (t === CARDINALITY) {
238
+ i++;
239
+ const size = readUint32(result, i);
240
+ addField(edgeDef, readUint32(result, i + 4), item);
241
+ i += size + 4;
242
+ }
237
243
  else {
238
244
  i++;
239
245
  readMainValue(edgeDef, result, i, item);
@@ -290,7 +296,7 @@ export const readAllFields = (q, result, offset, end, item, id) => {
290
296
  else if (prop.typeIndex === JSON) {
291
297
  q.include.propsRead[index] = id;
292
298
  const size = readUint32(result, i);
293
- addField(prop, global.JSON.parse(Buffer.from(result.subarray(i + 6, i + size)).toString()), item);
299
+ addField(prop, global.JSON.parse(readUtf8(result, i + 6, size - 6)), item);
294
300
  i += size + 4;
295
301
  }
296
302
  else if (prop.typeIndex === BINARY) {
@@ -2,16 +2,7 @@ import { langCodesMap } from '@based/schema';
2
2
  import { STRING, TEXT, VECTOR } from '@based/schema/def';
3
3
  import { getVectorFn } from '../filter/types.js';
4
4
  import { searchDoesNotExist, searchIncorrecQueryValue, searchIncorrectType, } from '../validation.js';
5
- const makeSize = (nr, u8 = false) => {
6
- if (u8) {
7
- const size = Buffer.allocUnsafe(1);
8
- size[0] = nr;
9
- return size;
10
- }
11
- const size = Buffer.allocUnsafe(2);
12
- size.writeUint16LE(nr);
13
- return size;
14
- };
5
+ const ENCODER = new TextEncoder();
15
6
  // vector
16
7
  export const vectorSearch = (def, q, field, opts) => {
17
8
  let prop = def.props[field];
@@ -23,7 +14,7 @@ export const vectorSearch = (def, q, field, opts) => {
23
14
  }
24
15
  // [isVec] [q len] [q len] [field] [fn] [score] [score] [score] [score] [q..]
25
16
  let size = 9;
26
- const vec = Buffer.from(q.buffer);
17
+ const vec = new Uint8Array(q.buffer, 0, q.byteLength);
27
18
  size += vec.byteLength;
28
19
  def.search = {
29
20
  size: size,
@@ -33,23 +24,38 @@ export const vectorSearch = (def, q, field, opts) => {
33
24
  opts,
34
25
  };
35
26
  };
27
+ function concatBufs(bufs, totalByteLength) {
28
+ const res = new Uint8Array(totalByteLength);
29
+ let off = 0;
30
+ for (let i = 0; i < bufs.length; i++) {
31
+ const buf = bufs[i];
32
+ res.set(buf, off);
33
+ off += buf.byteLength;
34
+ }
35
+ return res;
36
+ }
36
37
  export const search = (def, q, s) => {
37
38
  const bufs = [];
38
- let blocks = 0;
39
+ let nrBlocks = 0;
40
+ let totalByteLength = 1;
39
41
  if (typeof q !== 'string') {
40
42
  searchIncorrecQueryValue(def, q);
41
43
  q = '';
42
44
  }
43
- const x = q.toLowerCase().trim().split(' ');
45
+ const x = q.toLowerCase().normalize('NFKD').trim().split(' ').map((s) => ` ${s}`);
44
46
  for (const s of x) {
45
47
  if (s) {
46
- const b = Buffer.from(s);
47
- bufs.push(makeSize(b.byteLength), b);
48
- blocks++;
48
+ const buf = ENCODER.encode(s);
49
+ let len = buf.byteLength - 2;
50
+ buf[0] = len;
51
+ buf[1] = len >>> 8;
52
+ bufs.push(buf);
53
+ nrBlocks++;
54
+ totalByteLength += len + 2;
49
55
  }
50
56
  }
51
- bufs.unshift(makeSize(blocks, true));
52
- const query = Buffer.concat(bufs);
57
+ bufs.unshift(Uint8Array.from([nrBlocks]));
58
+ const query = concatBufs(bufs, totalByteLength);
53
59
  def.search = {
54
60
  size: query.byteLength + 3,
55
61
  query,
@@ -115,7 +121,7 @@ export const searchToBuffer = (search) => {
115
121
  result.writeUint16LE(search.query.byteLength, 1);
116
122
  result[3] = search.prop;
117
123
  result[4] = getVectorFn(search.opts.fn);
118
- result.set(Buffer.from(new Float32Array([search.opts.score ?? 0.5]).buffer), 5);
124
+ result.set(new Uint8Array(new Float32Array([search.opts.score ?? 0.5]).buffer), 5);
119
125
  result.set(search.query, 9);
120
126
  return result;
121
127
  }
@@ -0,0 +1,4 @@
1
+ import { QueryDef } from './types.js';
2
+ import { SchemaTypesParsed } from '@based/schema/def';
3
+ export declare const serialize: (q: QueryDef) => string;
4
+ export declare const parse: (str: string, parsedSchema: SchemaTypesParsed) => void;
@@ -0,0 +1,26 @@
1
+ const walk = (q) => {
2
+ const obj = {};
3
+ for (const key in q) {
4
+ if (key === 'schema') {
5
+ obj[key] = q[key].type;
6
+ }
7
+ else {
8
+ // if PROPDEF
9
+ if (typeof q[key] === 'object') {
10
+ obj[key] = walk(q[key]);
11
+ }
12
+ else {
13
+ obj[key] = q[key];
14
+ }
15
+ }
16
+ }
17
+ return obj;
18
+ };
19
+ export const serialize = (q) => {
20
+ const obj = walk(q);
21
+ return JSON.stringify(obj);
22
+ };
23
+ export const parse = (str, parsedSchema) => {
24
+ //
25
+ };
26
+ //# sourceMappingURL=serialize.js.map
@@ -1,3 +1,3 @@
1
1
  import { QueryDef, QueryDefSort } from './types.js';
2
- export declare const createSortBuffer: (sort: QueryDefSort) => Buffer;
2
+ export declare const createSortBuffer: (sort: QueryDefSort) => Uint8Array;
3
3
  export declare const sort: (def: QueryDef, field: string, order?: "asc" | "desc") => void;
@@ -1,15 +1,15 @@
1
1
  import { validateSort } from './validation.js';
2
2
  export const createSortBuffer = (sort) => {
3
- const buf = Buffer.allocUnsafe(8);
3
+ const buf = new Uint8Array(8);
4
4
  // [order] [propType] [start] [start] [len] [len] [lang]
5
5
  buf[0] = sort.order;
6
6
  buf[1] = sort.prop.prop;
7
7
  buf[2] = sort.prop.typeIndex;
8
- buf.writeUint16LE(sort.prop.start, 3);
9
- buf.writeUint16LE(sort.prop.len, 5);
8
+ buf[3] = sort.prop.start;
9
+ buf[4] = sort.prop.start >>> 8;
10
+ buf[5] = sort.prop.len;
11
+ buf[6] = sort.prop.len >>> 8;
10
12
  buf[7] = sort.lang;
11
- // console.info({ sort, buf: new Uint8Array(buf) })
12
- //[LANG]
13
13
  return buf;
14
14
  };
15
15
  // NO REF / REFERENCES SUPPORT
@@ -16,7 +16,7 @@ export const resultsAreEqual = (a, b) => {
16
16
  return false;
17
17
  return true;
18
18
  };
19
- const EMPTY = new Uint8Array(Buffer.alloc(4));
19
+ const EMPTY = new Uint8Array(4);
20
20
  export const runSubscription = (subscription) => {
21
21
  if (!subscription.inProgress) {
22
22
  subscription.inProgress = true;
@@ -30,6 +30,10 @@ export declare const isRefDef: (def: QueryDef) => def is QueryDefRest;
30
30
  export type QueryDefFilter = {
31
31
  size: number;
32
32
  conditions: Map<number, Buffer[]>;
33
+ exists?: {
34
+ prop: PropDef | PropDefEdge;
35
+ negate: boolean;
36
+ }[];
33
37
  references?: Map<number, QueryDefFilter>;
34
38
  fromRef?: PropDef;
35
39
  schema?: SchemaTypeDef;
@@ -39,7 +43,7 @@ export type QueryDefFilter = {
39
43
  };
40
44
  export type QueryDefSearch = {
41
45
  size: number;
42
- query: Buffer;
46
+ query: Uint8Array;
43
47
  isVector: false;
44
48
  fields: {
45
49
  weight: number;
@@ -49,7 +53,7 @@ export type QueryDefSearch = {
49
53
  }[];
50
54
  } | {
51
55
  size: number;
52
- query: Buffer;
56
+ query: Uint8Array;
53
57
  prop: number;
54
58
  isVector: true;
55
59
  opts: FilterOpts;
@@ -1,6 +1,6 @@
1
1
  import picocolors from 'picocolors';
2
- import { ALIAS, BINARY, BOOLEAN, REFERENCE, REFERENCES, REVERSE_TYPE_INDEX_MAP, STRING, TEXT, TIMESTAMP, VECTOR, propIsNumerical, } from '@based/schema/def';
3
- import { EQUAL, HAS, isNumerical, LIKE, operatorReverseMap, VECTOR_FNS, } from './filter/types.js';
2
+ import { ALIAS, BINARY, BOOLEAN, REFERENCE, REFERENCES, REVERSE_TYPE_INDEX_MAP, STRING, TEXT, TIMESTAMP, VECTOR, propIsNumerical, createEmptyDef, } from '@based/schema/def';
3
+ import { EQUAL, EXISTS, HAS, isNumerical, LIKE, operatorReverseMap, VECTOR_FNS, } from './filter/types.js';
4
4
  import { MAX_ID, MAX_ID_VALUE, MAX_IDS_PER_QUERY, MIN_ID_VALUE, } from './thresholds.js';
5
5
  import { displayTarget, safeStringify } from './display.js';
6
6
  import { langCodesMap } from '@based/schema';
@@ -125,7 +125,17 @@ export const validateFilter = (def, prop, f) => {
125
125
  }
126
126
  const t = prop.typeIndex;
127
127
  const op = f[1].operation;
128
- if (t === REFERENCES || t === REFERENCE) {
128
+ if (op == EXISTS) {
129
+ // fields...
130
+ if (f[2] !== undefined) {
131
+ def.errors.push({
132
+ code: ERR_FILTER_OP_FIELD,
133
+ payload: f,
134
+ });
135
+ return true;
136
+ }
137
+ }
138
+ else if (t === REFERENCES || t === REFERENCE) {
129
139
  if (op == LIKE) {
130
140
  def.errors.push({ code: ERR_FILTER_OP_FIELD, payload: f });
131
141
  return true;
@@ -431,38 +441,10 @@ export const ERROR_VECTOR = {
431
441
  path: ['ERROR_VECTOR'],
432
442
  };
433
443
  export const EMPTY_SCHEMA_DEF = {
434
- type: '_error',
435
- cnt: 0,
436
- checksum: 0,
437
- total: 0,
438
- lastId: 0,
439
- blockCapacity: 0,
440
- mainLen: 0,
444
+ ...createEmptyDef('_error', { props: {} }, {}),
441
445
  buf: new Uint8Array([]),
442
446
  propNames: new Uint8Array([]),
443
447
  packed: new Uint8Array([]),
444
- props: {},
445
- locales: {},
446
- reverseProps: {},
447
- id: 0,
448
448
  idUint8: new Uint8Array([0, 0]),
449
- main: {},
450
- separate: [],
451
- tree: {},
452
- hasSeperateSort: false,
453
- seperateSort: {
454
- size: 0,
455
- buffer: new Uint8Array([]),
456
- bufferTmp: new Uint8Array([]),
457
- props: [],
458
- },
459
- hasSeperateTextSort: false,
460
- seperateTextSort: {
461
- size: 0,
462
- buffer: new Uint8Array([]),
463
- bufferTmp: new Uint8Array([]),
464
- props: [],
465
- },
466
- localeSize: 0,
467
449
  };
468
450
  //# sourceMappingURL=validation.js.map
@@ -1,6 +1,6 @@
1
1
  import { LangCode } from '@based/schema';
2
- export declare const write: (buf: Buffer, value: string, offset: number, noCompression: boolean, lang?: LangCode) => number;
3
- export declare const compress: (str: string) => Buffer;
2
+ export declare const write: (buf: Buffer | Uint8Array, value: string, offset: number, noCompression: boolean, lang?: LangCode) => number;
3
+ export declare const compress: (str: string) => Uint8Array;
4
4
  export declare const decompress: (val: Uint8Array) => string;
5
5
  export declare const read: (val: Uint8Array, offset: number, len: number) => string;
6
6
  export declare const readUtf8: (val: Uint8Array, offset: number, len: number) => string;