@aws-amplify/predictions 6.0.22 → 6.0.23
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/cjs/Predictions.js +2 -4
- package/dist/cjs/Predictions.js.map +1 -1
- package/dist/cjs/providers/AmazonAIConvertPredictionsProvider.js +9 -9
- package/dist/cjs/providers/AmazonAIConvertPredictionsProvider.js.map +1 -1
- package/dist/cjs/providers/AmazonAIIdentifyPredictionsProvider.js +25 -20
- package/dist/cjs/providers/AmazonAIIdentifyPredictionsProvider.js.map +1 -1
- package/dist/cjs/providers/AmazonAIInterpretPredictionsProvider.js +7 -7
- package/dist/cjs/providers/AmazonAIInterpretPredictionsProvider.js.map +1 -1
- package/dist/cjs/providers/IdentifyTextUtils.js +9 -9
- package/dist/cjs/providers/IdentifyTextUtils.js.map +1 -1
- package/dist/cjs/providers/Utils.js +6 -6
- package/dist/cjs/providers/Utils.js.map +1 -1
- package/dist/cjs/types/Predictions.js +15 -14
- package/dist/cjs/types/Predictions.js.map +1 -1
- package/dist/esm/Predictions.mjs +0 -2
- package/dist/esm/Predictions.mjs.map +1 -1
- package/dist/esm/providers/AmazonAIConvertPredictionsProvider.mjs +9 -9
- package/dist/esm/providers/AmazonAIConvertPredictionsProvider.mjs.map +1 -1
- package/dist/esm/providers/AmazonAIIdentifyPredictionsProvider.d.ts +6 -6
- package/dist/esm/providers/AmazonAIIdentifyPredictionsProvider.mjs +25 -20
- package/dist/esm/providers/AmazonAIIdentifyPredictionsProvider.mjs.map +1 -1
- package/dist/esm/providers/AmazonAIInterpretPredictionsProvider.mjs +7 -7
- package/dist/esm/providers/AmazonAIInterpretPredictionsProvider.mjs.map +1 -1
- package/dist/esm/providers/IdentifyTextUtils.mjs +9 -9
- package/dist/esm/providers/IdentifyTextUtils.mjs.map +1 -1
- package/dist/esm/providers/Utils.mjs +6 -6
- package/dist/esm/providers/Utils.mjs.map +1 -1
- package/dist/esm/types/AWSTypes.d.ts +2 -2
- package/dist/esm/types/Predictions.d.ts +30 -30
- package/dist/esm/types/Predictions.mjs +15 -14
- package/dist/esm/types/Predictions.mjs.map +1 -1
- package/package.json +6 -5
- package/src/Predictions.ts +2 -3
- package/src/providers/AmazonAIConvertPredictionsProvider.ts +20 -10
- package/src/providers/AmazonAIIdentifyPredictionsProvider.ts +41 -26
- package/src/providers/AmazonAIInterpretPredictionsProvider.ts +22 -18
- package/src/providers/IdentifyTextUtils.ts +25 -22
- package/src/providers/Utils.ts +8 -6
- package/src/providers/index.ts +1 -0
- package/src/types/AWSTypes.ts +2 -3
- package/src/types/Predictions.ts +60 -44
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
DetectDocumentTextCommandInput,
|
|
27
27
|
TextractClient,
|
|
28
28
|
} from '@aws-sdk/client-textract';
|
|
29
|
+
|
|
29
30
|
import { PredictionsValidationErrorCode } from '../errors/types/validation';
|
|
30
31
|
import { assertValidationError } from '../errors/utils/assertValidationError';
|
|
31
32
|
import {
|
|
@@ -50,12 +51,8 @@ import {
|
|
|
50
51
|
isStorageSource,
|
|
51
52
|
isValidIdentifyInput,
|
|
52
53
|
} from '../types';
|
|
53
|
-
import {
|
|
54
|
-
|
|
55
|
-
Document,
|
|
56
|
-
Image,
|
|
57
|
-
TextDetectionList,
|
|
58
|
-
} from '../types/AWSTypes';
|
|
54
|
+
import { BlockList, Image, TextDetectionList } from '../types/AWSTypes';
|
|
55
|
+
|
|
59
56
|
import {
|
|
60
57
|
categorizeRekognitionBlocks,
|
|
61
58
|
categorizeTextractBlocks,
|
|
@@ -84,12 +81,15 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
84
81
|
|
|
85
82
|
if (isIdentifyTextInput(input)) {
|
|
86
83
|
logger.debug('identifyText');
|
|
84
|
+
|
|
87
85
|
return this.identifyText(input);
|
|
88
86
|
} else if (isIdentifyLabelsInput(input)) {
|
|
89
87
|
logger.debug('identifyLabels');
|
|
88
|
+
|
|
90
89
|
return this.identifyLabels(input);
|
|
91
90
|
} else {
|
|
92
91
|
logger.debug('identifyEntities');
|
|
92
|
+
|
|
93
93
|
return this.identifyEntities(input);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -102,7 +102,7 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
102
102
|
* @return {Promise<Image>} - Promise resolving to the converted source object.
|
|
103
103
|
*/
|
|
104
104
|
private configureSource(source: IdentifySource): Promise<Image> {
|
|
105
|
-
return new Promise((
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
106
|
if (isStorageSource(source)) {
|
|
107
107
|
const storageConfig = {
|
|
108
108
|
accessLevel: source.level,
|
|
@@ -114,37 +114,44 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
114
114
|
const parser =
|
|
115
115
|
/https:\/\/([a-zA-Z0-9%\-_.]+)\.s3\.[A-Za-z0-9%\-._~]+\/([a-zA-Z0-9%\-._~/]+)\?/;
|
|
116
116
|
const parsedURL = value.url.toString().match(parser) ?? '';
|
|
117
|
-
if (parsedURL.length < 3)
|
|
118
|
-
|
|
117
|
+
if (parsedURL.length < 3)
|
|
118
|
+
reject(new Error('Invalid S3 key was given.'));
|
|
119
|
+
resolve({
|
|
119
120
|
S3Object: {
|
|
120
121
|
Bucket: parsedURL[1],
|
|
121
122
|
Name: decodeURIComponent(parsedURL[2]),
|
|
122
123
|
},
|
|
123
124
|
});
|
|
124
125
|
})
|
|
125
|
-
.catch(err =>
|
|
126
|
+
.catch(err => {
|
|
127
|
+
reject(err);
|
|
128
|
+
});
|
|
126
129
|
} else if (isFileSource(source)) {
|
|
127
130
|
blobToArrayBuffer(source.file)
|
|
128
131
|
.then(buffer => {
|
|
129
|
-
|
|
132
|
+
resolve({ Bytes: new Uint8Array(buffer) });
|
|
130
133
|
})
|
|
131
|
-
.catch(err =>
|
|
134
|
+
.catch(err => {
|
|
135
|
+
reject(err);
|
|
136
|
+
});
|
|
132
137
|
} else if (isIdentifyBytesSource(source)) {
|
|
133
|
-
const bytes = source
|
|
138
|
+
const { bytes } = source;
|
|
134
139
|
if (bytes instanceof Blob) {
|
|
135
140
|
blobToArrayBuffer(bytes)
|
|
136
141
|
.then(buffer => {
|
|
137
|
-
|
|
142
|
+
resolve({ Bytes: new Uint8Array(buffer) });
|
|
138
143
|
})
|
|
139
|
-
.catch(err =>
|
|
144
|
+
.catch(err => {
|
|
145
|
+
reject(err);
|
|
146
|
+
});
|
|
140
147
|
}
|
|
141
148
|
if (bytes instanceof ArrayBuffer || bytes instanceof Buffer) {
|
|
142
|
-
|
|
149
|
+
resolve({ Bytes: new Uint8Array(bytes) } as Image);
|
|
143
150
|
}
|
|
144
151
|
// everything else can be directly passed to Rekognition / Textract.
|
|
145
|
-
|
|
152
|
+
resolve({ Bytes: bytes } as Image);
|
|
146
153
|
} else {
|
|
147
|
-
|
|
154
|
+
reject(new Error('Input source is not configured correctly.'));
|
|
148
155
|
}
|
|
149
156
|
});
|
|
150
157
|
}
|
|
@@ -179,9 +186,8 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
179
186
|
credentials,
|
|
180
187
|
customUserAgent: _getPredictionsIdentifyAmplifyUserAgent(),
|
|
181
188
|
});
|
|
182
|
-
let inputDocument: Document;
|
|
183
189
|
|
|
184
|
-
inputDocument = await this.configureSource(input.text?.source);
|
|
190
|
+
const inputDocument = await this.configureSource(input.text?.source);
|
|
185
191
|
|
|
186
192
|
// get default value if format isn't specified in the input.
|
|
187
193
|
const format = input.text?.format ?? configFormat;
|
|
@@ -237,6 +243,7 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
237
243
|
|
|
238
244
|
const analyzeDocumentCommand = new AnalyzeDocumentCommand(param);
|
|
239
245
|
const { Blocks } = await this.textractClient.send(analyzeDocumentCommand);
|
|
246
|
+
|
|
240
247
|
return categorizeTextractBlocks(Blocks as BlockList);
|
|
241
248
|
}
|
|
242
249
|
}
|
|
@@ -285,14 +292,15 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
285
292
|
data.forEach(val => {
|
|
286
293
|
identifyResult = { ...identifyResult, ...val };
|
|
287
294
|
});
|
|
295
|
+
|
|
288
296
|
return identifyResult;
|
|
289
297
|
});
|
|
290
298
|
}
|
|
291
299
|
|
|
292
300
|
/**
|
|
293
301
|
* Calls Rekognition.detectLabels and organizes the returned data.
|
|
294
|
-
* @param
|
|
295
|
-
* @return
|
|
302
|
+
* @param param - parameters as {@link DetectLabelsCommandInput} to be passed onto Rekognition
|
|
303
|
+
* @return a promise resolving to organized detectLabels response as {@link IdentifyLabelsOutput}.
|
|
296
304
|
*/
|
|
297
305
|
private async detectLabels(
|
|
298
306
|
param: DetectLabelsCommandInput,
|
|
@@ -306,6 +314,7 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
306
314
|
instance =>
|
|
307
315
|
makeCamelCase(instance.BoundingBox) as BoundingBox | undefined,
|
|
308
316
|
) || [];
|
|
317
|
+
|
|
309
318
|
return {
|
|
310
319
|
name: label.Name,
|
|
311
320
|
boundingBoxes: boxes,
|
|
@@ -315,13 +324,14 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
315
324
|
},
|
|
316
325
|
};
|
|
317
326
|
});
|
|
327
|
+
|
|
318
328
|
return { labels: detectLabelData };
|
|
319
329
|
}
|
|
320
330
|
|
|
321
331
|
/**
|
|
322
332
|
* Calls Rekognition.detectModerationLabels and organizes the returned data.
|
|
323
|
-
* @param
|
|
324
|
-
* @return
|
|
333
|
+
* @param param parameter to be passed onto Rekognition as {@link DetectModerationLabelsCommandInput}
|
|
334
|
+
* @return a promise resolving to organized detectModerationLabels response as {@link IdentifyLabelsOutput}.
|
|
325
335
|
*/
|
|
326
336
|
private async detectModerationLabels(
|
|
327
337
|
param: DetectModerationLabelsCommandInput,
|
|
@@ -342,8 +352,8 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
342
352
|
/**
|
|
343
353
|
* Identify faces within an image that is provided as input, and match faces from a collection
|
|
344
354
|
* or identify celebrities.
|
|
345
|
-
* @param
|
|
346
|
-
* @return
|
|
355
|
+
* @param input - object of {@link IdentifyEntitiesInput} containing the source image and face match options.
|
|
356
|
+
* @return a promise resolving to identify results as {@link IdentifyEntitiesOutput}.
|
|
347
357
|
*/
|
|
348
358
|
protected async identifyEntities(
|
|
349
359
|
input: IdentifyEntitiesInput,
|
|
@@ -401,6 +411,7 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
401
411
|
},
|
|
402
412
|
}) as IdentifyEntity,
|
|
403
413
|
) ?? [];
|
|
414
|
+
|
|
404
415
|
return { entities: faces };
|
|
405
416
|
} else if (
|
|
406
417
|
isIdentifyFromCollection(input.entities) &&
|
|
@@ -425,6 +436,7 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
425
436
|
const externalImageId = match.Face?.ExternalImageId
|
|
426
437
|
? this.decodeExternalImageId(match.Face.ExternalImageId)
|
|
427
438
|
: undefined;
|
|
439
|
+
|
|
428
440
|
return {
|
|
429
441
|
boundingBox: makeCamelCase(match.Face?.BoundingBox),
|
|
430
442
|
metadata: {
|
|
@@ -433,6 +445,7 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
433
445
|
},
|
|
434
446
|
} as IdentifyEntity;
|
|
435
447
|
}) ?? [];
|
|
448
|
+
|
|
436
449
|
return { entities: faces };
|
|
437
450
|
} else {
|
|
438
451
|
const detectFacesCommand = new DetectFacesCommand(param);
|
|
@@ -458,6 +471,7 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
458
471
|
faceAttributes.emotions = detail.Emotions?.map(
|
|
459
472
|
emotion => emotion.Type,
|
|
460
473
|
);
|
|
474
|
+
|
|
461
475
|
return {
|
|
462
476
|
boundingBox: makeCamelCase(detail.BoundingBox),
|
|
463
477
|
landmarks: makeCamelCaseArray(detail.Landmarks),
|
|
@@ -469,6 +483,7 @@ export class AmazonAIIdentifyPredictionsProvider {
|
|
|
469
483
|
},
|
|
470
484
|
} as IdentifyEntity;
|
|
471
485
|
}) ?? [];
|
|
486
|
+
|
|
472
487
|
return { entities: faces };
|
|
473
488
|
}
|
|
474
489
|
}
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
PredictionsAction,
|
|
7
7
|
getAmplifyUserAgentObject,
|
|
8
8
|
} from '@aws-amplify/core/internals/utils';
|
|
9
|
-
|
|
10
9
|
import {
|
|
11
10
|
ComprehendClient,
|
|
12
11
|
DetectDominantLanguageCommand,
|
|
@@ -17,6 +16,7 @@ import {
|
|
|
17
16
|
Entity,
|
|
18
17
|
SyntaxToken,
|
|
19
18
|
} from '@aws-sdk/client-comprehend';
|
|
19
|
+
|
|
20
20
|
import { PredictionsValidationErrorCode } from '../errors/types/validation';
|
|
21
21
|
import { assertValidationError } from '../errors/utils/assertValidationError';
|
|
22
22
|
import {
|
|
@@ -63,9 +63,9 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
63
63
|
const { text: textSource } = input;
|
|
64
64
|
const { source, type = defaultType } = textSource;
|
|
65
65
|
const { text } = source;
|
|
66
|
-
let
|
|
66
|
+
let sourceLanguage;
|
|
67
67
|
if (isInterpretTextOthers(textSource)) {
|
|
68
|
-
|
|
68
|
+
sourceLanguage = (textSource as InterpretTextOthers).source.language;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
this.comprehendClient = new ComprehendClient({
|
|
@@ -79,7 +79,7 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
79
79
|
|
|
80
80
|
const doAll = type === 'all';
|
|
81
81
|
|
|
82
|
-
let languageCode =
|
|
82
|
+
let languageCode = sourceLanguage;
|
|
83
83
|
if (doAll || type === 'language') {
|
|
84
84
|
const languageDetectionParams = {
|
|
85
85
|
Text: text,
|
|
@@ -87,7 +87,7 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
87
87
|
languageCode = await this.detectLanguage(languageDetectionParams);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
let entitiesPromise: Promise<
|
|
90
|
+
let entitiesPromise: Promise<TextEntities[]> | undefined;
|
|
91
91
|
if (doAll || type === 'entities') {
|
|
92
92
|
assertValidationError(
|
|
93
93
|
!!languageCode,
|
|
@@ -113,7 +113,7 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
113
113
|
sentimentPromise = this.detectSentiment(sentimentParams);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
let syntaxPromise: Promise<
|
|
116
|
+
let syntaxPromise: Promise<TextSyntax[]> | undefined;
|
|
117
117
|
if (doAll || type === 'syntax') {
|
|
118
118
|
assertValidationError(
|
|
119
119
|
!!languageCode,
|
|
@@ -145,6 +145,7 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
145
145
|
syntaxPromise,
|
|
146
146
|
keyPhrasesPromise,
|
|
147
147
|
]);
|
|
148
|
+
|
|
148
149
|
return {
|
|
149
150
|
textInterpretation: {
|
|
150
151
|
keyPhrases,
|
|
@@ -160,8 +161,9 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
160
161
|
try {
|
|
161
162
|
const detectKeyPhrasesCommand = new DetectKeyPhrasesCommand(params);
|
|
162
163
|
const data = await this.comprehendClient!.send(detectKeyPhrasesCommand);
|
|
163
|
-
const { KeyPhrases = [] } = data || {};
|
|
164
|
-
|
|
164
|
+
const { KeyPhrases: keyPhrases = [] } = data || {};
|
|
165
|
+
|
|
166
|
+
return keyPhrases.map(({ Text: text }) => {
|
|
165
167
|
return { text };
|
|
166
168
|
});
|
|
167
169
|
} catch (err: any) {
|
|
@@ -176,11 +178,12 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
176
178
|
}
|
|
177
179
|
}
|
|
178
180
|
|
|
179
|
-
private async detectSyntax(params: DetectParams): Promise<
|
|
181
|
+
private async detectSyntax(params: DetectParams): Promise<TextSyntax[]> {
|
|
180
182
|
try {
|
|
181
183
|
const detectSyntaxCommand = new DetectSyntaxCommand(params);
|
|
182
184
|
const data = await this.comprehendClient!.send(detectSyntaxCommand);
|
|
183
185
|
const { SyntaxTokens = [] } = data || {};
|
|
186
|
+
|
|
184
187
|
return this.serializeSyntaxFromComprehend(SyntaxTokens);
|
|
185
188
|
} catch (err: any) {
|
|
186
189
|
if (err.code === 'AccessDeniedException') {
|
|
@@ -194,9 +197,7 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
194
197
|
}
|
|
195
198
|
}
|
|
196
199
|
|
|
197
|
-
private serializeSyntaxFromComprehend(
|
|
198
|
-
tokens: SyntaxToken[],
|
|
199
|
-
): Array<TextSyntax> {
|
|
200
|
+
private serializeSyntaxFromComprehend(tokens: SyntaxToken[]): TextSyntax[] {
|
|
200
201
|
let response: TextSyntax[] = [];
|
|
201
202
|
if (tokens && Array.isArray(tokens)) {
|
|
202
203
|
response = tokens.map(
|
|
@@ -205,6 +206,7 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
205
206
|
},
|
|
206
207
|
);
|
|
207
208
|
}
|
|
209
|
+
|
|
208
210
|
return response;
|
|
209
211
|
}
|
|
210
212
|
|
|
@@ -220,7 +222,8 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
220
222
|
Neutral: neutral = 0,
|
|
221
223
|
Mixed: mixed = 0,
|
|
222
224
|
} = {},
|
|
223
|
-
} =
|
|
225
|
+
} = data ?? {};
|
|
226
|
+
|
|
224
227
|
return { predominant, positive, negative, neutral, mixed };
|
|
225
228
|
} catch (err: any) {
|
|
226
229
|
if (err.code === 'AccessDeniedException') {
|
|
@@ -234,13 +237,12 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
234
237
|
}
|
|
235
238
|
}
|
|
236
239
|
|
|
237
|
-
private async detectEntities(
|
|
238
|
-
params: DetectParams,
|
|
239
|
-
): Promise<Array<TextEntities>> {
|
|
240
|
+
private async detectEntities(params: DetectParams): Promise<TextEntities[]> {
|
|
240
241
|
try {
|
|
241
242
|
const detectEntitiesCommand = new DetectEntitiesCommand(params);
|
|
242
243
|
const data = await this.comprehendClient!.send(detectEntitiesCommand);
|
|
243
244
|
const { Entities = [] } = data || {};
|
|
245
|
+
|
|
244
246
|
return this.serializeEntitiesFromComprehend(Entities);
|
|
245
247
|
} catch (err: any) {
|
|
246
248
|
if (err.code === 'AccessDeniedException') {
|
|
@@ -254,13 +256,14 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
254
256
|
}
|
|
255
257
|
}
|
|
256
258
|
|
|
257
|
-
private serializeEntitiesFromComprehend(data: Entity[]):
|
|
259
|
+
private serializeEntitiesFromComprehend(data: Entity[]): TextEntities[] {
|
|
258
260
|
let response: TextEntities[] = [];
|
|
259
261
|
if (data && Array.isArray(data)) {
|
|
260
262
|
response = data.map(({ Type: type, Text: text }) => {
|
|
261
263
|
return { type, text };
|
|
262
264
|
});
|
|
263
265
|
}
|
|
266
|
+
|
|
264
267
|
return response;
|
|
265
268
|
}
|
|
266
269
|
|
|
@@ -272,7 +275,8 @@ export class AmazonAIInterpretPredictionsProvider {
|
|
|
272
275
|
const data = await this.comprehendClient!.send(
|
|
273
276
|
detectDominantLanguageCommand,
|
|
274
277
|
);
|
|
275
|
-
const { Languages: [{ LanguageCode }] = [{}] } =
|
|
278
|
+
const { Languages: [{ LanguageCode }] = [{ LanguageCode: undefined }] } =
|
|
279
|
+
data ?? {};
|
|
276
280
|
assertValidationError(
|
|
277
281
|
!!LanguageCode,
|
|
278
282
|
PredictionsValidationErrorCode.NoLanguage,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
TableCell,
|
|
12
12
|
} from '../types';
|
|
13
13
|
import { Block, BlockList, TextDetectionList } from '../types/AWSTypes';
|
|
14
|
+
|
|
14
15
|
import { makeCamelCase, makeCamelCaseArray } from './Utils';
|
|
15
16
|
|
|
16
17
|
function getBoundingBox(geometry?: Geometry): BoundingBox | undefined {
|
|
@@ -19,6 +20,7 @@ function getBoundingBox(geometry?: Geometry): BoundingBox | undefined {
|
|
|
19
20
|
|
|
20
21
|
function getPolygon(geometry?: Geometry): Polygon | undefined {
|
|
21
22
|
if (!geometry?.Polygon) return undefined;
|
|
23
|
+
|
|
22
24
|
return makeCamelCaseArray(Array.from(geometry.Polygon)) as Polygon;
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -69,6 +71,7 @@ export function categorizeRekognitionBlocks(
|
|
|
69
71
|
0,
|
|
70
72
|
response.text.fullText.length - 1,
|
|
71
73
|
);
|
|
74
|
+
|
|
72
75
|
return response;
|
|
73
76
|
}
|
|
74
77
|
|
|
@@ -102,9 +105,9 @@ export function categorizeTextractBlocks(
|
|
|
102
105
|
* Note that we do not map `WORD` and `TABLE` in `blockMap` because they will not be referenced by any other
|
|
103
106
|
* block except the Page block.
|
|
104
107
|
*/
|
|
105
|
-
const tableBlocks: BlockList =
|
|
106
|
-
const keyValueBlocks: BlockList =
|
|
107
|
-
const blockMap:
|
|
108
|
+
const tableBlocks: BlockList = [];
|
|
109
|
+
const keyValueBlocks: BlockList = [];
|
|
110
|
+
const blockMap: Record<string, Block> = {};
|
|
108
111
|
|
|
109
112
|
blocks.forEach(block => {
|
|
110
113
|
switch (block.BlockType) {
|
|
@@ -130,9 +133,8 @@ export function categorizeTextractBlocks(
|
|
|
130
133
|
blockMap[block.Id] = block;
|
|
131
134
|
}
|
|
132
135
|
break;
|
|
133
|
-
case 'SELECTION_ELEMENT':
|
|
134
|
-
const selectionStatus =
|
|
135
|
-
block.SelectionStatus === 'SELECTED' ? true : false;
|
|
136
|
+
case 'SELECTION_ELEMENT': {
|
|
137
|
+
const selectionStatus = block.SelectionStatus === 'SELECTED';
|
|
136
138
|
if (!response.text.selections) response.text.selections = [];
|
|
137
139
|
response.text.selections.push({
|
|
138
140
|
selected: selectionStatus,
|
|
@@ -143,6 +145,7 @@ export function categorizeTextractBlocks(
|
|
|
143
145
|
blockMap[block.Id] = block;
|
|
144
146
|
}
|
|
145
147
|
break;
|
|
148
|
+
}
|
|
146
149
|
case 'TABLE':
|
|
147
150
|
tableBlocks.push(block);
|
|
148
151
|
break;
|
|
@@ -166,14 +169,14 @@ export function categorizeTextractBlocks(
|
|
|
166
169
|
|
|
167
170
|
// Post-process complex structures if they exist.
|
|
168
171
|
if (tableBlocks.length !== 0) {
|
|
169
|
-
const tableResponse: Table[] =
|
|
172
|
+
const tableResponse: Table[] = [];
|
|
170
173
|
tableBlocks.forEach(table => {
|
|
171
174
|
tableResponse.push(constructTable(table, blockMap));
|
|
172
175
|
});
|
|
173
176
|
response.text.tables = tableResponse;
|
|
174
177
|
}
|
|
175
178
|
if (keyValueBlocks.length !== 0) {
|
|
176
|
-
const keyValueResponse: KeyValue[] =
|
|
179
|
+
const keyValueResponse: KeyValue[] = [];
|
|
177
180
|
keyValueBlocks.forEach(keyValue => {
|
|
178
181
|
// We need the KeyValue blocks of EntityType = `KEY`, which has both key and value references.
|
|
179
182
|
if (keyValue.EntityTypes) {
|
|
@@ -185,6 +188,7 @@ export function categorizeTextractBlocks(
|
|
|
185
188
|
});
|
|
186
189
|
response.text.keyValues = keyValueResponse;
|
|
187
190
|
}
|
|
191
|
+
|
|
188
192
|
return response;
|
|
189
193
|
}
|
|
190
194
|
|
|
@@ -193,12 +197,8 @@ export function categorizeTextractBlocks(
|
|
|
193
197
|
* @param {Block} table - Table block that has references (`Relationships`) to its cells
|
|
194
198
|
* @param {[id: string]: Block} blockMap - Maps block Ids to blocks.
|
|
195
199
|
*/
|
|
196
|
-
function constructTable(
|
|
197
|
-
|
|
198
|
-
blockMap: { [key: string]: Block },
|
|
199
|
-
): Table {
|
|
200
|
-
let tableMatrix: TableCell[][];
|
|
201
|
-
tableMatrix = [];
|
|
200
|
+
function constructTable(table: Block, blockMap: Record<string, Block>): Table {
|
|
201
|
+
const tableMatrix: TableCell[][] = [];
|
|
202
202
|
// visit each of the cell associated with the table's relationship.
|
|
203
203
|
for (const tableRelation of table.Relationships ?? []) {
|
|
204
204
|
for (const cellId of tableRelation.Ids ?? []) {
|
|
@@ -225,6 +225,7 @@ function constructTable(
|
|
|
225
225
|
const columnSize = tableMatrix[0].length;
|
|
226
226
|
const boundingBox = getBoundingBox(table.Geometry);
|
|
227
227
|
const polygon = getPolygon(table.Geometry);
|
|
228
|
+
|
|
228
229
|
// Note that we leave spanned cells undefined for distinction
|
|
229
230
|
return {
|
|
230
231
|
size: { rows: rowSize, columns: columnSize },
|
|
@@ -241,11 +242,11 @@ function constructTable(
|
|
|
241
242
|
*/
|
|
242
243
|
function constructKeyValue(
|
|
243
244
|
keyBlock: Block,
|
|
244
|
-
blockMap:
|
|
245
|
+
blockMap: Record<string, Block>,
|
|
245
246
|
): KeyValue {
|
|
246
|
-
let keyText
|
|
247
|
-
let valueText
|
|
248
|
-
let valueSelected
|
|
247
|
+
let keyText = '';
|
|
248
|
+
let valueText = '';
|
|
249
|
+
let valueSelected = false;
|
|
249
250
|
for (const keyValueRelation of keyBlock.Relationships ?? []) {
|
|
250
251
|
if (keyValueRelation.Type === 'CHILD') {
|
|
251
252
|
// relation refers to key
|
|
@@ -261,6 +262,7 @@ function constructKeyValue(
|
|
|
261
262
|
}
|
|
262
263
|
}
|
|
263
264
|
}
|
|
265
|
+
|
|
264
266
|
return {
|
|
265
267
|
key: keyText,
|
|
266
268
|
value: { text: valueText, selected: valueSelected },
|
|
@@ -276,10 +278,10 @@ function constructKeyValue(
|
|
|
276
278
|
*/
|
|
277
279
|
function extractContentsFromBlock(
|
|
278
280
|
block: Block,
|
|
279
|
-
blockMap:
|
|
281
|
+
blockMap: Record<string, Block>,
|
|
280
282
|
): Content {
|
|
281
|
-
let words
|
|
282
|
-
let isSelected
|
|
283
|
+
let words = '';
|
|
284
|
+
let isSelected = false;
|
|
283
285
|
|
|
284
286
|
if (!block.Relationships) {
|
|
285
287
|
// some block might have no content
|
|
@@ -291,11 +293,12 @@ function extractContentsFromBlock(
|
|
|
291
293
|
if (contentBlock.BlockType === 'WORD') {
|
|
292
294
|
words += contentBlock.Text + ' ';
|
|
293
295
|
} else if (contentBlock.BlockType === 'SELECTION_ELEMENT') {
|
|
294
|
-
isSelected = contentBlock.SelectionStatus === 'SELECTED'
|
|
296
|
+
isSelected = contentBlock.SelectionStatus === 'SELECTED';
|
|
295
297
|
}
|
|
296
298
|
}
|
|
297
299
|
}
|
|
298
300
|
|
|
299
301
|
words = words.substr(0, words.length - 1); // remove trailing space.
|
|
302
|
+
|
|
300
303
|
return { text: words, selected: isSelected };
|
|
301
304
|
}
|
package/src/providers/Utils.ts
CHANGED
|
@@ -7,14 +7,15 @@
|
|
|
7
7
|
export function makeCamelCase(obj?: any, keys?: string[]) {
|
|
8
8
|
if (!obj) return undefined;
|
|
9
9
|
const newObj = {};
|
|
10
|
-
const keysToRename = keys
|
|
10
|
+
const keysToRename = keys || Object.keys(obj);
|
|
11
11
|
keysToRename.forEach(key => {
|
|
12
|
-
if (
|
|
12
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
13
13
|
// change the key to camelcase.
|
|
14
14
|
const camelCaseKey = key.charAt(0).toLowerCase() + key.substr(1);
|
|
15
15
|
Object.assign(newObj, { [camelCaseKey]: obj[key] });
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
+
|
|
18
19
|
return newObj;
|
|
19
20
|
}
|
|
20
21
|
|
|
@@ -23,6 +24,7 @@ export function makeCamelCase(obj?: any, keys?: string[]) {
|
|
|
23
24
|
*/
|
|
24
25
|
export function makeCamelCaseArray(objArr?: object[], keys?: string[]) {
|
|
25
26
|
if (!objArr) return undefined;
|
|
27
|
+
|
|
26
28
|
return objArr.map(obj => makeCamelCase(obj, keys));
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -30,18 +32,18 @@ export function makeCamelCaseArray(objArr?: object[], keys?: string[]) {
|
|
|
30
32
|
* Converts blob to array buffer
|
|
31
33
|
*/
|
|
32
34
|
export function blobToArrayBuffer(blob: Blob): Promise<Uint8Array> {
|
|
33
|
-
return new Promise((
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
34
36
|
const reader = new FileReader();
|
|
35
37
|
reader.onload = _event => {
|
|
36
|
-
|
|
38
|
+
resolve(reader.result as Uint8Array);
|
|
37
39
|
};
|
|
38
40
|
reader.onerror = err => {
|
|
39
|
-
|
|
41
|
+
reject(err);
|
|
40
42
|
};
|
|
41
43
|
try {
|
|
42
44
|
reader.readAsArrayBuffer(blob);
|
|
43
45
|
} catch (err) {
|
|
44
|
-
|
|
46
|
+
reject(err); // in case user gives invalid type
|
|
45
47
|
}
|
|
46
48
|
});
|
|
47
49
|
}
|
package/src/providers/index.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { AmazonAIConvertPredictionsProvider } from './AmazonAIConvertPredictionsProvider';
|
|
4
4
|
import { AmazonAIIdentifyPredictionsProvider } from './AmazonAIIdentifyPredictionsProvider';
|
|
5
5
|
import { AmazonAIInterpretPredictionsProvider } from './AmazonAIInterpretPredictionsProvider';
|
|
6
|
+
|
|
6
7
|
export {
|
|
7
8
|
AmazonAIConvertPredictionsProvider,
|
|
8
9
|
AmazonAIIdentifyPredictionsProvider,
|
package/src/types/AWSTypes.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
/* tslint:disable:max-line-length */
|
|
4
3
|
import { Geometry, Relationship } from './Predictions';
|
|
5
4
|
|
|
6
5
|
export type BlockList = Block[];
|
|
@@ -61,13 +60,13 @@ export interface Block {
|
|
|
61
60
|
/**
|
|
62
61
|
* <p>A list of child blocks of the current block. For example a LINE object has child blocks for each WORD block that's part of the line of text. There aren't Relationship objects in the list for relationships that don't exist, such as when the current block has no child blocks. The list size can be the following:</p> <ul> <li> <p>0 - The block has no child blocks.</p> </li> <li> <p>1 - The block has child blocks.</p> </li> </ul>
|
|
63
62
|
*/
|
|
64
|
-
Relationships?:
|
|
63
|
+
Relationships?: Relationship[] | Iterable<Relationship>;
|
|
65
64
|
|
|
66
65
|
/**
|
|
67
66
|
* <p>The type of entity. The following can be returned:</p> <ul> <li> <p> <i>KEY</i> - An identifier for a field on the document.</p> </li> <li> <p> <i>VALUE</i> - The field text.</p> </li> </ul> <p> <code>EntityTypes</code> isn't returned by <code>DetectDocumentText</code> and <code>GetDocumentTextDetection</code>.</p>
|
|
68
67
|
*/
|
|
69
68
|
EntityTypes?:
|
|
70
|
-
|
|
|
69
|
+
| ('KEY' | 'VALUE' | string)[]
|
|
71
70
|
| Iterable<'KEY' | 'VALUE' | string>;
|
|
72
71
|
|
|
73
72
|
/**
|