@peerbit/document 7.0.13 → 7.0.14-ccaf4f4
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/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/operation.d.ts +38 -0
- package/dist/src/operation.d.ts.map +1 -0
- package/dist/src/operation.js +125 -0
- package/dist/src/operation.js.map +1 -0
- package/dist/src/program.d.ts +12 -10
- package/dist/src/program.d.ts.map +1 -1
- package/dist/src/program.js +40 -33
- package/dist/src/program.js.map +1 -1
- package/dist/src/search.d.ts +19 -52
- package/dist/src/search.d.ts.map +1 -1
- package/dist/src/search.js +25 -142
- package/dist/src/search.js.map +1 -1
- package/package.json +74 -74
- package/src/index.ts +1 -4
- package/src/operation.ts +106 -0
- package/src/program.ts +79 -49
- package/src/search.ts +65 -168
package/src/search.ts
CHANGED
|
@@ -18,12 +18,14 @@ import {
|
|
|
18
18
|
type RPCResponse,
|
|
19
19
|
queryAll,
|
|
20
20
|
} from "@peerbit/rpc";
|
|
21
|
-
import { SharedLog } from "@peerbit/shared-log";
|
|
21
|
+
import { type ReplicationDomain, SharedLog } from "@peerbit/shared-log";
|
|
22
22
|
import { SilentDelivery } from "@peerbit/stream-interface";
|
|
23
23
|
import { AbortError } from "@peerbit/time";
|
|
24
24
|
import { concat, fromString } from "uint8arrays";
|
|
25
25
|
import { copySerialization } from "./borsh.js";
|
|
26
26
|
import { MAX_BATCH_SIZE } from "./constants.js";
|
|
27
|
+
import { type Operation, isPutOperation } from "./operation.js";
|
|
28
|
+
import type { ExtractArgs } from "./program.js";
|
|
27
29
|
|
|
28
30
|
const logger = loggerFn({ module: "document-index" });
|
|
29
31
|
|
|
@@ -34,119 +36,17 @@ type BufferedResult<T> = {
|
|
|
34
36
|
from: PublicSignKey;
|
|
35
37
|
};
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
export const BORSH_ENCODING_OPERATION = BORSH_ENCODING(Operation);
|
|
41
|
-
|
|
42
|
-
// @deprecated
|
|
43
|
-
@variant(0)
|
|
44
|
-
export class PutWithKeyOperation extends Operation {
|
|
45
|
-
@field({ type: "string" })
|
|
46
|
-
key: string;
|
|
47
|
-
|
|
48
|
-
@field({ type: Uint8Array })
|
|
49
|
-
data: Uint8Array;
|
|
50
|
-
|
|
51
|
-
constructor(props: { key: string; data: Uint8Array }) {
|
|
52
|
-
super();
|
|
53
|
-
this.key = props.key;
|
|
54
|
-
this.data = props.data;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// @deprecated
|
|
59
|
-
/* @variant(1)
|
|
60
|
-
export class PutAllOperation<T> extends Operation<T> {
|
|
61
|
-
@field({ type: vec(PutOperation) })
|
|
62
|
-
docs: PutOperation<T>[];
|
|
63
|
-
|
|
64
|
-
constructor(props?: { docs: PutOperation<T>[] }) {
|
|
65
|
-
super();
|
|
66
|
-
if (props) {
|
|
67
|
-
this.docs = props.docs;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
*/
|
|
72
|
-
|
|
73
|
-
// @deprecated
|
|
74
|
-
@variant(2)
|
|
75
|
-
export class DeleteByStringKeyOperation extends Operation {
|
|
76
|
-
@field({ type: "string" })
|
|
77
|
-
key: string;
|
|
78
|
-
|
|
79
|
-
constructor(props: { key: string }) {
|
|
80
|
-
super();
|
|
81
|
-
this.key = props.key;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
toDeleteOperation(): DeleteOperation {
|
|
85
|
-
return new DeleteOperation({ key: indexerTypes.toId(this.key) });
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export const coerceDeleteOperation = (
|
|
90
|
-
operation: DeleteOperation | DeleteByStringKeyOperation,
|
|
91
|
-
): DeleteOperation => {
|
|
92
|
-
return operation instanceof DeleteByStringKeyOperation
|
|
93
|
-
? operation.toDeleteOperation()
|
|
94
|
-
: operation;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
@variant(3)
|
|
98
|
-
export class PutOperation extends Operation {
|
|
99
|
-
@field({ type: Uint8Array })
|
|
100
|
-
data: Uint8Array;
|
|
101
|
-
|
|
102
|
-
constructor(props: { data: Uint8Array }) {
|
|
103
|
-
super();
|
|
104
|
-
this.data = props.data;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export const isPutOperation = (
|
|
109
|
-
operation: Operation,
|
|
110
|
-
): operation is PutOperation | PutWithKeyOperation => {
|
|
111
|
-
return (
|
|
112
|
-
operation instanceof PutOperation ||
|
|
113
|
-
operation instanceof PutWithKeyOperation
|
|
114
|
-
);
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Delete a document at a key
|
|
119
|
-
*/
|
|
120
|
-
@variant(4)
|
|
121
|
-
export class DeleteOperation extends Operation {
|
|
122
|
-
@field({ type: indexerTypes.IdKey })
|
|
123
|
-
key: indexerTypes.IdKey;
|
|
124
|
-
|
|
125
|
-
constructor(props: { key: indexerTypes.IdKey }) {
|
|
126
|
-
super();
|
|
127
|
-
this.key = props.key;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export const isDeleteOperation = (
|
|
132
|
-
operation: Operation,
|
|
133
|
-
): operation is DeleteOperation | DeleteByStringKeyOperation => {
|
|
134
|
-
return (
|
|
135
|
-
operation instanceof DeleteOperation ||
|
|
136
|
-
operation instanceof DeleteByStringKeyOperation
|
|
137
|
-
);
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
export type RemoteQueryOptions<R> = RPCRequestAllOptions<R> & {
|
|
141
|
-
sync?: boolean;
|
|
39
|
+
export type RemoteQueryOptions<R, D> = RPCRequestAllOptions<R> & {
|
|
40
|
+
replicate?: boolean;
|
|
142
41
|
minAge?: number;
|
|
143
42
|
throwOnMissing?: boolean;
|
|
43
|
+
domain?: ExtractArgs<D>;
|
|
144
44
|
};
|
|
145
|
-
export type QueryOptions<R> = {
|
|
146
|
-
remote?: boolean | RemoteQueryOptions<types.AbstractSearchResult<R
|
|
45
|
+
export type QueryOptions<R, D> = {
|
|
46
|
+
remote?: boolean | RemoteQueryOptions<types.AbstractSearchResult<R>, D>;
|
|
147
47
|
local?: boolean;
|
|
148
48
|
};
|
|
149
|
-
export type SearchOptions<R> = QueryOptions<R>;
|
|
49
|
+
export type SearchOptions<R, D> = QueryOptions<R, D>;
|
|
150
50
|
|
|
151
51
|
type Transformer<T, I> = (obj: T, context: types.Context) => MaybePromise<I>;
|
|
152
52
|
|
|
@@ -156,18 +56,18 @@ export type ResultsIterator<T> = {
|
|
|
156
56
|
done: () => boolean;
|
|
157
57
|
};
|
|
158
58
|
|
|
159
|
-
type QueryDetailedOptions<T> = QueryOptions<T> & {
|
|
59
|
+
type QueryDetailedOptions<T, D> = QueryOptions<T, D> & {
|
|
160
60
|
onResponse?: (
|
|
161
61
|
response: types.AbstractSearchResult<T>,
|
|
162
62
|
from: PublicSignKey,
|
|
163
63
|
) => void | Promise<void>;
|
|
164
64
|
};
|
|
165
65
|
|
|
166
|
-
const introduceEntries = async <T>(
|
|
66
|
+
const introduceEntries = async <T, D>(
|
|
167
67
|
responses: RPCResponse<types.AbstractSearchResult<T>>[],
|
|
168
68
|
type: AbstractType<T>,
|
|
169
69
|
sync: (result: types.Results<T>) => Promise<void>,
|
|
170
|
-
options?: QueryDetailedOptions<T>,
|
|
70
|
+
options?: QueryDetailedOptions<T, D>,
|
|
171
71
|
): Promise<RPCResponse<types.Results<T>>[]> => {
|
|
172
72
|
const results: RPCResponse<types.Results<T>>[] = [];
|
|
173
73
|
for (const response of responses) {
|
|
@@ -177,7 +77,7 @@ const introduceEntries = async <T>(
|
|
|
177
77
|
|
|
178
78
|
if (response.response instanceof types.Results) {
|
|
179
79
|
response.response.results.forEach((r) => r.init(type));
|
|
180
|
-
if (typeof options?.remote !== "boolean" && options?.remote?.
|
|
80
|
+
if (typeof options?.remote !== "boolean" && options?.remote?.replicate) {
|
|
181
81
|
await sync(response.response);
|
|
182
82
|
}
|
|
183
83
|
options?.onResponse &&
|
|
@@ -290,11 +190,10 @@ const isTransformerWithFunction = <T, I>(
|
|
|
290
190
|
return (options as TransformerAsFunction<T, I>).transform != null;
|
|
291
191
|
};
|
|
292
192
|
|
|
293
|
-
export type OpenOptions<T, I
|
|
193
|
+
export type OpenOptions<T, I, D extends ReplicationDomain<any, Operation>> = {
|
|
294
194
|
documentType: AbstractType<T>;
|
|
295
|
-
|
|
296
195
|
dbType: AbstractType<types.IDocumentStore<T>>;
|
|
297
|
-
log: SharedLog<Operation>;
|
|
196
|
+
log: SharedLog<Operation, D>;
|
|
298
197
|
canRead?: CanRead<T>;
|
|
299
198
|
canSearch?: CanSearch;
|
|
300
199
|
sync: (result: types.Results<T>) => Promise<void>;
|
|
@@ -308,9 +207,11 @@ type IndexableClass<I> = new (
|
|
|
308
207
|
) => IDocumentWithContext<I>;
|
|
309
208
|
|
|
310
209
|
@variant("documents_index")
|
|
311
|
-
export class DocumentIndex<
|
|
312
|
-
|
|
313
|
-
|
|
210
|
+
export class DocumentIndex<
|
|
211
|
+
T,
|
|
212
|
+
I extends Record<string, any>,
|
|
213
|
+
D extends ReplicationDomain<any, Operation>,
|
|
214
|
+
> extends Program<OpenOptions<T, I, D>> {
|
|
314
215
|
@field({ type: RPC })
|
|
315
216
|
_query: RPC<
|
|
316
217
|
indexerTypes.AbstractSearchRequest,
|
|
@@ -342,7 +243,7 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
342
243
|
|
|
343
244
|
private _sync: (result: types.Results<T>) => Promise<void>;
|
|
344
245
|
|
|
345
|
-
private _log: SharedLog<Operation>;
|
|
246
|
+
private _log: SharedLog<Operation, D>;
|
|
346
247
|
|
|
347
248
|
private _resolverProgramCache?: Map<string | number | bigint, T>;
|
|
348
249
|
private _resolverCache: Cache<T>;
|
|
@@ -372,7 +273,7 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
372
273
|
return this._valueEncoding;
|
|
373
274
|
}
|
|
374
275
|
|
|
375
|
-
async open(properties: OpenOptions<T, I>) {
|
|
276
|
+
async open(properties: OpenOptions<T, I, D>) {
|
|
376
277
|
this._log = properties.log;
|
|
377
278
|
|
|
378
279
|
this.documentType = properties.documentType;
|
|
@@ -527,7 +428,7 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
527
428
|
|
|
528
429
|
public async get(
|
|
529
430
|
key: indexerTypes.Ideable | indexerTypes.IdKey,
|
|
530
|
-
options?: QueryOptions<T>,
|
|
431
|
+
options?: QueryOptions<T, D>,
|
|
531
432
|
): Promise<T | undefined> {
|
|
532
433
|
return (
|
|
533
434
|
await this.getDetailed(
|
|
@@ -579,7 +480,7 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
579
480
|
|
|
580
481
|
public async getDetailed(
|
|
581
482
|
key: indexerTypes.IdKey | indexerTypes.IdPrimitive,
|
|
582
|
-
options?: QueryOptions<T>,
|
|
483
|
+
options?: QueryOptions<T, D>,
|
|
583
484
|
): Promise<types.Results<T>[] | undefined> {
|
|
584
485
|
let results: types.Results<T>[] | undefined;
|
|
585
486
|
if (key instanceof Uint8Array) {
|
|
@@ -808,11 +709,12 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
808
709
|
*/
|
|
809
710
|
public async queryDetailed(
|
|
810
711
|
queryRequest: indexerTypes.SearchRequest,
|
|
811
|
-
options?: QueryDetailedOptions<T>,
|
|
712
|
+
options?: QueryDetailedOptions<T, D>,
|
|
812
713
|
): Promise<types.Results<T>[]> {
|
|
813
714
|
const local = typeof options?.local === "boolean" ? options?.local : true;
|
|
814
|
-
let remote:
|
|
815
|
-
|
|
715
|
+
let remote:
|
|
716
|
+
| RemoteQueryOptions<types.AbstractSearchResult<T>, D>
|
|
717
|
+
| undefined = undefined;
|
|
816
718
|
if (typeof options?.remote === "boolean") {
|
|
817
719
|
if (options?.remote) {
|
|
818
720
|
remote = {};
|
|
@@ -829,7 +731,6 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
829
731
|
remote.priority = 1;
|
|
830
732
|
}
|
|
831
733
|
|
|
832
|
-
const promises: Promise<types.Results<T>[] | undefined>[] = [];
|
|
833
734
|
if (!local && !remote) {
|
|
834
735
|
throw new Error(
|
|
835
736
|
"Expecting either 'options.remote' or 'options.local' to be true",
|
|
@@ -850,53 +751,50 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
850
751
|
}
|
|
851
752
|
}
|
|
852
753
|
|
|
754
|
+
let resolved: types.Results<T>[] = [];
|
|
853
755
|
if (remote) {
|
|
854
|
-
const replicatorGroups = await this._log.
|
|
756
|
+
const replicatorGroups = await this._log.getCover(
|
|
757
|
+
remote.domain ?? (undefined as any),
|
|
855
758
|
remote.minAge,
|
|
856
759
|
);
|
|
857
760
|
|
|
858
761
|
if (replicatorGroups) {
|
|
859
762
|
const groupHashes: string[][] = replicatorGroups.map((x) => [x]);
|
|
860
|
-
const
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (
|
|
889
|
-
logger.warn("Did not reciveve responses from all shard");
|
|
890
|
-
if (remote?.throwOnMissing) {
|
|
891
|
-
throw error;
|
|
892
|
-
}
|
|
893
|
-
} else {
|
|
763
|
+
const responseHandler = async (
|
|
764
|
+
results: RPCResponse<types.AbstractSearchResult<T>>[],
|
|
765
|
+
) => {
|
|
766
|
+
for (const r of await introduceEntries(
|
|
767
|
+
results,
|
|
768
|
+
this.documentType,
|
|
769
|
+
this._sync,
|
|
770
|
+
options,
|
|
771
|
+
)) {
|
|
772
|
+
resolved.push(r.response);
|
|
773
|
+
}
|
|
774
|
+
};
|
|
775
|
+
try {
|
|
776
|
+
if (queryRequest instanceof indexerTypes.CloseIteratorRequest) {
|
|
777
|
+
// don't wait for responses
|
|
778
|
+
await this._query.request(queryRequest, { mode: remote!.mode });
|
|
779
|
+
} else {
|
|
780
|
+
await queryAll(
|
|
781
|
+
this._query,
|
|
782
|
+
groupHashes,
|
|
783
|
+
queryRequest,
|
|
784
|
+
responseHandler,
|
|
785
|
+
remote,
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
} catch (error) {
|
|
789
|
+
if (error instanceof MissingResponsesError) {
|
|
790
|
+
logger.warn("Did not reciveve responses from all shard");
|
|
791
|
+
if (remote?.throwOnMissing) {
|
|
894
792
|
throw error;
|
|
895
793
|
}
|
|
794
|
+
} else {
|
|
795
|
+
throw error;
|
|
896
796
|
}
|
|
897
|
-
|
|
898
|
-
};
|
|
899
|
-
promises.push(fn());
|
|
797
|
+
}
|
|
900
798
|
} else {
|
|
901
799
|
// TODO send without direction out to the world? or just assume we can insert?
|
|
902
800
|
/* promises.push(
|
|
@@ -909,7 +807,6 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
909
807
|
); */
|
|
910
808
|
}
|
|
911
809
|
}
|
|
912
|
-
const resolved = await Promise.all(promises);
|
|
913
810
|
for (const r of resolved) {
|
|
914
811
|
if (r) {
|
|
915
812
|
if (r instanceof Array) {
|
|
@@ -930,7 +827,7 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
930
827
|
*/
|
|
931
828
|
public async search(
|
|
932
829
|
queryRequest: indexerTypes.SearchRequest,
|
|
933
|
-
options?: SearchOptions<T>,
|
|
830
|
+
options?: SearchOptions<T, D>,
|
|
934
831
|
): Promise<T[]> {
|
|
935
832
|
// Set fetch to search size, or max value (default to max u32 (4294967295))
|
|
936
833
|
queryRequest.fetch = queryRequest.fetch ?? 0xffffffff;
|
|
@@ -966,7 +863,7 @@ export class DocumentIndex<T, I extends Record<string, any>> extends Program<
|
|
|
966
863
|
*/
|
|
967
864
|
public iterate(
|
|
968
865
|
queryRequest: indexerTypes.SearchRequest,
|
|
969
|
-
options?: QueryOptions<T>,
|
|
866
|
+
options?: QueryOptions<T, D>,
|
|
970
867
|
): ResultsIterator<T> {
|
|
971
868
|
let fetchPromise: Promise<any> | undefined = undefined;
|
|
972
869
|
const peerBufferMap: Map<
|