@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.
Files changed (99) hide show
  1. package/README.md +7 -1
  2. package/archive/ApiAttachPoint.ts +9 -0
  3. package/archive/ApiCertificate.ts +32 -0
  4. package/{lib/CognitoApiGatewayAuthorizer.d.ts → archive/CognitoApiGatewayAuthorizer.ts} +13 -7
  5. package/archive/DynamoDbTable.ts +40 -0
  6. package/archive/ICorsConfig.ts +5 -0
  7. package/archive/IDomainConfig.ts +8 -0
  8. package/archive/IHostedZoneConfig.ts +5 -0
  9. package/archive/NodeJsLambdaLayer.ts +42 -0
  10. package/archive/Output.ts +11 -0
  11. package/{lib/RestApi.js → archive/RestApi.ts} +96 -60
  12. package/{lib/Role.d.ts → archive/Role.ts} +165 -139
  13. package/archive/StaticWebSite.ts +159 -0
  14. package/archive/index.ts +18 -0
  15. package/archive/methods/apply-schema-to-method-options.ts +38 -0
  16. package/archive/methods/attach-function-to-api.ts +69 -0
  17. package/lib/{methods → build}/copy-files.js +1 -1
  18. package/lib/{methods → build/nodejs}/build-ecmascript.d.ts +2 -2
  19. package/lib/{methods → build/nodejs}/build-ecmascript.js +5 -5
  20. package/lib/{methods → build/nodejs}/build-node-source.d.ts +3 -1
  21. package/lib/{methods → build/nodejs}/build-node-source.js +6 -6
  22. package/lib/{methods → build/nodejs}/build-typescript.d.ts +2 -2
  23. package/lib/{methods → build/nodejs}/build-typescript.js +5 -5
  24. package/lib/{methods → build/nodejs}/install-node-modules.js +1 -1
  25. package/lib/create-stack.d.ts +41 -0
  26. package/lib/create-stack.js +48 -0
  27. package/lib/generate-identifier.d.ts +27 -0
  28. package/lib/generate-identifier.js +65 -0
  29. package/lib/index.d.ts +8 -15
  30. package/lib/index.js +40 -25
  31. package/lib/lambda/create-function.d.ts +20 -0
  32. package/lib/lambda/create-function.js +39 -0
  33. package/lib/lambda/create-nodejs-lambda.d.ts +28 -0
  34. package/lib/lambda/create-nodejs-lambda.js +38 -0
  35. package/lib/lambda-layer/apply-honeycomb-to-lambda.d.ts +2 -0
  36. package/lib/lambda-layer/apply-honeycomb-to-lambda.js +25 -0
  37. package/lib/lambda-layer/get-layer.d.ts +2 -0
  38. package/lib/lambda-layer/get-layer.js +20 -0
  39. package/lib/lambda-layer/layer-cache.d.ts +3 -0
  40. package/lib/lambda-layer/layer-cache.js +12 -0
  41. package/lib/load-configuration.d.ts +12 -0
  42. package/lib/load-configuration.js +42 -0
  43. package/lib/ssm/SsmParameter.d.ts +12 -0
  44. package/lib/ssm/get-existing-parameter.d.ts +9 -0
  45. package/lib/ssm/get-existing-parameter.js +41 -0
  46. package/lib/ssm/grant-read.d.ts +7 -0
  47. package/lib/ssm/grant-read.js +24 -0
  48. package/lib/ssm/index.d.ts +3 -0
  49. package/lib/ssm/index.js +9 -0
  50. package/lib/ssm/parameter-cache.d.ts +13 -0
  51. package/lib/ssm/parameter-cache.js +23 -0
  52. package/lib/ssm/string-value.d.ts +8 -0
  53. package/lib/ssm/string-value.js +14 -0
  54. package/package.json +4 -3
  55. package/lib/ApiCertificate.d.ts +0 -10
  56. package/lib/ApiCertificate.js +0 -31
  57. package/lib/CognitoApiGatewayAuthorizer.js +0 -24
  58. package/lib/DeployStack.d.ts +0 -19
  59. package/lib/DeployStack.js +0 -57
  60. package/lib/DynamoDbTable.d.ts +0 -12
  61. package/lib/DynamoDbTable.js +0 -34
  62. package/lib/FunctionIntegration.d.ts +0 -25
  63. package/lib/FunctionIntegration.js +0 -65
  64. package/lib/ICorsConfig.d.ts +0 -5
  65. package/lib/IDomainConfig.d.ts +0 -7
  66. package/lib/IDomainConfig.js +0 -2
  67. package/lib/IHostedZoneConfig.d.ts +0 -5
  68. package/lib/IHostedZoneConfig.js +0 -2
  69. package/lib/IStackArguments.d.ts +0 -8
  70. package/lib/IStackArguments.js +0 -2
  71. package/lib/NodeJsLambda.d.ts +0 -35
  72. package/lib/NodeJsLambda.js +0 -44
  73. package/lib/NodeJsLambdaLayer.d.ts +0 -25
  74. package/lib/NodeJsLambdaLayer.js +0 -35
  75. package/lib/Output.d.ts +0 -5
  76. package/lib/Output.js +0 -13
  77. package/lib/RestApi.d.ts +0 -28
  78. package/lib/Role.js +0 -27
  79. package/lib/SsmParameter.d.ts +0 -18
  80. package/lib/SsmParameter.js +0 -40
  81. package/lib/StaticWebSite.d.ts +0 -33
  82. package/lib/StaticWebSite.js +0 -136
  83. package/lib/methods/BuildOptions.d.ts +0 -3
  84. package/lib/methods/BuildOptions.js +0 -2
  85. package/lib/methods/apply-honeycomb-to-lambda.d.ts +0 -3
  86. package/lib/methods/apply-honeycomb-to-lambda.js +0 -23
  87. /package/lib/{methods → build}/copy-files.d.ts +0 -0
  88. /package/lib/{methods → build}/generate-hash.d.ts +0 -0
  89. /package/lib/{methods → build}/generate-hash.js +0 -0
  90. /package/lib/{methods → build}/get-files.d.ts +0 -0
  91. /package/lib/{methods → build}/get-files.js +0 -0
  92. /package/lib/{methods → build}/get-source-directory.d.ts +0 -0
  93. /package/lib/{methods → build}/get-source-directory.js +0 -0
  94. /package/lib/{methods → build}/hash-file.d.ts +0 -0
  95. /package/lib/{methods → build}/hash-file.js +0 -0
  96. /package/lib/{methods → build/nodejs}/install-node-modules.d.ts +0 -0
  97. /package/lib/{ICorsConfig.js → ssm/SsmParameter.js} +0 -0
  98. /package/lib/{methods → tools}/duration.d.ts +0 -0
  99. /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
