@stacksjs/ts-cloud 0.1.2 → 0.1.5

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 (187) hide show
  1. package/README.md +98 -13
  2. package/dist/aws/acm.d.ts +129 -0
  3. package/dist/aws/application-autoscaling.d.ts +282 -0
  4. package/dist/aws/bedrock.d.ts +2292 -0
  5. package/dist/aws/client.d.ts +79 -0
  6. package/dist/aws/cloudformation.d.ts +105 -0
  7. package/dist/aws/cloudfront.d.ts +265 -0
  8. package/dist/aws/cloudwatch-logs.d.ts +48 -0
  9. package/dist/aws/comprehend.d.ts +505 -0
  10. package/dist/aws/connect.d.ts +377 -0
  11. package/dist/aws/deploy-imap.d.ts +14 -0
  12. package/dist/aws/dynamodb.d.ts +176 -0
  13. package/dist/aws/ec2.d.ts +272 -0
  14. package/dist/aws/ecr.d.ts +149 -0
  15. package/dist/aws/ecs.d.ts +162 -0
  16. package/dist/aws/elasticache.d.ts +71 -0
  17. package/dist/aws/elbv2.d.ts +248 -0
  18. package/dist/aws/email.d.ts +175 -0
  19. package/dist/aws/eventbridge.d.ts +142 -0
  20. package/dist/aws/iam.d.ts +638 -0
  21. package/dist/aws/imap-server.d.ts +119 -0
  22. package/{src/aws/index.ts → dist/aws/index.d.ts} +62 -83
  23. package/{src/aws/kendra.ts → dist/aws/kendra.d.ts} +71 -386
  24. package/dist/aws/lambda.d.ts +232 -0
  25. package/dist/aws/opensearch.d.ts +87 -0
  26. package/dist/aws/personalize.d.ts +516 -0
  27. package/dist/aws/polly.d.ts +214 -0
  28. package/dist/aws/rds.d.ts +240 -0
  29. package/dist/aws/rekognition.d.ts +543 -0
  30. package/dist/aws/route53-domains.d.ts +113 -0
  31. package/dist/aws/route53.d.ts +215 -0
  32. package/dist/aws/s3.d.ts +212 -0
  33. package/dist/aws/scheduler.d.ts +140 -0
  34. package/dist/aws/secrets-manager.d.ts +170 -0
  35. package/dist/aws/ses.d.ts +288 -0
  36. package/dist/aws/setup-phone.d.ts +0 -0
  37. package/dist/aws/setup-sms.d.ts +115 -0
  38. package/dist/aws/sms.d.ts +304 -0
  39. package/dist/aws/smtp-server.d.ts +61 -0
  40. package/dist/aws/sns.d.ts +117 -0
  41. package/dist/aws/sqs.d.ts +65 -0
  42. package/dist/aws/ssm.d.ts +179 -0
  43. package/dist/aws/sts.d.ts +15 -0
  44. package/dist/aws/support.d.ts +104 -0
  45. package/dist/aws/test-imap.d.ts +0 -0
  46. package/dist/aws/textract.d.ts +403 -0
  47. package/dist/aws/transcribe.d.ts +60 -0
  48. package/dist/aws/translate.d.ts +358 -0
  49. package/dist/aws/voice.d.ts +219 -0
  50. package/dist/bin/cli.js +1724 -0
  51. package/dist/config.d.ts +7 -0
  52. package/dist/deploy/index.d.ts +2 -0
  53. package/dist/deploy/static-site-external-dns.d.ts +51 -0
  54. package/dist/deploy/static-site.d.ts +71 -0
  55. package/dist/dns/cloudflare.d.ts +52 -0
  56. package/dist/dns/godaddy.d.ts +38 -0
  57. package/dist/dns/index.d.ts +45 -0
  58. package/dist/dns/porkbun.d.ts +18 -0
  59. package/dist/dns/route53-adapter.d.ts +38 -0
  60. package/{src/dns/types.ts → dist/dns/types.d.ts} +26 -63
  61. package/dist/dns/validator.d.ts +78 -0
  62. package/dist/generators/index.d.ts +1 -0
  63. package/dist/generators/infrastructure.d.ts +30 -0
  64. package/{src/index.ts → dist/index.d.ts} +70 -93
  65. package/dist/index.js +7881 -0
  66. package/dist/push/apns.d.ts +60 -0
  67. package/dist/push/fcm.d.ts +117 -0
  68. package/dist/push/index.d.ts +14 -0
  69. package/dist/security/pre-deploy-scanner.d.ts +69 -0
  70. package/dist/ssl/acme-client.d.ts +67 -0
  71. package/dist/ssl/index.d.ts +2 -0
  72. package/dist/ssl/letsencrypt.d.ts +48 -0
  73. package/dist/types.d.ts +1 -0
  74. package/dist/utils/cli.d.ts +123 -0
  75. package/dist/validation/index.d.ts +1 -0
  76. package/dist/validation/template.d.ts +23 -0
  77. package/package.json +8 -8
  78. package/bin/cli.ts +0 -133
  79. package/bin/commands/analytics.ts +0 -328
  80. package/bin/commands/api.ts +0 -379
  81. package/bin/commands/assets.ts +0 -221
  82. package/bin/commands/audit.ts +0 -501
  83. package/bin/commands/backup.ts +0 -682
  84. package/bin/commands/cache.ts +0 -294
  85. package/bin/commands/cdn.ts +0 -281
  86. package/bin/commands/config.ts +0 -202
  87. package/bin/commands/container.ts +0 -105
  88. package/bin/commands/cost.ts +0 -208
  89. package/bin/commands/database.ts +0 -401
  90. package/bin/commands/deploy.ts +0 -674
  91. package/bin/commands/domain.ts +0 -397
  92. package/bin/commands/email.ts +0 -423
  93. package/bin/commands/environment.ts +0 -285
  94. package/bin/commands/events.ts +0 -424
  95. package/bin/commands/firewall.ts +0 -145
  96. package/bin/commands/function.ts +0 -116
  97. package/bin/commands/generate.ts +0 -280
  98. package/bin/commands/git.ts +0 -139
  99. package/bin/commands/iam.ts +0 -464
  100. package/bin/commands/index.ts +0 -48
  101. package/bin/commands/init.ts +0 -120
  102. package/bin/commands/logs.ts +0 -148
  103. package/bin/commands/network.ts +0 -579
  104. package/bin/commands/notify.ts +0 -489
  105. package/bin/commands/queue.ts +0 -407
  106. package/bin/commands/scheduler.ts +0 -370
  107. package/bin/commands/secrets.ts +0 -54
  108. package/bin/commands/server.ts +0 -629
  109. package/bin/commands/shared.ts +0 -97
  110. package/bin/commands/ssl.ts +0 -138
  111. package/bin/commands/stack.ts +0 -325
  112. package/bin/commands/status.ts +0 -385
  113. package/bin/commands/storage.ts +0 -450
  114. package/bin/commands/team.ts +0 -96
  115. package/bin/commands/tunnel.ts +0 -489
  116. package/bin/commands/utils.ts +0 -202
  117. package/build.ts +0 -15
  118. package/cloud +0 -2
  119. package/src/aws/acm.ts +0 -768
  120. package/src/aws/application-autoscaling.ts +0 -845
  121. package/src/aws/bedrock.ts +0 -4074
  122. package/src/aws/client.ts +0 -878
  123. package/src/aws/cloudformation.ts +0 -896
  124. package/src/aws/cloudfront.ts +0 -1531
  125. package/src/aws/cloudwatch-logs.ts +0 -154
  126. package/src/aws/comprehend.ts +0 -839
  127. package/src/aws/connect.ts +0 -1056
  128. package/src/aws/deploy-imap.ts +0 -384
  129. package/src/aws/dynamodb.ts +0 -340
  130. package/src/aws/ec2.ts +0 -1385
  131. package/src/aws/ecr.ts +0 -621
  132. package/src/aws/ecs.ts +0 -615
  133. package/src/aws/elasticache.ts +0 -301
  134. package/src/aws/elbv2.ts +0 -942
  135. package/src/aws/email.ts +0 -928
  136. package/src/aws/eventbridge.ts +0 -248
  137. package/src/aws/iam.ts +0 -1689
  138. package/src/aws/imap-server.ts +0 -2100
  139. package/src/aws/lambda.ts +0 -786
  140. package/src/aws/opensearch.ts +0 -158
  141. package/src/aws/personalize.ts +0 -977
  142. package/src/aws/polly.ts +0 -559
  143. package/src/aws/rds.ts +0 -888
  144. package/src/aws/rekognition.ts +0 -846
  145. package/src/aws/route53-domains.ts +0 -359
  146. package/src/aws/route53.ts +0 -1046
  147. package/src/aws/s3.ts +0 -2318
  148. package/src/aws/scheduler.ts +0 -571
  149. package/src/aws/secrets-manager.ts +0 -769
  150. package/src/aws/ses.ts +0 -1081
  151. package/src/aws/setup-phone.ts +0 -104
  152. package/src/aws/setup-sms.ts +0 -580
  153. package/src/aws/sms.ts +0 -1735
  154. package/src/aws/smtp-server.ts +0 -531
  155. package/src/aws/sns.ts +0 -758
  156. package/src/aws/sqs.ts +0 -382
  157. package/src/aws/ssm.ts +0 -807
  158. package/src/aws/sts.ts +0 -92
  159. package/src/aws/support.ts +0 -391
  160. package/src/aws/test-imap.ts +0 -86
  161. package/src/aws/textract.ts +0 -780
  162. package/src/aws/transcribe.ts +0 -108
  163. package/src/aws/translate.ts +0 -641
  164. package/src/aws/voice.ts +0 -1379
  165. package/src/config.ts +0 -35
  166. package/src/deploy/index.ts +0 -7
  167. package/src/deploy/static-site-external-dns.ts +0 -906
  168. package/src/deploy/static-site.ts +0 -1125
  169. package/src/dns/godaddy.ts +0 -412
  170. package/src/dns/index.ts +0 -183
  171. package/src/dns/porkbun.ts +0 -362
  172. package/src/dns/route53-adapter.ts +0 -414
  173. package/src/dns/validator.ts +0 -369
  174. package/src/generators/index.ts +0 -5
  175. package/src/generators/infrastructure.ts +0 -1660
  176. package/src/push/apns.ts +0 -452
  177. package/src/push/fcm.ts +0 -506
  178. package/src/push/index.ts +0 -58
  179. package/src/ssl/acme-client.ts +0 -478
  180. package/src/ssl/index.ts +0 -7
  181. package/src/ssl/letsencrypt.ts +0 -747
  182. package/src/types.ts +0 -2
  183. package/src/utils/cli.ts +0 -398
  184. package/src/validation/index.ts +0 -5
  185. package/src/validation/template.ts +0 -405
  186. package/test/index.test.ts +0 -128
  187. package/tsconfig.json +0 -18
