@stacksjs/buddy 0.70.258 → 0.70.259

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 (112) hide show
  1. package/dist/cli.d.ts +11 -1
  2. package/dist/cli.js +5 -164
  3. package/dist/commands/about.js +1 -35
  4. package/dist/commands/add.js +1 -25
  5. package/dist/commands/ai-context.js +4 -27
  6. package/dist/commands/auth.js +1 -68
  7. package/dist/commands/build.js +1 -221
  8. package/dist/commands/cd.js +8 -39
  9. package/dist/commands/changelog.js +1 -32
  10. package/dist/commands/clean.js +1 -44
  11. package/dist/commands/cloud.js +2 -519
  12. package/dist/commands/commit.js +1 -16
  13. package/dist/commands/completion.js +6 -42
  14. package/dist/commands/config-migrate.js +6 -94
  15. package/dist/commands/configure.js +2 -45
  16. package/dist/commands/create.js +1 -162
  17. package/dist/commands/deploy.js +13 -1676
  18. package/dist/commands/desktop-apple.js +12 -399
  19. package/dist/commands/dev.js +6 -1083
  20. package/dist/commands/dns.js +3 -103
  21. package/dist/commands/docs/buddy-commands.js +10 -132
  22. package/dist/commands/docs/buddy-commands.test.js +1 -38
  23. package/dist/commands/docs/framework-repo.js +1 -14
  24. package/dist/commands/docs/framework-repo.test.js +1 -68
  25. package/dist/commands/docs/generated-artifacts.js +3 -70
  26. package/dist/commands/docs/generated-artifacts.test.js +1 -19
  27. package/dist/commands/docs/links.js +2 -85
  28. package/dist/commands/docs/links.test.js +4 -66
  29. package/dist/commands/docs.js +1 -24
  30. package/dist/commands/doctor.js +2 -478
  31. package/dist/commands/domains.js +2 -152
  32. package/dist/commands/email.js +31 -503
  33. package/dist/commands/env.js +1 -312
  34. package/dist/commands/extension.js +1 -239
  35. package/dist/commands/features.js +9 -345
  36. package/dist/commands/fresh.js +1 -46
  37. package/dist/commands/generate.js +2 -152
  38. package/dist/commands/http.js +1 -33
  39. package/dist/commands/index.js +1 -57
  40. package/dist/commands/install.js +1 -22
  41. package/dist/commands/key.js +1 -23
  42. package/dist/commands/link.js +2 -147
  43. package/dist/commands/lint.js +2 -84
  44. package/dist/commands/list.js +1 -140
  45. package/dist/commands/mail.js +15 -1477
  46. package/dist/commands/maintenance.js +1 -141
  47. package/dist/commands/make.js +1 -392
  48. package/dist/commands/migrate-project.js +1 -49
  49. package/dist/commands/migrate.js +27 -625
  50. package/dist/commands/outdated.js +1 -19
  51. package/dist/commands/package.js +1 -17
  52. package/dist/commands/phone.js +17 -181
  53. package/dist/commands/ports.js +2 -118
  54. package/dist/commands/prepublish.js +1 -17
  55. package/dist/commands/projects.js +1 -29
  56. package/dist/commands/protocol/craft-evidence.js +4 -98
  57. package/dist/commands/protocol/craft-evidence.test.js +1 -20
  58. package/dist/commands/protocol/desktop-lifecycle-report.js +3 -57
  59. package/dist/commands/protocol/desktop-lifecycle-report.test.js +1 -32
  60. package/dist/commands/protocol/desktop-support.js +2 -32
  61. package/dist/commands/protocol/desktop-workflow.test.js +3 -35
  62. package/dist/commands/protocol/driver-registry.js +2 -71
  63. package/dist/commands/protocol/pantry-evidence.js +4 -144
  64. package/dist/commands/protocol/pantry-evidence.test.js +1 -29
  65. package/dist/commands/protocol/release-manifest.js +3 -102
  66. package/dist/commands/protocol/release-manifest.test.js +2 -34
  67. package/dist/commands/protocol/run-conformance.js +4 -346
  68. package/dist/commands/protocol/run-conformance.test.js +1 -52
  69. package/dist/commands/protocol/run-driver-contracts.js +4 -83
  70. package/dist/commands/protocol/run-driver-contracts.test.js +1 -18
  71. package/dist/commands/protocol/source-manifest.js +3 -113
  72. package/dist/commands/protocol/sync-suite.js +3 -136
  73. package/dist/commands/protocol/sync-suite.test.js +1 -44
  74. package/dist/commands/protocol.js +1 -60
  75. package/dist/commands/publish.js +8 -500
  76. package/dist/commands/queue.js +1 -248
  77. package/dist/commands/release.js +1 -42
  78. package/dist/commands/route.js +1 -21
  79. package/dist/commands/run-tool.js +1 -9
  80. package/dist/commands/saas.js +1 -25
  81. package/dist/commands/schedule.js +1 -61
  82. package/dist/commands/search.js +1 -84
  83. package/dist/commands/seed.js +1 -47
  84. package/dist/commands/serve.js +1 -55
  85. package/dist/commands/setup-ai.js +2 -121
  86. package/dist/commands/setup.js +2 -305
  87. package/dist/commands/share.js +1 -214
  88. package/dist/commands/sms.js +32 -319
  89. package/dist/commands/stacks.js +1 -72
  90. package/dist/commands/telemetry.js +1 -74
  91. package/dist/commands/test.js +1 -130
  92. package/dist/commands/tinker.js +1 -37
  93. package/dist/commands/types.js +1 -18
  94. package/dist/commands/upgrade.js +1 -98
  95. package/dist/commands/user.js +3 -84
  96. package/dist/commands/version.js +1 -14
  97. package/dist/config.js +1 -231
  98. package/dist/custom-cli.js +1 -23
  99. package/dist/database-preflight.js +1 -88
  100. package/dist/global-options.js +1 -4
  101. package/dist/index.js +1 -1
  102. package/dist/lazy-commands.js +1 -241
  103. package/dist/migrators/index.js +2 -62
  104. package/dist/migrators/laravel/index.js +1 -148
  105. package/dist/migrators/laravel/migrations.js +4 -231
  106. package/dist/migrators/laravel/models.js +8 -111
  107. package/dist/migrators/rails/index.js +1 -11
  108. package/dist/production-server.js +1 -257
  109. package/dist/project-setup.js +1 -36
  110. package/dist/serve-entry.js +1 -5
  111. package/dist/version-info.js +1 -5
  112. package/package.json +53 -46