- - [NodeJsLambda](./src/NodeJsLambda.md)
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,9 @@
1
+ import { Method } from "aws-cdk-lib/aws-apigateway";
2
+
3
+ /**
4
+ * Interface for the API attach point.
5
+ */
6
+ export interface ApiAttachPoint {
7
+ method: Method
8
+ resourceArn: string
9
+ }
@@ -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 declare class CognitoApiGatewayAuthorizer extends CfnAuthorizer implements IAuthorizer {
17
- readonly authorizerId: string;
18
- constructor(scope: Construct, id: string, props: CfnAuthorizerProps);
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,5 @@
1
+ export interface ICorsConfig {
2
+ maxAge?: number
3
+ exposeHeaders?: string[],
4
+ allowOrigin?: string|string[]
5
+ }
@@ -0,0 +1,8 @@
1
+ import IHostedZoneConfig from "./IHostedZoneConfig";
2
+
3
+ export interface IDomainConfig {
4
+ domainName: string,
5
+ subdomain?: string,
6
+ hostedZone: IHostedZoneConfig
7
+ }
8
+ export default IDomainConfig
@@ -0,0 +1,5 @@
1
+ export interface IHostedZoneConfig {
2
+ name: string,
3
+ id: string
4
+ }
5
+ export default IHostedZoneConfig
@@ -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
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RestApi = void 0;
4
- const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
5
- const aws_cdk_lib_1 = require("aws-cdk-lib");
6
- const aws_iam_1 = require("aws-cdk-lib/aws-iam");
7
- const DEFAULT_EXPOSE_HEADERS = ['Date'];
8
- class RestApi extends aws_apigateway_1.RestApi {
9
- _id;
10
- _tree;
11
- constructor(stack, id, props) {
12
- const { stage } = stack;
13
- console.log('Defining Rest API', stack.genId(id, 'api'));
14
- const cors = props.cors || {};
15
- const allowOrigins = Array.isArray(cors.allowOrigin) ? cors.allowOrigin : [cors.allowOrigin || '*'];
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: aws_cdk_lib_1.Size.bytes(1000),
53
+ minCompressionSize: Size.bytes(1000),
24
54
  endpointConfiguration: {
25
- types: [aws_apigateway_1.EndpointType.EDGE]
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: aws_cdk_lib_1.Duration.seconds(cors.maxAge || 86400),
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 aws_apigateway_1.MockIntegration({
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
- statusCode: '200',
46
- contentHandling: aws_apigateway_1.ContentHandling.CONVERT_TO_TEXT,
47
- responseTemplates: {
48
- 'application/json': `
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: [{ statusCode: "200" }]
97
- });
98
- this._tree = { node: this.root, children: {} };
127
+ methodResponses: [{statusCode: "200"}]
128
+ })
129
+
130
+ this._tree = {node: this.root, children: {}}
99
131
  }
100
- addBasePathMapping(stack, config) {
101
- let domain = config.domain;
132
+
133
+ addBasePathMapping(stack: DeployStack, config: IBasePathMappingConfig) {
134
+ let domain = config.domain
102
135
  if (!domain && config.domainName && config.hostedZoneId) {
103
- domain = aws_apigateway_1.DomainName.fromDomainNameAttributes(stack, stack.genName('domain-name'), {
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
- throw new Error('Missing Domain Configuration For Base Path Mapping');
111
- new aws_apigateway_1.BasePathMapping(stack, stack.genId(this._id, 'base-path-mapping'), {
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
- addAuthorizedRole(stack, roleArn) {
119
- const policyStatement = new aws_iam_1.PolicyStatement({
120
- effect: aws_iam_1.Effect.ALLOW,
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
- const authRole = aws_iam_1.Role.fromRoleArn(stack, stack.genId('authenticated-role'), roleArn);
124
- authRole.attachInlinePolicy(new aws_iam_1.Policy(stack, stack.genId('api-access-policy'), {
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
- path(uri) {
130
- const { node } = uri.split('/')
164
+
165
+ path(uri: string): IResource {
166
+ const {node} = uri.split('/')
131
167
  .filter(path => !!path)
132
168
  .reduce((resource, path) => {
133
- if (!resource.children[path]) {
134
- resource.children[path] = {
135
- children: {},
136
- node: resource.node.addResource(path)
137
- };
138
- }
139
- return resource.children[path];
140
- }, this._tree);
141
- return node;
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
+ }