@byaga/cdk-patterns 0.10.0 → 0.11.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/README.md +7 -1
- package/archive/ApiAttachPoint.ts +9 -0
- package/archive/ApiCertificate.ts +32 -0
- package/{lib/CognitoApiGatewayAuthorizer.d.ts → archive/CognitoApiGatewayAuthorizer.ts} +13 -7
- package/archive/DynamoDbTable.ts +40 -0
- package/archive/ICorsConfig.ts +5 -0
- package/archive/IDomainConfig.ts +8 -0
- package/archive/IHostedZoneConfig.ts +5 -0
- package/archive/NodeJsLambdaLayer.ts +42 -0
- package/archive/Output.ts +11 -0
- package/{lib/RestApi.js → archive/RestApi.ts} +96 -60
- package/{lib/Role.d.ts → archive/Role.ts} +165 -139
- package/archive/StaticWebSite.ts +159 -0
- package/archive/index.ts +18 -0
- package/archive/methods/apply-schema-to-method-options.ts +38 -0
- package/archive/methods/attach-function-to-api.ts +69 -0
- package/lib/{methods → build}/copy-files.js +1 -1
- package/lib/{methods → build/nodejs}/build-ecmascript.d.ts +2 -2
- package/lib/{methods → build/nodejs}/build-ecmascript.js +5 -5
- package/lib/{methods → build/nodejs}/build-node-source.d.ts +3 -1
- package/lib/{methods → build/nodejs}/build-node-source.js +6 -6
- package/lib/{methods → build/nodejs}/build-typescript.d.ts +2 -2
- package/lib/{methods → build/nodejs}/build-typescript.js +5 -5
- package/lib/{methods → build/nodejs}/install-node-modules.js +1 -1
- package/lib/create-stack.d.ts +41 -0
- package/lib/create-stack.js +48 -0
- package/lib/generate-identifier.d.ts +27 -0
- package/lib/generate-identifier.js +65 -0
- package/lib/index.d.ts +8 -15
- package/lib/index.js +40 -25
- package/lib/lambda/create-function.d.ts +20 -0
- package/lib/lambda/create-function.js +39 -0
- package/lib/lambda/create-nodejs-lambda.d.ts +28 -0
- package/lib/lambda/create-nodejs-lambda.js +38 -0
- package/lib/lambda-layer/apply-honeycomb-to-lambda.d.ts +2 -0
- package/lib/lambda-layer/apply-honeycomb-to-lambda.js +25 -0
- package/lib/lambda-layer/get-layer.d.ts +2 -0
- package/lib/lambda-layer/get-layer.js +20 -0
- package/lib/lambda-layer/layer-cache.d.ts +3 -0
- package/lib/lambda-layer/layer-cache.js +12 -0
- package/lib/load-configuration.d.ts +12 -0
- package/lib/load-configuration.js +42 -0
- package/lib/ssm/SsmParameter.d.ts +12 -0
- package/lib/ssm/get-existing-parameter.d.ts +9 -0
- package/lib/ssm/get-existing-parameter.js +41 -0
- package/lib/ssm/grant-read.d.ts +7 -0
- package/lib/ssm/grant-read.js +24 -0
- package/lib/ssm/index.d.ts +3 -0
- package/lib/ssm/index.js +9 -0
- package/lib/ssm/parameter-cache.d.ts +13 -0
- package/lib/ssm/parameter-cache.js +23 -0
- package/lib/ssm/string-value.d.ts +8 -0
- package/lib/ssm/string-value.js +14 -0
- package/package.json +4 -3
- package/lib/ApiCertificate.d.ts +0 -10
- package/lib/ApiCertificate.js +0 -31
- package/lib/CognitoApiGatewayAuthorizer.js +0 -24
- package/lib/DeployStack.d.ts +0 -19
- package/lib/DeployStack.js +0 -57
- package/lib/DynamoDbTable.d.ts +0 -12
- package/lib/DynamoDbTable.js +0 -34
- package/lib/FunctionIntegration.d.ts +0 -25
- package/lib/FunctionIntegration.js +0 -65
- package/lib/ICorsConfig.d.ts +0 -5
- package/lib/IDomainConfig.d.ts +0 -7
- package/lib/IDomainConfig.js +0 -2
- package/lib/IHostedZoneConfig.d.ts +0 -5
- package/lib/IHostedZoneConfig.js +0 -2
- package/lib/IStackArguments.d.ts +0 -8
- package/lib/IStackArguments.js +0 -2
- package/lib/NodeJsLambda.d.ts +0 -35
- package/lib/NodeJsLambda.js +0 -44
- package/lib/NodeJsLambdaLayer.d.ts +0 -25
- package/lib/NodeJsLambdaLayer.js +0 -35
- package/lib/Output.d.ts +0 -5
- package/lib/Output.js +0 -13
- package/lib/RestApi.d.ts +0 -28
- package/lib/Role.js +0 -27
- package/lib/SsmParameter.d.ts +0 -18
- package/lib/SsmParameter.js +0 -40
- package/lib/StaticWebSite.d.ts +0 -33
- package/lib/StaticWebSite.js +0 -136
- package/lib/methods/BuildOptions.d.ts +0 -3
- package/lib/methods/BuildOptions.js +0 -2
- package/lib/methods/apply-honeycomb-to-lambda.d.ts +0 -3
- package/lib/methods/apply-honeycomb-to-lambda.js +0 -23
- /package/lib/{methods → build}/copy-files.d.ts +0 -0
- /package/lib/{methods → build}/generate-hash.d.ts +0 -0
- /package/lib/{methods → build}/generate-hash.js +0 -0
- /package/lib/{methods → build}/get-files.d.ts +0 -0
- /package/lib/{methods → build}/get-files.js +0 -0
- /package/lib/{methods → build}/get-source-directory.d.ts +0 -0
- /package/lib/{methods → build}/get-source-directory.js +0 -0
- /package/lib/{methods → build}/hash-file.d.ts +0 -0
- /package/lib/{methods → build}/hash-file.js +0 -0
- /package/lib/{methods → build/nodejs}/install-node-modules.d.ts +0 -0
- /package/lib/{ICorsConfig.js → ssm/SsmParameter.js} +0 -0
- /package/lib/{methods → tools}/duration.d.ts +0 -0
- /package/lib/{methods → tools}/duration.js +0 -0
package/README.md
CHANGED
@@ -26,7 +26,13 @@ Then, you can use the patterns provided by the package in your CDK stacks.
|
|
26
26
|
|
27
27
|
The package includes the following patterns:
|
28
28
|
|
29
|
-
- [
|
29
|
+
- [createStack](./src/create-stack.md)
|
30
|
+
- [createNodeJsLambda](./src/create-nodejs-lambda.md)
|
31
|
+
|
32
|
+
And the below helpful functions:
|
33
|
+
|
34
|
+
- [Building Code](./src/build-code.md)
|
35
|
+
- [Generating Identifiers](./src/generate-identifier.md)
|
30
36
|
|
31
37
|
## Contributing
|
32
38
|
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import {Certificate, CertificateValidation} from "aws-cdk-lib/aws-certificatemanager";
|
2
|
+
import {HostedZone, IHostedZone} from "aws-cdk-lib/aws-route53";
|
3
|
+
import {Output} from "./Output";
|
4
|
+
import DeployStack from "./DeployStack";
|
5
|
+
import IDomainConfig from "./IDomainConfig";
|
6
|
+
|
7
|
+
export class ApiCertificate extends Certificate {
|
8
|
+
hostedZone: IHostedZone
|
9
|
+
domain: string
|
10
|
+
|
11
|
+
constructor(stack: DeployStack, id: string, domain: IDomainConfig) {
|
12
|
+
const certDomain = [domain.domainName]
|
13
|
+
if (domain.subdomain) certDomain.splice(0, 0, domain.subdomain)
|
14
|
+
const domainName = certDomain.join('.')
|
15
|
+
|
16
|
+
console.log('Getting Hosted Zone', domain.hostedZone.name)
|
17
|
+
const hostedZone: IHostedZone = HostedZone.fromHostedZoneAttributes(stack, stack.genId(id, 'hosted-zone'), {
|
18
|
+
hostedZoneId: domain.hostedZone.id,
|
19
|
+
zoneName: domain.hostedZone.name
|
20
|
+
})
|
21
|
+
console.log('Defining Certificate For', domainName)
|
22
|
+
super(stack, stack.genId(id), {
|
23
|
+
domainName,
|
24
|
+
validation: CertificateValidation.fromDns(hostedZone)
|
25
|
+
});
|
26
|
+
|
27
|
+
this.domain = domainName
|
28
|
+
new Output(stack, id, this.certificateArn)
|
29
|
+
this.hostedZone = hostedZone
|
30
|
+
}
|
31
|
+
}
|
32
|
+
export default ApiCertificate
|
@@ -1,6 +1,7 @@
|
|
1
|
-
import { Construct } from 'constructs'
|
2
|
-
import { CfnAuthorizer, IAuthorizer } from 'aws-cdk-lib/aws-apigateway'
|
3
|
-
import { CfnAuthorizerProps } from 'aws-cdk-lib/aws-apigateway/lib/apigateway.generated'
|
1
|
+
import { Construct } from 'constructs'
|
2
|
+
import { CfnAuthorizer, IAuthorizer } from 'aws-cdk-lib/aws-apigateway'
|
3
|
+
import { CfnAuthorizerProps } from 'aws-cdk-lib/aws-apigateway/lib/apigateway.generated'
|
4
|
+
|
4
5
|
/**
|
5
6
|
* Custom construct that implements a Cognito based API Gateway Authorizer.
|
6
7
|
*
|
@@ -13,7 +14,12 @@ import { CfnAuthorizerProps } from 'aws-cdk-lib/aws-apigateway/lib/apigateway.ge
|
|
13
14
|
*
|
14
15
|
* @see https://github.com/aws/aws-cdk/issues/5618#issuecomment-666922559
|
15
16
|
*/
|
16
|
-
export
|
17
|
-
readonly authorizerId: string
|
18
|
-
|
19
|
-
|
17
|
+
export class CognitoApiGatewayAuthorizer extends CfnAuthorizer implements IAuthorizer {
|
18
|
+
public readonly authorizerId: string
|
19
|
+
|
20
|
+
constructor(scope: Construct, id: string, props: CfnAuthorizerProps) {
|
21
|
+
super(scope, id, props)
|
22
|
+
|
23
|
+
this.authorizerId = this.ref
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import {CfnOutput, RemovalPolicy} from 'aws-cdk-lib';
|
2
|
+
import {Table, BillingMode, AttributeType} from 'aws-cdk-lib/aws-dynamodb'
|
3
|
+
import {Effect, Policy, PolicyStatement} from "aws-cdk-lib/aws-iam";
|
4
|
+
import {DeployStack} from "./DeployStack"
|
5
|
+
|
6
|
+
interface DynamoDbTableConfig {
|
7
|
+
partitionKey: string,
|
8
|
+
sortKey?: string
|
9
|
+
}
|
10
|
+
|
11
|
+
export class DynamoDbTable extends Table {
|
12
|
+
getPolicy: Policy
|
13
|
+
|
14
|
+
constructor(stack: DeployStack, id: string, props: DynamoDbTableConfig) {
|
15
|
+
console.log('Creating DynamoDb Table', stack.genName(id, 'data-table'))
|
16
|
+
super(stack, stack.genId(id, 'data-table'), {
|
17
|
+
tableName: stack.genName(id, 'data-table'),
|
18
|
+
partitionKey: {name: props.partitionKey, type: AttributeType.STRING},
|
19
|
+
sortKey: props.sortKey ? {name: props.sortKey, type: AttributeType.STRING} : undefined,
|
20
|
+
billingMode: BillingMode.PAY_PER_REQUEST,
|
21
|
+
removalPolicy: RemovalPolicy.DESTROY
|
22
|
+
});
|
23
|
+
stack.set('dynamo', id, this)
|
24
|
+
|
25
|
+
new CfnOutput(stack, stack.genId(id, 'table'), {
|
26
|
+
value: this.tableName,
|
27
|
+
exportName: stack.genName(id, 'table')
|
28
|
+
})
|
29
|
+
|
30
|
+
this.getPolicy = new Policy(stack, stack.genId(id, 'get-policy'), {
|
31
|
+
statements: [
|
32
|
+
new PolicyStatement({
|
33
|
+
actions: ['dynamodb:GetItem'],
|
34
|
+
effect: Effect.ALLOW,
|
35
|
+
resources: [this.tableArn]
|
36
|
+
})
|
37
|
+
]
|
38
|
+
})
|
39
|
+
}
|
40
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import {Code, LayerVersion, Runtime} from "aws-cdk-lib/aws-lambda";
|
2
|
+
import {DeployStack} from "./DeployStack";
|
3
|
+
import {LayerVersionOptions} from "aws-cdk-lib/aws-lambda/lib/layers";
|
4
|
+
import {Architecture} from "aws-cdk-lib/aws-lambda/lib/architecture";
|
5
|
+
import {buildNodeSource} from "./methods/build-node-source";
|
6
|
+
import duration from "./methods/duration";
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Interface for the properties of the NodeJsLambdaLayer class.
|
10
|
+
*/
|
11
|
+
interface NodeJsLambdaLayerProps extends LayerVersionOptions {
|
12
|
+
readonly compatibleRuntimes?: Runtime[];
|
13
|
+
readonly compatibleArchitectures?: Architecture[];
|
14
|
+
}
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Class representing a Node.js AWS Lambda layer.
|
18
|
+
* Extends the LayerVersion class from the AWS CDK library.
|
19
|
+
*/
|
20
|
+
export class NodeJsLambdaLayer extends LayerVersion {
|
21
|
+
/**
|
22
|
+
* Constructs a new NodeJsLambdaLayer instance.
|
23
|
+
* @param {DeployStack} stack - The deployment stack.
|
24
|
+
* @param {string} id - The ID of the layer.
|
25
|
+
* @param {NodeJsLambdaLayerProps} props - The properties of the layer.
|
26
|
+
*/
|
27
|
+
constructor(stack: DeployStack, id: string, props: NodeJsLambdaLayerProps = {}) {
|
28
|
+
console.log("Building Lambda Layer", id);
|
29
|
+
const done = duration()
|
30
|
+
const buildDir = buildNodeSource('lambda-layer', id, {subdirectory:'nodejs'})
|
31
|
+
console.log('Build Duration (ms)', done())
|
32
|
+
|
33
|
+
super(stack, stack.genId(id), {
|
34
|
+
compatibleRuntimes: [Runtime.NODEJS_20_X],
|
35
|
+
...props,
|
36
|
+
layerVersionName: stack.genName(id),
|
37
|
+
code: Code.fromAsset(buildDir),
|
38
|
+
|
39
|
+
});
|
40
|
+
stack.set('lambda-layer', id, this)
|
41
|
+
}
|
42
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import {CfnOutput} from 'aws-cdk-lib/core';
|
2
|
+
import {DeployStack} from './DeployStack';
|
3
|
+
|
4
|
+
export class Output extends CfnOutput {
|
5
|
+
constructor(stack: DeployStack, name: string, value: string) {
|
6
|
+
super(stack, stack.genId(name, 'output'), {
|
7
|
+
value,
|
8
|
+
exportName: stack.genName(name)
|
9
|
+
})
|
10
|
+
}
|
11
|
+
}
|
@@ -1,18 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
1
|
+
import {
|
2
|
+
BasePathMapping,
|
3
|
+
ContentHandling,
|
4
|
+
DomainName,
|
5
|
+
EndpointType,
|
6
|
+
IDomainName,
|
7
|
+
IResource,
|
8
|
+
MockIntegration,
|
9
|
+
RestApi as RestApiBase
|
10
|
+
} from "aws-cdk-lib/aws-apigateway";
|
11
|
+
import {DeployStack} from "./DeployStack"
|
12
|
+
import {ICorsConfig} from "./ICorsConfig";
|
13
|
+
import {Duration, Size} from "aws-cdk-lib";
|
14
|
+
import {Effect, Policy, PolicyStatement, Role} from "aws-cdk-lib/aws-iam";
|
15
|
+
|
16
|
+
interface IRestApiConfig {
|
17
|
+
cors?: ICorsConfig,
|
18
|
+
allowCredentials: boolean
|
19
|
+
}
|
20
|
+
|
21
|
+
interface IBasePathMappingConfig {
|
22
|
+
domain?: IDomainName,
|
23
|
+
domainName?: string,
|
24
|
+
hostedZoneId?: string
|
25
|
+
}
|
26
|
+
|
27
|
+
interface IResourceNode {
|
28
|
+
children: { [key: string]: IResourceNode }
|
29
|
+
node: IResource
|
30
|
+
}
|
31
|
+
|
32
|
+
const DEFAULT_EXPOSE_HEADERS = ['Date']
|
33
|
+
|
34
|
+
export class RestApi extends RestApiBase {
|
35
|
+
_id: string
|
36
|
+
_tree: IResourceNode
|
37
|
+
|
38
|
+
|
39
|
+
constructor(stack: DeployStack, id: string, props: IRestApiConfig) {
|
40
|
+
const {stage} = stack
|
41
|
+
|
42
|
+
console.log('Defining Rest API', stack.genId(id, 'api'))
|
43
|
+
|
44
|
+
const cors: ICorsConfig = props.cors || {}
|
45
|
+
const allowOrigins: string[] = Array.isArray(cors.allowOrigin) ? cors.allowOrigin : [cors.allowOrigin || '*']
|
16
46
|
super(stack, stack.genId(id, 'api'), {
|
17
47
|
restApiName: stack.genName('api'),
|
18
48
|
deploy: true,
|
@@ -20,32 +50,33 @@ class RestApi extends aws_apigateway_1.RestApi {
|
|
20
50
|
stageName: stage,
|
21
51
|
tracingEnabled: true
|
22
52
|
},
|
23
|
-
minCompressionSize:
|
53
|
+
minCompressionSize: Size.bytes(1000),
|
24
54
|
endpointConfiguration: {
|
25
|
-
types: [
|
55
|
+
types: [EndpointType.EDGE]
|
26
56
|
},
|
27
57
|
defaultCorsPreflightOptions: {
|
28
58
|
allowHeaders: ['*'],
|
29
59
|
allowMethods: ['*'],
|
30
60
|
allowCredentials: props.allowCredentials,
|
31
61
|
allowOrigins,
|
32
|
-
maxAge:
|
62
|
+
maxAge: Duration.seconds(cors.maxAge || 86400),
|
33
63
|
exposeHeaders: cors.exposeHeaders || DEFAULT_EXPOSE_HEADERS
|
34
64
|
}
|
35
|
-
})
|
36
|
-
this._id = id
|
65
|
+
})
|
66
|
+
this._id = id
|
67
|
+
|
37
68
|
// APIs MUST have at least one endpoint, so this will give it one
|
38
|
-
console.log('Adding health endpoint', '/health')
|
39
|
-
const health = this.root.addResource('health')
|
40
|
-
health.addMethod("GET", new
|
69
|
+
console.log('Adding health endpoint', '/health')
|
70
|
+
const health = this.root.addResource('health')
|
71
|
+
health.addMethod("GET", new MockIntegration({
|
41
72
|
requestTemplates: {
|
42
73
|
"application/json": "{\"statusCode\": 200}"
|
43
74
|
},
|
44
75
|
integrationResponses: [{
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
76
|
+
statusCode: '200',
|
77
|
+
contentHandling: ContentHandling.CONVERT_TO_TEXT,
|
78
|
+
responseTemplates: {
|
79
|
+
'application/json': `
|
49
80
|
## See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
|
50
81
|
## This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload
|
51
82
|
#set($allParams = $input.params())
|
@@ -90,55 +121,60 @@ class RestApi extends aws_apigateway_1.RestApi {
|
|
90
121
|
"resource-path" : "$context.resourcePath"
|
91
122
|
}
|
92
123
|
}`
|
93
|
-
|
94
|
-
|
124
|
+
}
|
125
|
+
}]
|
95
126
|
}), {
|
96
|
-
methodResponses: [{
|
97
|
-
})
|
98
|
-
|
127
|
+
methodResponses: [{statusCode: "200"}]
|
128
|
+
})
|
129
|
+
|
130
|
+
this._tree = {node: this.root, children: {}}
|
99
131
|
}
|
100
|
-
|
101
|
-
|
132
|
+
|
133
|
+
addBasePathMapping(stack: DeployStack, config: IBasePathMappingConfig) {
|
134
|
+
let domain = config.domain
|
102
135
|
if (!domain && config.domainName && config.hostedZoneId) {
|
103
|
-
domain =
|
136
|
+
domain = DomainName.fromDomainNameAttributes(stack, stack.genName('domain-name'), {
|
104
137
|
domainName: config.domainName,
|
105
138
|
domainNameAliasHostedZoneId: config.hostedZoneId,
|
106
139
|
domainNameAliasTarget: this.restApiRootResourceId
|
107
|
-
})
|
140
|
+
})
|
108
141
|
}
|
109
|
-
if (!domain)
|
110
|
-
|
111
|
-
new
|
142
|
+
if (!domain) throw new Error('Missing Domain Configuration For Base Path Mapping')
|
143
|
+
|
144
|
+
new BasePathMapping(stack, stack.genId(this._id, 'base-path-mapping'), {
|
112
145
|
domainName: domain,
|
113
146
|
stage: this.deploymentStage,
|
114
147
|
restApi: this,
|
115
148
|
basePath: this._id
|
116
|
-
})
|
149
|
+
})
|
117
150
|
}
|
118
|
-
|
119
|
-
|
120
|
-
|
151
|
+
|
152
|
+
addAuthorizedRole(stack: DeployStack, roleArn: string): PolicyStatement {
|
153
|
+
const policyStatement = new PolicyStatement({
|
154
|
+
effect: Effect.ALLOW,
|
121
155
|
actions: ['execute-api:Invoke']
|
122
|
-
})
|
123
|
-
|
124
|
-
authRole
|
156
|
+
})
|
157
|
+
|
158
|
+
const authRole = Role.fromRoleArn(stack, stack.genId('authenticated-role'), roleArn)
|
159
|
+
authRole.attachInlinePolicy(new Policy(stack, stack.genId('api-access-policy'), {
|
125
160
|
statements: [policyStatement]
|
126
|
-
}))
|
161
|
+
}))
|
127
162
|
return policyStatement;
|
128
163
|
}
|
129
|
-
|
130
|
-
|
164
|
+
|
165
|
+
path(uri: string): IResource {
|
166
|
+
const {node} = uri.split('/')
|
131
167
|
.filter(path => !!path)
|
132
168
|
.reduce((resource, path) => {
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
169
|
+
if (!resource.children[path]) {
|
170
|
+
resource.children[path] = {
|
171
|
+
children: {},
|
172
|
+
node: resource.node.addResource(path)
|
173
|
+
}
|
174
|
+
}
|
175
|
+
return resource.children[path];
|
176
|
+
}, this._tree);
|
177
|
+
|
178
|
+
return node
|
142
179
|
}
|
143
|
-
}
|
144
|
-
exports.RestApi = RestApi;
|
180
|
+
}
|