@stacksjs/ts-cloud 0.1.9 → 0.1.14

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 (150) hide show
  1. package/README.md +39 -377
  2. package/dist/bin/cli.js +1047 -424
  3. package/dist/index.d.ts +36 -3
  4. package/dist/index.js +76430 -7096
  5. package/package.json +7 -8
  6. package/dist/aws/acm.d.ts +0 -129
  7. package/dist/aws/application-autoscaling.d.ts +0 -282
  8. package/dist/aws/bedrock.d.ts +0 -2292
  9. package/dist/aws/client.d.ts +0 -79
  10. package/dist/aws/cloudformation.d.ts +0 -105
  11. package/dist/aws/cloudfront.d.ts +0 -265
  12. package/dist/aws/cloudwatch-logs.d.ts +0 -48
  13. package/dist/aws/comprehend.d.ts +0 -505
  14. package/dist/aws/connect.d.ts +0 -377
  15. package/dist/aws/deploy-imap.d.ts +0 -14
  16. package/dist/aws/dynamodb.d.ts +0 -176
  17. package/dist/aws/ec2.d.ts +0 -272
  18. package/dist/aws/ecr.d.ts +0 -149
  19. package/dist/aws/ecs.d.ts +0 -162
  20. package/dist/aws/elasticache.d.ts +0 -71
  21. package/dist/aws/elbv2.d.ts +0 -248
  22. package/dist/aws/email.d.ts +0 -175
  23. package/dist/aws/eventbridge.d.ts +0 -142
  24. package/dist/aws/iam.d.ts +0 -638
  25. package/dist/aws/imap-server.d.ts +0 -119
  26. package/dist/aws/index.d.ts +0 -192
  27. package/dist/aws/kendra.d.ts +0 -782
  28. package/dist/aws/lambda.d.ts +0 -232
  29. package/dist/aws/opensearch.d.ts +0 -87
  30. package/dist/aws/personalize.d.ts +0 -516
  31. package/dist/aws/polly.d.ts +0 -214
  32. package/dist/aws/rds.d.ts +0 -240
  33. package/dist/aws/rekognition.d.ts +0 -543
  34. package/dist/aws/route53-domains.d.ts +0 -113
  35. package/dist/aws/route53.d.ts +0 -215
  36. package/dist/aws/s3.d.ts +0 -212
  37. package/dist/aws/scheduler.d.ts +0 -140
  38. package/dist/aws/secrets-manager.d.ts +0 -170
  39. package/dist/aws/ses.d.ts +0 -288
  40. package/dist/aws/setup-phone.d.ts +0 -0
  41. package/dist/aws/setup-sms.d.ts +0 -115
  42. package/dist/aws/sms.d.ts +0 -304
  43. package/dist/aws/smtp-server.d.ts +0 -61
  44. package/dist/aws/sns.d.ts +0 -117
  45. package/dist/aws/sqs.d.ts +0 -65
  46. package/dist/aws/ssm.d.ts +0 -179
  47. package/dist/aws/sts.d.ts +0 -15
  48. package/dist/aws/support.d.ts +0 -104
  49. package/dist/aws/test-imap.d.ts +0 -0
  50. package/dist/aws/textract.d.ts +0 -403
  51. package/dist/aws/transcribe.d.ts +0 -60
  52. package/dist/aws/translate.d.ts +0 -358
  53. package/dist/aws/voice.d.ts +0 -219
  54. package/dist/config.d.ts +0 -7
  55. package/dist/deploy/index.d.ts +0 -2
  56. package/dist/deploy/static-site-external-dns.d.ts +0 -51
  57. package/dist/deploy/static-site.d.ts +0 -71
  58. package/dist/dns/cloudflare.d.ts +0 -52
  59. package/dist/dns/godaddy.d.ts +0 -38
  60. package/dist/dns/index.d.ts +0 -45
  61. package/dist/dns/porkbun.d.ts +0 -18
  62. package/dist/dns/route53-adapter.d.ts +0 -38
  63. package/dist/dns/types.d.ts +0 -77
  64. package/dist/dns/validator.d.ts +0 -78
  65. package/dist/generators/index.d.ts +0 -1
  66. package/dist/generators/infrastructure.d.ts +0 -30
  67. package/dist/push/apns.d.ts +0 -60
  68. package/dist/push/fcm.d.ts +0 -117
  69. package/dist/push/index.d.ts +0 -14
  70. package/dist/security/pre-deploy-scanner.d.ts +0 -69
  71. package/dist/ssl/acme-client.d.ts +0 -67
  72. package/dist/ssl/index.d.ts +0 -2
  73. package/dist/ssl/letsencrypt.d.ts +0 -48
  74. package/dist/types.d.ts +0 -1
  75. package/dist/utils/cli.d.ts +0 -123
  76. package/dist/validation/index.d.ts +0 -1
  77. package/dist/validation/template.d.ts +0 -23
  78. package/src/aws/acm.ts +0 -768
  79. package/src/aws/application-autoscaling.ts +0 -845
  80. package/src/aws/bedrock.ts +0 -4074
  81. package/src/aws/client.ts +0 -891
  82. package/src/aws/cloudformation.ts +0 -896
  83. package/src/aws/cloudfront.ts +0 -1531
  84. package/src/aws/cloudwatch-logs.ts +0 -154
  85. package/src/aws/comprehend.ts +0 -839
  86. package/src/aws/connect.ts +0 -1056
  87. package/src/aws/deploy-imap.ts +0 -384
  88. package/src/aws/dynamodb.ts +0 -340
  89. package/src/aws/ec2.ts +0 -1385
  90. package/src/aws/ecr.ts +0 -621
  91. package/src/aws/ecs.ts +0 -615
  92. package/src/aws/elasticache.ts +0 -301
  93. package/src/aws/elbv2.ts +0 -942
  94. package/src/aws/email.ts +0 -928
  95. package/src/aws/eventbridge.ts +0 -248
  96. package/src/aws/iam.ts +0 -1689
  97. package/src/aws/imap-server.ts +0 -2100
  98. package/src/aws/index.ts +0 -213
  99. package/src/aws/kendra.ts +0 -1097
  100. package/src/aws/lambda.ts +0 -786
  101. package/src/aws/opensearch.ts +0 -158
  102. package/src/aws/personalize.ts +0 -977
  103. package/src/aws/polly.ts +0 -559
  104. package/src/aws/rds.ts +0 -888
  105. package/src/aws/rekognition.ts +0 -846
  106. package/src/aws/route53-domains.ts +0 -359
  107. package/src/aws/route53.ts +0 -1046
  108. package/src/aws/s3.ts +0 -2334
  109. package/src/aws/scheduler.ts +0 -571
  110. package/src/aws/secrets-manager.ts +0 -769
  111. package/src/aws/ses.ts +0 -1081
  112. package/src/aws/setup-phone.ts +0 -104
  113. package/src/aws/setup-sms.ts +0 -580
  114. package/src/aws/sms.ts +0 -1735
  115. package/src/aws/smtp-server.ts +0 -531
  116. package/src/aws/sns.ts +0 -758
  117. package/src/aws/sqs.ts +0 -382
  118. package/src/aws/ssm.ts +0 -807
  119. package/src/aws/sts.ts +0 -92
  120. package/src/aws/support.ts +0 -391
  121. package/src/aws/test-imap.ts +0 -86
  122. package/src/aws/textract.ts +0 -780
  123. package/src/aws/transcribe.ts +0 -108
  124. package/src/aws/translate.ts +0 -641
  125. package/src/aws/voice.ts +0 -1379
  126. package/src/config.ts +0 -35
  127. package/src/deploy/index.ts +0 -7
  128. package/src/deploy/static-site-external-dns.ts +0 -945
  129. package/src/deploy/static-site.ts +0 -1175
  130. package/src/dns/cloudflare.ts +0 -548
  131. package/src/dns/godaddy.ts +0 -412
  132. package/src/dns/index.ts +0 -205
  133. package/src/dns/porkbun.ts +0 -362
  134. package/src/dns/route53-adapter.ts +0 -414
  135. package/src/dns/types.ts +0 -119
  136. package/src/dns/validator.ts +0 -369
  137. package/src/generators/index.ts +0 -5
  138. package/src/generators/infrastructure.ts +0 -1660
  139. package/src/index.ts +0 -163
  140. package/src/push/apns.ts +0 -452
  141. package/src/push/fcm.ts +0 -506
  142. package/src/push/index.ts +0 -58
  143. package/src/security/pre-deploy-scanner.ts +0 -655
  144. package/src/ssl/acme-client.ts +0 -478
  145. package/src/ssl/index.ts +0 -7
  146. package/src/ssl/letsencrypt.ts +0 -747
  147. package/src/types.ts +0 -2
  148. package/src/utils/cli.ts +0 -398
  149. package/src/validation/index.ts +0 -5
  150. package/src/validation/template.ts +0 -405
