@tertium/hlpr 0.3.3 → 0.3.4
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/index.js +144 -17
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
1
3
|
// src/index.ts
|
|
2
4
|
import { readFile } from "node:fs/promises";
|
|
3
5
|
import { exec } from "node:child_process";
|
|
@@ -76,6 +78,142 @@ async function executeCommand(command, variables) {
|
|
|
76
78
|
});
|
|
77
79
|
});
|
|
78
80
|
}
|
|
81
|
+
async function showHelp() {
|
|
82
|
+
async function getCommandDescription(filePath) {
|
|
83
|
+
try {
|
|
84
|
+
const content = await readFile(filePath, "utf-8");
|
|
85
|
+
const descMatch = content.match(/(?:\/\/|#)\s*@description\s+(.+)/);
|
|
86
|
+
if (descMatch) {
|
|
87
|
+
return descMatch[1].trim();
|
|
88
|
+
}
|
|
89
|
+
const dir = path.dirname(filePath);
|
|
90
|
+
const readmePath = path.join(dir, "README.md");
|
|
91
|
+
if (fs.existsSync(readmePath)) {
|
|
92
|
+
const readme = await readFile(readmePath, "utf-8");
|
|
93
|
+
const firstLine = readme.split(`
|
|
94
|
+
`).find((line) => line.trim() && !line.startsWith("#"));
|
|
95
|
+
if (firstLine) {
|
|
96
|
+
return firstLine.trim();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch (error) {}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
async function discoverCommands(commandsDir) {
|
|
103
|
+
const commands2 = [];
|
|
104
|
+
try {
|
|
105
|
+
const categories = await fs.promises.readdir(commandsDir, { withFileTypes: true });
|
|
106
|
+
for (const category of categories) {
|
|
107
|
+
if (!category.isDirectory())
|
|
108
|
+
continue;
|
|
109
|
+
const categoryPath = path.join(commandsDir, category.name);
|
|
110
|
+
const items = await fs.promises.readdir(categoryPath, { withFileTypes: true });
|
|
111
|
+
for (const item of items) {
|
|
112
|
+
if (item.isDirectory()) {
|
|
113
|
+
const nestedJsPath = path.join(categoryPath, item.name, `${item.name}.js`);
|
|
114
|
+
const nestedShPath = path.join(categoryPath, item.name, `${item.name}.sh`);
|
|
115
|
+
let commandPath;
|
|
116
|
+
let commandType;
|
|
117
|
+
if (fs.existsSync(nestedJsPath)) {
|
|
118
|
+
commandPath = nestedJsPath;
|
|
119
|
+
commandType = "typescript";
|
|
120
|
+
} else if (fs.existsSync(nestedShPath)) {
|
|
121
|
+
commandPath = nestedShPath;
|
|
122
|
+
commandType = "shell";
|
|
123
|
+
} else {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const description = await getCommandDescription(commandPath);
|
|
127
|
+
commands2.push({
|
|
128
|
+
category: category.name,
|
|
129
|
+
name: item.name,
|
|
130
|
+
type: commandType,
|
|
131
|
+
path: commandPath,
|
|
132
|
+
description
|
|
133
|
+
});
|
|
134
|
+
} else if (item.name.endsWith(".js")) {
|
|
135
|
+
const jsPath = path.join(categoryPath, item.name);
|
|
136
|
+
const commandName = path.basename(item.name, ".js");
|
|
137
|
+
if (commandName !== "test" && !commandName.endsWith(".test")) {
|
|
138
|
+
const description = await getCommandDescription(jsPath);
|
|
139
|
+
commands2.push({
|
|
140
|
+
category: category.name,
|
|
141
|
+
name: commandName,
|
|
142
|
+
type: "typescript",
|
|
143
|
+
path: jsPath,
|
|
144
|
+
description
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
} else if (item.name.endsWith(".sh")) {
|
|
148
|
+
const shPath = path.join(categoryPath, item.name);
|
|
149
|
+
const commandName = path.basename(item.name, ".sh");
|
|
150
|
+
const description = await getCommandDescription(shPath);
|
|
151
|
+
commands2.push({
|
|
152
|
+
category: category.name,
|
|
153
|
+
name: commandName,
|
|
154
|
+
type: "shell",
|
|
155
|
+
path: shPath,
|
|
156
|
+
description
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {}
|
|
162
|
+
return commands2;
|
|
163
|
+
}
|
|
164
|
+
const version = await getVersion();
|
|
165
|
+
const binCommandsDir = path.join(__dirname2, "commands");
|
|
166
|
+
const srcCommandsDir = path.join(__dirname2, "..", "src", "commands");
|
|
167
|
+
const commands = [
|
|
168
|
+
...await discoverCommands(binCommandsDir),
|
|
169
|
+
...await discoverCommands(srcCommandsDir)
|
|
170
|
+
];
|
|
171
|
+
const uniqueCommands = commands.filter((cmd, index, self) => index === self.findIndex((c) => c.category === cmd.category && c.name === cmd.name));
|
|
172
|
+
console.log(`
|
|
173
|
+
╔════════════════════════════════════════════════════════════╗`);
|
|
174
|
+
console.log(`║ hlpr - Helper CLI Tool v${version.padEnd(16)}║`);
|
|
175
|
+
console.log(`╚════════════════════════════════════════════════════════════╝
|
|
176
|
+
`);
|
|
177
|
+
console.log("USAGE:");
|
|
178
|
+
console.log(` hlpr [options] <category> <command> [args...]
|
|
179
|
+
`);
|
|
180
|
+
console.log("OPTIONS:");
|
|
181
|
+
console.log(" -f Force execution (continue on errors)");
|
|
182
|
+
console.log(" -v, --version Show version information");
|
|
183
|
+
console.log(" help, -h, --help, /h, /help, /?");
|
|
184
|
+
console.log(` Show this help message
|
|
185
|
+
`);
|
|
186
|
+
console.log(`AVAILABLE COMMANDS:
|
|
187
|
+
`);
|
|
188
|
+
const grouped = uniqueCommands.reduce((acc, cmd) => {
|
|
189
|
+
if (!acc[cmd.category]) {
|
|
190
|
+
acc[cmd.category] = [];
|
|
191
|
+
}
|
|
192
|
+
acc[cmd.category].push(cmd);
|
|
193
|
+
return acc;
|
|
194
|
+
}, {});
|
|
195
|
+
const sortedCategories = Object.keys(grouped).sort();
|
|
196
|
+
for (const category of sortedCategories) {
|
|
197
|
+
console.log(` ${category}:`);
|
|
198
|
+
const categoryCommands = grouped[category].sort((a, b) => a.name.localeCompare(b.name));
|
|
199
|
+
for (const cmd of categoryCommands) {
|
|
200
|
+
const typeLabel = cmd.type === "typescript" ? "(TS)" : "(sh)";
|
|
201
|
+
const cmdDisplay = cmd.category === cmd.name ? `hlpr ${cmd.name}`.padEnd(35) : `hlpr ${cmd.category} ${cmd.name}`.padEnd(35);
|
|
202
|
+
if (cmd.description) {
|
|
203
|
+
console.log(` ${cmdDisplay} ${typeLabel.padEnd(6)} ${cmd.description}`);
|
|
204
|
+
} else {
|
|
205
|
+
console.log(` ${cmdDisplay} ${typeLabel}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
console.log("");
|
|
209
|
+
}
|
|
210
|
+
console.log("EXAMPLES:");
|
|
211
|
+
console.log(" hlpr help");
|
|
212
|
+
console.log(" hlpr file rename --style kebab --dir ./src");
|
|
213
|
+
console.log(" hlpr ssh init-dir");
|
|
214
|
+
console.log(` hlpr -f git precommit
|
|
215
|
+
`);
|
|
216
|
+
}
|
|
79
217
|
async function main() {
|
|
80
218
|
if (commandArgs[0] === "--version" || commandArgs[0] === "-v") {
|
|
81
219
|
const version = await getVersion();
|
|
@@ -83,17 +221,8 @@ async function main() {
|
|
|
83
221
|
process.exit(0);
|
|
84
222
|
}
|
|
85
223
|
if (commandArgs.length === 0 || commandArgs[0] === "help" || commandArgs[0] === "--help" || commandArgs[0] === "-h" || commandArgs[0] === "/help" || commandArgs[0] === "/h" || commandArgs[0] === "/?") {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const helpCommand = `node "${helpScriptPath}"`;
|
|
89
|
-
await executeCommand(helpCommand, {});
|
|
90
|
-
rl.close();
|
|
91
|
-
process.exit(0);
|
|
92
|
-
} else {
|
|
93
|
-
console.error("Please provide a command. Example: hlpr ssh init-dir");
|
|
94
|
-
console.error("Run 'hlpr help' for available commands.");
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
224
|
+
await showHelp();
|
|
225
|
+
process.exit(0);
|
|
97
226
|
}
|
|
98
227
|
try {
|
|
99
228
|
const category = commandArgs[0];
|
|
@@ -179,9 +308,7 @@ async function main() {
|
|
|
179
308
|
rl.close();
|
|
180
309
|
}
|
|
181
310
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
main
|
|
187
|
-
};
|
|
311
|
+
main().catch((error) => {
|
|
312
|
+
console.error("Fatal error:", error);
|
|
313
|
+
process.exit(1);
|
|
314
|
+
});
|