@digitraffic/common 2023.3.10-1 → 2023.3.21-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aws/infra/api/handler-factory.d.ts +2 -2
- package/dist/aws/infra/api/handler-factory.js +7 -2
- package/dist/aws/infra/api/integration.d.ts +1 -1
- package/dist/aws/infra/canaries/canary-parameters.d.ts +1 -1
- package/dist/aws/infra/canaries/url-checker.d.ts +2 -2
- package/dist/aws/infra/stack/lambda-configs.d.ts +3 -3
- package/dist/aws/infra/stack/monitoredfunction.js +33 -33
- package/dist/aws/runtime/dt-logger-default.d.ts +5 -0
- package/dist/aws/runtime/dt-logger-default.js +9 -0
- package/dist/aws/runtime/dt-logger.d.ts +58 -3
- package/dist/aws/runtime/dt-logger.js +46 -10
- package/dist/aws/runtime/environment.d.ts +8 -0
- package/dist/aws/runtime/environment.js +10 -1
- package/dist/aws/runtime/secrets/dbsecret.d.ts +2 -2
- package/dist/aws/runtime/secrets/secret-holder.d.ts +4 -0
- package/dist/aws/runtime/secrets/secret-holder.js +4 -0
- package/dist/aws/runtime/secrets/secret.d.ts +1 -1
- package/dist/aws/runtime/secrets/secret.js +15 -4
- package/dist/database/database.d.ts +2 -2
- package/dist/test/asserter.d.ts +1 -1
- package/dist/test/httpserver.d.ts +1 -1
- package/dist/test/secrets-manager.js +4 -1
- package/dist/types/aws-env.d.ts +3 -0
- package/dist/types/aws-env.js +3 -0
- package/dist/types/either.d.ts +1 -1
- package/dist/types/urn.d.ts +1 -1
- package/dist/utils/logging.d.ts +4 -0
- package/dist/utils/logging.js +30 -0
- package/dist/utils/utils.d.ts +31 -1
- package/dist/utils/utils.js +72 -1
- package/package.json +4 -3
- package/src/aws/infra/api/handler-factory.ts +8 -2
- package/src/aws/runtime/dt-logger-default.ts +6 -0
- package/src/aws/runtime/dt-logger.ts +71 -17
- package/src/aws/runtime/environment.ts +9 -0
- package/src/aws/runtime/secrets/secret-holder.ts +4 -0
- package/src/aws/runtime/secrets/secret.ts +18 -5
- package/src/test/secrets-manager.ts +5 -2
- package/src/types/aws-env.ts +3 -0
- package/src/utils/logging.ts +41 -0
- package/src/utils/utils.ts +56 -2
@@ -1,7 +1,7 @@
|
|
1
1
|
import { DtLogger } from "../../runtime/dt-logger";
|
2
2
|
import { LambdaResponse } from "../../types/lambda-response";
|
3
|
-
export type LoggingHandler = (method: () => Promise<LambdaResponse>, logger: DtLogger) => Promise<LambdaResponse>;
|
4
|
-
export type ErrorHandler = (error: unknown, logger: DtLogger) => LambdaResponse;
|
3
|
+
export declare type LoggingHandler = (method: () => Promise<LambdaResponse>, logger: DtLogger) => Promise<LambdaResponse>;
|
4
|
+
export declare type ErrorHandler = (error: unknown, logger: DtLogger) => LambdaResponse;
|
5
5
|
/**
|
6
6
|
* Factory class for creating lambda-handler functions. You can set functionality to handle logging and error-handling,
|
7
7
|
* with the defaults:
|
@@ -1,6 +1,8 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.createJsonLoggingHandler = exports.HandlerFactory = void 0;
|
4
|
+
const utils_1 = require("../../../utils/utils");
|
5
|
+
const functionName = (0, utils_1.getEnvVariableOrElse)("AWS_LAMBDA_FUNCTION_NAME", "test");
|
4
6
|
/**
|
5
7
|
* Factory class for creating lambda-handler functions. You can set functionality to handle logging and error-handling,
|
6
8
|
* with the defaults:
|
@@ -18,7 +20,7 @@ class HandlerFactory {
|
|
18
20
|
return await method();
|
19
21
|
}
|
20
22
|
finally {
|
21
|
-
console.info("method=%s.handler tookMs=%d",
|
23
|
+
console.info("method=%s.handler tookMs=%d", functionName, Date.now() - start);
|
22
24
|
}
|
23
25
|
};
|
24
26
|
this.errorHandler = (error) => {
|
@@ -54,7 +56,10 @@ function createJsonLoggingHandler() {
|
|
54
56
|
return await method();
|
55
57
|
}
|
56
58
|
finally {
|
57
|
-
logger.info({
|
59
|
+
logger.info({
|
60
|
+
method: `${functionName}.handler`,
|
61
|
+
tookMs: Date.now() - start,
|
62
|
+
});
|
58
63
|
}
|
59
64
|
};
|
60
65
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { IntegrationResponse, LambdaIntegration } from "aws-cdk-lib/aws-apigateway";
|
2
2
|
import { IFunction } from "aws-cdk-lib/aws-lambda";
|
3
3
|
import { MediaType } from "../../types/mediatypes";
|
4
|
-
type ParameterType = "path" | "querystring";
|
4
|
+
declare type ParameterType = "path" | "querystring";
|
5
5
|
interface ApiParameter {
|
6
6
|
type: ParameterType;
|
7
7
|
name: string;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Schedule } from "@aws-cdk/aws-synthetics-alpha";
|
2
2
|
/** Optional env parameters for canary */
|
3
|
-
type CanaryEnv = Record<string, string>;
|
3
|
+
declare type CanaryEnv = Record<string, string>;
|
4
4
|
export interface CanaryParameters {
|
5
5
|
readonly name: string;
|
6
6
|
readonly schedule?: Schedule;
|
@@ -3,8 +3,8 @@ import { IncomingMessage } from "http";
|
|
3
3
|
import { MediaType } from "../../types/mediatypes";
|
4
4
|
import { FeatureCollection } from "geojson";
|
5
5
|
export declare const API_KEY_HEADER = "x-api-key";
|
6
|
-
type CheckerFunction = (Res: IncomingMessage) => Promise<void>;
|
7
|
-
type JsonCheckerFunction<T> = (json: T, body: string, message: IncomingMessage) => Promise<void>;
|
6
|
+
declare type CheckerFunction = (Res: IncomingMessage) => Promise<void>;
|
7
|
+
declare type JsonCheckerFunction<T> = (json: T, body: string, message: IncomingMessage) => Promise<void>;
|
8
8
|
export declare class UrlChecker {
|
9
9
|
private readonly requestOptions;
|
10
10
|
constructor(hostname: string, apiKey?: string);
|
@@ -3,8 +3,8 @@ import { IVpc, SubnetSelection } from "aws-cdk-lib/aws-ec2";
|
|
3
3
|
import { Role } from "aws-cdk-lib/aws-iam";
|
4
4
|
import { DigitrafficStack } from "./stack";
|
5
5
|
import { MonitoredFunctionAlarmProps } from "./monitoredfunction";
|
6
|
-
export type LambdaEnvironment = Record<string, string>;
|
7
|
-
export type DBLambdaEnvironment = LambdaEnvironment & {
|
6
|
+
export declare type LambdaEnvironment = Record<string, string>;
|
7
|
+
export declare type DBLambdaEnvironment = LambdaEnvironment & {
|
8
8
|
SECRET_ID?: string;
|
9
9
|
DB_APPLICATION: string;
|
10
10
|
};
|
@@ -27,7 +27,7 @@ export interface FunctionParameters {
|
|
27
27
|
architecture?: Architecture;
|
28
28
|
singleLambda?: boolean;
|
29
29
|
}
|
30
|
-
export type MonitoredFunctionParameters = FunctionParameters & {
|
30
|
+
export declare type MonitoredFunctionParameters = FunctionParameters & {
|
31
31
|
readonly durationAlarmProps?: MonitoredFunctionAlarmProps;
|
32
32
|
readonly durationWarningProps?: MonitoredFunctionAlarmProps;
|
33
33
|
readonly errorAlarmProps?: MonitoredFunctionAlarmProps;
|
@@ -11,39 +11,6 @@ const subscription_1 = require("../stack/subscription");
|
|
11
11
|
* Creates a Lambda function that monitors default CloudWatch Lambda metrics with CloudWatch Alarms.
|
12
12
|
*/
|
13
13
|
class MonitoredFunction extends aws_lambda_1.Function {
|
14
|
-
/**
|
15
|
-
* Create new MonitoredFunction. Use topics from given DigitrafficStack.
|
16
|
-
*
|
17
|
-
* @param stack DigitrafficStack
|
18
|
-
* @param id Lambda construct Id
|
19
|
-
* @param functionProps Lambda function properties
|
20
|
-
* @param props Monitored function properties
|
21
|
-
*/
|
22
|
-
static create(stack, id, functionProps, props) {
|
23
|
-
if (props === MonitoredFunction.DISABLE_ALARMS &&
|
24
|
-
stack.configuration.production) {
|
25
|
-
throw new Error(
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
27
|
-
`Function ${functionProps.functionName} has DISABLE_ALARMS. Remove before installing to production or define your own properties!`);
|
28
|
-
}
|
29
|
-
return new MonitoredFunction(stack, id, functionProps, stack.alarmTopic, stack.warningTopic, stack.configuration.production, stack.configuration.trafficType, props);
|
30
|
-
}
|
31
|
-
/**
|
32
|
-
* Create new MonitoredFunction. Use topics from given DigitrafficStack. Generate names from given name and configuration shortName.
|
33
|
-
*
|
34
|
-
* For example, shortName FOO and given name update-things will create function FOO-UpdateThings and use code from lambda/update-things/update-things.ts method handler.
|
35
|
-
*
|
36
|
-
* @param stack DigitrafficStack
|
37
|
-
* @param name param-case name
|
38
|
-
* @param environment Lambda environment
|
39
|
-
* @param functionParameters Lambda function parameters
|
40
|
-
*/
|
41
|
-
static createV2(stack, name, environment, functionParameters) {
|
42
|
-
const functionName = functionParameters?.functionName ??
|
43
|
-
`${stack.configuration.shortName}-${(0, change_case_1.pascalCase)(name)}`;
|
44
|
-
const functionProps = (0, lambda_configs_1.databaseFunctionProps)(stack, environment, functionName, name, functionParameters);
|
45
|
-
return MonitoredFunction.create(stack, functionName, functionProps, functionParameters);
|
46
|
-
}
|
47
14
|
/**
|
48
15
|
* @param scope Stack
|
49
16
|
* @param id Lambda construct Id
|
@@ -81,6 +48,39 @@ class MonitoredFunction extends aws_lambda_1.Function {
|
|
81
48
|
this.createAlarm(scope, this.metricThrottles(), "Throttles", "Throttles alarm", "Has throttled", trafficType, this.getAlarmActionForEnv(alarmSnsAction, warningSnsAction, production), 0, 1, 1, aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD, props?.throttleAlarmProps);
|
82
49
|
}
|
83
50
|
}
|
51
|
+
/**
|
52
|
+
* Create new MonitoredFunction. Use topics from given DigitrafficStack.
|
53
|
+
*
|
54
|
+
* @param stack DigitrafficStack
|
55
|
+
* @param id Lambda construct Id
|
56
|
+
* @param functionProps Lambda function properties
|
57
|
+
* @param props Monitored function properties
|
58
|
+
*/
|
59
|
+
static create(stack, id, functionProps, props) {
|
60
|
+
if (props === MonitoredFunction.DISABLE_ALARMS &&
|
61
|
+
stack.configuration.production) {
|
62
|
+
throw new Error(
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
64
|
+
`Function ${functionProps.functionName} has DISABLE_ALARMS. Remove before installing to production or define your own properties!`);
|
65
|
+
}
|
66
|
+
return new MonitoredFunction(stack, id, functionProps, stack.alarmTopic, stack.warningTopic, stack.configuration.production, stack.configuration.trafficType, props);
|
67
|
+
}
|
68
|
+
/**
|
69
|
+
* Create new MonitoredFunction. Use topics from given DigitrafficStack. Generate names from given name and configuration shortName.
|
70
|
+
*
|
71
|
+
* For example, shortName FOO and given name update-things will create function FOO-UpdateThings and use code from lambda/update-things/update-things.ts method handler.
|
72
|
+
*
|
73
|
+
* @param stack DigitrafficStack
|
74
|
+
* @param name param-case name
|
75
|
+
* @param environment Lambda environment
|
76
|
+
* @param functionParameters Lambda function parameters
|
77
|
+
*/
|
78
|
+
static createV2(stack, name, environment, functionParameters) {
|
79
|
+
const functionName = functionParameters?.functionName ??
|
80
|
+
`${stack.configuration.shortName}-${(0, change_case_1.pascalCase)(name)}`;
|
81
|
+
const functionProps = (0, lambda_configs_1.databaseFunctionProps)(stack, environment, functionName, name, functionParameters);
|
82
|
+
return MonitoredFunction.create(stack, functionName, functionProps, functionParameters);
|
83
|
+
}
|
84
84
|
createAlarm(stack, metric, alarmId, alarmName, alarmDescription, trafficType, alarmSnsAction, threshold, evaluationPeriods, datapointsToAlarm, comparisonOperator, alarmProps) {
|
85
85
|
metric
|
86
86
|
.createAlarm(stack, `${this.node.id}-${alarmId}`, {
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.logger = void 0;
|
4
|
+
const dt_logger_1 = require("./dt-logger");
|
5
|
+
/**
|
6
|
+
* You can use this for your logging needs or create one locally and configure it as you wish.
|
7
|
+
*/
|
8
|
+
exports.logger = new dt_logger_1.DtLogger();
|
9
|
+
//# sourceMappingURL=dt-logger-default.js.map
|
@@ -1,16 +1,35 @@
|
|
1
1
|
/// <reference types="node" />
|
2
2
|
import { Writable } from "stream";
|
3
|
-
type LOG_LEVEL = "DEBUG" | "INFO" | "ERROR";
|
3
|
+
declare type LOG_LEVEL = "DEBUG" | "INFO" | "WARN" | "ERROR";
|
4
4
|
export interface LoggerConfiguration {
|
5
5
|
lambdaName?: string;
|
6
6
|
fileName?: string;
|
7
7
|
runTime?: string;
|
8
8
|
writeStream?: Writable;
|
9
9
|
}
|
10
|
-
export
|
10
|
+
export interface LoggableType {
|
11
|
+
/** name of method logging the message */
|
12
|
+
method: `${string}.${string}`;
|
13
|
+
/** message to log, optional */
|
14
|
+
message?: string;
|
15
|
+
/** type of message, optional */
|
16
|
+
type?: string;
|
17
|
+
/** stack trace, optional */
|
18
|
+
stack?: string;
|
19
|
+
/** amount of time some operation took in milliseconds, optional */
|
20
|
+
tookMs?: number;
|
21
|
+
/** count of something, optional */
|
22
|
+
count?: number;
|
23
|
+
/** do not log your apikey! */
|
24
|
+
apikey?: never;
|
25
|
+
/** do not log your apikey! */
|
26
|
+
apiKey?: never;
|
27
|
+
/** any other loggable key */
|
28
|
+
[key: string]: string | number | boolean | Date | undefined;
|
29
|
+
}
|
11
30
|
/**
|
12
31
|
* Helper class for json-logging. Logged line will include
|
13
|
-
* * log-level
|
32
|
+
* * log-level
|
14
33
|
* * lambdaName (taken from process environment)
|
15
34
|
* * runtime (taken from process environment)
|
16
35
|
* * the actual message (as json or as string)
|
@@ -21,8 +40,44 @@ export declare class DtLogger {
|
|
21
40
|
readonly runtime?: string;
|
22
41
|
readonly writeStream: Writable;
|
23
42
|
constructor(config?: LoggerConfiguration);
|
43
|
+
/**
|
44
|
+
* Log given message with level DEBUG
|
45
|
+
*
|
46
|
+
* @param message Either a string or json-object
|
47
|
+
* @see log
|
48
|
+
*/
|
49
|
+
debug(message: LoggableType): void;
|
50
|
+
/**
|
51
|
+
* Log given message with level INFO
|
52
|
+
*
|
53
|
+
* @param message Either a string or json-object
|
54
|
+
* @see log
|
55
|
+
*/
|
24
56
|
info(message: LoggableType): void;
|
57
|
+
/**
|
58
|
+
* Log given message with level WARN
|
59
|
+
*
|
60
|
+
* @param message Either a string or json-object
|
61
|
+
* @see log
|
62
|
+
*/
|
63
|
+
warn(message: LoggableType): void;
|
64
|
+
/**
|
65
|
+
* Log given message with level INFO
|
66
|
+
*
|
67
|
+
* @param message Either a string or json-object
|
68
|
+
* @see log
|
69
|
+
*/
|
25
70
|
error(message: LoggableType): void;
|
71
|
+
/**
|
72
|
+
* Log message with given log level. If message is a json object, it will be logged as it is and if it is a string it will be wrapped into json-element with key "message".
|
73
|
+
* Some metadata is also added to the message:
|
74
|
+
* * runtime - can be configured with constructor or inferred from environment
|
75
|
+
* * lambdaName - can be configured with constructor or inferred from environment
|
76
|
+
* * fileName - can be configured with constructor
|
77
|
+
*
|
78
|
+
* @param level "DEBUG", "INFO" or "ERROR"
|
79
|
+
* @param message Either a string or json-object
|
80
|
+
*/
|
26
81
|
log(level: LOG_LEVEL, message: LoggableType): void;
|
27
82
|
}
|
28
83
|
export {};
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DtLogger = void 0;
|
4
4
|
/**
|
5
5
|
* Helper class for json-logging. Logged line will include
|
6
|
-
* * log-level
|
6
|
+
* * log-level
|
7
7
|
* * lambdaName (taken from process environment)
|
8
8
|
* * runtime (taken from process environment)
|
9
9
|
* * the actual message (as json or as string)
|
@@ -16,23 +16,59 @@ class DtLogger {
|
|
16
16
|
this.runtime = config?.runTime ?? process.env.AWS_EXECUTION_ENV;
|
17
17
|
this.writeStream = config?.writeStream ?? process.stdout;
|
18
18
|
}
|
19
|
+
/**
|
20
|
+
* Log given message with level DEBUG
|
21
|
+
*
|
22
|
+
* @param message Either a string or json-object
|
23
|
+
* @see log
|
24
|
+
*/
|
25
|
+
debug(message) {
|
26
|
+
this.log("DEBUG", message);
|
27
|
+
}
|
28
|
+
/**
|
29
|
+
* Log given message with level INFO
|
30
|
+
*
|
31
|
+
* @param message Either a string or json-object
|
32
|
+
* @see log
|
33
|
+
*/
|
19
34
|
info(message) {
|
20
35
|
this.log("INFO", message);
|
21
36
|
}
|
37
|
+
/**
|
38
|
+
* Log given message with level WARN
|
39
|
+
*
|
40
|
+
* @param message Either a string or json-object
|
41
|
+
* @see log
|
42
|
+
*/
|
43
|
+
warn(message) {
|
44
|
+
this.log("WARN", message);
|
45
|
+
}
|
46
|
+
/**
|
47
|
+
* Log given message with level INFO
|
48
|
+
*
|
49
|
+
* @param message Either a string or json-object
|
50
|
+
* @see log
|
51
|
+
*/
|
22
52
|
error(message) {
|
23
53
|
this.log("ERROR", message);
|
24
54
|
}
|
55
|
+
/**
|
56
|
+
* Log message with given log level. If message is a json object, it will be logged as it is and if it is a string it will be wrapped into json-element with key "message".
|
57
|
+
* Some metadata is also added to the message:
|
58
|
+
* * runtime - can be configured with constructor or inferred from environment
|
59
|
+
* * lambdaName - can be configured with constructor or inferred from environment
|
60
|
+
* * fileName - can be configured with constructor
|
61
|
+
*
|
62
|
+
* @param level "DEBUG", "INFO" or "ERROR"
|
63
|
+
* @param message Either a string or json-object
|
64
|
+
*/
|
25
65
|
log(level, message) {
|
26
|
-
// put string/number messages into message object
|
27
|
-
const actualMessage = typeof message == "object" ? message : { message: message };
|
28
66
|
const logMessage = {
|
29
|
-
...
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
runtime: this.runtime,
|
35
|
-
},
|
67
|
+
...message,
|
68
|
+
level,
|
69
|
+
fileName: message.fileName ?? this.fileName,
|
70
|
+
lambdaName: this.lambdaName,
|
71
|
+
runtime: this.runtime,
|
36
72
|
};
|
37
73
|
this.writeStream.write(JSON.stringify(logMessage) + "\n");
|
38
74
|
}
|
@@ -1 +1,9 @@
|
|
1
|
+
export declare enum EnvKeys {
|
2
|
+
AWS_REGION = "AWS_REGION",
|
3
|
+
SECRET_ID = "SECRET_ID",
|
4
|
+
SECRET_OVERRIDE_AWS_REGION = "SECRET_OVERRIDE_AWS_REGION"
|
5
|
+
}
|
6
|
+
/**
|
7
|
+
* @deprecated Use digitraffic/common/utils/utils#getEnvVariable
|
8
|
+
*/
|
1
9
|
export declare function envValue(key: string, defaultValue?: string): string;
|
@@ -1,6 +1,15 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.envValue = void 0;
|
3
|
+
exports.envValue = exports.EnvKeys = void 0;
|
4
|
+
var EnvKeys;
|
5
|
+
(function (EnvKeys) {
|
6
|
+
EnvKeys["AWS_REGION"] = "AWS_REGION";
|
7
|
+
EnvKeys["SECRET_ID"] = "SECRET_ID";
|
8
|
+
EnvKeys["SECRET_OVERRIDE_AWS_REGION"] = "SECRET_OVERRIDE_AWS_REGION";
|
9
|
+
})(EnvKeys = exports.EnvKeys || (exports.EnvKeys = {}));
|
10
|
+
/**
|
11
|
+
* @deprecated Use digitraffic/common/utils/utils#getEnvVariable
|
12
|
+
*/
|
4
13
|
function envValue(key, defaultValue) {
|
5
14
|
const value = process.env[key];
|
6
15
|
if (value == null) {
|
@@ -11,6 +11,6 @@ export declare enum RdsSecretKey {
|
|
11
11
|
host = "host",
|
12
12
|
ro_host = "ro_host"
|
13
13
|
}
|
14
|
-
export type RdsProxySecret = Record<RdsProxySecretKey, string>;
|
15
|
-
export type RdsSecret = Record<RdsSecretKey, string>;
|
14
|
+
export declare type RdsProxySecret = Record<RdsProxySecretKey, string>;
|
15
|
+
export declare type RdsSecret = Record<RdsSecretKey, string>;
|
16
16
|
export declare function checkExpectedSecretKeys<Secret extends GenericSecret>(keys: string[], secret: Secret): void;
|
@@ -6,6 +6,10 @@ import { GenericSecret } from "./secret";
|
|
6
6
|
* By default, secrets are cached for 5 minutes and then reread from the Secrets Manager(This can be overridden with configuration).
|
7
7
|
*
|
8
8
|
* Supports setting the database environment paramaters from the secret too.
|
9
|
+
*
|
10
|
+
* If you want secret manager to get values from different region than the lambda runtime is running, you can override this by
|
11
|
+
* setting the region with utils setSecretOverideAwsRegionEnv method.
|
12
|
+
*
|
9
13
|
*/
|
10
14
|
export declare class SecretHolder<Secret extends GenericSecret> {
|
11
15
|
private readonly secretId;
|
@@ -18,6 +18,10 @@ const DEFAULT_CONFIGURATION = {
|
|
18
18
|
* By default, secrets are cached for 5 minutes and then reread from the Secrets Manager(This can be overridden with configuration).
|
19
19
|
*
|
20
20
|
* Supports setting the database environment paramaters from the secret too.
|
21
|
+
*
|
22
|
+
* If you want secret manager to get values from different region than the lambda runtime is running, you can override this by
|
23
|
+
* setting the region with utils setSecretOverideAwsRegionEnv method.
|
24
|
+
*
|
21
25
|
*/
|
22
26
|
class SecretHolder {
|
23
27
|
constructor(secretId, prefix = "", expectedKeys = [], configuration = DEFAULT_CONFIGURATION) {
|
@@ -1,2 +1,2 @@
|
|
1
|
-
export type GenericSecret = Record<string, string>;
|
1
|
+
export declare type GenericSecret = Record<string, string>;
|
2
2
|
export declare function getSecret<Secret>(secretId: string, prefix?: string): Promise<Secret>;
|
@@ -2,11 +2,22 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.getSecret = void 0;
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
5
|
-
const
|
6
|
-
|
7
|
-
|
5
|
+
const utils_1 = require("../../../utils/utils");
|
6
|
+
const environment_1 = require("../environment");
|
7
|
+
// SECRET_OVERRIDE_AWS_REGION might not have been set before import of
|
8
|
+
// secret, so we need to lazy initialize SecretsManager
|
9
|
+
let smClient;
|
10
|
+
function getSmClient() {
|
11
|
+
if (!smClient) {
|
12
|
+
smClient = new aws_sdk_1.SecretsManager({
|
13
|
+
region: (0, utils_1.getEnvVariableOrElse)(environment_1.EnvKeys.SECRET_OVERRIDE_AWS_REGION, // this is override secret region
|
14
|
+
(0, utils_1.getEnvVariable)(environment_1.EnvKeys.AWS_REGION)),
|
15
|
+
});
|
16
|
+
}
|
17
|
+
return smClient;
|
18
|
+
}
|
8
19
|
async function getSecret(secretId, prefix = "") {
|
9
|
-
const secretObj = await
|
20
|
+
const secretObj = await getSmClient()
|
10
21
|
.getSecretValue({
|
11
22
|
SecretId: secretId,
|
12
23
|
})
|
@@ -6,8 +6,8 @@ export declare enum DatabaseEnvironmentKeys {
|
|
6
6
|
DB_RO_URI = "DB_RO_URI",
|
7
7
|
DB_APPLICATION = "DB_APPLICATION"
|
8
8
|
}
|
9
|
-
export type DTDatabase = IDatabase<unknown>;
|
10
|
-
export type DTTransaction = ITask<unknown>;
|
9
|
+
export declare type DTDatabase = IDatabase<unknown>;
|
10
|
+
export declare type DTTransaction = ITask<unknown>;
|
11
11
|
/**
|
12
12
|
* Creates a non-pooling database connection primarily used by Lambdas.
|
13
13
|
*
|
package/dist/test/asserter.d.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* A simple asserter-class for writing canaries without dependency to testing-libraries.
|
3
3
|
*/
|
4
|
-
type AssertedValue = string | number;
|
4
|
+
declare type AssertedValue = string | number;
|
5
5
|
export declare abstract class Asserter {
|
6
6
|
static assertEquals(value: AssertedValue, expected: AssertedValue): void;
|
7
7
|
static assertTrue(value: boolean): void;
|
@@ -14,4 +14,4 @@ export declare class TestHttpServer {
|
|
14
14
|
close(): void;
|
15
15
|
private debuglog;
|
16
16
|
}
|
17
|
-
export type ListenProperties = Record<string, (url?: string, data?: string) => string>;
|
17
|
+
export declare type ListenProperties = Record<string, (url?: string, data?: string) => string>;
|
@@ -26,6 +26,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.mockSecret = exports.stubSecretsManager = void 0;
|
27
27
|
const AWS = require("aws-sdk");
|
28
28
|
const sinon = __importStar(require("sinon"));
|
29
|
+
const environment_1 = require("../aws/runtime/environment");
|
30
|
+
const utils_1 = require("../utils/utils");
|
31
|
+
(0, utils_1.setEnvVariable)(environment_1.EnvKeys.AWS_REGION, "eu-west-1");
|
29
32
|
const secretValue = sinon.stub();
|
30
33
|
/**
|
31
34
|
* Stub Secrets Manager for tests. You must call this
|
@@ -37,7 +40,7 @@ function stubSecretsManager() {
|
|
37
40
|
const smStub = {
|
38
41
|
getSecretValue: secretValue,
|
39
42
|
};
|
40
|
-
sinon.stub(AWS,
|
43
|
+
sinon.stub(AWS, "SecretsManager").returns(smStub);
|
41
44
|
return smStub.getSecretValue;
|
42
45
|
}
|
43
46
|
exports.stubSecretsManager = stubSecretsManager;
|
package/dist/types/either.d.ts
CHANGED
package/dist/types/urn.d.ts
CHANGED
@@ -1 +1 @@
|
|
1
|
-
export type URN<Namespace extends string, NamespaceSpecificString extends string = ""> = `urn:${Namespace}:${NamespaceSpecificString}`;
|
1
|
+
export declare type URN<Namespace extends string, NamespaceSpecificString extends string = ""> = `urn:${Namespace}:${NamespaceSpecificString}`;
|
@@ -0,0 +1,4 @@
|
|
1
|
+
import { AxiosError } from "axios";
|
2
|
+
import { DtLogger } from "../aws/runtime/dt-logger";
|
3
|
+
export declare function logException(logger: DtLogger, error: Error | string, includeStack: boolean): void;
|
4
|
+
export declare function logException(logger: DtLogger, error: AxiosError): void;
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.logException = void 0;
|
4
|
+
const axios_1 = require("axios");
|
5
|
+
const utils_1 = require("./utils");
|
6
|
+
const functionName = (0, utils_1.getEnvVariableOrElse)("AWS_LAMBDA_FUNCTION_NAME", "test");
|
7
|
+
/**
|
8
|
+
* Log given exception with level ERROR to given logger.
|
9
|
+
*
|
10
|
+
* Supports AxiosError, Error and string
|
11
|
+
*
|
12
|
+
* @param logger DtLogger to use
|
13
|
+
* @param error AxiosError, Error or string to log
|
14
|
+
* @param includeStack Include stack in the message, default false
|
15
|
+
* @see log
|
16
|
+
*/
|
17
|
+
function logException(logger, error, includeStack = false) {
|
18
|
+
const message = error instanceof Error ? error.message : error;
|
19
|
+
const stack = error instanceof Error && includeStack ? error.stack : undefined;
|
20
|
+
const code = error instanceof axios_1.AxiosError ? error.code : undefined;
|
21
|
+
logger.error({
|
22
|
+
type: "Error",
|
23
|
+
method: `${functionName}.logException`,
|
24
|
+
message,
|
25
|
+
code,
|
26
|
+
stack,
|
27
|
+
});
|
28
|
+
}
|
29
|
+
exports.logException = logException;
|
30
|
+
//# sourceMappingURL=logging.js.map
|
package/dist/utils/utils.d.ts
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import { AwsEnv } from "../types/aws-env";
|
2
|
+
import { Either } from "../types/either";
|
1
3
|
/**
|
2
4
|
* Check if arrays have only elements that also exists also in other array.
|
3
5
|
* Individual element count doesn't matter.
|
@@ -19,7 +21,6 @@
|
|
19
21
|
* @param a first array to compare
|
20
22
|
* @param b second array to compare
|
21
23
|
*/
|
22
|
-
import { Either } from "../types/either";
|
23
24
|
export declare function bothArraysHasSameValues(a: null | undefined | unknown[], b: null | undefined | unknown[]): boolean;
|
24
25
|
/**
|
25
26
|
* Returns the last item on the array. If the array is empty, throws an error!
|
@@ -29,6 +30,14 @@ export declare function getLast<T>(array: T[], sortFunction?: (a: T) => number):
|
|
29
30
|
* Returns the first item on the array. If the array is empty, throws an error!
|
30
31
|
*/
|
31
32
|
export declare function getFirst<T>(array: T[], sortFunction?: (a: T) => number): T;
|
33
|
+
/**
|
34
|
+
* Gets basic AWS environment variables. Throws error if variables are not found.
|
35
|
+
*
|
36
|
+
* @param key Environment key
|
37
|
+
* @return string
|
38
|
+
* @See https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
|
39
|
+
*/
|
40
|
+
export declare function getAwsEnv(): AwsEnv;
|
32
41
|
/**
|
33
42
|
* Gets environment variable. Throws error if variable is not found.
|
34
43
|
*
|
@@ -44,6 +53,13 @@ export declare function getEnvVariable(key: string): string;
|
|
44
53
|
* @return Either<string>
|
45
54
|
*/
|
46
55
|
export declare function getEnvVariableSafe(key: string): Either<string>;
|
56
|
+
/**
|
57
|
+
* Sets environment variable.
|
58
|
+
*
|
59
|
+
* @param key Environment key
|
60
|
+
* @param value Environment variable value
|
61
|
+
*/
|
62
|
+
export declare function setEnvVariable(key: string, value: string): void;
|
47
63
|
/**
|
48
64
|
* Gets environment variable. If environment variable is undefined, returns value of given function.
|
49
65
|
*
|
@@ -59,3 +75,17 @@ export declare function getEnvVariableOr<T>(key: string, fn: () => T): string |
|
|
59
75
|
* @param orElse Alternative value
|
60
76
|
*/
|
61
77
|
export declare function getEnvVariableOrElse<T>(key: string, orElse: T): string | T;
|
78
|
+
export declare function setSecretOverideAwsRegionEnv(region: string): void;
|
79
|
+
/**
|
80
|
+
* ESLint won't allow to call Object.prototype builtin methods.
|
81
|
+
* To call hasOwnProperty we must use Object.prototype.hasOwnProperty.call()
|
82
|
+
* @param object to test for property
|
83
|
+
* @param propertyName property name to check
|
84
|
+
* @see https://eslint.org/docs/latest/rules/no-prototype-builtins
|
85
|
+
*/
|
86
|
+
export declare function hasOwnPropertySafe(object: object, propertyName: string): boolean;
|
87
|
+
/**
|
88
|
+
* Return an error message from the given object hat might be an Error object.
|
89
|
+
* @param maybeError
|
90
|
+
*/
|
91
|
+
export declare function getErrorMessage(maybeError: unknown): string;
|
package/dist/utils/utils.js
CHANGED
@@ -1,6 +1,28 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.getEnvVariableOrElse = exports.getEnvVariableOr = exports.getEnvVariableSafe = exports.getEnvVariable = exports.getFirst = exports.getLast = exports.bothArraysHasSameValues = void 0;
|
3
|
+
exports.getErrorMessage = exports.hasOwnPropertySafe = exports.setSecretOverideAwsRegionEnv = exports.getEnvVariableOrElse = exports.getEnvVariableOr = exports.setEnvVariable = exports.getEnvVariableSafe = exports.getEnvVariable = exports.getAwsEnv = exports.getFirst = exports.getLast = exports.bothArraysHasSameValues = void 0;
|
4
|
+
const environment_1 = require("../aws/runtime/environment");
|
5
|
+
/**
|
6
|
+
* Check if arrays have only elements that also exists also in other array.
|
7
|
+
* Individual element count doesn't matter.
|
8
|
+
* Function works only for primitive types and for other it just checks the reference to object.
|
9
|
+
*
|
10
|
+
* Some examples
|
11
|
+
* bothArraysHasSameValues( [a, b], [b, a] ) => true
|
12
|
+
* bothArraysHasSameValues( [a, a], [a, a, a] ) => true
|
13
|
+
* bothArraysHasSameValues( [a, b], [a] ) => false
|
14
|
+
*
|
15
|
+
* Object references:
|
16
|
+
* const o1 = { a: 1, b: 2};
|
17
|
+
* const o2 = { a: 1, b: 2};
|
18
|
+
* // Arrays has references to same objects
|
19
|
+
* bothArraysHasSameValues([o1], [o1])) => true
|
20
|
+
* Arrays have references to different objects
|
21
|
+
* bothArraysHasSameValues([o1], [o2])) => false
|
22
|
+
*
|
23
|
+
* @param a first array to compare
|
24
|
+
* @param b second array to compare
|
25
|
+
*/
|
4
26
|
function bothArraysHasSameValues(a, b) {
|
5
27
|
if ((a && !b) || (!a && b)) {
|
6
28
|
return false;
|
@@ -40,6 +62,19 @@ function getFirstOrLast(getFirst, array, sortFunction) {
|
|
40
62
|
}
|
41
63
|
return array[index];
|
42
64
|
}
|
65
|
+
/**
|
66
|
+
* Gets basic AWS environment variables. Throws error if variables are not found.
|
67
|
+
*
|
68
|
+
* @param key Environment key
|
69
|
+
* @return string
|
70
|
+
* @See https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
|
71
|
+
*/
|
72
|
+
function getAwsEnv() {
|
73
|
+
return {
|
74
|
+
region: getEnvVariable("AWS_REGION"),
|
75
|
+
};
|
76
|
+
}
|
77
|
+
exports.getAwsEnv = getAwsEnv;
|
43
78
|
/**
|
44
79
|
* Gets environment variable. Throws error if variable is not found.
|
45
80
|
*
|
@@ -72,6 +107,16 @@ function getEnvVariableSafe(key) {
|
|
72
107
|
return { result: "ok", value };
|
73
108
|
}
|
74
109
|
exports.getEnvVariableSafe = getEnvVariableSafe;
|
110
|
+
/**
|
111
|
+
* Sets environment variable.
|
112
|
+
*
|
113
|
+
* @param key Environment key
|
114
|
+
* @param value Environment variable value
|
115
|
+
*/
|
116
|
+
function setEnvVariable(key, value) {
|
117
|
+
process.env[key] = value;
|
118
|
+
}
|
119
|
+
exports.setEnvVariable = setEnvVariable;
|
75
120
|
/**
|
76
121
|
* Gets environment variable. If environment variable is undefined, returns value of given function.
|
77
122
|
*
|
@@ -97,4 +142,30 @@ function getEnvVariableOrElse(key, orElse) {
|
|
97
142
|
return getEnvVariableOr(key, () => orElse);
|
98
143
|
}
|
99
144
|
exports.getEnvVariableOrElse = getEnvVariableOrElse;
|
145
|
+
function setSecretOverideAwsRegionEnv(region) {
|
146
|
+
setEnvVariable(environment_1.EnvKeys.SECRET_OVERRIDE_AWS_REGION, region);
|
147
|
+
}
|
148
|
+
exports.setSecretOverideAwsRegionEnv = setSecretOverideAwsRegionEnv;
|
149
|
+
/**
|
150
|
+
* ESLint won't allow to call Object.prototype builtin methods.
|
151
|
+
* To call hasOwnProperty we must use Object.prototype.hasOwnProperty.call()
|
152
|
+
* @param object to test for property
|
153
|
+
* @param propertyName property name to check
|
154
|
+
* @see https://eslint.org/docs/latest/rules/no-prototype-builtins
|
155
|
+
*/
|
156
|
+
function hasOwnPropertySafe(object, propertyName) {
|
157
|
+
return Object.prototype.hasOwnProperty.call(object, propertyName);
|
158
|
+
}
|
159
|
+
exports.hasOwnPropertySafe = hasOwnPropertySafe;
|
160
|
+
/**
|
161
|
+
* Return an error message from the given object hat might be an Error object.
|
162
|
+
* @param maybeError
|
163
|
+
*/
|
164
|
+
function getErrorMessage(maybeError) {
|
165
|
+
if (maybeError instanceof Error) {
|
166
|
+
return maybeError.name + ": " + maybeError.message;
|
167
|
+
}
|
168
|
+
return String(maybeError);
|
169
|
+
}
|
170
|
+
exports.getErrorMessage = getErrorMessage;
|
100
171
|
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@digitraffic/common",
|
3
|
-
"version": "2023.
|
3
|
+
"version": "2023.3.21-1",
|
4
4
|
"description": "",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -45,7 +45,7 @@
|
|
45
45
|
"axios": "^1.2.6",
|
46
46
|
"change-case": "^4.1.2",
|
47
47
|
"constructs": "^10.1.222",
|
48
|
-
"eslint": "
|
48
|
+
"eslint": "~8.34.0",
|
49
49
|
"eslint-config-prettier": "^8.6.0",
|
50
50
|
"eslint-plugin-deprecation": "1.3.3",
|
51
51
|
"geojson-validation": "^1.0.2",
|
@@ -62,7 +62,7 @@
|
|
62
62
|
"rimraf": "^4.1.0",
|
63
63
|
"sinon": "^15.0.1",
|
64
64
|
"ts-jest": "^29.0.5",
|
65
|
-
"typescript": "
|
65
|
+
"typescript": "~4.8.4"
|
66
66
|
},
|
67
67
|
"externals": [
|
68
68
|
"aws-sdk",
|
@@ -75,6 +75,7 @@
|
|
75
75
|
"build": "tsc",
|
76
76
|
"lint": "eslint --cache .",
|
77
77
|
"eslint-report": "eslint . --format html",
|
78
|
+
"ci:eslint-report": "eslint . --format html -o report.html",
|
78
79
|
"clean": "rimraf dist output",
|
79
80
|
"test": "jest --detectOpenHandles --forceExit --coverage --coverageDirectory=output/coverage/jest"
|
80
81
|
}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { getEnvVariableOrElse } from "../../../utils/utils";
|
1
2
|
import { DtLogger } from "../../runtime/dt-logger";
|
2
3
|
import { LambdaResponse } from "../../types/lambda-response";
|
3
4
|
|
@@ -8,6 +9,8 @@ export type LoggingHandler = (
|
|
8
9
|
|
9
10
|
export type ErrorHandler = (error: unknown, logger: DtLogger) => LambdaResponse;
|
10
11
|
|
12
|
+
const functionName = getEnvVariableOrElse("AWS_LAMBDA_FUNCTION_NAME", "test");
|
13
|
+
|
11
14
|
/**
|
12
15
|
* Factory class for creating lambda-handler functions. You can set functionality to handle logging and error-handling,
|
13
16
|
* with the defaults:
|
@@ -30,7 +33,7 @@ export class HandlerFactory {
|
|
30
33
|
} finally {
|
31
34
|
console.info(
|
32
35
|
"method=%s.handler tookMs=%d",
|
33
|
-
|
36
|
+
functionName,
|
34
37
|
Date.now() - start
|
35
38
|
);
|
36
39
|
}
|
@@ -74,7 +77,10 @@ export function createJsonLoggingHandler(): LoggingHandler {
|
|
74
77
|
try {
|
75
78
|
return await method();
|
76
79
|
} finally {
|
77
|
-
logger.info({
|
80
|
+
logger.info({
|
81
|
+
method: `${functionName}.handler`,
|
82
|
+
tookMs: Date.now() - start,
|
83
|
+
});
|
78
84
|
}
|
79
85
|
};
|
80
86
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Writable } from "stream";
|
2
2
|
|
3
|
-
type LOG_LEVEL = "DEBUG" | "INFO" | "ERROR";
|
3
|
+
type LOG_LEVEL = "DEBUG" | "INFO" | "WARN" | "ERROR";
|
4
4
|
|
5
5
|
export interface LoggerConfiguration {
|
6
6
|
lambdaName?: string;
|
@@ -9,11 +9,30 @@ export interface LoggerConfiguration {
|
|
9
9
|
writeStream?: Writable;
|
10
10
|
}
|
11
11
|
|
12
|
-
export
|
12
|
+
export interface LoggableType {
|
13
|
+
/** name of method logging the message */
|
14
|
+
method: `${string}.${string}`;
|
15
|
+
/** message to log, optional */
|
16
|
+
message?: string;
|
17
|
+
/** type of message, optional */
|
18
|
+
type?: string;
|
19
|
+
/** stack trace, optional */
|
20
|
+
stack?: string;
|
21
|
+
/** amount of time some operation took in milliseconds, optional */
|
22
|
+
tookMs?: number;
|
23
|
+
/** count of something, optional */
|
24
|
+
count?: number;
|
25
|
+
/** do not log your apikey! */
|
26
|
+
apikey?: never;
|
27
|
+
/** do not log your apikey! */
|
28
|
+
apiKey?: never;
|
29
|
+
/** any other loggable key */
|
30
|
+
[key: string]: string | number | boolean | Date | undefined;
|
31
|
+
}
|
13
32
|
|
14
33
|
/**
|
15
34
|
* Helper class for json-logging. Logged line will include
|
16
|
-
* * log-level
|
35
|
+
* * log-level
|
17
36
|
* * lambdaName (taken from process environment)
|
18
37
|
* * runtime (taken from process environment)
|
19
38
|
* * the actual message (as json or as string)
|
@@ -33,27 +52,62 @@ export class DtLogger {
|
|
33
52
|
this.writeStream = config?.writeStream ?? process.stdout;
|
34
53
|
}
|
35
54
|
|
36
|
-
|
55
|
+
/**
|
56
|
+
* Log given message with level DEBUG
|
57
|
+
*
|
58
|
+
* @param message Either a string or json-object
|
59
|
+
* @see log
|
60
|
+
*/
|
61
|
+
debug(message: LoggableType): void {
|
62
|
+
this.log("DEBUG", message);
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Log given message with level INFO
|
67
|
+
*
|
68
|
+
* @param message Either a string or json-object
|
69
|
+
* @see log
|
70
|
+
*/
|
71
|
+
info(message: LoggableType): void {
|
37
72
|
this.log("INFO", message);
|
38
73
|
}
|
39
74
|
|
40
|
-
|
75
|
+
/**
|
76
|
+
* Log given message with level WARN
|
77
|
+
*
|
78
|
+
* @param message Either a string or json-object
|
79
|
+
* @see log
|
80
|
+
*/
|
81
|
+
warn(message: LoggableType): void {
|
82
|
+
this.log("WARN", message);
|
83
|
+
}
|
84
|
+
/**
|
85
|
+
* Log given message with level INFO
|
86
|
+
*
|
87
|
+
* @param message Either a string or json-object
|
88
|
+
* @see log
|
89
|
+
*/
|
90
|
+
error(message: LoggableType): void {
|
41
91
|
this.log("ERROR", message);
|
42
92
|
}
|
43
93
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
94
|
+
/**
|
95
|
+
* Log message with given log level. If message is a json object, it will be logged as it is and if it is a string it will be wrapped into json-element with key "message".
|
96
|
+
* Some metadata is also added to the message:
|
97
|
+
* * runtime - can be configured with constructor or inferred from environment
|
98
|
+
* * lambdaName - can be configured with constructor or inferred from environment
|
99
|
+
* * fileName - can be configured with constructor
|
100
|
+
*
|
101
|
+
* @param level "DEBUG", "INFO" or "ERROR"
|
102
|
+
* @param message Either a string or json-object
|
103
|
+
*/
|
104
|
+
log(level: LOG_LEVEL, message: LoggableType): void {
|
49
105
|
const logMessage = {
|
50
|
-
...
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
runtime: this.runtime,
|
56
|
-
},
|
106
|
+
...message,
|
107
|
+
level,
|
108
|
+
fileName: message.fileName ?? this.fileName,
|
109
|
+
lambdaName: this.lambdaName,
|
110
|
+
runtime: this.runtime,
|
57
111
|
};
|
58
112
|
|
59
113
|
this.writeStream.write(JSON.stringify(logMessage) + "\n");
|
@@ -1,3 +1,12 @@
|
|
1
|
+
export enum EnvKeys {
|
2
|
+
AWS_REGION = "AWS_REGION",
|
3
|
+
SECRET_ID = "SECRET_ID",
|
4
|
+
SECRET_OVERRIDE_AWS_REGION = "SECRET_OVERRIDE_AWS_REGION",
|
5
|
+
}
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @deprecated Use digitraffic/common/utils/utils#getEnvVariable
|
9
|
+
*/
|
1
10
|
export function envValue(key: string, defaultValue?: string): string {
|
2
11
|
const value = process.env[key];
|
3
12
|
|
@@ -18,6 +18,10 @@ const DEFAULT_CONFIGURATION = {
|
|
18
18
|
* By default, secrets are cached for 5 minutes and then reread from the Secrets Manager(This can be overridden with configuration).
|
19
19
|
*
|
20
20
|
* Supports setting the database environment paramaters from the secret too.
|
21
|
+
*
|
22
|
+
* If you want secret manager to get values from different region than the lambda runtime is running, you can override this by
|
23
|
+
* setting the region with utils setSecretOverideAwsRegionEnv method.
|
24
|
+
*
|
21
25
|
*/
|
22
26
|
export class SecretHolder<Secret extends GenericSecret> {
|
23
27
|
private readonly secretId: string;
|
@@ -1,8 +1,21 @@
|
|
1
1
|
import { SecretsManager } from "aws-sdk";
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
import { getEnvVariable, getEnvVariableOrElse } from "../../../utils/utils";
|
3
|
+
import { EnvKeys } from "../environment";
|
4
|
+
|
5
|
+
// SECRET_OVERRIDE_AWS_REGION might not have been set before import of
|
6
|
+
// secret, so we need to lazy initialize SecretsManager
|
7
|
+
let smClient: SecretsManager | undefined;
|
8
|
+
function getSmClient(): SecretsManager {
|
9
|
+
if (!smClient) {
|
10
|
+
smClient = new SecretsManager({
|
11
|
+
region: getEnvVariableOrElse<string>(
|
12
|
+
EnvKeys.SECRET_OVERRIDE_AWS_REGION, // this is override secret region
|
13
|
+
getEnvVariable(EnvKeys.AWS_REGION)
|
14
|
+
),
|
15
|
+
});
|
16
|
+
}
|
17
|
+
return smClient;
|
18
|
+
}
|
6
19
|
|
7
20
|
export type GenericSecret = Record<string, string>;
|
8
21
|
|
@@ -10,7 +23,7 @@ export async function getSecret<Secret>(
|
|
10
23
|
secretId: string,
|
11
24
|
prefix = ""
|
12
25
|
): Promise<Secret> {
|
13
|
-
const secretObj = await
|
26
|
+
const secretObj = await getSmClient()
|
14
27
|
.getSecretValue({
|
15
28
|
SecretId: secretId,
|
16
29
|
})
|
@@ -1,6 +1,9 @@
|
|
1
|
-
import AWS = require(
|
1
|
+
import AWS = require("aws-sdk");
|
2
2
|
import * as sinon from "sinon";
|
3
|
+
import { EnvKeys } from "../aws/runtime/environment";
|
4
|
+
import { setEnvVariable } from "../utils/utils";
|
3
5
|
|
6
|
+
setEnvVariable(EnvKeys.AWS_REGION, "eu-west-1");
|
4
7
|
const secretValue = sinon.stub();
|
5
8
|
|
6
9
|
/**
|
@@ -14,7 +17,7 @@ export function stubSecretsManager() {
|
|
14
17
|
getSecretValue: secretValue,
|
15
18
|
};
|
16
19
|
|
17
|
-
sinon.stub(AWS,
|
20
|
+
sinon.stub(AWS, "SecretsManager").returns(smStub);
|
18
21
|
|
19
22
|
return smStub.getSecretValue;
|
20
23
|
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { AxiosError } from "axios";
|
2
|
+
import { DtLogger } from "../aws/runtime/dt-logger";
|
3
|
+
import { getEnvVariableOrElse } from "./utils";
|
4
|
+
|
5
|
+
const functionName = getEnvVariableOrElse("AWS_LAMBDA_FUNCTION_NAME", "test");
|
6
|
+
|
7
|
+
export function logException(
|
8
|
+
logger: DtLogger,
|
9
|
+
error: Error | string,
|
10
|
+
includeStack: boolean
|
11
|
+
): void;
|
12
|
+
export function logException(logger: DtLogger, error: AxiosError): void;
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Log given exception with level ERROR to given logger.
|
16
|
+
*
|
17
|
+
* Supports AxiosError, Error and string
|
18
|
+
*
|
19
|
+
* @param logger DtLogger to use
|
20
|
+
* @param error AxiosError, Error or string to log
|
21
|
+
* @param includeStack Include stack in the message, default false
|
22
|
+
* @see log
|
23
|
+
*/
|
24
|
+
export function logException(
|
25
|
+
logger: DtLogger,
|
26
|
+
error: Error | string | AxiosError,
|
27
|
+
includeStack = false
|
28
|
+
) {
|
29
|
+
const message = error instanceof Error ? error.message : error;
|
30
|
+
const stack =
|
31
|
+
error instanceof Error && includeStack ? error.stack : undefined;
|
32
|
+
const code = error instanceof AxiosError ? error.code : undefined;
|
33
|
+
|
34
|
+
logger.error({
|
35
|
+
type: "Error",
|
36
|
+
method: `${functionName}.logException`,
|
37
|
+
message,
|
38
|
+
code,
|
39
|
+
stack,
|
40
|
+
});
|
41
|
+
}
|
package/src/utils/utils.ts
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
import { AwsEnv } from "../types/aws-env";
|
2
|
+
import { Either } from "../types/either";
|
3
|
+
import { EnvKeys } from "../aws/runtime/environment";
|
4
|
+
|
1
5
|
/**
|
2
6
|
* Check if arrays have only elements that also exists also in other array.
|
3
7
|
* Individual element count doesn't matter.
|
@@ -19,8 +23,6 @@
|
|
19
23
|
* @param a first array to compare
|
20
24
|
* @param b second array to compare
|
21
25
|
*/
|
22
|
-
import { Either } from "../types/either";
|
23
|
-
|
24
26
|
export function bothArraysHasSameValues(
|
25
27
|
a: null | undefined | unknown[],
|
26
28
|
b: null | undefined | unknown[]
|
@@ -72,6 +74,19 @@ function getFirstOrLast<T>(
|
|
72
74
|
return array[index];
|
73
75
|
}
|
74
76
|
|
77
|
+
/**
|
78
|
+
* Gets basic AWS environment variables. Throws error if variables are not found.
|
79
|
+
*
|
80
|
+
* @param key Environment key
|
81
|
+
* @return string
|
82
|
+
* @See https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
|
83
|
+
*/
|
84
|
+
export function getAwsEnv(): AwsEnv {
|
85
|
+
return {
|
86
|
+
region: getEnvVariable("AWS_REGION"),
|
87
|
+
};
|
88
|
+
}
|
89
|
+
|
75
90
|
/**
|
76
91
|
* Gets environment variable. Throws error if variable is not found.
|
77
92
|
*
|
@@ -104,6 +119,16 @@ export function getEnvVariableSafe(key: string): Either<string> {
|
|
104
119
|
return { result: "ok", value };
|
105
120
|
}
|
106
121
|
|
122
|
+
/**
|
123
|
+
* Sets environment variable.
|
124
|
+
*
|
125
|
+
* @param key Environment key
|
126
|
+
* @param value Environment variable value
|
127
|
+
*/
|
128
|
+
export function setEnvVariable(key: string, value: string) {
|
129
|
+
process.env[key] = value;
|
130
|
+
}
|
131
|
+
|
107
132
|
/**
|
108
133
|
* Gets environment variable. If environment variable is undefined, returns value of given function.
|
109
134
|
*
|
@@ -128,3 +153,32 @@ export function getEnvVariableOr<T>(key: string, fn: () => T): string | T {
|
|
128
153
|
export function getEnvVariableOrElse<T>(key: string, orElse: T): string | T {
|
129
154
|
return getEnvVariableOr(key, () => orElse);
|
130
155
|
}
|
156
|
+
|
157
|
+
export function setSecretOverideAwsRegionEnv(region: string) {
|
158
|
+
setEnvVariable(EnvKeys.SECRET_OVERRIDE_AWS_REGION, region);
|
159
|
+
}
|
160
|
+
|
161
|
+
/**
|
162
|
+
* ESLint won't allow to call Object.prototype builtin methods.
|
163
|
+
* To call hasOwnProperty we must use Object.prototype.hasOwnProperty.call()
|
164
|
+
* @param object to test for property
|
165
|
+
* @param propertyName property name to check
|
166
|
+
* @see https://eslint.org/docs/latest/rules/no-prototype-builtins
|
167
|
+
*/
|
168
|
+
export function hasOwnPropertySafe(
|
169
|
+
object: object,
|
170
|
+
propertyName: string
|
171
|
+
): boolean {
|
172
|
+
return Object.prototype.hasOwnProperty.call(object, propertyName);
|
173
|
+
}
|
174
|
+
|
175
|
+
/**
|
176
|
+
* Return an error message from the given object hat might be an Error object.
|
177
|
+
* @param maybeError
|
178
|
+
*/
|
179
|
+
export function getErrorMessage(maybeError: unknown) {
|
180
|
+
if (maybeError instanceof Error) {
|
181
|
+
return maybeError.name + ": " + maybeError.message;
|
182
|
+
}
|
183
|
+
return String(maybeError);
|
184
|
+
}
|