UNPKG

@grlt-hub/app-compose

Version:
197 lines (183 loc) 7.08 kB
import * as effector from 'effector'; import { StoreWritable } from 'effector'; type NonEmptyTuple<T = unknown> = [T, ...T[]]; type StageId = string; type Stage = { id: StageId; containersToBoot: AnyContainer[]; }; type AnyObject = Record<string, unknown>; type ValueOf<T> = T[keyof T]; declare const CONTAINER_STATUS: { readonly idle: "idle"; readonly pending: "pending"; readonly done: "done"; readonly fail: "fail"; readonly off: "off"; }; type ContainerStatus = ValueOf<typeof CONTAINER_STATUS>; type StartResult<T> = Promise<{ api: T; }> | { api: T; }; type EnableResult = Promise<boolean> | boolean; type AnyAPI = AnyObject | null; type AnyStartFn = (...x: any) => StartResult<AnyAPI>; type AnyContainer = { id: string; domain: string; $status: StoreWritable<ContainerStatus>; start: AnyStartFn; dependencies?: AnyContainer[]; optionalDependencies?: AnyContainer[]; enable?: (..._: any) => EnableResult; }; type AnyDeps = NonEmptyTuple<AnyContainer> | void; type ContainerId = AnyContainer['id']; type ContainerDomain = AnyContainer['domain']; type ValidateParams = Pick<AnyContainer, 'id' | 'domain' | 'dependencies' | 'optionalDependencies'>; declare const ERROR: { readonly CONTAINER_ID_EMPTY_STRING: "Container ID cannot be an empty string."; readonly CONTAINER_DOMAIN_NAME_EMPTY_STRING: "Container Domain cannot be an empty string."; readonly depsIntersection: (intersection: string[], containerId: ValidateParams["id"]) => string; }; type ContainerIdEmptyStringError = ValidateParams & { id: never; error: typeof ERROR.CONTAINER_ID_EMPTY_STRING; }; type ContainerDomainNameEmptyStringError = ValidateParams & { domain: never; error: typeof ERROR.CONTAINER_DOMAIN_NAME_EMPTY_STRING; }; type ExtractDeps<D extends AnyContainer[]> = { [K in D[number] as Awaited<ReturnType<K['start']>>['api'] extends Record<string, never> ? never : K['id']]: Awaited<ReturnType<K['start']>>['api']; }; type ExtractEnabled<D extends AnyContainer[]> = { [K in D[number] as K['id']]: boolean; }; type DependenciesConfig<Deps extends AnyDeps, OptionalDeps extends AnyDeps> = [ Deps ] extends [void] ? [ OptionalDeps ] extends [void] ? {} : { optionalDependencies: Exclude<OptionalDeps, void>; } : [OptionalDeps] extends [void] ? { dependencies: Exclude<Deps, void>; } : { dependencies: Exclude<Deps, void>; optionalDependencies: Exclude<OptionalDeps, void>; }; type Params$4<Id extends string, Domain extends string, API extends AnyAPI, Deps extends AnyDeps = void, OptionalDeps extends AnyDeps = void> = '' extends Id ? ContainerIdEmptyStringError : '' extends Domain ? ContainerDomainNameEmptyStringError : DependenciesConfig<Deps, OptionalDeps> & { id: Id; domain: Domain; start: (api: ExtractDeps<Exclude<Deps, void>> & Partial<ExtractDeps<Exclude<OptionalDeps, void>>>, enabled: ExtractEnabled<Exclude<Deps, void>> & ExtractEnabled<Exclude<OptionalDeps, void>>) => StartResult<API>; enable?: (api: ExtractDeps<Exclude<Deps, void>> & Partial<ExtractDeps<Exclude<OptionalDeps, void>>>, enabled: ExtractEnabled<Exclude<Deps, void>> & ExtractEnabled<Exclude<OptionalDeps, void>>) => EnableResult; }; declare const createContainer: <Id extends string, Domain extends string, API extends AnyAPI, Deps extends AnyDeps = void, OptionalDeps extends AnyDeps = void>(__params: Params$4<Id, Domain, API, Deps, OptionalDeps>) => Exclude<Params$4<Id, Domain, API, Deps, OptionalDeps>, ContainerIdEmptyStringError | ContainerDomainNameEmptyStringError> & { $status: effector.StoreWritable<ContainerStatus>; }; type View = 'domains' | 'containers'; type TransitiveDependency<Id extends ContainerId | ContainerDomain = ContainerId> = { id: Id; path: string; }; type ContainersGraph = Record<ContainerId, { domain: ContainerDomain; dependencies: ContainerId[]; optionalDependencies: ContainerId[]; transitive: { dependencies: TransitiveDependency<ContainerId>[]; optionalDependencies: TransitiveDependency<ContainerId>[]; }; }>; type DomainsGraph = Record<ContainerDomain, { containers: ContainerId[]; strict: ContainerDomain[]; optional: ContainerDomain[]; transitive: { strict: TransitiveDependency<ContainerDomain>[]; optional: TransitiveDependency<ContainerDomain>[]; }; }>; type StageTuples = [Stage['id'], NonEmptyTuple<AnyContainer>][]; type Params$3 = { stages: Stage[]; }; type Result$1<T extends View = 'containers'> = T extends 'domains' ? { graph: DomainsGraph; dependsOn: (_: ContainerDomain[]) => DomainsGraph; requiredBy: (_: ContainerDomain[]) => DomainsGraph; } : { graph: ContainersGraph; dependsOn: (_: AnyContainer[]) => ContainersGraph; requiredBy: (_: AnyContainer[]) => ContainersGraph; }; declare const graph: <T extends View = "containers">(params: Params$3, config: { view: T; }) => Result$1<T>; type Config$1 = { debug?: boolean; onContainerFail?: (_: { container: { id: ContainerId; domain: ContainerDomain; }; stageId: Stage['id']; error: Error; }) => unknown; }; type APIs = Record<string, Awaited<ReturnType<AnyContainer['start']>>['api']>; type UpResult = { allDone: boolean; containerStatuses: Record<ContainerId, ContainerStatus>; }; declare const createStageUpFn: (__config?: Config$1) => (stage: Stage, apis: APIs) => Promise<UpResult>; type Params$2 = { required: (AnyContainer | NonEmptyTuple<AnyContainer>)[] | 'all' | undefined; } & Pick<Awaited<ReturnType<ReturnType<typeof createStageUpFn>>>, 'containerStatuses'>; type Result = { ok: true; } | { ok: false; id: ContainerId[]; }; declare const validateStageUp: (params: Params$2) => Result; type Params$1 = { stages: Stage[]; required?: Parameters<typeof validateStageUp>[0]['required']; }; type Config = Parameters<typeof createStageUpFn>[0]; declare const up: (params: Params$1, config: Config) => Promise<{ allDone: boolean; stages: Record<string, { allDone: boolean; containerStatuses: Record<ContainerId, ContainerStatus>; }>; }>; type UpFn = typeof up; type GraphFn = typeof graph; type Params = { stages: StageTuples; required?: Parameters<UpFn>[0]['required']; }; declare const compose: (params: Params) => Promise<{ up: (config?: Parameters<UpFn>[1]) => Promise<{ allDone: boolean; stages: Record<string, { allDone: boolean; containerStatuses: Record<ContainerId, ContainerStatus>; }>; }>; diff: () => Promise<void>; graph: (config?: Parameters<GraphFn>[1]) => Promise<{ graph: DomainsGraph; dependsOn: (_: ContainerDomain[]) => DomainsGraph; requiredBy: (_: ContainerDomain[]) => DomainsGraph; } | { graph: ContainersGraph; dependsOn: (_: AnyContainer[]) => ContainersGraph; requiredBy: (_: AnyContainer[]) => ContainersGraph; }>; }>; export { compose, createContainer };