gensx
Version:
`GenSX command line tools.
234 lines • 11.9 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 { useEffect, useState } from "react";
import { ErrorMessage } from "../../components/ErrorMessage.js";
import { LoadingSpinner } from "../../components/LoadingSpinner.js";
import { checkProjectExists, createProject } from "../../models/projects.js";
import { getAuth } from "../../utils/config.js";
import { validateAndSelectEnvironment } from "../../utils/env-config.js";
import { readProjectConfig } from "../../utils/project-config.js";
function useCreateProject(initialProjectName, initialDescription, initialEnvironmentName, yes) {
const { exit } = useApp();
const [step, setStep] = useState("initial");
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
const [shouldCreate, setShouldCreate] = useState(null);
const [projectConfig, setProjectConfig] = useState({
projectName: initialProjectName,
description: initialDescription,
environmentName: initialEnvironmentName,
});
const setProjectName = (name) => {
setProjectConfig((prev) => ({ ...prev, projectName: name }));
};
const handleProjectNameSubmit = (value) => {
const trimmed = value.trim();
if (trimmed) {
setProjectName(trimmed);
// After setting project name, prompt for environment name
setStep("prompting_environment_name");
}
else {
setError(new Error("No project name found. Either specify --project or create a gensx.yaml file with a 'projectName' field."));
setStep("error");
setTimeout(() => {
exit();
}, 100);
}
};
const setEnvironmentName = (name) => {
setProjectConfig((prev) => ({ ...prev, environmentName: name }));
};
useEffect(() => {
let mounted = true;
async function initializeProject() {
try {
// Check authentication first
const authConfig = await getAuth();
if (!authConfig) {
throw new Error("Not authenticated. Please run 'gensx login' first.");
}
// Try to read project config from gensx.yaml if not provided via CLI
let configFromFile = null;
if (!initialProjectName || !initialDescription) {
try {
configFromFile = await readProjectConfig(process.cwd());
}
catch {
// No config file or error reading it, that's okay
}
}
if (!mounted)
return;
// Use CLI args first, then config file, then prompt
const resolvedConfig = {
projectName: initialProjectName ?? configFromFile?.projectName,
description: initialDescription ?? configFromFile?.description,
environmentName: initialEnvironmentName,
};
setProjectConfig(resolvedConfig);
// Check what we need to prompt for
if (!resolvedConfig.projectName) {
setStep("prompting_project_name");
setLoading(false);
}
else {
// Check if project already exists
const projectExists = await checkProjectExists(resolvedConfig.projectName);
if (projectExists) {
throw new Error(`Project ${resolvedConfig.projectName} already exists`);
}
// If yes flag is set, skip environment name prompt and go straight to creation
if (yes) {
// Set default environment name only if none provided via CLI
if (!resolvedConfig.environmentName) {
setProjectConfig((prev) => ({
...prev,
environmentName: "default",
}));
}
setStep("confirming_creation");
setShouldCreate(true);
}
else if (resolvedConfig.environmentName) {
// If environment name provided via CLI, skip the prompt but still show confirmation
setStep("confirming_creation");
}
else {
// Only prompt for environment name if not provided via CLI
setStep("prompting_environment_name");
}
setLoading(false);
}
}
catch (err) {
if (!mounted)
return;
const thrownError = err instanceof Error ? err : new Error(String(err));
setError(thrownError);
setStep("error");
setLoading(false);
setTimeout(() => {
exit();
}, 100);
}
}
// Only run initialization once
if (step === "initial") {
void initializeProject();
}
return () => {
mounted = false;
};
}, [
step,
initialProjectName,
initialDescription,
initialEnvironmentName,
yes,
exit,
]);
// Separate useEffect for handling project creation
useEffect(() => {
let mounted = true;
async function handleProjectCreation() {
if (step !== "confirming_creation" || shouldCreate === null)
return;
try {
if (shouldCreate) {
if (!projectConfig.projectName) {
throw new Error("Project name is required");
}
setStep("creating_project");
// Create the project with environment
await createProject(projectConfig.projectName, projectConfig.environmentName, projectConfig.description);
// Set the environment as active
if (projectConfig.environmentName) {
setStep("creating_environment");
const success = await validateAndSelectEnvironment(projectConfig.projectName, projectConfig.environmentName);
if (!success) {
throw new Error("Failed to set environment as active");
}
}
setStep("done");
}
else {
setError(new Error("Project creation cancelled"));
setStep("error");
setTimeout(() => {
exit();
}, 100);
}
}
catch (err) {
if (!mounted)
return;
const thrownError = err instanceof Error ? err : new Error(String(err));
setError(thrownError);
setStep("error");
setTimeout(() => {
exit();
}, 100);
}
}
// Handle project creation confirmation
if (step === "confirming_creation" && shouldCreate !== null) {
void handleProjectCreation();
}
return () => {
mounted = false;
};
}, [step, shouldCreate, projectConfig, exit]);
return {
loading,
error,
step,
projectConfig,
setProjectName,
setEnvironmentName,
setShouldCreate,
setStep,
handleProjectNameSubmit,
};
}
export function CreateProjectUI({ projectName: initialProjectName, description: initialDescription, environmentName: initialEnvironmentName, yes, }) {
const { loading, error, step, projectConfig, setProjectName, setEnvironmentName, setShouldCreate, setStep, handleProjectNameSubmit, } = useCreateProject(initialProjectName, initialDescription, initialEnvironmentName, yes);
if (error) {
return _jsx(ErrorMessage, { message: error.message });
}
if (loading ||
step === "creating_project" ||
step === "creating_environment") {
const message = step === "creating_project"
? "Creating project..."
: step === "creating_environment"
? "Setting up environment..."
: "Loading...";
return _jsx(LoadingSpinner, { message: message });
}
if (step === "prompting_project_name") {
return (_jsx(Box, { flexDirection: "column", children: _jsxs(Text, { color: "blue", children: ["\u279C ", _jsx(Text, { color: "white", children: "Enter project name:" }), " ", _jsx(TextInput, { value: projectConfig.projectName ?? "", onChange: setProjectName, onSubmit: handleProjectNameSubmit })] }) }));
}
if (step === "prompting_environment_name") {
return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [!initialProjectName && (_jsxs(Text, { children: [_jsx(Text, { color: "cyan", children: "\u2139" }), " Using project name from gensx.yaml:", " ", _jsx(Text, { color: "cyan", children: projectConfig.projectName })] })), _jsxs(Text, { color: "blue", children: ["\u279C ", _jsx(Text, { color: "white", children: "Enter initial environment name:" }), " ", _jsx(TextInput, { value: projectConfig.environmentName ?? "default", onChange: setEnvironmentName, onSubmit: (value) => {
const trimmed = value.trim() || "default";
setEnvironmentName(trimmed);
setStep("confirming_creation");
} })] })] }));
}
if (step === "confirming_creation") {
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "gray", children: "─".repeat(40) }), _jsx(Box, { paddingLeft: 1, children: _jsx(Text, { children: _jsx(Text, { color: "white", children: "Project Details" }) }) }), _jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "gray", children: "─".repeat(40) }), _jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { children: ["Project: ", _jsx(Text, { color: "cyan", children: projectConfig.projectName })] }) }), _jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { children: ["Environment:", " ", _jsx(Text, { color: "cyan", children: projectConfig.environmentName })] }) }), _jsx(Text, { color: "gray", children: "─".repeat(40) })] }), _jsxs(Box, { paddingTop: 1, flexDirection: "column", children: [_jsxs(Text, { children: [_jsx(Text, { color: "blue", children: "\u279C" }), " Create this project?"] }), _jsx(SelectInput, { items: [
{ label: "Yes", value: "yes" },
{ label: "No", value: "no" },
], onSelect: (item) => {
setShouldCreate(item.value === "yes");
} })] })] }));
}
if (step === "done") {
return (_jsxs(Box, { flexDirection: "column", gap: 1, children: [_jsxs(Text, { children: [_jsx(Text, { bold: true, color: "green", children: "\u2714" }), " ", "Project ", _jsx(Text, { color: "green", children: projectConfig.projectName }), " created successfully"] }), _jsxs(Text, { children: [_jsx(Text, { bold: true, color: "green", children: "\u2714" }), " ", "Environment ", _jsx(Text, { color: "cyan", children: projectConfig.environmentName }), " ", "created and selected"] })] }));
}
return null;
}
//# sourceMappingURL=create.js.map