UNPKG

@jalasem/dss

Version:

Dev Spaces Switcher (DSS) - Seamlessly manage isolated development environments with separate SSH keys and Git configurations. Enhanced UI with beautiful tables and improved documentation.

666 lines (665 loc) 33.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.onboardUser = exports.inspectSpace = exports.modifySpace = exports.testSpace = exports.removeSpace = exports.switchSpace = exports.listSpaces = exports.addSpace = void 0; const child_process_1 = require("child_process"); const prompts_1 = require("@inquirer/prompts"); const os_1 = __importDefault(require("os")); const fs_extra_1 = __importDefault(require("fs-extra")); const path_1 = __importDefault(require("path")); const sshKeyGen_1 = require("./sshKeyGen"); const _1 = require("."); const ui_1 = require("./ui"); // import { FuzzySpaceSearch } from "./fuzzySearch"; const util_1 = require("util"); const execAsync = (0, util_1.promisify)(require('child_process').exec); const configPath = path_1.default.join(os_1.default.homedir(), ".dss", "spaces", "config.json"); function ensureConfigFileExists() { return __awaiter(this, void 0, void 0, function* () { yield fs_extra_1.default.ensureFile(configPath); const exists = yield fs_extra_1.default.readJson(configPath).catch(() => null); if (!exists) { yield fs_extra_1.default.writeJson(configPath, { spaces: [] }); } }); } function addSpace() { return __awaiter(this, void 0, void 0, function* () { var _a; yield ensureConfigFileExists(); ui_1.UIHelper.printHeader("Create New Development Space"); ui_1.UIHelper.info("Please provide the following information:"); const name = yield (0, prompts_1.input)({ message: "Space name:", validate: (input) => { if (!input.trim()) return "Space name is required!"; if (input.length < 2) return "Space name must be at least 2 characters long"; if (!/^[a-zA-Z0-9\s\-_]+$/.test(input)) return "Space name can only contain letters, numbers, spaces, hyphens, and underscores"; return true; }, }); const email = (_a = (yield (0, prompts_1.input)({ message: "Email address:", validate: (input) => { if (!input.trim()) return "Email is required!"; const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; if (!emailRegex.test(input)) return "Please enter a valid email address"; return true; }, }))) === null || _a === void 0 ? void 0 : _a.trim(); const userName = yield (0, prompts_1.input)({ message: "User name:", validate: (input) => { if (!input.trim()) return "User name is required!"; if (input.length < 2) return "User name must be at least 2 characters long"; return true; }, }); const generateKey = yield (0, prompts_1.confirm)({ message: "Generate a new SSH key for this space?", default: true, }); const config = yield fs_extra_1.default.readJson(configPath); const slugifiedSpaceName = name.toLowerCase().replace(/\s/g, "-"); if (config.spaces.find((space) => space.name === slugifiedSpaceName)) { ui_1.UIHelper.error(`A space with the name "${name}" already exists.`); ui_1.UIHelper.info("Please choose a different name or use " + ui_1.UIHelper.command("dss edit") + " to modify the existing space."); return; } let sshKeyPath = ""; if (generateKey) { ui_1.UIHelper.printProgress("Generating SSH key"); sshKeyPath = yield (0, sshKeyGen_1.generateSSHKey)(slugifiedSpaceName, email); ui_1.UIHelper.clearProgress(); const publicKeyPath = `${sshKeyPath}.pub`; try { const publicKey = yield fs_extra_1.default.readFile(publicKeyPath, "utf8"); yield (0, _1.copyToClipboard)(publicKey); ui_1.UIHelper.success("SSH key generated successfully!"); ui_1.UIHelper.printSuccessBox("SSH Key Ready", [ "✓ Public key copied to clipboard", "✓ Add it to your GitHub account", "", "GitHub SSH Keys: https://github.com/settings/keys" ]); console.log(ui_1.UIHelper.dim("\nPublic SSH Key:")); console.log(ui_1.UIHelper.highlight(publicKey)); } catch (err) { ui_1.UIHelper.error("Failed to read the public SSH key or copy it to the clipboard: " + err.message); } } const newSpace = { name, email, userName, sshKeyPath, }; config.spaces.push(newSpace); yield fs_extra_1.default.writeJson(configPath, config); const switchToNewSpace = yield (0, prompts_1.confirm)({ message: `Do you want to switch to the newly added space "${name}" now?`, default: true, }); if (switchToNewSpace) { ui_1.UIHelper.info("Switching to new space..."); yield switchSpace(name); } else { ui_1.UIHelper.success(`Space "${ui_1.UIHelper.highlight(name)}" added successfully!`); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command(`dss switch ${name}`) + " to activate it."); } }); } exports.addSpace = addSpace; function listSpaces() { return __awaiter(this, void 0, void 0, function* () { yield ensureConfigFileExists(); const config = yield fs_extra_1.default.readJson(configPath); if (config.spaces.length === 0) { ui_1.UIHelper.warning("No spaces have been added yet."); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command("dss add") + " to create your first space."); return; } ui_1.UIHelper.printHeader("Your Development Spaces"); ui_1.UIHelper.printSpaceTable(config.spaces, config.activeSpace); }); } exports.listSpaces = listSpaces; function switchSpace(spaceName, options) { return __awaiter(this, void 0, void 0, function* () { const spaceNameProvided = spaceName ? typeof spaceName === "string" ? spaceName : spaceName.name : null; yield ensureConfigFileExists(); const config = yield fs_extra_1.default.readJson(configPath); if (config.spaces.length === 0) { ui_1.UIHelper.warning("No spaces have been added yet."); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command("dss add") + " to create your first space."); return; } let selectedSpaceName = spaceNameProvided; if (!selectedSpaceName) { ui_1.UIHelper.printHeader("Switch Development Space"); ui_1.UIHelper.printKeyInstruction(); // Use enhanced selection with fuzzy search selectedSpaceName = yield (0, prompts_1.select)({ message: "Choose a space to switch to:", choices: config.spaces.map((space) => ({ name: space.name === config.activeSpace ? ui_1.UIHelper.activeSpace(space.name) : ui_1.UIHelper.inactiveSpace(space.name), value: space.name, description: `${space.email} (${space.userName})` })), }).catch(() => null); } if (!selectedSpaceName) return; const space = config.spaces.find((s) => s.name === selectedSpaceName); if (!space || !space.sshKeyPath) { ui_1.UIHelper.error(`Space "${selectedSpaceName}" not found or does not have an associated SSH key.`); ui_1.UIHelper.info("Available spaces:"); config.spaces.forEach(s => { console.log(` • ${ui_1.UIHelper.highlight(s.name)} (${s.email})`); }); return; } if (config.activeSpace === selectedSpaceName) { ui_1.UIHelper.warning(`Space "${ui_1.UIHelper.highlight(selectedSpaceName)}" is already active.`); return; } // Check for dry-run mode if (options === null || options === void 0 ? void 0 : options.dryRun) { ui_1.UIHelper.printInfoBox("Dry Run: Switch Space Preview", [ `✓ Would switch to: ${space.name}`, `✓ Would set Git user: ${space.userName}`, `✓ Would set Git email: ${space.email}`, `✓ Would activate SSH key: ${space.sshKeyPath}`, `✓ Would update SSH config for GitHub`, `✓ Would save configuration`, '', 'Use without --dry-run to apply changes' ]); return; } try { ui_1.UIHelper.printProgress("Switching to space"); // Set Git configuration (0, child_process_1.execSync)(`git config --global user.name "${space.userName}"`); (0, child_process_1.execSync)(`git config --global user.email "${space.email}"`); ui_1.UIHelper.success(`Git user set to ${ui_1.UIHelper.highlight(space.userName)} <${ui_1.UIHelper.highlight(space.email)}>.`); // Add SSH key to the ssh-agent const addKeyCommand = `ssh-add ${space.sshKeyPath}`; (0, child_process_1.execSync)(addKeyCommand); ui_1.UIHelper.success(`SSH key added to ssh-agent successfully.`); config.activeSpace = space.name; yield (0, _1.setGitHubSSHKey)(space.sshKeyPath); yield fs_extra_1.default.writeJson(configPath, config); ui_1.UIHelper.clearProgress(); ui_1.UIHelper.printSuccessBox("Space Activated", [ `✓ Switched to: ${space.name}`, `✓ Git user: ${space.userName}`, `✓ Email: ${space.email}`, `✓ SSH key: activated` ]); const confirmTest = yield (0, prompts_1.confirm)({ message: "Test GitHub access for this space?", default: false, }); if (confirmTest) { yield (0, _1.testGithubAccess)(space.sshKeyPath); } console.log(""); // Add spacing yield listSpaces(); } catch (error) { ui_1.UIHelper.clearProgress(); ui_1.UIHelper.error(`Failed to switch to space "${selectedSpaceName}": ${error.message}`); } }); } exports.switchSpace = switchSpace; function removeSpace(spaceName, options) { return __awaiter(this, void 0, void 0, function* () { yield ensureConfigFileExists(); const config = yield fs_extra_1.default.readJson(configPath); if (config.spaces.length === 0) { ui_1.UIHelper.warning("No spaces have been added yet."); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command("dss add") + " to create your first space."); return; } ui_1.UIHelper.printHeader("Remove Development Space"); if (!(options === null || options === void 0 ? void 0 : options.dryRun)) { ui_1.UIHelper.warning("This action cannot be undone!"); } let selectedSpaceName = spaceName; if (!selectedSpaceName) { selectedSpaceName = yield (0, prompts_1.select)({ message: "Select a space to remove:", choices: config.spaces.map((space) => ({ name: space.name === config.activeSpace ? ui_1.UIHelper.activeSpace(space.name) + " (active)" : space.name, value: space.name, description: `${space.email} (${space.userName})` })), }); } if (selectedSpaceName === config.activeSpace) { ui_1.UIHelper.error(`Cannot remove the active space '${ui_1.UIHelper.highlight(selectedSpaceName)}'.`); ui_1.UIHelper.info("Please switch to another space first using " + ui_1.UIHelper.command("dss switch") + "."); return; } const spaceToRemove = config.spaces.find((space) => space.name === selectedSpaceName); if (!spaceToRemove) return; // Show details of what will be removed console.log(ui_1.UIHelper.dim("\nSpace to be removed:")); console.log(` Name: ${ui_1.UIHelper.highlight(spaceToRemove.name)}`); console.log(` Email: ${spaceToRemove.email}`); console.log(` User: ${spaceToRemove.userName}`); console.log(` SSH Key: ${ui_1.UIHelper.filename(spaceToRemove.sshKeyPath)}`); // Check for dry-run mode if (options === null || options === void 0 ? void 0 : options.dryRun) { ui_1.UIHelper.printInfoBox("Dry Run: Remove Space Preview", [ `✓ Would remove space: ${spaceToRemove.name}`, `✓ Would remove from configuration`, `✓ Would remove SSH key from agent`, `✓ SSH key files would remain on disk`, '', 'Use without --dry-run to actually remove' ]); return; } const confirmRemoval = yield (0, prompts_1.confirm)({ message: `Are you absolutely sure you want to remove '${selectedSpaceName}'?`, default: false, }); if (!confirmRemoval) { ui_1.UIHelper.info("Removal cancelled."); return; } try { ui_1.UIHelper.printProgress("Removing space"); // Remove SSH key from agent yield (0, _1.removeSSHKeyFromAgent)(spaceToRemove.sshKeyPath); // Remove from config config.spaces = config.spaces.filter((space) => space.name !== selectedSpaceName); yield fs_extra_1.default.writeJson(configPath, config); ui_1.UIHelper.clearProgress(); ui_1.UIHelper.success(`Space '${ui_1.UIHelper.highlight(selectedSpaceName)}' has been removed successfully.`); // Show remaining spaces if (config.spaces.length > 0) { console.log(ui_1.UIHelper.dim("\nRemaining spaces:")); config.spaces.forEach(space => { console.log(` • ${ui_1.UIHelper.highlight(space.name)} (${space.email})`); }); } else { ui_1.UIHelper.info("No spaces remaining. Use " + ui_1.UIHelper.command("dss add") + " to create a new one."); } } catch (error) { ui_1.UIHelper.clearProgress(); ui_1.UIHelper.error(`Failed to remove space: ${error.message}`); } }); } exports.removeSpace = removeSpace; function testSpace(spaceName) { return __awaiter(this, void 0, void 0, function* () { spaceName = spaceName ? typeof spaceName === "string" ? spaceName : spaceName === null || spaceName === void 0 ? void 0 : spaceName.name : null; yield ensureConfigFileExists(); const config = yield fs_extra_1.default.readJson(configPath); if (config.spaces.length === 0) { ui_1.UIHelper.warning("No spaces have been added yet."); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command("dss add") + " to create your first space."); return; } const space = spaceName && config.spaces.find(s => s.name === spaceName) || config.spaces.find(s => s.name === config.activeSpace); if (!space) { ui_1.UIHelper.error(spaceName ? `Space "${spaceName}" not found.` : `Active space "${config.activeSpace}" not found.`); return; } if (!space.sshKeyPath) { ui_1.UIHelper.warning(`Active space "${config.activeSpace}" does not have an associated SSH key.`); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command("dss edit " + space.name) + " to configure SSH keys."); return; } yield (0, _1.testGithubAccess)(space.sshKeyPath); }); } exports.testSpace = testSpace; function modifySpace() { return __awaiter(this, void 0, void 0, function* () { yield ensureConfigFileExists(); const config = yield fs_extra_1.default.readJson(configPath); if (config.spaces.length === 0) { ui_1.UIHelper.warning("No spaces have been added yet."); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command("dss add") + " to create your first space."); return; } const selectedSpace = yield (0, prompts_1.select)({ message: "Which space would you like to modify?", choices: config.spaces.map((space) => ({ name: space.name, value: space.name, })), }); const space = config.spaces.find((space) => space.name === selectedSpace); if (!space) { ui_1.UIHelper.error(`Space "${selectedSpace}" not found.`); return; } const spaceName = yield (0, prompts_1.input)({ message: `New name for "${space.name}" (leave blank to skip):`, default: space.name, }); const email = yield (0, prompts_1.input)({ message: "New email (leave blank to skip):", default: space.email, }); const userName = yield (0, prompts_1.input)({ message: "New user name (leave blank to skip):", default: space.userName, }); let isUpdateMade = false; if (spaceName !== space.name) { if (config.spaces.some((s) => s.name === spaceName)) { ui_1.UIHelper.error(`Another space with the name "${spaceName}" already exists.`); return; } space.name = spaceName; isUpdateMade = true; } if (email !== space.email) { space.email = email; isUpdateMade = true; } if (userName !== space.userName) { space.userName = userName; isUpdateMade = true; } yield fs_extra_1.default.writeJson(configPath, config); if (isUpdateMade) { ui_1.UIHelper.success(`Space "${ui_1.UIHelper.highlight(selectedSpace)}" updated successfully.`); } else { ui_1.UIHelper.info("No changes were made to the space."); } }); } exports.modifySpace = modifySpace; function inspectSpace(spaceName) { return __awaiter(this, void 0, void 0, function* () { yield ensureConfigFileExists(); const config = yield fs_extra_1.default.readJson(configPath); if (config.spaces.length === 0) { ui_1.UIHelper.warning("No spaces have been added yet."); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command("dss add") + " to create your first space."); return; } let selectedSpaceName = spaceName; if (!selectedSpaceName) { selectedSpaceName = yield (0, prompts_1.select)({ message: "Select a space to inspect:", choices: config.spaces.map((space) => ({ name: space.name === config.activeSpace ? ui_1.UIHelper.activeSpace(space.name) : space.name, value: space.name, description: `${space.email} (${space.userName})` })), }); } const space = config.spaces.find((s) => s.name === selectedSpaceName); if (!space) { ui_1.UIHelper.error(`Space "${selectedSpaceName}" not found.`); return; } ui_1.UIHelper.printHeader(`Space Details: ${space.name}`); // Basic Information console.log(ui_1.UIHelper.bold("Basic Information:")); ui_1.UIHelper.printStatus("Name", space.name, space.name === config.activeSpace ? 'success' : 'info'); ui_1.UIHelper.printStatus("Email", space.email, 'info'); ui_1.UIHelper.printStatus("Username", space.userName, 'info'); ui_1.UIHelper.printStatus("Status", space.name === config.activeSpace ? 'Active' : 'Inactive', space.name === config.activeSpace ? 'success' : 'info'); console.log(""); // SSH Key Status console.log(ui_1.UIHelper.bold("SSH Configuration:")); if (space.sshKeyPath) { const keyExists = yield fs_extra_1.default.pathExists(space.sshKeyPath); const pubKeyExists = yield fs_extra_1.default.pathExists(`${space.sshKeyPath}.pub`); ui_1.UIHelper.printStatus("SSH Key Path", space.sshKeyPath, keyExists ? 'success' : 'error'); ui_1.UIHelper.printStatus("Private Key", keyExists ? 'Found' : 'Missing', keyExists ? 'success' : 'error'); ui_1.UIHelper.printStatus("Public Key", pubKeyExists ? 'Found' : 'Missing', pubKeyExists ? 'success' : 'error'); // Check if key is loaded in ssh-agent try { const { stdout } = yield execAsync('ssh-add -l'); const keyInAgent = stdout.includes(space.sshKeyPath) || stdout.includes('no identities') === false; ui_1.UIHelper.printStatus("SSH Agent", keyInAgent ? 'Key loaded' : 'Key not loaded', keyInAgent ? 'success' : 'warning'); } catch (_a) { ui_1.UIHelper.printStatus("SSH Agent", 'Unable to check', 'warning'); } // Check SSH config const sshConfigPath = path_1.default.join(os_1.default.homedir(), '.ssh', 'config'); if (yield fs_extra_1.default.pathExists(sshConfigPath)) { const sshConfig = yield fs_extra_1.default.readFile(sshConfigPath, 'utf8'); const hasGithubConfig = sshConfig.includes('Host github.com'); const usesThisKey = sshConfig.includes(space.sshKeyPath); ui_1.UIHelper.printStatus("SSH Config", hasGithubConfig ? (usesThisKey ? 'Configured for this key' : 'Configured for different key') : 'No GitHub config', hasGithubConfig ? (usesThisKey ? 'success' : 'warning') : 'warning'); } else { ui_1.UIHelper.printStatus("SSH Config", 'No SSH config file', 'warning'); } // Check key file permissions if (keyExists) { try { const stats = yield fs_extra_1.default.stat(space.sshKeyPath); const permissions = (stats.mode & parseInt('777', 8)).toString(8); const isSecure = permissions === '600'; ui_1.UIHelper.printStatus("Key Permissions", permissions, isSecure ? 'success' : 'warning'); } catch (_b) { ui_1.UIHelper.printStatus("Key Permissions", 'Unable to check', 'warning'); } } } else { ui_1.UIHelper.printStatus("SSH Key", 'Not configured', 'error'); } console.log(""); // Git Status console.log(ui_1.UIHelper.bold("Git Configuration:")); try { const currentGitUser = (0, child_process_1.execSync)('git config --global user.name', { encoding: 'utf8' }).trim(); const currentGitEmail = (0, child_process_1.execSync)('git config --global user.email', { encoding: 'utf8' }).trim(); const userMatches = currentGitUser === space.userName; const emailMatches = currentGitEmail === space.email; ui_1.UIHelper.printStatus("Git User", currentGitUser, userMatches ? 'success' : 'warning'); ui_1.UIHelper.printStatus("Git Email", currentGitEmail, emailMatches ? 'success' : 'warning'); if (userMatches && emailMatches) { ui_1.UIHelper.printStatus("Git Config", 'Matches this space', 'success'); } else { ui_1.UIHelper.printStatus("Git Config", 'Does not match this space', 'warning'); } } catch (_c) { ui_1.UIHelper.printStatus("Git Config", 'Unable to check', 'warning'); } console.log(""); // File System Info console.log(ui_1.UIHelper.bold("File System:")); if (space.sshKeyPath) { const keyDir = path_1.default.dirname(space.sshKeyPath); const keyDirExists = yield fs_extra_1.default.pathExists(keyDir); ui_1.UIHelper.printStatus("Key Directory", keyDir, keyDirExists ? 'success' : 'error'); if (keyDirExists) { try { const files = yield fs_extra_1.default.readdir(keyDir); const keyFiles = files.filter(file => file.includes(path_1.default.basename(space.sshKeyPath))); ui_1.UIHelper.printStatus("Key Files", `${keyFiles.length} files found`, keyFiles.length >= 2 ? 'success' : 'warning'); } catch (_d) { ui_1.UIHelper.printStatus("Key Files", 'Unable to check', 'warning'); } } } console.log(""); // Action suggestions console.log(ui_1.UIHelper.bold("Available Actions:")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command(`dss switch ${space.name}`) + " - Switch to this space")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command(`dss edit ${space.name}`) + " - Edit space configuration")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command(`dss test ${space.name}`) + " - Test GitHub access")); if (space.name !== config.activeSpace) { console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command(`dss remove ${space.name}`) + " - Remove this space")); } }); } exports.inspectSpace = inspectSpace; function onboardUser() { return __awaiter(this, void 0, void 0, function* () { ui_1.UIHelper.printHeader("🎉 Welcome to DSS (Dev Spaces Switcher)"); console.log(ui_1.UIHelper.dim("Let's get you set up with your first development space!")); console.log(""); // Check if user already has spaces yield ensureConfigFileExists(); const config = yield fs_extra_1.default.readJson(configPath); if (config.spaces.length > 0) { ui_1.UIHelper.info(`You already have ${config.spaces.length} space(s) configured.`); const continueOnboarding = yield (0, prompts_1.confirm)({ message: "Would you like to continue with the onboarding tutorial?", default: false }); if (!continueOnboarding) { ui_1.UIHelper.info("Onboarding cancelled. Use " + ui_1.UIHelper.command("dss list") + " to see your spaces."); return; } } // Introduction ui_1.UIHelper.printInfoBox("What is DSS?", [ "DSS helps you manage multiple development identities by:", "• Switching between different Git configurations", "• Managing separate SSH keys for different accounts", "• Organizing your development environments", "• Testing GitHub access for each identity" ]); const startTutorial = yield (0, prompts_1.confirm)({ message: "Ready to create your first development space?", default: true }); if (!startTutorial) { ui_1.UIHelper.info("You can start the onboarding anytime with " + ui_1.UIHelper.command("dss onboard")); return; } // Step 1: Create first space console.log(""); ui_1.UIHelper.printHeader("📝 Step 1: Create Your First Space"); console.log(ui_1.UIHelper.dim("A 'space' represents a development identity with its own:")); console.log(ui_1.UIHelper.dim("• Git username and email")); console.log(ui_1.UIHelper.dim("• SSH key for GitHub authentication")); console.log(ui_1.UIHelper.dim("• Isolated configuration")); console.log(""); const createFirstSpace = yield (0, prompts_1.confirm)({ message: "Create your first space now?", default: true }); if (createFirstSpace) { yield addSpace(); // Refresh config const updatedConfig = yield fs_extra_1.default.readJson(configPath); if (updatedConfig.spaces.length === 0) { ui_1.UIHelper.warning("Space creation was cancelled. You can try again with " + ui_1.UIHelper.command("dss add")); return; } } else { ui_1.UIHelper.info("You can create a space later with " + ui_1.UIHelper.command("dss add")); } // Step 2: Explain switching console.log(""); ui_1.UIHelper.printHeader("🔄 Step 2: Understanding Space Switching"); ui_1.UIHelper.printInfoBox("What happens when you switch spaces?", [ "1. Git global config is updated with space's user/email", "2. SSH key is added to ssh-agent", "3. SSH config is updated for GitHub", "4. Space becomes 'active' for your development work" ]); const demoSwitch = yield (0, prompts_1.confirm)({ message: "Would you like to see the switch command in action?", default: true }); if (demoSwitch) { console.log(""); ui_1.UIHelper.info("Here's how to switch spaces:"); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss switch") + " - Interactive selection")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss switch <space-name>") + " - Direct switch")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss switch --dry-run") + " - Preview changes")); const trySwitch = yield (0, prompts_1.confirm)({ message: "Try switching to your new space?", default: true }); if (trySwitch) { yield switchSpace(); } } // Step 3: Essential commands console.log(""); ui_1.UIHelper.printHeader("📚 Step 3: Essential Commands"); console.log(ui_1.UIHelper.bold("Core Commands:")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss list") + " - View all your spaces")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss switch") + " - Change active space")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss test") + " - Test GitHub access")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss inspect <space>") + " - Detailed space info")); console.log(""); console.log(ui_1.UIHelper.bold("Management Commands:")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss add") + " - Create new space")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss edit") + " - Modify existing space")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss remove") + " - Delete space")); console.log(""); console.log(ui_1.UIHelper.bold("Advanced Commands:")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss batch") + " - Switch between multiple spaces")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss bulk") + " - Bulk update operations")); console.log(ui_1.UIHelper.dim(" • " + ui_1.UIHelper.command("dss export/import") + " - Backup/restore config")); // Step 4: Next steps console.log(""); ui_1.UIHelper.printHeader("🚀 Step 4: Next Steps"); const nextSteps = [ "1. Add your SSH key to GitHub at https://github.com/settings/keys", "2. Test your GitHub access with " + ui_1.UIHelper.command("dss test"), "3. Create additional spaces for different projects/companies", "4. Use " + ui_1.UIHelper.command("dss list") + " to see all your spaces", "5. Switch between spaces as needed for your work" ]; ui_1.UIHelper.printSuccessBox("You're all set!", nextSteps); const testGitHub = yield (0, prompts_1.confirm)({ message: "Would you like to test GitHub access now?", default: true }); if (testGitHub) { yield testSpace(); } console.log(""); ui_1.UIHelper.success("Onboarding complete! 🎉"); ui_1.UIHelper.info("Use " + ui_1.UIHelper.command("dss --help") + " anytime to see all available commands."); }); } exports.onboardUser = onboardUser;