xitdb 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,19 +3,22 @@
3
3
  <br/>
4
4
  <br/>
5
5
  <b>Choose your flavor:</b>
6
- <a href="https://github.com/radarroark/xitdb">Zig</a> |
7
- <a href="https://github.com/radarroark/xitdb-java">Java</a> |
6
+ <a href="https://github.com/xit-vcs/xitdb">Zig</a> |
7
+ <a href="https://github.com/xit-vcs/xitdb-java">Java</a> |
8
8
  <a href="https://github.com/codeboost/xitdb-clj">Clojure</a> |
9
- <a href="https://github.com/radarroark/xitdb-ts">TypeScript</a>
9
+ <a href="https://github.com/xit-vcs/xitdb-ts">TypeScript</a>
10
10
  </p>
11
11
 
12
- * Each transaction efficiently creates a new "copy" of the database, and past copies can still be read from.
13
- * It supports writing to a file as well as purely in-memory use.
12
+ * Each transaction efficiently creates a new "copy" of the database, and past copies can still be read from and reverted to.
13
+ * Supports storing in a single file as well as purely in-memory use.
14
+ * Runs as a library (embedded in process).
15
+ * Incrementally reads and writes, so file-based databases can contain larger-than-memory datasets.
16
+ * Reads never block writes, and a database can be read from multiple threads/processes without locks.
14
17
  * No query engine of any kind. You just write data structures (primarily an `ArrayList` and `HashMap`) that can be nested arbitrarily.
15
18
  * No dependencies besides the JavaScript standard library.
