UNPKG

git-intent

Version:

Git workflow tool for intentional commits — define your commit intentions first for clearer, more atomic changes.

441 lines (427 loc) 15.3 kB
#!/usr/bin/env node // src/index.ts import { getPackageInfo, storage as storage10 } from "@offlegacy/git-intent-core"; import { program } from "commander"; // src/commands/list.ts import { storage } from "@offlegacy/git-intent-core"; import chalk from "chalk"; import { Command } from "commander"; var list = new Command().command("list").description("List all intentional commits").action(async () => { const commits = await storage.loadCommits(); if (commits.length === 0) { console.log("No intents found"); return; } console.log("\nCreated:"); const createdCommits = commits.filter((commit2) => commit2.status === "created"); for (const commit2 of createdCommits) { console.log(chalk.white(` [${commit2.id}] ${commit2.message}`)); } console.log("\nIn Progress:"); const inProgressCommits = commits.filter((commit2) => commit2.status === "in_progress"); for (const commit2 of inProgressCommits) { console.log(chalk.blue(` [${commit2.id}] ${commit2.message}`)); } }); var list_default = list; // src/commands/start.ts import { gitService, storage as storage2 } from "@offlegacy/git-intent-core"; import chalk2 from "chalk"; import { Command as Command2 } from "commander"; import prompts from "prompts"; var start = new Command2().command("start").argument("[id]", "Intent ID").description("Start working on a planned intent").action(async (id) => { const commits = await storage2.loadCommits(); let selectedId = id; if (!selectedId) { const createdCommits = commits.filter((c) => c.status === "created"); if (createdCommits.length === 0) { console.log("No created intents found"); return; } const response = await prompts({ type: "select", name: "id", message: "Select an intent to start:", choices: createdCommits.map((c) => ({ title: `${c.message} (${c.id})`, value: c.id })) }); selectedId = response.id; } if (!selectedId) { console.error("No intent selected"); return; } const targetCommit = commits.find((c) => c.id === selectedId); if (!targetCommit) { console.error("Intent not found"); return; } if (targetCommit.status !== "created") { console.error("Intent is not in created status"); return; } const currentBranch = await gitService.getCurrentBranch(); targetCommit.status = "in_progress"; targetCommit.metadata.startedAt = (/* @__PURE__ */ new Date()).toISOString(); targetCommit.metadata.branch = currentBranch; await storage2.saveCommits(commits); console.log(chalk2.green("\u2713 Started working on:")); console.log(`ID: ${chalk2.blue(targetCommit.id)}`); console.log(`Message: ${targetCommit.message}`); }); var start_default = start; // src/commands/show.ts import { storage as storage3 } from "@offlegacy/git-intent-core"; import chalk3 from "chalk"; import { Command as Command3 } from "commander"; var show = new Command3().command("show").description("Show current intention").action(async () => { const commits = await storage3.loadCommits(); const currentCommit = commits.find((c) => c.status === "in_progress"); if (!currentCommit) { console.log("No active intention"); return; } console.log(chalk3.blue("Current intention:")); console.log(`ID: ${chalk3.dim(currentCommit.id)}`); console.log(`Message: ${currentCommit.message}`); console.log(`Status: ${chalk3.yellow(currentCommit.status)}`); console.log(`Created at: ${new Date(currentCommit.metadata.createdAt).toLocaleString()}`); }); var show_default = show; // src/commands/commit.ts import { gitService as gitService2, storage as storage4 } from "@offlegacy/git-intent-core"; import chalk4 from "chalk"; import { Command as Command4 } from "commander"; var commit = new Command4().command("commit").description("Complete current intention and commit").option("-m, --message <message>", "Additional commit message").action(async (options) => { const commits = await storage4.loadCommits(); const currentCommit = commits.find((c) => c.status === "in_progress"); if (!currentCommit) { console.log("No active intention"); return; } const message = options.message ? `${currentCommit.message} ${options.message}` : currentCommit.message; await gitService2.createCommit(message); await storage4.deleteCommit(currentCommit.id); console.log(chalk4.green("\u2713 Intention completed and committed")); }); var commit_default = commit; // src/commands/drop.ts import { storage as storage5 } from "@offlegacy/git-intent-core"; import chalk5 from "chalk"; import { Command as Command5 } from "commander"; import prompts2 from "prompts"; var drop = new Command5().command("drop").description("Drop a planned intent").argument("[id]", "Intent ID").option("-a, --all", "Drop all created intents").action(async (id, options) => { const commits = await storage5.loadCommits(); const createdCommits = commits.filter((c) => c.status === "created"); if (options.all) { await storage5.saveCommits([]); console.log(chalk5.green("\u2713 All created intents removed")); return; } let selectedId = id; if (!selectedId) { if (createdCommits.length === 0) { console.log("No created intents found. Nothing to remove."); return; } const response = await prompts2({ type: "select", name: "id", message: "Select an intent to remove:", choices: createdCommits.map((c) => ({ title: `${c.message} (${c.id})`, value: c.id })) }); selectedId = response.id; } if (!selectedId) { console.error("No intent selected"); return; } const targetCommit = commits.find((c) => c.id === selectedId); if (!targetCommit) { console.error("Intent not found"); return; } if (targetCommit.status !== "created") { console.error("Can only remove intents in created status"); return; } const updatedCommits = commits.filter((c) => c.id !== selectedId); await storage5.saveCommits(updatedCommits); console.log(chalk5.green("\u2713 Intent removed:")); console.log(`ID: ${chalk5.blue(targetCommit.id)}`); console.log(`Message: ${targetCommit.message}`); }); var drop_default = drop; // src/commands/cancel.ts import { storage as storage6 } from "@offlegacy/git-intent-core"; import chalk6 from "chalk"; import { Command as Command6 } from "commander"; import prompts3 from "prompts"; var cancel = new Command6().command("cancel").description("Cancel current intention").action(async () => { const commits = await storage6.loadCommits(); const currentCommit = commits.find((c) => c.status === "in_progress"); if (!currentCommit) { console.log("No active intention"); return; } const { action } = await prompts3({ type: "select", name: "action", message: "What would you like to do with the intent?", choices: [ { title: "Reset to created status", value: "reset" }, { title: "Delete the intent", value: "delete" } ] }); if (!action) { return; } let updatedCommits; if (action === "reset") { updatedCommits = commits.map( (c) => c.id === currentCommit.id ? { ...c, status: "created", metadata: { ...c.metadata, startedAt: void 0 } } : c ); console.log(chalk6.green("\u2713 Intent reset to created status:")); } else { updatedCommits = commits.filter((c) => c.id !== currentCommit.id); console.log(chalk6.green("\u2713 Intent deleted:")); } await storage6.saveCommits(updatedCommits); console.log(`ID: ${chalk6.blue(currentCommit.id)}`); console.log(`Message: ${currentCommit.message}`); console.log("\nNote: Your staged changes are preserved."); }); var cancel_default = cancel; // src/commands/reset.ts import { storage as storage7 } from "@offlegacy/git-intent-core"; import { Command as Command7 } from "commander"; import prompts4 from "prompts"; var reset = new Command7().command("reset").description("Reset all intents").action(async () => { const response = await prompts4({ type: "confirm", name: "reset", message: "Are you sure you want to reset all intents?", initial: false }); if (!response.reset) { return; } await storage7.clearCommits(); console.log("All intents reset"); }); var reset_default = reset; // src/commands/divide.ts import { storage as storage8 } from "@offlegacy/git-intent-core"; import chalk7 from "chalk"; import { Command as Command8 } from "commander"; import edit from "external-editor"; import prompts5 from "prompts"; var divide = new Command8().command("divide").description("Divide an intent into smaller parts").action(async () => { const commits = await storage8.loadCommits(); if (commits.length === 0) { console.log("No intents found to divide"); return; } const response = await prompts5({ type: "select", name: "id", message: "Select an intent to divide:", choices: commits.map((c) => ({ title: `[${c.status === "created" ? "Created" : "In Progress"}] ${c.message.split("\n")[0]} (${c.id})`, value: c.id })), onState: (state) => { if (state.aborted) { process.nextTick(() => { process.exit(0); }); } } }); const selectedId = response.id; if (!selectedId) { console.log("No intent selected"); return; } const targetCommit = commits.find((c) => c.id === selectedId); if (!targetCommit) { console.error("Intent not found"); return; } console.log(chalk7.blue("\nOriginal commit:"), targetCommit.message); const tasks = []; console.log(chalk7.yellow("\nDividing commit into two tasks.")); console.log( chalk7.dim( "Tip: Enter a title directly for a simple task, or leave it empty to open an editor for a detailed commit message." ) ); console.log(chalk7.blue("\nFirst task:")); const { taskTitle: firstTaskTitle } = await prompts5({ type: "text", name: "taskTitle", message: "Task 1 title:", onState: (state) => { if (state.aborted) { process.nextTick(() => { process.exit(0); }); } } }); if (firstTaskTitle && firstTaskTitle.trim() !== "") { tasks.push(firstTaskTitle.trim()); } else { console.log(chalk7.dim("Opening editor for commit message. Save and close the editor when done.")); let initialText = targetCommit.message; initialText = `# Enter commit message for the first task # Lines starting with # will be ignored ${initialText}`; const message = edit.edit(initialText, { postfix: ".git-intent-divide" }); const fullMessage = message.split("\n").filter((line) => !line.trim().startsWith("#")).join("\n").trim(); if (!fullMessage) { console.log("No message provided for the first task. Operation cancelled."); return; } tasks.push(fullMessage); } console.log(chalk7.blue("\nSecond task:")); const { taskTitle: secondTaskTitle } = await prompts5({ type: "text", name: "taskTitle", message: "Task 2 title:", onState: (state) => { if (state.aborted) { process.nextTick(() => { process.exit(0); }); } } }); if (secondTaskTitle && secondTaskTitle.trim() !== "") { tasks.push(secondTaskTitle.trim()); } else { console.log(chalk7.dim("Opening editor for commit message. Save and close the editor when done.")); const initialText = "# Enter commit message for the second task\n# Lines starting with # will be ignored\n"; const message = edit.edit(initialText, { postfix: ".git-intent-divide" }); const fullMessage = message.split("\n").filter((line) => !line.trim().startsWith("#")).join("\n").trim(); if (!fullMessage) { console.log("No message provided for the second task. Operation cancelled."); return; } tasks.push(fullMessage); } console.log(chalk7.blue("\nTasks to create:")); tasks.forEach((task, index) => { const title = task.split("\n")[0]; console.log(`${index + 1}. ${title}`); if (task.includes("\n")) { const preview = task.split("\n").slice(1).join(" ").trim(); const shortPreview = preview.length > 60 ? `${preview.substring(0, 57)}...` : preview; if (shortPreview) { console.log(` ${chalk7.dim(shortPreview)}`); } } }); const { confirmed } = await prompts5({ type: "confirm", name: "confirmed", message: "Do you want to divide the commit with these tasks?", initial: true, onState: (state) => { if (state.aborted) { process.nextTick(() => { process.exit(0); }); } } }); if (!confirmed) { console.log("Operation cancelled."); return; } const { shouldRemoveOriginal } = await prompts5({ type: "confirm", name: "shouldRemoveOriginal", message: "Do you want to remove the original commit?", initial: false, onState: (state) => { if (state.aborted) { process.nextTick(() => { process.exit(0); }); } } }); const newCommitIds = []; for (const task of tasks) { const newCommitId = await storage8.addCommit({ message: task, status: "created", metadata: { createdAt: (/* @__PURE__ */ new Date()).toISOString() } }); newCommitIds.push(newCommitId); } if (shouldRemoveOriginal) { await storage8.deleteCommit(targetCommit.id); } console.log(chalk7.green("\u2713 Successfully divided the commit:")); for (let i = 0; i < tasks.length; i++) { const title = tasks[i].split("\n")[0]; console.log(`${i + 1}. ${chalk7.blue(title)} (ID: ${newCommitIds[i]})`); } if (!shouldRemoveOriginal) { console.log(chalk7.yellow("\nOriginal commit was kept:")); const originalTitle = targetCommit.message.split("\n")[0]; console.log(`${chalk7.blue(originalTitle)} (ID: ${targetCommit.id})`); } }); var divide_default = divide; // src/commands/add.ts import { storage as storage9 } from "@offlegacy/git-intent-core"; import chalk8 from "chalk"; import { Command as Command9 } from "commander"; import edit2 from "external-editor"; var add = new Command9().command("add").description("Add a new intentional commit before starting work").argument("[message]", "Intent message").action(async (message) => { let commitMessage = message; if (!commitMessage) { const text = edit2.edit("", { postfix: ".git-intent" }); commitMessage = text.trim(); } if (!commitMessage) { console.error("Commit message is required"); process.exit(1); } const newCommitId = await storage9.addCommit({ message: commitMessage, status: "created", metadata: { createdAt: (/* @__PURE__ */ new Date()).toISOString() } }); console.log(chalk8.green("\u2713 Intent created:")); console.log(`ID: ${chalk8.blue(newCommitId)}`); console.log(`Message: ${commitMessage}`); }); var add_default = add; // src/index.ts (async () => { await storage10.initializeRefs(); const { version, description } = getPackageInfo(); program.name("git-intent").description(description).version(version).addCommand(add_default).addCommand(list_default).addCommand(start_default).addCommand(show_default).addCommand(commit_default).addCommand(cancel_default).addCommand(reset_default).addCommand(divide_default).addCommand(drop_default); program.parse(); })();