1import type { EnvironmentId, MergebotDeployments } from "@t3tools/contracts";
2import type { ReactNode } from "react";
3
4import { useEnvironment } from "../../state/environments";
5import { useMergebotDeployments } from "../../state/mergebot";
6
7type DeploymentsRender = (deployments: readonly MergebotDeployments[]) => ReactNode;
8
9/**
10 * Renders `children` with deployment data for every Mergebot repository configured on the
11 * environment that has any. One component per repository keeps each hook call order stable.
12 */
13export function ConfiguredDeployments(props: {
14 environmentId: EnvironmentId;
15 children: DeploymentsRender;
16}) {
17 const environment = useEnvironment(props.environmentId);
18
19 return (
20 <Collect
21 environmentId={props.environmentId}
22 repositories={environment?.serverConfig?.mergebot?.repositories ?? []}
23 found={[]}
24 >
25 {props.children}
26 </Collect>
27 );
28}
29
30function Collect(props: {
31 environmentId: EnvironmentId;
32 repositories: readonly string[];
33 found: readonly MergebotDeployments[];
34 children: DeploymentsRender;
35}) {
36 const [repository, ...rest] = props.repositories;
37 if (repository === undefined) return props.children(props.found);
38
39 return (
40 <CollectRepository
41 environmentId={props.environmentId}
42 repository={repository}
43 rest={rest}
44 found={props.found}
45 >
46 {props.children}
47 </CollectRepository>
48 );
49}
50
51function CollectRepository(props: {
52 environmentId: EnvironmentId;
53 repository: string;
54 rest: readonly string[];
55 found: readonly MergebotDeployments[];
56 children: DeploymentsRender;
57}) {
58 const deployments = useMergebotDeployments(props.environmentId, props.repository);
59
60 return (
61 <Collect
62 environmentId={props.environmentId}
63 repositories={props.rest}
64 found={deployments ? [...props.found, deployments] : props.found}
65 >
66 {props.children}
67 </Collect>
68 );
69}