@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
@@ -1,780 +0,0 @@
1
- /**
2
- * AWS Textract Client
3
- * Document OCR, form extraction, table extraction
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 S3Object {
14
- Bucket?: string
15
- Name?: string
16
- Version?: string
17
- }
18
-
19
- export interface Document {
20
- Bytes?: Uint8Array
21
- S3Object?: S3Object
22
- }
23
-
24
- export interface BoundingBox {
25
- Width?: number
26
- Height?: number
27
- Left?: number
28
- Top?: number
29
- }
30
-
31
- export interface Point {
32
- X?: number
33
- Y?: number
34
- }
35
-
36
- export interface Geometry {
37
- BoundingBox?: BoundingBox
38
- Polygon?: Point[]
39
- }
40
-
41
- export interface Relationship {
42
- Type?: 'VALUE' | 'CHILD' | 'COMPLEX_FEATURES' | 'MERGED_CELL' | 'TITLE' | 'ANSWER' | 'TABLE' | 'TABLE_TITLE' | 'TABLE_FOOTER'
43
- Ids?: string[]
44
- }
45
-
46
- export interface Block {
47
- BlockType?: 'KEY_VALUE_SET' | 'PAGE' | 'LINE' | 'WORD' | 'TABLE' | 'CELL' | 'SELECTION_ELEMENT' | 'MERGED_CELL' | 'TITLE' | 'QUERY' | 'QUERY_RESULT' | 'SIGNATURE' | 'TABLE_TITLE' | 'TABLE_FOOTER' | 'LAYOUT_TEXT' | 'LAYOUT_TITLE' | 'LAYOUT_HEADER' | 'LAYOUT_FOOTER' | 'LAYOUT_SECTION_HEADER' | 'LAYOUT_PAGE_NUMBER' | 'LAYOUT_LIST' | 'LAYOUT_FIGURE' | 'LAYOUT_TABLE' | 'LAYOUT_KEY_VALUE'
48
- Confidence?: number
49
- Text?: string
50
- TextType?: 'HANDWRITING' | 'PRINTED'
51
- RowIndex?: number
52
- ColumnIndex?: number
53
- RowSpan?: number
54
- ColumnSpan?: number
55
- Geometry?: Geometry
56
- Id?: string
57
- Relationships?: Relationship[]
58
- EntityTypes?: ('KEY' | 'VALUE' | 'COLUMN_HEADER' | 'TABLE_TITLE' | 'TABLE_FOOTER' | 'TABLE_SECTION_TITLE' | 'TABLE_SUMMARY' | 'STRUCTURED_TABLE' | 'SEMI_STRUCTURED_TABLE')[]
59
- SelectionStatus?: 'SELECTED' | 'NOT_SELECTED'
60
- Page?: number
61
- Query?: {
62
- Text: string
63
- Alias?: string
64
- Pages?: string[]
65
- }
66
- }
67
-
68
- export interface DocumentMetadata {
69
- Pages?: number
70
- }
71
-
72
- export interface Warning {
73
- ErrorCode?: string
74
- Pages?: number[]
75
- }
76
-
77
- export interface DetectDocumentTextCommandInput {
78
- Document: Document
79
- }
80
-
81
- export interface DetectDocumentTextCommandOutput {
82
- DocumentMetadata?: DocumentMetadata
83
- Blocks?: Block[]
84
- DetectDocumentTextModelVersion?: string
85
- }
86
-
87
- export interface AnalyzeDocumentCommandInput {
88
- Document: Document
89
- FeatureTypes: ('TABLES' | 'FORMS' | 'QUERIES' | 'SIGNATURES' | 'LAYOUT')[]
90
- HumanLoopConfig?: {
91
- HumanLoopName: string
92
- FlowDefinitionArn: string
93
- DataAttributes?: {
94
- ContentClassifiers?: ('FreeOfPersonallyIdentifiableInformation' | 'FreeOfAdultContent')[]
95
- }
96
- }
97
- QueriesConfig?: {
98
- Queries: Array<{
99
- Text: string
100
- Alias?: string
101
- Pages?: string[]
102
- }>
103
- }
104
- AdaptersConfig?: {
105
- Adapters: Array<{
106
- AdapterId: string
107
- Pages?: string[]
108
- Version: string
109
- }>
110
- }
111
- }
112
-
113
- export interface AnalyzeDocumentCommandOutput {
114
- DocumentMetadata?: DocumentMetadata
115
- Blocks?: Block[]
116
- HumanLoopActivationOutput?: {
117
- HumanLoopArn?: string
118
- HumanLoopActivationReasons?: string[]
119
- HumanLoopActivationConditionsEvaluationResults?: string
120
- }
121
- AnalyzeDocumentModelVersion?: string
122
- }
123
-
124
- export interface AnalyzeExpenseCommandInput {
125
- Document: Document
126
- }
127
-
128
- export interface ExpenseField {
129
- Type?: {
130
- Text?: string
131
- Confidence?: number
132
- }
133
- LabelDetection?: {
134
- Text?: string
135
- Geometry?: Geometry
136
- Confidence?: number
137
- }
138
- ValueDetection?: {
139
- Text?: string
140
- Geometry?: Geometry
141
- Confidence?: number
142
- }
143
- PageNumber?: number
144
- Currency?: {
145
- Code?: string
146
- Confidence?: number
147
- }
148
- GroupProperties?: Array<{
149
- Types?: string[]
150
- Id?: string
151
- }>
152
- }
153
-
154
- export interface LineItemGroup {
155
- LineItemGroupIndex?: number
156
- LineItems?: Array<{
157
- LineItemExpenseFields?: ExpenseField[]
158
- }>
159
- }
160
-
161
- export interface ExpenseDocument {
162
- ExpenseIndex?: number
163
- SummaryFields?: ExpenseField[]
164
- LineItemGroups?: LineItemGroup[]
165
- Blocks?: Block[]
166
- }
167
-
168
- export interface AnalyzeExpenseCommandOutput {
169
- DocumentMetadata?: DocumentMetadata
170
- ExpenseDocuments?: ExpenseDocument[]
171
- }
172
-
173
- export interface AnalyzeIDCommandInput {
174
- DocumentPages: Document[]
175
- }
176
-
177
- export interface IdentityDocument {
178
- DocumentIndex?: number
179
- IdentityDocumentFields?: Array<{
180
- Type?: {
181
- Text?: string
182
- Confidence?: number
183
- }
184
- ValueDetection?: {
185
- Text?: string
186
- NormalizedValue?: {
187
- Value?: string
188
- ValueType?: 'DATE'
189
- }
190
- Confidence?: number
191
- }
192
- }>
193
- Blocks?: Block[]
194
- }
195
-
196
- export interface AnalyzeIDCommandOutput {
197
- IdentityDocuments?: IdentityDocument[]
198
- DocumentMetadata?: DocumentMetadata
199
- AnalyzeIDModelVersion?: string
200
- }
201
-
202
- export interface StartDocumentTextDetectionCommandInput {
203
- DocumentLocation: {
204
- S3Object?: S3Object
205
- }
206
- ClientRequestToken?: string
207
- JobTag?: string
208
- NotificationChannel?: {
209
- SNSTopicArn: string
210
- RoleArn: string
211
- }
212
- OutputConfig?: {
213
- S3Bucket: string
214
- S3Prefix?: string
215
- }
216
- KMSKeyId?: string
217
- }
218
-
219
- export interface StartDocumentTextDetectionCommandOutput {
220
- JobId?: string
221
- }
222
-
223
- export interface GetDocumentTextDetectionCommandInput {
224
- JobId: string
225
- MaxResults?: number
226
- NextToken?: string
227
- }
228
-
229
- export interface GetDocumentTextDetectionCommandOutput {
230
- DocumentMetadata?: DocumentMetadata
231
- JobStatus?: 'IN_PROGRESS' | 'SUCCEEDED' | 'FAILED' | 'PARTIAL_SUCCESS'
232
- NextToken?: string
233
- Blocks?: Block[]
234
- Warnings?: Warning[]
235
- StatusMessage?: string
236
- DetectDocumentTextModelVersion?: string
237
- }
238
-
239
- export interface StartDocumentAnalysisCommandInput {
240
- DocumentLocation: {
241
- S3Object?: S3Object
242
- }
243
- FeatureTypes: ('TABLES' | 'FORMS' | 'QUERIES' | 'SIGNATURES' | 'LAYOUT')[]
244
- ClientRequestToken?: string
245
- JobTag?: string
246
- NotificationChannel?: {
247
- SNSTopicArn: string
248
- RoleArn: string
249
- }
250
- OutputConfig?: {
251
- S3Bucket: string
252
- S3Prefix?: string
253
- }
254
- KMSKeyId?: string
255
- QueriesConfig?: {
256
- Queries: Array<{
257
- Text: string
258
- Alias?: string
259
- Pages?: string[]
260
- }>
261
- }
262
- AdaptersConfig?: {
263
- Adapters: Array<{
264
- AdapterId: string
265
- Pages?: string[]
266
- Version: string
267
- }>
268
- }
269
- }
270
-
271
- export interface StartDocumentAnalysisCommandOutput {
272
- JobId?: string
273
- }
274
-
275
- export interface GetDocumentAnalysisCommandInput {
276
- JobId: string
277
- MaxResults?: number
278
- NextToken?: string
279
- }
280
-
281
- export interface GetDocumentAnalysisCommandOutput {
282
- DocumentMetadata?: DocumentMetadata
283
- JobStatus?: 'IN_PROGRESS' | 'SUCCEEDED' | 'FAILED' | 'PARTIAL_SUCCESS'
284
- NextToken?: string
285
- Blocks?: Block[]
286
- Warnings?: Warning[]
287
- StatusMessage?: string
288
- AnalyzeDocumentModelVersion?: string
289
- }
290
-
291
- export interface StartExpenseAnalysisCommandInput {
292
- DocumentLocation: {
293
- S3Object?: S3Object
294
- }
295
- ClientRequestToken?: string
296
- JobTag?: string
297
- NotificationChannel?: {
298
- SNSTopicArn: string
299
- RoleArn: string
300
- }
301
- OutputConfig?: {
302
- S3Bucket: string
303
- S3Prefix?: string
304
- }
305
- KMSKeyId?: string
306
- }
307
-
308
- export interface StartExpenseAnalysisCommandOutput {
309
- JobId?: string
310
- }
311
-
312
- export interface GetExpenseAnalysisCommandInput {
313
- JobId: string
314
- MaxResults?: number
315
- NextToken?: string
316
- }
317
-
318
- export interface GetExpenseAnalysisCommandOutput {
319
- DocumentMetadata?: DocumentMetadata
320
- JobStatus?: 'IN_PROGRESS' | 'SUCCEEDED' | 'FAILED' | 'PARTIAL_SUCCESS'
321
- NextToken?: string
322
- ExpenseDocuments?: ExpenseDocument[]
323
- Warnings?: Warning[]
324
- StatusMessage?: string
325
- AnalyzeExpenseModelVersion?: string
326
- }
327
-
328
- export interface StartLendingAnalysisCommandInput {
329
- DocumentLocation: {
330
- S3Object?: S3Object
331
- }
332
- ClientRequestToken?: string
333
- JobTag?: string
334
- NotificationChannel?: {
335
- SNSTopicArn: string
336
- RoleArn: string
337
- }
338
- OutputConfig?: {
339
- S3Bucket: string
340
- S3Prefix?: string
341
- }
342
- KMSKeyId?: string
343
- }
344
-
345
- export interface StartLendingAnalysisCommandOutput {
346
- JobId?: string
347
- }
348
-
349
- export interface GetLendingAnalysisCommandInput {
350
- JobId: string
351
- MaxResults?: number
352
- NextToken?: string
353
- }
354
-
355
- export interface LendingDocument {
356
- LendingFields?: Array<{
357
- Type?: string
358
- KeyDetection?: {
359
- Text?: string
360
- Geometry?: Geometry
361
- Confidence?: number
362
- }
363
- ValueDetections?: Array<{
364
- Text?: string
365
- Geometry?: Geometry
366
- Confidence?: number
367
- SelectionStatus?: 'SELECTED' | 'NOT_SELECTED'
368
- }>
369
- }>
370
- SignatureDetections?: Array<{
371
- Confidence?: number
372
- Geometry?: Geometry
373
- }>
374
- }
375
-
376
- export interface LendingResult {
377
- Page?: number
378
- PageClassification?: {
379
- PageType?: Array<{
380
- Value?: string
381
- Confidence?: number
382
- }>
383
- PageNumber?: Array<{
384
- Value?: string
385
- Confidence?: number
386
- }>
387
- }
388
- Extractions?: Array<{
389
- LendingDocument?: LendingDocument
390
- ExpenseDocument?: ExpenseDocument
391
- IdentityDocument?: IdentityDocument
392
- }>
393
- }
394
-
395
- export interface GetLendingAnalysisCommandOutput {
396
- DocumentMetadata?: DocumentMetadata
397
- JobStatus?: 'IN_PROGRESS' | 'SUCCEEDED' | 'FAILED' | 'PARTIAL_SUCCESS'
398
- NextToken?: string
399
- Results?: LendingResult[]
400
- Warnings?: Warning[]
401
- StatusMessage?: string
402
- AnalyzeLendingModelVersion?: string
403
- }
404
-
405
- // ============================================================================
406
- // Textract Client
407
- // ============================================================================
408
-
409
- export class TextractClient {
410
- private client: AWSClient
411
- private region: string
412
-
413
- constructor(region: string = 'us-east-1') {
414
- this.region = region
415
- this.client = new AWSClient()
416
- }
417
-
418
- private async request<T>(action: string, params: Record<string, unknown>): Promise<T> {
419
- return this.client.request({
420
- service: 'textract',
421
- region: this.region,
422
- method: 'POST',
423
- path: '/',
424
- headers: {
425
- 'Content-Type': 'application/x-amz-json-1.1',
426
- 'X-Amz-Target': `Textract.${action}`,
427
- },
428
- body: JSON.stringify(params),
429
- })
430
- }
431
-
432
- // -------------------------------------------------------------------------
433
- // Synchronous Operations
434
- // -------------------------------------------------------------------------
435
-
436
- /**
437
- * Detect text in a document (OCR)
438
- */
439
- async detectDocumentText(params: DetectDocumentTextCommandInput): Promise<DetectDocumentTextCommandOutput> {
440
- return this.request('DetectDocumentText', params as unknown as Record<string, unknown>)
441
- }
442
-
443
- /**
444
- * Analyze a document (forms, tables, queries)
445
- */
446
- async analyzeDocument(params: AnalyzeDocumentCommandInput): Promise<AnalyzeDocumentCommandOutput> {
447
- return this.request('AnalyzeDocument', params as unknown as Record<string, unknown>)
448
- }
449
-
450
- /**
451
- * Analyze expense document (receipts, invoices)
452
- */
453
- async analyzeExpense(params: AnalyzeExpenseCommandInput): Promise<AnalyzeExpenseCommandOutput> {
454
- return this.request('AnalyzeExpense', params as unknown as Record<string, unknown>)
455
- }
456
-
457
- /**
458
- * Analyze ID document (driver's license, passport)
459
- */
460
- async analyzeID(params: AnalyzeIDCommandInput): Promise<AnalyzeIDCommandOutput> {
461
- return this.request('AnalyzeID', params as unknown as Record<string, unknown>)
462
- }
463
-
464
- // -------------------------------------------------------------------------
465
- // Asynchronous Operations
466
- // -------------------------------------------------------------------------
467
-
468
- /**
469
- * Start async text detection job
470
- */
471
- async startDocumentTextDetection(params: StartDocumentTextDetectionCommandInput): Promise<StartDocumentTextDetectionCommandOutput> {
472
- return this.request('StartDocumentTextDetection', params as unknown as Record<string, unknown>)
473
- }
474
-
475
- /**
476
- * Get results of text detection job
477
- */
478
- async getDocumentTextDetection(params: GetDocumentTextDetectionCommandInput): Promise<GetDocumentTextDetectionCommandOutput> {
479
- return this.request('GetDocumentTextDetection', params as unknown as Record<string, unknown>)
480
- }
481
-
482
- /**
483
- * Start async document analysis job
484
- */
485
- async startDocumentAnalysis(params: StartDocumentAnalysisCommandInput): Promise<StartDocumentAnalysisCommandOutput> {
486
- return this.request('StartDocumentAnalysis', params as unknown as Record<string, unknown>)
487
- }
488
-
489
- /**
490
- * Get results of document analysis job
491
- */
492
- async getDocumentAnalysis(params: GetDocumentAnalysisCommandInput): Promise<GetDocumentAnalysisCommandOutput> {
493
- return this.request('GetDocumentAnalysis', params as unknown as Record<string, unknown>)
494
- }
495
-
496
- /**
497
- * Start async expense analysis job
498
- */
499
- async startExpenseAnalysis(params: StartExpenseAnalysisCommandInput): Promise<StartExpenseAnalysisCommandOutput> {
500
- return this.request('StartExpenseAnalysis', params as unknown as Record<string, unknown>)
501
- }
502
-
503
- /**
504
- * Get results of expense analysis job
505
- */
506
- async getExpenseAnalysis(params: GetExpenseAnalysisCommandInput): Promise<GetExpenseAnalysisCommandOutput> {
507
- return this.request('GetExpenseAnalysis', params as unknown as Record<string, unknown>)
508
- }
509
-
510
- /**
511
- * Start async lending analysis job
512
- */
513
- async startLendingAnalysis(params: StartLendingAnalysisCommandInput): Promise<StartLendingAnalysisCommandOutput> {
514
- return this.request('StartLendingAnalysis', params as unknown as Record<string, unknown>)
515
- }
516
-
517
- /**
518
- * Get results of lending analysis job
519
- */
520
- async getLendingAnalysis(params: GetLendingAnalysisCommandInput): Promise<GetLendingAnalysisCommandOutput> {
521
- return this.request('GetLendingAnalysis', params as unknown as Record<string, unknown>)
522
- }
523
-
524
- // -------------------------------------------------------------------------
525
- // Convenience Methods
526
- // -------------------------------------------------------------------------
527
-
528
- /**
529
- * Extract all text from a document
530
- */
531
- async extractText(document: Document): Promise<string[]> {
532
- const result = await this.detectDocumentText({ Document: document })
533
- return result.Blocks?.filter(b => b.BlockType === 'LINE').map(b => b.Text || '') || []
534
- }
535
-
536
- /**
537
- * Extract text from S3 document
538
- */
539
- async extractTextFromS3(bucket: string, key: string): Promise<string[]> {
540
- return this.extractText({ S3Object: { Bucket: bucket, Name: key } })
541
- }
542
-
543
- /**
544
- * Extract key-value pairs (forms) from a document
545
- */
546
- async extractForms(document: Document): Promise<Array<{ key: string; value: string; confidence: number }>> {
547
- const result = await this.analyzeDocument({
548
- Document: document,
549
- FeatureTypes: ['FORMS'],
550
- })
551
-
552
- const blocks = result.Blocks || []
553
- const blockMap = new Map<string, Block>()
554
- blocks.forEach(b => b.Id && blockMap.set(b.Id, b))
555
-
556
- const forms: Array<{ key: string; value: string; confidence: number }> = []
557
-
558
- for (const block of blocks) {
559
- if (block.BlockType === 'KEY_VALUE_SET' && block.EntityTypes?.includes('KEY')) {
560
- const keyText = this.getBlockText(block, blockMap)
561
- const valueBlock = block.Relationships?.find(r => r.Type === 'VALUE')
562
- let valueText = ''
563
- if (valueBlock?.Ids) {
564
- for (const id of valueBlock.Ids) {
565
- const vb = blockMap.get(id)
566
- if (vb) valueText += this.getBlockText(vb, blockMap) + ' '
567
- }
568
- }
569
- forms.push({
570
- key: keyText.trim(),
571
- value: valueText.trim(),
572
- confidence: block.Confidence || 0,
573
- })
574
- }
575
- }
576
-
577
- return forms
578
- }
579
-
580
- /**
581
- * Extract tables from a document
582
- */
583
- async extractTables(document: Document): Promise<Array<{ rows: string[][] }>> {
584
- const result = await this.analyzeDocument({
585
- Document: document,
586
- FeatureTypes: ['TABLES'],
587
- })
588
-
589
- const blocks = result.Blocks || []
590
- const blockMap = new Map<string, Block>()
591
- blocks.forEach(b => b.Id && blockMap.set(b.Id, b))
592
-
593
- const tables: Array<{ rows: string[][] }> = []
594
-
595
- for (const block of blocks) {
596
- if (block.BlockType === 'TABLE') {
597
- const cellIds = block.Relationships?.find(r => r.Type === 'CHILD')?.Ids || []
598
- const cells: Block[] = cellIds.map(id => blockMap.get(id)).filter(Boolean) as Block[]
599
-
600
- // Find max row and column
601
- let maxRow = 0
602
- let maxCol = 0
603
- for (const cell of cells) {
604
- if (cell.RowIndex && cell.RowIndex > maxRow) maxRow = cell.RowIndex
605
- if (cell.ColumnIndex && cell.ColumnIndex > maxCol) maxCol = cell.ColumnIndex
606
- }
607
-
608
- // Build 2D array
609
- const rows: string[][] = Array.from({ length: maxRow }, () => Array.from({ length: maxCol }, () => ''))
610
-
611
- for (const cell of cells) {
612
- if (cell.RowIndex && cell.ColumnIndex) {
613
- rows[cell.RowIndex - 1][cell.ColumnIndex - 1] = this.getBlockText(cell, blockMap)
614
- }
615
- }
616
-
617
- tables.push({ rows })
618
- }
619
- }
620
-
621
- return tables
622
- }
623
-
624
- /**
625
- * Extract expense summary from receipt/invoice
626
- */
627
- async extractExpenseSummary(document: Document): Promise<{
628
- vendor?: string
629
- total?: string
630
- date?: string
631
- items: Array<{ description?: string; quantity?: string; price?: string }>
632
- }> {
633
- const result = await this.analyzeExpense({ Document: document })
634
- const expense = result.ExpenseDocuments?.[0]
635
-
636
- if (!expense) {
637
- return { items: [] }
638
- }
639
-
640
- const summary: { vendor?: string; total?: string; date?: string } = {}
641
-
642
- for (const field of expense.SummaryFields || []) {
643
- const type = field.Type?.Text?.toUpperCase()
644
- const value = field.ValueDetection?.Text
645
-
646
- if (type === 'VENDOR_NAME') summary.vendor = value
647
- if (type === 'TOTAL') summary.total = value
648
- if (type === 'INVOICE_RECEIPT_DATE') summary.date = value
649
- }
650
-
651
- const items: Array<{ description?: string; quantity?: string; price?: string }> = []
652
-
653
- for (const group of expense.LineItemGroups || []) {
654
- for (const lineItem of group.LineItems || []) {
655
- const item: { description?: string; quantity?: string; price?: string } = {}
656
- for (const field of lineItem.LineItemExpenseFields || []) {
657
- const type = field.Type?.Text?.toUpperCase()
658
- const value = field.ValueDetection?.Text
659
-
660
- if (type === 'ITEM') item.description = value
661
- if (type === 'QUANTITY') item.quantity = value
662
- if (type === 'PRICE') item.price = value
663
- }
664
- if (item.description || item.price) items.push(item)
665
- }
666
- }
667
-
668
- return { ...summary, items }
669
- }
670
-
671
- /**
672
- * Answer questions about a document
673
- */
674
- async queryDocument(document: Document, questions: string[]): Promise<Array<{ question: string; answer: string; confidence: number }>> {
675
- const result = await this.analyzeDocument({
676
- Document: document,
677
- FeatureTypes: ['QUERIES'],
678
- QueriesConfig: {
679
- Queries: questions.map(q => ({ Text: q })),
680
- },
681
- })
682
-
683
- const blocks = result.Blocks || []
684
- const answers: Array<{ question: string; answer: string; confidence: number }> = []
685
-
686
- for (const block of blocks) {
687
- if (block.BlockType === 'QUERY_RESULT' && block.Text) {
688
- // Find the corresponding query
689
- const queryBlock = blocks.find(b =>
690
- b.BlockType === 'QUERY' && b.Relationships?.some(r =>
691
- r.Type === 'ANSWER' && r.Ids?.includes(block.Id || ''),
692
- ),
693
- )
694
- answers.push({
695
- question: queryBlock?.Query?.Text || '',
696
- answer: block.Text,
697
- confidence: block.Confidence || 0,
698
- })
699
- }
700
- }
701
-
702
- return answers
703
- }
704
-
705
- /**
706
- * Wait for async job to complete
707
- */
708
- async waitForJob(
709
- jobId: string,
710
- getJob: (jobId: string) => Promise<{ JobStatus?: string }>,
711
- options?: { maxWaitMs?: number; pollIntervalMs?: number },
712
- ): Promise<void> {
713
- const maxWaitMs = options?.maxWaitMs ?? 300000 // 5 minutes
714
- const pollIntervalMs = options?.pollIntervalMs ?? 5000
715
- const startTime = Date.now()
716
-
717
- while (Date.now() - startTime < maxWaitMs) {
718
- const result = await getJob(jobId)
719
- if (result.JobStatus === 'SUCCEEDED' || result.JobStatus === 'PARTIAL_SUCCESS') {
720
- return
721
- }
722
- if (result.JobStatus === 'FAILED') {
723
- throw new Error(`Textract job ${jobId} failed`)
724
- }
725
- await new Promise(resolve => setTimeout(resolve, pollIntervalMs))
726
- }
727
-
728
- throw new Error(`Timeout waiting for Textract job ${jobId}`)
729
- }
730
-
731
- private getBlockText(block: Block, blockMap: Map<string, Block>): string {
732
- if (block.Text) return block.Text
733
-
734
- const childIds = block.Relationships?.find(r => r.Type === 'CHILD')?.Ids || []
735
- return childIds.map(id => blockMap.get(id)?.Text || '').join(' ')
736
- }
737
- }
738
-
739
- // ============================================================================
740
- // Helper Functions
741
- // ============================================================================
742
-
743
- /**
744
- * Quick text extraction from S3 document
745
- */
746
- export async function extractTextFromS3(
747
- bucket: string,
748
- key: string,
749
- region?: string,
750
- ): Promise<string> {
751
- const client = new TextractClient(region || 'us-east-1')
752
- const lines = await client.extractTextFromS3(bucket, key)
753
- return lines.join('\n')
754
- }
755
-
756
- /**
757
- * Quick form extraction from S3 document
758
- */
759
- export async function extractFormsFromS3(
760
- bucket: string,
761
- key: string,
762
- region?: string,
763
- ): Promise<Record<string, string>> {
764
- const client = new TextractClient(region || 'us-east-1')
765
- const forms = await client.extractForms({ S3Object: { Bucket: bucket, Name: key } })
766
- return Object.fromEntries(forms.map(f => [f.key, f.value]))
767
- }
768
-
769
- /**
770
- * Quick table extraction from S3 document
771
- */
772
- export async function extractTablesFromS3(
773
- bucket: string,
774
- key: string,
775
- region?: string,
776
- ): Promise<string[][][]> {
777
- const client = new TextractClient(region || 'us-east-1')
778
- const tables = await client.extractTables({ S3Object: { Bucket: bucket, Name: key } })
779
- return tables.map(t => t.rows)
780
- }