@ikonintegration/ikapi 4.0.1 → 5.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.
- package/.eslintignore +3 -0
- package/.eslintrc.cjs +81 -0
- package/.github/workflows/npmpublish.yml +8 -19
- package/.github/workflows/prs.yml +12 -0
- package/README.md +89 -99
- package/dist/index.d.ts +16 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/package-lock.json +11881 -0
- package/dist/package.json +81 -0
- package/dist/src/API/Request.d.ts +125 -0
- package/dist/src/API/Request.js +185 -0
- package/dist/src/API/Request.js.map +1 -0
- package/dist/src/API/Response.d.ts +188 -0
- package/dist/src/API/Response.js +270 -0
- package/dist/src/API/Response.js.map +1 -0
- package/dist/src/BaseEvent/DynamoTransaction.d.ts +70 -0
- package/dist/src/BaseEvent/DynamoTransaction.js +104 -0
- package/dist/src/BaseEvent/DynamoTransaction.js.map +1 -0
- package/dist/src/BaseEvent/EventProcessor.d.ts +58 -0
- package/dist/src/BaseEvent/EventProcessor.js +101 -0
- package/dist/src/BaseEvent/EventProcessor.js.map +1 -0
- package/dist/src/BaseEvent/Process.d.ts +50 -0
- package/dist/src/BaseEvent/Process.js +64 -0
- package/dist/src/BaseEvent/Process.js.map +1 -0
- package/dist/src/BaseEvent/StepTransaction.d.ts +23 -0
- package/dist/src/BaseEvent/StepTransaction.js +27 -0
- package/dist/src/BaseEvent/StepTransaction.js.map +1 -0
- package/dist/src/BaseEvent/Transaction.d.ts +149 -0
- package/dist/src/BaseEvent/Transaction.js +224 -0
- package/dist/src/BaseEvent/Transaction.js.map +1 -0
- package/dist/src/Cache/Redis.d.ts +29 -0
- package/dist/src/Cache/Redis.js +80 -0
- package/dist/src/Cache/Redis.js.map +1 -0
- package/dist/src/Cache/types.d.ts +31 -0
- package/dist/src/Cache/types.js +2 -0
- package/dist/src/Cache/types.js.map +1 -0
- package/dist/src/Config/Configuration.d.ts +123 -0
- package/dist/src/Config/Configuration.js +109 -0
- package/dist/src/Config/Configuration.js.map +1 -0
- package/dist/src/Config/EnvironmentVar.d.ts +74 -0
- package/dist/src/Config/EnvironmentVar.js +138 -0
- package/dist/src/Config/EnvironmentVar.js.map +1 -0
- package/dist/src/Crypto/Crypto.d.ts +45 -0
- package/dist/src/Crypto/Crypto.js +72 -0
- package/dist/src/Crypto/Crypto.js.map +1 -0
- package/dist/src/Database/Database.d.ts +21 -0
- package/dist/src/Database/Database.js +15 -0
- package/dist/src/Database/Database.js.map +1 -0
- package/dist/src/Database/DatabaseManager.d.ts +47 -0
- package/dist/src/Database/DatabaseManager.js +60 -0
- package/dist/src/Database/DatabaseManager.js.map +1 -0
- package/dist/src/Database/DatabaseTransaction.d.ts +101 -0
- package/dist/src/Database/DatabaseTransaction.js +126 -0
- package/dist/src/Database/DatabaseTransaction.js.map +1 -0
- package/dist/src/Database/index.d.ts +10 -0
- package/dist/src/Database/index.js +15 -0
- package/dist/src/Database/index.js.map +1 -0
- package/dist/src/Database/integrations/dynamo/DynamoDatabase.d.ts +35 -0
- package/dist/src/Database/integrations/dynamo/DynamoDatabase.js +59 -0
- package/dist/src/Database/integrations/dynamo/DynamoDatabase.js.map +1 -0
- package/dist/src/Database/integrations/kysely/KyselyDatabase.d.ts +66 -0
- package/dist/src/Database/integrations/kysely/KyselyDatabase.js +86 -0
- package/dist/src/Database/integrations/kysely/KyselyDatabase.js.map +1 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.d.ts +70 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.js +118 -0
- package/dist/src/Database/integrations/kysely/KyselyTransaction.js.map +1 -0
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.d.ts +36 -0
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.js +54 -0
- package/dist/src/Database/integrations/pgsql/PostgresDatabase.js.map +1 -0
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.d.ts +63 -0
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.js +61 -0
- package/dist/src/Database/integrations/pgsql/PostgresTransaction.js.map +1 -0
- package/dist/src/Database/types.d.ts +76 -0
- package/dist/src/Database/types.js +2 -0
- package/dist/src/Database/types.js.map +1 -0
- package/dist/src/Globals.d.ts +93 -0
- package/dist/src/Globals.js +99 -0
- package/dist/src/Globals.js.map +1 -0
- package/dist/src/Logger/Logger.d.ts +161 -0
- package/dist/src/Logger/Logger.js +299 -0
- package/dist/src/Logger/Logger.js.map +1 -0
- package/dist/src/Mailer/Mailer.d.ts +78 -0
- package/dist/src/Mailer/Mailer.js +182 -0
- package/dist/src/Mailer/Mailer.js.map +1 -0
- package/dist/src/Publisher/Publisher.d.ts +39 -0
- package/dist/src/Publisher/Publisher.js +77 -0
- package/dist/src/Publisher/Publisher.js.map +1 -0
- package/dist/src/Server/RouteResolver.d.ts +33 -0
- package/dist/src/Server/RouteResolver.js +100 -0
- package/dist/src/Server/RouteResolver.js.map +1 -0
- package/dist/src/Server/Router.d.ts +157 -0
- package/dist/src/Server/Router.js +32 -0
- package/dist/src/Server/Router.js.map +1 -0
- package/dist/src/Server/lib/ContainerServer.d.ts +42 -0
- package/dist/src/Server/lib/ContainerServer.js +66 -0
- package/dist/src/Server/lib/ContainerServer.js.map +1 -0
- package/dist/src/Server/lib/Server.d.ts +45 -0
- package/dist/src/Server/lib/Server.js +93 -0
- package/dist/src/Server/lib/Server.js.map +1 -0
- package/dist/src/Server/lib/container/GenericHandler.d.ts +9 -0
- package/dist/src/Server/lib/container/GenericHandler.js +82 -0
- package/dist/src/Server/lib/container/GenericHandler.js.map +1 -0
- package/dist/src/Server/lib/container/GenericHandlerEvent.d.ts +52 -0
- package/dist/src/Server/lib/container/GenericHandlerEvent.js +132 -0
- package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +1 -0
- package/dist/src/Server/lib/container/HealthHandler.d.ts +9 -0
- package/dist/src/Server/lib/container/HealthHandler.js +19 -0
- package/dist/src/Server/lib/container/HealthHandler.js.map +1 -0
- package/dist/src/Server/lib/container/Proxy.d.ts +67 -0
- package/dist/src/Server/lib/container/Proxy.js +143 -0
- package/dist/src/Server/lib/container/Proxy.js.map +1 -0
- package/dist/src/Server/lib/container/Utils.d.ts +14 -0
- package/dist/src/Server/lib/container/Utils.js +37 -0
- package/dist/src/Server/lib/container/Utils.js.map +1 -0
- package/dist/src/Util/AsyncSingleton.d.ts +31 -0
- package/dist/src/Util/AsyncSingleton.js +83 -0
- package/dist/src/Util/AsyncSingleton.js.map +1 -0
- package/dist/src/Util/Utils.d.ts +61 -0
- package/dist/src/Util/Utils.js +147 -0
- package/dist/src/Util/Utils.js.map +1 -0
- package/dist/src/Validation/Validator.d.ts +17 -0
- package/dist/src/Validation/Validator.js +39 -0
- package/dist/src/Validation/Validator.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/index.ts +41 -0
- package/jest.config.ts +37 -0
- package/jest.smoke.config.ts +34 -0
- package/package.json +66 -22
- package/src/API/Request.ts +214 -0
- package/src/API/Response.ts +370 -0
- package/src/BaseEvent/DynamoTransaction.ts +175 -0
- package/src/BaseEvent/EventProcessor.ts +140 -0
- package/src/BaseEvent/Process.ts +78 -0
- package/src/BaseEvent/StepTransaction.ts +35 -0
- package/src/BaseEvent/Transaction.ts +323 -0
- package/src/Cache/Redis.ts +89 -0
- package/src/Cache/types.ts +33 -0
- package/src/Config/Configuration.ts +199 -0
- package/src/Config/EnvironmentVar.ts +142 -0
- package/src/Crypto/Crypto.ts +89 -0
- package/src/Database/Database.ts +22 -0
- package/src/Database/DatabaseManager.ts +67 -0
- package/src/Database/DatabaseTransaction.ts +170 -0
- package/src/Database/index.ts +27 -0
- package/src/Database/integrations/dynamo/DynamoDatabase.ts +58 -0
- package/src/Database/integrations/kysely/KyselyDatabase.ts +99 -0
- package/src/Database/integrations/kysely/KyselyTransaction.ts +172 -0
- package/src/Database/integrations/pgsql/PostgresDatabase.ts +56 -0
- package/src/Database/integrations/pgsql/PostgresTransaction.ts +87 -0
- package/src/Database/types.ts +85 -0
- package/src/Globals.ts +103 -0
- package/src/Logger/Logger.ts +363 -0
- package/src/Mailer/Mailer.ts +217 -0
- package/src/Publisher/Publisher.ts +96 -0
- package/src/Server/RouteResolver.ts +124 -0
- package/src/Server/Router.ts +200 -0
- package/src/Server/lib/ContainerServer.ts +65 -0
- package/src/Server/lib/Server.ts +109 -0
- package/src/Server/lib/container/GenericHandler.ts +76 -0
- package/src/Server/lib/container/GenericHandlerEvent.ts +154 -0
- package/src/Server/lib/container/HealthHandler.ts +11 -0
- package/src/Server/lib/container/Proxy.ts +172 -0
- package/src/Server/lib/container/Utils.ts +33 -0
- package/src/Util/AsyncSingleton.ts +86 -0
- package/src/Util/Utils.ts +131 -0
- package/src/Validation/Validator.ts +45 -0
- package/tests/API/Request.test.ts +273 -0
- package/tests/API/Response.test.ts +367 -0
- package/tests/BaseEvent/DynamoTransaction.test.ts +272 -0
- package/tests/BaseEvent/EventProcessor.test.ts +263 -0
- package/tests/BaseEvent/Process.test.ts +47 -0
- package/tests/BaseEvent/StepTransaction.test.ts +44 -0
- package/tests/BaseEvent/Transaction.test.ts +402 -0
- package/tests/Cache/Redis-client.test.ts +90 -0
- package/tests/Cache/Redis-cluster.test.ts +100 -0
- package/tests/Config/Config.test.ts +205 -0
- package/tests/Config/EnvironmentVar.test.ts +251 -0
- package/tests/Crypto/Crypto.test.ts +88 -0
- package/tests/Database/DatabaseManager.test.ts +79 -0
- package/tests/Database/integrations/dynamo/DynamoDatabase.test.ts +44 -0
- package/tests/Database/integrations/kysely/KyselyDatabase.test.ts +113 -0
- package/tests/Database/integrations/kysely/KyselyTransaction.test.ts +119 -0
- package/tests/Database/integrations/pg/PostgresDatabase.test.ts +76 -0
- package/tests/Database/integrations/pg/PostgresTransaction.test.ts +118 -0
- package/tests/Logger/Logger.test.ts +215 -0
- package/tests/Mailer/Mailer.test.ts +59 -0
- package/tests/Publisher/Publisher.test.ts +60 -0
- package/tests/Server/RouteResolver.test.ts +116 -0
- package/tests/Server/Router.test.ts +39 -0
- package/tests/Server/lib/ContainerServer.test.ts +531 -0
- package/tests/Server/lib/Server.test.ts +12 -0
- package/tests/Server/lib/container/GenericHandler.test.ts +131 -0
- package/tests/Server/lib/container/GenericHandlerEvent.test.ts +103 -0
- package/tests/Server/lib/container/HealthHandler.test.ts +30 -0
- package/tests/Server/lib/container/Proxy.test.ts +268 -0
- package/tests/Server/lib/container/Utils.test.ts +47 -0
- package/tests/Test.utils.ts +78 -0
- package/tests/Utils/Utils.test.ts +229 -0
- package/tests/Validation/Validator.test.ts +82 -0
- package/tsconfig.json +26 -0
- package/tsconfig.smoke.json +26 -0
- package/index.js +0 -88
- package/src/API/IKRequest.js +0 -52
- package/src/API/IKResponse.js +0 -119
- package/src/API/IKUtils.js +0 -51
- package/src/BaseEvent/IKProcess.js +0 -77
- package/src/BaseEvent/IKTransaction.js +0 -139
- package/src/Cache/Prototype/IKCache.js +0 -17
- package/src/Cache/Redis/IKRedis.js +0 -148
- package/src/Database/DDB/IKDB.js +0 -56
- package/src/Database/DDB/IKDBBaseExpression.js +0 -130
- package/src/Database/DDB/IKDBBaseQuery.js +0 -151
- package/src/Database/DDB/IKDBQueryBatchGet.js +0 -37
- package/src/Database/DDB/IKDBQueryBatchWrite.js +0 -64
- package/src/Database/DDB/IKDBQueryDelete.js +0 -34
- package/src/Database/DDB/IKDBQueryGet.js +0 -48
- package/src/Database/DDB/IKDBQueryPut.js +0 -87
- package/src/Database/DDB/IKDBQueryScan.js +0 -45
- package/src/Database/DDB/IKDBQueryTransactionalWrite.js +0 -69
- package/src/Database/DDB/IKDBQueryUpdate.js +0 -221
- package/src/Database/DDB/_IKDBQueryTransactionalRead.js +0 -46
- package/src/Database/PSQL/IKDB.js +0 -41
- package/src/Database/PSQL/IKDBBaseQuery.js +0 -26
- package/src/Database/Prototype/IKDB.js +0 -21
- package/src/Database/Prototype/IKDBBaseQuery.js +0 -14
- package/src/IKDynamoStream.js +0 -42
- package/src/IKEventProcessor.js +0 -42
- package/src/IKGlobals.js +0 -24
- package/src/IKRouter.js +0 -47
- package/src/IKStepTransaction.js +0 -14
- package/src/Logger/IKLogger.js +0 -136
- package/src/Mailer/IKMailer.js +0 -69
- package/src/Publisher/IKPublisher.js +0 -44
- package/src/Tracker/IKExecutionTracker.js +0 -79
- package/src/Validation/IKValidation.js +0 -76
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { TransactionConfig } from './Transaction.js'
|
|
2
|
+
import Logger from '../Logger/Logger.js'
|
|
3
|
+
import Publisher from '../Publisher/Publisher.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A type that represents a modified version of the TransactionConfig type, excluding the 'throwOnErrors' and 'syncReturn' properties.
|
|
7
|
+
*/
|
|
8
|
+
export type ProcessConfig = Omit<TransactionConfig, 'throwOnErrors' | 'syncReturn'>
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents a long-running process that executes a given function at a specified interval.
|
|
12
|
+
*/
|
|
13
|
+
export default class Process {
|
|
14
|
+
/**
|
|
15
|
+
* Private member variable representing the interval value.
|
|
16
|
+
* @type {number}
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
private interval: number
|
|
20
|
+
/**
|
|
21
|
+
* A logger object used for logging messages, errors, and other information.
|
|
22
|
+
* @readonly
|
|
23
|
+
*/
|
|
24
|
+
public readonly logger: Logger
|
|
25
|
+
/**
|
|
26
|
+
* The publisher of the content.
|
|
27
|
+
*/
|
|
28
|
+
public readonly publisher: Publisher
|
|
29
|
+
/**
|
|
30
|
+
* A reference to the NodeJS.Timeout object representing the interval timer.
|
|
31
|
+
*/
|
|
32
|
+
public timeout: NodeJS.Timeout
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Constructs a new instance of the LongRunningProcess class.
|
|
36
|
+
* @param {ProcessConfig} config - The configuration object for the process.
|
|
37
|
+
* @param {number} interval - The interval at which the process should run.
|
|
38
|
+
* @returns None
|
|
39
|
+
*/
|
|
40
|
+
constructor(config: ProcessConfig, interval: number) {
|
|
41
|
+
this.interval = interval
|
|
42
|
+
this.logger = new Logger(config.logger, 'long-running-process')
|
|
43
|
+
this.publisher = new Publisher(config.publisher)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Executes the provided execution function at a specified interval.
|
|
48
|
+
* @param {Function} executionFunc - The function to execute.
|
|
49
|
+
* @returns None
|
|
50
|
+
*/
|
|
51
|
+
public async execute(executionFunc) {
|
|
52
|
+
this.logger.debug('Starting main process code')
|
|
53
|
+
//Program loop
|
|
54
|
+
this.timeout = setInterval(async () => {
|
|
55
|
+
await this.iexecute(executionFunc)
|
|
56
|
+
}, this.interval)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Executes the given execution function asynchronously and handles any exceptions that occur.
|
|
61
|
+
* @param {Function} executionFunc - The function to execute.
|
|
62
|
+
* @returns {boolean} - Returns true if the execution failed, false otherwise.
|
|
63
|
+
*/
|
|
64
|
+
private async iexecute(executionFunc) {
|
|
65
|
+
let executionFailed = true //failed til we say no!
|
|
66
|
+
// safe execution handler
|
|
67
|
+
try {
|
|
68
|
+
// Execute
|
|
69
|
+
await executionFunc(this)
|
|
70
|
+
executionFailed = false
|
|
71
|
+
} catch (e) {
|
|
72
|
+
/* EXECUTION FAIL */
|
|
73
|
+
this.logger.error('Exception when executing main process code. Rolling back DB!')
|
|
74
|
+
this.logger.exception(e)
|
|
75
|
+
}
|
|
76
|
+
return executionFailed
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Context } from 'aws-lambda'
|
|
2
|
+
|
|
3
|
+
import Transaction, { TransactionConfig } from './Transaction.js'
|
|
4
|
+
import Response, { ResponseErrorType } from '../API/Response.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Represents a step transaction that extends the Transaction class.
|
|
8
|
+
*/
|
|
9
|
+
export default class StepTransaction extends Transaction {
|
|
10
|
+
/**
|
|
11
|
+
* Constructor for creating a new Transaction object.
|
|
12
|
+
* @param {any} event - The event object.
|
|
13
|
+
* @param {Context} context - The context object.
|
|
14
|
+
* @param {TransactionConfig} [config] - Optional configuration for the transaction.
|
|
15
|
+
* @returns None
|
|
16
|
+
*/
|
|
17
|
+
constructor(event: any, context: Context, config?: TransactionConfig) {
|
|
18
|
+
super(event, context, {
|
|
19
|
+
syncReturn: true,
|
|
20
|
+
throwOnErrors: true,
|
|
21
|
+
// allow override
|
|
22
|
+
...(config || {}),
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Generates an error response with the provided error message and error code.
|
|
28
|
+
* @param {string} error - The error message to include in the response.
|
|
29
|
+
* @param {string} code - The error code associated with the error.
|
|
30
|
+
* @returns {Response<ResponseErrorType>} - The error response object.
|
|
31
|
+
*/
|
|
32
|
+
protected getErrorResponse(error: string, code: string): Response<ResponseErrorType> {
|
|
33
|
+
return Response.StepFunctionResponse({ err: error, errCode: code }, 400)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import type { APIGatewayEvent, Context, DynamoDBStreamEvent, SQSEvent } from 'aws-lambda'
|
|
2
|
+
|
|
3
|
+
import Request from '../API/Request.js'
|
|
4
|
+
import Response, { ResponseErrorType } from '../API/Response.js'
|
|
5
|
+
import { DatabaseManager } from '../Database/DatabaseManager.js'
|
|
6
|
+
import { DatabaseTransaction } from '../Database/DatabaseTransaction.js'
|
|
7
|
+
import type {
|
|
8
|
+
DatabaseImplType,
|
|
9
|
+
DatabaseTransactionType,
|
|
10
|
+
DatabaseType,
|
|
11
|
+
DbConfig,
|
|
12
|
+
} from '../Database/types.js'
|
|
13
|
+
import Globals from '../Globals.js'
|
|
14
|
+
import Logger, { LoggerConfig } from '../Logger/Logger.js'
|
|
15
|
+
import Publisher, { PublisherConfig } from '../Publisher/Publisher.js'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Defines a type for executing a transaction and returning a promise with the response.
|
|
19
|
+
* @param {TransactionType} transaction - The transaction to execute.
|
|
20
|
+
* @returns A promise that resolves to the response of the transaction.
|
|
21
|
+
*/
|
|
22
|
+
export type TransactionExecution<TransactionType, ResponseInnerType, MiscRespType = never> = (
|
|
23
|
+
transaction: TransactionType
|
|
24
|
+
) => Promise<Response<ResponseInnerType> | Response<ResponseErrorType> | MiscRespType>
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Represents the configuration options for a transaction.
|
|
28
|
+
* @typedef {Object} TransactionConfig
|
|
29
|
+
* @property {boolean} [throwOnErrors] - Whether to throw an error if there are any errors during the transaction.
|
|
30
|
+
* @property {boolean} [syncReturn] - Whether to return the result of the transaction synchronously.
|
|
31
|
+
* @property {boolean} [skipCleanTmp] - Whether to skip cleaning the temporary folder, in EventProcessor.
|
|
32
|
+
* @property {LoggerConfig} [logger] - The configuration options for the logger.
|
|
33
|
+
* @property {PublisherConfig} [publisher] - The configuration options for the publisher.
|
|
34
|
+
*/
|
|
35
|
+
export type TransactionConfig = {
|
|
36
|
+
throwOnErrors?: boolean
|
|
37
|
+
syncReturn?: boolean
|
|
38
|
+
skipCleanTmp?: boolean
|
|
39
|
+
//
|
|
40
|
+
logger?: LoggerConfig
|
|
41
|
+
publisher?: PublisherConfig
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Represents a simple string dictionary with string values
|
|
46
|
+
*/
|
|
47
|
+
export type StringMap = { [key: string]: string | null }
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Represents a transaction object that handles the execution of a request and manages the response.
|
|
51
|
+
* @template InputType - The type of the input data for the transaction.
|
|
52
|
+
* @template ResponseInnerType - The type of the inner response data for the transaction.
|
|
53
|
+
* @template MiscRespType - The type of miscellaneous response data for the transaction.
|
|
54
|
+
*/
|
|
55
|
+
export default class Transaction<
|
|
56
|
+
InputType = never,
|
|
57
|
+
ResponseInnerType = null,
|
|
58
|
+
MiscRespType = never,
|
|
59
|
+
PathParamsType = StringMap,
|
|
60
|
+
QueryParamsType = StringMap,
|
|
61
|
+
> {
|
|
62
|
+
/**
|
|
63
|
+
* The instance of the DatabaseManager class used for managing the database.
|
|
64
|
+
*/
|
|
65
|
+
private databaseManager: DatabaseManager = DatabaseManager.INSTANCE
|
|
66
|
+
/**
|
|
67
|
+
* An array of database transactions.
|
|
68
|
+
* @type {DatabaseTransaction[]}
|
|
69
|
+
*/
|
|
70
|
+
private transactions: DatabaseTransaction[] = []
|
|
71
|
+
/**
|
|
72
|
+
* Represents an event object.
|
|
73
|
+
* @private
|
|
74
|
+
* @type {any}
|
|
75
|
+
*/
|
|
76
|
+
private event: any
|
|
77
|
+
/**
|
|
78
|
+
* The context object for the current instance.
|
|
79
|
+
*/
|
|
80
|
+
private context: Context
|
|
81
|
+
/**
|
|
82
|
+
* The response object that can hold different types of responses.
|
|
83
|
+
* @type {Response<ResponseInnerType | ResponseErrorType> | MiscRespType | null}
|
|
84
|
+
*/
|
|
85
|
+
private response: Response<ResponseInnerType | ResponseErrorType> | MiscRespType
|
|
86
|
+
/**
|
|
87
|
+
* A private boolean variable indicating whether the return value of a synchronous operation
|
|
88
|
+
* should be synchronized with the calling thread.
|
|
89
|
+
*/
|
|
90
|
+
private syncReturn: boolean
|
|
91
|
+
/**
|
|
92
|
+
* A boolean flag indicating whether retroactive errors are enabled or not.
|
|
93
|
+
* @private
|
|
94
|
+
*/
|
|
95
|
+
private retrowErrors: boolean
|
|
96
|
+
/**
|
|
97
|
+
* A logger object used for logging messages, errors, and other information.
|
|
98
|
+
* @readonly
|
|
99
|
+
*/
|
|
100
|
+
public readonly logger: Logger
|
|
101
|
+
/**
|
|
102
|
+
* The request object for making a request of type InputType.
|
|
103
|
+
* @readonly
|
|
104
|
+
*/
|
|
105
|
+
public readonly request: Request<InputType, PathParamsType, QueryParamsType>
|
|
106
|
+
/**
|
|
107
|
+
* The publisher of the content.
|
|
108
|
+
*/
|
|
109
|
+
public readonly publisher: Publisher
|
|
110
|
+
/**
|
|
111
|
+
* A function that acts as a response proxy for a given response object.
|
|
112
|
+
* @param {Response<ResponseInnerType>} response - The response object to proxy.
|
|
113
|
+
* @returns A promise that resolves to void.
|
|
114
|
+
*/
|
|
115
|
+
public responseProxy: ((response: Response<ResponseInnerType>) => Promise<void>) | null
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Constructs a new instance of the Transaction class.
|
|
119
|
+
* @param {APIGatewayEvent | SQSEvent | DynamoDBStreamEvent} event - The event object passed to the Lambda function.
|
|
120
|
+
* @param {Context} context - The context object passed to the Lambda function.
|
|
121
|
+
* @param {TransactionConfig} [config] - Optional configuration object for the transaction.
|
|
122
|
+
* @returns None
|
|
123
|
+
*/
|
|
124
|
+
constructor(
|
|
125
|
+
event: APIGatewayEvent | SQSEvent | DynamoDBStreamEvent,
|
|
126
|
+
context: Context,
|
|
127
|
+
config?: TransactionConfig
|
|
128
|
+
) {
|
|
129
|
+
const transactionId = context.awsRequestId
|
|
130
|
+
? context.awsRequestId
|
|
131
|
+
: (<APIGatewayEvent>event).requestContext
|
|
132
|
+
? (<APIGatewayEvent>event).requestContext.requestId
|
|
133
|
+
: 'unknown'
|
|
134
|
+
// transaction ctx
|
|
135
|
+
this.event = event
|
|
136
|
+
this.context = context
|
|
137
|
+
// when set, this will be called with the response context right before calling the context suceed/fail - useful for writing the resp for example.
|
|
138
|
+
this.responseProxy = null
|
|
139
|
+
// transaction flags
|
|
140
|
+
this.syncReturn = !!config?.syncReturn
|
|
141
|
+
this.retrowErrors = !!config?.throwOnErrors /* retrow internal errors */
|
|
142
|
+
// components
|
|
143
|
+
this.logger = new Logger(config?.logger, transactionId)
|
|
144
|
+
this.request = new Request<InputType, PathParamsType, QueryParamsType>(
|
|
145
|
+
this.event,
|
|
146
|
+
this.context,
|
|
147
|
+
this.logger
|
|
148
|
+
)
|
|
149
|
+
this.publisher = new Publisher(config?.publisher)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Executes a transaction using the provided execution function and returns a promise
|
|
154
|
+
* that resolves to the response or miscellaneous response.
|
|
155
|
+
* @param {TransactionExecution<Transaction<InputType, ResponseInnerType, MiscRespType>, ResponseInnerType, MiscRespType>} executionFunc - The execution function to be executed.
|
|
156
|
+
* @returns {Promise<Response<ResponseInnerType | ResponseErrorType> | MiscRespType>} - A promise that resolves to the response or miscellaneous response.
|
|
157
|
+
*/
|
|
158
|
+
public async execute(
|
|
159
|
+
executionFunc: TransactionExecution<
|
|
160
|
+
Transaction<InputType, ResponseInnerType, MiscRespType, PathParamsType, QueryParamsType>,
|
|
161
|
+
ResponseInnerType,
|
|
162
|
+
MiscRespType
|
|
163
|
+
>
|
|
164
|
+
): Promise<Response<ResponseInnerType | ResponseErrorType> | MiscRespType | null> {
|
|
165
|
+
await this.executeLoggerFlush(async () => {
|
|
166
|
+
await this.executeDBTransactions(async () => {
|
|
167
|
+
return await this.iexecute(executionFunc)
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
// return raw response if sync return is requested
|
|
171
|
+
if (this.syncReturn) return this.response
|
|
172
|
+
// allow request to async succeed through lambda context
|
|
173
|
+
return null
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Executes a transaction using the provided execution function and handles the response.
|
|
178
|
+
* @param {TransactionExecution<Transaction<InputType, ResponseInnerType, MiscRespType>, ResponseInnerType, MiscRespType>} executionFunc - The function to execute the transaction.
|
|
179
|
+
* @returns {Promise<boolean>} - A promise that resolves to a boolean indicating whether the execution failed or not.
|
|
180
|
+
*/
|
|
181
|
+
private async iexecute(
|
|
182
|
+
executionFunc: TransactionExecution<
|
|
183
|
+
Transaction<InputType, ResponseInnerType, MiscRespType, PathParamsType, QueryParamsType>,
|
|
184
|
+
ResponseInnerType,
|
|
185
|
+
MiscRespType
|
|
186
|
+
>
|
|
187
|
+
): Promise<boolean> {
|
|
188
|
+
let executionFailed = true //failed til we say no!
|
|
189
|
+
//safe execution handler
|
|
190
|
+
try {
|
|
191
|
+
//Execute
|
|
192
|
+
this.logger.debug('Starting main request code')
|
|
193
|
+
this.response = await executionFunc(this)
|
|
194
|
+
//Answer client
|
|
195
|
+
if (this.response && this.response instanceof Response) {
|
|
196
|
+
await this.response.build(this.context, this, this.syncReturn)
|
|
197
|
+
executionFailed = !!(this.response.getBody() && this.response.getBody()['rollback'])
|
|
198
|
+
} else if (this.syncReturn && this.response) {
|
|
199
|
+
this.logger.log('Sync return with different response object')
|
|
200
|
+
this.logger.debug(this.response)
|
|
201
|
+
executionFailed = false
|
|
202
|
+
} else {
|
|
203
|
+
this.response = this.getErrorResponse(
|
|
204
|
+
Globals.ErrorResponseInvalidServerResponse,
|
|
205
|
+
Globals.ErrorCode_APIError
|
|
206
|
+
)
|
|
207
|
+
await this.response.build(this.context, this, this.syncReturn)
|
|
208
|
+
this.logger.error('Invalid response object from main request code.')
|
|
209
|
+
}
|
|
210
|
+
} catch (e) {
|
|
211
|
+
/*EXECUTION FAIL*/
|
|
212
|
+
this.logger.error('Exception when executing main request code.')
|
|
213
|
+
this.logger.exception(e)
|
|
214
|
+
//retrow?
|
|
215
|
+
if (this.retrowErrors) throw e
|
|
216
|
+
//envelope exception?
|
|
217
|
+
this.response = this.getErrorResponse(
|
|
218
|
+
Globals.ErrorResponseUnhandledError,
|
|
219
|
+
Globals.ErrorCode_APIError
|
|
220
|
+
)
|
|
221
|
+
await this.response.build(this.context, this, this.syncReturn)
|
|
222
|
+
}
|
|
223
|
+
return executionFailed
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Retrieves a database transaction based on the provided database configuration.
|
|
228
|
+
* @param {DbConfig<S>} config - The configuration object for the database.
|
|
229
|
+
* @returns {Promise<DatabaseTransactionType<S, DBSchema>>} A promise that resolves to the database transaction.
|
|
230
|
+
*/
|
|
231
|
+
public async getDbTransaction<S extends DatabaseType, DBSchema>(
|
|
232
|
+
config: DbConfig<S>
|
|
233
|
+
): Promise<DatabaseTransactionType<S, DBSchema>> {
|
|
234
|
+
const db = this.getDatabase<S, DBSchema>(config)
|
|
235
|
+
const dbTrans = await db.transaction()
|
|
236
|
+
this.transactions.push(dbTrans)
|
|
237
|
+
return dbTrans as any
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Retrieves a database instance based on the provided configuration.
|
|
242
|
+
* @param {DbConfig<S>} config - The configuration object specifying the type of database.
|
|
243
|
+
* @returns {DatabaseImplType<S, DBSchema>} A database instance based on the provided configuration.
|
|
244
|
+
*/
|
|
245
|
+
public getDatabase<S extends DatabaseType, DBSchema>(
|
|
246
|
+
config: DbConfig<S>
|
|
247
|
+
): DatabaseImplType<S, DBSchema> {
|
|
248
|
+
return this.databaseManager.create<S, DBSchema>(config)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Get the remaining time in milliseconds for the current execution context.
|
|
253
|
+
* @returns {number} The remaining time in milliseconds, or -1 if the time is not available.
|
|
254
|
+
*/
|
|
255
|
+
public getRemainingTimeInMillis() {
|
|
256
|
+
return this.context?.getRemainingTimeInMillis?.() || -1
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/*
|
|
260
|
+
* Executes a series of database transactions in a safe manner.
|
|
261
|
+
* @param {Function} safeExecution - The function that contains the database transactions to be executed.
|
|
262
|
+
* @returns None
|
|
263
|
+
* @throws {Error} - If an exception occurs during the execution of the transactions and `retrowErrors` is true.
|
|
264
|
+
*/
|
|
265
|
+
private async executeDBTransactions(safeExecution: () => Promise<boolean>): Promise<void> {
|
|
266
|
+
try {
|
|
267
|
+
// Execute
|
|
268
|
+
const execFailed = await safeExecution()
|
|
269
|
+
for (const transaction of [...this.transactions].reverse()) {
|
|
270
|
+
try {
|
|
271
|
+
await transaction[execFailed ? 'closeFailure' : 'closeSuccess']()
|
|
272
|
+
} catch (e) {
|
|
273
|
+
this.logger.error('Exception when closing DB transactions after success.')
|
|
274
|
+
this.logger.exception(e)
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
} catch (e) {
|
|
278
|
+
/* this part of the code handle exceptions at transaction level,
|
|
279
|
+
so probably a bug but we still handle such */
|
|
280
|
+
for (const transaction of [...this.transactions].reverse()) {
|
|
281
|
+
try {
|
|
282
|
+
await transaction.closeFailure()
|
|
283
|
+
} catch (e) {
|
|
284
|
+
this.logger.error('Exception when closing DB transactions after failure.')
|
|
285
|
+
this.logger.exception(e)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
this.logger.error('Exception when executing DB transactions.')
|
|
289
|
+
this.logger.log(e.stack)
|
|
290
|
+
//retrow?
|
|
291
|
+
if (this.retrowErrors) throw e
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Executes a logger flush operation with error handling and logging.
|
|
297
|
+
* @param {Function} safeExecution - The function to execute safely.
|
|
298
|
+
* @returns None
|
|
299
|
+
* @throws {Error} - If `retrowErrors` is true and an error occurs during execution.
|
|
300
|
+
*/
|
|
301
|
+
private async executeLoggerFlush(safeExecution): Promise<void> {
|
|
302
|
+
try {
|
|
303
|
+
await safeExecution()
|
|
304
|
+
} catch (e) {
|
|
305
|
+
this.logger.error('Exception when flushing logs.')
|
|
306
|
+
this.logger.exception(e)
|
|
307
|
+
//retrow?
|
|
308
|
+
if (this.retrowErrors) throw e
|
|
309
|
+
} finally {
|
|
310
|
+
this.logger.debug('Transaction ended')
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Generates an error response with the provided error message and code.
|
|
316
|
+
* @param {string} error - The error message to include in the response.
|
|
317
|
+
* @param {string} code - The error code associated with the response.
|
|
318
|
+
* @returns {Response<ResponseErrorType>} - The error response object.
|
|
319
|
+
*/
|
|
320
|
+
protected getErrorResponse(error: string, code: string): Response<ResponseErrorType> {
|
|
321
|
+
return Response.BadRequestResponseWithRollback(error, code)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { RedisClientType, RedisClusterType, createCluster, createClient } from 'redis'
|
|
2
|
+
|
|
3
|
+
import { CacheConfig } from './types.js'
|
|
4
|
+
import AsyncSingleton from '../Util/AsyncSingleton.js'
|
|
5
|
+
/**
|
|
6
|
+
* Represents a Redis cache connection class.
|
|
7
|
+
*/
|
|
8
|
+
export default class Redis {
|
|
9
|
+
private static singleton = new AsyncSingleton<
|
|
10
|
+
RedisClientType | RedisClusterType,
|
|
11
|
+
CacheConfig<'redis'>
|
|
12
|
+
>(Redis.connectionFactory, async c => c.isOpen)
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A private static property that holds a reference to the redis.createClient function.
|
|
16
|
+
* This property is used to create client.
|
|
17
|
+
*/
|
|
18
|
+
private static ClientFactory = createClient
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A private static property that references the createCluster function.
|
|
22
|
+
* This property can be used to create clusters within the class.
|
|
23
|
+
*/
|
|
24
|
+
private static ClusterFactory = createCluster
|
|
25
|
+
|
|
26
|
+
public static connection(
|
|
27
|
+
config: CacheConfig<'redis'>
|
|
28
|
+
): Promise<RedisClientType | RedisClusterType> {
|
|
29
|
+
return Redis.singleton.instance(config)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private static async connectionFactory(
|
|
33
|
+
config: CacheConfig<'redis'>
|
|
34
|
+
): Promise<RedisClientType | RedisClusterType> {
|
|
35
|
+
if (config.clusterMode) return Redis.redisClusterConnection(config)
|
|
36
|
+
else return Redis.redisClientConnection(config)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Establishes a connection to a Redis client based on the provided configuration
|
|
41
|
+
* and holds it for reusability. If connection is detected closed, new connection is
|
|
42
|
+
* initialized and established.
|
|
43
|
+
* @param {CacheConfig<'redis'>} config - The configuration object for connecting to the Redis client.
|
|
44
|
+
* @returns {Promise<RedisClientType>} A promise that resolves to the Redis client connection.
|
|
45
|
+
*/
|
|
46
|
+
private static async redisClientConnection(
|
|
47
|
+
config: CacheConfig<'redis'>
|
|
48
|
+
): Promise<RedisClientType> {
|
|
49
|
+
console.debug('Starting remote client cache connection')
|
|
50
|
+
const connection = Redis.ClientFactory({
|
|
51
|
+
username: config.username,
|
|
52
|
+
...(config.password ? { password: config.password } : {}),
|
|
53
|
+
disableOfflineQueue: true,
|
|
54
|
+
socket: {
|
|
55
|
+
host: config.hostname,
|
|
56
|
+
tls: config.enableTLS,
|
|
57
|
+
connectTimeout: 10000,
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
await connection.connect()
|
|
61
|
+
|
|
62
|
+
return connection as any
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private static async redisClusterConnection(
|
|
66
|
+
config: CacheConfig<'redis'>
|
|
67
|
+
): Promise<RedisClusterType> {
|
|
68
|
+
console.debug('Starting remote cluster cache connection')
|
|
69
|
+
const connection = Redis.ClusterFactory({
|
|
70
|
+
defaults: {
|
|
71
|
+
username: config.username,
|
|
72
|
+
...(config.password ? { password: config.password } : {}),
|
|
73
|
+
socket: {
|
|
74
|
+
tls: config.enableTLS,
|
|
75
|
+
connectTimeout: 10000,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
rootNodes: [
|
|
79
|
+
{
|
|
80
|
+
url: `redis://${config.username}:${config.username}@${config.hostname}:6379`,
|
|
81
|
+
disableOfflineQueue: true,
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
})
|
|
85
|
+
await connection.connect()
|
|
86
|
+
|
|
87
|
+
return connection as any
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import Redis from './Redis.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Defines a type alias for specifying the cache type as 'redis'.
|
|
5
|
+
*/
|
|
6
|
+
export type CacheType = 'redis'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Defines a CacheClass type that has a 'redis' property which is a constructor function
|
|
10
|
+
* that takes in any number of arguments and returns an instance of Redis.
|
|
11
|
+
*/
|
|
12
|
+
export type CacheClass = {
|
|
13
|
+
redis: new (...args: any[]) => Redis
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Represents the base configuration for a cache, including host, username, password, and TLS settings.
|
|
18
|
+
*/
|
|
19
|
+
export type CacheBaseConfig = {
|
|
20
|
+
hostname: string
|
|
21
|
+
username: string
|
|
22
|
+
password?: string
|
|
23
|
+
enableTLS: boolean
|
|
24
|
+
clusterMode?: boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Defines a CacheConfig type that extends CacheBaseConfig and includes a specific cache type.
|
|
29
|
+
* @template S - The specific cache type to be included in the CacheConfig.
|
|
30
|
+
* @extends CacheBaseConfig
|
|
31
|
+
* @property {S} type - The specific cache type included in the CacheConfig.
|
|
32
|
+
*/
|
|
33
|
+
export type CacheConfig<S extends CacheType> = CacheBaseConfig & { type: S }
|