2026-04-03
This commit is contained in:
parent
15371d2469
commit
5f835ca4e6
45 changed files with 819 additions and 626 deletions
|
|
@ -1,40 +1,63 @@
|
|||
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 { YAML } from "bun";
|
||||
import { Array as EffectArray, Console, Data, Effect, pipe, Record, Schema, SchemaIssue } from "effect";
|
||||
import { NoSuchElementError } from "effect/Cause";
|
||||
import { type ReadonlyRecord } from "effect/Record";
|
||||
import { SchemaError } from "effect/Schema";
|
||||
|
||||
const COMPOSE_PATH = "compose.yaml";
|
||||
|
||||
const getServicesKey = (yaml: ReadonlyRecord<string | symbol, any>): Option.Option<ReadonlyArray<string>> =>
|
||||
class ScriptError extends Data.TaggedError("ScriptError")<{ cause: unknown }> {}
|
||||
|
||||
const ComposeSchema = Schema.Record(Schema.Union([Schema.String, Schema.Symbol]), Schema.Any);
|
||||
|
||||
type ComposeYaml = ReadonlyRecord<string | symbol, any>;
|
||||
|
||||
const getObjectKey = (key: string, yaml: ComposeYaml): Effect.Effect<ReadonlyArray<string>, ScriptError> =>
|
||||
pipe(
|
||||
Record.get("services")(yaml),
|
||||
Option.andThen((yaml) => Record.keys(yaml)),
|
||||
Record.get(key)(yaml),
|
||||
Effect.fromOption,
|
||||
Effect.map((yaml: any) => Record.keys(yaml)),
|
||||
Effect.mapError((e: NoSuchElementError) => new ScriptError({ cause: e })),
|
||||
);
|
||||
|
||||
const getComposeYaml = <A, I, R>(
|
||||
filePath: string,
|
||||
schema: Schema.Schema<A, I, R>,
|
||||
): Effect.Effect<A, UnknownException | ParseError, R> =>
|
||||
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 getFileContent = Effect.fn("getFileContent")(function* (filePath: string) {
|
||||
const fileRef = Bun.file(filePath);
|
||||
|
||||
const programEffect: Effect.Effect<ReadonlyArray<string>> = 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<string | symbol, unknown>) => getServicesKey(yaml)),
|
||||
// Retire la clé de l'image WordPress.
|
||||
Effect.andThen((keys: ReadonlyArray<string>) => 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 })),
|
||||
);
|
||||
yield* Effect.tryPromise({
|
||||
try: () => fileRef.exists(),
|
||||
catch: (_) => new ScriptError({ cause: "The wanted file does not exist." }),
|
||||
});
|
||||
|
||||
return yield* Effect.tryPromise({
|
||||
try: () => fileRef.text(),
|
||||
catch: (_) => new ScriptError({ cause: "Can't retrieve the file's text content." }),
|
||||
});
|
||||
});
|
||||
|
||||
Effect.runFork(programEffect).pipe(Effect.tapErrorCause(Console.error));
|
||||
const getComposeYaml = <A>(filePath: string, schema: Schema.Schema<A>) =>
|
||||
pipe(
|
||||
getFileContent(filePath),
|
||||
Effect.map((text: string) => YAML.parse(text)),
|
||||
Effect.flatMap((yaml: unknown) => Schema.decodeUnknownEffect(schema)(yaml, { errors: "all" })),
|
||||
Effect.mapError((error) => {
|
||||
if (error instanceof SchemaError) {
|
||||
return new ScriptError({ cause: SchemaIssue.makeFormatterStandardSchemaV1()(error.issue) });
|
||||
} else {
|
||||
return error;
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
const program: Effect.Effect<ReadonlyArray<string>, ScriptError> = pipe(
|
||||
getComposeYaml(COMPOSE_PATH, ComposeSchema),
|
||||
Effect.flatMap((yaml: ComposeYaml) => getObjectKey("services", yaml)),
|
||||
Effect.map((keys: ReadonlyArray<string>) => EffectArray.filter(keys, (key) => key !== "wordpress")),
|
||||
Effect.orElseSucceed(() => [""]),
|
||||
Effect.tap((services: ReadonlyArray<string>) => {
|
||||
Bun.spawn({ cmd: ["podman", "compose", "pull", ...services], timeout: 10000 });
|
||||
return Effect.succeed(services);
|
||||
}),
|
||||
Effect.tapCause(Console.error),
|
||||
);
|
||||
|
||||
Effect.runFork(program);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue