@gogd-core/ggd 0.1.0 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/main.js +246 -3
- package/package.json +4 -1
- package/postinstall.js +201 -0
- package/src/commands/completion.d.ts +36 -0
- package/src/commands/index.d.ts +3 -0
- package/src/commands/mt.d.ts +32 -0
- package/src/commands/rsh.d.ts +27 -0
- package/src/index.d.ts +1 -1
- package/src/postinstall.d.ts +33 -0
package/main.js
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// apps/ggd/src/main.ts
|
|
27
|
-
var
|
|
27
|
+
var import_commander6 = require("commander");
|
|
28
28
|
|
|
29
29
|
// apps/ggd/src/commands/env.ts
|
|
30
30
|
var import_commander = require("commander");
|
|
@@ -81,9 +81,252 @@ function createRunCommand() {
|
|
|
81
81
|
return run;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
// apps/ggd/src/commands/rsh.ts
|
|
85
|
+
var import_commander3 = require("commander");
|
|
86
|
+
var import_execa2 = __toESM(require("execa"));
|
|
87
|
+
var readline = __toESM(require("readline"));
|
|
88
|
+
async function getCurrentBranch() {
|
|
89
|
+
const { stdout } = await (0, import_execa2.default)("git", ["symbolic-ref", "--short", "HEAD"]);
|
|
90
|
+
return stdout.trim();
|
|
91
|
+
}
|
|
92
|
+
async function getUncommittedChangeCount() {
|
|
93
|
+
const { stdout } = await (0, import_execa2.default)("git", ["status", "--porcelain"]);
|
|
94
|
+
if (!stdout.trim())
|
|
95
|
+
return 0;
|
|
96
|
+
return stdout.trim().split("\n").length;
|
|
97
|
+
}
|
|
98
|
+
function confirm(message) {
|
|
99
|
+
const rl = readline.createInterface({
|
|
100
|
+
input: process.stdin,
|
|
101
|
+
output: process.stderr
|
|
102
|
+
});
|
|
103
|
+
return new Promise((resolve) => {
|
|
104
|
+
rl.question(message, (answer) => {
|
|
105
|
+
rl.close();
|
|
106
|
+
const normalized = (answer || "Y").trim().toLowerCase();
|
|
107
|
+
resolve(normalized === "y" || normalized === "yes");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async function resetHard(branch) {
|
|
112
|
+
try {
|
|
113
|
+
await (0, import_execa2.default)("git", ["fetch", "origin", branch], { stdio: "inherit" });
|
|
114
|
+
await (0, import_execa2.default)("git", ["reset", "--hard", `origin/${branch}`], { stdio: "inherit" });
|
|
115
|
+
return 0;
|
|
116
|
+
} catch {
|
|
117
|
+
return 1;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function createRshCommand() {
|
|
121
|
+
const rsh = new import_commander3.Command("rsh").description("Reset current branch to origin (git reset --hard)").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
|
|
122
|
+
try {
|
|
123
|
+
const branch = await getCurrentBranch();
|
|
124
|
+
const changeCount = await getUncommittedChangeCount();
|
|
125
|
+
console.error(`\x1B[36mBranch:\x1B[0m ${branch}`);
|
|
126
|
+
if (changeCount > 0) {
|
|
127
|
+
console.error(`\x1B[33mUncommitted changes: ${changeCount} file(s) will be lost\x1B[0m`);
|
|
128
|
+
}
|
|
129
|
+
console.error(`\x1B[31mTarget: git reset --hard origin/${branch}\x1B[0m`);
|
|
130
|
+
if (!opts.yes) {
|
|
131
|
+
const ok = await confirm("\nProceed? (Y/n): ");
|
|
132
|
+
if (!ok) {
|
|
133
|
+
console.error("Reset aborted.");
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const exitCode = await resetHard(branch);
|
|
138
|
+
if (exitCode !== 0) {
|
|
139
|
+
process.exitCode = exitCode;
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
143
|
+
console.error(`\x1B[31mError: ${message}\x1B[0m`);
|
|
144
|
+
process.exitCode = 1;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
return rsh;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// apps/ggd/src/commands/mt.ts
|
|
151
|
+
var import_commander4 = require("commander");
|
|
152
|
+
var import_execa3 = __toESM(require("execa"));
|
|
153
|
+
async function localBranchExists(branch) {
|
|
154
|
+
try {
|
|
155
|
+
await (0, import_execa3.default)("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`]);
|
|
156
|
+
return true;
|
|
157
|
+
} catch {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async function deleteLocalBranch(branch) {
|
|
162
|
+
await (0, import_execa3.default)("git", ["branch", "-D", branch], { stdio: "inherit" });
|
|
163
|
+
}
|
|
164
|
+
async function switchBranch(branch) {
|
|
165
|
+
await (0, import_execa3.default)("git", ["switch", branch], { stdio: "inherit" });
|
|
166
|
+
}
|
|
167
|
+
async function mergeBranch(source) {
|
|
168
|
+
try {
|
|
169
|
+
await (0, import_execa3.default)("git", ["merge", source], { stdio: "inherit" });
|
|
170
|
+
return 0;
|
|
171
|
+
} catch {
|
|
172
|
+
return 1;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function pushBranch(branch) {
|
|
176
|
+
try {
|
|
177
|
+
await (0, import_execa3.default)("git", ["push", "origin", branch], { stdio: "inherit" });
|
|
178
|
+
return 0;
|
|
179
|
+
} catch {
|
|
180
|
+
return 1;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function createMtCommand() {
|
|
184
|
+
const mt = new import_commander4.Command("mt").description("Merge current branch into target branch").argument("<branch>", "Target branch to merge into").option("-y, --yes", "Skip confirmation prompt").action(async (targetBranch, opts) => {
|
|
185
|
+
try {
|
|
186
|
+
const sourceBranch = await getCurrentBranch();
|
|
187
|
+
if (sourceBranch === targetBranch) {
|
|
188
|
+
console.error("\x1B[31mError: Cannot merge a branch into itself\x1B[0m");
|
|
189
|
+
process.exitCode = 1;
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
console.error(`\x1B[36mSource:\x1B[0m ${sourceBranch}`);
|
|
193
|
+
console.error(`\x1B[36mTarget:\x1B[0m ${targetBranch}`);
|
|
194
|
+
console.error(`\x1B[33mWill: delete local ${targetBranch} (if exists), switch to it, merge ${sourceBranch}\x1B[0m`);
|
|
195
|
+
if (!opts.yes) {
|
|
196
|
+
const ok = await confirm(`
|
|
197
|
+
Merge ${sourceBranch} into ${targetBranch}? (Y/n): `);
|
|
198
|
+
if (!ok) {
|
|
199
|
+
console.error("Merge aborted.");
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (await localBranchExists(targetBranch)) {
|
|
204
|
+
console.error(`\x1B[33mDeleting local ${targetBranch}...\x1B[0m`);
|
|
205
|
+
await deleteLocalBranch(targetBranch);
|
|
206
|
+
}
|
|
207
|
+
await switchBranch(targetBranch);
|
|
208
|
+
const exitCode = await mergeBranch(sourceBranch);
|
|
209
|
+
if (exitCode !== 0) {
|
|
210
|
+
console.error(`\x1B[31mMerge failed. You are now on ${targetBranch}.\x1B[0m`);
|
|
211
|
+
process.exitCode = exitCode;
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
console.error(`\x1B[32mMerge successful!\x1B[0m`);
|
|
215
|
+
const shouldPush = await confirm(`Push ${targetBranch} to origin? (Y/n): `);
|
|
216
|
+
if (shouldPush) {
|
|
217
|
+
const pushExit = await pushBranch(targetBranch);
|
|
218
|
+
if (pushExit !== 0) {
|
|
219
|
+
console.error(`\x1B[31mPush failed.\x1B[0m`);
|
|
220
|
+
process.exitCode = pushExit;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} catch (error) {
|
|
224
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
225
|
+
console.error(`\x1B[31mError: ${message}\x1B[0m`);
|
|
226
|
+
process.exitCode = 1;
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
return mt;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// apps/ggd/src/commands/completion.ts
|
|
233
|
+
var import_commander5 = require("commander");
|
|
234
|
+
function detectShell() {
|
|
235
|
+
const shell = process.env["SHELL"] || "";
|
|
236
|
+
if (shell.includes("zsh"))
|
|
237
|
+
return "zsh";
|
|
238
|
+
if (shell.includes("bash"))
|
|
239
|
+
return "bash";
|
|
240
|
+
if (process.platform === "win32")
|
|
241
|
+
return "powershell";
|
|
242
|
+
return "bash";
|
|
243
|
+
}
|
|
244
|
+
function generateBashCompletion() {
|
|
245
|
+
return `###-begin-ggd-completions-###
|
|
246
|
+
_ggd_completions() {
|
|
247
|
+
local cur commands
|
|
248
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
249
|
+
commands="$(ggd --get-completions "\${COMP_WORDS[@]}")"
|
|
250
|
+
COMPREPLY=($(compgen -W "$commands" -- "$cur"))
|
|
251
|
+
}
|
|
252
|
+
complete -F _ggd_completions ggd
|
|
253
|
+
###-end-ggd-completions-###`;
|
|
254
|
+
}
|
|
255
|
+
function generateZshCompletion() {
|
|
256
|
+
return `###-begin-ggd-completions-###
|
|
257
|
+
_ggd_completions() {
|
|
258
|
+
local commands
|
|
259
|
+
commands="$(ggd --get-completions "\${words[@]}")"
|
|
260
|
+
reply=(\${=commands})
|
|
261
|
+
}
|
|
262
|
+
compctl -K _ggd_completions ggd
|
|
263
|
+
###-end-ggd-completions-###`;
|
|
264
|
+
}
|
|
265
|
+
function generatePowershellCompletion() {
|
|
266
|
+
return `# begin-ggd-completions
|
|
267
|
+
Register-ArgumentCompleter -Native -CommandName ggd -ScriptBlock {
|
|
268
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
269
|
+
$words = $commandAst.ToString().Split(' ')
|
|
270
|
+
$completions = & ggd --get-completions @words 2>$null
|
|
271
|
+
$completions -split '\\s+' | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
|
|
272
|
+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
# end-ggd-completions`;
|
|
276
|
+
}
|
|
277
|
+
function getCompletionScript(shell) {
|
|
278
|
+
switch (shell) {
|
|
279
|
+
case "bash":
|
|
280
|
+
return generateBashCompletion();
|
|
281
|
+
case "zsh":
|
|
282
|
+
return generateZshCompletion();
|
|
283
|
+
case "powershell":
|
|
284
|
+
return generatePowershellCompletion();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
function getCompletions(program2, args) {
|
|
288
|
+
const commandNames = program2.commands.map((cmd) => cmd.name());
|
|
289
|
+
const current = args[args.length - 1] || "";
|
|
290
|
+
if (args.length <= 2) {
|
|
291
|
+
return commandNames.filter((name) => name.startsWith(current));
|
|
292
|
+
}
|
|
293
|
+
const subcommandName = args[1];
|
|
294
|
+
const subcommand = program2.commands.find((cmd) => cmd.name() === subcommandName);
|
|
295
|
+
if (subcommand && subcommand.commands.length > 0) {
|
|
296
|
+
const subNames = subcommand.commands.map((cmd) => cmd.name());
|
|
297
|
+
return subNames.filter((name) => name.startsWith(current));
|
|
298
|
+
}
|
|
299
|
+
return [];
|
|
300
|
+
}
|
|
301
|
+
var VALID_SHELLS = ["bash", "zsh", "powershell"];
|
|
302
|
+
function createCompletionCommand() {
|
|
303
|
+
const completion = new import_commander5.Command("completion").description("Output shell completion script").argument("[shell]", "Shell type: bash, zsh, powershell (auto-detected if omitted)").action((shell) => {
|
|
304
|
+
const resolved = shell ? validateShell(shell) : detectShell();
|
|
305
|
+
console.log(getCompletionScript(resolved));
|
|
306
|
+
});
|
|
307
|
+
return completion;
|
|
308
|
+
}
|
|
309
|
+
function validateShell(shell) {
|
|
310
|
+
if (!VALID_SHELLS.includes(shell)) {
|
|
311
|
+
console.error(`Unknown shell: ${shell}. Supported: ${VALID_SHELLS.join(", ")}`);
|
|
312
|
+
process.exitCode = 1;
|
|
313
|
+
return "bash";
|
|
314
|
+
}
|
|
315
|
+
return shell;
|
|
316
|
+
}
|
|
317
|
+
|
|
84
318
|
// apps/ggd/src/main.ts
|
|
85
|
-
var program = new
|
|
86
|
-
program.name("ggd").description("GoGoodDev workspace CLI").version("0.1.
|
|
319
|
+
var program = new import_commander6.Command();
|
|
320
|
+
program.name("ggd").description("GoGoodDev workspace CLI").version("0.1.3");
|
|
87
321
|
program.addCommand(createEnvCommand());
|
|
88
322
|
program.addCommand(createRunCommand());
|
|
323
|
+
program.addCommand(createRshCommand());
|
|
324
|
+
program.addCommand(createMtCommand());
|
|
325
|
+
program.addCommand(createCompletionCommand());
|
|
326
|
+
if (process.argv.includes("--get-completions")) {
|
|
327
|
+
const args = process.argv.slice(process.argv.indexOf("--get-completions") + 1);
|
|
328
|
+
const suggestions = getCompletions(program, args);
|
|
329
|
+
console.log(suggestions.join(" "));
|
|
330
|
+
process.exit(0);
|
|
331
|
+
}
|
|
89
332
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gogd-core/ggd",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"commander": "12.1.0",
|
|
6
6
|
"execa": "5.1.1"
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
"bin": {
|
|
11
11
|
"ggd": "./main.js"
|
|
12
12
|
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"postinstall": "node ./postinstall.js"
|
|
15
|
+
},
|
|
13
16
|
"description": "GoGoodDev workspace CLI",
|
|
14
17
|
"repository": {
|
|
15
18
|
"type": "git",
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// apps/ggd/src/postinstall.ts
|
|
32
|
+
var postinstall_exports = {};
|
|
33
|
+
__export(postinstall_exports, {
|
|
34
|
+
detectShellForInstall: () => detectShellForInstall,
|
|
35
|
+
getCompletionScriptForShell: () => getCompletionScriptForShell,
|
|
36
|
+
getShellConfigPath: () => getShellConfigPath,
|
|
37
|
+
installCompletions: () => installCompletions,
|
|
38
|
+
removeExistingCompletions: () => removeExistingCompletions,
|
|
39
|
+
runPostinstall: () => runPostinstall
|
|
40
|
+
});
|
|
41
|
+
module.exports = __toCommonJS(postinstall_exports);
|
|
42
|
+
var fs = __toESM(require("fs"));
|
|
43
|
+
var path = __toESM(require("path"));
|
|
44
|
+
var os = __toESM(require("os"));
|
|
45
|
+
|
|
46
|
+
// apps/ggd/src/commands/completion.ts
|
|
47
|
+
var import_commander = require("commander");
|
|
48
|
+
function generateBashCompletion() {
|
|
49
|
+
return `###-begin-ggd-completions-###
|
|
50
|
+
_ggd_completions() {
|
|
51
|
+
local cur commands
|
|
52
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
53
|
+
commands="$(ggd --get-completions "\${COMP_WORDS[@]}")"
|
|
54
|
+
COMPREPLY=($(compgen -W "$commands" -- "$cur"))
|
|
55
|
+
}
|
|
56
|
+
complete -F _ggd_completions ggd
|
|
57
|
+
###-end-ggd-completions-###`;
|
|
58
|
+
}
|
|
59
|
+
function generateZshCompletion() {
|
|
60
|
+
return `###-begin-ggd-completions-###
|
|
61
|
+
_ggd_completions() {
|
|
62
|
+
local commands
|
|
63
|
+
commands="$(ggd --get-completions "\${words[@]}")"
|
|
64
|
+
reply=(\${=commands})
|
|
65
|
+
}
|
|
66
|
+
compctl -K _ggd_completions ggd
|
|
67
|
+
###-end-ggd-completions-###`;
|
|
68
|
+
}
|
|
69
|
+
function generatePowershellCompletion() {
|
|
70
|
+
return `# begin-ggd-completions
|
|
71
|
+
Register-ArgumentCompleter -Native -CommandName ggd -ScriptBlock {
|
|
72
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
73
|
+
$words = $commandAst.ToString().Split(' ')
|
|
74
|
+
$completions = & ggd --get-completions @words 2>$null
|
|
75
|
+
$completions -split '\\s+' | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
|
|
76
|
+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
# end-ggd-completions`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// apps/ggd/src/postinstall.ts
|
|
83
|
+
var COMPLETION_MARKERS = ["###-begin-ggd-completions-###", "# begin-ggd-completions"];
|
|
84
|
+
var COMPLETION_END_MARKERS = ["###-end-ggd-completions-###", "# end-ggd-completions"];
|
|
85
|
+
function detectShellForInstall() {
|
|
86
|
+
const shellEnv = process.env["SHELL"] || "";
|
|
87
|
+
if (shellEnv.includes("zsh"))
|
|
88
|
+
return "zsh";
|
|
89
|
+
if (shellEnv.includes("bash"))
|
|
90
|
+
return "bash";
|
|
91
|
+
if (process.platform === "win32")
|
|
92
|
+
return "powershell";
|
|
93
|
+
if (shellEnv)
|
|
94
|
+
return "bash";
|
|
95
|
+
return "unknown";
|
|
96
|
+
}
|
|
97
|
+
function getShellConfigPath(shell) {
|
|
98
|
+
const home = os.homedir();
|
|
99
|
+
switch (shell) {
|
|
100
|
+
case "bash":
|
|
101
|
+
return path.join(home, ".bashrc");
|
|
102
|
+
case "zsh":
|
|
103
|
+
return path.join(home, ".zshrc");
|
|
104
|
+
case "powershell": {
|
|
105
|
+
const psProfile = process.env["USERPROFILE"] ? path.join(process.env["USERPROFILE"], "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1") : null;
|
|
106
|
+
return psProfile;
|
|
107
|
+
}
|
|
108
|
+
default:
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function getCompletionScriptForShell(shell) {
|
|
113
|
+
switch (shell) {
|
|
114
|
+
case "bash":
|
|
115
|
+
return generateBashCompletion();
|
|
116
|
+
case "zsh":
|
|
117
|
+
return generateZshCompletion();
|
|
118
|
+
case "powershell":
|
|
119
|
+
return generatePowershellCompletion();
|
|
120
|
+
default:
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function removeExistingCompletions(content) {
|
|
125
|
+
let startIdx = -1;
|
|
126
|
+
let startMarkerLen = 0;
|
|
127
|
+
for (const marker of COMPLETION_MARKERS) {
|
|
128
|
+
const idx = content.indexOf(marker);
|
|
129
|
+
if (idx !== -1) {
|
|
130
|
+
startIdx = idx;
|
|
131
|
+
startMarkerLen = marker.length;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (startIdx === -1)
|
|
136
|
+
return content;
|
|
137
|
+
let endIdx = -1;
|
|
138
|
+
let endMarkerLen = 0;
|
|
139
|
+
for (const marker of COMPLETION_END_MARKERS) {
|
|
140
|
+
const idx = content.indexOf(marker, startIdx + startMarkerLen);
|
|
141
|
+
if (idx !== -1) {
|
|
142
|
+
endIdx = idx;
|
|
143
|
+
endMarkerLen = marker.length;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (endIdx === -1)
|
|
148
|
+
return content;
|
|
149
|
+
const before = content.substring(0, startIdx).trimEnd();
|
|
150
|
+
const after = content.substring(endIdx + endMarkerLen).trimStart();
|
|
151
|
+
return before + (after ? "\n" + after : "") + "\n";
|
|
152
|
+
}
|
|
153
|
+
function installCompletions(shell) {
|
|
154
|
+
const configPath = getShellConfigPath(shell);
|
|
155
|
+
if (!configPath)
|
|
156
|
+
return false;
|
|
157
|
+
const script = getCompletionScriptForShell(shell);
|
|
158
|
+
if (!script)
|
|
159
|
+
return false;
|
|
160
|
+
try {
|
|
161
|
+
const dir = path.dirname(configPath);
|
|
162
|
+
if (!fs.existsSync(dir)) {
|
|
163
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
164
|
+
}
|
|
165
|
+
let existing = "";
|
|
166
|
+
if (fs.existsSync(configPath)) {
|
|
167
|
+
existing = fs.readFileSync(configPath, "utf8");
|
|
168
|
+
}
|
|
169
|
+
const cleaned = removeExistingCompletions(existing);
|
|
170
|
+
const updated = cleaned.trimEnd() + "\n\n" + script + "\n";
|
|
171
|
+
fs.writeFileSync(configPath, updated, "utf8");
|
|
172
|
+
return true;
|
|
173
|
+
} catch {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function runPostinstall() {
|
|
178
|
+
if (process.env["CI"] || process.env["CONTINUOUS_INTEGRATION"]) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const shell = detectShellForInstall();
|
|
182
|
+
if (shell === "unknown") {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const success = installCompletions(shell);
|
|
186
|
+
if (success) {
|
|
187
|
+
console.log(`ggd: shell completions installed for ${shell}. Restart your shell to activate.`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (require.main === module) {
|
|
191
|
+
runPostinstall();
|
|
192
|
+
}
|
|
193
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
194
|
+
0 && (module.exports = {
|
|
195
|
+
detectShellForInstall,
|
|
196
|
+
getCompletionScriptForShell,
|
|
197
|
+
getShellConfigPath,
|
|
198
|
+
installCompletions,
|
|
199
|
+
removeExistingCompletions,
|
|
200
|
+
runPostinstall
|
|
201
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ggd completion` command — outputs shell completion scripts.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
type ShellType = 'bash' | 'zsh' | 'powershell';
|
|
6
|
+
/**
|
|
7
|
+
* Auto-detects the current shell from environment variables.
|
|
8
|
+
*/
|
|
9
|
+
export declare function detectShell(): ShellType;
|
|
10
|
+
/**
|
|
11
|
+
* Generates a Bash completion script for ggd.
|
|
12
|
+
*/
|
|
13
|
+
export declare function generateBashCompletion(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Generates a Zsh completion script for ggd.
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateZshCompletion(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Generates a PowerShell completion script for ggd.
|
|
20
|
+
*/
|
|
21
|
+
export declare function generatePowershellCompletion(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Returns the completion script for the given shell type.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCompletionScript(shell: ShellType): string;
|
|
26
|
+
/**
|
|
27
|
+
* Returns completion suggestions for the given CLI arguments.
|
|
28
|
+
* Used internally by `--get-completions`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getCompletions(program: Command, args: string[]): string[];
|
|
31
|
+
/**
|
|
32
|
+
* Creates the `completion` command.
|
|
33
|
+
* Outputs a shell completion script to stdout.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createCompletionCommand(): Command;
|
|
36
|
+
export {};
|
package/src/commands/index.d.ts
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ggd mt` command — merge current branch into a target branch.
|
|
3
|
+
*
|
|
4
|
+
* Switches to target branch (re-creating from origin if it exists locally),
|
|
5
|
+
* then merges the source branch into it with confirmation.
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
/**
|
|
9
|
+
* Checks if a local branch exists.
|
|
10
|
+
*/
|
|
11
|
+
export declare function localBranchExists(branch: string): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Deletes a local branch.
|
|
14
|
+
*/
|
|
15
|
+
export declare function deleteLocalBranch(branch: string): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Switches to a branch.
|
|
18
|
+
*/
|
|
19
|
+
export declare function switchBranch(branch: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Merges a source branch into the current branch.
|
|
22
|
+
*/
|
|
23
|
+
export declare function mergeBranch(source: string): Promise<number>;
|
|
24
|
+
/**
|
|
25
|
+
* Pushes the current branch to origin.
|
|
26
|
+
*/
|
|
27
|
+
export declare function pushBranch(branch: string): Promise<number>;
|
|
28
|
+
/**
|
|
29
|
+
* Creates the `mt` command.
|
|
30
|
+
* Merges current branch into a target branch with confirmation.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createMtCommand(): Command;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ggd rsh` command — safe git reset --hard to origin/<current-branch>.
|
|
3
|
+
*
|
|
4
|
+
* Shows branch name and uncommitted change count before prompting for confirmation.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
/**
|
|
8
|
+
* Returns the current git branch name.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getCurrentBranch(): Promise<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Returns the number of uncommitted changes (staged + unstaged + untracked).
|
|
13
|
+
*/
|
|
14
|
+
export declare function getUncommittedChangeCount(): Promise<number>;
|
|
15
|
+
/**
|
|
16
|
+
* Prompts the user with a yes/no question. Returns true for yes.
|
|
17
|
+
*/
|
|
18
|
+
export declare function confirm(message: string): Promise<boolean>;
|
|
19
|
+
/**
|
|
20
|
+
* Executes git reset --hard origin/<branch>.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resetHard(branch: string): Promise<number>;
|
|
23
|
+
/**
|
|
24
|
+
* Creates the `rsh` command.
|
|
25
|
+
* Resets current branch to origin/<branch> with confirmation.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createRshCommand(): Command;
|
package/src/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createEnvCommand, createRunCommand } from './commands';
|
|
1
|
+
export { createEnvCommand, createRunCommand, createCompletionCommand } from './commands';
|
|
2
2
|
export { exec, isWindows, defaultShell } from './core';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postinstall script for ggd CLI.
|
|
3
|
+
*
|
|
4
|
+
* Auto-installs shell completion on `npm install -g @gogd-core/ggd`.
|
|
5
|
+
* Gracefully skips if it cannot detect the shell or write to config files.
|
|
6
|
+
*/
|
|
7
|
+
type ShellType = 'bash' | 'zsh' | 'powershell' | 'unknown';
|
|
8
|
+
/**
|
|
9
|
+
* Detects the user's shell for postinstall context.
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectShellForInstall(): ShellType;
|
|
12
|
+
/**
|
|
13
|
+
* Returns the shell config file path for the given shell.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getShellConfigPath(shell: ShellType): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Returns the completion script for the given shell.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getCompletionScriptForShell(shell: ShellType): string | null;
|
|
20
|
+
/**
|
|
21
|
+
* Removes any existing ggd completion block from content.
|
|
22
|
+
*/
|
|
23
|
+
export declare function removeExistingCompletions(content: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Installs shell completions by appending to the shell config file.
|
|
26
|
+
* Returns true on success, false on skip/failure.
|
|
27
|
+
*/
|
|
28
|
+
export declare function installCompletions(shell: ShellType): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Main postinstall entry point.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runPostinstall(): void;
|
|
33
|
+
export {};
|