├── .eslintignore ├── .eslintrc ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .prettierrc ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── examples ├── app │ ├── .eslintrc │ ├── .gitignore │ ├── cdk.json │ ├── package.json │ └── src │ │ ├── __tests__ │ │ └── app-stack.test.ts │ │ ├── app-app.ts │ │ └── app-stack.ts ├── construct │ ├── .eslintrc │ ├── .gitignore │ ├── API.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── demo-layer.test.ts │ │ │ └── example.test.ts │ │ ├── demo-layer.ts │ │ ├── example.ts │ │ ├── index.ts │ │ ├── lambdas │ │ │ ├── shared │ │ │ │ └── index.ts │ │ │ ├── test1 │ │ │ │ ├── __tests__ │ │ │ │ │ └── index.test.ts │ │ │ │ └── index.ts │ │ │ ├── test2 │ │ │ │ └── index.ts │ │ │ └── tsconfig.json │ │ └── layers │ │ │ └── demo │ │ │ ├── .dockerignore │ │ │ ├── Dockerfile │ │ │ └── layer.zip │ ├── tsconfig.eslint.json │ └── tsconfig.json ├── jsii-construct │ ├── .eslintrc │ ├── .gitignore │ ├── .npmignore │ ├── API.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ └── example.test.ts │ │ ├── index.ts │ │ └── lambdas │ │ │ ├── test1 │ │ │ └── index.ts │ │ │ └── test2 │ │ │ └── index.ts │ └── tsconfig.eslint.json └── react │ ├── .eslintrc │ ├── .gitignore │ ├── cdk.json │ ├── lambda-file-sizes.json │ ├── package.json │ └── src │ ├── __tests__ │ └── react-stack.test.ts │ ├── lambdas │ └── web │ │ ├── app.tsx │ │ └── index.tsx │ ├── react-app.ts │ └── react-stack.ts ├── lerna.json ├── package.json ├── packages ├── cdkdx │ ├── LICENSE │ ├── README.md │ ├── bin │ │ └── cdkdx.js │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── base-command.ts │ │ ├── bundler.ts │ │ ├── cdkdx-config.ts │ │ ├── cli.ts │ │ ├── commands │ │ │ ├── build-command.ts │ │ │ ├── bump-command.ts │ │ │ ├── bundle-command.ts │ │ │ ├── create-command.ts │ │ │ ├── docgen-command.ts │ │ │ ├── help-command.ts │ │ │ ├── index.ts │ │ │ ├── layer-command.ts │ │ │ ├── linter-command.ts │ │ │ ├── node-command.ts │ │ │ ├── package-command.ts │ │ │ ├── release-command.ts │ │ │ ├── test-command.ts │ │ │ ├── upgrade-cdk-command.ts │ │ │ └── version-command.ts │ │ ├── compiler.ts │ │ ├── docgen.ts │ │ ├── docker.ts │ │ ├── env.d.ts │ │ ├── git-repository.ts │ │ ├── logger.ts │ │ ├── package-manager.ts │ │ ├── plugins │ │ │ ├── index.ts │ │ │ ├── lambda-file-size-plugin.ts │ │ │ └── node-modules-plugin.ts │ │ ├── project-info.ts │ │ ├── semver.ts │ │ ├── template.ts │ │ ├── templates │ │ │ ├── app-project.ts │ │ │ ├── directory.ts │ │ │ ├── file-base.ts │ │ │ ├── git-ignore.ts │ │ │ ├── index.ts │ │ │ ├── jsii-lib-project.ts │ │ │ ├── json-file.ts │ │ │ ├── lib-project.ts │ │ │ ├── project.ts │ │ │ └── template-file.ts │ │ ├── timer.ts │ │ └── ts-config.ts │ ├── templates │ │ ├── app │ │ │ └── default │ │ │ │ ├── API.md │ │ │ │ ├── LICENCE │ │ │ │ ├── README.md │ │ │ │ └── src │ │ │ │ ├── ${name}-app.ts │ │ │ │ ├── ${name}-stack.ts │ │ │ │ ├── __tests__ │ │ │ │ └── ${name}-stack.test.ts │ │ │ │ └── lambdas │ │ │ │ └── .gitkeep │ │ └── lib │ │ │ └── default │ │ │ ├── API.md │ │ │ ├── LICENCE │ │ │ ├── README.md │ │ │ └── src │ │ │ ├── ${name}.ts │ │ │ ├── __tests__ │ │ │ └── ${name}.test.ts │ │ │ ├── index.ts │ │ │ └── lambdas │ │ │ └── demo │ │ │ └── index.ts │ ├── test │ │ ├── __fixtures__ │ │ │ ├── tsc-docgen │ │ │ │ └── index.ts │ │ │ └── ws │ │ │ │ ├── p3 │ │ │ │ └── package.json │ │ │ │ ├── package.json │ │ │ │ └── packages │ │ │ │ ├── p1 │ │ │ │ └── package.json │ │ │ │ └── p2 │ │ │ │ └── package.json │ │ ├── __snapshots__ │ │ │ └── ts-config.test.ts.snap │ │ ├── logger.test.ts │ │ ├── projecg-info.test.ts │ │ ├── semver.test.ts │ │ └── ts-config.test.ts │ └── tsconfig.json ├── eslint-config-cdk │ ├── LICENSE │ ├── README.md │ ├── index.js │ └── package.json └── eslint-plugin-cdk │ ├── LICENSE │ ├── README.md │ ├── docs │ └── .gitkeep │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── index.ts │ ├── rules │ │ ├── ban-lambda-runtimes.ts │ │ ├── ban-reserved-words.ts │ │ ├── construct-ctor.ts │ │ ├── construct-props-struct-name.ts │ │ ├── filename-match-regex.ts │ │ ├── index.ts │ │ ├── no-static-import.ts │ │ ├── prefer-type-only-imports.ts │ │ ├── public-static-property-all-caps.ts │ │ └── stack-props-struct-name.ts │ └── utils │ │ ├── cdk.ts │ │ ├── create-rule.ts │ │ ├── index.ts │ │ ├── jsii.ts │ │ └── misc.ts │ ├── test │ ├── fixtures │ │ ├── construct │ │ │ ├── construct.ts │ │ │ └── package.json │ │ └── jsii-construct │ │ │ ├── package.json │ │ │ └── src │ │ │ └── construct.ts │ ├── rule-tester.ts │ └── rules │ │ ├── ban-lambda-runtimes.test.ts │ │ ├── ban-reserved-words.test.ts │ │ ├── construct-ctor.test.ts │ │ ├── construct-props-struct-name.test.ts │ │ ├── filename-match.regex.test.ts │ │ ├── index.test.ts │ │ ├── no-static-import.test.ts │ │ ├── prefer-type-only-imports.test.ts │ │ ├── public-static-property-all-caps.test.ts │ │ └── stack-props-struct-name.test.ts │ └── tsconfig.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | .cdkdx 2 | lib 3 | node_modules 4 | examples 5 | packages/cdkdx/templates 6 | eslint-config-cdk 7 | jest.config.js 8 | bin -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "plugin:@typescript-eslint/recommended", 5 | "prettier" 6 | ], 7 | "plugins": ["@typescript-eslint", "prettier"], 8 | "rules": { 9 | "prettier/prettier": ["error"], 10 | 11 | "@typescript-eslint/no-unused-vars": [ 12 | "error", 13 | { 14 | "vars": "all", 15 | "args": "after-used", 16 | "ignoreRestSiblings": false, 17 | "argsIgnorePattern": "^_" 18 | } 19 | ], 20 | 21 | "@typescript-eslint/interface-name-prefix": "off", 22 | "@typescript-eslint/no-use-before-define": "off", 23 | 24 | // Require use of the `import { foo } from "bar";` form instead of `import foo = require("bar");` 25 | "@typescript-eslint/no-require-imports": [ 26 | "error" 27 | ] 28 | } 29 | } -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | node: ["14", "16"] 15 | name: Node ${{ matrix.node }} build 16 | steps: 17 | - uses: actions/checkout@v2 18 | - uses: actions/setup-node@v1 19 | with: 20 | node-version: ${{ matrix.node }} 21 | - name: Installing 22 | run: yarn install --frozen-lockfile 23 | - name: Linting 24 | run: yarn lint 25 | - name: UnitTesting 26 | run: yarn test:unit 27 | - name: TscIntegrationTesting 28 | run: yarn test:tsc-integration 29 | - name: JsiiIntegrationTesting 30 | run: yarn test:jsii-integration 31 | - name: AppIntegrationTesting 32 | run: yarn test:app-integration 33 | - name: Anti-tamper check 34 | run: git diff --exit-code -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Build 107 | lib 108 | !packages/cdkdx/templates/lib 109 | 110 | .DS_Store 111 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "semi": true, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "tabWidth": 2 7 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.alwaysShowStatus": true, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll.eslint": true 5 | }, 6 | "explorer.autoReveal": false 7 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Frank Hübner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cdkdx 2 | > Buildtools for [aws cdk](https://github.com/awslabs/aws-cdk) development 3 | 4 | ## Packages 5 | 6 | This repository is a monorepo managed with [Lerna](https://github.com/lerna/lerna). [Several packages](/packages) are published to npm from the same codebase. 7 | 8 | | Package | Description | 9 | | -------------------------------------------------------- | -------------------------------------------------------------------- | 10 | | [cdkdx](/packages/cdkdx) | Zero-config CLI for aws cdk development | 11 | | [eslint-config-cdk](/packages/eslint-config-cdk) | ESLint configuration used by cdkdx | 12 | | [eslint-plugin-cdk](/packages/eslint-plugin-cdk) | ESLint rules for aws cdk | 13 | 14 | ## License 15 | 16 | [MIT](LICENSE) 17 | -------------------------------------------------------------------------------- /examples/app/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "cdk" 3 | } -------------------------------------------------------------------------------- /examples/app/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage(https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory(https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # Optional npm cache directory 48 | .npm 49 | 50 | # Optional eslint cache 51 | .eslintcache 52 | 53 | # Optional REPL history 54 | .node_repl_history 55 | 56 | # Output of `npm pack` 57 | *.tgz 58 | 59 | # Yarn Integrity file 60 | .yarn-integrity 61 | 62 | # dotenv environment variables file 63 | .env 64 | 65 | # next.js build output 66 | .next 67 | 68 | # cdkdx 69 | .DS_Store 70 | lib 71 | *.tsbuildinfo 72 | tsconfig.json 73 | tsconfig.eslint.json 74 | cdk.out 75 | cdk.context.json -------------------------------------------------------------------------------- /examples/app/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "cdkdx node src/app-app.ts", 3 | "context": { 4 | "@aws-cdk/core:enableStackNameDuplicates": "true", 5 | "aws-cdk:enableDiffNoFail": "true" 6 | } 7 | } -------------------------------------------------------------------------------- /examples/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "private": true, 4 | "license": "MIT", 5 | "author": { 6 | "name": "hupe1980" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/hupe1980/cdkdx.git", 11 | "directory": "example/app" 12 | }, 13 | "version": "1.9.0", 14 | "keywords": [ 15 | "cdk" 16 | ], 17 | "engines": { 18 | "node": ">= 12.22.0" 19 | }, 20 | "scripts": { 21 | "build": "cdkdx build", 22 | "watch": "cdkdx build -w", 23 | "test": "cdkdx test", 24 | "lint": "cdkdx lint", 25 | "upgrade:cdk": "cdkdx upgrade-cdk", 26 | "docgen": "cdkdx docgen", 27 | "cdk": "cdk" 28 | }, 29 | "dependencies": { 30 | "@aws-cdk/core": "^1.181.1", 31 | "source-map-support": "^0.5.20" 32 | }, 33 | "devDependencies": { 34 | "@aws-cdk/assertions": "1.181.1", 35 | "@types/node": "12.12.50", 36 | "aws-cdk": "^1.181.1", 37 | "cdkdx": "^1.9.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/app/src/__tests__/app-stack.test.ts: -------------------------------------------------------------------------------- 1 | import { Template } from '@aws-cdk/assertions'; 2 | import { App } from '@aws-cdk/core'; 3 | import { AppStack } from '../app-stack'; 4 | 5 | test('Empty Stack', () => { 6 | // GIVEN 7 | const app = new App(); 8 | 9 | // WHEN 10 | const stack = new AppStack(app, 'AppStack'); 11 | 12 | // THEN 13 | const template = Template.fromStack(stack); 14 | template.templateMatches({}); 15 | }); 16 | -------------------------------------------------------------------------------- /examples/app/src/app-app.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import 'source-map-support/register'; 3 | 4 | import { App } from '@aws-cdk/core'; 5 | import { AppStack } from './app-stack'; 6 | 7 | const app = new App(); 8 | new AppStack(app, 'AppStack'); 9 | -------------------------------------------------------------------------------- /examples/app/src/app-stack.ts: -------------------------------------------------------------------------------- 1 | import { Construct, Stack, StackProps } from '@aws-cdk/core'; 2 | 3 | export class AppStack extends Stack { 4 | constructor(scope: Construct, id: string, props?: StackProps) { 5 | super(scope, id, props); 6 | 7 | // The code that defines your stack goes here 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/construct/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "cdk" 3 | } -------------------------------------------------------------------------------- /examples/construct/.gitignore: -------------------------------------------------------------------------------- 1 | *.js 2 | !jest.config.js 3 | *.d.ts 4 | node_modules 5 | *.tgz 6 | 7 | # CDK asset staging directory 8 | .cdk.staging 9 | cdk.out 10 | lambda-file-sizes.json 11 | -------------------------------------------------------------------------------- /examples/construct/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "construct", 3 | "private": true, 4 | "version": "1.9.0", 5 | "main": "lib/index.js", 6 | "types": "lib/index.d.ts", 7 | "scripts": { 8 | "build": "cdkdx build", 9 | "watch": "cdkdx build -w", 10 | "test": "cdkdx test", 11 | "lint": "cdkdx lint", 12 | "docgen": "cdkdx docgen", 13 | "package": "cdkdx package", 14 | "cdkdx": "cdkdx" 15 | }, 16 | "peerDependencies": { 17 | "@aws-cdk/aws-lambda": "^1.181.1", 18 | "@aws-cdk/aws-sns": "^1.181.1", 19 | "@aws-cdk/aws-sns-subscriptions": "^1.181.1", 20 | "@aws-cdk/aws-sqs": "^1.181.1", 21 | "@aws-cdk/core": "^1.181.1" 22 | }, 23 | "devDependencies": { 24 | "@aws-cdk/assertions": "1.181.1", 25 | "@aws-cdk/aws-lambda": "1.181.1", 26 | "@aws-cdk/aws-sns": "1.181.1", 27 | "@aws-cdk/aws-sns-subscriptions": "1.181.1", 28 | "@aws-cdk/aws-sqs": "1.181.1", 29 | "@aws-cdk/core": "1.181.1", 30 | "@types/node": "12.12.50", 31 | "axios": "^0.24.0", 32 | "cdkdx": "^1.9.0" 33 | }, 34 | "gitHead": "c9a66a2cd9732cacf54f79f0c5052693d157704d" 35 | } 36 | -------------------------------------------------------------------------------- /examples/construct/src/__tests__/demo-layer.test.ts: -------------------------------------------------------------------------------- 1 | import { Template } from '@aws-cdk/assertions'; 2 | import { App, Stack } from '@aws-cdk/core'; 3 | import { DemoLayer } from '../demo-layer'; 4 | 5 | test('Layer', () => { 6 | const app = new App(); 7 | const stack = new Stack(app, 'TestStack'); 8 | // WHEN 9 | new DemoLayer(stack, 'MyLayerConstruct'); 10 | // THEN 11 | const template = Template.fromStack(stack); 12 | template.hasResource('AWS::Lambda::LayerVersion', {}); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/construct/src/__tests__/example.test.ts: -------------------------------------------------------------------------------- 1 | import { Template } from '@aws-cdk/assertions'; 2 | import { Stack } from '@aws-cdk/core'; 3 | import { Example } from '../example'; 4 | 5 | test('SQS Queue Created', () => { 6 | const stack = new Stack(); 7 | // WHEN 8 | new Example(stack, 'MyTestConstruct'); 9 | // THEN 10 | const template = Template.fromStack(stack); 11 | template.hasResource('AWS::SQS::Queue', {}); 12 | }); 13 | 14 | test('SNS Topic Created!', () => { 15 | const stack = new Stack(); 16 | // WHEN 17 | new Example(stack, 'MyTestConstruct'); 18 | // THEN 19 | const template = Template.fromStack(stack); 20 | template.hasResource('AWS::SNS::Topic', {}); 21 | }); 22 | -------------------------------------------------------------------------------- /examples/construct/src/demo-layer.ts: -------------------------------------------------------------------------------- 1 | import * as crypto from 'crypto'; 2 | import * as fs from 'fs'; 3 | import * as path from 'path'; 4 | import * as lambda from '@aws-cdk/aws-lambda'; 5 | import { Construct } from '@aws-cdk/core'; 6 | 7 | /** 8 | * A demo Lambda layer. 9 | */ 10 | export class DemoLayer extends lambda.LayerVersion { 11 | constructor(scope: Construct, id: string) { 12 | super(scope, id, { 13 | code: lambda.Code.fromAsset(path.join(__dirname, 'layers', 'demo', 'layer.zip'), { 14 | // we hash the Dockerfile (it contains the tools versions) because hashing the zip is non-deterministic 15 | assetHash: hashFile(path.join(__dirname, 'layers', 'demo', 'Dockerfile')), 16 | }), 17 | description: '/opt/demo', 18 | }); 19 | } 20 | } 21 | 22 | function hashFile(fileName: string) { 23 | return crypto.createHash('sha256').update(fs.readFileSync(fileName)).digest('hex'); 24 | } 25 | -------------------------------------------------------------------------------- /examples/construct/src/example.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; 3 | import * as sns from '@aws-cdk/aws-sns'; 4 | import * as subs from '@aws-cdk/aws-sns-subscriptions'; 5 | import * as sqs from '@aws-cdk/aws-sqs'; 6 | import { Construct, Duration } from '@aws-cdk/core'; 7 | 8 | export interface ExampleProps { 9 | /** 10 | * The visibility timeout to be configured on the SQS Queue, in seconds. 11 | * 12 | * @default Duration.seconds(300) 13 | */ 14 | visibilityTimeout?: Duration; 15 | } 16 | 17 | export class Example extends Construct { 18 | /** @returns the ARN of the SQS queue */ 19 | public readonly queueArn: string; 20 | 21 | constructor(scope: Construct, id: string, props: ExampleProps = {}) { 22 | super(scope, id); 23 | 24 | const queue = new sqs.Queue(this, 'ExampleQueue', { 25 | visibilityTimeout: props.visibilityTimeout || Duration.seconds(300), 26 | }); 27 | 28 | const topic = new sns.Topic(this, 'ExampleTopic'); 29 | 30 | topic.addSubscription(new subs.SqsSubscription(queue)); 31 | 32 | this.queueArn = queue.queueArn; 33 | 34 | new Function(this, 'Test1Function', { 35 | runtime: Runtime.NODEJS_14_X, 36 | handler: 'index.handler', 37 | code: Code.fromAsset(path.join(__dirname, 'lambdas', 'test1')), 38 | }); 39 | 40 | new Function(this, 'Test2Function', { 41 | runtime: Runtime.NODEJS_14_X, 42 | handler: 'index.handler', 43 | code: Code.fromAsset(path.join(__dirname, 'lambdas', 'test2')), 44 | }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/construct/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './example'; 2 | export * from './demo-layer'; 3 | -------------------------------------------------------------------------------- /examples/construct/src/lambdas/shared/index.ts: -------------------------------------------------------------------------------- 1 | export const shared = 'SHARED'; 2 | -------------------------------------------------------------------------------- /examples/construct/src/lambdas/test1/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | test('Dummy', () => { 2 | expect('foo').toBe('foo'); 3 | }); 4 | -------------------------------------------------------------------------------- /examples/construct/src/lambdas/test1/index.ts: -------------------------------------------------------------------------------- 1 | import type { Handler } from 'aws-lambda'; 2 | import axios from 'axios'; 3 | 4 | import { shared } from '../shared'; 5 | 6 | export const handler: Handler = async () => { 7 | console.log(shared); 8 | 9 | const response = await axios.get('http://google.com'); 10 | 11 | console.log(response); 12 | }; 13 | -------------------------------------------------------------------------------- /examples/construct/src/lambdas/test2/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import axios from 'axios'; 3 | 4 | export const handler = async () => { 5 | console.log(path.join(__dirname)); 6 | 7 | const response = await axios.get('http://google.com'); 8 | 9 | console.log(response); 10 | }; 11 | -------------------------------------------------------------------------------- /examples/construct/src/lambdas/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "alwaysStrict": true, 4 | "charset": "utf8", 5 | "declaration": false, 6 | "experimentalDecorators": true, 7 | "esModuleInterop": true, 8 | "sourceMap": true, 9 | "inlineSources": true, 10 | "lib": [ 11 | "es2018" 12 | ], 13 | "module": "CommonJS", 14 | "noEmit": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "noImplicitAny": true, 17 | "noImplicitReturns": true, 18 | "noImplicitThis": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "resolveJsonModule": true, 22 | "strict": true, 23 | "strictNullChecks": true, 24 | "strictPropertyInitialization": true, 25 | "stripInternal": true, 26 | "target": "ES2018", 27 | "jsx": "react" 28 | }, 29 | "exclude": [ 30 | "**/__tests__/*" 31 | ], 32 | "include": [ 33 | "**/*.ts", 34 | "**/*.tsx" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /examples/construct/src/layers/demo/.dockerignore: -------------------------------------------------------------------------------- 1 | layer.zip -------------------------------------------------------------------------------- /examples/construct/src/layers/demo/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM public.ecr.aws/lambda/provided:latest 2 | 3 | ARG asset_name 4 | ARG KUBECTL_VERSION=1.20.0 5 | 6 | USER root 7 | RUN mkdir -p /opt 8 | WORKDIR /opt 9 | 10 | # 11 | # tools 12 | # 13 | 14 | RUN yum update -y && yum install -y zip 15 | 16 | # 17 | # layer 18 | # 19 | 20 | RUN mkdir -p /opt/kubectl 21 | RUN cd /opt/kubectl && curl -LO "https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl" 22 | RUN chmod +x /opt/kubectl/kubectl 23 | 24 | # 25 | # create the bundle 26 | # 27 | 28 | RUN zip --symlinks -r ../$asset_name * 29 | 30 | WORKDIR / 31 | ENTRYPOINT [ "/bin/bash" ] -------------------------------------------------------------------------------- /examples/construct/src/layers/demo/layer.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hupe1980/cdkdx/f83a96f79ef9a438ecc7bee39a0c992f4a08c83a/examples/construct/src/layers/demo/layer.zip -------------------------------------------------------------------------------- /examples/construct/tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "alwaysStrict": true, 4 | "charset": "utf8", 5 | "declaration": true, 6 | "experimentalDecorators": true, 7 | "inlineSourceMap": true, 8 | "inlineSources": true, 9 | "lib": [ 10 | "es2018" 11 | ], 12 | "module": "CommonJS", 13 | "noEmitOnError": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noImplicitAny": true, 16 | "noImplicitReturns": true, 17 | "noImplicitThis": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "resolveJsonModule": true, 21 | "strict": true, 22 | "strictNullChecks": true, 23 | "strictPropertyInitialization": true, 24 | "stripInternal": true, 25 | "target": "ES2018" 26 | }, 27 | "include": [ 28 | "src/**/*.ts", 29 | "src/**/*.tsx" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /examples/construct/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "alwaysStrict": true, 4 | "charset": "utf8", 5 | "declaration": true, 6 | "experimentalDecorators": true, 7 | "inlineSourceMap": true, 8 | "inlineSources": true, 9 | "lib": [ 10 | "es2018" 11 | ], 12 | "module": "CommonJS", 13 | "noEmitOnError": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noImplicitAny": true, 16 | "noImplicitReturns": true, 17 | "noImplicitThis": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "resolveJsonModule": true, 21 | "strict": true, 22 | "strictNullChecks": true, 23 | "strictPropertyInitialization": true, 24 | "stripInternal": true, 25 | "target": "ES2018", 26 | "outDir": "./lib" 27 | }, 28 | "include": [ 29 | "src" 30 | ], 31 | "exclude": [ 32 | "src/lambdas", 33 | "src/**/__tests__" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /examples/jsii-construct/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "cdk" 3 | } -------------------------------------------------------------------------------- /examples/jsii-construct/.gitignore: -------------------------------------------------------------------------------- 1 | *.js 2 | !jest.config.js 3 | *.d.ts 4 | node_modules 5 | *.tgz 6 | 7 | # CDK asset staging directory 8 | .cdk.staging 9 | cdk.out 10 | lambda-file-sizes.json 11 | tsconfig.json 12 | .jsii 13 | -------------------------------------------------------------------------------- /examples/jsii-construct/.npmignore: -------------------------------------------------------------------------------- 1 | 2 | # Exclude typescript source and config 3 | *.ts 4 | tsconfig.json 5 | 6 | # Include javascript files and typescript declarations 7 | !*.js 8 | !*.d.ts 9 | 10 | # Exclude jsii outdir 11 | dist 12 | 13 | # Include .jsii 14 | !.jsii 15 | -------------------------------------------------------------------------------- /examples/jsii-construct/API.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | @test/jsii-construct 4 | 5 | # @test/jsii-construct 6 | 7 | ## Table of contents 8 | 9 | ### Classes 10 | 11 | - [Example](#example) 12 | 13 | ### Interfaces 14 | 15 | - [ExampleProps](#example-props) 16 | 17 | # Example 18 | 19 | [@test/jsii-construct](#readme) / Example 20 | 21 | # Class: Example 22 | 23 | ## Hierarchy 24 | 25 | - `Construct` 26 | 27 | ↳ **`Example`** 28 | 29 | ## Table of contents 30 | 31 | ### Constructors 32 | 33 | - [constructor](#constructor) 34 | 35 | ### Properties 36 | 37 | - [node](#node) 38 | - [queueArn](#queuearn) 39 | 40 | ### Methods 41 | 42 | - [onPrepare](#onprepare) 43 | - [onSynthesize](#onsynthesize) 44 | - [onValidate](#onvalidate) 45 | - [prepare](#prepare) 46 | - [synthesize](#synthesize) 47 | - [toString](#tostring) 48 | - [validate](#validate) 49 | - [isConstruct](#isconstruct) 50 | 51 | ## Constructors 52 | 53 | ### constructor 54 | 55 | • **new Example**(`scope`, `id`, `props?`) 56 | 57 | #### Parameters 58 | 59 | | Name | Type | 60 | | :------ | :------ | 61 | | `scope` | `Construct` | 62 | | `id` | `string` | 63 | | `props` | [`ExampleProps`](#example-props) | 64 | 65 | #### Overrides 66 | 67 | cdk.Construct.constructor 68 | 69 | ## Properties 70 | 71 | ### node 72 | 73 | • `Readonly` **node**: `ConstructNode` 74 | 75 | The construct tree node associated with this construct. 76 | 77 | #### Inherited from 78 | 79 | cdk.Construct.node 80 | 81 | ___ 82 | 83 | ### queueArn 84 | 85 | • `Readonly` **queueArn**: `string` 86 | 87 | ## Methods 88 | 89 | ### onPrepare 90 | 91 | ▸ `Protected` **onPrepare**(): `void` 92 | 93 | Perform final modifications before synthesis 94 | 95 | This method can be implemented by derived constructs in order to perform 96 | final changes before synthesis. prepare() will be called after child 97 | constructs have been prepared. 98 | 99 | This is an advanced framework feature. Only use this if you 100 | understand the implications. 101 | 102 | #### Returns 103 | 104 | `void` 105 | 106 | #### Inherited from 107 | 108 | cdk.Construct.onPrepare 109 | 110 | ___ 111 | 112 | ### onSynthesize 113 | 114 | ▸ `Protected` **onSynthesize**(`session`): `void` 115 | 116 | Allows this construct to emit artifacts into the cloud assembly during synthesis. 117 | 118 | This method is usually implemented by framework-level constructs such as `Stack` and `Asset` 119 | as they participate in synthesizing the cloud assembly. 120 | 121 | #### Parameters 122 | 123 | | Name | Type | Description | 124 | | :------ | :------ | :------ | 125 | | `session` | `ISynthesisSession` | The synthesis session. | 126 | 127 | #### Returns 128 | 129 | `void` 130 | 131 | #### Inherited from 132 | 133 | cdk.Construct.onSynthesize 134 | 135 | ___ 136 | 137 | ### onValidate 138 | 139 | ▸ `Protected` **onValidate**(): `string`[] 140 | 141 | Validate the current construct. 142 | 143 | This method can be implemented by derived constructs in order to perform 144 | validation logic. It is called on all constructs before synthesis. 145 | 146 | #### Returns 147 | 148 | `string`[] 149 | 150 | An array of validation error messages, or an empty array if the construct is valid. 151 | 152 | #### Inherited from 153 | 154 | cdk.Construct.onValidate 155 | 156 | ___ 157 | 158 | ### prepare 159 | 160 | ▸ `Protected` **prepare**(): `void` 161 | 162 | Perform final modifications before synthesis 163 | 164 | This method can be implemented by derived constructs in order to perform 165 | final changes before synthesis. prepare() will be called after child 166 | constructs have been prepared. 167 | 168 | This is an advanced framework feature. Only use this if you 169 | understand the implications. 170 | 171 | #### Returns 172 | 173 | `void` 174 | 175 | #### Inherited from 176 | 177 | cdk.Construct.prepare 178 | 179 | ___ 180 | 181 | ### synthesize 182 | 183 | ▸ `Protected` **synthesize**(`session`): `void` 184 | 185 | Allows this construct to emit artifacts into the cloud assembly during synthesis. 186 | 187 | This method is usually implemented by framework-level constructs such as `Stack` and `Asset` 188 | as they participate in synthesizing the cloud assembly. 189 | 190 | #### Parameters 191 | 192 | | Name | Type | Description | 193 | | :------ | :------ | :------ | 194 | | `session` | `ISynthesisSession` | The synthesis session. | 195 | 196 | #### Returns 197 | 198 | `void` 199 | 200 | #### Inherited from 201 | 202 | cdk.Construct.synthesize 203 | 204 | ___ 205 | 206 | ### toString 207 | 208 | ▸ **toString**(): `string` 209 | 210 | Returns a string representation of this construct. 211 | 212 | #### Returns 213 | 214 | `string` 215 | 216 | #### Inherited from 217 | 218 | cdk.Construct.toString 219 | 220 | ___ 221 | 222 | ### validate 223 | 224 | ▸ `Protected` **validate**(): `string`[] 225 | 226 | Validate the current construct. 227 | 228 | This method can be implemented by derived constructs in order to perform 229 | validation logic. It is called on all constructs before synthesis. 230 | 231 | #### Returns 232 | 233 | `string`[] 234 | 235 | An array of validation error messages, or an empty array if the construct is valid. 236 | 237 | #### Inherited from 238 | 239 | cdk.Construct.validate 240 | 241 | ___ 242 | 243 | ### isConstruct 244 | 245 | ▸ `Static` **isConstruct**(`x`): x is Construct 246 | 247 | Return whether the given object is a Construct 248 | 249 | #### Parameters 250 | 251 | | Name | Type | 252 | | :------ | :------ | 253 | | `x` | `any` | 254 | 255 | #### Returns 256 | 257 | x is Construct 258 | 259 | #### Inherited from 260 | 261 | cdk.Construct.isConstruct 262 | 263 | # Example Props 264 | 265 | [@test/jsii-construct](#readme) / ExampleProps 266 | 267 | # Interface: ExampleProps 268 | 269 | ## Table of contents 270 | 271 | ### Properties 272 | 273 | - [visibilityTimeout](#visibilitytimeout) 274 | 275 | ## Properties 276 | 277 | ### visibilityTimeout 278 | 279 | • `Optional` `Readonly` **visibilityTimeout**: `Duration` 280 | 281 | The visibility timeout to be configured on the SQS Queue, in seconds. 282 | 283 | **`Default`** 284 | 285 | Duration.seconds(300) 286 | -------------------------------------------------------------------------------- /examples/jsii-construct/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hupe1980/cdkdx/f83a96f79ef9a438ecc7bee39a0c992f4a08c83a/examples/jsii-construct/README.md -------------------------------------------------------------------------------- /examples/jsii-construct/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@test/jsii-construct", 3 | "private": true, 4 | "license": "MIT", 5 | "author": { 6 | "name": "hupe1980" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/hupe1980/cdkdx", 11 | "directory": "example/jsii-construct" 12 | }, 13 | "version": "1.9.0", 14 | "main": "lib/index.js", 15 | "types": "lib/index.d.ts", 16 | "scripts": { 17 | "build": "cdkdx build", 18 | "watch": "cdkdx build -w", 19 | "test": "cdkdx test", 20 | "lint": "cdkdx lint", 21 | "docgen": "cdkdx docgen", 22 | "package": "cdkdx package", 23 | "cdkdx": "cdkdx" 24 | }, 25 | "jsii": { 26 | "outdir": "dist", 27 | "tsc": { 28 | "outDir": "./lib" 29 | }, 30 | "excludeTypescript": [ 31 | "src/lambdas", 32 | "src/**/__tests__" 33 | ], 34 | "targets": { 35 | "python": { 36 | "distName": "cdkdx.jsii-construct", 37 | "module": "cdkdx.jsii_construct" 38 | } 39 | } 40 | }, 41 | "peerDependencies": { 42 | "@aws-cdk/aws-lambda": "^1.181.1", 43 | "@aws-cdk/aws-sns": "^1.181.1", 44 | "@aws-cdk/aws-sns-subscriptions": "^1.181.1", 45 | "@aws-cdk/aws-sqs": "^1.181.1", 46 | "@aws-cdk/core": "^1.181.1", 47 | "constructs": "^3.0.2" 48 | }, 49 | "devDependencies": { 50 | "@aws-cdk/assertions": "1.181.1", 51 | "@aws-cdk/aws-lambda": "1.181.1", 52 | "@aws-cdk/aws-sns": "1.181.1", 53 | "@aws-cdk/aws-sns-subscriptions": "1.181.1", 54 | "@aws-cdk/aws-sqs": "1.181.1", 55 | "@aws-cdk/core": "1.181.1", 56 | "@types/node": "12.12.50", 57 | "axios": "^0.24.0", 58 | "cdkdx": "^1.9.0", 59 | "constructs": "3.0.2" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/jsii-construct/src/__tests__/example.test.ts: -------------------------------------------------------------------------------- 1 | import { Template } from '@aws-cdk/assertions'; 2 | import { App, Stack } from '@aws-cdk/core'; 3 | import { Example } from '../index'; 4 | 5 | test('SQS Queue Created', () => { 6 | const app = new App(); 7 | const stack = new Stack(app, 'TestStack'); 8 | // WHEN 9 | new Example(stack, 'MyTestConstruct'); 10 | // THEN 11 | const template = Template.fromStack(stack); 12 | template.hasResource('AWS::SQS::Queue', {}); 13 | }); 14 | 15 | test('SNS Topic Created', () => { 16 | const app = new App(); 17 | const stack = new Stack(app, 'TestStack'); 18 | // WHEN 19 | new Example(stack, 'MyTestConstruct'); 20 | // THEN 21 | const template = Template.fromStack(stack); 22 | template.hasResource('AWS::SNS::Topic', {}); 23 | }); 24 | -------------------------------------------------------------------------------- /examples/jsii-construct/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; 3 | import * as sns from '@aws-cdk/aws-sns'; 4 | import * as subs from '@aws-cdk/aws-sns-subscriptions'; 5 | import * as sqs from '@aws-cdk/aws-sqs'; 6 | import * as cdk from '@aws-cdk/core'; 7 | 8 | export interface ExampleProps { 9 | /** 10 | * The visibility timeout to be configured on the SQS Queue, in seconds. 11 | * 12 | * @default Duration.seconds(300) 13 | */ 14 | readonly visibilityTimeout?: cdk.Duration; 15 | } 16 | 17 | export class Example extends cdk.Construct { 18 | /** @returns the ARN of the SQS queue */ 19 | public readonly queueArn: string; 20 | 21 | constructor(scope: cdk.Construct, id: string, props: ExampleProps = {}) { 22 | super(scope, id); 23 | 24 | const queue = new sqs.Queue(this, 'ExampleQueue', { 25 | visibilityTimeout: props.visibilityTimeout || cdk.Duration.seconds(300), 26 | }); 27 | 28 | const topic = new sns.Topic(this, 'ExampleTopic'); 29 | 30 | topic.addSubscription(new subs.SqsSubscription(queue)); 31 | 32 | this.queueArn = queue.queueArn; 33 | 34 | new Function(this, 'Test1Function', { 35 | runtime: Runtime.NODEJS_14_X, 36 | handler: 'index.handler', 37 | code: Code.fromAsset(path.join(__dirname, 'lambdas', 'test1')), 38 | }); 39 | 40 | new Function(this, 'Test2Function', { 41 | runtime: Runtime.NODEJS_14_X, 42 | handler: 'index.handler', 43 | code: Code.fromAsset(path.join(__dirname, 'lambdas', 'test2')), 44 | }); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/jsii-construct/src/lambdas/test1/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import axios from 'axios'; 3 | 4 | export const handler = async () => { 5 | console.log(path.join(__dirname)); 6 | 7 | const response = await axios.get('http://google.com'); 8 | 9 | console.log(response); 10 | }; 11 | -------------------------------------------------------------------------------- /examples/jsii-construct/src/lambdas/test2/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import axios from 'axios'; 3 | 4 | export const handler = async () => { 5 | console.log(path.join(__dirname)); 6 | 7 | const response = await axios.get('http://google.com'); 8 | 9 | console.log(response); 10 | }; 11 | -------------------------------------------------------------------------------- /examples/jsii-construct/tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "alwaysStrict": true, 4 | "charset": "utf8", 5 | "declaration": true, 6 | "experimentalDecorators": true, 7 | "inlineSourceMap": true, 8 | "inlineSources": true, 9 | "lib": [ 10 | "es2018" 11 | ], 12 | "module": "CommonJS", 13 | "noEmitOnError": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noImplicitAny": true, 16 | "noImplicitReturns": true, 17 | "noImplicitThis": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "resolveJsonModule": true, 21 | "strict": true, 22 | "strictNullChecks": true, 23 | "strictPropertyInitialization": true, 24 | "stripInternal": true, 25 | "target": "ES2018" 26 | }, 27 | "include": [ 28 | "src/**/*.ts", 29 | "src/**/*.tsx" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /examples/react/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "cdk" 3 | } -------------------------------------------------------------------------------- /examples/react/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage(https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory(https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # Optional npm cache directory 48 | .npm 49 | 50 | # Optional eslint cache 51 | .eslintcache 52 | 53 | # Optional REPL history 54 | .node_repl_history 55 | 56 | # Output of `npm pack` 57 | *.tgz 58 | 59 | # Yarn Integrity file 60 | .yarn-integrity 61 | 62 | # dotenv environment variables file 63 | .env 64 | 65 | # next.js build output 66 | .next 67 | 68 | # cdkdx 69 | .DS_Store 70 | lib 71 | *.tsbuildinfo 72 | tsconfig.json 73 | tsconfig.eslint.json 74 | cdk.out 75 | cdk.context.json -------------------------------------------------------------------------------- /examples/react/cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "cdkdx node src/react-app.ts", 3 | "context": { 4 | "@aws-cdk/core:enableStackNameDuplicates": "true", 5 | "aws-cdk:enableDiffNoFail": "true" 6 | } 7 | } -------------------------------------------------------------------------------- /examples/react/lambda-file-sizes.json: -------------------------------------------------------------------------------- 1 | [{"timestamp":1643739651734,"files":[{"filename":"web/index.js","previous":12214,"size":11956,"diff":-258}]},{"timestamp":1643739111989,"files":[{"filename":"web/index.js","previous":11956,"size":12214,"diff":258}]},{"timestamp":1643738673719,"files":[{"filename":"web/index.js","previous":12214,"size":11956,"diff":-258}]},{"timestamp":1643732326850,"files":[{"filename":"web/index.js","previous":1415,"size":12214,"diff":10799}]},{"timestamp":1643731917046,"files":[{"filename":"web/index.js","previous":11956,"size":1415,"diff":-10541}]},{"timestamp":1640640051178,"files":[{"filename":"web/index.js","previous":0,"size":11956,"diff":11956}]}] 2 | -------------------------------------------------------------------------------- /examples/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react", 3 | "private": true, 4 | "license": "MIT", 5 | "author": { 6 | "name": "hupe1980" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/hupe1980/cdkdx.git", 11 | "directory": "example/react" 12 | }, 13 | "version": "1.9.0", 14 | "keywords": [ 15 | "cdk" 16 | ], 17 | "engines": { 18 | "node": ">= 12.22.0" 19 | }, 20 | "scripts": { 21 | "build": "cdkdx build", 22 | "watch": "cdkdx build -w", 23 | "test": "cdkdx test", 24 | "lint": "cdkdx lint", 25 | "upgrade:cdk": "cdkdx upgrade-cdk", 26 | "docgen": "cdkdx docgen", 27 | "cdk": "cdk" 28 | }, 29 | "dependencies": { 30 | "@aws-cdk/aws-apigateway": "1.181.1", 31 | "@aws-cdk/aws-lambda": "1.181.1", 32 | "@aws-cdk/core": "1.181.1", 33 | "source-map-support": "^0.5.20" 34 | }, 35 | "devDependencies": { 36 | "@aws-cdk/assertions": "1.181.1", 37 | "@types/node": "12.12.50", 38 | "@types/react": "^17.0.20", 39 | "@types/react-dom": "^17.0.9", 40 | "aws-cdk": "^1.181.1", 41 | "cdkdx": "^1.9.0", 42 | "react": "^17.0.2", 43 | "react-dom": "^17.0.2" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/react/src/__tests__/react-stack.test.ts: -------------------------------------------------------------------------------- 1 | import { Template } from '@aws-cdk/assertions'; 2 | import { App } from '@aws-cdk/core'; 3 | import { ReactStack } from '../react-stack'; 4 | 5 | test('SSR Stack', () => { 6 | // GIVEN 7 | const app = new App(); 8 | 9 | // WHEN 10 | const stack = new ReactStack(app, 'ReactStack'); 11 | 12 | // THEN 13 | const template = Template.fromStack(stack as any); 14 | template.hasResource('AWS::Lambda::Function', {}); 15 | template.hasResource('AWS::ApiGateway::Resource', {}); 16 | }); 17 | -------------------------------------------------------------------------------- /examples/react/src/lambdas/web/app.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const App =() => { 4 | return ( 5 |
6 | Hello World 7 |
8 | ) 9 | } 10 | 11 | export default App; -------------------------------------------------------------------------------- /examples/react/src/lambdas/web/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOMServer from 'react-dom/server'; 3 | 4 | import App from './app'; 5 | 6 | const indexFile = ` 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | React App 18 | 19 | 20 | 21 |
22 |
Rendered on Server
23 | 24 | `; 25 | 26 | export const handler = async () => { 27 | const app = ReactDOMServer.renderToString(); 28 | const html = indexFile.replace( 29 | '
', 30 | `
${app}
` 31 | ); 32 | 33 | return { 34 | statusCode: 200, 35 | headers: { "Content-Type": "text/html" }, 36 | body: html, 37 | }; 38 | }; 39 | -------------------------------------------------------------------------------- /examples/react/src/react-app.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | import 'source-map-support/register'; 3 | 4 | import { App } from '@aws-cdk/core'; 5 | import { ReactStack } from './react-stack'; 6 | 7 | const app = new App(); 8 | new ReactStack(app, 'ReactStack'); 9 | -------------------------------------------------------------------------------- /examples/react/src/react-stack.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import { LambdaRestApi } from '@aws-cdk/aws-apigateway'; 3 | import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; 4 | import { Construct, Stack, StackProps } from '@aws-cdk/core'; 5 | 6 | export class ReactStack extends Stack { 7 | constructor(scope: Construct, id: string, props?: StackProps) { 8 | super(scope, id, props); 9 | 10 | const ssrFunction = new Function(this, 'Test1Function', { 11 | runtime: Runtime.NODEJS_14_X, 12 | handler: 'index.handler', 13 | code: Code.fromAsset(path.join(process.env.LAMBDAS as string, 'web')), 14 | }); 15 | 16 | new LambdaRestApi(this, 'SSREndpoint', { 17 | handler: ssrFunction, 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { "npmClient": "yarn", "useWorkspaces": true, "version": "1.9.0" } 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "private": true, 4 | "scripts": { 5 | "outdated:all": "yarn outdated", 6 | "upgrade:all": "yarn upgrade-interactive --latest", 7 | "prepare": "yarn build", 8 | "build": "cross-env FORCE_COLOR=1 lerna run build", 9 | "watch": "cross-env FORCE_COLOR=1 lerna run watch", 10 | "test:unit": "lerna run test", 11 | "test:tsc-integration": "cd examples/construct && yarn build && yarn docgen && yarn test && yarn lint", 12 | "test:jsii-integration": "cd examples/jsii-construct && yarn build && yarn docgen && yarn test && yarn lint", 13 | "test:app-integration": "cd examples/app && yarn build && yarn docgen && yarn test && yarn lint && yarn cdk synth", 14 | "lint": "eslint '*/**/*.ts' --report-unused-disable-directives", 15 | "lint:fix": "eslint '*/**/*.ts' --fix" 16 | }, 17 | "workspaces": [ 18 | "packages/*", 19 | "examples/*" 20 | ], 21 | "resolutions": { 22 | "@types/prettier": "2.6.0" 23 | }, 24 | "devDependencies": { 25 | "@typescript-eslint/eslint-plugin": "^5.4.0", 26 | "@typescript-eslint/parser": "^5.4.0", 27 | "cross-env": "^7.0.3", 28 | "eslint": "^8.3.0", 29 | "eslint-config-prettier": "^8.2.0", 30 | "eslint-plugin-prettier": "^4.0.0", 31 | "lerna": "^6.1.0", 32 | "prettier": "^2.2.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/cdkdx/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Frank Hübner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/cdkdx/README.md: -------------------------------------------------------------------------------- 1 | # cdkdx 2 | 3 | > Zero-config CLI for [aws cdk](https://github.com/awslabs/aws-cdk) development 4 | 5 | - [Features](#features) 6 | - [Quick Start](#quick-start) 7 | - [Folder structures](#folder-structures) 8 | - [App](#app) 9 | - [Lib](#lib) 10 | - [Lambda development](#lambda-development) 11 | - [Lambda Layer support](#lambda-layer-support) 12 | - [Optimizations](#optimizations) 13 | - [Moment.js](#moment.js) 14 | - [Customization](#customization) 15 | - [Displaying Lint Output in the Editor](#displaying-lint-output-in-the-editor) 16 | - [Colored output during execution with lerna run](#colored-output-during-execution-with-lerna-run) 17 | - [Extending webpack config](#extending-webpack-config) 18 | - [Extending Typescript config](#extending-typescript-config) 19 | - [API Reference](#api-reference) 20 | - [`cdkdx build`](#cdkdx-build) 21 | - [`cdkdx lint`](#cdkdx-lint) 22 | - [`cdkdx test`](#cdkdx-test) 23 | - [`cdkdx docgen`](#cdkdx-docgen) 24 | - [`cdkdx bump`](#cdkdx-bump) 25 | - [`cdkdx release`](#cdkdx-release) 26 | - [`cdkdx upgrade-cdk`](#cdkdx-upgrade-cdk) 27 | - [`cdkdx node`](#cdkdx-node) 28 | - [`cdkdx create`](#cdkdx-create) 29 | - [Example](#example) 30 | - [License](#license) 31 | 32 | ## Features 33 | 34 | - [Tsc](https://github.com/microsoft/TypeScript) and [jsii](https://github.com/aws/jsii) compiler support 35 | - Pre-configured linter with [custom cdk eslint rules](https://github.com/hupe1980/cdkdx/blob/master/packages/eslint-config-cdk) 36 | - Jest test runner setup for testing lambdas and constructs 37 | - Bundles your lambda functions with webpack 38 | - Typechecking for lambdas and constructs 39 | - Yarn workspaces compatible 40 | - Generates docs for your project 41 | - Lambda layer support 42 | - [React SSR support](../../examples/react) 43 | 44 | ## Quick Start 45 | 46 | ```sh 47 | npx cdkdx create app my-app 48 | cd my-app 49 | ``` 50 | 51 | ```sh 52 | npx cdkdx create lib my-construct 53 | cd my-construct 54 | ``` 55 | 56 | ```sh 57 | npx cdkdx create jsii-lib my-jsii-construct 58 | cd my-jsii-construct 59 | ``` 60 | 61 | ## Folder structures 62 | 63 | ### App 64 | 65 | ``` 66 | my-app 67 | ├── API.md 68 | ├── README.md 69 | ├── LICENCE 70 | ├── node_modules 71 | ├── package.json 72 | ├── .gitignore 73 | ├── tsconfig.json 74 | ├── tsconfig.eslint.json 75 | ├── cdk.json 76 | └── src 77 | ├── __tests__ 78 | ├── lambdas 79 | │ ├── tsconfig.json 80 | │ ├── lambda1 81 | │ │ ├── __tests__ 82 | │ │ └── index.ts 83 | │ ├── lambda2 84 | │ │ └── index.ts 85 | │ └── shared 86 | ├── layers 87 | │ └── demo 88 | │ │ ├── .dockerignore 89 | │ │ ├── layer.zip //dummy 90 | │ │ └── Dockerfile 91 | ├── my-app.ts 92 | └── my-stack.ts 93 | ``` 94 | 95 | ```json 96 | // cdk.json 97 | { 98 | "app": "cdkdx node src/my-app.ts" 99 | } 100 | ``` 101 | 102 | ### Lib 103 | 104 | ``` 105 | my-construct 106 | ├── API.md 107 | ├── README.md 108 | ├── LICENCE 109 | ├── node_modules 110 | ├── package.json 111 | ├── .gitignore 112 | ├── tsconfig.json 113 | ├── tsconfig.eslint.json 114 | └── src 115 | ├── __tests__ 116 | ├── lambdas 117 | │ ├── tsconfig.json 118 | │ ├── lambda1 119 | │ │ ├── __tests__ 120 | │ │ └── index.ts 121 | │ ├── lambda2 122 | │ │ └── index.ts 123 | │ └── shared 124 | ├── layers 125 | │ └── demo 126 | │ │ ├── .dockerignore 127 | │ │ ├── layer.zip //dummy 128 | │ │ └── Dockerfile 129 | ├── index.ts 130 | └── my-construct.ts 131 | ``` 132 | 133 | ## Lambda development 134 | 135 | - Create a separate folder for each lambda 136 | - The file `index.ts` must export the handler function 137 | - LambdaDependencies should be added as devDependencies 138 | - @types/aws-lambda must be used as type only import: 139 | 140 | ```typescript 141 | import type { Handler } from 'aws-lambda'; 142 | ``` 143 | - To exclude dependencies when bundling the lambda, an `externals` section can be added in the package.json: 144 | 145 | ```json 146 | // package.json 147 | 148 | { 149 | "name": "construct", 150 | ... 151 | "externals": [ 152 | "aws-sdk" 153 | ] 154 | } 155 | ``` 156 | - Use the `nodeModules` section to specify a list of modules that should not be bundled but instead included in the node_modules folder of the Lambda package. 157 | 158 | ```json 159 | // package.json 160 | 161 | { 162 | "name": "construct", 163 | ... 164 | "nodeModules": [ 165 | "express" 166 | ] 167 | } 168 | ``` 169 | - Cross lambda code should be placed in the `/src/lambdas/shared` folder 170 | - The Path must be passed to the aws-lambda construct with a code object: 171 | 172 | ```typescript 173 | // construct.ts 174 | 175 | import { Code, Function, Runtime } from '@aws-cdk/aws-lambda'; 176 | 177 | // ... 178 | 179 | new Function(this, 'Lambda1', { 180 | runtime: Runtime.NODEJS_12_X, 181 | handler: 'index.handler', 182 | code: Code.fromAsset(path.join(__dirname, 'lambdas', 'lambda1')), 183 | }); 184 | ``` 185 | 186 | ## Lambda Layer support 187 | 188 | - Create a separate folder for each layer 189 | - The folder must contain a Dockerfile 190 | - Add a dummy layer.zip file to prevent test cases from aborting 191 | - Docker muss be installed! 192 | 193 | ```typescript 194 | import * as crypto from 'crypto'; 195 | import * as fs from 'fs'; 196 | import * as path from 'path'; 197 | import * as lambda from '@aws-cdk/aws-lambda'; 198 | import { Construct } from '@aws-cdk/core'; 199 | 200 | /** 201 | * A demo Lambda layer. 202 | */ 203 | export class DemoLayer extends lambda.LayerVersion { 204 | constructor(scope: Construct, id: string) { 205 | super(scope, id, { 206 | code: lambda.Code.fromAsset(path.join(__dirname, 'layers', 'demo', 'layer.zip'), { 207 | // we hash the Dockerfile (it contains the tools versions) because hashing the zip is non-deterministic 208 | assetHash: hashFile(path.join(__dirname, 'layers', 'demo', 'Dockerfile')), 209 | }), 210 | description: '/opt/demo', 211 | }); 212 | } 213 | } 214 | 215 | function hashFile(fileName: string) { 216 | return crypto 217 | .createHash('sha256') 218 | .update(fs.readFileSync(fileName)) 219 | .digest('hex'); 220 | } 221 | ``` 222 | 223 | ## Optimizations 224 | 225 | ### Moment.js 226 | If you use [Moment.js](https://momentjs.com/), only the English locale is available by default. To add a specific Moment.js locale to your bundle, you need to import it explicitly. 227 | 228 | ```typescript 229 | import moment from 'moment'; 230 | import 'moment/locale/fr'; 231 | ``` 232 | 233 | ## Customization 234 | 235 | ### Displaying Lint Output in the Editor 236 | 237 | You would need to install an ESLint plugin for your editor first. Then, add a file called `.eslintrc.json` to the project root: 238 | 239 | ```json 240 | { 241 | "extends": "cdk" 242 | } 243 | ``` 244 | 245 | ### Colored output during execution with lerna run 246 | ```json 247 | // package.json 248 | "scripts": { 249 | "build": "FORCE_COLOR=1 lerna run build" 250 | } 251 | ``` 252 | 253 | ### Extending webpack config 254 | To extend the configuration, create a cdkdx.config.js file at the root of your project und use the webpack field: 255 | 256 | ```javascript 257 | // cdkdx.config.js 258 | 259 | module.exports = { 260 | webpack: (config, projectInfo) => config 261 | } 262 | ``` 263 | Make sure to preserve the following config options: 264 | - entry 265 | - output 266 | 267 | ### Extending Typescript config 268 | To extend the typescript configuration, create a cdkdx.config.js config file as described above. 269 | Use the lambdaTsConfig field, which gives you a partial configuration object (and project info as second argument). 270 | ```javascript 271 | module.exports = { 272 | lambdaTsConfig: (config, projectInfo) => { 273 | config.compilerOptions = { 274 | experimentalDecorators: true, 275 | emitDecoratorMetadata: true 276 | } 277 | 278 | return config; 279 | } 280 | } 281 | ``` 282 | ## API Reference 283 | 284 | ### `cdkdx build` 285 | ```shell 286 | Build the project 287 | 288 | Usage: 289 | 290 | $ cdkdx build [-w] [--watch] [--minify-lambdas] [--ignore-layers] 291 | 292 | Details: 293 | 294 | This command will bundle the lambdas, build the layers and build the project. 295 | 296 | Examples: 297 | 298 | Build the project 299 | $ cdkdx build 300 | 301 | Rebuilds on any change 302 | $ cdkdx build -w 303 | ``` 304 | 305 | ### `cdkdx lint` 306 | ```shell 307 | Run eslint with prettier and custom cdk rules 308 | 309 | Usage: 310 | 311 | $ cdkdx lint [--fix] [--cache] [--report-unused-disable-directives] 312 | 313 | Details: 314 | 315 | This command runs eslint with prettier. 316 | 317 | Examples: 318 | 319 | Run linting 320 | $ cdkdx lint 321 | 322 | Fix fixable errors and warnings 323 | $ cdkdx lint --fix 324 | ``` 325 | 326 | ### `cdkdx test` 327 | ```shell 328 | Run jest test runner 329 | 330 | Usage: 331 | 332 | $ cdkdx test 333 | 334 | Details: 335 | 336 | All flags are passed through directly to jest. 337 | 338 | Examples: 339 | 340 | Run jest test runner 341 | $ cdkdx test 342 | 343 | Run jest test runner in watch mode 344 | $ cdkdx test --watch 345 | ``` 346 | 347 | ### `cdkdx docgen` 348 | ```shell 349 | Generate docs for the project 350 | 351 | $ cdkdx docgen 352 | ``` 353 | 354 | ### `cdkdx bump` 355 | 356 | ### `cdkdx release` 357 | ```shell 358 | Release the project 359 | 360 | Usage: 361 | 362 | $ cdkdx release 363 | 364 | Details: 365 | 366 | This command releases the project to npm, pypi or both. 367 | 368 | It is checked whether the package version is not yet registered. If the version is not in the registry, it will be released. Otherwise the process will be ignored. 369 | 370 | Examples: 371 | 372 | Release to npm 373 | $ cdkdx release npm 374 | 375 | Release to pypi 376 | $ cdkdx release pypi 377 | ``` 378 | 379 | ### `cdkdx upgrade-cdk` 380 | ```shell 381 | Upgrade aws cdk 382 | 383 | $ cdkdx upgrade-cdk [--dry-run] [--mode #0] [--version #0] [--skip-dependencies] [--skip-dev-dependencies] [--skip-peer-dependencies] 384 | ``` 385 | 386 | ### `cdkdx node` 387 | ```shell 388 | Execute cdk apps 389 | 390 | Usage: 391 | 392 | $ cdkdx node