@digitraffic/common 2024.3.14-1 → 2024.3.22-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/dist/__test__/api/static-integration.test.d.mts +1 -0
- package/dist/__test__/api/static-integration.test.mjs +26 -0
- package/dist/aws/infra/api/static-integration.d.mts +13 -4
- package/dist/aws/infra/api/static-integration.mjs +32 -28
- package/dist/aws/infra/stack/rest_apis.d.mts +3 -1
- package/dist/aws/infra/stack/rest_apis.mjs +16 -27
- package/dist/utils/utils.d.mts +6 -0
- package/dist/utils/utils.mjs +18 -0
- package/package.json +4 -4
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { DigitrafficStaticIntegration } from "../../aws/infra/api/static-integration.mjs";
|
2
|
+
import { MediaType } from "../../aws/types/mediatypes.mjs";
|
3
|
+
describe("response tests", () => {
|
4
|
+
it("createIntegrationResponse works", () => {
|
5
|
+
const integrationResponse = DigitrafficStaticIntegration.createIntegrationResponse("FakeResource", MediaType.APPLICATION_JSON, { "test-header": "test-value" });
|
6
|
+
expect(integrationResponse).toEqual({
|
7
|
+
responseParameters: {
|
8
|
+
"method.response.header.test-header": "'test-value'"
|
9
|
+
},
|
10
|
+
responseTemplates: {
|
11
|
+
"application/json": "FakeResource"
|
12
|
+
},
|
13
|
+
statusCode: "200"
|
14
|
+
});
|
15
|
+
});
|
16
|
+
it("createMethodResponse works", () => {
|
17
|
+
const methodResponse = DigitrafficStaticIntegration.createMethodResponse({ "test-header": "test-value" });
|
18
|
+
expect(methodResponse).toEqual({
|
19
|
+
responseParameters: {
|
20
|
+
"method.response.header.test-header": true
|
21
|
+
},
|
22
|
+
statusCode: "200"
|
23
|
+
});
|
24
|
+
});
|
25
|
+
});
|
26
|
+
//# sourceMappingURL=static-integration.test.mjs.map
|
@@ -8,8 +8,17 @@ import { MediaType } from "../../types/mediatypes.mjs";
|
|
8
8
|
* @param response
|
9
9
|
*/
|
10
10
|
export declare class DigitrafficStaticIntegration extends MockIntegration {
|
11
|
-
constructor(resource: Resource, mediaType: MediaType, response: string, enableCors?: boolean, apiKeyRequired?: boolean);
|
12
|
-
static json<K>(resource: Resource, response: K, enableCors?: boolean, apiKeyRequired?: boolean): DigitrafficStaticIntegration;
|
13
|
-
|
14
|
-
|
11
|
+
constructor(resource: Resource, mediaType: MediaType, response: string, enableCors?: boolean, apiKeyRequired?: boolean, headers?: Record<string, string>);
|
12
|
+
static json<K>(resource: Resource, response: K, enableCors?: boolean, apiKeyRequired?: boolean, headers?: Record<string, string>): DigitrafficStaticIntegration;
|
13
|
+
static createIntegrationResponse(response: string, mediaType: MediaType, headers?: Record<string, string>): {
|
14
|
+
statusCode: string;
|
15
|
+
responseTemplates: {
|
16
|
+
[x: string]: string;
|
17
|
+
};
|
18
|
+
responseParameters: Record<string, string>;
|
19
|
+
};
|
20
|
+
static createMethodResponse(headers: Record<string, string>): {
|
21
|
+
statusCode: string;
|
22
|
+
responseParameters: Record<string, boolean>;
|
23
|
+
};
|
15
24
|
}
|
@@ -1,12 +1,8 @@
|
|
1
|
-
import { MockIntegration, PassthroughBehavior, Resource
|
1
|
+
import { MockIntegration, PassthroughBehavior, Resource } from "aws-cdk-lib/aws-apigateway";
|
2
2
|
import { MediaType } from "../../types/mediatypes.mjs";
|
3
|
-
import { RESPONSE_CORS_INTEGRATION } from "./responses.mjs";
|
4
3
|
const INTEGRATION_RESPONSE_200 = `{
|
5
4
|
"statusCode": 200
|
6
5
|
}`;
|
7
|
-
const METHOD_RESPONSE_200 = {
|
8
|
-
statusCode: "200",
|
9
|
-
};
|
10
6
|
/**
|
11
7
|
* Static integration, that returns the given response with given mediaType from given resource.
|
12
8
|
*
|
@@ -15,8 +11,11 @@ const METHOD_RESPONSE_200 = {
|
|
15
11
|
* @param response
|
16
12
|
*/
|
17
13
|
export class DigitrafficStaticIntegration extends MockIntegration {
|
18
|
-
constructor(resource, mediaType, response, enableCors = true, apiKeyRequired = true) {
|
19
|
-
|
14
|
+
constructor(resource, mediaType, response, enableCors = true, apiKeyRequired = true, headers = {}) {
|
15
|
+
if (enableCors) {
|
16
|
+
headers = { ...headers, "Access-Control-Allow-Origin": "*" };
|
17
|
+
}
|
18
|
+
const integrationResponse = DigitrafficStaticIntegration.createIntegrationResponse(response, mediaType, headers);
|
20
19
|
super({
|
21
20
|
passthroughBehavior: PassthroughBehavior.WHEN_NO_TEMPLATES,
|
22
21
|
requestTemplates: {
|
@@ -28,39 +27,44 @@ export class DigitrafficStaticIntegration extends MockIntegration {
|
|
28
27
|
resource.addMethod(httpMethod, this, {
|
29
28
|
apiKeyRequired,
|
30
29
|
methodResponses: [
|
31
|
-
DigitrafficStaticIntegration.createMethodResponse(
|
30
|
+
DigitrafficStaticIntegration.createMethodResponse(headers),
|
32
31
|
],
|
33
32
|
});
|
34
33
|
});
|
35
34
|
}
|
36
|
-
static json(resource, response, enableCors = true, apiKeyRequired = true) {
|
37
|
-
return new DigitrafficStaticIntegration(resource, MediaType.APPLICATION_JSON, JSON.stringify(response), enableCors, apiKeyRequired);
|
35
|
+
static json(resource, response, enableCors = true, apiKeyRequired = true, headers = {}) {
|
36
|
+
return new DigitrafficStaticIntegration(resource, MediaType.APPLICATION_JSON, JSON.stringify(response), enableCors, apiKeyRequired, headers);
|
38
37
|
}
|
39
|
-
static createIntegrationResponse(response, mediaType,
|
40
|
-
const
|
38
|
+
static createIntegrationResponse(response, mediaType, headers = {}) {
|
39
|
+
const params = mapRecord(headers, (entry) => ["method.response.header." + entry[0], `'${entry[1]}'`]);
|
40
|
+
return {
|
41
41
|
statusCode: "200",
|
42
42
|
responseTemplates: {
|
43
43
|
[mediaType]: response,
|
44
44
|
},
|
45
|
+
responseParameters: params
|
45
46
|
};
|
46
|
-
return enableCors
|
47
|
-
? { ...integrationResponse, ...RESPONSE_CORS_INTEGRATION }
|
48
|
-
: integrationResponse;
|
49
47
|
}
|
50
|
-
static createMethodResponse(
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
static createMethodResponse(headers) {
|
49
|
+
const allowedHeaders = Object.keys(headers);
|
50
|
+
const entries = Object.fromEntries(allowedHeaders.map((key) => [key, true]));
|
51
|
+
return {
|
52
|
+
statusCode: "200",
|
53
|
+
responseParameters: prefixKeys("method.response.header.", entries)
|
54
|
+
};
|
54
55
|
}
|
55
56
|
}
|
56
|
-
function
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
57
|
+
function mapRecord(obj, func) {
|
58
|
+
const mappedEntries = Object.entries(obj).map((entry) => func(entry));
|
59
|
+
return Object.fromEntries(mappedEntries);
|
60
|
+
}
|
61
|
+
/**
|
62
|
+
* Create a new Record with prefix added to each of the keys.
|
63
|
+
*
|
64
|
+
* @param prefix
|
65
|
+
* @param obj
|
66
|
+
*/
|
67
|
+
function prefixKeys(prefix, obj) {
|
68
|
+
return mapRecord(obj, (entry) => [prefix + entry[0], entry[1]]);
|
65
69
|
}
|
66
70
|
//# sourceMappingURL=static-integration.mjs.map
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { type IResource, type JsonSchema, Resource, RestApi, type RestApiProps } from "aws-cdk-lib/aws-apigateway";
|
1
|
+
import { type IResource, type JsonSchema, Resource, type ResourceOptions, RestApi, type RestApiProps } from "aws-cdk-lib/aws-apigateway";
|
2
2
|
import { PolicyDocument } from "aws-cdk-lib/aws-iam";
|
3
3
|
import { Construct } from "constructs";
|
4
4
|
import type { ModelWithReference } from "../../types/model-with-reference.mjs";
|
@@ -16,6 +16,7 @@ export declare class DigitrafficRestApi extends RestApi {
|
|
16
16
|
private getModelWithReference;
|
17
17
|
private addDocumentationPart;
|
18
18
|
documentResource(resource: Resource, ...documentationPart: DocumentationPart[]): void;
|
19
|
+
addResourceWithCorsOptionsSubTree(resource: Resource, pathPart: string, config?: ResourceOptions): Resource;
|
19
20
|
/**
|
20
21
|
* Add support for HTTP OPTIONS to an API GW resource,
|
21
22
|
* this is required for preflight CORS requests made by browsers.
|
@@ -45,3 +46,4 @@ export declare function setReturnCodeForMissingAuthenticationToken(returnCode: n
|
|
45
46
|
export declare function createRestApi(stack: Construct, apiId: string, apiName: string, allowFromIpAddresses?: string[] | undefined): RestApi;
|
46
47
|
export declare function createDefaultPolicyDocument(): PolicyDocument;
|
47
48
|
export declare function createIpRestrictionPolicyDocument(allowFromIpAddresses: string[]): PolicyDocument;
|
49
|
+
export declare const PUBLIC_REST_API_CORS_CONFIG: Partial<ResourceOptions>;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { CfnDocumentationPart, EndpointType, GatewayResponse, MethodLoggingLevel,
|
1
|
+
import { CfnDocumentationPart, Cors, EndpointType, GatewayResponse, MethodLoggingLevel, Model, Resource, ResponseType, RestApi, } from "aws-cdk-lib/aws-apigateway";
|
2
2
|
import { AnyPrincipal, Effect, PolicyDocument, PolicyStatement, } from "aws-cdk-lib/aws-iam";
|
3
3
|
import { Construct } from "constructs";
|
4
4
|
import { getModelReference } from "../../../utils/api-model.mjs";
|
@@ -82,38 +82,20 @@ export class DigitrafficRestApi extends RestApi {
|
|
82
82
|
console.info("Skipping documentation for %s", resource.path);
|
83
83
|
}
|
84
84
|
}
|
85
|
+
addResourceWithCorsOptionsSubTree(resource, pathPart, config) {
|
86
|
+
const mergedConfig = {
|
87
|
+
...PUBLIC_REST_API_CORS_CONFIG,
|
88
|
+
...config
|
89
|
+
};
|
90
|
+
return resource.addResource(pathPart, mergedConfig);
|
91
|
+
}
|
85
92
|
/**
|
86
93
|
* Add support for HTTP OPTIONS to an API GW resource,
|
87
94
|
* this is required for preflight CORS requests made by browsers.
|
88
95
|
* @param apiResource
|
89
96
|
*/
|
90
97
|
addCorsOptions(apiResource) {
|
91
|
-
apiResource.
|
92
|
-
integrationResponses: [
|
93
|
-
{
|
94
|
-
statusCode: "200",
|
95
|
-
responseParameters: {
|
96
|
-
"method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Digitraffic-User'",
|
97
|
-
"method.response.header.Access-Control-Allow-Origin": "'*'",
|
98
|
-
"method.response.header.Access-Control-Allow-Methods": "'OPTIONS,GET,HEAD'",
|
99
|
-
},
|
100
|
-
},
|
101
|
-
],
|
102
|
-
requestTemplates: {
|
103
|
-
"application/json": '{"statusCode": 200}',
|
104
|
-
},
|
105
|
-
}), {
|
106
|
-
methodResponses: [
|
107
|
-
{
|
108
|
-
statusCode: "200",
|
109
|
-
responseParameters: {
|
110
|
-
"method.response.header.Access-Control-Allow-Headers": true,
|
111
|
-
"method.response.header.Access-Control-Allow-Methods": true,
|
112
|
-
"method.response.header.Access-Control-Allow-Origin": true,
|
113
|
-
},
|
114
|
-
},
|
115
|
-
],
|
116
|
-
});
|
98
|
+
apiResource.addCorsPreflight(PUBLIC_REST_API_CORS_CONFIG.defaultCorsPreflightOptions);
|
117
99
|
}
|
118
100
|
}
|
119
101
|
/**
|
@@ -206,4 +188,11 @@ export function createIpRestrictionPolicyDocument(allowFromIpAddresses) {
|
|
206
188
|
],
|
207
189
|
});
|
208
190
|
}
|
191
|
+
export const PUBLIC_REST_API_CORS_CONFIG = {
|
192
|
+
defaultCorsPreflightOptions: {
|
193
|
+
allowOrigins: Cors.ALL_ORIGINS,
|
194
|
+
allowHeaders: ["Content-Type", "X-Amz-Date", "Authorization", "X-Api-Key", "X-Amz-Security-Token", "Digitraffic-User"],
|
195
|
+
allowMethods: ["OPTIONS", "GET", "HEAD"]
|
196
|
+
}
|
197
|
+
};
|
209
198
|
//# sourceMappingURL=rest_apis.mjs.map
|
package/dist/utils/utils.d.mts
CHANGED
@@ -75,6 +75,12 @@ export declare function getEnvVariableOr<T>(key: string, fn: () => T): string |
|
|
75
75
|
* @param orElse Alternative value
|
76
76
|
*/
|
77
77
|
export declare function getEnvVariableOrElse<T>(key: string, orElse: T): string | T;
|
78
|
+
/**
|
79
|
+
* Gets variable from environment or from an AWS Secrets Manager secret if not found in the environment.
|
80
|
+
* @param Environment key
|
81
|
+
* @param Secret id in Secrets Manager
|
82
|
+
*/
|
83
|
+
export declare function getFromEnvOrSecret(key: string, secretId: string): Promise<string>;
|
78
84
|
export declare function setSecretOverideAwsRegionEnv(region: string): void;
|
79
85
|
/**
|
80
86
|
* ESLint won't allow to call Object.prototype builtin methods.
|
package/dist/utils/utils.mjs
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { EnvKeys } from "../aws/runtime/environment.mjs";
|
2
|
+
import { getSecret, } from "../aws/runtime/secrets/secret.mjs";
|
2
3
|
/**
|
3
4
|
* Check if arrays have only elements that also exists also in other array.
|
4
5
|
* Individual element count doesn't matter.
|
@@ -130,6 +131,23 @@ export function getEnvVariableOr(key, fn) {
|
|
130
131
|
export function getEnvVariableOrElse(key, orElse) {
|
131
132
|
return getEnvVariableOr(key, () => orElse);
|
132
133
|
}
|
134
|
+
/**
|
135
|
+
* Gets variable from environment or from an AWS Secrets Manager secret if not found in the environment.
|
136
|
+
* @param Environment key
|
137
|
+
* @param Secret id in Secrets Manager
|
138
|
+
*/
|
139
|
+
export async function getFromEnvOrSecret(key, secretId) {
|
140
|
+
const envValue = getEnvVariableSafe(key);
|
141
|
+
if (envValue.result === "ok") {
|
142
|
+
return envValue.value;
|
143
|
+
}
|
144
|
+
const secret = await getSecret(secretId);
|
145
|
+
const secretValue = secret[key];
|
146
|
+
if (secretValue !== undefined) {
|
147
|
+
return secretValue;
|
148
|
+
}
|
149
|
+
throw new Error(`Cannot get value with key ${key} from env or secret`);
|
150
|
+
}
|
133
151
|
export function setSecretOverideAwsRegionEnv(region) {
|
134
152
|
setEnvVariable(EnvKeys.SECRET_OVERRIDE_AWS_REGION, region);
|
135
153
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@digitraffic/common",
|
3
|
-
"version": "2024.3.
|
3
|
+
"version": "2024.3.22-2",
|
4
4
|
"description": "",
|
5
5
|
"type": "module",
|
6
6
|
"repository": {
|
@@ -109,7 +109,7 @@
|
|
109
109
|
"@aws-sdk/client-api-gateway": "^3.533.0",
|
110
110
|
"@aws-sdk/client-sns": "^3.533.0",
|
111
111
|
"@types/geojson": "^7946.0.14",
|
112
|
-
"aws-cdk-lib": "^2.
|
112
|
+
"aws-cdk-lib": "^2.133.0",
|
113
113
|
"change-case": "5.0.0",
|
114
114
|
"constructs": "^10.3.0",
|
115
115
|
"date-fns": "~2.30.0",
|
@@ -137,7 +137,7 @@
|
|
137
137
|
"@rushstack/heft-typescript-plugin": "^0.3.20",
|
138
138
|
"@types/aws-lambda": "8.10.136",
|
139
139
|
"@types/etag": "1.8.3",
|
140
|
-
"@types/geojson": "7946.0.14",
|
140
|
+
"@types/geojson": "^7946.0.14",
|
141
141
|
"@types/geojson-validation": "^1.0.3",
|
142
142
|
"@types/jest": "29.5.12",
|
143
143
|
"@types/lodash": "4.14.202",
|
@@ -145,7 +145,7 @@
|
|
145
145
|
"@types/sinon": "17.0.3",
|
146
146
|
"@typescript-eslint/eslint-plugin": "~6.18.1",
|
147
147
|
"@typescript-eslint/parser": "^6.20.0",
|
148
|
-
"aws-cdk-lib": "
|
148
|
+
"aws-cdk-lib": "^2.133.0",
|
149
149
|
"change-case": "5.3.0",
|
150
150
|
"constructs": "10.3.0",
|
151
151
|
"date-fns": "~2.30.0",
|