@based/db 0.1.2 → 0.1.3

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 (65) hide show
  1. package/dist/basedDbNative.cjs +23 -0
  2. package/dist/lib/darwin_aarch64/include/cdefs.h +4 -1
  3. package/dist/lib/darwin_aarch64/include/selva/db.h +28 -5
  4. package/dist/lib/darwin_aarch64/include/selva/fast_linear_search.h +2 -2
  5. package/dist/lib/darwin_aarch64/include/selva/fields.h +13 -41
  6. package/dist/lib/darwin_aarch64/include/selva/selva_string.h +4 -0
  7. package/dist/lib/darwin_aarch64/include/selva/types.h +1 -11
  8. package/dist/lib/darwin_aarch64/libdeflate.dylib +0 -0
  9. package/dist/lib/darwin_aarch64/libjemalloc_selva.2.dylib +0 -0
  10. package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
  11. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  12. package/dist/lib/darwin_aarch64/libxxhash.dylib +0 -0
  13. package/dist/src/client/index.d.ts +2 -0
  14. package/dist/src/client/index.js +11 -2
  15. package/dist/src/client/modify/Ctx.d.ts +3 -5
  16. package/dist/src/client/modify/Ctx.js +0 -3
  17. package/dist/src/client/modify/Tmp.d.ts +2 -2
  18. package/dist/src/client/modify/Tmp.js +27 -23
  19. package/dist/src/client/modify/create/index.js +36 -25
  20. package/dist/src/client/modify/cursor.d.ts +0 -1
  21. package/dist/src/client/modify/cursor.js +10 -26
  22. package/dist/src/client/modify/delete/index.js +6 -6
  23. package/dist/src/client/modify/drain.js +20 -23
  24. package/dist/src/client/modify/edges/references.js +3 -2
  25. package/dist/src/client/modify/error.d.ts +2 -1
  26. package/dist/src/client/modify/error.js +2 -2
  27. package/dist/src/client/modify/expire/index.js +5 -6
  28. package/dist/src/client/modify/props/object.js +3 -2
  29. package/dist/src/client/modify/props/reference.js +3 -3
  30. package/dist/src/client/modify/props/references.js +2 -1
  31. package/dist/src/client/modify/types.d.ts +4 -1
  32. package/dist/src/client/modify/types.js +4 -0
  33. package/dist/src/client/modify/update/index.d.ts +3 -0
  34. package/dist/src/client/modify/update/index.js +33 -20
  35. package/dist/src/client/modify/upsert/index.d.ts +2 -1
  36. package/dist/src/client/modify/upsert/index.js +67 -44
  37. package/dist/src/client/query/BasedDbQuery.js +12 -7
  38. package/dist/src/client/query/aggregates/aggregation.d.ts +1 -1
  39. package/dist/src/client/query/aggregates/aggregation.js +24 -3
  40. package/dist/src/client/query/filter/convertFilter.js +16 -3
  41. package/dist/src/client/query/filter/types.d.ts +1 -1
  42. package/dist/src/client/query/include/include.js +2 -5
  43. package/dist/src/client/query/queryDefToReadSchema.js +20 -1
  44. package/dist/src/client/query/search/index.js +9 -1
  45. package/dist/src/client/string.d.ts +1 -1
  46. package/dist/src/client/string.js +1 -1
  47. package/dist/src/hooks.d.ts +3 -6
  48. package/dist/src/hooks.js +5 -12
  49. package/dist/src/index.d.ts +3 -3
  50. package/dist/src/index.js +5 -3
  51. package/dist/src/native.d.ts +4 -3
  52. package/dist/src/native.js +11 -10
  53. package/dist/src/server/blocks.js +1 -1
  54. package/dist/src/server/index.d.ts +3 -2
  55. package/dist/src/server/index.js +23 -47
  56. package/dist/src/server/migrate/index.js +4 -0
  57. package/dist/src/server/resizeModifyDirtyRanges.js +1 -1
  58. package/dist/src/server/save.d.ts +0 -1
  59. package/dist/src/server/save.js +2 -2
  60. package/dist/src/server/schema.js +6 -1
  61. package/dist/src/server/start.js +0 -2
  62. package/dist/src/shared/Emitter.d.ts +1 -1
  63. package/dist/src/utils.d.ts +0 -2
  64. package/dist/src/utils.js +1 -3
  65. package/package.json +17 -7
@@ -1,48 +1,32 @@
1
1
  import { MICRO_BUFFER } from '@based/schema/def';
