gensx
Version:
`GenSX command line tools.
164 lines • 7.79 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box, Text, useApp } from "ink";
import SelectInput from "ink-select-input";
import TextInput from "ink-text-input";
import { useCallback, useEffect, useState } from "react";
// Core service helpers – replace with real ones
import { createEnvironment, listEnvironments } from "../models/environment.js";
import { checkProjectExists, createProject } from "../models/projects.js";
import { getSelectedEnvironment, validateAndSelectEnvironment, } from "../utils/env-config.js";
import { ErrorMessage } from "./ErrorMessage.js";
import { LoadingSpinner } from "./LoadingSpinner.js";
export const EnvironmentResolver = ({ projectName, specifiedEnvironment, allowCreate = true, yes = false, onResolved, }) => {
const { exit } = useApp();
const [phase, setPhase] = useState("loading");
const [error, setError] = useState(null);
const [environments, setEnvironments] = useState([]);
const [selected, setSelected] = useState(null);
const [newEnvName, setNewEnvName] = useState("");
const [projectExists, setProjectExists] = useState(false);
//-----------------------------------------------------------
// Helpers
//-----------------------------------------------------------
const finish = useCallback((envName) => {
setPhase("done");
onResolved(envName);
}, [onResolved]);
const bootstrap = useCallback(async () => {
try {
// 1. Flag overrides everything
if (specifiedEnvironment) {
finish(specifiedEnvironment);
return;
}
// 2. Fetch project state
const [exists, envs, preselected] = await Promise.all([
checkProjectExists(projectName),
listEnvironments(projectName),
getSelectedEnvironment(projectName),
]);
setProjectExists(exists);
if (!allowCreate && !exists) {
throw new Error(`Project '${projectName}' does not exist.`);
}
// 3. Non‑interactive shortcut
if (yes) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
const envName = preselected ?? envs[0]?.name ?? "default";
// Auto‑create if necessary (but no persistence beyond that)
if (!envs.some((env) => env.name === envName)) {
if (!exists) {
await createProject(projectName, envName);
await validateAndSelectEnvironment(projectName, envName);
}
else {
await createEnvironment(projectName, envName);
}
}
finish(envName);
return;
}
// 4. If there was a pre‑selected env, ask confirmation first
if (preselected) {
setSelected(preselected);
setEnvironments(envs.map((env) => env.name));
setNewEnvName(envs.length === 0 ? "default" : "");
setPhase("auto‑resolved");
return;
}
// 5. Otherwise show list prompt
setEnvironments(envs.map((env) => env.name));
setNewEnvName(envs.length === 0 ? "default" : "");
setPhase("select");
}
catch (err) {
setError(err.message);
setPhase("error");
setTimeout(() => {
exit();
}, 50);
}
}, [specifiedEnvironment, projectName, yes, finish, exit]);
useEffect(() => {
void bootstrap();
}, [bootstrap]);
if (phase === "loading") {
return (_jsx(Box, { children: _jsx(LoadingSpinner, { message: "Resolving environment..." }) }));
}
if (phase === "error" && error) {
return _jsx(ErrorMessage, { message: error });
}
// 1️⃣ Confirm use of pre‑selected environment
if (phase === "auto‑resolved" && selected) {
return (_jsx(ConfirmSelected, { env: selected, onYes: () => {
finish(selected);
}, onNo: () => {
setPhase("select");
} }));
}
// 2️⃣ Select from existing list or create new
if (phase === "select") {
const items = [
...environments.map((name) => ({ label: name, value: name })),
...(allowCreate ? [{ label: "+ create new", value: "__create__" }] : []),
];
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "\u279C" }), " Select an environment for project", " ", _jsx(Text, { color: "cyan", children: projectName }), ":"] }), _jsx(SelectInput, { items: items, onSelect: (item) => {
if (item.value === "__create__") {
setPhase("createPrompt");
}
else {
finish(item.value);
}
} })] }));
}
// 3️⃣ Ask for new env name
if (phase === "createPrompt") {
return (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { color: "blue", children: ["\u279C ", _jsx(Text, { color: "white", children: "Enter a name for the new environment:" }), " ", _jsx(TextInput, { value: newEnvName, onChange: setNewEnvName, onSubmit: (value) => {
const trimmed = value.trim();
if (!trimmed)
return;
setPhase("creating");
void (async () => {
try {
if (!projectExists) {
await createProject(projectName, trimmed);
await validateAndSelectEnvironment(projectName, trimmed);
}
else {
await createEnvironment(projectName, trimmed);
}
finish(trimmed);
}
catch (err) {
setError(err.message);
setPhase("error");
setTimeout(() => {
exit();
}, 50);
}
})();
} })] }) }));
}
if (phase === "creating") {
return (_jsx(Box, { children: _jsx(LoadingSpinner, { message: !projectExists
? `Creating project ${projectName} and environment ${newEnvName}...`
: `Creating environment ${newEnvName}...` }) }));
}
// done – we unmount via onResolved in parent
return null;
};
const ConfirmSelected = ({ env, onYes, onNo }) => {
const items = [
{ label: "Yes", value: "yes" },
{ label: "No", value: "no" },
];
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "\u279C" }), " Use selected environment", " ", _jsx(Text, { color: "green", children: env }), "?"] }), _jsx(SelectInput, { items: items, onSelect: (item) => {
if (item.value === "yes") {
onYes();
}
else {
onNo();
}
} })] }));
};
//# sourceMappingURL=EnvironmentResolver.js.map