@xyo-network/diviner-payload-generic 2.95.4

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,27 @@
1
+ import { Hash } from '@xylabs/hex';
2
+ import { ArchivistInstance, ArchivistModuleEventData } from '@xyo-network/archivist-model';
3
+ import { DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model';
4
+ import { PayloadDiviner } from '@xyo-network/diviner-payload-abstract';
5
+ import { Order, PayloadDivinerParams, PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model';
6
+ import { EventListener } from '@xyo-network/module-events';
7
+ import { Payload, WithMeta } from '@xyo-network/payload-model';
8
+ export declare class GenericPayloadDiviner<TParams extends PayloadDivinerParams = PayloadDivinerParams, TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload, TOut extends Payload = Payload, TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut>> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {
9
+ static configSchemas: "network.xyo.diviner.payload.config"[];
10
+ protected payloadPairs: [WithMeta<TOut>, Hash][];
11
+ private _archivistInstance?;
12
+ private _updatePayloadPairsMutex;
13
+ protected get indexBatchSize(): number;
14
+ protected get maxIndexSize(): number;
15
+ protected get payloadPairsOffset(): Lowercase<string> | undefined;
16
+ protected all(order?: Order, offset?: Hash): WithMeta<TOut>[];
17
+ protected allAsc(offset?: Hash): WithMeta<TOut>[];
18
+ protected allDesc(offset?: Hash): WithMeta<TOut>[];
19
+ protected archivistInstance(): Promise<ArchivistInstance | undefined>;
20
+ protected archivistInstance(required: true): Promise<ArchivistInstance>;
21
+ protected divineHandler(payloads?: TIn[]): Promise<WithMeta<TOut>[]>;
22
+ protected onArchivistInsert: EventListener<ArchivistModuleEventData['inserted']>;
23
+ protected stopHandler(_timeout?: number | undefined): Promise<boolean>;
24
+ protected updateIndex(): Promise<void>;
25
+ private indexPayloads;
26
+ }
27
+ //# sourceMappingURL=Diviner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AAC1F,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAEL,KAAK,EAEL,oBAAoB,EACpB,0BAA0B,EAC3B,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE1D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAM9D,qBAAa,qBAAqB,CAChC,OAAO,SAAS,oBAAoB,GAAG,oBAAoB,EAC3D,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAChH,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,EACnC,GAAG,EACH,IAAI,CACL,CACD,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,yCAA+B;IAE5D,SAAS,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAK;IAErD,OAAO,CAAC,kBAAkB,CAAC,CAAmB;IAC9C,OAAO,CAAC,wBAAwB,CAAc;IAE9C,SAAS,KAAK,cAAc,WAE3B;IAED,SAAS,KAAK,YAAY,WAEzB;IAED,SAAS,KAAK,kBAAkB,kCAE/B;IAED,SAAS,CAAC,GAAG,CAAC,KAAK,GAAE,KAAa,EAAE,MAAM,CAAC,EAAE,IAAI;IAIjD,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI;IAM9B,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI;cAMN,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;cAC3D,iBAAiB,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC;cAa7D,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IAoCnF,SAAS,CAAC,iBAAiB,EAAE,aAAa,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAE/E;cAEwB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;cAOrE,WAAW;YAYb,aAAa;CAI5B"}
@@ -0,0 +1,27 @@
1
+ import { Hash } from '@xylabs/hex';
2
+ import { ArchivistInstance, ArchivistModuleEventData } from '@xyo-network/archivist-model';
3
+ import { DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model';
4
+ import { PayloadDiviner } from '@xyo-network/diviner-payload-abstract';
5
+ import { Order, PayloadDivinerParams, PayloadDivinerQueryPayload } from '@xyo-network/diviner-payload-model';
6
+ import { EventListener } from '@xyo-network/module-events';
7
+ import { Payload, WithMeta } from '@xyo-network/payload-model';
8
+ export declare class GenericPayloadDiviner<TParams extends PayloadDivinerParams = PayloadDivinerParams, TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload, TOut extends Payload = Payload, TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut>> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {
9
+ static configSchemas: "network.xyo.diviner.payload.config"[];
10
+ protected payloadPairs: [WithMeta<TOut>, Hash][];
11
+ private _archivistInstance?;
12
+ private _updatePayloadPairsMutex;
13
+ protected get indexBatchSize(): number;
14
+ protected get maxIndexSize(): number;
15
+ protected get payloadPairsOffset(): Lowercase<string> | undefined;
16
+ protected all(order?: Order, offset?: Hash): WithMeta<TOut>[];
17
+ protected allAsc(offset?: Hash): WithMeta<TOut>[];
18
+ protected allDesc(offset?: Hash): WithMeta<TOut>[];
19
+ protected archivistInstance(): Promise<ArchivistInstance | undefined>;
20
+ protected archivistInstance(required: true): Promise<ArchivistInstance>;
21
+ protected divineHandler(payloads?: TIn[]): Promise<WithMeta<TOut>[]>;
22
+ protected onArchivistInsert: EventListener<ArchivistModuleEventData['inserted']>;
23
+ protected stopHandler(_timeout?: number | undefined): Promise<boolean>;
24
+ protected updateIndex(): Promise<void>;
25
+ private indexPayloads;
26
+ }
27
+ //# sourceMappingURL=Diviner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Diviner.d.ts","sourceRoot":"","sources":["../../src/Diviner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AAC1F,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAA;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,EAEL,KAAK,EAEL,oBAAoB,EACpB,0BAA0B,EAC3B,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE1D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAM9D,qBAAa,qBAAqB,CAChC,OAAO,SAAS,oBAAoB,GAAG,oBAAoB,EAC3D,GAAG,SAAS,0BAA0B,GAAG,0BAA0B,EACnE,IAAI,SAAS,OAAO,GAAG,OAAO,EAC9B,UAAU,SAAS,sBAAsB,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,sBAAsB,CAChH,eAAe,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,EACnC,GAAG,EACH,IAAI,CACL,CACD,SAAQ,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,CAAC;IACtD,OAAgB,aAAa,yCAA+B;IAE5D,SAAS,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAK;IAErD,OAAO,CAAC,kBAAkB,CAAC,CAAmB;IAC9C,OAAO,CAAC,wBAAwB,CAAc;IAE9C,SAAS,KAAK,cAAc,WAE3B;IAED,SAAS,KAAK,YAAY,WAEzB;IAED,SAAS,KAAK,kBAAkB,kCAE/B;IAED,SAAS,CAAC,GAAG,CAAC,KAAK,GAAE,KAAa,EAAE,MAAM,CAAC,EAAE,IAAI;IAIjD,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI;IAM9B,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI;cAMN,iBAAiB,IAAI,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;cAC3D,iBAAiB,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC;cAa7D,aAAa,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IAoCnF,SAAS,CAAC,iBAAiB,EAAE,aAAa,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAE/E;cAEwB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;cAOrE,WAAW;YAYb,aAAa;CAI5B"}
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+ var __publicField = (obj, key, value) => {
22
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
23
+ return value;
24
+ };
25
+
26
+ // src/index.ts
27
+ var src_exports = {};
28
+ __export(src_exports, {
29
+ GenericPayloadDiviner: () => GenericPayloadDiviner
30
+ });
31
+ module.exports = __toCommonJS(src_exports);
32
+
33
+ // src/Diviner.ts
34
+ var import_assert = require("@xylabs/assert");
35
+ var import_forget = require("@xylabs/forget");
36
+ var import_diviner_payload_abstract = require("@xyo-network/diviner-payload-abstract");
37
+ var import_diviner_payload_model = require("@xyo-network/diviner-payload-model");
38
+ var import_payload_builder = require("@xyo-network/payload-builder");
39
+ var import_async_mutex = require("async-mutex");
40
+ var DEFAULT_INDEX_BATCH_SIZE = 100;
41
+ var DEFAULT_MAX_INDEX_SIZE = 8e3;
42
+ var _GenericPayloadDiviner = class _GenericPayloadDiviner extends import_diviner_payload_abstract.PayloadDiviner {
43
+ payloadPairs = [];
44
+ _archivistInstance;
45
+ _updatePayloadPairsMutex = new import_async_mutex.Mutex();
46
+ get indexBatchSize() {
47
+ return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE;
48
+ }
49
+ get maxIndexSize() {
50
+ return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE;
51
+ }
52
+ get payloadPairsOffset() {
53
+ var _a;
54
+ return (_a = this.payloadPairs.at(-1)) == null ? void 0 : _a[1];
55
+ }
56
+ all(order = "asc", offset) {
57
+ return order === "asc" ? this.allAsc(offset) : this.allDesc(offset);
58
+ }
59
+ allAsc(offset) {
60
+ const pairs = this.payloadPairs;
61
+ const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0;
62
+ return this.payloadPairs.slice(startIndex).map(([payload]) => payload);
63
+ }
64
+ allDesc(offset) {
65
+ const pairs = this.payloadPairs.reverse();
66
+ const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0;
67
+ return this.payloadPairs.slice(startIndex).map(([payload]) => payload);
68
+ }
69
+ async archivistInstance(required = false) {
70
+ if (!this._archivistInstance) {
71
+ const archivist = await super.archivistInstance();
72
+ if (required && !archivist) {
73
+ throw new Error("Failed to find archivist");
74
+ }
75
+ archivist == null ? void 0 : archivist.on("inserted", this.onArchivistInsert);
76
+ this._archivistInstance = archivist;
77
+ }
78
+ return this._archivistInstance;
79
+ }
80
+ async divineHandler(payloads) {
81
+ const filters = (payloads == null ? void 0 : payloads.filter(import_diviner_payload_model.isPayloadDivinerQueryPayload)) ?? [];
82
+ (0, import_assert.assertEx)(filters.length < 2, () => "Multiple PayloadDivinerQuery payloads may not be specified");
83
+ const filter = (0, import_assert.assertEx)(filters.shift(), () => "No PayloadDivinerQuery specified");
84
+ await this.updateIndex();
85
+ const { $hash, $meta, schema, schemas, order, limit, offset, ...props } = filter;
86
+ let all = this.all(order, offset);
87
+ if (all) {
88
+ if (schemas == null ? void 0 : schemas.length)
89
+ all = all.filter((payload) => schemas.includes(payload.schema));
90
+ if (Object.keys(props).length > 0) {
91
+ const additionalFilterCriteria = Object.entries(props);
92
+ for (const [prop, filter2] of additionalFilterCriteria) {
93
+ const property = prop;
94
+ all = Array.isArray(filter2) ? all.filter((payload) => filter2.every((value) => {
95
+ var _a;
96
+ const prop2 = payload == null ? void 0 : payload[property];
97
+ return Array.isArray(prop2) && ((_a = prop2.includes) == null ? void 0 : _a.call(prop2, value));
98
+ })) : all.filter((payload) => (payload == null ? void 0 : payload[property]) === filter2);
99
+ }
100
+ }
101
+ return limit ? all.slice(0, limit) : all;
102
+ } else {
103
+ throw new Error('Archivist does not support "all"');
104
+ }
105
+ }
106
+ onArchivistInsert = ({ payloads }) => {
107
+ (0, import_forget.forget)(this.indexPayloads(payloads));
108
+ };
109
+ async stopHandler(_timeout) {
110
+ const archivist = await this.archivistInstance(true);
111
+ archivist.off("inserted", this.onArchivistInsert);
112
+ return await super.stopHandler();
113
+ }
114
+ //index any new payloads
115
+ async updateIndex() {
116
+ await this._updatePayloadPairsMutex.runExclusive(async () => {
117
+ const archivist = await this.archivistInstance(true);
118
+ let newPayloads = await archivist.next({
119
+ limit: 100,
120
+ offset: this.payloadPairsOffset
121
+ });
122
+ while (newPayloads.length > 0) {
123
+ (0, import_assert.assertEx)(this.payloadPairs.length + newPayloads.length <= this.maxIndexSize, () => "maxIndexSize exceeded");
124
+ await this.indexPayloads(newPayloads);
125
+ newPayloads = await archivist.next({
126
+ limit: 100,
127
+ offset: this.payloadPairsOffset
128
+ });
129
+ }
130
+ });
131
+ }
132
+ async indexPayloads(payloads) {
133
+ const pairs = await import_payload_builder.PayloadBuilder.hashPairs(payloads);
134
+ this.payloadPairs.push(...pairs);
135
+ }
136
+ };
137
+ __name(_GenericPayloadDiviner, "GenericPayloadDiviner");
138
+ __publicField(_GenericPayloadDiviner, "configSchemas", [
139
+ import_diviner_payload_model.PayloadDivinerConfigSchema
140
+ ]);
141
+ var GenericPayloadDiviner = _GenericPayloadDiviner;
142
+ // Annotate the CommonJS export names for ESM import in node:
143
+ 0 && (module.exports = {
144
+ GenericPayloadDiviner
145
+ });
146
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner'\n","import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { EmptyObject } from '@xylabs/object'\nimport { ArchivistInstance, ArchivistModuleEventData } from '@xyo-network/archivist-model'\nimport { DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { PayloadDiviner } from '@xyo-network/diviner-payload-abstract'\nimport {\n isPayloadDivinerQueryPayload,\n Order,\n PayloadDivinerConfigSchema,\n PayloadDivinerParams,\n PayloadDivinerQueryPayload,\n} from '@xyo-network/diviner-payload-model'\nimport { EventListener } from '@xyo-network/module-events'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, WithMeta } from '@xyo-network/payload-model'\nimport { Mutex } from 'async-mutex'\n\nconst DEFAULT_INDEX_BATCH_SIZE = 100 as const\nconst DEFAULT_MAX_INDEX_SIZE = 8000 as const\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams = PayloadDivinerParams,\n TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {\n static override configSchemas = [PayloadDivinerConfigSchema]\n\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected get payloadPairsOffset() {\n return this.payloadPairs.at(-1)?.[1]\n }\n\n protected all(order: Order = 'asc', offset?: Hash) {\n return order === 'asc' ? this.allAsc(offset) : this.allDesc(offset)\n }\n\n protected allAsc(offset?: Hash) {\n const pairs = this.payloadPairs\n const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0\n return this.payloadPairs.slice(startIndex).map(([payload]) => payload)\n }\n\n protected allDesc(offset?: Hash) {\n const pairs = this.payloadPairs.reverse()\n const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0\n return this.payloadPairs.slice(startIndex).map(([payload]) => payload)\n }\n\n protected override async archivistInstance(): Promise<ArchivistInstance | undefined>\n protected override async archivistInstance(required: true): Promise<ArchivistInstance>\n protected override async archivistInstance(required = false): Promise<ArchivistInstance | undefined> {\n if (!this._archivistInstance) {\n const archivist = await super.archivistInstance()\n if (required && !archivist) {\n throw new Error('Failed to find archivist')\n }\n archivist?.on('inserted', this.onArchivistInsert)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected override async divineHandler(payloads?: TIn[]): Promise<WithMeta<TOut>[]> {\n const filters = payloads?.filter(isPayloadDivinerQueryPayload) ?? []\n assertEx(filters.length < 2, () => 'Multiple PayloadDivinerQuery payloads may not be specified')\n const filter = assertEx(filters.shift(), () => 'No PayloadDivinerQuery specified') as unknown as WithMeta<\n PayloadDivinerQueryPayload<EmptyObject, Hash>\n >\n\n await this.updateIndex()\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { $hash, $meta, schema, schemas, order, limit, offset, ...props } = filter\n let all: WithMeta<TOut>[] = this.all(order, offset)\n if (all) {\n if (schemas?.length) all = all.filter((payload) => schemas.includes(payload.schema))\n if (Object.keys(props).length > 0) {\n const additionalFilterCriteria = Object.entries(props)\n for (const [prop, filter] of additionalFilterCriteria) {\n const property = prop as keyof TOut\n all =\n Array.isArray(filter) ?\n all.filter((payload) =>\n filter.every((value) => {\n const prop = payload?.[property]\n //TODO: This seems to be written just to check arrays, and now that $meta is there, need to check type?\n return Array.isArray(prop) && prop.includes?.(value)\n }),\n )\n : all.filter((payload) => payload?.[property] === filter)\n }\n }\n return limit ? all.slice(0, limit) : all\n } else {\n throw new Error('Archivist does not support \"all\"')\n }\n }\n\n protected onArchivistInsert: EventListener<ArchivistModuleEventData['inserted']> = ({ payloads }) => {\n forget(this.indexPayloads(payloads as WithMeta<TOut>[]))\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInsert)\n return await super.stopHandler()\n }\n\n //index any new payloads\n protected async updateIndex() {\n await this._updatePayloadPairsMutex.runExclusive(async () => {\n const archivist = await this.archivistInstance(true)\n let newPayloads = (await archivist.next({ limit: 100, offset: this.payloadPairsOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n assertEx(this.payloadPairs.length + newPayloads.length <= this.maxIndexSize, () => 'maxIndexSize exceeded')\n await this.indexPayloads(newPayloads)\n newPayloads = (await archivist.next({ limit: 100, offset: this.payloadPairsOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: WithMeta<TOut>[]) {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n }\n}\n"],"mappings":"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","names":["DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDiviner","PayloadDiviner","payloadPairs","_archivistInstance","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","maxIndexSize","payloadPairsOffset","at","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInsert","divineHandler","payloads","filters","filter","isPayloadDivinerQueryPayload","assertEx","length","shift","updateIndex","$hash","$meta","schema","schemas","limit","props","includes","Object","keys","additionalFilterCriteria","entries","prop","property","Array","isArray","every","value","forget","indexPayloads","stopHandler","_timeout","off","runExclusive","newPayloads","next","PayloadBuilder","hashPairs","push","configSchemas","PayloadDivinerConfigSchema"]}
@@ -0,0 +1,2 @@
1
+ export * from './Diviner';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './Diviner';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './Diviner';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA"}
@@ -0,0 +1,121 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
+ var __publicField = (obj, key, value) => {
5
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
6
+ return value;
7
+ };
8
+
9
+ // src/Diviner.ts
10
+ import { assertEx } from "@xylabs/assert";
11
+ import { forget } from "@xylabs/forget";
12
+ import { PayloadDiviner } from "@xyo-network/diviner-payload-abstract";
13
+ import { isPayloadDivinerQueryPayload, PayloadDivinerConfigSchema } from "@xyo-network/diviner-payload-model";
14
+ import { PayloadBuilder } from "@xyo-network/payload-builder";
15
+ import { Mutex } from "async-mutex";
16
+ var DEFAULT_INDEX_BATCH_SIZE = 100;
17
+ var DEFAULT_MAX_INDEX_SIZE = 8e3;
18
+ var _GenericPayloadDiviner = class _GenericPayloadDiviner extends PayloadDiviner {
19
+ payloadPairs = [];
20
+ _archivistInstance;
21
+ _updatePayloadPairsMutex = new Mutex();
22
+ get indexBatchSize() {
23
+ return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE;
24
+ }
25
+ get maxIndexSize() {
26
+ return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE;
27
+ }
28
+ get payloadPairsOffset() {
29
+ var _a;
30
+ return (_a = this.payloadPairs.at(-1)) == null ? void 0 : _a[1];
31
+ }
32
+ all(order = "asc", offset) {
33
+ return order === "asc" ? this.allAsc(offset) : this.allDesc(offset);
34
+ }
35
+ allAsc(offset) {
36
+ const pairs = this.payloadPairs;
37
+ const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0;
38
+ return this.payloadPairs.slice(startIndex).map(([payload]) => payload);
39
+ }
40
+ allDesc(offset) {
41
+ const pairs = this.payloadPairs.reverse();
42
+ const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0;
43
+ return this.payloadPairs.slice(startIndex).map(([payload]) => payload);
44
+ }
45
+ async archivistInstance(required = false) {
46
+ if (!this._archivistInstance) {
47
+ const archivist = await super.archivistInstance();
48
+ if (required && !archivist) {
49
+ throw new Error("Failed to find archivist");
50
+ }
51
+ archivist == null ? void 0 : archivist.on("inserted", this.onArchivistInsert);
52
+ this._archivistInstance = archivist;
53
+ }
54
+ return this._archivistInstance;
55
+ }
56
+ async divineHandler(payloads) {
57
+ const filters = (payloads == null ? void 0 : payloads.filter(isPayloadDivinerQueryPayload)) ?? [];
58
+ assertEx(filters.length < 2, () => "Multiple PayloadDivinerQuery payloads may not be specified");
59
+ const filter = assertEx(filters.shift(), () => "No PayloadDivinerQuery specified");
60
+ await this.updateIndex();
61
+ const { $hash, $meta, schema, schemas, order, limit, offset, ...props } = filter;
62
+ let all = this.all(order, offset);
63
+ if (all) {
64
+ if (schemas == null ? void 0 : schemas.length)
65
+ all = all.filter((payload) => schemas.includes(payload.schema));
66
+ if (Object.keys(props).length > 0) {
67
+ const additionalFilterCriteria = Object.entries(props);
68
+ for (const [prop, filter2] of additionalFilterCriteria) {
69
+ const property = prop;
70
+ all = Array.isArray(filter2) ? all.filter((payload) => filter2.every((value) => {
71
+ var _a;
72
+ const prop2 = payload == null ? void 0 : payload[property];
73
+ return Array.isArray(prop2) && ((_a = prop2.includes) == null ? void 0 : _a.call(prop2, value));
74
+ })) : all.filter((payload) => (payload == null ? void 0 : payload[property]) === filter2);
75
+ }
76
+ }
77
+ return limit ? all.slice(0, limit) : all;
78
+ } else {
79
+ throw new Error('Archivist does not support "all"');
80
+ }
81
+ }
82
+ onArchivistInsert = ({ payloads }) => {
83
+ forget(this.indexPayloads(payloads));
84
+ };
85
+ async stopHandler(_timeout) {
86
+ const archivist = await this.archivistInstance(true);
87
+ archivist.off("inserted", this.onArchivistInsert);
88
+ return await super.stopHandler();
89
+ }
90
+ //index any new payloads
91
+ async updateIndex() {
92
+ await this._updatePayloadPairsMutex.runExclusive(async () => {
93
+ const archivist = await this.archivistInstance(true);
94
+ let newPayloads = await archivist.next({
95
+ limit: 100,
96
+ offset: this.payloadPairsOffset
97
+ });
98
+ while (newPayloads.length > 0) {
99
+ assertEx(this.payloadPairs.length + newPayloads.length <= this.maxIndexSize, () => "maxIndexSize exceeded");
100
+ await this.indexPayloads(newPayloads);
101
+ newPayloads = await archivist.next({
102
+ limit: 100,
103
+ offset: this.payloadPairsOffset
104
+ });
105
+ }
106
+ });
107
+ }
108
+ async indexPayloads(payloads) {
109
+ const pairs = await PayloadBuilder.hashPairs(payloads);
110
+ this.payloadPairs.push(...pairs);
111
+ }
112
+ };
113
+ __name(_GenericPayloadDiviner, "GenericPayloadDiviner");
114
+ __publicField(_GenericPayloadDiviner, "configSchemas", [
115
+ PayloadDivinerConfigSchema
116
+ ]);
117
+ var GenericPayloadDiviner = _GenericPayloadDiviner;
118
+ export {
119
+ GenericPayloadDiviner
120
+ };
121
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Diviner.ts"],"sourcesContent":["import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { EmptyObject } from '@xylabs/object'\nimport { ArchivistInstance, ArchivistModuleEventData } from '@xyo-network/archivist-model'\nimport { DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'\nimport { PayloadDiviner } from '@xyo-network/diviner-payload-abstract'\nimport {\n isPayloadDivinerQueryPayload,\n Order,\n PayloadDivinerConfigSchema,\n PayloadDivinerParams,\n PayloadDivinerQueryPayload,\n} from '@xyo-network/diviner-payload-model'\nimport { EventListener } from '@xyo-network/module-events'\nimport { PayloadBuilder } from '@xyo-network/payload-builder'\nimport { Payload, WithMeta } from '@xyo-network/payload-model'\nimport { Mutex } from 'async-mutex'\n\nconst DEFAULT_INDEX_BATCH_SIZE = 100 as const\nconst DEFAULT_MAX_INDEX_SIZE = 8000 as const\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams = PayloadDivinerParams,\n TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload,\n TOut extends Payload = Payload,\n TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<\n DivinerInstance<TParams, TIn, TOut>,\n TIn,\n TOut\n >,\n> extends PayloadDiviner<TParams, TIn, TOut, TEventData> {\n static override configSchemas = [PayloadDivinerConfigSchema]\n\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected get payloadPairsOffset() {\n return this.payloadPairs.at(-1)?.[1]\n }\n\n protected all(order: Order = 'asc', offset?: Hash) {\n return order === 'asc' ? this.allAsc(offset) : this.allDesc(offset)\n }\n\n protected allAsc(offset?: Hash) {\n const pairs = this.payloadPairs\n const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0\n return this.payloadPairs.slice(startIndex).map(([payload]) => payload)\n }\n\n protected allDesc(offset?: Hash) {\n const pairs = this.payloadPairs.reverse()\n const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0\n return this.payloadPairs.slice(startIndex).map(([payload]) => payload)\n }\n\n protected override async archivistInstance(): Promise<ArchivistInstance | undefined>\n protected override async archivistInstance(required: true): Promise<ArchivistInstance>\n protected override async archivistInstance(required = false): Promise<ArchivistInstance | undefined> {\n if (!this._archivistInstance) {\n const archivist = await super.archivistInstance()\n if (required && !archivist) {\n throw new Error('Failed to find archivist')\n }\n archivist?.on('inserted', this.onArchivistInsert)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected override async divineHandler(payloads?: TIn[]): Promise<WithMeta<TOut>[]> {\n const filters = payloads?.filter(isPayloadDivinerQueryPayload) ?? []\n assertEx(filters.length < 2, () => 'Multiple PayloadDivinerQuery payloads may not be specified')\n const filter = assertEx(filters.shift(), () => 'No PayloadDivinerQuery specified') as unknown as WithMeta<\n PayloadDivinerQueryPayload<EmptyObject, Hash>\n >\n\n await this.updateIndex()\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { $hash, $meta, schema, schemas, order, limit, offset, ...props } = filter\n let all: WithMeta<TOut>[] = this.all(order, offset)\n if (all) {\n if (schemas?.length) all = all.filter((payload) => schemas.includes(payload.schema))\n if (Object.keys(props).length > 0) {\n const additionalFilterCriteria = Object.entries(props)\n for (const [prop, filter] of additionalFilterCriteria) {\n const property = prop as keyof TOut\n all =\n Array.isArray(filter) ?\n all.filter((payload) =>\n filter.every((value) => {\n const prop = payload?.[property]\n //TODO: This seems to be written just to check arrays, and now that $meta is there, need to check type?\n return Array.isArray(prop) && prop.includes?.(value)\n }),\n )\n : all.filter((payload) => payload?.[property] === filter)\n }\n }\n return limit ? all.slice(0, limit) : all\n } else {\n throw new Error('Archivist does not support \"all\"')\n }\n }\n\n protected onArchivistInsert: EventListener<ArchivistModuleEventData['inserted']> = ({ payloads }) => {\n forget(this.indexPayloads(payloads as WithMeta<TOut>[]))\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInsert)\n return await super.stopHandler()\n }\n\n //index any new payloads\n protected async updateIndex() {\n await this._updatePayloadPairsMutex.runExclusive(async () => {\n const archivist = await this.archivistInstance(true)\n let newPayloads = (await archivist.next({ limit: 100, offset: this.payloadPairsOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n assertEx(this.payloadPairs.length + newPayloads.length <= this.maxIndexSize, () => 'maxIndexSize exceeded')\n await this.indexPayloads(newPayloads)\n newPayloads = (await archivist.next({ limit: 100, offset: this.payloadPairsOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: WithMeta<TOut>[]) {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n }\n}\n"],"mappings":"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","names":["assertEx","forget","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadDivinerConfigSchema","PayloadBuilder","Mutex","DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDiviner","PayloadDiviner","payloadPairs","_archivistInstance","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","maxIndexSize","payloadPairsOffset","at","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInsert","divineHandler","payloads","filters","filter","isPayloadDivinerQueryPayload","assertEx","length","shift","updateIndex","$hash","$meta","schema","schemas","limit","props","includes","Object","keys","additionalFilterCriteria","entries","prop","property","Array","isArray","every","value","forget","indexPayloads","stopHandler","_timeout","off","runExclusive","newPayloads","next","PayloadBuilder","hashPairs","push","configSchemas","PayloadDivinerConfigSchema"]}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@xyo-network/diviner-payload-generic",
3
+ "author": {
4
+ "email": "support@xyo.network",
5
+ "name": "XYO Development Team",
6
+ "url": "https://xyo.network"
7
+ },
8
+ "bugs": {
9
+ "email": "support@xyo.network",
10
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
11
+ },
12
+ "dependencies": {
13
+ "@xylabs/assert": "^3.1.7",
14
+ "@xylabs/forget": "^3.1.7",
15
+ "@xylabs/hex": "^3.1.7",
16
+ "@xylabs/object": "^3.1.7",
17
+ "@xyo-network/archivist-model": "~2.95.4",
18
+ "@xyo-network/diviner-model": "~2.95.4",
19
+ "@xyo-network/diviner-payload-abstract": "~2.95.4",
20
+ "@xyo-network/diviner-payload-model": "~2.95.4",
21
+ "@xyo-network/module-events": "~2.95.4",
22
+ "@xyo-network/payload-builder": "~2.95.4",
23
+ "@xyo-network/payload-model": "~2.95.4",
24
+ "async-mutex": "^0.5.0"
25
+ },
26
+ "devDependencies": {
27
+ "@xylabs/ts-scripts-yarn3": "^3.9.0",
28
+ "@xylabs/tsconfig": "^3.9.0",
29
+ "@xyo-network/account": "~2.95.4",
30
+ "@xyo-network/archivist-memory": "~2.95.4",
31
+ "@xyo-network/node-memory": "~2.95.4",
32
+ "@xyo-network/payload-builder": "~2.95.4",
33
+ "typescript": "^5.4.5"
34
+ },
35
+ "description": "Primary SDK for using XYO Protocol 2.0",
36
+ "types": "dist/node/index.d.ts",
37
+ "exports": {
38
+ ".": {
39
+ "browser": {
40
+ "require": {
41
+ "types": "./dist/browser/index.d.cts",
42
+ "default": "./dist/browser/index.cjs"
43
+ },
44
+ "import": {
45
+ "types": "./dist/browser/index.d.mts",
46
+ "default": "./dist/browser/index.js"
47
+ }
48
+ },
49
+ "node": {
50
+ "require": {
51
+ "types": "./dist/node/index.d.cts",
52
+ "default": "./dist/node/index.cjs"
53
+ },
54
+ "import": {
55
+ "types": "./dist/node/index.d.mts",
56
+ "default": "./dist/node/index.js"
57
+ }
58
+ }
59
+ },
60
+ "./package.json": "./package.json"
61
+ },
62
+ "main": "dist/node/index.cjs",
63
+ "module": "dist/node/index.js",
64
+ "homepage": "https://xyo.network",
65
+ "license": "LGPL-3.0-only",
66
+ "publishConfig": {
67
+ "access": "public"
68
+ },
69
+ "repository": {
70
+ "type": "git",
71
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
72
+ },
73
+ "sideEffects": false,
74
+ "version": "2.95.4",
75
+ "type": "module"
76
+ }
package/src/Diviner.ts ADDED
@@ -0,0 +1,145 @@
1
+ import { assertEx } from '@xylabs/assert'
2
+ import { forget } from '@xylabs/forget'
3
+ import { Hash } from '@xylabs/hex'
4
+ import { EmptyObject } from '@xylabs/object'
5
+ import { ArchivistInstance, ArchivistModuleEventData } from '@xyo-network/archivist-model'
6
+ import { DivinerInstance, DivinerModuleEventData } from '@xyo-network/diviner-model'
7
+ import { PayloadDiviner } from '@xyo-network/diviner-payload-abstract'
8
+ import {
9
+ isPayloadDivinerQueryPayload,
10
+ Order,
11
+ PayloadDivinerConfigSchema,
12
+ PayloadDivinerParams,
13
+ PayloadDivinerQueryPayload,
14
+ } from '@xyo-network/diviner-payload-model'
15
+ import { EventListener } from '@xyo-network/module-events'
16
+ import { PayloadBuilder } from '@xyo-network/payload-builder'
17
+ import { Payload, WithMeta } from '@xyo-network/payload-model'
18
+ import { Mutex } from 'async-mutex'
19
+
20
+ const DEFAULT_INDEX_BATCH_SIZE = 100 as const
21
+ const DEFAULT_MAX_INDEX_SIZE = 8000 as const
22
+
23
+ export class GenericPayloadDiviner<
24
+ TParams extends PayloadDivinerParams = PayloadDivinerParams,
25
+ TIn extends PayloadDivinerQueryPayload = PayloadDivinerQueryPayload,
26
+ TOut extends Payload = Payload,
27
+ TEventData extends DivinerModuleEventData<DivinerInstance<TParams, TIn, TOut>, TIn, TOut> = DivinerModuleEventData<
28
+ DivinerInstance<TParams, TIn, TOut>,
29
+ TIn,
30
+ TOut
31
+ >,
32
+ > extends PayloadDiviner<TParams, TIn, TOut, TEventData> {
33
+ static override configSchemas = [PayloadDivinerConfigSchema]
34
+
35
+ protected payloadPairs: [WithMeta<TOut>, Hash][] = []
36
+
37
+ private _archivistInstance?: ArchivistInstance
38
+ private _updatePayloadPairsMutex = new Mutex()
39
+
40
+ protected get indexBatchSize() {
41
+ return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE
42
+ }
43
+
44
+ protected get maxIndexSize() {
45
+ return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE
46
+ }
47
+
48
+ protected get payloadPairsOffset() {
49
+ return this.payloadPairs.at(-1)?.[1]
50
+ }
51
+
52
+ protected all(order: Order = 'asc', offset?: Hash) {
53
+ return order === 'asc' ? this.allAsc(offset) : this.allDesc(offset)
54
+ }
55
+
56
+ protected allAsc(offset?: Hash) {
57
+ const pairs = this.payloadPairs
58
+ const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0
59
+ return this.payloadPairs.slice(startIndex).map(([payload]) => payload)
60
+ }
61
+
62
+ protected allDesc(offset?: Hash) {
63
+ const pairs = this.payloadPairs.reverse()
64
+ const startIndex = offset ? pairs.findIndex(([, hash]) => hash === offset) ?? 0 : 0
65
+ return this.payloadPairs.slice(startIndex).map(([payload]) => payload)
66
+ }
67
+
68
+ protected override async archivistInstance(): Promise<ArchivistInstance | undefined>
69
+ protected override async archivistInstance(required: true): Promise<ArchivistInstance>
70
+ protected override async archivistInstance(required = false): Promise<ArchivistInstance | undefined> {
71
+ if (!this._archivistInstance) {
72
+ const archivist = await super.archivistInstance()
73
+ if (required && !archivist) {
74
+ throw new Error('Failed to find archivist')
75
+ }
76
+ archivist?.on('inserted', this.onArchivistInsert)
77
+ this._archivistInstance = archivist
78
+ }
79
+ return this._archivistInstance
80
+ }
81
+
82
+ protected override async divineHandler(payloads?: TIn[]): Promise<WithMeta<TOut>[]> {
83
+ const filters = payloads?.filter(isPayloadDivinerQueryPayload) ?? []
84
+ assertEx(filters.length < 2, () => 'Multiple PayloadDivinerQuery payloads may not be specified')
85
+ const filter = assertEx(filters.shift(), () => 'No PayloadDivinerQuery specified') as unknown as WithMeta<
86
+ PayloadDivinerQueryPayload<EmptyObject, Hash>
87
+ >
88
+
89
+ await this.updateIndex()
90
+
91
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
92
+ const { $hash, $meta, schema, schemas, order, limit, offset, ...props } = filter
93
+ let all: WithMeta<TOut>[] = this.all(order, offset)
94
+ if (all) {
95
+ if (schemas?.length) all = all.filter((payload) => schemas.includes(payload.schema))
96
+ if (Object.keys(props).length > 0) {
97
+ const additionalFilterCriteria = Object.entries(props)
98
+ for (const [prop, filter] of additionalFilterCriteria) {
99
+ const property = prop as keyof TOut
100
+ all =
101
+ Array.isArray(filter) ?
102
+ all.filter((payload) =>
103
+ filter.every((value) => {
104
+ const prop = payload?.[property]
105
+ //TODO: This seems to be written just to check arrays, and now that $meta is there, need to check type?
106
+ return Array.isArray(prop) && prop.includes?.(value)
107
+ }),
108
+ )
109
+ : all.filter((payload) => payload?.[property] === filter)
110
+ }
111
+ }
112
+ return limit ? all.slice(0, limit) : all
113
+ } else {
114
+ throw new Error('Archivist does not support "all"')
115
+ }
116
+ }
117
+
118
+ protected onArchivistInsert: EventListener<ArchivistModuleEventData['inserted']> = ({ payloads }) => {
119
+ forget(this.indexPayloads(payloads as WithMeta<TOut>[]))
120
+ }
121
+
122
+ protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {
123
+ const archivist = await this.archivistInstance(true)
124
+ archivist.off('inserted', this.onArchivistInsert)
125
+ return await super.stopHandler()
126
+ }
127
+
128
+ //index any new payloads
129
+ protected async updateIndex() {
130
+ await this._updatePayloadPairsMutex.runExclusive(async () => {
131
+ const archivist = await this.archivistInstance(true)
132
+ let newPayloads = (await archivist.next({ limit: 100, offset: this.payloadPairsOffset })) as WithMeta<TOut>[]
133
+ while (newPayloads.length > 0) {
134
+ assertEx(this.payloadPairs.length + newPayloads.length <= this.maxIndexSize, () => 'maxIndexSize exceeded')
135
+ await this.indexPayloads(newPayloads)
136
+ newPayloads = (await archivist.next({ limit: 100, offset: this.payloadPairsOffset })) as WithMeta<TOut>[]
137
+ }
138
+ })
139
+ }
140
+
141
+ private async indexPayloads(payloads: WithMeta<TOut>[]) {
142
+ const pairs = await PayloadBuilder.hashPairs(payloads)
143
+ this.payloadPairs.push(...pairs)
144
+ }
145
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './Diviner'
package/typedoc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "https://typedoc.org/schema.json",
3
+ "entryPoints": ["src/index.ts"],
4
+ "tsconfig": "./tsconfig.typedoc.json"
5
+ }