@stacksjs/ts-cloud 0.1.8 → 0.1.9

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 (75) hide show
  1. package/dist/bin/cli.js +1 -1
  2. package/package.json +18 -16
  3. package/src/aws/acm.ts +768 -0
  4. package/src/aws/application-autoscaling.ts +845 -0
  5. package/src/aws/bedrock.ts +4074 -0
  6. package/src/aws/client.ts +891 -0
  7. package/src/aws/cloudformation.ts +896 -0
  8. package/src/aws/cloudfront.ts +1531 -0
  9. package/src/aws/cloudwatch-logs.ts +154 -0
  10. package/src/aws/comprehend.ts +839 -0
  11. package/src/aws/connect.ts +1056 -0
  12. package/src/aws/deploy-imap.ts +384 -0
  13. package/src/aws/dynamodb.ts +340 -0
  14. package/src/aws/ec2.ts +1385 -0
  15. package/src/aws/ecr.ts +621 -0
  16. package/src/aws/ecs.ts +615 -0
  17. package/src/aws/elasticache.ts +301 -0
  18. package/src/aws/elbv2.ts +942 -0
  19. package/src/aws/email.ts +928 -0
  20. package/src/aws/eventbridge.ts +248 -0
  21. package/src/aws/iam.ts +1689 -0
  22. package/src/aws/imap-server.ts +2100 -0
  23. package/src/aws/index.ts +213 -0
  24. package/src/aws/kendra.ts +1097 -0
  25. package/src/aws/lambda.ts +786 -0
  26. package/src/aws/opensearch.ts +158 -0
  27. package/src/aws/personalize.ts +977 -0
  28. package/src/aws/polly.ts +559 -0
  29. package/src/aws/rds.ts +888 -0
  30. package/src/aws/rekognition.ts +846 -0
  31. package/src/aws/route53-domains.ts +359 -0
  32. package/src/aws/route53.ts +1046 -0
  33. package/src/aws/s3.ts +2334 -0
  34. package/src/aws/scheduler.ts +571 -0
  35. package/src/aws/secrets-manager.ts +769 -0
  36. package/src/aws/ses.ts +1081 -0
  37. package/src/aws/setup-phone.ts +104 -0
  38. package/src/aws/setup-sms.ts +580 -0
  39. package/src/aws/sms.ts +1735 -0
  40. package/src/aws/smtp-server.ts +531 -0
  41. package/src/aws/sns.ts +758 -0
  42. package/src/aws/sqs.ts +382 -0
  43. package/src/aws/ssm.ts +807 -0
  44. package/src/aws/sts.ts +92 -0
  45. package/src/aws/support.ts +391 -0
  46. package/src/aws/test-imap.ts +86 -0
  47. package/src/aws/textract.ts +780 -0
  48. package/src/aws/transcribe.ts +108 -0
  49. package/src/aws/translate.ts +641 -0
  50. package/src/aws/voice.ts +1379 -0
  51. package/src/config.ts +35 -0
  52. package/src/deploy/index.ts +7 -0
  53. package/src/deploy/static-site-external-dns.ts +945 -0
  54. package/src/deploy/static-site.ts +1175 -0
  55. package/src/dns/cloudflare.ts +548 -0
  56. package/src/dns/godaddy.ts +412 -0
  57. package/src/dns/index.ts +205 -0
  58. package/src/dns/porkbun.ts +362 -0
  59. package/src/dns/route53-adapter.ts +414 -0
  60. package/src/dns/types.ts +119 -0
  61. package/src/dns/validator.ts +369 -0
  62. package/src/generators/index.ts +5 -0
  63. package/src/generators/infrastructure.ts +1660 -0
  64. package/src/index.ts +163 -0
  65. package/src/push/apns.ts +452 -0
  66. package/src/push/fcm.ts +506 -0
  67. package/src/push/index.ts +58 -0
  68. package/src/security/pre-deploy-scanner.ts +655 -0
  69. package/src/ssl/acme-client.ts +478 -0
  70. package/src/ssl/index.ts +7 -0
  71. package/src/ssl/letsencrypt.ts +747 -0
  72. package/src/types.ts +2 -0
  73. package/src/utils/cli.ts +398 -0
  74. package/src/validation/index.ts +5 -0
  75. package/src/validation/template.ts +405 -0
