@aws-amplify/predictions 5.5.6-api-v6-models.b3abc9b.0 → 6.0.0

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 (148) hide show
  1. package/README.md +3 -0
  2. package/lib/Predictions.d.ts +11 -45
  3. package/lib/Predictions.js +24 -132
  4. package/lib/errors/PredictionsError.d.ts +4 -0
  5. package/lib/errors/PredictionsError.js +15 -0
  6. package/lib/errors/types/validation.d.ts +14 -0
  7. package/lib/errors/types/validation.js +50 -0
  8. package/lib/errors/utils/assertValidationError.d.ts +2 -0
  9. package/lib/errors/utils/assertValidationError.js +14 -0
  10. package/lib/index.d.ts +2 -4
  11. package/lib/index.js +2 -9
  12. package/{lib-esm/Providers → lib/providers}/AmazonAIConvertPredictionsProvider.d.ts +6 -7
  13. package/lib/providers/AmazonAIConvertPredictionsProvider.js +307 -0
  14. package/lib/{Providers → providers}/AmazonAIIdentifyPredictionsProvider.d.ts +5 -6
  15. package/lib/providers/AmazonAIIdentifyPredictionsProvider.js +334 -0
  16. package/lib/{Providers → providers}/AmazonAIInterpretPredictionsProvider.d.ts +3 -4
  17. package/lib/providers/AmazonAIInterpretPredictionsProvider.js +208 -0
  18. package/lib/providers/IdentifyTextUtils.d.ts +16 -0
  19. package/lib/{Providers → providers}/IdentifyTextUtils.js +97 -148
  20. package/lib/{Providers → providers}/Utils.d.ts +2 -2
  21. package/lib/{Providers → providers}/Utils.js +11 -12
  22. package/lib/{Providers → providers}/index.d.ts +1 -2
  23. package/lib/providers/index.js +11 -0
  24. package/lib/tsconfig.tsbuildinfo +1 -0
  25. package/lib/types/AWSTypes.d.ts +8 -9
  26. package/lib/types/AWSTypes.js +0 -1
  27. package/lib/types/Predictions.d.ts +63 -59
  28. package/lib/types/Predictions.js +41 -28
  29. package/lib/types/index.js +1 -2
  30. package/lib-esm/Predictions.d.ts +11 -45
  31. package/lib-esm/Predictions.js +23 -133
  32. package/lib-esm/errors/PredictionsError.d.ts +4 -0
  33. package/lib-esm/errors/PredictionsError.js +11 -0
  34. package/lib-esm/errors/types/validation.d.ts +14 -0
  35. package/lib-esm/errors/types/validation.js +47 -0
  36. package/lib-esm/errors/utils/assertValidationError.d.ts +2 -0
  37. package/lib-esm/errors/utils/assertValidationError.js +10 -0
  38. package/lib-esm/index.d.ts +2 -4
  39. package/lib-esm/index.js +1 -5
  40. package/{lib/Providers → lib-esm/providers}/AmazonAIConvertPredictionsProvider.d.ts +6 -7
  41. package/lib-esm/providers/AmazonAIConvertPredictionsProvider.js +303 -0
  42. package/lib-esm/{Providers → providers}/AmazonAIIdentifyPredictionsProvider.d.ts +5 -6
  43. package/lib-esm/providers/AmazonAIIdentifyPredictionsProvider.js +330 -0
  44. package/lib-esm/{Providers → providers}/AmazonAIInterpretPredictionsProvider.d.ts +3 -4
  45. package/lib-esm/providers/AmazonAIInterpretPredictionsProvider.js +204 -0
  46. package/lib-esm/providers/IdentifyTextUtils.d.ts +16 -0
  47. package/lib-esm/providers/IdentifyTextUtils.js +264 -0
  48. package/lib-esm/{Providers → providers}/Utils.d.ts +2 -2
  49. package/lib-esm/{Providers → providers}/Utils.js +10 -12
  50. package/lib-esm/{Providers → providers}/index.d.ts +1 -2
  51. package/lib-esm/{Providers → providers}/index.js +1 -3
  52. package/lib-esm/tsconfig.tsbuildinfo +1 -0
  53. package/lib-esm/types/AWSTypes.d.ts +8 -9
  54. package/lib-esm/types/AWSTypes.js +1 -1
  55. package/lib-esm/types/Predictions.d.ts +63 -59
  56. package/lib-esm/types/Predictions.js +34 -27
  57. package/lib-esm/types/index.js +0 -1
  58. package/package.json +39 -48
  59. package/src/Predictions.ts +33 -220
  60. package/src/errors/PredictionsError.ts +16 -0
  61. package/src/errors/types/validation.ts +51 -0
  62. package/src/errors/utils/assertValidationError.ts +18 -0
  63. package/src/index.ts +16 -16
  64. package/src/{Providers → providers}/AmazonAIConvertPredictionsProvider.ts +210 -171
  65. package/src/{Providers → providers}/AmazonAIIdentifyPredictionsProvider.ts +244 -246
  66. package/src/providers/AmazonAIInterpretPredictionsProvider.ts +293 -0
  67. package/src/{Providers → providers}/IdentifyTextUtils.ts +69 -52
  68. package/src/{Providers → providers}/Utils.ts +2 -2
  69. package/src/{Providers → providers}/index.ts +0 -2
  70. package/src/types/AWSTypes.ts +5 -6
  71. package/src/types/Predictions.ts +107 -62
  72. package/lib/.tsbuildinfo +0 -3
  73. package/lib/Predictions.js.map +0 -1
  74. package/lib/Providers/AmazonAIConvertPredictionsProvider.js +0 -377
  75. package/lib/Providers/AmazonAIConvertPredictionsProvider.js.map +0 -1
  76. package/lib/Providers/AmazonAIIdentifyPredictionsProvider.js +0 -441
  77. package/lib/Providers/AmazonAIIdentifyPredictionsProvider.js.map +0 -1
  78. package/lib/Providers/AmazonAIInterpretPredictionsProvider.js +0 -321
  79. package/lib/Providers/AmazonAIInterpretPredictionsProvider.js.map +0 -1
  80. package/lib/Providers/AmazonAIPredictionsProvider.d.ts +0 -14
  81. package/lib/Providers/AmazonAIPredictionsProvider.js +0 -43
  82. package/lib/Providers/AmazonAIPredictionsProvider.js.map +0 -1
  83. package/lib/Providers/IdentifyTextUtils.d.ts +0 -40
  84. package/lib/Providers/IdentifyTextUtils.js.map +0 -1
  85. package/lib/Providers/Utils.js.map +0 -1
  86. package/lib/Providers/index.js +0 -13
  87. package/lib/Providers/index.js.map +0 -1
  88. package/lib/index.js.map +0 -1
  89. package/lib/types/AWSTypes.js.map +0 -1
  90. package/lib/types/Predictions.js.map +0 -1
  91. package/lib/types/Providers/AbstractConvertPredictionsProvider.d.ts +0 -9
  92. package/lib/types/Providers/AbstractConvertPredictionsProvider.js +0 -44
  93. package/lib/types/Providers/AbstractConvertPredictionsProvider.js.map +0 -1
  94. package/lib/types/Providers/AbstractIdentifyPredictionsProvider.d.ts +0 -9
  95. package/lib/types/Providers/AbstractIdentifyPredictionsProvider.js +0 -44
  96. package/lib/types/Providers/AbstractIdentifyPredictionsProvider.js.map +0 -1
  97. package/lib/types/Providers/AbstractInterpretPredictionsProvider.d.ts +0 -7
  98. package/lib/types/Providers/AbstractInterpretPredictionsProvider.js +0 -27
  99. package/lib/types/Providers/AbstractInterpretPredictionsProvider.js.map +0 -1
  100. package/lib/types/Providers/AbstractPredictionsProvider.d.ts +0 -7
  101. package/lib/types/Providers/AbstractPredictionsProvider.js +0 -16
  102. package/lib/types/Providers/AbstractPredictionsProvider.js.map +0 -1
  103. package/lib/types/Providers/index.d.ts +0 -4
  104. package/lib/types/Providers/index.js +0 -10
  105. package/lib/types/Providers/index.js.map +0 -1
  106. package/lib/types/index.js.map +0 -1
  107. package/lib-esm/.tsbuildinfo +0 -3
  108. package/lib-esm/Predictions.js.map +0 -1
  109. package/lib-esm/Providers/AmazonAIConvertPredictionsProvider.js +0 -375
  110. package/lib-esm/Providers/AmazonAIConvertPredictionsProvider.js.map +0 -1
  111. package/lib-esm/Providers/AmazonAIIdentifyPredictionsProvider.js +0 -439
  112. package/lib-esm/Providers/AmazonAIIdentifyPredictionsProvider.js.map +0 -1
  113. package/lib-esm/Providers/AmazonAIInterpretPredictionsProvider.js +0 -319
  114. package/lib-esm/Providers/AmazonAIInterpretPredictionsProvider.js.map +0 -1
  115. package/lib-esm/Providers/AmazonAIPredictionsProvider.d.ts +0 -14
  116. package/lib-esm/Providers/AmazonAIPredictionsProvider.js +0 -41
  117. package/lib-esm/Providers/AmazonAIPredictionsProvider.js.map +0 -1
  118. package/lib-esm/Providers/IdentifyTextUtils.d.ts +0 -40
  119. package/lib-esm/Providers/IdentifyTextUtils.js +0 -313
  120. package/lib-esm/Providers/IdentifyTextUtils.js.map +0 -1
  121. package/lib-esm/Providers/Utils.js.map +0 -1
  122. package/lib-esm/Providers/index.js.map +0 -1
  123. package/lib-esm/index.js.map +0 -1
  124. package/lib-esm/types/AWSTypes.js.map +0 -1
  125. package/lib-esm/types/Predictions.js.map +0 -1
  126. package/lib-esm/types/Providers/AbstractConvertPredictionsProvider.d.ts +0 -9
  127. package/lib-esm/types/Providers/AbstractConvertPredictionsProvider.js +0 -42
  128. package/lib-esm/types/Providers/AbstractConvertPredictionsProvider.js.map +0 -1
  129. package/lib-esm/types/Providers/AbstractIdentifyPredictionsProvider.d.ts +0 -9
  130. package/lib-esm/types/Providers/AbstractIdentifyPredictionsProvider.js +0 -42
  131. package/lib-esm/types/Providers/AbstractIdentifyPredictionsProvider.js.map +0 -1
  132. package/lib-esm/types/Providers/AbstractInterpretPredictionsProvider.d.ts +0 -7
  133. package/lib-esm/types/Providers/AbstractInterpretPredictionsProvider.js +0 -25
  134. package/lib-esm/types/Providers/AbstractInterpretPredictionsProvider.js.map +0 -1
  135. package/lib-esm/types/Providers/AbstractPredictionsProvider.d.ts +0 -7
  136. package/lib-esm/types/Providers/AbstractPredictionsProvider.js +0 -14
  137. package/lib-esm/types/Providers/AbstractPredictionsProvider.js.map +0 -1
  138. package/lib-esm/types/Providers/index.d.ts +0 -4
  139. package/lib-esm/types/Providers/index.js +0 -7
  140. package/lib-esm/types/Providers/index.js.map +0 -1
  141. package/lib-esm/types/index.js.map +0 -1
  142. package/src/Providers/AmazonAIInterpretPredictionsProvider.ts +0 -281
  143. package/src/Providers/AmazonAIPredictionsProvider.ts +0 -69
  144. package/src/types/Providers/AbstractConvertPredictionsProvider.ts +0 -55
  145. package/src/types/Providers/AbstractIdentifyPredictionsProvider.ts +0 -57
  146. package/src/types/Providers/AbstractInterpretPredictionsProvider.ts +0 -26
  147. package/src/types/Providers/AbstractPredictionsProvider.ts +0 -20
  148. package/src/types/Providers/index.ts +0 -6
