@xyo-network/diviner-payload-generic 2.110.19 → 2.111.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -144,7 +144,7 @@ var GenericPayloadDiviner = class extends import_diviner_payload_abstract.Payloa
144
144
  archivist.off("cleared", this.onArchivistCleared);
145
145
  return await super.stopHandler();
146
146
  }
147
- //index any new payloads
147
+ // index any new payloads
148
148
  async updateIndex() {
149
149
  await this._updatePayloadPairsMutex.runExclusive(async () => {
150
150
  const archivist = await this.archivistInstance(true);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner.ts'\n","import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { EmptyObject, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n //update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","configSchemas","defaultConfigSchema","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner.ts'\n","import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { EmptyObject, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n // update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","configSchemas","defaultConfigSchema","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index"]}
@@ -119,7 +119,7 @@ var GenericPayloadDiviner = class extends PayloadDiviner {
119
119
  archivist.off("cleared", this.onArchivistCleared);
120
120
  return await super.stopHandler();
121
121
  }
122
- //index any new payloads
122
+ // index any new payloads
123
123
  async updateIndex() {
124
124
  await this._updatePayloadPairsMutex.runExclusive(async () => {
125
125
  const archivist = await this.archivistInstance(true);
@@ -158,4 +158,4 @@ export {
158
158
  GenericPayloadDiviner,
159
159
  GenericPayloadDivinerConfigSchema
160
160
  };
161
- //# sourceMappingURL=index.js.map
161
+ //# sourceMappingURL=index.mjs.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, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n // update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["assertEx","forget","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadBuilder","Mutex","DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","configSchemas","defaultConfigSchema","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index"]}
@@ -144,7 +144,7 @@ var GenericPayloadDiviner = class extends import_diviner_payload_abstract.Payloa
144
144
  archivist.off("cleared", this.onArchivistCleared);
145
145
  return await super.stopHandler();
146
146
  }
147
- //index any new payloads
147
+ // index any new payloads
148
148
  async updateIndex() {
149
149
  await this._updatePayloadPairsMutex.runExclusive(async () => {
150
150
  const archivist = await this.archivistInstance(true);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner.ts'\n","import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { EmptyObject, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n //update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","configSchemas","defaultConfigSchema","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner.ts'\n","import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { EmptyObject, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n // update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","configSchemas","defaultConfigSchema","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index"]}
@@ -119,7 +119,7 @@ var GenericPayloadDiviner = class extends PayloadDiviner {
119
119
  archivist.off("cleared", this.onArchivistCleared);
120
120
  return await super.stopHandler();
121
121
  }
122
- //index any new payloads
122
+ // index any new payloads
123
123
  async updateIndex() {
124
124
  await this._updatePayloadPairsMutex.runExclusive(async () => {
125
125
  const archivist = await this.archivistInstance(true);
@@ -158,4 +158,4 @@ export {
158
158
  GenericPayloadDiviner,
159
159
  GenericPayloadDivinerConfigSchema
160
160
  };
161
- //# sourceMappingURL=index.js.map
161
+ //# sourceMappingURL=index.mjs.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, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n // update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["assertEx","forget","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadBuilder","Mutex","DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","configSchemas","defaultConfigSchema","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index"]}
@@ -142,7 +142,7 @@ var _GenericPayloadDiviner = class _GenericPayloadDiviner extends import_diviner
142
142
  archivist.off("cleared", this.onArchivistCleared);
143
143
  return await super.stopHandler();
144
144
  }
145
- //index any new payloads
145
+ // index any new payloads
146
146
  async updateIndex() {
147
147
  await this._updatePayloadPairsMutex.runExclusive(async () => {
148
148
  const archivist = await this.archivistInstance(true);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner.ts'\n","import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { EmptyObject, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n //update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index","configSchemas","defaultConfigSchema"]}
1
+ {"version":3,"sources":["../../src/index.ts","../../src/Diviner.ts"],"sourcesContent":["export * from './Diviner.ts'\n","import { assertEx } from '@xylabs/assert'\nimport { forget } from '@xylabs/forget'\nimport { Hash } from '@xylabs/hex'\nimport { EmptyObject, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n // update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index","configSchemas","defaultConfigSchema"]}
@@ -117,7 +117,7 @@ var _GenericPayloadDiviner = class _GenericPayloadDiviner extends PayloadDiviner
117
117
  archivist.off("cleared", this.onArchivistCleared);
118
118
  return await super.stopHandler();
119
119
  }
120
- //index any new payloads
120
+ // index any new payloads
121
121
  async updateIndex() {
122
122
  await this._updatePayloadPairsMutex.runExclusive(async () => {
123
123
  const archivist = await this.archivistInstance(true);
@@ -163,4 +163,4 @@ export {
163
163
  GenericPayloadDiviner,
164
164
  GenericPayloadDivinerConfigSchema
165
165
  };
166
- //# sourceMappingURL=index.js.map
166
+ //# sourceMappingURL=index.mjs.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, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n // update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["assertEx","forget","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadBuilder","Mutex","DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index","configSchemas","defaultConfigSchema"]}
package/package.json CHANGED
@@ -10,26 +10,26 @@
10
10
  "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js/issues"
11
11
  },
12
12
  "dependencies": {
13
- "@xylabs/assert": "^3.6.6",
14
- "@xylabs/forget": "^3.6.6",
15
- "@xylabs/hex": "^3.6.6",
16
- "@xylabs/object": "^3.6.6",
17
- "@xyo-network/archivist-model": "^2.110.19",
18
- "@xyo-network/diviner-model": "^2.110.19",
19
- "@xyo-network/diviner-payload-abstract": "^2.110.19",
20
- "@xyo-network/diviner-payload-model": "^2.110.19",
21
- "@xyo-network/module-events": "^2.110.19",
22
- "@xyo-network/payload-builder": "^2.110.19",
23
- "@xyo-network/payload-model": "^2.110.19",
13
+ "@xylabs/assert": "^3.6.8",
14
+ "@xylabs/forget": "^3.6.8",
15
+ "@xylabs/hex": "^3.6.8",
16
+ "@xylabs/object": "^3.6.8",
17
+ "@xyo-network/archivist-model": "^2.111.0",
18
+ "@xyo-network/diviner-model": "^2.111.0",
19
+ "@xyo-network/diviner-payload-abstract": "^2.111.0",
20
+ "@xyo-network/diviner-payload-model": "^2.111.0",
21
+ "@xyo-network/module-events": "^2.111.0",
22
+ "@xyo-network/payload-builder": "^2.111.0",
23
+ "@xyo-network/payload-model": "^2.111.0",
24
24
  "async-mutex": "^0.5.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@xylabs/ts-scripts-yarn3": "^3.14.1",
28
- "@xylabs/tsconfig": "^3.14.1",
29
- "@xyo-network/archivist-indexeddb": "^2.110.19",
30
- "@xyo-network/archivist-memory": "^2.110.19",
31
- "@xyo-network/node-memory": "^2.110.19",
32
- "@xyo-network/payload-builder": "^2.110.19",
27
+ "@xylabs/ts-scripts-yarn3": "^3.15.5",
28
+ "@xylabs/tsconfig": "^3.15.5",
29
+ "@xyo-network/archivist-indexeddb": "^2.111.0",
30
+ "@xyo-network/archivist-memory": "^2.111.0",
31
+ "@xyo-network/node-memory": "^2.111.0",
32
+ "@xyo-network/payload-builder": "^2.111.0",
33
33
  "fake-indexeddb": "^6.0.0",
34
34
  "typescript": "^5.5.4"
35
35
  },
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "import": {
46
46
  "types": "./dist/browser/index.d.mts",
47
- "default": "./dist/browser/index.js"
47
+ "default": "./dist/browser/index.mjs"
48
48
  }
49
49
  },
50
50
  "node": {
@@ -54,14 +54,14 @@
54
54
  },
55
55
  "import": {
56
56
  "types": "./dist/node/index.d.mts",
57
- "default": "./dist/node/index.js"
57
+ "default": "./dist/node/index.mjs"
58
58
  }
59
59
  }
60
60
  },
61
61
  "./package.json": "./package.json"
62
62
  },
63
63
  "main": "dist/node/index.cjs",
64
- "module": "dist/node/index.js",
64
+ "module": "dist/node/index.mjs",
65
65
  "homepage": "https://xyo.network",
66
66
  "license": "LGPL-3.0-only",
67
67
  "publishConfig": {
@@ -72,6 +72,6 @@
72
72
  "url": "https://github.com/XYOracleNetwork/sdk-xyo-client-js.git"
73
73
  },
74
74
  "sideEffects": false,
75
- "version": "2.110.19",
75
+ "version": "2.111.0",
76
76
  "type": "module"
77
77
  }
package/src/Diviner.ts CHANGED
@@ -115,21 +115,21 @@ export class GenericPayloadDiviner<
115
115
  const { $hash, $meta, schema, schemas, order, limit, offset, ...props } = filter
116
116
  let all: WithMeta<TOut>[] = this.all(order, offset)
117
117
  if (all) {
118
- if (schemas?.length) all = all.filter((payload) => schemas.includes(payload.schema))
118
+ if (schemas?.length) all = all.filter(payload => schemas.includes(payload.schema))
119
119
  if (Object.keys(props).length > 0) {
120
120
  const additionalFilterCriteria = Object.entries(props)
121
121
  for (const [prop, filter] of additionalFilterCriteria) {
122
122
  const property = prop as keyof TOut
123
- all =
124
- Array.isArray(filter) ?
125
- all.filter((payload) =>
123
+ all
124
+ = Array.isArray(filter)
125
+ ? all.filter(payload =>
126
126
  filter.every((value) => {
127
127
  const prop = payload?.[property]
128
- //TODO: This seems to be written just to check arrays, and now that $meta is there, need to check type?
128
+ // TODO: This seems to be written just to check arrays, and now that $meta is there, need to check type?
129
129
  return Array.isArray(prop) && prop.includes?.(value)
130
130
  }),
131
131
  )
132
- : all.filter((payload) => payload?.[property] === filter)
132
+ : all.filter(payload => payload?.[property] === filter)
133
133
  }
134
134
  }
135
135
  return limit ? all.slice(0, limit) : all
@@ -169,7 +169,7 @@ export class GenericPayloadDiviner<
169
169
  return await super.stopHandler()
170
170
  }
171
171
 
172
- //index any new payloads
172
+ // index any new payloads
173
173
  protected async updateIndex() {
174
174
  await this._updatePayloadPairsMutex.runExclusive(async () => {
175
175
  const archivist = await this.archivistInstance(true)
@@ -191,7 +191,7 @@ export class GenericPayloadDiviner<
191
191
  const pairs = await PayloadBuilder.hashPairs(payloads)
192
192
  this.payloadPairs.push(...pairs)
193
193
 
194
- //update the custom indexes
194
+ // update the custom indexes
195
195
  for (const index of this.indexes ?? []) {
196
196
  this.indexMaps[index] = this.indexMaps[index] ?? []
197
197
  for (const [payload] of pairs) {
@@ -1 +0,0 @@
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, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n //update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["assertEx","forget","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadBuilder","Mutex","DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","configSchemas","defaultConfigSchema","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index"]}
@@ -1 +0,0 @@
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, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n //update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["assertEx","forget","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadBuilder","Mutex","DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","configSchemas","defaultConfigSchema","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index"]}
@@ -1 +0,0 @@
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, JsonObject } 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 PayloadDivinerConfig,\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, Schema, 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 const GenericPayloadDivinerConfigSchema = 'network.xyo.diviner.payload.generic.config' as const\nexport type GenericPayloadDivinerConfigSchema = typeof GenericPayloadDivinerConfigSchema\n\nexport type GenericPayloadDivinerConfig = PayloadDivinerConfig<\n {\n indexes?: string[]\n },\n GenericPayloadDivinerConfigSchema\n>\n\nexport class GenericPayloadDiviner<\n TParams extends PayloadDivinerParams<GenericPayloadDivinerConfig> = PayloadDivinerParams<GenericPayloadDivinerConfig>,\n TIn extends PayloadDivinerQueryPayload<EmptyObject, Hash> = PayloadDivinerQueryPayload<EmptyObject, Hash>,\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 readonly configSchemas: Schema[] = [...super.configSchemas, GenericPayloadDivinerConfigSchema]\n static override readonly defaultConfigSchema: Schema = GenericPayloadDivinerConfigSchema\n\n protected indexMaps: Record<string, WithMeta<TOut>[]> = {}\n protected payloadPairs: [WithMeta<TOut>, Hash][] = []\n\n private _archivistInstance?: ArchivistInstance\n private _indexOffset?: Hash\n private _updatePayloadPairsMutex = new Mutex()\n\n protected get indexBatchSize() {\n return this.config.indexBatchSize ?? DEFAULT_INDEX_BATCH_SIZE\n }\n\n protected get indexes(): string[] {\n return ['schema', ...(this.config.indexes ?? [])]\n }\n\n protected get maxIndexSize() {\n return this.config.maxIndexSize ?? DEFAULT_MAX_INDEX_SIZE\n }\n\n protected all(order: Order = 'desc', 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) ?? -1) : -1) + 1\n return pairs.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) ?? -1) : -1) + 1\n return pairs.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.onArchivistInserted)\n archivist?.on('cleared', this.onArchivistCleared)\n archivist?.on('deleted', this.onArchivistDeleted)\n this._archivistInstance = archivist\n }\n return this._archivistInstance\n }\n\n protected async clearIndex() {\n await this._updatePayloadPairsMutex.runExclusive(() => {\n this._indexOffset = undefined\n this.payloadPairs = []\n this.indexMaps = {}\n })\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 onArchivistCleared: EventListener<ArchivistModuleEventData['cleared']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n // we are just rebuilding the entire index at this point on delete since large archivists do not support delete\n protected onArchivistDeleted: EventListener<ArchivistModuleEventData['deleted']> = () => {\n forget(\n (async () => {\n await this.clearIndex()\n await this.updateIndex()\n })(),\n )\n }\n\n protected onArchivistInserted: EventListener<ArchivistModuleEventData['inserted']> = () => {\n forget(this.updateIndex())\n }\n\n protected override async stopHandler(_timeout?: number | undefined): Promise<boolean> {\n const archivist = await this.archivistInstance(true)\n archivist.off('inserted', this.onArchivistInserted)\n archivist.off('deleted', this.onArchivistDeleted)\n archivist.off('cleared', this.onArchivistCleared)\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._indexOffset })) as WithMeta<TOut>[]\n while (newPayloads.length > 0) {\n const prevOffset = this._indexOffset\n this._indexOffset = await PayloadBuilder.hash(assertEx(newPayloads.at(-1)))\n if (this._indexOffset === prevOffset) {\n this.logger.warn('next offset not found', prevOffset)\n }\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._indexOffset })) as WithMeta<TOut>[]\n }\n })\n }\n\n private async indexPayloads(payloads: TOut[]): Promise<Hash> {\n const pairs = await PayloadBuilder.hashPairs(payloads)\n this.payloadPairs.push(...pairs)\n\n //update the custom indexes\n for (const index of this.indexes ?? []) {\n this.indexMaps[index] = this.indexMaps[index] ?? []\n for (const [payload] of pairs) {\n if ((payload as unknown as JsonObject)[index] !== undefined) this.indexMaps[index].push(payload)\n }\n }\n return assertEx(pairs.at(-1))[1]\n }\n}\n"],"mappings":"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","names":["assertEx","forget","PayloadDiviner","isPayloadDivinerQueryPayload","PayloadBuilder","Mutex","DEFAULT_INDEX_BATCH_SIZE","DEFAULT_MAX_INDEX_SIZE","GenericPayloadDivinerConfigSchema","GenericPayloadDiviner","PayloadDiviner","indexMaps","payloadPairs","_archivistInstance","_indexOffset","_updatePayloadPairsMutex","Mutex","indexBatchSize","config","indexes","maxIndexSize","all","order","offset","allAsc","allDesc","pairs","startIndex","findIndex","hash","slice","map","payload","reverse","archivistInstance","required","archivist","Error","on","onArchivistInserted","onArchivistCleared","onArchivistDeleted","clearIndex","runExclusive","undefined","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","stopHandler","_timeout","off","newPayloads","next","prevOffset","PayloadBuilder","at","logger","warn","indexPayloads","hashPairs","push","index","configSchemas","defaultConfigSchema"]}