@jannael/glinter 1.2.8 → 1.2.9
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 +104 -104
- package/dist/index.js +122 -118
- package/package.json +14 -18
package/README.md
CHANGED
|
@@ -1,104 +1,104 @@
|
|
|
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
|
-
</p>
|
|
10
|
-
|
|
11
|
-
Glinter is a high-performance, transparent Git wrapper built with **Bun**.
|
|
12
|
-
|
|
13
|
-
[Tutorial](https://youtu.be/LQWp6flYeyI)
|
|
14
|
-
|
|
15
|
-
[Commands](https://glinter.jannael.com/#commands)
|
|
16
|
-
|
|
17
|
-
[Aliases](https://glinter.jannael.com/alias)
|
|
18
|
-
|
|
19
|
-
[Quick start](https://glinter.jannael.com/#quick-start)
|
|
20
|
-
|
|
21
|
-
## Preview
|
|
22
|
-
|
|
23
|
-
### Badge
|
|
24
|
-
|
|
25
|
-
| Preview | Copy |
|
|
26
|
-
| -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
27
|
-
| [](https://glinter.jannael.com) | `[](https://glinter.jannael.com)` |
|
|
28
|
-
|
|
29
|
-
<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%;">
|
|
30
|
-
Your browser does not support the video tag.
|
|
31
|
-
</video>
|
|
32
|
-
|
|
33
|
-
### Screenshots
|
|
34
|
-
|
|
35
|
-
| `g add` | `g commit` |
|
|
36
|
-
| ------------------------------------ | --------------------------------------- |
|
|
37
|
-
|  |  |
|
|
38
|
-
|
|
39
|
-
## Security
|
|
40
|
-
|
|
41
|
-
Security is a top priority for this project.
|
|
42
|
-
|
|
43
|
-
This project uses Bun as its runtime and package manager. You don't need to worry about package vulnerabilities — the `bunfig.toml` configuration includes `minimumReleaseAge = 259200` (3 days), which prevents newly published packages from being installed automatically. This protects against supply chain attacks that have become increasingly common in the npm ecosystem.
|
|
44
|
-
|
|
45
|
-
## Features
|
|
46
|
-
|
|
47
|
-
- **Abbreviation**: You can use `g` instead of `git`.
|
|
48
|
-
|
|
49
|
-
- **Safe by Default**: Automatically filters and prevents accidental staging of sensitive files: `.env` and `node_modules`.
|
|
50
|
-
|
|
51
|
-
- **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.
|
|
52
|
-
|
|
53
|
-
## Test environment
|
|
54
|
-
|
|
55
|
-
- for windows i used my own laptop (windows 11) so if you have a problem please create an issue
|
|
56
|
-
|
|
57
|
-
- for linux i used WSL (windows subsystem linux) with a kali-linux vm so if you have a problem please create an issue
|
|
58
|
-
|
|
59
|
-
## How it works
|
|
60
|
-
|
|
61
|
-
Glinter is designed to be as "natural" as possible, meaning it shouldn't feel like a wrapper at all.
|
|
62
|
-
|
|
63
|
-
### 1. The Transparent Proxy
|
|
64
|
-
|
|
65
|
-
In `src/index.ts`, Glinter uses `Bun.spawn` with `stdio: 'inherit'`. This is a low-level operation that connects the standard input, output, and error streams of the Git process directly to your terminal.
|
|
66
|
-
|
|
67
|
-
- **Result**: Git "knows" it's in a real terminal, so it correctly detects colors and allows for interactive prompts (like credential entry).
|
|
68
|
-
|
|
69
|
-
### 2. Reliable Status Parsing
|
|
70
|
-
|
|
71
|
-
For the interactive `add` feature, Glinter runs `git status --porcelain`.
|
|
72
|
-
|
|
73
|
-
- **Why?**: Standard `git status` output is designed for humans and can change based on your Git version or system language. `--porcelain` is a machine-readable format that is consistent across all environments, making the file detection 100% reliable.
|
|
74
|
-
|
|
75
|
-
### 3. Interactive Selection
|
|
76
|
-
|
|
77
|
-
Using the `@clack/prompts` library, Glinter transforms the raw status data into a selectable list.
|
|
78
|
-
|
|
79
|
-
- The selection logic uses Bun's high-speed shell to execute the final `git add` command, correctly escaping filenames to handle spaces and special characters.
|
|
80
|
-
|
|
81
|
-
## Installation
|
|
82
|
-
|
|
83
|
-
To use Glinter as your primary Git interface (e.g., using the command `g`):
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
npm install -g @jannael/glinter
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### For Development
|
|
90
|
-
|
|
91
|
-
1. **Clone the repo**
|
|
92
|
-
2. **Install dependencies**: `bun install`
|
|
93
|
-
3. **Link the binary**: `bun link`
|
|
94
|
-
|
|
95
|
-
now you can simply run:
|
|
96
|
-
|
|
97
|
-
```bash
|
|
98
|
-
g add # Opens the interactive selector
|
|
99
|
-
g commit # Opens commit type + message prompt
|
|
100
|
-
g add <file> # Runs standard git add <file>
|
|
101
|
-
g commit -m "" # Runs standard git commit -m ""
|
|
102
|
-
g status # Runs standard git status
|
|
103
|
-
g push # Runs standard git push
|
|
104
|
-
```
|
|
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
|
+
</p>
|
|
10
|
+
|
|
11
|
+
Glinter is a high-performance, transparent Git wrapper built with **Bun**.
|
|
12
|
+
|
|
13
|
+
[Tutorial](https://youtu.be/LQWp6flYeyI)
|
|
14
|
+
|
|
15
|
+
[Commands](https://glinter.jannael.com/#commands)
|
|
16
|
+
|
|
17
|
+
[Aliases](https://glinter.jannael.com/alias)
|
|
18
|
+
|
|
19
|
+
[Quick start](https://glinter.jannael.com/#quick-start)
|
|
20
|
+
|
|
21
|
+
## Preview
|
|
22
|
+
|
|
23
|
+
### Badge
|
|
24
|
+
|
|
25
|
+
| Preview | Copy |
|
|
26
|
+
| -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
27
|
+
| [](https://glinter.jannael.com) | `[](https://glinter.jannael.com)` |
|
|
28
|
+
|
|
29
|
+
<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%;">
|
|
30
|
+
Your browser does not support the video tag.
|
|
31
|
+
</video>
|
|
32
|
+
|
|
33
|
+
### Screenshots
|
|
34
|
+
|
|
35
|
+
| `g add` | `g commit` |
|
|
36
|
+
| ------------------------------------ | --------------------------------------- |
|
|
37
|
+
|  |  |
|
|
38
|
+
|
|
39
|
+
## Security
|
|
40
|
+
|
|
41
|
+
Security is a top priority for this project.
|
|
42
|
+
|
|
43
|
+
This project uses Bun as its runtime and package manager. You don't need to worry about package vulnerabilities — the `bunfig.toml` configuration includes `minimumReleaseAge = 259200` (3 days), which prevents newly published packages from being installed automatically. This protects against supply chain attacks that have become increasingly common in the npm ecosystem.
|
|
44
|
+
|
|
45
|
+
## Features
|
|
46
|
+
|
|
47
|
+
- **Abbreviation**: You can use `g` instead of `git`.
|
|
48
|
+
|
|
49
|
+
- **Safe by Default**: Automatically filters and prevents accidental staging of sensitive files: `.env` and `node_modules`.
|
|
50
|
+
|
|
51
|
+
- **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.
|
|
52
|
+
|
|
53
|
+
## Test environment
|
|
54
|
+
|
|
55
|
+
- for windows i used my own laptop (windows 11) so if you have a problem please create an issue
|
|
56
|
+
|
|
57
|
+
- for linux i used WSL (windows subsystem linux) with a kali-linux vm so if you have a problem please create an issue
|
|
58
|
+
|
|
59
|
+
## How it works
|
|
60
|
+
|
|
61
|
+
Glinter is designed to be as "natural" as possible, meaning it shouldn't feel like a wrapper at all.
|
|
62
|
+
|
|
63
|
+
### 1. The Transparent Proxy
|
|
64
|
+
|
|
65
|
+
In `src/index.ts`, Glinter uses `Bun.spawn` with `stdio: 'inherit'`. This is a low-level operation that connects the standard input, output, and error streams of the Git process directly to your terminal.
|
|
66
|
+
|
|
67
|
+
- **Result**: Git "knows" it's in a real terminal, so it correctly detects colors and allows for interactive prompts (like credential entry).
|
|
68
|
+
|
|
69
|
+
### 2. Reliable Status Parsing
|
|
70
|
+
|
|
71
|
+
For the interactive `add` feature, Glinter runs `git status --porcelain`.
|
|
72
|
+
|
|
73
|
+
- **Why?**: Standard `git status` output is designed for humans and can change based on your Git version or system language. `--porcelain` is a machine-readable format that is consistent across all environments, making the file detection 100% reliable.
|
|
74
|
+
|
|
75
|
+
### 3. Interactive Selection
|
|
76
|
+
|
|
77
|
+
Using the `@clack/prompts` library, Glinter transforms the raw status data into a selectable list.
|
|
78
|
+
|
|
79
|
+
- The selection logic uses Bun's high-speed shell to execute the final `git add` command, correctly escaping filenames to handle spaces and special characters.
|
|
80
|
+
|
|
81
|
+
## Installation
|
|
82
|
+
|
|
83
|
+
To use Glinter as your primary Git interface (e.g., using the command `g`):
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
npm install -g @jannael/glinter
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### For Development
|
|
90
|
+
|
|
91
|
+
1. **Clone the repo**
|
|
92
|
+
2. **Install dependencies**: `bun install`
|
|
93
|
+
3. **Link the binary**: `bun link`
|
|
94
|
+
|
|
95
|
+
now you can simply run:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
g add # Opens the interactive selector
|
|
99
|
+
g commit # Opens commit type + message prompt
|
|
100
|
+
g add <file> # Runs standard git add <file>
|
|
101
|
+
g commit -m "" # Runs standard git commit -m ""
|
|
102
|
+
g status # Runs standard git status
|
|
103
|
+
g push # Runs standard git push
|
|
104
|
+
```
|
package/dist/index.js
CHANGED
|
@@ -1188,8 +1188,8 @@ var u$1 = class u extends V {
|
|
|
1188
1188
|
var o$1 = /* @__PURE__ */ new Set(["up", "down", "left", "right"]);
|
|
1189
1189
|
|
|
1190
1190
|
class h extends V {
|
|
1191
|
-
#
|
|
1192
|
-
#
|
|
1191
|
+
#t = false;
|
|
1192
|
+
#s;
|
|
1193
1193
|
focused = "editor";
|
|
1194
1194
|
get userInputWithCursor() {
|
|
1195
1195
|
if (this.state === "submit")
|
|
@@ -1197,10 +1197,10 @@ class h extends V {
|
|
|
1197
1197
|
const t2 = this.userInput;
|
|
1198
1198
|
if (this.cursor >= t2.length)
|
|
1199
1199
|
return `${t2}\u2588`;
|
|
1200
|
-
const s = t2.slice(0, this.cursor), r2 = t2[this.cursor],
|
|
1200
|
+
const s = t2.slice(0, this.cursor), r2 = t2[this.cursor], i = t2.slice(this.cursor + 1);
|
|
1201
1201
|
return r2 === `
|
|
1202
1202
|
` ? `${s}\u2588
|
|
1203
|
-
${
|
|
1203
|
+
${i}` : `${s}${styleText("inverse", r2)}${i}`;
|
|
1204
1204
|
}
|
|
1205
1205
|
get cursor() {
|
|
1206
1206
|
return this._cursor;
|
|
@@ -1230,37 +1230,41 @@ ${e}` : `${s}${styleText("inverse", r2)}${e}`;
|
|
|
1230
1230
|
}
|
|
1231
1231
|
}
|
|
1232
1232
|
_shouldSubmit(t2, s) {
|
|
1233
|
-
if (this.#
|
|
1233
|
+
if (this.#s)
|
|
1234
1234
|
return this.focused === "submit" ? true : (this.#r(`
|
|
1235
1235
|
`), this._cursor++, false);
|
|
1236
|
-
const r2 = this.#
|
|
1237
|
-
return this.#
|
|
1236
|
+
const r2 = this.#t;
|
|
1237
|
+
return this.#t = true, r2 && this.cursor === this.userInput.length ? (this.userInput[this.cursor - 1] === `
|
|
1238
1238
|
` && (this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--), true) : (this.#r(`
|
|
1239
1239
|
`), this._cursor++, false);
|
|
1240
1240
|
}
|
|
1241
1241
|
constructor(t2) {
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1242
|
+
const s = t2.initialUserInput ?? t2.initialValue;
|
|
1243
|
+
super({
|
|
1244
|
+
...t2,
|
|
1245
|
+
initialUserInput: s
|
|
1246
|
+
}, false), s !== undefined && (this._cursor = s.length), this.#s = t2.showSubmit ?? false, this.on("key", (r2, i) => {
|
|
1247
|
+
if (i?.name && o$1.has(i.name)) {
|
|
1248
|
+
this.#t = false, this.#i(i.name);
|
|
1245
1249
|
return;
|
|
1246
1250
|
}
|
|
1247
|
-
if (
|
|
1251
|
+
if (r2 === "\t" && this.#s) {
|
|
1248
1252
|
this.focused = this.focused === "editor" ? "submit" : "editor";
|
|
1249
1253
|
return;
|
|
1250
1254
|
}
|
|
1251
|
-
if (
|
|
1252
|
-
if (this.#
|
|
1255
|
+
if (i?.name !== "return") {
|
|
1256
|
+
if (this.#t = false, i?.name === "backspace" && this.cursor > 0) {
|
|
1253
1257
|
this._setUserInput(this.userInput.slice(0, this.cursor - 1) + this.userInput.slice(this.cursor)), this._cursor--;
|
|
1254
1258
|
return;
|
|
1255
1259
|
}
|
|
1256
|
-
if (
|
|
1260
|
+
if (i?.name === "delete" && this.cursor < this.userInput.length) {
|
|
1257
1261
|
this._setUserInput(this.userInput.slice(0, this.cursor) + this.userInput.slice(this.cursor + 1));
|
|
1258
1262
|
return;
|
|
1259
1263
|
}
|
|
1260
|
-
|
|
1264
|
+
r2 && (this.#s && this.focused === "submit" && (this.focused = "editor"), this.#r(r2 ?? ""), this._cursor++);
|
|
1261
1265
|
}
|
|
1262
|
-
}), this.on("userInput", (
|
|
1263
|
-
this._setValue(
|
|
1266
|
+
}), this.on("userInput", (r2) => {
|
|
1267
|
+
this._setValue(r2);
|
|
1264
1268
|
}), this.on("finalize", () => {
|
|
1265
1269
|
this.value || (this.value = t2.defaultValue), this.value === undefined && (this.value = "");
|
|
1266
1270
|
});
|
|
@@ -1377,7 +1381,7 @@ function isUnicodeSupported() {
|
|
|
1377
1381
|
}
|
|
1378
1382
|
var unicode = isUnicodeSupported();
|
|
1379
1383
|
var isCI = () => process.env.CI === "true";
|
|
1380
|
-
var unicodeOr = (
|
|
1384
|
+
var unicodeOr = (o2, e) => unicode ? o2 : e;
|
|
1381
1385
|
var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
|
|
1382
1386
|
var S_STEP_CANCEL = unicodeOr("\u25A0", "x");
|
|
1383
1387
|
var S_STEP_ERROR = unicodeOr("\u25B2", "x");
|
|
@@ -1403,8 +1407,8 @@ var S_INFO = unicodeOr("\u25CF", "\u2022");
|
|
|
1403
1407
|
var S_SUCCESS = unicodeOr("\u25C6", "*");
|
|
1404
1408
|
var S_WARN = unicodeOr("\u25B2", "!");
|
|
1405
1409
|
var S_ERROR = unicodeOr("\u25A0", "x");
|
|
1406
|
-
var symbol = (
|
|
1407
|
-
switch (
|
|
1410
|
+
var symbol = (o2) => {
|
|
1411
|
+
switch (o2) {
|
|
1408
1412
|
case "initial":
|
|
1409
1413
|
case "active":
|
|
1410
1414
|
return styleText2("cyan", S_STEP_ACTIVE);
|
|
@@ -1416,8 +1420,8 @@ var symbol = (e) => {
|
|
|
1416
1420
|
return styleText2("green", S_STEP_SUBMIT);
|
|
1417
1421
|
}
|
|
1418
1422
|
};
|
|
1419
|
-
var symbolBar = (
|
|
1420
|
-
switch (
|
|
1423
|
+
var symbolBar = (o2) => {
|
|
1424
|
+
switch (o2) {
|
|
1421
1425
|
case "initial":
|
|
1422
1426
|
case "active":
|
|
1423
1427
|
return styleText2("cyan", S_BAR);
|
|
@@ -1429,6 +1433,10 @@ var symbolBar = (e) => {
|
|
|
1429
1433
|
return styleText2("green", S_BAR);
|
|
1430
1434
|
}
|
|
1431
1435
|
};
|
|
1436
|
+
function formatInstructionFooter(o2, e) {
|
|
1437
|
+
const r2 = [`${e ? `${styleText2("cyan", S_BAR)} ` : ""}${o2.join(" \u2022 ")}`];
|
|
1438
|
+
return e && r2.push(styleText2("cyan", S_BAR_END)), r2;
|
|
1439
|
+
}
|
|
1432
1440
|
var E$1 = (l2, o2, g2, c2, h2, O = false) => {
|
|
1433
1441
|
let r2 = o2, w = 0;
|
|
1434
1442
|
if (O)
|
|
@@ -1513,61 +1521,48 @@ ${g2}
|
|
|
1513
1521
|
}
|
|
1514
1522
|
}).prompt();
|
|
1515
1523
|
};
|
|
1516
|
-
var
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
|
|
1524
|
-
i.write(`${e}${o2}
|
|
1525
|
-
`);
|
|
1526
|
-
};
|
|
1527
|
-
var outro = (o2 = "", t2) => {
|
|
1528
|
-
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
|
|
1529
|
-
${styleText2("gray", S_BAR_END)} ` : "";
|
|
1530
|
-
i.write(`${e}${o2}
|
|
1531
|
-
|
|
1532
|
-
`);
|
|
1533
|
-
};
|
|
1534
|
-
var d = (n2, a3) => n2.split(`
|
|
1535
|
-
`).map((m2) => a3(m2)).join(`
|
|
1524
|
+
var MULTISELECT_INSTRUCTIONS = [
|
|
1525
|
+
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
1526
|
+
`${styleText2("dim", "Space:")} select`,
|
|
1527
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1528
|
+
];
|
|
1529
|
+
var m2 = (n2, o2) => n2.split(`
|
|
1530
|
+
`).map((d) => o2(d)).join(`
|
|
1536
1531
|
`);
|
|
1537
1532
|
var multiselect = (n2) => {
|
|
1538
|
-
const
|
|
1533
|
+
const o2 = (t2, a3) => {
|
|
1539
1534
|
const r2 = t2.label ?? String(t2.value);
|
|
1540
|
-
return
|
|
1541
|
-
},
|
|
1535
|
+
return a3 === "disabled" ? `${styleText2("gray", S_CHECKBOX_INACTIVE)} ${m2(r2, (l2) => styleText2(["strikethrough", "gray"], l2))}${t2.hint ? ` ${styleText2("dim", `(${t2.hint ?? "disabled"})`)}` : ""}` : a3 === "active" ? `${styleText2("cyan", S_CHECKBOX_ACTIVE)} ${r2}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a3 === "selected" ? `${styleText2("green", S_CHECKBOX_SELECTED)} ${m2(r2, (l2) => styleText2("dim", l2))}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a3 === "cancelled" ? `${m2(r2, (l2) => styleText2(["strikethrough", "dim"], l2))}` : a3 === "active-selected" ? `${styleText2("green", S_CHECKBOX_SELECTED)} ${r2}${t2.hint ? ` ${styleText2("dim", `(${t2.hint})`)}` : ""}` : a3 === "submitted" ? `${m2(r2, (l2) => styleText2("dim", l2))}` : `${styleText2("dim", S_CHECKBOX_INACTIVE)} ${m2(r2, (l2) => styleText2("dim", l2))}`;
|
|
1536
|
+
}, d = n2.required ?? true;
|
|
1542
1537
|
return new a$1({
|
|
1543
1538
|
options: n2.options,
|
|
1544
1539
|
signal: n2.signal,
|
|
1545
1540
|
input: n2.input,
|
|
1546
1541
|
output: n2.output,
|
|
1547
1542
|
initialValues: n2.initialValues,
|
|
1548
|
-
required:
|
|
1543
|
+
required: d,
|
|
1549
1544
|
cursorAt: n2.cursorAt,
|
|
1550
1545
|
validate(t2) {
|
|
1551
|
-
if (
|
|
1546
|
+
if (d && (t2 === undefined || t2.length === 0))
|
|
1552
1547
|
return `Please select at least one option.
|
|
1553
1548
|
${styleText2("reset", styleText2("dim", `Press ${styleText2(["gray", "bgWhite", "inverse"], " space ")} to select, ${styleText2("gray", styleText2("bgWhite", styleText2("inverse", " enter ")))} to submit`))}`;
|
|
1554
1549
|
},
|
|
1555
1550
|
render() {
|
|
1556
|
-
const t2 = n2.withGuide ?? settings.withGuide,
|
|
1557
|
-
` : ""}${
|
|
1558
|
-
`, l2 = this.value ?? [],
|
|
1551
|
+
const t2 = n2.withGuide ?? settings.withGuide, a3 = wrapTextWithPrefix(n2.output, n2.message, t2 ? `${symbolBar(this.state)} ` : "", `${symbol(this.state)} `), r2 = `${t2 ? `${styleText2("gray", S_BAR)}
|
|
1552
|
+
` : ""}${a3}
|
|
1553
|
+
`, l2 = this.value ?? [], p2 = (i, u3) => {
|
|
1559
1554
|
if (i.disabled)
|
|
1560
|
-
return
|
|
1555
|
+
return o2(i, "disabled");
|
|
1561
1556
|
const s = l2.includes(i.value);
|
|
1562
|
-
return u3 && s ?
|
|
1557
|
+
return u3 && s ? o2(i, "active-selected") : s ? o2(i, "selected") : o2(i, u3 ? "active" : "inactive");
|
|
1563
1558
|
};
|
|
1564
1559
|
switch (this.state) {
|
|
1565
1560
|
case "submit": {
|
|
1566
|
-
const i = this.options.filter(({ value: s }) => l2.includes(s)).map((s) =>
|
|
1561
|
+
const i = this.options.filter(({ value: s }) => l2.includes(s)).map((s) => o2(s, "submitted")).join(styleText2("dim", ", ")) || styleText2("dim", "none"), u3 = wrapTextWithPrefix(n2.output, i, t2 ? `${styleText2("gray", S_BAR)} ` : "");
|
|
1567
1562
|
return `${r2}${u3}`;
|
|
1568
1563
|
}
|
|
1569
1564
|
case "cancel": {
|
|
1570
|
-
const i = this.options.filter(({ value: s }) => l2.includes(s)).map((s) =>
|
|
1565
|
+
const i = this.options.filter(({ value: s }) => l2.includes(s)).map((s) => o2(s, "cancelled")).join(styleText2("dim", ", "));
|
|
1571
1566
|
if (i.trim() === "")
|
|
1572
1567
|
return `${r2}${styleText2("gray", S_BAR)}`;
|
|
1573
1568
|
const u3 = wrapTextWithPrefix(n2.output, i, t2 ? `${styleText2("gray", S_BAR)} ` : "");
|
|
@@ -1576,9 +1571,9 @@ ${styleText2("gray", S_BAR)}` : ""}`;
|
|
|
1576
1571
|
}
|
|
1577
1572
|
case "error": {
|
|
1578
1573
|
const i = t2 ? `${styleText2("yellow", S_BAR)} ` : "", u3 = this.error.split(`
|
|
1579
|
-
`).map((
|
|
1574
|
+
`).map(($, x) => x === 0 ? `${t2 ? `${styleText2("yellow", S_BAR_END)} ` : ""}${styleText2("yellow", $)}` : ` ${$}`).join(`
|
|
1580
1575
|
`), s = r2.split(`
|
|
1581
|
-
`).length,
|
|
1576
|
+
`).length, g2 = u3.split(`
|
|
1582
1577
|
`).length + 1;
|
|
1583
1578
|
return `${r2}${i}${limitOptions({
|
|
1584
1579
|
output: n2.output,
|
|
@@ -1586,8 +1581,8 @@ ${styleText2("gray", S_BAR)}` : ""}`;
|
|
|
1586
1581
|
cursor: this.cursor,
|
|
1587
1582
|
maxItems: n2.maxItems,
|
|
1588
1583
|
columnPadding: i.length,
|
|
1589
|
-
rowPadding: s +
|
|
1590
|
-
style:
|
|
1584
|
+
rowPadding: s + g2,
|
|
1585
|
+
style: p2
|
|
1591
1586
|
}).join(`
|
|
1592
1587
|
${i}`)}
|
|
1593
1588
|
${u3}
|
|
@@ -1595,24 +1590,43 @@ ${u3}
|
|
|
1595
1590
|
}
|
|
1596
1591
|
default: {
|
|
1597
1592
|
const i = t2 ? `${styleText2("cyan", S_BAR)} ` : "", u3 = r2.split(`
|
|
1598
|
-
`).length, s = t2
|
|
1593
|
+
`).length, s = formatInstructionFooter(MULTISELECT_INSTRUCTIONS, t2), g2 = s.join(`
|
|
1594
|
+
`), $ = s.length + 1;
|
|
1599
1595
|
return `${r2}${i}${limitOptions({
|
|
1600
1596
|
output: n2.output,
|
|
1601
1597
|
options: this.options,
|
|
1602
1598
|
cursor: this.cursor,
|
|
1603
1599
|
maxItems: n2.maxItems,
|
|
1604
1600
|
columnPadding: i.length,
|
|
1605
|
-
rowPadding: u3 +
|
|
1606
|
-
style:
|
|
1601
|
+
rowPadding: u3 + $,
|
|
1602
|
+
style: p2
|
|
1607
1603
|
}).join(`
|
|
1608
1604
|
${i}`)}
|
|
1609
|
-
${
|
|
1605
|
+
${g2}
|
|
1610
1606
|
`;
|
|
1611
1607
|
}
|
|
1612
1608
|
}
|
|
1613
1609
|
}
|
|
1614
1610
|
}).prompt();
|
|
1615
1611
|
};
|
|
1612
|
+
var cancel = (o2 = "", t2) => {
|
|
1613
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_END)} ` : "";
|
|
1614
|
+
i.write(`${e}${styleText2("red", o2)}
|
|
1615
|
+
|
|
1616
|
+
`);
|
|
1617
|
+
};
|
|
1618
|
+
var intro = (o2 = "", t2) => {
|
|
1619
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR_START)} ` : "";
|
|
1620
|
+
i.write(`${e}${o2}
|
|
1621
|
+
`);
|
|
1622
|
+
};
|
|
1623
|
+
var outro = (o2 = "", t2) => {
|
|
1624
|
+
const i = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText2("gray", S_BAR)}
|
|
1625
|
+
${styleText2("gray", S_BAR_END)} ` : "";
|
|
1626
|
+
i.write(`${e}${o2}
|
|
1627
|
+
|
|
1628
|
+
`);
|
|
1629
|
+
};
|
|
1616
1630
|
var W = (l2) => styleText2("magenta", l2);
|
|
1617
1631
|
var spinner = ({
|
|
1618
1632
|
indicator: l2 = "dots",
|
|
@@ -1622,18 +1636,18 @@ var spinner = ({
|
|
|
1622
1636
|
errorMessage: O,
|
|
1623
1637
|
frames: E = unicode ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"],
|
|
1624
1638
|
delay: F = unicode ? 80 : 120,
|
|
1625
|
-
signal:
|
|
1639
|
+
signal: m3,
|
|
1626
1640
|
...I
|
|
1627
1641
|
} = {}) => {
|
|
1628
1642
|
const u3 = isCI();
|
|
1629
|
-
let M2, T3,
|
|
1643
|
+
let M2, T3, d = false, S = false, s = "", p2, w = performance.now();
|
|
1630
1644
|
const x = getColumns(n2), k = I?.styleFrame ?? W, g2 = (e) => {
|
|
1631
1645
|
const r2 = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
|
|
1632
|
-
S = e === 1,
|
|
1646
|
+
S = e === 1, d && (a3(r2, e), S && typeof h2 == "function" && h2());
|
|
1633
1647
|
}, f2 = () => g2(2), i = () => g2(1), A = () => {
|
|
1634
|
-
process.on("uncaughtExceptionMonitor", f2), process.on("unhandledRejection", f2), process.on("SIGINT", i), process.on("SIGTERM", i), process.on("exit", g2),
|
|
1648
|
+
process.on("uncaughtExceptionMonitor", f2), process.on("unhandledRejection", f2), process.on("SIGINT", i), process.on("SIGTERM", i), process.on("exit", g2), m3 && m3.addEventListener("abort", i);
|
|
1635
1649
|
}, H = () => {
|
|
1636
|
-
process.removeListener("uncaughtExceptionMonitor", f2), process.removeListener("unhandledRejection", f2), process.removeListener("SIGINT", i), process.removeListener("SIGTERM", i), process.removeListener("exit", g2),
|
|
1650
|
+
process.removeListener("uncaughtExceptionMonitor", f2), process.removeListener("unhandledRejection", f2), process.removeListener("SIGINT", i), process.removeListener("SIGTERM", i), process.removeListener("exit", g2), m3 && m3.removeEventListener("abort", i);
|
|
1637
1651
|
}, y = () => {
|
|
1638
1652
|
if (p2 === undefined)
|
|
1639
1653
|
return;
|
|
@@ -1649,7 +1663,7 @@ var spinner = ({
|
|
|
1649
1663
|
const r2 = (performance.now() - e) / 1000, t2 = Math.floor(r2 / 60), o2 = Math.floor(r2 % 60);
|
|
1650
1664
|
return t2 > 0 ? `[${t2}m ${o2}s]` : `[${o2}s]`;
|
|
1651
1665
|
}, N = I.withGuide ?? settings.withGuide, P2 = (e = "") => {
|
|
1652
|
-
|
|
1666
|
+
d = true, M2 = block({ output: n2 }), s = C2(e), w = performance.now(), N && n2.write(`${styleText2("gray", S_BAR)}
|
|
1653
1667
|
`);
|
|
1654
1668
|
let r2 = 0, t2 = 0;
|
|
1655
1669
|
A(), T3 = setInterval(() => {
|
|
@@ -1673,9 +1687,9 @@ var spinner = ({
|
|
|
1673
1687
|
n2.write(j), r2 = r2 + 1 < E.length ? r2 + 1 : 0, t2 = t2 < 4 ? t2 + 0.125 : 0;
|
|
1674
1688
|
}, F);
|
|
1675
1689
|
}, a3 = (e = "", r2 = 0, t2 = false) => {
|
|
1676
|
-
if (!
|
|
1690
|
+
if (!d)
|
|
1677
1691
|
return;
|
|
1678
|
-
|
|
1692
|
+
d = false, clearInterval(T3), y();
|
|
1679
1693
|
const o2 = r2 === 0 ? styleText2("green", S_STEP_SUBMIT) : r2 === 1 ? styleText2("red", S_STEP_CANCEL) : styleText2("red", S_STEP_ERROR);
|
|
1680
1694
|
s = e ?? s, t2 || (l2 === "timer" ? n2.write(`${o2} ${s} ${_2(w)}
|
|
1681
1695
|
`) : n2.write(`${o2} ${s}
|
|
@@ -1700,20 +1714,24 @@ var u3 = {
|
|
|
1700
1714
|
heavy: unicodeOr("\u2501", "="),
|
|
1701
1715
|
block: unicodeOr("\u2588", "#")
|
|
1702
1716
|
};
|
|
1703
|
-
var
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
var
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1717
|
+
var SELECT_INSTRUCTIONS = [
|
|
1718
|
+
`${styleText2("dim", "\u2191/\u2193")} to navigate`,
|
|
1719
|
+
`${styleText2("dim", "Enter:")} confirm`
|
|
1720
|
+
];
|
|
1721
|
+
var c2 = (t2, a3) => t2.includes(`
|
|
1722
|
+
`) ? t2.split(`
|
|
1723
|
+
`).map((i) => a3(i)).join(`
|
|
1724
|
+
`) : a3(t2);
|
|
1725
|
+
var select = (t2) => {
|
|
1726
|
+
const a3 = (i, m3) => {
|
|
1727
|
+
const s = i.label ?? String(i.value);
|
|
1728
|
+
switch (m3) {
|
|
1711
1729
|
case "disabled":
|
|
1712
|
-
return `${styleText2("gray", S_RADIO_INACTIVE)} ${c2(s, (n2) => styleText2("gray", n2))}${
|
|
1730
|
+
return `${styleText2("gray", S_RADIO_INACTIVE)} ${c2(s, (n2) => styleText2("gray", n2))}${i.hint ? ` ${styleText2("dim", `(${i.hint ?? "disabled"})`)}` : ""}`;
|
|
1713
1731
|
case "selected":
|
|
1714
1732
|
return `${c2(s, (n2) => styleText2("dim", n2))}`;
|
|
1715
1733
|
case "active":
|
|
1716
|
-
return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${
|
|
1734
|
+
return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${i.hint ? ` ${styleText2("dim", `(${i.hint})`)}` : ""}`;
|
|
1717
1735
|
case "cancelled":
|
|
1718
1736
|
return `${c2(s, (n2) => styleText2(["strikethrough", "dim"], n2))}`;
|
|
1719
1737
|
default:
|
|
@@ -1721,39 +1739,40 @@ var select = (e) => {
|
|
|
1721
1739
|
}
|
|
1722
1740
|
};
|
|
1723
1741
|
return new a2({
|
|
1724
|
-
options:
|
|
1725
|
-
signal:
|
|
1726
|
-
input:
|
|
1727
|
-
output:
|
|
1728
|
-
initialValue:
|
|
1742
|
+
options: t2.options,
|
|
1743
|
+
signal: t2.signal,
|
|
1744
|
+
input: t2.input,
|
|
1745
|
+
output: t2.output,
|
|
1746
|
+
initialValue: t2.initialValue,
|
|
1729
1747
|
render() {
|
|
1730
|
-
const
|
|
1748
|
+
const i = t2.withGuide ?? settings.withGuide, m3 = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, n2 = wrapTextWithPrefix(t2.output, t2.message, s, m3), u4 = `${i ? `${styleText2("gray", S_BAR)}
|
|
1731
1749
|
` : ""}${n2}
|
|
1732
1750
|
`;
|
|
1733
1751
|
switch (this.state) {
|
|
1734
1752
|
case "submit": {
|
|
1735
|
-
const r2 =
|
|
1736
|
-
return `${u4}${
|
|
1753
|
+
const r2 = i ? `${styleText2("gray", S_BAR)} ` : "", o2 = wrapTextWithPrefix(t2.output, a3(this.options[this.cursor], "selected"), r2);
|
|
1754
|
+
return `${u4}${o2}`;
|
|
1737
1755
|
}
|
|
1738
1756
|
case "cancel": {
|
|
1739
|
-
const r2 =
|
|
1740
|
-
return `${u4}${
|
|
1757
|
+
const r2 = i ? `${styleText2("gray", S_BAR)} ` : "", o2 = wrapTextWithPrefix(t2.output, a3(this.options[this.cursor], "cancelled"), r2);
|
|
1758
|
+
return `${u4}${o2}${i ? `
|
|
1741
1759
|
${styleText2("gray", S_BAR)}` : ""}`;
|
|
1742
1760
|
}
|
|
1743
1761
|
default: {
|
|
1744
|
-
const r2 =
|
|
1745
|
-
`).length,
|
|
1762
|
+
const r2 = i ? `${styleText2("cyan", S_BAR)} ` : "", o2 = u4.split(`
|
|
1763
|
+
`).length, $ = formatInstructionFooter(SELECT_INSTRUCTIONS, i), h2 = $.join(`
|
|
1764
|
+
`), b2 = $.length + 1;
|
|
1746
1765
|
return `${u4}${r2}${limitOptions({
|
|
1747
|
-
output:
|
|
1766
|
+
output: t2.output,
|
|
1748
1767
|
cursor: this.cursor,
|
|
1749
1768
|
options: this.options,
|
|
1750
|
-
maxItems:
|
|
1769
|
+
maxItems: t2.maxItems,
|
|
1751
1770
|
columnPadding: r2.length,
|
|
1752
|
-
rowPadding:
|
|
1753
|
-
style: (p2,
|
|
1771
|
+
rowPadding: o2 + b2,
|
|
1772
|
+
style: (p2, x) => a3(p2, p2.disabled ? "disabled" : x ? "active" : "inactive")
|
|
1754
1773
|
}).join(`
|
|
1755
1774
|
${r2}`)}
|
|
1756
|
-
${
|
|
1775
|
+
${h2}
|
|
1757
1776
|
`;
|
|
1758
1777
|
}
|
|
1759
1778
|
}
|
|
@@ -1775,10 +1794,10 @@ var text = (t2) => new n({
|
|
|
1775
1794
|
`, c3 = t2.placeholder ? styleText2("inverse", t2.placeholder[0]) + styleText2("dim", t2.placeholder.slice(1)) : styleText2(["inverse", "hidden"], "_"), o2 = this.userInput ? this.userInputWithCursor : c3, a3 = this.value ?? "";
|
|
1776
1795
|
switch (this.state) {
|
|
1777
1796
|
case "error": {
|
|
1778
|
-
const n2 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "",
|
|
1797
|
+
const n2 = this.error ? ` ${styleText2("yellow", this.error)}` : "", r2 = i2 ? `${styleText2("yellow", S_BAR)} ` : "", d = i2 ? styleText2("yellow", S_BAR_END) : "";
|
|
1779
1798
|
return `${s.trim()}
|
|
1780
1799
|
${r2}${o2}
|
|
1781
|
-
${
|
|
1800
|
+
${d}${n2}
|
|
1782
1801
|
`;
|
|
1783
1802
|
}
|
|
1784
1803
|
case "submit": {
|
|
@@ -2108,10 +2127,7 @@ var commitTypeOptions = [
|
|
|
2108
2127
|
];
|
|
2109
2128
|
|
|
2110
2129
|
// apps/cli/utils/input.ts
|
|
2111
|
-
async function Input({
|
|
2112
|
-
message,
|
|
2113
|
-
placeholder
|
|
2114
|
-
}) {
|
|
2130
|
+
async function Input({ message, placeholder }) {
|
|
2115
2131
|
const value = await text({
|
|
2116
2132
|
message,
|
|
2117
2133
|
placeholder,
|
|
@@ -2129,10 +2145,7 @@ async function Input({
|
|
|
2129
2145
|
}
|
|
2130
2146
|
|
|
2131
2147
|
// apps/cli/utils/select.ts
|
|
2132
|
-
async function Select({
|
|
2133
|
-
message,
|
|
2134
|
-
options
|
|
2135
|
-
}) {
|
|
2148
|
+
async function Select({ message, options }) {
|
|
2136
2149
|
const selected = await select({
|
|
2137
2150
|
message,
|
|
2138
2151
|
options
|
|
@@ -2210,11 +2223,7 @@ class SetupAliasesUseCase {
|
|
|
2210
2223
|
}
|
|
2211
2224
|
|
|
2212
2225
|
// apps/cli/utils/confirm.ts
|
|
2213
|
-
async function Confirm({
|
|
2214
|
-
message,
|
|
2215
|
-
cancelMessage,
|
|
2216
|
-
exitOnCancel = true
|
|
2217
|
-
}) {
|
|
2226
|
+
async function Confirm({ message, cancelMessage, exitOnCancel = true }) {
|
|
2218
2227
|
const confirmed = await confirm({
|
|
2219
2228
|
message
|
|
2220
2229
|
});
|
|
@@ -2360,12 +2369,7 @@ ${functionLine}
|
|
|
2360
2369
|
return path2.join(this.getWindowsDocumentsPath(), "PowerShell", "Microsoft.PowerShell_profile.ps1");
|
|
2361
2370
|
}
|
|
2362
2371
|
getWindowsDocumentsPath() {
|
|
2363
|
-
const proc = Bun.spawnSync([
|
|
2364
|
-
"powershell",
|
|
2365
|
-
"-NoProfile",
|
|
2366
|
-
"-Command",
|
|
2367
|
-
"[Environment]::GetFolderPath('MyDocuments')"
|
|
2368
|
-
], {
|
|
2372
|
+
const proc = Bun.spawnSync(["powershell", "-NoProfile", "-Command", "[Environment]::GetFolderPath('MyDocuments')"], {
|
|
2369
2373
|
stdout: "pipe",
|
|
2370
2374
|
stderr: "pipe"
|
|
2371
2375
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jannael/glinter",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.9",
|
|
4
4
|
"description": "A high-performance, transparent Git wrapper with interactive staging",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -36,12 +36,12 @@
|
|
|
36
36
|
"scripts": {
|
|
37
37
|
"build": "bun build ./apps/cli/index.ts --outfile=./dist/index.js --target=bun",
|
|
38
38
|
"prepublishOnly": "bun run build",
|
|
39
|
-
"test": "
|
|
40
|
-
"lint": "oxlint",
|
|
41
|
-
"lint:fix": "oxlint --fix",
|
|
42
|
-
"format": "prettier --write .",
|
|
43
|
-
"format:check": "prettier --check .",
|
|
39
|
+
"test": "bun test",
|
|
44
40
|
"type-check": "bunx tsc --noEmit",
|
|
41
|
+
"lint": "eslint .",
|
|
42
|
+
"lint:fix": "eslint --fix .",
|
|
43
|
+
"fmt": "prettier --write .",
|
|
44
|
+
"fmt:check": "prettier --check .",
|
|
45
45
|
"prepare": "husky"
|
|
46
46
|
},
|
|
47
47
|
"bin": {
|
|
@@ -51,27 +51,23 @@
|
|
|
51
51
|
"bun": ">=1.0.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
+
"@eslint/js": "10.0.1",
|
|
54
55
|
"@types/bun": "1.3.14",
|
|
56
|
+
"eslint": "10.5.0",
|
|
57
|
+
"eslint-plugin-astro": "2.0.0",
|
|
55
58
|
"husky": "9.1.7",
|
|
56
|
-
"
|
|
57
|
-
"prettier": "3.8.
|
|
59
|
+
"lint-staged": "17.0.8",
|
|
60
|
+
"prettier": "3.8.4",
|
|
58
61
|
"prettier-plugin-astro": "0.14.1",
|
|
59
62
|
"prettier-plugin-tailwindcss": "0.8.0",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"wrangler": "4.98.0"
|
|
63
|
+
"typescript-eslint": "8.62.0",
|
|
64
|
+
"wrangler": "4.104.0"
|
|
63
65
|
},
|
|
64
66
|
"peerDependencies": {
|
|
65
67
|
"bun": "1.3.14",
|
|
66
68
|
"typescript": "6.0.3"
|
|
67
69
|
},
|
|
68
70
|
"dependencies": {
|
|
69
|
-
"@clack/prompts": "1.
|
|
70
|
-
},
|
|
71
|
-
"lint-staged": {
|
|
72
|
-
"*.{ts,tsx,js,jsx,astro}": [
|
|
73
|
-
"bun run lint:fix",
|
|
74
|
-
"bun run format"
|
|
75
|
-
]
|
|
71
|
+
"@clack/prompts": "1.6.0"
|
|
76
72
|
}
|
|
77
73
|
}
|