@@ -1,73 +1,103 @@
1
1
  // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import {
4
- Category,
5
- Credentials,
4
+ Amplify,
6
5
  ConsoleLogger as Logger,
6
+ fetchAuthSession,
7
+ } from '@aws-amplify/core';
8
+ import {
9
+ Category,
7
10
  PredictionsAction,
8
11
  getAmplifyUserAgentObject,
9
- } from '@aws-amplify/core';
10
- import { Storage } from '@aws-amplify/storage';
11
- import { AbstractIdentifyPredictionsProvider } from '../types/Providers';
12
+ } from '@aws-amplify/core/internals/utils';
13
+ import { getUrl } from '@aws-amplify/storage';
12
14
  import {
13
- RekognitionClient,
14
- SearchFacesByImageCommand,
15
- DetectTextCommand,
16
- DetectTextCommandInput,
15
+ DetectFacesCommand,
17
16
  DetectLabelsCommand,
18
17
  DetectLabelsCommandInput,
19
- DetectFacesCommand,
20
18
  DetectModerationLabelsCommand,
21
19
  DetectModerationLabelsCommandInput,
20
+ DetectTextCommand,
21
+ DetectTextCommandInput,
22
22
  RecognizeCelebritiesCommand,
23
+ RekognitionClient,
24
+ SearchFacesByImageCommand,
23
25
  } from '@aws-sdk/client-rekognition';
