balda-js 0.0.58 → 0.0.60
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/lib/cli.js +19 -1209
- package/lib/cli.js.map +1 -1
- package/lib/index.cjs +84 -5866
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +101 -21
- package/lib/index.d.ts +101 -21
- package/lib/index.js +84 -5805
- package/lib/index.js.map +1 -1
- package/package.json +6 -2
- package/.github/workflows/publish.yml +0 -38
package/lib/cli.js
CHANGED
|
@@ -1,729 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var __defProp = Object.defineProperty;
|
|
7
|
-
var __decorateClass = (decorators, target, key, kind) => {
|
|
8
|
-
var result = void 0 ;
|
|
9
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
10
|
-
if (decorator = decorators[i])
|
|
11
|
-
result = (decorator(target, key, result) ) || result;
|
|
12
|
-
if (result) __defProp(target, key, result);
|
|
13
|
-
return result;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
// src/runtime/runtime.ts
|
|
17
|
-
var RunTime = class {
|
|
18
|
-
type;
|
|
19
|
-
constructor() {
|
|
20
|
-
this.type = this.getRunTime();
|
|
21
|
-
}
|
|
22
|
-
getRunTime() {
|
|
23
|
-
if (typeof Bun !== "undefined") {
|
|
24
|
-
return "bun";
|
|
25
|
-
} else if (typeof Deno !== "undefined") {
|
|
26
|
-
return "deno";
|
|
27
|
-
} else if (typeof process !== "undefined") {
|
|
28
|
-
return "node";
|
|
29
|
-
}
|
|
30
|
-
throw new Error("No environment detected");
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
var runtime = new RunTime();
|
|
34
|
-
|
|
35
|
-
// src/runtime/native_args.ts
|
|
36
|
-
var NativeArgs = class {
|
|
37
|
-
/**
|
|
38
|
-
* Gets CLI arguments, dynamically determining where they start
|
|
39
|
-
* Handles different execution contexts (direct execution, tsx, ts-node, etc.)
|
|
40
|
-
*/
|
|
41
|
-
getCliArgs() {
|
|
42
|
-
switch (runtime.type) {
|
|
43
|
-
case "bun":
|
|
44
|
-
return this.getBunArgs();
|
|
45
|
-
case "node":
|
|
46
|
-
return this.getNodeArgs();
|
|
47
|
-
case "deno":
|
|
48
|
-
return Deno.args;
|
|
49
|
-
default:
|
|
50
|
-
throw new Error("Unsupported runtime");
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Gets Bun arguments, handling different execution contexts
|
|
55
|
-
*/
|
|
56
|
-
getBunArgs() {
|
|
57
|
-
const args2 = Bun.argv;
|
|
58
|
-
const scriptIndex = this.findScriptIndex(args2);
|
|
59
|
-
return args2.slice(scriptIndex + 1);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Gets Node.js arguments, handling different execution contexts
|
|
63
|
-
*/
|
|
64
|
-
getNodeArgs() {
|
|
65
|
-
const args2 = process.argv;
|
|
66
|
-
const scriptIndex = this.findScriptIndex(args2);
|
|
67
|
-
return args2.slice(scriptIndex + 1);
|
|
68
|
-
}
|
|
69
|
-
findScriptIndex(args2) {
|
|
70
|
-
if (args2.length >= 3 && args2[1].includes(".bin/")) {
|
|
71
|
-
return 1;
|
|
72
|
-
}
|
|
73
|
-
for (let i = 0; i < args2.length; i++) {
|
|
74
|
-
const arg2 = args2[i];
|
|
75
|
-
const argBasename = arg2.split("/").pop() || arg2;
|
|
76
|
-
if (arg2.startsWith("-")) {
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
if (argBasename === "yarn" && i + 1 < args2.length && args2[i + 1] === "run") {
|
|
80
|
-
return i + 1;
|
|
81
|
-
}
|
|
82
|
-
if (argBasename === "npx" && i + 1 < args2.length) {
|
|
83
|
-
return i + 1;
|
|
84
|
-
}
|
|
85
|
-
if (argBasename === "yarn" || argBasename === "pnpm") {
|
|
86
|
-
return i;
|
|
87
|
-
}
|
|
88
|
-
if (argBasename === "npm" && i + 1 < args2.length && args2[i + 1] === "run") {
|
|
89
|
-
return i + 1;
|
|
90
|
-
}
|
|
91
|
-
if (argBasename === "bun" && i + 1 < args2.length && args2[i + 1] === "run") {
|
|
92
|
-
return i + 1;
|
|
93
|
-
}
|
|
94
|
-
if (/\.(js|ts|mjs|cjs)$/.test(arg2)) {
|
|
95
|
-
return i;
|
|
96
|
-
}
|
|
97
|
-
if (/^(tsx|ts-node|node|bun)$/.test(argBasename)) {
|
|
98
|
-
for (let j = i + 1; j < args2.length; j++) {
|
|
99
|
-
if (!args2[j].startsWith("-") && /\.(js|ts|mjs|cjs)$/.test(args2[j])) {
|
|
100
|
-
return j;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return i;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
for (let i = args2.length - 1; i >= 0; i--) {
|
|
107
|
-
const arg2 = args2[i];
|
|
108
|
-
if (!arg2.startsWith("-")) {
|
|
109
|
-
return i;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return 1;
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
var nativeArgs = new NativeArgs();
|
|
116
|
-
|
|
117
|
-
// src/utils.ts
|
|
118
|
-
var levenshteinDistance = (str1, str2) => {
|
|
119
|
-
const matrix = Array(str2.length + 1).fill(null).map(() => Array(str1.length + 1).fill(null));
|
|
120
|
-
for (let i = 0; i <= str1.length; i++) {
|
|
121
|
-
matrix[0][i] = i;
|
|
122
|
-
}
|
|
123
|
-
for (let j = 0; j <= str2.length; j++) {
|
|
124
|
-
matrix[j][0] = j;
|
|
125
|
-
}
|
|
126
|
-
for (let j = 1; j <= str2.length; j++) {
|
|
127
|
-
for (let i = 1; i <= str1.length; i++) {
|
|
128
|
-
const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
129
|
-
matrix[j][i] = Math.min(
|
|
130
|
-
matrix[j][i - 1] + 1,
|
|
131
|
-
matrix[j - 1][i] + 1,
|
|
132
|
-
matrix[j - 1][i - 1] + indicator
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return matrix[str2.length][str1.length];
|
|
137
|
-
};
|
|
138
|
-
var toLowerSnakeCase = (str) => {
|
|
139
|
-
return str.toLowerCase().replace(/[-_.]/g, "_").replace(/([A-Z])/g, "_$1").replace(/^_+/, "").replace(/_+$/, "").toLowerCase();
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
// src/commands/arg_parser.ts
|
|
143
|
-
var parseFlag = (arg2) => {
|
|
144
|
-
if (!arg2 || arg2 === "-" || arg2 === "--") {
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
const equalIndex = arg2.indexOf("=");
|
|
148
|
-
if (equalIndex > 0) {
|
|
149
|
-
const name = arg2.substring(0, equalIndex);
|
|
150
|
-
const value = arg2.substring(equalIndex + 1);
|
|
151
|
-
return {
|
|
152
|
-
name,
|
|
153
|
-
value: parseFlagValue(value)
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
return { name: arg2, value: true };
|
|
157
|
-
};
|
|
158
|
-
var parseFlagValue = (value) => {
|
|
159
|
-
if (value.toLowerCase() === "true") {
|
|
160
|
-
return true;
|
|
161
|
-
}
|
|
162
|
-
if (value.toLowerCase() === "false") {
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
const numValue = Number(value);
|
|
166
|
-
if (!Number.isNaN(numValue) && Number.isFinite(numValue)) {
|
|
167
|
-
return numValue;
|
|
168
|
-
}
|
|
169
|
-
return value;
|
|
170
|
-
};
|
|
171
|
-
var parseCliArgsAndFlags = () => {
|
|
172
|
-
const cliArgs = nativeArgs.getCliArgs();
|
|
173
|
-
const parsedArgs = [];
|
|
174
|
-
const parsedFlags = {};
|
|
175
|
-
if (!cliArgs || !cliArgs.length) {
|
|
176
|
-
return { args: parsedArgs, flags: parsedFlags };
|
|
177
|
-
}
|
|
178
|
-
for (let i = 0; i < cliArgs.length; i++) {
|
|
179
|
-
const arg2 = cliArgs[i];
|
|
180
|
-
if (!arg2 || typeof arg2 !== "string") {
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
if (arg2.startsWith("-")) {
|
|
184
|
-
const flag2 = parseFlag(arg2);
|
|
185
|
-
if (flag2) {
|
|
186
|
-
if (flag2.value === true && i + 1 < cliArgs.length) {
|
|
187
|
-
const nextArg = cliArgs[i + 1];
|
|
188
|
-
if (nextArg && typeof nextArg === "string" && !nextArg.startsWith("-")) {
|
|
189
|
-
flag2.value = parseFlagValue(nextArg);
|
|
190
|
-
i++;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
parsedFlags[flag2.name] = flag2.value;
|
|
194
|
-
}
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
parsedArgs.push(arg2);
|
|
198
|
-
}
|
|
199
|
-
return { args: parsedArgs, flags: parsedFlags };
|
|
200
|
-
};
|
|
201
|
-
var findSimilarCommands = (notFoundCommand, availableCommands) => {
|
|
202
|
-
if (!notFoundCommand || typeof notFoundCommand !== "string") {
|
|
203
|
-
return "";
|
|
204
|
-
}
|
|
205
|
-
if (!availableCommands || !Array.isArray(availableCommands) || availableCommands.length === 0) {
|
|
206
|
-
return "";
|
|
207
|
-
}
|
|
208
|
-
const searchTerm = notFoundCommand.toLowerCase().trim();
|
|
209
|
-
const similarCommands = availableCommands.filter((command) => {
|
|
210
|
-
const normalizedCommand = command.toLowerCase();
|
|
211
|
-
if (normalizedCommand === searchTerm) {
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
if (normalizedCommand.includes(searchTerm) || searchTerm.includes(normalizedCommand)) {
|
|
215
|
-
return true;
|
|
216
|
-
}
|
|
217
|
-
const distance = levenshteinDistance(normalizedCommand, searchTerm);
|
|
218
|
-
const maxDistance = Math.max(searchTerm.length, normalizedCommand.length) * 0.4;
|
|
219
|
-
return distance <= maxDistance;
|
|
220
|
-
});
|
|
221
|
-
if (similarCommands.length === 0) {
|
|
222
|
-
return "";
|
|
223
|
-
}
|
|
224
|
-
const topSuggestions = similarCommands.slice(0, 3);
|
|
225
|
-
const suggestions = topSuggestions.map((cmd) => `\x1B[36m${cmd}\x1B[0m`).join(", ");
|
|
226
|
-
return `\x1B[31m\u2717\x1B[0m Command \x1B[33m${notFoundCommand}\x1B[0m not found
|
|
227
|
-
\x1B[32m\u{1F4A1}\x1B[0m Did you mean: ${suggestions}?`;
|
|
228
|
-
};
|
|
229
|
-
var getCalledCommandName = () => {
|
|
230
|
-
const cliArgs = nativeArgs.getCliArgs();
|
|
231
|
-
return cliArgs[0] || null;
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
// src/runtime/native_exit.ts
|
|
235
|
-
var NativeExit = class {
|
|
236
|
-
exit(code) {
|
|
237
|
-
switch (runtime.type) {
|
|
238
|
-
case "bun":
|
|
239
|
-
case "node":
|
|
240
|
-
process.exit(code);
|
|
241
|
-
case "deno":
|
|
242
|
-
Deno.exit(code);
|
|
243
|
-
default:
|
|
244
|
-
throw new Error("Unsupported runtime");
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
};
|
|
248
|
-
var nativeExit = new NativeExit();
|
|
249
|
-
|
|
250
|
-
// src/metadata_store.ts
|
|
251
|
-
var MetadataStore = class {
|
|
252
|
-
static metadata = /* @__PURE__ */ new WeakMap();
|
|
253
|
-
/**
|
|
254
|
-
* Set the metadata for the given target and property key
|
|
255
|
-
*/
|
|
256
|
-
static set(target, propertyKey, value) {
|
|
257
|
-
if (!this.metadata.has(target)) {
|
|
258
|
-
this.metadata.set(target, /* @__PURE__ */ new Map());
|
|
259
|
-
}
|
|
260
|
-
this.metadata.get(target).set(propertyKey, value);
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Get the metadata for the given target and property key
|
|
264
|
-
*/
|
|
265
|
-
static get(target, propertyKey) {
|
|
266
|
-
return this.metadata.get(target)?.get(propertyKey);
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Get all the metadata for the given target
|
|
270
|
-
*/
|
|
271
|
-
static getAll(target) {
|
|
272
|
-
return this.metadata.get(target) || /* @__PURE__ */ new Map();
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Delete the metadata for the given target and property key
|
|
276
|
-
*/
|
|
277
|
-
static delete(target, propertyKey) {
|
|
278
|
-
this.metadata.get(target)?.delete(propertyKey.toString());
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Clear all the metadata for the given target
|
|
282
|
-
*/
|
|
283
|
-
static clear(target) {
|
|
284
|
-
this.metadata.delete(target);
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
// src/decorators/command/arg.ts
|
|
289
|
-
var VALIDATION_ERROR_SYMBOL = "VALIDATION_ERROR";
|
|
290
|
-
var args = parseCliArgsAndFlags().args.slice(1);
|
|
291
|
-
var arg = (options) => {
|
|
292
|
-
return (target, propertyKey) => {
|
|
293
|
-
const currentCommandName = getCalledCommandName();
|
|
294
|
-
if (!currentCommandName || currentCommandName !== target.commandName) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
const argName = propertyKey;
|
|
298
|
-
MetadataStore.set(target, propertyKey, {
|
|
299
|
-
type: "arg",
|
|
300
|
-
name: argName,
|
|
301
|
-
description: options.description
|
|
302
|
-
});
|
|
303
|
-
let argValue = args.length ? args.shift() : options.defaultValue;
|
|
304
|
-
if (options.required && !argValue) {
|
|
305
|
-
const errorChain = MetadataStore.get(target, VALIDATION_ERROR_SYMBOL);
|
|
306
|
-
MetadataStore.set(target, VALIDATION_ERROR_SYMBOL, [
|
|
307
|
-
...errorChain || [],
|
|
308
|
-
{
|
|
309
|
-
type: "arg",
|
|
310
|
-
name: argName,
|
|
311
|
-
message: "Required argument not provided"
|
|
312
|
-
}
|
|
313
|
-
]);
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
if (options.parse && argValue) {
|
|
317
|
-
argValue = options.parse(argValue);
|
|
318
|
-
}
|
|
319
|
-
Object.defineProperty(target, propertyKey, {
|
|
320
|
-
value: argValue,
|
|
321
|
-
enumerable: true,
|
|
322
|
-
configurable: true,
|
|
323
|
-
writable: true
|
|
324
|
-
});
|
|
325
|
-
};
|
|
326
|
-
};
|
|
327
|
-
var createBaseLogger = () => {
|
|
328
|
-
const baseOptions = {
|
|
329
|
-
level: "info",
|
|
330
|
-
formatters: {
|
|
331
|
-
level: (label) => {
|
|
332
|
-
return { level: label };
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
return pino(baseOptions);
|
|
337
|
-
};
|
|
338
|
-
var logger = createBaseLogger();
|
|
339
|
-
|
|
340
|
-
// src/commands/base_command.ts
|
|
341
|
-
var Command = class {
|
|
342
|
-
/**
|
|
343
|
-
* The name of the command.
|
|
344
|
-
*/
|
|
345
|
-
static commandName = this.name;
|
|
346
|
-
/**
|
|
347
|
-
* The description of the command.
|
|
348
|
-
*/
|
|
349
|
-
static description = "";
|
|
350
|
-
/**
|
|
351
|
-
* The help text of the command.
|
|
352
|
-
*/
|
|
353
|
-
static help = [];
|
|
354
|
-
/**
|
|
355
|
-
* The options of the command.
|
|
356
|
-
*/
|
|
357
|
-
static options = {
|
|
358
|
-
keepAlive: false
|
|
359
|
-
};
|
|
360
|
-
/**
|
|
361
|
-
* Static arguments in order to be validated by decorators. Will be fetched in the command instance.
|
|
362
|
-
*/
|
|
363
|
-
static args = parseCliArgsAndFlags().args.slice(1);
|
|
364
|
-
/**
|
|
365
|
-
* Static flags in order to be validated by decorators. Will be fetched in the command instance.
|
|
366
|
-
*/
|
|
367
|
-
static flags = parseCliArgsAndFlags().flags;
|
|
368
|
-
static logger = logger;
|
|
369
|
-
/**
|
|
370
|
-
* Main entry point for the command.
|
|
371
|
-
*/
|
|
372
|
-
static handle() {
|
|
373
|
-
throw new Error(
|
|
374
|
-
`Handle method not implemented in command class ${this.name}`
|
|
375
|
-
);
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Enhanced help flag handler with rich formatting and command information
|
|
379
|
-
*/
|
|
380
|
-
static handleHelpFlag(flags) {
|
|
381
|
-
const helpFlags = ["-h", "--help"];
|
|
382
|
-
const hasHelpFlag = Object.keys(flags).some(
|
|
383
|
-
(flag2) => helpFlags.includes(flag2)
|
|
384
|
-
);
|
|
385
|
-
if (!hasHelpFlag) {
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
const commandName = this.commandName;
|
|
389
|
-
const description = this.description || "No description available";
|
|
390
|
-
const helpText = this.help || [];
|
|
391
|
-
const options = this.options;
|
|
392
|
-
const helpOutput = this.generateHelpOutput(
|
|
393
|
-
{
|
|
394
|
-
name: commandName,
|
|
395
|
-
description,
|
|
396
|
-
helpText,
|
|
397
|
-
options,
|
|
398
|
-
args: this.args,
|
|
399
|
-
flags: this.flags
|
|
400
|
-
},
|
|
401
|
-
this
|
|
402
|
-
);
|
|
403
|
-
console.log(helpOutput);
|
|
404
|
-
nativeExit.exit(0);
|
|
405
|
-
}
|
|
406
|
-
static generateHelpOutput = (info, commandClass) => {
|
|
407
|
-
const { name, description, helpText, options, args: args2, flags } = info;
|
|
408
|
-
const colors = {
|
|
409
|
-
title: "\x1B[1;36m",
|
|
410
|
-
// Bright cyan
|
|
411
|
-
subtitle: "\x1B[1;33m",
|
|
412
|
-
// Bright yellow
|
|
413
|
-
description: "\x1B[0;37m",
|
|
414
|
-
// White
|
|
415
|
-
code: "\x1B[0;32m",
|
|
416
|
-
// Green
|
|
417
|
-
flag: "\x1B[0;35m",
|
|
418
|
-
// Magenta
|
|
419
|
-
reset: "\x1B[0m",
|
|
420
|
-
// Reset
|
|
421
|
-
error: "\x1B[0;31m",
|
|
422
|
-
// Red
|
|
423
|
-
success: "\x1B[0;32m",
|
|
424
|
-
// Green
|
|
425
|
-
info: "\x1B[0;34m"
|
|
426
|
-
// Blue
|
|
427
|
-
};
|
|
428
|
-
const lines = [
|
|
429
|
-
`${colors.title}${name}${colors.reset}`,
|
|
430
|
-
`${colors.description}${description}${colors.reset}`,
|
|
431
|
-
"",
|
|
432
|
-
`${colors.subtitle}Usage:${colors.reset}`,
|
|
433
|
-
` ${colors.code}${name}${colors.reset} [options] [arguments]`,
|
|
434
|
-
"",
|
|
435
|
-
`${colors.subtitle}Options:${colors.reset}`,
|
|
436
|
-
` ${colors.flag}-h, --help${colors.reset} Show this help message`,
|
|
437
|
-
"",
|
|
438
|
-
`${colors.subtitle}Command Options:${colors.reset}`,
|
|
439
|
-
` ${colors.flag}keepAlive${colors.reset} ${options?.keepAlive ?? false ? colors.success + "Enabled" + colors.reset : colors.error + "Disabled" + colors.reset}`,
|
|
440
|
-
""
|
|
441
|
-
];
|
|
442
|
-
if (helpText) {
|
|
443
|
-
const helpLines = Array.isArray(helpText) ? helpText : [helpText];
|
|
444
|
-
lines.push(`${colors.subtitle}Help:${colors.reset}`);
|
|
445
|
-
helpLines.forEach((line) => {
|
|
446
|
-
lines.push(` ${colors.description}${line}${colors.reset}`);
|
|
447
|
-
});
|
|
448
|
-
lines.push("");
|
|
449
|
-
}
|
|
450
|
-
const allMeta = MetadataStore.getAll(commandClass);
|
|
451
|
-
const argsMeta = Array.from(allMeta.values()).filter(
|
|
452
|
-
(meta) => meta.type === "arg"
|
|
453
|
-
);
|
|
454
|
-
const flagsMeta = Array.from(allMeta.values()).filter(
|
|
455
|
-
(meta) => meta.type === "flag"
|
|
456
|
-
);
|
|
457
|
-
if (argsMeta.length) {
|
|
458
|
-
lines.push(`${colors.subtitle}Available Arguments:${colors.reset}`);
|
|
459
|
-
argsMeta.forEach((meta) => {
|
|
460
|
-
const required = meta.required ? ` ${colors.error}(required)${colors.reset}` : "";
|
|
461
|
-
const description2 = meta.description ? ` ${colors.description}${meta.description}${colors.reset}` : "";
|
|
462
|
-
lines.push(
|
|
463
|
-
` ${colors.code}${meta.name}${colors.reset}${required}${description2}`
|
|
464
|
-
);
|
|
465
|
-
});
|
|
466
|
-
lines.push("");
|
|
467
|
-
}
|
|
468
|
-
if (flagsMeta.length) {
|
|
469
|
-
lines.push(`${colors.subtitle}Available Flags:${colors.reset}`);
|
|
470
|
-
flagsMeta.forEach((meta) => {
|
|
471
|
-
if (meta.aliases && !Array.isArray(meta.aliases)) {
|
|
472
|
-
meta.aliases = [meta.aliases];
|
|
473
|
-
}
|
|
474
|
-
const aliases = meta.aliases.length ? ` ${colors.flag}(${meta.aliases.join(", ")})${colors.reset}` : "";
|
|
475
|
-
const required = meta.required ? ` ${colors.error}(required)${colors.reset}` : "";
|
|
476
|
-
const description2 = meta.description ? ` ${colors.description}${meta.description}${colors.reset}` : "";
|
|
477
|
-
lines.push(
|
|
478
|
-
` ${colors.flag}--${meta.name}${aliases}${colors.reset}${required}${description2}`
|
|
479
|
-
);
|
|
480
|
-
});
|
|
481
|
-
lines.push("");
|
|
482
|
-
}
|
|
483
|
-
if ((args2?.length ?? 0) > 0 || flags && Object.keys(flags).length > 0) {
|
|
484
|
-
lines.push(`${colors.subtitle}Current Context:${colors.reset}`);
|
|
485
|
-
if (args2?.length) {
|
|
486
|
-
lines.push(
|
|
487
|
-
` ${colors.info}Provided Arguments:${colors.reset} ${colors.code}${args2.join(" ")}${colors.reset}`
|
|
488
|
-
);
|
|
489
|
-
}
|
|
490
|
-
if (flags && Object.keys(flags).length > 0) {
|
|
491
|
-
lines.push(` ${colors.info}Provided Flags:${colors.reset}`);
|
|
492
|
-
Object.keys(flags).forEach((flagKey) => {
|
|
493
|
-
const flagValue = flags[flagKey];
|
|
494
|
-
const valueDisplay = flagValue !== void 0 && flagValue !== null ? ` = ${colors.code}${flagValue}${colors.reset}` : "";
|
|
495
|
-
lines.push(
|
|
496
|
-
` ${colors.flag}${flagKey}${colors.reset}${valueDisplay}`
|
|
497
|
-
);
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
lines.push("");
|
|
501
|
-
}
|
|
502
|
-
if (helpText && (Array.isArray(helpText) ? helpText.some((line) => line.includes("example")) : helpText.includes("example"))) {
|
|
503
|
-
lines.push(`${colors.subtitle}Examples:${colors.reset}`);
|
|
504
|
-
const examples = Array.isArray(helpText) ? helpText.filter((line) => line.includes("example")) : [helpText.split("example")[1].trim()];
|
|
505
|
-
examples.forEach((example) => {
|
|
506
|
-
lines.push(` ${colors.code}${example}${colors.reset}`);
|
|
507
|
-
});
|
|
508
|
-
lines.push("");
|
|
509
|
-
}
|
|
510
|
-
return lines.join("\n");
|
|
511
|
-
};
|
|
512
|
-
static validateContext = (target) => {
|
|
513
|
-
const errorChain = Array.from(
|
|
514
|
-
MetadataStore.get(target, VALIDATION_ERROR_SYMBOL) || []
|
|
515
|
-
);
|
|
516
|
-
if (errorChain.length) {
|
|
517
|
-
const colors = {
|
|
518
|
-
error: "\x1B[0;31m",
|
|
519
|
-
// Red
|
|
520
|
-
title: "\x1B[1;31m",
|
|
521
|
-
// Bright red
|
|
522
|
-
reset: "\x1B[0m",
|
|
523
|
-
// Reset
|
|
524
|
-
info: "\x1B[0;34m",
|
|
525
|
-
// Blue
|
|
526
|
-
code: "\x1B[0;32m"
|
|
527
|
-
// Green
|
|
528
|
-
};
|
|
529
|
-
console.error(`${colors.title}\u274C Validation Errors:${colors.reset}`);
|
|
530
|
-
console.error("");
|
|
531
|
-
errorChain.forEach((error, index) => {
|
|
532
|
-
const errorNumber = `${colors.info}${index + 1}.${colors.reset}`;
|
|
533
|
-
const errorType = `${colors.error}${error.type.toUpperCase()}${colors.reset}`;
|
|
534
|
-
const errorName = `${colors.code}${error.name}${colors.reset}`;
|
|
535
|
-
console.error(
|
|
536
|
-
` ${errorNumber} ${errorType} ${errorName}: ${colors.error}${error.message}${colors.reset}`
|
|
537
|
-
);
|
|
538
|
-
});
|
|
539
|
-
console.error("");
|
|
540
|
-
console.error(
|
|
541
|
-
`${colors.info}\u{1F4A1} Tip: Use --help for usage information${colors.reset}`
|
|
542
|
-
);
|
|
543
|
-
nativeExit.exit(1);
|
|
544
|
-
}
|
|
545
|
-
};
|
|
546
|
-
};
|
|
547
|
-
|
|
548
|
-
// src/runtime/native_fs.ts
|
|
549
|
-
var NativeFs = class {
|
|
550
|
-
async mkdir(path2, options) {
|
|
551
|
-
switch (runtime.type) {
|
|
552
|
-
case "bun":
|
|
553
|
-
case "node":
|
|
554
|
-
const fs = await import('fs/promises');
|
|
555
|
-
await fs.mkdir(path2, {
|
|
556
|
-
recursive: options?.recursive ?? false,
|
|
557
|
-
mode: options?.mode
|
|
558
|
-
});
|
|
559
|
-
break;
|
|
560
|
-
case "deno":
|
|
561
|
-
if (typeof options?.mode === "string") {
|
|
562
|
-
options.mode = Number.parseInt(options.mode);
|
|
563
|
-
}
|
|
564
|
-
await Deno.mkdir(path2, {
|
|
565
|
-
recursive: options?.recursive ?? false,
|
|
566
|
-
mode: options?.mode
|
|
567
|
-
});
|
|
568
|
-
break;
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
async exists(path2) {
|
|
572
|
-
switch (runtime.type) {
|
|
573
|
-
case "node":
|
|
574
|
-
const fs = await import('fs');
|
|
575
|
-
return fs.existsSync(path2);
|
|
576
|
-
case "bun":
|
|
577
|
-
return Bun.file(path2).exists();
|
|
578
|
-
case "deno":
|
|
579
|
-
return Deno.stat(path2).then(() => true).catch(() => false);
|
|
580
|
-
default:
|
|
581
|
-
throw new Error("Unsupported runtime");
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
async readFile(path2) {
|
|
585
|
-
switch (runtime.type) {
|
|
586
|
-
case "node":
|
|
587
|
-
const fs = await import('fs/promises');
|
|
588
|
-
const buffer = await fs.readFile(path2);
|
|
589
|
-
return new Uint8Array(buffer);
|
|
590
|
-
case "bun":
|
|
591
|
-
const arrayBuffer = await Bun.file(path2).arrayBuffer();
|
|
592
|
-
return new Uint8Array(arrayBuffer);
|
|
593
|
-
case "deno":
|
|
594
|
-
return new Uint8Array(await Deno.readFile(path2));
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
async writeFile(path2, data) {
|
|
598
|
-
switch (runtime.type) {
|
|
599
|
-
case "node":
|
|
600
|
-
const fs = await import('fs/promises');
|
|
601
|
-
await fs.writeFile(path2, data);
|
|
602
|
-
break;
|
|
603
|
-
case "bun":
|
|
604
|
-
await Bun.write(path2, data);
|
|
605
|
-
break;
|
|
606
|
-
case "deno":
|
|
607
|
-
await Deno.writeFile(path2, data);
|
|
608
|
-
break;
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
async stat(path2) {
|
|
612
|
-
switch (runtime.type) {
|
|
613
|
-
case "node":
|
|
614
|
-
const fs = await import('fs/promises');
|
|
615
|
-
const stats = await fs.stat(path2);
|
|
616
|
-
return {
|
|
617
|
-
isDirectory: stats.isDirectory(),
|
|
618
|
-
isFile: stats.isFile(),
|
|
619
|
-
isSymbolicLink: stats.isSymbolicLink(),
|
|
620
|
-
size: stats.size
|
|
621
|
-
};
|
|
622
|
-
case "bun":
|
|
623
|
-
const bunStats = await Bun.file(path2).stat();
|
|
624
|
-
return {
|
|
625
|
-
isDirectory: bunStats.isDirectory(),
|
|
626
|
-
isFile: bunStats.isFile(),
|
|
627
|
-
isSymbolicLink: bunStats.isSymbolicLink(),
|
|
628
|
-
size: bunStats.size
|
|
629
|
-
};
|
|
630
|
-
case "deno":
|
|
631
|
-
const denoStats = await Deno.stat(path2);
|
|
632
|
-
return {
|
|
633
|
-
isDirectory: denoStats.isDirectory,
|
|
634
|
-
isFile: denoStats.isFile,
|
|
635
|
-
isSymbolicLink: false,
|
|
636
|
-
size: denoStats.size
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
async unlink(path2) {
|
|
641
|
-
switch (runtime.type) {
|
|
642
|
-
case "node":
|
|
643
|
-
const fs = await import('fs/promises');
|
|
644
|
-
await fs.unlink(path2);
|
|
645
|
-
break;
|
|
646
|
-
case "bun":
|
|
647
|
-
await Bun.file(path2).delete();
|
|
648
|
-
break;
|
|
649
|
-
case "deno":
|
|
650
|
-
await Deno.remove(path2);
|
|
651
|
-
break;
|
|
652
|
-
default:
|
|
653
|
-
throw new Error("Unsupported runtime");
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
};
|
|
657
|
-
var nativeFs = new NativeFs();
|
|
658
|
-
var NativePath = class {
|
|
659
|
-
join(...paths) {
|
|
660
|
-
switch (runtime.type) {
|
|
661
|
-
case "node":
|
|
662
|
-
case "bun":
|
|
663
|
-
case "deno":
|
|
664
|
-
return path.join(...paths);
|
|
665
|
-
default:
|
|
666
|
-
throw new Error("Unsupported runtime");
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
extName(inputPath) {
|
|
670
|
-
switch (runtime.type) {
|
|
671
|
-
case "bun":
|
|
672
|
-
case "node":
|
|
673
|
-
case "deno":
|
|
674
|
-
return path.extname(inputPath);
|
|
675
|
-
default:
|
|
676
|
-
throw new Error("Unsupported runtime");
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
resolve(...paths) {
|
|
680
|
-
switch (runtime.type) {
|
|
681
|
-
case "bun":
|
|
682
|
-
case "node":
|
|
683
|
-
case "deno":
|
|
684
|
-
return path.resolve(...paths);
|
|
685
|
-
default:
|
|
686
|
-
throw new Error("Unsupported runtime");
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
};
|
|
690
|
-
var nativePath = new NativePath();
|
|
691
|
-
|
|
692
|
-
// src/commands/base_commands/generate_command.ts
|
|
693
|
-
var GenerateCommand = class extends Command {
|
|
694
|
-
static commandName = "generate-command";
|
|
695
|
-
static description = "Generate a new command in the specified path";
|
|
696
|
-
static help = [
|
|
697
|
-
"Generate a new cli command in the specified path",
|
|
698
|
-
"Example: npx balda generate-command my-command -p src/commands"
|
|
699
|
-
];
|
|
700
|
-
/**
|
|
701
|
-
* The path where the command will be generated
|
|
702
|
-
*/
|
|
703
|
-
static path = "src/commands";
|
|
704
|
-
static name;
|
|
705
|
-
static async handle() {
|
|
706
|
-
const commandTemplate = this.getCommandTemplate();
|
|
707
|
-
this.path = nativePath.join(this.path, `${this.name}.ts`);
|
|
708
|
-
if (!await nativeFs.exists(nativePath.join(process.cwd(), this.path))) {
|
|
709
|
-
await nativeFs.mkdir(
|
|
710
|
-
nativePath.join(
|
|
711
|
-
process.cwd(),
|
|
712
|
-
this.path.split("/").slice(0, -1).join("/")
|
|
713
|
-
),
|
|
714
|
-
{ recursive: true }
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
await nativeFs.writeFile(
|
|
718
|
-
this.path,
|
|
719
|
-
new TextEncoder().encode(commandTemplate)
|
|
720
|
-
);
|
|
721
|
-
this.logger.info(
|
|
722
|
-
`Command ${this.name} created successfully at ${this.path}`
|
|
723
|
-
);
|
|
724
|
-
}
|
|
725
|
-
static getCommandTemplate() {
|
|
726
|
-
return `import { Command, CommandOptions } from "balda-js";
|
|
2
|
+
import {glob}from'glob';import ce from'pino';import z from'path';import {execSync}from'child_process';import M from'fs';var ne=Object.defineProperty;var m=(r,e,t,s)=>{for(var i=void 0,a=r.length-1,o;a>=0;a--)(o=r[a])&&(i=(o(e,t,i))||i);return i&&ne(e,t,i),i};var V=class{type;constructor(){this.type=this.getRunTime();}getRunTime(){if(typeof Bun<"u")return "bun";if(typeof Deno<"u")return "deno";if(typeof process<"u")return "node";throw new Error("No environment detected")}},f=new V;var _=class{getCliArgs(){switch(f.type){case "bun":return this.getBunArgs();case "node":return this.getNodeArgs();case "deno":return Deno.args;default:throw new Error("Unsupported runtime")}}getBunArgs(){let e=Bun.argv,t=this.findScriptIndex(e);return e.slice(t+1)}getNodeArgs(){let e=process.argv,t=this.findScriptIndex(e);return e.slice(t+1)}findScriptIndex(e){if(e.length>=3&&e[1].includes(".bin/"))return 1;for(let t=0;t<e.length;t++){let s=e[t],i=s.split("/").pop()||s;if(!s.startsWith("-")){if(i==="yarn"&&t+1<e.length&&e[t+1]==="run"||i==="npx"&&t+1<e.length)return t+1;if(i==="yarn"||i==="pnpm")return t;if(i==="npm"&&t+1<e.length&&e[t+1]==="run"||i==="bun"&&t+1<e.length&&e[t+1]==="run")return t+1;if(/\.(js|ts|mjs|cjs)$/.test(s))return t;if(/^(tsx|ts-node|node|bun)$/.test(i)){for(let a=t+1;a<e.length;a++)if(!e[a].startsWith("-")&&/\.(js|ts|mjs|cjs)$/.test(e[a]))return a;return t}}}for(let t=e.length-1;t>=0;t--)if(!e[t].startsWith("-"))return t;return 1}},E=new _;var G=(r,e)=>{let t=Array(e.length+1).fill(null).map(()=>Array(r.length+1).fill(null));for(let s=0;s<=r.length;s++)t[0][s]=s;for(let s=0;s<=e.length;s++)t[s][0]=s;for(let s=1;s<=e.length;s++)for(let i=1;i<=r.length;i++){let a=r[i-1]===e[s-1]?0:1;t[s][i]=Math.min(t[s][i-1]+1,t[s-1][i]+1,t[s-1][i-1]+a);}return t[e.length][r.length]},Q=r=>r.toLowerCase().replace(/[-_.]/g,"_").replace(/([A-Z])/g,"_$1").replace(/^_+/,"").replace(/_+$/,"").toLowerCase();var oe=r=>{if(!r||r==="-"||r==="--")return null;let e=r.indexOf("=");if(e>0){let t=r.substring(0,e),s=r.substring(e+1);return {name:t,value:X(s)}}return {name:r,value:true}},X=r=>{if(r.toLowerCase()==="true")return true;if(r.toLowerCase()==="false")return false;let e=Number(r);return !Number.isNaN(e)&&Number.isFinite(e)?e:r},N=()=>{let r=E.getCliArgs(),e=[],t={};if(!r||!r.length)return {args:e,flags:t};for(let s=0;s<r.length;s++){let i=r[s];if(!(!i||typeof i!="string")){if(i.startsWith("-")){let a=oe(i);if(a){if(a.value===true&&s+1<r.length){let o=r[s+1];o&&typeof o=="string"&&!o.startsWith("-")&&(a.value=X(o),s++);}t[a.name]=a.value;}continue}e.push(i);}}return {args:e,flags:t}},K=(r,e)=>{if(!r||typeof r!="string"||!e||!Array.isArray(e)||e.length===0)return "";let t=r.toLowerCase().trim(),s=e.filter(o=>{let h=o.toLowerCase();if(h===t||h.includes(t)||t.includes(h))return true;let p=G(h,t),n=Math.max(t.length,h.length)*.4;return p<=n});if(s.length===0)return "";let a=s.slice(0,3).map(o=>`\x1B[36m${o}\x1B[0m`).join(", ");return `\x1B[31m\u2717\x1B[0m Command \x1B[33m${r}\x1B[0m not found
|
|
3
|
+
\x1B[32m\u{1F4A1}\x1B[0m Did you mean: ${a}?`},I=()=>E.getCliArgs()[0]||null;var B=class{exit(e){switch(f.type){case "bun":case "node":process.exit(e);case "deno":Deno.exit(e);default:throw new Error("Unsupported runtime")}}},v=new B;var x=class{static metadata=new WeakMap;static set(e,t,s){this.metadata.has(e)||this.metadata.set(e,new Map),this.metadata.get(e).set(t,s);}static get(e,t){return this.metadata.get(e)?.get(t)}static getAll(e){return this.metadata.get(e)||new Map}static delete(e,t){this.metadata.get(e)?.delete(t.toString());}static clear(e){this.metadata.delete(e);}};var k="VALIDATION_ERROR";var ee=N().args.slice(1),j=r=>(e,t)=>{let s=I();if(!s||s!==e.commandName)return;let i=t;x.set(e,t,{type:"arg",name:i,description:r.description});let a=ee.length?ee.shift():r.defaultValue;if(r.required&&!a){let o=x.get(e,k);x.set(e,k,[...o||[],{type:"arg",name:i,message:"Required argument not provided"}]);return}r.parse&&a&&(a=r.parse(a)),Object.defineProperty(e,t,{value:a,enumerable:true,configurable:true,writable:true});};var le=()=>ce({level:"info",formatters:{level:e=>({level:e})}}),R=le();var y=class{static commandName=this.name;static description="";static help=[];static options={keepAlive:false};static args=N().args.slice(1);static flags=N().flags;static logger=R;static handle(){throw new Error(`Handle method not implemented in command class ${this.name}`)}static handleHelpFlag(e){let t=["-h","--help"];if(!Object.keys(e).some(n=>t.includes(n)))return;let i=this.commandName,a=this.description||"No description available",o=this.help||[],h=this.options,p=this.generateHelpOutput({name:i,description:a,helpText:o,options:h,args:this.args,flags:this.flags},this);console.log(p),v.exit(0);}static generateHelpOutput=(e,t)=>{let{name:s,description:i,helpText:a,options:o,args:h,flags:p}=e,n={title:"\x1B[1;36m",subtitle:"\x1B[1;33m",description:"\x1B[0;37m",code:"\x1B[0;32m",flag:"\x1B[0;35m",reset:"\x1B[0m",error:"\x1B[0;31m",success:"\x1B[0;32m",info:"\x1B[0;34m"},u=[`${n.title}${s}${n.reset}`,`${n.description}${i}${n.reset}`,"",`${n.subtitle}Usage:${n.reset}`,` ${n.code}${s}${n.reset} [options] [arguments]`,"",`${n.subtitle}Options:${n.reset}`,` ${n.flag}-h, --help${n.reset} Show this help message`,"",`${n.subtitle}Command Options:${n.reset}`,` ${n.flag}keepAlive${n.reset} ${o?.keepAlive??false?n.success+"Enabled"+n.reset:n.error+"Disabled"+n.reset}`,""];if(a){let c=Array.isArray(a)?a:[a];u.push(`${n.subtitle}Help:${n.reset}`),c.forEach(b=>{u.push(` ${n.description}${b}${n.reset}`);}),u.push("");}let O=x.getAll(t),J=Array.from(O.values()).filter(c=>c.type==="arg"),Z=Array.from(O.values()).filter(c=>c.type==="flag");return J.length&&(u.push(`${n.subtitle}Available Arguments:${n.reset}`),J.forEach(c=>{let b=c.required?` ${n.error}(required)${n.reset}`:"",D=c.description?` ${n.description}${c.description}${n.reset}`:"";u.push(` ${n.code}${c.name}${n.reset}${b}${D}`);}),u.push("")),Z.length&&(u.push(`${n.subtitle}Available Flags:${n.reset}`),Z.forEach(c=>{c.aliases&&!Array.isArray(c.aliases)&&(c.aliases=[c.aliases]);let b=c.aliases.length?` ${n.flag}(${c.aliases.join(", ")})${n.reset}`:"",D=c.required?` ${n.error}(required)${n.reset}`:"",ie=c.description?` ${n.description}${c.description}${n.reset}`:"";u.push(` ${n.flag}--${c.name}${b}${n.reset}${D}${ie}`);}),u.push("")),((h?.length??0)>0||p&&Object.keys(p).length>0)&&(u.push(`${n.subtitle}Current Context:${n.reset}`),h?.length&&u.push(` ${n.info}Provided Arguments:${n.reset} ${n.code}${h.join(" ")}${n.reset}`),p&&Object.keys(p).length>0&&(u.push(` ${n.info}Provided Flags:${n.reset}`),Object.keys(p).forEach(c=>{let b=p[c],D=b!=null?` = ${n.code}${b}${n.reset}`:"";u.push(` ${n.flag}${c}${n.reset}${D}`);})),u.push("")),a&&(Array.isArray(a)?a.some(c=>c.includes("example")):a.includes("example"))&&(u.push(`${n.subtitle}Examples:${n.reset}`),(Array.isArray(a)?a.filter(b=>b.includes("example")):[a.split("example")[1].trim()]).forEach(b=>{u.push(` ${n.code}${b}${n.reset}`);}),u.push("")),u.join(`
|
|
4
|
+
`)};static validateContext=e=>{let t=Array.from(x.get(e,k)||[]);if(t.length){let s={error:"\x1B[0;31m",title:"\x1B[1;31m",reset:"\x1B[0m",info:"\x1B[0;34m",code:"\x1B[0;32m"};console.error(`${s.title}\u274C Validation Errors:${s.reset}`),console.error(""),t.forEach((i,a)=>{let o=`${s.info}${a+1}.${s.reset}`,h=`${s.error}${i.type.toUpperCase()}${s.reset}`,p=`${s.code}${i.name}${s.reset}`;console.error(` ${o} ${h} ${p}: ${s.error}${i.message}${s.reset}`);}),console.error(""),console.error(`${s.info}\u{1F4A1} Tip: Use --help for usage information${s.reset}`),v.exit(1);}}};var U=class{async mkdir(e,t){switch(f.type){case "bun":case "node":await(await import('fs/promises')).mkdir(e,{recursive:t?.recursive??false,mode:t?.mode});break;case "deno":typeof t?.mode=="string"&&(t.mode=Number.parseInt(t.mode)),await Deno.mkdir(e,{recursive:t?.recursive??false,mode:t?.mode});break}}async exists(e){switch(f.type){case "node":return (await import('fs')).existsSync(e);case "bun":return Bun.file(e).exists();case "deno":return Deno.stat(e).then(()=>true).catch(()=>false);default:throw new Error("Unsupported runtime")}}async readFile(e){switch(f.type){case "node":let s=await(await import('fs/promises')).readFile(e);return new Uint8Array(s);case "bun":let i=await Bun.file(e).arrayBuffer();return new Uint8Array(i);case "deno":return new Uint8Array(await Deno.readFile(e))}}async writeFile(e,t){switch(f.type){case "node":await(await import('fs/promises')).writeFile(e,t);break;case "bun":await Bun.write(e,t);break;case "deno":await Deno.writeFile(e,t);break}}async stat(e){switch(f.type){case "node":let s=await(await import('fs/promises')).stat(e);return {isDirectory:s.isDirectory(),isFile:s.isFile(),isSymbolicLink:s.isSymbolicLink(),size:s.size};case "bun":let i=await Bun.file(e).stat();return {isDirectory:i.isDirectory(),isFile:i.isFile(),isSymbolicLink:i.isSymbolicLink(),size:i.size};case "deno":let a=await Deno.stat(e);return {isDirectory:a.isDirectory,isFile:a.isFile,isSymbolicLink:false,size:a.size}}}async unlink(e){switch(f.type){case "node":await(await import('fs/promises')).unlink(e);break;case "bun":await Bun.file(e).delete();break;case "deno":await Deno.remove(e);break;default:throw new Error("Unsupported runtime")}}},l=new U;var W=class{join(...e){switch(f.type){case "node":case "bun":case "deno":return z.join(...e);default:throw new Error("Unsupported runtime")}}extName(e){switch(f.type){case "bun":case "node":case "deno":return z.extname(e);default:throw new Error("Unsupported runtime")}}resolve(...e){switch(f.type){case "bun":case "node":case "deno":return z.resolve(...e);default:throw new Error("Unsupported runtime")}}},d=new W;var S=class extends y{static commandName="generate-command";static description="Generate a new command in the specified path";static help=["Generate a new cli command in the specified path","Example: npx balda generate-command my-command -p src/commands"];static path="src/commands";static name;static async handle(){let e=this.getCommandTemplate();this.path=d.join(this.path,`${this.name}.ts`),await l.exists(d.join(process.cwd(),this.path))||await l.mkdir(d.join(process.cwd(),this.path.split("/").slice(0,-1).join("/")),{recursive:true}),await l.writeFile(this.path,new TextEncoder().encode(e)),this.logger.info(`Command ${this.name} created successfully at ${this.path}`);}static getCommandTemplate(){return `import { Command, CommandOptions } from "balda-js";
|
|
727
5
|
|
|
728
6
|
export default class extends Command {
|
|
729
7
|
static commandName = "${this.name}";
|
|
@@ -737,121 +15,7 @@ export default class extends Command {
|
|
|
737
15
|
static async handle(): Promise<void> {
|
|
738
16
|
// Implement your command logic here
|
|
739
17
|
}
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
};
|
|
743
|
-
__decorateClass([
|
|
744
|
-
arg({
|
|
745
|
-
description: "The name of the command to generate",
|
|
746
|
-
required: true
|
|
747
|
-
})
|
|
748
|
-
], GenerateCommand, "name");
|
|
749
|
-
|
|
750
|
-
// src/decorators/command/flag.ts
|
|
751
|
-
var flagDecorator = (options) => {
|
|
752
|
-
return (target, propertyKey) => {
|
|
753
|
-
const currentCommandName = getCalledCommandName();
|
|
754
|
-
if (!currentCommandName || currentCommandName !== target.commandName) {
|
|
755
|
-
return;
|
|
756
|
-
}
|
|
757
|
-
const primaryFlagName = options.name || propertyKey;
|
|
758
|
-
const parsedFlags = parseCliArgsAndFlags().flags;
|
|
759
|
-
const flagAliases = options.aliases || [];
|
|
760
|
-
const allFlagVariants = [primaryFlagName, ...flagAliases];
|
|
761
|
-
let resolvedFlagValue = options.defaultValue;
|
|
762
|
-
for (const flagVariant of allFlagVariants) {
|
|
763
|
-
const possibleNames = [
|
|
764
|
-
flagVariant,
|
|
765
|
-
`-${flagVariant}`,
|
|
766
|
-
`--${flagVariant}`
|
|
767
|
-
];
|
|
768
|
-
for (const flagName of possibleNames) {
|
|
769
|
-
if (flagName in parsedFlags) {
|
|
770
|
-
resolvedFlagValue = parsedFlags[flagName];
|
|
771
|
-
if (options.type === "boolean") {
|
|
772
|
-
resolvedFlagValue = Boolean(resolvedFlagValue);
|
|
773
|
-
} else if (options.type === "number") {
|
|
774
|
-
resolvedFlagValue = Number(resolvedFlagValue);
|
|
775
|
-
}
|
|
776
|
-
if (options.parse) {
|
|
777
|
-
resolvedFlagValue = options.parse(resolvedFlagValue);
|
|
778
|
-
}
|
|
779
|
-
break;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
if (resolvedFlagValue !== options.defaultValue) {
|
|
783
|
-
break;
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
MetadataStore.set(target, propertyKey, {
|
|
787
|
-
type: "flag",
|
|
788
|
-
name: primaryFlagName,
|
|
789
|
-
aliases: flagAliases || [],
|
|
790
|
-
description: options.description
|
|
791
|
-
});
|
|
792
|
-
if (options.required && !resolvedFlagValue) {
|
|
793
|
-
const errorChain = MetadataStore.get(target, VALIDATION_ERROR_SYMBOL);
|
|
794
|
-
MetadataStore.set(target, VALIDATION_ERROR_SYMBOL, [
|
|
795
|
-
...errorChain || [],
|
|
796
|
-
{
|
|
797
|
-
type: "flag",
|
|
798
|
-
name: primaryFlagName,
|
|
799
|
-
message: "Required flag not provided"
|
|
800
|
-
}
|
|
801
|
-
]);
|
|
802
|
-
return;
|
|
803
|
-
}
|
|
804
|
-
Object.defineProperty(target, propertyKey, {
|
|
805
|
-
value: resolvedFlagValue,
|
|
806
|
-
enumerable: true,
|
|
807
|
-
configurable: true,
|
|
808
|
-
writable: true
|
|
809
|
-
});
|
|
810
|
-
};
|
|
811
|
-
};
|
|
812
|
-
flagDecorator.boolean = (options) => {
|
|
813
|
-
return flagDecorator({ ...options, type: "boolean" });
|
|
814
|
-
};
|
|
815
|
-
flagDecorator.string = (options) => {
|
|
816
|
-
return flagDecorator({ ...options, type: "string" });
|
|
817
|
-
};
|
|
818
|
-
flagDecorator.number = (options) => {
|
|
819
|
-
return flagDecorator({ ...options, type: "number" });
|
|
820
|
-
};
|
|
821
|
-
var flag = flagDecorator;
|
|
822
|
-
|
|
823
|
-
// src/commands/base_commands/generate_plugin.ts
|
|
824
|
-
var GeneratePluginCommand = class extends Command {
|
|
825
|
-
static commandName = "generate-plugin";
|
|
826
|
-
static description = "Generate a new plugin in the specified path";
|
|
827
|
-
static help = [
|
|
828
|
-
"Generate a new plugin in the specified path",
|
|
829
|
-
"Example: npx balda generate-plugin my-plugin -p src/plugins"
|
|
830
|
-
];
|
|
831
|
-
static pluginName;
|
|
832
|
-
static pluginPath;
|
|
833
|
-
static async handle() {
|
|
834
|
-
const pluginTemplate = this.getPluginTemplate();
|
|
835
|
-
this.pluginPath = nativePath.join(this.pluginPath, `${this.pluginName}.ts`);
|
|
836
|
-
if (!await nativeFs.exists(nativePath.join(process.cwd(), this.pluginPath))) {
|
|
837
|
-
await nativeFs.mkdir(
|
|
838
|
-
nativePath.join(
|
|
839
|
-
process.cwd(),
|
|
840
|
-
this.pluginPath.split("/").slice(0, -1).join("/")
|
|
841
|
-
),
|
|
842
|
-
{ recursive: true }
|
|
843
|
-
);
|
|
844
|
-
}
|
|
845
|
-
await nativeFs.writeFile(
|
|
846
|
-
this.pluginPath,
|
|
847
|
-
new TextEncoder().encode(pluginTemplate)
|
|
848
|
-
);
|
|
849
|
-
this.logger.info(
|
|
850
|
-
`Plugin ${this.name} created successfully at ${this.pluginPath}`
|
|
851
|
-
);
|
|
852
|
-
}
|
|
853
|
-
static getPluginTemplate() {
|
|
854
|
-
return `import { BasePlugin, Request, Response, NextFunction, ServerRouteMiddleware } from "balda-js";
|
|
18
|
+
}`}};m([j({description:"The name of the command to generate",required:true})],S,"name");var C=r=>(e,t)=>{let s=I();if(!s||s!==e.commandName)return;let i=r.name||t,a=N().flags,o=r.aliases||[],h=[i,...o],p=r.defaultValue;for(let n of h){let u=[n,`-${n}`,`--${n}`];for(let O of u)if(O in a){p=a[O],r.type==="boolean"?p=!!p:r.type==="number"&&(p=Number(p)),r.parse&&(p=r.parse(p));break}if(p!==r.defaultValue)break}if(x.set(e,t,{type:"flag",name:i,aliases:o||[],description:r.description}),r.required&&!p){let n=x.get(e,k);x.set(e,k,[...n||[],{type:"flag",name:i,message:"Required flag not provided"}]);return}Object.defineProperty(e,t,{value:p,enumerable:true,configurable:true,writable:true});};C.boolean=r=>C({...r,type:"boolean"});C.string=r=>C({...r,type:"string"});C.number=r=>C({...r,type:"number"});var g=C;var F=class extends y{static commandName="generate-plugin";static description="Generate a new plugin in the specified path";static help=["Generate a new plugin in the specified path","Example: npx balda generate-plugin my-plugin -p src/plugins"];static pluginName;static pluginPath;static async handle(){let e=this.getPluginTemplate();this.pluginPath=d.join(this.pluginPath,`${this.pluginName}.ts`),await l.exists(d.join(process.cwd(),this.pluginPath))||await l.mkdir(d.join(process.cwd(),this.pluginPath.split("/").slice(0,-1).join("/")),{recursive:true}),await l.writeFile(this.pluginPath,new TextEncoder().encode(e)),this.logger.info(`Plugin ${this.name} created successfully at ${this.pluginPath}`);}static getPluginTemplate(){return `import { BasePlugin, Request, Response, NextFunction, ServerRouteMiddleware } from "balda-js";
|
|
855
19
|
|
|
856
20
|
export default class extends BasePlugin {
|
|
857
21
|
async handle(): Promise<ServerRouteMiddleware> {
|
|
@@ -860,226 +24,36 @@ export default class extends BasePlugin {
|
|
|
860
24
|
await next();
|
|
861
25
|
};
|
|
862
26
|
}
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
};
|
|
866
|
-
__decorateClass([
|
|
867
|
-
arg({
|
|
868
|
-
description: "The name of the plugin to generate",
|
|
869
|
-
required: true
|
|
870
|
-
})
|
|
871
|
-
], GeneratePluginCommand, "pluginName");
|
|
872
|
-
__decorateClass([
|
|
873
|
-
flag({
|
|
874
|
-
description: "The path to the plugin to generate, default is src/plugins",
|
|
875
|
-
type: "string",
|
|
876
|
-
aliases: "p",
|
|
877
|
-
name: "path",
|
|
878
|
-
required: false,
|
|
879
|
-
defaultValue: "src/plugins"
|
|
880
|
-
})
|
|
881
|
-
], GeneratePluginCommand, "pluginPath");
|
|
882
|
-
|
|
883
|
-
// src/runtime/native_cwd.ts
|
|
884
|
-
var NativeCwd = class {
|
|
885
|
-
getCwd() {
|
|
886
|
-
switch (runtime.type) {
|
|
887
|
-
case "node":
|
|
888
|
-
case "bun":
|
|
889
|
-
return process.cwd();
|
|
890
|
-
case "deno":
|
|
891
|
-
return Deno.cwd();
|
|
892
|
-
default:
|
|
893
|
-
throw new Error("Unsupported runtime");
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
};
|
|
897
|
-
var nativeCwd = new NativeCwd();
|
|
898
|
-
|
|
899
|
-
// src/commands/base_commands/generate_cron.ts
|
|
900
|
-
var GenerateCron = class extends Command {
|
|
901
|
-
static commandName = "generate-cron";
|
|
902
|
-
static description = "Generate a new cron job in the specified path";
|
|
903
|
-
static help = [
|
|
904
|
-
"Generate a new cron job in the specified path",
|
|
905
|
-
"Example: npx balda generate-cron my-cron -p src/cron"
|
|
906
|
-
];
|
|
907
|
-
static fileName;
|
|
908
|
-
static path;
|
|
909
|
-
static async handle() {
|
|
910
|
-
const cronTemplate = this.getCronTemplate();
|
|
911
|
-
this.path = nativePath.join(this.path, `${this.fileName}.ts`);
|
|
912
|
-
if (!await nativeFs.exists(nativePath.join(process.cwd(), this.path))) {
|
|
913
|
-
await nativeFs.mkdir(
|
|
914
|
-
nativePath.join(
|
|
915
|
-
process.cwd(),
|
|
916
|
-
this.path.split("/").slice(0, -1).join("/")
|
|
917
|
-
),
|
|
918
|
-
{ recursive: true }
|
|
919
|
-
);
|
|
920
|
-
}
|
|
921
|
-
await nativeFs.writeFile(this.path, new TextEncoder().encode(cronTemplate));
|
|
922
|
-
this.logger.info(
|
|
923
|
-
`Cron job ${this.fileName} created successfully at ${this.path}`
|
|
924
|
-
);
|
|
925
|
-
}
|
|
926
|
-
static getCronTemplate() {
|
|
927
|
-
return `import { cron } from "balda-js";
|
|
27
|
+
}`}};m([j({description:"The name of the plugin to generate",required:true})],F,"pluginName"),m([g({description:"The path to the plugin to generate, default is src/plugins",type:"string",aliases:"p",name:"path",required:false,defaultValue:"src/plugins"})],F,"pluginPath");var H=class{getCwd(){switch(f.type){case "node":case "bun":return process.cwd();case "deno":return Deno.cwd();default:throw new Error("Unsupported runtime")}}},te=new H;var T=class extends y{static commandName="generate-cron";static description="Generate a new cron job in the specified path";static help=["Generate a new cron job in the specified path","Example: npx balda generate-cron my-cron -p src/cron"];static fileName;static path;static async handle(){let e=this.getCronTemplate();this.path=d.join(this.path,`${this.fileName}.ts`),await l.exists(d.join(process.cwd(),this.path))||await l.mkdir(d.join(process.cwd(),this.path.split("/").slice(0,-1).join("/")),{recursive:true}),await l.writeFile(this.path,new TextEncoder().encode(e)),this.logger.info(`Cron job ${this.fileName} created successfully at ${this.path}`);}static getCronTemplate(){return `import { cron } from "balda-js";
|
|
928
28
|
|
|
929
29
|
export default class {
|
|
930
30
|
@cron("* * * * *")
|
|
931
31
|
handle() {
|
|
932
32
|
// Implement your cron job logic here
|
|
933
33
|
}
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
};
|
|
937
|
-
__decorateClass([
|
|
938
|
-
arg({
|
|
939
|
-
description: "The name of the cron job file to generate",
|
|
940
|
-
required: true
|
|
941
|
-
})
|
|
942
|
-
], GenerateCron, "fileName");
|
|
943
|
-
__decorateClass([
|
|
944
|
-
flag({
|
|
945
|
-
description: "The path to the cron job to generate, default is src/cron",
|
|
946
|
-
type: "string",
|
|
947
|
-
aliases: "p",
|
|
948
|
-
name: "path",
|
|
949
|
-
required: false,
|
|
950
|
-
defaultValue: "src/cron"
|
|
951
|
-
})
|
|
952
|
-
], GenerateCron, "path");
|
|
953
|
-
|
|
954
|
-
// src/commands/base_commands/init_command.ts
|
|
955
|
-
var InitCommand = class extends Command {
|
|
956
|
-
static commandName = "init";
|
|
957
|
-
static description = "Initialize a new balda project in the current directory";
|
|
958
|
-
static help = [
|
|
959
|
-
"Initialize a new balda project, it is given for granted that balda-js is installed in the project as a dependency",
|
|
960
|
-
"All the files are created in the /src directory (created if not exists)",
|
|
961
|
-
"It adds a server.ts for the file instance and a index.ts for the entry point with a dummy hello world route",
|
|
962
|
-
"Example: npx balda init -p ./src -t true"
|
|
963
|
-
];
|
|
964
|
-
static srcPath;
|
|
965
|
-
static typescript;
|
|
966
|
-
static async handle() {
|
|
967
|
-
const ext = this.typescript ? "ts" : "js";
|
|
968
|
-
const serverTemplate = this.getServerTemplate();
|
|
969
|
-
const indexTemplate = this.getIndexTemplate();
|
|
970
|
-
if (!nativeFs.exists(this.srcPath)) {
|
|
971
|
-
await nativeFs.mkdir(this.srcPath, { recursive: true });
|
|
972
|
-
}
|
|
973
|
-
await nativeFs.writeFile(
|
|
974
|
-
`${this.srcPath}/server.${ext}`,
|
|
975
|
-
new TextEncoder().encode(serverTemplate)
|
|
976
|
-
);
|
|
977
|
-
await nativeFs.writeFile(
|
|
978
|
-
`${this.srcPath}/index.${ext}`,
|
|
979
|
-
new TextEncoder().encode(indexTemplate)
|
|
980
|
-
);
|
|
981
|
-
}
|
|
982
|
-
static getServerTemplate() {
|
|
983
|
-
return `import { Server } from "balda-js";
|
|
34
|
+
}`}};m([j({description:"The name of the cron job file to generate",required:true})],T,"fileName"),m([g({description:"The path to the cron job to generate, default is src/cron",type:"string",aliases:"p",name:"path",required:false,defaultValue:"src/cron"})],T,"path");var re=async()=>await l.exists(d.join(process.cwd(),"yarn.lock"))?["yarn","add","-D"]:await l.exists(d.join(process.cwd(),"pnpm-lock.yaml"))?["pnpm","add","-D"]:await l.exists(d.join(process.cwd(),"package-lock.json"))?["npm","install","-D"]:await l.exists(d.join(process.cwd(),"bun.lockb"))?["bun","add","-D"]:await l.exists(d.join(process.cwd(),"deno.lock"))?["deno","add","-D"]:["npm","install","-D"];var q=class extends y{static commandName="init";static description="Initialize a new balda project in the current directory";static help=["Initialize a new balda project, it is given for granted that balda-js is installed in the project as a dependency","All the files are created in the /src directory (created if not exists)","It adds a server.ts for the file instance and a index.ts for the entry point with a dummy hello world route","Example: npx balda init -p ./src -t true"];static srcPath;static typescript;static devDependencies=["esbuild","esbuild-plugin-copy","tsx","typescript"];static async handle(){this.logger.info("Initializing project...");let[e,t,s]=await re();["npm","yarn","pnpm"].includes(e)&&(this.logger.info(`Installing dev dependencies with ${e}...`),execSync(`${e} ${t} ${this.devDependencies.join(" ")} -${s}`,{stdio:"inherit"}));let i=this.typescript?"ts":"js",a=this.getServerTemplate(),o=this.getIndexTemplate();l.exists(this.srcPath)||await l.mkdir(this.srcPath,{recursive:true}),this.logger.info(`Creating server.${i} file...`),await l.writeFile(`${this.srcPath}/server.${i}`,new TextEncoder().encode(a)),this.logger.info(`Creating index.${i} file...`),await l.writeFile(`${this.srcPath}/index.${i}`,new TextEncoder().encode(o)),this.logger.info("Project initialized successfully!");}static getServerTemplate(){return `import { Server } from "balda-js";
|
|
984
35
|
|
|
985
36
|
const serverInstance = new Server({
|
|
986
37
|
port: 80,
|
|
987
38
|
host: "0.0.0.0",
|
|
39
|
+
plugins: {
|
|
40
|
+
json: {
|
|
41
|
+
sizeLimit: "100kb",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
988
44
|
});
|
|
989
45
|
|
|
990
46
|
export { serverInstance as server };
|
|
991
|
-
|
|
992
|
-
}
|
|
993
|
-
static getIndexTemplate() {
|
|
994
|
-
return `import { server } from "./server";
|
|
47
|
+
`}static getIndexTemplate(){return `import { server } from "./server";
|
|
995
48
|
|
|
996
49
|
server.listen(({ url }) => {
|
|
997
50
|
console.log(\`Server is running on \${url}\`);
|
|
998
51
|
});
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
};
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
description: "The path to the project, default is the current directory /src",
|
|
1005
|
-
aliases: "p",
|
|
1006
|
-
name: "path",
|
|
1007
|
-
required: false,
|
|
1008
|
-
defaultValue: "./src"
|
|
1009
|
-
})
|
|
1010
|
-
], InitCommand, "srcPath");
|
|
1011
|
-
__decorateClass([
|
|
1012
|
-
flag.boolean({
|
|
1013
|
-
description: "Whether to use typescript, default is true",
|
|
1014
|
-
aliases: "t",
|
|
1015
|
-
name: "typescript",
|
|
1016
|
-
required: false,
|
|
1017
|
-
defaultValue: true
|
|
1018
|
-
})
|
|
1019
|
-
], InitCommand, "typescript");
|
|
1020
|
-
|
|
1021
|
-
// src/commands/base_commands/list_command.ts
|
|
1022
|
-
var ListCommand = class extends Command {
|
|
1023
|
-
static commandName = "list";
|
|
1024
|
-
static description = "List all available commands";
|
|
1025
|
-
static help = [
|
|
1026
|
-
"Display all registered Balda CLI commands with their descriptions",
|
|
1027
|
-
"Example: npx balda list"
|
|
1028
|
-
];
|
|
1029
|
-
static async handle() {
|
|
1030
|
-
const commands = commandRegistry.getCommands();
|
|
1031
|
-
console.log("\n\u2728 Available Balda Commands:\n");
|
|
1032
|
-
const maxNameLength = Math.max(
|
|
1033
|
-
...commands.map((cmd) => cmd.commandName.length)
|
|
1034
|
-
);
|
|
1035
|
-
for (const command of commands) {
|
|
1036
|
-
const name = command.commandName.padEnd(maxNameLength + 2);
|
|
1037
|
-
const desc = command.description || "No description available";
|
|
1038
|
-
console.log(` \x1B[36m${name}\x1B[0m ${desc}`);
|
|
1039
|
-
}
|
|
1040
|
-
console.log(
|
|
1041
|
-
"\n\x1B[90mRun 'npx balda <command> -h' for more information on a specific command.\x1B[0m\n"
|
|
1042
|
-
);
|
|
1043
|
-
}
|
|
1044
|
-
};
|
|
1045
|
-
|
|
1046
|
-
// src/commands/base_commands/generate_queue.ts
|
|
1047
|
-
var GenerateQueueCommand = class extends Command {
|
|
1048
|
-
static commandName = "generate-queue";
|
|
1049
|
-
static description = "Generate a new queue in the specified path";
|
|
1050
|
-
static help = [
|
|
1051
|
-
"Generate a new queue in the specified path",
|
|
1052
|
-
"Example: npx balda generate-queue my-queue -p src/queues --provider bullmq"
|
|
1053
|
-
];
|
|
1054
|
-
static queueName;
|
|
1055
|
-
static path;
|
|
1056
|
-
static provider;
|
|
1057
|
-
static async handle() {
|
|
1058
|
-
const isValidLiteral = this.queueName.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/);
|
|
1059
|
-
const queueTemplate = this.getQueueTemplate(!!isValidLiteral);
|
|
1060
|
-
this.path = nativePath.join(
|
|
1061
|
-
this.path,
|
|
1062
|
-
`${toLowerSnakeCase(this.queueName)}.ts`
|
|
1063
|
-
);
|
|
1064
|
-
if (!await nativeFs.exists(nativePath.join(process.cwd(), this.path))) {
|
|
1065
|
-
await nativeFs.mkdir(
|
|
1066
|
-
nativePath.join(
|
|
1067
|
-
process.cwd(),
|
|
1068
|
-
this.path.split("/").slice(0, -1).join("/")
|
|
1069
|
-
),
|
|
1070
|
-
{ recursive: true }
|
|
1071
|
-
);
|
|
1072
|
-
}
|
|
1073
|
-
await nativeFs.writeFile(
|
|
1074
|
-
this.path,
|
|
1075
|
-
new TextEncoder().encode(queueTemplate)
|
|
1076
|
-
);
|
|
1077
|
-
this.logger.info(
|
|
1078
|
-
`Queue ${this.queueName} created successfully at ${this.path}`
|
|
1079
|
-
);
|
|
1080
|
-
}
|
|
1081
|
-
static getQueueTemplate(isValidLiteral) {
|
|
1082
|
-
return `import { queue, logger } from "balda-js";
|
|
52
|
+
`}};m([g.string({description:"The path to the project, default is the current directory /src",aliases:"p",name:"path",required:false,defaultValue:"./src"})],q,"srcPath"),m([g.boolean({description:"Whether to use typescript, default is true",aliases:"t",name:"typescript",required:false,defaultValue:true})],q,"typescript");var L=class extends y{static commandName="list";static description="List all available commands";static help=["Display all registered Balda CLI commands with their descriptions","Example: npx balda list"];static async handle(){let e=P.getCommands();console.log(`
|
|
53
|
+
\u2728 Available Balda Commands:
|
|
54
|
+
`);let t=Math.max(...e.map(s=>s.commandName.length));for(let s of e){let i=s.commandName.padEnd(t+2),a=s.description||"No description available";console.log(` \x1B[36m${i}\x1B[0m ${a}`);}console.log(`
|
|
55
|
+
\x1B[90mRun 'npx balda <command> -h' for more information on a specific command.\x1B[0m
|
|
56
|
+
`);}};var A=class extends y{static commandName="generate-queue";static description="Generate a new queue in the specified path";static help=["Generate a new queue in the specified path","Example: npx balda generate-queue my-queue -p src/queues --provider bullmq"];static queueName;static path;static provider;static async handle(){let e=this.queueName.match(/^[a-zA-Z_][a-zA-Z0-9_]*$/),t=this.getQueueTemplate(!!e);this.path=d.join(this.path,`${Q(this.queueName)}.ts`),await l.exists(d.join(process.cwd(),this.path))||await l.mkdir(d.join(process.cwd(),this.path.split("/").slice(0,-1).join("/")),{recursive:true}),await l.writeFile(this.path,new TextEncoder().encode(t)),this.logger.info(`Queue ${this.queueName} created successfully at ${this.path}`);}static getQueueTemplate(e){return `import { queue, logger } from "balda-js";
|
|
1083
57
|
|
|
1084
58
|
export type Payload = {
|
|
1085
59
|
// Add your payload here
|
|
@@ -1087,7 +61,7 @@ export type Payload = {
|
|
|
1087
61
|
|
|
1088
62
|
declare module "balda-js" {
|
|
1089
63
|
export interface QueueTopic {
|
|
1090
|
-
${
|
|
64
|
+
${e?this.queueName:`'${this.queueName}'`}: Payload;
|
|
1091
65
|
}
|
|
1092
66
|
}
|
|
1093
67
|
|
|
@@ -1100,169 +74,5 @@ export default class {
|
|
|
1100
74
|
this.logger.info({ payload }, 'Payload received');
|
|
1101
75
|
return Promise.resolve();
|
|
1102
76
|
}
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
};
|
|
1106
|
-
__decorateClass([
|
|
1107
|
-
arg({
|
|
1108
|
-
description: "The name of the queue to generate",
|
|
1109
|
-
required: true
|
|
1110
|
-
})
|
|
1111
|
-
], GenerateQueueCommand, "queueName");
|
|
1112
|
-
__decorateClass([
|
|
1113
|
-
flag({
|
|
1114
|
-
description: "The path to the queue to generate, default is src/queues",
|
|
1115
|
-
type: "string",
|
|
1116
|
-
aliases: "p",
|
|
1117
|
-
name: "path",
|
|
1118
|
-
required: false,
|
|
1119
|
-
defaultValue: "src/queues"
|
|
1120
|
-
})
|
|
1121
|
-
], GenerateQueueCommand, "path");
|
|
1122
|
-
__decorateClass([
|
|
1123
|
-
flag({
|
|
1124
|
-
description: "The provider of the queue to generate, default is bullmq",
|
|
1125
|
-
type: "string",
|
|
1126
|
-
aliases: ["pr"],
|
|
1127
|
-
name: "provider",
|
|
1128
|
-
required: false,
|
|
1129
|
-
defaultValue: "bullmq"
|
|
1130
|
-
})
|
|
1131
|
-
], GenerateQueueCommand, "provider");
|
|
1132
|
-
|
|
1133
|
-
// src/commands/command_registry.ts
|
|
1134
|
-
var CommandRegistry = class _CommandRegistry {
|
|
1135
|
-
commands;
|
|
1136
|
-
static commandsPattern = "src/commands/**/*.{ts,js}";
|
|
1137
|
-
static logger = logger;
|
|
1138
|
-
/**
|
|
1139
|
-
* Private constructor to prevent direct instantiation
|
|
1140
|
-
* @internal Not meant to be used outside by the user
|
|
1141
|
-
*/
|
|
1142
|
-
constructor() {
|
|
1143
|
-
this.commands = /* @__PURE__ */ new Map();
|
|
1144
|
-
}
|
|
1145
|
-
static getInstance() {
|
|
1146
|
-
return new _CommandRegistry();
|
|
1147
|
-
}
|
|
1148
|
-
static setCommandsPattern(pattern) {
|
|
1149
|
-
this.commandsPattern = pattern;
|
|
1150
|
-
}
|
|
1151
|
-
getCommand(name) {
|
|
1152
|
-
return this.commands.get(name) ?? null;
|
|
1153
|
-
}
|
|
1154
|
-
getCommands() {
|
|
1155
|
-
return Array.from(this.commands.values());
|
|
1156
|
-
}
|
|
1157
|
-
async loadCommands(commandsPattern) {
|
|
1158
|
-
_CommandRegistry.logger.info(`Loading commands from ${commandsPattern}`);
|
|
1159
|
-
const commandFiles = await glob(commandsPattern, {
|
|
1160
|
-
absolute: true,
|
|
1161
|
-
cwd: nativeCwd.getCwd()
|
|
1162
|
-
});
|
|
1163
|
-
if (commandFiles.some((file) => file.endsWith(".ts"))) {
|
|
1164
|
-
try {
|
|
1165
|
-
const { register } = await import('module');
|
|
1166
|
-
register("ts-node/esm", import.meta.url);
|
|
1167
|
-
} catch {
|
|
1168
|
-
_CommandRegistry.logger.error(
|
|
1169
|
-
`Failed to register ts-node/esm, you need to install it in your project in order to use typescript in the cli
|
|
1170
|
-
try running: \`npm install -D ts-node\``
|
|
1171
|
-
);
|
|
1172
|
-
process.exit(1);
|
|
1173
|
-
}
|
|
1174
|
-
}
|
|
1175
|
-
for (const commandFile of commandFiles) {
|
|
1176
|
-
const command = await import(commandFile).then((module) => {
|
|
1177
|
-
if (module.default) {
|
|
1178
|
-
return module.default;
|
|
1179
|
-
}
|
|
1180
|
-
return module;
|
|
1181
|
-
}).catch((error) => {
|
|
1182
|
-
_CommandRegistry.logger.error(
|
|
1183
|
-
`Error loading command ${commandFile}: ${error}`
|
|
1184
|
-
);
|
|
1185
|
-
return null;
|
|
1186
|
-
});
|
|
1187
|
-
if (command) {
|
|
1188
|
-
this.commands.set(command.commandName, command);
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
const baseCommands = [
|
|
1192
|
-
GeneratePluginCommand,
|
|
1193
|
-
GenerateCommand,
|
|
1194
|
-
GenerateCron,
|
|
1195
|
-
GenerateQueueCommand,
|
|
1196
|
-
InitCommand,
|
|
1197
|
-
ListCommand
|
|
1198
|
-
];
|
|
1199
|
-
for (const command of baseCommands) {
|
|
1200
|
-
this.commands.set(command.commandName, command);
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
};
|
|
1204
|
-
var commandRegistry = CommandRegistry.getInstance();
|
|
1205
|
-
|
|
1206
|
-
// src/cli.ts
|
|
1207
|
-
var cli = async () => {
|
|
1208
|
-
await commandRegistry.loadCommands(CommandRegistry.commandsPattern);
|
|
1209
|
-
const commandName = nativeArgs.getCliArgs()[0];
|
|
1210
|
-
if (!commandName) {
|
|
1211
|
-
console.error(
|
|
1212
|
-
`No command provided, available commands: ${commandRegistry.getCommands().map((command) => command.commandName).join(", ")}`
|
|
1213
|
-
);
|
|
1214
|
-
nativeExit.exit(1);
|
|
1215
|
-
return;
|
|
1216
|
-
}
|
|
1217
|
-
const CommandClass = commandRegistry.getCommand(commandName);
|
|
1218
|
-
if (!CommandClass) {
|
|
1219
|
-
console.error(
|
|
1220
|
-
findSimilarCommands(
|
|
1221
|
-
commandName,
|
|
1222
|
-
commandRegistry.getCommands().map((command) => command.commandName)
|
|
1223
|
-
) || `Command ${commandName} not found`
|
|
1224
|
-
);
|
|
1225
|
-
nativeExit.exit(1);
|
|
1226
|
-
return;
|
|
1227
|
-
}
|
|
1228
|
-
const commandClass = CommandClass;
|
|
1229
|
-
commandClass.handleHelpFlag(commandClass.flags);
|
|
1230
|
-
commandClass.validateContext(commandClass);
|
|
1231
|
-
await commandClass.handle();
|
|
1232
|
-
const keepAlive = CommandClass.options?.keepAlive ?? false;
|
|
1233
|
-
if (!keepAlive) {
|
|
1234
|
-
nativeExit.exit(0);
|
|
1235
|
-
}
|
|
1236
|
-
};
|
|
1237
|
-
if (typeof process !== "undefined") {
|
|
1238
|
-
cli().catch(async (err) => {
|
|
1239
|
-
if (err?.message?.includes("SyntaxError") || err?.code === "ERR_UNKNOWN_FILE_EXTENSION") {
|
|
1240
|
-
try {
|
|
1241
|
-
const { register } = await import('module');
|
|
1242
|
-
register("ts-node/esm", import.meta.url);
|
|
1243
|
-
cli().catch((retryErr) => {
|
|
1244
|
-
CommandRegistry.logger.error(retryErr);
|
|
1245
|
-
process.exit(1);
|
|
1246
|
-
});
|
|
1247
|
-
} catch (registerErr) {
|
|
1248
|
-
CommandRegistry.logger.error(
|
|
1249
|
-
`Failed to register ts-node/esm, you need to install it in your project in order to use typescript in the cli
|
|
1250
|
-
try running: \`npm install -D ts-node\``
|
|
1251
|
-
);
|
|
1252
|
-
process.exit(1);
|
|
1253
|
-
}
|
|
1254
|
-
} else {
|
|
1255
|
-
CommandRegistry.logger.error(err);
|
|
1256
|
-
process.exit(1);
|
|
1257
|
-
}
|
|
1258
|
-
});
|
|
1259
|
-
} else {
|
|
1260
|
-
cli().catch((err) => {
|
|
1261
|
-
CommandRegistry.logger.error(err);
|
|
1262
|
-
nativeExit.exit(1);
|
|
1263
|
-
});
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
export { cli };
|
|
1267
|
-
//# sourceMappingURL=cli.js.map
|
|
77
|
+
}`}};m([j({description:"The name of the queue to generate",required:true})],A,"queueName"),m([g({description:"The path to the queue to generate, default is src/queues",type:"string",aliases:"p",name:"path",required:false,defaultValue:"src/queues"})],A,"path"),m([g({description:"The provider of the queue to generate, default is bullmq",type:"string",aliases:["pr"],name:"provider",required:false,defaultValue:"bullmq"})],A,"provider");var w=class extends y{static commandName="build";static description="Build the project for production, node.js only";static help=["Build the project for production, node.js only","It will create a production build of the project in the dist directory","Must have a tsconfig.json file in the root of the project","Must have esbuild installed as a dependency while running the command","Must have esbuild-plugin-copy installed as a dependency while running the command if you want to copy assets to the output directory","Example: npx balda build -t ./tsconfig.json -a ./assets"];static clearDist;static entry;static output;static tsconfig;static assets;static format;static packages;static sourcemap;static async handle(){typeof process===void 0&&(this.logger.error("Build command is only supported in node.js"),process.exit(1)),["esm","cjs"].includes(this.format)||(this.logger.error("Invalid format, must be 'esm' or 'cjs'"),process.exit(1)),["bundle","external"].includes(this.packages)||(this.logger.error("Invalid packages, must be 'bundle' or 'external'"),process.exit(1));let e=await import('esbuild').catch(o=>{throw this.logger.error("esbuild is not installed, please install it with `npm install -D esbuild` to use the build command"),new Error("esbuild is not installed")}),t=z.join(this.output,"assets"),s=[];if(this.assets){let{copy:o}=await import('esbuild-plugin-copy').catch(h=>{throw this.logger.error("esbuild-plugin-copy is not installed, please install it with `npm install -D esbuild-plugin-copy` to use the build command"),new Error("esbuild-plugin-copy is not installed")});M.existsSync(t)||M.mkdirSync(t,{recursive:true}),s.push(o({assets:{from:this.assets,to:t}}));}this.clearDist&&M.existsSync(this.output)&&(this.logger.info("Clearing dist directory..."),M.rmSync(this.output,{recursive:true})),this.logger.info("Building project...");let i=z.join(this.output,"server.js"),a=await e.build({tsconfig:this.tsconfig,entryPoints:[this.entry],bundle:true,platform:"node",outfile:i,minify:true,sourcemap:this.sourcemap,plugins:s,format:this.format,packages:this.packages});a.errors.length&&(this.logger.error(JSON.stringify({message:"Failed to build the project",errors:a.errors},null,2)),process.exit(1)),a.warnings.length&&this.logger.warn(JSON.stringify({message:"Failed to build the project",warnings:a.warnings},null,2)),this.logger.info(JSON.stringify({message:`Project built successfully in ${i}`,output:i,assets:!!this.assets},null,2)),process.exit(0);}};m([g({type:"boolean",aliases:["c"],name:"clear-dist",required:false,defaultValue:false,description:"Whether to clear the dist directory before building the project"})],w,"clearDist"),m([g({type:"string",aliases:["e"],name:"entry",required:false,defaultValue:"./src/index.ts",description:"The entry point of the project, default is ./src/index.ts"})],w,"entry"),m([g({type:"string",aliases:["o"],name:"output",required:false,defaultValue:"./dist",description:"The path to the output directory, default is ./dist"})],w,"output"),m([g({type:"string",aliases:["t"],name:"tsconfig",required:false,defaultValue:"./tsconfig.json",description:"The path to the tsconfig.json file, default is ./tsconfig.json"})],w,"tsconfig"),m([g({type:"string",aliases:["a"],name:"assets",required:false,description:"The path to the assets directory that will be loaded in the production build"})],w,"assets"),m([g({type:"string",aliases:["f"],name:"format",required:false,defaultValue:"esm",description:"The format to build the project, default is esm, can be 'esm' or 'cjs'"})],w,"format"),m([g({type:"string",aliases:["p"],name:"packages",required:false,defaultValue:"external",description:"Weather to bundle node_modules or not, default is external, can be 'bundle' or 'external'"})],w,"packages"),m([g({type:"boolean",aliases:["s"],name:"sourcemap",required:false,defaultValue:true,description:"Whether to generate sourcemaps or not, default is true"})],w,"sourcemap");var $=class r{commands;static commandsPattern="src/commands/**/*.{ts,js}";static logger=R;constructor(){this.commands=new Map;}static getInstance(){return new r}static setCommandsPattern(e){this.commandsPattern=e;}getCommand(e){return this.commands.get(e)??null}getCommands(){return Array.from(this.commands.values())}async loadCommands(e){r.logger.info(`Loading commands from ${e}`);let t=await glob(e,{absolute:true,cwd:te.getCwd()});if(t.some(i=>i.endsWith(".ts")))try{let{register:i}=await import('module');i("ts-node/esm",import.meta.url);}catch{r.logger.error("Failed to register ts-node/esm, you need to install it in your project in order to use typescript in the cli\ntry running: `npm install -D ts-node`"),process.exit(1);}for(let i of t){let a=await import(i).then(o=>o.default?o.default:o).catch(o=>(r.logger.error(`Error loading command ${i}: ${o}`),null));a&&this.commands.set(a.commandName,a);}let s=[F,S,T,A,q,L,w];for(let i of s)this.commands.set(i.commandName,i);}},P=$.getInstance();var Y=async()=>{await P.loadCommands($.commandsPattern);let r=E.getCliArgs()[0];if(!r){console.error(`No command provided, available commands: ${P.getCommands().map(i=>i.commandName).join(", ")}`),v.exit(1);return}let e=P.getCommand(r);if(!e){console.error(K(r,P.getCommands().map(i=>i.commandName))||`Command ${r} not found`),v.exit(1);return}let t=e;t.handleHelpFlag(t.flags),t.validateContext(t),await t.handle(),(e.options?.keepAlive??false)||v.exit(0);};typeof process<"u"?Y().catch(async r=>{if(r?.message?.includes("SyntaxError")||r?.code==="ERR_UNKNOWN_FILE_EXTENSION")try{let{register:e}=await import('module');e("ts-node/esm",import.meta.url),Y().catch(t=>{$.logger.error(t),process.exit(1);});}catch{$.logger.error("Failed to register ts-node/esm, you need to install it in your project in order to use typescript in the cli\ntry running: `npm install -D ts-node`"),process.exit(1);}else $.logger.error(r),process.exit(1);}):Y().catch(r=>{$.logger.error(r),v.exit(1);});export{Y as cli};//# sourceMappingURL=cli.js.map
|
|
1268
78
|
//# sourceMappingURL=cli.js.map
|