quidproquo-actionprocessor-awslambda 0.0.256 → 0.0.257
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/lib/commonjs/getActionProcessor/core/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/core/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js +35 -0
- package/lib/commonjs/getActionProcessor/core/file/index.js +2 -1
- package/lib/commonjs/getActionProcessor/webserver/extract/getExtractExpenseActionProcessor.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/webserver/extract/getExtractExpenseActionProcessor.js +56 -0
- package/lib/commonjs/getActionProcessor/webserver/extract/index.d.ts +2 -0
- package/lib/commonjs/getActionProcessor/webserver/extract/index.js +17 -0
- package/lib/commonjs/getActionProcessor/webserver/index.d.ts +1 -0
- package/lib/commonjs/getActionProcessor/webserver/index.js +3 -1
- package/lib/commonjs/logic/dynamo/qpqDynamoOrm/buildDynamoUpdate.d.ts +1 -2
- package/lib/commonjs/logic/dynamo/qpqDynamoOrm/buildDynamoUpdate.js +43 -21
- package/lib/commonjs/logic/s3/generatePresignedUploadUrl.d.ts +1 -0
- package/lib/commonjs/logic/s3/generatePresignedUploadUrl.js +59 -0
- package/lib/commonjs/logic/textract/analyzeExpense.d.ts +51 -0
- package/lib/commonjs/logic/textract/analyzeExpense.js +31 -0
- package/lib/commonjs/logic/textract/index.d.ts +2 -0
- package/lib/commonjs/logic/textract/index.js +18 -0
- package/lib/commonjs/logic/textract/transformExpenseResponse.d.ts +29 -0
- package/lib/commonjs/logic/textract/transformExpenseResponse.js +180 -0
- package/lib/esm/getActionProcessor/core/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.d.ts +2 -0
- package/lib/esm/getActionProcessor/core/file/getFileGenerateTemporaryUploadSecureUrlActionProcessor.js +20 -0
- package/lib/esm/getActionProcessor/core/file/index.js +2 -0
- package/lib/esm/getActionProcessor/webserver/extract/getExtractExpenseActionProcessor.d.ts +2 -0
- package/lib/esm/getActionProcessor/webserver/extract/getExtractExpenseActionProcessor.js +40 -0
- package/lib/esm/getActionProcessor/webserver/extract/index.d.ts +2 -0
- package/lib/esm/getActionProcessor/webserver/extract/index.js +4 -0
- package/lib/esm/getActionProcessor/webserver/index.d.ts +1 -0
- package/lib/esm/getActionProcessor/webserver/index.js +3 -0
- package/lib/esm/logic/dynamo/qpqDynamoOrm/buildDynamoUpdate.d.ts +1 -2
- package/lib/esm/logic/dynamo/qpqDynamoOrm/buildDynamoUpdate.js +42 -19
- package/lib/esm/logic/s3/generatePresignedUploadUrl.d.ts +1 -0
- package/lib/esm/logic/s3/generatePresignedUploadUrl.js +49 -0
- package/lib/esm/logic/textract/analyzeExpense.d.ts +51 -0
- package/lib/esm/logic/textract/analyzeExpense.js +18 -0
- package/lib/esm/logic/textract/index.d.ts +2 -0
- package/lib/esm/logic/textract/index.js +2 -0
- package/lib/esm/logic/textract/transformExpenseResponse.d.ts +29 -0
- package/lib/esm/logic/textract/transformExpenseResponse.js +173 -0
- package/package.json +8 -6
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getFileGenerateTemporaryUploadSecureUrlActionProcessor = void 0;
|
|
13
|
+
const quidproquo_config_aws_1 = require("quidproquo-config-aws");
|
|
14
|
+
const quidproquo_core_1 = require("quidproquo-core");
|
|
15
|
+
const quidproquo_core_2 = require("quidproquo-core");
|
|
16
|
+
const generatePresignedUploadUrl_1 = require("../../../logic/s3/generatePresignedUploadUrl");
|
|
17
|
+
const utils_1 = require("./utils");
|
|
18
|
+
const getProcessFileGenerateTemporaryUploadSecureUrl = (qpqConfig) => {
|
|
19
|
+
return (_a, session_1) => __awaiter(void 0, [_a, session_1], void 0, function* ({ drive, filepath, expirationMs, contentType }, session) {
|
|
20
|
+
try {
|
|
21
|
+
const s3BucketName = (0, utils_1.resolveStorageDriveBucketName)(drive, qpqConfig);
|
|
22
|
+
const url = yield (0, generatePresignedUploadUrl_1.generatePresignedUploadUrl)(s3BucketName, filepath, quidproquo_config_aws_1.qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig), expirationMs, session.correlation, contentType);
|
|
23
|
+
return (0, quidproquo_core_2.actionResult)(url);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return (0, quidproquo_core_1.actionResultError)(quidproquo_core_1.ErrorTypeEnum.GenericError, 'Unable to generate temporary upload secure URL', error);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
const getFileGenerateTemporaryUploadSecureUrlActionProcessor = (qpqConfig) => __awaiter(void 0, void 0, void 0, function* () {
|
|
31
|
+
return ({
|
|
32
|
+
[quidproquo_core_2.FileActionType.GenerateTemporaryUploadSecureUrl]: getProcessFileGenerateTemporaryUploadSecureUrl(qpqConfig),
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
exports.getFileGenerateTemporaryUploadSecureUrlActionProcessor = getFileGenerateTemporaryUploadSecureUrlActionProcessor;
|
|
@@ -13,6 +13,7 @@ exports.getFileActionProcessor = void 0;
|
|
|
13
13
|
const getFileDeleteActionProcessor_1 = require("./getFileDeleteActionProcessor");
|
|
14
14
|
const getFileExistsActionProcessor_1 = require("./getFileExistsActionProcessor");
|
|
15
15
|
const getFileGenerateTemporarySecureUrlActionProcessor_1 = require("./getFileGenerateTemporarySecureUrlActionProcessor");
|
|
16
|
+
const getFileGenerateTemporaryUploadSecureUrlActionProcessor_1 = require("./getFileGenerateTemporaryUploadSecureUrlActionProcessor");
|
|
16
17
|
const getFileIsColdStorageActionProcessor_1 = require("./getFileIsColdStorageActionProcessor");
|
|
17
18
|
const getFileListDirectoryActionProcessor_1 = require("./getFileListDirectoryActionProcessor");
|
|
18
19
|
const getFileReadBinaryContentsActionProcessor_1 = require("./getFileReadBinaryContentsActionProcessor");
|
|
@@ -22,6 +23,6 @@ const getFileWriteBinaryContentsActionProcessor_1 = require("./getFileWriteBinar
|
|
|
22
23
|
const getFileWriteObjectJsonActionProcessor_1 = require("./getFileWriteObjectJsonActionProcessor");
|
|
23
24
|
const getFileWriteTextContentsActionProcessor_1 = require("./getFileWriteTextContentsActionProcessor");
|
|
24
25
|
const getFileActionProcessor = (qpqConfig, dynamicModuleLoader) => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
-
return (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (yield (0, getFileDeleteActionProcessor_1.getFileDeleteActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileExistsActionProcessor_1.getFileExistsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileGenerateTemporarySecureUrlActionProcessor_1.getFileGenerateTemporarySecureUrlActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileIsColdStorageActionProcessor_1.getFileIsColdStorageActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileListDirectoryActionProcessor_1.getFileListDirectoryActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadTextContentsActionProcessor_1.getFileReadTextContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadObjectJsonActionProcessor_1.getFileReadObjectJsonActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteTextContentsActionProcessor_1.getFileWriteTextContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadBinaryContentsActionProcessor_1.getFileReadBinaryContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteObjectJsonActionProcessor_1.getFileWriteObjectJsonActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteBinaryContentsActionProcessor_1.getFileWriteBinaryContentsActionProcessor)(qpqConfig, dynamicModuleLoader))));
|
|
26
|
+
return (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (yield (0, getFileDeleteActionProcessor_1.getFileDeleteActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileExistsActionProcessor_1.getFileExistsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileGenerateTemporarySecureUrlActionProcessor_1.getFileGenerateTemporarySecureUrlActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileGenerateTemporaryUploadSecureUrlActionProcessor_1.getFileGenerateTemporaryUploadSecureUrlActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileIsColdStorageActionProcessor_1.getFileIsColdStorageActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileListDirectoryActionProcessor_1.getFileListDirectoryActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadTextContentsActionProcessor_1.getFileReadTextContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadObjectJsonActionProcessor_1.getFileReadObjectJsonActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteTextContentsActionProcessor_1.getFileWriteTextContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadBinaryContentsActionProcessor_1.getFileReadBinaryContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteObjectJsonActionProcessor_1.getFileWriteObjectJsonActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteBinaryContentsActionProcessor_1.getFileWriteBinaryContentsActionProcessor)(qpqConfig, dynamicModuleLoader))));
|
|
26
27
|
});
|
|
27
28
|
exports.getFileActionProcessor = getFileActionProcessor;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getExtractExpenseActionProcessor = void 0;
|
|
13
|
+
const quidproquo_config_aws_1 = require("quidproquo-config-aws");
|
|
14
|
+
const quidproquo_core_1 = require("quidproquo-core");
|
|
15
|
+
const quidproquo_webserver_1 = require("quidproquo-webserver");
|
|
16
|
+
const awsNamingUtils_1 = require("../../../awsNamingUtils");
|
|
17
|
+
const textract_1 = require("../../../logic/textract");
|
|
18
|
+
const resolveStorageDriveBucketName = (drive, qpqConfig) => {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
const storageDriveConfig = quidproquo_core_1.qpqCoreUtils.getStorageDriveByName(drive, qpqConfig);
|
|
21
|
+
if (!storageDriveConfig) {
|
|
22
|
+
throw new Error(`Could not find storage drive config for [${drive}]`);
|
|
23
|
+
}
|
|
24
|
+
return (0, awsNamingUtils_1.getConfigRuntimeResourceNameFromConfigWithServiceOverride)(((_a = storageDriveConfig.owner) === null || _a === void 0 ? void 0 : _a.resourceNameOverride) || drive, qpqConfig, (_b = storageDriveConfig.owner) === null || _b === void 0 ? void 0 : _b.module);
|
|
25
|
+
};
|
|
26
|
+
const getProcessExtractExpense = (qpqConfig) => {
|
|
27
|
+
return (_a) => __awaiter(void 0, [_a], void 0, function* ({ storageDriveName, filePath }) {
|
|
28
|
+
try {
|
|
29
|
+
const bucketName = resolveStorageDriveBucketName(storageDriveName, qpqConfig);
|
|
30
|
+
const region = quidproquo_config_aws_1.qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig);
|
|
31
|
+
// Call Textract to analyze the expense document
|
|
32
|
+
const textractResponse = yield (0, textract_1.analyzeExpenseDocument)(bucketName, filePath, region);
|
|
33
|
+
// Transform the response to our format
|
|
34
|
+
const extractedDocument = (0, textract_1.transformTextractExpenseResponse)(textractResponse, storageDriveName, filePath, true);
|
|
35
|
+
return (0, quidproquo_core_1.actionResult)(extractedDocument);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// Handle specific AWS errors with proper error mapping
|
|
39
|
+
return (0, quidproquo_core_1.actionResultErrorFromCaughtError)(error, {
|
|
40
|
+
InvalidS3ObjectException: () => (0, quidproquo_core_1.actionResultError)(quidproquo_webserver_1.ExtractExpenseErrorTypeEnum.FileNotFound, 'The specified file could not be found or accessed'),
|
|
41
|
+
NoSuchKey: () => (0, quidproquo_core_1.actionResultError)(quidproquo_webserver_1.ExtractExpenseErrorTypeEnum.FileNotFound, 'The specified file does not exist'),
|
|
42
|
+
UnsupportedDocumentException: () => (0, quidproquo_core_1.actionResultError)(quidproquo_webserver_1.ExtractExpenseErrorTypeEnum.UnsupportedFormat, 'The document format is not supported for expense analysis'),
|
|
43
|
+
InvalidParameterException: () => (0, quidproquo_core_1.actionResultError)(quidproquo_webserver_1.ExtractExpenseErrorTypeEnum.InvalidParameter, 'Invalid parameters provided to the extraction service'),
|
|
44
|
+
ThrottlingException: () => (0, quidproquo_core_1.actionResultError)(quidproquo_webserver_1.ExtractExpenseErrorTypeEnum.RateLimited, 'Too many requests, please try again later'),
|
|
45
|
+
InvalidObjectState: () => (0, quidproquo_core_1.actionResultError)(quidproquo_webserver_1.ExtractExpenseErrorTypeEnum.InvalidStorageClass, 'File is in the wrong storage class'),
|
|
46
|
+
AccessDenied: () => (0, quidproquo_core_1.actionResultError)(quidproquo_webserver_1.ExtractExpenseErrorTypeEnum.AccessDenied, 'Access denied to the specified file'),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
const getExtractExpenseActionProcessor = (qpqConfig) => __awaiter(void 0, void 0, void 0, function* () {
|
|
52
|
+
return ({
|
|
53
|
+
[quidproquo_webserver_1.ExtractActionType.Expense]: getProcessExtractExpense(qpqConfig),
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
exports.getExtractExpenseActionProcessor = getExtractExpenseActionProcessor;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.getExtractActionProcessor = void 0;
|
|
13
|
+
const getExtractExpenseActionProcessor_1 = require("./getExtractExpenseActionProcessor");
|
|
14
|
+
const getExtractActionProcessor = (qpqConfig, dynamicModuleLoader) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
return (Object.assign({}, (yield (0, getExtractExpenseActionProcessor_1.getExtractExpenseActionProcessor)(qpqConfig, dynamicModuleLoader))));
|
|
16
|
+
});
|
|
17
|
+
exports.getExtractActionProcessor = getExtractActionProcessor;
|
|
@@ -24,13 +24,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.getWebserverActionProcessor = void 0;
|
|
27
|
+
const extract_1 = require("./extract");
|
|
27
28
|
const serviceFunction_1 = require("./serviceFunction");
|
|
28
29
|
const webEntry_1 = require("./webEntry");
|
|
29
30
|
const websocket_1 = require("./websocket");
|
|
31
|
+
__exportStar(require("./extract"), exports);
|
|
30
32
|
__exportStar(require("./serviceFunction"), exports);
|
|
31
33
|
__exportStar(require("./webEntry"), exports);
|
|
32
34
|
__exportStar(require("./websocket"), exports);
|
|
33
35
|
const getWebserverActionProcessor = (qpqConfig, dynamicModuleLoader) => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
-
return (Object.assign(Object.assign(Object.assign({}, (yield (0, webEntry_1.getWebEntryActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, serviceFunction_1.getServiceFunctionActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, websocket_1.getWebsocketActionProcessor)(qpqConfig, dynamicModuleLoader))));
|
|
36
|
+
return (Object.assign(Object.assign(Object.assign(Object.assign({}, (yield (0, extract_1.getExtractActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, webEntry_1.getWebEntryActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, serviceFunction_1.getServiceFunctionActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, websocket_1.getWebsocketActionProcessor)(qpqConfig, dynamicModuleLoader))));
|
|
35
37
|
});
|
|
36
38
|
exports.getWebserverActionProcessor = getWebserverActionProcessor;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { KvsUpdate
|
|
1
|
+
import { KvsUpdate } from 'quidproquo-core';
|
|
2
2
|
import { AttributeValue } from '@aws-sdk/client-dynamodb';
|
|
3
3
|
interface ExpressionAttributeNameMap {
|
|
4
4
|
[key: string]: string;
|
|
@@ -7,6 +7,5 @@ export declare const buildUpdateExpressionAttributeNames: (updates: KvsUpdate) =
|
|
|
7
7
|
export declare const buildUpdateExpressionAttributeValues: (updates: KvsUpdate) => {
|
|
8
8
|
[key: string]: AttributeValue;
|
|
9
9
|
} | undefined;
|
|
10
|
-
export declare const buildDynamoUpdateExpressionForType: (type: KvsUpdateActionType, kvsUpdate: KvsUpdate) => string;
|
|
11
10
|
export declare const buildDynamoUpdateExpression: (updates: KvsUpdate) => string;
|
|
12
11
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildDynamoUpdateExpression = exports.
|
|
3
|
+
exports.buildDynamoUpdateExpression = exports.buildUpdateExpressionAttributeValues = exports.buildUpdateExpressionAttributeNames = void 0;
|
|
4
4
|
const quidproquo_core_1 = require("quidproquo-core");
|
|
5
5
|
const buildDynamoQuery_1 = require("./buildDynamoQuery");
|
|
6
6
|
const buildUpdateExpressionAttributeNames = (updates) => {
|
|
@@ -35,6 +35,11 @@ const buildUpdateExpressionAttributeValues = (updates) => {
|
|
|
35
35
|
const valuePlaceholder = (0, buildDynamoQuery_1.getValueName)(update.value);
|
|
36
36
|
attributeValues[valuePlaceholder] = (0, buildDynamoQuery_1.buildAttributeValue)(update.value);
|
|
37
37
|
}
|
|
38
|
+
// Include defaultValue for Increment actions
|
|
39
|
+
if (update.defaultValue !== undefined && update.defaultValue !== null) {
|
|
40
|
+
const defaultPlaceholder = (0, buildDynamoQuery_1.getValueName)(update.defaultValue);
|
|
41
|
+
attributeValues[defaultPlaceholder] = (0, buildDynamoQuery_1.buildAttributeValue)(update.defaultValue);
|
|
42
|
+
}
|
|
38
43
|
}
|
|
39
44
|
return Object.keys(attributeValues).length > 0 ? attributeValues : undefined;
|
|
40
45
|
};
|
|
@@ -62,6 +67,23 @@ const buildDynamoUpdateExpressionDelete = (update) => {
|
|
|
62
67
|
return `${getNestedItemName(update.attributePath)}`;
|
|
63
68
|
}
|
|
64
69
|
};
|
|
70
|
+
const buildDynamoUpdateExpressionSetIfNotExists = (update) => {
|
|
71
|
+
if (update.value === undefined || update.value === null) {
|
|
72
|
+
throw new Error("Value must be provided for 'SetIfNotExists' action");
|
|
73
|
+
}
|
|
74
|
+
const attrPath = getNestedItemName(update.attributePath);
|
|
75
|
+
return `${attrPath} = if_not_exists(${attrPath}, ${(0, buildDynamoQuery_1.getValueName)(update.value)})`;
|
|
76
|
+
};
|
|
77
|
+
const buildDynamoUpdateExpressionIncrement = (update) => {
|
|
78
|
+
if (update.value === undefined || update.value === null) {
|
|
79
|
+
throw new Error("Increment value must be provided for 'Increment' action");
|
|
80
|
+
}
|
|
81
|
+
if (update.defaultValue === undefined || update.defaultValue === null) {
|
|
82
|
+
throw new Error("Default value must be provided for 'Increment' action");
|
|
83
|
+
}
|
|
84
|
+
const attrPath = getNestedItemName(update.attributePath);
|
|
85
|
+
return `${attrPath} = if_not_exists(${attrPath}, ${(0, buildDynamoQuery_1.getValueName)(update.defaultValue)}) + ${(0, buildDynamoQuery_1.getValueName)(update.value)}`;
|
|
86
|
+
};
|
|
65
87
|
const getNestedItemName = (attributePath) => {
|
|
66
88
|
if (Array.isArray(attributePath)) {
|
|
67
89
|
let path = '';
|
|
@@ -89,36 +111,36 @@ const buildDynamoUpdateExpressionPart = (update, updateIndex) => {
|
|
|
89
111
|
return buildDynamoUpdateExpressionAdd(update);
|
|
90
112
|
case quidproquo_core_1.KvsUpdateActionType.Delete:
|
|
91
113
|
return buildDynamoUpdateExpressionDelete(update);
|
|
114
|
+
case quidproquo_core_1.KvsUpdateActionType.SetIfNotExists:
|
|
115
|
+
return buildDynamoUpdateExpressionSetIfNotExists(update);
|
|
116
|
+
case quidproquo_core_1.KvsUpdateActionType.Increment:
|
|
117
|
+
return buildDynamoUpdateExpressionIncrement(update);
|
|
92
118
|
default:
|
|
93
119
|
throw new Error(`Invalid update action type: ${update.action}`);
|
|
94
120
|
}
|
|
95
121
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
122
|
+
// Types that generate SET expressions
|
|
123
|
+
const SET_ACTION_TYPES = [
|
|
124
|
+
quidproquo_core_1.KvsUpdateActionType.Set,
|
|
125
|
+
quidproquo_core_1.KvsUpdateActionType.SetIfNotExists,
|
|
126
|
+
quidproquo_core_1.KvsUpdateActionType.Increment
|
|
127
|
+
];
|
|
128
|
+
const buildDynamoUpdateExpressionForClause = (clause, actionTypes, kvsUpdate) => {
|
|
129
|
+
const actions = kvsUpdate.filter((update) => actionTypes.includes(update.action));
|
|
99
130
|
if (actions.length === 0) {
|
|
100
131
|
return '';
|
|
101
132
|
}
|
|
102
133
|
const expressions = actions.map((update, index) => buildDynamoUpdateExpressionPart(update, index)).join(', ');
|
|
103
|
-
|
|
104
|
-
case quidproquo_core_1.KvsUpdateActionType.Set:
|
|
105
|
-
return `SET ${expressions}`;
|
|
106
|
-
case quidproquo_core_1.KvsUpdateActionType.Remove:
|
|
107
|
-
return `REMOVE ${expressions}`;
|
|
108
|
-
case quidproquo_core_1.KvsUpdateActionType.Add:
|
|
109
|
-
return `ADD ${expressions}`;
|
|
110
|
-
case quidproquo_core_1.KvsUpdateActionType.Delete:
|
|
111
|
-
return `DELETE ${expressions}`;
|
|
112
|
-
default:
|
|
113
|
-
throw new Error(`Invalid update action type: ${type}`);
|
|
114
|
-
}
|
|
134
|
+
return `${clause} ${expressions}`;
|
|
115
135
|
};
|
|
116
|
-
exports.buildDynamoUpdateExpressionForType = buildDynamoUpdateExpressionForType;
|
|
117
136
|
const buildDynamoUpdateExpression = (updates) => {
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
137
|
+
const clauses = [
|
|
138
|
+
buildDynamoUpdateExpressionForClause('SET', SET_ACTION_TYPES, updates),
|
|
139
|
+
buildDynamoUpdateExpressionForClause('REMOVE', [quidproquo_core_1.KvsUpdateActionType.Remove], updates),
|
|
140
|
+
buildDynamoUpdateExpressionForClause('ADD', [quidproquo_core_1.KvsUpdateActionType.Add], updates),
|
|
141
|
+
buildDynamoUpdateExpressionForClause('DELETE', [quidproquo_core_1.KvsUpdateActionType.Delete], updates),
|
|
142
|
+
].filter((expression) => !!expression);
|
|
143
|
+
const result = clauses.join(' ');
|
|
122
144
|
console.log('Update Expression: ', result);
|
|
123
145
|
return result;
|
|
124
146
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const generatePresignedUploadUrl: (bucketName: string, objectKey: string, region: string, expirationMs: number, correlationId?: string, contentType?: string) => Promise<string>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.generatePresignedUploadUrl = void 0;
|
|
13
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
14
|
+
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
15
|
+
// import { createPresignedPost } from '@aws-sdk/s3-presigned-post';
|
|
16
|
+
const createAwsClient_1 = require("../createAwsClient");
|
|
17
|
+
// export const generatePresignedUploadFormUrl = async (
|
|
18
|
+
// bucketName: string,
|
|
19
|
+
// objectKey: string,
|
|
20
|
+
// region: string,
|
|
21
|
+
// expirationMs: number,
|
|
22
|
+
// contentType: string | undefined,
|
|
23
|
+
// maxSizeBytes?: number | undefined
|
|
24
|
+
// ): Promise<{ url: string; fields: Record<string, string> }> => {
|
|
25
|
+
// const s3Client = createAwsClient(S3Client, { region });
|
|
26
|
+
// const conditions: any[] = [];
|
|
27
|
+
// // Add content type condition if provided
|
|
28
|
+
// if (contentType) {
|
|
29
|
+
// conditions.push(['eq', '$Content-Type', contentType]);
|
|
30
|
+
// }
|
|
31
|
+
// // Add file size limit condition if provided
|
|
32
|
+
// if (maxSizeBytes) {
|
|
33
|
+
// conditions.push(['content-length-range', 0, maxSizeBytes]);
|
|
34
|
+
// }
|
|
35
|
+
// const presignedPost = await createPresignedPost(s3Client, {
|
|
36
|
+
// Bucket: bucketName,
|
|
37
|
+
// Key: objectKey,
|
|
38
|
+
// Conditions: conditions,
|
|
39
|
+
// Expires: Math.floor(expirationMs / 1000),
|
|
40
|
+
// });
|
|
41
|
+
// return {
|
|
42
|
+
// url: presignedPost.url,
|
|
43
|
+
// fields: presignedPost.fields
|
|
44
|
+
// };
|
|
45
|
+
// };
|
|
46
|
+
const generatePresignedUploadUrl = (bucketName, objectKey, region, expirationMs, correlationId, contentType) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
+
const s3Client = (0, createAwsClient_1.createAwsClient)(client_s3_1.S3Client, { region });
|
|
48
|
+
const putObjectCommand = new client_s3_1.PutObjectCommand({
|
|
49
|
+
Bucket: bucketName,
|
|
50
|
+
Key: objectKey,
|
|
51
|
+
ContentType: contentType,
|
|
52
|
+
Metadata: Object.assign(Object.assign({}, (correlationId && { 'correlation-id': correlationId })), { 'upload-timestamp': Date.now().toString() })
|
|
53
|
+
});
|
|
54
|
+
const url = yield (0, s3_request_presigner_1.getSignedUrl)(s3Client, putObjectCommand, {
|
|
55
|
+
expiresIn: expirationMs / 1000,
|
|
56
|
+
});
|
|
57
|
+
return url;
|
|
58
|
+
});
|
|
59
|
+
exports.generatePresignedUploadUrl = generatePresignedUploadUrl;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface TextractExpenseAnalysis {
|
|
2
|
+
DocumentMetadata?: {
|
|
3
|
+
Pages?: number;
|
|
4
|
+
};
|
|
5
|
+
ExpenseDocuments?: Array<{
|
|
6
|
+
ExpenseIndex?: number;
|
|
7
|
+
SummaryFields?: Array<{
|
|
8
|
+
Type?: {
|
|
9
|
+
Text?: string;
|
|
10
|
+
Confidence?: number;
|
|
11
|
+
};
|
|
12
|
+
ValueDetection?: {
|
|
13
|
+
Text?: string;
|
|
14
|
+
Confidence?: number;
|
|
15
|
+
};
|
|
16
|
+
LabelDetection?: {
|
|
17
|
+
Text?: string;
|
|
18
|
+
Confidence?: number;
|
|
19
|
+
};
|
|
20
|
+
PageNumber?: number;
|
|
21
|
+
}>;
|
|
22
|
+
LineItemGroups?: Array<{
|
|
23
|
+
LineItemGroupIndex?: number;
|
|
24
|
+
LineItems?: Array<{
|
|
25
|
+
LineItemExpenseFields?: Array<{
|
|
26
|
+
Type?: {
|
|
27
|
+
Text?: string;
|
|
28
|
+
Confidence?: number;
|
|
29
|
+
};
|
|
30
|
+
ValueDetection?: {
|
|
31
|
+
Text?: string;
|
|
32
|
+
Confidence?: number;
|
|
33
|
+
};
|
|
34
|
+
LabelDetection?: {
|
|
35
|
+
Text?: string;
|
|
36
|
+
Confidence?: number;
|
|
37
|
+
};
|
|
38
|
+
PageNumber?: number;
|
|
39
|
+
}>;
|
|
40
|
+
}>;
|
|
41
|
+
}>;
|
|
42
|
+
Blocks?: Array<{
|
|
43
|
+
BlockType?: string;
|
|
44
|
+
Text?: string;
|
|
45
|
+
Confidence?: number;
|
|
46
|
+
Page?: number;
|
|
47
|
+
Id?: string;
|
|
48
|
+
}>;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
export declare const analyzeExpenseDocument: (bucketName: string, documentKey: string, region: string) => Promise<TextractExpenseAnalysis>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.analyzeExpenseDocument = void 0;
|
|
13
|
+
const client_textract_1 = require("@aws-sdk/client-textract");
|
|
14
|
+
const createAwsClient_1 = require("../createAwsClient");
|
|
15
|
+
const analyzeExpenseDocument = (bucketName, documentKey, region) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
+
const textractClient = (0, createAwsClient_1.createAwsClient)(client_textract_1.TextractClient, { region });
|
|
17
|
+
const command = new client_textract_1.AnalyzeExpenseCommand({
|
|
18
|
+
Document: {
|
|
19
|
+
S3Object: {
|
|
20
|
+
Bucket: bucketName,
|
|
21
|
+
Name: documentKey,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
const response = yield textractClient.send(command);
|
|
26
|
+
return {
|
|
27
|
+
DocumentMetadata: response.DocumentMetadata,
|
|
28
|
+
ExpenseDocuments: response.ExpenseDocuments,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
exports.analyzeExpenseDocument = analyzeExpenseDocument;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./analyzeExpense"), exports);
|
|
18
|
+
__exportStar(require("./transformExpenseResponse"), exports);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { TextractExpenseAnalysis } from './analyzeExpense';
|
|
2
|
+
export interface ExtractedExpenseDocument {
|
|
3
|
+
metadata: {
|
|
4
|
+
merchantName?: string;
|
|
5
|
+
merchantAddress?: string;
|
|
6
|
+
date?: string;
|
|
7
|
+
currency?: string;
|
|
8
|
+
paymentMethod?: string;
|
|
9
|
+
subtotal?: number;
|
|
10
|
+
tax?: number;
|
|
11
|
+
total?: number;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
};
|
|
14
|
+
lineItems?: Array<{
|
|
15
|
+
description: string;
|
|
16
|
+
quantity?: number;
|
|
17
|
+
unitPrice?: number;
|
|
18
|
+
total?: number;
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
}>;
|
|
21
|
+
rawText?: string;
|
|
22
|
+
source: {
|
|
23
|
+
storageDrive: string;
|
|
24
|
+
filePath: string;
|
|
25
|
+
textractJobId?: string;
|
|
26
|
+
};
|
|
27
|
+
_raw?: any;
|
|
28
|
+
}
|
|
29
|
+
export declare function transformTextractExpenseResponse(textractResponse: TextractExpenseAnalysis, storageDrive: string, filePath: string, includeRaw?: boolean): ExtractedExpenseDocument;
|