2
- import { writeUint32 } from '@based/utils';
3
- import { SWITCH_TYPE, SWITCH_FIELD, CREATE, SWITCH_ID_CREATE, SWITCH_ID_UPDATE, } from './types.js';
2
+ import { SWITCH_TYPE, SWITCH_FIELD } from './types.js';
3
+ import { writeU8, writeU8Array } from './uint.js';
4
4
  export const TYPE_CURSOR_SIZE = 3;
5
5
  export const PROP_CURSOR_SIZE = 3;
6
6
  export const NODE_CURSOR_SIZE = 5;
7
7
  export const FULL_CURSOR_SIZE = TYPE_CURSOR_SIZE + NODE_CURSOR_SIZE + PROP_CURSOR_SIZE;
8
8
  export const writeTypeCursor = (ctx) => {
9
9
  if (ctx.schema.id !== ctx.cursor.type) {
10
- ctx.array[ctx.index] = SWITCH_TYPE; // switch node type
11
- ctx.array.set(ctx.schema.idUint8, ctx.index + 1);
12
- ctx.index += 3;
10
+ writeU8(ctx, SWITCH_TYPE);
11
+ writeU8Array(ctx, ctx.schema.idUint8);
13
12
  ctx.cursor.type = ctx.schema.id;
14
- ctx.cursor.main = null;
15
13
  ctx.cursor.prop = null;
16
- ctx.cursor.id = null;
17
14
  }
18
15
  };
19
16
  export const writePropCursor = (ctx, def, typeIndex = def.typeIndex) => {
20
17
  if (def.prop !== ctx.cursor.prop) {
21
- ctx.array[ctx.index] = SWITCH_FIELD;
22
- ctx.array[ctx.index + 1] = def.prop;
23
- ctx.array[ctx.index + 2] = typeIndex;
24
- ctx.index += 3;
18
+ writeU8(ctx, SWITCH_FIELD);
19
+ writeU8(ctx, def.prop);
20
+ writeU8(ctx, typeIndex);
25
21
  ctx.cursor.prop = def.prop;
26
22
  }
27
23
  };
28
24
  export const writeMainCursor = (ctx) => {
29
25
  if (ctx.cursor.prop !== 0) {
30
- ctx.array[ctx.index] = SWITCH_FIELD;
31
- ctx.array[ctx.index + 1] = 0;
32
- ctx.array[ctx.index + 2] = MICRO_BUFFER;
33
- ctx.index += 3;
26
+ writeU8(ctx, SWITCH_FIELD);
27
+ writeU8(ctx, 0);
28
+ writeU8(ctx, MICRO_BUFFER);
34
29
  ctx.cursor.prop = 0;
35
30
  }
36
31
  };
37
- export const writeNodeCursor = (ctx) => {
38
- if (ctx.id !== ctx.cursor.id || ctx.operation !== ctx.cursor.operation) {
39
- ctx.array[ctx.index] =
40
- ctx.operation === CREATE ? SWITCH_ID_CREATE : SWITCH_ID_UPDATE; // swtch id
41
- writeUint32(ctx.array, ctx.id, ctx.index + 1);
42
- ctx.index += 5;
43
- ctx.cursor.id = ctx.id;
44
- ctx.cursor.main = null;
45
- ctx.cursor.operation = ctx.operation;
46
- }
47
- };
48
32
  //# sourceMappingURL=cursor.js.map
@@ -1,8 +1,8 @@
1
1
  import { getValidSchema, validateId } from '../validate.js';
2
- import { FULL_CURSOR_SIZE, writeMainCursor, writeNodeCursor, writePropCursor, writeTypeCursor, } from '../cursor.js';
2
+ import { FULL_CURSOR_SIZE, writeMainCursor, writePropCursor, writeTypeCursor, } from '../cursor.js';
3
3
  import { reserve } from '../resize.js';
4
- import { DELETE_NODE, DELETE_SORT_INDEX, UPDATE } from '../types.js';
5
- import { writeU8 } from '../uint.js';
4
+ import { DELETE_NODE, DELETE_SORT_INDEX, SWITCH_ID_UPDATE, UPDATE, } from '../types.js';
5
+ import { writeU32, writeU8 } from '../uint.js';
6
6
  import { handleError } from '../error.js';
7
7
  import { Tmp } from '../Tmp.js';
8
8
  import { schedule } from '../drain.js';
