@stacksjs/buddy 0.70.86 → 0.70.88

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 (143) hide show
  1. package/package.json +2 -2
  2. package/dist/cli.d.ts +0 -1
  3. package/dist/cli.js +0 -165
  4. package/dist/commands/about.d.ts +0 -2
  5. package/dist/commands/about.js +0 -35
  6. package/dist/commands/add.d.ts +0 -2
  7. package/dist/commands/add.js +0 -33
  8. package/dist/commands/auth.d.ts +0 -2
  9. package/dist/commands/auth.js +0 -68
  10. package/dist/commands/build.d.ts +0 -2
  11. package/dist/commands/build.js +0 -153
  12. package/dist/commands/cd.d.ts +0 -20
  13. package/dist/commands/cd.js +0 -39
  14. package/dist/commands/changelog.d.ts +0 -2
  15. package/dist/commands/changelog.js +0 -32
  16. package/dist/commands/clean.d.ts +0 -2
  17. package/dist/commands/clean.js +0 -37
  18. package/dist/commands/cloud.d.ts +0 -2
  19. package/dist/commands/cloud.js +0 -503
  20. package/dist/commands/commit.d.ts +0 -2
  21. package/dist/commands/commit.js +0 -16
  22. package/dist/commands/completion.d.ts +0 -2
  23. package/dist/commands/completion.js +0 -143
  24. package/dist/commands/config-migrate.d.ts +0 -26
  25. package/dist/commands/config-migrate.js +0 -94
  26. package/dist/commands/configure.d.ts +0 -2
  27. package/dist/commands/configure.js +0 -48
  28. package/dist/commands/create.d.ts +0 -2
  29. package/dist/commands/create.js +0 -141
  30. package/dist/commands/deploy.d.ts +0 -107
  31. package/dist/commands/deploy.js +0 -1439
  32. package/dist/commands/dev.d.ts +0 -10
  33. package/dist/commands/dev.js +0 -907
  34. package/dist/commands/dns.d.ts +0 -2
  35. package/dist/commands/dns.js +0 -102
  36. package/dist/commands/doctor.d.ts +0 -2
  37. package/dist/commands/doctor.js +0 -285
  38. package/dist/commands/domains.d.ts +0 -2
  39. package/dist/commands/domains.js +0 -159
  40. package/dist/commands/email.d.ts +0 -2
  41. package/dist/commands/email.js +0 -524
  42. package/dist/commands/env.d.ts +0 -2
  43. package/dist/commands/env.js +0 -246
  44. package/dist/commands/extension.d.ts +0 -8
  45. package/dist/commands/extension.js +0 -78
  46. package/dist/commands/features.d.ts +0 -180
  47. package/dist/commands/features.js +0 -422
  48. package/dist/commands/fresh.d.ts +0 -2
  49. package/dist/commands/fresh.js +0 -39
  50. package/dist/commands/generate.d.ts +0 -2
  51. package/dist/commands/generate.js +0 -104
  52. package/dist/commands/http.d.ts +0 -2
  53. package/dist/commands/http.js +0 -33
  54. package/dist/commands/index.d.ts +0 -53
  55. package/dist/commands/index.js +0 -53
  56. package/dist/commands/install.d.ts +0 -2
  57. package/dist/commands/install.js +0 -22
  58. package/dist/commands/key.d.ts +0 -2
  59. package/dist/commands/key.js +0 -23
  60. package/dist/commands/lint.d.ts +0 -2
  61. package/dist/commands/lint.js +0 -46
  62. package/dist/commands/list.d.ts +0 -2
  63. package/dist/commands/list.js +0 -108
  64. package/dist/commands/mail.d.ts +0 -2
  65. package/dist/commands/mail.js +0 -693
  66. package/dist/commands/maintenance.d.ts +0 -2
  67. package/dist/commands/maintenance.js +0 -141
  68. package/dist/commands/make.d.ts +0 -2
  69. package/dist/commands/make.js +0 -375
  70. package/dist/commands/migrate-project.d.ts +0 -2
  71. package/dist/commands/migrate-project.js +0 -49
  72. package/dist/commands/migrate.d.ts +0 -4
  73. package/dist/commands/migrate.js +0 -455
  74. package/dist/commands/outdated.d.ts +0 -2
  75. package/dist/commands/outdated.js +0 -19
  76. package/dist/commands/package.d.ts +0 -2
  77. package/dist/commands/package.js +0 -17
  78. package/dist/commands/phone.d.ts +0 -2
  79. package/dist/commands/phone.js +0 -188
  80. package/dist/commands/ports.d.ts +0 -2
  81. package/dist/commands/ports.js +0 -118
  82. package/dist/commands/prepublish.d.ts +0 -2
  83. package/dist/commands/prepublish.js +0 -17
  84. package/dist/commands/projects.d.ts +0 -2
  85. package/dist/commands/projects.js +0 -29
  86. package/dist/commands/publish.d.ts +0 -2
  87. package/dist/commands/publish.js +0 -172
  88. package/dist/commands/queue.d.ts +0 -2
  89. package/dist/commands/queue.js +0 -248
  90. package/dist/commands/release.d.ts +0 -2
  91. package/dist/commands/release.js +0 -30
  92. package/dist/commands/route.d.ts +0 -2
  93. package/dist/commands/route.js +0 -21
  94. package/dist/commands/saas.d.ts +0 -2
  95. package/dist/commands/saas.js +0 -25
  96. package/dist/commands/schedule.d.ts +0 -2
  97. package/dist/commands/schedule.js +0 -61
  98. package/dist/commands/search.d.ts +0 -2
  99. package/dist/commands/search.js +0 -84
  100. package/dist/commands/seed.d.ts +0 -2
  101. package/dist/commands/seed.js +0 -71
  102. package/dist/commands/serve.d.ts +0 -25
  103. package/dist/commands/serve.js +0 -182
  104. package/dist/commands/setup.d.ts +0 -12
  105. package/dist/commands/setup.js +0 -215
  106. package/dist/commands/share.d.ts +0 -2
  107. package/dist/commands/share.js +0 -214
  108. package/dist/commands/sms.d.ts +0 -2
  109. package/dist/commands/sms.js +0 -328
  110. package/dist/commands/stacks.d.ts +0 -2
  111. package/dist/commands/stacks.js +0 -69
  112. package/dist/commands/telemetry.d.ts +0 -2
  113. package/dist/commands/telemetry.js +0 -74
  114. package/dist/commands/test.d.ts +0 -2
  115. package/dist/commands/test.js +0 -130
  116. package/dist/commands/tinker.d.ts +0 -2
  117. package/dist/commands/tinker.js +0 -37
  118. package/dist/commands/types.d.ts +0 -2
  119. package/dist/commands/types.js +0 -18
  120. package/dist/commands/upgrade.d.ts +0 -2
  121. package/dist/commands/upgrade.js +0 -98
  122. package/dist/commands/version.d.ts +0 -2
  123. package/dist/commands/version.js +0 -16
  124. package/dist/config.d.ts +0 -43
  125. package/dist/config.js +0 -223
  126. package/dist/custom-cli.d.ts +0 -1
  127. package/dist/custom-cli.js +0 -23
  128. package/dist/index.d.ts +0 -1
  129. package/dist/index.js +0 -1
  130. package/dist/lazy-commands.d.ts +0 -61
  131. package/dist/lazy-commands.js +0 -188
  132. package/dist/migrators/index.d.ts +0 -9
  133. package/dist/migrators/index.js +0 -62
  134. package/dist/migrators/laravel/index.d.ts +0 -2
  135. package/dist/migrators/laravel/index.js +0 -148
  136. package/dist/migrators/laravel/migrations.d.ts +0 -52
  137. package/dist/migrators/laravel/migrations.js +0 -232
  138. package/dist/migrators/laravel/models.d.ts +0 -34
  139. package/dist/migrators/laravel/models.js +0 -134
  140. package/dist/migrators/rails/index.d.ts +0 -2
  141. package/dist/migrators/rails/index.js +0 -11
  142. package/dist/migrators/types.d.ts +0 -44
  143. package/dist/migrators/types.js +0 -0
