import { BunFile, YAML } from "bun"; import { Array, Console, Effect, Option, pipe, Record, Schema } from "effect"; import { type UnknownException } from "effect/Cause"; import { type ParseError } from "effect/ParseResult"; import { type ReadonlyRecord } from "effect/Record"; const COMPOSE_PATH = "compose.yaml"; const getServicesKey = ( yaml: ReadonlyRecord, ): Option.Option> => pipe( Record.get("services")(yaml), Option.andThen(yaml => Record.keys(yaml)), ); const getComposeYaml = ( filePath: string, schema: Schema.Schema, ): Effect.Effect => pipe( Effect.try(() => Bun.file(filePath)), Effect.andThen((file: BunFile) => Effect.tryPromise(() => file.text())), Effect.andThen((text: string) => Effect.try(() => YAML.parse(text))), Effect.andThen((yaml: unknown) => Schema.decodeUnknown(schema)(yaml)), ); const programEffect: Effect.Effect> = Effect.gen(function*() { return yield* pipe( // Récupère le contenu du fichier compose.yaml sous forme de Record. getComposeYaml(COMPOSE_PATH, Schema.Record({ key: Schema.String, value: Schema.Unknown })), // Récupère la clé des services. Effect.andThen((yaml: ReadonlyRecord) => getServicesKey(yaml)), // Retire la clé de l'image WordPress. Effect.andThen((keys: ReadonlyArray) => Array.filter(keys, key => key !== "wordpress")), Effect.orElseSucceed(() => [""]), // Exécute la commande podman. Effect.tap(services => Bun.spawn({ cmd: ["podman", "compose", "pull", ...services], timeout: 10000 })), ); }); Effect.runFork(programEffect).pipe(Effect.tapErrorCause(Console.error));