import * as _ from 'lodash' import { ScenarioApi } from "./api" import * as t from "io-ts" import { reporter } from 'io-ts-reporters' import { ThrowReporter } from "io-ts/lib/ThrowReporter" import { ChildProcess } from 'child_process'; import logger from "./logger"; import { Conductor } from "./conductor" import { Player } from "./player" export const decodeOrThrow = (validator, value) => { const result = validator.decode(value) const errors = reporter(result) if (errors.length > 0) { const msg = `Tried to use an invalid value for a complex type and found the following problems:\n - ${errors.join("\n - ")}` logger.error(msg) throw new Error(msg) } return result } export type ObjectN = { [name: number]: V } export type ObjectS = { [name: string]: V } export type SpawnConductorFn = (player: Player, args: any) => Promise export type ScenarioFn = (s: ScenarioApi) => Promise export type IntermediateConfig = RawConductorConfig // TODO: constrain export type ConfigSeed = (args: ConfigSeedArgs) => Promise export type ConfigSeedArgs = { playerName: string, uuid: string, configDir: string, adminPort: number, zomePort: number, } export type AnyConfigBuilder = ConfigSeed | EitherInstancesConfig export type PlayerConfigs = ObjectS export type MachineConfigs = ObjectS export const adminWsUrl = ({ urlBase, adminPort }) => `${urlBase}:${adminPort}` export const zomeWsUrl = ({ urlBase, zomePort }) => `${urlBase}:${zomePort}` /** "F or T" */ export type Fort = T | ((ConfigSeedArgs) => T) export const collapseFort = (fort: Fort, args: ConfigSeedArgs): T => _.isFunction(fort) ? fort(args) : fort export const AgentConfigV = t.intersection([ t.type({ id: t.string, name: t.string, keystore_file: t.string, public_address: t.string, }), t.partial({ test_agent: t.boolean, }) ]) export type AgentConfig = t.TypeOf export const DnaConfigV = t.intersection([ t.type({ id: t.string, file: t.string, }), t.partial({ hash: t.string, uuid: t.string, }) ]) export type DnaConfig = t.TypeOf export const RawInstanceConfigV = t.type({ id: t.string, agent: t.string, dna: t.string, }) export type RawInstanceConfig = t.TypeOf export const DryInstanceConfigV = t.type({ id: t.string, agent: AgentConfigV, dna: DnaConfigV, }) export type DryInstanceConfig = t.TypeOf export const BridgeConfigV = t.type({ handle: t.string, caller_id: t.string, callee_id: t.string, }) export type BridgeConfig = t.TypeOf export const DpkiConfigV = t.type({ instance_id: t.string, init_params: t.string, }) export type DpkiConfig = t.TypeOf export const NetworkModeV = t.union([ t.literal('n3h'), t.literal('memory'), t.literal('websocket'), ]) export type NetworkMode = t.TypeOf export const RawNetworkConfigV = t.record(t.string, t.any) export type RawNetworkConfig = t.TypeOf export const NetworkConfigV = t.union([ NetworkModeV, RawNetworkConfigV, // TODO: could make this actually match the shape of networking ]) export type NetworkConfig = t.TypeOf export const RawLoggerConfigV = t.record(t.string, t.any) export type RawLoggerConfig = t.TypeOf export const LoggerConfigV = t.union([ t.boolean, t.record(t.string, t.any), ]) export type LoggerConfig = t.TypeOf export const ConductorConfigCommonV = t.partial({ bridges: t.array(BridgeConfigV), dpki: DpkiConfigV, // raw network: RawNetworkConfigV, logger: RawLoggerConfigV, }) export type ConductorConfigCommon = t.TypeOf /** Base representation of a Conductor */ export const DryInstancesConfigV = t.array(DryInstanceConfigV) export type DryInstancesConfig = t.TypeOf /** Shorthand representation of a Conductor, * where keys of `instance` are used as instance IDs as well as agent IDs */ export const SugaredInstancesConfigV = t.record(t.string, DnaConfigV) export type SugaredInstancesConfig = t.TypeOf /** For situations where we can accept either flavor of config */ export const EitherInstancesConfigV = t.union([DryInstancesConfigV, SugaredInstancesConfigV]) export type EitherInstancesConfig = t.TypeOf type RawInterfaceConfig = any export interface RawConductorConfig { agents: Array dnas: Array instances: Array interfaces: Array bridges: Array dpki?: DpkiConfig network?: RawNetworkConfig, logger?: RawLoggerConfig, } export type KillFn = (signal?: string) => Promise