@@ -1,503 +0,0 @@
1
- import process from "node:process";
2
- import { intro, italic, log, onUnknownSubcommand, outro, prompts, runCommand, underline } from "@stacksjs/cli";
3
- import {
4
- addJumpBox,
5
- deleteCdkRemnants,
6
- deleteIamUsers,
7
- deleteJumpBox,
8
- deleteLogGroups,
9
- deleteParameterStore,
10
- deleteStacksBuckets,
11
- deleteStacksFunctions,
12
- deleteSubnets,
13
- deleteVpcs,
14
- getCloudFrontDistributionId,
15
- getJumpBoxInstanceId
16
- } from "@stacksjs/cloud";
17
- import { path as p } from "@stacksjs/path";
18
- import { ExitCode } from "@stacksjs/types";
19
- async function createTemporaryCdkRole(roleName) {
20
- const { AWSClient } = await import("@stacksjs/ts-cloud"), client = new AWSClient, trustPolicy = {
21
- Version: "2012-10-17",
22
- Statement: [
23
- {
24
- Effect: "Allow",
25
- Principal: {
26
- Service: "cloudformation.amazonaws.com"
27
- },
28
- Action: "sts:AssumeRole"
29
- }
30
- ]
31
- };
32
- try {
33
- try {
34
- const getRoleParams = new URLSearchParams({
35
- Action: "GetRole",
36
- RoleName: roleName,
37
- Version: "2010-05-08"
38
- });
39
- await client.request({
40
- service: "iam",
41
- region: "us-east-1",
42
- method: "POST",
43
- path: "/",
44
- body: getRoleParams.toString()
45
- });
46
- log.debug(`Role ${roleName} already exists`);
47
- return;
48
- } catch (e) {
49
- if (!e.message?.includes("NoSuchEntity") && !e.message?.includes("cannot be found"))
50
- throw e;
51
- }
52
- log.info("Creating temporary IAM role to enable stack deletion...");
53
- const createRoleParams = new URLSearchParams({
54
- Action: "CreateRole",
55
- RoleName: roleName,
56
- AssumeRolePolicyDocument: JSON.stringify(trustPolicy),
57
- Description: "Temporary role to allow CloudFormation to delete stuck stack",
58
- Version: "2010-05-08"
59
- });
60
- await client.request({
61
- service: "iam",
62
- region: "us-east-1",
63
- method: "POST",
64
- path: "/",
65
- body: createRoleParams.toString()
66
- });
67
- log.success("Created IAM role");
68
- log.info("Attaching permissions...");
69
- const attachPolicyParams = new URLSearchParams({
70
- Action: "AttachRolePolicy",
71
- RoleName: roleName,
72
- PolicyArn: "arn:aws:iam::aws:policy/AdministratorAccess",
73
- Version: "2010-05-08"
74
- });
75
- await client.request({
76
- service: "iam",
77
- region: "us-east-1",
78
- method: "POST",
79
- path: "/",
80
- body: attachPolicyParams.toString()
81
- });
82
- log.success("IAM role ready for stack deletion");
83
- log.info("Waiting for IAM role to propagate...");
84
- await new Promise((resolve) => setTimeout(resolve, 1e4));
85
- } catch (error) {
86
- if (error.message?.includes("EntityAlreadyExists"))
87
- log.debug("Role already exists");
88
- else
89
- throw error;
90
- }
91
- }
92
- async function deleteTemporaryCdkRole(roleName) {
93
- const { AWSClient } = await import("@stacksjs/ts-cloud"), client = new AWSClient;
94
- try {
95
- const detachPolicyParams = new URLSearchParams({
96
- Action: "DetachRolePolicy",
97
- RoleName: roleName,
98
- PolicyArn: "arn:aws:iam::aws:policy/AdministratorAccess",
99
- Version: "2010-05-08"
100
- });
101
- await client.request({
102
- service: "iam",
103
- region: "us-east-1",
104
- method: "POST",
105
- path: "/",
106
- body: detachPolicyParams.toString()
107
- });
108
- const deleteRoleParams = new URLSearchParams({
109
- Action: "DeleteRole",
110
- RoleName: roleName,
111
- Version: "2010-05-08"
112
- });
113
- await client.request({
114
- service: "iam",
115
- region: "us-east-1",
116
- method: "POST",
117
- path: "/",
118
- body: deleteRoleParams.toString()
119
- });
120
- log.success("Cleaned up temporary IAM role");
121
- } catch (error) {
122
- log.debug(`Could not clean up temporary role: ${error.message}`);
123
- }
124
- }
125
- function isResultError(result) {
126
- if (!result || typeof result !== "object")
127
- return !1;
128
- const r = result;
129
- if (typeof r.isErr === "function")
130
- return r.isErr();
131
- return !!r.isErr;
132
- }
133
- function getResultError(result) {
134
- if (!result || typeof result !== "object")
135
- return "Unknown error";
136
- return String(result.error || "Unknown error");
137
- }
138
- function getResultValue(result) {
139
- if (!result || typeof result !== "object")
140
- return;
141
- return result.value;
142
- }
143
- export function cloud(buddy) {
144
- const descriptions = {
145
- cloud: "Interact with the Stacks Cloud",
146
- ssh: "SSH into the Stacks Cloud",
147
- add: "Add a resource to the Stacks Cloud",
148
- remove: "Remove the Stacks Cloud. In case it fails, try again",
149
- optimizeCost: "Remove certain resources that may be re-applied at a later time",
150
- cleanUp: "Remove all resources that were retained during the cloud deletion",
151
- invalidateCache: "Invalidate the CloudFront cache",
152
- diff: "Show the diff of the current, undeployed cloud changes ",
153
- dashboard: "Run the local Stacks Cloud management cockpit (servers, sites, deploys)",
154
- host: "Host to bind the dashboard to",
155
- port: "Port to bind the dashboard to",
156
- env: "Environment to manage",
157
- paths: "The paths to invalidate",
158
- project: "Target a specific project",
159
- verbose: "Enable verbose output"
160
- };
161
- buddy.command("cloud", descriptions.cloud).option("--ssh", descriptions.ssh, { default: !1 }).option("--connect", descriptions.ssh, { default: !1 }).option("--invalidate-cache", descriptions.invalidateCache, { default: !1 }).option("--paths [paths]", descriptions.paths).option("--diff", descriptions.diff, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
162
- log.debug("Running `buddy cloud` ...", options);
163
- const startTime = performance.now();
164
- if (options.ssh || options.connect) {
165
- const jumpBoxId = await getJumpBoxInstanceId(), result = await runCommand(`aws ssm start-session --target ${jumpBoxId}`, {
166
- ...options,
167
- cwd: p.projectPath(),
168
- stdin: "pipe"
169
- });
170
- if (isResultError(result)) {
171
- await outro("While running the cloud command, there was an issue", { startTime, useSeconds: !0 }, getResultError(result));
172
- process.exit(ExitCode.FatalError);
173
- }
174
- await outro("Exited", { startTime, useSeconds: !0 });
175
- process.exit(ExitCode.Success);
176
- }
177
- if (options.invalidateCache) {
178
- const { confirm } = await prompts({
179
- name: "confirm",
180
- type: "confirm",
181
- message: "Would you like to invalidate the CDN (CloudFront) cache?"
182
- });
183
- if (!confirm) {
184
- await outro("Exited", { startTime, useSeconds: !0 });
185
- process.exit(ExitCode.Success);
186
- }
187
- log.info("Invalidating the CloudFront cache...");
188
- const { AWSCloudFrontClient } = await import("@stacksjs/ts-cloud"), cloudfront = new AWSCloudFrontClient, distributionId = await getCloudFrontDistributionId();
189
- try {
190
- const invalidationId = await cloudfront.invalidateAll(distributionId);
191
- log.success(`Invalidation created: ${invalidationId}`);
192
- log.info("Status: pending");
193
- } catch (err) {
194
- log.error(`Failed to invalidate CloudFront cache: ${err.message}`);
195
- }
196
- await outro("Exited", { startTime, useSeconds: !0 });
197
- process.exit(ExitCode.Success);
198
- }
199
- if (options.diff) {
200
- try {
201
- const { InfrastructureGenerator } = await import("@stacksjs/ts-cloud"), { CloudFormationClient } = await import("@stacksjs/ts-cloud/aws"), { tsCloud: cloudConfig } = await import("~/config/cloud"), environment = process.env.APP_ENV || process.env.NODE_ENV || "production", newTemplate = new InfrastructureGenerator({
202
- config: cloudConfig,
203
- environment
204
- }).generate().toJSON(), stackName = `${cloudConfig.project?.slug || "stacks"}-${environment}`, cfn = new CloudFormationClient(process.env.AWS_REGION || "us-east-1");
205
- let currentTemplate = "{}";
206
- try {
207
- currentTemplate = (await cfn.getTemplate(stackName)).TemplateBody;
208
- } catch {
209
- log.info("No deployed stack found. Showing full template as diff.");
210
- }
211
- if (currentTemplate === newTemplate)
212
- log.info("No changes detected.");
213
- else {
214
- log.info("Changes detected between deployed and local template:");
215
- log.info(`Current template: ${currentTemplate.length} bytes`);
216
- log.info(`New template: ${newTemplate.length} bytes`);
217
- }
218
- } catch (error) {
219
- log.error(`Failed to compute diff: ${error.message}`);
220
- }
221
- await outro("Cloud diff complete", { startTime, useSeconds: !0 });
222
- process.exit(ExitCode.Success);
223
- }
224
- log.info("Not implemented yet. Read more about `buddy cloud` here: https://stacksjs.com/docs/cloud");
225
- process.exit(ExitCode.Success);
226
- });
227
- buddy.command("cloud:add", descriptions.add).option("--jump-box", "Remove the jump-box", { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
228
- log.debug("Running `buddy cloud:add` ...", options);
229
- const startTime = await intro("buddy cloud:add");
230
- if (options.jumpBox) {
231
- const { confirm } = await prompts({
232
- name: "confirm",
233
- type: "confirm",
234
- message: "Would you like to add a jump-box to your cloud?"
235
- });
236
- if (!confirm) {
237
- await outro("Exited", { startTime, useSeconds: !0 });
238
- process.exit(ExitCode.Success);
239
- }
240
- log.info("The jump-box is getting added to your cloud resources...");
241
- log.info("This takes a few moments, please be patient.");
242
- await new Promise((resolve) => setTimeout(resolve, 2000));
243
- const result = await addJumpBox();
244
- if (isResultError(result)) {
245
- await outro("While running the cloud:add command, there was an issue", { startTime, useSeconds: !0 }, getResultError(result));
246
- process.exit(ExitCode.FatalError);
247
- }
248
- log.info(italic("View the jump-box in the AWS console:"));
249
- log.info(underline("https://us-east-1.console.aws.amazon.com/ec2/home?region=us-east-1#Instances:instanceState=running"));
250
- log.info(italic("Once it finished initializing, you may SSH into it:"));
251
- log.info(underline("buddy cloud --ssh"));
252
- await outro("Your jump-box was added.", {
253
- startTime,
254
- useSeconds: !0
255
- });
256
- process.exit(ExitCode.Success);
257
- }
258
- log.info("This functionality is not yet implemented.");
259
- process.exit(ExitCode.Success);
260
- });
261
- buddy.command("cloud:remove", descriptions.remove).alias("cloud:destroy").alias("cloud:rm").alias("undeploy").option("--jump-box", "Remove the jump-box", { default: !1 }).option("--force", "Force deletion of stack in bad state", { default: !1 }).option("--yes", "Skip confirmation prompts", { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
262
- log.debug("Running `buddy cloud:remove` ...", options);
263
- const startTime = await intro("buddy cloud:remove");
264
- if (options.jumpBox) {
265
- const { confirm } = await prompts({
266
- name: "confirm",
267
- type: "confirm",
268
- message: "Would you like to remove your jump-box for now?"
269
- });
270
- if (!confirm) {
271
- await outro("Exited", { startTime, useSeconds: !0 });
272
- process.exit(ExitCode.Success);
273
- }
274
- const result = await deleteJumpBox();
275
- if (isResultError(result)) {
276
- await outro("While removing your jump-box, there was an issue", { startTime, useSeconds: !0 }, getResultError(result));
277
- process.exit(ExitCode.FatalError);
278
- }
279
- await outro("Your jump-box was removed.", {
280
- startTime,
281
- useSeconds: !0
282
- });
283
- process.exit(ExitCode.Success);
284
- }
285
- console.log("");
286
- console.log("Removing cloud infrastructure...");
287
- console.log(` ${italic("This typically takes 2-5 minutes.")}`);
288
- console.log("");
289
- const environment = process.env.APP_ENV || process.env.NODE_ENV || "production";
290
- if (!process.env.AWS_ACCESS_KEY_ID || !process.env.AWS_SECRET_ACCESS_KEY) {
291
- const { existsSync, readFileSync } = await import("node:fs"), { projectPath } = await import("@stacksjs/path"), envFiles = [
292
- projectPath(`.env.${environment}`),
293
- projectPath(".env")
294
- ];
295
- for (const envPath of envFiles)
296
- if (existsSync(envPath)) {
297
- const lines = readFileSync(envPath, "utf-8").split(`
298
- `);
299
- for (const line of lines) {
300
- const trimmed = line.trim();
301
- if (trimmed.startsWith("#") || !trimmed.includes("="))
302
- continue;
303
- const [key, ...valueParts] = trimmed.split("="), value = valueParts.join("=").replace(/^["']|["']$/g, "");
304
- if (key === "AWS_ACCESS_KEY_ID" || key === "AWS_SECRET_ACCESS_KEY" || key === "AWS_REGION" || key === "AWS_ACCOUNT_ID")
305
- process.env[key] = value;
306
- }
307
- break;
308
- }
309
- }
310
- delete process.env.AWS_PROFILE;
311
- try {
312
- const { undeployStack } = await import("../../../actions/deploy"), region = process.env.AWS_REGION || "us-east-1";
313
- await undeployStack({
314
- environment,
315
- region,
316
- verbose: options.verbose
317
- });
318
- await outro("Cloud infrastructure removed", { startTime, useSeconds: !0 });
319
- process.exit(ExitCode.Success);
320
- } catch (error) {
321
- console.log("");
322
- console.error("\u2717 Failed to remove cloud infrastructure");
323
- const errorStr = String(error.message || error);
324
- if (errorStr.includes("security token") || errorStr.includes("credentials")) {
325
- console.log("");
326
- console.error(" AWS credentials are invalid or expired");
327
- console.log(" Check your AWS credentials in .env.production:");
328
- console.log(" - AWS_ACCESS_KEY_ID");
329
- console.log(" - AWS_SECRET_ACCESS_KEY");
330
- } else if (errorStr.includes("region") || errorStr.includes("AWS_REGION")) {
331
- console.log("");
332
- console.error(" AWS Region not configured");
333
- console.log(" Add AWS_REGION to your .env.production file");
334
- } else if (errorStr.includes("AccessDenied")) {
335
- console.log("");
336
- console.error(" Access denied");
337
- console.log(" Your AWS credentials may not have permission to delete stacks");
338
- } else
339
- console.error(` ${errorStr}`);
340
- console.log("");
341
- console.log("Troubleshooting:");
342
- console.log(" ./buddy cloud:cleanup - Clean up resources manually");
343
- console.log(" --verbose - Show detailed error information");
344
- console.log("");
345
- if (options.verbose)
346
- console.error("Error details:", error);
347
- await outro("Failed to remove infrastructure", { startTime, useSeconds: !0 });
348
- process.exit(ExitCode.FatalError);
349
- }
350
- });
351
- buddy.command("cloud:optimize-cost", descriptions.optimizeCost).option("--jump-box", "Remove the jump-box", { default: !0 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
352
- log.debug("Running `buddy cloud:optimize-cost` ...", options);
353
- const startTime = await intro("buddy cloud:optimize-cost");
354
- if (options.jumpBox) {
355
- const { confirm } = await prompts({
356
- name: "confirm",
357
- type: "confirm",
358
- message: "Would you like to remove your jump-box to optimize your costs?"
359
- });
360
- if (!confirm) {
361
- await outro("Exited", { startTime, useSeconds: !0 });
362
- process.exit(ExitCode.Success);
363
- }
364
- await deleteJumpBox();
365
- await outro("Your jump-box was removed & cost optimizations are applied.", { startTime, useSeconds: !0 });
366
- process.exit(ExitCode.Success);
367
- }
368
- await outro("No cost optimization was applied", {
369
- startTime,
370
- useSeconds: !0
371
- });
372
- process.exit(ExitCode.Success);
373
- });
374
- buddy.command("cloud:cleanup", descriptions.cleanUp).alias("cloud:clean-up").option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
375
- log.debug("Running `buddy cloud:cleanup` ...", options);
376
- const startTime = await intro("buddy cloud:cleanup");
377
- delete process.env.AWS_PROFILE;
378
- log.info("Cleaning up your cloud resources will take a while to complete. Please be patient.");
379
- await new Promise((resolve) => setTimeout(resolve, 2000));
380
- const cleanupSteps = [
381
- { label: "jump-boxes", fn: deleteJumpBox, ignoreErrors: ["Jump-box not found"] },
382
- { label: "retained S3 buckets", fn: deleteStacksBuckets },
383
- { label: "retained Lambda functions", fn: deleteStacksFunctions, ignoreErrors: ["No stacks functions found"] },
384
- { label: "remaining Stacks logs", fn: deleteLogGroups },
385
- { label: "stored parameters", fn: deleteParameterStore },
386
- { label: "VPCs", fn: deleteVpcs },
387
- { label: "Subnets", fn: deleteSubnets },
388
- { label: "CDK remnants", fn: deleteCdkRemnants },
389
- { label: "IAM users", fn: deleteIamUsers }
390
- ], errors = [];
391
- for (const step of cleanupSteps) {
392
- log.info(`Removing any ${step.label}...`);
393
- try {
394
- const result = await step.fn();
395
- if (isResultError(result)) {
396
- const errMsg = getResultError(result);
397
- if (!step.ignoreErrors?.includes(errMsg)) {
398
- log.warn(`${step.label} cleanup issue: ${errMsg}`);
399
- errors.push({ label: step.label, error: errMsg });
400
- }
401
- } else {
402
- const value = getResultValue(result);
403
- if (value)
404
- log.info(String(value));
405
- }
406
- } catch (e) {
407
- const errMsg = e.message || "AWS SDK error";
408
- log.warn(`${step.label} cleanup skipped: ${errMsg}`);
409
- errors.push({ label: step.label, error: errMsg });
410
- }
411
- }
412
- if (errors.length > 0) {
413
- log.warn(`Cleanup completed with ${errors.length} issue(s):`);
414
- for (const { label, error } of errors)
415
- log.warn(` - ${label}: ${error}`);
416
- }
417
- await outro("AWS resources have been removed", {
418
- startTime,
419
- useSeconds: !0
420
- });
421
- process.exit(ExitCode.Success);
422
- });
423
- buddy.command("cloud:invalidate-cache", descriptions.invalidateCache).option("--paths [paths]", descriptions.paths, { default: !1 }).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
424
- log.debug("Running `buddy cloud:invalidate-cache` ...", options);
425
- const startTime = await intro("buddy cloud:invalidate-cache"), { confirm } = await prompts({
426
- name: "confirm",
427
- type: "confirm",
428
- message: "Would you like to invalidate the CloudFront cache?"
429
- });
430
- if (!confirm) {
431
- await outro("Exited", { startTime, useSeconds: !0 });
432
- process.exit(ExitCode.Success);
433
- }
434
- log.info("Invalidating the CloudFront cache...");
435
- const distributionId = await getCloudFrontDistributionId();
436
- if (!distributionId) {
437
- await outro("Could not resolve CloudFront distribution ID", { startTime, useSeconds: !0 }, "Ensure your cloud stack is deployed before invalidating cache.");
438
- process.exit(ExitCode.FatalError);
439
- }
440
- const paths = options.paths ? String(options.paths) : "/*", result = await runCommand(`aws cloudfront create-invalidation --distribution-id ${distributionId} --paths ${paths}`, {
441
- ...options,
442
- cwd: p.projectPath(),
443
- stdin: "pipe"
444
- });
445
- if (isResultError(result)) {
446
- await outro("While running the cloud command, there was an issue", { startTime, useSeconds: !0 }, getResultError(result));
447
- process.exit(ExitCode.FatalError);
448
- }
449
- await outro("Exited", { startTime, useSeconds: !0 });
450
- process.exit(ExitCode.Success);
451
- });
452
- buddy.command("cloud:diff", descriptions.diff).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
453
- log.debug("Running `buddy cloud:diff` ...", options);
454
- const startTime = await intro("buddy cloud:diff");
455
- try {
456
- const { InfrastructureGenerator } = await import("@stacksjs/ts-cloud"), { CloudFormationClient } = await import("@stacksjs/ts-cloud/aws"), { tsCloud: cloudConfig } = await import("~/config/cloud"), environment = process.env.APP_ENV || process.env.NODE_ENV || "production", newTemplate = new InfrastructureGenerator({
457
- config: cloudConfig,
458
- environment
459
- }).generate().toJSON(), stackName = `${cloudConfig.project?.slug || "stacks"}-${environment}`, cfn = new CloudFormationClient(process.env.AWS_REGION || "us-east-1");
460
- let currentTemplate = "{}";
461
- try {
462
- currentTemplate = (await cfn.getTemplate(stackName)).TemplateBody;
463
- } catch {
464
- log.info("No deployed stack found. Showing full template as diff.");
465
- }
466
- if (currentTemplate === newTemplate)
467
- log.info("No changes detected.");
468
- else {
469
- log.info("Changes detected between deployed and local template:");
470
- log.info(`Current template: ${currentTemplate.length} bytes`);
471
- log.info(`New template: ${newTemplate.length} bytes`);
472
- }
473
- } catch (error) {
474
- await outro("While running the cloud diff command, there was an issue", { startTime, useSeconds: !0 }, error.message);
475
- process.exit(ExitCode.FatalError);
476
- }
477
- await outro("Cloud diff complete", { startTime, useSeconds: !0 });
478
- process.exit(ExitCode.Success);
479
- });
480
- buddy.command("cloud:dashboard", descriptions.dashboard).alias("cloud:cockpit").option("--host [host]", descriptions.host, { default: "127.0.0.1" }).option("--port [port]", descriptions.port, { default: "7676" }).option("--env [env]", descriptions.env).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
481
- log.debug("Running `buddy cloud:dashboard` ...", options);
482
- const startTime = await intro("buddy cloud:dashboard"), tsCloud = await import("@stacksjs/ts-cloud");
483
- if (typeof tsCloud.startLocalDashboardServer !== "function") {
484
- await outro("The installed @stacksjs/ts-cloud does not provide the local cockpit yet", { startTime, useSeconds: !0 }, "Update your dependencies (requires @stacksjs/ts-cloud >= 0.5.27).");
485
- process.exit(ExitCode.FatalError);
486
- }
487
- try {
488
- const server = await tsCloud.startLocalDashboardServer({
489
- host: options.host ? String(options.host) : void 0,
490
- port: options.port ? Number(options.port) : void 0,
491
- environment: options.env,
492
- verbose: !!options.verbose
493
- });
494
- log.success(`Stacks Cloud cockpit running at ${underline(server.url)}`);
495
- log.info(italic("Manage servers, sites, SSH keys and deploys. Press Ctrl+C to stop."));
496
- await new Promise(() => {});
497
- } catch (error) {
498
- await outro("While starting the cloud dashboard, there was an issue", { startTime, useSeconds: !0 }, error?.message ?? String(error));
499
- process.exit(ExitCode.FatalError);
500
- }
501
- });
502
- onUnknownSubcommand(buddy, "cloud");
503
- }
@@ -1,2 +0,0 @@
1
- import type { CLI } from '@stacksjs/types';
2
- export declare function commit(buddy: CLI): void;
@@ -1,16 +0,0 @@
1
- import process from "node:process";
2
- import { runCommit } from "@stacksjs/actions";
3
- import { log } from "@stacksjs/logging";
4
- import { onUnknownSubcommand } from "@stacksjs/cli";
5
- export function commit(buddy) {
6
- const descriptions = {
7
- commit: "Commit your stashed changes",
8
- project: "Target a specific project",
9
- verbose: "Enable verbose output"
10
- };
11
- buddy.command("commit", descriptions.commit).option("-p, --project [project]", descriptions.project, { default: !1 }).option("--verbose", descriptions.verbose, { default: !1 }).action(async (options) => {
12
- log.debug("Running `buddy commit` ...", options);
13
- await runCommit(options);
14
- });
15
- onUnknownSubcommand(buddy, "commit");
16
- }
@@ -1,2 +0,0 @@
1
- import type { CLI } from '@stacksjs/types';
2
- export declare function completion(buddy: CLI): void;
@@ -1,143 +0,0 @@
1
- import process from "node:process";
2
- import { log, onUnknownSubcommand } from "@stacksjs/cli";
3
- export function completion(buddy) {
4
- const descriptions = {
5
- completion: "Generate shell completion scripts",
6
- shell: "Shell type (bash, zsh, fish)"
7
- };
8
- buddy.command("completion [shell]", descriptions.completion).option("-s, --shell [shell]", descriptions.shell).example("buddy completion bash").example("buddy completion zsh").example("buddy completion fish").example("buddy completion bash > /usr/local/etc/bash_completion.d/buddy").action(async (shell, options) => {
9
- log.debug("Running `buddy completion` ...", options);
10
- const targetShell = shell || options.shell || "bash", commandNames = (buddy.commands || []).map((cmd) => cmd.name).filter((name) => Boolean(name));
11
- switch (targetShell) {
12
- case "bash":
13
- console.log(generateBashCompletion(commandNames));
14
- break;
15
- case "zsh":
16
- console.log(generateZshCompletion(commandNames));
17
- break;
18
- case "fish":
19
- console.log(generateFishCompletion(commandNames));
20
- break;
21
- default:
22
- console.error(`Unknown shell: ${targetShell}`);
23
- console.error("Supported shells: bash, zsh, fish");
24
- process.exit(1);
25
- }
26
- });
27
- onUnknownSubcommand(buddy, "completion");
28
- }
29
- function generateBashCompletion(commands) {
30
- return `# buddy completion for bash
31
-
32
- _buddy_completion() {
33
- local cur prev commands
34
- COMPREPLY=()
35
- cur="\${COMP_WORDS[COMP_CWORD]}"
36
- prev="\${COMP_WORDS[COMP_CWORD-1]}"
37
-
38
- commands="${commands.join(" ")}"
39
-
40
- # Complete command names
41
- if [ $COMP_CWORD -eq 1 ]; then
42
- COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
43
- return 0
44
- fi
45
-
46
- # Complete global flags
47
- case "$prev" in
48
- buddy|*)
49
- COMPREPLY=( $(compgen -W "--help --version --verbose --quiet --debug --no-interaction --env --dry-run --force" -- "$cur") )
50
- return 0
51
- ;;
52
- esac
53
- }
54
-
55
- complete -F _buddy_completion buddy
56
-
57
- # Installation:
58
- # To install this completion script, save it to:
59
- # - Linux: /etc/bash_completion.d/buddy or ~/.bash_completion
60
- # - macOS: /usr/local/etc/bash_completion.d/buddy
61
- #
62
- # Then reload your shell or run: source ~/.bashrc
63
- `;
64
- }
65
- function generateZshCompletion(commands) {
66
- return `#compdef buddy
67
-
68
- # buddy completion for zsh
69
-
70
- _buddy() {
71
- local -a commands
72
- commands=(
73
- ${commands.map((cmd) => ` '${cmd}:${cmd} command'`).join(`
74
- `)}
75
- )
76
-
77
- local -a global_flags
78
- global_flags=(
79
- '--help[Display help message]'
80
- '--version[Display version number]'
81
- '--verbose[Enable verbose output]'
82
- '--quiet[Suppress non-essential output]'
83
- '--debug[Enable debug mode]'
84
- '--no-interaction[Do not ask interactive questions]'
85
- '--env[Target environment]:environment:'
86
- '--dry-run[Preview actions without executing]'
87
- '--force[Skip confirmation prompts]'
88
- )
89
-
90
- _arguments -C \\
91
- '1: :->command' \\
92
- '*::arg:->args' \\
93
- $global_flags
94
-
95
- case $state in
96
- command)
97
- _describe 'buddy command' commands
98
- ;;
99
- *)
100
- # Add subcommand-specific completions here if needed
101
- ;;
102
- esac
103
- }
104
-
105
- _buddy "$@"
106
-
107
- # Installation:
108
- # Save this file to a directory in your $fpath, for example:
109
- # ~/.zsh/completions/_buddy
110
- #
111
- # Then add to your ~/.zshrc:
112
- # fpath=(~/.zsh/completions $fpath)
113
- # autoload -Uz compinit && compinit
114
- `;
115
- }
116
- function generateFishCompletion(commands) {
117
- return `# buddy completion for fish
118
-
119
- # Remove old completions
120
- complete -c buddy -e
121
-
122
- # Command completions
123
- ${commands.map((cmd) => `complete -c buddy -n "__fish_use_subcommand" -a "${cmd}" -d "${cmd} command"`).join(`
124
- `)}
125
-
126
- # Global flag completions
127
- complete -c buddy -l help -d "Display help message"
128
- complete -c buddy -l version -d "Display version number"
129
- complete -c buddy -s v -l verbose -d "Enable verbose output"
130
- complete -c buddy -s q -l quiet -d "Suppress non-essential output"
131
- complete -c buddy -l debug -d "Enable debug mode"
132
- complete -c buddy -s n -l no-interaction -d "Do not ask interactive questions"
133
- complete -c buddy -l env -d "Target environment" -r
134
- complete -c buddy -l dry-run -d "Preview actions without executing"
135
- complete -c buddy -s f -l force -d "Skip confirmation prompts"
136
-
137
- # Installation:
138
- # Save this file to:
139
- # ~/.config/fish/completions/buddy.fish
140
- #
141
- # Fish will automatically load it on startup
142
- `;
143
- }