UNPKG

codestate-cli

Version:

CodeState CLI - Configuration, Script, and Git Management

1,377 lines (1,337 loc) 106 kB
#!/usr/bin/env node "use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // packages/cli-interface/cli.ts var import_core36 = require("codestate-core"); // packages/cli-interface/commands/index.ts var import_core35 = require("codestate-core"); // packages/cli-interface/commands/config/showConfig.ts var import_core = require("codestate-core"); async function showConfigCommand() { const logger2 = new import_core.ConfigurableLogger(); const getConfig = new import_core.GetConfig(); const result = await getConfig.execute(); if (result.ok) { const config = result.value; logger2.plainLog("\n\u{1F4CB} Current Configuration:"); logger2.plainLog("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"); logger2.plainLog(`Editor: ${config.ide}`); logger2.plainLog(`Version: ${config.version}`); logger2.plainLog(`Encryption: ${config.encryption.enabled ? "Yes" : "No"}`); logger2.plainLog(`Storage Path: ${config.storagePath}`); logger2.plainLog(`Log Level: ${config.logger.level}`); logger2.plainLog(`Log Sinks: ${config.logger.sinks.join(", ")}`); if (config.experimental && Object.keys(config.experimental).length > 0) { logger2.plainLog("\n\u{1F52C} Experimental Features:"); Object.entries(config.experimental).forEach(([key, value]) => { logger2.plainLog(` ${key}: ${value ? "\u2705" : "\u274C"}`); }); } if (config.extensions && Object.keys(config.extensions).length > 0) { logger2.plainLog("\n\u{1F50C} Extensions:"); Object.keys(config.extensions).forEach((key) => { logger2.plainLog(` ${key}`); }); } logger2.plainLog(""); } else { logger2.error("Failed to load config", { error: result.error }); } } // packages/cli-interface/tui/config/showConfigTui.ts async function showConfigTui() { await showConfigCommand(); } // packages/cli-interface/utils/inquirer.ts var import_core2 = require("codestate-core"); var import_inquirer = __toESM(require("inquirer")); var inquirer = { ...import_inquirer.default, customPrompt: async function(questions) { try { return await import_inquirer.default.prompt(questions); } catch (error) { if (error.message?.includes("SIGINT") || error.message?.includes("force closed")) { const logger2 = new import_core2.ConfigurableLogger(); logger2.plainLog("\n\u{1F44B} You have exited CodeState CLI"); process.exit(0); } throw error; } } }; var inquirer_default = inquirer; // packages/cli-interface/commands/config/updateConfig.ts var import_core3 = require("codestate-core"); async function updateConfigCommand(partial) { const logger2 = new import_core3.ConfigurableLogger(); const updateConfig = new import_core3.UpdateConfig(); const result = await updateConfig.execute(partial); if (result.ok) { const config = result.value; logger2.log("Configuration updated successfully!"); logger2.plainLog("\n\u{1F4CB} Current Configuration:"); logger2.plainLog("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"); logger2.plainLog(`Editor: ${config.ide}`); logger2.plainLog(`Version: ${config.version}`); logger2.plainLog(`Encryption: ${config.encryption.enabled ? "Yes" : "No"}`); logger2.plainLog(`Storage Path: ${config.storagePath}`); logger2.plainLog(`Log Level: ${config.logger.level}`); logger2.plainLog(`Log Sinks: ${config.logger.sinks.join(", ")}`); if (config.experimental && Object.keys(config.experimental).length > 0) { logger2.plainLog("\n\u{1F52C} Experimental Features:"); Object.entries(config.experimental).forEach(([key, value]) => { logger2.plainLog(` ${key}: ${value ? "\u2705" : "\u274C"}`); }); } if (config.extensions && Object.keys(config.extensions).length > 0) { logger2.plainLog("\n\u{1F50C} Extensions:"); Object.keys(config.extensions).forEach((key) => { logger2.plainLog(` ${key}`); }); } logger2.plainLog(""); } else { logger2.error("Failed to update config", { error: result.error }); } } // packages/cli-interface/tui/config/updateConfigTui.ts async function updateConfigTui() { const answers = await inquirer_default.customPrompt([ { name: "ide", message: "Default IDE:", type: "list", choices: ["cursor", "vscode"] }, { name: "encryption", message: "Enable encryption?", type: "confirm" } ]); let encryptionKey = void 0; if (answers.encryption) { const keyAnswer = await inquirer_default.customPrompt([ { name: "encryptionKey", message: "Encryption key:", type: "password", mask: "*" } ]); encryptionKey = keyAnswer.encryptionKey; } const partial = { ide: answers.ide, encryption: { enabled: answers.encryption, encryptionKey } }; await updateConfigCommand(partial); } // packages/cli-interface/commands/config/resetConfig.ts var import_core4 = require("codestate-core"); async function resetConfigCommand() { const logger2 = new import_core4.ConfigurableLogger(); const resetConfig = new import_core4.ResetConfig(); const result = await resetConfig.execute(); if (result.ok) { logger2.log("Config reset to defaults:", { config: result.value }); } else { logger2.error("Failed to reset config", { error: result.error }); } } // packages/cli-interface/tui/config/resetConfigTui.ts async function resetConfigTui() { const { confirm } = await inquirer_default.customPrompt([ { name: "confirm", message: "Are you sure you want to reset config to defaults?", type: "confirm" } ]); if (confirm) { await resetConfigCommand(); } } // packages/cli-interface/tui/config/exportConfigTui.ts var import_core6 = require("codestate-core"); var fs = __toESM(require("fs/promises")); // packages/cli-interface/commands/config/exportConfig.ts var import_core5 = require("codestate-core"); async function exportConfigCommand() { const logger2 = new import_core5.ConfigurableLogger(); const exportConfig = new import_core5.ExportConfig(); const result = await exportConfig.execute(); if (result.ok) { logger2.log("Exported config:", { config: result.value }); } else { logger2.error("Failed to export config", { error: result.error }); } } // packages/cli-interface/tui/config/exportConfigTui.ts async function exportConfigTui() { const logger2 = new import_core6.ConfigurableLogger(); const { filePath } = await inquirer_default.customPrompt([ { name: "filePath", message: "Export to file (leave blank to print to console):", type: "input" } ]); let output = ""; const originalLog = logger2.log; logger2.log = (msg, meta) => { if (typeof msg === "string" && msg.startsWith("Exported config:")) { output = meta?.config || ""; } else { originalLog(msg, meta); } }; await exportConfigCommand(); logger2.log = originalLog; if (filePath && output) { await fs.writeFile(filePath, output, "utf8"); logger2.plainLog(`Config exported to ${filePath}`); } else if (output) { logger2.plainLog(output); } } // packages/cli-interface/commands/config/importConfig.ts var import_core7 = require("codestate-core"); async function importConfigCommand(json) { const logger2 = new import_core7.ConfigurableLogger(); const importConfig = new import_core7.ImportConfig(); const result = await importConfig.execute(json); if (result.ok) { logger2.log("Config imported:", { config: result.value }); } else { logger2.error("Failed to import config", { error: result.error }); } } // packages/cli-interface/tui/config/importConfigTui.ts var fs2 = __toESM(require("fs/promises")); async function importConfigTui() { const { importType } = await inquirer_default.customPrompt([ { name: "importType", message: "Import from:", type: "list", choices: ["File", "Paste JSON"] } ]); let json = ""; if (importType === "File") { const { filePath } = await inquirer_default.customPrompt([ { name: "filePath", message: "Path to config file:", type: "input" } ]); json = await fs2.readFile(filePath, "utf8"); } else { const { jsonString } = await inquirer_default.customPrompt([ { name: "jsonString", message: "Paste config JSON:", type: "editor" } ]); json = jsonString; } await importConfigCommand(json); } // packages/cli-interface/tui/config/cliHandler.ts var import_core8 = require("codestate-core"); async function handleConfigCommand(subcommand, options) { const logger2 = new import_core8.ConfigurableLogger(); switch (subcommand) { case "show": await showConfigTui(); break; case "edit": await updateConfigTui(); break; case "reset": await resetConfigTui(); break; case "export": await exportConfigTui(); break; case "import": const fileIndex = options.indexOf("--file"); if (fileIndex === -1 || fileIndex === options.length - 1) { logger2.error("Error: --file option is required for import command"); logger2.plainLog("Usage: codestate config import --file <path>"); process.exit(1); } const filePath = options[fileIndex + 1]; await importConfigTui(); break; default: logger2.error(`Error: Unknown config subcommand '${subcommand}'`); logger2.plainLog( "Available config subcommands: show, edit, reset, export, import" ); process.exit(1); } } // packages/cli-interface/commands/scripts/showScripts.ts var import_core9 = require("codestate-core"); async function showScriptsCommand() { const logger2 = new import_core9.ConfigurableLogger(); const getScripts = new import_core9.GetScripts(); const result = await getScripts.execute(); if (result.ok) { const scripts = result.value; if (scripts.length === 0) { logger2.plainLog("\n\u{1F4DD} No scripts found."); logger2.plainLog( "Use `codestate scripts create` to add your first script.\n" ); return; } const scriptsByPath = /* @__PURE__ */ new Map(); scripts.forEach((script) => { if (!scriptsByPath.has(script.rootPath)) { scriptsByPath.set(script.rootPath, []); } scriptsByPath.get(script.rootPath).push(script); }); logger2.plainLog("\n\u{1F4DD} Scripts by Project Path:"); logger2.plainLog("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"); scriptsByPath.forEach((pathScripts, rootPath) => { logger2.plainLog( ` \u{1F4C1} ${rootPath} (${pathScripts.length} script${pathScripts.length > 1 ? "s" : ""})` ); logger2.plainLog("\u2500".repeat(rootPath.length + 10)); pathScripts.forEach((script) => { const executionMode = script.executionMode || "same-terminal"; const modeIcon = executionMode === "new-terminals" ? "\u{1F4F1}" : "\u{1F5A5}\uFE0F"; const modeText = executionMode === "new-terminals" ? "new terminal" : "same terminal"; let closeInfo = ""; if (executionMode === "new-terminals") { const closeAfterExecution = script.closeTerminalAfterExecution || false; closeInfo = closeAfterExecution ? " (auto-close)" : " (keep open)"; } if (script.script) { logger2.plainLog(` \u2022 ${script.name} - ${script.script} ${modeIcon} (${modeText}${closeInfo})`); } else if (script.commands && script.commands.length > 0) { logger2.plainLog(` \u2022 ${script.name} ${modeIcon} (${modeText}${closeInfo}):`); script.commands.sort((a, b) => a.priority - b.priority).forEach((cmd) => { logger2.plainLog(` ${cmd.priority}. ${cmd.name} - ${cmd.command}`); }); } else { logger2.plainLog(` \u2022 ${script.name} - (no commands)`); } }); }); logger2.plainLog(""); } else { logger2.error("Failed to load scripts", { error: result.error }); } } // packages/cli-interface/tui/scripts/showScriptsTui.ts async function showScriptsTui() { await showScriptsCommand(); } // packages/cli-interface/commands/scripts/createScript.ts var import_core10 = require("codestate-core"); async function createScriptCommand(scripts) { const logger2 = new import_core10.ConfigurableLogger(); const createScripts = new import_core10.CreateScripts(); const scriptsArray = Array.isArray(scripts) ? scripts : [scripts]; const result = await createScripts.execute(scriptsArray); if (result.ok) { const scriptNames = scriptsArray.map((s) => s.name).join(", "); if (scriptsArray.length === 1) { logger2.log(`Script '${scriptNames}' created successfully`); } else { logger2.log(`Scripts created successfully: ${scriptNames}`); } } else { logger2.error("Failed to create scripts", { error: result.error, count: scriptsArray.length }); } } // packages/cli-interface/tui/scripts/createScriptTui.ts var import_crypto = require("crypto"); async function createScriptTui() { await createScriptsInteractively(); } async function createScriptsInteractively() { const scripts = []; let continueAdding = true; const currentPath = process.cwd(); while (continueAdding) { const answers = await inquirer_default.customPrompt([ { name: "name", message: `Script name (${scripts.length + 1}):`, type: "input", validate: (input) => input.trim() ? true : "Script name is required" }, { name: "rootPath", message: `Root path (current: ${currentPath}):`, type: "input", default: currentPath, validate: (input) => input.trim() ? true : "Root path is required" }, { name: "scriptType", message: "Script type:", type: "list", choices: [ { name: "Single command (legacy)", value: "single" }, { name: "Multiple commands with priority", value: "multiple" } ], default: "single" } ]); if (answers.scriptType === "single") { const scriptAnswer = await inquirer_default.customPrompt([ { name: "script", message: "Script command:", type: "input", validate: (input) => input.trim() ? true : "Script command is required" } ]); const executionModeAnswer = await inquirer_default.customPrompt([ { name: "executionMode", message: "How should this command be executed?", type: "list", choices: [ { name: "Same terminal (run in current terminal)", value: "same-terminal" }, { name: "New terminal (open new terminal window and run)", value: "new-terminals" } ], default: "same-terminal" } ]); let closeTerminalAfterExecution = false; if (executionModeAnswer.executionMode === "new-terminals") { const closeAnswer = await inquirer_default.customPrompt([ { name: "closeTerminalAfterExecution", message: "Should the terminal close after running the command?", type: "list", choices: [ { name: "Keep terminal open (useful for debugging, manual follow-up)", value: false }, { name: "Close terminal automatically (clean exit)", value: true } ], default: false } ]); closeTerminalAfterExecution = closeAnswer.closeTerminalAfterExecution; } scripts.push({ id: (0, import_crypto.randomUUID)(), name: answers.name.trim(), rootPath: answers.rootPath.trim(), script: scriptAnswer.script.trim(), executionMode: executionModeAnswer.executionMode, closeTerminalAfterExecution }); } else { const commands = []; let continueAddingCommands = true; let commandPriority = 1; while (continueAddingCommands) { const commandAnswers = await inquirer_default.customPrompt([ { name: "commandName", message: `Command name (${commandPriority}):`, type: "input", validate: (input) => input.trim() ? true : "Command name is required" }, { name: "command", message: `Command (${commandPriority}):`, type: "input", validate: (input) => input.trim() ? true : "Command is required" }, { name: "addAnotherCommand", message: "Add another command?", type: "confirm", default: true } ]); commands.push({ name: commandAnswers.commandName.trim(), command: commandAnswers.command.trim(), priority: commandPriority }); commandPriority++; continueAddingCommands = commandAnswers.addAnotherCommand; } const executionModeAnswer = await inquirer_default.customPrompt([ { name: "executionMode", message: "How should these commands be executed?", type: "list", choices: [ { name: "Same terminal (run all commands in sequence)", value: "same-terminal" }, { name: "New terminal (open new terminal window and run all commands in sequence)", value: "new-terminals" } ], default: "same-terminal" } ]); let closeTerminalAfterExecution = false; if (executionModeAnswer.executionMode === "new-terminals") { const closeAnswer = await inquirer_default.customPrompt([ { name: "closeTerminalAfterExecution", message: "Should the terminal close after running all commands?", type: "list", choices: [ { name: "Keep terminal open (useful for debugging, manual follow-up)", value: false }, { name: "Close terminal automatically (clean exit)", value: true } ], default: false } ]); closeTerminalAfterExecution = closeAnswer.closeTerminalAfterExecution; } scripts.push({ id: (0, import_crypto.randomUUID)(), name: answers.name.trim(), rootPath: answers.rootPath.trim(), commands, executionMode: executionModeAnswer.executionMode, closeTerminalAfterExecution }); } const addAnotherAnswer = await inquirer_default.customPrompt([ { name: "addAnother", message: "Add another script?", type: "confirm", default: true } ]); continueAdding = addAnotherAnswer.addAnother; } if (scripts.length > 0) { await createScriptCommand(scripts); } } // packages/cli-interface/commands/scripts/updateScript.ts var import_core11 = require("codestate-core"); async function updateScriptCommand(name, rootPath, scriptUpdate) { const logger2 = new import_core11.ConfigurableLogger(); const updateScript = new import_core11.UpdateScript(); const result = await updateScript.execute(name, rootPath, scriptUpdate); if (result.ok) { const updatedFields = Object.keys(scriptUpdate).join(", "); logger2.log(`Script '${name}' updated successfully (${updatedFields})`); } else { logger2.error(`Failed to update script '${name}'`, { error: result.error }); } } // packages/cli-interface/tui/scripts/updateScriptTui.ts async function updateScriptTui() { const currentPath = process.cwd(); const answers = await inquirer_default.customPrompt([ { name: "name", message: "Script name to update:", type: "input", validate: (input) => input.trim() ? true : "Script name is required" }, { name: "rootPath", message: `Root path (current: ${currentPath}):`, type: "input", default: currentPath, validate: (input) => input.trim() ? true : "Root path is required" }, { name: "newName", message: "New script name (leave empty to keep current):", type: "input" }, { name: "updateType", message: "What would you like to update?", type: "list", choices: [ { name: "Single command (legacy)", value: "single" }, { name: "Multiple commands with priority", value: "multiple" } ], default: "single" } ]); const scriptUpdate = {}; if (answers.newName.trim()) { scriptUpdate.name = answers.newName.trim(); } if (answers.updateType === "single") { const scriptAnswer = await inquirer_default.customPrompt([ { name: "newScript", message: "New script command (leave empty to keep current):", type: "input" } ]); if (scriptAnswer.newScript.trim()) { scriptUpdate.script = scriptAnswer.newScript.trim(); } const executionModeAnswer = await inquirer_default.customPrompt([ { name: "executionMode", message: "How should this command be executed?", type: "list", choices: [ { name: "Same terminal (run in current terminal)", value: "same-terminal" }, { name: "New terminal (open new terminal window and run)", value: "new-terminals" } ], default: "same-terminal" } ]); scriptUpdate.executionMode = executionModeAnswer.executionMode; if (executionModeAnswer.executionMode === "new-terminals") { const closeAnswer = await inquirer_default.customPrompt([ { name: "closeTerminalAfterExecution", message: "Should the terminal close after running the command?", type: "list", choices: [ { name: "Keep terminal open (useful for debugging, manual follow-up)", value: false }, { name: "Close terminal automatically (clean exit)", value: true } ], default: false } ]); scriptUpdate.closeTerminalAfterExecution = closeAnswer.closeTerminalAfterExecution; } } else { const commands = []; let continueAddingCommands = true; let commandPriority = 1; while (continueAddingCommands) { const commandAnswers = await inquirer_default.customPrompt([ { name: "commandName", message: `Command name (${commandPriority}):`, type: "input", validate: (input) => input.trim() ? true : "Command name is required" }, { name: "command", message: `Command (${commandPriority}):`, type: "input", validate: (input) => input.trim() ? true : "Command is required" }, { name: "addAnotherCommand", message: "Add another command?", type: "confirm", default: true } ]); commands.push({ name: commandAnswers.commandName.trim(), command: commandAnswers.command.trim(), priority: commandPriority }); commandPriority++; continueAddingCommands = commandAnswers.addAnotherCommand; } if (commands.length > 0) { scriptUpdate.commands = commands; } const executionModeAnswer = await inquirer_default.customPrompt([ { name: "executionMode", message: "How should these commands be executed?", type: "list", choices: [ { name: "Same terminal (run all commands in sequence)", value: "same-terminal" }, { name: "New terminal (open new terminal window and run all commands in sequence)", value: "new-terminals" } ], default: "same-terminal" } ]); scriptUpdate.executionMode = executionModeAnswer.executionMode; if (executionModeAnswer.executionMode === "new-terminals") { const closeAnswer = await inquirer_default.customPrompt([ { name: "closeTerminalAfterExecution", message: "Should the terminal close after running all commands?", type: "list", choices: [ { name: "Keep terminal open (useful for debugging, manual follow-up)", value: false }, { name: "Close terminal automatically (clean exit)", value: true } ], default: false } ]); scriptUpdate.closeTerminalAfterExecution = closeAnswer.closeTerminalAfterExecution; } } await updateScriptCommand( answers.name.trim(), answers.rootPath.trim(), scriptUpdate ); } // packages/cli-interface/tui/scripts/deleteScriptTui.ts var import_core13 = require("codestate-core"); // packages/cli-interface/commands/scripts/deleteScript.ts var import_core12 = require("codestate-core"); async function deleteScriptCommand(name, rootPath) { const logger2 = new import_core12.ConfigurableLogger(); const deleteScript = new import_core12.DeleteScript(); const result = await deleteScript.execute(name, rootPath); if (result.ok) { logger2.log(`Script '${name}' deleted successfully`); } else { logger2.error(`Failed to delete script '${name}'`, { error: result.error }); } } // packages/cli-interface/tui/scripts/deleteScriptTui.ts async function deleteScriptTui() { const logger2 = new import_core13.ConfigurableLogger(); const currentPath = process.cwd(); const answers = await inquirer_default.customPrompt([ { name: "name", message: "Script name to delete:", type: "input", validate: (input) => input.trim() ? true : "Script name is required" }, { name: "rootPath", message: `Root path (current: ${currentPath}):`, type: "input", default: currentPath, validate: (input) => input.trim() ? true : "Root path is required" }, { name: "confirm", message: "Are you sure you want to delete this script?", type: "confirm", default: false } ]); if (answers.confirm) { await deleteScriptCommand(answers.name.trim(), answers.rootPath.trim()); } else { logger2.plainLog("Script deletion cancelled."); } } // packages/cli-interface/tui/scripts/deleteScriptsByRootPathTui.ts var import_core15 = require("codestate-core"); // packages/cli-interface/commands/scripts/deleteScriptsByRootPath.ts var import_core14 = require("codestate-core"); async function deleteScriptsByRootPathCommand(rootPath) { const logger2 = new import_core14.ConfigurableLogger(); const deleteScriptsByRootPath = new import_core14.DeleteScriptsByRootPath(); const result = await deleteScriptsByRootPath.execute(rootPath); if (result.ok) { logger2.log("Scripts deleted for root path successfully", { rootPath }); } else { logger2.error("Failed to delete scripts for root path", { error: result.error, rootPath }); } } // packages/cli-interface/tui/scripts/deleteScriptsByRootPathTui.ts async function deleteScriptsByRootPathTui() { const logger2 = new import_core15.ConfigurableLogger(); const currentPath = process.cwd(); const answers = await inquirer_default.customPrompt([ { name: "rootPath", message: `Root path to delete all scripts from (current: ${currentPath}):`, type: "input", default: currentPath, validate: (input) => input.trim() ? true : "Root path is required" }, { name: "confirm", message: "Are you sure you want to delete ALL scripts for this root path?", type: "confirm", default: false } ]); if (answers.confirm) { await deleteScriptsByRootPathCommand(answers.rootPath.trim()); } else { logger2.plainLog("Script deletion cancelled."); } } // packages/cli-interface/commands/scripts/exportScripts.ts var import_core16 = require("codestate-core"); async function exportScriptsCommand() { const logger2 = new import_core16.ConfigurableLogger(); const exportScripts = new import_core16.ExportScripts(); const result = await exportScripts.execute(); if (result.ok) { logger2.log("Scripts exported successfully:", { scripts: result.value }); } else { logger2.error("Failed to export scripts", { error: result.error }); } } // packages/cli-interface/tui/scripts/exportScriptsTui.ts async function exportScriptsTui() { await exportScriptsCommand(); } // packages/cli-interface/commands/scripts/importScripts.ts var import_core17 = require("codestate-core"); async function importScriptsCommand(json) { const logger2 = new import_core17.ConfigurableLogger(); const importScripts = new import_core17.ImportScripts(); const result = await importScripts.execute(json); if (result.ok) { logger2.log("Scripts imported successfully"); } else { logger2.error("Failed to import scripts", { error: result.error }); } } // packages/cli-interface/tui/scripts/importScriptsTui.ts var fs3 = __toESM(require("fs/promises")); async function importScriptsTui() { const { importType } = await inquirer_default.customPrompt([ { name: "importType", message: "Import from:", type: "list", choices: ["File", "Paste JSON"] } ]); let json = ""; if (importType === "File") { const { filePath } = await inquirer_default.customPrompt([ { name: "filePath", message: "Path to scripts file:", type: "input" } ]); json = await fs3.readFile(filePath, "utf8"); } else { const { jsonString } = await inquirer_default.customPrompt([ { name: "jsonString", message: "Paste scripts JSON:", type: "editor" } ]); json = jsonString; } await importScriptsCommand(json); } // packages/cli-interface/tui/scripts/cliHandler.ts var import_core20 = require("codestate-core"); // packages/cli-interface/commands/scripts/showScriptsByRootPath.ts var import_core18 = require("codestate-core"); async function showScriptsByRootPathCommand(rootPath) { const logger2 = new import_core18.ConfigurableLogger(); const getScriptsByRootPath = new import_core18.GetScriptsByRootPath(); const result = await getScriptsByRootPath.execute(rootPath); if (result.ok) { const scripts = result.value; if (scripts.length === 0) { logger2.plainLog(` \u{1F4DD} No scripts found for ${rootPath}.`); return; } logger2.plainLog(` \u{1F4DD} Scripts for ${rootPath}:`); logger2.plainLog("\u2500".repeat(rootPath.length + 15)); scripts.forEach((script) => { if (script.script) { logger2.plainLog(` \u2022 ${script.name} - ${script.script}`); } else if (script.commands && script.commands.length > 0) { logger2.plainLog(` \u2022 ${script.name}:`); script.commands.sort((a, b) => a.priority - b.priority).forEach((cmd) => { logger2.plainLog(` ${cmd.priority}. ${cmd.name} - ${cmd.command}`); }); } else { logger2.plainLog(` \u2022 ${script.name} - (no commands)`); } }); logger2.plainLog(""); } else { logger2.error("Failed to load scripts for root path", { error: result.error, rootPath }); } } // packages/cli-interface/commands/scripts/resumeScript.ts var import_core19 = require("codestate-core"); async function resumeScriptCommand(scriptName, rootPath) { const logger2 = new import_core19.ConfigurableLogger(); const getScriptsByRootPath = new import_core19.GetScriptsByRootPath(); const terminal = new import_core19.Terminal(); try { let targetScriptName = scriptName; let targetRootPath = rootPath || process.cwd(); if (!targetScriptName) { const scriptsResult2 = await getScriptsByRootPath.execute(targetRootPath); if (!scriptsResult2.ok || scriptsResult2.value.length === 0) { logger2.warn("No scripts found for the current directory."); return; } const scripts = scriptsResult2.value; const { selectedScript } = await inquirer_default.customPrompt([ { type: "list", name: "selectedScript", message: "Select a script to resume:", choices: scripts.map((s) => ({ name: `${s.name} - ${s.script || "Multi-command script"}`, value: s.name })) } ]); targetScriptName = selectedScript || ""; } if (!targetScriptName || !targetScriptName.trim()) { logger2.plainLog("No script specified. Resume cancelled."); return; } const scriptsResult = await getScriptsByRootPath.execute(targetRootPath); if (!scriptsResult.ok) { logger2.error("Failed to get scripts", { error: scriptsResult.error }); return; } const targetScript = scriptsResult.value.find((s) => s.name === targetScriptName); if (!targetScript) { logger2.error(`Script '${targetScriptName}' not found in ${targetRootPath}`); return; } logger2.plainLog(`\u{1F4DC} Resuming script: "${targetScript.name}"`); const executionMode = targetScript.executionMode || "same-terminal"; if (targetScript.script) { if (executionMode === "new-terminals") { const closeAfterExecution = targetScript.closeTerminalAfterExecution || false; let finalCommand = targetScript.script; if (closeAfterExecution) { finalCommand = `${targetScript.script} && echo "Script execution completed. Closing terminal..." && sleep 2 && exit`; } else { finalCommand = `${targetScript.script} && echo 'Script execution completed. Terminal will remain open.'`; } const spawnResult = await terminal.spawnTerminal(finalCommand, { cwd: targetRootPath, timeout: 5e3 }); if (spawnResult.ok) { logger2.plainLog(`\u2705 Script executed in new terminal`); } else { logger2.error(`\u274C Failed to spawn terminal`, { error: spawnResult.error }); } } else { const scriptResult = await terminal.execute(targetScript.script, { cwd: targetRootPath, timeout: 3e4 }); if (scriptResult.ok && scriptResult.value.success) { logger2.plainLog(`\u2705 Script completed successfully`); } else { logger2.error(`\u274C Script failed`, { error: scriptResult.ok ? scriptResult.value : scriptResult.error }); } } } else if (targetScript.commands && targetScript.commands.length > 0) { const commands = targetScript.commands.sort((a, b) => a.priority - b.priority); if (executionMode === "new-terminals") { const combinedCommand = commands.sort((a, b) => a.priority - b.priority).map((cmd) => cmd.command).join(" && "); const closeAfterExecution = targetScript.closeTerminalAfterExecution || false; let finalCommand = combinedCommand; if (closeAfterExecution) { finalCommand = `${combinedCommand} && echo "Script execution completed. Closing terminal..." && sleep 2 && exit`; } else { finalCommand = `${combinedCommand} && echo 'Script execution completed. Terminal will remain open.'`; } const spawnResult = await terminal.spawnTerminal(finalCommand, { cwd: targetRootPath, timeout: 5e3 }); if (spawnResult.ok) { logger2.plainLog(`\u2705 Script executed in new terminal`); } else { logger2.error(`\u274C Failed to spawn terminal`, { error: spawnResult.error }); } } else { for (const cmd of commands) { const cmdResult = await terminal.execute(cmd.command, { cwd: targetRootPath, timeout: 3e4 }); if (!cmdResult.ok || !cmdResult.value.success) { logger2.error(`\u274C Command '${cmd.name}' failed`, { error: cmdResult.ok ? cmdResult.value : cmdResult.error }); } if (cmd.priority < commands.length) { await new Promise((resolve) => setTimeout(resolve, 1e3)); } } logger2.plainLog(`\u2705 Script completed successfully`); } } else { logger2.warn(`\u26A0\uFE0F Script has no commands to execute`); } } catch (error) { logger2.error("Unexpected error during script resume", { error }); } } // packages/cli-interface/tui/scripts/resumeScriptTui.ts async function resumeScriptTui() { await resumeScriptCommand(); } // packages/cli-interface/tui/scripts/cliHandler.ts async function handleScriptCommand(subcommand, options) { const logger2 = new import_core20.ConfigurableLogger(); switch (subcommand) { case "show": await showScriptsTui(); break; case "show-by-path": if (options.length === 0) { logger2.error("Error: root path is required for show-by-path command"); logger2.plainLog("Usage: codestate scripts show-by-path <root-path>"); process.exit(1); } await showScriptsByRootPathCommand(options[0]); break; case "create": await createScriptTui(); break; case "update": await updateScriptTui(); break; case "delete": await deleteScriptTui(); break; case "delete-by-path": await deleteScriptsByRootPathTui(); break; case "export": await exportScriptsTui(); break; case "import": await importScriptsTui(); break; case "resume": if (options.length > 0) { await resumeScriptCommand(options[0]); } else { await resumeScriptTui(); } break; default: logger2.error(`Error: Unknown scripts subcommand '${subcommand}'`); logger2.plainLog( "Available scripts subcommands: show, show-by-path, create, update, delete, delete-by-path, export, import, resume" ); process.exit(1); } } // packages/cli-interface/tui/session/cliHandler.ts var import_core26 = require("codestate-core"); // packages/cli-interface/commands/session/saveSession.ts var import_core21 = require("codestate-core"); // packages/cli-interface/commands/session/utils.ts async function promptSessionDetails(defaults) { const prompts = [ { type: "input", name: "sessionName", message: "Enter session name:", default: defaults?.name || "", validate: (input) => { if (!input.trim()) { return "Session name is required"; } return true; } }, { type: "input", name: "sessionNotes", message: "Enter session notes (optional):", default: defaults?.notes || "" }, { type: "input", name: "sessionTags", message: "Enter session tags (comma-separated, optional):", default: defaults?.tags || "" } ]; if (defaults?.terminalCollectionChoices && defaults.terminalCollectionChoices.length > 0) { prompts.push({ type: "checkbox", name: "terminalCollections", message: "Select terminal collections to include in this session:", choices: defaults.terminalCollectionChoices, default: [] }); } if (defaults?.scriptChoices && defaults.scriptChoices.length > 0) { prompts.push({ type: "checkbox", name: "scripts", message: "Select individual scripts to include in this session:", choices: defaults.scriptChoices, default: [] }); } const result = await inquirer_default.customPrompt(prompts); if (!result.terminalCollections) { result.terminalCollections = []; } if (!result.scripts) { result.scripts = []; } return result; } async function promptDirtyState(gitStatus, canStash) { const choices = [{ name: "Commit changes", value: "commit" }]; choices.push({ name: "Cancel", value: "cancel" }); return inquirer_default.customPrompt([ { type: "list", name: "dirtyAction", message: "How would you like to handle these changes?", choices } ]); } async function getCurrentGitState(gitService, logger2) { const currentBranchResult = await gitService.getCurrentBranch(); const currentCommitResult = await gitService.getCurrentCommit(); const isDirtyResult = await gitService.getIsDirty(); if (!currentBranchResult.ok || !currentCommitResult.ok || !isDirtyResult.ok) { logger2.error("Failed to get Git state", { branchError: currentBranchResult.ok ? void 0 : currentBranchResult.error, commitError: currentCommitResult.ok ? void 0 : currentCommitResult.error, isDirtyError: isDirtyResult.ok ? void 0 : isDirtyResult.error }); return null; } return { branch: currentBranchResult.value, commit: currentCommitResult.value, isDirty: isDirtyResult.value, stashId: null // No stash ID for current state }; } async function handleSessionSave({ sessionDetails, projectRoot, git, saveSession, logger: logger2 }) { const result = await saveSession.execute({ name: sessionDetails.sessionName, projectRoot, notes: sessionDetails.sessionNotes || "", tags: sessionDetails.sessionTags.split(",").map((tag) => tag.trim()).filter((tag) => tag.length > 0), files: [], git, extensions: {}, terminalCollections: sessionDetails.terminalCollections || [], scripts: sessionDetails.scripts || [] }); if (result.ok) { logger2.log( `\u2705 Session "${sessionDetails.sessionName}" saved successfully!` ); } else { logger2.error("Failed to save session", { error: result.error }); } return result; } // packages/cli-interface/commands/session/saveSession.ts async function saveSessionCommand() { const logger2 = new import_core21.ConfigurableLogger(); const saveSession = new import_core21.SaveSession(); const gitService = new import_core21.GitService(); try { const isRepoResult = await gitService.isGitRepository(); if (!isRepoResult.ok || !isRepoResult.value) { logger2.warn("Current directory is not a Git repository."); const { continueWithoutGit } = await inquirer_default.customPrompt([ { type: "confirm", name: "continueWithoutGit", message: "Do you want to continue without Git integration?", default: false } ]); if (!continueWithoutGit) { logger2.warn("Session save cancelled."); return; } const listTerminalCollections2 = new import_core21.ListTerminalCollections(); const terminalCollectionsResult2 = await listTerminalCollections2.execute(); const terminalCollectionChoices2 = terminalCollectionsResult2.ok ? terminalCollectionsResult2.value.map((tc) => ({ name: `${tc.name} (${tc.rootPath})`, value: tc.id })) : []; const { GetScripts: GetScripts4 } = await import("codestate-core"); const getScripts2 = new GetScripts4(); const scriptsResult2 = await getScripts2.execute(); const scriptChoices2 = scriptsResult2.ok ? scriptsResult2.value.map((script) => ({ name: `${script.name} (${script.rootPath})`, value: script.id })) : []; const sessionDetails2 = await promptSessionDetails({ terminalCollectionChoices: terminalCollectionChoices2, scriptChoices: scriptChoices2 }); const projectRoot2 = process.cwd(); await handleSessionSave({ sessionDetails: sessionDetails2, projectRoot: projectRoot2, git: { branch: "no-git", commit: "no-git", isDirty: false, stashId: null }, saveSession, logger: logger2 }); return; } const gitStatusResult = await gitService.getStatus(); if (!gitStatusResult.ok) { logger2.error("Failed to get Git status", { error: gitStatusResult.error }); return; } const gitStatus = gitStatusResult.value; if (gitStatus.isDirty) { logger2.warn("\u26A0\uFE0F Repository has uncommitted changes:"); gitStatus.dirtyFiles.forEach((file) => { logger2.plainLog(` ${file.status}: ${file.path}`); }); const hasNewFiles = gitStatus.newFiles.length > 0; const hasDeletedFiles = gitStatus.deletedFiles.length > 0; const hasUntrackedFiles = gitStatus.untrackedFiles.length > 0; const canStash = !hasNewFiles && !hasDeletedFiles && !hasUntrackedFiles; const { dirtyAction } = await promptDirtyState(gitStatus, canStash); if (dirtyAction === "cancel") { logger2.warn("Session save cancelled."); return; } if (dirtyAction === "commit") { const configResult = await gitService.isGitConfigured(); if (!configResult.ok) { logger2.error("Failed to check Git configuration", { error: configResult.error }); logger2.warn("Session save cancelled."); return; } if (!configResult.value) { logger2.error("Git is not properly configured for commits."); logger2.warn("Please configure Git with your name and email:"); logger2.warn(' git config --global user.name "Your Name"'); logger2.warn( ' git config --global user.email "your.email@example.com"' ); const { configureGit } = await inquirer_default.customPrompt([ { type: "confirm", name: "configureGit", message: "Would you like to configure Git now?", default: false } ]); if (configureGit) { const { userName, userEmail } = await inquirer_default.customPrompt([ { type: "input", name: "userName", message: "Enter your name for Git:", validate: (input) => { if (!input.trim()) { return "Name is required"; } return true; } }, { type: "input", name: "userEmail", message: "Enter your email for Git:", validate: (input) => { if (!input.trim()) { return "Email is required"; } return true; } } ]); const terminal = new import_core21.Terminal(); await terminal.execute(`git config user.name "${userName}"`); await terminal.execute(`git config user.email "${userEmail}"`); logger2.plainLog("Git configured successfully."); } else { logger2.warn("Session save cancelled."); return; } } const { commitMessage } = await inquirer_default.customPrompt([ { type: "input", name: "commitMessage", message: "Enter commit message:", validate: (input) => { if (!input.trim()) { return "Commit message is required"; } return true; } } ]); logger2.plainLog(" Committing changes..."); const commitResult = await gitService.commitChanges(commitMessage); if (!commitResult.ok) { logger2.error("Failed to commit changes", { error: commitResult.error, message: commitResult.error.message }); logger2.warn("Git commit failed. This might be due to:"); logger2.warn(" - No changes to commit"); logger2.warn(" - Git configuration issues"); logger2.warn(" - Repository permissions"); logger2.warn( 'Consider using "stash" instead or check your git status.' ); const { retryAction } = await inquirer_default.customPrompt([ { type: "list", name: "retryAction", message: "What would you like to do?", choices: [ { name: "Try stashing instead", value: "stash" }, { name: "Cancel session save", value: "cancel" } ] } ]); if (retryAction === "stash") { logger2.plainLog("Attempting to stash changes..."); const stashResult = await gitService.createStash( "Session save stash" ); if (!stashResult.ok) { logger2.error("Failed to stash changes", { error: stashResult.error }); logger2.warn("Session save cancelled."); return; } logger2.plainLog("Changes stashed successfully."); } else { logger2.warn("Session save cancelled."); return; } } else { logger2.plainLog(" Changes committed successfully."); } } else if (dirtyAction === "stash") { const stashResult = await gitService.createSt