@jannael/glinter 1.0.5 → 1.1.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 +1 -1
- package/dist/index.js +139 -79
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Glinter is a high-performance, transparent Git wrapper built with **Bun**. It en
|
|
|
4
4
|
|
|
5
5
|
## Preview
|
|
6
6
|
|
|
7
|
-
<video src="https://github.com/user-attachments/assets/
|
|
7
|
+
<video src="https://github.com/user-attachments/assets/7c7cddef-d656-45e7-82e3-452cf669bbfc" controls="false" autoplay="true" loop="true" muted="true" style="max-width: 100%;">
|
|
8
8
|
Your browser does not support the video tag.
|
|
9
9
|
</video>
|
|
10
10
|
|
package/dist/index.js
CHANGED
|
@@ -91,17 +91,58 @@ var require_src = __commonJS((exports, module) => {
|
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
// src/utils/colors.ts
|
|
94
|
-
var GREEN = "\x1B[32m";
|
|
95
|
-
var YELLOW = "\x1B[33m";
|
|
96
|
-
var RED = "\x1B[31m";
|
|
97
|
-
var MAGENTA = "\x1B[35m";
|
|
98
|
-
var BLUE = "\x1B[34m";
|
|
99
|
-
var BLACK = "\x1B[30m";
|
|
100
|
-
var BG_YELLOW = "\x1B[43m";
|
|
101
94
|
var RESET = "\x1B[0m";
|
|
95
|
+
var GREEN = ({ text }) => `\x1B[32m${text}${RESET}`;
|
|
96
|
+
var YELLOW = ({ text }) => `\x1B[33m${text}${RESET}`;
|
|
97
|
+
var RED = ({ text }) => `\x1B[31m${text}${RESET}`;
|
|
98
|
+
var MAGENTA = ({ text }) => `\x1B[35m${text}${RESET}`;
|
|
99
|
+
var BLUE = ({ text }) => `\x1B[34m${text}${RESET}`;
|
|
100
|
+
var BLACK = ({ text }) => `\x1B[30m${text}${RESET}`;
|
|
101
|
+
var BG_YELLOW = ({ text }) => `\x1B[43m${text}${RESET}`;
|
|
102
102
|
|
|
103
|
-
// src/utils/
|
|
104
|
-
var
|
|
103
|
+
// src/utils/icons-terminal.ts
|
|
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
|
|
109
|
+
function CreateError(name) {
|
|
110
|
+
const capitalize = (text) => text.charAt(0).toUpperCase() + text.slice(1);
|
|
111
|
+
return class extends Error {
|
|
112
|
+
description;
|
|
113
|
+
constructor(message, description) {
|
|
114
|
+
super(capitalize(message));
|
|
115
|
+
this.name = name;
|
|
116
|
+
this.description = description !== undefined ? capitalize(description) : undefined;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/error/error-instance.ts
|
|
122
|
+
var NotFound = CreateError("NotFound");
|
|
123
|
+
var Forbidden = CreateError("Forbidden");
|
|
124
|
+
var Conflict = CreateError("Conflict");
|
|
125
|
+
var ServerError = CreateError("ServerError");
|
|
126
|
+
var BadRequest = CreateError("BadRequest");
|
|
127
|
+
|
|
128
|
+
// src/error/error-handler.ts
|
|
129
|
+
function errorHandler(error) {
|
|
130
|
+
if (error instanceof ServerError) {
|
|
131
|
+
console.error(X({ text: error.message }));
|
|
132
|
+
if (error.description) {
|
|
133
|
+
console.error(` ${error.description}`);
|
|
134
|
+
}
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (error instanceof NotFound) {
|
|
138
|
+
console.error(WARNING({ text: error.message }));
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
console.error(X({ text: "An unexpected error occurred" }));
|
|
142
|
+
if (error instanceof Error) {
|
|
143
|
+
console.error(` ${error.message}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
105
146
|
|
|
106
147
|
// node_modules/@clack/core/dist/index.mjs
|
|
107
148
|
import { styleText as y } from "util";
|
|
@@ -744,9 +785,9 @@ var H = class extends p {
|
|
|
744
785
|
}
|
|
745
786
|
}
|
|
746
787
|
};
|
|
747
|
-
var
|
|
788
|
+
var X2 = { Y: { type: "year", len: 4 }, M: { type: "month", len: 2 }, D: { type: "day", len: 2 } };
|
|
748
789
|
function L(r) {
|
|
749
|
-
return [...r].map((t) =>
|
|
790
|
+
return [...r].map((t) => X2[t]);
|
|
750
791
|
}
|
|
751
792
|
function Z(r) {
|
|
752
793
|
const t = new Intl.DateTimeFormat(r, { year: "numeric", month: "2-digit", day: "2-digit" }).formatToParts(new Date(2000, 0, 15)), e = [];
|
|
@@ -1280,32 +1321,41 @@ class AddCommand {
|
|
|
1280
1321
|
this.stageChangesUseCase = stageChangesUseCase;
|
|
1281
1322
|
}
|
|
1282
1323
|
async execute() {
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1324
|
+
try {
|
|
1325
|
+
const { changes, warnings } = await this.getChangesUseCase.execute();
|
|
1326
|
+
if (changes.length === 0) {
|
|
1327
|
+
console.log(`${CHECK({ text: "All changes are either staged or sensitive (like .env)." })}`);
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
const options = [
|
|
1331
|
+
...changes.map((c2) => ({ value: c2.value, label: c2.label }))
|
|
1332
|
+
];
|
|
1333
|
+
const selectedChanges = await MultiSelect({
|
|
1334
|
+
message: `Select the changes you want to commit.
|
|
1335
|
+
` + BLUE({ text: "[space] to select and" }) + `
|
|
1336
|
+
` + GREEN({ text: "[enter] to confirm" }) + `
|
|
1337
|
+
` + MAGENTA({ text: "[a] to select all" }) + `
|
|
1338
|
+
` + RED({ text: "[esc] to cancel" }) + `
|
|
1339
|
+
`,
|
|
1340
|
+
options
|
|
1341
|
+
});
|
|
1342
|
+
let selected = selectedChanges.map((file) => file.trim());
|
|
1343
|
+
if (selected.includes("all")) {
|
|
1344
|
+
selected = changes.map((c2) => c2.value);
|
|
1345
|
+
}
|
|
1346
|
+
if (selected.length > 0) {
|
|
1347
|
+
await this.stageChangesUseCase.execute(selected);
|
|
1348
|
+
if (warnings.size > 0) {
|
|
1349
|
+
console.log(`
|
|
1350
|
+
${WARNING({ text: " WARNING " })}`);
|
|
1351
|
+
for (const warning of warnings) {
|
|
1352
|
+
console.log(warning);
|
|
1353
|
+
}
|
|
1354
|
+
console.log("");
|
|
1306
1355
|
}
|
|
1307
|
-
console.log("");
|
|
1308
1356
|
}
|
|
1357
|
+
} catch (error) {
|
|
1358
|
+
errorHandler(error);
|
|
1309
1359
|
}
|
|
1310
1360
|
}
|
|
1311
1361
|
}
|
|
@@ -1329,16 +1379,16 @@ class Change {
|
|
|
1329
1379
|
const { status, displayPath } = this.props;
|
|
1330
1380
|
let label = `${status}: ${displayPath}`;
|
|
1331
1381
|
if (status.includes("M")) {
|
|
1332
|
-
label =
|
|
1382
|
+
label = YELLOW({ text: `modified: ${displayPath}` });
|
|
1333
1383
|
}
|
|
1334
1384
|
if (status.includes("A") || status.includes("?")) {
|
|
1335
|
-
label =
|
|
1385
|
+
label = GREEN({ text: `new file: ${displayPath}` });
|
|
1336
1386
|
}
|
|
1337
1387
|
if (status.includes("D")) {
|
|
1338
|
-
label =
|
|
1388
|
+
label = RED({ text: `deleted: ${displayPath}` });
|
|
1339
1389
|
}
|
|
1340
1390
|
if (status.includes("R")) {
|
|
1341
|
-
label =
|
|
1391
|
+
label = MAGENTA({ text: `renamed: ${displayPath}` });
|
|
1342
1392
|
}
|
|
1343
1393
|
return label;
|
|
1344
1394
|
}
|
|
@@ -1347,10 +1397,10 @@ class Change {
|
|
|
1347
1397
|
}
|
|
1348
1398
|
getWarning() {
|
|
1349
1399
|
if (this.value.includes(".env")) {
|
|
1350
|
-
return
|
|
1400
|
+
return YELLOW({ text: " .env file hidden" }) + " (Add to .gitignore to avoid leaks)";
|
|
1351
1401
|
}
|
|
1352
1402
|
if (this.value.includes("node_modules")) {
|
|
1353
|
-
return
|
|
1403
|
+
return YELLOW({ text: " node_modules hidden" }) + " (Add to .gitignore to save space)";
|
|
1354
1404
|
}
|
|
1355
1405
|
return null;
|
|
1356
1406
|
}
|
|
@@ -1419,14 +1469,17 @@ class StageChangesUseCase {
|
|
|
1419
1469
|
|
|
1420
1470
|
// src/modules/add/infra/bun-git.repository.ts
|
|
1421
1471
|
var {$: $2 } = globalThis.Bun;
|
|
1422
|
-
|
|
1423
1472
|
class BunGitRepository {
|
|
1424
1473
|
async getEntries() {
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1474
|
+
try {
|
|
1475
|
+
const output = await $2`git status --porcelain -z`.quiet().text();
|
|
1476
|
+
if (!output.trim()) {
|
|
1477
|
+
return [];
|
|
1478
|
+
}
|
|
1479
|
+
return output.split("\x00").filter(Boolean);
|
|
1480
|
+
} catch {
|
|
1481
|
+
throw new ServerError("Git status failed", "Could not retrieve repository status");
|
|
1428
1482
|
}
|
|
1429
|
-
return output.split("\x00").filter(Boolean);
|
|
1430
1483
|
}
|
|
1431
1484
|
async stageFiles(files) {
|
|
1432
1485
|
if (files.length === 0)
|
|
@@ -1436,7 +1489,7 @@ class BunGitRepository {
|
|
|
1436
1489
|
});
|
|
1437
1490
|
const exitCode = await proc.exited;
|
|
1438
1491
|
if (exitCode !== 0) {
|
|
1439
|
-
throw new
|
|
1492
|
+
throw new ServerError("Git add failed", `Failed to stage ${files.length} file(s)`);
|
|
1440
1493
|
}
|
|
1441
1494
|
}
|
|
1442
1495
|
}
|
|
@@ -1535,49 +1588,56 @@ class SwitchCommand {
|
|
|
1535
1588
|
this.switchBranch = switchBranch;
|
|
1536
1589
|
}
|
|
1537
1590
|
async execute() {
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
const options = [];
|
|
1544
|
-
for (const branch of branches) {
|
|
1545
|
-
let label = branch.name;
|
|
1546
|
-
let value = branch.name;
|
|
1547
|
-
if (branch.isHeadBranch)
|
|
1548
|
-
continue;
|
|
1549
|
-
if (branch.isCurrentBranch) {
|
|
1550
|
-
console.log(`${CHECK} Current branch: ${branch.name}`);
|
|
1551
|
-
continue;
|
|
1591
|
+
try {
|
|
1592
|
+
const branches = await this.getBranchesUseCase.execute();
|
|
1593
|
+
if (branches.length === 0) {
|
|
1594
|
+
console.log(`${CHECK({ text: "No branches found." })}`);
|
|
1595
|
+
return;
|
|
1552
1596
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1597
|
+
const options = [];
|
|
1598
|
+
for (const branch of branches) {
|
|
1599
|
+
let label = branch.name;
|
|
1600
|
+
let value = branch.name;
|
|
1601
|
+
if (branch.isHeadBranch)
|
|
1602
|
+
continue;
|
|
1603
|
+
if (branch.isCurrentBranch) {
|
|
1604
|
+
console.log(`${CHECK({ text: `Current branch: ${branch.name}` })}`);
|
|
1605
|
+
continue;
|
|
1606
|
+
}
|
|
1607
|
+
if (branch.isRemoteBranch) {
|
|
1608
|
+
label = branch.name.replace("remotes/origin/", GREEN({ text: "remote branch: " }));
|
|
1609
|
+
value = branch.name.replace("remotes/origin/", "");
|
|
1610
|
+
}
|
|
1611
|
+
options.push({
|
|
1612
|
+
value,
|
|
1613
|
+
label
|
|
1614
|
+
});
|
|
1556
1615
|
}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1616
|
+
const selectedBranch = await Select({
|
|
1617
|
+
message: "Select the branch you want to switch to.",
|
|
1618
|
+
options
|
|
1560
1619
|
});
|
|
1620
|
+
await this.switchBranch.execute({ branch: selectedBranch });
|
|
1621
|
+
} catch (error) {
|
|
1622
|
+
errorHandler(error);
|
|
1561
1623
|
}
|
|
1562
|
-
const selectedBranch = await Select({
|
|
1563
|
-
message: "Select the branch you want to switch to.",
|
|
1564
|
-
options
|
|
1565
|
-
});
|
|
1566
|
-
await this.switchBranch.execute({ branch: selectedBranch });
|
|
1567
1624
|
}
|
|
1568
1625
|
}
|
|
1569
1626
|
|
|
1570
1627
|
// src/modules/switch/infra/bun-switch-repository.ts
|
|
1571
1628
|
var {$: $3 } = globalThis.Bun;
|
|
1572
|
-
|
|
1573
1629
|
class BunSwitchRepository {
|
|
1574
1630
|
async getBranches() {
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1631
|
+
try {
|
|
1632
|
+
const output = await $3`git branch -a`.quiet().text();
|
|
1633
|
+
if (!output.trim()) {
|
|
1634
|
+
return [];
|
|
1635
|
+
}
|
|
1636
|
+
return output.split(`
|
|
1580
1637
|
`).map((branch) => branch.trim());
|
|
1638
|
+
} catch {
|
|
1639
|
+
throw new ServerError("Git branch failed", "Could not retrieve branches");
|
|
1640
|
+
}
|
|
1581
1641
|
}
|
|
1582
1642
|
async switchBranch({ branch }) {
|
|
1583
1643
|
const proc = Bun.spawn(["git", "checkout", branch], {
|
|
@@ -1585,7 +1645,7 @@ class BunSwitchRepository {
|
|
|
1585
1645
|
});
|
|
1586
1646
|
const exitCode = await proc.exited;
|
|
1587
1647
|
if (exitCode !== 0) {
|
|
1588
|
-
throw new
|
|
1648
|
+
throw new ServerError("Git checkout failed", `Failed to switch to branch ${branch}`);
|
|
1589
1649
|
}
|
|
1590
1650
|
}
|
|
1591
1651
|
}
|