@@ -0,0 +1,641 @@
1
+ /**
2
+ * AWS Translate Client
3
+ * Machine translation service
4
+ * No external SDK dependencies - implements AWS Signature V4 directly
5
+ */
6
+
7
+ import { AWSClient } from './client'
8
+
9
+ // ============================================================================
10
+ // Types
11
+ // ============================================================================
12
+
13
+ export interface TranslateTextCommandInput {
14
+ Text: string
15
+ SourceLanguageCode: string
16
+ TargetLanguageCode: string
17
+ TerminologyNames?: string[]
18
+ Settings?: {
19
+ Formality?: 'FORMAL' | 'INFORMAL'
20
+ Profanity?: 'MASK'
21
+ Brevity?: 'ON'
22
+ }
23
+ }
24
+
25
+ export interface TranslatedDocument {
26
+ Content: Uint8Array
27
+ }
28
+
29
+ export interface AppliedTerminology {
30
+ Name?: string
31
+ Terms?: Array<{
32
+ SourceText?: string
33
+ TargetText?: string
34
+ }>
35
+ }
36
+
37
+ export interface TranslateTextCommandOutput {
38
+ TranslatedText: string
39
+ SourceLanguageCode: string
40
+ TargetLanguageCode: string
41
+ AppliedTerminologies?: AppliedTerminology[]
42
+ AppliedSettings?: {
43
+ Formality?: 'FORMAL' | 'INFORMAL'
44
+ Profanity?: 'MASK'
45
+ Brevity?: 'ON'
46
+ }
47
+ }
48
+
49
+ export interface TranslateDocumentCommandInput {
50
+ Document: {
51
+ Content: Uint8Array
52
+ ContentType: 'text/html' | 'text/plain' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
53
+ }
54
+ SourceLanguageCode: string
55
+ TargetLanguageCode: string
56
+ TerminologyNames?: string[]
57
+ Settings?: {
58
+ Formality?: 'FORMAL' | 'INFORMAL'
59
+ Profanity?: 'MASK'
60
+ Brevity?: 'ON'
61
+ }
62
+ }
63
+
64
+ export interface TranslateDocumentCommandOutput {
65
+ TranslatedDocument: TranslatedDocument
66
+ SourceLanguageCode: string
67
+ TargetLanguageCode: string
68
+ AppliedTerminologies?: AppliedTerminology[]
69
+ AppliedSettings?: {
70
+ Formality?: 'FORMAL' | 'INFORMAL'
71
+ Profanity?: 'MASK'
72
+ Brevity?: 'ON'
73
+ }
74
+ }
75
+
76
+ export interface StartTextTranslationJobCommandInput {
77
+ JobName?: string
78
+ InputDataConfig: {
79
+ S3Uri: string
80
+ ContentType: 'text/html' | 'text/plain' | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' | 'application/vnd.openxmlformats-officedocument.presentationml.presentation' | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | 'application/x-xliff+xml'
81
+ }
82
+ OutputDataConfig: {
83
+ S3Uri: string
84
+ EncryptionKey?: {
85
+ Type: 'KMS'
86
+ Id: string
87
+ }
88
+ }
89
+ DataAccessRoleArn: string
90
+ SourceLanguageCode: string
91
+ TargetLanguageCodes: string[]
92
+ TerminologyNames?: string[]
93
+ ParallelDataNames?: string[]
94
+ ClientToken?: string
95
+ Settings?: {
96
+ Formality?: 'FORMAL' | 'INFORMAL'
97
+ Profanity?: 'MASK'
98
+ Brevity?: 'ON'
99
+ }
100
+ }
101
+
102
+ export interface StartTextTranslationJobCommandOutput {
103
+ JobId?: string
104
+ JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'COMPLETED_WITH_ERROR' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
105
+ }
106
+
107
+ export interface DescribeTextTranslationJobCommandInput {
108
+ JobId: string
109
+ }
110
+
111
+ export interface TextTranslationJobProperties {
112
+ JobId?: string
113
+ JobName?: string
114
+ JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'COMPLETED_WITH_ERROR' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
115
+ JobDetails?: {
116
+ TranslatedDocumentsCount?: number
117
+ DocumentsWithErrorsCount?: number
118
+ InputDocumentsCount?: number
119
+ }
120
+ SourceLanguageCode?: string
121
+ TargetLanguageCodes?: string[]
122
+ TerminologyNames?: string[]
123
+ ParallelDataNames?: string[]
124
+ Message?: string
125
+ SubmittedTime?: string
126
+ EndTime?: string
127
+ InputDataConfig?: {
128
+ S3Uri?: string
129
+ ContentType?: string
130
+ }
131
+ OutputDataConfig?: {
132
+ S3Uri?: string
133
+ EncryptionKey?: {
134
+ Type?: string
135
+ Id?: string
136
+ }
137
+ }
138
+ DataAccessRoleArn?: string
139
+ Settings?: {
140
+ Formality?: 'FORMAL' | 'INFORMAL'
141
+ Profanity?: 'MASK'
142
+ Brevity?: 'ON'
143
+ }
144
+ }
145
+
146
+ export interface DescribeTextTranslationJobCommandOutput {
147
+ TextTranslationJobProperties?: TextTranslationJobProperties
148
+ }
149
+
150
+ export interface ListTextTranslationJobsCommandInput {
151
+ Filter?: {
152
+ JobName?: string
153
+ JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'COMPLETED_WITH_ERROR' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
154
+ SubmittedBeforeTime?: string
155
+ SubmittedAfterTime?: string
156
+ }
157
+ NextToken?: string
158
+ MaxResults?: number
159
+ }
160
+
161
+ export interface ListTextTranslationJobsCommandOutput {
162
+ TextTranslationJobPropertiesList?: TextTranslationJobProperties[]
163
+ NextToken?: string
164
+ }
165
+
166
+ export interface StopTextTranslationJobCommandInput {
167
+ JobId: string
168
+ }
169
+
170
+ export interface StopTextTranslationJobCommandOutput {
171
+ JobId?: string
172
+ JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'COMPLETED_WITH_ERROR' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
173
+ }
174
+
175
+ export interface ListLanguagesCommandInput {
176
+ DisplayLanguageCode?: string
177
+ NextToken?: string
178
+ MaxResults?: number
179
+ }
180
+
181
+ export interface Language {
182
+ LanguageName?: string
183
+ LanguageCode?: string
184
+ }
185
+
186
+ export interface ListLanguagesCommandOutput {
187
+ Languages?: Language[]
188
+ DisplayLanguageCode?: string
189
+ NextToken?: string
190
+ }
191
+
192
+ export interface ImportTerminologyCommandInput {
193
+ Name: string
194
+ MergeStrategy: 'OVERWRITE'
195
+ Description?: string
196
+ TerminologyData: {
197
+ File: Uint8Array
198
+ Format: 'CSV' | 'TMX' | 'TSV'
199
+ Directionality?: 'UNI' | 'MULTI'
200
+ }
201
+ EncryptionKey?: {
202
+ Type: 'KMS'
203
+ Id: string
204
+ }
205
+ Tags?: Array<{ Key: string; Value: string }>
206
+ }
207
+
208
+ export interface TerminologyProperties {
209
+ Name?: string
210
+ Description?: string
211
+ Arn?: string
212
+ SourceLanguageCode?: string
213
+ TargetLanguageCodes?: string[]
214
+ EncryptionKey?: {
215
+ Type?: string
216
+ Id?: string
217
+ }
218
+ SizeBytes?: number
219
+ TermCount?: number
220
+ CreatedAt?: string
221
+ LastUpdatedAt?: string
222
+ Directionality?: 'UNI' | 'MULTI'
223
+ Message?: string
224
+ SkippedTermCount?: number
225
+ Format?: 'CSV' | 'TMX' | 'TSV'
226
+ }
227
+
228
+ export interface ImportTerminologyCommandOutput {
229
+ TerminologyProperties?: TerminologyProperties
230
+ AuxiliaryDataLocation?: {
231
+ RepositoryType?: string
232
+ Location?: string
233
+ }
234
+ }
235
+
236
+ export interface GetTerminologyCommandInput {
237
+ Name: string
238
+ TerminologyDataFormat?: 'CSV' | 'TMX' | 'TSV'
239
+ }
240
+
241
+ export interface GetTerminologyCommandOutput {
242
+ TerminologyProperties?: TerminologyProperties
243
+ TerminologyDataLocation?: {
244
+ RepositoryType?: string
245
+ Location?: string
246
+ }
247
+ AuxiliaryDataLocation?: {
248
+ RepositoryType?: string
249
+ Location?: string
250
+ }
251
+ }
252
+
253
+ export interface ListTerminologiesCommandInput {
254
+ NextToken?: string
255
+ MaxResults?: number
256
+ }
257
+
258
+ export interface ListTerminologiesCommandOutput {
259
+ TerminologyPropertiesList?: TerminologyProperties[]
260
+ NextToken?: string
261
+ }
262
+
263
+ export interface DeleteTerminologyCommandInput {
264
+ Name: string
265
+ }
266
+
267
+ export interface DeleteTerminologyCommandOutput {
268
+ // Empty
269
+ }
270
+
271
+ export interface CreateParallelDataCommandInput {
272
+ Name: string
273
+ Description?: string
274
+ ParallelDataConfig: {
275
+ S3Uri: string
276
+ Format: 'TSV' | 'CSV' | 'TMX'
277
+ }
278
+ EncryptionKey?: {
279
+ Type: 'KMS'
280
+ Id: string
281
+ }
282
+ ClientToken?: string
283
+ Tags?: Array<{ Key: string; Value: string }>
284
+ }
285
+
286
+ export interface ParallelDataProperties {
287
+ Name?: string
288
+ Arn?: string
289
+ Description?: string
290
+ Status?: 'CREATING' | 'UPDATING' | 'ACTIVE' | 'DELETING' | 'FAILED'
291
+ SourceLanguageCode?: string
292
+ TargetLanguageCodes?: string[]
293
+ ParallelDataConfig?: {
294
+ S3Uri?: string
295
+ Format?: 'TSV' | 'CSV' | 'TMX'
296
+ }
297
+ Message?: string
298
+ ImportedDataSize?: number
299
+ ImportedRecordCount?: number
300
+ FailedRecordCount?: number
301
+ SkippedRecordCount?: number
302
+ EncryptionKey?: {
303
+ Type?: string
304
+ Id?: string
305
+ }
306
+ CreatedAt?: string
307
+ LastUpdatedAt?: string
308
+ LatestUpdateAttemptStatus?: 'CREATING' | 'UPDATING' | 'ACTIVE' | 'DELETING' | 'FAILED'
309
+ LatestUpdateAttemptAt?: string
310
+ }
311
+
312
+ export interface CreateParallelDataCommandOutput {
313
+ Name?: string
314
+ Status?: 'CREATING' | 'UPDATING' | 'ACTIVE' | 'DELETING' | 'FAILED'
315
+ }
316
+
317
+ export interface GetParallelDataCommandInput {
318
+ Name: string
319
+ }
320
+
321
+ export interface GetParallelDataCommandOutput {
322
+ ParallelDataProperties?: ParallelDataProperties
323
+ DataLocation?: {
324
+ RepositoryType?: string
325
+ Location?: string
326
+ }
327
+ AuxiliaryDataLocation?: {
328
+ RepositoryType?: string
329
+ Location?: string
330
+ }
331
+ LatestUpdateAttemptAuxiliaryDataLocation?: {
332
+ RepositoryType?: string
333
+ Location?: string
334
+ }
335
+ }
336
+
337
+ export interface ListParallelDataCommandInput {
338
+ NextToken?: string
339
+ MaxResults?: number
340
+ }
341
+
342
+ export interface ListParallelDataCommandOutput {
343
+ ParallelDataPropertiesList?: ParallelDataProperties[]
344
+ NextToken?: string
345
+ }
346
+
347
+ export interface DeleteParallelDataCommandInput {
348
+ Name: string
349
+ }
350
+
351
+ export interface DeleteParallelDataCommandOutput {
352
+ Name?: string
353
+ Status?: 'CREATING' | 'UPDATING' | 'ACTIVE' | 'DELETING' | 'FAILED'
354
+ }
355
+
356
+ // ============================================================================
357
+ // Translate Client
358
+ // ============================================================================
359
+
360
+ export class TranslateClient {
361
+ private client: AWSClient
362
+ private region: string
363
+
364
+ constructor(region: string = 'us-east-1') {
365
+ this.region = region
366
+ this.client = new AWSClient()
367
+ }
368
+
369
+ private async request<T>(action: string, params: Record<string, unknown>): Promise<T> {
370
+ return this.client.request({
371
+ service: 'translate',
372
+ region: this.region,
373
+ method: 'POST',
374
+ path: '/',
375
+ headers: {
376
+ 'Content-Type': 'application/x-amz-json-1.1',
377
+ 'X-Amz-Target': `AWSShineFrontendService_20170701.${action}`,
378
+ },
379
+ body: JSON.stringify(params),
380
+ })
381
+ }
382
+
383
+ // -------------------------------------------------------------------------
384
+ // Real-time Translation
385
+ // -------------------------------------------------------------------------
386
+
387
+ /**
388
+ * Translate text
389
+ */
390
+ async translateText(params: TranslateTextCommandInput): Promise<TranslateTextCommandOutput> {
391
+ return this.request('TranslateText', params as unknown as Record<string, unknown>)
392
+ }
393
+
394
+ /**
395
+ * Translate a document
396
+ */
397
+ async translateDocument(params: TranslateDocumentCommandInput): Promise<TranslateDocumentCommandOutput> {
398
+ return this.request('TranslateDocument', params as unknown as Record<string, unknown>)
399
+ }
400
+
401
+ // -------------------------------------------------------------------------
402
+ // Batch Translation
403
+ // -------------------------------------------------------------------------
404
+
405
+ /**
406
+ * Start a batch translation job
407
+ */
408
+ async startTextTranslationJob(params: StartTextTranslationJobCommandInput): Promise<StartTextTranslationJobCommandOutput> {
409
+ return this.request('StartTextTranslationJob', params as unknown as Record<string, unknown>)
410
+ }
411
+
412
+ /**
413
+ * Describe a batch translation job
414
+ */
415
+ async describeTextTranslationJob(params: DescribeTextTranslationJobCommandInput): Promise<DescribeTextTranslationJobCommandOutput> {
416
+ return this.request('DescribeTextTranslationJob', params as unknown as Record<string, unknown>)
417
+ }
418
+
419
+ /**
420
+ * List batch translation jobs
421
+ */
422
+ async listTextTranslationJobs(params?: ListTextTranslationJobsCommandInput): Promise<ListTextTranslationJobsCommandOutput> {
423
+ return this.request('ListTextTranslationJobs', (params || {}) as unknown as Record<string, unknown>)
424
+ }
425
+
426
+ /**
427
+ * Stop a batch translation job
428
+ */
429
+ async stopTextTranslationJob(params: StopTextTranslationJobCommandInput): Promise<StopTextTranslationJobCommandOutput> {
430
+ return this.request('StopTextTranslationJob', params as unknown as Record<string, unknown>)
431
+ }
432
+
433
+ // -------------------------------------------------------------------------
434
+ // Languages
435
+ // -------------------------------------------------------------------------
436
+
437
+ /**
438
+ * List supported languages
439
+ */
440
+ async listLanguages(params?: ListLanguagesCommandInput): Promise<ListLanguagesCommandOutput> {
441
+ return this.request('ListLanguages', (params || {}) as unknown as Record<string, unknown>)
442
+ }
443
+
444
+ // -------------------------------------------------------------------------
445
+ // Terminologies
446
+ // -------------------------------------------------------------------------
447
+
448
+ /**
449
+ * Import a custom terminology
450
+ */
451
+ async importTerminology(params: ImportTerminologyCommandInput): Promise<ImportTerminologyCommandOutput> {
452
+ return this.request('ImportTerminology', params as unknown as Record<string, unknown>)
453
+ }
454
+
455
+ /**
456
+ * Get a terminology
457
+ */
458
+ async getTerminology(params: GetTerminologyCommandInput): Promise<GetTerminologyCommandOutput> {
459
+ return this.request('GetTerminology', params as unknown as Record<string, unknown>)
460
+ }
461
+
462
+ /**
463
+ * List terminologies
464
+ */
465
+ async listTerminologies(params?: ListTerminologiesCommandInput): Promise<ListTerminologiesCommandOutput> {
466
+ return this.request('ListTerminologies', (params || {}) as unknown as Record<string, unknown>)
467
+ }
468
+
469
+ /**
470
+ * Delete a terminology
471
+ */
472
+ async deleteTerminology(params: DeleteTerminologyCommandInput): Promise<DeleteTerminologyCommandOutput> {
473
+ return this.request('DeleteTerminology', params as unknown as Record<string, unknown>)
474
+ }
475
+
476
+ // -------------------------------------------------------------------------
477
+ // Parallel Data
478
+ // -------------------------------------------------------------------------
479
+
480
+ /**
481
+ * Create parallel data for custom translation
482
+ */
483
+ async createParallelData(params: CreateParallelDataCommandInput): Promise<CreateParallelDataCommandOutput> {
484
+ return this.request('CreateParallelData', params as unknown as Record<string, unknown>)
485
+ }
486
+
487
+ /**
488
+ * Get parallel data
489
+ */
490
+ async getParallelData(params: GetParallelDataCommandInput): Promise<GetParallelDataCommandOutput> {
491
+ return this.request('GetParallelData', params as unknown as Record<string, unknown>)
492
+ }
493
+
494
+ /**
495
+ * List parallel data
496
+ */
497
+ async listParallelData(params?: ListParallelDataCommandInput): Promise<ListParallelDataCommandOutput> {
498
+ return this.request('ListParallelData', (params || {}) as unknown as Record<string, unknown>)
499
+ }
500
+
501
+ /**
502
+ * Delete parallel data
503
+ */
504
+ async deleteParallelData(params: DeleteParallelDataCommandInput): Promise<DeleteParallelDataCommandOutput> {
505
+ return this.request('DeleteParallelData', params as unknown as Record<string, unknown>)
506
+ }
507
+
508
+ // -------------------------------------------------------------------------
509
+ // Convenience Methods
510
+ // -------------------------------------------------------------------------
511
+
512
+ /**
513
+ * Simple translation
514
+ */
515
+ async translate(
516
+ text: string,
517
+ targetLanguage: string,
518
+ sourceLanguage: string = 'auto',
519
+ ): Promise<string> {
520
+ const result = await this.translateText({
521
+ Text: text,
522
+ SourceLanguageCode: sourceLanguage,
523
+ TargetLanguageCode: targetLanguage,
524
+ })
525
+ return result.TranslatedText
526
+ }
527
+
528
+ /**
529
+ * Translate with formality setting
530
+ */
531
+ async translateFormal(
532
+ text: string,
533
+ targetLanguage: string,
534
+ sourceLanguage: string = 'auto',
535
+ formality: 'FORMAL' | 'INFORMAL' = 'FORMAL',
536
+ ): Promise<string> {
537
+ const result = await this.translateText({
538
+ Text: text,
539
+ SourceLanguageCode: sourceLanguage,
540
+ TargetLanguageCode: targetLanguage,
541
+ Settings: { Formality: formality },
542
+ })
543
+ return result.TranslatedText
544
+ }
545
+
546
+ /**
547
+ * Translate to multiple languages
548
+ */
549
+ async translateToMultiple(
550
+ text: string,
551
+ targetLanguages: string[],
552
+ sourceLanguage: string = 'auto',
553
+ ): Promise<Record<string, string>> {
554
+ const results: Record<string, string> = {}
555
+
556
+ for (const targetLang of targetLanguages) {
557
+ results[targetLang] = await this.translate(text, targetLang, sourceLanguage)
558
+ }
559
+
560
+ return results
561
+ }
562
+
563
+ /**
564
+ * Wait for batch translation job to complete
565
+ */
566
+ async waitForJob(
567
+ jobId: string,
568
+ options?: { maxWaitMs?: number; pollIntervalMs?: number },
569
+ ): Promise<TextTranslationJobProperties> {
570
+ const maxWaitMs = options?.maxWaitMs ?? 3600000 // 1 hour
571
+ const pollIntervalMs = options?.pollIntervalMs ?? 30000
572
+ const startTime = Date.now()
573
+
574
+ while (Date.now() - startTime < maxWaitMs) {
575
+ const result = await this.describeTextTranslationJob({ JobId: jobId })
576
+ const job = result.TextTranslationJobProperties
577
+
578
+ if (job?.JobStatus === 'COMPLETED' || job?.JobStatus === 'COMPLETED_WITH_ERROR') {
579
+ return job
580
+ }
581
+ if (job?.JobStatus === 'FAILED' || job?.JobStatus === 'STOPPED') {
582
+ throw new Error(`Translation job ${jobId} failed: ${job.Message}`)
583
+ }
584
+
585
+ await new Promise(resolve => setTimeout(resolve, pollIntervalMs))
586
+ }
587
+
588
+ throw new Error(`Timeout waiting for translation job ${jobId}`)
589
+ }
590
+
591
+ /**
592
+ * Get all supported language codes
593
+ */
594
+ async getSupportedLanguages(): Promise<string[]> {
595
+ const result = await this.listLanguages()
596
+ return result.Languages?.map(l => l.LanguageCode || '').filter(Boolean) || []
597
+ }
598
+ }
599
+
600
+ // ============================================================================
601
+ // Helper Functions
602
+ // ============================================================================
603
+
604
+ /**
605
+ * Quick translation
606
+ */
607
+ export async function translate(
608
+ text: string,
609
+ targetLanguage: string,
610
+ options?: {
611
+ sourceLanguage?: string
612
+ region?: string
613
+ },
614
+ ): Promise<string> {
615
+ const client = new TranslateClient(options?.region || 'us-east-1')
616
+ return client.translate(text, targetLanguage, options?.sourceLanguage || 'auto')
617
+ }
618
+
619
+ /**
620
+ * Translate to multiple languages
621
+ */
622
+ export async function translateToMultiple(
623
+ text: string,
624
+ targetLanguages: string[],
625
+ options?: {
626
+ sourceLanguage?: string
627
+ region?: string
628
+ },
629
+ ): Promise<Record<string, string>> {
630
+ const client = new TranslateClient(options?.region || 'us-east-1')
631
+ return client.translateToMultiple(text, targetLanguages, options?.sourceLanguage || 'auto')
632
+ }
633
+
634
+ /**
635
+ * List supported languages
636
+ */
637
+ export async function listLanguages(region?: string): Promise<Language[]> {
638
+ const client = new TranslateClient(region || 'us-east-1')
639
+ const result = await client.listLanguages()
640
+ return result.Languages || []
641
+ }