@stacksjs/buddy 0.70.59 → 0.70.61

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.
Files changed (79) hide show
  1. package/dist/cli.js +164 -4
  2. package/dist/commands/about.js +35 -0
  3. package/dist/commands/add.d.ts +2 -0
  4. package/dist/commands/add.js +33 -0
  5. package/dist/commands/auth.js +68 -0
  6. package/dist/commands/build.js +153 -0
  7. package/dist/commands/cd.js +39 -0
  8. package/dist/commands/changelog.js +32 -0
  9. package/dist/commands/clean.js +37 -0
  10. package/dist/commands/cloud.js +503 -0
  11. package/dist/commands/commit.js +16 -0
  12. package/dist/commands/completion.js +143 -0
  13. package/dist/commands/config-migrate.js +94 -0
  14. package/dist/commands/configure.js +48 -0
  15. package/dist/commands/create.js +137 -0
  16. package/dist/commands/deploy.js +1404 -0
  17. package/dist/commands/dev.js +911 -0
  18. package/dist/commands/dns.js +62 -0
  19. package/dist/commands/doctor.js +280 -0
  20. package/dist/commands/domains.js +159 -0
  21. package/dist/commands/email.js +526 -0
  22. package/dist/commands/env.js +246 -0
  23. package/dist/commands/features.js +422 -0
  24. package/dist/commands/fresh.js +39 -0
  25. package/dist/commands/generate.js +104 -0
  26. package/dist/commands/http.js +30 -0
  27. package/dist/commands/index.js +53 -0
  28. package/dist/commands/install.js +23 -0
  29. package/dist/commands/key.js +23 -0
  30. package/dist/commands/lint.js +50 -0
  31. package/dist/commands/list.js +108 -0
  32. package/dist/commands/mail.js +693 -0
  33. package/dist/commands/maintenance.d.ts +2 -0
  34. package/dist/commands/maintenance.js +141 -0
  35. package/dist/commands/make.js +375 -0
  36. package/dist/commands/migrate-project.js +49 -0
  37. package/dist/commands/migrate.js +373 -0
  38. package/dist/commands/outdated.js +19 -0
  39. package/dist/commands/package.d.ts +2 -0
  40. package/dist/commands/package.js +17 -0
  41. package/dist/commands/phone.js +188 -0
  42. package/dist/commands/ports.js +118 -0
  43. package/dist/commands/prepublish.js +17 -0
  44. package/dist/commands/projects.js +29 -0
  45. package/dist/commands/publish.js +169 -0
  46. package/dist/commands/queue.js +249 -0
  47. package/dist/commands/release.js +30 -0
  48. package/dist/commands/route.js +21 -0
  49. package/dist/commands/saas.js +25 -0
  50. package/dist/commands/schedule.js +61 -0
  51. package/dist/commands/search.js +84 -0
  52. package/dist/commands/seed.js +71 -0
  53. package/dist/commands/serve.js +176 -0
  54. package/dist/commands/setup.js +215 -0
  55. package/dist/commands/share.d.ts +2 -0
  56. package/dist/commands/share.js +209 -0
  57. package/dist/commands/sms.js +328 -0
  58. package/dist/commands/stacks.d.ts +2 -0
  59. package/dist/commands/stacks.js +69 -0
  60. package/dist/commands/telemetry.js +74 -0
  61. package/dist/commands/test.js +130 -0
  62. package/dist/commands/tinker.js +37 -0
  63. package/dist/commands/types.js +18 -0
  64. package/dist/commands/upgrade.js +97 -0
  65. package/dist/commands/version.js +16 -0
  66. package/dist/config.d.ts +43 -0
  67. package/dist/config.js +223 -0
  68. package/dist/custom-cli.d.ts +1 -0
  69. package/dist/custom-cli.js +23 -0
  70. package/dist/index.js +1 -3424
  71. package/dist/lazy-commands.d.ts +61 -0
  72. package/dist/lazy-commands.js +182 -0
  73. package/dist/migrators/index.js +62 -0
  74. package/dist/migrators/laravel/index.js +148 -0
  75. package/dist/migrators/laravel/migrations.js +231 -0
  76. package/dist/migrators/laravel/models.js +132 -0
  77. package/dist/migrators/rails/index.js +11 -0
  78. package/dist/migrators/types.js +0 -0
  79. package/package.json +1 -1
