import { AutoConfigure, DeepPartial, Effects, ExpectedExports } from "../types" import { Utils, utils } from "../util/utils" import { deepEqual } from "../util/deepEqual" import { deepMerge } from "../util/deepMerge" import { Config } from "../config/builder/config" export type AutoConfigFrom< Store, Vault, Input, NestedConfigs extends Record, > = { [key in keyof NestedConfigs & string]: { serviceConfig: Config autoConfig: (options: { effects: Effects localConfig: Input remoteConfig: NestedConfigs[key] utils: Utils }) => Promise> } } export class AutoConfig< Store, Vault, Input, NestedConfigs extends Record, > { constructor( readonly configs: AutoConfigFrom, readonly path: keyof AutoConfigFrom, ) {} async check( options: Parameters[0], ): ReturnType { const origConfig = JSON.parse(JSON.stringify(options.localConfig)) const newOptions = { ...options, utils: utils(options.effects), localConfig: options.localConfig as Input, remoteConfig: options.remoteConfig as any, } if ( !deepEqual( origConfig, deepMerge( {}, options.localConfig, await this.configs[this.path].autoConfig(newOptions), ), ) ) throw new Error(`Check failed for ${this.path}`) } async autoConfigure( options: Parameters[0], ): ReturnType { const newOptions = { ...options, utils: utils(options.effects), localConfig: options.localConfig as Input, remoteConfig: options.remoteConfig as any, } return deepMerge( {}, options.localConfig, await this.configs[this.path].autoConfig(newOptions), ) } }