@snelusha/noto 1.0.7 → 1.1.0
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 +15 -0
- package/dist/index.js +147 -49
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -90,8 +90,23 @@ Retrieve the previously generated commit message:
|
|
|
90
90
|
noto prev
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
Amend the previously generated commit message:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
noto prev --amend --edit # or simply: noto prev --amend -e
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
> Note: When using the `--amend` flag with the noto prev command, the `--edit` (`-e`) flag is also required. This combination will allow you to modify (amend) the previous commit message before applying it.
|
|
100
|
+
|
|
93
101
|
Note: All of the flags shown above (`--apply`, `--copy`, `--type`, `--edit`) can also be used with the `noto prev` command to work with the previously generated commit message.
|
|
94
102
|
|
|
103
|
+
Switch between branches in you git repo with an interactive prompt:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
noto checkout
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
|
|
95
110
|
## Pro Tips
|
|
96
111
|
|
|
97
112
|
- 🚀 Get fast commits on the fly with `noto -e -a` to streamline your workflow!
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import * as
|
|
3
|
-
import
|
|
2
|
+
import * as p7 from "@clack/prompts";
|
|
3
|
+
import color8 from "picocolors";
|
|
4
4
|
|
|
5
5
|
// src/utils/parser.ts
|
|
6
6
|
import arg from "arg";
|
|
@@ -181,11 +181,12 @@ var getStagedDiff = async () => {
|
|
|
181
181
|
return null;
|
|
182
182
|
}
|
|
183
183
|
};
|
|
184
|
-
var commit = async (message) => {
|
|
184
|
+
var commit = async (message, amend) => {
|
|
185
185
|
try {
|
|
186
|
+
const options = amend ? { "--amend": null } : void 0;
|
|
186
187
|
const {
|
|
187
188
|
summary: { changes }
|
|
188
|
-
} = await git.commit(message);
|
|
189
|
+
} = await git.commit(message, void 0, options);
|
|
189
190
|
return Boolean(changes);
|
|
190
191
|
} catch {
|
|
191
192
|
return false;
|
|
@@ -199,6 +200,32 @@ var push = async () => {
|
|
|
199
200
|
return false;
|
|
200
201
|
}
|
|
201
202
|
};
|
|
203
|
+
var getCurrentBranch = async () => {
|
|
204
|
+
try {
|
|
205
|
+
const branch = await git.branch();
|
|
206
|
+
return branch.current;
|
|
207
|
+
} catch {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
var getBranches = async () => {
|
|
212
|
+
try {
|
|
213
|
+
const branches = await git.branch();
|
|
214
|
+
return Object.keys(branches.branches).filter(
|
|
215
|
+
(b) => !b.startsWith("remotes/")
|
|
216
|
+
);
|
|
217
|
+
} catch {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
var checkout = async (branch) => {
|
|
222
|
+
try {
|
|
223
|
+
await git.checkout(branch);
|
|
224
|
+
return true;
|
|
225
|
+
} catch {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
202
229
|
|
|
203
230
|
// src/middleware/git.ts
|
|
204
231
|
var withRepository = (fn, options = { enabled: true }) => {
|
|
@@ -477,6 +504,11 @@ var command2 = {
|
|
|
477
504
|
flag: "--edit",
|
|
478
505
|
alias: "-e",
|
|
479
506
|
description: "edit the last generated commit message"
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
type: Boolean,
|
|
510
|
+
flag: "--amend",
|
|
511
|
+
description: "amend the last commit with the last generated message"
|
|
480
512
|
}
|
|
481
513
|
],
|
|
482
514
|
execute: withAuth(
|
|
@@ -488,6 +520,13 @@ var command2 = {
|
|
|
488
520
|
return await exit(1);
|
|
489
521
|
}
|
|
490
522
|
const isEditMode = options["--edit"];
|
|
523
|
+
const isAmend = options["--amend"];
|
|
524
|
+
if (isAmend && !isEditMode) {
|
|
525
|
+
p4.log.error(
|
|
526
|
+
color4.red("the --amend option requires the --edit option")
|
|
527
|
+
);
|
|
528
|
+
return await exit(1);
|
|
529
|
+
}
|
|
491
530
|
p4.log.step(
|
|
492
531
|
isEditMode ? color4.white(lastGeneratedMessage) : color4.green(lastGeneratedMessage)
|
|
493
532
|
);
|
|
@@ -514,7 +553,7 @@ var command2 = {
|
|
|
514
553
|
color4.dim("copied last generated commit message to clipboard")
|
|
515
554
|
);
|
|
516
555
|
}
|
|
517
|
-
if (options["--apply"]) {
|
|
556
|
+
if (options["--apply"] || isAmend) {
|
|
518
557
|
if (!options.isRepo) {
|
|
519
558
|
p4.log.error(
|
|
520
559
|
dedent4`${color4.red("no git repository found in cwd.")}
|
|
@@ -522,14 +561,14 @@ var command2 = {
|
|
|
522
561
|
);
|
|
523
562
|
return await exit(1);
|
|
524
563
|
}
|
|
525
|
-
if (!options.diff) {
|
|
564
|
+
if (!options.diff && !isAmend) {
|
|
526
565
|
p4.log.error(
|
|
527
566
|
dedent4`${color4.red("no staged changes found.")}
|
|
528
567
|
${color4.dim(`run ${color4.cyan("`git add <file>`")} or ${color4.cyan("`git add .`")} to stage changes.`)}`
|
|
529
568
|
);
|
|
530
569
|
return await exit(1);
|
|
531
570
|
}
|
|
532
|
-
const success = await commit(lastGeneratedMessage);
|
|
571
|
+
const success = await commit(lastGeneratedMessage, isAmend);
|
|
533
572
|
if (success) {
|
|
534
573
|
p4.log.step(color4.dim("commit successful"));
|
|
535
574
|
} else {
|
|
@@ -544,30 +583,89 @@ var command2 = {
|
|
|
544
583
|
};
|
|
545
584
|
var prev_default = command2;
|
|
546
585
|
|
|
547
|
-
// src/commands/
|
|
586
|
+
// src/commands/checkout.ts
|
|
548
587
|
import * as p5 from "@clack/prompts";
|
|
549
588
|
import color5 from "picocolors";
|
|
589
|
+
import dedent5 from "dedent";
|
|
590
|
+
var command3 = {
|
|
591
|
+
name: "checkout",
|
|
592
|
+
description: "checkout a branch",
|
|
593
|
+
usage: "checkout [options]",
|
|
594
|
+
execute: withRepository(
|
|
595
|
+
async (options) => {
|
|
596
|
+
if (!options.isRepo) {
|
|
597
|
+
p5.log.error(
|
|
598
|
+
dedent5`${color5.red("no git repository found in cwd.")}
|
|
599
|
+
${color5.dim(`run ${color5.cyan("`git init`")} to initialize a new repository.`)}`
|
|
600
|
+
);
|
|
601
|
+
return await exit(1);
|
|
602
|
+
}
|
|
603
|
+
const branches = await getBranches();
|
|
604
|
+
if (!branches) {
|
|
605
|
+
p5.log.error("failed to fetch branches");
|
|
606
|
+
return await exit(1);
|
|
607
|
+
}
|
|
608
|
+
const currentBranch = await getCurrentBranch();
|
|
609
|
+
const branch = await p5.select({
|
|
610
|
+
message: "select a branch to checkout",
|
|
611
|
+
options: branches.map((branch2) => ({
|
|
612
|
+
value: branch2,
|
|
613
|
+
label: color5.bold(
|
|
614
|
+
branch2 === currentBranch ? color5.green(branch2) : branch2
|
|
615
|
+
),
|
|
616
|
+
hint: branch2 === currentBranch ? "current branch" : void 0
|
|
617
|
+
})),
|
|
618
|
+
initialValue: currentBranch
|
|
619
|
+
});
|
|
620
|
+
if (p5.isCancel(branch)) {
|
|
621
|
+
p5.log.error("nothing selected!");
|
|
622
|
+
return await exit(1);
|
|
623
|
+
}
|
|
624
|
+
if (!branch) {
|
|
625
|
+
p5.log.error("no branch selected");
|
|
626
|
+
return await exit(1);
|
|
627
|
+
}
|
|
628
|
+
if (branch === currentBranch) {
|
|
629
|
+
p5.log.error(`${color5.red("already on branch")}`);
|
|
630
|
+
return await exit(1);
|
|
631
|
+
}
|
|
632
|
+
const result = await checkout(branch);
|
|
633
|
+
if (!result) {
|
|
634
|
+
p5.log.error(`failed to checkout ${color5.bold(branch)}`);
|
|
635
|
+
return await exit(1);
|
|
636
|
+
}
|
|
637
|
+
p5.log.success(`checked out ${color5.green(branch)}`);
|
|
638
|
+
await exit(0);
|
|
639
|
+
},
|
|
640
|
+
{ enabled: false }
|
|
641
|
+
)
|
|
642
|
+
};
|
|
643
|
+
var checkout_default = command3;
|
|
644
|
+
|
|
645
|
+
// src/commands/config.ts
|
|
646
|
+
import * as p6 from "@clack/prompts";
|
|
647
|
+
import color6 from "picocolors";
|
|
550
648
|
var key = {
|
|
551
649
|
name: "key",
|
|
552
650
|
description: "configure api key",
|
|
553
651
|
usage: "noto config key [options]",
|
|
554
652
|
execute: async (options) => {
|
|
555
653
|
if ((await StorageManager.get()).llm?.apiKey) {
|
|
556
|
-
const confirm2 = await
|
|
654
|
+
const confirm2 = await p6.confirm({
|
|
557
655
|
message: "noto api key already configured, do you want to update it?"
|
|
558
656
|
});
|
|
559
|
-
if (
|
|
560
|
-
|
|
657
|
+
if (p6.isCancel(confirm2) || !confirm2) {
|
|
658
|
+
p6.log.error(color6.red("nothing changed!"));
|
|
561
659
|
return await exit(1);
|
|
562
660
|
}
|
|
563
661
|
}
|
|
564
662
|
let apiKey = options._[0];
|
|
565
663
|
if (!apiKey) {
|
|
566
|
-
const result = await
|
|
664
|
+
const result = await p6.text({
|
|
567
665
|
message: "enter your noto api key"
|
|
568
666
|
});
|
|
569
|
-
if (
|
|
570
|
-
|
|
667
|
+
if (p6.isCancel(result)) {
|
|
668
|
+
p6.log.error(color6.red("nothing changed!"));
|
|
571
669
|
return await exit(1);
|
|
572
670
|
}
|
|
573
671
|
apiKey = result;
|
|
@@ -579,7 +677,7 @@ var key = {
|
|
|
579
677
|
apiKey
|
|
580
678
|
}
|
|
581
679
|
}));
|
|
582
|
-
|
|
680
|
+
p6.log.success(color6.green("noto api key configured!"));
|
|
583
681
|
console.log();
|
|
584
682
|
}
|
|
585
683
|
};
|
|
@@ -588,7 +686,7 @@ var model = {
|
|
|
588
686
|
description: "configure model",
|
|
589
687
|
usage: "noto config model [options]",
|
|
590
688
|
execute: async (options) => {
|
|
591
|
-
const model2 = await
|
|
689
|
+
const model2 = await p6.select({
|
|
592
690
|
message: "select a model",
|
|
593
691
|
initialValue: (await StorageManager.get()).llm?.model,
|
|
594
692
|
options: Object.keys(models).map((model3) => ({
|
|
@@ -596,16 +694,16 @@ var model = {
|
|
|
596
694
|
value: model3
|
|
597
695
|
}))
|
|
598
696
|
});
|
|
599
|
-
if (
|
|
600
|
-
|
|
697
|
+
if (p6.isCancel(model2)) {
|
|
698
|
+
p6.log.error(color6.red("nothing changed!"));
|
|
601
699
|
return await exit(1);
|
|
602
700
|
}
|
|
603
701
|
if (model2 === "gemini-2.5-pro-exp-03-25") {
|
|
604
|
-
const confirm2 = await
|
|
702
|
+
const confirm2 = await p6.confirm({
|
|
605
703
|
message: "this model has a rate limit of 5 RPM (requests per minute) 50 requests per day, do you want to continue?"
|
|
606
704
|
});
|
|
607
|
-
if (
|
|
608
|
-
|
|
705
|
+
if (p6.isCancel(confirm2) || !confirm2) {
|
|
706
|
+
p6.log.error(color6.red("nothing changed!"));
|
|
609
707
|
return await exit(1);
|
|
610
708
|
}
|
|
611
709
|
}
|
|
@@ -616,7 +714,7 @@ var model = {
|
|
|
616
714
|
model: model2
|
|
617
715
|
}
|
|
618
716
|
}));
|
|
619
|
-
|
|
717
|
+
p6.log.success(color6.green("model configured!"));
|
|
620
718
|
console.log();
|
|
621
719
|
}
|
|
622
720
|
};
|
|
@@ -625,37 +723,37 @@ var reset = {
|
|
|
625
723
|
description: "reset configuration",
|
|
626
724
|
usage: "noto config reset",
|
|
627
725
|
execute: async () => {
|
|
628
|
-
const confirm2 = await
|
|
726
|
+
const confirm2 = await p6.confirm({
|
|
629
727
|
message: "are you sure you want to reset the configuration?"
|
|
630
728
|
});
|
|
631
|
-
if (
|
|
632
|
-
|
|
729
|
+
if (p6.isCancel(confirm2) || !confirm2) {
|
|
730
|
+
p6.log.error(color6.red("nothing changed!"));
|
|
633
731
|
return await exit(1);
|
|
634
732
|
}
|
|
635
733
|
await StorageManager.clear();
|
|
636
|
-
|
|
734
|
+
p6.log.success(color6.green("configuration reset!"));
|
|
637
735
|
console.log();
|
|
638
736
|
}
|
|
639
737
|
};
|
|
640
738
|
var subCommands = [key, model, reset];
|
|
641
|
-
var
|
|
739
|
+
var command4 = {
|
|
642
740
|
name: "config",
|
|
643
741
|
description: "configure noto",
|
|
644
742
|
usage: "noto config [subcommand]",
|
|
645
743
|
execute: async (options) => {
|
|
646
|
-
const
|
|
744
|
+
const command5 = await p6.select({
|
|
647
745
|
message: "Select a subcommand",
|
|
648
746
|
options: subCommands.map((cmd2) => ({
|
|
649
747
|
label: cmd2.description,
|
|
650
748
|
value: cmd2.name
|
|
651
749
|
}))
|
|
652
750
|
});
|
|
653
|
-
if (
|
|
751
|
+
if (p6.isCancel(command5)) {
|
|
654
752
|
return await exit(1);
|
|
655
753
|
}
|
|
656
|
-
const cmd = getCommand(
|
|
754
|
+
const cmd = getCommand(command5, subCommands);
|
|
657
755
|
if (!cmd) {
|
|
658
|
-
|
|
756
|
+
p6.log.error(color6.red("unknown config command"));
|
|
659
757
|
return await exit(1);
|
|
660
758
|
}
|
|
661
759
|
options._ = options._.slice(1);
|
|
@@ -663,34 +761,34 @@ var command3 = {
|
|
|
663
761
|
},
|
|
664
762
|
subCommands
|
|
665
763
|
};
|
|
666
|
-
var config_default =
|
|
764
|
+
var config_default = command4;
|
|
667
765
|
|
|
668
766
|
// src/commands/help.ts
|
|
669
|
-
import
|
|
767
|
+
import color7 from "picocolors";
|
|
670
768
|
var help = {
|
|
671
769
|
name: "help",
|
|
672
770
|
description: "show help",
|
|
673
771
|
usage: "noto help [command]",
|
|
674
772
|
execute: async (options) => {
|
|
675
|
-
const
|
|
676
|
-
if (
|
|
773
|
+
const command5 = getCommand(options._[0]);
|
|
774
|
+
if (command5) {
|
|
677
775
|
console.log();
|
|
678
|
-
console.log(
|
|
679
|
-
console.log(` ${
|
|
776
|
+
console.log(color7.bold("Usage"));
|
|
777
|
+
console.log(` ${command5.usage}`);
|
|
680
778
|
console.log();
|
|
681
|
-
console.log(
|
|
682
|
-
console.log(` ${
|
|
779
|
+
console.log(color7.bold("Description"));
|
|
780
|
+
console.log(` ${command5.description}`);
|
|
683
781
|
console.log();
|
|
684
782
|
} else {
|
|
685
783
|
const commands2 = listCommand();
|
|
686
784
|
console.log();
|
|
687
|
-
console.log(
|
|
785
|
+
console.log(color7.bold("Usage"));
|
|
688
786
|
console.log(` noto [command] [options]`);
|
|
689
787
|
console.log();
|
|
690
|
-
console.log(
|
|
691
|
-
commands2.forEach((
|
|
788
|
+
console.log(color7.bold("Commands"));
|
|
789
|
+
commands2.forEach((command6) => {
|
|
692
790
|
console.log(
|
|
693
|
-
` ${
|
|
791
|
+
` ${color7.bold(command6.name)} ${color7.dim(command6.description)}`
|
|
694
792
|
);
|
|
695
793
|
});
|
|
696
794
|
console.log();
|
|
@@ -700,7 +798,7 @@ var help = {
|
|
|
700
798
|
var help_default = help;
|
|
701
799
|
|
|
702
800
|
// src/commands/index.ts
|
|
703
|
-
var commands = [noto_default, prev_default, config_default, help_default];
|
|
801
|
+
var commands = [noto_default, prev_default, checkout_default, config_default, help_default];
|
|
704
802
|
var getCommand = (name, cmds = commands) => {
|
|
705
803
|
return cmds.find((cmd) => cmd.name === name);
|
|
706
804
|
};
|
|
@@ -709,7 +807,7 @@ var listCommand = () => {
|
|
|
709
807
|
};
|
|
710
808
|
|
|
711
809
|
// package.json
|
|
712
|
-
var version = "1.0
|
|
810
|
+
var version = "1.1.0";
|
|
713
811
|
|
|
714
812
|
// src/index.ts
|
|
715
813
|
var globalSpec = {
|
|
@@ -720,15 +818,15 @@ var globalSpec = {
|
|
|
720
818
|
};
|
|
721
819
|
function main() {
|
|
722
820
|
const args = process.argv.slice(2);
|
|
723
|
-
const { command:
|
|
821
|
+
const { command: command5, options: globalOptions } = parse(globalSpec, args);
|
|
724
822
|
console.log();
|
|
725
|
-
|
|
726
|
-
if (globalOptions["--version"]) return
|
|
823
|
+
p7.intro(`${color8.bgCyan(color8.black(" @snelusha/noto "))}`);
|
|
824
|
+
if (globalOptions["--version"]) return p7.outro(version);
|
|
727
825
|
if (globalOptions["--help"]) {
|
|
728
826
|
getCommand("help")?.execute(globalOptions);
|
|
729
827
|
return;
|
|
730
828
|
}
|
|
731
|
-
const cmd = getCommand(
|
|
829
|
+
const cmd = getCommand(command5) ?? getCommand("noto");
|
|
732
830
|
if (!cmd) return getCommand("noto")?.execute(globalOptions);
|
|
733
831
|
let commandArgs = args;
|
|
734
832
|
let selectedCommand = cmd;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snelusha/noto",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Generate clean commit messages in a snap! ✨",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"homepage": "https://noto.snelusha.dev",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "
|
|
15
|
+
"url": "https://github.com/snelusha/noto.git",
|
|
16
16
|
"directory": "packages/cli"
|
|
17
17
|
},
|
|
18
18
|
"bugs": {
|
|
@@ -42,21 +42,21 @@
|
|
|
42
42
|
"cli"
|
|
43
43
|
],
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@types/node": "^22.
|
|
45
|
+
"@types/node": "^22.14.0",
|
|
46
46
|
"tsup": "^8.4.0",
|
|
47
|
-
"typescript": "^5.8.
|
|
47
|
+
"typescript": "^5.8.3",
|
|
48
|
+
"vitest": "^3.1.1"
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
|
-
"@ai-sdk/google": "^1.2.
|
|
51
|
+
"@ai-sdk/google": "^1.2.7",
|
|
51
52
|
"@clack/prompts": "^0.10.0",
|
|
52
|
-
"ai": "^4.2
|
|
53
|
+
"ai": "^4.3.2",
|
|
53
54
|
"arg": "^5.0.2",
|
|
54
55
|
"clipboardy": "^4.0.0",
|
|
55
56
|
"dedent": "^1.5.3",
|
|
56
57
|
"picocolors": "^1.1.1",
|
|
57
58
|
"simple-git": "^3.27.0",
|
|
58
59
|
"tinyexec": "^0.3.2",
|
|
59
|
-
"vitest": "^3.0.9",
|
|
60
60
|
"zod": "^3.24.2"
|
|
61
61
|
}
|
|
62
62
|
}
|