@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
JavaScript
;
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;