@stacksjs/ts-cloud 0.1.7 → 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.
- package/dist/aws/s3.d.ts +1 -1
- package/dist/bin/cli.js +223 -222
- package/dist/index.js +132 -132
- package/package.json +18 -16
- package/src/aws/acm.ts +768 -0
- package/src/aws/application-autoscaling.ts +845 -0
- package/src/aws/bedrock.ts +4074 -0
- package/src/aws/client.ts +891 -0
- package/src/aws/cloudformation.ts +896 -0
- package/src/aws/cloudfront.ts +1531 -0
- package/src/aws/cloudwatch-logs.ts +154 -0
- package/src/aws/comprehend.ts +839 -0
- package/src/aws/connect.ts +1056 -0
- package/src/aws/deploy-imap.ts +384 -0
- package/src/aws/dynamodb.ts +340 -0
- package/src/aws/ec2.ts +1385 -0
- package/src/aws/ecr.ts +621 -0
- package/src/aws/ecs.ts +615 -0
- package/src/aws/elasticache.ts +301 -0
- package/src/aws/elbv2.ts +942 -0
- package/src/aws/email.ts +928 -0
- package/src/aws/eventbridge.ts +248 -0
- package/src/aws/iam.ts +1689 -0
- package/src/aws/imap-server.ts +2100 -0
- package/src/aws/index.ts +213 -0
- package/src/aws/kendra.ts +1097 -0
- package/src/aws/lambda.ts +786 -0
- package/src/aws/opensearch.ts +158 -0
- package/src/aws/personalize.ts +977 -0
- package/src/aws/polly.ts +559 -0
- package/src/aws/rds.ts +888 -0
- package/src/aws/rekognition.ts +846 -0
- package/src/aws/route53-domains.ts +359 -0
- package/src/aws/route53.ts +1046 -0
- package/src/aws/s3.ts +2334 -0
- package/src/aws/scheduler.ts +571 -0
- package/src/aws/secrets-manager.ts +769 -0
- package/src/aws/ses.ts +1081 -0
- package/src/aws/setup-phone.ts +104 -0
- package/src/aws/setup-sms.ts +580 -0
- package/src/aws/sms.ts +1735 -0
- package/src/aws/smtp-server.ts +531 -0
- package/src/aws/sns.ts +758 -0
- package/src/aws/sqs.ts +382 -0
- package/src/aws/ssm.ts +807 -0
- package/src/aws/sts.ts +92 -0
- package/src/aws/support.ts +391 -0
- package/src/aws/test-imap.ts +86 -0
- package/src/aws/textract.ts +780 -0
- package/src/aws/transcribe.ts +108 -0
- package/src/aws/translate.ts +641 -0
- package/src/aws/voice.ts +1379 -0
- package/src/config.ts +35 -0
- package/src/deploy/index.ts +7 -0
- package/src/deploy/static-site-external-dns.ts +945 -0
- package/src/deploy/static-site.ts +1175 -0
- package/src/dns/cloudflare.ts +548 -0
- package/src/dns/godaddy.ts +412 -0
- package/src/dns/index.ts +205 -0
- package/src/dns/porkbun.ts +362 -0
- package/src/dns/route53-adapter.ts +414 -0
- package/src/dns/types.ts +119 -0
- package/src/dns/validator.ts +369 -0
- package/src/generators/index.ts +5 -0
- package/src/generators/infrastructure.ts +1660 -0
- package/src/index.ts +163 -0
- package/src/push/apns.ts +452 -0
- package/src/push/fcm.ts +506 -0
- package/src/push/index.ts +58 -0
- package/src/security/pre-deploy-scanner.ts +655 -0
- package/src/ssl/acme-client.ts +478 -0
- package/src/ssl/index.ts +7 -0
- package/src/ssl/letsencrypt.ts +747 -0
- package/src/types.ts +2 -0
- package/src/utils/cli.ts +398 -0
- package/src/validation/index.ts +5 -0
- package/src/validation/template.ts +405 -0
|
@@ -0,0 +1,839 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Comprehend Client
|
|
3
|
+
* Natural Language Processing - sentiment, entities, key phrases, language detection, PII
|
|
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 DetectSentimentCommandInput {
|
|
14
|
+
Text: string
|
|
15
|
+
LanguageCode: 'en' | 'es' | 'fr' | 'de' | 'it' | 'pt' | 'ar' | 'hi' | 'ja' | 'ko' | 'zh' | 'zh-TW'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface DetectSentimentCommandOutput {
|
|
19
|
+
Sentiment: 'POSITIVE' | 'NEGATIVE' | 'NEUTRAL' | 'MIXED'
|
|
20
|
+
SentimentScore: {
|
|
21
|
+
Positive: number
|
|
22
|
+
Negative: number
|
|
23
|
+
Neutral: number
|
|
24
|
+
Mixed: number
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface DetectEntitiesCommandInput {
|
|
29
|
+
Text: string
|
|
30
|
+
LanguageCode: string
|
|
31
|
+
EndpointArn?: string
|
|
32
|
+
Bytes?: Uint8Array
|
|
33
|
+
DocumentReaderConfig?: {
|
|
34
|
+
DocumentReadAction: 'TEXTRACT_DETECT_DOCUMENT_TEXT' | 'TEXTRACT_ANALYZE_DOCUMENT'
|
|
35
|
+
DocumentReadMode?: 'SERVICE_DEFAULT' | 'FORCE_DOCUMENT_READ_ACTION'
|
|
36
|
+
FeatureTypes?: ('TABLES' | 'FORMS')[]
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface Entity {
|
|
41
|
+
Score?: number
|
|
42
|
+
Type?: 'PERSON' | 'LOCATION' | 'ORGANIZATION' | 'COMMERCIAL_ITEM' | 'EVENT' | 'DATE' | 'QUANTITY' | 'TITLE' | 'OTHER'
|
|
43
|
+
Text?: string
|
|
44
|
+
BeginOffset?: number
|
|
45
|
+
EndOffset?: number
|
|
46
|
+
BlockReferences?: Array<{
|
|
47
|
+
BlockId?: string
|
|
48
|
+
BeginOffset?: number
|
|
49
|
+
EndOffset?: number
|
|
50
|
+
ChildBlocks?: Array<{
|
|
51
|
+
ChildBlockId?: string
|
|
52
|
+
BeginOffset?: number
|
|
53
|
+
EndOffset?: number
|
|
54
|
+
}>
|
|
55
|
+
}>
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface DetectEntitiesCommandOutput {
|
|
59
|
+
Entities: Entity[]
|
|
60
|
+
DocumentMetadata?: {
|
|
61
|
+
Pages?: number
|
|
62
|
+
ExtractedCharacters?: Array<{
|
|
63
|
+
Page?: number
|
|
64
|
+
Count?: number
|
|
65
|
+
}>
|
|
66
|
+
}
|
|
67
|
+
DocumentType?: Array<{
|
|
68
|
+
Page?: number
|
|
69
|
+
Type?: 'NATIVE_PDF' | 'SCANNED_PDF' | 'MS_WORD' | 'IMAGE' | 'PLAIN_TEXT' | 'TEXTRACT_DETECT_DOCUMENT_TEXT_JSON' | 'TEXTRACT_ANALYZE_DOCUMENT_JSON'
|
|
70
|
+
}>
|
|
71
|
+
Blocks?: Array<{
|
|
72
|
+
Id?: string
|
|
73
|
+
BlockType?: 'LINE' | 'WORD'
|
|
74
|
+
Text?: string
|
|
75
|
+
Page?: number
|
|
76
|
+
Geometry?: {
|
|
77
|
+
BoundingBox?: {
|
|
78
|
+
Height?: number
|
|
79
|
+
Left?: number
|
|
80
|
+
Top?: number
|
|
81
|
+
Width?: number
|
|
82
|
+
}
|
|
83
|
+
Polygon?: Array<{
|
|
84
|
+
X?: number
|
|
85
|
+
Y?: number
|
|
86
|
+
}>
|
|
87
|
+
}
|
|
88
|
+
Relationships?: Array<{
|
|
89
|
+
Ids?: string[]
|
|
90
|
+
Type?: 'CHILD'
|
|
91
|
+
}>
|
|
92
|
+
}>
|
|
93
|
+
Errors?: Array<{
|
|
94
|
+
Page?: number
|
|
95
|
+
ErrorCode?: 'TEXTRACT_BAD_PAGE' | 'TEXTRACT_PROVISIONED_THROUGHPUT_EXCEEDED' | 'PAGE_CHARACTERS_EXCEEDED' | 'PAGE_SIZE_EXCEEDED' | 'INTERNAL_SERVER_ERROR'
|
|
96
|
+
ErrorMessage?: string
|
|
97
|
+
}>
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface DetectKeyPhrasesCommandInput {
|
|
101
|
+
Text: string
|
|
102
|
+
LanguageCode: string
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface KeyPhrase {
|
|
106
|
+
Score?: number
|
|
107
|
+
Text?: string
|
|
108
|
+
BeginOffset?: number
|
|
109
|
+
EndOffset?: number
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface DetectKeyPhrasesCommandOutput {
|
|
113
|
+
KeyPhrases: KeyPhrase[]
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface DetectDominantLanguageCommandInput {
|
|
117
|
+
Text: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface DominantLanguage {
|
|
121
|
+
LanguageCode?: string
|
|
122
|
+
Score?: number
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface DetectDominantLanguageCommandOutput {
|
|
126
|
+
Languages: DominantLanguage[]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface DetectPiiEntitiesCommandInput {
|
|
130
|
+
Text: string
|
|
131
|
+
LanguageCode: string
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface PiiEntity {
|
|
135
|
+
Score?: number
|
|
136
|
+
Type?: 'BANK_ACCOUNT_NUMBER' | 'BANK_ROUTING' | 'CREDIT_DEBIT_NUMBER' | 'CREDIT_DEBIT_CVV' | 'CREDIT_DEBIT_EXPIRY' | 'PIN' | 'EMAIL' | 'ADDRESS' | 'NAME' | 'PHONE' | 'SSN' | 'DATE_TIME' | 'PASSPORT_NUMBER' | 'DRIVER_ID' | 'URL' | 'AGE' | 'USERNAME' | 'PASSWORD' | 'AWS_ACCESS_KEY' | 'AWS_SECRET_KEY' | 'IP_ADDRESS' | 'MAC_ADDRESS' | 'LICENSE_PLATE' | 'VEHICLE_IDENTIFICATION_NUMBER' | 'UK_NATIONAL_INSURANCE_NUMBER' | 'CA_SOCIAL_INSURANCE_NUMBER' | 'US_INDIVIDUAL_TAX_IDENTIFICATION_NUMBER' | 'UK_UNIQUE_TAXPAYER_REFERENCE_NUMBER' | 'IN_PERMANENT_ACCOUNT_NUMBER' | 'IN_NREGA' | 'INTERNATIONAL_BANK_ACCOUNT_NUMBER' | 'SWIFT_CODE' | 'UK_NATIONAL_HEALTH_SERVICE_NUMBER' | 'CA_HEALTH_NUMBER' | 'IN_AADHAAR' | 'IN_VOTER_NUMBER'
|
|
137
|
+
BeginOffset?: number
|
|
138
|
+
EndOffset?: number
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface DetectPiiEntitiesCommandOutput {
|
|
142
|
+
Entities: PiiEntity[]
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface ContainsPiiEntitiesCommandInput {
|
|
146
|
+
Text: string
|
|
147
|
+
LanguageCode: string
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface ContainsPiiEntitiesCommandOutput {
|
|
151
|
+
Labels: Array<{
|
|
152
|
+
Name?: string
|
|
153
|
+
Score?: number
|
|
154
|
+
}>
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface DetectSyntaxCommandInput {
|
|
158
|
+
Text: string
|
|
159
|
+
LanguageCode: 'en' | 'es' | 'fr' | 'de' | 'it' | 'pt'
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface SyntaxToken {
|
|
163
|
+
TokenId?: number
|
|
164
|
+
Text?: string
|
|
165
|
+
BeginOffset?: number
|
|
166
|
+
EndOffset?: number
|
|
167
|
+
PartOfSpeech?: {
|
|
168
|
+
Tag?: 'ADJ' | 'ADP' | 'ADV' | 'AUX' | 'CONJ' | 'CCONJ' | 'DET' | 'INTJ' | 'NOUN' | 'NUM' | 'O' | 'PART' | 'PRON' | 'PROPN' | 'PUNCT' | 'SCONJ' | 'SYM' | 'VERB'
|
|
169
|
+
Score?: number
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface DetectSyntaxCommandOutput {
|
|
174
|
+
SyntaxTokens: SyntaxToken[]
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export interface DetectTargetedSentimentCommandInput {
|
|
178
|
+
Text: string
|
|
179
|
+
LanguageCode: string
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export interface TargetedSentimentEntity {
|
|
183
|
+
DescriptiveMentionIndex?: number[]
|
|
184
|
+
Mentions?: Array<{
|
|
185
|
+
Score?: number
|
|
186
|
+
GroupScore?: number
|
|
187
|
+
Text?: string
|
|
188
|
+
Type?: 'PERSON' | 'LOCATION' | 'ORGANIZATION' | 'FACILITY' | 'BRAND' | 'COMMERCIAL_ITEM' | 'MOVIE' | 'MUSIC' | 'BOOK' | 'SOFTWARE' | 'GAME' | 'PERSONAL_TITLE' | 'EVENT' | 'DATE' | 'QUANTITY' | 'ATTRIBUTE' | 'OTHER'
|
|
189
|
+
MentionSentiment?: {
|
|
190
|
+
Sentiment?: 'POSITIVE' | 'NEGATIVE' | 'NEUTRAL' | 'MIXED'
|
|
191
|
+
SentimentScore?: {
|
|
192
|
+
Positive?: number
|
|
193
|
+
Negative?: number
|
|
194
|
+
Neutral?: number
|
|
195
|
+
Mixed?: number
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
BeginOffset?: number
|
|
199
|
+
EndOffset?: number
|
|
200
|
+
}>
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export interface DetectTargetedSentimentCommandOutput {
|
|
204
|
+
Entities: TargetedSentimentEntity[]
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface ClassifyDocumentCommandInput {
|
|
208
|
+
Text?: string
|
|
209
|
+
EndpointArn: string
|
|
210
|
+
Bytes?: Uint8Array
|
|
211
|
+
DocumentReaderConfig?: {
|
|
212
|
+
DocumentReadAction: 'TEXTRACT_DETECT_DOCUMENT_TEXT' | 'TEXTRACT_ANALYZE_DOCUMENT'
|
|
213
|
+
DocumentReadMode?: 'SERVICE_DEFAULT' | 'FORCE_DOCUMENT_READ_ACTION'
|
|
214
|
+
FeatureTypes?: ('TABLES' | 'FORMS')[]
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export interface ClassifyDocumentCommandOutput {
|
|
219
|
+
Classes?: Array<{
|
|
220
|
+
Name?: string
|
|
221
|
+
Score?: number
|
|
222
|
+
Page?: number
|
|
223
|
+
}>
|
|
224
|
+
Labels?: Array<{
|
|
225
|
+
Name?: string
|
|
226
|
+
Score?: number
|
|
227
|
+
Page?: number
|
|
228
|
+
}>
|
|
229
|
+
DocumentMetadata?: {
|
|
230
|
+
Pages?: number
|
|
231
|
+
ExtractedCharacters?: Array<{
|
|
232
|
+
Page?: number
|
|
233
|
+
Count?: number
|
|
234
|
+
}>
|
|
235
|
+
}
|
|
236
|
+
DocumentType?: Array<{
|
|
237
|
+
Page?: number
|
|
238
|
+
Type?: string
|
|
239
|
+
}>
|
|
240
|
+
Errors?: Array<{
|
|
241
|
+
Page?: number
|
|
242
|
+
ErrorCode?: string
|
|
243
|
+
ErrorMessage?: string
|
|
244
|
+
}>
|
|
245
|
+
Warnings?: Array<{
|
|
246
|
+
Page?: number
|
|
247
|
+
WarnCode?: string
|
|
248
|
+
WarnMessage?: string
|
|
249
|
+
}>
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export interface BatchDetectSentimentCommandInput {
|
|
253
|
+
TextList: string[]
|
|
254
|
+
LanguageCode: string
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export interface BatchDetectSentimentCommandOutput {
|
|
258
|
+
ResultList: Array<{
|
|
259
|
+
Index?: number
|
|
260
|
+
Sentiment?: 'POSITIVE' | 'NEGATIVE' | 'NEUTRAL' | 'MIXED'
|
|
261
|
+
SentimentScore?: {
|
|
262
|
+
Positive?: number
|
|
263
|
+
Negative?: number
|
|
264
|
+
Neutral?: number
|
|
265
|
+
Mixed?: number
|
|
266
|
+
}
|
|
267
|
+
}>
|
|
268
|
+
ErrorList: Array<{
|
|
269
|
+
Index?: number
|
|
270
|
+
ErrorCode?: string
|
|
271
|
+
ErrorMessage?: string
|
|
272
|
+
}>
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export interface BatchDetectEntitiesCommandInput {
|
|
276
|
+
TextList: string[]
|
|
277
|
+
LanguageCode: string
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export interface BatchDetectEntitiesCommandOutput {
|
|
281
|
+
ResultList: Array<{
|
|
282
|
+
Index?: number
|
|
283
|
+
Entities?: Entity[]
|
|
284
|
+
}>
|
|
285
|
+
ErrorList: Array<{
|
|
286
|
+
Index?: number
|
|
287
|
+
ErrorCode?: string
|
|
288
|
+
ErrorMessage?: string
|
|
289
|
+
}>
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
export interface BatchDetectKeyPhrasesCommandInput {
|
|
293
|
+
TextList: string[]
|
|
294
|
+
LanguageCode: string
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export interface BatchDetectKeyPhrasesCommandOutput {
|
|
298
|
+
ResultList: Array<{
|
|
299
|
+
Index?: number
|
|
300
|
+
KeyPhrases?: KeyPhrase[]
|
|
301
|
+
}>
|
|
302
|
+
ErrorList: Array<{
|
|
303
|
+
Index?: number
|
|
304
|
+
ErrorCode?: string
|
|
305
|
+
ErrorMessage?: string
|
|
306
|
+
}>
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export interface BatchDetectDominantLanguageCommandInput {
|
|
310
|
+
TextList: string[]
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export interface BatchDetectDominantLanguageCommandOutput {
|
|
314
|
+
ResultList: Array<{
|
|
315
|
+
Index?: number
|
|
316
|
+
Languages?: DominantLanguage[]
|
|
317
|
+
}>
|
|
318
|
+
ErrorList: Array<{
|
|
319
|
+
Index?: number
|
|
320
|
+
ErrorCode?: string
|
|
321
|
+
ErrorMessage?: string
|
|
322
|
+
}>
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export interface BatchDetectSyntaxCommandInput {
|
|
326
|
+
TextList: string[]
|
|
327
|
+
LanguageCode: string
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export interface BatchDetectSyntaxCommandOutput {
|
|
331
|
+
ResultList: Array<{
|
|
332
|
+
Index?: number
|
|
333
|
+
SyntaxTokens?: SyntaxToken[]
|
|
334
|
+
}>
|
|
335
|
+
ErrorList: Array<{
|
|
336
|
+
Index?: number
|
|
337
|
+
ErrorCode?: string
|
|
338
|
+
ErrorMessage?: string
|
|
339
|
+
}>
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export interface StartSentimentDetectionJobCommandInput {
|
|
343
|
+
InputDataConfig: {
|
|
344
|
+
S3Uri: string
|
|
345
|
+
InputFormat?: 'ONE_DOC_PER_FILE' | 'ONE_DOC_PER_LINE'
|
|
346
|
+
DocumentReaderConfig?: {
|
|
347
|
+
DocumentReadAction: 'TEXTRACT_DETECT_DOCUMENT_TEXT' | 'TEXTRACT_ANALYZE_DOCUMENT'
|
|
348
|
+
DocumentReadMode?: 'SERVICE_DEFAULT' | 'FORCE_DOCUMENT_READ_ACTION'
|
|
349
|
+
FeatureTypes?: ('TABLES' | 'FORMS')[]
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
OutputDataConfig: {
|
|
353
|
+
S3Uri: string
|
|
354
|
+
KmsKeyId?: string
|
|
355
|
+
}
|
|
356
|
+
DataAccessRoleArn: string
|
|
357
|
+
JobName?: string
|
|
358
|
+
LanguageCode: string
|
|
359
|
+
ClientRequestToken?: string
|
|
360
|
+
VolumeKmsKeyId?: string
|
|
361
|
+
VpcConfig?: {
|
|
362
|
+
SecurityGroupIds: string[]
|
|
363
|
+
Subnets: string[]
|
|
364
|
+
}
|
|
365
|
+
Tags?: Array<{ Key: string; Value: string }>
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
export interface StartSentimentDetectionJobCommandOutput {
|
|
369
|
+
JobId?: string
|
|
370
|
+
JobArn?: string
|
|
371
|
+
JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export interface StartEntitiesDetectionJobCommandInput {
|
|
375
|
+
InputDataConfig: {
|
|
376
|
+
S3Uri: string
|
|
377
|
+
InputFormat?: 'ONE_DOC_PER_FILE' | 'ONE_DOC_PER_LINE'
|
|
378
|
+
DocumentReaderConfig?: {
|
|
379
|
+
DocumentReadAction: 'TEXTRACT_DETECT_DOCUMENT_TEXT' | 'TEXTRACT_ANALYZE_DOCUMENT'
|
|
380
|
+
DocumentReadMode?: 'SERVICE_DEFAULT' | 'FORCE_DOCUMENT_READ_ACTION'
|
|
381
|
+
FeatureTypes?: ('TABLES' | 'FORMS')[]
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
OutputDataConfig: {
|
|
385
|
+
S3Uri: string
|
|
386
|
+
KmsKeyId?: string
|
|
387
|
+
}
|
|
388
|
+
DataAccessRoleArn: string
|
|
389
|
+
JobName?: string
|
|
390
|
+
EntityRecognizerArn?: string
|
|
391
|
+
LanguageCode: string
|
|
392
|
+
ClientRequestToken?: string
|
|
393
|
+
VolumeKmsKeyId?: string
|
|
394
|
+
VpcConfig?: {
|
|
395
|
+
SecurityGroupIds: string[]
|
|
396
|
+
Subnets: string[]
|
|
397
|
+
}
|
|
398
|
+
Tags?: Array<{ Key: string; Value: string }>
|
|
399
|
+
FlywheelArn?: string
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export interface StartEntitiesDetectionJobCommandOutput {
|
|
403
|
+
JobId?: string
|
|
404
|
+
JobArn?: string
|
|
405
|
+
JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
|
|
406
|
+
EntityRecognizerArn?: string
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface StartKeyPhrasesDetectionJobCommandInput {
|
|
410
|
+
InputDataConfig: {
|
|
411
|
+
S3Uri: string
|
|
412
|
+
InputFormat?: 'ONE_DOC_PER_FILE' | 'ONE_DOC_PER_LINE'
|
|
413
|
+
}
|
|
414
|
+
OutputDataConfig: {
|
|
415
|
+
S3Uri: string
|
|
416
|
+
KmsKeyId?: string
|
|
417
|
+
}
|
|
418
|
+
DataAccessRoleArn: string
|
|
419
|
+
JobName?: string
|
|
420
|
+
LanguageCode: string
|
|
421
|
+
ClientRequestToken?: string
|
|
422
|
+
VolumeKmsKeyId?: string
|
|
423
|
+
VpcConfig?: {
|
|
424
|
+
SecurityGroupIds: string[]
|
|
425
|
+
Subnets: string[]
|
|
426
|
+
}
|
|
427
|
+
Tags?: Array<{ Key: string; Value: string }>
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export interface StartKeyPhrasesDetectionJobCommandOutput {
|
|
431
|
+
JobId?: string
|
|
432
|
+
JobArn?: string
|
|
433
|
+
JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export interface StartPiiEntitiesDetectionJobCommandInput {
|
|
437
|
+
InputDataConfig: {
|
|
438
|
+
S3Uri: string
|
|
439
|
+
InputFormat?: 'ONE_DOC_PER_FILE' | 'ONE_DOC_PER_LINE'
|
|
440
|
+
}
|
|
441
|
+
OutputDataConfig: {
|
|
442
|
+
S3Uri: string
|
|
443
|
+
KmsKeyId?: string
|
|
444
|
+
}
|
|
445
|
+
Mode: 'ONLY_REDACTION' | 'ONLY_OFFSETS'
|
|
446
|
+
RedactionConfig?: {
|
|
447
|
+
PiiEntityTypes?: string[]
|
|
448
|
+
MaskMode?: 'MASK' | 'REPLACE_WITH_PII_ENTITY_TYPE'
|
|
449
|
+
MaskCharacter?: string
|
|
450
|
+
}
|
|
451
|
+
DataAccessRoleArn: string
|
|
452
|
+
JobName?: string
|
|
453
|
+
LanguageCode: string
|
|
454
|
+
ClientRequestToken?: string
|
|
455
|
+
Tags?: Array<{ Key: string; Value: string }>
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export interface StartPiiEntitiesDetectionJobCommandOutput {
|
|
459
|
+
JobId?: string
|
|
460
|
+
JobArn?: string
|
|
461
|
+
JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export interface DescribeSentimentDetectionJobCommandInput {
|
|
465
|
+
JobId: string
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export interface DescribeSentimentDetectionJobCommandOutput {
|
|
469
|
+
SentimentDetectionJobProperties?: {
|
|
470
|
+
JobId?: string
|
|
471
|
+
JobArn?: string
|
|
472
|
+
JobName?: string
|
|
473
|
+
JobStatus?: 'SUBMITTED' | 'IN_PROGRESS' | 'COMPLETED' | 'FAILED' | 'STOP_REQUESTED' | 'STOPPED'
|
|
474
|
+
Message?: string
|
|
475
|
+
SubmitTime?: string
|
|
476
|
+
EndTime?: string
|
|
477
|
+
InputDataConfig?: {
|
|
478
|
+
S3Uri?: string
|
|
479
|
+
InputFormat?: string
|
|
480
|
+
}
|
|
481
|
+
OutputDataConfig?: {
|
|
482
|
+
S3Uri?: string
|
|
483
|
+
KmsKeyId?: string
|
|
484
|
+
}
|
|
485
|
+
LanguageCode?: string
|
|
486
|
+
DataAccessRoleArn?: string
|
|
487
|
+
VolumeKmsKeyId?: string
|
|
488
|
+
VpcConfig?: {
|
|
489
|
+
SecurityGroupIds?: string[]
|
|
490
|
+
Subnets?: string[]
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// ============================================================================
|
|
496
|
+
// Comprehend Client
|
|
497
|
+
// ============================================================================
|
|
498
|
+
|
|
499
|
+
export class ComprehendClient {
|
|
500
|
+
private client: AWSClient
|
|
501
|
+
private region: string
|
|
502
|
+
|
|
503
|
+
constructor(region: string = 'us-east-1') {
|
|
504
|
+
this.region = region
|
|
505
|
+
this.client = new AWSClient()
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
private async request<T>(action: string, params: Record<string, unknown>): Promise<T> {
|
|
509
|
+
return this.client.request({
|
|
510
|
+
service: 'comprehend',
|
|
511
|
+
region: this.region,
|
|
512
|
+
method: 'POST',
|
|
513
|
+
path: '/',
|
|
514
|
+
headers: {
|
|
515
|
+
'Content-Type': 'application/x-amz-json-1.1',
|
|
516
|
+
'X-Amz-Target': `Comprehend_20171127.${action}`,
|
|
517
|
+
},
|
|
518
|
+
body: JSON.stringify(params),
|
|
519
|
+
})
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// -------------------------------------------------------------------------
|
|
523
|
+
// Detect Operations (Synchronous)
|
|
524
|
+
// -------------------------------------------------------------------------
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Detect sentiment in text
|
|
528
|
+
*/
|
|
529
|
+
async detectSentiment(params: DetectSentimentCommandInput): Promise<DetectSentimentCommandOutput> {
|
|
530
|
+
return this.request('DetectSentiment', params as unknown as Record<string, unknown>)
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Detect entities in text
|
|
535
|
+
*/
|
|
536
|
+
async detectEntities(params: DetectEntitiesCommandInput): Promise<DetectEntitiesCommandOutput> {
|
|
537
|
+
return this.request('DetectEntities', params as unknown as Record<string, unknown>)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Detect key phrases in text
|
|
542
|
+
*/
|
|
543
|
+
async detectKeyPhrases(params: DetectKeyPhrasesCommandInput): Promise<DetectKeyPhrasesCommandOutput> {
|
|
544
|
+
return this.request('DetectKeyPhrases', params as unknown as Record<string, unknown>)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Detect the dominant language of text
|
|
549
|
+
*/
|
|
550
|
+
async detectDominantLanguage(params: DetectDominantLanguageCommandInput): Promise<DetectDominantLanguageCommandOutput> {
|
|
551
|
+
return this.request('DetectDominantLanguage', params as unknown as Record<string, unknown>)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Detect PII entities in text
|
|
556
|
+
*/
|
|
557
|
+
async detectPiiEntities(params: DetectPiiEntitiesCommandInput): Promise<DetectPiiEntitiesCommandOutput> {
|
|
558
|
+
return this.request('DetectPiiEntities', params as unknown as Record<string, unknown>)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Check if text contains PII
|
|
563
|
+
*/
|
|
564
|
+
async containsPiiEntities(params: ContainsPiiEntitiesCommandInput): Promise<ContainsPiiEntitiesCommandOutput> {
|
|
565
|
+
return this.request('ContainsPiiEntities', params as unknown as Record<string, unknown>)
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Detect syntax (parts of speech) in text
|
|
570
|
+
*/
|
|
571
|
+
async detectSyntax(params: DetectSyntaxCommandInput): Promise<DetectSyntaxCommandOutput> {
|
|
572
|
+
return this.request('DetectSyntax', params as unknown as Record<string, unknown>)
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Detect targeted sentiment (sentiment per entity)
|
|
577
|
+
*/
|
|
578
|
+
async detectTargetedSentiment(params: DetectTargetedSentimentCommandInput): Promise<DetectTargetedSentimentCommandOutput> {
|
|
579
|
+
return this.request('DetectTargetedSentiment', params as unknown as Record<string, unknown>)
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Classify a document using a custom endpoint
|
|
584
|
+
*/
|
|
585
|
+
async classifyDocument(params: ClassifyDocumentCommandInput): Promise<ClassifyDocumentCommandOutput> {
|
|
586
|
+
return this.request('ClassifyDocument', params as unknown as Record<string, unknown>)
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// -------------------------------------------------------------------------
|
|
590
|
+
// Batch Operations
|
|
591
|
+
// -------------------------------------------------------------------------
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Batch detect sentiment
|
|
595
|
+
*/
|
|
596
|
+
async batchDetectSentiment(params: BatchDetectSentimentCommandInput): Promise<BatchDetectSentimentCommandOutput> {
|
|
597
|
+
return this.request('BatchDetectSentiment', params as unknown as Record<string, unknown>)
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Batch detect entities
|
|
602
|
+
*/
|
|
603
|
+
async batchDetectEntities(params: BatchDetectEntitiesCommandInput): Promise<BatchDetectEntitiesCommandOutput> {
|
|
604
|
+
return this.request('BatchDetectEntities', params as unknown as Record<string, unknown>)
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Batch detect key phrases
|
|
609
|
+
*/
|
|
610
|
+
async batchDetectKeyPhrases(params: BatchDetectKeyPhrasesCommandInput): Promise<BatchDetectKeyPhrasesCommandOutput> {
|
|
611
|
+
return this.request('BatchDetectKeyPhrases', params as unknown as Record<string, unknown>)
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Batch detect dominant language
|
|
616
|
+
*/
|
|
617
|
+
async batchDetectDominantLanguage(params: BatchDetectDominantLanguageCommandInput): Promise<BatchDetectDominantLanguageCommandOutput> {
|
|
618
|
+
return this.request('BatchDetectDominantLanguage', params as unknown as Record<string, unknown>)
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Batch detect syntax
|
|
623
|
+
*/
|
|
624
|
+
async batchDetectSyntax(params: BatchDetectSyntaxCommandInput): Promise<BatchDetectSyntaxCommandOutput> {
|
|
625
|
+
return this.request('BatchDetectSyntax', params as unknown as Record<string, unknown>)
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// -------------------------------------------------------------------------
|
|
629
|
+
// Async Job Operations
|
|
630
|
+
// -------------------------------------------------------------------------
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Start an async sentiment detection job
|
|
634
|
+
*/
|
|
635
|
+
async startSentimentDetectionJob(params: StartSentimentDetectionJobCommandInput): Promise<StartSentimentDetectionJobCommandOutput> {
|
|
636
|
+
return this.request('StartSentimentDetectionJob', params as unknown as Record<string, unknown>)
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Start an async entities detection job
|
|
641
|
+
*/
|
|
642
|
+
async startEntitiesDetectionJob(params: StartEntitiesDetectionJobCommandInput): Promise<StartEntitiesDetectionJobCommandOutput> {
|
|
643
|
+
return this.request('StartEntitiesDetectionJob', params as unknown as Record<string, unknown>)
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Start an async key phrases detection job
|
|
648
|
+
*/
|
|
649
|
+
async startKeyPhrasesDetectionJob(params: StartKeyPhrasesDetectionJobCommandInput): Promise<StartKeyPhrasesDetectionJobCommandOutput> {
|
|
650
|
+
return this.request('StartKeyPhrasesDetectionJob', params as unknown as Record<string, unknown>)
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Start an async PII entities detection job
|
|
655
|
+
*/
|
|
656
|
+
async startPiiEntitiesDetectionJob(params: StartPiiEntitiesDetectionJobCommandInput): Promise<StartPiiEntitiesDetectionJobCommandOutput> {
|
|
657
|
+
return this.request('StartPiiEntitiesDetectionJob', params as unknown as Record<string, unknown>)
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Describe a sentiment detection job
|
|
662
|
+
*/
|
|
663
|
+
async describeSentimentDetectionJob(params: DescribeSentimentDetectionJobCommandInput): Promise<DescribeSentimentDetectionJobCommandOutput> {
|
|
664
|
+
return this.request('DescribeSentimentDetectionJob', params as unknown as Record<string, unknown>)
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// -------------------------------------------------------------------------
|
|
668
|
+
// Convenience Methods
|
|
669
|
+
// -------------------------------------------------------------------------
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Simple sentiment analysis
|
|
673
|
+
*/
|
|
674
|
+
async analyzeSentiment(text: string, languageCode: string = 'en'): Promise<{
|
|
675
|
+
sentiment: 'POSITIVE' | 'NEGATIVE' | 'NEUTRAL' | 'MIXED'
|
|
676
|
+
scores: { positive: number; negative: number; neutral: number; mixed: number }
|
|
677
|
+
}> {
|
|
678
|
+
const result = await this.detectSentiment({
|
|
679
|
+
Text: text,
|
|
680
|
+
LanguageCode: languageCode as DetectSentimentCommandInput['LanguageCode'],
|
|
681
|
+
})
|
|
682
|
+
return {
|
|
683
|
+
sentiment: result.Sentiment,
|
|
684
|
+
scores: {
|
|
685
|
+
positive: result.SentimentScore.Positive,
|
|
686
|
+
negative: result.SentimentScore.Negative,
|
|
687
|
+
neutral: result.SentimentScore.Neutral,
|
|
688
|
+
mixed: result.SentimentScore.Mixed,
|
|
689
|
+
},
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Extract entities from text
|
|
695
|
+
*/
|
|
696
|
+
async extractEntities(text: string, languageCode: string = 'en'): Promise<Array<{
|
|
697
|
+
text: string
|
|
698
|
+
type: string
|
|
699
|
+
score: number
|
|
700
|
+
}>> {
|
|
701
|
+
const result = await this.detectEntities({
|
|
702
|
+
Text: text,
|
|
703
|
+
LanguageCode: languageCode,
|
|
704
|
+
})
|
|
705
|
+
return result.Entities.map(e => ({
|
|
706
|
+
text: e.Text || '',
|
|
707
|
+
type: e.Type || 'UNKNOWN',
|
|
708
|
+
score: e.Score || 0,
|
|
709
|
+
}))
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* Extract key phrases from text
|
|
714
|
+
*/
|
|
715
|
+
async extractKeyPhrases(text: string, languageCode: string = 'en'): Promise<string[]> {
|
|
716
|
+
const result = await this.detectKeyPhrases({
|
|
717
|
+
Text: text,
|
|
718
|
+
LanguageCode: languageCode,
|
|
719
|
+
})
|
|
720
|
+
return result.KeyPhrases.map(kp => kp.Text || '').filter(Boolean)
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/**
|
|
724
|
+
* Detect language of text
|
|
725
|
+
*/
|
|
726
|
+
async detectLanguage(text: string): Promise<{ languageCode: string; confidence: number }> {
|
|
727
|
+
const result = await this.detectDominantLanguage({ Text: text })
|
|
728
|
+
const dominant = result.Languages[0]
|
|
729
|
+
return {
|
|
730
|
+
languageCode: dominant?.LanguageCode || 'unknown',
|
|
731
|
+
confidence: dominant?.Score || 0,
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Find PII in text
|
|
737
|
+
*/
|
|
738
|
+
async findPii(text: string, languageCode: string = 'en'): Promise<Array<{
|
|
739
|
+
type: string
|
|
740
|
+
beginOffset: number
|
|
741
|
+
endOffset: number
|
|
742
|
+
score: number
|
|
743
|
+
}>> {
|
|
744
|
+
const result = await this.detectPiiEntities({
|
|
745
|
+
Text: text,
|
|
746
|
+
LanguageCode: languageCode,
|
|
747
|
+
})
|
|
748
|
+
return result.Entities.map(e => ({
|
|
749
|
+
type: e.Type || 'UNKNOWN',
|
|
750
|
+
beginOffset: e.BeginOffset || 0,
|
|
751
|
+
endOffset: e.EndOffset || 0,
|
|
752
|
+
score: e.Score || 0,
|
|
753
|
+
}))
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Check if text contains any PII
|
|
758
|
+
*/
|
|
759
|
+
async hasPii(text: string, languageCode: string = 'en'): Promise<boolean> {
|
|
760
|
+
const result = await this.detectPiiEntities({
|
|
761
|
+
Text: text,
|
|
762
|
+
LanguageCode: languageCode,
|
|
763
|
+
})
|
|
764
|
+
return result.Entities.length > 0
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Redact PII from text (replaces PII with [TYPE])
|
|
769
|
+
*/
|
|
770
|
+
async redactPii(text: string, languageCode: string = 'en'): Promise<string> {
|
|
771
|
+
const result = await this.detectPiiEntities({
|
|
772
|
+
Text: text,
|
|
773
|
+
LanguageCode: languageCode,
|
|
774
|
+
})
|
|
775
|
+
|
|
776
|
+
// Sort by end offset descending to replace from end to start
|
|
777
|
+
const sorted = [...result.Entities].sort((a, b) => (b.EndOffset || 0) - (a.EndOffset || 0))
|
|
778
|
+
|
|
779
|
+
let redacted = text
|
|
780
|
+
for (const entity of sorted) {
|
|
781
|
+
if (entity.BeginOffset !== undefined && entity.EndOffset !== undefined) {
|
|
782
|
+
redacted = redacted.slice(0, entity.BeginOffset) + `[${entity.Type}]` + redacted.slice(entity.EndOffset)
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
return redacted
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// ============================================================================
|
|
791
|
+
// Helper Functions
|
|
792
|
+
// ============================================================================
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Quick sentiment analysis
|
|
796
|
+
*/
|
|
797
|
+
export async function analyzeSentiment(
|
|
798
|
+
text: string,
|
|
799
|
+
options?: { languageCode?: string; region?: string },
|
|
800
|
+
): Promise<{ sentiment: string; confidence: number }> {
|
|
801
|
+
const client = new ComprehendClient(options?.region || 'us-east-1')
|
|
802
|
+
const result = await client.analyzeSentiment(text, options?.languageCode || 'en')
|
|
803
|
+
const maxScore = Math.max(result.scores.positive, result.scores.negative, result.scores.neutral, result.scores.mixed)
|
|
804
|
+
return { sentiment: result.sentiment, confidence: maxScore }
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Quick entity extraction
|
|
809
|
+
*/
|
|
810
|
+
export async function extractEntities(
|
|
811
|
+
text: string,
|
|
812
|
+
options?: { languageCode?: string; region?: string },
|
|
813
|
+
): Promise<Array<{ text: string; type: string }>> {
|
|
814
|
+
const client = new ComprehendClient(options?.region || 'us-east-1')
|
|
815
|
+
return client.extractEntities(text, options?.languageCode || 'en')
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Quick language detection
|
|
820
|
+
*/
|
|
821
|
+
export async function detectLanguage(
|
|
822
|
+
text: string,
|
|
823
|
+
region?: string,
|
|
824
|
+
): Promise<string> {
|
|
825
|
+
const client = new ComprehendClient(region || 'us-east-1')
|
|
826
|
+
const result = await client.detectLanguage(text)
|
|
827
|
+
return result.languageCode
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
/**
|
|
831
|
+
* Quick PII check
|
|
832
|
+
*/
|
|
833
|
+
export async function containsPii(
|
|
834
|
+
text: string,
|
|
835
|
+
options?: { languageCode?: string; region?: string },
|
|
836
|
+
): Promise<boolean> {
|
|
837
|
+
const client = new ComprehendClient(options?.region || 'us-east-1')
|
|
838
|
+
return client.hasPii(text, options?.languageCode || 'en')
|
|
839
|
+
}
|