@stacksjs/ts-cloud 0.1.3 → 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
package/src/aws/elbv2.ts DELETED
@@ -1,942 +0,0 @@
1
- /**
2
- * AWS Elastic Load Balancing V2 (ELBv2) Operations
3
- * Direct API calls without AWS CLI dependency
4
- *
5
- * Supports Application Load Balancers (ALB), Network Load Balancers (NLB),
6
- * and Gateway Load Balancers (GWLB)
7
- */
8
-
9
- import { AWSClient } from './client'
10
-
11
- export interface LoadBalancer {
12
- LoadBalancerArn?: string
13
- DNSName?: string
14
- CanonicalHostedZoneId?: string
15
- CreatedTime?: string
16
- LoadBalancerName?: string
17
- Scheme?: 'internet-facing' | 'internal'
18
- VpcId?: string
19
- State?: {
20
- Code?: 'active' | 'provisioning' | 'active_impaired' | 'failed'
21
- Reason?: string
22
- }
23
- Type?: 'application' | 'network' | 'gateway'
24
- AvailabilityZones?: AvailabilityZone[]
25
- SecurityGroups?: string[]
26
- IpAddressType?: 'ipv4' | 'dualstack'
27
- }
28
-
29
- export interface AvailabilityZone {
30
- ZoneName?: string
31
- SubnetId?: string
32
- OutpostId?: string
33
- LoadBalancerAddresses?: LoadBalancerAddress[]
34
- }
35
-
36
- export interface LoadBalancerAddress {
37
- IpAddress?: string
38
- AllocationId?: string
39
- PrivateIPv4Address?: string
40
- IPv6Address?: string
41
- }
42
-
43
- export interface TargetGroup {
44
- TargetGroupArn?: string
45
- TargetGroupName?: string
46
- Protocol?: string
47
- Port?: number
48
- VpcId?: string
49
- HealthCheckProtocol?: string
50
- HealthCheckPort?: string
51
- HealthCheckEnabled?: boolean
52
- HealthCheckIntervalSeconds?: number
53
- HealthCheckTimeoutSeconds?: number
54
- HealthyThresholdCount?: number
55
- UnhealthyThresholdCount?: number
56
- HealthCheckPath?: string
57
- Matcher?: {
58
- HttpCode?: string
59
- GrpcCode?: string
60
- }
61
- LoadBalancerArns?: string[]
62
- TargetType?: 'instance' | 'ip' | 'lambda' | 'alb'
63
- ProtocolVersion?: string
64
- IpAddressType?: 'ipv4' | 'ipv6'
65
- }
66
-
67
- export interface Listener {
68
- ListenerArn?: string
69
- LoadBalancerArn?: string
70
- Port?: number
71
- Protocol?: string
72
- Certificates?: Certificate[]
73
- SslPolicy?: string
74
- DefaultActions?: Action[]
75
- AlpnPolicy?: string[]
76
- }
77
-
78
- export interface Certificate {
79
- CertificateArn?: string
80
- IsDefault?: boolean
81
- }
82
-
83
- export interface Action {
84
- Type?: 'forward' | 'redirect' | 'fixed-response' | 'authenticate-oidc' | 'authenticate-cognito'
85
- TargetGroupArn?: string
86
- Order?: number
87
- RedirectConfig?: {
88
- Protocol?: string
89
- Port?: string
90
- Host?: string
91
- Path?: string
92
- Query?: string
93
- StatusCode?: 'HTTP_301' | 'HTTP_302'
94
- }
95
- FixedResponseConfig?: {
96
- MessageBody?: string
97
- StatusCode?: string
98
- ContentType?: string
99
- }
100
- ForwardConfig?: {
101
- TargetGroups?: Array<{
102
- TargetGroupArn?: string
103
- Weight?: number
104
- }>
105
- TargetGroupStickinessConfig?: {
106
- Enabled?: boolean
107
- DurationSeconds?: number
108
- }
109
- }
110
- }
111
-
112
- export interface Rule {
113
- RuleArn?: string
114
- Priority?: string
115
- Conditions?: Condition[]
116
- Actions?: Action[]
117
- IsDefault?: boolean
118
- }
119
-
120
- export interface Condition {
121
- Field?: string
122
- Values?: string[]
123
- HostHeaderConfig?: { Values?: string[] }
124
- PathPatternConfig?: { Values?: string[] }
125
- HttpHeaderConfig?: { HttpHeaderName?: string, Values?: string[] }
126
- QueryStringConfig?: { Values?: Array<{ Key?: string, Value?: string }> }
127
- HttpRequestMethodConfig?: { Values?: string[] }
128
- SourceIpConfig?: { Values?: string[] }
129
- }
130
-
131
- export interface TargetHealthDescription {
132
- Target?: {
133
- Id?: string
134
- Port?: number
135
- AvailabilityZone?: string
136
- }
137
- HealthCheckPort?: string
138
- TargetHealth?: {
139
- State?: 'initial' | 'healthy' | 'unhealthy' | 'unused' | 'draining' | 'unavailable'
140
- Reason?: string
141
- Description?: string
142
- }
143
- }
144
-
145
- /**
146
- * ELBv2 client for managing Application, Network, and Gateway Load Balancers
147
- */
148
- export class ELBv2Client {
149
- private client: AWSClient
150
- private region: string
151
-
152
- constructor(region: string = 'us-east-1') {
153
- this.region = region
154
- this.client = new AWSClient()
155
- }
156
-
157
- /**
158
- * Describe load balancers
159
- */
160
- async describeLoadBalancers(options?: {
161
- LoadBalancerArns?: string[]
162
- Names?: string[]
163
- Marker?: string
164
- PageSize?: number
165
- }): Promise<{ LoadBalancers?: LoadBalancer[], NextMarker?: string }> {
166
- const params: Record<string, any> = {}
167
-
168
- if (options?.LoadBalancerArns) {
169
- options.LoadBalancerArns.forEach((arn, index) => {
170
- params[`LoadBalancerArns.member.${index + 1}`] = arn
171
- })
172
- }
173
-
174
- if (options?.Names) {
175
- options.Names.forEach((name, index) => {
176
- params[`Names.member.${index + 1}`] = name
177
- })
178
- }
179
-
180
- if (options?.Marker) {
181
- params.Marker = options.Marker
182
- }
183
-
184
- if (options?.PageSize) {
185
- params.PageSize = options.PageSize
186
- }
187
-
188
- const result = await this.client.request({
189
- service: 'elasticloadbalancing',
190
- region: this.region,
191
- method: 'POST',
192
- path: '/',
193
- headers: {
194
- 'Content-Type': 'application/x-www-form-urlencoded',
195
- },
196
- body: this.buildFormBody('DescribeLoadBalancers', params),
197
- })
198
-
199
- return this.normalizeResult(result, 'DescribeLoadBalancersResult')
200
- }
201
-
202
- /**
203
- * Describe target groups
204
- */
205
- async describeTargetGroups(options?: {
206
- LoadBalancerArn?: string
207
- TargetGroupArns?: string[]
208
- Names?: string[]
209
- Marker?: string
210
- PageSize?: number
211
- }): Promise<{ TargetGroups?: TargetGroup[], NextMarker?: string }> {
212
- const params: Record<string, any> = {}
213
-
214
- if (options?.LoadBalancerArn) {
215
- params.LoadBalancerArn = options.LoadBalancerArn
216
- }
217
-
218
- if (options?.TargetGroupArns) {
219
- options.TargetGroupArns.forEach((arn, index) => {
220
- params[`TargetGroupArns.member.${index + 1}`] = arn
221
- })
222
- }
223
-
224
- if (options?.Names) {
225
- options.Names.forEach((name, index) => {
226
- params[`Names.member.${index + 1}`] = name
227
- })
228
- }
229
-
230
- if (options?.Marker) {
231
- params.Marker = options.Marker
232
- }
233
-
234
- if (options?.PageSize) {
235
- params.PageSize = options.PageSize
236
- }
237
-
238
- const result = await this.client.request({
239
- service: 'elasticloadbalancing',
240
- region: this.region,
241
- method: 'POST',
242
- path: '/',
243
- headers: {
244
- 'Content-Type': 'application/x-www-form-urlencoded',
245
- },
246
- body: this.buildFormBody('DescribeTargetGroups', params),
247
- })
248
-
249
- return this.normalizeResult(result, 'DescribeTargetGroupsResult')
250
- }
251
-
252
- /**
253
- * Describe target health
254
- */
255
- async describeTargetHealth(options: {
256
- TargetGroupArn: string
257
- Targets?: Array<{ Id: string, Port?: number, AvailabilityZone?: string }>
258
- }): Promise<{ TargetHealthDescriptions?: TargetHealthDescription[] }> {
259
- const params: Record<string, any> = {
260
- TargetGroupArn: options.TargetGroupArn,
261
- }
262
-
263
- if (options.Targets) {
264
- options.Targets.forEach((target, index) => {
265
- params[`Targets.member.${index + 1}.Id`] = target.Id
266
- if (target.Port) {
267
- params[`Targets.member.${index + 1}.Port`] = target.Port
268
- }
269
- if (target.AvailabilityZone) {
270
- params[`Targets.member.${index + 1}.AvailabilityZone`] = target.AvailabilityZone
271
- }
272
- })
273
- }
274
-
275
- const result = await this.client.request({
276
- service: 'elasticloadbalancing',
277
- region: this.region,
278
- method: 'POST',
279
- path: '/',
280
- headers: {
281
- 'Content-Type': 'application/x-www-form-urlencoded',
282
- },
283
- body: this.buildFormBody('DescribeTargetHealth', params),
284
- })
285
-
286
- return this.normalizeResult(result, 'DescribeTargetHealthResult')
287
- }
288
-
289
- /**
290
- * Describe listeners
291
- */
292
- async describeListeners(options?: {
293
- LoadBalancerArn?: string
294
- ListenerArns?: string[]
295
- Marker?: string
296
- PageSize?: number
297
- }): Promise<{ Listeners?: Listener[], NextMarker?: string }> {
298
- const params: Record<string, any> = {}
299
-
300
- if (options?.LoadBalancerArn) {
301
- params.LoadBalancerArn = options.LoadBalancerArn
302
- }
303
-
304
- if (options?.ListenerArns) {
305
- options.ListenerArns.forEach((arn, index) => {
306
- params[`ListenerArns.member.${index + 1}`] = arn
307
- })
308
- }
309
-
310
- if (options?.Marker) {
311
- params.Marker = options.Marker
312
- }
313
-
314
- if (options?.PageSize) {
315
- params.PageSize = options.PageSize
316
- }
317
-
318
- const result = await this.client.request({
319
- service: 'elasticloadbalancing',
320
- region: this.region,
321
- method: 'POST',
322
- path: '/',
323
- headers: {
324
- 'Content-Type': 'application/x-www-form-urlencoded',
325
- },
326
- body: this.buildFormBody('DescribeListeners', params),
327
- })
328
-
329
- return this.normalizeResult(result, 'DescribeListenersResult')
330
- }
331
-
332
- /**
333
- * Describe rules for a listener
334
- */
335
- async describeRules(options?: {
336
- ListenerArn?: string
337
- RuleArns?: string[]
338
- Marker?: string
339
- PageSize?: number
340
- }): Promise<{ Rules?: Rule[], NextMarker?: string }> {
341
- const params: Record<string, any> = {}
342
-
343
- if (options?.ListenerArn) {
344
- params.ListenerArn = options.ListenerArn
345
- }
346
-
347
- if (options?.RuleArns) {
348
- options.RuleArns.forEach((arn, index) => {
349
- params[`RuleArns.member.${index + 1}`] = arn
350
- })
351
- }
352
-
353
- if (options?.Marker) {
354
- params.Marker = options.Marker
355
- }
356
-
357
- if (options?.PageSize) {
358
- params.PageSize = options.PageSize
359
- }
360
-
361
- const result = await this.client.request({
362
- service: 'elasticloadbalancing',
363
- region: this.region,
364
- method: 'POST',
365
- path: '/',
366
- headers: {
367
- 'Content-Type': 'application/x-www-form-urlencoded',
368
- },
369
- body: this.buildFormBody('DescribeRules', params),
370
- })
371
-
372
- return this.normalizeResult(result, 'DescribeRulesResult')
373
- }
374
-
375
- /**
376
- * Describe load balancer attributes
377
- */
378
- async describeLoadBalancerAttributes(loadBalancerArn: string): Promise<{ Attributes?: Array<{ Key: string, Value: string }> }> {
379
- const params = {
380
- LoadBalancerArn: loadBalancerArn,
381
- }
382
-
383
- const result = await this.client.request({
384
- service: 'elasticloadbalancing',
385
- region: this.region,
386
- method: 'POST',
387
- path: '/',
388
- headers: {
389
- 'Content-Type': 'application/x-www-form-urlencoded',
390
- },
391
- body: this.buildFormBody('DescribeLoadBalancerAttributes', params),
392
- })
393
-
394
- return this.normalizeResult(result, 'DescribeLoadBalancerAttributesResult')
395
- }
396
-
397
- /**
398
- * Describe target group attributes
399
- */
400
- async describeTargetGroupAttributes(targetGroupArn: string): Promise<{ Attributes?: Array<{ Key: string, Value: string }> }> {
401
- const params = {
402
- TargetGroupArn: targetGroupArn,
403
- }
404
-
405
- const result = await this.client.request({
406
- service: 'elasticloadbalancing',
407
- region: this.region,
408
- method: 'POST',
409
- path: '/',
410
- headers: {
411
- 'Content-Type': 'application/x-www-form-urlencoded',
412
- },
413
- body: this.buildFormBody('DescribeTargetGroupAttributes', params),
414
- })
415
-
416
- return this.normalizeResult(result, 'DescribeTargetGroupAttributesResult')
417
- }
418
-
419
- /**
420
- * Create a load balancer
421
- */
422
- async createLoadBalancer(options: {
423
- Name: string
424
- Subnets?: string[]
425
- SubnetMappings?: Array<{
426
- SubnetId: string
427
- AllocationId?: string
428
- PrivateIPv4Address?: string
429
- IPv6Address?: string
430
- }>
431
- SecurityGroups?: string[]
432
- Scheme?: 'internet-facing' | 'internal'
433
- Type?: 'application' | 'network' | 'gateway'
434
- IpAddressType?: 'ipv4' | 'dualstack'
435
- Tags?: Array<{ Key: string, Value: string }>
436
- }): Promise<{ LoadBalancers?: LoadBalancer[] }> {
437
- const params: Record<string, any> = {
438
- Name: options.Name,
439
- }
440
-
441
- if (options.Subnets) {
442
- options.Subnets.forEach((subnet, index) => {
443
- params[`Subnets.member.${index + 1}`] = subnet
444
- })
445
- }
446
-
447
- if (options.SubnetMappings) {
448
- options.SubnetMappings.forEach((mapping, index) => {
449
- params[`SubnetMappings.member.${index + 1}.SubnetId`] = mapping.SubnetId
450
- if (mapping.AllocationId) {
451
- params[`SubnetMappings.member.${index + 1}.AllocationId`] = mapping.AllocationId
452
- }
453
- if (mapping.PrivateIPv4Address) {
454
- params[`SubnetMappings.member.${index + 1}.PrivateIPv4Address`] = mapping.PrivateIPv4Address
455
- }
456
- if (mapping.IPv6Address) {
457
- params[`SubnetMappings.member.${index + 1}.IPv6Address`] = mapping.IPv6Address
458
- }
459
- })
460
- }
461
-
462
- if (options.SecurityGroups) {
463
- options.SecurityGroups.forEach((sg, index) => {
464
- params[`SecurityGroups.member.${index + 1}`] = sg
465
- })
466
- }
467
-
468
- if (options.Scheme) {
469
- params.Scheme = options.Scheme
470
- }
471
-
472
- if (options.Type) {
473
- params.Type = options.Type
474
- }
475
-
476
- if (options.IpAddressType) {
477
- params.IpAddressType = options.IpAddressType
478
- }
479
-
480
- if (options.Tags) {
481
- options.Tags.forEach((tag, index) => {
482
- params[`Tags.member.${index + 1}.Key`] = tag.Key
483
- params[`Tags.member.${index + 1}.Value`] = tag.Value
484
- })
485
- }
486
-
487
- const result = await this.client.request({
488
- service: 'elasticloadbalancing',
489
- region: this.region,
490
- method: 'POST',
491
- path: '/',
492
- headers: {
493
- 'Content-Type': 'application/x-www-form-urlencoded',
494
- },
495
- body: this.buildFormBody('CreateLoadBalancer', params),
496
- })
497
-
498
- return this.normalizeResult(result, 'CreateLoadBalancerResult')
499
- }
500
-
501
- /**
502
- * Delete a load balancer
503
- */
504
- async deleteLoadBalancer(loadBalancerArn: string): Promise<void> {
505
- const params = {
506
- LoadBalancerArn: loadBalancerArn,
507
- }
508
-
509
- await this.client.request({
510
- service: 'elasticloadbalancing',
511
- region: this.region,
512
- method: 'POST',
513
- path: '/',
514
- headers: {
515
- 'Content-Type': 'application/x-www-form-urlencoded',
516
- },
517
- body: this.buildFormBody('DeleteLoadBalancer', params),
518
- })
519
- }
520
-
521
- /**
522
- * Create a target group
523
- */
524
- async createTargetGroup(options: {
525
- Name: string
526
- Protocol?: string
527
- ProtocolVersion?: string
528
- Port?: number
529
- VpcId?: string
530
- HealthCheckProtocol?: string
531
- HealthCheckPort?: string
532
- HealthCheckEnabled?: boolean
533
- HealthCheckPath?: string
534
- HealthCheckIntervalSeconds?: number
535
- HealthCheckTimeoutSeconds?: number
536
- HealthyThresholdCount?: number
537
- UnhealthyThresholdCount?: number
538
- Matcher?: { HttpCode?: string, GrpcCode?: string }
539
- TargetType?: 'instance' | 'ip' | 'lambda' | 'alb'
540
- Tags?: Array<{ Key: string, Value: string }>
541
- IpAddressType?: 'ipv4' | 'ipv6'
542
- }): Promise<{ TargetGroups?: TargetGroup[] }> {
543
- const params: Record<string, any> = {
544
- Name: options.Name,
545
- }
546
-
547
- if (options.Protocol) params.Protocol = options.Protocol
548
- if (options.ProtocolVersion) params.ProtocolVersion = options.ProtocolVersion
549
- if (options.Port) params.Port = options.Port
550
- if (options.VpcId) params.VpcId = options.VpcId
551
- if (options.HealthCheckProtocol) params.HealthCheckProtocol = options.HealthCheckProtocol
552
- if (options.HealthCheckPort) params.HealthCheckPort = options.HealthCheckPort
553
- if (options.HealthCheckEnabled !== undefined) params.HealthCheckEnabled = options.HealthCheckEnabled
554
- if (options.HealthCheckPath) params.HealthCheckPath = options.HealthCheckPath
555
- if (options.HealthCheckIntervalSeconds) params.HealthCheckIntervalSeconds = options.HealthCheckIntervalSeconds
556
- if (options.HealthCheckTimeoutSeconds) params.HealthCheckTimeoutSeconds = options.HealthCheckTimeoutSeconds
557
- if (options.HealthyThresholdCount) params.HealthyThresholdCount = options.HealthyThresholdCount
558
- if (options.UnhealthyThresholdCount) params.UnhealthyThresholdCount = options.UnhealthyThresholdCount
559
- if (options.TargetType) params.TargetType = options.TargetType
560
- if (options.IpAddressType) params.IpAddressType = options.IpAddressType
561
-
562
- if (options.Matcher) {
563
- if (options.Matcher.HttpCode) params['Matcher.HttpCode'] = options.Matcher.HttpCode
564
- if (options.Matcher.GrpcCode) params['Matcher.GrpcCode'] = options.Matcher.GrpcCode
565
- }
566
-
567
- if (options.Tags) {
568
- options.Tags.forEach((tag, index) => {
569
- params[`Tags.member.${index + 1}.Key`] = tag.Key
570
- params[`Tags.member.${index + 1}.Value`] = tag.Value
571
- })
572
- }
573
-
574
- const result = await this.client.request({
575
- service: 'elasticloadbalancing',
576
- region: this.region,
577
- method: 'POST',
578
- path: '/',
579
- headers: {
580
- 'Content-Type': 'application/x-www-form-urlencoded',
581
- },
582
- body: this.buildFormBody('CreateTargetGroup', params),
583
- })
584
-
585
- return this.normalizeResult(result, 'CreateTargetGroupResult')
586
- }
587
-
588
- /**
589
- * Delete a target group
590
- */
591
- async deleteTargetGroup(targetGroupArn: string): Promise<void> {
592
- const params = {
593
- TargetGroupArn: targetGroupArn,
594
- }
595
-
596
- await this.client.request({
597
- service: 'elasticloadbalancing',
598
- region: this.region,
599
- method: 'POST',
600
- path: '/',
601
- headers: {
602
- 'Content-Type': 'application/x-www-form-urlencoded',
603
- },
604
- body: this.buildFormBody('DeleteTargetGroup', params),
605
- })
606
- }
607
-
608
- /**
609
- * Register targets with a target group
610
- */
611
- async registerTargets(options: {
612
- TargetGroupArn: string
613
- Targets: Array<{ Id: string, Port?: number, AvailabilityZone?: string }>
614
- }): Promise<void> {
615
- const params: Record<string, any> = {
616
- TargetGroupArn: options.TargetGroupArn,
617
- }
618
-
619
- options.Targets.forEach((target, index) => {
620
- params[`Targets.member.${index + 1}.Id`] = target.Id
621
- if (target.Port) {
622
- params[`Targets.member.${index + 1}.Port`] = target.Port
623
- }
624
- if (target.AvailabilityZone) {
625
- params[`Targets.member.${index + 1}.AvailabilityZone`] = target.AvailabilityZone
626
- }
627
- })
628
-
629
- await this.client.request({
630
- service: 'elasticloadbalancing',
631
- region: this.region,
632
- method: 'POST',
633
- path: '/',
634
- headers: {
635
- 'Content-Type': 'application/x-www-form-urlencoded',
636
- },
637
- body: this.buildFormBody('RegisterTargets', params),
638
- })
639
- }
640
-
641
- /**
642
- * Deregister targets from a target group
643
- */
644
- async deregisterTargets(options: {
645
- TargetGroupArn: string
646
- Targets: Array<{ Id: string, Port?: number, AvailabilityZone?: string }>
647
- }): Promise<void> {
648
- const params: Record<string, any> = {
649
- TargetGroupArn: options.TargetGroupArn,
650
- }
651
-
652
- options.Targets.forEach((target, index) => {
653
- params[`Targets.member.${index + 1}.Id`] = target.Id
654
- if (target.Port) {
655
- params[`Targets.member.${index + 1}.Port`] = target.Port
656
- }
657
- if (target.AvailabilityZone) {
658
- params[`Targets.member.${index + 1}.AvailabilityZone`] = target.AvailabilityZone
659
- }
660
- })
661
-
662
- await this.client.request({
663
- service: 'elasticloadbalancing',
664
- region: this.region,
665
- method: 'POST',
666
- path: '/',
667
- headers: {
668
- 'Content-Type': 'application/x-www-form-urlencoded',
669
- },
670
- body: this.buildFormBody('DeregisterTargets', params),
671
- })
672
- }
673
-
674
- /**
675
- * Create a listener
676
- */
677
- async createListener(options: {
678
- LoadBalancerArn: string
679
- Protocol?: string
680
- Port: number
681
- SslPolicy?: string
682
- Certificates?: Array<{ CertificateArn: string }>
683
- DefaultActions: Array<{
684
- Type: 'forward' | 'redirect' | 'fixed-response'
685
- TargetGroupArn?: string
686
- Order?: number
687
- RedirectConfig?: {
688
- Protocol?: string
689
- Port?: string
690
- Host?: string
691
- Path?: string
692
- Query?: string
693
- StatusCode: 'HTTP_301' | 'HTTP_302'
694
- }
695
- FixedResponseConfig?: {
696
- MessageBody?: string
697
- StatusCode: string
698
- ContentType?: string
699
- }
700
- }>
701
- AlpnPolicy?: string[]
702
- Tags?: Array<{ Key: string, Value: string }>
703
- }): Promise<{ Listeners?: Listener[] }> {
704
- const params: Record<string, any> = {
705
- LoadBalancerArn: options.LoadBalancerArn,
706
- Port: options.Port,
707
- }
708
-
709
- if (options.Protocol) params.Protocol = options.Protocol
710
- if (options.SslPolicy) params.SslPolicy = options.SslPolicy
711
-
712
- if (options.Certificates) {
713
- options.Certificates.forEach((cert, index) => {
714
- params[`Certificates.member.${index + 1}.CertificateArn`] = cert.CertificateArn
715
- })
716
- }
717
-
718
- options.DefaultActions.forEach((action, index) => {
719
- params[`DefaultActions.member.${index + 1}.Type`] = action.Type
720
- if (action.TargetGroupArn) {
721
- params[`DefaultActions.member.${index + 1}.TargetGroupArn`] = action.TargetGroupArn
722
- }
723
- if (action.Order !== undefined) {
724
- params[`DefaultActions.member.${index + 1}.Order`] = action.Order
725
- }
726
- if (action.RedirectConfig) {
727
- const rc = action.RedirectConfig
728
- if (rc.Protocol) params[`DefaultActions.member.${index + 1}.RedirectConfig.Protocol`] = rc.Protocol
729
- if (rc.Port) params[`DefaultActions.member.${index + 1}.RedirectConfig.Port`] = rc.Port
730
- if (rc.Host) params[`DefaultActions.member.${index + 1}.RedirectConfig.Host`] = rc.Host
731
- if (rc.Path) params[`DefaultActions.member.${index + 1}.RedirectConfig.Path`] = rc.Path
732
- if (rc.Query) params[`DefaultActions.member.${index + 1}.RedirectConfig.Query`] = rc.Query
733
- params[`DefaultActions.member.${index + 1}.RedirectConfig.StatusCode`] = rc.StatusCode
734
- }
735
- if (action.FixedResponseConfig) {
736
- const fr = action.FixedResponseConfig
737
- if (fr.MessageBody) params[`DefaultActions.member.${index + 1}.FixedResponseConfig.MessageBody`] = fr.MessageBody
738
- params[`DefaultActions.member.${index + 1}.FixedResponseConfig.StatusCode`] = fr.StatusCode
739
- if (fr.ContentType) params[`DefaultActions.member.${index + 1}.FixedResponseConfig.ContentType`] = fr.ContentType
740
- }
741
- })
742
-
743
- if (options.AlpnPolicy) {
744
- options.AlpnPolicy.forEach((policy, index) => {
745
- params[`AlpnPolicy.member.${index + 1}`] = policy
746
- })
747
- }
748
-
749
- if (options.Tags) {
750
- options.Tags.forEach((tag, index) => {
751
- params[`Tags.member.${index + 1}.Key`] = tag.Key
752
- params[`Tags.member.${index + 1}.Value`] = tag.Value
753
- })
754
- }
755
-
756
- const result = await this.client.request({
757
- service: 'elasticloadbalancing',
758
- region: this.region,
759
- method: 'POST',
760
- path: '/',
761
- headers: {
762
- 'Content-Type': 'application/x-www-form-urlencoded',
763
- },
764
- body: this.buildFormBody('CreateListener', params),
765
- })
766
-
767
- return this.normalizeResult(result, 'CreateListenerResult')
768
- }
769
-
770
- /**
771
- * Delete a listener
772
- */
773
- async deleteListener(listenerArn: string): Promise<void> {
774
- const params = {
775
- ListenerArn: listenerArn,
776
- }
777
-
778
- await this.client.request({
779
- service: 'elasticloadbalancing',
780
- region: this.region,
781
- method: 'POST',
782
- path: '/',
783
- headers: {
784
- 'Content-Type': 'application/x-www-form-urlencoded',
785
- },
786
- body: this.buildFormBody('DeleteListener', params),
787
- })
788
- }
789
-
790
- /**
791
- * Modify listener
792
- */
793
- async modifyListener(options: {
794
- ListenerArn: string
795
- Port?: number
796
- Protocol?: string
797
- SslPolicy?: string
798
- Certificates?: Array<{ CertificateArn: string }>
799
- DefaultActions?: Action[]
800
- AlpnPolicy?: string[]
801
- }): Promise<{ Listeners?: Listener[] }> {
802
- const params: Record<string, any> = {
803
- ListenerArn: options.ListenerArn,
804
- }
805
-
806
- if (options.Port) params.Port = options.Port
807
- if (options.Protocol) params.Protocol = options.Protocol
808
- if (options.SslPolicy) params.SslPolicy = options.SslPolicy
809
-
810
- if (options.Certificates) {
811
- options.Certificates.forEach((cert, index) => {
812
- params[`Certificates.member.${index + 1}.CertificateArn`] = cert.CertificateArn
813
- })
814
- }
815
-
816
- if (options.DefaultActions) {
817
- options.DefaultActions.forEach((action, index) => {
818
- if (action.Type) params[`DefaultActions.member.${index + 1}.Type`] = action.Type
819
- if (action.TargetGroupArn) params[`DefaultActions.member.${index + 1}.TargetGroupArn`] = action.TargetGroupArn
820
- if (action.Order !== undefined) params[`DefaultActions.member.${index + 1}.Order`] = action.Order
821
- })
822
- }
823
-
824
- if (options.AlpnPolicy) {
825
- options.AlpnPolicy.forEach((policy, index) => {
826
- params[`AlpnPolicy.member.${index + 1}`] = policy
827
- })
828
- }
829
-
830
- const result = await this.client.request({
831
- service: 'elasticloadbalancing',
832
- region: this.region,
833
- method: 'POST',
834
- path: '/',
835
- headers: {
836
- 'Content-Type': 'application/x-www-form-urlencoded',
837
- },
838
- body: this.buildFormBody('ModifyListener', params),
839
- })
840
-
841
- return this.normalizeResult(result, 'ModifyListenerResult')
842
- }
843
-
844
- /**
845
- * Build form URL encoded body for ELBv2 API
846
- */
847
- private buildFormBody(action: string, params: Record<string, any>): string {
848
- const formParams: Record<string, string> = {
849
- Action: action,
850
- Version: '2015-12-01',
851
- }
852
-
853
- // Flatten params
854
- for (const [key, value] of Object.entries(params)) {
855
- if (value !== undefined && value !== null) {
856
- formParams[key] = String(value)
857
- }
858
- }
859
-
860
- return Object.entries(formParams)
861
- .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
862
- .join('&')
863
- }
864
-
865
- /**
866
- * Normalize the parsed XML result from AWS API
867
- * The client parses XML to JSON, so we need to extract the result
868
- */
869
- private normalizeResult(parsed: any, resultKey: string): any {
870
- // The AWS response is wrapped like: { DescribeLoadBalancersResponse: { DescribeLoadBalancersResult: {...} } }
871
- // fast-xml-parser returns: { DescribeLoadBalancersResult: {...}, ResponseMetadata: {...} }
872
-
873
- // Try direct access first
874
- if (parsed && parsed[resultKey]) {
875
- return this.normalizeArrays(parsed[resultKey])
876
- }
877
-
878
- // Try accessing through response wrapper
879
- const responseKey = resultKey.replace('Result', 'Response')
880
- if (parsed && parsed[responseKey] && parsed[responseKey][resultKey]) {
881
- return this.normalizeArrays(parsed[responseKey][resultKey])
882
- }
883
-
884
- // Return parsed as-is if no wrapper found
885
- return this.normalizeArrays(parsed)
886
- }
887
-
888
- /**
889
- * Normalize arrays in the response
890
- * AWS XML parsing sometimes returns single items as objects instead of arrays
891
- */
892
- private normalizeArrays(obj: any): any {
893
- if (!obj || typeof obj !== 'object') {
894
- return obj
895
- }
896
-
897
- // Handle arrays
898
- if (Array.isArray(obj)) {
899
- return obj.map(item => this.normalizeArrays(item))
900
- }
901
-
902
- const result: any = {}
903
- for (const [key, value] of Object.entries(obj)) {
904
- // Known array fields that should always be arrays
905
- const arrayFields = [
906
- 'LoadBalancers', 'TargetGroups', 'Listeners', 'Rules',
907
- 'TargetHealthDescriptions', 'Attributes', 'SecurityGroups',
908
- 'AvailabilityZones', 'Certificates', 'DefaultActions',
909
- 'Conditions', 'Actions', 'member'
910
- ]
911
-
912
- if (key === 'member') {
913
- // AWS returns arrays as { member: [...] } or { member: {...} }
914
- if (Array.isArray(value)) {
915
- return value.map(item => this.normalizeArrays(item))
916
- }
917
- return [this.normalizeArrays(value)]
918
- }
919
-
920
- if (arrayFields.includes(key)) {
921
- if (value && typeof value === 'object' && 'member' in (value as any)) {
922
- const memberValue = (value as any).member
923
- result[key] = Array.isArray(memberValue)
924
- ? memberValue.map((item: any) => this.normalizeArrays(item))
925
- : [this.normalizeArrays(memberValue)]
926
- } else if (Array.isArray(value)) {
927
- result[key] = value.map(item => this.normalizeArrays(item))
928
- } else if (value) {
929
- result[key] = [this.normalizeArrays(value)]
930
- } else {
931
- result[key] = []
932
- }
933
- } else if (typeof value === 'object') {
934
- result[key] = this.normalizeArrays(value)
935
- } else {
936
- result[key] = value
937
- }
938
- }
939
-
940
- return result
941
- }
942
- }