Skip to content

Commit 153fd70

Browse files
committed
fixing the ui
1 parent b21d151 commit 153fd70

6 files changed

Lines changed: 75 additions & 66 deletions

File tree

README.md

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,8 @@ src/
7979
│ └── httpClient.ts
8080
├── lib/ # Shared utilities
8181
│ ├── config.ts # All config management (auth + project)
82-
│ ├── inject.ts # Secret injection
83-
│ ├── keyring.ts # Secure keyring storage
84-
│ ├── error.ts # Error handling
85-
│ ├── input.ts # User input helpers
86-
│ └── terminal.ts # Terminal utilities
82+
|
8783
└── ui/ # Ink UI components
88-
├── LoginFlow.tsx
89-
├── RunFlow.tsx
90-
├── EnkryptifyLogin.tsx
91-
├── AwsLogin.tsx
92-
├── SecretsTable.tsx
93-
├── SelectItem.tsx
94-
├── Confirm.tsx
95-
└── SuccessMessage.tsx
9684
```
9785

9886
---

src/cmd/run.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ export async function runCommand(
2727
options.unmountSpinner();
2828
}
2929

30+
// ✅ Print immediately after injection (before the user's command output starts)
31+
const successMessage = options?.env
32+
? `Secrets injected successfully for environment "${options.env}".\n`
33+
: "Secrets injected successfully.\n";
34+
process.stderr.write(successMessage);
35+
3036
if (cmd.length === 0) {
3137
throw new Error("Command is required. Please provide a command to run.");
3238
}
@@ -43,7 +49,7 @@ export async function runCommand(
4349
stdout: "inherit",
4450
stderr: "inherit",
4551
});
46-
await proc.exited;
52+
4753
const exitCode = await proc.exited;
4854
if (exitCode !== 0) {
4955
throw new Error(`Command exited with code ${exitCode}`);

src/providers/enkryptify/provider.ts

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,24 @@ export class EnkryptifyProvider implements Provider {
103103
throw new Error("No workspaces found. Please create a workspace first before setting up.");
104104
}
105105

106-
const workspaceSlug = await selectName(
107-
workspaces.map((ws) => `${ws.slug}`),
108-
"Select workspace",
109-
);
106+
const workspaceMap = new Map<string, Workspace>();
107+
const workspaceLabels = workspaces.map((ws) => {
108+
const label = `${ws.name} (${ws.slug})`;
109+
workspaceMap.set(label, ws);
110+
return label;
111+
});
110112

111-
if (!workspaceSlug) throw new Error("Failed to select workspace");
113+
const selectedWorkspaceLabel = await selectName(workspaceLabels, "Select workspace");
112114

113-
const selectedWorkspace = workspaces.find((ws) => ws.slug === workspaceSlug);
115+
if (!selectedWorkspaceLabel) throw new Error("Failed to select workspace");
116+
117+
const selectedWorkspace = workspaceMap.get(selectedWorkspaceLabel);
114118
if (!selectedWorkspace) {
115119
throw new Error("Failed to find selected workspace");
116120
}
117121

122+
const workspaceSlug = selectedWorkspace.slug;
123+
118124
const projectsResponse = await this.fetchResource<ProjectTeam>(`/v1/workspace/${workspaceSlug}/project`);
119125

120126
const allProjects: Project[] = [];
@@ -130,18 +136,24 @@ export class EnkryptifyProvider implements Provider {
130136
);
131137
}
132138

133-
const projectSlug = await selectName(
134-
allProjects.map((p) => p.slug),
135-
"Select project",
136-
);
139+
const projectMap = new Map<string, Project>();
140+
const projectLabels = allProjects.map((p) => {
141+
const label = `${p.name} (${p.slug})`;
142+
projectMap.set(label, p);
143+
return label;
144+
});
137145

138-
if (!projectSlug) throw new Error("Failed to select project");
146+
const selectedProjectLabel = await selectName(projectLabels, "Select project");
139147

140-
const selectedProject = allProjects.find((p) => p.slug === projectSlug);
148+
if (!selectedProjectLabel) throw new Error("Failed to select project");
149+
150+
const selectedProject = projectMap.get(selectedProjectLabel);
141151
if (!selectedProject) {
142152
throw new Error("Failed to find selected project");
143153
}
144154

155+
const projectSlug = selectedProject.slug;
156+
145157
const environments = await this.fetchResource<Environment>(
146158
`/v1/workspace/${workspaceSlug}/project/${projectSlug}/environment`,
147159
);

src/ui/Confirm.tsx

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,27 @@ import SelectInput from "ink-select-input";
33

44
export async function confirm(message: string): Promise<boolean> {
55
const items = [
6-
{ label: "Yes", value: "yes" },
7-
{ label: "No", value: "no" },
6+
{ label: "Yes", value: true },
7+
{ label: "No", value: false },
88
];
99

1010
return new Promise((resolve) => {
11-
const confirm = render(
11+
const app = render(
1212
<Box flexDirection="column">
13-
{message && (
13+
{message ? (
1414
<Box marginBottom={1}>
1515
<Text bold>{message}</Text>
1616
</Box>
17-
)}
18-
<Box flexDirection="column">
19-
<SelectInput
20-
items={items}
21-
onSelect={(item) => {
22-
confirm.unmount();
23-
process.stdout.write("\x1b[2J\x1b[H");
24-
resolve(item.value === "yes");
25-
}}
26-
/>
27-
</Box>
17+
) : null}
18+
19+
<SelectInput
20+
items={items}
21+
onSelect={(item) => {
22+
app.clear();
23+
app.unmount();
24+
resolve(item.value);
25+
}}
26+
/>
2827
</Box>,
2928
);
3029
});

src/ui/RunFlow.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import ansiEscapes from "ansi-escapes";
12
import { Box, Text, render } from "ink";
23
import Spinner from "ink-spinner";
34

@@ -24,18 +25,22 @@ export async function RunFlow({ envName, run }: RunFlowProps): Promise<void> {
2425
stdout: process.stderr,
2526
});
2627

27-
const unmountSpinner = () => spinner.unmount();
28+
let done = false;
2829

29-
try {
30-
await run(unmountSpinner);
30+
const unmountSpinner = () => {
31+
if (done) return;
32+
done = true;
33+
34+
spinner.unmount();
3135

32-
const successMessage = envName
33-
? `Secrets injected successfully for environment "${envName}".\n`
34-
: "Secrets injected successfully.\n";
36+
process.stderr.write(ansiEscapes.eraseLines(1));
37+
};
3538

36-
process.stderr.write(successMessage);
39+
try {
40+
await run(unmountSpinner);
41+
unmountSpinner();
3742
} catch (error) {
38-
spinner.unmount();
43+
unmountSpinner();
3944
throw error;
4045
}
4146
}

src/ui/SelectItem.tsx

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,31 @@ import { Box, Text, render } from "ink";
22
import SelectInput from "ink-select-input";
33

44
export async function selectName(options: string[], title?: string): Promise<string> {
5-
if (!options.length) {
6-
throw new Error("options array cannot be empty");
7-
}
5+
if (!options.length) throw new Error("options array cannot be empty");
6+
87
const items = options.map((name, index) => ({
98
label: name,
109
value: name,
1110
key: `${name}-${index}`,
1211
}));
12+
1313
return new Promise((resolve) => {
14-
const select = render(
15-
<Box flexDirection="column" padding={1}>
16-
{title && (
14+
const app = render(
15+
<Box flexDirection="column">
16+
{title ? (
1717
<Box marginBottom={1}>
1818
<Text bold>{title}</Text>
1919
</Box>
20-
)}
21-
<Box flexDirection="column">
22-
<SelectInput
23-
items={items}
24-
onSelect={(item) => {
25-
select.unmount();
26-
process.stdout.write("\x1b[2J\x1b[H");
27-
resolve(item.value as string);
28-
}}
29-
/>
30-
</Box>
20+
) : null}
21+
22+
<SelectInput
23+
items={items}
24+
onSelect={(item) => {
25+
app.clear();
26+
app.unmount();
27+
resolve(item.value);
28+
}}
29+
/>
3130
</Box>,
3231
);
3332
});

0 commit comments

Comments
 (0)