@peerbit/document 8.2.0 → 9.0.0-63e24d5

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.
@@ -8,9 +8,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { field, serialize, variant } from "@dao-xyz/borsh";
11
- import { BlockResponse } from "@peerbit/blocks";
12
11
  import { Cache } from "@peerbit/cache";
13
- import { PublicSignKey, sha256Base64Sync, } from "@peerbit/crypto";
12
+ import { PublicSignKey, getPublicKeyFromPeerId, sha256Base64Sync, } from "@peerbit/crypto";
14
13
  import * as types from "@peerbit/document-interface";
15
14
  import * as indexerTypes from "@peerbit/indexer-interface";
16
15
  import { HashmapIndex } from "@peerbit/indexer-simple";
@@ -18,23 +17,48 @@ import { BORSH_ENCODING, Entry } from "@peerbit/log";
18
17
  import { logger as loggerFn } from "@peerbit/logger";
19
18
  import { ClosedError, Program } from "@peerbit/program";
20
19
  import { MissingResponsesError, RPC, queryAll, } from "@peerbit/rpc";
21
- import { BlocksMessage, SharedLog, } from "@peerbit/shared-log";
20
+ import { SharedLog } from "@peerbit/shared-log";
22
21
  import { SilentDelivery } from "@peerbit/stream-interface";
23
- import { AbortError } from "@peerbit/time";
22
+ import { AbortError, waitFor } from "@peerbit/time";
24
23
  import { concat, fromString } from "uint8arrays";
25
24
  import { copySerialization } from "./borsh.js";
26
25
  import { MAX_BATCH_SIZE } from "./constants.js";
27
26
  import { isPutOperation } from "./operation.js";
28
27
  import { ResumableIterators } from "./resumable-iterator.js";
29
28
  const logger = loggerFn({ module: "document-index" });
