serializable-bptree 3.1.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,8 +15,7 @@ import {
15
15
 
16
16
  class FileStoreStrategySync extends SerializeStrategySync<K, V> {
17
17
  id(): number {
18
- const random = Math.ceil(Math.random()*1000000)
19
- return random
18
+ return this.autoIncrement('index', 1)
20
19
  }
21
20
 
22
21
  read(id: number): BPTreeNode<K, V> {
@@ -202,7 +201,25 @@ id(): number {
202
201
 
203
202
  Or, you could use file input/output to save and load the value of the **before** variable.
204
203
 
205
- This method is called before a node is created in the tree. Therefore, it can also be used to allocate space for storing the node.
204
+ Typically, such an **id** value increases sequentially, and it would be beneficial to store such a value separately within the tree. For that purpose, the **setHeadData** and **getHeadData** methods are available. These methods are responsible for storing arbitrary data in the tree's header or retrieving stored data. Below is an example of usage:
205
+
206
+ ```typescript
207
+ id(): number {
208
+ const current = this.getHeadData('index', 1) as number
209
+ this.setHeadData('index', current+1)
210
+ return current
211
+ }
212
+ ```
213
+
214
+ Additionally, there is a more user-friendly usage of this code.
215
+
216
+ ```typescript
217
+ id(): number {
218
+ return this.autoIncrement('index', 1)
219
+ }
220
+ ```
221
+
222
+ The **id** method is called before a node is created in the tree. Therefore, it can also be used to allocate space for storing the node.
206
223
 
207
224
  #### read(id: `number`): `BPTreeNode<K, V>`
208
225
 
@@ -350,8 +367,7 @@ import {
350
367
 
351
368
  class FileStoreStrategyAsync extends SerializeStrategyAsync<K, V> {
352
369
  async id(): Promise<number> {
353
- const random = Math.ceil(Math.random()*1000000)
354
- return random
370
+ return await this.autoIncrement('index', 1)
355
371
  }
356
372
 
357
373
  async read(id: number): Promise<BPTreeNode<K, V>> {
package/dist/cjs/index.js CHANGED
@@ -78,11 +78,9 @@ var BPTree = class {
78
78
  comparator;
79
79
  nodes;
80
80
  order;
81
- data;
82
81
  root;
83
82
  _nodeCreateBuffer;
84
83
  _nodeUpdateBuffer;
85
- _headBuffer;
86
84
  verifierMap = {
87
85
  gt: (nv, v) => this.comparator.isHigher(nv, v),
88
86
  gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
@@ -127,19 +125,8 @@ var BPTree = class {
127
125
  notEqual: true,
128
126
  like: true
129
127
  };
130
- get headState() {
131
- const root = this.root.id;
132
- const order = this.order;
133
- const data = this.data;
134
- return {
135
- root,
136
- order,
137
- data
138
- };
139
- }
140
128
  constructor(strategy, comparator) {
141
129
  this._regexpCache = new CacheStorage();
142
- this._headBuffer = null;
143
130
  this._nodeCreateBuffer = /* @__PURE__ */ new Map();
144
131
  this._nodeUpdateBuffer = /* @__PURE__ */ new Map();
145
132
  this.nodes = /* @__PURE__ */ new Map();
@@ -173,9 +160,6 @@ var BPTree = class {
173
160
  this.bufferForNodeUpdate(node);
174
161
  }
175
162
  }
176
- bufferForHeadUpdate(head) {
177
- this._headBuffer = head;
178
- }
179
163
  bufferForNodeCreate(node) {
180
164
  this._nodeCreateBuffer.set(node.id, node);
181
165
  }
@@ -188,7 +172,7 @@ var BPTree = class {
188
172
  * @returns User-defined data stored in the head of the tree.
189
173
  */
190
174
  getHeadData() {
191
- return this.data;
175
+ return this.strategy.head.data;
192
176
  }
193
177
  };
194
178
 
@@ -307,7 +291,7 @@ var BPTreeSync = class extends BPTree {
307
291
  const keys = node.keys;
308
292
  this.root = this.getNode(keys[0]);
309
293
  this.root.parent = 0;
310
- this.bufferForHeadUpdate(this.headState);
294
+ this.strategy.head.root = this.root.id;
311
295
  this.bufferForNodeUpdate(this.root);
312
296
  return;
313
297
  } else if (this.root === node) {
@@ -513,9 +497,9 @@ var BPTreeSync = class extends BPTree {
513
497
  if (this.root === node) {
514
498
  const root = this._createNode([node.id, pointer.id], [value]);
515
499
  this.root = root;
500
+ this.strategy.head.root = root.id;
516
501
  node.parent = root.id;
517
502
  pointer.parent = root.id;
518
- this.bufferForHeadUpdate(this.headState);
519
503
  this.bufferForNodeCreate(root);
520
504
  this.bufferForNodeUpdate(node);
521
505
  this.bufferForNodeUpdate(pointer);
@@ -562,16 +546,15 @@ var BPTreeSync = class extends BPTree {
562
546
  const head = this.strategy.readHead();
563
547
  if (head === null) {
564
548
  this.order = this.strategy.order;
565
- this.data = {};
566
549
  this.root = this._createNode([], [], true);
567
- this.bufferForHeadUpdate(this.headState);
550
+ this.strategy.head.root = this.root.id;
568
551
  this.bufferForNodeCreate(this.root);
569
552
  this.commitHeadBuffer();
570
553
  this.commitNodeCreateBuffer();
571
554
  } else {
572
- const { root, order, data } = head;
555
+ const { root, order } = head;
556
+ this.strategy.head = head;
573
557
  this.order = order;
574
- this.data = data ?? {};
575
558
  this.root = this.getNode(root);
576
559
  }
577
560
  if (this.order < 3) {
@@ -613,10 +596,7 @@ var BPTreeSync = class extends BPTree {
613
596
  return node;
614
597
  }
615
598
  commitHeadBuffer() {
616
- if (this._headBuffer !== null) {
617
- this.strategy.writeHead(this._headBuffer);
618
- }
619
- this.bufferForHeadUpdate(null);
599
+ this.strategy.writeHead(this.strategy.head);
620
600
  }
621
601
  commitNodeCreateBuffer() {
622
602
  for (const node of this._nodeCreateBuffer.values()) {
@@ -739,8 +719,7 @@ var BPTreeSync = class extends BPTree {
739
719
  return false;
740
720
  }
741
721
  setHeadData(data) {
742
- this.data = data;
743
- this.bufferForHeadUpdate(this.headState);
722
+ this.strategy.head.data = data;
744
723
  this.commitHeadBuffer();
745
724
  }
746
725
  forceUpdate() {
@@ -869,7 +848,7 @@ var BPTreeAsync = class extends BPTree {
869
848
  const keys = node.keys;
870
849
  this.root = await this.getNode(keys[0]);
871
850
  this.root.parent = 0;
872
- this.bufferForHeadUpdate(this.headState);
851
+ this.strategy.head.root = this.root.id;
873
852
  this.bufferForNodeUpdate(this.root);
874
853
  return;
875
854
  } else if (this.root === node) {
@@ -1048,9 +1027,9 @@ var BPTreeAsync = class extends BPTree {
1048
1027
  if (this.root === node) {
1049
1028
  const root = await this._createNode([node.id, pointer.id], [value]);
1050
1029
  this.root = root;
1030
+ this.strategy.head.root = root.id;
1051
1031
  node.parent = root.id;
1052
1032
  pointer.parent = root.id;
1053
- this.bufferForHeadUpdate(this.headState);
1054
1033
  this.bufferForNodeCreate(root);
1055
1034
  this.bufferForNodeUpdate(node);
1056
1035
  this.bufferForNodeUpdate(pointer);
@@ -1097,16 +1076,15 @@ var BPTreeAsync = class extends BPTree {
1097
1076
  const head = await this.strategy.readHead();
1098
1077
  if (head === null) {
1099
1078
  this.order = this.strategy.order;
1100
- this.data = {};
1101
1079
  this.root = await this._createNode([], [], true);
1102
- this.bufferForHeadUpdate(this.headState);
1080
+ this.strategy.head.root = this.root.id;
1103
1081
  this.bufferForNodeCreate(this.root);
1104
1082
  this.commitHeadBuffer();
1105
1083
  this.commitNodeCreateBuffer();
1106
1084
  } else {
1107
- const { root, order, data } = head;
1085
+ const { root, order } = head;
1086
+ this.strategy.head = head;
1108
1087
  this.order = order;
1109
- this.data = data ?? {};
1110
1088
  this.root = await this.getNode(root);
1111
1089
  }
1112
1090
  if (this.order < 3) {
@@ -1148,10 +1126,7 @@ var BPTreeAsync = class extends BPTree {
1148
1126
  return node;
1149
1127
  }
1150
1128
  async commitHeadBuffer() {
1151
- if (this._headBuffer !== null) {
1152
- await this.strategy.writeHead(this._headBuffer);
1153
- }
1154
- this.bufferForHeadUpdate(null);
1129
+ await this.strategy.writeHead(this.strategy.head);
1155
1130
  }
1156
1131
  async commitNodeCreateBuffer() {
1157
1132
  for (const node of this._nodeCreateBuffer.values()) {
@@ -1274,8 +1249,7 @@ var BPTreeAsync = class extends BPTree {
1274
1249
  return false;
1275
1250
  }
1276
1251
  async setHeadData(data) {
1277
- this.data = data;
1278
- this.bufferForHeadUpdate(this.headState);
1252
+ this.strategy.head.data = data;
1279
1253
  await this.commitHeadBuffer();
1280
1254
  }
1281
1255
  async forceUpdate() {
@@ -1292,71 +1266,109 @@ var BPTreeAsync = class extends BPTree {
1292
1266
  // src/base/SerializeStrategy.ts
1293
1267
  var SerializeStrategy = class {
1294
1268
  order;
1269
+ head;
1295
1270
  constructor(order) {
1296
1271
  this.order = order;
1272
+ this.head = {
1273
+ order,
1274
+ root: 0,
1275
+ data: {}
1276
+ };
1297
1277
  }
1298
1278
  };
1299
1279
 
1300
1280
  // src/SerializeStrategySync.ts
1301
1281
  var SerializeStrategySync = class extends SerializeStrategy {
1282
+ getHeadData(key, defaultValue) {
1283
+ if (!Object.hasOwn(this.head.data, key)) {
1284
+ return defaultValue;
1285
+ }
1286
+ return this.head.data[key];
1287
+ }
1288
+ setHeadData(key, data) {
1289
+ this.head.data[key] = data;
1290
+ this.writeHead(this.head);
1291
+ }
1292
+ autoIncrement(key, defaultValue) {
1293
+ const current = this.getHeadData(key, defaultValue);
1294
+ const next = current + 1;
1295
+ this.setHeadData(key, next);
1296
+ return current;
1297
+ }
1302
1298
  };
1303
1299
  var InMemoryStoreStrategySync = class extends SerializeStrategySync {
1304
- data;
1300
+ node;
1305
1301
  constructor(order) {
1306
1302
  super(order);
1307
- this.data = {
1308
- head: null,
1309
- node: {}
1310
- };
1303
+ this.node = {};
1311
1304
  }
1312
1305
  id() {
1313
- return Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER - 1);
1306
+ return this.autoIncrement("index", 1);
1314
1307
  }
1315
1308
  read(id) {
1316
- if (!Object.prototype.hasOwnProperty.call(this.data.node, id)) {
1309
+ if (!Object.hasOwn(this.node, id)) {
1317
1310
  throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
1318
1311
  }
1319
- return this.data.node[id];
1312
+ return this.node[id];
1320
1313
  }
1321
1314
  write(id, node) {
1322
- this.data.node[id] = node;
1315
+ this.node[id] = node;
1323
1316
  }
1324
1317
  readHead() {
1325
- return this.data.head;
1318
+ if (this.head.root === 0) {
1319
+ return null;
1320
+ }
1321
+ return this.head;
1326
1322
  }
1327
1323
  writeHead(head) {
1328
- this.data.head = head;
1324
+ this.head = head;
1329
1325
  }
1330
1326
  };
1331
1327
 
1332
1328
  // src/SerializeStrategyAsync.ts
1333
1329
  var SerializeStrategyAsync = class extends SerializeStrategy {
1330
+ async getHeadData(key, defaultValue) {
1331
+ if (!Object.hasOwn(this.head.data, key)) {
1332
+ return defaultValue;
1333
+ }
1334
+ return this.head.data[key];
1335
+ }
1336
+ async setHeadData(key, data) {
1337
+ this.head.data[key] = data;
1338
+ await this.writeHead(this.head);
1339
+ }
1340
+ async autoIncrement(key, defaultValue) {
1341
+ const current = await this.getHeadData(key, defaultValue);
1342
+ const next = current + 1;
1343
+ await this.setHeadData(key, next);
1344
+ return current;
1345
+ }
1334
1346
  };
1335
1347
  var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
1336
- data;
1348
+ node;
1337
1349
  constructor(order) {
1338
1350
  super(order);
1339
- this.data = {
1340
- head: null,
1341
- node: {}
1342
- };
1351
+ this.node = {};
1343
1352
  }
1344
1353
  async id() {
1345
- return Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER - 1);
1354
+ return await this.autoIncrement("index", 1);
1346
1355
  }
1347
1356
  async read(id) {
1348
- if (!Object.prototype.hasOwnProperty.call(this.data.node, id)) {
1357
+ if (!Object.hasOwn(this.node, id)) {
1349
1358
  throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
1350
1359
  }
1351
- return this.data.node[id];
1360
+ return this.node[id];
1352
1361
  }
1353
1362
  async write(id, node) {
1354
- this.data.node[id] = node;
1363
+ this.node[id] = node;
1355
1364
  }
1356
1365
  async readHead() {
1357
- return this.data.head;
1366
+ if (this.head.root === 0) {
1367
+ return null;
1368
+ }
1369
+ return this.head;
1358
1370
  }
1359
1371
  async writeHead(head) {
1360
- this.data.head = head;
1372
+ this.head = head;
1361
1373
  }
1362
1374
  };
package/dist/esm/index.js CHANGED
@@ -44,11 +44,9 @@ var BPTree = class {
44
44
  comparator;
45
45
  nodes;
46
46
  order;
47
- data;
48
47
  root;
49
48
  _nodeCreateBuffer;
50
49
  _nodeUpdateBuffer;
51
- _headBuffer;
52
50
  verifierMap = {
53
51
  gt: (nv, v) => this.comparator.isHigher(nv, v),
54
52
  gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
@@ -93,19 +91,8 @@ var BPTree = class {
93
91
  notEqual: true,
94
92
  like: true
95
93
  };
96
- get headState() {
97
- const root = this.root.id;
98
- const order = this.order;
99
- const data = this.data;
100
- return {
101
- root,
102
- order,
103
- data
104
- };
105
- }
106
94
  constructor(strategy, comparator) {
107
95
  this._regexpCache = new CacheStorage();
108
- this._headBuffer = null;
109
96
  this._nodeCreateBuffer = /* @__PURE__ */ new Map();
110
97
  this._nodeUpdateBuffer = /* @__PURE__ */ new Map();
111
98
  this.nodes = /* @__PURE__ */ new Map();
@@ -139,9 +126,6 @@ var BPTree = class {
139
126
  this.bufferForNodeUpdate(node);
140
127
  }
141
128
  }
142
- bufferForHeadUpdate(head) {
143
- this._headBuffer = head;
144
- }
145
129
  bufferForNodeCreate(node) {
146
130
  this._nodeCreateBuffer.set(node.id, node);
147
131
  }
@@ -154,7 +138,7 @@ var BPTree = class {
154
138
  * @returns User-defined data stored in the head of the tree.
155
139
  */
156
140
  getHeadData() {
157
- return this.data;
141
+ return this.strategy.head.data;
158
142
  }
159
143
  };
160
144
 
@@ -273,7 +257,7 @@ var BPTreeSync = class extends BPTree {
273
257
  const keys = node.keys;
274
258
  this.root = this.getNode(keys[0]);
275
259
  this.root.parent = 0;
276
- this.bufferForHeadUpdate(this.headState);
260
+ this.strategy.head.root = this.root.id;
277
261
  this.bufferForNodeUpdate(this.root);
278
262
  return;
279
263
  } else if (this.root === node) {
@@ -479,9 +463,9 @@ var BPTreeSync = class extends BPTree {
479
463
  if (this.root === node) {
480
464
  const root = this._createNode([node.id, pointer.id], [value]);
481
465
  this.root = root;
466
+ this.strategy.head.root = root.id;
482
467
  node.parent = root.id;
483
468
  pointer.parent = root.id;
484
- this.bufferForHeadUpdate(this.headState);
485
469
  this.bufferForNodeCreate(root);
486
470
  this.bufferForNodeUpdate(node);
487
471
  this.bufferForNodeUpdate(pointer);
@@ -528,16 +512,15 @@ var BPTreeSync = class extends BPTree {
528
512
  const head = this.strategy.readHead();
529
513
  if (head === null) {
530
514
  this.order = this.strategy.order;
531
- this.data = {};
532
515
  this.root = this._createNode([], [], true);
533
- this.bufferForHeadUpdate(this.headState);
516
+ this.strategy.head.root = this.root.id;
534
517
  this.bufferForNodeCreate(this.root);
535
518
  this.commitHeadBuffer();
536
519
  this.commitNodeCreateBuffer();
537
520
  } else {
538
- const { root, order, data } = head;
521
+ const { root, order } = head;
522
+ this.strategy.head = head;
539
523
  this.order = order;
540
- this.data = data ?? {};
541
524
  this.root = this.getNode(root);
542
525
  }
543
526
  if (this.order < 3) {
@@ -579,10 +562,7 @@ var BPTreeSync = class extends BPTree {
579
562
  return node;
580
563
  }
581
564
  commitHeadBuffer() {
582
- if (this._headBuffer !== null) {
583
- this.strategy.writeHead(this._headBuffer);
584
- }
585
- this.bufferForHeadUpdate(null);
565
+ this.strategy.writeHead(this.strategy.head);
586
566
  }
587
567
  commitNodeCreateBuffer() {
588
568
  for (const node of this._nodeCreateBuffer.values()) {
@@ -705,8 +685,7 @@ var BPTreeSync = class extends BPTree {
705
685
  return false;
706
686
  }
707
687
  setHeadData(data) {
708
- this.data = data;
709
- this.bufferForHeadUpdate(this.headState);
688
+ this.strategy.head.data = data;
710
689
  this.commitHeadBuffer();
711
690
  }
712
691
  forceUpdate() {
@@ -835,7 +814,7 @@ var BPTreeAsync = class extends BPTree {
835
814
  const keys = node.keys;
836
815
  this.root = await this.getNode(keys[0]);
837
816
  this.root.parent = 0;
838
- this.bufferForHeadUpdate(this.headState);
817
+ this.strategy.head.root = this.root.id;
839
818
  this.bufferForNodeUpdate(this.root);
840
819
  return;
841
820
  } else if (this.root === node) {
@@ -1014,9 +993,9 @@ var BPTreeAsync = class extends BPTree {
1014
993
  if (this.root === node) {
1015
994
  const root = await this._createNode([node.id, pointer.id], [value]);
1016
995
  this.root = root;
996
+ this.strategy.head.root = root.id;
1017
997
  node.parent = root.id;
1018
998
  pointer.parent = root.id;
1019
- this.bufferForHeadUpdate(this.headState);
1020
999
  this.bufferForNodeCreate(root);
1021
1000
  this.bufferForNodeUpdate(node);
1022
1001
  this.bufferForNodeUpdate(pointer);
@@ -1063,16 +1042,15 @@ var BPTreeAsync = class extends BPTree {
1063
1042
  const head = await this.strategy.readHead();
1064
1043
  if (head === null) {
1065
1044
  this.order = this.strategy.order;
1066
- this.data = {};
1067
1045
  this.root = await this._createNode([], [], true);
1068
- this.bufferForHeadUpdate(this.headState);
1046
+ this.strategy.head.root = this.root.id;
1069
1047
  this.bufferForNodeCreate(this.root);
1070
1048
  this.commitHeadBuffer();
1071
1049
  this.commitNodeCreateBuffer();
1072
1050
  } else {
1073
- const { root, order, data } = head;
1051
+ const { root, order } = head;
1052
+ this.strategy.head = head;
1074
1053
  this.order = order;
1075
- this.data = data ?? {};
1076
1054
  this.root = await this.getNode(root);
1077
1055
  }
1078
1056
  if (this.order < 3) {
@@ -1114,10 +1092,7 @@ var BPTreeAsync = class extends BPTree {
1114
1092
  return node;
1115
1093
  }
1116
1094
  async commitHeadBuffer() {
1117
- if (this._headBuffer !== null) {
1118
- await this.strategy.writeHead(this._headBuffer);
1119
- }
1120
- this.bufferForHeadUpdate(null);
1095
+ await this.strategy.writeHead(this.strategy.head);
1121
1096
  }
1122
1097
  async commitNodeCreateBuffer() {
1123
1098
  for (const node of this._nodeCreateBuffer.values()) {
@@ -1240,8 +1215,7 @@ var BPTreeAsync = class extends BPTree {
1240
1215
  return false;
1241
1216
  }
1242
1217
  async setHeadData(data) {
1243
- this.data = data;
1244
- this.bufferForHeadUpdate(this.headState);
1218
+ this.strategy.head.data = data;
1245
1219
  await this.commitHeadBuffer();
1246
1220
  }
1247
1221
  async forceUpdate() {
@@ -1258,72 +1232,110 @@ var BPTreeAsync = class extends BPTree {
1258
1232
  // src/base/SerializeStrategy.ts
1259
1233
  var SerializeStrategy = class {
1260
1234
  order;
1235
+ head;
1261
1236
  constructor(order) {
1262
1237
  this.order = order;
1238
+ this.head = {
1239
+ order,
1240
+ root: 0,
1241
+ data: {}
1242
+ };
1263
1243
  }
1264
1244
  };
1265
1245
 
1266
1246
  // src/SerializeStrategySync.ts
1267
1247
  var SerializeStrategySync = class extends SerializeStrategy {
1248
+ getHeadData(key, defaultValue) {
1249
+ if (!Object.hasOwn(this.head.data, key)) {
1250
+ return defaultValue;
1251
+ }
1252
+ return this.head.data[key];
1253
+ }
1254
+ setHeadData(key, data) {
1255
+ this.head.data[key] = data;
1256
+ this.writeHead(this.head);
1257
+ }
1258
+ autoIncrement(key, defaultValue) {
1259
+ const current = this.getHeadData(key, defaultValue);
1260
+ const next = current + 1;
1261
+ this.setHeadData(key, next);
1262
+ return current;
1263
+ }
1268
1264
  };
1269
1265
  var InMemoryStoreStrategySync = class extends SerializeStrategySync {
1270
- data;
1266
+ node;
1271
1267
  constructor(order) {
1272
1268
  super(order);
1273
- this.data = {
1274
- head: null,
1275
- node: {}
1276
- };
1269
+ this.node = {};
1277
1270
  }
1278
1271
  id() {
1279
- return Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER - 1);
1272
+ return this.autoIncrement("index", 1);
1280
1273
  }
1281
1274
  read(id) {
1282
- if (!Object.prototype.hasOwnProperty.call(this.data.node, id)) {
1275
+ if (!Object.hasOwn(this.node, id)) {
1283
1276
  throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
1284
1277
  }
1285
- return this.data.node[id];
1278
+ return this.node[id];
1286
1279
  }
1287
1280
  write(id, node) {
1288
- this.data.node[id] = node;
1281
+ this.node[id] = node;
1289
1282
  }
1290
1283
  readHead() {
1291
- return this.data.head;
1284
+ if (this.head.root === 0) {
1285
+ return null;
1286
+ }
1287
+ return this.head;
1292
1288
  }
1293
1289
  writeHead(head) {
1294
- this.data.head = head;
1290
+ this.head = head;
1295
1291
  }
1296
1292
  };
1297
1293
 
1298
1294
  // src/SerializeStrategyAsync.ts
1299
1295
  var SerializeStrategyAsync = class extends SerializeStrategy {
1296
+ async getHeadData(key, defaultValue) {
1297
+ if (!Object.hasOwn(this.head.data, key)) {
1298
+ return defaultValue;
1299
+ }
1300
+ return this.head.data[key];
1301
+ }
1302
+ async setHeadData(key, data) {
1303
+ this.head.data[key] = data;
1304
+ await this.writeHead(this.head);
1305
+ }
1306
+ async autoIncrement(key, defaultValue) {
1307
+ const current = await this.getHeadData(key, defaultValue);
1308
+ const next = current + 1;
1309
+ await this.setHeadData(key, next);
1310
+ return current;
1311
+ }
1300
1312
  };
1301
1313
  var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
1302
- data;
1314
+ node;
1303
1315
  constructor(order) {
1304
1316
  super(order);
1305
- this.data = {
1306
- head: null,
1307
- node: {}
1308
- };
1317
+ this.node = {};
1309
1318
  }
1310
1319
  async id() {
1311
- return Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER - 1);
1320
+ return await this.autoIncrement("index", 1);
1312
1321
  }
1313
1322
  async read(id) {
1314
- if (!Object.prototype.hasOwnProperty.call(this.data.node, id)) {
1323
+ if (!Object.hasOwn(this.node, id)) {
1315
1324
  throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
1316
1325
  }
1317
- return this.data.node[id];
1326
+ return this.node[id];
1318
1327
  }
1319
1328
  async write(id, node) {
1320
- this.data.node[id] = node;
1329
+ this.node[id] = node;
1321
1330
  }
1322
1331
  async readHead() {
1323
- return this.data.head;
1332
+ if (this.head.root === 0) {
1333
+ return null;
1334
+ }
1335
+ return this.head;
1324
1336
  }
1325
1337
  async writeHead(head) {
1326
- this.data.head = head;
1338
+ this.head = head;
1327
1339
  }
1328
1340
  };
1329
1341
  export {
@@ -1,7 +1,7 @@
1
- import type { Json } from './utils/types';
2
1
  import { BPTree, BPTreeCondition, BPTreeLeafNode, BPTreePair, BPTreeNodeKey, BPTreeUnknownNode } from './base/BPTree';
3
2
  import { SerializeStrategyAsync } from './SerializeStrategyAsync';
4
3
  import { ValueComparator } from './base/ValueComparator';
4
+ import { SerializableData } from './base/SerializeStrategy';
5
5
  export declare class BPTreeAsync<K, V> extends BPTree<K, V> {
6
6
  protected readonly strategy: SerializeStrategyAsync<K, V>;
7
7
  constructor(strategy: SerializeStrategyAsync<K, V>, comparator: ValueComparator<V>);
@@ -24,6 +24,6 @@ export declare class BPTreeAsync<K, V> extends BPTree<K, V> {
24
24
  insert(key: K, value: V): Promise<void>;
25
25
  delete(key: K, value: V): Promise<void>;
26
26
  exists(key: K, value: V): Promise<boolean>;
27
- setHeadData(data: Record<string, Json>): Promise<void>;
27
+ setHeadData(data: SerializableData): Promise<void>;
28
28
  forceUpdate(): Promise<number>;
29
29
  }
@@ -1,7 +1,7 @@
1
- import type { Json } from './utils/types';
2
1
  import { BPTree, BPTreeCondition, BPTreeLeafNode, BPTreePair, BPTreeNodeKey, BPTreeUnknownNode } from './base/BPTree';
3
2
  import { SerializeStrategySync } from './SerializeStrategySync';
4
3
  import { ValueComparator } from './base/ValueComparator';
4
+ import { SerializableData } from './base/SerializeStrategy';
5
5
  export declare class BPTreeSync<K, V> extends BPTree<K, V> {
6
6
  protected readonly strategy: SerializeStrategySync<K, V>;
7
7
  constructor(strategy: SerializeStrategySync<K, V>, comparator: ValueComparator<V>);
@@ -25,6 +25,6 @@ export declare class BPTreeSync<K, V> extends BPTree<K, V> {
25
25
  insert(key: K, value: V): void;
26
26
  delete(key: K, value: V): void;
27
27
  exists(key: K, value: V): boolean;
28
- setHeadData(data: Record<string, Json>): void;
28
+ setHeadData(data: SerializableData): void;
29
29
  forceUpdate(): number;
30
30
  }
@@ -1,17 +1,18 @@
1
1
  import { BPTreeNode } from './base/BPTree';
2
2
  import { SerializeStrategy, SerializeStrategyHead } from './base/SerializeStrategy';
3
+ import { Json } from './utils/types';
3
4
  export declare abstract class SerializeStrategyAsync<K, V> extends SerializeStrategy<K, V> {
4
5
  abstract id(): Promise<number>;
5
6
  abstract read(id: number): Promise<BPTreeNode<K, V>>;
6
7
  abstract write(id: number, node: BPTreeNode<K, V>): Promise<void>;
7
8
  abstract readHead(): Promise<SerializeStrategyHead | null>;
8
9
  abstract writeHead(head: SerializeStrategyHead): Promise<void>;
10
+ getHeadData(key: string, defaultValue: Json): Promise<Json>;
11
+ setHeadData(key: string, data: Json): Promise<void>;
12
+ autoIncrement(key: string, defaultValue: number): Promise<number>;
9
13
  }
10
14
  export declare class InMemoryStoreStrategyAsync<K, V> extends SerializeStrategyAsync<K, V> {
11
- protected readonly data: {
12
- head: SerializeStrategyHead | null;
13
- node: Record<number, BPTreeNode<K, V>>;
14
- };
15
+ protected readonly node: Record<number, BPTreeNode<K, V>>;
15
16
  constructor(order: number);
16
17
  id(): Promise<number>;
17
18
  read(id: number): Promise<BPTreeNode<K, V>>;
@@ -1,17 +1,18 @@
1
1
  import { BPTreeNode } from './base/BPTree';
2
2
  import { SerializeStrategy, SerializeStrategyHead } from './base/SerializeStrategy';
3
+ import { Json } from './utils/types';
3
4
  export declare abstract class SerializeStrategySync<K, V> extends SerializeStrategy<K, V> {
4
5
  abstract id(): number;
5
6
  abstract read(id: number): BPTreeNode<K, V>;
6
7
  abstract write(id: number, node: BPTreeNode<K, V>): void;
7
8
  abstract readHead(): SerializeStrategyHead | null;
8
9
  abstract writeHead(head: SerializeStrategyHead): void;
10
+ getHeadData(key: string, defaultValue: Json): Json;
11
+ setHeadData(key: string, data: Json): void;
12
+ autoIncrement(key: string, defaultValue: number): number;
9
13
  }
10
14
  export declare class InMemoryStoreStrategySync<K, V> extends SerializeStrategySync<K, V> {
11
- protected readonly data: {
12
- head: SerializeStrategyHead | null;
13
- node: Record<number, BPTreeNode<K, V>>;
14
- };
15
+ protected readonly node: Record<number, BPTreeNode<K, V>>;
15
16
  constructor(order: number);
16
17
  id(): number;
17
18
  read(id: number): BPTreeNode<K, V>;
@@ -1,6 +1,5 @@
1
- import type { Json } from '../utils/types';
2
1
  import { ValueComparator } from './ValueComparator';
3
- import { SerializeStrategy, SerializeStrategyHead } from './SerializeStrategy';
2
+ import { SerializableData, SerializeStrategy } from './SerializeStrategy';
4
3
  type Sync<T> = T;
5
4
  type Async<T> = Promise<T>;
6
5
  type Deferred<T> = Sync<T> | Async<T>;
@@ -49,16 +48,13 @@ export declare abstract class BPTree<K, V> {
49
48
  protected readonly comparator: ValueComparator<V>;
50
49
  protected readonly nodes: Map<number, BPTreeUnknownNode<K, V>>;
51
50
  protected order: number;
52
- protected data: Record<string, Json>;
53
51
  protected root: BPTreeUnknownNode<K, V>;
54
52
  protected readonly _nodeCreateBuffer: Map<number, BPTreeUnknownNode<K, V>>;
55
53
  protected readonly _nodeUpdateBuffer: Map<number, BPTreeUnknownNode<K, V>>;
56
- protected _headBuffer: SerializeStrategyHead | null;
57
54
  protected readonly verifierMap: Record<keyof BPTreeCondition<V>, (nodeValue: V, value: V) => boolean>;
58
55
  protected readonly verifierStartNode: Record<keyof BPTreeCondition<V>, (value: V) => Deferred<BPTreeLeafNode<K, V>>>;
59
56
  protected readonly verifierDirection: Record<keyof BPTreeCondition<V>, -1 | 1>;
60
57
  protected readonly verifierFullScan: Record<keyof BPTreeCondition<V>, boolean>;
61
- protected get headState(): SerializeStrategyHead;
62
58
  protected constructor(strategy: SerializeStrategy<K, V>, comparator: ValueComparator<V>);
63
59
  protected abstract _getPairsRightToLeft(value: V, startNode: BPTreeLeafNode<K, V>, fullSearch: boolean, comparator: (nodeValue: V, value: V) => boolean): Deferred<BPTreePair<K, V>[]>;
64
60
  protected abstract _getPairsLeftToRight(value: V, startNode: BPTreeLeafNode<K, V>, fullSearch: boolean, comparator: (nodeValue: V, value: V) => boolean): Deferred<BPTreePair<K, V>[]>;
@@ -117,7 +113,7 @@ export declare abstract class BPTree<K, V> {
117
113
  * For example, you can store information such as the last update time and the number of insertions.
118
114
  * @param data User-defined data to be stored in the head of the tree.
119
115
  */
120
- abstract setHeadData(data: Record<string, Json>): Deferred<void>;
116
+ abstract setHeadData(data: SerializableData): Deferred<void>;
121
117
  /**
122
118
  * This method deletes nodes cached in-memory and caches new nodes from the stored nodes.
123
119
  * Typically, there's no need to use this method, but it can be used to synchronize data in scenarios where the remote storage and the client are in a 1:n relationship.
@@ -125,7 +121,6 @@ export declare abstract class BPTree<K, V> {
125
121
  */
126
122
  abstract forceUpdate(nodeId: number): Deferred<number>;
127
123
  protected _insertAtLeaf(node: BPTreeLeafNode<K, V>, key: K, value: V): void;
128
- protected bufferForHeadUpdate(head: SerializeStrategyHead | null): Deferred<void>;
129
124
  protected bufferForNodeCreate(node: BPTreeUnknownNode<K, V>): Deferred<void>;
130
125
  protected bufferForNodeUpdate(node: BPTreeUnknownNode<K, V>): Deferred<void>;
131
126
  /**
@@ -133,6 +128,6 @@ export declare abstract class BPTree<K, V> {
133
128
  * This value can be set using the `setHeadData` method. If no data has been previously inserted, the default value is returned, and the default value is `{}`.
134
129
  * @returns User-defined data stored in the head of the tree.
135
130
  */
136
- getHeadData(): Record<string, Json>;
131
+ getHeadData(): SerializableData;
137
132
  }
138
133
  export {};
@@ -1,12 +1,14 @@
1
1
  import { BPTreeNode } from './BPTree';
2
2
  import type { Json } from '../utils/types';
3
+ export type SerializableData = Record<string, Json>;
3
4
  export interface SerializeStrategyHead {
4
5
  root: number;
5
6
  order: number;
6
- data: Record<string, Json>;
7
+ data: SerializableData;
7
8
  }
8
9
  export declare abstract class SerializeStrategy<K, V> {
9
10
  readonly order: number;
11
+ head: SerializeStrategyHead;
10
12
  constructor(order: number);
11
13
  /**
12
14
  * The rule for generating node IDs is set.
@@ -42,4 +44,28 @@ export declare abstract class SerializeStrategy<K, V> {
42
44
  * @param head This is the current state of the tree.
43
45
  */
44
46
  abstract writeHead(head: SerializeStrategyHead): void | Promise<void>;
47
+ /**
48
+ * Retrieves the data stored in the tree.
49
+ * If there are no values stored in the tree, it returns the `defaultValue`.
50
+ * @param key The key of the data stored in the tree.
51
+ */
52
+ abstract getHeadData(key: string, defaultValue: Json): Json | Promise<Json>;
53
+ /**
54
+ * Stores data in the tree.
55
+ * This data is permanently stored in the head.
56
+ * The stored data can be retrieved later using the `getHeadData` method.
57
+ * @param key The key of the data to be stored in the tree.
58
+ * @param data The data to be stored in the tree.
59
+ */
60
+ abstract setHeadData(key: string, data: Json): void | Promise<void>;
61
+ /**
62
+ * This method returns a numeric value and increments it by `1`, storing it in the tree's header.
63
+ * Therefore, when called again, the value incremented by `+1` is returned.
64
+ *
65
+ * This is a syntactic sugar for using the `setHeadData` and `getHeadData` methods.
66
+ * It assists in simplifying the implementation of node ID generation in the `id` method.
67
+ * @param key The key of the data to be stored in the tree.
68
+ * @param defaultValue The data to be stored in the tree.
69
+ */
70
+ abstract autoIncrement(key: string, defaultValue: number): number | Promise<number>;
45
71
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serializable-bptree",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "Store the B+tree flexibly, not only in-memory.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",