24
26
  import {
27
+ AnalyzeDocumentCommand,
28
+ AnalyzeDocumentCommandInput,
29
+ DetectDocumentTextCommand,
30
+ DetectDocumentTextCommandInput,
31
+ TextractClient,
32
+ } from '@aws-sdk/client-textract';
33
+ import { PredictionsValidationErrorCode } from '../errors/types/validation';
34
+ import { assertValidationError } from '../errors/utils/assertValidationError';
35
+ import {
36
+ BoundingBox,
37
+ FaceAttributes,
38
+ FeatureTypes,
39
+ IdentifyEntitiesInput,
40
+ IdentifyEntitiesOutput,
41
+ IdentifyEntity,
42
+ IdentifyFromCollection,
25
43
  IdentifyLabelsInput,
26
44
  IdentifyLabelsOutput,
27
45
  IdentifySource,
28
- IdentifyEntitiesInput,
29
- IdentifyEntitiesOutput,
30
- isStorageSource,
31
- isFileSource,
32
- isBytesSource,
33
46
  IdentifyTextInput,
34
47
  IdentifyTextOutput,
48
+ isFileSource,
49
+ isIdentifyBytesSource,
35
50
  isIdentifyCelebrities,
36
51
  isIdentifyFromCollection,
37
- IdentifyFromCollection,
38
- FeatureTypes,
52
+ isIdentifyLabelsInput,
53
+ isIdentifyTextInput,
54
+ isStorageSource,
55
+ isValidIdentifyInput,
39
56
  } from '../types';