16
- * It is available [on npm](https://www.npmjs.com/package/xitdb).
19
+ * Available [on npm](https://www.npmjs.com/package/xitdb).
17
20
 
18
- This database was originally made for the [xit version control system](https://github.com/radarroark/xit), but I bet it has a lot of potential for other projects. The combination of being immutable and having an API similar to in-memory data structures is pretty powerful. Consider using it [instead of SQLite](https://gist.github.com/radarroark/03a0724484e1111ef4c05d72a935c42c) for your TypeScript projects: it's simpler, it's pure TypeScript, and it creates no impedance mismatch with your program the way SQL databases do.
21
+ This database was originally made for the [xit version control system](https://github.com/xit-vcs/xit), but I bet it has a lot of potential for other projects. The combination of being immutable and having an API similar to in-memory data structures is pretty powerful. Consider using it [instead of SQLite](https://gist.github.com/radarroark/03a0724484e1111ef4c05d72a935c42c) for your TypeScript projects: it's simpler, it's pure TypeScript, and it creates no impedance mismatch with your program the way SQL databases do.
19
22
 
20
23
  * [Example](#example)
21
24
  * [Initializing a Database](#initializing-a-database)
@@ -24,6 +27,7 @@ This database was originally made for the [xit version control system](https://g
24
27
  * [Large Byte Arrays](#large-byte-arrays)
25
28
  * [Iterators](#iterators)
26
29
  * [Hashing](#hashing)
30
+ * [Compaction](#compaction)
27
31
 
28
32
  ## Example
29
33
 
@@ -85,7 +89,7 @@ await history.appendContext(await history.getSlot(-1), async (cursor) => {
85
89
  // get the most recent copy of the database, like a moment
86
90
  // in time. the -1 index will return the last index in the list.
87
91
  const momentCursor = await history.getCursor(-1);
88
- const moment = await ReadHashMap.create(momentCursor!);
92
+ const moment = new ReadHashMap(momentCursor!);
89
93
 
90
94
  // we can read the value of "foo" from the map by getting
91
95
  // the cursor to "foo" and then calling readBytes on it
@@ -180,7 +184,7 @@ await history.appendContext(await history.getSlot(-1), async (cursor) => {
180
184
  });
181
185
 
182
186
  const momentCursor = await history.getCursor(-1);
183
- const moment = await ReadHashMap.create(momentCursor!);
187
+ const moment = new ReadHashMap(momentCursor!);
184
188
 
185
189
  // the food list includes the fruits
186
190
  const foodCursor = await moment.getCursor('food');
@@ -221,7 +225,7 @@ await history.appendContext(await history.getSlot(-1), async (cursor) => {
221
225
  });
222
226
 
223
227
  const momentCursor = await history.getCursor(-1);
224
- const moment = await ReadHashMap.create(momentCursor!);
228
+ const moment = new ReadHashMap(momentCursor!);
225
229
 
226
230
  // the cities list contains all four
227
231
  const citiesCursor = await moment.getCursor('cities');
@@ -267,7 +271,7 @@ await history.appendContext(await history.getSlot(-1), async (cursor) => {
267
271
  });
268
272
 
269
273
  const momentCursor = await history.getCursor(-1);
270
- const moment = await ReadHashMap.create(momentCursor!);
274
+ const moment = new ReadHashMap(momentCursor!);
271
275
 
272
276
  // the cities list contains all four
273
277
  const citiesCursor = await moment.getCursor('cities');
@@ -323,7 +327,7 @@ const people = new ReadArrayList(peopleCursor!);
323
327
  const peopleIter = await people.iterator();
324
328
  while (await peopleIter.hasNext()) {
325
329
  const personCursor = await peopleIter.next();
326
- const person = await ReadHashMap.create(personCursor!);
330
+ const person = new ReadHashMap(personCursor!);
327
331
  const personIter = await person.iterator();
328
332
  while (await personIter.hasNext()) {
329
333
  const kvPairCursor = await personIter.next();
@@ -414,3 +418,18 @@ switch (hashIdStr) {
414
418
  throw new Error('Invalid hash algorithm');
415
419
  }
416
420
  ```
421
+
422
+ ## Compaction
423
+
424
+ Normally, an immutable database grows forever, because old data is never deleted. To reclaim disk space and clear the history, xitdb supports compaction. This involves completely rebuilding the database file to only contain the data accessible from the latest copy (i.e., "moment") of the database.
425
+
426
+ ```typescript
427
+ // create the file and core for the new database
428
+ using compactCore = await CoreBufferedFile.create('compact.db');
429
+
430
+ const compactDb = await db.compact(compactCore);
431
+
432
+ // read from the new compacted db
433
+ const history = new ReadArrayList(compactDb.rootCursor());
434
+ expect(await history.count()).toBe(1);
435
+ ```
@@ -223,6 +223,7 @@ export declare class Database {
223
223
  static create(core: Core, hasher: Hasher): Promise<Database>;
224
224
  rootCursor(): WriteCursor;
225
225
  freeze(): Promise<void>;
226
+ compact(targetCore: Core): Promise<Database>;
226
227
  truncate(): Promise<void>;
227
228
  checkHashBytes(hash: Uint8Array): Uint8Array;
228
229
  checkHash(target: HashMapGetTarget): Uint8Array;
package/dist/index.js CHANGED
@@ -2317,6 +2317,43 @@ class Database3 {
2317
2317
  throw new ExpectedTxStartException;
2318
2318
  }
2319
2319
  }
2320
+ async compact(targetCore) {
2321
+ const offsetMap = new Map;
2322
+ const hasher = new Hasher(this.hasher.algorithm, this.header.hashId);
2323
+ const target = await Database3.create(targetCore, hasher);
2324
+ if (this.header.tag === 0 /* NONE */)
2325
+ return target;
2326
+ if (this.header.tag !== 2 /* ARRAY_LIST */)
2327
+ throw new UnexpectedTagException;
2328
+ await this.core.seek(Header.LENGTH);
2329
+ const sourceReader = this.core.reader();
2330
+ const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
2331
+ await sourceReader.readFully(headerBytes);
2332
+ const sourceHeader = ArrayListHeader.fromBytes(headerBytes);
2333
+ if (sourceHeader.size === 0)
2334
+ return target;
2335
+ const lastKey = sourceHeader.size - 1;
2336
+ const shift = lastKey < SLOT_COUNT ? 0 : Math.floor(Math.log(lastKey) / Math.log(SLOT_COUNT));
2337
+ const lastSlotPtr = await this.readArrayListSlot(sourceHeader.ptr, lastKey, shift, 0 /* READ_ONLY */, true);
2338
+ const momentSlot = lastSlotPtr.slot;
2339
+ const targetWriter = targetCore.writer();
2340
+ await targetCore.seek(Header.LENGTH);
2341
+ const targetArrayListPtr = Header.LENGTH + TopLevelArrayListHeader.LENGTH;
2342
+ await targetWriter.write(new TopLevelArrayListHeader(0, new ArrayListHeader(targetArrayListPtr, 1)).toBytes());
2343
+ await targetWriter.write(new Uint8Array(INDEX_BLOCK_SIZE));
2344
+ const remappedMoment = await remapSlot(this.core, targetCore, this.header.hashSize, offsetMap, momentSlot);
2345
+ await targetCore.seek(targetArrayListPtr);
2346
+ await targetWriter.write(remappedMoment.toBytes());
2347
+ target.header = target.header.withTag(2 /* ARRAY_LIST */);
2348
+ await targetCore.seek(0);
2349
+ await target.header.write(targetCore);
2350
+ await targetCore.flush();
2351
+ const fileSize = await targetCore.length();
2352
+ await targetCore.seek(Header.LENGTH + ArrayListHeader.LENGTH);
2353
+ await targetWriter.writeLong(fileSize);
2354
+ await targetCore.flush();
2355
+ return target;
2356
+ }
2320
2357
  async truncate() {
2321
2358
  if (this.header.tag !== 2 /* ARRAY_LIST */)
2322
2359
  return;
@@ -3141,17 +3178,229 @@ class Database3 {
3141
3178
  return new LinkedArrayListHeader(nextShift, rootPtr, headerA.size + headerB.size);
3142
3179
  }
3143
3180
  }
3181
+ async function remapSlot(sourceCore, targetCore, hashSize, offsetMap, slot) {
3182
+ switch (slot.tag) {
3183
+ case 0 /* NONE */:
3184
+ case 8 /* UINT */:
3185
+ case 9 /* INT */:
3186
+ case 10 /* FLOAT */:
3187
+ case 7 /* SHORT_BYTES */:
3188
+ return slot;
3189
+ case 6 /* BYTES */: {
3190
+ const mapped = offsetMap.get(Number(slot.value));
3191
+ if (mapped !== undefined)
3192
+ return new Slot(mapped, slot.tag, slot.full);
3193
+ const newOffset = await remapBytes(sourceCore, targetCore, slot);
3194
+ offsetMap.set(Number(slot.value), newOffset);
3195
+ return new Slot(newOffset, slot.tag, slot.full);
3196
+ }
3197
+ case 1 /* INDEX */: {
3198
+ const mapped = offsetMap.get(Number(slot.value));
3199
+ if (mapped !== undefined)
3200
+ return new Slot(mapped, slot.tag, slot.full);
3201
+ const newOffset = await remapIndex(sourceCore, targetCore, hashSize, offsetMap, slot);
3202
+ offsetMap.set(Number(slot.value), newOffset);
3203
+ return new Slot(newOffset, slot.tag, slot.full);
3204
+ }
3205
+ case 2 /* ARRAY_LIST */: {
3206
+ const mapped = offsetMap.get(Number(slot.value));
3207
+ if (mapped !== undefined)
3208
+ return new Slot(mapped, slot.tag, slot.full);
3209
+ const newOffset = await remapArrayList(sourceCore, targetCore, hashSize, offsetMap, slot);
3210
+ offsetMap.set(Number(slot.value), newOffset);
3211
+ return new Slot(newOffset, slot.tag, slot.full);
3212
+ }
3213
+ case 3 /* LINKED_ARRAY_LIST */: {
3214
+ const mapped = offsetMap.get(Number(slot.value));
3215
+ if (mapped !== undefined)
3216
+ return new Slot(mapped, slot.tag, slot.full);
3217
+ const newOffset = await remapLinkedArrayList(sourceCore, targetCore, hashSize, offsetMap, slot);
3218
+ offsetMap.set(Number(slot.value), newOffset);
3219
+ return new Slot(newOffset, slot.tag, slot.full);
3220
+ }
3221
+ case 4 /* HASH_MAP */:
3222
+ case 11 /* HASH_SET */: {
3223
+ const mapped = offsetMap.get(Number(slot.value));
3224
+ if (mapped !== undefined)
3225
+ return new Slot(mapped, slot.tag, slot.full);
3226
+ const newOffset = await remapHashMapOrSet(sourceCore, targetCore, hashSize, offsetMap, slot, false);
3227
+ offsetMap.set(Number(slot.value), newOffset);
3228
+ return new Slot(newOffset, slot.tag, slot.full);
3229
+ }
3230
+ case 12 /* COUNTED_HASH_MAP */:
3231
+ case 13 /* COUNTED_HASH_SET */: {
3232
+ const mapped = offsetMap.get(Number(slot.value));
3233
+ if (mapped !== undefined)
3234
+ return new Slot(mapped, slot.tag, slot.full);
3235
+ const newOffset = await remapHashMapOrSet(sourceCore, targetCore, hashSize, offsetMap, slot, true);
3236
+ offsetMap.set(Number(slot.value), newOffset);
3237
+ return new Slot(newOffset, slot.tag, slot.full);
3238
+ }
3239
+ case 5 /* KV_PAIR */: {
3240
+ const mapped = offsetMap.get(Number(slot.value));
3241
+ if (mapped !== undefined)
3242
+ return new Slot(mapped, slot.tag, slot.full);
3243
+ const newOffset = await remapKvPair(sourceCore, targetCore, hashSize, offsetMap, slot);
3244
+ offsetMap.set(Number(slot.value), newOffset);
3245
+ return new Slot(newOffset, slot.tag, slot.full);
3246
+ }
3247
+ default:
3248
+ throw new UnexpectedTagException;
3249
+ }
3250
+ }
3251
+ async function remapBytes(sourceCore, targetCore, slot) {
3252
+ await sourceCore.seek(Number(slot.value));
3253
+ const sourceReader = sourceCore.reader();
3254
+ const length = await sourceReader.readLong();
3255
+ const formatTagSize = slot.full ? 2 : 0;
3256
+ const totalPayload = length + formatTagSize;
3257
+ const newOffset = await targetCore.length();
3258
+ await targetCore.seek(newOffset);
3259
+ const targetWriter = targetCore.writer();
3260
+ await targetWriter.writeLong(length);
3261
+ let remaining = totalPayload;
3262
+ while (remaining > 0) {
3263
+ const chunk = Math.min(remaining, 4096);
3264
+ const buf = new Uint8Array(chunk);
3265
+ await sourceReader.readFully(buf);
3266
+ await targetWriter.write(buf);
3267
+ remaining -= chunk;
3268
+ }
3269
+ return newOffset;
3270
+ }
3271
+ async function remapIndex(sourceCore, targetCore, hashSize, offsetMap, slot) {
3272
+ await sourceCore.seek(Number(slot.value));
3273
+ const sourceReader = sourceCore.reader();
3274
+ const blockBytes = new Uint8Array(INDEX_BLOCK_SIZE);
3275
+ await sourceReader.readFully(blockBytes);
3276
+ const remappedSlots = [];
3277
+ for (let i = 0;i < SLOT_COUNT; i++) {
3278
+ const slotBytes = blockBytes.slice(i * Slot.LENGTH, (i + 1) * Slot.LENGTH);
3279
+ const childSlot = Slot.fromBytes(slotBytes);
3280
+ remappedSlots.push(await remapSlot(sourceCore, targetCore, hashSize, offsetMap, childSlot));
3281
+ }
3282
+ const newOffset = await targetCore.length();
3283
+ await targetCore.seek(newOffset);
3284
+ const targetWriter = targetCore.writer();
3285
+ for (const s of remappedSlots) {
3286
+ await targetWriter.write(s.toBytes());
3287
+ }
3288
+ return newOffset;
3289
+ }
3290
+ async function remapArrayList(sourceCore, targetCore, hashSize, offsetMap, slot) {
3291
+ await sourceCore.seek(Number(slot.value));
3292
+ const sourceReader = sourceCore.reader();
3293
+ const headerBytes = new Uint8Array(ArrayListHeader.LENGTH);
3294
+ await sourceReader.readFully(headerBytes);
3295
+ const header = ArrayListHeader.fromBytes(headerBytes);
3296
+ const indexSlot = new Slot(header.ptr, 1 /* INDEX */);
3297
+ const remappedIndex = await remapSlot(sourceCore, targetCore, hashSize, offsetMap, indexSlot);
3298
+ const newOffset = await targetCore.length();
3299
+ await targetCore.seek(newOffset);
3300
+ const targetWriter = targetCore.writer();
3301
+ await targetWriter.write(new ArrayListHeader(Number(remappedIndex.value), header.size).toBytes());
3302
+ return newOffset;
3303
+ }
3304
+ async function remapLinkedArrayList(sourceCore, targetCore, hashSize, offsetMap, slot) {
3305
+ await sourceCore.seek(Number(slot.value));
3306
+ const sourceReader = sourceCore.reader();
3307
+ const headerBytes = new Uint8Array(LinkedArrayListHeader.LENGTH);
3308
+ await sourceReader.readFully(headerBytes);
3309
+ const header = LinkedArrayListHeader.fromBytes(headerBytes);
3310
+ const remappedPtr = await remapLinkedArrayListBlock(sourceCore, targetCore, hashSize, offsetMap, header.ptr);
3311
+ const newOffset = await targetCore.length();
3312
+ await targetCore.seek(newOffset);
3313
+ const targetWriter = targetCore.writer();
3314
+ await targetWriter.write(new LinkedArrayListHeader(header.shift, remappedPtr, header.size).toBytes());
3315
+ return newOffset;
3316
+ }
3317
+ async function remapLinkedArrayListBlock(sourceCore, targetCore, hashSize, offsetMap, blockOffset) {
3318
+ const mapped = offsetMap.get(blockOffset);
3319
+ if (mapped !== undefined)
3320
+ return mapped;
3321
+ await sourceCore.seek(blockOffset);
3322
+ const sourceReader = sourceCore.reader();
3323
+ const blockBytes = new Uint8Array(LINKED_ARRAY_LIST_INDEX_BLOCK_SIZE);
3324
+ await sourceReader.readFully(blockBytes);
3325
+ const slots = [];
3326
+ for (let i = 0;i < SLOT_COUNT; i++) {
3327
+ const slotBytes = blockBytes.slice(i * LinkedArrayListSlot2.LENGTH, (i + 1) * LinkedArrayListSlot2.LENGTH);
3328
+ slots.push(LinkedArrayListSlot2.fromBytes(slotBytes));
3329
+ }
3330
+ const remappedSlots = [];
3331
+ for (const s of slots) {
3332
+ if (s.slot.tag === 1 /* INDEX */) {
3333
+ const remappedPtr = await remapLinkedArrayListBlock(sourceCore, targetCore, hashSize, offsetMap, Number(s.slot.value));
3334
+ remappedSlots.push(new LinkedArrayListSlot2(s.size, new Slot(remappedPtr, 1 /* INDEX */, s.slot.full)));
3335
+ } else if (s.slot.empty()) {
3336
+ remappedSlots.push(s);
3337
+ } else {
3338
+ const remapped = await remapSlot(sourceCore, targetCore, hashSize, offsetMap, s.slot);
3339
+ remappedSlots.push(new LinkedArrayListSlot2(s.size, remapped));
3340
+ }
3341
+ }
3342
+ const newOffset = await targetCore.length();
3343
+ await targetCore.seek(newOffset);
3344
+ const targetWriter = targetCore.writer();
3345
+ for (const s of remappedSlots) {
3346
+ await targetWriter.write(s.toBytes());
3347
+ }
3348
+ offsetMap.set(blockOffset, newOffset);
3349
+ return newOffset;
3350
+ }
3351
+ async function remapHashMapOrSet(sourceCore, targetCore, hashSize, offsetMap, slot, counted) {
3352
+ await sourceCore.seek(Number(slot.value));
3353
+ const sourceReader = sourceCore.reader();
3354
+ let countValue = -1;
3355
+ if (counted) {
3356
+ countValue = await sourceReader.readLong();
3357
+ }
3358
+ const blockBytes = new Uint8Array(INDEX_BLOCK_SIZE);
3359
+ await sourceReader.readFully(blockBytes);
3360
+ const remappedSlots = [];
3361
+ for (let i = 0;i < SLOT_COUNT; i++) {
3362
+ const slotBytes = blockBytes.slice(i * Slot.LENGTH, (i + 1) * Slot.LENGTH);
3363
+ const childSlot = Slot.fromBytes(slotBytes);
3364
+ remappedSlots.push(await remapSlot(sourceCore, targetCore, hashSize, offsetMap, childSlot));
3365
+ }
3366
+ const newOffset = await targetCore.length();
3367
+ await targetCore.seek(newOffset);
3368
+ const targetWriter = targetCore.writer();
3369
+ if (counted) {
3370
+ await targetWriter.writeLong(countValue);
3371
+ }
3372
+ for (const s of remappedSlots) {
3373
+ await targetWriter.write(s.toBytes());
3374
+ }
3375
+ return newOffset;
3376
+ }
3377
+ async function remapKvPair(sourceCore, targetCore, hashSize, offsetMap, slot) {
3378
+ await sourceCore.seek(Number(slot.value));
3379
+ const sourceReader = sourceCore.reader();
3380
+ const kvPairBytes = new Uint8Array(KeyValuePair.length(hashSize));
3381
+ await sourceReader.readFully(kvPairBytes);
3382
+ const kvPair = KeyValuePair.fromBytes(kvPairBytes, hashSize);
3383
+ const remappedKey = await remapSlot(sourceCore, targetCore, hashSize, offsetMap, kvPair.keySlot);
3384
+ const remappedValue = await remapSlot(sourceCore, targetCore, hashSize, offsetMap, kvPair.valueSlot);
3385
+ const newOffset = await targetCore.length();
3386
+ await targetCore.seek(newOffset);
3387
+ const targetWriter = targetCore.writer();
3388
+ await targetWriter.write(new KeyValuePair(remappedValue, remappedKey, kvPair.hash).toBytes());
3389
+ return newOffset;
3390
+ }
3144
3391
  // src/read-array-list.ts
3145
3392
  class ReadArrayList {
3146
3393
  cursor;
3147
3394
  constructor(cursor) {
3148
- switch (cursor.slotPtr.slot.tag) {
3149
- case 0 /* NONE */:
3150
- case 2 /* ARRAY_LIST */:
3151
- this.cursor = cursor;
3152
- break;
3153
- default:
3154
- throw new UnexpectedTagException;
3395
+ if (cursor) {
3396
+ switch (cursor.slotPtr.slot.tag) {
3397
+ case 0 /* NONE */:
3398
+ case 2 /* ARRAY_LIST */:
3399
+ this.cursor = cursor;
3400
+ break;
3401
+ default:
3402
+ throw new UnexpectedTagException;
3403
+ }
3155
3404
  }
3156
3405
  }
3157
3406
  slot() {
@@ -3175,12 +3424,14 @@ class ReadArrayList {
3175
3424
  }
3176
3425
  // src/write-array-list.ts
3177
3426
  class WriteArrayList extends ReadArrayList {
3178
- constructor(cursor) {
3179
- super(cursor);
3427
+ constructor() {
3428
+ super();
3180
3429
  }
3181
3430
  static async create(cursor) {
3431
+ const list = new WriteArrayList;
3182
3432
  const newCursor = await cursor.writePath([new ArrayListInit]);
3183
- return new WriteArrayList(newCursor);
3433
+ list.cursor = newCursor;
3434
+ return list;
3184
3435
  }
3185
3436
  async iterator() {
3186
3437
  return this.cursor.iterator();
@@ -3220,19 +3471,18 @@ class WriteArrayList extends ReadArrayList {
3220
3471
  // src/read-hash-map.ts
3221
3472
  class ReadHashMap {
3222
3473
  cursor;
3223
- constructor() {}
3224
- static async create(cursor) {
3225
- const map = new ReadHashMap;
3226
- switch (cursor.slotPtr.slot.tag) {
3227
- case 0 /* NONE */:
3228
- case 4 /* HASH_MAP */:
3229
- case 11 /* HASH_SET */:
3230
- map.cursor = cursor;
3231
- break;
3232
- default:
3233
- throw new UnexpectedTagException;
3474
+ constructor(cursor) {
3475
+ if (cursor) {
3476
+ switch (cursor.slotPtr.slot.tag) {
3477
+ case 0 /* NONE */:
3478
+ case 4 /* HASH_MAP */:
3479
+ case 11 /* HASH_SET */:
3480
+ this.cursor = cursor;
3481
+ break;
3482
+ default:
3483
+ throw new UnexpectedTagException;
3484
+ }
3234
3485
  }
3235
- return map;
3236
3486
  }
3237
3487
  slot() {
3238
3488
  return this.cursor.slot();
@@ -3367,19 +3617,18 @@ class WriteHashMap extends ReadHashMap {
3367
3617
  // src/read-hash-set.ts
3368
3618
  class ReadHashSet {
3369
3619
  cursor;
3370
- constructor() {}
3371
- static async create(cursor) {
3372
- const set = new ReadHashSet;
3373
- switch (cursor.slotPtr.slot.tag) {
3374
- case 0 /* NONE */:
3375
- case 4 /* HASH_MAP */:
3376
- case 11 /* HASH_SET */:
3377
- set.cursor = cursor;
3378
- break;
3379
- default:
3380
- throw new UnexpectedTagException;
3620
+ constructor(cursor) {
3621
+ if (cursor) {
3622
+ switch (cursor.slotPtr.slot.tag) {
3623
+ case 0 /* NONE */:
3624
+ case 4 /* HASH_MAP */:
3625
+ case 11 /* HASH_SET */:
3626
+ this.cursor = cursor;
3627
+ break;
3628
+ default:
3629
+ throw new UnexpectedTagException;
3630
+ }
3381
3631
  }
3382
- return set;
3383
3632
  }
3384
3633
  slot() {
3385
3634
  return this.cursor.slot();
@@ -3469,13 +3718,15 @@ class WriteHashSet extends ReadHashSet {
3469
3718
  class ReadLinkedArrayList {
3470
3719
  cursor;
3471
3720
  constructor(cursor) {
3472
- switch (cursor.slotPtr.slot.tag) {
3473
- case 0 /* NONE */:
3474
- case 3 /* LINKED_ARRAY_LIST */:
3475
- this.cursor = cursor;
3476
- break;
3477
- default:
3478
- throw new UnexpectedTagException;
3721
+ if (cursor) {
3722
+ switch (cursor.slotPtr.slot.tag) {
3723
+ case 0 /* NONE */:
3724
+ case 3 /* LINKED_ARRAY_LIST */:
3725
+ this.cursor = cursor;
3726
+ break;
3727
+ default:
3728
+ throw new UnexpectedTagException;
3729
+ }
3479
3730
  }
3480
3731
  }
3481
3732
  slot() {
@@ -3499,12 +3750,14 @@ class ReadLinkedArrayList {
3499
3750
  }
3500
3751
  // src/write-linked-array-list.ts
3501
3752
  class WriteLinkedArrayList extends ReadLinkedArrayList {
3502
- constructor(cursor) {
3503
- super(cursor);
3753
+ constructor() {
3754
+ super();
3504
3755
  }
3505
3756
  static async create(cursor) {
3757
+ const list = new WriteLinkedArrayList;
3506
3758
  const newCursor = await cursor.writePath([new LinkedArrayListInit]);
3507
- return new WriteLinkedArrayList(newCursor);
3759
+ list.cursor = newCursor;
3760
+ return list;
3508
3761
  }
3509
3762
  async iterator() {
3510
3763
  return this.cursor.iterator();
@@ -3553,21 +3806,17 @@ class WriteLinkedArrayList extends ReadLinkedArrayList {
3553
3806
  }
3554
3807
  // src/read-counted-hash-map.ts
3555
3808
  class ReadCountedHashMap extends ReadHashMap {
3556
- constructor() {
3809
+ constructor(cursor) {
3557
3810
  super();
3558
- }
3559
- static async create(cursor) {
3560
- const map = new ReadCountedHashMap;
3561
3811
  switch (cursor.slotPtr.slot.tag) {
3562
3812
  case 0 /* NONE */:
3563
3813
  case 12 /* COUNTED_HASH_MAP */:
3564
3814
  case 13 /* COUNTED_HASH_SET */:
3565
- map.cursor = cursor;
3815
+ this.cursor = cursor;
3566
3816
  break;
3567
3817
  default:
3568
3818
  throw new UnexpectedTagException;
3569
3819
  }
3570
- return map;
3571
3820
  }
3572
3821
  async count() {
3573
3822
  return this.cursor.count();
@@ -3599,21 +3848,17 @@ class WriteCountedHashMap extends WriteHashMap {
3599
3848
  }
3600
3849
  // src/read-counted-hash-set.ts
3601
3850
  class ReadCountedHashSet extends ReadHashSet {
3602
- constructor() {
3851
+ constructor(cursor) {
3603
3852
  super();
3604
- }
3605
- static async create(cursor) {
3606
- const set = new ReadCountedHashSet;
3607
3853
  switch (cursor.slotPtr.slot.tag) {
3608
3854
  case 0 /* NONE */:
3609
3855
  case 12 /* COUNTED_HASH_MAP */:
3610
3856
  case 13 /* COUNTED_HASH_SET */:
3611
- set.cursor = cursor;
3857
+ this.cursor = cursor;
3612
3858
  break;
3613
3859
  default:
3614
3860
  throw new UnexpectedTagException;
3615
3861
  }
3616
- return set;
3617
3862
  }
3618
3863
  async count() {
3619
3864
  return this.cursor.count();
@@ -3,6 +3,7 @@ import type { Slotted } from './slotted';
3
3
  import { ReadCursor, CursorIterator } from './read-cursor';
4
4
  export declare class ReadArrayList implements Slotted {
5
5
  cursor: ReadCursor;
6
+ constructor();
6
7
  constructor(cursor: ReadCursor);
7
8
  slot(): Slot;
8
9
  count(): Promise<number>;
@@ -1,7 +1,6 @@
1
1
  import { ReadHashMap } from './read-hash-map';
2
2
  import { ReadCursor } from './read-cursor';
3
3
  export declare class ReadCountedHashMap extends ReadHashMap {
4
- protected constructor();
5
- static create(cursor: ReadCursor): Promise<ReadCountedHashMap>;
4
+ constructor(cursor: ReadCursor);
6
5
  count(): Promise<number>;
7
6
  }
@@ -1,7 +1,6 @@
1
1
  import { ReadHashSet } from './read-hash-set';
2
2
  import { ReadCursor } from './read-cursor';
3
3
  export declare class ReadCountedHashSet extends ReadHashSet {
4
- protected constructor();
5
- static create(cursor: ReadCursor): Promise<ReadCountedHashSet>;
4
+ constructor(cursor: ReadCursor);
6
5
  count(): Promise<number>;
7
6
  }
@@ -4,8 +4,8 @@ import { ReadCursor, CursorIterator, KeyValuePairCursor } from './read-cursor';
4
4
  import { Bytes } from './writeable-data';
5
5
  export declare class ReadHashMap implements Slotted {
6
6
  cursor: ReadCursor;
7
- protected constructor();
8
- static create(cursor: ReadCursor): Promise<ReadHashMap>;
7
+ constructor();
8
+ constructor(cursor: ReadCursor);
9
9
  slot(): Slot;
10
10
  iterator(): Promise<CursorIterator>;
11
11
  [Symbol.asyncIterator](): AsyncIterator<ReadCursor>;
@@ -4,8 +4,8 @@ import { ReadCursor, CursorIterator } from './read-cursor';
4
4
  import { Bytes } from './writeable-data';
5
5
  export declare class ReadHashSet implements Slotted {
6
6
  cursor: ReadCursor;
7
- protected constructor();
8
- static create(cursor: ReadCursor): Promise<ReadHashSet>;
7
+ constructor();
8
+ constructor(cursor: ReadCursor);
9
9
  slot(): Slot;
10
10
  iterator(): Promise<CursorIterator>;
11
11
  [Symbol.asyncIterator](): AsyncIterator<ReadCursor>;
@@ -3,6 +3,7 @@ import type { Slotted } from './slotted';
3
3
  import { ReadCursor, CursorIterator } from './read-cursor';
4
4
  export declare class ReadLinkedArrayList implements Slotted {
5
5
  cursor: ReadCursor;
6
+ constructor();
6
7
  constructor(cursor: ReadCursor);
7
8
  slot(): Slot;
8
9
  count(): Promise<number>;
@@ -3,7 +3,7 @@ import { WriteCursor, WriteCursorIterator } from './write-cursor';
3
3
  import { type ContextFunction } from './database';
4
4
  import type { WriteableData } from './writeable-data';
5
5
  export declare class WriteArrayList extends ReadArrayList {
6
- constructor(cursor: WriteCursor);
6
+ protected constructor();
7
7
  static create(cursor: WriteCursor): Promise<WriteArrayList>;
8
8
  iterator(): Promise<WriteCursorIterator>;
9
9
  [Symbol.asyncIterator](): AsyncIterator<WriteCursor>;
@@ -3,7 +3,7 @@ import { ReadLinkedArrayList } from './read-linked-array-list';
3
3
  import { WriteCursor, WriteCursorIterator } from './write-cursor';
4
4
  import type { WriteableData } from './writeable-data';
5
5
  export declare class WriteLinkedArrayList extends ReadLinkedArrayList {
6
- constructor(cursor: WriteCursor);
6
+ protected constructor();
7
7
  static create(cursor: WriteCursor): Promise<WriteLinkedArrayList>;
8
8
  iterator(): Promise<WriteCursorIterator>;
9
9
  [Symbol.asyncIterator](): AsyncIterator<WriteCursor>;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "xitdb",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "An immutable database",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/radarroark/xitdb-ts.git"
8
+ "url": "https://github.com/xit-vcs/xitdb-ts.git"
9
9
  },
10
10
  "type": "module",
11
11
  "main": "dist/index.js",