feat(cli): implement vcs auth and stack detect commands (replaces stubs)#573
feat(cli): implement vcs auth and stack detect commands (replaces stubs)#573threebeats wants to merge 1 commit into
Conversation
- vcs auth: interactive token setup wizard with provider selection and vault persistence via setSecretInLocal - stack detect: auto-detect language/framework from project files (package.json, bun.lock, pyproject.toml, Cargo.toml, etc.) Both commands previously existed as stubs with [stub] placeholders. This PR replaces them with real implementations that persist to the local vault and match the patterns established by login.ts and the existing vault API. Related: profullstack#564
Greptile SummaryThis PR replaces two
Confidence Score: 1/5Not safe to merge — the stray The stray packages/cli/src/commands/config.ts — the only changed file; all three issues are concentrated here. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[sh1pt config] --> B[vcs]
A --> C[stack]
B --> D[vcs set]
B --> E[vcs auth - INTENDED]
D -- "chained via ASI gap (bug)" --> F[vcs set auth - ACTUAL]
C --> G[stack detect]
G --> H{scan cwd}
H -- "*.csproj found via readdirSync" --> I[".NET detected"]
H -- "package.json found (checked before bun.lock)" --> J["Node.js detected (even for Bun projects)"]
H -- "bun.lock found" --> K["Bun detected"]
H -- "pyproject.toml found" --> L["Python detected"]
H -- "Cargo.toml found" --> M["Rust detected"]
H -- "CMakeLists.txt found" --> N["C++ detected"]
H -- "nothing found" --> O["No stack detected"]
style F fill:#f88,stroke:#c00
style J fill:#fa0,stroke:#c60
Reviews (1): Last reviewed commit: "feat(cli): implement vcs auth and stack ..." | Re-trigger Greptile |
| } | ||
| console.log(` ${kleur.yellow("○")} No supported stack detected. Run 'sh1pt config stack set' to pick one.`); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Stray
}); causes a module-level SyntaxError
The PR replaced the stub .action() body but did not remove the original closing }); that belonged to the old stub. The new action block already has its own closing }); at line 195, so the second one at line 196 is orphaned. At module scope there is no open ( or { left for it to close, causing a SyntaxError that prevents the entire config.ts module from loading — every sh1pt config subcommand breaks, not just detect.
| }); | ||
|
|
||
| vcsCmd | ||
| .command('auth') |
There was a problem hiding this comment.
auth command registered under vcs set, not vcs
The PR deleted the vcsCmd receiver on what was vcsCmd.command('auth'). Because the preceding vcs set chain at line 227 ends with }); and no semicolon, JavaScript ASI does not insert one — a leading . always continues the expression. The parser therefore chains .command('auth') off the set subcommand, registering auth as sh1pt config vcs set auth instead of sh1pt config vcs auth. The command is effectively invisible at its intended path.
| const checks = [ | ||
| { file: 'package.json', stack: 'node', label: 'Node.js / TypeScript' }, | ||
| { file: 'bun.lock', stack: 'bun', label: 'Bun' }, |
There was a problem hiding this comment.
bun.lock checked after package.json — Bun projects always detected as Node.js
Bun projects virtually always have both a package.json and a bun.lock. Because package.json appears first in the checks array and the action returns immediately on the first match, any Bun project will be reported as "Node.js / TypeScript". Moving bun.lock before package.json fixes this.
| const checks = [ | |
| { file: 'package.json', stack: 'node', label: 'Node.js / TypeScript' }, | |
| { file: 'bun.lock', stack: 'bun', label: 'Bun' }, | |
| const checks = [ | |
| { file: 'bun.lock', stack: 'bun', label: 'Bun' }, | |
| { file: 'package.json', stack: 'node', label: 'Node.js / TypeScript' }, |
| const { existsSync, readFileSync } = await import("node:fs"); | ||
| const { join } = await import("node:path"); |
There was a problem hiding this comment.
Redundant dynamic imports shadow already-available top-level imports
existsSync, readFileSync, and join are already statically imported at lines 4–5. Re-importing them dynamically inside the action handler is unnecessary and also re-binds them to new local names that shadow the outer imports. readFileSync is additionally destructured but never used in the action body.
| const { existsSync, readFileSync } = await import("node:fs"); | |
| const { join } = await import("node:path"); | |
| // existsSync and join are already imported at the top of the file. |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
2 similar comments
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
🤖 Auto-rebase: The branch was rebased successfully locally but could not be pushed to the fork. Please enable 'Allow edits from maintainers' in the PR settings, or rebase manually: |
|
tests are failing please fix. |
What
config vcs auth: Interactive token setup wizard. Prompts for provider (GitHub/GitLab/Gitea), checks if environment variable already set, then prompts for token and persists to local vault viasetSecretInLocal.config stack detect: Scans project directory for package.json, bun.lock, pyproject.toml, Cargo.toml, *.csproj, CMakeLists.txt to auto-detect the language/framework.Why
Both commands existed as
[stub]placeholders. This PR replaces them with real implementations that follow the established patterns (local-vault.ts for secrets, prompts for interactive input).Related
Closes #564
Closes #133 (partial — implements 2 of the 4 CLI commands)