40
57
  import {
41
- Image,
58
+ BlockList,
42
59
  Document,
60
+ Image,
43
61
  TextDetectionList,
44
- BlockList,
45
62
  } from '../types/AWSTypes';
46
- import {
47
- TextractClient,
48
- DetectDocumentTextCommand,
49
- DetectDocumentTextCommandInput,
50
- AnalyzeDocumentCommand,
51
- AnalyzeDocumentCommandInput,
52
- } from '@aws-sdk/client-textract';
53
- import { makeCamelCase, makeCamelCaseArray, blobToArrayBuffer } from './Utils';
54
63
  import {
55
64
  categorizeRekognitionBlocks,
56
65
  categorizeTextractBlocks,
57
66
  } from './IdentifyTextUtils';
67
+ import { blobToArrayBuffer, makeCamelCase, makeCamelCaseArray } from './Utils';
58
68
 
59
- export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredictionsProvider {
60
- private rekognitionClient: RekognitionClient;
61
- private textractClient: TextractClient;
69
+ const logger = new Logger('AmazonAIIdentifyPredictionsProvider');
62
70
 
63
- constructor() {
64
- super();
65
- }
71
+ export class AmazonAIIdentifyPredictionsProvider {
72
+ private rekognitionClient?: RekognitionClient;
73
+ private textractClient?: TextractClient;
66
74
 
67
75
  getProviderName() {
68
76
  return 'AmazonAIIdentifyPredictionsProvider';
69
77
  }
70
78
 
79
+ identify(
80
+ input: IdentifyTextInput | IdentifyLabelsInput | IdentifyEntitiesInput
81
+ ): Promise<
82
+ IdentifyTextOutput | IdentifyLabelsOutput | IdentifyEntitiesOutput
83
+ > {
84
+ assertValidationError(
85
+ isValidIdentifyInput(input),
86
+ PredictionsValidationErrorCode.InvalidInput
87
+ );
88
+
89
+ if (isIdentifyTextInput(input)) {
90
+ logger.debug('identifyText');
91
+ return this.identifyText(input);
92
+ } else if (isIdentifyLabelsInput(input)) {
93
+ logger.debug('identifyLabels');
94
+ return this.identifyLabels(input);
95
+ } else {
96
+ logger.debug('identifyEntities');
97
+ return this.identifyEntities(input);
98
+ }
99
+ }
100
+
71
101
  /**
72
102
  * Verify user input source and converts it into source object readable by Rekognition and Textract.
73
103
  * Note that Rekognition and Textract use the same source interface, so we need not worry about types.
@@ -79,14 +109,15 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
79
109
  return new Promise((res, rej) => {
80
110
  if (isStorageSource(source)) {
81
111
  const storageConfig = {
82
- level: source.level,
83
- identityId: source.identityId,
112
+ accessLevel: source.level,
113
+ targetIdentityId: source.identityId,
84
114
  };
85
- Storage.get(source.key, storageConfig)
86
- .then((url: string) => {
115
+
116
+ getUrl({ key: source.key, options: storageConfig })
117
+ .then(value => {
87
118
  const parser =
88
119
  /https:\/\/([a-zA-Z0-9%\-_.]+)\.s3\.[A-Za-z0-9%\-._~]+\/([a-zA-Z0-9%\-._~/]+)\?/;
89
- const parsedURL = url.match(parser);
120
+ const parsedURL = value.url.toString().match(parser) ?? '';
90
121
  if (parsedURL.length < 3) rej('Invalid S3 key was given.');
91
122
  res({
92
123
  S3Object: {
@@ -102,7 +133,7 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
102
133
  res({ Bytes: new Uint8Array(buffer) });
103
134
  })
104
135
  .catch(err => rej(err));
105
- } else if (isBytesSource(source)) {
136
+ } else if (isIdentifyBytesSource(source)) {
106
137
  const bytes = source.bytes;
107
138
  if (bytes instanceof Blob) {
108
139
  blobToArrayBuffer(bytes)
@@ -131,14 +162,17 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
131
162
  protected async identifyText(
132
163
  input: IdentifyTextInput
133
164
  ): Promise<IdentifyTextOutput> {
134
- const credentials = await Credentials.get();
135
- if (!credentials) return Promise.reject('No credentials');
136
- const {
137
- identifyText: {
138
- region = '',
139
- defaults: { format: configFormat = 'PLAIN' } = {},
140
- } = {},
141
- } = this._config;
165
+ const { credentials } = await fetchAuthSession();
166
+ assertValidationError(
167
+ !!credentials,
168
+ PredictionsValidationErrorCode.NoCredentials
169
+ );
170
+
171
+ const { identifyText = {} } =
172
+ Amplify.getConfig().Predictions?.identify ?? {};
173
+ const { region = '', defaults = {} } = identifyText;
174
+ const { format: configFormat = 'PLAIN' } = defaults;
175
+
142
176
  this.rekognitionClient = new RekognitionClient({
143
177
  region,
144
178
  credentials,
@@ -151,14 +185,10 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
151
185
  });
152
186
  let inputDocument: Document;
153
187
 
154
- try {
155
- inputDocument = await this.configureSource(input.text.source);
156
- } catch (err) {
157
- return Promise.reject(err);
158
- }
188
+ inputDocument = await this.configureSource(input.text?.source);
159
189
 
160
190
  // get default value if format isn't specified in the input.
161
- const format = input.text.format || configFormat;
191
+ const format = input.text?.format ?? configFormat;
162
192
  const featureTypes: FeatureTypes = []; // structures we want to analyze (e.g. [TABLES, FORMS]).
163
193
  if (format === 'FORM' || format === 'ALL') featureTypes.push('FORMS');
164
194
  if (format === 'TABLE' || format === 'ALL') featureTypes.push('TABLES');
@@ -176,51 +206,43 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
176
206
  Image: inputDocument,
177
207
  };
178
208
 
179
- try {
180
- const detectTextCommand = new DetectTextCommand(rekognitionParam);
181
- const rekognitionData = await this.rekognitionClient.send(
182
- detectTextCommand
183
- );
184
-
185
- const rekognitionResponse = categorizeRekognitionBlocks(
186
- rekognitionData.TextDetections as TextDetectionList
187
- );
188
- if (rekognitionResponse.text.words.length < 50) {
189
- // did not hit the word limit, return the data
190
- return rekognitionResponse;
191
- }
209
+ const detectTextCommand = new DetectTextCommand(rekognitionParam);
210
+ const rekognitionData = await this.rekognitionClient.send(
211
+ detectTextCommand
212
+ );
192
213
 
193
- const detectDocumentTextCommand = new DetectDocumentTextCommand(
194
- textractParam
195
- );
214
+ const rekognitionResponse = categorizeRekognitionBlocks(
215
+ rekognitionData.TextDetections as TextDetectionList
216
+ );
217
+ if (rekognitionResponse.text.words.length < 50) {
218
+ // did not hit the word limit, return the data
219
+ return rekognitionResponse;
220
+ }
196
221
 
197
- const { Blocks } = await this.textractClient.send(
198
- detectDocumentTextCommand
199
- );
222
+ const detectDocumentTextCommand = new DetectDocumentTextCommand(
223
+ textractParam
224
+ );
200
225
 
201
- if (rekognitionData.TextDetections.length > Blocks.length) {
202
- return rekognitionResponse;
203
- }
226
+ const { Blocks } = await this.textractClient.send(
227
+ detectDocumentTextCommand
228
+ );
204
229
 
205
- return categorizeTextractBlocks(Blocks as BlockList);
206
- } catch (err) {
207
- Promise.reject(err);
230
+ if (
231
+ (rekognitionData.TextDetections?.length ?? 0) > (Blocks?.length ?? 0)
232
+ ) {
233
+ return rekognitionResponse;
208
234
  }
235
+
236
+ return categorizeTextractBlocks(Blocks as BlockList);
209
237
  } else {
210
238
  const param: AnalyzeDocumentCommandInput = {
211
239
  Document: inputDocument,
212
240
  FeatureTypes: featureTypes,
213
241
  };
214
242
 
215
- try {
216
- const analyzeDocumentCommand = new AnalyzeDocumentCommand(param);
217
- const { Blocks } = await this.textractClient.send(
218
- analyzeDocumentCommand
219
- );
220
- return categorizeTextractBlocks(Blocks as BlockList);
221
- } catch (err) {
222
- return Promise.reject(err);
223
- }
243
+ const analyzeDocumentCommand = new AnalyzeDocumentCommand(param);
244
+ const { Blocks } = await this.textractClient.send(analyzeDocumentCommand);
245
+ return categorizeTextractBlocks(Blocks as BlockList);
224
246
  }
225
247
  }
226
248
 
@@ -232,53 +254,44 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
232
254
  protected async identifyLabels(
233
255
  input: IdentifyLabelsInput
234
256
  ): Promise<IdentifyLabelsOutput> {
235
- try {
236
- const credentials = await Credentials.get();
237
- if (!credentials) return Promise.reject('No credentials');
238
- const {
239
- identifyLabels: {
240
- region = '',
241
- defaults: { type = 'LABELS' } = {},
242
- } = {},
243
- } = this._config;
244
- this.rekognitionClient = new RekognitionClient({
245
- region,
246
- credentials,
247
- customUserAgent: _getPredictionsIdentifyAmplifyUserAgent(),
248
- });
249
- let inputImage: Image;
250
- await this.configureSource(input.labels.source)
251
- .then(data => {
252
- inputImage = data;
253
- })
254
- .catch(err => {
255
- return Promise.reject(err);
256
- });
257
- const param = { Image: inputImage };
258
- const servicePromises = [];
259
-
260
- // get default argument
261
- const entityType = input.labels.type || type;
262
- if (entityType === 'LABELS' || entityType === 'ALL') {
263
- servicePromises.push(this.detectLabels(param));
264
- }
265
- if (entityType === 'UNSAFE' || entityType === 'ALL') {
266
- servicePromises.push(this.detectModerationLabels(param));
267
- }
257
+ const { credentials } = await fetchAuthSession();
258
+ assertValidationError(
259
+ !!credentials,
260
+ PredictionsValidationErrorCode.NoCredentials
261
+ );
262
+
263
+ const { identifyLabels = {} } =
264
+ Amplify.getConfig().Predictions?.identify ?? {};
265
+ const { region = '', defaults = {} } = identifyLabels;
266
+ const { type = 'LABELS' } = defaults;
268
267
 
269
- return Promise.all(servicePromises)
270
- .then(data => {
271
- let identifyResult: IdentifyLabelsOutput = {};
272
- // concatenate resolved promises to a single object
273
- data.forEach(val => {
274
- identifyResult = { ...identifyResult, ...val };
275
- });
276
- return identifyResult;
277
- })
278
- .catch(err => Promise.reject(err));
279
- } catch (err) {
280
- return Promise.reject(err);
268
+ this.rekognitionClient = new RekognitionClient({
269
+ region,
270
+ credentials,
271
+ customUserAgent: _getPredictionsIdentifyAmplifyUserAgent(),
272
+ });
273
+
274
+ const inputImage = await this.configureSource(input.labels?.source);
275
+ const param = { Image: inputImage };
276
+ const servicePromises: Promise<IdentifyLabelsOutput>[] = [];
277
+
278
+ // get default argument
279
+ const entityType = input.labels?.type ?? type;
280
+ if (entityType === 'LABELS' || entityType === 'ALL') {
281
+ servicePromises.push(this.detectLabels(param));
281
282
  }
283
+ if (entityType === 'UNSAFE' || entityType === 'ALL') {
284
+ servicePromises.push(this.detectModerationLabels(param));
285
+ }
286
+
287
+ return Promise.all(servicePromises).then(data => {
288
+ let identifyResult: IdentifyLabelsOutput = {};
289
+ // concatenate resolved promises to a single object
290
+ data.forEach(val => {
291
+ identifyResult = { ...identifyResult, ...val };
292
+ });
293
+ return identifyResult;
294
+ });
282
295
  }
283
296
 
284
297
  /**
@@ -289,27 +302,25 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
289
302
  private async detectLabels(
290
303
  param: DetectLabelsCommandInput
291
304
  ): Promise<IdentifyLabelsOutput> {
292
- try {
293
- const detectLabelsCommand = new DetectLabelsCommand(param);
294
- const data = await this.rekognitionClient.send(detectLabelsCommand);
295
- if (!data.Labels) return { labels: null }; // no image was detected
296
- const detectLabelData = data.Labels.map(val => {
297
- const boxes = val.Instances
298
- ? val.Instances.map(val => makeCamelCase(val.BoundingBox))
299
- : undefined;
300
- return {
301
- name: val.Name,
302
- boundingBoxes: boxes,
303
- metadata: {
304
- confidence: val.Confidence,
305
- parents: makeCamelCaseArray(val.Parents),
306
- },
307
- };
308
- });
309
- return { labels: detectLabelData };
310
- } catch (err) {
311
- return Promise.reject(err);
312
- }
305
+ const detectLabelsCommand = new DetectLabelsCommand(param);
306
+ const data = await this.rekognitionClient!.send(detectLabelsCommand);
307
+ if (!data.Labels) return {}; // no image was detected
308
+ const detectLabelData = data.Labels.map(label => {
309
+ const boxes =
310
+ label.Instances?.map(
311
+ instance =>
312
+ makeCamelCase(instance.BoundingBox) as BoundingBox | undefined
313
+ ) || [];
314
+ return {
315
+ name: label.Name,
316
+ boundingBoxes: boxes,
317
+ metadata: {
318
+ confidence: label.Confidence,
319
+ parents: makeCamelCaseArray(label.Parents),
320
+ },
321
+ };
322
+ });
323
+ return { labels: detectLabelData };
313
324
  }
314
325
 
315
326
  /**
@@ -320,20 +331,16 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
320
331
  private async detectModerationLabels(
321
332
  param: DetectModerationLabelsCommandInput
322
333
  ): Promise<IdentifyLabelsOutput> {
323
- try {
324
- const detectModerationLabelsCommand = new DetectModerationLabelsCommand(
325
- param
326
- );
327
- const data = await this.rekognitionClient.send(
328
- detectModerationLabelsCommand
329
- );
330
- if (data.ModerationLabels.length !== 0) {
331
- return { unsafe: 'YES' };
332
- } else {
333
- return { unsafe: 'NO' };
334
- }
335
- } catch (err) {
336
- return Promise.reject(err);
334
+ const detectModerationLabelsCommand = new DetectModerationLabelsCommand(
335
+ param
336
+ );
337
+ const data = await this.rekognitionClient!.send(
338
+ detectModerationLabelsCommand
339
+ );
340
+ if (data.ModerationLabels?.length !== 0) {
341
+ return { unsafe: 'YES' };
342
+ } else {
343
+ return { unsafe: 'NO' };
337
344
  }
338
345
  }
339
346
 
@@ -346,18 +353,23 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
346
353
  protected async identifyEntities(
347
354
  input: IdentifyEntitiesInput
348
355
  ): Promise<IdentifyEntitiesOutput> {
349
- const credentials = await Credentials.get();
350
- if (!credentials) return Promise.reject('No credentials');
356
+ const { credentials } = await fetchAuthSession();
357
+ assertValidationError(
358
+ !!credentials,
359
+ PredictionsValidationErrorCode.NoCredentials
360
+ );
361
+
362
+ const { identifyEntities = {} } =
363
+ Amplify.getConfig().Predictions?.identify ?? {};
364
+ const {
365
+ region = '',
366
+ celebrityDetectionEnabled = false,
367
+ defaults = {},
368
+ } = identifyEntities;
351
369
  const {
352
- identifyEntities: {
353
- region = '',
354
- celebrityDetectionEnabled = false,
355
- defaults: {
356
- collectionId: collectionIdConfig = '',
357
- maxEntities: maxFacesConfig = 50,
358
- } = {},
359
- } = {},
360
- } = this._config;
370
+ collectionId: collectionIdConfig = '',
371
+ maxEntities: maxFacesConfig = 50,
372
+ } = defaults;
361
373
  // default arguments
362
374
 
363
375
  this.rekognitionClient = new RekognitionClient({
@@ -365,45 +377,36 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
365
377
  credentials,
366
378
  customUserAgent: _getPredictionsIdentifyAmplifyUserAgent(),
367
379
  });
368
- let inputImage: Image;
369
- await this.configureSource(input.entities.source)
370
- .then(data => (inputImage = data))
371
- .catch(err => {
372
- return Promise.reject(err);
373
- });
374
-
380
+ const inputImage = await this.configureSource(input.entities?.source);
375
381
  const param = { Attributes: ['ALL'], Image: inputImage };
376
382
 
377
383
  if (
378
384
  isIdentifyCelebrities(input.entities) &&
379
385
  input.entities.celebrityDetection
380
386
  ) {
381
- if (!celebrityDetectionEnabled) {
382
- return Promise.reject(
383
- 'Error: You have to enable celebrity detection first'
384
- );
385
- }
386
- try {
387
- const recognizeCelebritiesCommand = new RecognizeCelebritiesCommand(
388
- param
389
- );
390
- const data = await this.rekognitionClient.send(
391
- recognizeCelebritiesCommand
392
- );
393
- const faces = data.CelebrityFaces.map(celebrity => {
394
- return {
395
- boundingBox: makeCamelCase(celebrity.Face.BoundingBox),
396
- landmarks: makeCamelCaseArray(celebrity.Face.Landmarks),
397
- metadata: {
398
- ...makeCamelCase(celebrity, ['Id', 'Name', 'Urls']),
399
- pose: makeCamelCase(celebrity.Face.Pose),
400
- },
401
- };
402
- });
403
- return { entities: faces };
404
- } catch (err) {
405
- return Promise.reject(err);
406
- }
387
+ assertValidationError(
388
+ celebrityDetectionEnabled,
389
+ PredictionsValidationErrorCode.CelebrityDetectionNotEnabled
390
+ );
391
+ const recognizeCelebritiesCommand = new RecognizeCelebritiesCommand(
392
+ param
393
+ );
394
+ const data = await this.rekognitionClient.send(
395
+ recognizeCelebritiesCommand
396
+ );
397
+ const faces =
398
+ data.CelebrityFaces?.map(
399
+ celebrity =>
400
+ ({
401
+ boundingBox: makeCamelCase(celebrity.Face?.BoundingBox),
402
+ landmarks: makeCamelCaseArray(celebrity.Face?.Landmarks),
403
+ metadata: {
404
+ ...makeCamelCase(celebrity, ['Id', 'Name', 'Urls']),
405
+ pose: makeCamelCase(celebrity.Face?.Pose),
406
+ },
407
+ } as IdentifyEntity)
408
+ ) ?? [];
409
+ return { entities: faces };
407
410
  } else if (
408
411
  isIdentifyFromCollection(input.entities) &&
409
412
  input.entities.collection
@@ -418,33 +421,29 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
418
421
  CollectionId: collectionId,
419
422
  MaxFaces: maxFaces,
420
423
  };
421
- try {
422
- const searchFacesByImageCommand = new SearchFacesByImageCommand(
423
- updatedParam
424
- );
425
- const data = await this.rekognitionClient.send(
426
- searchFacesByImageCommand
427
- );
428
- const faces = data.FaceMatches.map(val => {
424
+ const searchFacesByImageCommand = new SearchFacesByImageCommand(
425
+ updatedParam
426
+ );
427
+ const data = await this.rekognitionClient.send(searchFacesByImageCommand);
428
+ const faces =
429
+ data.FaceMatches?.map(match => {
430
+ const externalImageId = match.Face?.ExternalImageId
431
+ ? this.decodeExternalImageId(match.Face.ExternalImageId)
432
+ : undefined;
429
433
  return {
430
- boundingBox: makeCamelCase(val.Face.BoundingBox),
434
+ boundingBox: makeCamelCase(match.Face?.BoundingBox),
431
435
  metadata: {
432
- externalImageId: this.decodeExternalImageId(
433
- val.Face.ExternalImageId
434
- ),
435
- similarity: val.Similarity,
436
+ externalImageId,
437
+ similarity: match.Similarity,
436
438
  },
437
- };
438
- });
439
- return { entities: faces };
440
- } catch (err) {
441
- return Promise.reject(err);
442
- }
439
+ } as IdentifyEntity;
440
+ }) ?? [];
441
+ return { entities: faces };
443
442
  } else {
444
- try {
445
- const detectFacesCommand = new DetectFacesCommand(param);
446
- const data = await this.rekognitionClient.send(detectFacesCommand);
447
- const faces = data.FaceDetails.map(detail => {
443
+ const detectFacesCommand = new DetectFacesCommand(param);
444
+ const data = await this.rekognitionClient.send(detectFacesCommand);
445
+ const faces =
446
+ data.FaceDetails?.map(detail => {
448
447
  // face attributes keys we want to extract from Rekognition's response
449
448
  const attributeKeys = [
450
449
  'Smile',
@@ -456,12 +455,14 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
456
455
  'EyesOpen',
457
456
  'MouthOpen',
458
457
  ];
459
- const faceAttributes = makeCamelCase(detail, attributeKeys);
460
- if (detail.Emotions) {
461
- faceAttributes['emotions'] = detail.Emotions.map(
462
- emotion => emotion.Type
463
- );
464
- }
458
+ const faceAttributes = makeCamelCase(
459
+ detail,
460
+ attributeKeys
461
+ ) as FaceAttributes;
462
+
463
+ faceAttributes.emotions = detail.Emotions?.map(
464
+ emotion => emotion.Type
465
+ );
465
466
  return {
466
467
  boundingBox: makeCamelCase(detail.BoundingBox),
467
468
  landmarks: makeCamelCaseArray(detail.Landmarks),
@@ -471,12 +472,9 @@ export class AmazonAIIdentifyPredictionsProvider extends AbstractIdentifyPredict
471
472
  confidence: detail.Confidence,
472
473
  pose: makeCamelCase(detail.Pose),
473
474
  },
474
- };
475
- });
476
- return { entities: faces };
477
- } catch (err) {
478
- return Promise.reject(err);
479
- }
475
+ } as IdentifyEntity;
476
+ }) ?? [];
477
+ return { entities: faces };
480
478
  }
481
479
  }
482
480