@digitraffic/common 2023.4.4-1 → 2023.5.9-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/response.d.ts +2 -1
- package/dist/aws/infra/api/response.js +6 -2
- package/dist/aws/infra/stacks/db-stack.d.ts +0 -2
- package/dist/aws/infra/stacks/db-stack.js +4 -2
- package/dist/aws/infra/stacks/network-stack.js +3 -1
- package/dist/aws/types/lambda-response.d.ts +5 -1
- package/dist/aws/types/lambda-response.js +16 -12
- package/dist/types/nullable.d.ts +5 -4
- package/dist/types/util-types.d.ts +1 -0
- package/dist/types/util-types.js +3 -0
- package/package.json +33 -32
- package/src/aws/infra/api/response.ts +6 -2
- package/src/aws/infra/stacks/db-stack.ts +12 -11
- package/src/aws/infra/stacks/network-stack.ts +3 -1
- package/src/aws/types/lambda-response.ts +38 -22
- package/src/types/nullable.ts +6 -4
- package/src/types/util-types.ts +1 -0
@@ -10,8 +10,9 @@ import { IModel } from "aws-cdk-lib/aws-apigateway/lib/model";
|
|
10
10
|
* non-textual content.
|
11
11
|
*
|
12
12
|
* If fileName is set, then Content-Disposition-header will be set to use it
|
13
|
+
* If timestamp is set, then ETag & Last-Modified headers will be set
|
13
14
|
*/
|
14
|
-
export declare const RESPONSE_DEFAULT_LAMBDA = "#set($inputRoot = $input.path('$'))\n
|
15
|
+
export declare const RESPONSE_DEFAULT_LAMBDA = "#set($inputRoot = $input.path('$'))\n#if ($inputRoot.status != 200)\n#set ($context.responseOverride.status = $inputRoot.status)\n#set ($context.responseOverride.header.Content-Type = 'text/plain')\n#end\n#set ($context.responseOverride.header.Access-Control-Allow-Origin = '*')\n#if (\"$!inputRoot.timestamp\" != \"\")\n#set ($context.responseOverride.header.ETag = $inputRoot.timestamp)\n#set ($context.responseOverride.header.Last-Modified = $inputRoot.timestamp)\n#end\n#if (\"$!inputRoot.fileName\" != \"\")\n#set ($disposition = 'attachment; filename=\"FN\"')\n#set ($context.responseOverride.header.Content-Disposition = $disposition.replaceAll('FN', $inputRoot.fileName))\n#end\n$util.base64Decode($inputRoot.body)";
|
15
16
|
/**
|
16
17
|
* Use this for deprecated integrations.
|
17
18
|
* Will add HTTP headers Deprecation and Sunset to response.
|
@@ -13,19 +13,23 @@ const date_utils_1 = require("../../../utils/date-utils");
|
|
13
13
|
* non-textual content.
|
14
14
|
*
|
15
15
|
* If fileName is set, then Content-Disposition-header will be set to use it
|
16
|
+
* If timestamp is set, then ETag & Last-Modified headers will be set
|
16
17
|
*/
|
17
18
|
exports.RESPONSE_DEFAULT_LAMBDA = `#set($inputRoot = $input.path('$'))
|
18
|
-
$util.base64Decode($inputRoot.body)
|
19
19
|
#if ($inputRoot.status != 200)
|
20
20
|
#set ($context.responseOverride.status = $inputRoot.status)
|
21
21
|
#set ($context.responseOverride.header.Content-Type = 'text/plain')
|
22
22
|
#end
|
23
23
|
#set ($context.responseOverride.header.Access-Control-Allow-Origin = '*')
|
24
|
+
#if ("$!inputRoot.timestamp" != "")
|
25
|
+
#set ($context.responseOverride.header.ETag = $inputRoot.timestamp)
|
26
|
+
#set ($context.responseOverride.header.Last-Modified = $inputRoot.timestamp)
|
27
|
+
#end
|
24
28
|
#if ("$!inputRoot.fileName" != "")
|
25
29
|
#set ($disposition = 'attachment; filename="FN"')
|
26
30
|
#set ($context.responseOverride.header.Content-Disposition = $disposition.replaceAll('FN', $inputRoot.fileName))
|
27
31
|
#end
|
28
|
-
`;
|
32
|
+
$util.base64Decode($inputRoot.body)`;
|
29
33
|
/**
|
30
34
|
* Use this for deprecated integrations.
|
31
35
|
* Will add HTTP headers Deprecation and Sunset to response.
|
@@ -12,8 +12,6 @@ export interface DbConfiguration {
|
|
12
12
|
readonly instances: number;
|
13
13
|
readonly customParameterGroup: boolean;
|
14
14
|
readonly securityGroupId: string;
|
15
|
-
readonly superuserName: string;
|
16
|
-
readonly superuserPassword: string;
|
17
15
|
readonly proxy: {
|
18
16
|
readonly name?: string;
|
19
17
|
readonly securityGroupId: string;
|
@@ -4,6 +4,7 @@ exports.DbStack = void 0;
|
|
4
4
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
5
5
|
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
|
6
6
|
const aws_rds_1 = require("aws-cdk-lib/aws-rds");
|
7
|
+
const aws_secretsmanager_1 = require("aws-cdk-lib/aws-secretsmanager");
|
7
8
|
const import_util_1 = require("../import-util");
|
8
9
|
/**
|
9
10
|
* Stack that creates DatabaseCluster.
|
@@ -43,6 +44,7 @@ class DbStack extends aws_cdk_lib_1.Stack {
|
|
43
44
|
: aws_rds_1.ParameterGroup.fromParameterGroupName(this, "ParameterGroup", `default.aurora-postgresql${configuration.dbVersion.auroraPostgresMajorVersion}`);
|
44
45
|
}
|
45
46
|
createClusterParameters(configuration, instanceName, vpc, securityGroup, parameterGroup) {
|
47
|
+
const secret = aws_secretsmanager_1.Secret.fromSecretCompleteArn(this, "DBSecret", configuration.secretArn);
|
46
48
|
return {
|
47
49
|
engine: aws_rds_1.DatabaseClusterEngine.auroraPostgres({
|
48
50
|
version: configuration.dbVersion,
|
@@ -71,7 +73,7 @@ class DbStack extends aws_cdk_lib_1.Stack {
|
|
71
73
|
instanceType: configuration.dbInstanceType,
|
72
74
|
parameterGroup,
|
73
75
|
},
|
74
|
-
credentials: aws_rds_1.Credentials.fromPassword(
|
76
|
+
credentials: aws_rds_1.Credentials.fromPassword(secret.secretValueFromJson("db.superuser").unsafeUnwrap(), secret.secretValueFromJson("db.superuser.password")),
|
75
77
|
parameterGroup,
|
76
78
|
};
|
77
79
|
}
|
@@ -93,7 +95,7 @@ class DbStack extends aws_cdk_lib_1.Stack {
|
|
93
95
|
throw new Error("Couldn't pull CfnDBInstances from the L1 constructs!");
|
94
96
|
}
|
95
97
|
cfnInstances.forEach((cfnInstance) => delete cfnInstance.engineVersion);
|
96
|
-
cluster.node.addDependency(parameterGroup
|
98
|
+
cluster.node.addDependency(parameterGroup);
|
97
99
|
return cluster;
|
98
100
|
}
|
99
101
|
}
|
@@ -19,7 +19,9 @@ class NetworkStack extends aws_cdk_lib_1.Stack {
|
|
19
19
|
createVpc(configuration) {
|
20
20
|
return new aws_ec2_1.Vpc(this, "DigitrafficVPC", {
|
21
21
|
vpcName: configuration.vpcName,
|
22
|
-
availabilityZones:
|
22
|
+
availabilityZones: aws_cdk_lib_1.Stack.of(this)
|
23
|
+
.availabilityZones.sort()
|
24
|
+
.slice(0, 2),
|
23
25
|
enableDnsHostnames: true,
|
24
26
|
enableDnsSupport: true,
|
25
27
|
ipAddresses: aws_ec2_1.IpAddresses.cidr(configuration.cidr),
|
@@ -2,7 +2,9 @@ export declare class LambdaResponse {
|
|
2
2
|
readonly status: number;
|
3
3
|
readonly body: string;
|
4
4
|
readonly fileName?: string;
|
5
|
-
|
5
|
+
readonly timestamp?: string;
|
6
|
+
constructor(status: number, body: string, fileName?: string, timestamp?: Date);
|
7
|
+
withTimestamp(timestamp: Date): LambdaResponse;
|
6
8
|
/**
|
7
9
|
* Create LambdaResponse for HTTP 200 from json.
|
8
10
|
*/
|
@@ -31,4 +33,6 @@ export declare class LambdaResponse {
|
|
31
33
|
* Create LambdaResponse for HTTP 501
|
32
34
|
*/
|
33
35
|
static notImplemented(): LambdaResponse;
|
36
|
+
private static createForString;
|
37
|
+
private static createForBase64;
|
34
38
|
}
|
@@ -2,10 +2,14 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.LambdaResponse = void 0;
|
4
4
|
class LambdaResponse {
|
5
|
-
constructor(status, body, fileName) {
|
5
|
+
constructor(status, body, fileName, timestamp) {
|
6
6
|
this.status = status;
|
7
7
|
this.body = body;
|
8
8
|
this.fileName = fileName;
|
9
|
+
this.timestamp = timestamp?.toUTCString();
|
10
|
+
}
|
11
|
+
withTimestamp(timestamp) {
|
12
|
+
return new LambdaResponse(this.status, this.body, this.fileName, timestamp);
|
9
13
|
}
|
10
14
|
/**
|
11
15
|
* Create LambdaResponse for HTTP 200 from json.
|
@@ -23,41 +27,41 @@ class LambdaResponse {
|
|
23
27
|
* Create LambdaResponse for HTTP 200 from base64-encoded data.
|
24
28
|
*/
|
25
29
|
static okBinary(base64, fileName) {
|
26
|
-
return createForBase64(200, base64, fileName);
|
30
|
+
return this.createForBase64(200, base64, fileName);
|
27
31
|
}
|
28
32
|
/**
|
29
33
|
* Create LambdaResponse for HTTP 400
|
30
34
|
*/
|
31
35
|
static badRequest(body) {
|
32
|
-
return createForString(400, body);
|
36
|
+
return this.createForString(400, body);
|
33
37
|
}
|
34
38
|
/**
|
35
39
|
* Create LambdaResponse for HTTP 404
|
36
40
|
*/
|
37
41
|
static notFound() {
|
38
|
-
return createForString(404, "Not found");
|
42
|
+
return this.createForString(404, "Not found");
|
39
43
|
}
|
40
44
|
/**
|
41
45
|
* Create LambdaResponse for HTTP 500
|
42
46
|
*/
|
43
47
|
static internalError() {
|
44
|
-
return createForString(500, "Internal error");
|
48
|
+
return this.createForString(500, "Internal error");
|
45
49
|
}
|
46
50
|
/**
|
47
51
|
* Create LambdaResponse for HTTP 501
|
48
52
|
*/
|
49
53
|
static notImplemented() {
|
50
|
-
return createForString(501, "Not implemented");
|
54
|
+
return this.createForString(501, "Not implemented");
|
55
|
+
}
|
56
|
+
static createForString(status, body, fileName) {
|
57
|
+
return this.createForBase64(status, toBase64(body), fileName);
|
58
|
+
}
|
59
|
+
static createForBase64(status, base64Body, fileName) {
|
60
|
+
return new LambdaResponse(status, base64Body, fileName);
|
51
61
|
}
|
52
62
|
}
|
53
63
|
exports.LambdaResponse = LambdaResponse;
|
54
64
|
function toBase64(body) {
|
55
65
|
return Buffer.from(body).toString("base64");
|
56
66
|
}
|
57
|
-
function createForString(status, body, fileName) {
|
58
|
-
return createForBase64(status, toBase64(body), fileName);
|
59
|
-
}
|
60
|
-
function createForBase64(status, base64Body, fileName) {
|
61
|
-
return new LambdaResponse(status, base64Body, fileName);
|
62
|
-
}
|
63
67
|
//# sourceMappingURL=lambda-response.js.map
|
package/dist/types/nullable.d.ts
CHANGED
@@ -1,19 +1,20 @@
|
|
1
|
+
import { ValueOf } from "./util-types";
|
1
2
|
/**
|
2
3
|
* Adds `null` as an accepted type to all properties in given type.
|
3
4
|
*/
|
4
5
|
export type Nullable<Obj> = {
|
5
6
|
[Key in keyof Obj]: Obj[Key] | null;
|
6
7
|
};
|
7
|
-
type RequiredKeys<Obj> = {
|
8
|
+
type RequiredKeys<Obj> = ValueOf<{
|
8
9
|
[Key in keyof Obj]-?: object extends {
|
9
10
|
[K in Key]: Obj[Key];
|
10
11
|
} ? never : Key;
|
11
|
-
}
|
12
|
-
type OptionalKeys<Obj> = {
|
12
|
+
}>;
|
13
|
+
type OptionalKeys<Obj> = ValueOf<{
|
13
14
|
[Key in keyof Obj]-?: object extends {
|
14
15
|
[K in Key]: Obj[Key];
|
15
16
|
} ? Key : never;
|
16
|
-
}
|
17
|
+
}>;
|
17
18
|
type RequiredProperties<Obj> = Pick<Obj, RequiredKeys<Obj>>;
|
18
19
|
type OptionalProperties<Obj> = Pick<Obj, OptionalKeys<Obj>>;
|
19
20
|
/**
|
@@ -0,0 +1 @@
|
|
1
|
+
export type ValueOf<Obj> = Obj[keyof Obj];
|
package/package.json
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
{
|
2
2
|
"name": "@digitraffic/common",
|
3
|
-
"version": "2023.
|
3
|
+
"version": "2023.5.9-1",
|
4
4
|
"description": "",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
7
7
|
"url": "https://github.com/tmfg/digitraffic-common.git"
|
8
8
|
},
|
9
9
|
"engines": {
|
10
|
-
"node": ">=14 <17"
|
10
|
+
"node": ">=14 <17 || >=18 <19"
|
11
11
|
},
|
12
12
|
"license": "EUPL-1.2",
|
13
13
|
"private": false,
|
@@ -17,53 +17,54 @@
|
|
17
17
|
"src/**/*.ts"
|
18
18
|
],
|
19
19
|
"peerDependencies": {
|
20
|
-
"@aws-cdk/aws-synthetics-alpha": "2.
|
20
|
+
"@aws-cdk/aws-synthetics-alpha": "^2.78.0-alpha.0",
|
21
21
|
"@types/geojson": "^7946.0.10",
|
22
|
-
"aws-cdk-lib": "2.
|
23
|
-
"aws-sdk": "^2.
|
24
|
-
"axios": "^1.
|
22
|
+
"aws-cdk-lib": "^2.78.0",
|
23
|
+
"aws-sdk": "^2.1374.0",
|
24
|
+
"axios": "^1.2.6",
|
25
25
|
"change-case": "^4.1.2",
|
26
|
-
"constructs": "^10.
|
26
|
+
"constructs": "^10.2.17",
|
27
27
|
"geojson-validation": "^1.0.2",
|
28
28
|
"moment": "^2.29.4",
|
29
29
|
"node-ttl": "^0.2.0",
|
30
30
|
"pg-native": "^3.0.1",
|
31
|
-
"pg-promise": "^
|
31
|
+
"pg-promise": "^11.0.0"
|
32
32
|
},
|
33
33
|
"devDependencies": {
|
34
|
-
"@aws-cdk/aws-synthetics-alpha": "2.
|
35
|
-
"@types/aws-lambda": "
|
34
|
+
"@aws-cdk/aws-synthetics-alpha": "2.78.0-alpha.0",
|
35
|
+
"@types/aws-lambda": "~8.10.115",
|
36
36
|
"@types/geojson": "^7946.0.10",
|
37
|
-
"@types/jest": "^29.5.
|
38
|
-
"@types/lodash": "^4.14.
|
39
|
-
"@types/node": "
|
40
|
-
"@types/ramda": "
|
41
|
-
"@types/sinon": "
|
42
|
-
"@typescript-eslint/eslint-plugin": "~5.
|
43
|
-
"@typescript-eslint/parser": "^5.
|
44
|
-
"aws-cdk-lib": "
|
45
|
-
"aws-sdk": "
|
46
|
-
"axios": "^1.3.
|
37
|
+
"@types/jest": "^29.5.1",
|
38
|
+
"@types/lodash": "^4.14.194",
|
39
|
+
"@types/node": "18.15.13",
|
40
|
+
"@types/ramda": "~0.29.1",
|
41
|
+
"@types/sinon": "10.0.14",
|
42
|
+
"@typescript-eslint/eslint-plugin": "~5.59.5",
|
43
|
+
"@typescript-eslint/parser": "^5.59.5",
|
44
|
+
"aws-cdk-lib": "~2.78.0",
|
45
|
+
"aws-sdk": "~2.1374.0",
|
46
|
+
"axios": "^1.3.6",
|
47
47
|
"change-case": "^4.1.2",
|
48
|
-
"constructs": "
|
49
|
-
"eslint": "~8.
|
48
|
+
"constructs": "10.2.17",
|
49
|
+
"eslint": "~8.40.0",
|
50
50
|
"eslint-config-prettier": "^8.8.0",
|
51
|
-
"eslint-plugin-deprecation": "~1.
|
51
|
+
"eslint-plugin-deprecation": "~1.4.1",
|
52
52
|
"geojson-validation": "^1.0.2",
|
53
53
|
"husky": "^8.0.3",
|
54
54
|
"jest": "^29.5.0",
|
55
|
-
"jest-junit": "^
|
56
|
-
"lint-staged": "^13.2.
|
55
|
+
"jest-junit": "^16.0.0",
|
56
|
+
"lint-staged": "^13.2.2",
|
57
57
|
"moment": "^2.29.4",
|
58
58
|
"node-ttl": "^0.2.0",
|
59
59
|
"pg-native": "^3.0.1",
|
60
|
-
"pg-promise": "^
|
61
|
-
"prettier": "^2.8.
|
62
|
-
"ramda": "
|
63
|
-
"rimraf": "^
|
64
|
-
"sinon": "
|
65
|
-
"ts-jest": "^29.0
|
66
|
-
"typescript": "~4.9.5"
|
60
|
+
"pg-promise": "^11.4.3",
|
61
|
+
"prettier": "^2.8.8",
|
62
|
+
"ramda": "~0.29.0",
|
63
|
+
"rimraf": "^5.0.0",
|
64
|
+
"sinon": "15.0.4",
|
65
|
+
"ts-jest": "^29.1.0",
|
66
|
+
"typescript": "~4.9.5",
|
67
|
+
"velocityjs": "2.0.6"
|
67
68
|
},
|
68
69
|
"externals": [
|
69
70
|
"aws-sdk",
|
@@ -18,19 +18,23 @@ import { dateFromIsoString } from "../../../utils/date-utils";
|
|
18
18
|
* non-textual content.
|
19
19
|
*
|
20
20
|
* If fileName is set, then Content-Disposition-header will be set to use it
|
21
|
+
* If timestamp is set, then ETag & Last-Modified headers will be set
|
21
22
|
*/
|
22
23
|
export const RESPONSE_DEFAULT_LAMBDA = `#set($inputRoot = $input.path('$'))
|
23
|
-
$util.base64Decode($inputRoot.body)
|
24
24
|
#if ($inputRoot.status != 200)
|
25
25
|
#set ($context.responseOverride.status = $inputRoot.status)
|
26
26
|
#set ($context.responseOverride.header.Content-Type = 'text/plain')
|
27
27
|
#end
|
28
28
|
#set ($context.responseOverride.header.Access-Control-Allow-Origin = '*')
|
29
|
+
#if ("$!inputRoot.timestamp" != "")
|
30
|
+
#set ($context.responseOverride.header.ETag = $inputRoot.timestamp)
|
31
|
+
#set ($context.responseOverride.header.Last-Modified = $inputRoot.timestamp)
|
32
|
+
#end
|
29
33
|
#if ("$!inputRoot.fileName" != "")
|
30
34
|
#set ($disposition = 'attachment; filename="FN"')
|
31
35
|
#set ($context.responseOverride.header.Content-Disposition = $disposition.replaceAll('FN', $inputRoot.fileName))
|
32
36
|
#end
|
33
|
-
`;
|
37
|
+
$util.base64Decode($inputRoot.body)`;
|
34
38
|
|
35
39
|
/**
|
36
40
|
* Use this for deprecated integrations.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Duration, RemovalPolicy,
|
1
|
+
import { Duration, RemovalPolicy, Stack } from "aws-cdk-lib";
|
2
2
|
import {
|
3
3
|
InstanceType,
|
4
4
|
IVpc,
|
@@ -19,8 +19,9 @@ import {
|
|
19
19
|
ParameterGroup,
|
20
20
|
} from "aws-cdk-lib/aws-rds";
|
21
21
|
import { Construct } from "constructs";
|
22
|
-
import {
|
22
|
+
import { Secret } from "aws-cdk-lib/aws-secretsmanager";
|
23
23
|
import { InfraStackConfiguration } from "./intra-stack-configuration";
|
24
|
+
import { exportValue, importVpc } from "../import-util";
|
24
25
|
|
25
26
|
export interface DbConfiguration {
|
26
27
|
readonly secretArn: string;
|
@@ -32,9 +33,6 @@ export interface DbConfiguration {
|
|
32
33
|
readonly customParameterGroup: boolean;
|
33
34
|
readonly securityGroupId: string;
|
34
35
|
|
35
|
-
readonly superuserName: string;
|
36
|
-
readonly superuserPassword: string;
|
37
|
-
|
38
36
|
readonly proxy: {
|
39
37
|
readonly name?: string;
|
40
38
|
readonly securityGroupId: string;
|
@@ -126,6 +124,12 @@ export class DbStack extends Stack {
|
|
126
124
|
securityGroup: ISecurityGroup,
|
127
125
|
parameterGroup: IParameterGroup
|
128
126
|
): DatabaseClusterProps {
|
127
|
+
const secret = Secret.fromSecretCompleteArn(
|
128
|
+
this,
|
129
|
+
"DBSecret",
|
130
|
+
configuration.secretArn
|
131
|
+
);
|
132
|
+
|
129
133
|
return {
|
130
134
|
engine: DatabaseClusterEngine.auroraPostgres({
|
131
135
|
version: configuration.dbVersion,
|
@@ -155,8 +159,8 @@ export class DbStack extends Stack {
|
|
155
159
|
parameterGroup,
|
156
160
|
},
|
157
161
|
credentials: Credentials.fromPassword(
|
158
|
-
|
159
|
-
|
162
|
+
secret.secretValueFromJson("db.superuser").unsafeUnwrap(),
|
163
|
+
secret.secretValueFromJson("db.superuser.password")
|
160
164
|
),
|
161
165
|
parameterGroup,
|
162
166
|
};
|
@@ -200,10 +204,7 @@ export class DbStack extends Stack {
|
|
200
204
|
}
|
201
205
|
cfnInstances.forEach((cfnInstance) => delete cfnInstance.engineVersion);
|
202
206
|
|
203
|
-
cluster.node.addDependency(
|
204
|
-
parameterGroup,
|
205
|
-
"Create ParameterGroup before DatabaseCluster"
|
206
|
-
);
|
207
|
+
cluster.node.addDependency(parameterGroup);
|
207
208
|
|
208
209
|
return cluster;
|
209
210
|
}
|
@@ -53,7 +53,9 @@ export class NetworkStack extends Stack {
|
|
53
53
|
createVpc(configuration: NetworkConfiguration): Vpc {
|
54
54
|
return new Vpc(this, "DigitrafficVPC", {
|
55
55
|
vpcName: configuration.vpcName,
|
56
|
-
availabilityZones:
|
56
|
+
availabilityZones: Stack.of(this)
|
57
|
+
.availabilityZones.sort()
|
58
|
+
.slice(0, 2), // take two first azs
|
57
59
|
enableDnsHostnames: true,
|
58
60
|
enableDnsSupport: true,
|
59
61
|
ipAddresses: IpAddresses.cidr(configuration.cidr),
|
@@ -2,11 +2,27 @@ export class LambdaResponse {
|
|
2
2
|
readonly status: number;
|
3
3
|
readonly body: string;
|
4
4
|
readonly fileName?: string;
|
5
|
+
readonly timestamp?: string;
|
5
6
|
|
6
|
-
constructor(
|
7
|
+
constructor(
|
8
|
+
status: number,
|
9
|
+
body: string,
|
10
|
+
fileName?: string,
|
11
|
+
timestamp?: Date
|
12
|
+
) {
|
7
13
|
this.status = status;
|
8
14
|
this.body = body;
|
9
15
|
this.fileName = fileName;
|
16
|
+
this.timestamp = timestamp?.toUTCString();
|
17
|
+
}
|
18
|
+
|
19
|
+
withTimestamp(timestamp: Date) {
|
20
|
+
return new LambdaResponse(
|
21
|
+
this.status,
|
22
|
+
this.body,
|
23
|
+
this.fileName,
|
24
|
+
timestamp
|
25
|
+
);
|
10
26
|
}
|
11
27
|
|
12
28
|
/**
|
@@ -27,54 +43,54 @@ export class LambdaResponse {
|
|
27
43
|
* Create LambdaResponse for HTTP 200 from base64-encoded data.
|
28
44
|
*/
|
29
45
|
static okBinary(base64: string, fileName?: string) {
|
30
|
-
return createForBase64(200, base64, fileName);
|
46
|
+
return this.createForBase64(200, base64, fileName);
|
31
47
|
}
|
32
48
|
|
33
49
|
/**
|
34
50
|
* Create LambdaResponse for HTTP 400
|
35
51
|
*/
|
36
52
|
static badRequest(body: string) {
|
37
|
-
return createForString(400, body);
|
53
|
+
return this.createForString(400, body);
|
38
54
|
}
|
39
55
|
|
40
56
|
/**
|
41
57
|
* Create LambdaResponse for HTTP 404
|
42
58
|
*/
|
43
59
|
static notFound() {
|
44
|
-
return createForString(404, "Not found");
|
60
|
+
return this.createForString(404, "Not found");
|
45
61
|
}
|
46
62
|
|
47
63
|
/**
|
48
64
|
* Create LambdaResponse for HTTP 500
|
49
65
|
*/
|
50
66
|
static internalError() {
|
51
|
-
return createForString(500, "Internal error");
|
67
|
+
return this.createForString(500, "Internal error");
|
52
68
|
}
|
53
69
|
|
54
70
|
/**
|
55
71
|
* Create LambdaResponse for HTTP 501
|
56
72
|
*/
|
57
73
|
static notImplemented() {
|
58
|
-
return createForString(501, "Not implemented");
|
74
|
+
return this.createForString(501, "Not implemented");
|
59
75
|
}
|
60
|
-
}
|
61
76
|
|
62
|
-
|
63
|
-
|
64
|
-
|
77
|
+
private static createForString(
|
78
|
+
status: number,
|
79
|
+
body: string,
|
80
|
+
fileName?: string
|
81
|
+
): LambdaResponse {
|
82
|
+
return this.createForBase64(status, toBase64(body), fileName);
|
83
|
+
}
|
65
84
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
): LambdaResponse {
|
71
|
-
|
85
|
+
private static createForBase64(
|
86
|
+
status: number,
|
87
|
+
base64Body: string,
|
88
|
+
fileName?: string
|
89
|
+
): LambdaResponse {
|
90
|
+
return new LambdaResponse(status, base64Body, fileName);
|
91
|
+
}
|
72
92
|
}
|
73
93
|
|
74
|
-
function
|
75
|
-
|
76
|
-
base64Body: string,
|
77
|
-
fileName?: string
|
78
|
-
): LambdaResponse {
|
79
|
-
return new LambdaResponse(status, base64Body, fileName);
|
94
|
+
function toBase64(body: string) {
|
95
|
+
return Buffer.from(body).toString("base64");
|
80
96
|
}
|
package/src/types/nullable.ts
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
+
import { ValueOf } from "./util-types";
|
2
|
+
|
1
3
|
/**
|
2
4
|
* Adds `null` as an accepted type to all properties in given type.
|
3
5
|
*/
|
4
6
|
export type Nullable<Obj> = { [Key in keyof Obj]: Obj[Key] | null };
|
5
7
|
|
6
|
-
type RequiredKeys<Obj> = {
|
8
|
+
type RequiredKeys<Obj> = ValueOf<{
|
7
9
|
[Key in keyof Obj]-?: object extends { [K in Key]: Obj[Key] } ? never : Key;
|
8
|
-
}
|
9
|
-
type OptionalKeys<Obj> = {
|
10
|
+
}>;
|
11
|
+
type OptionalKeys<Obj> = ValueOf<{
|
10
12
|
[Key in keyof Obj]-?: object extends { [K in Key]: Obj[Key] } ? Key : never;
|
11
|
-
}
|
13
|
+
}>;
|
12
14
|
type RequiredProperties<Obj> = Pick<Obj, RequiredKeys<Obj>>;
|
13
15
|
type OptionalProperties<Obj> = Pick<Obj, OptionalKeys<Obj>>;
|
14
16
|
|
@@ -0,0 +1 @@
|
|
1
|
+
export type ValueOf<Obj> = Obj[keyof Obj];
|