@@ -13,22 +13,22 @@ export function del(db, type, id) {
13
13
  if (schema.insertOnly) {
14
14
  throw `This type is insertOnly`;
15
15
  }
16
- ctx.id = id;
17
16
  ctx.start = ctx.index;
18
17
  ctx.schema = schema;
19
18
  ctx.operation = UPDATE;
20
19
  validateId(id);
21
20
  reserve(ctx, FULL_CURSOR_SIZE + 2 + schema.separate.length * 12); // 12 too much?
22
21
  writeTypeCursor(ctx);
22
+ writeU8(ctx, SWITCH_ID_UPDATE);
23
+ writeU32(ctx, id);
23
24
  writeMainCursor(ctx);
24
- writeNodeCursor(ctx);
25
25
  writeU8(ctx, DELETE_SORT_INDEX);
26
26
  for (const def of schema.separate) {
27
27
  writePropCursor(ctx, def);
28
28
  writeU8(ctx, DELETE_SORT_INDEX);
29
29
  }
30
30
  writeU8(ctx, DELETE_NODE);
31
- const tmp = new Tmp(ctx, id);
31
+ const tmp = new Tmp(ctx);
32
32
  schedule(db, ctx);
33
33
  return tmp;
34
34
  }
@@ -1,11 +1,9 @@
1
- import { writeUint16, writeUint32 } from '@based/utils';
2
1
  import { rejectTmp, resolveTmp } from './Tmp.js';
3
2
  export const reset = (ctx) => {
4
3
  ctx.index = 8;
5
4
  ctx.max = ctx.array.buffer.maxByteLength - 4;
6
5
  ctx.size = ctx.array.buffer.byteLength - 4;
7
6
  ctx.cursor = {};
8
- ctx.created = {};
9
7
  ctx.batch = {};
10
8
  };
