@tertium/hlpr 0.6.0 → 0.6.2
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/bin/commands/file/rename/README.md +225 -0
- package/bin/commands/git/README.md +129 -0
- package/bin/commands/hello/README.md +35 -0
- package/bin/commands/help/README.md +55 -0
- package/bin/commands/nvm/README.md +90 -0
- package/bin/commands/process/kill-port/README.md +49 -0
- package/bin/commands/process/list-port/README.md +58 -0
- package/bin/commands/ssh/README.md +80 -0
- package/bin/index.js +13 -16
- package/package.json +1 -1
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Rename Command
|
|
2
|
+
|
|
3
|
+
Recursively rename files and folders according to a specific case style.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
hlpr file rename <directory> <style> [--dry|-n] [--no-update-content]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Arguments
|
|
12
|
+
|
|
13
|
+
- `<directory>` - The root directory to recursively process
|
|
14
|
+
- `<style>` - The target case style (see Supported Styles below)
|
|
15
|
+
- `--dry` or `-n` - Optional dry-run mode (preview changes without applying)
|
|
16
|
+
- `--no-update-content` - Skip updating import/require statements in files (content updates are enabled by default)
|
|
17
|
+
|
|
18
|
+
## Supported Styles
|
|
19
|
+
|
|
20
|
+
| Style | Description | Example |
|
|
21
|
+
|-------|-------------|---------|
|
|
22
|
+
| `title_underscore` | Title case with underscores | `File_Name` |
|
|
23
|
+
| `pascal_underscore` | Pascal-style with underscores (alias `title_underscore`) | `File_Name` |
|
|
24
|
+
| `snake` | Lowercase with underscores | `file_name` |
|
|
25
|
+
| `kebab` | Lowercase with hyphens | `file-name` |
|
|
26
|
+
| `camel` | Lowercase first word, capitalized rest | `fileName` |
|
|
27
|
+
| `pascal` | All words capitalized, no separators | `FileName` |
|
|
28
|
+
| `upper` | Uppercase with underscores | `FILE_NAME` |
|
|
29
|
+
| `lower` | Lowercase with underscores | `file_name` |
|
|
30
|
+
|
|
31
|
+
## Examples
|
|
32
|
+
|
|
33
|
+
### Dry Run (Preview Changes)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Preview renaming all files/folders to kebab-case
|
|
37
|
+
hlpr file rename ./my-project kebab --dry
|
|
38
|
+
|
|
39
|
+
# Preview renaming with short flag
|
|
40
|
+
hlpr file rename ./src snake -n
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Apply Changes
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Rename all files/folders to kebab-case
|
|
47
|
+
hlpr file rename ./my-project kebab
|
|
48
|
+
|
|
49
|
+
# Rename to PascalCase
|
|
50
|
+
hlpr file rename ./docs pascal
|
|
51
|
+
|
|
52
|
+
# Rename current directory
|
|
53
|
+
hlpr file rename . snake
|
|
54
|
+
hlpr rename . snake
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
### ✅ Automatic Content Updates
|
|
60
|
+
|
|
61
|
+
**NEW:** By default, the rename command now automatically updates import and require statements in your code files when files are renamed!
|
|
62
|
+
|
|
63
|
+
The tool intelligently detects and updates **all text-based files** by analyzing file content (not just extensions). This includes:
|
|
64
|
+
|
|
65
|
+
- Source code: `.js`, `.ts`, `.jsx`, `.tsx`, `.py`, `.rb`, `.go`, `.rs`, etc.
|
|
66
|
+
- Config files: `.json`, `.yml`, `.yaml`, `.toml`, `.xml`, `.ini`, etc.
|
|
67
|
+
- Documentation: `.md`, `.txt`, `.rst`, etc.
|
|
68
|
+
- Shell scripts: `.sh`, `.bash`, `.zsh`, etc.
|
|
69
|
+
- And any other text file format!
|
|
70
|
+
|
|
71
|
+
Binary files (images, executables, etc.) are automatically skipped.
|
|
72
|
+
|
|
73
|
+
Example:
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
// Before renaming from kebab-case to snake_case:
|
|
77
|
+
import { helper } from './my-utils'
|
|
78
|
+
const x = require('./my-utils')
|
|
79
|
+
|
|
80
|
+
// After running: hlpr file rename . snake
|
|
81
|
+
import { helper } from './my_utils'
|
|
82
|
+
const x = require('./my_utils')
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The feature supports:
|
|
86
|
+
|
|
87
|
+
- Single quotes, double quotes, and backticks
|
|
88
|
+
- Relative paths (`./`, `../`)
|
|
89
|
+
- Files with and without extensions in import statements
|
|
90
|
+
- Both ES6 imports and CommonJS require statements
|
|
91
|
+
|
|
92
|
+
To disable this feature, use the `--no-update-content` flag.
|
|
93
|
+
|
|
94
|
+
### ✅ Recursive Processing
|
|
95
|
+
|
|
96
|
+
The command walks through all subdirectories, renaming:
|
|
97
|
+
|
|
98
|
+
1. Files first (so they don't interfere with directory renames)
|
|
99
|
+
2. Directories after processing their contents
|
|
100
|
+
3. Updates file content references after renaming (unless disabled)
|
|
101
|
+
|
|
102
|
+
### ✅ Extension Preservation
|
|
103
|
+
|
|
104
|
+
File extensions are preserved. Only the base name is transformed:
|
|
105
|
+
|
|
106
|
+
- `file-name.md` → `file_name.md` (snake case)
|
|
107
|
+
- `MyComponent.tsx` → `my-component.tsx` (kebab case)
|
|
108
|
+
|
|
109
|
+
### ✅ Leading Dot Files
|
|
110
|
+
|
|
111
|
+
Files starting with a dot (e.g., `.gitignore`, `.env`) are handled specially:
|
|
112
|
+
|
|
113
|
+
- The leading dot is preserved
|
|
114
|
+
- The rest of the name is transformed
|
|
115
|
+
- `.gitIgnore` → `.git-ignore` (kebab case)
|
|
116
|
+
|
|
117
|
+
### ✅ Case-Only Renames (Windows)
|
|
118
|
+
|
|
119
|
+
Windows filesystems are case-insensitive, so renaming `File.txt` to `file.txt` requires special handling. The command uses a temporary file strategy to handle this correctly.
|
|
120
|
+
|
|
121
|
+
### ✅ Conflict Resolution
|
|
122
|
+
|
|
123
|
+
If a renamed file would conflict with an existing file, the command automatically adds a `_N` suffix:
|
|
124
|
+
|
|
125
|
+
- If `file-name.txt` → `file_name.txt` already exists
|
|
126
|
+
- The new file becomes `file_name_1.txt`
|
|
127
|
+
|
|
128
|
+
### ✅ Dry-Run Mode
|
|
129
|
+
|
|
130
|
+
Use `--dry` or `-n` to preview all changes before applying them:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
hlpr file rename ./src kebab --dry
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Output:
|
|
137
|
+
|
|
138
|
+
```text
|
|
139
|
+
Dry run - would rename 3 items:
|
|
140
|
+
src/myFile.ts → src/my-file.ts
|
|
141
|
+
src/anotherFile.ts → src/another-file.ts
|
|
142
|
+
src/someFolder → src/some-folder
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## TypeScript API
|
|
146
|
+
|
|
147
|
+
The command can also be used programmatically:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { renameRecursive, transformBasename } from './commands/rename/rename.js'
|
|
151
|
+
|
|
152
|
+
// Transform a single basename
|
|
153
|
+
const newName = transformBasename('MyFileName', 'kebab')
|
|
154
|
+
// Returns: 'my-file-name'
|
|
155
|
+
|
|
156
|
+
// Recursively rename with dry-run
|
|
157
|
+
const changes = await renameRecursive('./my-project', 'snake', { dryRun: true })
|
|
158
|
+
// Returns: [{ from: '...', to: '...' }, ...]
|
|
159
|
+
|
|
160
|
+
// Apply changes with content updates (default)
|
|
161
|
+
await renameRecursive('./my-project', 'kebab')
|
|
162
|
+
|
|
163
|
+
// Apply changes without updating file contents
|
|
164
|
+
await renameRecursive('./my-project', 'kebab', { updateContent: false })
|
|
165
|
+
|
|
166
|
+
// Combine options
|
|
167
|
+
await renameRecursive('./my-project', 'snake', {
|
|
168
|
+
dryRun: false,
|
|
169
|
+
updateContent: true
|
|
170
|
+
})
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Technical Details
|
|
174
|
+
|
|
175
|
+
### Word Splitting
|
|
176
|
+
|
|
177
|
+
The command intelligently splits filenames into words by:
|
|
178
|
+
|
|
179
|
+
1. Splitting on non-alphanumeric characters (hyphens, underscores, spaces, etc.)
|
|
180
|
+
2. Splitting on CamelCase boundaries (`myFileName` → `my`, `File`, `Name`)
|
|
181
|
+
3. Preserving Unicode letters and numbers
|
|
182
|
+
|
|
183
|
+
### Transformation Algorithm
|
|
184
|
+
|
|
185
|
+
1. Walk directory tree recursively
|
|
186
|
+
2. For each file:
|
|
187
|
+
- Extract basename (without extension)
|
|
188
|
+
- Transform basename according to style
|
|
189
|
+
- Append original extension
|
|
190
|
+
- Rename file (handling case-only renames and conflicts)
|
|
191
|
+
3. For each directory (after processing contents):
|
|
192
|
+
- Transform directory name according to style
|
|
193
|
+
- Rename directory (handling case-only renames and conflicts)
|
|
194
|
+
|
|
195
|
+
### Error Handling
|
|
196
|
+
|
|
197
|
+
- If a rename fails, the command attempts to revert temporary changes
|
|
198
|
+
- All errors are logged to stderr
|
|
199
|
+
- The command exits with code 1 on failure
|
|
200
|
+
|
|
201
|
+
## Limitations
|
|
202
|
+
|
|
203
|
+
- Files and directories must be accessible (proper permissions)
|
|
204
|
+
- Very long paths (>260 characters on Windows) may fail
|
|
205
|
+
- Symlinks are not followed (treated as regular files/directories)
|
|
206
|
+
|
|
207
|
+
## Examples by Style
|
|
208
|
+
|
|
209
|
+
Starting with: `MyTestFile-name_Example.txt`
|
|
210
|
+
|
|
211
|
+
| Style | Result |
|
|
212
|
+
|-------|--------|
|
|
213
|
+
| `title_underscore` | `My_Test_File_Name_Example.txt` |
|
|
214
|
+
| `snake` | `my_test_file_name_example.txt` |
|
|
215
|
+
| `kebab` | `my-test-file-name-example.txt` |
|
|
216
|
+
| `camel` | `myTestFileNameExample.txt` |
|
|
217
|
+
| `pascal` | `MyTestFileNameExample.txt` |
|
|
218
|
+
| `upper` | `MY_TEST_FILE_NAME_EXAMPLE.txt` |
|
|
219
|
+
| `lower` | `my_test_file_name_example.txt` |
|
|
220
|
+
|
|
221
|
+
## See Also
|
|
222
|
+
|
|
223
|
+
- [Main hlpr README](../../README.md)
|
|
224
|
+
- [TypeScript Implementation](./rename.ts)
|
|
225
|
+
- [Tests](./rename.test.ts)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Git Commands
|
|
2
|
+
|
|
3
|
+
Helpful git utilities for common development workflows.
|
|
4
|
+
|
|
5
|
+
## Platform Support
|
|
6
|
+
|
|
7
|
+
All Git commands work on:
|
|
8
|
+
|
|
9
|
+
- ✅ **Linux** - Fully supported
|
|
10
|
+
- ✅ **macOS** - Fully supported
|
|
11
|
+
- ✅ **Windows** - Requires Git for Windows (includes Git Bash)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## fodd
|
|
16
|
+
|
|
17
|
+
Fetch and update develop branch from origin.
|
|
18
|
+
|
|
19
|
+
**Usage:**
|
|
20
|
+
```bash
|
|
21
|
+
hlpr git fodd
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**What it does:**
|
|
25
|
+
- Fetches the `develop` branch from origin
|
|
26
|
+
- Updates your local `develop` branch to match the remote
|
|
27
|
+
|
|
28
|
+
**When to use:**
|
|
29
|
+
- Before starting work to ensure you have the latest develop branch
|
|
30
|
+
- To sync your local develop with the remote
|
|
31
|
+
|
|
32
|
+
**Command:**
|
|
33
|
+
```bash
|
|
34
|
+
git fetch origin develop:develop
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## precommit
|
|
40
|
+
|
|
41
|
+
Run build and stage binaries before commit.
|
|
42
|
+
|
|
43
|
+
**Usage:**
|
|
44
|
+
```bash
|
|
45
|
+
hlpr git precommit
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**What it does:**
|
|
49
|
+
1. Runs `bun run build` to compile your project
|
|
50
|
+
2. Stages the `bin/` directory for commit
|
|
51
|
+
|
|
52
|
+
**When to use:**
|
|
53
|
+
- Before committing changes to ensure binaries are up-to-date
|
|
54
|
+
- As a git pre-commit hook to automate the process
|
|
55
|
+
|
|
56
|
+
**Example workflow:**
|
|
57
|
+
```bash
|
|
58
|
+
# Make changes to source files
|
|
59
|
+
hlpr git precommit # Build and stage bin/
|
|
60
|
+
git commit -m "feat: add new feature"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## switch-clean
|
|
66
|
+
|
|
67
|
+
Safely switch to a target branch and delete the previous branch (both local and remote).
|
|
68
|
+
|
|
69
|
+
**Usage:**
|
|
70
|
+
```bash
|
|
71
|
+
hlpr git switch-clean <target-branch>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**What it does:**
|
|
75
|
+
|
|
76
|
+
1. **Validates current state**
|
|
77
|
+
- Checks you're on a branch (not detached HEAD)
|
|
78
|
+
- Ensures you're not already on the target branch
|
|
79
|
+
- Verifies there are no uncommitted changes
|
|
80
|
+
|
|
81
|
+
2. **Checks for unpushed commits**
|
|
82
|
+
- Fails if current branch has commits that haven't been pushed
|
|
83
|
+
- Prevents accidental loss of work
|
|
84
|
+
|
|
85
|
+
3. **Fetches target branch**
|
|
86
|
+
- Runs `git fetch origin <target-branch>:<target-branch>`
|
|
87
|
+
- Updates the target branch to match remote
|
|
88
|
+
|
|
89
|
+
4. **Switches to target branch**
|
|
90
|
+
- Checks out the target branch
|
|
91
|
+
|
|
92
|
+
5. **Deletes previous branch**
|
|
93
|
+
- Deletes local branch: `git branch -d <old-branch>`
|
|
94
|
+
- Deletes remote branch (if exists): `git push origin --delete <old-branch>`
|
|
95
|
+
|
|
96
|
+
**Safety Features:**
|
|
97
|
+
|
|
98
|
+
- ✅ **Uncommitted changes check** - Prevents switching if you have uncommitted work
|
|
99
|
+
- ✅ **Unpushed commits check** - Ensures all work is pushed before deletion
|
|
100
|
+
- ✅ **Remote existence check** - Only deletes remote branch if it exists
|
|
101
|
+
- ✅ **Safe branch deletion** - Uses `git branch -d` (not `-D`), refuses to delete unmerged branches
|
|
102
|
+
|
|
103
|
+
**Examples:**
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Switch from feature branch to develop and clean up
|
|
107
|
+
hlpr git switch-clean develop
|
|
108
|
+
# ✓ Switched to 'develop' and deleted 'feature/add-auth' (local & remote)
|
|
109
|
+
|
|
110
|
+
# Switch to main
|
|
111
|
+
hlpr git switch-clean main
|
|
112
|
+
# ✓ Switched to 'main' and deleted 'develop' (local only)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Error Handling:**
|
|
116
|
+
|
|
117
|
+
The command will fail and exit if:
|
|
118
|
+
|
|
119
|
+
- No target branch is specified
|
|
120
|
+
- Not currently on a branch (detached HEAD)
|
|
121
|
+
- Already on the target branch
|
|
122
|
+
- There are uncommitted changes
|
|
123
|
+
- Current branch has unpushed commits
|
|
124
|
+
- Target branch doesn't exist on remote
|
|
125
|
+
|
|
126
|
+
**Solution:**
|
|
127
|
+
- Commit or stash uncommitted changes
|
|
128
|
+
- Push unpushed commits: `git push origin <branch>`
|
|
129
|
+
- Ensure target branch exists on remote
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Hello Commands
|
|
2
|
+
|
|
3
|
+
Example/demo commands for testing the hlpr CLI tool.
|
|
4
|
+
|
|
5
|
+
## Platform Support
|
|
6
|
+
|
|
7
|
+
- ✅ **Linux** - Fully supported
|
|
8
|
+
- ✅ **macOS** - Fully supported
|
|
9
|
+
- ✅ **Windows** - Requires Git Bash or WSL
|
|
10
|
+
|
|
11
|
+
## world
|
|
12
|
+
|
|
13
|
+
Print a personalized hello world message.
|
|
14
|
+
|
|
15
|
+
### Usage
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
hlpr hello world
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The command will prompt you for a name and then print a personalized greeting.
|
|
22
|
+
|
|
23
|
+
### Example
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
$ hlpr hello world
|
|
27
|
+
Enter name: Alice
|
|
28
|
+
Hello World, Alice
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Variables
|
|
32
|
+
|
|
33
|
+
- `name` - Your name (prompted during execution)
|
|
34
|
+
|
|
35
|
+
This command demonstrates the variable substitution feature of hlpr, where `{{name}}` in the script is replaced with user input.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Help Command
|
|
2
|
+
|
|
3
|
+
Displays help information about available commands in the hlpr CLI tool.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
hlpr help
|
|
9
|
+
# or
|
|
10
|
+
hlpr --help
|
|
11
|
+
# or
|
|
12
|
+
hlpr -h
|
|
13
|
+
# or just
|
|
14
|
+
hlpr
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Description
|
|
18
|
+
|
|
19
|
+
The help command automatically discovers all available commands in the `commands/` directory and displays them in an organized format. It shows:
|
|
20
|
+
|
|
21
|
+
- Command categories (e.g., file, git, ssh, nvm)
|
|
22
|
+
- Command names and full usage
|
|
23
|
+
- Command type (TypeScript or Shell)
|
|
24
|
+
- Command descriptions (when available)
|
|
25
|
+
- Usage examples
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- Auto-discovers commands from the commands directory
|
|
30
|
+
- Groups commands by category
|
|
31
|
+
- Shows command types (TypeScript or Shell scripts)
|
|
32
|
+
- Extracts descriptions from:
|
|
33
|
+
- `@description` comments in source files
|
|
34
|
+
- README.md files in command directories
|
|
35
|
+
- Displays formatted help with usage examples
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Show all available commands
|
|
41
|
+
hlpr help
|
|
42
|
+
|
|
43
|
+
# If no command is provided, help is shown automatically
|
|
44
|
+
hlpr
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Output
|
|
48
|
+
|
|
49
|
+
The help command displays:
|
|
50
|
+
|
|
51
|
+
1. **Header** - Tool name and version
|
|
52
|
+
2. **Usage** - Basic syntax
|
|
53
|
+
3. **Options** - Available flags (-f, -v, help)
|
|
54
|
+
4. **Available Commands** - Grouped by category with descriptions
|
|
55
|
+
5. **Examples** - Common usage patterns
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# NVM Commands
|
|
2
|
+
|
|
3
|
+
Node Version Manager (nvm) utility commands.
|
|
4
|
+
|
|
5
|
+
## install
|
|
6
|
+
|
|
7
|
+
Install Node Version Manager (nvm).
|
|
8
|
+
|
|
9
|
+
### Usage
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
hlpr nvm install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Platform Support
|
|
16
|
+
|
|
17
|
+
- ✅ **Linux** - Fully supported
|
|
18
|
+
- ✅ **macOS** - Fully supported
|
|
19
|
+
- ⚠️ **Windows** - Requires Git Bash or WSL (Windows Subsystem for Linux)
|
|
20
|
+
- **Alternative for Windows**: Use [nvm-windows](https://github.com/coreybutler/nvm-windows) instead
|
|
21
|
+
|
|
22
|
+
### What it does
|
|
23
|
+
|
|
24
|
+
Downloads and installs nvm from the official repository using the installation script:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Post-installation
|
|
31
|
+
|
|
32
|
+
After installation, you may need to:
|
|
33
|
+
|
|
34
|
+
1. Close and reopen your terminal
|
|
35
|
+
2. Or source your shell profile:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
source ~/.bashrc # or ~/.zshrc, ~/.bash_profile, etc.
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Verify installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
nvm --version
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## lts
|
|
48
|
+
|
|
49
|
+
Install and use the latest Node.js LTS (Long Term Support) version.
|
|
50
|
+
|
|
51
|
+
### Platform Support (lts)
|
|
52
|
+
|
|
53
|
+
Same as `install` command - requires nvm to be installed.
|
|
54
|
+
|
|
55
|
+
### Usage
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
hlpr nvm lts
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### What it does (lts)
|
|
62
|
+
|
|
63
|
+
1. Downloads and installs the latest LTS version of Node.js
|
|
64
|
+
2. Switches to use the newly installed LTS version
|
|
65
|
+
|
|
66
|
+
Equivalent to running:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
nvm install --lts
|
|
70
|
+
nvm use --lts
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Example
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
$ hlpr nvm lts
|
|
77
|
+
Downloading and installing node v20.11.0...
|
|
78
|
+
Now using node v20.11.0 (npm v10.2.4)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Prerequisites
|
|
82
|
+
|
|
83
|
+
- nvm must be installed first (use `hlpr nvm install`)
|
|
84
|
+
|
|
85
|
+
### Verify (lts)
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
node --version # Should show the LTS version
|
|
89
|
+
npm --version # npm comes with Node.js
|
|
90
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# kill-port
|
|
2
|
+
|
|
3
|
+
Kill process(es) running on a specified port. Supports both Windows and Linux/macOS.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
hlpr process kill-port <port> [options]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Arguments
|
|
12
|
+
|
|
13
|
+
- `port` - Port number (1-65535)
|
|
14
|
+
|
|
15
|
+
## Options
|
|
16
|
+
|
|
17
|
+
- `-f, --force` - Force kill (SIGKILL on Linux, /F on Windows)
|
|
18
|
+
- `-v, --verbose` - Show verbose output
|
|
19
|
+
- `-h, --help` - Show help message
|
|
20
|
+
|
|
21
|
+
## Examples
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Kill process on port 3000
|
|
25
|
+
hlpr process kill-port 3000
|
|
26
|
+
|
|
27
|
+
# Force kill with verbose output
|
|
28
|
+
hlpr process kill-port 8080 --force --verbose
|
|
29
|
+
|
|
30
|
+
# Kill process on port 5432
|
|
31
|
+
hlpr process kill-port 5432 -v
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Platform Support
|
|
35
|
+
|
|
36
|
+
### Windows
|
|
37
|
+
- Uses `netstat -ano` to find processes
|
|
38
|
+
- Uses `taskkill` to kill processes
|
|
39
|
+
- `-f/--force` flag uses `/F` switch (force termination)
|
|
40
|
+
|
|
41
|
+
### Linux/macOS
|
|
42
|
+
- Uses `lsof` (preferred) or `netstat` to find processes
|
|
43
|
+
- Uses `kill` command to terminate processes
|
|
44
|
+
- `-f/--force` flag sends SIGKILL instead of SIGTERM
|
|
45
|
+
|
|
46
|
+
## Exit Codes
|
|
47
|
+
|
|
48
|
+
- `0` - Success (all processes killed or no processes found)
|
|
49
|
+
- `1` - Failure (some processes could not be killed)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# list-port
|
|
2
|
+
|
|
3
|
+
List process(es) running on a specified port. Supports both Windows and Linux/macOS.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
hlpr process list-port <port> [options]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Arguments
|
|
12
|
+
|
|
13
|
+
- `port` - Port number (1-65535)
|
|
14
|
+
|
|
15
|
+
## Options
|
|
16
|
+
|
|
17
|
+
- `-v, --verbose` - Show verbose output
|
|
18
|
+
- `-h, --help` - Show help message
|
|
19
|
+
|
|
20
|
+
## Examples
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# List processes on port 3000
|
|
24
|
+
hlpr process list-port 3000
|
|
25
|
+
|
|
26
|
+
# List with verbose output
|
|
27
|
+
hlpr process list-port 8080 -v
|
|
28
|
+
|
|
29
|
+
# List processes on port 5432
|
|
30
|
+
hlpr process list-port 5432
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Output Format
|
|
34
|
+
|
|
35
|
+
Displays a table with:
|
|
36
|
+
- **PID** - Process ID
|
|
37
|
+
- **STATE** - Connection state (LISTENING, ESTABLISHED, etc.)
|
|
38
|
+
- **COMMAND** - Process name/command
|
|
39
|
+
|
|
40
|
+
## Platform Support
|
|
41
|
+
|
|
42
|
+
### Windows
|
|
43
|
+
- Uses `netstat -ano` to find processes
|
|
44
|
+
- Uses `tasklist` to get process names
|
|
45
|
+
- Shows PID, state, and command
|
|
46
|
+
|
|
47
|
+
### Linux/macOS
|
|
48
|
+
- Uses `lsof` (preferred) or `netstat` (fallback) to find processes
|
|
49
|
+
- Shows PID, state, and command name
|
|
50
|
+
|
|
51
|
+
## Exit Codes
|
|
52
|
+
|
|
53
|
+
- `0` - Success (processes found)
|
|
54
|
+
- `1` - No processes found or error
|
|
55
|
+
|
|
56
|
+
## See Also
|
|
57
|
+
|
|
58
|
+
- `hlpr process kill-port` - Kill processes on a port
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# SSH Commands
|
|
2
|
+
|
|
3
|
+
SSH configuration and setup utilities.
|
|
4
|
+
|
|
5
|
+
## Platform Support
|
|
6
|
+
|
|
7
|
+
- ✅ **Linux** - Fully supported
|
|
8
|
+
- ✅ **macOS** - Fully supported
|
|
9
|
+
- ✅ **Windows** - Requires Git Bash or WSL
|
|
10
|
+
- Git Bash (included with Git for Windows) provides Unix-like `~/.ssh` directory
|
|
11
|
+
- Native Windows SSH uses `%USERPROFILE%\.ssh` instead
|
|
12
|
+
|
|
13
|
+
## init-dir
|
|
14
|
+
|
|
15
|
+
Initialize SSH directory with proper permissions.
|
|
16
|
+
|
|
17
|
+
### Usage
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
hlpr ssh init-dir
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### What it does
|
|
24
|
+
|
|
25
|
+
Creates the `~/.ssh` directory and essential SSH configuration files with correct permissions:
|
|
26
|
+
|
|
27
|
+
1. Creates `~/.ssh` directory (if it doesn't exist)
|
|
28
|
+
2. Creates `~/.ssh/known_hosts` file
|
|
29
|
+
3. Creates `~/.ssh/config` file
|
|
30
|
+
4. Sets directory permissions to 700 (rwx------)
|
|
31
|
+
5. Sets file permissions to 644 (rw-r--r--)
|
|
32
|
+
|
|
33
|
+
### Permissions explained
|
|
34
|
+
|
|
35
|
+
- `~/.ssh/` → 700 (only owner can read/write/execute)
|
|
36
|
+
- `~/.ssh/known_hosts` → 644 (owner can write, others can read)
|
|
37
|
+
- `~/.ssh/config` → 644 (owner can write, others can read)
|
|
38
|
+
|
|
39
|
+
These permissions are required by SSH for security. If permissions are incorrect, SSH will refuse to use the files.
|
|
40
|
+
|
|
41
|
+
### When to use
|
|
42
|
+
|
|
43
|
+
- Setting up SSH on a new system
|
|
44
|
+
- Fixing SSH permission issues
|
|
45
|
+
- After accidentally deleting SSH configuration files
|
|
46
|
+
|
|
47
|
+
### Example
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
$ hlpr ssh init-dir
|
|
51
|
+
# Creates ~/.ssh/ with proper structure and permissions
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Verify
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
ls -la ~/.ssh/
|
|
58
|
+
# Should show:
|
|
59
|
+
# drwx------ ~/.ssh/
|
|
60
|
+
# -rw-r--r-- ~/.ssh/config
|
|
61
|
+
# -rw-r--r-- ~/.ssh/known_hosts
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Note
|
|
65
|
+
|
|
66
|
+
This command will fail if `~/.ssh` already exists. If you need to fix permissions on an existing directory, you can:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
chmod 700 ~/.ssh
|
|
70
|
+
chmod 644 ~/.ssh/known_hosts
|
|
71
|
+
chmod 644 ~/.ssh/config
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Next steps
|
|
75
|
+
|
|
76
|
+
After initializing the SSH directory, you typically:
|
|
77
|
+
|
|
78
|
+
1. Generate SSH keys: `ssh-keygen -t ed25519 -C "your_email@example.com"`
|
|
79
|
+
2. Add SSH config entries to `~/.ssh/config`
|
|
80
|
+
3. Add public key to remote servers or services (GitHub, GitLab, etc.)
|
package/bin/index.js
CHANGED
|
@@ -6,7 +6,6 @@ import { exec } from "node:child_process";
|
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
8
|
import * as readline from "node:readline";
|
|
9
|
-
import * as os from "node:os";
|
|
10
9
|
import { fileURLToPath } from "node:url";
|
|
11
10
|
async function getVersion() {
|
|
12
11
|
try {
|
|
@@ -20,13 +19,6 @@ async function getVersion() {
|
|
|
20
19
|
return "0.0.0";
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
|
-
function detectShell() {
|
|
24
|
-
const isWindows = os.platform() === "win32";
|
|
25
|
-
if (isWindows) {
|
|
26
|
-
return "powershell";
|
|
27
|
-
}
|
|
28
|
-
return "bash";
|
|
29
|
-
}
|
|
30
22
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
31
23
|
var __dirname2 = path.dirname(__filename2);
|
|
32
24
|
var scriptDir = path.join(__dirname2, "..", "src");
|
|
@@ -245,7 +237,7 @@ async function main() {
|
|
|
245
237
|
}
|
|
246
238
|
}
|
|
247
239
|
if (!isTypeScriptCommand && restArgs.length > 0) {
|
|
248
|
-
const scriptName = restArgs
|
|
240
|
+
const scriptName = restArgs[0];
|
|
249
241
|
let scriptPathCandidate = path.join(scriptDir, "commands", category, `${scriptName}.sh`);
|
|
250
242
|
if (!fs.existsSync(scriptPathCandidate)) {
|
|
251
243
|
scriptPathCandidate = path.join(__dirname2, "..", "bin", "commands", category, `${scriptName}.sh`);
|
|
@@ -273,8 +265,8 @@ async function main() {
|
|
|
273
265
|
const finalCommand = `node "${scriptPath}" ${tsArgs.join(" ")}`;
|
|
274
266
|
console.log(`Executing command: ${finalCommand}`);
|
|
275
267
|
const success2 = await executeCommand(finalCommand, {});
|
|
276
|
-
const
|
|
277
|
-
const isHelpInvocation = tsArgs.some((arg) =>
|
|
268
|
+
const helpFlags2 = ["-h", "--help", "help", "/h", "/help", "/?"];
|
|
269
|
+
const isHelpInvocation = tsArgs.some((arg) => helpFlags2.includes(arg));
|
|
278
270
|
if (!success2 && !forceFlag && !isHelpInvocation) {
|
|
279
271
|
console.error("Command failed, stopping execution.");
|
|
280
272
|
process.exit(1);
|
|
@@ -284,6 +276,7 @@ async function main() {
|
|
|
284
276
|
return;
|
|
285
277
|
}
|
|
286
278
|
const scriptContent = await readFile(scriptPath, "utf-8");
|
|
279
|
+
const scriptArgs = restArgs.slice(1);
|
|
287
280
|
const variableRegex = /{{([^}]+)}}/g;
|
|
288
281
|
const variables = {};
|
|
289
282
|
const uniqueVars = new Set;
|
|
@@ -291,9 +284,13 @@ async function main() {
|
|
|
291
284
|
while ((match = variableRegex.exec(scriptContent)) !== null) {
|
|
292
285
|
uniqueVars.add(match[1]);
|
|
293
286
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
287
|
+
const helpFlags = ["-h", "--help", "help", "/h", "/help", "/?"];
|
|
288
|
+
const isHelpRequested = scriptArgs.some((arg) => helpFlags.includes(arg));
|
|
289
|
+
if (!isHelpRequested) {
|
|
290
|
+
for (const varName of uniqueVars) {
|
|
291
|
+
const value = await prompt(`Enter ${varName}: `);
|
|
292
|
+
variables[varName] = value;
|
|
293
|
+
}
|
|
297
294
|
}
|
|
298
295
|
let processedScript = scriptContent;
|
|
299
296
|
for (const [key, value] of Object.entries(variables)) {
|
|
@@ -301,8 +298,8 @@ async function main() {
|
|
|
301
298
|
}
|
|
302
299
|
const tempScriptPath = path.join(path.dirname(scriptPath), `_temp_${path.basename(scriptPath)}`);
|
|
303
300
|
fs.writeFileSync(tempScriptPath, processedScript);
|
|
304
|
-
const
|
|
305
|
-
const command =
|
|
301
|
+
const argsStr = scriptArgs.map((arg) => `"${arg}"`).join(" ");
|
|
302
|
+
const command = `bash "${tempScriptPath}" ${argsStr}`;
|
|
306
303
|
const success = await executeCommand(command, {});
|
|
307
304
|
fs.unlinkSync(tempScriptPath);
|
|
308
305
|
if (!success && !forceFlag) {
|