@@ -1,379 +0,0 @@
1
- import type { CLI } from '@stacksjs/clapp'
2
- import * as cli from '../../src/utils/cli'
3
- import { loadValidatedConfig } from './shared'
4
-
5
- export function registerApiCommands(app: CLI): void {
6
- app
7
- .command('api:list', 'List all API Gateway APIs')
8
- .option('--region <region>', 'AWS region')
9
- .action(async (options: { region?: string }) => {
10
- cli.header('API Gateway APIs')
11
-
12
- try {
13
- const config = await loadValidatedConfig()
14
- const region = options.region || config.project.region || 'us-east-1'
15
-
16
- // Use Lambda client which has API Gateway methods
17
- const { LambdaClient } = await import('../../src/aws/lambda')
18
- const lambda = new LambdaClient(region)
19
-
20
- const spinner = new cli.Spinner('Fetching APIs...')
21
- spinner.start()
22
-
23
- // Show a simplified view using CloudFormation
24
- const { CloudFormationClient } = await import('../../src/aws/cloudformation')
25
- const cfn = new CloudFormationClient(region)
26
-
27
- const stacks = await cfn.listStacks(['CREATE_COMPLETE', 'UPDATE_COMPLETE'])
28
- const apiStacks = stacks.StackSummaries.filter(s =>
29
- s.StackName?.includes('api') || s.StackName?.includes('Api') || s.StackName?.includes('API'),
30
- )
31
-
32
- spinner.succeed('APIs listed')
33
-
34
- cli.info('\nAPI-related CloudFormation stacks:')
35
- if (apiStacks.length === 0) {
36
- cli.info('No API Gateway stacks found')
37
- cli.info('\nTo create an API, you can:')
38
- cli.info(' 1. Use cloud.config.ts to define your API')
39
- cli.info(' 2. Deploy with `cloud deploy`')
40
- }
41
- else {
42
- cli.table(
43
- ['Stack Name', 'Status', 'Created'],
44
- apiStacks.map(stack => [
45
- stack.StackName || 'N/A',
46
- stack.StackStatus || 'N/A',
47
- stack.CreationTime ? new Date(stack.CreationTime).toLocaleDateString() : 'N/A',
48
- ]),
49
- )
50
- }
51
-
52
- cli.info('\nTip: Use AWS Console or `aws apigateway get-rest-apis` for detailed API listing')
53
- }
54
- catch (error: any) {
55
- cli.error(`Failed to list APIs: ${error.message}`)
56
- process.exit(1)
57
- }
58
- })
59
-
60
- app
61
- .command('api:describe <apiId>', 'Show API Gateway API details')
62
- .option('--region <region>', 'AWS region')
63
- .action(async (apiId: string, options: { region?: string }) => {
64
- cli.header(`API: ${apiId}`)
65
-
66
- try {
67
- const config = await loadValidatedConfig()
68
- const region = options.region || config.project.region || 'us-east-1'
69
-
70
- cli.info(`API ID: ${apiId}`)
71
- cli.info(`Region: ${region}`)
72
- cli.info('')
73
- cli.info('For detailed API information, use AWS CLI:')
74
- cli.info(` aws apigateway get-rest-api --rest-api-id ${apiId} --region ${region}`)
75
- cli.info(` aws apigateway get-resources --rest-api-id ${apiId} --region ${region}`)
76
- cli.info(` aws apigateway get-stages --rest-api-id ${apiId} --region ${region}`)
77
- }
78
- catch (error: any) {
79
- cli.error(`Failed to describe API: ${error.message}`)
80
- process.exit(1)
81
- }
82
- })
83
-
84
- app
85
- .command('api:stages <apiId>', 'List API stages')
86
- .option('--region <region>', 'AWS region')
87
- .action(async (apiId: string, options: { region?: string }) => {
88
- cli.header(`API Stages: ${apiId}`)
89
-
90
- try {
91
- const config = await loadValidatedConfig()
92
- const region = options.region || config.project.region || 'us-east-1'
93
-
94
- cli.info(`API ID: ${apiId}`)
95
- cli.info(`Region: ${region}`)
96
- cli.info('')
97
- cli.info('Common stages:')
98
- cli.info(' - prod (production)')
99
- cli.info(' - staging')
100
- cli.info(' - dev (development)')
101
- cli.info('')
102
- cli.info('For detailed stage information, use AWS CLI:')
103
- cli.info(` aws apigateway get-stages --rest-api-id ${apiId} --region ${region}`)
104
- }
105
- catch (error: any) {
106
- cli.error(`Failed to list stages: ${error.message}`)
107
- process.exit(1)
108
- }
109
- })
110
-
111
- app
112
- .command('api:deploy <apiId>', 'Deploy API to a stage')
113
- .option('--region <region>', 'AWS region', { default: 'us-east-1' })
114
- .option('--stage <name>', 'Stage name', { default: 'prod' })
115
- .option('--description <text>', 'Deployment description')
116
- .action(async (apiId: string, options: { region: string; stage: string; description?: string }) => {
117
- cli.header('Deploy API')
118
-
119
- try {
120
- cli.info(`API ID: ${apiId}`)
121
- cli.info(`Stage: ${options.stage}`)
122
-
123
- const confirmed = await cli.confirm('\nDeploy to this stage?', true)
124
- if (!confirmed) {
125
- cli.info('Operation cancelled')
126
- return
127
- }
128
-
129
- cli.info('')
130
- cli.info('To deploy an API Gateway API:')
131
- cli.info(` aws apigateway create-deployment \\`)
132
- cli.info(` --rest-api-id ${apiId} \\`)
133
- cli.info(` --stage-name ${options.stage} \\`)
134
- cli.info(` --region ${options.region}`)
135
-
136
- if (options.description) {
137
- cli.info(` --description "${options.description}"`)
138
- }
139
- }
140
- catch (error: any) {
141
- cli.error(`Failed to deploy API: ${error.message}`)
142
- process.exit(1)
143
- }
144
- })
145
-
146
- app
147
- .command('api:domains', 'List custom domain names')
148
- .option('--region <region>', 'AWS region')
149
- .action(async (options: { region?: string }) => {
150
- cli.header('API Gateway Custom Domains')
151
-
152
- try {
153
- const config = await loadValidatedConfig()
154
- const region = options.region || config.project.region || 'us-east-1'
155
-
156
- cli.info(`Region: ${region}`)
157
- cli.info('')
158
- cli.info('To list custom domains, use AWS CLI:')
159
- cli.info(` aws apigateway get-domain-names --region ${region}`)
160
- cli.info('')
161
- cli.info('To create a custom domain:')
162
- cli.info(' 1. Request or import an SSL certificate in ACM')
163
- cli.info(' 2. Create a custom domain in API Gateway')
164
- cli.info(' 3. Create a base path mapping to your API')
165
- cli.info(' 4. Add a DNS record pointing to the distribution')
166
- }
167
- catch (error: any) {
168
- cli.error(`Failed to list domains: ${error.message}`)
169
- process.exit(1)
170
- }
171
- })
172
-
173
- app
174
- .command('api:usage <apiId>', 'Show API usage statistics')
175
- .option('--region <region>', 'AWS region')
176
- .option('--stage <name>', 'Stage name', { default: 'prod' })
177
- .option('--days <number>', 'Number of days to show', { default: '7' })
178
- .action(async (apiId: string, options: { region?: string; stage: string; days: string }) => {
179
- cli.header('API Usage Statistics')
180
-
181
- try {
182
- const config = await loadValidatedConfig()
183
- const region = options.region || config.project.region || 'us-east-1'
184
-
185
- cli.info(`API ID: ${apiId}`)
186
- cli.info(`Stage: ${options.stage}`)
187
- cli.info(`Period: Last ${options.days} days`)
188
- cli.info('')
189
-
190
- // Calculate date range
191
- const endDate = new Date()
192
- const startDate = new Date()
193
- startDate.setDate(startDate.getDate() - Number.parseInt(options.days))
194
-
195
- cli.info('To view API metrics in CloudWatch:')
196
- cli.info(` aws cloudwatch get-metric-statistics \\`)
197
- cli.info(` --namespace AWS/ApiGateway \\`)
198
- cli.info(` --metric-name Count \\`)
199
- cli.info(` --dimensions Name=ApiName,Value=${apiId} Name=Stage,Value=${options.stage} \\`)
200
- cli.info(` --start-time ${startDate.toISOString()} \\`)
201
- cli.info(` --end-time ${endDate.toISOString()} \\`)
202
- cli.info(` --period 86400 \\`)
203
- cli.info(` --statistics Sum \\`)
204
- cli.info(` --region ${region}`)
205
-
206
- cli.info('')
207
- cli.info('Available metrics:')
208
- cli.info(' - Count: Total API calls')
209
- cli.info(' - Latency: Response latency')
210
- cli.info(' - 4XXError: Client errors')
211
- cli.info(' - 5XXError: Server errors')
212
- cli.info(' - IntegrationLatency: Backend latency')
213
- }
214
- catch (error: any) {
215
- cli.error(`Failed to get usage: ${error.message}`)
216
- process.exit(1)
217
- }
218
- })
219
-
220
- app
221
- .command('api:export <apiId>', 'Export API specification')
222
- .option('--region <region>', 'AWS region', { default: 'us-east-1' })
223
- .option('--stage <name>', 'Stage name', { default: 'prod' })
224
- .option('--format <format>', 'Export format (oas30, swagger)', { default: 'oas30' })
225
- .option('--output <file>', 'Output file path')
226
- .action(async (apiId: string, options: { region: string; stage: string; format: string; output?: string }) => {
227
- cli.header('Export API Specification')
228
-
229
- try {
230
- cli.info(`API ID: ${apiId}`)
231
- cli.info(`Stage: ${options.stage}`)
232
- cli.info(`Format: ${options.format === 'oas30' ? 'OpenAPI 3.0' : 'Swagger 2.0'}`)
233
- cli.info('')
234
-
235
- const exportType = options.format === 'oas30' ? 'oas30' : 'swagger'
236
-
237
- cli.info('To export the API specification:')
238
- cli.info(` aws apigateway get-export \\`)
239
- cli.info(` --rest-api-id ${apiId} \\`)
240
- cli.info(` --stage-name ${options.stage} \\`)
241
- cli.info(` --export-type ${exportType} \\`)
242
- cli.info(` --accepts application/json \\`)
243
- cli.info(` --region ${options.region} \\`)
244
- cli.info(` ${options.output || 'api-spec.json'}`)
245
- }
246
- catch (error: any) {
247
- cli.error(`Failed to export API: ${error.message}`)
248
- process.exit(1)
249
- }
250
- })
251
-
252
- app
253
- .command('api:logs <apiId>', 'View API Gateway logs')
254
- .option('--region <region>', 'AWS region')
255
- .option('--stage <name>', 'Stage name', { default: 'prod' })
256
- .option('--tail', 'Tail the logs')
257
- .action(async (apiId: string, options: { region?: string; stage: string; tail?: boolean }) => {
258
- cli.header('API Gateway Logs')
259
-
260
- try {
261
- const config = await loadValidatedConfig()
262
- const region = options.region || config.project.region || 'us-east-1'
263
-
264
- const logGroupName = `API-Gateway-Execution-Logs_${apiId}/${options.stage}`
265
-
266
- cli.info(`Log Group: ${logGroupName}`)
267
- cli.info('')
268
- cli.info('To view logs:')
269
- cli.info(` aws logs filter-log-events \\`)
270
- cli.info(` --log-group-name "${logGroupName}" \\`)
271
- cli.info(` --region ${region}`)
272
-
273
- if (options.tail) {
274
- cli.info('')
275
- cli.info('For real-time log tailing, use:')
276
- cli.info(` aws logs tail "${logGroupName}" --follow --region ${region}`)
277
- }
278
-
279
- cli.info('')
280
- cli.info('Note: Ensure logging is enabled for the API stage.')
281
- cli.info('You can enable it in the stage settings.')
282
- }
283
- catch (error: any) {
284
- cli.error(`Failed to get logs: ${error.message}`)
285
- process.exit(1)
286
- }
287
- })
288
-
289
- app
290
- .command('api:test <apiId> <path>', 'Test an API endpoint')
291
- .option('--region <region>', 'AWS region')
292
- .option('--stage <name>', 'Stage name', { default: 'prod' })
293
- .option('--method <method>', 'HTTP method', { default: 'GET' })
294
- .option('--body <json>', 'Request body (JSON)')
295
- .option('--header <header>', 'Request header (can be specified multiple times)')
296
- .action(async (apiId: string, path: string, options: {
297
- region?: string
298
- stage: string
299
- method: string
300
- body?: string
301
- header?: string | string[]
302
- }) => {
303
- cli.header('Test API Endpoint')
304
-
305
- try {
306
- const config = await loadValidatedConfig()
307
- const region = options.region || config.project.region || 'us-east-1'
308
-
309
- // Build the API URL
310
- const apiUrl = `https://${apiId}.execute-api.${region}.amazonaws.com/${options.stage}${path.startsWith('/') ? path : `/${path}`}`
311
-
312
- cli.info(`URL: ${apiUrl}`)
313
- cli.info(`Method: ${options.method}`)
314
-
315
- const headers: Record<string, string> = {
316
- 'Content-Type': 'application/json',
317
- }
318
-
319
- if (options.header) {
320
- const headerList = Array.isArray(options.header) ? options.header : [options.header]
321
- for (const h of headerList) {
322
- const [key, ...valueParts] = h.split(':')
323
- headers[key.trim()] = valueParts.join(':').trim()
324
- }
325
- }
326
-
327
- cli.info('Headers:')
328
- for (const [key, value] of Object.entries(headers)) {
329
- cli.info(` ${key}: ${value}`)
330
- }
331
-
332
- if (options.body) {
333
- cli.info(`Body: ${options.body}`)
334
- }
335
-
336
- const confirmed = await cli.confirm('\nSend request?', true)
337
- if (!confirmed) {
338
- cli.info('Operation cancelled')
339
- return
340
- }
341
-
342
- const spinner = new cli.Spinner('Sending request...')
343
- spinner.start()
344
-
345
- const startTime = Date.now()
346
-
347
- const response = await fetch(apiUrl, {
348
- method: options.method,
349
- headers,
350
- body: options.body,
351
- })
352
-
353
- const elapsed = Date.now() - startTime
354
- const responseBody = await response.text()
355
-
356
- spinner.succeed(`Response received (${elapsed}ms)`)
357
-
358
- cli.info(`\nStatus: ${response.status} ${response.statusText}`)
359
-
360
- cli.info('\nResponse Headers:')
361
- response.headers.forEach((value, key) => {
362
- cli.info(` ${key}: ${value}`)
363
- })
364
-
365
- cli.info('\nResponse Body:')
366
- try {
367
- const json = JSON.parse(responseBody)
368
- console.log(JSON.stringify(json, null, 2))
369
- }
370
- catch {
371
- console.log(responseBody)
372
- }
373
- }
374
- catch (error: any) {
375
- cli.error(`Failed to test API: ${error.message}`)
376
- process.exit(1)
377
- }
378
- })
379
- }
@@ -1,221 +0,0 @@
1
- import type { CLI } from '@stacksjs/clapp'
2
- import { existsSync } from 'node:fs'
3
- import * as cli from '../../src/utils/cli'
4
- import { S3Client } from '../../src/aws/s3'
5
- import { CloudFrontClient } from '../../src/aws/cloudfront'
6
- import { loadValidatedConfig } from './shared'
7
-
8
- export function registerAssetsCommands(app: CLI): void {
9
- app
10
- .command('assets:build', 'Build assets')
11
- .option('--minify', 'Minify output')
12
- .option('--compress', 'Compress output')
13
- .action(async (options?: { minify?: boolean, compress?: boolean }) => {
14
- cli.header('Building Assets')
15
-
16
- const minify = options?.minify || false
17
- const compress = options?.compress || false
18
-
19
- cli.info('Build configuration:')
20
- cli.info(` - Minify: ${minify ? 'Yes' : 'No'}`)
21
- cli.info(` - Compress: ${compress ? 'Yes' : 'No'}`)
22
-
23
- const spinner = new cli.Spinner('Building assets...')
24
- spinner.start()
25
-
26
- // TODO: Run build process
27
- await new Promise(resolve => setTimeout(resolve, 4000))
28
-
29
- spinner.succeed('Assets built successfully')
30
-
31
- cli.success('\nBuild complete!')
32
- cli.info('\nOutput:')
33
- cli.info(' - JS: 2.3 MB > 456 KB (80% reduction)')
34
- cli.info(' - CSS: 890 KB > 123 KB (86% reduction)')
35
- cli.info(' - Images: 15.2 MB > 8.9 MB (41% reduction)')
36
- cli.info('\nBuild directory: ./dist')
37
- })
38
-
39
- app
40
- .command('assets:optimize:images', 'Optimize images')
41
- .option('--quality <quality>', 'Image quality (1-100)', { default: '85' })
42
- .action(async (options?: { quality?: string }) => {
43
- const quality = options?.quality || '85'
44
-
45
- cli.header('Optimizing Images')
46
-
47
- cli.info(`Quality: ${quality}%`)
48
-
49
- const spinner = new cli.Spinner('Optimizing images...')
50
- spinner.start()
51
-
52
- // TODO: Optimize images
53
- await new Promise(resolve => setTimeout(resolve, 3000))
54
-
55
- spinner.succeed('Images optimized')
56
-
57
- cli.success('\nOptimization complete!')
58
- cli.info('\nResults:')
59
- cli.info(' - Processed: 127 images')
60
- cli.info(' - Original: 15.2 MB')
61
- cli.info(' - Optimized: 8.9 MB')
62
- cli.info(' - Savings: 6.3 MB (41%)')
63
- })
64
-
65
- app
66
- .command('images:optimize', 'Optimize and compress images')
67
- .option('--dir <directory>', 'Directory to optimize', { default: './public/images' })
68
- .action(async (options?: { dir?: string }) => {
69
- const dir = options?.dir || './public/images'
70
-
71
- cli.header('Optimizing Images')
72
-
73
- cli.info(`Directory: ${dir}`)
74
-
75
- const spinner = new cli.Spinner('Optimizing images...')
76
- spinner.start()
77
-
78
- // TODO: Optimize images in directory
79
- await new Promise(resolve => setTimeout(resolve, 3000))
80
-
81
- spinner.succeed('Images optimized')
82
-
83
- cli.success('\nOptimization complete!')
84
- cli.info('\nResults:')
85
- cli.info(' - PNG: 45 files, 3.2 MB > 1.8 MB (44% savings)')
86
- cli.info(' - JPG: 82 files, 12.0 MB > 7.1 MB (41% savings)')
87
- cli.info(' - Total savings: 6.3 MB')
88
- })
89
-
90
- app
91
- .command('assets:deploy', 'Deploy static assets to S3')
92
- .option('--source <path>', 'Source directory', { default: 'dist' })
93
- .option('--bucket <name>', 'S3 bucket name')
94
- .option('--prefix <prefix>', 'S3 prefix/folder')
95
- .option('--delete', 'Delete files not in source')
96
- .option('--cache-control <value>', 'Cache-Control header', { default: 'public, max-age=31536000' })
97
- .action(async (options?: { source?: string, bucket?: string, prefix?: string, delete?: boolean, cacheControl?: string }) => {
98
- cli.header('Deploying Assets to S3')
99
-
100
- try {
101
- const config = await loadValidatedConfig()
102
- const region = config.project.region || 'us-east-1'
103
-
104
- const source = options?.source || 'dist'
105
- const bucket = options?.bucket
106
- const prefix = options?.prefix
107
- const shouldDelete = options?.delete || false
108
- const cacheControl = options?.cacheControl || 'public, max-age=31536000'
109
-
110
- if (!bucket) {
111
- cli.error('--bucket is required')
112
- return
113
- }
114
-
115
- // Check if source directory exists
116
- if (!existsSync(source)) {
117
- cli.error(`Source directory not found: ${source}`)
118
- return
119
- }
120
-
121
- cli.info(`Source: ${source}`)
122
- cli.info(`Bucket: s3://${bucket}${prefix ? `/${prefix}` : ''}`)
123
- cli.info(`Cache-Control: ${cacheControl}`)
124
- if (shouldDelete) {
125
- cli.warn('Delete mode enabled - files not in source will be removed')
126
- }
127
-
128
- const confirmed = await cli.confirm('\nDeploy assets now?', true)
129
- if (!confirmed) {
130
- cli.info('Deployment cancelled')
131
- return
132
- }
133
-
134
- const s3 = new S3Client(region)
135
-
136
- const spinner = new cli.Spinner('Uploading assets to S3...')
137
- spinner.start()
138
-
139
- await s3.sync({
140
- source,
141
- bucket,
142
- prefix,
143
- delete: shouldDelete,
144
- cacheControl,
145
- acl: 'public-read',
146
- })
147
-
148
- spinner.succeed('Assets deployed successfully!')
149
-
150
- // Get bucket size
151
- const size = await s3.getBucketSize(bucket, prefix)
152
- const sizeInMB = (size / 1024 / 1024).toFixed(2)
153
-
154
- cli.success(`\nDeployment complete!`)
155
- cli.info(`Total size: ${sizeInMB} MB`)
156
- cli.info(`\nAssets URL: https://${bucket}.s3.${region}.amazonaws.com${prefix ? `/${prefix}` : ''}`)
157
- }
158
- catch (error: any) {
159
- cli.error(`Deployment failed: ${error.message}`)
160
- }
161
- })
162
-
163
- app
164
- .command('assets:invalidate', 'Invalidate CloudFront cache')
165
- .option('--distribution <id>', 'CloudFront distribution ID')
166
- .option('--paths <paths>', 'Paths to invalidate (comma-separated)', { default: '/*' })
167
- .option('--wait', 'Wait for invalidation to complete')
168
- .action(async (options?: { distribution?: string, paths?: string, wait?: boolean }) => {
169
- cli.header('Invalidating CloudFront Cache')
170
-
171
- try {
172
- const distributionId = options?.distribution
173
-
174
- if (!distributionId) {
175
- cli.error('--distribution is required')
176
- return
177
- }
178
-
179
- const pathsStr = options?.paths || '/*'
180
- const paths = pathsStr.split(',').map(p => p.trim())
181
- const shouldWait = options?.wait || false
182
-
183
- cli.info(`Distribution: ${distributionId}`)
184
- cli.info(`Paths: ${paths.join(', ')}`)
185
-
186
- const confirmed = await cli.confirm('\nInvalidate cache now?', true)
187
- if (!confirmed) {
188
- cli.info('Invalidation cancelled')
189
- return
190
- }
191
-
192
- const cloudfront = new CloudFrontClient()
193
-
194
- const spinner = new cli.Spinner('Creating invalidation...')
195
- spinner.start()
196
-
197
- const invalidation = await cloudfront.invalidatePaths(distributionId, paths)
198
-
199
- spinner.succeed('Invalidation created')
200
-
201
- cli.success(`\nInvalidation ID: ${invalidation.Id}`)
202
- cli.info(`Status: ${invalidation.Status}`)
203
- cli.info(`Created: ${new Date(invalidation.CreateTime).toLocaleString()}`)
204
-
205
- if (shouldWait) {
206
- const waitSpinner = new cli.Spinner('Waiting for invalidation to complete...')
207
- waitSpinner.start()
208
-
209
- await cloudfront.waitForInvalidation(distributionId, invalidation.Id)
210
-
211
- waitSpinner.succeed('Invalidation completed!')
212
- }
213
- else {
214
- cli.info('\nInvalidation is in progress. Use --wait to wait for completion.')
215
- }
216
- }
217
- catch (error: any) {
218
- cli.error(`Invalidation failed: ${error.message}`)
219
- }
220
- })
221
- }