npmPackage extracts the npm package name from a shell install_cmd like `npm install -g @scope/name@latest`. Returns false when the command is not an npm install.
(installCmd string)
| 106 | // `npm install -g @scope/name@latest`. Returns false when the command is not |
| 107 | // an npm install. |
| 108 | func npmPackage(installCmd string) (string, bool) { |
| 109 | cmd := strings.TrimSpace(installCmd) |
| 110 | if !strings.HasPrefix(cmd, "npm ") { |
| 111 | return "", false |
| 112 | } |
| 113 | parts, err := shlex.Split(cmd) |
| 114 | if err != nil { |
| 115 | return "", false |
| 116 | } |
| 117 | skip := map[string]bool{"npm": true, "install": true, "i": true, "-g": true, "--global": true} |
| 118 | for _, p := range parts { |
| 119 | if skip[p] { |
| 120 | continue |
| 121 | } |
| 122 | // Strip version suffix after @, preserving @scope/name. |
| 123 | if strings.HasPrefix(p, "@") { |
| 124 | idx := strings.Index(p[1:], "@") |
| 125 | if idx >= 0 { |
| 126 | return p[:idx+1], true |
| 127 | } |
| 128 | return p, true |
| 129 | } |
| 130 | if idx := strings.Index(p, "@"); idx > 0 { |
| 131 | return p[:idx], true |
| 132 | } |
| 133 | return p, true |
| 134 | } |
| 135 | return "", false |
| 136 | } |
| 137 | |
| 138 | // versionProbeTimeout bounds how long a single `<bin> --version` probe waits |
| 139 | // for the process to exit. versionProbeWaitDelay bounds how long CombinedOutput |