11
9
  export const cancel = (ctx, error) => {
@@ -18,17 +16,7 @@ export const consume = (ctx) => {
18
16
  if (ctx.index > ctx.array.byteLength) {
19
17
  throw new Error('Invalid size - modify buffer length mismatch');
20
18
  }
21
- const typeIds = Object.keys(ctx.created);
22
- const typeSize = typeIds.length * 6 + 4;
23
- const payload = ctx.array.subarray(0, ctx.index + typeSize);
24
- let i = payload.byteLength - 4;
25
- writeUint32(payload, ctx.index, i);
26
- for (const typeId of typeIds) {
27
- const count = ctx.created[typeId];
28
- i -= 6;
29
- writeUint16(payload, Number(typeId), i);
30
- writeUint32(payload, count, i + 2);
31
- }
19
+ const payload = ctx.array.subarray(0, ctx.index);
32
20
  reset(ctx);
33
21
  return payload;
34
22
  };
@@ -36,21 +24,30 @@ export const drain = (db, ctx) => {
36
24
  if (ctx.index > 8) {
37
25
  const { batch } = ctx;
38
26
  const payload = consume(ctx);
27
+ let start;
39
28
  ctx.draining = db.hooks
40
29
  .flushModify(payload)
41
- .then(({ offsets, dbWriteTime }) => {
42
- db.writeTime += dbWriteTime ?? 0;
43
- batch.ready = true;
44
- batch.offsets = offsets;
45
- batch.promises?.forEach(resolveTmp);
46
- batch.promises = null;
30
+ .then((res) => {
31
+ if (res === null) {
32
+ throw Error('Schema mismatch');
33
+ }
34
+ batch.res = res;
47
35
  })
48
36
  .catch((e) => {
49
- console.error(e);
50
- batch.ready = true;
51
37
  batch.error = e;
52
- batch.promises?.forEach(rejectTmp);
53
- batch.promises = null;
38
+ })
39
+ .finally(() => {
40
+ batch.ready = true;
41
+ if (batch.promises) {
42
+ start = ctx.index;
43
+ batch.promises.forEach(batch.error ? rejectTmp : resolveTmp);
44
+ batch.promises = null;
45
+ }
46
+ })
47
+ .then(() => {
48
+ if (start && start !== ctx.index) {
49
+ return drain(db, ctx);
50
+ }
54
51
  });
55
52
  }
56
53
  return ctx.draining;
@@ -1,6 +1,6 @@
1
1
  import { REFERENCES } from '@based/schema/def';
2
2
  import { reserve } from '../resize.js';
3
- import { writeU32 } from '../uint.js';
3
+ import { writePadding, writeU32 } from '../uint.js';
4
4
  import { writeEdgeHeader } from './header.js';
5
5
  export const writeReferencesEdge = (ctx, edge, vals) => {
6
6
  if (vals === null) {
@@ -12,7 +12,7 @@ export const writeReferencesEdge = (ctx, edge, vals) => {
12
12
  if (!Array.isArray(vals)) {
13
13
  throw [edge, vals];
14
14
  }
15
- const size = vals.length * 4;
15
+ const size = vals.length * 4 + 3; // add 3 padding
16
16
  reserve(ctx, 3 + 4 + size);
17
17
  writeEdgeHeader(ctx, edge, REFERENCES);
18
18
  writeU32(ctx, size);
@@ -34,5 +34,6 @@ export const writeReferencesEdge = (ctx, edge, vals) => {
34
34
  }
35
35
  throw [edge, vals];
36
36
  }
37
+ writePadding(ctx, 3);
37
38
  };
38
39
  //# sourceMappingURL=references.js.map
@@ -4,4 +4,5 @@ import { Ctx } from './Ctx.js';
4
4
  import { del } from './delete/index.js';
5
5
  import { expire } from './expire/index.js';
6
6
  import { update } from './update/index.js';
7
- export declare const handleError: (db: DbClient, ctx: Ctx, fn: typeof create | typeof update | typeof del | typeof expire, args: IArguments, e: any) => Promise<number>;
7
+ import { upsert } from './upsert/index.js';
8
+ export declare const handleError: (db: DbClient, ctx: Ctx, fn: typeof create | typeof update | typeof del | typeof expire | typeof upsert, args: IArguments, e: any) => Promise<number>;
@@ -27,7 +27,7 @@ const parseVal = (val) => {
27
27
  }
28
28
  return val;
29
29
  };
30
- const parseErrorMsg = (prop, val, msg) => {
30
+ const parseErrorArr = (prop, val, msg) => {
31
31
  if (isPropDef(prop)) {
32
32
  if (msg) {
33
33
  return `Invalid value at '${prop.path.join('.')}'. Expected ${msg} received '${parseVal(val)}'`;
@@ -59,7 +59,7 @@ export const handleError = (db, ctx, fn, args, e) => {
59
59
  }
60
60
  if (Array.isArray(e)) {
61
61
  const [def, val, msg] = e;
62
- throw Error(parseErrorMsg(def, val, msg));
62
+ throw Error(parseErrorArr(def, val, msg));
63
63
  }
64
64
  throw e;
65
65
  };
@@ -1,8 +1,8 @@
1
1
  import { getValidSchema, validateId } from '../validate.js';
2
2
  import { handleError } from '../error.js';
3
3
  import { reserve } from '../resize.js';
4
- import { NODE_CURSOR_SIZE, TYPE_CURSOR_SIZE, writeNodeCursor, writeTypeCursor, } from '../cursor.js';
5
- import { EXPIRE } from '../types.js';
4
+ import { NODE_CURSOR_SIZE, TYPE_CURSOR_SIZE, writeTypeCursor, } from '../cursor.js';
5
+ import { EXPIRE, SWITCH_ID_UPDATE } from '../types.js';
6
6
  import { schedule } from '../drain.js';
7
7
  import { Tmp } from '../Tmp.js';
8
8
  import { writeU32, writeU8 } from '../uint.js';
@@ -10,17 +10,16 @@ export function expire(db, type, id, seconds) {
10
10
  const ctx = db.modifyCtx;
11
11
  const schema = getValidSchema(db, type);
12
12
  try {
13
- ctx.id = id;
14
13
  ctx.start = ctx.index;
15
14
  ctx.schema = schema;
16
- ctx.operation = EXPIRE;
17
15
  validateId(id);
18
16
  reserve(ctx, TYPE_CURSOR_SIZE + NODE_CURSOR_SIZE + 5);
19
17
  writeTypeCursor(ctx);
20
- writeNodeCursor(ctx);
18
+ writeU8(ctx, SWITCH_ID_UPDATE);
19
+ writeU32(ctx, id);
21
20
  writeU8(ctx, EXPIRE);
22
21
  writeU32(ctx, seconds);
23
- const tmp = new Tmp(ctx, id);
22
+ const tmp = new Tmp(ctx);
24
23
  schedule(db, ctx);
25
24
  return tmp;
26
25
  }
@@ -2,11 +2,12 @@ import { isPropDef } from '@based/schema/def';
2
2
  import { writeSeparate } from './separate.js';
3
3
  import { writeMainValue } from './main.js';
4
4
  import { writeIncrement } from './increment.js';
5
+ import { CREATE } from '../types.js';
5
6
  const writeProp = (ctx, def, val) => {
6
7
  if (def.separate) {
7
8
  writeSeparate(ctx, def, val);
8
9
  }
9
- else if (ctx.overwrite) {
10
+ else if (ctx.operation === CREATE) {
10
11
  writeMainValue(ctx, def, val);
11
12
  }
12
13
  else if (typeof val === 'object' && val !== null) {
@@ -24,7 +25,7 @@ export const writeObjectSafe = (ctx, tree, obj) => {
24
25
  }
25
26
  const def = tree[key];
26
27
  if (def === undefined) {
27
- throw [def, val];
28
+ throw [tree, val];
28
29
  }
29
30
  if (isPropDef(def)) {
30
31
  writeProp(ctx, def, val);
@@ -5,10 +5,8 @@ import { EDGE_NOINDEX_REALID, EDGE_NOINDEX_TMPID, NOEDGE_NOINDEX_REALID, NOEDGE_
5
5
  import { writeEdges } from '../edges/index.js';
6
6
  import { deleteProp } from './delete.js';
7
7
  import { writeU32, writeU8 } from '../uint.js';
8
+ import { validate } from '../validate.js';
8
9
  const writeReferenceId = (ctx, def, val, refOp) => {
9
- if (!def.validation(val, def)) {
10
- throw [def, val];
11
- }
12
10
  reserve(ctx, PROP_CURSOR_SIZE + 6);
13
11
  writePropCursor(ctx, def);
14
12
  writeU8(ctx, ctx.operation);
@@ -21,6 +19,7 @@ export const writeReference = (ctx, def, val) => {
21
19
  return;
22
20
  }
23
21
  if (typeof val === 'number') {
22
+ validate(def, val);
24
23
  if (def.hasDefaultEdges) {
25
24
  writeReferenceId(ctx, def, val, EDGE_NOINDEX_REALID);
26
25
  writeEdges(ctx, def, {}, true);
@@ -45,6 +44,7 @@ export const writeReference = (ctx, def, val) => {
45
44
  }
46
45
  }
47
46
  if (typeof val.id === 'number') {
47
+ validate(def, val.id);
48
48
  if (!def.edges || val instanceof Tmp || val instanceof Promise) {
49
49
  writeReferenceId(ctx, def, val.id, NOEDGE_NOINDEX_REALID);
50
50
  }
@@ -101,6 +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
105
  writeReferenceObj(ctx, def, id.id, id, false);
105
106
  continue;
106
107
  }
@@ -109,6 +110,7 @@ const updateReferences = (ctx, def, val, index, length, refOp) => {
109
110
  }
110
111
  if (typeof id.id.then === 'function') {
111
112
  if (id.id.id) {
113
+ validate(def, id.id.id);
112
114
  writeReferenceObj(ctx, def, id.id.id, id, false);
113
115
  continue;
114
116
  }
@@ -151,7 +153,6 @@ const putOrUpdateReferences = (ctx, def, val, refOp) => {
151
153
  const writeReferenceObj = (ctx, def, id, obj, isTmp) => {
152
154
  const hasIndex = typeof obj.$index === 'number';
153
155
  const hasEdges = hasAnEdge(def, obj);
154
- validate(def, id);
155
156
  if (hasIndex) {
156
157
  if (hasEdges) {
157
158
  writeU8(ctx, isTmp ? EDGE_INDEX_TMPID : EDGE_INDEX_REALID);
@@ -12,10 +12,14 @@ export declare const EXPIRE = 14;
12
12
  export declare const ADD_EMPTY_SORT_TEXT = 15;
13
13
  export declare const ADD_EMPTY_SORT = 7;
14
14
  export declare const DELETE_TEXT_FIELD = 16;
15
+ export declare const PADDING = 255;
15
16
  export declare const SWITCH_TYPE = 2;
16
17
  export declare const SWITCH_FIELD = 0;
17
18
  export declare const SWITCH_ID_CREATE = 9;
19
+ export declare const SWITCH_ID_CREATE_UNSAFE = 8;
18
20
  export declare const SWITCH_ID_UPDATE = 1;
21
+ export declare const UPSERT = 17;
22
+ export declare const INSERT = 18;
19
23
  export type ModifyOp = typeof CREATE | typeof UPDATE | typeof INCREMENT | typeof EXPIRE;
20
24
  export declare const MOD_OPS_TO_STRING: Record<ModifyOp, 'create' | 'update'>;
21
25
  export declare const enum SIZE {
@@ -24,7 +28,6 @@ export declare const enum SIZE {
24
28
  export type ModifyOpts = {
25
29
  unsafe?: boolean;
26
30
  locale?: LangName;
27
- overwrite?: boolean;
28
31
  };
29
32
  export declare const NOEDGE_NOINDEX_REALID = 0;
30
33
  export declare const EDGE_NOINDEX_REALID = 1;
@@ -11,10 +11,14 @@ export const EXPIRE = 14;
11
11
  export const ADD_EMPTY_SORT_TEXT = 15;
12
12
  export const ADD_EMPTY_SORT = 7;
13
13
  export const DELETE_TEXT_FIELD = 16;
14
+ export const PADDING = 255;
14
15
  export const SWITCH_TYPE = 2;
15
16
  export const SWITCH_FIELD = 0;
16
17
  export const SWITCH_ID_CREATE = 9;
18
+ export const SWITCH_ID_CREATE_UNSAFE = 8;
17
19
  export const SWITCH_ID_UPDATE = 1;
20
+ export const UPSERT = 17;
21
+ export const INSERT = 18;
18
22
  export const MOD_OPS_TO_STRING = {
19
23
  [CREATE]: 'create',
20
24
  [UPDATE]: 'update',
@@ -1,3 +1,6 @@
1
+ import { Ctx } from '../Ctx.js';
1
2
  import { ModifyOpts } from '../types.js';
2
3
  import { DbClient } from '../../../index.js';
4
+ import { SchemaTypeDef } from '@based/schema/def';
5
+ export declare const writeUpdate: (ctx: Ctx, schema: SchemaTypeDef, id: number, payload: any, opts: ModifyOpts) => void;
3
6
  export declare function update(db: DbClient, type: string, id: number, payload: any, opts: ModifyOpts): Promise<number>;
@@ -1,13 +1,13 @@
1
- import { UPDATE, UPDATE_PARTIAL } from '../types.js';
1
+ import { SWITCH_ID_UPDATE, UPDATE, UPDATE_PARTIAL, } from '../types.js';
2
2
  import { getValidSchema, validateId, validatePayload } from '../validate.js';
3
3
  import { langCodesMap } from '@based/schema';
4
4
  import { handleError } from '../error.js';
5
5
  import { Tmp } from '../Tmp.js';
6
6
  import { writeObject } from '../props/object.js';
7
7
  import { reserve } from '../resize.js';
8
- import { FULL_CURSOR_SIZE, PROP_CURSOR_SIZE, writeMainCursor, writeNodeCursor, writeTypeCursor, } from '../cursor.js';
8
+ import { FULL_CURSOR_SIZE, PROP_CURSOR_SIZE, writeMainCursor, writeTypeCursor, } from '../cursor.js';
9
9
  import { getByPath, writeUint32 } from '@based/utils';
10
- import { writeU16, writeU8 } from '../uint.js';
10
+ import { writeU16, writeU32, writeU8 } from '../uint.js';
11
11
  import { writeFixed } from '../props/fixed.js';
12
12
  import { schedule } from '../drain.js';
13
13
  const writeUpdateTs = (ctx, payload) => {
@@ -37,10 +37,35 @@ const writeMergeMain = (ctx) => {
37
37
  writeUint32(ctx.array, ctx.index - start, index);
38
38
  }
39
39
  };
40
- const writeUpdate = (ctx, payload) => {
40
+ export const writeUpdate = (ctx, schema, id, payload, opts) => {
41
+ validatePayload(payload);
42
+ if (schema.propHooks?.update) {
43
+ for (const def of schema.propHooks.update) {
44
+ let val = payload;
45
+ let obj;
46
+ let key;
47
+ for (key of def.path) {
48
+ obj = val;
49
+ val = val?.[key];
50
+ }
51
+ if (val !== undefined) {
52
+ obj[key] = def.hooks.update(val, obj);
53
+ }
54
+ }
55
+ }
56
+ if (schema.hooks?.update) {
57
+ payload = schema.hooks.update(payload) || payload;
58
+ }
59
+ ctx.schema = schema;
60
+ ctx.operation = UPDATE;
61
+ ctx.locale = opts?.locale && langCodesMap.get(opts.locale);
62
+ if (ctx.main.size) {
63
+ ctx.main.clear();
64
+ }
41
65
  reserve(ctx, FULL_CURSOR_SIZE);
42
66
  writeTypeCursor(ctx);
43
- writeNodeCursor(ctx);
67
+ writeU8(ctx, SWITCH_ID_UPDATE);
68
+ writeU32(ctx, id);
44
69
  writeObject(ctx, ctx.schema.tree, payload);
45
70
  writeUpdateTs(ctx, payload);
46
71
  writeMergeMain(ctx);
@@ -48,23 +73,11 @@ const writeUpdate = (ctx, payload) => {
48
73
  export function update(db, type, id, payload, opts) {
49
74
  const schema = getValidSchema(db, type);
50
75
  const ctx = db.modifyCtx;
76
+ ctx.start = ctx.index;
51
77
  try {
52
- validatePayload(payload);
53
78
  validateId(id);
54
- if (schema.hooks?.update) {
55
- payload = schema.hooks.update(payload) || payload;
56
- }
57
- ctx.id = id;
58
- ctx.schema = schema;
59
- ctx.operation = UPDATE;
60
- ctx.overwrite = opts?.overwrite;
61
- ctx.locale = opts?.locale && langCodesMap.get(opts.locale);
62
- ctx.start = ctx.index;
63
- if (ctx.main.size) {
64
- ctx.main.clear();
65
- }
66
- writeUpdate(ctx, payload);
67
- const tmp = new Tmp(ctx, id);
79
+ writeUpdate(ctx, schema, id, payload, opts);
80
+ const tmp = new Tmp(ctx);
68
81
  schedule(db, ctx);
69
82
  return tmp;
70
83
  }
@@ -1,3 +1,4 @@
1
1
  import { DbClient } from '../../../index.js';
2
2
  import { ModifyOpts } from '../types.js';
3
- export declare const upsert: (db: DbClient, type: string, obj: any, opts: ModifyOpts) => Promise<number>;
3
+ export declare function upsert(db: DbClient, type: string, payload: any, opts: ModifyOpts): Promise<number>;
4
+ export declare function insert(db: DbClient, type: string, payload: any, opts: ModifyOpts): Promise<number>;
@@ -1,54 +1,77 @@
1
1
  import { ALIAS, isPropDef } from '@based/schema/def';
2
- import { deepMerge } from '@based/utils';
3
- const filterAliases = (obj, tree) => {
4
- let aliases;
2
+ import { INSERT, UPSERT } from '../types.js';
3
+ import { getValidSchema } from '../validate.js';
4
+ import { writeU32, writeU8, writeU8Array } from '../uint.js';
5
+ import { reserve } from '../resize.js';
6
+ import { ENCODER, writeUint32 } from '@based/utils';
7
+ import { writeCreate } from '../create/index.js';
8
+ import { handleError } from '../error.js';
9
+ import { writeUpdate } from '../update/index.js';
10
+ import { schedule } from '../drain.js';
11
+ import { TYPE_CURSOR_SIZE, writeTypeCursor } from '../cursor.js';
12
+ import { Tmp } from '../Tmp.js';
13
+ const writeAliases = (ctx, tree, obj) => {
5
14
  for (const key in obj) {
6
15
  const def = tree[key];
7
- if (def === undefined) {
8
- return;
16
+ const val = obj[key];
17
+ if (def === undefined || val === undefined) {
18
+ continue;
9
19
  }
10
- if (isPropDef(def)) {
11
- if (def.typeIndex === ALIAS) {
12
- aliases ??= {};
13
- aliases[key] = obj[key];
14
- }
20
+ if (!isPropDef(def)) {
21
+ writeAliases(ctx, def, val);
15
22
  }
16
- else {
17
- const nested = filterAliases(obj[key], def);
18
- if (nested) {
19
- aliases ??= {};
20
- aliases[key] = nested;
21
- }
23
+ else if (def.typeIndex === ALIAS) {
24
+ const buf = ENCODER.encode(val);
25
+ reserve(ctx, 1 + 4 + buf.byteLength);
26
+ writeU8(ctx, def.prop);
27
+ writeU32(ctx, buf.byteLength);
28
+ writeU8Array(ctx, buf);
22
29
  }
23
30
  }
24
- return aliases;
25
31
  };
26
- export const upsert = (db, type, obj, opts) => {
27
- const tree = db.schemaTypesParsed[type].tree;
28
- const aliases = filterAliases(obj, tree);
29
- const q = db.query(type, aliases);
30
- q.register();
31
- if (db.upserting.has(q.id)) {
32
- const store = db.upserting.get(q.id);
33
- deepMerge(store.o, obj);
34
- return store.p;
32
+ export function upsert(db, type, payload, opts) {
33
+ const schema = getValidSchema(db, type);
34
+ const ctx = db.modifyCtx;
35
+ ctx.start = ctx.index;
36
+ ctx.schema = schema;
37
+ try {
38
+ reserve(ctx, TYPE_CURSOR_SIZE + 1 + 4 + 4);
39
+ writeTypeCursor(ctx);
40
+ writeU8(ctx, UPSERT);
41
+ const start = ctx.index;
42
+ ctx.index += 8;
43
+ writeAliases(ctx, schema.tree, payload);
44
+ writeUint32(ctx.array, ctx.index - start, start);
45
+ writeCreate(ctx, schema, {}, opts);
46
+ writeUint32(ctx.array, ctx.index - start, start + 4);
47
+ writeUpdate(ctx, schema, 0, payload, opts);
48
+ schedule(db, ctx);
49
+ return new Tmp(ctx);
35
50
  }
36
- const store = {
37
- o: obj,
38
- p: q.get().then((res) => {
39
- db.upserting.delete(q.id);
40
- if (res.length === 0) {
41
- return db.create(type, store.o, opts);
42
- }
43
- else {
44
- const obj = res.toObject();
45
- const id = Array.isArray(obj) ? obj[0].id : obj.id;
46
- // don't call update if it's not necessary
47
- return db.update(type, id, store.o, opts);
48
- }
49
- }),
50
- };
51
- db.upserting.set(q.id, store);
52
- return store.p;
53
- };
51
+ catch (e) {
52
+ return handleError(db, ctx, upsert, arguments, e);
53
+ }
54
+ }
55
+ export function insert(db, type, payload, opts) {
56
+ const schema = getValidSchema(db, type);
57
+ const ctx = db.modifyCtx;
58
+ ctx.start = ctx.index;
59
+ ctx.schema = schema;
60
+ try {
61
+ reserve(ctx, TYPE_CURSOR_SIZE + 1 + 4 + 4);
62
+ writeTypeCursor(ctx);
63
+ writeU8(ctx, INSERT);
64
+ const start = ctx.index;
65
+ ctx.index += 8;
66
+ writeAliases(ctx, schema.tree, payload);
67
+ writeUint32(ctx.array, ctx.index - start, start);
68
+ writeCreate(ctx, schema, payload, opts);
69
+ writeUint32(ctx.array, ctx.index - start, start + 4);
70
+ schedule(db, ctx);
71
+ return new Tmp(ctx);
72
+ }
73
+ catch (e) {
74
+ return handleError(db, ctx, insert, arguments, e);
75
+ }
76
+ }
54
77
  //# sourceMappingURL=index.js.map
@@ -123,13 +123,7 @@ export class QueryBranch {
123
123
  });
124
124
  }
125
125
  else {
126
- const groupByHook = this.def.schema.hooks?.groupBy;
127
- if (groupByHook) {
128
- this.def.schema.hooks.groupBy = null;
129
- groupByHook(this, field);
130
- this.def.schema.hooks.groupBy = groupByHook;
131
- }
132
- groupBy(this.def, field, step);
126
+ groupBy(this, field, step);
133
127
  }
134
128
  // only works with aggregates for now
135
129
  // @ts-ignore
@@ -347,6 +341,17 @@ export class QueryBranch {
347
341
  }
348
342
  else {
349
343
  include(this, fields);
344
+ if (this.def.schema.propHooks?.include) {
345
+ for (const field of this.def.include.stringFields.keys()) {
346
+ const hooks = this.def.schema.props[field]?.hooks;
347
+ const includeHook = hooks?.include;
348
+ if (includeHook) {
349
+ hooks.include = null;
350
+ includeHook(this, this.def.include.stringFields);
351
+ hooks.include = includeHook;
352
+ }
353
+ }
354
+ }
350
355
  const includeHook = this.def.schema.hooks?.include;
351
356
  if (includeHook) {
352
357
  this.def.schema.hooks.include = null;
@@ -3,6 +3,6 @@ import { StepInput, aggFnOptions } from './types.js';
3
3
  import { QueryBranch } from '../BasedDbQuery.js';
4
4
  import { AggregateType } from '@based/protocol/db-read';
5
5
  export declare const aggregateToBuffer: (aggregates: QueryDefAggregation) => Uint8Array;
6
- export declare const groupBy: (def: QueryDef, field: string, StepInput: StepInput) => void;
6
+ export declare const groupBy: (q: QueryBranch<any>, field: string, StepInput: StepInput) => void;
7
7
  export declare const addAggregate: (query: QueryBranch<any>, type: AggregateType, fields: string[], option?: aggFnOptions) => void;
8
8
  export declare const isRootCountOnly: (def: QueryDef, filterSize: number) => boolean;