@@ -1,72 +1 @@
1
- import process from "node:process";
2
- import { installStack, listStacks, uninstallStack } from "@stacksjs/actions";
3
- import { intro, italic, onUnknownSubcommand, outro } from "@stacksjs/cli";
4
- import { log } from "@stacksjs/logging";
5
- import { ExitCode } from "@stacksjs/types";
6
- export function stacks(buddy) {
7
- const descriptions = {
8
- install: "Install a stack into your project",
9
- uninstall: "Uninstall a stack from your project",
10
- list: "List available and installed stacks",
11
- force: "Force overwrite existing files",
12
- dryRun: "Show what would be installed without making changes",
13
- conflict: "Conflict resolution strategy: skip, overwrite, or backup",
14
- verbose: "Enable verbose output",
15
- project: "Target a specific Stacks project"
16
- };
17
- buddy.command("stack:install <name>", descriptions.install).option("--force", descriptions.force, { default: !1 }).option("--dry-run", descriptions.dryRun, { default: !1 }).option("--conflict <strategy>", descriptions.conflict, { default: "skip" }).option("-p, --project <path>", descriptions.project).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy add calendar").example("buddy add table --force").example("buddy add calendar --conflict backup --verbose").example("buddy add table --dry-run").action(async (name, options) => {
18
- const perf = await intro("buddy stack:install");
19
- if (!name) {
20
- log.error("You need to specify a stack name.");
21
- log.info("Example: buddy add calendar");
22
- process.exit(ExitCode.FatalError);
23
- }
24
- if (!await installStack({
25
- name,
26
- force: options.force,
27
- dryRun: options.dryRun,
28
- conflict: options.conflict || "skip",
29
- project: options.project,
30
- verbose: options.verbose
31
- }) && !options.dryRun) {
32
- await outro("Failed to install stack", { startTime: perf, useSeconds: !0 });
33
- process.exit(ExitCode.FatalError);
34
- }
35
- await outro(`Stack ${italic(name)} installed.`, { startTime: perf, useSeconds: !0 });
36
- process.exit(ExitCode.Success);
37
- });
38
- buddy.command("stack:uninstall <name>", descriptions.uninstall).option("--force", descriptions.force, { default: !1 }).option("-p, --project <path>", descriptions.project).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy stack:uninstall blog").example("buddy stack:uninstall blog --force").action(async (name, options) => {
39
- const perf = await intro("buddy stack:uninstall");
40
- if (!name) {
41
- log.error("You need to specify a stack name.");
42
- process.exit(ExitCode.FatalError);
43
- }
44
- if (!await uninstallStack({
45
- name,
46
- force: options.force,
47
- project: options.project,
48
- verbose: options.verbose
49
- })) {
50
- await outro("Failed to uninstall stack", { startTime: perf, useSeconds: !0 });
51
- process.exit(ExitCode.FatalError);
52
- }
53
- await outro(`Stack ${italic(name)} uninstalled.`, { startTime: perf, useSeconds: !0 });
54
- process.exit(ExitCode.Success);
55
- });
56
- buddy.command("stack:list", descriptions.list).alias("stack:ls").option("-p, --project <path>", descriptions.project).example("buddy stack:list").action(async (options) => {
57
- const perf = await intro("buddy stack:list"), entries = await listStacks(options.project);
58
- if (entries.length === 0)
59
- log.info("No stacks found. Install one with: buddy add <name>");
60
- else {
61
- log.info(`Found ${entries.length} stack(s):`);
62
- log.info("");
63
- for (const entry of entries) {
64
- const status = entry.installed ? "[installed]" : "[available]", desc = entry.description ? ` - ${entry.description}` : "", files = entry.fileCount ? ` (${entry.fileCount} files)` : "";
65
- log.info(` ${entry.name} ${italic(`v${entry.version}`)} ${status}${files}${desc}`);
66
- }
67
- }
68
- await outro("", { startTime: perf, useSeconds: !0 });
69
- process.exit(ExitCode.Success);
70
- });
71
- onUnknownSubcommand(buddy, "stack");
72
- }
1
+ import process from"node:process";import{installStack,listStacks,uninstallStack}from"@stacksjs/actions";import{intro,italic,onUnknownSubcommand,outro}from"@stacksjs/cli";import{log}from"@stacksjs/logging";import{ExitCode}from"@stacksjs/types";export function stacks(buddy){const descriptions={install:"Install a stack into your project",uninstall:"Uninstall a stack from your project",list:"List available and installed stacks",force:"Force overwrite existing files",dryRun:"Show what would be installed without making changes",conflict:"Conflict resolution strategy: skip, overwrite, or backup",verbose:"Enable verbose output",project:"Target a specific Stacks project"};buddy.command("stack:install <name>",descriptions.install).option("--force",descriptions.force,{default:!1}).option("--dry-run",descriptions.dryRun,{default:!1}).option("--conflict <strategy>",descriptions.conflict,{default:"skip"}).option("-p, --project <path>",descriptions.project).option("--verbose",descriptions.verbose,{default:!1}).example("buddy add calendar").example("buddy add table --force").example("buddy add calendar --conflict backup --verbose").example("buddy add table --dry-run").action(async(name,options)=>{const perf=await intro("buddy stack:install");if(!name){log.error("You need to specify a stack name.");log.info("Example: buddy add calendar");process.exit(ExitCode.FatalError)}if(!await installStack({name,force:options.force,dryRun:options.dryRun,conflict:options.conflict||"skip",project:options.project,verbose:options.verbose})&&!options.dryRun){await outro("Failed to install stack",{startTime:perf,useSeconds:!0});process.exit(ExitCode.FatalError)}await outro(`Stack ${italic(name)} installed.`,{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});buddy.command("stack:uninstall <name>",descriptions.uninstall).option("--force",descriptions.force,{default:!1}).option("-p, --project <path>",descriptions.project).option("--verbose",descriptions.verbose,{default:!1}).example("buddy stack:uninstall blog").example("buddy stack:uninstall blog --force").action(async(name,options)=>{const perf=await intro("buddy stack:uninstall");if(!name){log.error("You need to specify a stack name.");process.exit(ExitCode.FatalError)}if(!await uninstallStack({name,force:options.force,project:options.project,verbose:options.verbose})){await outro("Failed to uninstall stack",{startTime:perf,useSeconds:!0});process.exit(ExitCode.FatalError)}await outro(`Stack ${italic(name)} uninstalled.`,{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});buddy.command("stack:list",descriptions.list).alias("stack:ls").option("-p, --project <path>",descriptions.project).example("buddy stack:list").action(async(options)=>{const perf=await intro("buddy stack:list"),entries=await listStacks(options.project);if(entries.length===0)log.info("No stacks found. Install one with: buddy add <name>");else{log.info(`Found ${entries.length} stack(s):`);log.info("");for(const entry of entries){const status=entry.installed?"[installed]":"[available]",desc=entry.description?` - ${entry.description}`:"",files=entry.fileCount?` (${entry.fileCount} files)`:"";log.info(` ${entry.name} ${italic(`v${entry.version}`)} ${status}${files}${desc}`)}}await outro("",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});onUnknownSubcommand(buddy,"stack")}
@@ -1,74 +1 @@
1
- import process from "node:process";
2
- import { bold, dim, green, intro, log, onUnknownSubcommand } from "@stacksjs/cli";
3
- const telemetry = {
4
- async enable() {},
5
- async disable() {},
6
- async status() {
7
- return {
8
- enabled: !1,
9
- doNotTrack: !!process.env.DO_NOT_TRACK,
10
- eventsQueued: 0,
11
- lastSent: null
12
- };
13
- }
14
- };
15
- export function telemetryCommand(buddy) {
16
- buddy.command("telemetry", "Manage telemetry settings").option("--enable", "Enable telemetry").option("--disable", "Disable telemetry").option("--status", "Show telemetry status").example("buddy telemetry --status").example("buddy telemetry --enable").example("buddy telemetry --disable").action(async (options) => {
17
- log.debug("Running `buddy telemetry` ...", options);
18
- await intro("buddy telemetry");
19
- try {
20
- if (options.enable) {
21
- await telemetry.enable();
22
- log.success("Telemetry enabled");
23
- log.info("");
24
- log.info(dim("Anonymous usage statistics will be collected"));
25
- log.info(dim("to help improve Buddy CLI."));
26
- log.info("");
27
- log.info(dim("You can disable telemetry anytime with:"));
28
- log.info(dim(" buddy telemetry --disable"));
29
- log.info("");
30
- return;
31
- }
32
- if (options.disable) {
33
- await telemetry.disable();
34
- log.success("Telemetry disabled");
35
- log.info("");
36
- log.info(dim("No usage statistics will be collected."));
37
- log.info("");
38
- return;
39
- }
40
- const status = await telemetry.status();
41
- log.info("");
42
- log.info(green(bold("Telemetry Status")));
43
- log.info(dim("\u2500".repeat(50)));
44
- log.info("");
45
- log.info(bold("Configuration:"));
46
- log.info(` Enabled: ${dim(status.enabled ? "Yes" : "No")}`);
47
- log.info(` DO_NOT_TRACK: ${dim(status.doNotTrack ? "Yes (respected)" : "No")}`);
48
- log.info(` Events queued: ${dim(status.eventsQueued)}`);
49
- if (status.lastSent) {
50
- const lastSent = new Date(status.lastSent);
51
- log.info(` Last sent: ${dim(lastSent.toLocaleString())}`);
52
- } else
53
- log.info(` Last sent: ${dim("Never")}`);
54
- log.info("");
55
- log.info(bold("Privacy:"));
56
- log.info(` ${dim("\u2022 Opt-in only (disabled by default)")}`);
57
- log.info(` ${dim("\u2022 No personal information collected")}`);
58
- log.info(` ${dim("\u2022 Anonymous user IDs only")}`);
59
- log.info(` ${dim("\u2022 Respects DO_NOT_TRACK environment variable")}`);
60
- log.info("");
61
- if (!status.enabled) {
62
- log.info(dim("To enable telemetry: buddy telemetry --enable"));
63
- log.info("");
64
- } else {
65
- log.info(dim("To disable telemetry: buddy telemetry --disable"));
66
- log.info("");
67
- }
68
- } catch (error) {
69
- log.error("Failed to manage telemetry:", error);
70
- process.exit(1);
71
- }
72
- });
73
- onUnknownSubcommand(buddy, "telemetry");
74
- }
1
+ import process from"node:process";import{bold,dim,green,intro,log,onUnknownSubcommand}from"@stacksjs/cli";const telemetry={async enable(){},async disable(){},async status(){return{enabled:!1,doNotTrack:!!process.env.DO_NOT_TRACK,eventsQueued:0,lastSent:null}}};export function telemetryCommand(buddy){buddy.command("telemetry","Manage telemetry settings").option("--enable","Enable telemetry").option("--disable","Disable telemetry").option("--status","Show telemetry status").example("buddy telemetry --status").example("buddy telemetry --enable").example("buddy telemetry --disable").action(async(options)=>{log.debug("Running `buddy telemetry` ...",options);await intro("buddy telemetry");try{if(options.enable){await telemetry.enable();log.success("Telemetry enabled");log.info("");log.info(dim("Anonymous usage statistics will be collected"));log.info(dim("to help improve Buddy CLI."));log.info("");log.info(dim("You can disable telemetry anytime with:"));log.info(dim(" buddy telemetry --disable"));log.info("");return}if(options.disable){await telemetry.disable();log.success("Telemetry disabled");log.info("");log.info(dim("No usage statistics will be collected."));log.info("");return}const status=await telemetry.status();log.info("");log.info(green(bold("Telemetry Status")));log.info(dim("\u2500".repeat(50)));log.info("");log.info(bold("Configuration:"));log.info(` Enabled: ${dim(status.enabled?"Yes":"No")}`);log.info(` DO_NOT_TRACK: ${dim(status.doNotTrack?"Yes (respected)":"No")}`);log.info(` Events queued: ${dim(status.eventsQueued)}`);if(status.lastSent){const lastSent=new Date(status.lastSent);log.info(` Last sent: ${dim(lastSent.toLocaleString())}`)}else log.info(` Last sent: ${dim("Never")}`);log.info("");log.info(bold("Privacy:"));log.info(` ${dim("\u2022 Opt-in only (disabled by default)")}`);log.info(` ${dim("\u2022 No personal information collected")}`);log.info(` ${dim("\u2022 Anonymous user IDs only")}`);log.info(` ${dim("\u2022 Respects DO_NOT_TRACK environment variable")}`);log.info("");if(!status.enabled){log.info(dim("To enable telemetry: buddy telemetry --enable"));log.info("")}else{log.info(dim("To disable telemetry: buddy telemetry --disable"));log.info("")}}catch(error){log.error("Failed to manage telemetry:",error);process.exit(1)}});onUnknownSubcommand(buddy,"telemetry")}
@@ -1,130 +1 @@
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 { projectPath } from "@stacksjs/path";
6
- import { ExitCode } from "@stacksjs/types";
7
- export function test(buddy) {
8
- const descriptions = {
9
- command: "Runs your test suite",
10
- types: "Typechecks your codebase",
11
- coverage: "Generates a test coverage report",
12
- ui: "Runs your test suite in the browser",
13
- unit: "Runs your unit tests",
14
- feature: "Runs your feature tests",
15
- showReport: "Show the test report",
16
- project: "Target a specific project",
17
- verbose: "Enable verbose output"
18
- };
19
- buddy.command("test", descriptions.command).option("-f, --feature", descriptions.feature, { default: !1 }).option("-u, --unit", descriptions.unit, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !0 }).action(async (options) => {
20
- const perf = await intro("buddy test");
21
- if (options.feature && options.unit) {
22
- const result = await runAction(Action.Test, {
23
- ...options,
24
- cwd: projectPath()
25
- });
26
- if (result.isErr) {
27
- await outro("While running `buddy test`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
28
- process.exit(ExitCode.FatalError);
29
- }
30
- }
31
- if (options.feature && !options.unit) {
32
- log.info("Running Feature tests...");
33
- const result = await runAction(Action.TestFeature, {
34
- ...options,
35
- cwd: projectPath()
36
- });
37
- if (result.isErr) {
38
- await outro("While running `buddy test`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
39
- process.exit(ExitCode.FatalError);
40
- }
41
- }
42
- if (!options.feature && options.unit) {
43
- log.info("Running Unit tests...");
44
- const result = await runAction(Action.TestUnit, {
45
- ...options,
46
- cwd: projectPath()
47
- });
48
- if (result.isErr) {
49
- await outro("While running `buddy test`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
50
- process.exit(ExitCode.FatalError);
51
- }
52
- }
53
- if (!options.feature && !options.unit) {
54
- const result = await runAction(Action.Test, {
55
- ...options,
56
- cwd: projectPath()
57
- });
58
- if (result.isErr) {
59
- await outro("While running `buddy test`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
60
- process.exit(ExitCode.FatalError);
61
- }
62
- }
63
- await outro("Finished running tests", {
64
- startTime: perf,
65
- useSeconds: !0
66
- });
67
- process.exit(ExitCode.Success);
68
- });
69
- buddy.command("test:unit", descriptions.unit).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
70
- const perf = await intro("buddy test:unit"), result = await runAction(Action.TestUnit, {
71
- ...options,
72
- verbose: !0,
73
- cwd: projectPath()
74
- });
75
- if (result.isErr) {
76
- await outro("While running `buddy test:unit`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
77
- process.exit(ExitCode.FatalError);
78
- }
79
- await outro("Finished running unit tests", {
80
- startTime: perf,
81
- useSeconds: !0
82
- });
83
- });
84
- buddy.command("test:feature", descriptions.feature).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
85
- const perf = await intro("buddy test:feature"), result = await runAction(Action.TestFeature, {
86
- ...options,
87
- verbose: !0,
88
- cwd: projectPath()
89
- });
90
- if (result.isErr) {
91
- await outro("While running `buddy test:feature`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
92
- process.exit(ExitCode.FatalError);
93
- }
94
- await outro("Finished running feature tests", {
95
- startTime: perf,
96
- useSeconds: !0
97
- });
98
- });
99
- buddy.command("test:ui", descriptions.command).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
100
- const perf = await intro("buddy test:ui"), result = await runAction(Action.TestUi, {
101
- ...options,
102
- verbose: !0,
103
- cwd: projectPath()
104
- });
105
- if (result.isErr) {
106
- await outro("While running `buddy test:ui`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
107
- process.exit(ExitCode.FatalError);
108
- }
109
- await outro("Finished running tests in the browser", {
110
- startTime: perf,
111
- useSeconds: !0
112
- });
113
- });
114
- buddy.command("test:types", descriptions.types).alias("typecheck").option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
115
- const perf = await intro("buddy test:types"), result = await runAction(Action.Typecheck, {
116
- ...options,
117
- verbose: !0,
118
- cwd: projectPath()
119
- });
120
- if (result.isErr) {
121
- await outro("While running `buddy test:types`, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
122
- process.exit(ExitCode.FatalError);
123
- }
124
- await outro("Finished running typecheck", {
125
- startTime: perf,
126
- useSeconds: !0
127
- });
128
- });
129
- onUnknownSubcommand(buddy, "test");
130
- }
1
+ import process from"node:process";import{runAction}from"@stacksjs/actions";import{intro,log,onUnknownSubcommand,outro}from"@stacksjs/cli";import{Action}from"@stacksjs/enums";import{projectPath}from"@stacksjs/path";import{ExitCode}from"@stacksjs/types";export function test(buddy){const descriptions={command:"Runs your test suite",types:"Typechecks your codebase",coverage:"Generates a test coverage report",ui:"Runs your test suite in the browser",unit:"Runs your unit tests",feature:"Runs your feature tests",showReport:"Show the test report",project:"Target a specific project",verbose:"Enable verbose output"};buddy.command("test",descriptions.command).option("-f, --feature",descriptions.feature,{default:!1}).option("-u, --unit",descriptions.unit,{default:!1}).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!0}).action(async(options)=>{const perf=await intro("buddy test");if(options.feature&&options.unit){const result=await runAction(Action.Test,{...options,cwd:projectPath()});if(result.isErr){await outro("While running `buddy test`, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}}if(options.feature&&!options.unit){log.info("Running Feature tests...");const result=await runAction(Action.TestFeature,{...options,cwd:projectPath()});if(result.isErr){await outro("While running `buddy test`, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}}if(!options.feature&&options.unit){log.info("Running Unit tests...");const result=await runAction(Action.TestUnit,{...options,cwd:projectPath()});if(result.isErr){await outro("While running `buddy test`, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}}if(!options.feature&&!options.unit){const result=await runAction(Action.Test,{...options,cwd:projectPath()});if(result.isErr){await outro("While running `buddy test`, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}}await outro("Finished running tests",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});buddy.command("test:unit",descriptions.unit).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{const perf=await intro("buddy test:unit"),result=await runAction(Action.TestUnit,{...options,verbose:!0,cwd:projectPath()});if(result.isErr){await outro("While running `buddy test:unit`, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Finished running unit tests",{startTime:perf,useSeconds:!0})});buddy.command("test:feature",descriptions.feature).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{const perf=await intro("buddy test:feature"),result=await runAction(Action.TestFeature,{...options,verbose:!0,cwd:projectPath()});if(result.isErr){await outro("While running `buddy test:feature`, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Finished running feature tests",{startTime:perf,useSeconds:!0})});buddy.command("test:ui",descriptions.command).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{const perf=await intro("buddy test:ui"),result=await runAction(Action.TestUi,{...options,verbose:!0,cwd:projectPath()});if(result.isErr){await outro("While running `buddy test:ui`, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Finished running tests in the browser",{startTime:perf,useSeconds:!0})});buddy.command("test:types",descriptions.types).alias("typecheck").option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{const perf=await intro("buddy test:types"),result=await runAction(Action.Typecheck,{...options,verbose:!0,cwd:projectPath()});if(result.isErr){await outro("While running `buddy test:types`, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Finished running typecheck",{startTime:perf,useSeconds:!0})});onUnknownSubcommand(buddy,"test")}
@@ -1,37 +1 @@
1
- import process from "node:process";
2
- import { intro, log, onUnknownSubcommand, outro } from "@stacksjs/cli";
3
- import { ExitCode } from "@stacksjs/types";
4
- export function tinker(buddy) {
5
- const descriptions = {
6
- tinker: "Interactive REPL with Stacks framework preloaded",
7
- eval: "Evaluate a single expression and exit",
8
- print: "Evaluate, print, and exit",
9
- noBanner: "Skip the welcome banner",
10
- preload: "Additional modules to preload (comma-separated)",
11
- project: "Target a specific project",
12
- verbose: "Enable verbose output"
13
- };
14
- buddy.command("tinker", descriptions.tinker).option("-e, --eval [expression]", descriptions.eval, { default: "" }).option("--print [expression]", descriptions.print, { default: "" }).option("--no-banner", descriptions.noBanner, { default: !1 }).option("--preload [modules]", descriptions.preload, { default: "" }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
15
- log.debug("Running `buddy tinker` ...", options);
16
- const perf = await intro("buddy tinker");
17
- try {
18
- const { startTinker } = await import("@stacksjs/tinker"), preloadModules = typeof options.preload === "string" && options.preload ? options.preload.split(",").map((m) => m.trim()) : void 0;
19
- if ((await startTinker({
20
- eval: typeof options.eval === "string" && options.eval ? options.eval : void 0,
21
- print: typeof options.print === "string" && options.print ? options.print : void 0,
22
- banner: options.noBanner !== !0,
23
- preload: preloadModules,
24
- verbose: options.verbose === !0
25
- })).exitCode !== 0) {
26
- await outro("Tinker session ended with errors", { startTime: perf, useSeconds: !0 });
27
- process.exit(ExitCode.FatalError);
28
- }
29
- await outro("Tinker session ended.", { startTime: perf, useSeconds: !0 });
30
- process.exit(ExitCode.Success);
31
- } catch (error) {
32
- await outro("While running the tinker command, there was an issue", { startTime: perf, useSeconds: !0 }, error instanceof Error ? error : void 0);
33
- process.exit(ExitCode.FatalError);
34
- }
35
- });
36
- onUnknownSubcommand(buddy, "tinker");
37
- }
1
+ import process from"node:process";import{intro,log,onUnknownSubcommand,outro}from"@stacksjs/cli";import{ExitCode}from"@stacksjs/types";export function tinker(buddy){const descriptions={tinker:"Interactive REPL with Stacks framework preloaded",eval:"Evaluate a single expression and exit",print:"Evaluate, print, and exit",noBanner:"Skip the welcome banner",preload:"Additional modules to preload (comma-separated)",project:"Target a specific project",verbose:"Enable verbose output"};buddy.command("tinker",descriptions.tinker).option("-e, --eval [expression]",descriptions.eval,{default:""}).option("--print [expression]",descriptions.print,{default:""}).option("--no-banner",descriptions.noBanner,{default:!1}).option("--preload [modules]",descriptions.preload,{default:""}).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy tinker` ...",options);const perf=await intro("buddy tinker");try{const{startTinker}=await import("@stacksjs/tinker"),preloadModules=typeof options.preload==="string"&&options.preload?options.preload.split(",").map((m)=>m.trim()):void 0;if((await startTinker({eval:typeof options.eval==="string"&&options.eval?options.eval:void 0,print:typeof options.print==="string"&&options.print?options.print:void 0,banner:options.noBanner!==!0,preload:preloadModules,verbose:options.verbose===!0})).exitCode!==0){await outro("Tinker session ended with errors",{startTime:perf,useSeconds:!0});process.exit(ExitCode.FatalError)}await outro("Tinker session ended.",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)}catch(error){await outro("While running the tinker command, there was an issue",{startTime:perf,useSeconds:!0},error instanceof Error?error:void 0);process.exit(ExitCode.FatalError)}});onUnknownSubcommand(buddy,"tinker")}
@@ -1,18 +1 @@
1
- import process from "node:process";
2
- import { generateTypes } from "@stacksjs/actions";
3
- import { log } from "@stacksjs/logging";
4
- import { onUnknownSubcommand } from "@stacksjs/cli";
5
- export function types(buddy) {
6
- const descriptions = {
7
- generate: "Generate the types of & for your library/libraries",
8
- fix: "Fix the generated types of & for your library/libraries (not yet implemented)",
9
- project: "Target a specific project",
10
- verbose: "Enable verbose output"
11
- };
12
- buddy.command("types:generate", descriptions.generate).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
13
- log.debug("Running `buddy types:generate` ...", options);
14
- await generateTypes(options);
15
- });
16
- buddy.command("types:fix", descriptions.fix).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async () => {});
17
- onUnknownSubcommand(buddy, "types");
18
- }
1
+ import process from"node:process";import{generateTypes}from"@stacksjs/actions";import{log}from"@stacksjs/logging";import{onUnknownSubcommand}from"@stacksjs/cli";export function types(buddy){const descriptions={generate:"Generate the types of & for your library/libraries",fix:"Fix the generated types of & for your library/libraries (not yet implemented)",project:"Target a specific project",verbose:"Enable verbose output"};buddy.command("types:generate",descriptions.generate).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async(options)=>{log.debug("Running `buddy types:generate` ...",options);await generateTypes(options)});buddy.command("types:fix",descriptions.fix).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).action(async()=>{});onUnknownSubcommand(buddy,"types")}
@@ -1,98 +1 @@
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 upgrade(buddy) {
7
- const descriptions = {
8
- upgrade: "Upgrade the Stacks framework to the latest version",
9
- version: "Install a specific version (e.g., 0.70.23)",
10
- canary: "Upgrade to the latest canary (bleeding-edge `main`) build",
11
- stable: "Switch to the latest vetted stable release",
12
- dryRun: "Preview the upgrade (which dependencies would change) without writing or installing",
13
- force: "Force re-download, bypassing cache and version checks",
14
- from: "Sync from a local stacks checkout (e.g. ~/Code/stacks). Skips GitHub.",
15
- noPostinstall: "Skip post-sync hooks (auto-imports, bun install, migrate)",
16
- verbose: "Enable verbose output",
17
- dependencies: "Upgrade your dependencies (pantry.yaml & package.json)",
18
- bun: "Upgrade Bun to the latest version",
19
- shell: "Upgrade the shell integration (currently only supports Oh My Zsh)",
20
- binary: "Upgrade the `stacks` binary to the latest version",
21
- project: "Target a specific project",
22
- all: "Upgrade framework, dependencies, Bun, and binary"
23
- };
24
- buddy.command("upgrade", descriptions.upgrade).option("-V, --version <version>", descriptions.version).option("--canary", descriptions.canary, { default: !1 }).option("--stable", descriptions.stable, { default: !1 }).option("--dry-run", descriptions.dryRun, { default: !1 }).option("-f, --force", descriptions.force, { default: !1 }).option("--from <path>", descriptions.from).option("--no-postinstall", descriptions.noPostinstall).option("--verbose", descriptions.verbose, { default: !1 }).alias("update").example("buddy upgrade").example("buddy update").example("buddy upgrade --from ~/Code/stacks").example("buddy upgrade --version 0.70.23").example("buddy upgrade --dry-run").example("buddy upgrade --canary").example("buddy upgrade --stable").example("buddy upgrade --force").action(async (options) => {
25
- log.debug("Running `buddy upgrade` ...", options);
26
- const opts = { ...options };
27
- if (opts.postinstall === !1) {
28
- delete opts.postinstall;
29
- opts.noPostinstall = !0;
30
- }
31
- const perf = await intro("buddy upgrade"), result = await runAction(Action.UpgradeFramework, opts);
32
- if (result.isErr) {
33
- await outro("While running buddy upgrade, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
34
- process.exit(ExitCode.FatalError);
35
- }
36
- await outro("Upgrade complete.", { startTime: perf, useSeconds: !0 });
37
- process.exit(ExitCode.Success);
38
- });
39
- buddy.command("upgrade:all", descriptions.all).option("--canary", descriptions.canary, { default: !1 }).option("-f, --force", descriptions.force, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy upgrade:all").action(async (options) => {
40
- log.debug("Running `buddy upgrade:all` ...", options);
41
- const perf = await intro("buddy upgrade:all");
42
- options.all = !0;
43
- const result = await runAction(Action.Upgrade, options);
44
- if (result.isErr) {
45
- await outro("While running buddy upgrade:all, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
46
- process.exit(ExitCode.FatalError);
47
- }
48
- await outro("All upgrades complete.", { startTime: perf, useSeconds: !0 });
49
- process.exit(ExitCode.Success);
50
- });
51
- buddy.command("upgrade:dependencies", descriptions.dependencies).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).alias("upgrade:deps").example("buddy upgrade:dependencies").action(async (options) => {
52
- log.debug("Running `buddy upgrade:dependencies` ...", options);
53
- const perf = await intro("buddy upgrade:dependencies");
54
- options.dependencies = !0;
55
- const result = await runAction(Action.Upgrade, options);
56
- if (result.isErr) {
57
- await outro("While running buddy upgrade:dependencies, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
58
- process.exit(ExitCode.FatalError);
59
- }
60
- await outro("Dependencies upgraded.", { startTime: perf, useSeconds: !0 });
61
- process.exit(ExitCode.Success);
62
- });
63
- buddy.command("upgrade:bun", descriptions.bun).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy upgrade:bun").action(async (options) => {
64
- log.debug("Running `buddy upgrade:bun` ...", options);
65
- const perf = await intro("buddy upgrade:bun"), result = await runAction(Action.UpgradeBun, options);
66
- if (result.isErr) {
67
- await outro("While running buddy upgrade:bun, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
68
- process.exit(ExitCode.FatalError);
69
- }
70
- await outro("Bun upgraded.", { startTime: perf, useSeconds: !0 });
71
- process.exit(ExitCode.Success);
72
- });
73
- buddy.command("upgrade:shell", descriptions.shell).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy upgrade:shell").action(async (options) => {
74
- log.debug("Running `buddy upgrade:shell` ...", options);
75
- const perf = await intro("buddy upgrade:shell"), result = await runAction(Action.UpgradeShell, options);
76
- if (result.isErr) {
77
- await outro("While running buddy upgrade:shell, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
78
- process.exit(ExitCode.FatalError);
79
- }
80
- await outro("Shell integration upgraded.", { startTime: perf, useSeconds: !0 });
81
- process.exit(ExitCode.Success);
82
- });
83
- buddy.command("upgrade:binary", descriptions.binary).option("--verbose", descriptions.verbose, { default: !1 }).example("buddy upgrade:binary").action(async (options) => {
84
- if (process.getuid && process.getuid() !== 0) {
85
- log.warn("To upgrade the binary, you need to run this command with sudo, or as root.");
86
- process.exit(ExitCode.FatalError);
87
- }
88
- log.debug("Running `buddy upgrade:binary` ...", options);
89
- const perf = await intro("buddy upgrade:binary"), result = await runAction(Action.UpgradeBinary, options);
90
- if (result.isErr) {
91
- await outro("While running buddy upgrade:binary, there was an issue", { startTime: perf, useSeconds: !0 }, result.error);
92
- process.exit(ExitCode.FatalError);
93
- }
94
- await outro("Binary upgraded.", { startTime: perf, useSeconds: !0 });
95
- process.exit(ExitCode.Success);
96
- });
97
- onUnknownSubcommand(buddy, "upgrade");
98
- }
1
+ import process from"node:process";import{runAction}from"@stacksjs/actions";import{intro,log,onUnknownSubcommand,outro}from"@stacksjs/cli";import{Action}from"@stacksjs/enums";import{ExitCode}from"@stacksjs/types";export function upgrade(buddy){const descriptions={upgrade:"Upgrade the Stacks framework to the latest version",version:"Install a specific version (e.g., 0.70.23)",canary:"Upgrade to the latest canary (bleeding-edge `main`) build",stable:"Switch to the latest vetted stable release",dryRun:"Preview the upgrade (which dependencies would change) without writing or installing",force:"Force re-download, bypassing cache and version checks",from:"Sync from a local stacks checkout (e.g. ~/Code/stacks). Skips GitHub.",noPostinstall:"Skip post-sync hooks (auto-imports, bun install, migrate)",verbose:"Enable verbose output",dependencies:"Upgrade your dependencies (pantry.yaml & package.json)",bun:"Upgrade Bun to the latest version",shell:"Upgrade the shell integration (currently only supports Oh My Zsh)",binary:"Upgrade the `stacks` binary to the latest version",project:"Target a specific project",all:"Upgrade framework, dependencies, Bun, and binary"};buddy.command("upgrade",descriptions.upgrade).option("-V, --version <version>",descriptions.version).option("--canary",descriptions.canary,{default:!1}).option("--stable",descriptions.stable,{default:!1}).option("--dry-run",descriptions.dryRun,{default:!1}).option("-f, --force",descriptions.force,{default:!1}).option("--from <path>",descriptions.from).option("--no-postinstall",descriptions.noPostinstall).option("--verbose",descriptions.verbose,{default:!1}).alias("update").example("buddy upgrade").example("buddy update").example("buddy upgrade --from ~/Code/stacks").example("buddy upgrade --version 0.70.23").example("buddy upgrade --dry-run").example("buddy upgrade --canary").example("buddy upgrade --stable").example("buddy upgrade --force").action(async(options)=>{log.debug("Running `buddy upgrade` ...",options);const opts={...options};if(opts.postinstall===!1){delete opts.postinstall;opts.noPostinstall=!0}const perf=await intro("buddy upgrade"),result=await runAction(Action.UpgradeFramework,opts);if(result.isErr){await outro("While running buddy upgrade, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Upgrade complete.",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});buddy.command("upgrade:all",descriptions.all).option("--canary",descriptions.canary,{default:!1}).option("-f, --force",descriptions.force,{default:!1}).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).example("buddy upgrade:all").action(async(options)=>{log.debug("Running `buddy upgrade:all` ...",options);const perf=await intro("buddy upgrade:all");options.all=!0;const result=await runAction(Action.Upgrade,options);if(result.isErr){await outro("While running buddy upgrade:all, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("All upgrades complete.",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});buddy.command("upgrade:dependencies",descriptions.dependencies).option("-p, --project [project]",descriptions.project,{default:!1}).option("--verbose",descriptions.verbose,{default:!1}).alias("upgrade:deps").example("buddy upgrade:dependencies").action(async(options)=>{log.debug("Running `buddy upgrade:dependencies` ...",options);const perf=await intro("buddy upgrade:dependencies");options.dependencies=!0;const result=await runAction(Action.Upgrade,options);if(result.isErr){await outro("While running buddy upgrade:dependencies, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Dependencies upgraded.",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});buddy.command("upgrade:bun",descriptions.bun).option("--verbose",descriptions.verbose,{default:!1}).example("buddy upgrade:bun").action(async(options)=>{log.debug("Running `buddy upgrade:bun` ...",options);const perf=await intro("buddy upgrade:bun"),result=await runAction(Action.UpgradeBun,options);if(result.isErr){await outro("While running buddy upgrade:bun, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Bun upgraded.",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});buddy.command("upgrade:shell",descriptions.shell).option("--verbose",descriptions.verbose,{default:!1}).example("buddy upgrade:shell").action(async(options)=>{log.debug("Running `buddy upgrade:shell` ...",options);const perf=await intro("buddy upgrade:shell"),result=await runAction(Action.UpgradeShell,options);if(result.isErr){await outro("While running buddy upgrade:shell, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Shell integration upgraded.",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});buddy.command("upgrade:binary",descriptions.binary).option("--verbose",descriptions.verbose,{default:!1}).example("buddy upgrade:binary").action(async(options)=>{if(process.getuid&&process.getuid()!==0){log.warn("To upgrade the binary, you need to run this command with sudo, or as root.");process.exit(ExitCode.FatalError)}log.debug("Running `buddy upgrade:binary` ...",options);const perf=await intro("buddy upgrade:binary"),result=await runAction(Action.UpgradeBinary,options);if(result.isErr){await outro("While running buddy upgrade:binary, there was an issue",{startTime:perf,useSeconds:!0},result.error);process.exit(ExitCode.FatalError)}await outro("Binary upgraded.",{startTime:perf,useSeconds:!0});process.exit(ExitCode.Success)});onUnknownSubcommand(buddy,"upgrade")}
@@ -1,87 +1,6 @@
1
- import { randomBytes } from "node:crypto";
2
- import process from "node:process";
3
- import { log } from "@stacksjs/cli";
4
- import { ExitCode } from "@stacksjs/types";
5
- function generatePassword() {
6
- return randomBytes(18).toString("base64url");
7
- }
8
- async function loadUserModel() {
9
- const { existsSync } = await import("node:fs"), { join } = await import("node:path"), candidates = [
10
- join(process.cwd(), "app/Models/User.ts"),
11
- join(process.cwd(), "storage/framework/defaults/app/Models/User.ts"),
12
- join(process.cwd(), "node_modules/@stacksjs/defaults/app/Models/User.ts")
13
- ];
14
- for (const candidate of candidates) {
15
- if (!existsSync(candidate))
16
- continue;
17
- const loaded = (await import(candidate)).default;
18
- if (loaded?.where)
19
- return loaded;
20
- }
21
- const { User } = await import("@stacksjs/orm");
22
- if (User?.where)
23
- return User;
24
- log.error("Could not find a User model. Looked in app/Models, the framework defaults and @stacksjs/orm.");
25
- await log.flush();
26
- process.exit(ExitCode.FatalError);
27
- }
28
- export function user(buddy) {
29
- buddy.command("user:add <email>", "Create a user account (optionally an admin)").option("--name <name>", "Display name. Defaults to the local part of the email.").option("--password <password>", "Password. Generated and printed once if omitted.").option("--role <role>", "Role to assign, e.g. admin. Seeds the default roles if the table is empty.").option("--update", "If the account already exists, reset its password and ensure the role", { default: !1 }).example("buddy user:add chris@example.com --role admin").example("buddy user:add support@example.com --name Support --password s3cret").action(async (email, options) => {
30
- const address = String(email || "").trim().toLowerCase();
31
- if (!address.includes("@")) {
32
- log.error(`\`${email}\` is not an email address.`);
33
- await log.flush();
34
- process.exit(ExitCode.FatalError);
35
- }
36
- const password = options.password || generatePassword(), generated = !options.password, name = options.name || address.split("@")[0], User = await loadUserModel();
37
- let account = await User.where("email", address).first();
38
- if (account && !options.update) {
39
- log.error(`${address} already exists. Pass --update to reset its password and role.`);
40
- await log.flush();
41
- process.exit(ExitCode.FatalError);
42
- }
43
- if (account) {
44
- await User.where("email", address).update({ password });
45
- log.success(`Updated ${address}`);
46
- } else {
47
- await User.create({ email: address, name, password });
48
- account = await User.where("email", address).first();
49
- log.success(`Created ${address}`);
50
- }
51
- if (options.role) {
52
- const { createBqbRbacStore, Rbac, seedDefaultRoles } = await import("@stacksjs/auth");
53
- try {
54
- Rbac.setStore(createBqbRbacStore());
55
- await seedDefaultRoles();
56
- await Rbac.assignRole(account, options.role);
57
- log.success(`Assigned the ${options.role} role`);
58
- } catch (error) {
59
- log.error(`Could not assign the ${options.role} role: ${error instanceof Error ? error.message : String(error)}`);
60
- log.info("The account exists; assign the role once the roles tables are migrated.");
61
- }
62
- }
63
- if (generated) {
64
- process.stdout.write(`
1
+ import{randomBytes}from"node:crypto";import process from"node:process";import{log}from"@stacksjs/cli";import{ExitCode}from"@stacksjs/types";function generatePassword(){return randomBytes(18).toString("base64url")}async function loadUserModel(){const{existsSync}=await import("node:fs"),{join}=await import("node:path"),candidates=[join(process.cwd(),"app/Models/User.ts"),join(process.cwd(),"storage/framework/defaults/app/Models/User.ts"),join(process.cwd(),"node_modules/@stacksjs/defaults/app/Models/User.ts")];for(const candidate of candidates){if(!existsSync(candidate))continue;const loaded=(await import(candidate)).default;if(loaded?.where)return loaded}const{User}=await import("@stacksjs/orm");if(User?.where)return User;log.error("Could not find a User model. Looked in app/Models, the framework defaults and @stacksjs/orm.");await log.flush();process.exit(ExitCode.FatalError)}export function user(buddy){buddy.command("user:add <email>","Create a user account (optionally an admin)").option("--name <name>","Display name. Defaults to the local part of the email.").option("--password <password>","Password. Generated and printed once if omitted.").option("--role <role>","Role to assign, e.g. admin. Seeds the default roles if the table is empty.").option("--update","If the account already exists, reset its password and ensure the role",{default:!1}).example("buddy user:add chris@example.com --role admin").example("buddy user:add support@example.com --name Support --password s3cret").action(async(email,options)=>{const address=String(email||"").trim().toLowerCase();if(!address.includes("@")){log.error(`\`${email}\` is not an email address.`);await log.flush();process.exit(ExitCode.FatalError)}const password=options.password||generatePassword(),generated=!options.password,name=options.name||address.split("@")[0],User=await loadUserModel();let account=await User.where("email",address).first();if(account&&!options.update){log.error(`${address} already exists. Pass --update to reset its password and role.`);await log.flush();process.exit(ExitCode.FatalError)}if(account){await User.where("email",address).update({password});log.success(`Updated ${address}`)}else{await User.create({email:address,name,password});account=await User.where("email",address).first();log.success(`Created ${address}`)}if(options.role){const{createBqbRbacStore,Rbac,seedDefaultRoles}=await import("@stacksjs/auth");try{Rbac.setStore(createBqbRbacStore());await seedDefaultRoles();await Rbac.assignRole(account,options.role);log.success(`Assigned the ${options.role} role`)}catch(error){log.error(`Could not assign the ${options.role} role: ${error instanceof Error?error.message:String(error)}`);log.info("The account exists; assign the role once the roles tables are migrated.")}}if(generated){process.stdout.write(`
65
2
  ${address}
66
3
  ${password}
67
4
 
68
- `);
69
- log.info("That password is shown once. Store it in a password manager now.");
70
- }
71
- await log.flush();
72
- process.exit(ExitCode.Success);
73
- });
74
- buddy.command("user:list", "List the accounts that can sign in").option("--limit <limit>", "How many to show", { default: "25" }).action(async (options) => {
75
- const User = await loadUserModel(), limit = Number(options.limit) || 25, rows = await User.orderBy("id").limit(limit).get();
76
- if (rows.length === 0) {
77
- log.info("No accounts yet. Create one with `buddy user:add <email> --role admin`.");
78
- await log.flush();
79
- process.exit(ExitCode.Success);
80
- }
81
- for (const row of rows)
82
- process.stdout.write(` ${String(row.id).padStart(4)} ${String(row.email).padEnd(34)} ${row.name ?? ""}
83
- `);
84
- await log.flush();
85
- process.exit(ExitCode.Success);
86
- });
87
- }
5
+ `);log.info("That password is shown once. Store it in a password manager now.")}await log.flush();process.exit(ExitCode.Success)});buddy.command("user:list","List the accounts that can sign in").option("--limit <limit>","How many to show",{default:"25"}).action(async(options)=>{const User=await loadUserModel(),limit=Number(options.limit)||25,rows=await User.orderBy("id").limit(limit).get();if(rows.length===0){log.info("No accounts yet. Create one with `buddy user:add <email> --role admin`.");await log.flush();process.exit(ExitCode.Success)}for(const row of rows)process.stdout.write(` ${String(row.id).padStart(4)} ${String(row.email).padEnd(34)} ${row.name??""}
6
+ `);await log.flush();process.exit(ExitCode.Success)})}
@@ -1,14 +1 @@
1
- import { bold, dim, green, intro, log, onUnknownSubcommand } from "@stacksjs/cli";
2
- import { versionLine } from "../version-info";
3
- export function version(buddy) {
4
- const descriptions = {
5
- version: "Retrieving Stacks build version"
6
- };
7
- buddy.command("version", descriptions.version).action(async () => {
8
- log.debug("Running `buddy version` ...");
9
- await intro("buddy version");
10
- log.info(green(bold("Stacks: ")) + dim(` ${versionLine}`));
11
- log.info(green(bold("Bun: ")) + dim(` ${Bun.version}`));
12
- });
13
- onUnknownSubcommand(buddy, "version");
14
- }
1
+ import{bold,dim,green,intro,log,onUnknownSubcommand}from"@stacksjs/cli";import{versionLine}from"../version-info";export function version(buddy){const descriptions={version:"Retrieving Stacks build version"};buddy.command("version",descriptions.version).action(async()=>{log.debug("Running `buddy version` ...");await intro("buddy version");log.info(green(bold("Stacks: "))+dim(` ${versionLine}`));log.info(green(bold("Bun: "))+dim(` ${Bun.version}`))});onUnknownSubcommand(buddy,"version")}