1import * as Context from "effect/Context";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4
5import {
6 type VcsDriverKind,
7 type VcsError,
8 type VcsInitInput,
9 VcsUnsupportedOperationError,
10} from "@t3tools/contracts";
11import * as VcsDriverRegistry from "./VcsDriverRegistry.ts";
12
13export class VcsProvisioningService extends Context.Service<
14 VcsProvisioningService,
15 {
16 readonly initRepository: (input: VcsInitInput) => Effect.Effect<void, VcsError>;
17 }
18>()("t3/vcs/VcsProvisioningService") {}
19
20function resolveRequestedKind(
21 kind: VcsDriverKind | undefined,
22): Effect.Effect<VcsDriverKind, VcsUnsupportedOperationError> {
23 if (kind === undefined) {
24 return Effect.succeed("git");
25 }
26 if (kind === "unknown") {
27 return Effect.fail(
28 new VcsUnsupportedOperationError({
29 operation: "VcsProvisioningService.resolveRequestedKind",
30 kind,
31 detail: "A concrete VCS driver kind is required for repository provisioning.",
32 }),
33 );
34 }
35 return Effect.succeed(kind);
36}
37
38/** @public Service construction is part of the canonical Effect module API. */
39export const make = Effect.gen(function* () {
40 const registry = yield* VcsDriverRegistry.VcsDriverRegistry;
41
42 const initRepository: VcsProvisioningService["Service"]["initRepository"] = Effect.fn(
43 "VcsProvisioningService.initRepository",
44 )(function* (input) {
45 const kind = yield* resolveRequestedKind(input.kind);
46 const driver = yield* registry.get(kind);
47 return yield* driver.initRepository(input);
48 });
49
50 return VcsProvisioningService.of({
51 initRepository,
52 });
53});
54
55export const layer = Layer.effect(VcsProvisioningService, make);