import type { HttpClient } from "@effect/platform/HttpClient"; import { FileSystem } from "@effect/platform/FileSystem"; import { Path } from "@effect/platform/Path"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; import * as App from "./app.ts"; import { type AppliedPlan } from "./apply.ts"; import { DotAlchemy } from "./dot-alchemy.ts"; import type { DerivePlan, Providers, TraverseResources } from "./plan.ts"; import type { Instance } from "./policy.ts"; import type { AnyResource } from "./resource.ts"; import type { AnyService } from "./service.ts"; import { type StageConfig, type Stages } from "./stage.ts"; import * as State from "./state.ts"; import type { Ref } from "./ref.ts"; import type { CLI } from "./cli/service.ts"; export const defineStack = < const Name extends string, Resources extends (AnyResource | AnyService)[], Req = never, Err = never, >( stack: StackConfig, ): Stack, Req, Err> => stack as any; export type StackConfig< Name extends string, Resources extends (AnyResource | AnyService)[] = (AnyResource | AnyService)[], StagesReq = never, StagesErr = never, TapReq = never, TapErr = never, > = { name: Name; stages: Stages; resources: Resources; providers: Layer.Layer< Providers>, any, App.App | FileSystem | Path | DotAlchemy | HttpClient >; state?: Layer.Layer; tap?: ( output: StackOutput>, ) => Effect.Effect; } & (Exclude, BuiltInServices> extends never ? { layers?: never; } : { layers: Layer.Layer< Exclude, never, never >; }); export type StackOutput = AppliedPlan>; export type Stack< Name extends string = string, Resources extends AnyResource | AnyService = any, StagesReq = any, StagesErr = any, TapReq = any, TapErr = any, > = { name: Name; stages: Stages; resources: Resources[]; providers: Layer.Layer, any, BuiltInServices>; state?: Layer.Layer; cli?: Layer.Layer; tap?: (output: StackOutput) => Effect.Effect; } & (Exclude extends never ? { layers?: never; } : { layers: Layer.Layer< Exclude, never, never >; }); export type StackName = S extends Stack ? Name : never; export type StackResources = S extends Stack ? Resources : never; export type BuiltInServices = | App.App | FileSystem | Path | DotAlchemy | HttpClient; export interface StackRefConfig extends StageConfig { stack: S extends Stack ? Name : never; stage?: string; } export type StackRef = { [Id in keyof AsRecord]: Ref[Id]>; }; type AsRecord = { [Id in TraverseResources["id"]]: Extract< TraverseResources, { id: Id } >; };