@digitraffic/common 2026.3.17-1 → 2026.3.26-1-beta
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/README.md +18 -1
- package/dist/__test__/asserter.d.ts +13 -0
- package/dist/__test__/asserter.js +39 -0
- package/dist/__test__/db-testutils.d.ts +3 -0
- package/dist/__test__/db-testutils.js +38 -0
- package/dist/__test__/dependencies.test.d.ts +1 -0
- package/dist/__test__/dependencies.test.js +21 -0
- package/dist/__test__/imports.test.d.ts +1 -0
- package/dist/__test__/imports.test.js +318 -0
- package/dist/__test__/infra/acl-builder.test.d.ts +1 -0
- package/dist/__test__/infra/acl-builder.test.js +72 -0
- package/dist/__test__/infra/api/handler-factory.test.d.ts +1 -0
- package/dist/__test__/infra/api/handler-factory.test.js +42 -0
- package/dist/__test__/infra/api/integration.test.d.ts +1 -0
- package/dist/__test__/infra/api/integration.test.js +162 -0
- package/dist/__test__/infra/api/response.test.d.ts +1 -0
- package/dist/__test__/infra/api/response.test.js +77 -0
- package/dist/__test__/infra/api/static-integration.test.d.ts +1 -0
- package/dist/__test__/infra/api/static-integration.test.js +35 -0
- package/dist/__test__/infra/documentation.test.d.ts +1 -0
- package/dist/__test__/infra/documentation.test.js +38 -0
- package/dist/__test__/infra/scheduler.test.d.ts +1 -0
- package/dist/__test__/infra/scheduler.test.js +23 -0
- package/dist/__test__/infra/security-rule.test.d.ts +1 -0
- package/dist/__test__/infra/security-rule.test.js +21 -0
- package/dist/__test__/infra/stack/rest-apis.test.d.ts +1 -0
- package/dist/__test__/infra/stack/rest-apis.test.js +47 -0
- package/dist/__test__/marine/id_utils.test.d.ts +1 -0
- package/dist/__test__/marine/id_utils.test.js +45 -0
- package/dist/__test__/mock-ky.d.ts +2 -0
- package/dist/__test__/mock-ky.js +15 -0
- package/dist/__test__/promise/promise.test.d.ts +1 -0
- package/dist/__test__/promise/promise.test.js +126 -0
- package/dist/__test__/runtime/dt-logger.test.d.ts +1 -0
- package/dist/__test__/runtime/dt-logger.test.js +193 -0
- package/dist/__test__/secrets/secret-holder.test.d.ts +1 -0
- package/dist/__test__/secrets/secret-holder.test.js +96 -0
- package/dist/__test__/secrets/secret.test.d.ts +1 -0
- package/dist/__test__/secrets/secret.test.js +57 -0
- package/dist/__test__/stack/dt-function.test.d.ts +1 -0
- package/dist/__test__/stack/dt-function.test.js +340 -0
- package/dist/__test__/stack/rest-apis.test.d.ts +1 -0
- package/dist/__test__/stack/rest-apis.test.js +45 -0
- package/dist/__test__/test/mock-ky.test.d.ts +1 -0
- package/dist/__test__/test/mock-ky.test.js +46 -0
- package/dist/__test__/testutils.d.ts +12 -0
- package/dist/__test__/testutils.js +32 -0
- package/dist/__test__/types/lambda-proxy-types.test.d.ts +8 -0
- package/dist/__test__/types/lambda-proxy-types.test.js +155 -0
- package/dist/__test__/types/lambda-response-builder.test.d.ts +1 -0
- package/dist/__test__/types/lambda-response-builder.test.js +81 -0
- package/dist/__test__/types/lambda-response.test.d.ts +9 -0
- package/dist/__test__/types/lambda-response.test.js +73 -0
- package/dist/__test__/utils/base64.test.d.ts +1 -0
- package/dist/__test__/utils/base64.test.js +38 -0
- package/dist/__test__/utils/date-utils.test.d.ts +1 -0
- package/dist/__test__/utils/date-utils.test.js +32 -0
- package/dist/__test__/utils/geometry.test.d.ts +1 -0
- package/dist/__test__/utils/geometry.test.js +25 -0
- package/dist/__test__/utils/lambda-proxy-event.test.d.ts +1 -0
- package/dist/__test__/utils/lambda-proxy-event.test.js +45 -0
- package/dist/__test__/utils/logging.test.d.ts +1 -0
- package/dist/__test__/utils/logging.test.js +75 -0
- package/dist/__test__/utils/stop-watch.test.d.ts +1 -0
- package/dist/__test__/utils/stop-watch.test.js +118 -0
- package/dist/__test__/utils/utils.test.d.ts +1 -0
- package/dist/__test__/utils/utils.test.js +48 -0
- package/dist/aws/infra/acl-builder.d.ts +53 -0
- package/dist/aws/infra/acl-builder.js +407 -0
- package/dist/aws/infra/api/handler-factory.d.ts +22 -0
- package/dist/aws/infra/api/handler-factory.js +68 -0
- package/dist/aws/infra/api/integration.d.ts +49 -0
- package/dist/aws/infra/api/integration.js +162 -0
- package/dist/aws/infra/api/response.d.ts +62 -0
- package/dist/aws/infra/api/response.js +132 -0
- package/dist/aws/infra/api/responses.d.ts +60 -0
- package/dist/aws/infra/api/responses.js +90 -0
- package/dist/aws/infra/api/static-integration.d.ts +16 -0
- package/dist/aws/infra/api/static-integration.js +76 -0
- package/dist/aws/infra/bucket-policy.d.ts +38 -0
- package/dist/aws/infra/bucket-policy.js +30 -0
- package/dist/aws/infra/canaries/canary-alarm.d.ts +6 -0
- package/dist/aws/infra/canaries/canary-alarm.js +20 -0
- package/dist/aws/infra/canaries/canary-keys.d.ts +3 -0
- package/dist/aws/infra/canaries/canary-keys.js +4 -0
- package/dist/aws/infra/canaries/canary-parameters.d.ts +19 -0
- package/dist/aws/infra/canaries/canary-parameters.js +2 -0
- package/dist/aws/infra/canaries/canary-role.d.ts +14 -0
- package/dist/aws/infra/canaries/canary-role.js +51 -0
- package/dist/aws/infra/canaries/canary.d.ts +8 -0
- package/dist/aws/infra/canaries/canary.js +26 -0
- package/dist/aws/infra/canaries/database-canary.d.ts +17 -0
- package/dist/aws/infra/canaries/database-canary.js +65 -0
- package/dist/aws/infra/canaries/database-checker.d.ts +33 -0
- package/dist/aws/infra/canaries/database-checker.js +119 -0
- package/dist/aws/infra/canaries/url-canary.d.ts +16 -0
- package/dist/aws/infra/canaries/url-canary.js +55 -0
- package/dist/aws/infra/canaries/url-checker.d.ts +45 -0
- package/dist/aws/infra/canaries/url-checker.js +256 -0
- package/dist/aws/infra/documentation.d.ts +56 -0
- package/dist/aws/infra/documentation.js +90 -0
- package/dist/aws/infra/import-util.d.ts +17 -0
- package/dist/aws/infra/import-util.js +41 -0
- package/dist/aws/infra/scheduler.d.ts +12 -0
- package/dist/aws/infra/scheduler.js +27 -0
- package/dist/aws/infra/security-rule.d.ts +12 -0
- package/dist/aws/infra/security-rule.js +35 -0
- package/dist/aws/infra/sqs-integration.d.ts +4 -0
- package/dist/aws/infra/sqs-integration.js +85 -0
- package/dist/aws/infra/sqs-queue.d.ts +19 -0
- package/dist/aws/infra/sqs-queue.js +145 -0
- package/dist/aws/infra/stack/dt-function-alarms.d.ts +29 -0
- package/dist/aws/infra/stack/dt-function-alarms.js +54 -0
- package/dist/aws/infra/stack/dt-function.d.ts +124 -0
- package/dist/aws/infra/stack/dt-function.js +315 -0
- package/dist/aws/infra/stack/lambda-configs.d.ts +44 -0
- package/dist/aws/infra/stack/lambda-configs.js +71 -0
- package/dist/aws/infra/stack/lambda-log-group.d.ts +15 -0
- package/dist/aws/infra/stack/lambda-log-group.js +24 -0
- package/dist/aws/infra/stack/monitoredfunction.d.ts +85 -0
- package/dist/aws/infra/stack/monitoredfunction.js +147 -0
- package/dist/aws/infra/stack/parameters.d.ts +40 -0
- package/dist/aws/infra/stack/parameters.js +50 -0
- package/dist/aws/infra/stack/rest-api.d.ts +74 -0
- package/dist/aws/infra/stack/rest-api.js +235 -0
- package/dist/aws/infra/stack/stack-checking-aspect.d.ts +20 -0
- package/dist/aws/infra/stack/stack-checking-aspect.js +183 -0
- package/dist/aws/infra/stack/stack.d.ts +56 -0
- package/dist/aws/infra/stack/stack.js +71 -0
- package/dist/aws/infra/stack/subscription.d.ts +17 -0
- package/dist/aws/infra/stack/subscription.js +37 -0
- package/dist/aws/infra/stacks/db-dns-stack.d.ts +13 -0
- package/dist/aws/infra/stacks/db-dns-stack.js +60 -0
- package/dist/aws/infra/stacks/db-proxy-stack.d.ts +24 -0
- package/dist/aws/infra/stacks/db-proxy-stack.js +74 -0
- package/dist/aws/infra/stacks/db-stack.d.ts +65 -0
- package/dist/aws/infra/stacks/db-stack.js +189 -0
- package/dist/aws/infra/stacks/intra-stack-configuration.d.ts +5 -0
- package/dist/aws/infra/stacks/intra-stack-configuration.js +2 -0
- package/dist/aws/infra/stacks/network-stack.d.ts +14 -0
- package/dist/aws/infra/stacks/network-stack.js +45 -0
- package/dist/aws/infra/usage-plans.d.ts +16 -0
- package/dist/aws/infra/usage-plans.js +38 -0
- package/dist/aws/runtime/apikey.d.ts +2 -0
- package/dist/aws/runtime/apikey.js +13 -0
- package/dist/aws/runtime/digitraffic-integration-response.d.ts +8 -0
- package/dist/aws/runtime/digitraffic-integration-response.js +25 -0
- package/dist/aws/runtime/dt-logger-default.d.ts +9 -0
- package/dist/aws/runtime/dt-logger-default.js +6 -0
- package/dist/aws/runtime/dt-logger.d.ts +117 -0
- package/dist/aws/runtime/dt-logger.js +159 -0
- package/dist/aws/runtime/environment.d.ts +5 -0
- package/dist/aws/runtime/environment.js +7 -0
- package/dist/aws/runtime/s3.d.ts +3 -0
- package/dist/aws/runtime/s3.js +21 -0
- package/dist/aws/runtime/secrets/dbsecret.d.ts +16 -0
- package/dist/aws/runtime/secrets/dbsecret.js +26 -0
- package/dist/aws/runtime/secrets/proxy-holder.d.ts +9 -0
- package/dist/aws/runtime/secrets/proxy-holder.js +25 -0
- package/dist/aws/runtime/secrets/rds-holder.d.ts +9 -0
- package/dist/aws/runtime/secrets/rds-holder.js +25 -0
- package/dist/aws/runtime/secrets/secret-holder.d.ts +30 -0
- package/dist/aws/runtime/secrets/secret-holder.js +81 -0
- package/dist/aws/runtime/secrets/secret.d.ts +8 -0
- package/dist/aws/runtime/secrets/secret.js +61 -0
- package/dist/aws/types/errors.d.ts +8 -0
- package/dist/aws/types/errors.js +13 -0
- package/dist/aws/types/lambda-proxy-types.d.ts +59 -0
- package/dist/aws/types/lambda-proxy-types.js +210 -0
- package/dist/aws/types/lambda-response.d.ts +89 -0
- package/dist/aws/types/lambda-response.js +204 -0
- package/dist/aws/types/mediatypes.d.ts +11 -0
- package/dist/aws/types/mediatypes.js +14 -0
- package/dist/aws/types/model-with-reference.d.ts +7 -0
- package/dist/aws/types/model-with-reference.js +2 -0
- package/dist/aws/types/tags.d.ts +2 -0
- package/dist/aws/types/tags.js +4 -0
- package/dist/database/database.d.ts +27 -0
- package/dist/database/database.js +95 -0
- package/dist/database/last-updated.d.ts +15 -0
- package/dist/database/last-updated.js +46 -0
- package/dist/database/models.d.ts +6 -0
- package/dist/database/models.js +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/marine/id_utils.d.ts +3 -0
- package/dist/marine/id_utils.js +36 -0
- package/dist/marine/rtz.d.ts +48 -0
- package/dist/marine/rtz.js +2 -0
- package/dist/types/async-timeout-error.d.ts +3 -0
- package/dist/types/async-timeout-error.js +6 -0
- package/dist/types/either.d.ts +9 -0
- package/dist/types/either.js +2 -0
- package/dist/types/geojson.d.ts +47 -0
- package/dist/types/geojson.js +51 -0
- package/dist/types/http-error.d.ts +4 -0
- package/dist/types/http-error.js +8 -0
- package/dist/types/input-error.d.ts +2 -0
- package/dist/types/input-error.js +3 -0
- package/dist/types/language.d.ts +5 -0
- package/dist/types/language.js +7 -0
- package/dist/types/nullable.d.ts +24 -0
- package/dist/types/nullable.js +2 -0
- package/dist/types/openapi-schema.d.ts +932 -0
- package/dist/types/openapi-schema.js +151 -0
- package/dist/types/traffictype.d.ts +11 -0
- package/dist/types/traffictype.js +13 -0
- package/dist/types/urn.d.ts +1 -0
- package/dist/types/urn.js +2 -0
- package/dist/types/util-types.d.ts +11 -0
- package/dist/types/util-types.js +2 -0
- package/dist/types/validator.d.ts +4 -0
- package/dist/types/validator.js +9 -0
- package/dist/utils/api-model.d.ts +51 -0
- package/dist/utils/api-model.js +118 -0
- package/dist/utils/base64.d.ts +34 -0
- package/dist/utils/base64.js +53 -0
- package/dist/utils/date-utils.d.ts +27 -0
- package/dist/utils/date-utils.js +45 -0
- package/dist/utils/geojson-types.d.ts +14 -0
- package/dist/utils/geojson-types.js +15 -0
- package/dist/utils/geometry.d.ts +44 -0
- package/dist/utils/geometry.js +154 -0
- package/dist/utils/lambda-proxy-event.d.ts +9 -0
- package/dist/utils/lambda-proxy-event.js +31 -0
- package/dist/utils/logging.d.ts +40 -0
- package/dist/utils/logging.js +88 -0
- package/dist/utils/retry.d.ts +33 -0
- package/dist/utils/retry.js +135 -0
- package/dist/utils/slack.d.ts +5 -0
- package/dist/utils/slack.js +24 -0
- package/dist/utils/stop-watch.d.ts +46 -0
- package/dist/utils/stop-watch.js +114 -0
- package/dist/utils/utils.d.ts +95 -0
- package/dist/utils/utils.js +178 -0
- package/dist/utils/zod-utils.d.ts +27 -0
- package/dist/utils/zod-utils.js +57 -0
- package/package.json +30 -28
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { Writable } from "node:stream";
|
|
2
|
+
/** Logging level */
|
|
3
|
+
export type LOG_LEVEL = "DEBUG" | "INFO" | "WARN" | "ERROR";
|
|
4
|
+
export type LoggerMethodType = `${string}.${string}`;
|
|
5
|
+
/**
|
|
6
|
+
* Configuration object for configuring the Digitraffic logging utility
|
|
7
|
+
* @see {@link DtLogger}
|
|
8
|
+
*/
|
|
9
|
+
export interface LoggerConfiguration {
|
|
10
|
+
/** Name of the lambda */
|
|
11
|
+
lambdaName?: string;
|
|
12
|
+
/** The file name where the logging occurs */
|
|
13
|
+
fileName?: string;
|
|
14
|
+
/** The lambda runtime environment */
|
|
15
|
+
runTime?: string;
|
|
16
|
+
/** Custom end point to write the logs to */
|
|
17
|
+
writeStream?: Writable;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* CustomParams allows to add keys prefixed with `custom` keyword to be added to an
|
|
21
|
+
* object.
|
|
22
|
+
*/
|
|
23
|
+
export interface CustomParams {
|
|
24
|
+
/** do not log your apikey! */
|
|
25
|
+
customApikey?: never;
|
|
26
|
+
/** do not log your apikey! */
|
|
27
|
+
customApiKey?: never;
|
|
28
|
+
[key: `custom${Capitalize<string>}Count`]: number;
|
|
29
|
+
[key: `custom${Capitalize<string>}`]: string | number | bigint | boolean | Date | null | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Digitraffic logging object.
|
|
33
|
+
*
|
|
34
|
+
* `method` property is the only required propetry. {@link CustomParams} can be added by
|
|
35
|
+
* prefixin the property with keyword `custom`. The prefix is removed before writing to
|
|
36
|
+
* logging end point.
|
|
37
|
+
*
|
|
38
|
+
* @see {@link CustomParams}
|
|
39
|
+
*/
|
|
40
|
+
export interface LoggableType extends CustomParams {
|
|
41
|
+
/** Name of the method logging the message */
|
|
42
|
+
method: LoggerMethodType;
|
|
43
|
+
/** Message to log, optional */
|
|
44
|
+
message?: string;
|
|
45
|
+
/** Type of message, optional */
|
|
46
|
+
type?: string;
|
|
47
|
+
/** Stack trace, optional */
|
|
48
|
+
stack?: string | undefined;
|
|
49
|
+
/** Amount of time some operation took in milliseconds, optional */
|
|
50
|
+
tookMs?: number;
|
|
51
|
+
/** Pass error object, which will be stringified before logging */
|
|
52
|
+
error?: unknown;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Helper class for json-logging.
|
|
56
|
+
*
|
|
57
|
+
* Logged line will include:
|
|
58
|
+
* * log-level
|
|
59
|
+
* * lambdaName (taken from process environment)
|
|
60
|
+
* * runtime (taken from process environment)
|
|
61
|
+
* * the actual message (as json or as string)
|
|
62
|
+
*/
|
|
63
|
+
export declare class DtLogger {
|
|
64
|
+
readonly lambdaName?: string;
|
|
65
|
+
readonly runtime?: string;
|
|
66
|
+
readonly writeStream: Writable;
|
|
67
|
+
/**
|
|
68
|
+
* Create a new Logger instance.
|
|
69
|
+
* @constructor
|
|
70
|
+
* @param {LoggerConfiguration?} [config] - Accepts configuration options @see {@link LoggerConfiguration}
|
|
71
|
+
*/
|
|
72
|
+
constructor(config?: LoggerConfiguration);
|
|
73
|
+
/**
|
|
74
|
+
* Log given message with level DEBUG. This will not be forwarded to centralized logging system!.
|
|
75
|
+
*
|
|
76
|
+
* @param message anything
|
|
77
|
+
* @see {@link LoggableType}
|
|
78
|
+
* @see {@link DtLogger.log}
|
|
79
|
+
*/
|
|
80
|
+
debug(message: unknown): void;
|
|
81
|
+
/**
|
|
82
|
+
* Log given message with level INFO
|
|
83
|
+
*
|
|
84
|
+
* @param message Json-object to log
|
|
85
|
+
* @see {@link LoggableType}
|
|
86
|
+
* @see {@link DtLogger.log}
|
|
87
|
+
*/
|
|
88
|
+
info(message: LoggableType): void;
|
|
89
|
+
/**
|
|
90
|
+
* Log given message with level WARN
|
|
91
|
+
*
|
|
92
|
+
* @param message Json-object to log
|
|
93
|
+
* @see {@link LoggableType}
|
|
94
|
+
* @see {@link DtLogger.log}
|
|
95
|
+
*/
|
|
96
|
+
warn(message: LoggableType): void;
|
|
97
|
+
/**
|
|
98
|
+
* Log given message with level INFO
|
|
99
|
+
*
|
|
100
|
+
* @param message Json-object to log
|
|
101
|
+
* @see {@link LoggableType}
|
|
102
|
+
* @see {@link DtLogger.log}
|
|
103
|
+
*/
|
|
104
|
+
error(message: LoggableType): void;
|
|
105
|
+
/**
|
|
106
|
+
* Log message with given log level.
|
|
107
|
+
*
|
|
108
|
+
* Some metadata is also added to the message:
|
|
109
|
+
* * runtime - can be configured with constructor or inferred from environment
|
|
110
|
+
* * lambdaName - can be configured with constructor or inferred from environment
|
|
111
|
+
*
|
|
112
|
+
* @param message Json-object to log
|
|
113
|
+
* @see {@link LoggableType}
|
|
114
|
+
*/
|
|
115
|
+
private log;
|
|
116
|
+
private appendMessageFieldsToMessage;
|
|
117
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { lowerFirst, mapKeys } from "es-toolkit";
|
|
2
|
+
import { getEnvVariableOrElse } from "../../utils/utils.js";
|
|
3
|
+
/**
|
|
4
|
+
* Helper class for json-logging.
|
|
5
|
+
*
|
|
6
|
+
* Logged line will include:
|
|
7
|
+
* * log-level
|
|
8
|
+
* * lambdaName (taken from process environment)
|
|
9
|
+
* * runtime (taken from process environment)
|
|
10
|
+
* * the actual message (as json or as string)
|
|
11
|
+
*/
|
|
12
|
+
export class DtLogger {
|
|
13
|
+
lambdaName;
|
|
14
|
+
runtime;
|
|
15
|
+
writeStream;
|
|
16
|
+
/**
|
|
17
|
+
* Create a new Logger instance.
|
|
18
|
+
* @constructor
|
|
19
|
+
* @param {LoggerConfiguration?} [config] - Accepts configuration options @see {@link LoggerConfiguration}
|
|
20
|
+
*/
|
|
21
|
+
constructor(config) {
|
|
22
|
+
this.lambdaName =
|
|
23
|
+
config?.lambdaName ??
|
|
24
|
+
getEnvVariableOrElse("AWS_LAMBDA_FUNCTION_NAME", "unknown lambda name");
|
|
25
|
+
this.runtime =
|
|
26
|
+
config?.runTime ??
|
|
27
|
+
getEnvVariableOrElse("AWS_EXECUTION_ENV", "unknown runtime");
|
|
28
|
+
this.writeStream = config?.writeStream ?? process.stdout;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Log given message with level DEBUG. This will not be forwarded to centralized logging system!.
|
|
32
|
+
*
|
|
33
|
+
* @param message anything
|
|
34
|
+
* @see {@link LoggableType}
|
|
35
|
+
* @see {@link DtLogger.log}
|
|
36
|
+
*/
|
|
37
|
+
debug(message) {
|
|
38
|
+
const logMessage = {
|
|
39
|
+
message,
|
|
40
|
+
level: "DEBUG",
|
|
41
|
+
lambdaName: this.lambdaName,
|
|
42
|
+
runtime: this.runtime,
|
|
43
|
+
};
|
|
44
|
+
this.writeStream.write(`${JSON.stringify(logMessage)}\n`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Log given message with level INFO
|
|
48
|
+
*
|
|
49
|
+
* @param message Json-object to log
|
|
50
|
+
* @see {@link LoggableType}
|
|
51
|
+
* @see {@link DtLogger.log}
|
|
52
|
+
*/
|
|
53
|
+
info(message) {
|
|
54
|
+
this.log({ ...message, level: "INFO" });
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Log given message with level WARN
|
|
58
|
+
*
|
|
59
|
+
* @param message Json-object to log
|
|
60
|
+
* @see {@link LoggableType}
|
|
61
|
+
* @see {@link DtLogger.log}
|
|
62
|
+
*/
|
|
63
|
+
warn(message) {
|
|
64
|
+
this.log({ ...message, level: "WARN" });
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Log given message with level INFO
|
|
68
|
+
*
|
|
69
|
+
* @param message Json-object to log
|
|
70
|
+
* @see {@link LoggableType}
|
|
71
|
+
* @see {@link DtLogger.log}
|
|
72
|
+
*/
|
|
73
|
+
error(message) {
|
|
74
|
+
this.log({
|
|
75
|
+
...message,
|
|
76
|
+
level: "ERROR",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Log message with given log level.
|
|
81
|
+
*
|
|
82
|
+
* Some metadata is also added to the message:
|
|
83
|
+
* * runtime - can be configured with constructor or inferred from environment
|
|
84
|
+
* * lambdaName - can be configured with constructor or inferred from environment
|
|
85
|
+
*
|
|
86
|
+
* @param message Json-object to log
|
|
87
|
+
* @see {@link LoggableType}
|
|
88
|
+
*/
|
|
89
|
+
log(message) {
|
|
90
|
+
// Append always method to message
|
|
91
|
+
if (!message.message ||
|
|
92
|
+
!message.message.length ||
|
|
93
|
+
!message.message.includes(message.method)) {
|
|
94
|
+
message.message = `${message.method} ${message.message ?? ""}`;
|
|
95
|
+
}
|
|
96
|
+
const error = message.error
|
|
97
|
+
? message.error instanceof Error
|
|
98
|
+
? `${message.error.name}: ${message.error.message}`
|
|
99
|
+
: typeof message.error === "string"
|
|
100
|
+
? message.error
|
|
101
|
+
: JSON.stringify(message.error)
|
|
102
|
+
: undefined;
|
|
103
|
+
const stack = message.stack
|
|
104
|
+
? message.stack
|
|
105
|
+
: message.error
|
|
106
|
+
? message.error instanceof Error
|
|
107
|
+
? message.error.stack
|
|
108
|
+
: undefined
|
|
109
|
+
: undefined;
|
|
110
|
+
const messageFields = removePrefix("custom", message);
|
|
111
|
+
messageFields.message = this.appendMessageFieldsToMessage(messageFields);
|
|
112
|
+
const logMessage = {
|
|
113
|
+
...messageFields,
|
|
114
|
+
error,
|
|
115
|
+
stack,
|
|
116
|
+
lambdaName: this.lambdaName,
|
|
117
|
+
runtime: this.runtime,
|
|
118
|
+
};
|
|
119
|
+
this.writeStream.write(`${JSON.stringify(logMessage)}\n`);
|
|
120
|
+
}
|
|
121
|
+
appendMessageFieldsToMessage(message) {
|
|
122
|
+
// The order is not guaranteed to be alphabetical etc.
|
|
123
|
+
const fielValuePairs = Object.entries(message)
|
|
124
|
+
// Remove fields not logged in message field
|
|
125
|
+
.filter(([key]) => {
|
|
126
|
+
return (!["message", "level", "method", "stack", "error"].includes(key) &&
|
|
127
|
+
!(message.message ?? "").includes(`${key}=`));
|
|
128
|
+
})
|
|
129
|
+
// Map value to string
|
|
130
|
+
.map(([key, value]) => `${key}=${valueToString(value)}`)
|
|
131
|
+
.join(" ");
|
|
132
|
+
return `${message.message ?? ""}${fielValuePairs ? ` ${fielValuePairs}` : ""}`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Removes given prefixes from the keys of the object.
|
|
137
|
+
*/
|
|
138
|
+
function removePrefix(prefix, loggable) {
|
|
139
|
+
return mapKeys(loggable, (_index, key) => key.startsWith(prefix) ? lowerFirst(key.replace(prefix, "")) : key);
|
|
140
|
+
}
|
|
141
|
+
function valueToString(value) {
|
|
142
|
+
if (value === undefined) {
|
|
143
|
+
return "undefined";
|
|
144
|
+
}
|
|
145
|
+
else if (value === null) {
|
|
146
|
+
return "null";
|
|
147
|
+
}
|
|
148
|
+
else if (value instanceof Date) {
|
|
149
|
+
return value.toISOString();
|
|
150
|
+
}
|
|
151
|
+
else if (typeof value !== "string") {
|
|
152
|
+
return JSON.stringify(value);
|
|
153
|
+
}
|
|
154
|
+
else if (value.includes("=")) {
|
|
155
|
+
return JSON.stringify(value);
|
|
156
|
+
}
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=dt-logger.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export var EnvKeys;
|
|
2
|
+
(function (EnvKeys) {
|
|
3
|
+
EnvKeys["AWS_REGION"] = "AWS_REGION";
|
|
4
|
+
EnvKeys["SECRET_ID"] = "SECRET_ID";
|
|
5
|
+
EnvKeys["SECRET_OVERRIDE_AWS_REGION"] = "SECRET_OVERRIDE_AWS_REGION";
|
|
6
|
+
})(EnvKeys || (EnvKeys = {}));
|
|
7
|
+
//# sourceMappingURL=environment.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ObjectCannedACL, S3Client } from "@aws-sdk/client-s3";
|
|
2
|
+
import type { NodeJsRuntimeStreamingBlobPayloadInputTypes } from "@smithy/types";
|
|
3
|
+
export declare function uploadToS3(s3: S3Client, bucketName: string, body: NodeJsRuntimeStreamingBlobPayloadInputTypes, objectName: string, cannedAcl?: ObjectCannedACL, contentType?: string): Promise<void>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
|
2
|
+
import { logger } from "./dt-logger-default.js";
|
|
3
|
+
export async function uploadToS3(s3, bucketName, body, objectName, cannedAcl, contentType) {
|
|
4
|
+
const command = new PutObjectCommand({
|
|
5
|
+
Bucket: bucketName,
|
|
6
|
+
Key: objectName,
|
|
7
|
+
Body: body,
|
|
8
|
+
ACL: cannedAcl,
|
|
9
|
+
ContentType: contentType,
|
|
10
|
+
});
|
|
11
|
+
try {
|
|
12
|
+
await s3.send(command);
|
|
13
|
+
}
|
|
14
|
+
catch (_error) {
|
|
15
|
+
logger.error({
|
|
16
|
+
method: "s3.uploadToS3",
|
|
17
|
+
message: `upload failed to bucket ${bucketName}`,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=s3.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GenericSecret } from "./secret.js";
|
|
2
|
+
export declare enum RdsProxySecretKey {
|
|
3
|
+
username = "username",
|
|
4
|
+
password = "password",
|
|
5
|
+
proxy_host = "proxy_host",
|
|
6
|
+
proxy_ro_host = "proxy_ro_host"
|
|
7
|
+
}
|
|
8
|
+
export declare enum RdsSecretKey {
|
|
9
|
+
username = "username",
|
|
10
|
+
password = "password",
|
|
11
|
+
host = "host",
|
|
12
|
+
ro_host = "ro_host"
|
|
13
|
+
}
|
|
14
|
+
export type RdsProxySecret = Record<RdsProxySecretKey, string>;
|
|
15
|
+
export type RdsSecret = Record<RdsSecretKey, string>;
|
|
16
|
+
export declare function checkExpectedSecretKeys<Secret extends GenericSecret>(keys: string[], secret: Secret): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { logger } from "../dt-logger-default.js";
|
|
2
|
+
export var RdsProxySecretKey;
|
|
3
|
+
(function (RdsProxySecretKey) {
|
|
4
|
+
RdsProxySecretKey["username"] = "username";
|
|
5
|
+
RdsProxySecretKey["password"] = "password";
|
|
6
|
+
RdsProxySecretKey["proxy_host"] = "proxy_host";
|
|
7
|
+
RdsProxySecretKey["proxy_ro_host"] = "proxy_ro_host";
|
|
8
|
+
})(RdsProxySecretKey || (RdsProxySecretKey = {}));
|
|
9
|
+
export var RdsSecretKey;
|
|
10
|
+
(function (RdsSecretKey) {
|
|
11
|
+
RdsSecretKey["username"] = "username";
|
|
12
|
+
RdsSecretKey["password"] = "password";
|
|
13
|
+
RdsSecretKey["host"] = "host";
|
|
14
|
+
RdsSecretKey["ro_host"] = "ro_host";
|
|
15
|
+
})(RdsSecretKey || (RdsSecretKey = {}));
|
|
16
|
+
export function checkExpectedSecretKeys(keys, secret) {
|
|
17
|
+
const missingKeys = keys.filter((key) => !(key in secret));
|
|
18
|
+
if (missingKeys.length) {
|
|
19
|
+
logger.error({
|
|
20
|
+
method: "dbsecret.checkExpectedSecretKeys",
|
|
21
|
+
message: `secret didn't contain the key(s) ${missingKeys.toString()}`,
|
|
22
|
+
});
|
|
23
|
+
throw new Error("Expected keys were not found");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=dbsecret.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DatabaseEnvironmentKeys } from "../../../database/database.js";
|
|
2
|
+
import { getEnvVariable, setEnvVariable } from "../../../utils/utils.js";
|
|
3
|
+
import { RdsProxySecretKey } from "./dbsecret.js";
|
|
4
|
+
import { SecretHolder } from "./secret-holder.js";
|
|
5
|
+
const RDS_PROXY_SECRET_KEYS = Object.values(RdsProxySecretKey);
|
|
6
|
+
/**
|
|
7
|
+
* Holds credentials for RDS Proxy access.
|
|
8
|
+
*/
|
|
9
|
+
export class ProxyHolder {
|
|
10
|
+
secretHolder;
|
|
11
|
+
constructor(secretId) {
|
|
12
|
+
this.secretHolder = new SecretHolder(secretId, "", RDS_PROXY_SECRET_KEYS);
|
|
13
|
+
}
|
|
14
|
+
static create() {
|
|
15
|
+
return new ProxyHolder(getEnvVariable("SECRET_ID"));
|
|
16
|
+
}
|
|
17
|
+
async setCredentials() {
|
|
18
|
+
const secret = await this.secretHolder.get();
|
|
19
|
+
setEnvVariable(DatabaseEnvironmentKeys.DB_USER, secret.username);
|
|
20
|
+
setEnvVariable(DatabaseEnvironmentKeys.DB_PASS, secret.password);
|
|
21
|
+
setEnvVariable(DatabaseEnvironmentKeys.DB_URI, secret.proxy_host);
|
|
22
|
+
setEnvVariable(DatabaseEnvironmentKeys.DB_RO_URI, secret.proxy_ro_host);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=proxy-holder.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DatabaseEnvironmentKeys } from "../../../database/database.js";
|
|
2
|
+
import { getEnvVariable, setEnvVariable } from "../../../utils/utils.js";
|
|
3
|
+
import { RdsSecretKey } from "./dbsecret.js";
|
|
4
|
+
import { SecretHolder } from "./secret-holder.js";
|
|
5
|
+
const RDS_SECRET_KEYS = Object.values(RdsSecretKey);
|
|
6
|
+
/**
|
|
7
|
+
* Holds credentials for RDS access.
|
|
8
|
+
*/
|
|
9
|
+
export class RdsHolder {
|
|
10
|
+
secretHolder;
|
|
11
|
+
constructor(secretId) {
|
|
12
|
+
this.secretHolder = new SecretHolder(secretId, "", RDS_SECRET_KEYS);
|
|
13
|
+
}
|
|
14
|
+
static create() {
|
|
15
|
+
return new RdsHolder(getEnvVariable("SECRET_ID"));
|
|
16
|
+
}
|
|
17
|
+
async setCredentials() {
|
|
18
|
+
const secret = await this.secretHolder.get();
|
|
19
|
+
setEnvVariable(DatabaseEnvironmentKeys.DB_USER, secret.username);
|
|
20
|
+
setEnvVariable(DatabaseEnvironmentKeys.DB_PASS, secret.password);
|
|
21
|
+
setEnvVariable(DatabaseEnvironmentKeys.DB_URI, secret.host);
|
|
22
|
+
setEnvVariable(DatabaseEnvironmentKeys.DB_RO_URI, secret.ro_host);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=rds-holder.js.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { GenericSecret } from "./secret.js";
|
|
2
|
+
declare const DEFAULT_CONFIGURATION: {
|
|
3
|
+
readonly ttl: number;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Utility class for getting secrets from Secret Manager.
|
|
7
|
+
* Supports prefix for secrets, checking of expected keys and ttl-configuration.
|
|
8
|
+
*
|
|
9
|
+
* By default, secrets are cached for 5 minutes and then reread from the Secrets Manager(This can be overridden with configuration).
|
|
10
|
+
*
|
|
11
|
+
* Supports setting the database environment paramaters from the secret too.
|
|
12
|
+
*
|
|
13
|
+
* If you want secret manager to get values from different region than the lambda runtime is running, you can override this by
|
|
14
|
+
* setting the region with utils setSecretOverideAwsRegionEnv method.
|
|
15
|
+
*/
|
|
16
|
+
export declare class SecretHolder<Secret extends GenericSecret> {
|
|
17
|
+
private readonly secretId;
|
|
18
|
+
private readonly prefix;
|
|
19
|
+
private readonly expectedKeys;
|
|
20
|
+
private cachedSecret?;
|
|
21
|
+
private expirationTime;
|
|
22
|
+
private readonly ttl;
|
|
23
|
+
constructor(secretId: string, prefix?: string, expectedKeys?: string[], configuration?: typeof DEFAULT_CONFIGURATION);
|
|
24
|
+
private initSecret;
|
|
25
|
+
static create<S extends GenericSecret>(prefix?: string, expectedKeys?: string[]): SecretHolder<S>;
|
|
26
|
+
get(): Promise<Secret>;
|
|
27
|
+
private parseSecret;
|
|
28
|
+
private getSecret;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { getEnvVariable } from "../../../utils/utils.js";
|
|
2
|
+
import { logger } from "../dt-logger-default.js";
|
|
3
|
+
import { checkExpectedSecretKeys } from "./dbsecret.js";
|
|
4
|
+
import { getSecret } from "./secret.js";
|
|
5
|
+
const DEFAULT_PREFIX = "";
|
|
6
|
+
const DEFAULT_CONFIGURATION = {
|
|
7
|
+
ttl: 5 * 60, // timeout secrets in 5 minutes
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Utility class for getting secrets from Secret Manager.
|
|
11
|
+
* Supports prefix for secrets, checking of expected keys and ttl-configuration.
|
|
12
|
+
*
|
|
13
|
+
* By default, secrets are cached for 5 minutes and then reread from the Secrets Manager(This can be overridden with configuration).
|
|
14
|
+
*
|
|
15
|
+
* Supports setting the database environment paramaters from the secret too.
|
|
16
|
+
*
|
|
17
|
+
* If you want secret manager to get values from different region than the lambda runtime is running, you can override this by
|
|
18
|
+
* setting the region with utils setSecretOverideAwsRegionEnv method.
|
|
19
|
+
*/
|
|
20
|
+
export class SecretHolder {
|
|
21
|
+
secretId;
|
|
22
|
+
prefix;
|
|
23
|
+
expectedKeys;
|
|
24
|
+
cachedSecret;
|
|
25
|
+
expirationTime;
|
|
26
|
+
ttl; // seconds
|
|
27
|
+
constructor(secretId, prefix = "", expectedKeys = [], configuration = DEFAULT_CONFIGURATION) {
|
|
28
|
+
this.secretId = secretId;
|
|
29
|
+
this.prefix = prefix;
|
|
30
|
+
this.expectedKeys = expectedKeys;
|
|
31
|
+
this.expirationTime = new Date(0);
|
|
32
|
+
this.ttl = configuration.ttl;
|
|
33
|
+
}
|
|
34
|
+
async initSecret() {
|
|
35
|
+
const secretValue = await getSecret(this.secretId);
|
|
36
|
+
logger.info({
|
|
37
|
+
method: "SecretHolder.initSecret",
|
|
38
|
+
message: `Refreshing secret ${this.secretId}`,
|
|
39
|
+
});
|
|
40
|
+
this.cachedSecret = secretValue;
|
|
41
|
+
this.expirationTime = new Date(Date.now() + this.ttl * 1000);
|
|
42
|
+
}
|
|
43
|
+
static create(prefix = DEFAULT_PREFIX, expectedKeys = []) {
|
|
44
|
+
return new SecretHolder(getEnvVariable("SECRET_ID"), prefix, expectedKeys);
|
|
45
|
+
}
|
|
46
|
+
async get() {
|
|
47
|
+
const secret = await this.getSecret();
|
|
48
|
+
const parsedSecret = this.prefix === DEFAULT_PREFIX
|
|
49
|
+
? secret
|
|
50
|
+
: this.parseSecret(secret, `${this.prefix}.`);
|
|
51
|
+
if (this.expectedKeys.length > 0) {
|
|
52
|
+
checkExpectedSecretKeys(this.expectedKeys, parsedSecret);
|
|
53
|
+
}
|
|
54
|
+
return parsedSecret;
|
|
55
|
+
}
|
|
56
|
+
parseSecret(secret, prefix) {
|
|
57
|
+
const parsed = {};
|
|
58
|
+
const skip = prefix.length;
|
|
59
|
+
for (const key in secret) {
|
|
60
|
+
if (key.startsWith(prefix)) {
|
|
61
|
+
const withoutPrefix = key.substring(skip);
|
|
62
|
+
// skip undefined values
|
|
63
|
+
if (!secret[key]) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
parsed[withoutPrefix] = secret[key];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return parsed;
|
|
70
|
+
}
|
|
71
|
+
async getSecret() {
|
|
72
|
+
if (this.expirationTime.getTime() < Date.now()) {
|
|
73
|
+
await this.initSecret();
|
|
74
|
+
}
|
|
75
|
+
if (this.cachedSecret === undefined) {
|
|
76
|
+
throw new Error("SecretHolder in illegal state");
|
|
77
|
+
}
|
|
78
|
+
return this.cachedSecret;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=secret-holder.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type GenericSecret = Record<string, string>;
|
|
2
|
+
export declare function getSecret<Secret>(secretId: string, prefix?: string): Promise<Secret>;
|
|
3
|
+
/**
|
|
4
|
+
* Gets variable from environment or from an AWS Secrets Manager secret if not found in the environment.
|
|
5
|
+
* @param Environment key
|
|
6
|
+
* @param Secret id in Secrets Manager
|
|
7
|
+
*/
|
|
8
|
+
export declare function getFromEnvOrSecret(key: string, secretId: string): Promise<string>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { SecretsManager } from "@aws-sdk/client-secrets-manager";
|
|
2
|
+
import { getEnvVariable, getEnvVariableOrElse, getEnvVariableSafe, } from "../../../utils/utils.js";
|
|
3
|
+
import { EnvKeys } from "../environment.js";
|
|
4
|
+
// SECRET_OVERRIDE_AWS_REGION might not have been set before import of
|
|
5
|
+
// secret, so we need to lazy initialize SecretsManager
|
|
6
|
+
let smClient;
|
|
7
|
+
function getSmClient() {
|
|
8
|
+
if (!smClient) {
|
|
9
|
+
smClient = new SecretsManager({
|
|
10
|
+
region: getEnvVariableOrElse(EnvKeys.SECRET_OVERRIDE_AWS_REGION, // this is override secret region
|
|
11
|
+
getEnvVariable(EnvKeys.AWS_REGION)),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return smClient;
|
|
15
|
+
}
|
|
16
|
+
export async function getSecret(secretId, prefix = "") {
|
|
17
|
+
const secretObj = await getSmClient().getSecretValue({
|
|
18
|
+
SecretId: secretId,
|
|
19
|
+
});
|
|
20
|
+
if (!secretObj.SecretString) {
|
|
21
|
+
throw new Error("No secret found!");
|
|
22
|
+
}
|
|
23
|
+
const secret = JSON.parse(secretObj.SecretString);
|
|
24
|
+
if (!prefix) {
|
|
25
|
+
return secret;
|
|
26
|
+
}
|
|
27
|
+
return parseSecret(secret, `${prefix}.`);
|
|
28
|
+
}
|
|
29
|
+
function parseSecret(secret, prefix) {
|
|
30
|
+
const parsed = {};
|
|
31
|
+
const skip = prefix.length;
|
|
32
|
+
for (const key in secret) {
|
|
33
|
+
if (key.startsWith(prefix)) {
|
|
34
|
+
const withoutPrefix = key.substring(skip);
|
|
35
|
+
// skip undefined values
|
|
36
|
+
if (!secret[key]) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
parsed[withoutPrefix] = secret[key];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return parsed;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Gets variable from environment or from an AWS Secrets Manager secret if not found in the environment.
|
|
46
|
+
* @param Environment key
|
|
47
|
+
* @param Secret id in Secrets Manager
|
|
48
|
+
*/
|
|
49
|
+
export async function getFromEnvOrSecret(key, secretId) {
|
|
50
|
+
const envValue = getEnvVariableSafe(key);
|
|
51
|
+
if (envValue.result === "ok") {
|
|
52
|
+
return envValue.value;
|
|
53
|
+
}
|
|
54
|
+
const secret = await getSecret(secretId);
|
|
55
|
+
const secretValue = secret[key];
|
|
56
|
+
if (secretValue !== undefined) {
|
|
57
|
+
return secretValue;
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Cannot get value with key ${key} from env or secret`);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=secret.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const NOT_FOUND_MESSAGE = "NOT_FOUND";
|
|
2
|
+
export declare const ERROR_MESSAGE = "ERROR";
|
|
3
|
+
export declare const OK_MESSAGE = "OK";
|
|
4
|
+
export declare const BAD_REQUEST_MESSAGE = "BAD REQUEST";
|
|
5
|
+
export declare class ValidationError extends Error {
|
|
6
|
+
statusCode: number;
|
|
7
|
+
constructor(statusCode: number, body: string);
|
|
8
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// DEPRECATED, remove these!
|
|
2
|
+
export const NOT_FOUND_MESSAGE = "NOT_FOUND";
|
|
3
|
+
export const ERROR_MESSAGE = "ERROR";
|
|
4
|
+
export const OK_MESSAGE = "OK";
|
|
5
|
+
export const BAD_REQUEST_MESSAGE = "BAD REQUEST";
|
|
6
|
+
export class ValidationError extends Error {
|
|
7
|
+
statusCode;
|
|
8
|
+
constructor(statusCode, body) {
|
|
9
|
+
super(body);
|
|
10
|
+
this.statusCode = statusCode;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=errors.js.map
|