Skip to content

Commit 7200a3c

Browse files
committed
fix: flag parsing
1 parent 640a116 commit 7200a3c

8 files changed

Lines changed: 691 additions & 242 deletions

File tree

executor.go

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,55 +4,81 @@ import (
44
"fmt"
55
"os"
66
"os/exec"
7+
"strings"
78
)
89

9-
func PassThrough(args ...string) error {
10-
packageManager, err := DetectPackageManager()
10+
func ExecuteTranslatedCommand(pm PackageManager, translated *TranslatedCommand) error {
11+
// Build the final command
12+
finalArgs := append(translated.Command, translated.Flags...)
13+
finalArgs = append(finalArgs, translated.Args...)
14+
15+
fmt.Println("finalArgs", finalArgs)
16+
// Execute the main command
17+
err := executeCommand(string(pm), finalArgs...)
1118
if err != nil {
1219
return err
1320
}
1421

15-
cmd := exec.Command(string(packageManager), args...)
16-
17-
cmd.Stdin = os.Stdin
18-
cmd.Stdout = os.Stdout
19-
cmd.Stderr = os.Stderr
20-
21-
return cmd.Run()
22-
}
22+
fmt.Println("translated.Args", translated.Args)
23+
// Handle @types packages if needed
24+
typesToInstall := []string{}
2325

24-
func Exec(command CommandAlias, args ...string) error {
25-
return ExecWithFlag(command, []flagAlias{}, args...)
26-
}
26+
for _, pkg := range translated.Args {
27+
// Skip if already a @types package
28+
if strings.HasPrefix(pkg, "@types/") {
29+
continue
30+
}
2731

28-
func ExecWithFlag(command CommandAlias, flags []flagAlias, args ...string) error {
29-
packageManager, err := DetectPackageManager()
32+
// Check if the package already has types
33+
if IsTypedPackage(pkg) {
34+
continue
35+
}
3036

31-
if err != nil {
32-
return err
37+
// Check if @types package exists
38+
typesPackage := "@types/" + pkg
39+
exists, _ := CheckPackageExists(typesPackage)
40+
if exists {
41+
typesToInstall = append(typesToInstall, typesPackage)
42+
}
3343
}
3444

35-
flagArgs := make([]string, len(flags))
36-
for i, flag := range flags {
37-
switch packageManager {
45+
// Install @types packages as dev dependencies
46+
if len(typesToInstall) > 0 {
47+
devCommand := []string{}
48+
devFlag := []string{}
49+
50+
switch pm {
3851
case PackageManagerNpm:
39-
flagArgs[i] = flag[PackageManagerNpm][0]
52+
devCommand = []string{"install"}
53+
devFlag = []string{"--save-dev"}
4054
case PackageManagerYarn:
41-
flagArgs[i] = flag[PackageManagerYarn][0]
55+
devCommand = []string{"add"}
56+
devFlag = []string{"--dev"}
4257
case PackageManagerPnpm:
43-
flagArgs[i] = flag[PackageManagerPnpm][0]
58+
devCommand = []string{"add"}
59+
devFlag = []string{"--save-dev"}
4460
case PackageManagerBun:
45-
flagArgs[i] = flag[PackageManagerBun][0]
46-
default:
47-
return fmt.Errorf("unknown package manager: %s", packageManager)
61+
devCommand = []string{"add"}
62+
devFlag = []string{"--dev"}
63+
}
64+
65+
typesArgs := append(devCommand, devFlag...)
66+
typesArgs = append(typesArgs, typesToInstall...)
67+
68+
err = executeCommand(string(pm), typesArgs...)
69+
if err != nil {
70+
// Don't fail if @types installation fails
71+
fmt.Fprintf(os.Stderr, "Warning: Failed to install @types packages: %v\n", err)
4872
}
4973
}
5074

51-
cmd := exec.Command(string(packageManager), append(command[packageManager], append(flagArgs, args...)...)...)
75+
return nil
76+
}
5277

78+
func executeCommand(command string, args ...string) error {
79+
cmd := exec.Command(command, args...)
5380
cmd.Stdin = os.Stdin
5481
cmd.Stdout = os.Stdout
5582
cmd.Stderr = os.Stderr
56-
5783
return cmd.Run()
5884
}

flags.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
package main
22

3-
import (
4-
"strings"
5-
6-
"github.com/spf13/pflag"
7-
)
8-
93
type flagAlias map[PackageManager][]string
104

115
type flags struct {
@@ -48,43 +42,3 @@ var Flags = flags{
4842
PackageManagerBun: []string{"--exact"},
4943
},
5044
}
51-
52-
func isFlag(arg string) (bool, bool) {
53-
if strings.HasPrefix(arg, "--") {
54-
return true, false
55-
}
56-
if strings.HasPrefix(arg, "-") {
57-
return true, true
58-
}
59-
return false, false
60-
}
61-
62-
func filterFlags(args []string, flags *pflag.FlagSet) []string {
63-
filteredArgs := []string{}
64-
65-
for i := 0; i < len(args); {
66-
arg := args[i]
67-
68-
if ok, isShorthand := isFlag(arg); ok {
69-
var flag *pflag.Flag
70-
if isShorthand {
71-
flag = flags.ShorthandLookup(strings.TrimLeft(arg, "-"))
72-
} else {
73-
flag = flags.Lookup(strings.TrimLeft(arg, "-"))
74-
}
75-
if flag != nil {
76-
// If the flag has a value (e.g. --flag=value or -f value), skip it
77-
if flag.Value.Type() != "bool" && i+1 < len(args) {
78-
i++
79-
}
80-
} else {
81-
filteredArgs = append(filteredArgs, arg)
82-
}
83-
} else {
84-
filteredArgs = append(filteredArgs, arg)
85-
}
86-
i++
87-
}
88-
89-
return filteredArgs
90-
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ require golang.org/x/sys v0.33.0 // indirect
1111

1212
require (
1313
github.com/inconshreveable/mousetrap v1.1.0 // indirect
14-
github.com/spf13/pflag v1.0.5
14+
github.com/spf13/pflag v1.0.5 // indirect
1515
)

main.go

Lines changed: 5 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"log"
66
"os"
7-
"strings"
87

98
"github.com/spf13/cobra"
109
)
@@ -31,173 +30,16 @@ func main() {
3130
Exec(Commands.Run, script.Name)
3231
return
3332
}
34-
if IsBuiltInCommand(packageManager, args...) {
35-
if err := PassThrough(args...); err != nil {
36-
fmt.Fprintln(os.Stderr, err)
37-
}
38-
return
39-
}
40-
allArgs := append([]string{"run"}, args...)
41-
if err := PassThrough(allArgs...); err != nil {
42-
fmt.Fprintln(os.Stderr, err)
43-
}
44-
},
45-
Args: cobra.ArbitraryArgs,
46-
}
47-
48-
addCmd := &cobra.Command{
49-
Use: "add <package name>",
50-
Aliases: []string{"i", "install"},
51-
Short: "Add dependency if package name is given.",
52-
Run: func(cmd *cobra.Command, args []string) {
53-
if len(args) == 0 {
54-
log.Fatalf("No package name given")
55-
}
56-
57-
cmd.Flags().Parse(args)
58-
59-
dev := GetBoolFlag(cmd, "save-dev", "dev")
60-
peer := GetBoolFlag(cmd, "save-peer", "peer")
61-
optional := GetBoolFlag(cmd, "save-optional", "optional")
62-
global := GetBoolFlag(cmd, "global")
63-
exact := GetBoolFlag(cmd, "exact")
64-
frozenLockfile := GetBoolFlag(cmd, "frozen-lockfile")
65-
66-
if frozenLockfile {
67-
Exec(Commands.CI)
68-
return
69-
}
70-
71-
var flags []flagAlias
72-
if dev {
73-
flags = append(flags, Flags.Dev)
74-
}
75-
if peer {
76-
flags = append(flags, Flags.Peer)
77-
}
78-
if optional {
79-
flags = append(flags, Flags.Optional)
80-
}
81-
if global {
82-
flags = append(flags, Flags.Global)
83-
}
84-
if exact {
85-
flags = append(flags, Flags.Exact)
86-
}
87-
args = filterFlags(args, cmd.Flags())
88-
89-
ExecWithFlag(Commands.Add, flags, args...)
90-
91-
nonTypedPackages := []string{}
92-
for _, arg := range args {
93-
if !strings.HasPrefix(arg, "@types/") {
94-
if IsTypedPackage(arg) {
95-
continue
96-
}
97-
ok, _ := CheckPackageExists("@types/" + arg)
98-
if !ok {
99-
continue
100-
}
101-
nonTypedPackages = append(nonTypedPackages, "@types/"+arg)
102-
}
103-
}
104-
if !dev && !peer && !optional && !global {
105-
for _, packageName := range nonTypedPackages {
106-
ExecWithFlag(Commands.Add, []flagAlias{Flags.Dev}, packageName)
107-
}
108-
}
109-
},
110-
DisableFlagParsing: true,
111-
}
11233

113-
addCmd.Flags().BoolP("save-dev", "D", false, "install package as dev dependency")
114-
addCmd.Flags().Bool("dev", false, "install package as dev dependency")
115-
addCmd.Flags().MarkHidden("dev")
116-
addCmd.Flags().BoolP("save-peer", "P", false, "install package as peer dependency")
117-
addCmd.Flags().Bool("peer", false, "install package as peer dependency")
118-
addCmd.Flags().MarkHidden("peer")
119-
addCmd.Flags().BoolP("save-optional", "O", false, "install package as optional dependency")
120-
addCmd.Flags().Bool("optional", false, "install package as optional dependency")
121-
addCmd.Flags().MarkHidden("optional")
122-
addCmd.Flags().BoolP("global", "g", false, "install package globally")
123-
addCmd.Flags().BoolP("exact", "E", false, "install exact version")
124-
addCmd.Flags().Bool("frozen-lockfile", false, "don't generate a lockfile and fail if an update is needed")
125-
addCmd.FParseErrWhitelist = cobra.FParseErrWhitelist{UnknownFlags: true}
126-
127-
installCmd := &cobra.Command{
128-
Use: "install [package name]",
129-
Aliases: []string{"i"},
130-
Short: "Add dependency if package name is given. Otherwise, install the package",
131-
Run: func(cmd *cobra.Command, args []string) {
132-
frozenLockfile, _ := cmd.Flags().GetBool("frozen-lockfile")
34+
translator := NewCommandTranslator(packageManager)
35+
translated := translator.Translate(args)
13336

134-
if frozenLockfile {
135-
Exec(Commands.CI)
136-
return
137-
}
138-
139-
if len(args) > 0 {
140-
addCmd.Run(cmd, args)
141-
} else {
142-
Exec(Commands.Install)
143-
}
144-
},
145-
DisableFlagParsing: true,
146-
}
147-
148-
installCmd.Flags().Bool("frozen-lockfile", false, "don't generate a lockfile and fail if an update is needed")
149-
installCmd.FParseErrWhitelist = cobra.FParseErrWhitelist{UnknownFlags: true}
150-
151-
uninstallCmd := &cobra.Command{
152-
Use: "uninstall <package name>",
153-
Aliases: []string{"rm", "remove", "un"},
154-
Short: "Uninstall a package",
155-
Run: func(cmd *cobra.Command, args []string) {
156-
if len(args) == 0 {
157-
log.Fatalf("No package name given")
158-
}
159-
160-
Exec(Commands.Uninstall, args...)
161-
},
162-
DisableFlagParsing: true,
163-
}
164-
uninstallCmd.FParseErrWhitelist = cobra.FParseErrWhitelist{UnknownFlags: true}
165-
166-
ciCmd := &cobra.Command{
167-
Use: "ci",
168-
Short: "CI command",
169-
Run: func(cmd *cobra.Command, args []string) {
170-
Exec(Commands.CI)
171-
},
172-
}
173-
ciCmd.FParseErrWhitelist = cobra.FParseErrWhitelist{UnknownFlags: true}
174-
175-
runCmd := &cobra.Command{
176-
Use: "run",
177-
Short: "Run command",
178-
Run: func(cmd *cobra.Command, args []string) {
179-
if len(args) == 0 {
180-
script, err := showScriptPrompt()
181-
if err != nil {
182-
if err.Error() != "cancelled" {
183-
fmt.Fprintln(os.Stderr, err)
184-
}
185-
return
186-
}
187-
Exec(Commands.Run, script.Name)
188-
} else {
189-
Exec(Commands.Run, args...)
37+
if err := ExecuteTranslatedCommand(packageManager, translated); err != nil {
38+
fmt.Fprintln(os.Stderr, err)
19039
}
19140
},
192-
DisableFlagParsing: true,
41+
Args: cobra.ArbitraryArgs,
19342
}
194-
runCmd.FParseErrWhitelist = cobra.FParseErrWhitelist{UnknownFlags: true}
195-
196-
rootCmd.AddCommand(installCmd)
197-
rootCmd.AddCommand(addCmd)
198-
rootCmd.AddCommand(uninstallCmd)
199-
rootCmd.AddCommand(ciCmd)
200-
rootCmd.AddCommand(runCmd)
20143

20244
if err := rootCmd.Execute(); err != nil {
20345
log.Fatal(err)

npm.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ func CheckPackageExists(packageName string) (bool, error) {
1414
}
1515
defer resp.Body.Close()
1616

17-
if resp.StatusCode == http.StatusOK {
17+
switch resp.StatusCode {
18+
case http.StatusOK:
1819
return true, nil
19-
} else if resp.StatusCode == http.StatusNotFound {
20+
case http.StatusNotFound:
2021
return false, nil
21-
} else {
22+
default:
2223
return false, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
2324
}
2425
}
@@ -35,7 +36,7 @@ type PackageInfo struct {
3536

3637
func IsTypedPackage(packageName string) bool {
3738
url := fmt.Sprintf("https://registry.npmjs.org/%s", packageName)
38-
resp, err := http.Head(url)
39+
resp, err := http.Get(url)
3940
if err != nil {
4041
return false
4142
}

0 commit comments

Comments
 (0)