1/**
2 * The one mapping from plan actions / apply statuses to brand colors and
3 * icons — shared by the plan tree, the live progress view, and the plain
4 * logging CLI so an action never renders two different hues.
5 */
6import type { ApplyStatus } from "../../../Report.ts";
7import { theme, type GlyphName } from "../../CliKit/index.ts";
8
9/** Every verb a plan row can carry (resource CRUD + namespace/action rollups). */
10export type PlanAction =
11 | "create"
12 | "update"
13 | "adopted"
14 | "delete"
15 | "orphaned"
16 | "replace"
17 | "noop"
18 | "mixed"
19 | "run";
20
21export const actionStyle: Record<
22 PlanAction,
23 { readonly color: string; readonly icon: GlyphName }
24> = {
25 create: { color: theme.color.success, icon: "add" },
26 update: { color: theme.color.warning, icon: "edit" },
27 adopted: { color: theme.color.magenta, icon: "adopt" },
28 delete: { color: theme.color.danger, icon: "delete" },
29 orphaned: { color: theme.color.coral, icon: "orphan" },
30 replace: { color: theme.color.magenta, icon: "replace" },
31 noop: { color: theme.color.muted, icon: "bullet" },
32 mixed: { color: theme.color.info, icon: "info" },
33 run: { color: theme.color.info, icon: "run" },
34};
35
36export const applyStatusColor = (
37 status: ApplyStatus | "no change",
38): string | undefined => {
39 switch (status) {
40 case "no change":
41 case "pending":
42 case "skipped":
43 return theme.color.muted;
44 case "attaching":
45 case "post-attach":
46 case "pre-creating":
47 return theme.color.info;
48 case "creating":
49 case "creating replacement":
50 case "created":
51 case "orphaning":
52 case "orphaned":
53 return theme.color.success;
54 case "updating":
55 case "adopting":
56 case "replacing":
57 case "replaced":
58 case "updated":
59 case "adopted":
60 return theme.color.warning;
61 case "deleting":
62 case "deleted":
63 return theme.color.danger;
64 case "running":
65 case "ran":
66 return theme.color.info;
67 case "fail":
68 return theme.color.danger;
69 default:
70 return undefined;
71 }
72};
73
74/** Settled states — the row will not change again. */
75export const isTerminalStatus = (status: ApplyStatus): boolean =>
76 status === "created" ||
77 status === "updated" ||
78 status === "adopted" ||
79 status === "deleted" ||
80 status === "orphaned" ||
81 status === "replaced" ||
82 status === "ran" ||
83 status === "skipped" ||
84 status === "fail";
85
86export const isInProgress = (status: ApplyStatus): boolean =>
87 status === "attaching" ||
88 status === "post-attach" ||
89 status === "pre-creating" ||
90 status === "creating" ||
91 status === "creating replacement" ||
92 status === "updating" ||
93 status === "adopting" ||
94 status === "deleting" ||
95 status === "orphaning" ||
96 status === "replacing" ||
97 status === "running";