@peerbit/indexer-simple 0.0.1-cccc078

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.
@@ -0,0 +1,44 @@
1
+ import * as types from "@peerbit/indexer-interface";
2
+ export declare class HashmapIndex<T extends Record<string, any>, NestedType = any> implements types.Index<T, NestedType> {
3
+ private _index;
4
+ private _resultsCollectQueue;
5
+ private indexByArr;
6
+ private properties;
7
+ init(properties: types.IndexEngineInitProperties<T, NestedType>): this;
8
+ get(id: types.IdKey): Promise<types.IndexedResult<T> | undefined>;
9
+ put(value: T, id?: types.IdKey): void;
10
+ del(query: types.DeleteRequest): Promise<types.IdKey[]>;
11
+ getSize(): number | Promise<number>;
12
+ iterator(): IterableIterator<[string | number | bigint, types.IndexedValue<T>]>;
13
+ start(): void | Promise<void>;
14
+ stop(): void | Promise<void>;
15
+ drop(): void;
16
+ sum(query: types.SumRequest): Promise<number | bigint>;
17
+ count(query: types.CountRequest): Promise<number>;
18
+ private queryAll;
19
+ query(query: types.SearchRequest, properties: {
20
+ reference?: boolean;
21
+ }): Promise<types.IndexedResults<T>>;
22
+ next(query: types.CollectNextRequest): Promise<types.IndexedResults<T>>;
23
+ close(query: types.CloseIteratorRequest): void;
24
+ private handleFieldQuery;
25
+ private handleQueryObject;
26
+ private handleStringMatch;
27
+ private _queryDocuments;
28
+ getPending(cursorId: string): number | undefined;
29
+ get cursorCount(): number;
30
+ }
31
+ export declare class HashmapIndices implements types.Indices {
32
+ private scopes;
33
+ private indices;
34
+ private closed;
35
+ constructor();
36
+ init<T extends Record<string, any>, NestedType>(properties: types.IndexEngineInitProperties<T, any>): Promise<HashmapIndex<T, NestedType>>;
37
+ scope(name: string): Promise<types.Indices>;
38
+ start(): Promise<void>;
39
+ stop(): Promise<void>;
40
+ drop(): Promise<void>;
41
+ }
42
+ declare const create: () => HashmapIndices;
43
+ export { create };
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,4BAA4B,CAAC;AAqEpD,qBAAa,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,GAAG,CACxE,YAAW,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;IAErC,OAAO,CAAC,MAAM,CAAuD;IACrE,OAAO,CAAC,oBAAoB,CAGzB;IAEH,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,UAAU,CAAiD;IAEnE,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC,EAAE,UAAU,CAAC;IAuBzD,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAWvE,GAAG,CACF,KAAK,EAAE,CAAC,EACR,EAAE,cAA8D,GAC9D,IAAI;IAID,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAU7D,OAAO,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAInC,QAAQ;IAKR,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7B,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5B,IAAI;IAgBE,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC;IAiBtD,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;YAIzC,QAAQ;IAwChB,KAAK,CACV,KAAK,EAAE,KAAK,CAAC,aAAa,EAC1B,UAAU,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GACjC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAqC7B,IAAI,CACT,KAAK,EAAE,KAAK,CAAC,kBAAkB,GAC7B,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IA4BnC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,oBAAoB,GAAG,IAAI;YAIhC,gBAAgB;YA0FhB,iBAAiB;IAwD/B,OAAO,CAAC,iBAAiB;YAmBX,eAAe;IAa7B,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIhD,IAAI,WAAW,IAAI,MAAM,CAExB;CACD;AAED,qBAAa,cAAe,YAAW,KAAK,CAAC,OAAO;IACnD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,OAAO,CAAwD;IACvE,OAAO,CAAC,MAAM,CAAU;;IAMlB,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,EACnD,UAAU,EAAE,KAAK,CAAC,yBAAyB,CAAC,CAAC,EAAE,GAAG,CAAC;IAmB9C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;IAY3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAWtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAW3B;AAED,QAAA,MAAM,MAAM,sBAA6B,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,452 @@
1
+ import { deserialize, serialize } from "@dao-xyz/borsh";
2
+ import { Cache } from "@peerbit/cache";
3
+ import * as types from "@peerbit/indexer-interface";
4
+ import { logger as loggerFn } from "@peerbit/logger";
5
+ import { equals } from "uint8arrays";
6
+ const logger = loggerFn({ module: "simple-index-engine" });
7
+ const getBatchFromResults = (results, wantedSize) => {
8
+ const batch = [];
9
+ /* let size = 0; */
10
+ for (const result of results) {
11
+ batch.push(result);
12
+ /* size += types.extractFieldValue<number>(result, properties.sizeProperty);
13
+ if (size > properties.maxSize) {
14
+ break;
15
+ } */
16
+ if (wantedSize <= batch.length) {
17
+ break;
18
+ }
19
+ }
20
+ results.splice(0, batch.length);
21
+ return batch;
22
+ };
23
+ /* const resolveNestedAliasesRecursively = (request: types.SearchRequest) => {
24
+ const map = new Map();
25
+ for (const query of request.query) {
26
+ _resolveNestedAliasesRecursively(query, map);
27
+ }
28
+ return map;
29
+ }
30
+ */
31
+ const cloneResults = (indexed, schema) => {
32
+ return indexed.map((x) => {
33
+ return { id: x.id, value: deserialize(serialize(x.value), schema) };
34
+ });
35
+ };
36
+ /*
37
+ const _resolveNestedAliasesRecursively = (query: types.Query, aliases: Map<string, string>) => {
38
+
39
+ if (query instanceof types.Nested) {
40
+ aliases.set(query.id, query.path);
41
+ for (const subQuery of query.query) {
42
+ _resolveNestedAliasesRecursively(subQuery, aliases);
43
+ }
44
+ }
45
+ else if (query instanceof types.And) {
46
+ for (const subQuery of query.and) {
47
+ _resolveNestedAliasesRecursively(subQuery, aliases);
48
+ }
49
+ }
50
+ else if (query instanceof types.Or) {
51
+ for (const subQuery of query.or) {
52
+ _resolveNestedAliasesRecursively(subQuery, aliases);
53
+ }
54
+ }
55
+ else if (query instanceof types.Not) {
56
+ _resolveNestedAliasesRecursively(query.not, aliases);
57
+ }
58
+
59
+ }
60
+ */
61
+ export class HashmapIndex {
62
+ _index;
63
+ _resultsCollectQueue;
64
+ indexByArr;
65
+ properties;
66
+ init(properties) {
67
+ this.properties = properties;
68
+ this._index = new Map();
69
+ this._resultsCollectQueue = new Cache({ max: 10000 }); // TODO choose limit better
70
+ if (properties.indexBy) {
71
+ this.indexByArr = Array.isArray(properties.indexBy)
72
+ ? properties.indexBy
73
+ : [properties.indexBy];
74
+ }
75
+ else {
76
+ const indexBy = types.getIdProperty(properties.schema);
77
+ if (!indexBy) {
78
+ throw new Error("No indexBy property defined nor schema has a property decorated with `id({ type: '...' })`");
79
+ }
80
+ this.indexByArr = indexBy;
81
+ }
82
+ return this;
83
+ }
84
+ async get(id) {
85
+ const value = this._index.get(id.primitive);
86
+ if (!value) {
87
+ return;
88
+ }
89
+ return {
90
+ id,
91
+ value: value.value,
92
+ };
93
+ }
94
+ put(value, id = types.toId(types.extractFieldValue(value, this.indexByArr))) {
95
+ this._index.set(id.primitive, { id, value });
96
+ }
97
+ async del(query) {
98
+ let deleted = [];
99
+ for (const doc of await this.queryAll(query)) {
100
+ if (this._index.delete(doc.id.primitive)) {
101
+ deleted.push(doc.id);
102
+ }
103
+ }
104
+ return deleted;
105
+ }
106
+ getSize() {
107
+ return this._index.size;
108
+ }
109
+ iterator() {
110
+ // return a iterator if key value pairs, where the value is the indexed record
111
+ return this._index.entries();
112
+ }
113
+ start() {
114
+ // nothing to do
115
+ }
116
+ stop() {
117
+ this._resultsCollectQueue.clear();
118
+ }
119
+ drop() {
120
+ this._index.clear();
121
+ this._resultsCollectQueue.clear();
122
+ /* for (const subindex of this.subIndices) {
123
+ subindex[1].clear()
124
+ } */
125
+ }
126
+ /* subindex(name: string): types.IndexEngine<any> {
127
+
128
+ const subIndex = new HashmapIndexEngine();
129
+ this.subIndices.set(name, subIndex);
130
+ return subIndex;
131
+ }
132
+ */
133
+ async sum(query) {
134
+ let sum = undefined;
135
+ for (const doc of await this.queryAll(query)) {
136
+ let value = doc.value;
137
+ for (const path of query.key) {
138
+ value = value[path];
139
+ }
140
+ if (typeof value === "number") {
141
+ sum = (sum || 0) + value;
142
+ }
143
+ else if (typeof value === "bigint") {
144
+ sum = (sum || 0n) + value;
145
+ }
146
+ }
147
+ return sum != null ? sum : 0;
148
+ }
149
+ async count(query) {
150
+ return (await this.queryAll(query)).length;
151
+ }
152
+ async queryAll(query) {
153
+ if (query.query.length === 1 &&
154
+ (query.query[0] instanceof types.ByteMatchQuery ||
155
+ query.query[0] instanceof types.StringMatch) &&
156
+ types.stringArraysEquals(query.query[0].key, this.indexByArr)) {
157
+ const firstQuery = query.query[0];
158
+ if (firstQuery instanceof types.ByteMatchQuery) {
159
+ const doc = this._index.get(types.toId(firstQuery.value).primitive);
160
+ return doc ? [doc] : [];
161
+ }
162
+ else if (firstQuery instanceof types.StringMatch &&
163
+ firstQuery.method === types.StringMatchMethod.exact &&
164
+ firstQuery.caseInsensitive === false) {
165
+ const doc = this._index.get(firstQuery.value);
166
+ return doc ? [doc] : [];
167
+ }
168
+ }
169
+ // Handle query normally
170
+ const indexedDocuments = await this._queryDocuments(async (doc) => {
171
+ for (const f of query.query) {
172
+ if (!(await this.handleQueryObject(f, doc.value))) {
173
+ return false;
174
+ }
175
+ }
176
+ return true;
177
+ });
178
+ return indexedDocuments;
179
+ }
180
+ async query(query, properties) {
181
+ const indexedDocuments = await this.queryAll(query);
182
+ if (indexedDocuments.length <= 1) {
183
+ return {
184
+ kept: 0,
185
+ results: indexedDocuments,
186
+ };
187
+ }
188
+ /* const aliases = resolveNestedAliasesRecursively(query) */
189
+ // Sort
190
+ indexedDocuments.sort((a, b) => types.extractSortCompare(a.value, b.value, query.sort));
191
+ const batch = getBatchFromResults(indexedDocuments, query.fetch);
192
+ if (indexedDocuments.length > 0) {
193
+ this._resultsCollectQueue.add(query.idString, {
194
+ arr: indexedDocuments,
195
+ reference: properties?.reference,
196
+ }); // cache resulst not returned
197
+ }
198
+ // TODO dont leak kept if canRead is defined, or return something random
199
+ return {
200
+ kept: indexedDocuments.length,
201
+ results: properties?.reference
202
+ ? batch
203
+ : cloneResults(batch, this.properties.schema),
204
+ };
205
+ }
206
+ async next(query) {
207
+ const results = this._resultsCollectQueue.get(query.idString);
208
+ if (!results) {
209
+ return {
210
+ results: [],
211
+ kept: 0,
212
+ };
213
+ }
214
+ const batch = getBatchFromResults(results.arr, query.amount);
215
+ if (results.arr.length === 0) {
216
+ this._resultsCollectQueue.del(query.idString); // TODO add tests for proper cleanup/timeouts
217
+ }
218
+ // TODO dont leak kept if canRead is defined, or return something random
219
+ return {
220
+ results: results.reference
221
+ ? batch
222
+ : cloneResults(batch, this.properties.schema),
223
+ kept: results.arr.length,
224
+ };
225
+ }
226
+ close(query) {
227
+ this._resultsCollectQueue.del(query.idString);
228
+ }
229
+ async handleFieldQuery(f, obj, startIndex) {
230
+ // this clause is needed if we have a field that is of type [][] (we will recursively go through each subarray)
231
+ if (Array.isArray(obj) ||
232
+ (obj instanceof Uint8Array && f instanceof types.ByteMatchQuery === false)) {
233
+ for (const element of obj) {
234
+ if (await this.handleFieldQuery(f, element, startIndex)) {
235
+ return true;
236
+ }
237
+ }
238
+ return false;
239
+ }
240
+ // Resolve the field from the key path. If we reach an array or nested Document store,
241
+ // then do a recursive call or a search to look into them
242
+ for (let i = startIndex; i < f.key.length; i++) {
243
+ obj = obj[f.key[i]];
244
+ if (Array.isArray(obj) ||
245
+ (obj instanceof Uint8Array &&
246
+ f instanceof types.ByteMatchQuery === false)) {
247
+ for (const element of obj) {
248
+ if (await this.handleFieldQuery(f, element, i + 1)) {
249
+ return true;
250
+ }
251
+ }
252
+ return false;
253
+ }
254
+ if (this.properties.nested?.match(obj)) {
255
+ const queryCloned = f.clone();
256
+ queryCloned.key.splice(0, i + 1); // remove key path until the document store
257
+ const results = await this.properties.nested.query(obj, new types.SearchRequest({ query: [queryCloned] }));
258
+ return results.length > 0 ? true : false; // TODO return INNER HITS?
259
+ }
260
+ }
261
+ if (f instanceof types.IsNull) {
262
+ if (obj == null) {
263
+ return true;
264
+ }
265
+ return false;
266
+ }
267
+ if (obj == null) {
268
+ return undefined;
269
+ }
270
+ // When we reach here, the field value (obj) is comparable
271
+ if (f instanceof types.StringMatch) {
272
+ let compare = f.value;
273
+ if (f.caseInsensitive) {
274
+ compare = compare.toLowerCase();
275
+ }
276
+ if (this.handleStringMatch(f, compare, obj)) {
277
+ return true;
278
+ }
279
+ return false;
280
+ }
281
+ else if (f instanceof types.ByteMatchQuery) {
282
+ if (obj instanceof Uint8Array === false) {
283
+ if (types.stringArraysEquals(f.key, this.indexByArr)) {
284
+ return f.valueString === obj;
285
+ }
286
+ return false;
287
+ }
288
+ return equals(obj, f.value);
289
+ }
290
+ else if (f instanceof types.IntegerCompare) {
291
+ const value = obj;
292
+ if (typeof value !== "bigint" && typeof value !== "number") {
293
+ return false;
294
+ }
295
+ return types.compare(value, f.compare, f.value.value);
296
+ }
297
+ else if (f instanceof types.BoolQuery) {
298
+ return obj === f.value; // true/false
299
+ }
300
+ logger.warn("Unsupported query type: " + f.constructor.name);
301
+ return false;
302
+ }
303
+ async handleQueryObject(f, value) {
304
+ if (f instanceof types.StateFieldQuery) {
305
+ return this.handleFieldQuery(f, value, 0);
306
+ }
307
+ else if (f instanceof types.Nested) {
308
+ // assume field valua is of array type and iterate over each object and match its parts
309
+ let arr = value[f.path];
310
+ if (!Array.isArray(arr)) {
311
+ throw new Error("Nested field is not an array");
312
+ }
313
+ for (const element of arr) {
314
+ for (const query of f.query) {
315
+ if (await this.handleQueryObject(query, element)) {
316
+ return true;
317
+ }
318
+ }
319
+ }
320
+ return false; // TODO test this codepath
321
+ }
322
+ else if (f instanceof types.LogicalQuery) {
323
+ if (f instanceof types.And) {
324
+ for (const and of f.and) {
325
+ const ret = await this.handleQueryObject(and, value);
326
+ if (!ret) {
327
+ return ret;
328
+ }
329
+ }
330
+ return true;
331
+ }
332
+ if (f instanceof types.Or) {
333
+ for (const or of f.or) {
334
+ const ret = await this.handleQueryObject(or, value);
335
+ if (ret === true) {
336
+ return true;
337
+ }
338
+ else if (ret === undefined) {
339
+ return undefined;
340
+ }
341
+ }
342
+ return false;
343
+ }
344
+ if (f instanceof types.Not) {
345
+ const ret = await this.handleQueryObject(f.not, value);
346
+ if (ret === undefined) {
347
+ return undefined;
348
+ }
349
+ return !ret;
350
+ }
351
+ }
352
+ logger.info("Unsupported query type: " + f.constructor.name);
353
+ return false;
354
+ }
355
+ handleStringMatch(f, compare, fv) {
356
+ if (typeof fv !== "string") {
357
+ return false;
358
+ }
359
+ if (f.caseInsensitive) {
360
+ fv = fv.toLowerCase();
361
+ }
362
+ if (f.method === types.StringMatchMethod.exact) {
363
+ return fv === compare;
364
+ }
365
+ if (f.method === types.StringMatchMethod.prefix) {
366
+ return fv.startsWith(compare);
367
+ }
368
+ if (f.method === types.StringMatchMethod.contains) {
369
+ return fv.includes(compare);
370
+ }
371
+ throw new Error("Unsupported");
372
+ }
373
+ async _queryDocuments(filter) {
374
+ // Whether we return the full operation data or just the db value
375
+ const results = [];
376
+ for (const value of this._index.values()) {
377
+ if (await filter(value)) {
378
+ results.push(value);
379
+ }
380
+ }
381
+ return results;
382
+ }
383
+ getPending(cursorId) {
384
+ return this._resultsCollectQueue.get(cursorId)?.arr.length;
385
+ }
386
+ get cursorCount() {
387
+ return this._resultsCollectQueue.size;
388
+ }
389
+ }
390
+ export class HashmapIndices {
391
+ scopes;
392
+ indices = [];
393
+ closed;
394
+ constructor() {
395
+ this.scopes = new Map();
396
+ this.closed = true;
397
+ }
398
+ async init(properties) {
399
+ const existingIndex = this.indices.find((i) => i.schema === properties.schema);
400
+ if (existingIndex) {
401
+ return existingIndex.index;
402
+ }
403
+ const index = new HashmapIndex();
404
+ this.indices.push({ schema: properties.schema, index });
405
+ await index.init(properties);
406
+ if (!this.closed) {
407
+ await index.start();
408
+ }
409
+ return index;
410
+ }
411
+ async scope(name) {
412
+ let scope = this.scopes.get(name);
413
+ if (!scope) {
414
+ scope = new HashmapIndices();
415
+ if (!this.closed) {
416
+ await scope.start();
417
+ }
418
+ this.scopes.set(name, scope);
419
+ }
420
+ return scope;
421
+ }
422
+ async start() {
423
+ this.closed = false;
424
+ for (const scope of this.scopes.values()) {
425
+ await scope.start();
426
+ }
427
+ for (const index of this.indices) {
428
+ await index.index.start();
429
+ }
430
+ }
431
+ async stop() {
432
+ this.closed = true;
433
+ for (const scope of this.scopes.values()) {
434
+ await scope.stop();
435
+ }
436
+ for (const index of this.indices) {
437
+ await index.index.stop();
438
+ }
439
+ }
440
+ async drop() {
441
+ for (const scope of this.scopes.values()) {
442
+ await scope.drop();
443
+ }
444
+ for (const index of this.indices) {
445
+ await index.index.drop();
446
+ }
447
+ this.scopes.clear();
448
+ }
449
+ }
450
+ const create = () => new HashmapIndices();
451
+ export { create };
452
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@peerbit/indexer-simple",
3
+ "version": "0.0.1-cccc078",
4
+ "description": "Simple in memory index for document store",
5
+ "sideEffects": false,
6
+ "type": "module",
7
+ "types": "./dist/src/index.d.ts",
8
+ "typesVersions": {
9
+ "*": {
10
+ "*": [
11
+ "*",
12
+ "dist/*",
13
+ "dist/src/*",
14
+ "dist/src/*/index"
15
+ ],
16
+ "src/*": [
17
+ "*",
18
+ "dist/*",
19
+ "dist/src/*",
20
+ "dist/src/*/index"
21
+ ]
22
+ }
23
+ },
24
+ "files": [
25
+ "src",
26
+ "dist",
27
+ "!dist/e2e",
28
+ "!dist/test",
29
+ "!**/*.tsbuildinfo"
30
+ ],
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/src/index.d.ts",
34
+ "import": "./dist/src/index.js"
35
+ }
36
+ },
37
+ "eslintConfig": {
38
+ "extends": "peerbit",
39
+ "parserOptions": {
40
+ "project": true,
41
+ "sourceType": "module"
42
+ },
43
+ "ignorePatterns": [
44
+ "!.aegir.js",
45
+ "test/ts-use",
46
+ "*.d.ts"
47
+ ]
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "scripts": {
53
+ "clean": "aegir clean",
54
+ "build": "aegir build --no-bundle",
55
+ "test": "aegir test",
56
+ "lint": "aegir lint"
57
+ },
58
+ "author": "dao.xyz",
59
+ "license": "MIT",
60
+ "dependencies": {
61
+ "@peerbit/indexer-interface": "0.0.1-cccc078"
62
+ },
63
+ "devDependencies": {
64
+ "@peerbit/indexer-tests": "0.0.1-cccc078"
65
+ }
66
+ }
package/src/index.ts ADDED
@@ -0,0 +1,566 @@
1
+ import { deserialize, serialize } from "@dao-xyz/borsh";
2
+ import { Cache } from "@peerbit/cache";
3
+ import * as types from "@peerbit/indexer-interface";
4
+ import { logger as loggerFn } from "@peerbit/logger";
5
+ import { equals } from "uint8arrays";
6
+
7
+ const logger = loggerFn({ module: "simple-index-engine" });
8
+
9
+ const getBatchFromResults = <T extends Record<string, any>>(
10
+ results: types.IndexedValue<T>[],
11
+ wantedSize: number,
12
+ /* properties: types.IteratorBatchProperties */
13
+ ) => {
14
+ const batch: types.IndexedValue<T>[] = [];
15
+ /* let size = 0; */
16
+ for (const result of results) {
17
+ batch.push(result);
18
+ /* size += types.extractFieldValue<number>(result, properties.sizeProperty);
19
+ if (size > properties.maxSize) {
20
+ break;
21
+ } */
22
+ if (wantedSize <= batch.length) {
23
+ break;
24
+ }
25
+ }
26
+ results.splice(0, batch.length);
27
+ return batch;
28
+ };
29
+
30
+ /* const resolveNestedAliasesRecursively = (request: types.SearchRequest) => {
31
+ const map = new Map();
32
+ for (const query of request.query) {
33
+ _resolveNestedAliasesRecursively(query, map);
34
+ }
35
+ return map;
36
+ }
37
+ */
38
+ const cloneResults = <T>(
39
+ indexed: types.IndexedValue<T>[],
40
+ schema: any,
41
+ ): types.IndexedValue<T>[] => {
42
+ return indexed.map((x) => {
43
+ return { id: x.id, value: deserialize(serialize(x.value), schema) };
44
+ });
45
+ };
46
+ /*
47
+ const _resolveNestedAliasesRecursively = (query: types.Query, aliases: Map<string, string>) => {
48
+
49
+ if (query instanceof types.Nested) {
50
+ aliases.set(query.id, query.path);
51
+ for (const subQuery of query.query) {
52
+ _resolveNestedAliasesRecursively(subQuery, aliases);
53
+ }
54
+ }
55
+ else if (query instanceof types.And) {
56
+ for (const subQuery of query.and) {
57
+ _resolveNestedAliasesRecursively(subQuery, aliases);
58
+ }
59
+ }
60
+ else if (query instanceof types.Or) {
61
+ for (const subQuery of query.or) {
62
+ _resolveNestedAliasesRecursively(subQuery, aliases);
63
+ }
64
+ }
65
+ else if (query instanceof types.Not) {
66
+ _resolveNestedAliasesRecursively(query.not, aliases);
67
+ }
68
+
69
+ }
70
+ */
71
+
72
+ export class HashmapIndex<T extends Record<string, any>, NestedType = any>
73
+ implements types.Index<T, NestedType>
74
+ {
75
+ private _index: Map<string | bigint | number, types.IndexedValue<T>>;
76
+ private _resultsCollectQueue: Cache<{
77
+ arr: types.IndexedValue<T>[];
78
+ reference: boolean | undefined;
79
+ }>;
80
+
81
+ private indexByArr: string[];
82
+ private properties: types.IndexEngineInitProperties<T, NestedType>;
83
+
84
+ init(properties: types.IndexEngineInitProperties<T, NestedType>) {
85
+ this.properties = properties;
86
+ this._index = new Map();
87
+ this._resultsCollectQueue = new Cache({ max: 10000 }); // TODO choose limit better
88
+ if (properties.indexBy) {
89
+ this.indexByArr = Array.isArray(properties.indexBy)
90
+ ? properties.indexBy
91
+ : [properties.indexBy];
92
+ } else {
93
+ const indexBy = types.getIdProperty(properties.schema);
94
+
95
+ if (!indexBy) {
96
+ throw new Error(
97
+ "No indexBy property defined nor schema has a property decorated with `id({ type: '...' })`",
98
+ );
99
+ }
100
+
101
+ this.indexByArr = indexBy;
102
+ }
103
+
104
+ return this;
105
+ }
106
+
107
+ async get(id: types.IdKey): Promise<types.IndexedResult<T> | undefined> {
108
+ const value = this._index.get(id.primitive);
109
+ if (!value) {
110
+ return;
111
+ }
112
+ return {
113
+ id,
114
+ value: value.value,
115
+ };
116
+ }
117
+
118
+ put(
119
+ value: T,
120
+ id = types.toId(types.extractFieldValue(value, this.indexByArr)),
121
+ ): void {
122
+ this._index.set(id.primitive, { id, value });
123
+ }
124
+
125
+ async del(query: types.DeleteRequest): Promise<types.IdKey[]> {
126
+ let deleted: types.IdKey[] = [];
127
+ for (const doc of await this.queryAll(query)) {
128
+ if (this._index.delete(doc.id.primitive)) {
129
+ deleted.push(doc.id);
130
+ }
131
+ }
132
+ return deleted;
133
+ }
134
+
135
+ getSize(): number | Promise<number> {
136
+ return this._index.size;
137
+ }
138
+
139
+ iterator() {
140
+ // return a iterator if key value pairs, where the value is the indexed record
141
+ return this._index.entries();
142
+ }
143
+
144
+ start(): void | Promise<void> {
145
+ // nothing to do
146
+ }
147
+
148
+ stop(): void | Promise<void> {
149
+ this._resultsCollectQueue.clear();
150
+ }
151
+
152
+ drop() {
153
+ this._index.clear();
154
+ this._resultsCollectQueue.clear();
155
+ /* for (const subindex of this.subIndices) {
156
+ subindex[1].clear()
157
+ } */
158
+ }
159
+
160
+ /* subindex(name: string): types.IndexEngine<any> {
161
+
162
+ const subIndex = new HashmapIndexEngine();
163
+ this.subIndices.set(name, subIndex);
164
+ return subIndex;
165
+ }
166
+ */
167
+
168
+ async sum(query: types.SumRequest): Promise<number | bigint> {
169
+ let sum: undefined | number | bigint = undefined;
170
+ for (const doc of await this.queryAll(query)) {
171
+ let value: any = doc.value;
172
+ for (const path of query.key) {
173
+ value = value[path];
174
+ }
175
+
176
+ if (typeof value === "number") {
177
+ sum = ((sum as number) || 0) + value;
178
+ } else if (typeof value === "bigint") {
179
+ sum = ((sum as bigint) || 0n) + value;
180
+ }
181
+ }
182
+ return sum != null ? sum : 0;
183
+ }
184
+
185
+ async count(query: types.CountRequest): Promise<number> {
186
+ return (await this.queryAll(query)).length;
187
+ }
188
+
189
+ private async queryAll(
190
+ query:
191
+ | types.SearchRequest
192
+ | types.DeleteRequest
193
+ | types.CountRequest
194
+ | types.SumRequest,
195
+ ): Promise<types.IndexedValue<T>[]> {
196
+ if (
197
+ query.query.length === 1 &&
198
+ (query.query[0] instanceof types.ByteMatchQuery ||
199
+ query.query[0] instanceof types.StringMatch) &&
200
+ types.stringArraysEquals(query.query[0].key, this.indexByArr)
201
+ ) {
202
+ const firstQuery = query.query[0];
203
+ if (firstQuery instanceof types.ByteMatchQuery) {
204
+ const doc = this._index.get(types.toId(firstQuery.value).primitive);
205
+ return doc ? [doc] : [];
206
+ } else if (
207
+ firstQuery instanceof types.StringMatch &&
208
+ firstQuery.method === types.StringMatchMethod.exact &&
209
+ firstQuery.caseInsensitive === false
210
+ ) {
211
+ const doc = this._index.get(firstQuery.value);
212
+ return doc ? [doc] : [];
213
+ }
214
+ }
215
+
216
+ // Handle query normally
217
+ const indexedDocuments = await this._queryDocuments(async (doc) => {
218
+ for (const f of query.query) {
219
+ if (!(await this.handleQueryObject(f, doc.value))) {
220
+ return false;
221
+ }
222
+ }
223
+ return true;
224
+ });
225
+
226
+ return indexedDocuments;
227
+ }
228
+
229
+ async query(
230
+ query: types.SearchRequest,
231
+ properties: { reference?: boolean },
232
+ ): Promise<types.IndexedResults<T>> {
233
+ const indexedDocuments = await this.queryAll(query);
234
+ if (indexedDocuments.length <= 1) {
235
+ return {
236
+ kept: 0,
237
+ results: indexedDocuments,
238
+ };
239
+ }
240
+
241
+ /* const aliases = resolveNestedAliasesRecursively(query) */
242
+
243
+ // Sort
244
+ indexedDocuments.sort((a, b) =>
245
+ types.extractSortCompare(a.value, b.value, query.sort),
246
+ );
247
+ const batch = getBatchFromResults<T>(
248
+ indexedDocuments,
249
+ query.fetch,
250
+ /* this.properties.iterator.batch, */
251
+ );
252
+
253
+ if (indexedDocuments.length > 0) {
254
+ this._resultsCollectQueue.add(query.idString, {
255
+ arr: indexedDocuments,
256
+ reference: properties?.reference,
257
+ }); // cache resulst not returned
258
+ }
259
+
260
+ // TODO dont leak kept if canRead is defined, or return something random
261
+ return {
262
+ kept: indexedDocuments.length,
263
+ results: properties?.reference
264
+ ? batch
265
+ : cloneResults(batch, this.properties.schema),
266
+ };
267
+ }
268
+
269
+ async next(
270
+ query: types.CollectNextRequest,
271
+ ): Promise<types.IndexedResults<T>> {
272
+ const results = this._resultsCollectQueue.get(query.idString);
273
+ if (!results) {
274
+ return {
275
+ results: [],
276
+ kept: 0,
277
+ };
278
+ }
279
+
280
+ const batch = getBatchFromResults<T>(
281
+ results.arr,
282
+ query.amount,
283
+ /* this.properties.iterator.batch */
284
+ );
285
+
286
+ if (results.arr.length === 0) {
287
+ this._resultsCollectQueue.del(query.idString); // TODO add tests for proper cleanup/timeouts
288
+ }
289
+
290
+ // TODO dont leak kept if canRead is defined, or return something random
291
+ return {
292
+ results: results.reference
293
+ ? batch
294
+ : cloneResults(batch, this.properties.schema),
295
+ kept: results.arr.length,
296
+ };
297
+ }
298
+
299
+ close(query: types.CloseIteratorRequest): void {
300
+ this._resultsCollectQueue.del(query.idString);
301
+ }
302
+
303
+ private async handleFieldQuery(
304
+ f: types.StateFieldQuery,
305
+ obj: any,
306
+ startIndex: number,
307
+ ): Promise<boolean | undefined> {
308
+ // this clause is needed if we have a field that is of type [][] (we will recursively go through each subarray)
309
+
310
+ if (
311
+ Array.isArray(obj) ||
312
+ (obj instanceof Uint8Array && f instanceof types.ByteMatchQuery === false)
313
+ ) {
314
+ for (const element of obj) {
315
+ if (await this.handleFieldQuery(f, element, startIndex)) {
316
+ return true;
317
+ }
318
+ }
319
+ return false;
320
+ }
321
+
322
+ // Resolve the field from the key path. If we reach an array or nested Document store,
323
+ // then do a recursive call or a search to look into them
324
+ for (let i = startIndex; i < f.key.length; i++) {
325
+ obj = obj[f.key[i]];
326
+ if (
327
+ Array.isArray(obj) ||
328
+ (obj instanceof Uint8Array &&
329
+ f instanceof types.ByteMatchQuery === false)
330
+ ) {
331
+ for (const element of obj) {
332
+ if (await this.handleFieldQuery(f, element, i + 1)) {
333
+ return true;
334
+ }
335
+ }
336
+ return false;
337
+ }
338
+ if (this.properties.nested?.match(obj)) {
339
+ const queryCloned = f.clone();
340
+ queryCloned.key.splice(0, i + 1); // remove key path until the document store
341
+ const results = await this.properties.nested.query(
342
+ obj,
343
+ new types.SearchRequest({ query: [queryCloned] }),
344
+ );
345
+ return results.length > 0 ? true : false; // TODO return INNER HITS?
346
+ }
347
+ }
348
+
349
+ if (f instanceof types.IsNull) {
350
+ if (obj == null) {
351
+ return true;
352
+ }
353
+ return false;
354
+ }
355
+
356
+ if (obj == null) {
357
+ return undefined;
358
+ }
359
+
360
+ // When we reach here, the field value (obj) is comparable
361
+ if (f instanceof types.StringMatch) {
362
+ let compare = f.value;
363
+ if (f.caseInsensitive) {
364
+ compare = compare.toLowerCase();
365
+ }
366
+
367
+ if (this.handleStringMatch(f, compare, obj)) {
368
+ return true;
369
+ }
370
+ return false;
371
+ } else if (f instanceof types.ByteMatchQuery) {
372
+ if (obj instanceof Uint8Array === false) {
373
+ if (types.stringArraysEquals(f.key, this.indexByArr)) {
374
+ return f.valueString === obj;
375
+ }
376
+ return false;
377
+ }
378
+ return equals(obj as Uint8Array, f.value);
379
+ } else if (f instanceof types.IntegerCompare) {
380
+ const value: bigint | number = obj as any as bigint | number;
381
+
382
+ if (typeof value !== "bigint" && typeof value !== "number") {
383
+ return false;
384
+ }
385
+ return types.compare(value, f.compare, f.value.value);
386
+ } else if (f instanceof types.BoolQuery) {
387
+ return obj === f.value; // true/false
388
+ }
389
+ logger.warn("Unsupported query type: " + f.constructor.name);
390
+ return false;
391
+ }
392
+
393
+ private async handleQueryObject(
394
+ f: types.Query,
395
+ value: Record<string, any> | T,
396
+ ): Promise<boolean | undefined> {
397
+ if (f instanceof types.StateFieldQuery) {
398
+ return this.handleFieldQuery(f, value as T, 0);
399
+ } else if (f instanceof types.Nested) {
400
+ // assume field valua is of array type and iterate over each object and match its parts
401
+ let arr = value[f.path];
402
+ if (!Array.isArray(arr)) {
403
+ throw new Error("Nested field is not an array");
404
+ }
405
+
406
+ for (const element of arr) {
407
+ for (const query of f.query) {
408
+ if (await this.handleQueryObject(query, element)) {
409
+ return true;
410
+ }
411
+ }
412
+ }
413
+ return false; // TODO test this codepath
414
+ } else if (f instanceof types.LogicalQuery) {
415
+ if (f instanceof types.And) {
416
+ for (const and of f.and) {
417
+ const ret = await this.handleQueryObject(and, value);
418
+ if (!ret) {
419
+ return ret;
420
+ }
421
+ }
422
+ return true;
423
+ }
424
+
425
+ if (f instanceof types.Or) {
426
+ for (const or of f.or) {
427
+ const ret = await this.handleQueryObject(or, value);
428
+ if (ret === true) {
429
+ return true;
430
+ } else if (ret === undefined) {
431
+ return undefined;
432
+ }
433
+ }
434
+ return false;
435
+ }
436
+ if (f instanceof types.Not) {
437
+ const ret = await this.handleQueryObject(f.not, value);
438
+ if (ret === undefined) {
439
+ return undefined;
440
+ }
441
+ return !ret;
442
+ }
443
+ }
444
+
445
+ logger.info("Unsupported query type: " + f.constructor.name);
446
+ return false;
447
+ }
448
+
449
+ private handleStringMatch(f: types.StringMatch, compare: string, fv: string) {
450
+ if (typeof fv !== "string") {
451
+ return false;
452
+ }
453
+ if (f.caseInsensitive) {
454
+ fv = fv.toLowerCase();
455
+ }
456
+ if (f.method === types.StringMatchMethod.exact) {
457
+ return fv === compare;
458
+ }
459
+ if (f.method === types.StringMatchMethod.prefix) {
460
+ return fv.startsWith(compare);
461
+ }
462
+ if (f.method === types.StringMatchMethod.contains) {
463
+ return fv.includes(compare);
464
+ }
465
+ throw new Error("Unsupported");
466
+ }
467
+
468
+ private async _queryDocuments(
469
+ filter: (doc: types.IndexedValue) => Promise<boolean>,
470
+ ): Promise<types.IndexedValue<T>[]> {
471
+ // Whether we return the full operation data or just the db value
472
+ const results: types.IndexedValue<T>[] = [];
473
+ for (const value of this._index.values()) {
474
+ if (await filter(value)) {
475
+ results.push(value);
476
+ }
477
+ }
478
+ return results;
479
+ }
480
+
481
+ getPending(cursorId: string): number | undefined {
482
+ return this._resultsCollectQueue.get(cursorId)?.arr.length;
483
+ }
484
+
485
+ get cursorCount(): number {
486
+ return this._resultsCollectQueue.size;
487
+ }
488
+ }
489
+
490
+ export class HashmapIndices implements types.Indices {
491
+ private scopes: Map<string, types.Indices>;
492
+ private indices: { schema: any; index: HashmapIndex<any, any> }[] = [];
493
+ private closed: boolean;
494
+ constructor() {
495
+ this.scopes = new Map();
496
+ this.closed = true;
497
+ }
498
+
499
+ async init<T extends Record<string, any>, NestedType>(
500
+ properties: types.IndexEngineInitProperties<T, any>,
501
+ ) {
502
+ const existingIndex = this.indices.find(
503
+ (i) => i.schema === properties.schema,
504
+ );
505
+ if (existingIndex) {
506
+ return existingIndex.index as HashmapIndex<T, NestedType>;
507
+ }
508
+ const index = new HashmapIndex<T, NestedType>();
509
+ this.indices.push({ schema: properties.schema, index });
510
+ await index.init(properties);
511
+
512
+ if (!this.closed) {
513
+ await index.start();
514
+ }
515
+
516
+ return index;
517
+ }
518
+
519
+ async scope(name: string): Promise<types.Indices> {
520
+ let scope = this.scopes.get(name);
521
+ if (!scope) {
522
+ scope = new HashmapIndices();
523
+ if (!this.closed) {
524
+ await scope.start();
525
+ }
526
+ this.scopes.set(name, scope);
527
+ }
528
+ return scope;
529
+ }
530
+
531
+ async start(): Promise<void> {
532
+ this.closed = false;
533
+ for (const scope of this.scopes.values()) {
534
+ await scope.start();
535
+ }
536
+
537
+ for (const index of this.indices) {
538
+ await index.index.start();
539
+ }
540
+ }
541
+
542
+ async stop(): Promise<void> {
543
+ this.closed = true;
544
+ for (const scope of this.scopes.values()) {
545
+ await scope.stop();
546
+ }
547
+
548
+ for (const index of this.indices) {
549
+ await index.index.stop();
550
+ }
551
+ }
552
+ async drop(): Promise<void> {
553
+ for (const scope of this.scopes.values()) {
554
+ await scope.drop();
555
+ }
556
+
557
+ for (const index of this.indices) {
558
+ await index.index.drop();
559
+ }
560
+
561
+ this.scopes.clear();
562
+ }
563
+ }
564
+
565
+ const create = () => new HashmapIndices();
566
+ export { create };