@jannael/glinter 1.1.1 → 1.2.1
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/README.md +29 -7
- package/dist/index.js +672 -54
- package/package.json +10 -8
package/README.md
CHANGED
|
@@ -1,23 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<br>
|
|
3
|
+
<br>
|
|
4
|
+
<a href="https://glinter.jannael.com" target="_blank" rel="noopener noreferrer">
|
|
5
|
+
<picture>
|
|
6
|
+
<img alt="Glinter" src="https://github.com/Jannael/glinter/raw/main/apps/web/public/og.png">
|
|
7
|
+
</picture>
|
|
8
|
+
</a>
|
|
9
|
+
<br>
|
|
10
|
+
<br>
|
|
11
|
+
<br>
|
|
12
|
+
</p>
|
|
2
13
|
|
|
3
|
-
Glinter is a high-performance, transparent Git wrapper built with **Bun**.
|
|
14
|
+
Glinter is a high-performance, transparent Git wrapper built with **Bun**.
|
|
15
|
+
|
|
16
|
+
[Commands](https://glinter.jannael.com/#commands)
|
|
17
|
+
|
|
18
|
+
[Aliases](https://glinter.jannael.com/alias)
|
|
19
|
+
|
|
20
|
+
[Quick start](https://glinter.jannael.com/#quick-start)
|
|
4
21
|
|
|
5
22
|
## Preview
|
|
6
23
|
|
|
7
|
-
<video src="https://github.com/user-attachments/assets/
|
|
24
|
+
<video src="https://github.com/user-attachments/assets/63b401a0-e1e1-453c-9e38-c36cd14e200f" controls="false" autoplay="true" loop="true" muted="true" style="max-width: 100%;">
|
|
8
25
|
Your browser does not support the video tag.
|
|
9
26
|
</video>
|
|
10
27
|
|
|
28
|
+
### Screenshots
|
|
11
29
|
|
|
12
|
-
|
|
30
|
+
| `g add` | `g commit` |
|
|
31
|
+
|---|---|
|
|
32
|
+
|  |  |
|
|
13
33
|
|
|
14
|
-
|
|
34
|
+
## Features
|
|
15
35
|
|
|
16
|
-
- **
|
|
36
|
+
- **Abbreviation**: You can use `g` instead of `git`.
|
|
17
37
|
|
|
18
38
|
- **Safe by Default**: Automatically filters and prevents accidental staging of sensitive files: `.env` and `node_modules`.
|
|
19
39
|
|
|
20
|
-
- **
|
|
40
|
+
- **Transparent Wrapper**: For every other command (like `commit`, `push`, `log`, or `status`), Glinter acts as a direct tunnel to Git. It preserves all original colors, formatting, and interactive features of the native Git CLI.
|
|
21
41
|
|
|
22
42
|
## How it works
|
|
23
43
|
|
|
@@ -52,7 +72,9 @@ npm install -g @jannael/glinter
|
|
|
52
72
|
now you can simply run:
|
|
53
73
|
```bash
|
|
54
74
|
g add # Opens the interactive selector
|
|
75
|
+
g commit # Opens commit type + message prompt
|
|
55
76
|
g add <file> # Runs standard git add <file>
|
|
77
|
+
g commit -m "" # Runs standard git commit -m ""
|
|
56
78
|
g status # Runs standard git status
|
|
57
79
|
g push # Runs standard git push
|
|
58
80
|
```
|
package/dist/index.js
CHANGED
|
@@ -90,22 +90,41 @@ var require_src = __commonJS((exports, module) => {
|
|
|
90
90
|
module.exports = { cursor, scroll, erase, beep };
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
//
|
|
94
|
-
var
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
93
|
+
// apps/cli/commands.ts
|
|
94
|
+
var AVAILABLE_COMMANDS = [
|
|
95
|
+
{
|
|
96
|
+
name: "add",
|
|
97
|
+
command: "g add",
|
|
98
|
+
description: "Interactive add",
|
|
99
|
+
allowGitArgs: true
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "commit",
|
|
103
|
+
command: "g commit",
|
|
104
|
+
description: "Interactive commit",
|
|
105
|
+
allowGitArgs: true
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "switch",
|
|
109
|
+
command: "g switch",
|
|
110
|
+
description: "Interactive switch",
|
|
111
|
+
allowGitArgs: true
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "alias",
|
|
115
|
+
command: "g alias",
|
|
116
|
+
description: "Show all the aliases",
|
|
117
|
+
allowGitArgs: false
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: "setup",
|
|
121
|
+
command: "g setup",
|
|
122
|
+
description: "Setup alias for git and glinter",
|
|
123
|
+
allowGitArgs: true
|
|
124
|
+
}
|
|
125
|
+
];
|
|
102
126
|
|
|
103
|
-
//
|
|
104
|
-
var X = ({ text }) => RED({ text: `\u2716 ${text}` });
|
|
105
|
-
var CHECK = ({ text }) => `${GREEN({ text: "\u2714" })} ${text}`;
|
|
106
|
-
var WARNING = ({ text }) => BG_YELLOW({ text: BLACK({ text: ` \u26A0 ${text}` }) });
|
|
107
|
-
|
|
108
|
-
// src/error/error-constructor.ts
|
|
127
|
+
// apps/cli/error/error-constructor.ts
|
|
109
128
|
function CreateError(name) {
|
|
110
129
|
const capitalize = (text) => text.charAt(0).toUpperCase() + text.slice(1);
|
|
111
130
|
return class extends Error {
|
|
@@ -118,14 +137,29 @@ function CreateError(name) {
|
|
|
118
137
|
};
|
|
119
138
|
}
|
|
120
139
|
|
|
121
|
-
//
|
|
140
|
+
// apps/cli/error/error-instance.ts
|
|
122
141
|
var NotFound = CreateError("NotFound");
|
|
123
142
|
var Forbidden = CreateError("Forbidden");
|
|
124
143
|
var Conflict = CreateError("Conflict");
|
|
125
144
|
var ServerError = CreateError("ServerError");
|
|
126
145
|
var BadRequest = CreateError("BadRequest");
|
|
127
146
|
|
|
128
|
-
//
|
|
147
|
+
// apps/cli/utils/colors.ts
|
|
148
|
+
var RESET = "\x1B[0m";
|
|
149
|
+
var GREEN = ({ text }) => `\x1B[32m${text}${RESET}`;
|
|
150
|
+
var YELLOW = ({ text }) => `\x1B[33m${text}${RESET}`;
|
|
151
|
+
var RED = ({ text }) => `\x1B[31m${text}${RESET}`;
|
|
152
|
+
var MAGENTA = ({ text }) => `\x1B[35m${text}${RESET}`;
|
|
153
|
+
var BLUE = ({ text }) => `\x1B[34m${text}${RESET}`;
|
|
154
|
+
var BLACK = ({ text }) => `\x1B[30m${text}${RESET}`;
|
|
155
|
+
var BG_YELLOW = ({ text }) => `\x1B[43m${text}${RESET}`;
|
|
156
|
+
|
|
157
|
+
// apps/cli/utils/icons-terminal.ts
|
|
158
|
+
var X = ({ text }) => RED({ text: `\u2716 ${text}` });
|
|
159
|
+
var CHECK = ({ text }) => `${GREEN({ text: "\u2714" })} ${text}`;
|
|
160
|
+
var WARNING = ({ text }) => BG_YELLOW({ text: BLACK({ text: ` \u26A0 ${text}` }) });
|
|
161
|
+
|
|
162
|
+
// apps/cli/error/error-handler.ts
|
|
129
163
|
function errorHandler(error) {
|
|
130
164
|
if (error instanceof ServerError) {
|
|
131
165
|
console.error(X({ text: error.message }));
|
|
@@ -147,6 +181,7 @@ function errorHandler(error) {
|
|
|
147
181
|
// node_modules/@clack/core/dist/index.mjs
|
|
148
182
|
import { styleText as y } from "util";
|
|
149
183
|
import { stdout as S, stdin as $ } from "process";
|
|
184
|
+
import * as _ from "readline";
|
|
150
185
|
import P from "readline";
|
|
151
186
|
|
|
152
187
|
// node_modules/fast-string-truncated-width/dist/utils.js
|
|
@@ -535,6 +570,7 @@ function wrapAnsi(string, columns, options) {
|
|
|
535
570
|
|
|
536
571
|
// node_modules/@clack/core/dist/index.mjs
|
|
537
572
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
573
|
+
import { ReadStream as D } from "tty";
|
|
538
574
|
function d(r, t, e) {
|
|
539
575
|
if (!e.some((o) => !o.disabled))
|
|
540
576
|
return r;
|
|
@@ -571,6 +607,28 @@ function w(r, t) {
|
|
|
571
607
|
const e = r;
|
|
572
608
|
e.isTTY && e.setRawMode(t);
|
|
573
609
|
}
|
|
610
|
+
function z({ input: r = $, output: t = S, overwrite: e = true, hideCursor: s = true } = {}) {
|
|
611
|
+
const i = _.createInterface({ input: r, output: t, prompt: "", tabSize: 1 });
|
|
612
|
+
_.emitKeypressEvents(r, i), r instanceof D && r.isTTY && r.setRawMode(true);
|
|
613
|
+
const n = (o, { name: a, sequence: h }) => {
|
|
614
|
+
const l = String(o);
|
|
615
|
+
if (V([l, a, h], "cancel")) {
|
|
616
|
+
s && t.write(import_sisteransi.cursor.show), process.exit(0);
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
if (!e)
|
|
620
|
+
return;
|
|
621
|
+
const f = a === "return" ? 0 : -1, v = a === "return" ? -1 : 0;
|
|
622
|
+
_.moveCursor(t, f, v, () => {
|
|
623
|
+
_.clearLine(t, 1, () => {
|
|
624
|
+
r.once("keypress", n);
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
};
|
|
628
|
+
return s && t.write(import_sisteransi.cursor.hide), r.once("keypress", n), () => {
|
|
629
|
+
r.off("keypress", n), s && t.write(import_sisteransi.cursor.show), r instanceof D && r.isTTY && !Y && r.setRawMode(false), i.terminal = false, i.close();
|
|
630
|
+
};
|
|
631
|
+
}
|
|
574
632
|
var O = (r) => ("columns" in r) && typeof r.columns == "number" ? r.columns : 80;
|
|
575
633
|
var A = (r) => ("rows" in r) && typeof r.rows == "number" ? r.rows : 20;
|
|
576
634
|
function R(r, t, e, s = e) {
|
|
@@ -785,6 +843,24 @@ var H = class extends p {
|
|
|
785
843
|
}
|
|
786
844
|
}
|
|
787
845
|
};
|
|
846
|
+
|
|
847
|
+
class Q extends p {
|
|
848
|
+
get cursor() {
|
|
849
|
+
return this.value ? 0 : 1;
|
|
850
|
+
}
|
|
851
|
+
get _value() {
|
|
852
|
+
return this.cursor === 0;
|
|
853
|
+
}
|
|
854
|
+
constructor(t) {
|
|
855
|
+
super(t, false), this.value = !!t.initialValue, this.on("userInput", () => {
|
|
856
|
+
this.value = this._value;
|
|
857
|
+
}), this.on("confirm", (e) => {
|
|
858
|
+
this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = e, this.state = "submit", this.close();
|
|
859
|
+
}), this.on("cursor", () => {
|
|
860
|
+
this.value = !this.value;
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
}
|
|
788
864
|
var X2 = { Y: { type: "year", len: 4 }, M: { type: "month", len: 2 }, D: { type: "day", len: 2 } };
|
|
789
865
|
function L(r) {
|
|
790
866
|
return [...r].map((t) => X2[t]);
|
|
@@ -1089,6 +1165,27 @@ class nt extends p {
|
|
|
1089
1165
|
});
|
|
1090
1166
|
}
|
|
1091
1167
|
}
|
|
1168
|
+
class at extends p {
|
|
1169
|
+
get userInputWithCursor() {
|
|
1170
|
+
if (this.state === "submit")
|
|
1171
|
+
return this.userInput;
|
|
1172
|
+
const t = this.userInput;
|
|
1173
|
+
if (this.cursor >= t.length)
|
|
1174
|
+
return `${this.userInput}\u2588`;
|
|
1175
|
+
const e = t.slice(0, this.cursor), [s, ...i] = t.slice(this.cursor);
|
|
1176
|
+
return `${e}${y("inverse", s)}${i.join("")}`;
|
|
1177
|
+
}
|
|
1178
|
+
get cursor() {
|
|
1179
|
+
return this._cursor;
|
|
1180
|
+
}
|
|
1181
|
+
constructor(t) {
|
|
1182
|
+
super({ ...t, initialUserInput: t.initialUserInput ?? t.initialValue }), this.on("userInput", (e) => {
|
|
1183
|
+
this._setValue(e);
|
|
1184
|
+
}), this.on("finalize", () => {
|
|
1185
|
+
this.value || (this.value = t.defaultValue), this.value === undefined && (this.value = "");
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1092
1189
|
|
|
1093
1190
|
// node_modules/@clack/prompts/dist/index.mjs
|
|
1094
1191
|
import { styleText as t, stripVTControlCharacters as ne } from "util";
|
|
@@ -1098,6 +1195,7 @@ function Ze() {
|
|
|
1098
1195
|
return P2.platform !== "win32" ? P2.env.TERM !== "linux" : !!P2.env.CI || !!P2.env.WT_SESSION || !!P2.env.TERMINUS_SUBLIME || P2.env.ConEmuTask === "{cmd::Cmder}" || P2.env.TERM_PROGRAM === "Terminus-Sublime" || P2.env.TERM_PROGRAM === "vscode" || P2.env.TERM === "xterm-256color" || P2.env.TERM === "alacritty" || P2.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
1099
1196
|
}
|
|
1100
1197
|
var ee = Ze();
|
|
1198
|
+
var ae = () => process.env.CI === "true";
|
|
1101
1199
|
var w2 = (e, i) => ee ? e : i;
|
|
1102
1200
|
var _e = w2("\u25C6", "*");
|
|
1103
1201
|
var oe = w2("\u25A0", "x");
|
|
@@ -1175,7 +1273,7 @@ var Y2 = ({ cursor: e, options: i, style: s, output: r = process.stdout, maxItem
|
|
|
1175
1273
|
}
|
|
1176
1274
|
if (f > $2) {
|
|
1177
1275
|
let b = 0, x = 0, G2 = f;
|
|
1178
|
-
const M2 = e - v, R2 = (j2,
|
|
1276
|
+
const M2 = e - v, R2 = (j2, D2) => et2(h, G2, j2, D2, $2);
|
|
1179
1277
|
m ? ({ lineCount: G2, removals: b } = R2(0, M2), G2 > $2 && ({ lineCount: G2, removals: x } = R2(M2 + 1, h.length))) : ({ lineCount: G2, removals: x } = R2(M2 + 1, h.length), G2 > $2 && ({ lineCount: G2, removals: b } = R2(0, M2))), b > 0 && (m = true, h.splice(0, b)), x > 0 && (g = true, h.splice(h.length - x, x));
|
|
1180
1278
|
}
|
|
1181
1279
|
const C2 = [];
|
|
@@ -1185,10 +1283,49 @@ var Y2 = ({ cursor: e, options: i, style: s, output: r = process.stdout, maxItem
|
|
|
1185
1283
|
C2.push(x);
|
|
1186
1284
|
return g && C2.push(l), C2;
|
|
1187
1285
|
};
|
|
1286
|
+
var ot2 = (e) => {
|
|
1287
|
+
const i = e.active ?? "Yes", s = e.inactive ?? "No";
|
|
1288
|
+
return new Q({ active: i, inactive: s, signal: e.signal, input: e.input, output: e.output, initialValue: e.initialValue ?? true, render() {
|
|
1289
|
+
const r = e.withGuide ?? u.withGuide, u2 = `${V2(this.state)} `, n = r ? `${t("gray", d2)} ` : "", o = R(e.output, e.message, n, u2), c2 = `${r ? `${t("gray", d2)}
|
|
1290
|
+
` : ""}${o}
|
|
1291
|
+
`, a = this.value ? i : s;
|
|
1292
|
+
switch (this.state) {
|
|
1293
|
+
case "submit": {
|
|
1294
|
+
const l = r ? `${t("gray", d2)} ` : "";
|
|
1295
|
+
return `${c2}${l}${t("dim", a)}`;
|
|
1296
|
+
}
|
|
1297
|
+
case "cancel": {
|
|
1298
|
+
const l = r ? `${t("gray", d2)} ` : "";
|
|
1299
|
+
return `${c2}${l}${t(["strikethrough", "dim"], a)}${r ? `
|
|
1300
|
+
${t("gray", d2)}` : ""}`;
|
|
1301
|
+
}
|
|
1302
|
+
default: {
|
|
1303
|
+
const l = r ? `${t("cyan", d2)} ` : "", $2 = r ? t("cyan", E2) : "";
|
|
1304
|
+
return `${c2}${l}${this.value ? `${t("green", z2)} ${i}` : `${t("dim", H2)} ${t("dim", i)}`}${e.vertical ? r ? `
|
|
1305
|
+
${t("cyan", d2)} ` : `
|
|
1306
|
+
` : ` ${t("dim", "/")} `}${this.value ? `${t("dim", H2)} ${t("dim", s)}` : `${t("green", z2)} ${s}`}
|
|
1307
|
+
${$2}
|
|
1308
|
+
`;
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
} }).prompt();
|
|
1312
|
+
};
|
|
1188
1313
|
var pt = (e = "", i) => {
|
|
1189
1314
|
const s = i?.output ?? process.stdout, r = i?.withGuide ?? u.withGuide ? `${t("gray", E2)} ` : "";
|
|
1190
1315
|
s.write(`${r}${t("red", e)}
|
|
1191
1316
|
|
|
1317
|
+
`);
|
|
1318
|
+
};
|
|
1319
|
+
var mt = (e = "", i) => {
|
|
1320
|
+
const s = i?.output ?? process.stdout, r = i?.withGuide ?? u.withGuide ? `${t("gray", le)} ` : "";
|
|
1321
|
+
s.write(`${r}${e}
|
|
1322
|
+
`);
|
|
1323
|
+
};
|
|
1324
|
+
var gt = (e = "", i) => {
|
|
1325
|
+
const s = i?.output ?? process.stdout, r = i?.withGuide ?? u.withGuide ? `${t("gray", d2)}
|
|
1326
|
+
${t("gray", E2)} ` : "";
|
|
1327
|
+
s.write(`${r}${e}
|
|
1328
|
+
|
|
1192
1329
|
`);
|
|
1193
1330
|
};
|
|
1194
1331
|
var Q2 = (e, i) => e.split(`
|
|
@@ -1247,6 +1384,64 @@ ${r ? t("cyan", E2) : ""}
|
|
|
1247
1384
|
}
|
|
1248
1385
|
} }).prompt();
|
|
1249
1386
|
};
|
|
1387
|
+
var Ct = (e) => t("magenta", e);
|
|
1388
|
+
var fe = ({ indicator: e = "dots", onCancel: i, output: s = process.stdout, cancelMessage: r, errorMessage: u2, frames: n = ee ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], delay: o = ee ? 80 : 120, signal: c2, ...a } = {}) => {
|
|
1389
|
+
const l = ae();
|
|
1390
|
+
let $2, y2, p2 = false, m = false, g = "", S2, h = performance.now();
|
|
1391
|
+
const f = O(s), v = a?.styleFrame ?? Ct, T2 = (_2) => {
|
|
1392
|
+
const A2 = _2 > 1 ? u2 ?? u.messages.error : r ?? u.messages.cancel;
|
|
1393
|
+
m = _2 === 1, p2 && (W2(A2, _2), m && typeof i == "function" && i());
|
|
1394
|
+
}, C2 = () => T2(2), b = () => T2(1), x = () => {
|
|
1395
|
+
process.on("uncaughtExceptionMonitor", C2), process.on("unhandledRejection", C2), process.on("SIGINT", b), process.on("SIGTERM", b), process.on("exit", T2), c2 && c2.addEventListener("abort", b);
|
|
1396
|
+
}, G2 = () => {
|
|
1397
|
+
process.removeListener("uncaughtExceptionMonitor", C2), process.removeListener("unhandledRejection", C2), process.removeListener("SIGINT", b), process.removeListener("SIGTERM", b), process.removeListener("exit", T2), c2 && c2.removeEventListener("abort", b);
|
|
1398
|
+
}, M2 = () => {
|
|
1399
|
+
if (S2 === undefined)
|
|
1400
|
+
return;
|
|
1401
|
+
l && s.write(`
|
|
1402
|
+
`);
|
|
1403
|
+
const _2 = wrapAnsi(S2, f, { hard: true, trim: false }).split(`
|
|
1404
|
+
`);
|
|
1405
|
+
_2.length > 1 && s.write(import_sisteransi2.cursor.up(_2.length - 1)), s.write(import_sisteransi2.cursor.to(0)), s.write(import_sisteransi2.erase.down());
|
|
1406
|
+
}, R2 = (_2) => _2.replace(/\.+$/, ""), j2 = (_2) => {
|
|
1407
|
+
const A2 = (performance.now() - _2) / 1000, k2 = Math.floor(A2 / 60), L2 = Math.floor(A2 % 60);
|
|
1408
|
+
return k2 > 0 ? `[${k2}m ${L2}s]` : `[${L2}s]`;
|
|
1409
|
+
}, D2 = a.withGuide ?? u.withGuide, ie = (_2 = "") => {
|
|
1410
|
+
p2 = true, $2 = z({ output: s }), g = R2(_2), h = performance.now(), D2 && s.write(`${t("gray", d2)}
|
|
1411
|
+
`);
|
|
1412
|
+
let A2 = 0, k2 = 0;
|
|
1413
|
+
x(), y2 = setInterval(() => {
|
|
1414
|
+
if (l && g === S2)
|
|
1415
|
+
return;
|
|
1416
|
+
M2(), S2 = g;
|
|
1417
|
+
const L2 = v(n[A2]);
|
|
1418
|
+
let Z2;
|
|
1419
|
+
if (l)
|
|
1420
|
+
Z2 = `${L2} ${g}...`;
|
|
1421
|
+
else if (e === "timer")
|
|
1422
|
+
Z2 = `${L2} ${g} ${j2(h)}`;
|
|
1423
|
+
else {
|
|
1424
|
+
const Be = ".".repeat(Math.floor(k2)).slice(0, 3);
|
|
1425
|
+
Z2 = `${L2} ${g}${Be}`;
|
|
1426
|
+
}
|
|
1427
|
+
const Ne = wrapAnsi(Z2, f, { hard: true, trim: false });
|
|
1428
|
+
s.write(Ne), A2 = A2 + 1 < n.length ? A2 + 1 : 0, k2 = k2 < 4 ? k2 + 0.125 : 0;
|
|
1429
|
+
}, o);
|
|
1430
|
+
}, W2 = (_2 = "", A2 = 0, k2 = false) => {
|
|
1431
|
+
if (!p2)
|
|
1432
|
+
return;
|
|
1433
|
+
p2 = false, clearInterval(y2), M2();
|
|
1434
|
+
const L2 = A2 === 0 ? t("green", F2) : A2 === 1 ? t("red", oe) : t("red", ue);
|
|
1435
|
+
g = _2 ?? g, k2 || (e === "timer" ? s.write(`${L2} ${g} ${j2(h)}
|
|
1436
|
+
`) : s.write(`${L2} ${g}
|
|
1437
|
+
`)), G2(), $2();
|
|
1438
|
+
};
|
|
1439
|
+
return { start: ie, stop: (_2 = "") => W2(_2, 0), message: (_2 = "") => {
|
|
1440
|
+
g = R2(_2 ?? g);
|
|
1441
|
+
}, cancel: (_2 = "") => W2(_2, 1), error: (_2 = "") => W2(_2, 2), clear: () => W2("", 0, true), get isCancelled() {
|
|
1442
|
+
return m;
|
|
1443
|
+
} };
|
|
1444
|
+
};
|
|
1250
1445
|
var Ve = { light: w2("\u2500", "-"), heavy: w2("\u2501", "="), block: w2("\u2588", "#") };
|
|
1251
1446
|
var re = (e, i) => e.includes(`
|
|
1252
1447
|
`) ? e.split(`
|
|
@@ -1294,8 +1489,37 @@ ${a}
|
|
|
1294
1489
|
} }).prompt();
|
|
1295
1490
|
};
|
|
1296
1491
|
var je = `${t("gray", d2)} `;
|
|
1492
|
+
var Ot = (e) => new at({ validate: e.validate, placeholder: e.placeholder, defaultValue: e.defaultValue, initialValue: e.initialValue, output: e.output, signal: e.signal, input: e.input, render() {
|
|
1493
|
+
const i = e?.withGuide ?? u.withGuide, s = `${`${i ? `${t("gray", d2)}
|
|
1494
|
+
` : ""}${V2(this.state)} `}${e.message}
|
|
1495
|
+
`, r = e.placeholder ? t("inverse", e.placeholder[0]) + t("dim", e.placeholder.slice(1)) : t(["inverse", "hidden"], "_"), u2 = this.userInput ? this.userInputWithCursor : r, n = this.value ?? "";
|
|
1496
|
+
switch (this.state) {
|
|
1497
|
+
case "error": {
|
|
1498
|
+
const o = this.error ? ` ${t("yellow", this.error)}` : "", c2 = i ? `${t("yellow", d2)} ` : "", a = i ? t("yellow", E2) : "";
|
|
1499
|
+
return `${s.trim()}
|
|
1500
|
+
${c2}${u2}
|
|
1501
|
+
${a}${o}
|
|
1502
|
+
`;
|
|
1503
|
+
}
|
|
1504
|
+
case "submit": {
|
|
1505
|
+
const o = n ? ` ${t("dim", n)}` : "", c2 = i ? t("gray", d2) : "";
|
|
1506
|
+
return `${s}${c2}${o}`;
|
|
1507
|
+
}
|
|
1508
|
+
case "cancel": {
|
|
1509
|
+
const o = n ? ` ${t(["strikethrough", "dim"], n)}` : "", c2 = i ? t("gray", d2) : "";
|
|
1510
|
+
return `${s}${c2}${o}${n.trim() ? `
|
|
1511
|
+
${c2}` : ""}`;
|
|
1512
|
+
}
|
|
1513
|
+
default: {
|
|
1514
|
+
const o = i ? `${t("cyan", d2)} ` : "", c2 = i ? t("cyan", E2) : "";
|
|
1515
|
+
return `${s}${o}${u2}
|
|
1516
|
+
${c2}
|
|
1517
|
+
`;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
} }).prompt();
|
|
1297
1521
|
|
|
1298
|
-
//
|
|
1522
|
+
// apps/cli/utils/multiselect.ts
|
|
1299
1523
|
async function MultiSelect({
|
|
1300
1524
|
message,
|
|
1301
1525
|
options
|
|
@@ -1312,7 +1536,7 @@ async function MultiSelect({
|
|
|
1312
1536
|
return selected;
|
|
1313
1537
|
}
|
|
1314
1538
|
|
|
1315
|
-
//
|
|
1539
|
+
// apps/cli/modules/add/app/add-command.ts
|
|
1316
1540
|
class AddCommand {
|
|
1317
1541
|
getChangesUseCase;
|
|
1318
1542
|
stageChangesUseCase;
|
|
@@ -1332,7 +1556,7 @@ class AddCommand {
|
|
|
1332
1556
|
];
|
|
1333
1557
|
const selectedChanges = await MultiSelect({
|
|
1334
1558
|
message: `Select the changes you want to commit.
|
|
1335
|
-
` + BLUE({ text: "[space] to select
|
|
1559
|
+
` + BLUE({ text: "[space] to select" }) + `
|
|
1336
1560
|
` + GREEN({ text: "[enter] to confirm" }) + `
|
|
1337
1561
|
` + MAGENTA({ text: "[a] to select all" }) + `
|
|
1338
1562
|
` + RED({ text: "[esc] to cancel" }) + `
|
|
@@ -1360,7 +1584,7 @@ ${WARNING({ text: " WARNING " })}`);
|
|
|
1360
1584
|
}
|
|
1361
1585
|
}
|
|
1362
1586
|
|
|
1363
|
-
//
|
|
1587
|
+
// apps/cli/modules/add/domain/change.ts
|
|
1364
1588
|
class Change {
|
|
1365
1589
|
props;
|
|
1366
1590
|
constructor(props) {
|
|
@@ -1427,7 +1651,7 @@ class Change {
|
|
|
1427
1651
|
}
|
|
1428
1652
|
}
|
|
1429
1653
|
|
|
1430
|
-
//
|
|
1654
|
+
// apps/cli/modules/add/app/get-changes.use-case.ts
|
|
1431
1655
|
class GetChangesUseCase {
|
|
1432
1656
|
gitRepository;
|
|
1433
1657
|
constructor(gitRepository) {
|
|
@@ -1454,7 +1678,7 @@ class GetChangesUseCase {
|
|
|
1454
1678
|
}
|
|
1455
1679
|
}
|
|
1456
1680
|
|
|
1457
|
-
//
|
|
1681
|
+
// apps/cli/modules/add/app/stage-changes.use-case.ts
|
|
1458
1682
|
class StageChangesUseCase {
|
|
1459
1683
|
gitRepository;
|
|
1460
1684
|
constructor(gitRepository) {
|
|
@@ -1467,7 +1691,7 @@ class StageChangesUseCase {
|
|
|
1467
1691
|
}
|
|
1468
1692
|
}
|
|
1469
1693
|
|
|
1470
|
-
//
|
|
1694
|
+
// apps/cli/modules/add/infra/bun-git.repository.ts
|
|
1471
1695
|
var {$: $2 } = globalThis.Bun;
|
|
1472
1696
|
class BunGitRepository {
|
|
1473
1697
|
async getEntries() {
|
|
@@ -1494,7 +1718,7 @@ class BunGitRepository {
|
|
|
1494
1718
|
}
|
|
1495
1719
|
}
|
|
1496
1720
|
|
|
1497
|
-
//
|
|
1721
|
+
// apps/cli/modules/add/main.ts
|
|
1498
1722
|
async function addCommand() {
|
|
1499
1723
|
const gitRepository = new BunGitRepository;
|
|
1500
1724
|
const getChangesUseCase = new GetChangesUseCase(gitRepository);
|
|
@@ -1503,7 +1727,405 @@ async function addCommand() {
|
|
|
1503
1727
|
await addCommand2.execute();
|
|
1504
1728
|
}
|
|
1505
1729
|
|
|
1506
|
-
//
|
|
1730
|
+
// apps/cli/alias.ts
|
|
1731
|
+
var ALIASES = [
|
|
1732
|
+
{ name: "gs", command: "status -sb", kind: "git" },
|
|
1733
|
+
{
|
|
1734
|
+
name: "gl",
|
|
1735
|
+
command: "log --oneline --decorate --graph --all -n 20",
|
|
1736
|
+
kind: "git"
|
|
1737
|
+
},
|
|
1738
|
+
{ name: "gll", command: "log --stat", kind: "git" },
|
|
1739
|
+
{ name: "gd", command: "diff --word-diff=color", kind: "git" },
|
|
1740
|
+
{ name: "gds", command: "diff --staged --word-diff=color", kind: "git" },
|
|
1741
|
+
{ name: "ga", command: "add", kind: "glinter" },
|
|
1742
|
+
{ name: "gaa", command: "add -A", kind: "git" },
|
|
1743
|
+
{ name: "gc", command: "commit", kind: "glinter" },
|
|
1744
|
+
{ name: "gcm", command: "commit -m", kind: "git" },
|
|
1745
|
+
{ name: "gca", command: "commit --amend", kind: "git" },
|
|
1746
|
+
{ name: "gcan", command: "commit --amend --no-edit", kind: "git" },
|
|
1747
|
+
{ name: "gb", command: "branch", kind: "git" },
|
|
1748
|
+
{ name: "gba", command: "branch -a", kind: "git" },
|
|
1749
|
+
{ name: "gco", command: "switch", kind: "glinter" },
|
|
1750
|
+
{ name: "gcb", command: "checkout -b", kind: "git" },
|
|
1751
|
+
{ name: "gpl", command: "pull", kind: "git" },
|
|
1752
|
+
{ name: "gplr", command: "pull --rebase", kind: "git" },
|
|
1753
|
+
{ name: "gp", command: "push", kind: "git" },
|
|
1754
|
+
{ name: "ggpush", command: "push origin HEAD", kind: "git" },
|
|
1755
|
+
{ name: "gpf", command: "push --force-with-lease", kind: "git" },
|
|
1756
|
+
{ name: "gst", command: "stash", kind: "git" },
|
|
1757
|
+
{ name: "gstp", command: "stash pop", kind: "git" },
|
|
1758
|
+
{ name: "gstl", command: "stash list", kind: "git" },
|
|
1759
|
+
{ name: "gcl", command: "clean -fd", kind: "git" },
|
|
1760
|
+
{ name: "grh", command: "reset --hard", kind: "git" }
|
|
1761
|
+
];
|
|
1762
|
+
|
|
1763
|
+
// apps/cli/modules/alias/main.ts
|
|
1764
|
+
function resolveAlias(name, command) {
|
|
1765
|
+
return { name, value: command };
|
|
1766
|
+
}
|
|
1767
|
+
function printAliases({
|
|
1768
|
+
title = "The following aliases are configured by setup:"
|
|
1769
|
+
} = {}) {
|
|
1770
|
+
console.log(YELLOW({ text: `
|
|
1771
|
+
${title}
|
|
1772
|
+
` }));
|
|
1773
|
+
for (const alias of ALIASES) {
|
|
1774
|
+
const tag = alias.kind === "glinter" ? MAGENTA({ text: "[glinter]" }) : BLUE({ text: "[git] " });
|
|
1775
|
+
const { name, value } = resolveAlias(alias.name, alias.command);
|
|
1776
|
+
console.log(` ${tag} ${GREEN({ text: name.padEnd(8) })} \u2192 ${value}`);
|
|
1777
|
+
}
|
|
1778
|
+
console.log("");
|
|
1779
|
+
}
|
|
1780
|
+
async function aliasCommand() {
|
|
1781
|
+
printAliases();
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
// apps/cli/modules/commit/app/commit.use-case.ts
|
|
1785
|
+
class CommitUseCase {
|
|
1786
|
+
commitRepository;
|
|
1787
|
+
constructor(commitRepository) {
|
|
1788
|
+
this.commitRepository = commitRepository;
|
|
1789
|
+
}
|
|
1790
|
+
async execute({ message }) {
|
|
1791
|
+
await this.commitRepository.commit(message);
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
// apps/cli/commit-options.ts
|
|
1796
|
+
var commitTypeOptions = [
|
|
1797
|
+
{
|
|
1798
|
+
value: "feat",
|
|
1799
|
+
label: `${GREEN({ text: "feat" })}: A new feature`
|
|
1800
|
+
},
|
|
1801
|
+
{
|
|
1802
|
+
value: "fix",
|
|
1803
|
+
label: `${GREEN({ text: "fix" })}: A bug fix`
|
|
1804
|
+
},
|
|
1805
|
+
{
|
|
1806
|
+
value: "chore",
|
|
1807
|
+
label: `${GREEN({ text: "chore" })}: Routine maintenance`
|
|
1808
|
+
},
|
|
1809
|
+
{
|
|
1810
|
+
value: "docs",
|
|
1811
|
+
label: `${GREEN({ text: "docs" })}: Documentation updates`
|
|
1812
|
+
},
|
|
1813
|
+
{
|
|
1814
|
+
value: "refactor",
|
|
1815
|
+
label: `${GREEN({ text: "refactor" })}: Code changes without behavior change`
|
|
1816
|
+
},
|
|
1817
|
+
{
|
|
1818
|
+
value: "test",
|
|
1819
|
+
label: `${GREEN({ text: "test" })}: Add or update tests`
|
|
1820
|
+
},
|
|
1821
|
+
{
|
|
1822
|
+
value: "perf",
|
|
1823
|
+
label: `${GREEN({ text: "perf" })}: Performance improvements`
|
|
1824
|
+
},
|
|
1825
|
+
{
|
|
1826
|
+
value: "style",
|
|
1827
|
+
label: `${GREEN({ text: "style" })}: Formatting or style-only changes`
|
|
1828
|
+
}
|
|
1829
|
+
];
|
|
1830
|
+
|
|
1831
|
+
// apps/cli/utils/input.ts
|
|
1832
|
+
async function Input({
|
|
1833
|
+
message,
|
|
1834
|
+
placeholder
|
|
1835
|
+
}) {
|
|
1836
|
+
const value = await Ot({
|
|
1837
|
+
message,
|
|
1838
|
+
placeholder,
|
|
1839
|
+
validate(input) {
|
|
1840
|
+
if (!input?.trim()) {
|
|
1841
|
+
return "Commit message is required.";
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
});
|
|
1845
|
+
if (q(value)) {
|
|
1846
|
+
pt("Operation cancelled.");
|
|
1847
|
+
process.exit(0);
|
|
1848
|
+
}
|
|
1849
|
+
return value.trim();
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
// apps/cli/utils/select.ts
|
|
1853
|
+
async function Select({
|
|
1854
|
+
message,
|
|
1855
|
+
options
|
|
1856
|
+
}) {
|
|
1857
|
+
const selected = await _t({
|
|
1858
|
+
message,
|
|
1859
|
+
options
|
|
1860
|
+
});
|
|
1861
|
+
if (q(selected)) {
|
|
1862
|
+
pt("Operation cancelled.");
|
|
1863
|
+
process.exit(0);
|
|
1864
|
+
}
|
|
1865
|
+
return selected;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
// apps/cli/modules/commit/app/commit-command.ts
|
|
1869
|
+
class CommitCommand {
|
|
1870
|
+
commitUseCase;
|
|
1871
|
+
constructor(commitUseCase) {
|
|
1872
|
+
this.commitUseCase = commitUseCase;
|
|
1873
|
+
}
|
|
1874
|
+
async execute() {
|
|
1875
|
+
try {
|
|
1876
|
+
const commitType = await Select({
|
|
1877
|
+
message: "Select the commit type.",
|
|
1878
|
+
options: commitTypeOptions
|
|
1879
|
+
});
|
|
1880
|
+
const commitDescription = await Input({
|
|
1881
|
+
message: "Write your commit message.",
|
|
1882
|
+
placeholder: "e.g. add interactive commit flow"
|
|
1883
|
+
});
|
|
1884
|
+
await this.commitUseCase.execute({
|
|
1885
|
+
message: `${commitType}: ${commitDescription}`
|
|
1886
|
+
});
|
|
1887
|
+
} catch (error) {
|
|
1888
|
+
errorHandler(error);
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
// apps/cli/modules/commit/infra/bun-commit.repository.ts
|
|
1894
|
+
class BunCommitRepository {
|
|
1895
|
+
async commit(message) {
|
|
1896
|
+
const proc = Bun.spawn(["git", "commit", "-m", message], {
|
|
1897
|
+
stdio: ["inherit", "inherit", "inherit"]
|
|
1898
|
+
});
|
|
1899
|
+
const exitCode = await proc.exited;
|
|
1900
|
+
if (exitCode !== 0) {
|
|
1901
|
+
throw new ServerError("Git commit failed", "Could not create commit from interactive prompt");
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
// apps/cli/modules/commit/main.ts
|
|
1907
|
+
async function commitCommand() {
|
|
1908
|
+
const commitRepository = new BunCommitRepository;
|
|
1909
|
+
const commitUseCase = new CommitUseCase(commitRepository);
|
|
1910
|
+
const commitCommand2 = new CommitCommand(commitUseCase);
|
|
1911
|
+
await commitCommand2.execute();
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
// apps/cli/modules/setup/app/setup-aliases.use-case.ts
|
|
1915
|
+
class SetupAliasesUseCase {
|
|
1916
|
+
aliasRepository;
|
|
1917
|
+
constructor(aliasRepository) {
|
|
1918
|
+
this.aliasRepository = aliasRepository;
|
|
1919
|
+
}
|
|
1920
|
+
async execute() {
|
|
1921
|
+
for (const alias of ALIASES) {
|
|
1922
|
+
const { name, value } = this.resolveAlias(alias.name, alias.command, alias.kind);
|
|
1923
|
+
await this.aliasRepository.setAlias(name, value);
|
|
1924
|
+
}
|
|
1925
|
+
return { total: ALIASES.length };
|
|
1926
|
+
}
|
|
1927
|
+
resolveAlias(name, command, kind) {
|
|
1928
|
+
const aliasCommand2 = kind === "git" ? `git ${command}` : `g ${command}`;
|
|
1929
|
+
return { name, value: aliasCommand2 };
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
// apps/cli/utils/confirm.ts
|
|
1934
|
+
async function Confirm({
|
|
1935
|
+
message,
|
|
1936
|
+
cancelMessage,
|
|
1937
|
+
exitOnCancel = true
|
|
1938
|
+
}) {
|
|
1939
|
+
const confirmed = await ot2({
|
|
1940
|
+
message
|
|
1941
|
+
});
|
|
1942
|
+
if (q(confirmed)) {
|
|
1943
|
+
if (exitOnCancel) {
|
|
1944
|
+
pt(cancelMessage ?? "Operation cancelled.");
|
|
1945
|
+
process.exit(0);
|
|
1946
|
+
}
|
|
1947
|
+
return null;
|
|
1948
|
+
}
|
|
1949
|
+
return confirmed;
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
// apps/cli/utils/intro.ts
|
|
1953
|
+
function Intro(message) {
|
|
1954
|
+
mt(message);
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
// apps/cli/utils/outro.ts
|
|
1958
|
+
function Outro(message) {
|
|
1959
|
+
gt(message);
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
// apps/cli/utils/spinner.ts
|
|
1963
|
+
function Spinner() {
|
|
1964
|
+
return fe();
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
// apps/cli/modules/setup/app/setup-command.ts
|
|
1968
|
+
class SetupCommand {
|
|
1969
|
+
setupAliasesUseCase;
|
|
1970
|
+
constructor(setupAliasesUseCase) {
|
|
1971
|
+
this.setupAliasesUseCase = setupAliasesUseCase;
|
|
1972
|
+
}
|
|
1973
|
+
async execute() {
|
|
1974
|
+
try {
|
|
1975
|
+
Intro(MAGENTA({ text: " Glinter Setup " }));
|
|
1976
|
+
printAliases({ title: "The following aliases will be set globally:" });
|
|
1977
|
+
const confirmed = await Confirm({
|
|
1978
|
+
message: "Apply these aliases to your global git config?",
|
|
1979
|
+
exitOnCancel: false
|
|
1980
|
+
});
|
|
1981
|
+
if (!confirmed) {
|
|
1982
|
+
Outro("Setup cancelled.");
|
|
1983
|
+
return;
|
|
1984
|
+
}
|
|
1985
|
+
const spinner = Spinner();
|
|
1986
|
+
spinner.start("Writing aliases...");
|
|
1987
|
+
const { total } = await this.setupAliasesUseCase.execute();
|
|
1988
|
+
console.log("");
|
|
1989
|
+
spinner.stop(`${CHECK({ text: `${total} aliases configured successfully.` })}`);
|
|
1990
|
+
Outro(`${GREEN({ text: "GLINTER" })}, if you like the project, give a star on github: https://github.com/jannael/glinter`);
|
|
1991
|
+
console.log("");
|
|
1992
|
+
console.log(MAGENTA({ text: "To use the aliases, please restart your terminal." }));
|
|
1993
|
+
} catch (error) {
|
|
1994
|
+
errorHandler(error);
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
// apps/cli/modules/setup/infra/bun-alias-unix.ts
|
|
2000
|
+
import fs from "fs";
|
|
2001
|
+
import os from "os";
|
|
2002
|
+
import path from "path";
|
|
2003
|
+
|
|
2004
|
+
class BunAliasUnix {
|
|
2005
|
+
async setAlias(name, value) {
|
|
2006
|
+
const profilePath = this.getUnixProfilePath();
|
|
2007
|
+
fs.mkdirSync(path.dirname(profilePath), { recursive: true });
|
|
2008
|
+
const current = fs.existsSync(profilePath) ? fs.readFileSync(profilePath, "utf8") : "";
|
|
2009
|
+
const updated = this.upsertUnixProfileAlias(current, name, value);
|
|
2010
|
+
fs.writeFileSync(profilePath, updated);
|
|
2011
|
+
}
|
|
2012
|
+
upsertUnixProfileAlias(content, name, value) {
|
|
2013
|
+
const escapedName = this.escapeRegex(name);
|
|
2014
|
+
const escapedValue = this.escapeSingleQuotes(value);
|
|
2015
|
+
const aliasLine = `alias ${name}='${escapedValue}'`;
|
|
2016
|
+
const aliasRegex = new RegExp(`^alias ${escapedName}=.*\\r?\\n?`, "gm");
|
|
2017
|
+
const cleaned = content.replace(aliasRegex, "").trimEnd();
|
|
2018
|
+
const prefix = cleaned.length > 0 ? `${cleaned}
|
|
2019
|
+
` : "";
|
|
2020
|
+
return `${prefix}${aliasLine}
|
|
2021
|
+
`;
|
|
2022
|
+
}
|
|
2023
|
+
getUnixProfilePath() {
|
|
2024
|
+
const home = os.homedir();
|
|
2025
|
+
const shellName = path.basename(process.env.SHELL ?? "");
|
|
2026
|
+
const preferredProfile = shellName === "zsh" ? ".zshrc" : shellName === "bash" ? ".bashrc" : ".profile";
|
|
2027
|
+
const candidates = [preferredProfile, ".bashrc", ".zshrc", ".profile"];
|
|
2028
|
+
const uniqueCandidates = [...new Set(candidates)];
|
|
2029
|
+
for (const candidate of uniqueCandidates) {
|
|
2030
|
+
const candidatePath = path.join(home, candidate);
|
|
2031
|
+
if (fs.existsSync(candidatePath)) {
|
|
2032
|
+
return candidatePath;
|
|
2033
|
+
}
|
|
2034
|
+
}
|
|
2035
|
+
return path.join(home, preferredProfile);
|
|
2036
|
+
}
|
|
2037
|
+
escapeRegex(value) {
|
|
2038
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2039
|
+
}
|
|
2040
|
+
escapeSingleQuotes(value) {
|
|
2041
|
+
return value.replace(/'/g, `'"'"'`);
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
// apps/cli/modules/setup/infra/bun-alias-windows.ts
|
|
2046
|
+
import fs2 from "fs";
|
|
2047
|
+
import os2 from "os";
|
|
2048
|
+
import path2 from "path";
|
|
2049
|
+
|
|
2050
|
+
class BunAliasWindows {
|
|
2051
|
+
async setAlias(name, value) {
|
|
2052
|
+
const psProfilePath = this.getWindowsProfilePath();
|
|
2053
|
+
fs2.mkdirSync(path2.dirname(psProfilePath), { recursive: true });
|
|
2054
|
+
const current = fs2.existsSync(psProfilePath) ? fs2.readFileSync(psProfilePath, "utf8") : "";
|
|
2055
|
+
const updated = this.upsertWindowsProfileFunction(current, name, value);
|
|
2056
|
+
fs2.writeFileSync(psProfilePath, updated);
|
|
2057
|
+
}
|
|
2058
|
+
upsertWindowsProfileFunction(content, name, value) {
|
|
2059
|
+
const escapedName = this.escapeRegex(name);
|
|
2060
|
+
const removeAliasLine = `if (Get-Alias -Name ${name} -ErrorAction SilentlyContinue) { Remove-Item Alias:${name} -Force }`;
|
|
2061
|
+
const functionLine = `function ${name} { ${value} @args }`;
|
|
2062
|
+
const removeAliasRegex = new RegExp(`^if \\(Get-Alias -Name ${escapedName} -ErrorAction SilentlyContinue\\) \\{ Remove-Item Alias:${escapedName} -Force \\}\\r?\\n?`, "gm");
|
|
2063
|
+
const functionRegex = new RegExp(`^function ${escapedName} \\{[^\\r\\n]*\\}\\r?\\n?`, "gm");
|
|
2064
|
+
const cleaned = content.replace(removeAliasRegex, "").replace(functionRegex, "").trimEnd();
|
|
2065
|
+
const prefix = cleaned.length > 0 ? `${cleaned}
|
|
2066
|
+
` : "";
|
|
2067
|
+
return `${prefix}${removeAliasLine}
|
|
2068
|
+
${functionLine}
|
|
2069
|
+
`;
|
|
2070
|
+
}
|
|
2071
|
+
escapeRegex(value) {
|
|
2072
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2073
|
+
}
|
|
2074
|
+
getWindowsProfilePath() {
|
|
2075
|
+
return path2.join(this.getWindowsDocumentsPath(), "PowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
2076
|
+
}
|
|
2077
|
+
getWindowsDocumentsPath() {
|
|
2078
|
+
const proc = Bun.spawnSync([
|
|
2079
|
+
"powershell",
|
|
2080
|
+
"-NoProfile",
|
|
2081
|
+
"-Command",
|
|
2082
|
+
"[Environment]::GetFolderPath('MyDocuments')"
|
|
2083
|
+
], {
|
|
2084
|
+
stdout: "pipe",
|
|
2085
|
+
stderr: "pipe"
|
|
2086
|
+
});
|
|
2087
|
+
if (proc.exitCode === 0) {
|
|
2088
|
+
const docsPath = new TextDecoder().decode(proc.stdout).trim();
|
|
2089
|
+
if (docsPath.length > 0) {
|
|
2090
|
+
return docsPath;
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
return path2.join(os2.homedir(), "Documents");
|
|
2094
|
+
}
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
// apps/cli/modules/setup/infra/bun-alias.repository.ts
|
|
2098
|
+
class BunAliasRepository {
|
|
2099
|
+
getOS() {
|
|
2100
|
+
return process.platform === "win32" ? "windows" : "unix";
|
|
2101
|
+
}
|
|
2102
|
+
async setAlias(name, value) {
|
|
2103
|
+
try {
|
|
2104
|
+
const system = this.getOS();
|
|
2105
|
+
if (system === "windows") {
|
|
2106
|
+
const bunAliasWindows = new BunAliasWindows;
|
|
2107
|
+
await bunAliasWindows.setAlias(name, value);
|
|
2108
|
+
}
|
|
2109
|
+
if (system === "unix") {
|
|
2110
|
+
const bunAliasUnix = new BunAliasUnix;
|
|
2111
|
+
await bunAliasUnix.setAlias(name, value);
|
|
2112
|
+
}
|
|
2113
|
+
console.log(` ${MAGENTA({ text: name.padEnd(8) })} set ${GREEN({ text: "successfully".padStart(10) })}`);
|
|
2114
|
+
} catch {
|
|
2115
|
+
throw new ServerError("Unexpected execution error", `Failed to set alias: ${name}`);
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
// apps/cli/modules/setup/main.ts
|
|
2121
|
+
async function setupCommand() {
|
|
2122
|
+
const aliasRepository = new BunAliasRepository;
|
|
2123
|
+
const setupAliasesUseCase = new SetupAliasesUseCase(aliasRepository);
|
|
2124
|
+
const setupCommand2 = new SetupCommand(setupAliasesUseCase);
|
|
2125
|
+
await setupCommand2.execute();
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
// apps/cli/modules/switch/domain/branch.ts
|
|
1507
2129
|
class Branch {
|
|
1508
2130
|
props;
|
|
1509
2131
|
constructor(props) {
|
|
@@ -1539,7 +2161,7 @@ class Branch {
|
|
|
1539
2161
|
}
|
|
1540
2162
|
}
|
|
1541
2163
|
|
|
1542
|
-
//
|
|
2164
|
+
// apps/cli/modules/switch/app/get-branches.use-case.ts
|
|
1543
2165
|
class GetBranchesUseCase {
|
|
1544
2166
|
branchRepository;
|
|
1545
2167
|
constructor(branchRepository) {
|
|
@@ -1552,7 +2174,7 @@ class GetBranchesUseCase {
|
|
|
1552
2174
|
}
|
|
1553
2175
|
}
|
|
1554
2176
|
|
|
1555
|
-
//
|
|
2177
|
+
// apps/cli/modules/switch/app/switch-branch.use-case.ts
|
|
1556
2178
|
class SwitchBranch {
|
|
1557
2179
|
branchRepository;
|
|
1558
2180
|
constructor(branchRepository) {
|
|
@@ -1563,23 +2185,7 @@ class SwitchBranch {
|
|
|
1563
2185
|
}
|
|
1564
2186
|
}
|
|
1565
2187
|
|
|
1566
|
-
//
|
|
1567
|
-
async function Select({
|
|
1568
|
-
message,
|
|
1569
|
-
options
|
|
1570
|
-
}) {
|
|
1571
|
-
const selected = await _t({
|
|
1572
|
-
message,
|
|
1573
|
-
options
|
|
1574
|
-
});
|
|
1575
|
-
if (q(selected)) {
|
|
1576
|
-
pt("Operation cancelled.");
|
|
1577
|
-
process.exit(0);
|
|
1578
|
-
}
|
|
1579
|
-
return selected;
|
|
1580
|
-
}
|
|
1581
|
-
|
|
1582
|
-
// src/modules/switch/app/switch-command.ts
|
|
2188
|
+
// apps/cli/modules/switch/app/switch-command.ts
|
|
1583
2189
|
class SwitchCommand {
|
|
1584
2190
|
getBranchesUseCase;
|
|
1585
2191
|
switchBranch;
|
|
@@ -1624,7 +2230,7 @@ class SwitchCommand {
|
|
|
1624
2230
|
}
|
|
1625
2231
|
}
|
|
1626
2232
|
|
|
1627
|
-
//
|
|
2233
|
+
// apps/cli/modules/switch/infra/bun-switch-repository.ts
|
|
1628
2234
|
var {$: $3 } = globalThis.Bun;
|
|
1629
2235
|
class BunSwitchRepository {
|
|
1630
2236
|
async getBranches() {
|
|
@@ -1650,7 +2256,7 @@ class BunSwitchRepository {
|
|
|
1650
2256
|
}
|
|
1651
2257
|
}
|
|
1652
2258
|
|
|
1653
|
-
//
|
|
2259
|
+
// apps/cli/modules/switch/main.ts
|
|
1654
2260
|
async function switchCommand() {
|
|
1655
2261
|
const switchRepo = new BunSwitchRepository;
|
|
1656
2262
|
const switchBranchUseCase = new SwitchBranch(switchRepo);
|
|
@@ -1659,13 +2265,25 @@ async function switchCommand() {
|
|
|
1659
2265
|
await switchCommand2.execute();
|
|
1660
2266
|
}
|
|
1661
2267
|
|
|
1662
|
-
//
|
|
2268
|
+
// apps/cli/commands-fn.ts
|
|
2269
|
+
var COMMANDS_FN = {
|
|
2270
|
+
add: addCommand,
|
|
2271
|
+
commit: commitCommand,
|
|
2272
|
+
switch: switchCommand,
|
|
2273
|
+
alias: aliasCommand,
|
|
2274
|
+
setup: setupCommand
|
|
2275
|
+
};
|
|
2276
|
+
|
|
2277
|
+
// apps/cli/index.ts
|
|
1663
2278
|
var args = Bun.argv.slice(2);
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
2279
|
+
var command = AVAILABLE_COMMANDS.find((command2) => command2.name === args[0]);
|
|
2280
|
+
if (command) {
|
|
2281
|
+
if (args.length > 1 && !command.allowGitArgs) {
|
|
2282
|
+
console.error("This command does not accept any arguments");
|
|
2283
|
+
process.exit(1);
|
|
2284
|
+
}
|
|
2285
|
+
await COMMANDS_FN[command.name]?.(args.slice(1));
|
|
2286
|
+
} else {
|
|
1669
2287
|
const proc = Bun.spawn(["git", ...args], {
|
|
1670
2288
|
stdio: ["inherit", "inherit", "inherit"]
|
|
1671
2289
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jannael/glinter",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "A high-performance, transparent Git wrapper with interactive staging",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"name": "Jannael",
|
|
14
14
|
"url": "https://github.com/jannael"
|
|
15
15
|
},
|
|
16
|
-
"homepage": "https://
|
|
16
|
+
"homepage": "https://glinter.jannael.com",
|
|
17
17
|
"bugs": {
|
|
18
18
|
"url": "https://github.com/jannael/glinter/issues"
|
|
19
19
|
},
|
|
@@ -34,12 +34,13 @@
|
|
|
34
34
|
".": "./dist/index.js"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
37
|
+
"build:cli": "bun build ./apps/cli/index.ts --outfile=./dist/index.js --target=bun",
|
|
38
|
+
"prepublishOnly": "bun run build:cli",
|
|
39
|
+
|
|
40
40
|
"test": "vitest",
|
|
41
41
|
"lint": "biome check",
|
|
42
|
-
"lint:fix": "biome format --write"
|
|
42
|
+
"lint:fix": "biome format --write",
|
|
43
|
+
"type-check": "bunx tsc --noEmit"
|
|
43
44
|
},
|
|
44
45
|
"bin": {
|
|
45
46
|
"g": "./dist/index.js"
|
|
@@ -50,7 +51,8 @@
|
|
|
50
51
|
"devDependencies": {
|
|
51
52
|
"@biomejs/biome": "2.4.10",
|
|
52
53
|
"@types/bun": "latest",
|
|
53
|
-
"vitest": "4.1.4"
|
|
54
|
+
"vitest": "4.1.4",
|
|
55
|
+
"wrangler": "4.84.1"
|
|
54
56
|
},
|
|
55
57
|
"peerDependencies": {
|
|
56
58
|
"bun": ">=1.0.0",
|
|
@@ -59,4 +61,4 @@
|
|
|
59
61
|
"dependencies": {
|
|
60
62
|
"@clack/prompts": "1.2.0"
|
|
61
63
|
}
|
|
62
|
-
}
|
|
64
|
+
}
|