30
- const introduceEntries = async (queryRequest, responses, type, sync, options) => {
29
+ const coerceQuery = (query, options) => {
30
+ let replicate = typeof options?.remote !== "boolean" ? options?.remote?.replicate : false;
31
+ if (query instanceof types.SearchRequestIndexed &&
32
+ query.replicate === false &&
33
+ replicate) {
34
+ query.replicate = true;
35
+ return query;
36
+ }
37
+ if (query instanceof types.SearchRequest) {
38
+ return query;
39
+ }
40
+ const queryObject = query;
41
+ return options?.resolve || options?.resolve == null
42
+ ? new types.SearchRequest({
43
+ query: indexerTypes.toQuery(queryObject.query),
44
+ sort: indexerTypes.toSort(query.sort),
45
+ })
46
+ : new types.SearchRequestIndexed({
47
+ query: indexerTypes.toQuery(queryObject.query),
48
+ sort: indexerTypes.toSort(query.sort),
49
+ replicate,
50
+ });
51
+ };
52
+ const introduceEntries = async (queryRequest, responses, documentType, indexedType, sync, options) => {
31
53
  const results = [];
32
54
  for (const response of responses) {
33
55
  if (!response.from) {
34
56
  logger.error("Missing from for response");
35
57
  }
36
58
  if (response.response instanceof types.Results) {
37
- response.response.results.forEach((r) => r.init(type));
59
+ response.response.results.forEach((r) => r instanceof types.ResultValue
60
+ ? r.init(documentType)
61
+ : r.init(indexedType));
38
62
  if (typeof options?.remote !== "boolean" && options?.remote?.replicate) {
39
63
  await sync(queryRequest, response.response);
40
64
  }
@@ -124,6 +148,7 @@ let DocumentIndex = class DocumentIndex extends Program {
124
148
  transformer;
125
149
  // The indexed document wrapped in a context
126
150
  wrappedIndexedType;
151
+ indexedType;
127
152
  // The database type, for recursive indexing
128
153
  dbType;
129
154
  indexedTypeIsDocumentType;
@@ -132,7 +157,7 @@ let DocumentIndex = class DocumentIndex extends Program {
132
157
  indexByResolver;
133
158
  index;
134
159
  _resumableIterators;
135
- emitBlocksEagerly;
160
+ compatibility;
136
161
  // Transformation, indexer
137
162
  /* fields: IndexableFields<T, I>; */
138
163
  _valueEncoding;
@@ -155,7 +180,7 @@ let DocumentIndex = class DocumentIndex extends Program {
155
180
  this.indexedTypeIsDocumentType =
156
181
  !properties.transform?.type ||
157
182
  properties.transform?.type === properties.documentType;
158
- this.emitBlocksEagerly = properties.emitBlocksEagerly || false;
183
+ this.compatibility = properties.compatibility;
159
184
  let IndexedClassWithContext = class IndexedClassWithContext {
160
185
  __context;
161
186
  constructor(value, context) {
@@ -172,13 +197,62 @@ let DocumentIndex = class DocumentIndex extends Program {
172
197
  __metadata("design:paramtypes", [Object, IndexableContext])
173
198
  ], IndexedClassWithContext);
174
199
  // copy all prototype values from indexedType to IndexedClassWithContext
175
- copySerialization((properties.transform?.type || properties.documentType), IndexedClassWithContext);
200
+ this.indexedType = (properties.transform?.type || properties.documentType);
201
+ copySerialization(this.indexedType, IndexedClassWithContext);
176
202
  this.wrappedIndexedType = IndexedClassWithContext;
177
203
  // if this.type is a class that extends Program we want to do special functionality
178
204
  this._isProgramValues = this.documentType instanceof Program;
179
205
  this.dbType = properties.dbType;
180
206
  this._resultQueue = new Map();
181
- this._sync = properties.sync;
207
+ this._sync = async (request, results) => {
208
+ /*
209
+ let allPromises: Promise<void> | undefined = undefined
210
+ if (waitForValue) {
211
+ let promises: Map<string, DeferredPromise<T>> = new Map();
212
+
213
+ for (const result of results) {
214
+ for (let i = 0; i < result.results.length; i++) {
215
+ let promise = defer<T>();
216
+ let r = result.results[i];
217
+ promises.set(r.context.head, promise);
218
+ const head = result.results[0].context.head;
219
+ let listeners = this.hashToValueListener.get(head);
220
+ if (!listeners) {
221
+ listeners = [];
222
+ this.hashToValueListener.set(head, listeners);
223
+ }
224
+ listeners.push(async (value) => {
225
+ promise.resolve(value);
226
+ result.results[i] = new types.ResultValue<T>({
227
+ context: r.context,
228
+ value,
229
+ source: serialize(value),
230
+ indexed: r.indexed,
231
+ }) as any;
232
+ });
233
+ promise.promise.finally(() => {
234
+ this.hashToValueListener.delete(head);
235
+ });
236
+ }
237
+ }
238
+
239
+ let timeout = setTimeout(() => {
240
+ for (const promise of promises!) {
241
+ promise[1].reject("Timed out resolving search result from value");
242
+ }
243
+ }, 1e4);
244
+
245
+ allPromises = Promise.all([...promises.values()].map((x) => x.promise)).then(
246
+ () => {
247
+ clearTimeout(timeout);
248
+ },
249
+ );
250
+ } */
251
+ await properties.replicate(request, results);
252
+ /* if (allPromises) {
253
+ await allPromises;
254
+ } */
255
+ };
182
256
  const transformOptions = properties.transform;
183
257
  this.transformer = transformOptions
184
258
  ? isTransformerWithFunction(transformOptions)
@@ -226,22 +300,6 @@ let DocumentIndex = class DocumentIndex extends Program {
226
300
  const results = await this.processQuery(query, ctx.from, false, {
227
301
  canRead: properties.canRead,
228
302
  });
229
- if (this.emitBlocksEagerly) {
230
- await Promise.all(results.results.map(async (x) => {
231
- const hash = x.context.head;
232
- const block = await this._log.log.blocks.get(hash);
233
- if (!block) {
234
- return;
235
- }
236
- // todo dont do bytes -> entry -> bytes, but send the block directly
237
- return this._log.rpc.send(new BlocksMessage(new BlockResponse(hash, block)), {
238
- mode: new SilentDelivery({
239
- to: [ctx.from],
240
- redundancy: 1,
241
- }),
242
- });
243
- }));
244
- }
245
303
  return new types.Results({
246
304
  // Even if results might have length 0, respond, because then we now at least there are no matching results
247
305
  results: results.results,
@@ -320,8 +378,12 @@ let DocumentIndex = class DocumentIndex extends Program {
320
378
  }
321
379
  async getDetailed(key, options) {
322
380
  let results;
381
+ const resolve = options?.resolve || options?.resolve == null;
382
+ let requestClazz = resolve
383
+ ? types.SearchRequest
384
+ : types.SearchRequestIndexed;
323
385
  if (key instanceof Uint8Array) {
324
- results = await this.queryDetailed(new types.SearchRequest({
386
+ results = await this.queryCommence(new requestClazz({
325
387
  query: [
326
388
  new indexerTypes.ByteMatchQuery({ key: this.indexBy, value: key }),
327
389
  ],
@@ -331,7 +393,7 @@ let DocumentIndex = class DocumentIndex extends Program {
331
393
  const indexableKey = indexerTypes.toIdeable(key);
332
394
  if (typeof indexableKey === "number" ||
333
395
  typeof indexableKey === "bigint") {
334
- results = await this.queryDetailed(new types.SearchRequest({
396
+ results = await this.queryCommence(new requestClazz({
335
397
  query: [
336
398
  new indexerTypes.IntegerCompare({
337
399
  key: this.indexBy,
@@ -342,7 +404,7 @@ let DocumentIndex = class DocumentIndex extends Program {
342
404
  }), options);
343
405
  }
344
406
  else if (typeof indexableKey === "string") {
345
- results = await this.queryDetailed(new types.SearchRequest({
407
+ results = await this.queryCommence(new requestClazz({
346
408
  query: [
347
409
  new indexerTypes.StringMatch({
348
410
  key: this.indexBy,
@@ -352,7 +414,7 @@ let DocumentIndex = class DocumentIndex extends Program {
352
414
  }), options);
353
415
  }
354
416
  else if (indexableKey instanceof Uint8Array) {
355
- results = await this.queryDetailed(new types.SearchRequest({
417
+ results = await this.queryCommence(new requestClazz({
356
418
  query: [
357
419
  new indexerTypes.ByteMatchQuery({
358
420
  key: this.indexBy,
@@ -362,24 +424,48 @@ let DocumentIndex = class DocumentIndex extends Program {
362
424
  }), options);
363
425
  }
364
426
  }
427
+ if (resolve &&
428
+ requestClazz === types.SearchRequestIndexed &&
429
+ !this.indexedTypeIsDocumentType &&
430
+ results) {
431
+ for (const set of results) {
432
+ let coercedResult = [];
433
+ for (const value of set.results) {
434
+ const resolved = value instanceof types.ResultIndexedValue
435
+ ? (await this.resolveDocument({
436
+ indexed: value.value,
437
+ head: value.context.head,
438
+ }))?.value
439
+ : value.value;
440
+ if (resolved) {
441
+ coercedResult.push(new types.ResultValue({
442
+ context: value.context,
443
+ value: resolved,
444
+ }));
445
+ }
446
+ }
447
+ set.results = coercedResult;
448
+ }
449
+ }
365
450
  return results;
366
451
  }
367
452
  getSize() {
368
453
  return this.index.getSize();
369
454
  }
370
455
  async resolveDocument(value) {
371
- const cached = this._resolverCache.get(value.id.primitive) ||
372
- this._resolverProgramCache?.get(value.id.primitive);
456
+ const id = value.id ??
457
+ indexerTypes.toId(this.indexByResolver(value.indexed)).primitive;
458
+ const cached = this._resolverCache.get(id) || this._resolverProgramCache?.get(id);
373
459
  if (cached != null) {
374
460
  return { value: cached };
375
461
  }
376
462
  if (this.indexedTypeIsDocumentType) {
377
463
  // cast value to T, i.e. convert the class but keep all properties except the __context
378
- const obj = Object.assign(Object.create(this.documentType.prototype), value.value);
464
+ const obj = Object.assign(Object.create(this.documentType.prototype), value.indexed);
379
465
  delete obj.__context;
380
466
  return { value: obj };
381
467
  }
382
- const head = await this._log.log.get(value.value.__context.head);
468
+ const head = await this._log.log.get(value.head);
383
469
  if (!head) {
384
470
  return undefined; // we could end up here if we recently pruned the document and other peers never persisted the entry
385
471
  // TODO update changes in index before removing entries from log entry storage
@@ -403,10 +489,14 @@ let DocumentIndex = class DocumentIndex extends Program {
403
489
  throw new Error("Different from in queued results");
404
490
  }
405
491
  let indexedResult = undefined;
406
- if (query instanceof types.SearchRequest) {
492
+ let fromQuery;
493
+ if (query instanceof types.SearchRequest ||
494
+ query instanceof types.SearchRequestIndexed) {
495
+ fromQuery = query;
407
496
  indexedResult = await this._resumableIterators.iterateAndFetch(query);
408
497
  }
409
498
  else if (query instanceof types.CollectNextRequest) {
499
+ fromQuery = this._resumableIterators.queues.get(query.idString)?.request;
410
500
  indexedResult =
411
501
  prevQueued?.keptInIndex === 0
412
502
  ? []
@@ -415,7 +505,6 @@ let DocumentIndex = class DocumentIndex extends Program {
415
505
  else {
416
506
  throw new Error("Unsupported");
417
507
  }
418
- const filteredResults = [];
419
508
  let resultSize = 0;
420
509
  let toIterate = prevQueued
421
510
  ? [...prevQueued.queue, ...indexedResult]
@@ -437,6 +526,7 @@ let DocumentIndex = class DocumentIndex extends Program {
437
526
  };
438
527
  this._resultQueue.set(query.idString, prevQueued);
439
528
  }
529
+ const filteredResults = [];
440
530
  for (const result of toIterate) {
441
531
  if (!isLocal) {
442
532
  resultSize += result.value.__context.size;
@@ -445,17 +535,40 @@ let DocumentIndex = class DocumentIndex extends Program {
445
535
  continue;
446
536
  }
447
537
  }
448
- const value = await this.resolveDocument(result);
449
- if (!value ||
450
- (options?.canRead && !(await options.canRead(value.value, from)))) {
538
+ const indexedUnwrapped = Object.assign(Object.create(this.indexedType.prototype), result.value);
539
+ if (options?.canRead &&
540
+ !(await options.canRead(indexedUnwrapped, from))) {
451
541
  continue;
452
542
  }
453
- filteredResults.push(new types.ResultWithSource({
454
- context: result.value.__context.toContext(),
455
- value: value.value,
456
- source: serialize(value.value),
457
- indexed: result.value,
458
- }));
543
+ if (fromQuery instanceof types.SearchRequest) {
544
+ const value = await this.resolveDocument({
545
+ indexed: result.value,
546
+ head: result.value.__context.head,
547
+ });
548
+ if (!value) {
549
+ continue;
550
+ }
551
+ filteredResults.push(new types.ResultValue({
552
+ context: result.value.__context.toContext(),
553
+ value: value.value,
554
+ source: serialize(value.value),
555
+ indexed: indexedUnwrapped,
556
+ }));
557
+ }
558
+ else if (fromQuery instanceof types.SearchRequestIndexed) {
559
+ const context = result.value.__context.toContext();
560
+ const head = await this._log.log.get(context.head);
561
+ // assume remote peer will start to replicate (TODO is this ideal?)
562
+ if (fromQuery.replicate) {
563
+ this._log.addPeersToGidPeerHistory(context.gid, [from.hashcode()]);
564
+ }
565
+ filteredResults.push(new types.ResultIndexedValue({
566
+ context,
567
+ source: serialize(indexedUnwrapped),
568
+ indexed: indexedUnwrapped,
569
+ entries: head ? [head] : [],
570
+ }));
571
+ }
459
572
  }
460
573
  const results = new types.Results({
461
574
  results: filteredResults,
@@ -495,7 +608,7 @@ let DocumentIndex = class DocumentIndex extends Program {
495
608
  * @param options
496
609
  * @returns
497
610
  */
498
- async queryDetailed(queryRequest, options) {
611
+ async queryCommence(queryRequest, options) {
499
612
  const local = typeof options?.local === "boolean" ? options?.local : true;
500
613
  let remote = undefined;
501
614
  if (typeof options?.remote === "boolean") {
@@ -536,7 +649,8 @@ let DocumentIndex = class DocumentIndex extends Program {
536
649
  if (replicatorGroups) {
537
650
  const groupHashes = replicatorGroups.map((x) => [x]);
538
651
  const responseHandler = async (results) => {
539
- for (const r of await introduceEntries(queryRequest, results, this.documentType, this._sync, options)) {
652
+ const resultInitialized = await introduceEntries(queryRequest, results, this.documentType, this.indexedType, this._sync, options);
653
+ for (const r of resultInitialized) {
540
654
  resolved.push(r.response);
541
655
  }
542
656
  };
@@ -583,7 +697,7 @@ let DocumentIndex = class DocumentIndex extends Program {
583
697
  }
584
698
  }
585
699
  }
586
- return allResults;
700
+ return allResults; // TODO types
587
701
  }
588
702
  /**
589
703
  * Query and retrieve results
@@ -593,19 +707,21 @@ let DocumentIndex = class DocumentIndex extends Program {
593
707
  */
594
708
  async search(queryRequest, options) {
595
709
  // Set fetch to search size, or max value (default to max u32 (4294967295))
596
- queryRequest.fetch = queryRequest.fetch ?? 0xffffffff;
710
+ const coercedRequest = coerceQuery(queryRequest, options);
711
+ coercedRequest.fetch = coercedRequest.fetch ?? 0xffffffff;
597
712
  // So that the iterator is pre-fetching the right amount of entries
598
- const iterator = this.iterate(queryRequest, options);
713
+ const iterator = this.iterate(coercedRequest, options);
599
714
  // So that this call will not do any remote requests
600
715
  const allResults = [];
601
- while (iterator.done() !== true && queryRequest.fetch > allResults.length) {
716
+ while (iterator.done() !== true &&
717
+ coercedRequest.fetch > allResults.length) {
602
718
  // We might need to pull .next multiple time due to data message size limitations
603
- for (const result of await iterator.next(queryRequest.fetch - allResults.length)) {
719
+ for (const result of await iterator.next(coercedRequest.fetch - allResults.length)) {
604
720
  allResults.push(result);
605
721
  }
606
722
  }
607
723
  await iterator.close();
608
- //s Deduplicate and return values directly
724
+ // Deduplicate and return values directly
609
725
  return dedup(allResults, this.indexByResolver);
610
726
  }
611
727
  /**
@@ -615,6 +731,30 @@ let DocumentIndex = class DocumentIndex extends Program {
615
731
  * @returns
616
732
  */
617
733
  iterate(queryRequest, options) {
734
+ let queryRequestCoerced = coerceQuery(queryRequest, options);
735
+ let resolve = false;
736
+ if (options?.remote &&
737
+ typeof options.remote !== "boolean" &&
738
+ options.remote.replicate &&
739
+ options?.resolve !== false) {
740
+ if ((queryRequest instanceof types.SearchRequestIndexed === false &&
741
+ this.compatibility == null) ||
742
+ (this.compatibility != null && this.compatibility > 8)) {
743
+ queryRequestCoerced = new types.SearchRequestIndexed({
744
+ query: queryRequestCoerced.query,
745
+ fetch: queryRequestCoerced.fetch,
746
+ sort: queryRequestCoerced.sort,
747
+ });
748
+ resolve = true;
749
+ }
750
+ }
751
+ let replicate = options?.remote &&
752
+ typeof options.remote !== "boolean" &&
753
+ options.remote.replicate;
754
+ if (replicate &&
755
+ queryRequestCoerced instanceof types.SearchRequestIndexed) {
756
+ queryRequestCoerced.replicate = true;
757
+ }
618
758
  let fetchPromise = undefined;
619
759
  const peerBufferMap = new Map();
620
760
  const visited = new Set();
@@ -627,8 +767,8 @@ let DocumentIndex = class DocumentIndex extends Program {
627
767
  };
628
768
  const fetchFirst = async (n) => {
629
769
  done = true; // Assume we are donne
630
- queryRequest.fetch = n;
631
- await this.queryDetailed(queryRequest, {
770
+ queryRequestCoerced.fetch = n;
771
+ await this.queryCommence(queryRequestCoerced, {
632
772
  ...options,
633
773
  onResponse: async (response, from) => {
634
774
  if (!from) {
@@ -649,18 +789,33 @@ let DocumentIndex = class DocumentIndex extends Program {
649
789
  }
650
790
  const buffer = [];
651
791
  for (const result of results.results) {
652
- const indexKey = indexerTypes.toId(this.indexByResolver(result.value)).primitive;
653
- if (visited.has(indexKey)) {
654
- continue;
792
+ if (result instanceof types.ResultValue) {
793
+ const indexKey = indexerTypes.toId(this.indexByResolver(result.value)).primitive;
794
+ if (visited.has(indexKey)) {
795
+ continue;
796
+ }
797
+ visited.add(indexKey);
798
+ buffer.push({
799
+ value: result.value,
800
+ context: result.context,
801
+ from,
802
+ indexed: result.indexed ||
803
+ (await this.transformer(result.value, result.context)),
804
+ });
805
+ }
806
+ else {
807
+ const indexKey = indexerTypes.toId(this.indexByResolver(result.value)).primitive;
808
+ if (visited.has(indexKey)) {
809
+ continue;
810
+ }
811
+ visited.add(indexKey);
812
+ buffer.push({
813
+ value: result.value,
814
+ context: result.context,
815
+ from,
816
+ indexed: result.indexed || result.value,
817
+ });
655
818
  }
656
- visited.add(indexKey);
657
- buffer.push({
658
- value: result.value,
659
- context: result.context,
660
- from,
661
- indexed: result.indexed ||
662
- (await this.transformer(result.value, result.context)),
663
- });
664
819
  }
665
820
  peerBufferMap.set(from.hashcode(), {
666
821
  buffer,
@@ -673,7 +828,7 @@ let DocumentIndex = class DocumentIndex extends Program {
673
828
  },
674
829
  });
675
830
  if (done) {
676
- this.clearResultsQueue(queryRequest);
831
+ this.clearResultsQueue(queryRequestCoerced);
677
832
  }
678
833
  return done;
679
834
  };
@@ -703,7 +858,7 @@ let DocumentIndex = class DocumentIndex extends Program {
703
858
  // TODO buffer more than deleted?
704
859
  // TODO batch to multiple 'to's
705
860
  const collectRequest = new types.CollectNextRequest({
706
- id: queryRequest.id,
861
+ id: queryRequestCoerced.id,
707
862
  amount: n - buffer.buffer.length,
708
863
  });
709
864
  // Fetch locally?
@@ -753,11 +908,12 @@ let DocumentIndex = class DocumentIndex extends Program {
753
908
  priority: 1,
754
909
  mode: new SilentDelivery({ to: [peer], redundancy: 1 }),
755
910
  })
756
- .then((response) => introduceEntries(queryRequest, response, this.documentType, this._sync, options)
757
- .then((responses) => {
758
- responses.map((response) => {
911
+ .then((response) => introduceEntries(queryRequestCoerced, response, this.documentType, this.indexedType, this._sync, options)
912
+ .then(async (responses) => {
913
+ return Promise.all(responses.map(async (response, i) => {
759
914
  resultsLeft += Number(response.response.kept);
760
- if (!response.from) {
915
+ const from = responses[i].from;
916
+ if (!from) {
761
917
  logger.error("Missing from for sorted query");
762
918
  return;
763
919
  }
@@ -773,19 +929,22 @@ let DocumentIndex = class DocumentIndex extends Program {
773
929
  }
774
930
  peerBuffer.kept = Number(response.response.kept);
775
931
  for (const result of response.response.results) {
776
- if (visited.has(indexerTypes.toId(this.indexByResolver(result.value)).primitive)) {
932
+ const idPrimitive = indexerTypes.toId(this.indexByResolver(result.value)).primitive;
933
+ if (visited.has(idPrimitive)) {
777
934
  continue;
778
935
  }
779
- visited.add(indexerTypes.toId(this.indexByResolver(result.value)).primitive);
936
+ visited.add(idPrimitive);
780
937
  peerBuffer.buffer.push({
781
938
  value: result.value,
782
939
  context: result.context,
783
- from: response.from,
784
- indexed: this.transformer(result.value, result.context),
940
+ from: from,
941
+ indexed: result instanceof types.ResultIndexedValue
942
+ ? result.value
943
+ : await this.transformer(result.value, result.context),
785
944
  });
786
945
  }
787
946
  }
788
- });
947
+ }));
789
948
  })
790
949
  .catch((e) => {
791
950
  logger.error("Failed to collect sorted results from: " +
@@ -815,7 +974,7 @@ let DocumentIndex = class DocumentIndex extends Program {
815
974
  const fetchedAll = await fetchAtLeast(n);
816
975
  // get n next top entries, shift and pull more results
817
976
  const peerBuffersArr = peerBuffers();
818
- const results = peerBuffersArr.sort((a, b) => indexerTypes.extractSortCompare(a.indexed, b.indexed, queryRequest.sort));
977
+ const results = peerBuffersArr.sort((a, b) => indexerTypes.extractSortCompare(a.indexed, b.indexed, queryRequestCoerced.sort));
819
978
  const pendingMoreResults = n < results.length;
820
979
  const batch = results.splice(0, n);
821
980
  for (const result of batch) {
@@ -830,12 +989,24 @@ let DocumentIndex = class DocumentIndex extends Program {
830
989
  }
831
990
  }
832
991
  done = fetchedAll && !pendingMoreResults;
833
- return dedup(batch.map((x) => x.value), this.indexByResolver);
992
+ let coercedBatch;
993
+ if (resolve) {
994
+ coercedBatch = (await Promise.all(batch.map(async (x) => x.value instanceof this.documentType
995
+ ? x.value
996
+ : (await this.resolveDocument({
997
+ head: x.context.head,
998
+ indexed: x.indexed,
999
+ }))?.value))).filter((x) => !!x);
1000
+ }
1001
+ else {
1002
+ coercedBatch = batch.map((x) => x.value);
1003
+ }
1004
+ return dedup(coercedBatch, this.indexByResolver);
834
1005
  };
835
1006
  const close = async () => {
836
1007
  controller.abort(new AbortError("Iterator closed"));
837
1008
  const closeRequest = new types.CloseIteratorRequest({
838
- id: queryRequest.id,
1009
+ id: queryRequestCoerced.id,
839
1010
  });
840
1011
  const promises = [];
841
1012
  for (const [peer, buffer] of peerBufferMap) {
@@ -872,6 +1043,19 @@ let DocumentIndex = class DocumentIndex extends Program {
872
1043
  },
873
1044
  };
874
1045
  }
1046
+ async waitFor(other, options) {
1047
+ await super.waitFor(other, options);
1048
+ const ids = Array.isArray(other) ? other : [other];
1049
+ const expectedHashes = new Set(ids.map((x) => typeof x === "string"
1050
+ ? x
1051
+ : x instanceof PublicSignKey
1052
+ ? x.hashcode()
1053
+ : getPublicKeyFromPeerId(x).hashcode()));
1054
+ for (const key of expectedHashes) {
1055
+ await waitFor(async () => (await this._log.replicationIndex.count({ query: { hash: key } })) >
1056
+ 0, options);
1057
+ }
1058
+ }
875
1059
  };
876
1060
  __decorate([
877
1061
  field({ type: RPC }),