XYOracleNetwork/sdk-xyo-client-js

View on GitHub
packages/sdk-utils/packages/payloadset-plugin/src/Resolver.ts

Summary

Maintainability
B
6 hrs
Test Coverage
import { forget } from '@xylabs/forget'
import { Validator } from '@xylabs/object'
import { QueryBoundWitness } from '@xyo-network/boundwitness-model'
import { QueryBoundWitnessWrapper } from '@xyo-network/boundwitness-wrapper'
import { DivinerModule, DivinerParams } from '@xyo-network/diviner-model'
import { PayloadBuilder } from '@xyo-network/payload-builder'
import { PayloadSetPayload } from '@xyo-network/payload-model'
import { WitnessModule, WitnessParams } from '@xyo-network/witness-model'

import {
  isPayloadSetDivinerPlugin,
  isPayloadSetWitnessPlugin,
  PayloadSetDivinerPlugin,
  PayloadSetPlugin,
  PayloadSetWitnessPlugin,
  tryAsPayloadSetDivinerPlugin,
  tryAsPayloadSetWitnessPlugin,
} from './Plugin'

export class PayloadSetPluginResolver {
  protected _params: Record<string, PayloadSetPlugin['params'] | undefined> = {}
  protected _plugins: Record<string, PayloadSetPlugin> = {}

  constructor(
    /** @param plugins The initial set of plugins */
    plugins?: PayloadSetPlugin[],
  ) {
    for (const plugin of plugins ?? []) forget(this.register(plugin))
  }

  async diviner(set: PayloadSetPayload): Promise<DivinerModule | undefined>
  async diviner(set: string): Promise<DivinerModule | undefined>
  async diviner(set: string | PayloadSetPayload): Promise<DivinerModule | undefined> {
    const setHash = typeof set === 'string' ? set : await PayloadBuilder.dataHash(set)
    return await tryAsPayloadSetDivinerPlugin(this._plugins[setHash])?.diviner?.(this._params[setHash] as DivinerParams)
  }

  diviners(): PayloadSetDivinerPlugin[] {
    return Object.values(this._plugins).filter(isPayloadSetDivinerPlugin)
  }

  params(): (PayloadSetPlugin['params'] | undefined)[] {
    return Object.values(this._params)
  }

  plugins(): PayloadSetPlugin[] {
    return Object.values(this._plugins)
  }

  async register<TModule extends WitnessModule | DivinerModule>(plugin: PayloadSetPlugin<TModule>, params?: TModule['params']) {
    const setHash = await PayloadBuilder.dataHash(plugin.set)
    this._plugins[setHash] = plugin
    this._params[setHash] = params
    return this
  }

  async resolve(set?: PayloadSetPayload): Promise<PayloadSetPlugin | undefined>
  async resolve(set?: string): Promise<PayloadSetPlugin | undefined>
  async resolve(set?: string | PayloadSetPayload): Promise<PayloadSetPlugin | undefined> {
    const setHash =
      typeof set === 'string' ? set
      : set ? await PayloadBuilder.dataHash(set)
      : undefined
    return setHash ? this._plugins[setHash] : undefined
  }

  sets(): PayloadSetPayload[] {
    return Object.values(this._plugins).map((value) => value.set)
  }

  async validate(boundwitness: QueryBoundWitness): Promise<Validator<QueryBoundWitness> | undefined> {
    const resultSet = await this.resolve(boundwitness.resultSet)
    return resultSet?.validate?.(boundwitness)
  }

  async witness(set: PayloadSetPayload): Promise<WitnessModule | undefined>
  async witness(set: string): Promise<WitnessModule | undefined>
  async witness(set: string | PayloadSetPayload): Promise<WitnessModule | undefined> {
    const setHash = typeof set === 'string' ? set : await PayloadBuilder.dataHash(set)
    return await tryAsPayloadSetWitnessPlugin(this._plugins[setHash])?.witness?.(this._params[setHash] as WitnessParams)
  }

  witnesses(): PayloadSetWitnessPlugin[] {
    return Object.values(this._plugins).filter(isPayloadSetWitnessPlugin)
  }

  async wrap(boundwitness: QueryBoundWitness): Promise<QueryBoundWitnessWrapper | undefined> {
    const resultSet = await this.resolve(boundwitness.resultSet)
    return resultSet?.wrap?.(boundwitness)
  }
}