package/src/aws/polly.ts DELETED
@@ -1,559 +0,0 @@
1
- /**
2
- * AWS Polly Client
3
- * Text-to-Speech 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 type VoiceId =
14
- | 'Aditi' | 'Amy' | 'Aria' | 'Arlet' | 'Arthur' | 'Astrid'
15
- | 'Ayanda' | 'Bianca' | 'Brian' | 'Camila' | 'Carla' | 'Carmen'
16
- | 'Celine' | 'Chantal' | 'Conchita' | 'Cristiano' | 'Daniel' | 'Dora'
17
- | 'Elin' | 'Emma' | 'Enrique' | 'Ewa' | 'Filiz' | 'Gabrielle'
18
- | 'Geraint' | 'Giorgio' | 'Gwyneth' | 'Hala' | 'Hannah' | 'Hans'
19
- | 'Hiujin' | 'Ida' | 'Ines' | 'Ivy' | 'Jacek' | 'Jan'
20
- | 'Joanna' | 'Joey' | 'Justin' | 'Kajal' | 'Karl' | 'Kazuha'
21
- | 'Kendra' | 'Kevin' | 'Kimberly' | 'Laura' | 'Lea' | 'Liam'
22
- | 'Lisa' | 'Liv' | 'Lotte' | 'Lucia' | 'Lupe' | 'Mads'
23
- | 'Maja' | 'Marlene' | 'Mathieu' | 'Matthew' | 'Maxim' | 'Mia'
24
- | 'Miguel' | 'Mizuki' | 'Naja' | 'Niamh' | 'Nicole' | 'Ola'
25
- | 'Olivia' | 'Pedro' | 'Penelope' | 'Raveena' | 'Remi' | 'Ricardo'
26
- | 'Ruben' | 'Russell' | 'Ruth' | 'Salli' | 'Seoyeon' | 'Sergio'
27
- | 'Sofie' | 'Stephen' | 'Suvi' | 'Takumi' | 'Tatyana' | 'Thiago'
28
- | 'Tomoko' | 'Vicki' | 'Vitoria' | 'Zayd' | 'Zeina' | 'Zhiyu'
29
-
30
- export type LanguageCode =
31
- | 'arb' | 'ca-ES' | 'cmn-CN' | 'cy-GB' | 'da-DK' | 'de-AT' | 'de-DE'
32
- | 'en-AU' | 'en-GB' | 'en-GB-WLS' | 'en-IE' | 'en-IN' | 'en-NZ' | 'en-US' | 'en-ZA'
33
- | 'es-ES' | 'es-MX' | 'es-US' | 'fi-FI' | 'fr-BE' | 'fr-CA' | 'fr-FR'
34
- | 'hi-IN' | 'is-IS' | 'it-IT' | 'ja-JP' | 'ko-KR' | 'nb-NO' | 'nl-BE' | 'nl-NL'
35
- | 'pl-PL' | 'pt-BR' | 'pt-PT' | 'ro-RO' | 'ru-RU' | 'sv-SE' | 'tr-TR' | 'yue-CN'
36
-
37
- export type Engine = 'standard' | 'neural' | 'long-form' | 'generative'
38
-
39
- export type OutputFormat = 'json' | 'mp3' | 'ogg_vorbis' | 'pcm'
40
-
41
- export type TextType = 'ssml' | 'text'
42
-
43
- export type SpeechMarkType = 'sentence' | 'ssml' | 'viseme' | 'word'
44
-
45
- export interface Voice {
46
- Gender?: 'Female' | 'Male'
47
- Id?: VoiceId
48
- LanguageCode?: LanguageCode
49
- LanguageName?: string
50
- Name?: string
51
- AdditionalLanguageCodes?: LanguageCode[]
52
- SupportedEngines?: Engine[]
53
- }
54
-
55
- export interface SynthesizeSpeechCommandInput {
56
- Engine?: Engine
57
- LanguageCode?: LanguageCode
58
- LexiconNames?: string[]
59
- OutputFormat: OutputFormat
60
- SampleRate?: string
61
- SpeechMarkTypes?: SpeechMarkType[]
62
- Text: string
63
- TextType?: TextType
64
- VoiceId: VoiceId
65
- }
66
-
67
- export interface SynthesizeSpeechCommandOutput {
68
- AudioStream?: Uint8Array
69
- ContentType?: string
70
- RequestCharacters?: number
71
- }
72
-
73
- export interface DescribeVoicesCommandInput {
74
- Engine?: Engine
75
- LanguageCode?: LanguageCode
76
- IncludeAdditionalLanguageCodes?: boolean
77
- NextToken?: string
78
- }
79
-
80
- export interface DescribeVoicesCommandOutput {
81
- Voices?: Voice[]
82
- NextToken?: string
83
- }
84
-
85
- export interface StartSpeechSynthesisTaskCommandInput {
86
- Engine?: Engine
87
- LanguageCode?: LanguageCode
88
- LexiconNames?: string[]
89
- OutputFormat: OutputFormat
90
- OutputS3BucketName: string
91
- OutputS3KeyPrefix?: string
92
- SampleRate?: string
93
- SnsTopicArn?: string
94
- SpeechMarkTypes?: SpeechMarkType[]
95
- Text: string
96
- TextType?: TextType
97
- VoiceId: VoiceId
98
- }
99
-
100
- export interface SynthesisTask {
101
- Engine?: Engine
102
- TaskId?: string
103
- TaskStatus?: 'scheduled' | 'inProgress' | 'completed' | 'failed'
104
- TaskStatusReason?: string
105
- OutputUri?: string
106
- CreationTime?: string
107
- RequestCharacters?: number
108
- SnsTopicArn?: string
109
- LexiconNames?: string[]
110
- OutputFormat?: OutputFormat
111
- SampleRate?: string
112
- SpeechMarkTypes?: SpeechMarkType[]
113
- TextType?: TextType
114
- VoiceId?: VoiceId
115
- LanguageCode?: LanguageCode
116
- }
117
-
118
- export interface StartSpeechSynthesisTaskCommandOutput {
119
- SynthesisTask?: SynthesisTask
120
- }
121
-
122
- export interface GetSpeechSynthesisTaskCommandInput {
123
- TaskId: string
124
- }
125
-
126
- export interface GetSpeechSynthesisTaskCommandOutput {
127
- SynthesisTask?: SynthesisTask
128
- }
129
-
130
- export interface ListSpeechSynthesisTasksCommandInput {
131
- MaxResults?: number
132
- NextToken?: string
133
- Status?: 'scheduled' | 'inProgress' | 'completed' | 'failed'
134
- }
135
-
136
- export interface ListSpeechSynthesisTasksCommandOutput {
137
- NextToken?: string
138
- SynthesisTasks?: SynthesisTask[]
139
- }
140
-
141
- export interface PutLexiconCommandInput {
142
- Name: string
143
- Content: string
144
- }
145
-
146
- export interface PutLexiconCommandOutput {
147
- // Empty
148
- }
149
-
150
- export interface GetLexiconCommandInput {
151
- Name: string
152
- }
153
-
154
- export interface Lexicon {
155
- Content?: string
156
- Name?: string
157
- }
158
-
159
- export interface LexiconAttributes {
160
- Alphabet?: string
161
- LanguageCode?: LanguageCode
162
- LastModified?: string
163
- LexemesCount?: number
164
- LexiconArn?: string
165
- Size?: number
166
- }
167
-
168
- export interface GetLexiconCommandOutput {
169
- Lexicon?: Lexicon
170
- LexiconAttributes?: LexiconAttributes
171
- }
172
-
173
- export interface DeleteLexiconCommandInput {
174
- Name: string
175
- }
176
-
177
- export interface DeleteLexiconCommandOutput {
178
- // Empty
179
- }
180
-
181
- export interface ListLexiconsCommandInput {
182
- NextToken?: string
183
- }
184
-
185
- export interface ListLexiconsCommandOutput {
186
- Lexicons?: Array<{
187
- Name?: string
188
- Attributes?: LexiconAttributes
189
- }>
190
- NextToken?: string
191
- }
192
-
193
- // ============================================================================
194
- // Polly Client
195
- // ============================================================================
196
-
197
- export class PollyClient {
198
- private client: AWSClient
199
- private region: string
200
-
201
- constructor(region: string = 'us-east-1') {
202
- this.region = region
203
- this.client = new AWSClient()
204
- }
205
-
206
- // -------------------------------------------------------------------------
207
- // Speech Synthesis
208
- // -------------------------------------------------------------------------
209
-
210
- /**
211
- * Synthesize speech from text (synchronous)
212
- */
213
- async synthesizeSpeech(params: SynthesizeSpeechCommandInput): Promise<SynthesizeSpeechCommandOutput> {
214
- const result = await this.client.request({
215
- service: 'polly',
216
- region: this.region,
217
- method: 'POST',
218
- path: '/v1/speech',
219
- headers: {
220
- 'Content-Type': 'application/json',
221
- },
222
- body: JSON.stringify({
223
- Engine: params.Engine,
224
- LanguageCode: params.LanguageCode,
225
- LexiconNames: params.LexiconNames,
226
- OutputFormat: params.OutputFormat,
227
- SampleRate: params.SampleRate,
228
- SpeechMarkTypes: params.SpeechMarkTypes,
229
- Text: params.Text,
230
- TextType: params.TextType,
231
- VoiceId: params.VoiceId,
232
- }),
233
- rawResponse: true,
234
- returnHeaders: true,
235
- })
236
-
237
- return {
238
- AudioStream: new TextEncoder().encode(result.body),
239
- ContentType: result.headers?.['content-type'],
240
- RequestCharacters: result.headers?.['x-amzn-requestcharacters']
241
- ? Number.parseInt(result.headers['x-amzn-requestcharacters'])
242
- : undefined,
243
- }
244
- }
245
-
246
- /**
247
- * Start async speech synthesis task
248
- */
249
- async startSpeechSynthesisTask(params: StartSpeechSynthesisTaskCommandInput): Promise<StartSpeechSynthesisTaskCommandOutput> {
250
- return this.client.request({
251
- service: 'polly',
252
- region: this.region,
253
- method: 'POST',
254
- path: '/v1/synthesisTasks',
255
- headers: {
256
- 'Content-Type': 'application/json',
257
- },
258
- body: JSON.stringify(params),
259
- })
260
- }
261
-
262
- /**
263
- * Get speech synthesis task status
264
- */
265
- async getSpeechSynthesisTask(params: GetSpeechSynthesisTaskCommandInput): Promise<GetSpeechSynthesisTaskCommandOutput> {
266
- return this.client.request({
267
- service: 'polly',
268
- region: this.region,
269
- method: 'GET',
270
- path: `/v1/synthesisTasks/${encodeURIComponent(params.TaskId)}`,
271
- })
272
- }
273
-
274
- /**
275
- * List speech synthesis tasks
276
- */
277
- async listSpeechSynthesisTasks(params?: ListSpeechSynthesisTasksCommandInput): Promise<ListSpeechSynthesisTasksCommandOutput> {
278
- const queryParams: Record<string, string> = {}
279
- if (params?.MaxResults) queryParams.MaxResults = params.MaxResults.toString()
280
- if (params?.NextToken) queryParams.NextToken = params.NextToken
281
- if (params?.Status) queryParams.Status = params.Status
282
-
283
- return this.client.request({
284
- service: 'polly',
285
- region: this.region,
286
- method: 'GET',
287
- path: '/v1/synthesisTasks',
288
- queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,
289
- })
290
- }
291
-
292
- // -------------------------------------------------------------------------
293
- // Voices
294
- // -------------------------------------------------------------------------
295
-
296
- /**
297
- * List available voices
298
- */
299
- async describeVoices(params?: DescribeVoicesCommandInput): Promise<DescribeVoicesCommandOutput> {
300
- const queryParams: Record<string, string> = {}
301
- if (params?.Engine) queryParams.Engine = params.Engine
302
- if (params?.LanguageCode) queryParams.LanguageCode = params.LanguageCode
303
- if (params?.IncludeAdditionalLanguageCodes !== undefined) {
304
- queryParams.IncludeAdditionalLanguageCodes = params.IncludeAdditionalLanguageCodes.toString()
305
- }
306
- if (params?.NextToken) queryParams.NextToken = params.NextToken
307
-
308
- return this.client.request({
309
- service: 'polly',
310
- region: this.region,
311
- method: 'GET',
312
- path: '/v1/voices',
313
- queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,
314
- })
315
- }
316
-
317
- // -------------------------------------------------------------------------
318
- // Lexicons
319
- // -------------------------------------------------------------------------
320
-
321
- /**
322
- * Store a pronunciation lexicon
323
- */
324
- async putLexicon(params: PutLexiconCommandInput): Promise<PutLexiconCommandOutput> {
325
- return this.client.request({
326
- service: 'polly',
327
- region: this.region,
328
- method: 'PUT',
329
- path: `/v1/lexicons/${encodeURIComponent(params.Name)}`,
330
- headers: {
331
- 'Content-Type': 'application/pls+xml',
332
- },
333
- body: params.Content,
334
- })
335
- }
336
-
337
- /**
338
- * Get a lexicon
339
- */
340
- async getLexicon(params: GetLexiconCommandInput): Promise<GetLexiconCommandOutput> {
341
- return this.client.request({
342
- service: 'polly',
343
- region: this.region,
344
- method: 'GET',
345
- path: `/v1/lexicons/${encodeURIComponent(params.Name)}`,
346
- })
347
- }
348
-
349
- /**
350
- * Delete a lexicon
351
- */
352
- async deleteLexicon(params: DeleteLexiconCommandInput): Promise<DeleteLexiconCommandOutput> {
353
- return this.client.request({
354
- service: 'polly',
355
- region: this.region,
356
- method: 'DELETE',
357
- path: `/v1/lexicons/${encodeURIComponent(params.Name)}`,
358
- })
359
- }
360
-
361
- /**
362
- * List lexicons
363
- */
364
- async listLexicons(params?: ListLexiconsCommandInput): Promise<ListLexiconsCommandOutput> {
365
- const queryParams: Record<string, string> = {}
366
- if (params?.NextToken) queryParams.NextToken = params.NextToken
367
-
368
- return this.client.request({
369
- service: 'polly',
370
- region: this.region,
371
- method: 'GET',
372
- path: '/v1/lexicons',
373
- queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,
374
- })
375
- }
376
-
377
- // -------------------------------------------------------------------------
378
- // Convenience Methods
379
- // -------------------------------------------------------------------------
380
-
381
- /**
382
- * Simple text to speech - returns MP3 audio bytes
383
- */
384
- async textToSpeech(
385
- text: string,
386
- options?: {
387
- voiceId?: VoiceId
388
- engine?: Engine
389
- languageCode?: LanguageCode
390
- },
391
- ): Promise<Uint8Array> {
392
- const result = await this.synthesizeSpeech({
393
- Text: text,
394
- VoiceId: options?.voiceId || 'Joanna',
395
- Engine: options?.engine || 'neural',
396
- LanguageCode: options?.languageCode,
397
- OutputFormat: 'mp3',
398
- })
399
- return result.AudioStream || new Uint8Array()
400
- }
401
-
402
- /**
403
- * Text to speech with SSML support
404
- */
405
- async ssmlToSpeech(
406
- ssml: string,
407
- options?: {
408
- voiceId?: VoiceId
409
- engine?: Engine
410
- languageCode?: LanguageCode
411
- },
412
- ): Promise<Uint8Array> {
413
- const result = await this.synthesizeSpeech({
414
- Text: ssml,
415
- TextType: 'ssml',
416
- VoiceId: options?.voiceId || 'Joanna',
417
- Engine: options?.engine || 'neural',
418
- LanguageCode: options?.languageCode,
419
- OutputFormat: 'mp3',
420
- })
421
- return result.AudioStream || new Uint8Array()
422
- }
423
-
424
- /**
425
- * Save speech to S3 (for longer texts)
426
- */
427
- async saveToS3(
428
- text: string,
429
- bucket: string,
430
- keyPrefix: string,
431
- options?: {
432
- voiceId?: VoiceId
433
- engine?: Engine
434
- languageCode?: LanguageCode
435
- textType?: TextType
436
- },
437
- ): Promise<{ taskId: string; outputUri: string }> {
438
- const result = await this.startSpeechSynthesisTask({
439
- Text: text,
440
- TextType: options?.textType || 'text',
441
- VoiceId: options?.voiceId || 'Joanna',
442
- Engine: options?.engine || 'neural',
443
- LanguageCode: options?.languageCode,
444
- OutputFormat: 'mp3',
445
- OutputS3BucketName: bucket,
446
- OutputS3KeyPrefix: keyPrefix,
447
- })
448
-
449
- return {
450
- taskId: result.SynthesisTask?.TaskId || '',
451
- outputUri: result.SynthesisTask?.OutputUri || '',
452
- }
453
- }
454
-
455
- /**
456
- * List voices for a specific language
457
- */
458
- async listVoicesForLanguage(languageCode: LanguageCode): Promise<Voice[]> {
459
- const result = await this.describeVoices({ LanguageCode: languageCode })
460
- return result.Voices || []
461
- }
462
-
463
- /**
464
- * List neural voices
465
- */
466
- async listNeuralVoices(): Promise<Voice[]> {
467
- const result = await this.describeVoices({ Engine: 'neural' })
468
- return result.Voices || []
469
- }
470
-
471
- /**
472
- * Wait for synthesis task to complete
473
- */
474
- async waitForTask(
475
- taskId: string,
476
- options?: { maxWaitMs?: number; pollIntervalMs?: number },
477
- ): Promise<SynthesisTask> {
478
- const maxWaitMs = options?.maxWaitMs ?? 300000 // 5 minutes
479
- const pollIntervalMs = options?.pollIntervalMs ?? 5000
480
- const startTime = Date.now()
481
-
482
- while (Date.now() - startTime < maxWaitMs) {
483
- const result = await this.getSpeechSynthesisTask({ TaskId: taskId })
484
- const task = result.SynthesisTask
485
-
486
- if (task?.TaskStatus === 'completed') {
487
- return task
488
- }
489
- if (task?.TaskStatus === 'failed') {
490
- throw new Error(`Polly task ${taskId} failed: ${task.TaskStatusReason}`)
491
- }
492
-
493
- await new Promise(resolve => setTimeout(resolve, pollIntervalMs))
494
- }
495
-
496
- throw new Error(`Timeout waiting for Polly task ${taskId}`)
497
- }
498
- }
499
-
500
- // ============================================================================
501
- // Helper Functions
502
- // ============================================================================
503
-
504
- /**
505
- * Quick text to speech
506
- */
507
- export async function textToSpeech(
508
- text: string,
509
- options?: {
510
- voiceId?: VoiceId
511
- engine?: Engine
512
- region?: string
513
- },
514
- ): Promise<Uint8Array> {
515
- const client = new PollyClient(options?.region || 'us-east-1')
516
- return client.textToSpeech(text, options)
517
- }
518
-
519
- /**
520
- * List available voices
521
- */
522
- export async function listVoices(
523
- options?: {
524
- languageCode?: LanguageCode
525
- engine?: Engine
526
- region?: string
527
- },
528
- ): Promise<Voice[]> {
529
- const client = new PollyClient(options?.region || 'us-east-1')
530
- const result = await client.describeVoices({
531
- LanguageCode: options?.languageCode,
532
- Engine: options?.engine,
533
- })
534
- return result.Voices || []
535
- }
536
-
537
- /**
538
- * Create SSML with speech marks (pauses, emphasis, etc.)
539
- */
540
- export function createSSML(text: string, options?: {
541
- rate?: 'x-slow' | 'slow' | 'medium' | 'fast' | 'x-fast'
542
- pitch?: 'x-low' | 'low' | 'medium' | 'high' | 'x-high'
543
- volume?: 'silent' | 'x-soft' | 'soft' | 'medium' | 'loud' | 'x-loud'
544
- }): string {
545
- let ssml = '<speak>'
546
-
547
- if (options?.rate || options?.pitch || options?.volume) {
548
- ssml += '<prosody'
549
- if (options.rate) ssml += ` rate="${options.rate}"`
550
- if (options.pitch) ssml += ` pitch="${options.pitch}"`
551
- if (options.volume) ssml += ` volume="${options.volume}"`
552
- ssml += `>${text}</prosody>`
553
- } else {
554
- ssml += text
555
- }
556
-
557
- ssml += '</speak>'
558
- return ssml
559
- }