@@ -0,0 +1,39 @@
1
+ import process from "node:process";
2
+ import { runAction } from "@stacksjs/actions";
3
+ import { intro, log, onUnknownSubcommand, outro } from "@stacksjs/cli";
4
+ import { Action } from "@stacksjs/enums";
5
+ import { ExitCode } from "@stacksjs/types";
6
+ export function fresh(buddy) {
7
+ const descriptions = {
8
+ fresh: "Re-installs your npm dependencies",
9
+ project: "Target a specific project",
10
+ verbose: "Enable verbose output"
11
+ };
12
+ buddy.command("fresh", descriptions.fresh).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
13
+ log.debug("Running `buddy fresh` ...", options);
14
+ if (!buddy.isForce && !buddy.isNoInteraction) {
15
+ const { confirm } = await import("@stacksjs/cli");
16
+ if (!await confirm({
17
+ message: "This will remove and reinstall all dependencies. Continue?",
18
+ initial: !1
19
+ })) {
20
+ log.info("Fresh install cancelled");
21
+ process.exit(ExitCode.Success);
22
+ }
23
+ }
24
+ const perf = await intro("buddy fresh"), result = await runAction(Action.Fresh, {
25
+ ...options,
26
+ stdout: "inherit"
27
+ });
28
+ if (result.isErr) {
29
+ await outro("While running `buddy fresh`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
30
+ process.exit(ExitCode.FatalError);
31
+ }
32
+ await outro("Freshly reinstalled your dependencies", {
33
+ startTime: perf,
34
+ useSeconds: !0
35
+ });
36
+ process.exit(ExitCode.Success);
37
+ });
38
+ onUnknownSubcommand(buddy, "fresh");
39
+ }
@@ -0,0 +1,104 @@
1
+ import process from "node:process";
2
+ import {
3
+ generateComponentMeta,
4
+ generateCoreSymlink,
5
+ generateIdeHelpers,
6
+ generateLibEntries,
7
+ generateOpenApiSpec,
8
+ generatePantryConfig,
9
+ generateTypes,
10
+ generateVsCodeCustomData,
11
+ generateWebTypes,
12
+ invoke as startGenerationProcess,
13
+ watchTypes
14
+ } from "@stacksjs/actions";
15
+ import { intro, log, onUnknownSubcommand, outro } from "@stacksjs/cli";
16
+ import { ExitCode } from "@stacksjs/types";
17
+ export function generate(buddy) {
18
+ const descriptions = {
19
+ command: "Automagically build any of your libraries/packages for production use. Select any of the following packages",
20
+ types: "Generate your TypeScript types",
21
+ entries: "Generate your function & Component Library Entry Points",
22
+ webTypes: "Generate web-types.json for IDEs",
23
+ customData: "Generate VS Code custom data (custom-elements.json) for IDEs",
24
+ ideHelpers: "Generate IDE helpers",
25
+ componentMeta: "Generate component meta information",
26
+ coreSymlink: "Generate symlink of the core framework to the project root",
27
+ pantry: "Generate the pantry configuration file",
28
+ openApi: "Generate the OpenAPI specification",
29
+ select: "What are you trying to generate?",
30
+ project: "Target a specific project",
31
+ verbose: "Enable verbose output"
32
+ };
33
+ buddy.command("generate", descriptions.command).option("-t, --types", descriptions.types).option("-e, --entries", descriptions.entries).option("-w, --web-types", descriptions.webTypes).option("-c, --custom-data", descriptions.customData).option("-i, --ide-helpers", descriptions.ideHelpers).option("-c, --component-meta", descriptions.componentMeta).option("-p, --pantry", descriptions.pantry).option("-o, --openapi", descriptions.openApi).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--core-symlink", descriptions.coreSymlink).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
34
+ log.debug("Running `buddy generate` ...", options);
35
+ await startGenerationProcess(options);
36
+ process.exit(ExitCode.Success);
37
+ });
38
+ buddy.command("generate:types", descriptions.types).option("-p, --project [project]", descriptions.project, { default: !1 }).option("-w, --watch", "Re-run on changes to models/ and config/", { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).alias("types:generate").action(async (options) => {
39
+ log.debug("Running `buddy generate:types` ...", options);
40
+ await generateTypes(options);
41
+ try {
42
+ const { buildDatabaseSchema } = await import("@stacksjs/orm");
43
+ await buildDatabaseSchema();
44
+ } catch (err) {
45
+ log.warn(`[generate:db-types] skipped: ${err.message}`);
46
+ }
47
+ if (options.watch)
48
+ await watchTypes(options);
49
+ });
50
+ buddy.command("generate:db-types", "Refresh database/types.d.ts for db.selectFrom autocomplete (stacksjs/stacks#1923)").option("--dry-run", "Print the would-be file content without writing", { default: !1 }).action(async (options) => {
51
+ const { buildDatabaseSchema } = await import("@stacksjs/orm"), result = await buildDatabaseSchema({ dryRun: options.dryRun });
52
+ if (options.dryRun)
53
+ console.log(result.content);
54
+ for (const e of result.errors)
55
+ log.warn(`[generate:db-types] ${e.file}: ${e.error}`);
56
+ log.info(`[generate:db-types] resolved ${result.tables.length} table(s)`);
57
+ });
58
+ buddy.command("generate:entries", descriptions.entries).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
59
+ log.debug("Running `buddy generate:entries` ...", options);
60
+ await generateLibEntries(options);
61
+ });
62
+ buddy.command("generate:web-types", descriptions.webTypes).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
63
+ log.debug("Running `buddy generate:web-types` ...", options);
64
+ await generateWebTypes(options);
65
+ });
66
+ buddy.command("generate:vscode-custom-data", descriptions.customData).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
67
+ log.debug("Running `buddy generate:vscode-custom-data` ...", options);
68
+ await generateVsCodeCustomData(options);
69
+ });
70
+ buddy.command("generate:ide-helpers", descriptions.ideHelpers).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
71
+ log.debug("Running `buddy generate:ide-helpers` ...", options);
72
+ await generateIdeHelpers(options);
73
+ });
74
+ buddy.command("generate:component-meta", descriptions.componentMeta).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
75
+ log.debug("Running `buddy generate:component-meta` ...", options);
76
+ await generateComponentMeta();
77
+ });
78
+ buddy.command("generate:pantry-config", descriptions.pantry).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
79
+ log.debug("Running `buddy generate:pantry-config` ...", options);
80
+ await generatePantryConfig();
81
+ });
82
+ buddy.command("generate:openapi-spec", descriptions.openApi).alias("generate:openapi").option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
83
+ log.debug("Running `buddy generate:openapi-spec` ...", options);
84
+ const perf = await intro("buddy generate:openapi-spec");
85
+ await generateOpenApiSpec();
86
+ await outro("Generated OpenAPI specification", {
87
+ startTime: perf,
88
+ useSeconds: !0
89
+ });
90
+ });
91
+ buddy.command("generate:migrations", "Generate Migrations").action(async (options) => {
92
+ log.debug("Running `buddy generate:migrations` ...", options);
93
+ const { generateMigrations } = await import("@stacksjs/database"), result = await generateMigrations();
94
+ if (result?.isErr) {
95
+ log.error("generateMigrations failed", result.error);
96
+ process.exit(ExitCode.FatalError);
97
+ }
98
+ });
99
+ buddy.command("generate:core-symlink", "Generate core symlink. A shortcut for core developers.").action(async (options) => {
100
+ log.debug("Running `buddy core-symlink` ...", options);
101
+ await generateCoreSymlink();
102
+ });
103
+ onUnknownSubcommand(buddy, "generate");
104
+ }
@@ -0,0 +1,30 @@
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/cli";
3
+ import { config } from "@stacksjs/config";
4
+ import { HttxClient } from "@stacksjs/httx";
5
+ import { ExitCode } from "@stacksjs/types";
6
+ export function http(buddy) {
7
+ const descriptions = {
8
+ http: "Send an HTTP request to a domain",
9
+ project: "Target a specific project",
10
+ verbose: "Enable verbose output"
11
+ };
12
+ buddy.command("http [domain]", descriptions.http).option("-p, --project [project]", descriptions.project, { default: !1 }).option("-v, --verbose", descriptions.verbose, { default: !1 }).action(async (domain, options) => {
13
+ log.debug("Running `buddy http [domain]` ...", options);
14
+ const url = domain || config.app.url, client = new HttxClient({ verbose: options.verbose });
15
+ log.info(`GET ${url}`);
16
+ (await client.request(url.startsWith("http") ? url : `https://${url}`, {
17
+ method: "GET"
18
+ })).match({
19
+ ok: (response) => {
20
+ log.info(`${response.status} ${response.statusText} (${response.timings.duration.toFixed(0)}ms)`);
21
+ console.log(typeof response.data === "string" ? response.data : JSON.stringify(response.data, null, 2));
22
+ process.exit(ExitCode.Success);
23
+ },
24
+ err: (error) => {
25
+ log.error(`Request failed: ${error.message}`);
26
+ process.exit(ExitCode.FatalError);
27
+ }
28
+ });
29
+ });
30
+ }
@@ -0,0 +1,53 @@
1
+ export * from "./about";
2
+ export * from "./auth";
3
+ export * from "./build";
4
+ export * from "./cd";
5
+ export * from "./changelog";
6
+ export * from "./clean";
7
+ export * from "./cloud";
8
+ export * from "./commit";
9
+ export * from "./completion";
10
+ export * from "./config-migrate";
11
+ export * from "./configure";
12
+ export * from "./create";
13
+ export * from "./deploy";
14
+ export * from "./dev";
15
+ export * from "./dns";
16
+ export * from "./doctor";
17
+ export * from "./domains";
18
+ export * from "./email";
19
+ export * from "./env";
20
+ export * from "./features";
21
+ export * from "./fresh";
22
+ export * from "./generate";
23
+ export * from "./http";
24
+ export * from "./install";
25
+ export * from "./key";
26
+ export * from "./lint";
27
+ export * from "./list";
28
+ export * from "./mail";
29
+ export * from "./make";
30
+ export * from "./migrate";
31
+ export * from "./migrate-project";
32
+ export * from "./outdated";
33
+ export * from "./phone";
34
+ export * from "./ports";
35
+ export * from "./prepublish";
36
+ export * from "./projects";
37
+ export * from "./publish";
38
+ export * from "./queue";
39
+ export * from "./release";
40
+ export * from "./route";
41
+ export * from "./saas";
42
+ export * from "./schedule";
43
+ export * from "./search";
44
+ export * from "./seed";
45
+ export * from "./serve";
46
+ export * from "./setup";
47
+ export * from "./sms";
48
+ export * from "./telemetry";
49
+ export * from "./test";
50
+ export * from "./tinker";
51
+ export * from "./types";
52
+ export * from "./upgrade";
53
+ export * from "./version";
@@ -0,0 +1,23 @@
1
+ import process from "node:process";
2
+ import { log, onUnknownSubcommand, runCommand } from "@stacksjs/cli";
3
+ import { path as p } from "@stacksjs/path";
4
+ import { ExitCode } from "@stacksjs/types";
5
+ export function install(buddy) {
6
+ const descriptions = {
7
+ install: "Install your dependencies",
8
+ project: "Target a specific project",
9
+ verbose: "Enable verbose output"
10
+ };
11
+ buddy.command("install", descriptions.install).option("-p, --project [project]", descriptions.project, { default: !1 }).option("-v, --verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
12
+ log.debug("Running `buddy install` ...", options);
13
+ const result = await runCommand("bun install", {
14
+ ...options,
15
+ cwd: p.projectPath()
16
+ });
17
+ if (result && typeof result === "object" && "isErr" in result && result.isErr?.()) {
18
+ log.error("bun install failed");
19
+ process.exit(ExitCode.FatalError);
20
+ }
21
+ });
22
+ onUnknownSubcommand(buddy, "install");
23
+ }
@@ -0,0 +1,23 @@
1
+ import process from "node:process";
2
+ import { runAction } from "@stacksjs/actions";
3
+ import { intro, log, onUnknownSubcommand, outro } from "@stacksjs/cli";
4
+ import { Action } from "@stacksjs/enums";
5
+ import { ExitCode } from "@stacksjs/types";
6
+ export function key(buddy) {
7
+ const descriptions = {
8
+ command: "Generate & set the application key.",
9
+ project: "Target a specific project",
10
+ verbose: "Enable verbose output"
11
+ };
12
+ buddy.command("key:generate", descriptions.command).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
13
+ log.debug("Running `buddy key:generate` ...", options);
14
+ await intro("buddy key:generate");
15
+ const result = await runAction(Action.KeyGenerate, options);
16
+ if (result.isErr) {
17
+ log.error("Failed to set random application key.", result.error);
18
+ process.exit(ExitCode.FatalError);
19
+ }
20
+ await outro("Random application key set.");
21
+ });
22
+ onUnknownSubcommand(buddy, "key");
23
+ }
@@ -0,0 +1,50 @@
1
+ import process from "node:process";
2
+ import { intro, log, onUnknownSubcommand, outro, runCommand } from "@stacksjs/cli";
3
+ import { path } from "@stacksjs/path";
4
+ import { ExitCode } from "@stacksjs/types";
5
+ function exitOnFailure(result, label) {
6
+ if (!result || typeof result !== "object" || !("isErr" in result))
7
+ return;
8
+ const marker = result.isErr;
9
+ if (typeof marker === "function" ? marker() : marker === !0) {
10
+ log.error(`${label} reported failure`);
11
+ process.exit(ExitCode.FatalError);
12
+ }
13
+ }
14
+ export function lint(buddy) {
15
+ const descriptions = {
16
+ lint: "Automagically lints your project codebase",
17
+ lintFix: "Automagically fixes all lint errors",
18
+ format: "Format your project codebase",
19
+ formatCheck: "Check formatting without making changes",
20
+ project: "Target a specific project",
21
+ verbose: "Enable verbose output"
22
+ };
23
+ buddy.command("lint", descriptions.lint).option("-f, --fix", descriptions.lintFix, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
24
+ log.debug("Running `buddy lint` ...", options);
25
+ const startTime = await intro("buddy lint"), result = options.fix ? await runCommand("bun storage/framework/core/actions/src/lint/fix.ts", { cwd: path.projectPath() }) : await runCommand("bun storage/framework/core/actions/src/lint/index.ts", { cwd: path.projectPath() });
26
+ exitOnFailure(result, "lint");
27
+ await outro("Linted your project", { startTime, useSeconds: !0 });
28
+ });
29
+ buddy.command("lint:fix", descriptions.lintFix).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
30
+ log.debug("Running `buddy lint:fix` ...", options);
31
+ const startTime = await intro("buddy lint:fix");
32
+ log.info("Fixing lint errors...");
33
+ const result = await runCommand("bun storage/framework/core/actions/src/lint/fix.ts", { cwd: path.projectPath() });
34
+ exitOnFailure(result, "lint:fix");
35
+ await outro("Fixed lint errors", { startTime, useSeconds: !0 });
36
+ });
37
+ buddy.command("format", descriptions.format).option("-w, --write", "Write changes to files", { default: !1 }).option("-c, --check", descriptions.formatCheck, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
38
+ log.debug("Running `buddy format` ...", options);
39
+ const startTime = await intro("buddy format"), result = options.check ? await runCommand("bunx --bun pickier run --mode format --config ./pickier.config.ts --check", { cwd: path.projectPath() }) : await runCommand("bunx --bun pickier run --mode format --config ./pickier.config.ts --write", { cwd: path.projectPath() });
40
+ exitOnFailure(result, "format");
41
+ await outro("Formatted your project", { startTime, useSeconds: !0 });
42
+ });
43
+ buddy.command("format:check", descriptions.formatCheck).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
44
+ log.debug("Running `buddy format:check` ...", options);
45
+ const startTime = await intro("buddy format:check"), result = await runCommand("bunx --bun pickier run --mode format --config ./pickier.config.ts --check", { cwd: path.projectPath() });
46
+ exitOnFailure(result, "format:check");
47
+ await outro("Format check complete", { startTime, useSeconds: !0 });
48
+ });
49
+ onUnknownSubcommand(buddy, "lint");
50
+ }
@@ -0,0 +1,108 @@
1
+ import process from "node:process";
2
+ import { log } from "@stacksjs/logging";
3
+ import { onUnknownSubcommand } from "@stacksjs/cli";
4
+ export function list(buddy) {
5
+ const descriptions = {
6
+ list: "List all available Buddy commands",
7
+ project: "Target a specific project",
8
+ verbose: "Enable verbose output",
9
+ filter: "Filter commands by name or group",
10
+ namespace: "Filter commands by namespace (e.g., make, env, db)",
11
+ grouped: "Group commands by category",
12
+ format: "Output format (text, json)"
13
+ };
14
+ buddy.command("list", descriptions.list).option("-p, --project [project]", descriptions.project, { default: !1 }).option("-f, --filter [filter]", descriptions.filter).option("-n, --namespace [namespace]", descriptions.namespace).option("-g, --grouped", descriptions.grouped, { default: !0 }).option("--format [format]", descriptions.format, { default: "text" }).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy list").example("buddy list --filter=make").example("buddy list --namespace=make").example("buddy list --namespace=env").example("buddy list --no-grouped").example("buddy list --format=json").action(async (options) => {
15
+ log.debug("Running `buddy list` ...", options);
16
+ const { bold, dim, green } = await import("@stacksjs/cli"), commands = buddy.commands || [];
17
+ let filteredCommands = commands;
18
+ if (options.filter) {
19
+ const filterStr = String(options.filter).toLowerCase();
20
+ filteredCommands = commands.filter((cmd) => {
21
+ const name = cmd.name || "", desc = cmd.description || "";
22
+ return name.toLowerCase().includes(filterStr) || desc.toLowerCase().includes(filterStr);
23
+ });
24
+ }
25
+ if (options.namespace) {
26
+ const namespaceStr = String(options.namespace).toLowerCase();
27
+ filteredCommands = filteredCommands.filter((cmd) => {
28
+ return (cmd.namespace || "").toLowerCase() === namespaceStr;
29
+ });
30
+ }
31
+ if (filteredCommands.length === 0) {
32
+ if (options.format === "json")
33
+ console.log(JSON.stringify({ commands: [], total: 0 }, null, 2));
34
+ else {
35
+ console.log(dim("No commands found"));
36
+ if (options.filter)
37
+ console.log(dim(`Try removing the filter: ${options.filter}`));
38
+ }
39
+ return;
40
+ }
41
+ if (options.format === "json") {
42
+ const jsonOutput = filteredCommands.map((cmd) => ({
43
+ name: cmd.name || "",
44
+ description: cmd.description || "",
45
+ aliases: cmd.aliasNames || []
46
+ }));
47
+ console.log(JSON.stringify({ commands: jsonOutput, total: jsonOutput.length }, null, 2));
48
+ return;
49
+ }
50
+ if (options.grouped) {
51
+ const groups = new Map;
52
+ for (const cmd of filteredCommands) {
53
+ const name = cmd.name || "";
54
+ if (!name)
55
+ continue;
56
+ let group = "General";
57
+ if (name.includes(":"))
58
+ group = name.split(":")[0];
59
+ else if (["dev", "build", "test", "lint"].includes(name))
60
+ group = "Development";
61
+ else if (["deploy", "release", "publish"].includes(name))
62
+ group = "Deployment";
63
+ else if (["migrate", "seed", "fresh"].includes(name))
64
+ group = "Database";
65
+ else if (["doctor", "about", "version"].includes(name))
66
+ group = "Info";
67
+ if (!groups.has(group))
68
+ groups.set(group, []);
69
+ groups.get(group).push(cmd);
70
+ }
71
+ console.log("");
72
+ console.log(bold(green("Available Commands:")));
73
+ console.log("");
74
+ const sortedGroups = Array.from(groups.entries()).sort((a, b) => {
75
+ const order = ["Development", "General", "Info"], aIndex = order.indexOf(a[0]), bIndex = order.indexOf(b[0]);
76
+ if (aIndex >= 0 && bIndex >= 0)
77
+ return aIndex - bIndex;
78
+ if (aIndex >= 0)
79
+ return -1;
80
+ if (bIndex >= 0)
81
+ return 1;
82
+ return a[0].localeCompare(b[0]);
83
+ });
84
+ for (const [group, cmds] of sortedGroups) {
85
+ console.log(bold(`${group}:`));
86
+ cmds.sort((a, b) => (a.name || "").localeCompare(b.name || ""));
87
+ for (const cmd of cmds) {
88
+ const name = (cmd.name || "").padEnd(20), desc = cmd.description || "";
89
+ console.log(` ${green(name)} ${dim(desc)}`);
90
+ }
91
+ console.log("");
92
+ }
93
+ } else {
94
+ console.log("");
95
+ console.log(bold(green("Available Commands:")));
96
+ console.log("");
97
+ filteredCommands.sort((a, b) => (a.name || "").localeCompare(b.name || ""));
98
+ for (const cmd of filteredCommands) {
99
+ const name = (cmd.name || "").padEnd(20), desc = cmd.description || "";
100
+ console.log(` ${green(name)} ${dim(desc)}`);
101
+ }
102
+ console.log("");
103
+ }
104
+ console.log(dim(`Total: ${filteredCommands.length} commands`));
105
+ console.log("");
106
+ });
107
+ onUnknownSubcommand(buddy, "list");
108
+ }