@digitraffic/common 2022.10.25-1 → 2022.10.28-2
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/{aws → dist/aws}/infra/api/integration.d.ts +0 -0
- package/dist/aws/infra/api/integration.js +52 -0
- package/dist/aws/infra/api/integration.js.map +1 -0
- package/{aws → dist/aws}/infra/api/response.d.ts +0 -0
- package/dist/aws/infra/api/response.js +61 -0
- package/dist/aws/infra/api/response.js.map +1 -0
- package/{aws → dist/aws}/infra/api/responses.d.ts +3 -3
- package/dist/aws/infra/api/responses.js +82 -0
- package/dist/aws/infra/api/responses.js.map +1 -0
- package/{aws → dist/aws}/infra/api/static-integration.d.ts +0 -0
- package/dist/aws/infra/api/static-integration.js +54 -0
- package/dist/aws/infra/api/static-integration.js.map +1 -0
- package/{aws → dist/aws}/infra/canaries/canary-alarm.d.ts +0 -0
- package/dist/aws/infra/canaries/canary-alarm.js +26 -0
- package/dist/aws/infra/canaries/canary-alarm.js.map +1 -0
- package/dist/aws/infra/canaries/canary-keys.d.ts +3 -0
- package/dist/aws/infra/canaries/canary-keys.js +7 -0
- package/dist/aws/infra/canaries/canary-keys.js.map +1 -0
- package/{aws → dist/aws}/infra/canaries/canary-parameters.d.ts +0 -0
- package/dist/aws/infra/canaries/canary-parameters.js +3 -0
- package/dist/aws/infra/canaries/canary-parameters.js.map +1 -0
- package/{aws → dist/aws}/infra/canaries/canary-role.d.ts +0 -0
- package/dist/aws/infra/canaries/canary-role.js +46 -0
- package/dist/aws/infra/canaries/canary-role.js.map +1 -0
- package/{aws → dist/aws}/infra/canaries/canary.d.ts +0 -0
- package/dist/aws/infra/canaries/canary.js +32 -0
- package/dist/aws/infra/canaries/canary.js.map +1 -0
- package/{aws → dist/aws}/infra/canaries/database-canary.d.ts +0 -0
- package/dist/aws/infra/canaries/database-canary.js +70 -0
- package/dist/aws/infra/canaries/database-canary.js.map +1 -0
- package/{aws → dist/aws}/infra/canaries/database-checker.d.ts +2 -2
- package/dist/aws/infra/canaries/database-checker.js +103 -0
- package/dist/aws/infra/canaries/database-checker.js.map +1 -0
- package/{aws → dist/aws}/infra/canaries/url-canary.d.ts +0 -3
- package/dist/aws/infra/canaries/url-canary.js +47 -0
- package/dist/aws/infra/canaries/url-canary.js.map +1 -0
- package/{aws → dist/aws}/infra/canaries/url-checker.d.ts +0 -0
- package/dist/aws/infra/canaries/url-checker.js +252 -0
- package/dist/aws/infra/canaries/url-checker.js.map +1 -0
- package/{aws → dist/aws}/infra/documentation.d.ts +0 -0
- package/dist/aws/infra/documentation.js +95 -0
- package/dist/aws/infra/documentation.js.map +1 -0
- package/{aws → dist/aws}/infra/scheduler.d.ts +7 -7
- package/dist/aws/infra/scheduler.js +31 -0
- package/dist/aws/infra/scheduler.js.map +1 -0
- package/{aws → dist/aws}/infra/security-rule.d.ts +0 -0
- package/dist/aws/infra/security-rule.js +39 -0
- package/dist/aws/infra/security-rule.js.map +1 -0
- package/{aws → dist/aws}/infra/sqs-integration.d.ts +0 -0
- package/dist/aws/infra/sqs-integration.js +93 -0
- package/dist/aws/infra/sqs-integration.js.map +1 -0
- package/{aws → dist/aws}/infra/sqs-queue.d.ts +0 -0
- package/dist/aws/infra/sqs-queue.js +130 -0
- package/dist/aws/infra/sqs-queue.js.map +1 -0
- package/{aws → dist/aws}/infra/stack/lambda-configs.d.ts +5 -5
- package/dist/aws/infra/stack/lambda-configs.js +105 -0
- package/dist/aws/infra/stack/lambda-configs.js.map +1 -0
- package/{aws → dist/aws}/infra/stack/monitoredfunction.d.ts +1 -1
- package/dist/aws/infra/stack/monitoredfunction.js +143 -0
- package/dist/aws/infra/stack/monitoredfunction.js.map +1 -0
- package/{aws → dist/aws}/infra/stack/rest_apis.d.ts +0 -0
- package/dist/aws/infra/stack/rest_apis.js +185 -0
- package/dist/aws/infra/stack/rest_apis.js.map +1 -0
- package/{aws → dist/aws}/infra/stack/stack-checking-aspect.d.ts +0 -0
- package/dist/aws/infra/stack/stack-checking-aspect.js +174 -0
- package/dist/aws/infra/stack/stack-checking-aspect.js.map +1 -0
- package/{aws → dist/aws}/infra/stack/stack.d.ts +5 -4
- package/dist/aws/infra/stack/stack.js +67 -0
- package/dist/aws/infra/stack/stack.js.map +1 -0
- package/{aws → dist/aws}/infra/stack/subscription.d.ts +3 -3
- package/dist/aws/infra/stack/subscription.js +42 -0
- package/dist/aws/infra/stack/subscription.js.map +1 -0
- package/{aws → dist/aws}/infra/usage-plans.d.ts +0 -0
- package/dist/aws/infra/usage-plans.js +42 -0
- package/dist/aws/infra/usage-plans.js.map +1 -0
- package/{aws → dist/aws}/runtime/apikey.d.ts +0 -0
- package/dist/aws/runtime/apikey.js +13 -0
- package/dist/aws/runtime/apikey.js.map +1 -0
- package/{aws → dist/aws}/runtime/digitraffic-integration-response.d.ts +0 -0
- package/dist/aws/runtime/digitraffic-integration-response.js +26 -0
- package/dist/aws/runtime/digitraffic-integration-response.js.map +1 -0
- package/{aws → dist/aws}/runtime/environment.d.ts +0 -0
- package/dist/aws/runtime/environment.js +12 -0
- package/dist/aws/runtime/environment.js.map +1 -0
- package/{aws → dist/aws}/runtime/messaging.d.ts +0 -0
- package/dist/aws/runtime/messaging.js +31 -0
- package/dist/aws/runtime/messaging.js.map +1 -0
- package/{aws → dist/aws}/runtime/s3.d.ts +0 -0
- package/dist/aws/runtime/s3.js +30 -0
- package/dist/aws/runtime/s3.js.map +1 -0
- package/{aws → dist/aws}/runtime/secrets/dbsecret.d.ts +0 -0
- package/dist/aws/runtime/secrets/dbsecret.js +96 -0
- package/dist/aws/runtime/secrets/dbsecret.js.map +1 -0
- package/{aws → dist/aws}/runtime/secrets/proxy-holder.d.ts +0 -0
- package/dist/aws/runtime/secrets/proxy-holder.js +27 -0
- package/dist/aws/runtime/secrets/proxy-holder.js.map +1 -0
- package/{aws → dist/aws}/runtime/secrets/rds-holder.d.ts +0 -0
- package/dist/aws/runtime/secrets/rds-holder.js +27 -0
- package/dist/aws/runtime/secrets/rds-holder.js.map +1 -0
- package/{aws → dist/aws}/runtime/secrets/secret-holder.d.ts +0 -0
- package/dist/aws/runtime/secrets/secret-holder.js +76 -0
- package/dist/aws/runtime/secrets/secret-holder.js.map +1 -0
- package/{aws → dist/aws}/runtime/secrets/secret.d.ts +0 -0
- package/dist/aws/runtime/secrets/secret.js +43 -0
- package/dist/aws/runtime/secrets/secret.js.map +1 -0
- package/{aws → dist/aws}/types/errors.d.ts +4 -0
- package/dist/aws/types/errors.js +16 -0
- package/dist/aws/types/errors.js.map +1 -0
- package/{aws → dist/aws}/types/lambda-response.d.ts +4 -3
- package/dist/aws/types/lambda-response.js +33 -0
- package/dist/aws/types/lambda-response.js.map +1 -0
- package/{aws → dist/aws}/types/mediatypes.d.ts +1 -1
- package/dist/aws/types/mediatypes.js +16 -0
- package/dist/aws/types/mediatypes.js.map +1 -0
- package/{aws → dist/aws}/types/model-with-reference.d.ts +0 -0
- package/dist/aws/types/model-with-reference.js +3 -0
- package/dist/aws/types/model-with-reference.js.map +1 -0
- package/{aws → dist/aws}/types/proxytypes.d.ts +0 -0
- package/dist/aws/types/proxytypes.js +3 -0
- package/dist/aws/types/proxytypes.js.map +1 -0
- package/{aws → dist/aws}/types/tags.d.ts +0 -0
- package/dist/aws/types/tags.js +7 -0
- package/dist/aws/types/tags.js.map +1 -0
- package/{database → dist/database}/cached.d.ts +0 -0
- package/dist/database/cached.js +32 -0
- package/dist/database/cached.js.map +1 -0
- package/{database → dist/database}/database.d.ts +0 -0
- package/dist/database/database.js +70 -0
- package/dist/database/database.js.map +1 -0
- package/{database → dist/database}/last-updated.d.ts +0 -0
- package/dist/database/last-updated.js +54 -0
- package/dist/database/last-updated.js.map +1 -0
- package/{database → dist/database}/models.d.ts +0 -0
- package/dist/database/models.js +3 -0
- package/dist/database/models.js.map +1 -0
- package/{marine → dist/marine}/id_utils.d.ts +0 -0
- package/dist/marine/id_utils.js +33 -0
- package/dist/marine/id_utils.js.map +1 -0
- package/{marine → dist/marine}/rtz.d.ts +0 -0
- package/dist/marine/rtz.js +3 -0
- package/dist/marine/rtz.js.map +1 -0
- package/{test → dist/test}/asserter.d.ts +0 -0
- package/dist/test/asserter.js +45 -0
- package/dist/test/asserter.js.map +1 -0
- package/{test → dist/test}/db-testutils.d.ts +0 -0
- package/dist/test/db-testutils.js +31 -0
- package/dist/test/db-testutils.js.map +1 -0
- package/{test → dist/test}/httpserver.d.ts +2 -1
- package/dist/test/httpserver.js +74 -0
- package/dist/test/httpserver.js.map +1 -0
- package/{test → dist/test}/secret.d.ts +0 -0
- package/dist/test/secret.js +25 -0
- package/dist/test/secret.js.map +1 -0
- package/{test → dist/test}/secrets-manager.d.ts +0 -0
- package/dist/test/secrets-manager.js +59 -0
- package/dist/test/secrets-manager.js.map +1 -0
- package/{test → dist/test}/testutils.d.ts +0 -0
- package/dist/test/testutils.js +44 -0
- package/dist/test/testutils.js.map +1 -0
- package/dist/types/either.d.ts +9 -0
- package/dist/types/either.js +3 -0
- package/dist/types/either.js.map +1 -0
- package/{types → dist/types}/input-error.d.ts +0 -0
- package/dist/types/input-error.js +7 -0
- package/dist/types/input-error.js.map +1 -0
- package/{types → dist/types}/language.d.ts +0 -0
- package/dist/types/language.js +10 -0
- package/dist/types/language.js.map +1 -0
- package/{types → dist/types}/traffictype.d.ts +0 -0
- package/dist/types/traffictype.js +13 -0
- package/dist/types/traffictype.js.map +1 -0
- package/{types → dist/types}/validator.d.ts +0 -0
- package/dist/types/validator.js +14 -0
- package/dist/types/validator.js.map +1 -0
- package/{utils → dist/utils}/api-model.d.ts +0 -0
- package/dist/utils/api-model.js +129 -0
- package/dist/utils/api-model.js.map +1 -0
- package/{utils → dist/utils}/base64.d.ts +0 -0
- package/dist/utils/base64.js +21 -0
- package/dist/utils/base64.js.map +1 -0
- package/{utils → dist/utils}/date-utils.d.ts +0 -0
- package/dist/utils/date-utils.js +34 -0
- package/dist/utils/date-utils.js.map +1 -0
- package/{utils → dist/utils}/geojson-types.d.ts +0 -0
- package/dist/utils/geojson-types.js +18 -0
- package/dist/utils/geojson-types.js.map +1 -0
- package/{utils → dist/utils}/geometry.d.ts +0 -0
- package/dist/utils/geometry.js +164 -0
- package/dist/utils/geometry.js.map +1 -0
- package/{utils → dist/utils}/retry.d.ts +0 -0
- package/dist/utils/retry.js +50 -0
- package/dist/utils/retry.js.map +1 -0
- package/{utils → dist/utils}/slack.d.ts +0 -0
- package/dist/utils/slack.js +25 -0
- package/dist/utils/slack.js.map +1 -0
- package/{utils → dist/utils}/utils.d.ts +16 -0
- package/dist/utils/utils.js +75 -0
- package/dist/utils/utils.js.map +1 -0
- package/package.json +12 -10
- package/src/@types/geojson-validation/index.d.ts +4 -0
- package/src/aws/infra/api/integration.ts +73 -0
- package/src/aws/infra/api/response.ts +67 -0
- package/src/aws/infra/api/responses.ts +124 -0
- package/src/aws/infra/api/static-integration.ts +62 -0
- package/src/aws/infra/canaries/canary-alarm.ts +31 -0
- package/src/aws/infra/canaries/canary-keys.ts +3 -0
- package/src/aws/infra/canaries/canary-parameters.ts +19 -0
- package/src/aws/infra/canaries/canary-role.ts +47 -0
- package/src/aws/infra/canaries/canary.ts +46 -0
- package/src/aws/infra/canaries/database-canary.ts +98 -0
- package/src/aws/infra/canaries/database-checker.ts +155 -0
- package/src/aws/infra/canaries/url-canary.ts +74 -0
- package/src/aws/infra/canaries/url-checker.ts +366 -0
- package/src/aws/infra/documentation.ts +124 -0
- package/src/aws/infra/scheduler.ts +59 -0
- package/src/aws/infra/security-rule.ts +38 -0
- package/src/aws/infra/sqs-integration.ts +102 -0
- package/src/aws/infra/sqs-queue.ts +148 -0
- package/src/aws/infra/stack/lambda-configs.ts +207 -0
- package/src/aws/infra/stack/monitoredfunction.ts +342 -0
- package/src/aws/infra/stack/rest_apis.ts +223 -0
- package/src/aws/infra/stack/stack-checking-aspect.ts +279 -0
- package/src/aws/infra/stack/stack.ts +145 -0
- package/src/aws/infra/stack/subscription.ts +58 -0
- package/src/aws/infra/usage-plans.ts +41 -0
- package/src/aws/runtime/apikey.ts +9 -0
- package/src/aws/runtime/digitraffic-integration-response.ts +28 -0
- package/src/aws/runtime/environment.ts +9 -0
- package/src/aws/runtime/messaging.ts +26 -0
- package/src/aws/runtime/s3.ts +44 -0
- package/src/aws/runtime/secrets/dbsecret.ts +116 -0
- package/src/aws/runtime/secrets/proxy-holder.ts +37 -0
- package/src/aws/runtime/secrets/rds-holder.ts +33 -0
- package/src/aws/runtime/secrets/secret-holder.ts +116 -0
- package/src/aws/runtime/secrets/secret.ts +50 -0
- package/src/aws/types/errors.ts +14 -0
- package/src/aws/types/lambda-response.ts +43 -0
- package/src/aws/types/mediatypes.ts +11 -0
- package/src/aws/types/model-with-reference.ts +8 -0
- package/src/aws/types/proxytypes.ts +27 -0
- package/src/aws/types/tags.ts +3 -0
- package/src/database/cached.ts +35 -0
- package/src/database/database.ts +96 -0
- package/src/database/last-updated.ts +59 -0
- package/src/database/models.ts +7 -0
- package/src/marine/id_utils.ts +30 -0
- package/src/marine/rtz.ts +57 -0
- package/src/test/asserter.ts +48 -0
- package/src/test/db-testutils.ts +44 -0
- package/src/test/httpserver.ts +96 -0
- package/src/test/secret.ts +23 -0
- package/src/test/secrets-manager.ts +34 -0
- package/src/test/testutils.ts +39 -0
- package/src/types/either.ts +3 -0
- package/src/types/input-error.ts +2 -0
- package/src/types/language.ts +3 -0
- package/src/types/traffictype.ts +8 -0
- package/src/types/validator.ts +10 -0
- package/src/utils/api-model.ts +133 -0
- package/src/utils/base64.ts +16 -0
- package/src/utils/date-utils.ts +30 -0
- package/src/utils/geojson-types.ts +22 -0
- package/src/utils/geometry.ts +164 -0
- package/src/utils/retry.ts +49 -0
- package/src/utils/slack.ts +22 -0
- package/src/utils/utils.ts +105 -0
- package/aws/infra/api/integration.js +0 -52
- package/aws/infra/api/response.js +0 -61
- package/aws/infra/api/responses.js +0 -79
- package/aws/infra/api/static-integration.js +0 -54
- package/aws/infra/canaries/canary-alarm.js +0 -26
- package/aws/infra/canaries/canary-parameters.js +0 -3
- package/aws/infra/canaries/canary-role.js +0 -46
- package/aws/infra/canaries/canary.js +0 -32
- package/aws/infra/canaries/database-canary.js +0 -55
- package/aws/infra/canaries/database-checker.js +0 -109
- package/aws/infra/canaries/url-canary.js +0 -46
- package/aws/infra/canaries/url-checker.js +0 -238
- package/aws/infra/documentation.js +0 -95
- package/aws/infra/scheduler.js +0 -31
- package/aws/infra/security-rule.js +0 -39
- package/aws/infra/sqs-integration.js +0 -93
- package/aws/infra/sqs-queue.js +0 -130
- package/aws/infra/stack/lambda-configs.js +0 -93
- package/aws/infra/stack/monitoredfunction.js +0 -135
- package/aws/infra/stack/rest_apis.js +0 -185
- package/aws/infra/stack/stack-checking-aspect.js +0 -174
- package/aws/infra/stack/stack.js +0 -60
- package/aws/infra/stack/subscription.js +0 -41
- package/aws/infra/usage-plans.js +0 -42
- package/aws/runtime/apikey.js +0 -13
- package/aws/runtime/digitraffic-integration-response.js +0 -26
- package/aws/runtime/environment.js +0 -12
- package/aws/runtime/messaging.js +0 -31
- package/aws/runtime/s3.js +0 -30
- package/aws/runtime/secrets/dbsecret.js +0 -96
- package/aws/runtime/secrets/proxy-holder.js +0 -26
- package/aws/runtime/secrets/rds-holder.js +0 -26
- package/aws/runtime/secrets/secret-holder.js +0 -73
- package/aws/runtime/secrets/secret.js +0 -43
- package/aws/types/errors.js +0 -9
- package/aws/types/lambda-response.js +0 -28
- package/aws/types/mediatypes.js +0 -15
- package/aws/types/model-with-reference.js +0 -3
- package/aws/types/proxytypes.js +0 -3
- package/aws/types/tags.js +0 -7
- package/database/cached.js +0 -32
- package/database/database.js +0 -62
- package/database/last-updated.js +0 -54
- package/database/models.js +0 -3
- package/index.d.ts +0 -1
- package/index.js +0 -18
- package/marine/id_utils.js +0 -33
- package/marine/rtz.js +0 -3
- package/test/asserter.js +0 -45
- package/test/db-testutils.js +0 -31
- package/test/httpserver.js +0 -67
- package/test/secret.js +0 -25
- package/test/secrets-manager.js +0 -59
- package/test/testutils.js +0 -44
- package/types/input-error.js +0 -7
- package/types/language.js +0 -10
- package/types/traffictype.js +0 -13
- package/types/validator.js +0 -14
- package/utils/api-model.js +0 -129
- package/utils/base64.js +0 -21
- package/utils/date-utils.js +0 -34
- package/utils/geojson-types.js +0 -18
- package/utils/geometry.js +0 -140
- package/utils/retry.js +0 -50
- package/utils/slack.js +0 -25
- package/utils/utils.js +0 -64
@@ -0,0 +1,116 @@
|
|
1
|
+
import {withSecret, withSecretAndPrefix} from "./secret";
|
2
|
+
|
3
|
+
export type DbSecret = {
|
4
|
+
readonly username: string
|
5
|
+
readonly password: string
|
6
|
+
readonly host: string
|
7
|
+
readonly ro_host: string
|
8
|
+
};
|
9
|
+
|
10
|
+
export enum RdsProxySecretKey {
|
11
|
+
username = "username", password = "password", proxy_host = "proxy_host", proxy_ro_host = "proxy_ro_host"
|
12
|
+
}
|
13
|
+
|
14
|
+
export enum RdsSecretKey {
|
15
|
+
username = "username", password = "password", host = "host", ro_host = "ro_host"
|
16
|
+
}
|
17
|
+
|
18
|
+
export type RdsProxySecret = Record<RdsProxySecretKey, string>;
|
19
|
+
export type RdsSecret = Record<RdsSecretKey, string>;
|
20
|
+
|
21
|
+
export enum DatabaseEnvironmentKeys {
|
22
|
+
DB_USER = "DB_USER",
|
23
|
+
DB_PASS = "DB_PASS",
|
24
|
+
DB_URI = "DB_URI",
|
25
|
+
DB_RO_URI = "DB_RO_URI",
|
26
|
+
DB_APPLICATION = "DB_APPLICATION",
|
27
|
+
}
|
28
|
+
|
29
|
+
function setDbSecret(secret: DbSecret) {
|
30
|
+
process.env[DatabaseEnvironmentKeys.DB_USER] = secret.username;
|
31
|
+
process.env[DatabaseEnvironmentKeys.DB_PASS] = secret.password;
|
32
|
+
process.env[DatabaseEnvironmentKeys.DB_URI] = secret.host;
|
33
|
+
process.env[DatabaseEnvironmentKeys.DB_RO_URI] = secret.ro_host;
|
34
|
+
}
|
35
|
+
|
36
|
+
// cached at Lambda container level
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
38
|
+
let cachedSecret: any;
|
39
|
+
|
40
|
+
const missingSecretErrorText = 'Missing or empty secretId';
|
41
|
+
|
42
|
+
/**
|
43
|
+
* You can give the following options for retrieving a secret:
|
44
|
+
*
|
45
|
+
* expectedKeys: the list of keys the secret must include. If not, an error will be thrown.
|
46
|
+
* prefix: a prefix that's included in retrieved secret's keys. Only keys begining with the prefix will be included.
|
47
|
+
* The secret that is passed to the given function will not include the prefix in it's keys.
|
48
|
+
|
49
|
+
*/
|
50
|
+
export type SecretOptions = {
|
51
|
+
readonly expectedKeys?: string[],
|
52
|
+
readonly prefix?: string
|
53
|
+
}
|
54
|
+
|
55
|
+
export type SecretToPromiseFunction<Secret, Response = void> = (secret: Secret) => Promise<Response> | void;
|
56
|
+
export type SecretFunction<Secret, Response = void> = (secretId: string, fn: SecretToPromiseFunction<Secret, Response>, options?: SecretOptions) => Promise<Response | void>;
|
57
|
+
export type EmptySecretFunction<Response = void> = SecretFunction<DbSecret, Response>;
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Run the given function with secret retrieved from Secrets Manager. Also injects database-credentials into environment.
|
61
|
+
*
|
62
|
+
* @deprecated use SecretHolder & ProxyHolder
|
63
|
+
* @see SecretOptions
|
64
|
+
*
|
65
|
+
* @param {string} secretId
|
66
|
+
* @param {function} fn
|
67
|
+
* @param {SecretOptions} options
|
68
|
+
*/
|
69
|
+
export async function withDbSecret<Secret, Response>(secretId: string, fn: SecretToPromiseFunction<Secret, Response>, options?: SecretOptions): Promise<Response | void> {
|
70
|
+
if (!secretId) {
|
71
|
+
console.error(missingSecretErrorText);
|
72
|
+
return Promise.reject(missingSecretErrorText);
|
73
|
+
}
|
74
|
+
|
75
|
+
if (!cachedSecret) {
|
76
|
+
// if prefix is given, first set db values and then fetch secret
|
77
|
+
if (options?.prefix) {
|
78
|
+
// first set db values
|
79
|
+
await withSecret(secretId, (fetchedSecret: DbSecret) => {
|
80
|
+
setDbSecret(fetchedSecret);
|
81
|
+
});
|
82
|
+
|
83
|
+
// then actual secret
|
84
|
+
await withSecretAndPrefix(secretId, options.prefix, (fetchedSecret: Secret) => {
|
85
|
+
cachedSecret = fetchedSecret;
|
86
|
+
});
|
87
|
+
} else {
|
88
|
+
await withSecret(secretId, (fetchedSecret: DbSecret) => {
|
89
|
+
setDbSecret(fetchedSecret);
|
90
|
+
cachedSecret = fetchedSecret;
|
91
|
+
});
|
92
|
+
}
|
93
|
+
}
|
94
|
+
try {
|
95
|
+
if (options?.expectedKeys?.length) {
|
96
|
+
checkExpectedSecretKeys(options.expectedKeys, cachedSecret);
|
97
|
+
}
|
98
|
+
return fn(cachedSecret);
|
99
|
+
} catch (error) {
|
100
|
+
console.error('method=withDbSecret Caught an error, refreshing secret', error);
|
101
|
+
// try to refetch secret in case it has changed
|
102
|
+
await withSecret(secretId, (fetchedSecret: DbSecret) => {
|
103
|
+
setDbSecret(fetchedSecret);
|
104
|
+
cachedSecret = fetchedSecret;
|
105
|
+
});
|
106
|
+
return fn(cachedSecret);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
export function checkExpectedSecretKeys<Secret>(keys: string[], secret: Secret) {
|
111
|
+
const missingKeys = keys.filter(key => !(key in secret));
|
112
|
+
if (missingKeys.length) {
|
113
|
+
console.error(`method=checkExpectedSecretKeys secret didn't contain the key(s) ${missingKeys}`);
|
114
|
+
throw new Error('Expected keys were not found');
|
115
|
+
}
|
116
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { SecretHolder } from "./secret-holder";
|
2
|
+
import {
|
3
|
+
DatabaseEnvironmentKeys,
|
4
|
+
RdsProxySecretKey,
|
5
|
+
RdsProxySecret,
|
6
|
+
} from "./dbsecret";
|
7
|
+
import { getEnvVariable } from "../../../utils/utils";
|
8
|
+
|
9
|
+
const RDS_PROXY_SECRET_KEYS = Object.values(RdsProxySecretKey);
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Holds credentials for RDS Proxy access.
|
13
|
+
*/
|
14
|
+
export class ProxyHolder {
|
15
|
+
private readonly secretHolder;
|
16
|
+
|
17
|
+
constructor(secretId: string) {
|
18
|
+
this.secretHolder = new SecretHolder<RdsProxySecret>(
|
19
|
+
secretId,
|
20
|
+
"",
|
21
|
+
RDS_PROXY_SECRET_KEYS
|
22
|
+
);
|
23
|
+
}
|
24
|
+
|
25
|
+
static create() {
|
26
|
+
return new ProxyHolder(getEnvVariable("SECRET_ID"));
|
27
|
+
}
|
28
|
+
|
29
|
+
public async setCredentials() {
|
30
|
+
const secret = await this.secretHolder.get();
|
31
|
+
|
32
|
+
process.env[DatabaseEnvironmentKeys.DB_USER] = secret.username;
|
33
|
+
process.env[DatabaseEnvironmentKeys.DB_PASS] = secret.password;
|
34
|
+
process.env[DatabaseEnvironmentKeys.DB_URI] = secret.proxy_host;
|
35
|
+
process.env[DatabaseEnvironmentKeys.DB_RO_URI] = secret.proxy_ro_host;
|
36
|
+
}
|
37
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import { SecretHolder } from "./secret-holder";
|
2
|
+
import { DatabaseEnvironmentKeys, RdsSecret, RdsSecretKey } from "./dbsecret";
|
3
|
+
import { getEnvVariable } from "../../../utils/utils";
|
4
|
+
|
5
|
+
const RDS_SECRET_KEYS = Object.values(RdsSecretKey);
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Holds credentials for RDS access.
|
9
|
+
*/
|
10
|
+
export class RdsHolder {
|
11
|
+
private readonly secretHolder;
|
12
|
+
|
13
|
+
constructor(secretId: string) {
|
14
|
+
this.secretHolder = new SecretHolder<RdsSecret>(
|
15
|
+
secretId,
|
16
|
+
"",
|
17
|
+
RDS_SECRET_KEYS
|
18
|
+
);
|
19
|
+
}
|
20
|
+
|
21
|
+
static create() {
|
22
|
+
return new RdsHolder(getEnvVariable("SECRET_ID"));
|
23
|
+
}
|
24
|
+
|
25
|
+
public async setCredentials() {
|
26
|
+
const secret = await this.secretHolder.get();
|
27
|
+
|
28
|
+
process.env[DatabaseEnvironmentKeys.DB_USER] = secret.username;
|
29
|
+
process.env[DatabaseEnvironmentKeys.DB_PASS] = secret.password;
|
30
|
+
process.env[DatabaseEnvironmentKeys.DB_URI] = secret.host;
|
31
|
+
process.env[DatabaseEnvironmentKeys.DB_RO_URI] = secret.ro_host;
|
32
|
+
}
|
33
|
+
}
|
@@ -0,0 +1,116 @@
|
|
1
|
+
import { GenericSecret, getSecret } from "./secret";
|
2
|
+
import {
|
3
|
+
checkExpectedSecretKeys,
|
4
|
+
DatabaseEnvironmentKeys,
|
5
|
+
DbSecret,
|
6
|
+
} from "./dbsecret";
|
7
|
+
import { getEnvVariable } from "../../../utils/utils";
|
8
|
+
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
10
|
+
const NodeTtl = require("node-ttl");
|
11
|
+
|
12
|
+
const DEFAULT_PREFIX = "";
|
13
|
+
const DEFAULT_SECRET_KEY = "SECRET";
|
14
|
+
const DEFAULT_CONFIGURATION = {
|
15
|
+
ttl: 5 * 60, // timeout secrets in 5 minutes
|
16
|
+
};
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Utility class for getting secrets from Secret Manager.
|
20
|
+
* Supports prefix for secrets, checking of expected keys and ttl-configuration.
|
21
|
+
*
|
22
|
+
* By default, secrets are cached for 5 minutes and then reread from the Secrets Manager(This can be overridden with configuration).
|
23
|
+
*
|
24
|
+
* Supports setting the database environment paramaters from the secret too.
|
25
|
+
*/
|
26
|
+
export class SecretHolder<Secret> {
|
27
|
+
private readonly secretId: string;
|
28
|
+
private readonly prefix: string;
|
29
|
+
private readonly expectedKeys: string[];
|
30
|
+
|
31
|
+
private readonly secretCache;
|
32
|
+
|
33
|
+
constructor(
|
34
|
+
secretId: string,
|
35
|
+
prefix = "",
|
36
|
+
expectedKeys: string[] = [],
|
37
|
+
configuration = DEFAULT_CONFIGURATION
|
38
|
+
) {
|
39
|
+
this.secretId = secretId;
|
40
|
+
this.prefix = prefix;
|
41
|
+
this.expectedKeys = expectedKeys;
|
42
|
+
|
43
|
+
this.secretCache = new NodeTtl(configuration);
|
44
|
+
}
|
45
|
+
|
46
|
+
private async initSecret() {
|
47
|
+
const secretValue = await getSecret<Secret>(this.secretId);
|
48
|
+
|
49
|
+
console.info("refreshing secret " + this.secretId);
|
50
|
+
|
51
|
+
this.secretCache.push(DEFAULT_SECRET_KEY, secretValue);
|
52
|
+
}
|
53
|
+
|
54
|
+
public static create<S>(
|
55
|
+
prefix = DEFAULT_PREFIX,
|
56
|
+
expectedKeys: string[] = []
|
57
|
+
) {
|
58
|
+
return new SecretHolder<S>(
|
59
|
+
getEnvVariable("SECRET_ID"),
|
60
|
+
prefix,
|
61
|
+
expectedKeys
|
62
|
+
);
|
63
|
+
}
|
64
|
+
|
65
|
+
public async get(): Promise<Secret> {
|
66
|
+
const secret = await this.getSecret<Secret>();
|
67
|
+
const parsedSecret =
|
68
|
+
this.prefix === DEFAULT_PREFIX
|
69
|
+
? secret
|
70
|
+
: this.parseSecret(
|
71
|
+
secret as unknown as GenericSecret,
|
72
|
+
`${this.prefix}.`
|
73
|
+
);
|
74
|
+
|
75
|
+
if (this.expectedKeys.length > 0) {
|
76
|
+
checkExpectedSecretKeys(this.expectedKeys, parsedSecret);
|
77
|
+
}
|
78
|
+
|
79
|
+
return parsedSecret;
|
80
|
+
}
|
81
|
+
|
82
|
+
private parseSecret(secret: GenericSecret, prefix: string): Secret {
|
83
|
+
const parsed: GenericSecret = {};
|
84
|
+
const skip = prefix.length;
|
85
|
+
|
86
|
+
for (const key in secret) {
|
87
|
+
if (key.startsWith(prefix)) {
|
88
|
+
parsed[key.substring(skip)] = secret[key];
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
return parsed as unknown as Secret;
|
93
|
+
}
|
94
|
+
|
95
|
+
private async getSecret<S>(): Promise<S> {
|
96
|
+
const secret = this.secretCache.get(DEFAULT_SECRET_KEY);
|
97
|
+
|
98
|
+
if (!secret) {
|
99
|
+
await this.initSecret();
|
100
|
+
}
|
101
|
+
|
102
|
+
return secret || this.secretCache.get(DEFAULT_SECRET_KEY);
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* @deprecated Use ProxyHolder
|
107
|
+
*/
|
108
|
+
public async setDatabaseCredentials() {
|
109
|
+
const secret = await this.getSecret<DbSecret>();
|
110
|
+
|
111
|
+
process.env[DatabaseEnvironmentKeys.DB_USER] = secret.username;
|
112
|
+
process.env[DatabaseEnvironmentKeys.DB_PASS] = secret.password;
|
113
|
+
process.env[DatabaseEnvironmentKeys.DB_URI] = secret.host;
|
114
|
+
process.env[DatabaseEnvironmentKeys.DB_RO_URI] = secret.ro_host;
|
115
|
+
}
|
116
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import {SecretsManager} from 'aws-sdk';
|
2
|
+
import {SecretToPromiseFunction} from "./dbsecret";
|
3
|
+
|
4
|
+
const smClient = new SecretsManager({
|
5
|
+
region: process.env.AWS_REGION,
|
6
|
+
});
|
7
|
+
|
8
|
+
export type GenericSecret = Record<string, string>;
|
9
|
+
|
10
|
+
/**
|
11
|
+
@deprecated use SecretHolder & ProxyHolder
|
12
|
+
*/
|
13
|
+
export async function withSecret<Secret, Response>(secretId: string, fn: SecretToPromiseFunction<Secret, Response>): Promise<Response | void> {
|
14
|
+
return fn(await getSecret(secretId));
|
15
|
+
}
|
16
|
+
|
17
|
+
export async function getSecret<Secret>(secretId: string, prefix = ''): Promise<Secret> {
|
18
|
+
const secretObj = await smClient.getSecretValue({
|
19
|
+
SecretId: secretId,
|
20
|
+
}).promise();
|
21
|
+
|
22
|
+
if (!secretObj.SecretString) {
|
23
|
+
throw new Error('No secret found!');
|
24
|
+
}
|
25
|
+
|
26
|
+
const secret = JSON.parse(secretObj.SecretString);
|
27
|
+
|
28
|
+
if (prefix === '') {
|
29
|
+
return secret;
|
30
|
+
}
|
31
|
+
|
32
|
+
return parseSecret(secret, `${prefix}.`);
|
33
|
+
}
|
34
|
+
|
35
|
+
function parseSecret<Secret>(secret: GenericSecret, prefix: string): Secret {
|
36
|
+
const parsed: GenericSecret = {};
|
37
|
+
const skip = prefix.length;
|
38
|
+
|
39
|
+
for (const key in secret) {
|
40
|
+
if (key.startsWith(prefix)) {
|
41
|
+
parsed[key.substring(skip)] = secret[key];
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
return parsed as unknown as Secret;
|
46
|
+
}
|
47
|
+
|
48
|
+
export async function withSecretAndPrefix<Secret, Response>(secretId: string, prefix: string, fn: SecretToPromiseFunction<Secret, Response>): Promise<Response | void> {
|
49
|
+
return fn(await getSecret(secretId, prefix));
|
50
|
+
}
|
@@ -0,0 +1,14 @@
|
|
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
|
+
|
7
|
+
export class ValidationError extends Error {
|
8
|
+
statusCode: number;
|
9
|
+
|
10
|
+
constructor(statusCode: number, body: string) {
|
11
|
+
super(body);
|
12
|
+
this.statusCode = statusCode;
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
export class LambdaResponse<T> {
|
2
|
+
readonly status: number;
|
3
|
+
readonly body: T;
|
4
|
+
readonly fileName?: string;
|
5
|
+
|
6
|
+
constructor(status: number, body: T, fileName?: string) {
|
7
|
+
this.status = status;
|
8
|
+
this.body = body;
|
9
|
+
this.fileName = fileName;
|
10
|
+
}
|
11
|
+
|
12
|
+
static ok<T>(body: T, fileName?: string) {
|
13
|
+
return this.create(200, body, fileName);
|
14
|
+
}
|
15
|
+
|
16
|
+
static okJson<T>(json: T, fileName?: string) {
|
17
|
+
return this.create(200, JSON.stringify(json, null, 2), fileName);
|
18
|
+
}
|
19
|
+
|
20
|
+
static badRequest(body: string) {
|
21
|
+
return this.create(400, body);
|
22
|
+
}
|
23
|
+
|
24
|
+
static notFound() {
|
25
|
+
return this.create(404, "Not found");
|
26
|
+
}
|
27
|
+
|
28
|
+
static internalError() {
|
29
|
+
return this.create(500, "Internal error");
|
30
|
+
}
|
31
|
+
|
32
|
+
static notImplemented() {
|
33
|
+
return this.create(501, "Not implemented");
|
34
|
+
}
|
35
|
+
|
36
|
+
static create<T>(
|
37
|
+
status: number,
|
38
|
+
body: T,
|
39
|
+
fileName?: string
|
40
|
+
): Promise<LambdaResponse<T>> {
|
41
|
+
return Promise.resolve(new LambdaResponse(status, body, fileName));
|
42
|
+
}
|
43
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
// charset=UTF-8 is deprecated but mobile applications sometimes needs it
|
2
|
+
export enum MediaType {
|
3
|
+
APPLICATION_JSON = "application/json;charset=UTF-8",
|
4
|
+
APPLICATION_XML = "application/xml",
|
5
|
+
APPLICATION_GEOJSON = "application/geo+json;charset=UTF-8",
|
6
|
+
IMAGE_SVG = "image/svg+xml",
|
7
|
+
IMAGE_JPEG = "image/jpeg",
|
8
|
+
TEXT_PLAIN = "text/plain",
|
9
|
+
TEXT_HTML = "text/html",
|
10
|
+
TEXT_CSV = "text/csv",
|
11
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
/**
|
2
|
+
* https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format
|
3
|
+
*
|
4
|
+
* Not fully described, extend if necessary.
|
5
|
+
*/
|
6
|
+
export type ProxyLambdaResponse = {
|
7
|
+
readonly statusCode: number
|
8
|
+
readonly body: string
|
9
|
+
readonly headers?: Record<string, string>
|
10
|
+
readonly multiValueHeaders?: Record<string, string[]>
|
11
|
+
}
|
12
|
+
|
13
|
+
/**
|
14
|
+
* https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
|
15
|
+
*
|
16
|
+
* Not fully described, extend if necessary.
|
17
|
+
*/
|
18
|
+
export type ProxyLambdaRequest = {
|
19
|
+
readonly resource: string
|
20
|
+
readonly path: string
|
21
|
+
readonly httpMethod: string
|
22
|
+
readonly headers: Record<string, string>
|
23
|
+
readonly multiValueHeaders: Record<string, string[]>
|
24
|
+
readonly queryStringParameters: Record<string, string>
|
25
|
+
readonly multiValueQueryStringParameters: Record<string, string[]>
|
26
|
+
readonly body?: string
|
27
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import {PreparedStatement} from "pg-promise";
|
2
|
+
import {DTDatabase, DTTransaction} from "./database";
|
3
|
+
|
4
|
+
const SQL_UPDATE_CACHE_VALUE =
|
5
|
+
`insert into cached_json(cache_id, content, last_updated)
|
6
|
+
values ($1, $2, now())
|
7
|
+
on conflict(cache_id) do
|
8
|
+
update set content = $2, last_updated = now()`;
|
9
|
+
|
10
|
+
const SQL_GET_CACHE_VALUE =
|
11
|
+
`select content, last_updated from cached_json
|
12
|
+
where cache_id = $1`;
|
13
|
+
|
14
|
+
const PS_UPDATE_CACHE_VALUE = new PreparedStatement({
|
15
|
+
name: 'update-cache-value',
|
16
|
+
text: SQL_UPDATE_CACHE_VALUE,
|
17
|
+
});
|
18
|
+
|
19
|
+
const PS_GET_CACHE_VALUE = new PreparedStatement({
|
20
|
+
name: 'get-cache-value',
|
21
|
+
text: SQL_GET_CACHE_VALUE,
|
22
|
+
});
|
23
|
+
|
24
|
+
export enum JSON_CACHE_KEY {
|
25
|
+
NAUTICAL_WARNINGS_ACTIVE = 'nautical-warnings-active',
|
26
|
+
NAUTICAL_WARNINGS_ARCHIVED = 'nautical-warnings-archived'
|
27
|
+
}
|
28
|
+
|
29
|
+
export function updateCachedJson<T>(db: DTDatabase | DTTransaction, cacheKey: JSON_CACHE_KEY, value: T): Promise<null> {
|
30
|
+
return db.none(PS_UPDATE_CACHE_VALUE, [cacheKey, value]);
|
31
|
+
}
|
32
|
+
|
33
|
+
export function getJsonFromCache<T>(db: DTDatabase | DTTransaction, cacheKey: JSON_CACHE_KEY): Promise<T | null> {
|
34
|
+
return db.oneOrNone(PS_GET_CACHE_VALUE, [cacheKey]).then(value => value?.content ?? null);
|
35
|
+
}
|
@@ -0,0 +1,96 @@
|
|
1
|
+
import { IDatabase, ITask } from "pg-promise";
|
2
|
+
import { DatabaseEnvironmentKeys } from "../aws/runtime/secrets/dbsecret";
|
3
|
+
import { getEnvVariable, getEnvVariableSafe } from "../utils/utils";
|
4
|
+
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
6
|
+
const pgp = require("pg-promise")();
|
7
|
+
|
8
|
+
// convert numeric types to number instead of string
|
9
|
+
pgp.pg.types.setTypeParser(pgp.pg.types.builtins.INT8, (value: string) => {
|
10
|
+
return parseInt(value);
|
11
|
+
});
|
12
|
+
|
13
|
+
pgp.pg.types.setTypeParser(pgp.pg.types.builtins.FLOAT8, (value: string) => {
|
14
|
+
return parseFloat(value);
|
15
|
+
});
|
16
|
+
|
17
|
+
pgp.pg.types.setTypeParser(pgp.pg.types.builtins.NUMERIC, (value: string) => {
|
18
|
+
return parseFloat(value);
|
19
|
+
});
|
20
|
+
|
21
|
+
export type DTDatabase = IDatabase<unknown>;
|
22
|
+
|
23
|
+
export type DTTransaction = ITask<unknown>;
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Creates a non-pooling database connection primarily used by Lambdas.
|
27
|
+
*
|
28
|
+
* Note! Using this method opens a new RDS connection on every invocation. It is advised to
|
29
|
+
* use RDS proxy to pool connections transparently.
|
30
|
+
* https://docs.amazonaws.cn/en_us/AmazonRDS/latest/AuroraUserGuide/rds-proxy.html
|
31
|
+
* @param username Username
|
32
|
+
* @param password Password
|
33
|
+
* @param applicationName name of application
|
34
|
+
* @param url Connection URL
|
35
|
+
* @param options pg-promise options
|
36
|
+
*/
|
37
|
+
export function initDbConnection(
|
38
|
+
username: string,
|
39
|
+
password: string,
|
40
|
+
applicationName: string,
|
41
|
+
url: string,
|
42
|
+
options?: object
|
43
|
+
): DTDatabase {
|
44
|
+
const finalUrl = `postgresql://${username}:${password}@${url}?application_name=${applicationName}`;
|
45
|
+
|
46
|
+
return pgp(finalUrl, options);
|
47
|
+
}
|
48
|
+
|
49
|
+
export function inTransaction<T>(
|
50
|
+
fn: (db: DTTransaction) => Promise<T>
|
51
|
+
): Promise<T> {
|
52
|
+
return inDatabase((db) => db.tx((t: DTTransaction) => fn(t)));
|
53
|
+
}
|
54
|
+
|
55
|
+
export function inDatabase<T>(fn: (db: DTDatabase) => Promise<T>): Promise<T> {
|
56
|
+
return doInDatabase(false, fn);
|
57
|
+
}
|
58
|
+
|
59
|
+
export function inDatabaseReadonly<T>(
|
60
|
+
fn: (db: DTDatabase) => Promise<T>
|
61
|
+
): Promise<T> {
|
62
|
+
return doInDatabase(true, fn);
|
63
|
+
}
|
64
|
+
|
65
|
+
async function doInDatabase<T>(
|
66
|
+
readonly: boolean,
|
67
|
+
fn: (db: DTDatabase) => Promise<T>
|
68
|
+
): Promise<T> {
|
69
|
+
const db_application = getEnvVariableSafe(
|
70
|
+
DatabaseEnvironmentKeys.DB_APPLICATION
|
71
|
+
);
|
72
|
+
const db_ro_uri = getEnvVariableSafe(DatabaseEnvironmentKeys.DB_RO_URI);
|
73
|
+
const db_uri =
|
74
|
+
db_ro_uri.result === "ok"
|
75
|
+
? db_ro_uri.value
|
76
|
+
: getEnvVariable(DatabaseEnvironmentKeys.DB_URI);
|
77
|
+
const db = initDbConnection(
|
78
|
+
getEnvVariable(DatabaseEnvironmentKeys.DB_USER),
|
79
|
+
getEnvVariable(DatabaseEnvironmentKeys.DB_PASS),
|
80
|
+
db_application.result === "ok"
|
81
|
+
? db_application.value
|
82
|
+
: "unknown-cdk-application",
|
83
|
+
db_uri
|
84
|
+
);
|
85
|
+
try {
|
86
|
+
// deallocate all prepared statements to allow for connection pooling
|
87
|
+
// DISCARD instead of DEALLOCATE as it didn't always clean all prepared statements
|
88
|
+
await db.none("DISCARD ALL");
|
89
|
+
return await fn(db);
|
90
|
+
} catch (e) {
|
91
|
+
console.error("Error in db:", e);
|
92
|
+
throw e;
|
93
|
+
} finally {
|
94
|
+
db.$pool.end();
|
95
|
+
}
|
96
|
+
}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import {DTDatabase, DTTransaction} from "./database";
|
2
|
+
|
3
|
+
export enum DataType {
|
4
|
+
VS_DATEX2="VS_DATEX2",
|
5
|
+
COUNTING_SITES_DATA="COUNTING_SITES_DATA",
|
6
|
+
COUNTING_SITES_METADATA="COUNTING_SITES_METADATA",
|
7
|
+
COUNTING_SITES_METADATA_CHECK="COUNTING_SITES_METADATA_CHECK",
|
8
|
+
MAINTENANCE_TRACKING_DATA_CHECKED="MAINTENANCE_TRACKING_DATA_CHECKED",
|
9
|
+
PERMIT_DATA="PERMIT_DATA",
|
10
|
+
PERMIT_DATA_CHECK="PERMIT_DATA_CHECK",
|
11
|
+
}
|
12
|
+
|
13
|
+
const UNSET_SUBTYPE = '-';
|
14
|
+
|
15
|
+
type UpdatedTimestamp = {
|
16
|
+
updated: Date
|
17
|
+
} | null;
|
18
|
+
|
19
|
+
export function getLastUpdated(db: DTDatabase, datatype: DataType): Promise<Date | null> {
|
20
|
+
return db.oneOrNone("select updated from data_updated where data_type=$(datatype) and subtype=$(subtype)", {
|
21
|
+
datatype: datatype, subtype: UNSET_SUBTYPE,
|
22
|
+
}, (x: UpdatedTimestamp) => x?.updated || null);
|
23
|
+
}
|
24
|
+
|
25
|
+
export function getLastUpdatedWithSubtype(db: DTDatabase, datatype: DataType, subtype: string): Promise<Date | null> {
|
26
|
+
return db.oneOrNone("SELECT updated FROM data_updated WHERE data_type=$(datatype) AND subtype=$(subtype)", {
|
27
|
+
datatype: datatype, subtype: subtype,
|
28
|
+
}, (x: UpdatedTimestamp) => x?.updated || null);
|
29
|
+
}
|
30
|
+
|
31
|
+
export function updateLastUpdated(db: DTDatabase | DTTransaction, datatype: DataType, updated: Date): Promise<null> {
|
32
|
+
return db.none(`insert into data_updated(id, data_type, updated)
|
33
|
+
values(nextval('seq_data_updated'), $(datatype), $(updated))
|
34
|
+
on conflict (data_type, subtype)
|
35
|
+
do update set updated = $(updated)`,
|
36
|
+
{ updated, datatype });
|
37
|
+
}
|
38
|
+
|
39
|
+
export function updateLastUpdatedWithSubtype(db: DTDatabase | DTTransaction, datatype: DataType, subtype: string, updated: Date): Promise<null> {
|
40
|
+
return db.none(`insert into data_updated(id, data_type, subtype, updated)
|
41
|
+
values(nextval('seq_data_updated'), $(datatype), $(subtype), $(updated))
|
42
|
+
on conflict (data_type, subtype)
|
43
|
+
do update set updated = $(updated)`,
|
44
|
+
{ updated, subtype, datatype });
|
45
|
+
}
|
46
|
+
|
47
|
+
export function getUpdatedTimestamp(db: DTDatabase, datatype: string): Promise<Date | null> {
|
48
|
+
return db.oneOrNone("select updated_time as updated from updated_timestamp where updated_name=$(datatype)", {
|
49
|
+
datatype: datatype,
|
50
|
+
}, (x: UpdatedTimestamp) => x?.updated || null);
|
51
|
+
}
|
52
|
+
|
53
|
+
export function updateUpdatedTimestamp(db: DTDatabase | DTTransaction, datatype: string, date: Date, by = ''): Promise<null> {
|
54
|
+
return db.none(`insert into updated_timestamp(updated_name, updated_time, updated_by)
|
55
|
+
values($(datatype), $(date), $(by))
|
56
|
+
on conflict (updated_name)
|
57
|
+
do update set updated_time = $(date), updated_by = $(by)`,
|
58
|
+
{ date, datatype, by });
|
59
|
+
}
|