├── .gitattributes ├── .github ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .npmignore ├── .projen ├── deps.json └── tasks.json ├── .projenrc.js ├── .versionrc.json ├── API.md ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package.json ├── src ├── index.ts └── pascalCase.ts ├── test └── project.test.ts ├── tsconfig.jest.json └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | 3 | *.snap linguist-generated 4 | /.gitattributes linguist-generated 5 | /.github/dependabot.yml linguist-generated 6 | /.github/pull_request_template.md linguist-generated 7 | /.github/workflows/build.yml linguist-generated 8 | /.github/workflows/release.yml linguist-generated 9 | /.npmignore linguist-generated 10 | /.projen/ linguist-generated 11 | /.versionrc.json linguist-generated 12 | /LICENSE linguist-generated 13 | /package.json linguist-generated 14 | /tsconfig.jest.json linguist-generated 15 | /yarn.lock linguist-generated -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | 3 | version: 2 4 | updates: 5 | - package-ecosystem: npm 6 | versioning-strategy: lockfile-only 7 | directory: / 8 | schedule: 9 | interval: daily 10 | ignore: 11 | - dependency-name: projen 12 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Fixes # -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | 3 | name: Build 4 | on: 5 | pull_request: {} 6 | workflow_dispatch: {} 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | env: 11 | CI: "true" 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v2 15 | with: 16 | ref: ${{ github.event.pull_request.head.ref }} 17 | repository: ${{ github.event.pull_request.head.repo.full_name }} 18 | - name: Install dependencies 19 | run: yarn install --check-files --frozen-lockfile 20 | - name: Set git identity 21 | run: |- 22 | git config user.name "Automation" 23 | git config user.email "github-actions@github.com" 24 | - name: Build 25 | run: npx projen build 26 | - name: Check for changes 27 | id: git_diff 28 | run: git diff --exit-code || echo "::set-output name=has_changes::true" 29 | - if: steps.git_diff.outputs.has_changes 30 | name: Commit and push changes (if changed) 31 | run: 'git add . && git commit -m "chore: self mutation" && git push origin 32 | HEAD:${{ github.event.pull_request.head.ref }}' 33 | - if: steps.git_diff.outputs.has_changes 34 | name: Update status check (if changed) 35 | run: gh api -X POST /repos/${{ github.event.pull_request.head.repo.full_name 36 | }}/check-runs -F name="build" -F head_sha="$(git rev-parse HEAD)" -F 37 | status="completed" -F conclusion="success" 38 | env: 39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 40 | container: 41 | image: jsii/superchain 42 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | 3 | name: Release 4 | on: 5 | push: 6 | branches: 7 | - main 8 | workflow_dispatch: {} 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | env: 13 | CI: "true" 14 | RELEASE: "true" 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v2 18 | with: 19 | fetch-depth: 0 20 | - name: Install dependencies 21 | run: yarn install --check-files --frozen-lockfile 22 | - name: Anti-tamper check 23 | run: git diff --ignore-space-at-eol --exit-code 24 | - name: Set git identity 25 | run: |- 26 | git config user.name "Automation" 27 | git config user.email "github-actions@github.com" 28 | - name: Bump to next version 29 | run: npx projen bump 30 | - name: Build 31 | run: npx projen build 32 | - name: Check for new commits 33 | id: git_remote 34 | run: echo ::set-output name=latest_commit::"$(git ls-remote origin -h ${{ 35 | github.ref }} | cut -f1)" 36 | - name: Create release 37 | if: ${{ steps.git_remote.outputs.latest_commit == github.sha }} 38 | run: gh release create v$(node -p "require('./package.json').version") -F 39 | .changelog.tmp.md -t v$(node -p "require('./package.json').version") 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | - name: Unbump 43 | run: npx projen unbump 44 | - name: Upload artifact 45 | if: ${{ steps.git_remote.outputs.latest_commit == github.sha }} 46 | uses: actions/upload-artifact@v2.1.1 47 | with: 48 | name: dist 49 | path: dist 50 | - name: Anti-tamper check 51 | run: git diff --ignore-space-at-eol --exit-code 52 | container: 53 | image: jsii/superchain 54 | release_npm: 55 | name: Release to NPM 56 | needs: release 57 | runs-on: ubuntu-latest 58 | container: 59 | image: jsii/superchain 60 | steps: 61 | - name: Download build artifacts 62 | uses: actions/download-artifact@v2 63 | with: 64 | name: dist 65 | path: dist 66 | - name: Release 67 | run: npx -p jsii-release@latest jsii-release-npm 68 | env: 69 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 70 | NPM_DIST_TAG: latest 71 | NPM_REGISTRY: registry.npmjs.org 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | *.lcov 3 | *.log 4 | *.pid 5 | *.pid.lock 6 | *.seed 7 | *.tgz 8 | *.tsbuildinfo 9 | .cache 10 | .eslintcache 11 | .jsii 12 | .nyc_output 13 | .yarn-integrity 14 | /.changelog.tmp.md 15 | /.version.tmp.json 16 | /coverage 17 | /dist 18 | /lib 19 | /test-reports/ 20 | build/Release 21 | coverage 22 | jspm_packages/ 23 | junit.xml 24 | lerna-debug.log* 25 | lib-cov 26 | logs 27 | node_modules/ 28 | npm-debug.log* 29 | pids 30 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 31 | tsconfig.json 32 | yarn-debug.log* 33 | yarn-error.log* 34 | !/.gitattributes 35 | !/.github/dependabot.yml 36 | !/.github/pull_request_template.md 37 | !/.github/workflows/build.yml 38 | !/.github/workflows/release.yml 39 | !/.npmignore 40 | !/.projen/deps.json 41 | !/.projen/tasks.json 42 | !/.projenrc.js 43 | !/.versionrc.json 44 | !/API.md 45 | !/LICENSE 46 | !/package.json 47 | !/src 48 | !/test 49 | !/tsconfig.jest.json 50 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". 2 | /.github 3 | /.idea 4 | /.projen 5 | /.projenrc.js 6 | /.vscode 7 | /coverage 8 | /src 9 | /test 10 | /test-reports/ 11 | /tsconfig.jest.json 12 | /tsconfig.json 13 | dist 14 | junit.xml 15 | tsconfig.tsbuildinfo 16 | !.jsii 17 | !/lib 18 | !/lib/**/*.d.ts 19 | !/lib/**/*.js 20 | -------------------------------------------------------------------------------- /.projen/deps.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | { 4 | "name": "@types/fs-extra", 5 | "version": "^8", 6 | "type": "build" 7 | }, 8 | { 9 | "name": "@types/jest", 10 | "type": "build" 11 | }, 12 | { 13 | "name": "@types/node", 14 | "version": "^10.17.0", 15 | "type": "build" 16 | }, 17 | { 18 | "name": "jest", 19 | "type": "build" 20 | }, 21 | { 22 | "name": "jest-junit", 23 | "version": "^12", 24 | "type": "build" 25 | }, 26 | { 27 | "name": "jsii", 28 | "type": "build" 29 | }, 30 | { 31 | "name": "jsii-diff", 32 | "type": "build" 33 | }, 34 | { 35 | "name": "jsii-docgen", 36 | "type": "build" 37 | }, 38 | { 39 | "name": "jsii-pacmak", 40 | "type": "build" 41 | }, 42 | { 43 | "name": "projen", 44 | "type": "build" 45 | }, 46 | { 47 | "name": "projen", 48 | "version": "^0.17.83", 49 | "type": "build" 50 | }, 51 | { 52 | "name": "standard-version", 53 | "version": "^9", 54 | "type": "build" 55 | }, 56 | { 57 | "name": "ts-jest", 58 | "type": "build" 59 | }, 60 | { 61 | "name": "typescript", 62 | "type": "build" 63 | }, 64 | { 65 | "name": "fs-extra", 66 | "type": "bundled" 67 | }, 68 | { 69 | "name": "projen", 70 | "type": "peer" 71 | }, 72 | { 73 | "name": "projen", 74 | "type": "runtime" 75 | } 76 | ], 77 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 78 | } 79 | -------------------------------------------------------------------------------- /.projen/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "clobber": { 4 | "name": "clobber", 5 | "category": "30.maintain", 6 | "description": "hard resets to HEAD of origin and cleans the local repo", 7 | "env": { 8 | "BRANCH": "$(git branch --show-current)" 9 | }, 10 | "steps": [ 11 | { 12 | "exec": "git checkout -b scratch", 13 | "name": "save current HEAD in \"scratch\" branch" 14 | }, 15 | { 16 | "exec": "git checkout $BRANCH" 17 | }, 18 | { 19 | "exec": "git fetch origin", 20 | "name": "fetch latest changes from origin" 21 | }, 22 | { 23 | "exec": "git reset --hard origin/$BRANCH", 24 | "name": "hard reset to origin commit" 25 | }, 26 | { 27 | "exec": "git clean -fdx", 28 | "name": "clean all untracked files" 29 | }, 30 | { 31 | "say": "ready to rock! (unpushed commits are under the \"scratch\" branch)" 32 | } 33 | ], 34 | "condition": "git diff --exit-code > /dev/null" 35 | }, 36 | "bump": { 37 | "name": "bump", 38 | "category": "20.release", 39 | "description": "Bumps version based on latest git tag and generates a changelog entry", 40 | "steps": [ 41 | { 42 | "exec": "git -c \"versionsort.suffix=-\" tag --sort=\"-version:refname\" --list \"v*\" | head -n1 > .version.tmp.json" 43 | }, 44 | { 45 | "exec": "standard-version" 46 | } 47 | ], 48 | "condition": "! git log --oneline -1 | grep -q \"chore(release):\"" 49 | }, 50 | "unbump": { 51 | "name": "unbump", 52 | "category": "20.release", 53 | "description": "Restores version to 0.0.0", 54 | "steps": [ 55 | { 56 | "exec": "standard-version -r 0.0.0" 57 | } 58 | ] 59 | }, 60 | "compile": { 61 | "name": "compile", 62 | "category": "00.build", 63 | "description": "Only compile", 64 | "steps": [ 65 | { 66 | "exec": "jsii --silence-warnings=reserved-word --no-fix-peer-dependencies" 67 | }, 68 | { 69 | "spawn": "docgen" 70 | } 71 | ] 72 | }, 73 | "test:compile": { 74 | "name": "test:compile", 75 | "category": "10.test", 76 | "description": "compiles the test code", 77 | "steps": [ 78 | { 79 | "exec": "tsc --noEmit --project tsconfig.jest.json" 80 | } 81 | ] 82 | }, 83 | "test": { 84 | "name": "test", 85 | "category": "10.test", 86 | "description": "Run tests", 87 | "steps": [ 88 | { 89 | "exec": "rm -fr lib/" 90 | }, 91 | { 92 | "spawn": "test:compile" 93 | }, 94 | { 95 | "exec": "jest --passWithNoTests --all --updateSnapshot" 96 | } 97 | ] 98 | }, 99 | "build": { 100 | "name": "build", 101 | "category": "00.build", 102 | "description": "Full release build (test+compile)", 103 | "steps": [ 104 | { 105 | "exec": "npx projen" 106 | }, 107 | { 108 | "spawn": "test" 109 | }, 110 | { 111 | "spawn": "compile" 112 | }, 113 | { 114 | "spawn": "package" 115 | } 116 | ] 117 | }, 118 | "test:watch": { 119 | "name": "test:watch", 120 | "category": "10.test", 121 | "description": "Run jest in watch mode", 122 | "steps": [ 123 | { 124 | "exec": "jest --watch" 125 | } 126 | ] 127 | }, 128 | "test:update": { 129 | "name": "test:update", 130 | "category": "10.test", 131 | "description": "Update jest snapshots", 132 | "steps": [ 133 | { 134 | "exec": "jest --updateSnapshot" 135 | } 136 | ] 137 | }, 138 | "projen:upgrade": { 139 | "name": "projen:upgrade", 140 | "category": "30.maintain", 141 | "description": "upgrades projen to the latest version", 142 | "steps": [ 143 | { 144 | "exec": "yarn upgrade -L projen" 145 | }, 146 | { 147 | "exec": "CI=\"\" yarn projen" 148 | } 149 | ] 150 | }, 151 | "default": { 152 | "name": "default", 153 | "steps": [ 154 | { 155 | "exec": "node .projenrc.js" 156 | } 157 | ] 158 | }, 159 | "watch": { 160 | "name": "watch", 161 | "category": "00.build", 162 | "description": "Watch & compile in the background", 163 | "steps": [ 164 | { 165 | "exec": "jsii -w --silence-warnings=reserved-word --no-fix-peer-dependencies" 166 | } 167 | ] 168 | }, 169 | "package": { 170 | "name": "package", 171 | "category": "20.release", 172 | "description": "Create an npm tarball", 173 | "steps": [ 174 | { 175 | "exec": "jsii-pacmak" 176 | } 177 | ] 178 | }, 179 | "compat": { 180 | "name": "compat", 181 | "category": "20.release", 182 | "description": "Perform API compatibility check against latest version", 183 | "steps": [ 184 | { 185 | "exec": "jsii-diff npm:$(node -p \"require('./package.json').name\") -k --ignore-file .compatignore || (echo \"\nUNEXPECTED BREAKING CHANGES: add keys such as 'removed:constructs.Node.of' to .compatignore to skip.\n\" && exit 1)" 186 | } 187 | ] 188 | }, 189 | "docgen": { 190 | "name": "docgen", 191 | "category": "20.release", 192 | "description": "Generate API.md from .jsii manifest", 193 | "steps": [ 194 | { 195 | "exec": "jsii-docgen" 196 | } 197 | ] 198 | } 199 | }, 200 | "env": { 201 | "PATH": "$(npx -c \"node -e \\\"console.log(process.env.PATH)\\\"\")" 202 | }, 203 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 204 | } 205 | -------------------------------------------------------------------------------- /.projenrc.js: -------------------------------------------------------------------------------- 1 | const { JsiiProject } = require('projen'); 2 | 3 | const project = new JsiiProject({ 4 | name: 'cdk-appsync-project', 5 | repository: 'https://github.com/kcwinner/cdk-appsync-project.git', 6 | stability: 'experimental', 7 | defaultReleaseBranch: 'main', 8 | authorName: 'Ken Winner', 9 | authorAddress: 'kcswinner@gmail.com', 10 | 11 | entrypoint: 'lib/index.js', 12 | projenDevDependency: true, 13 | deps: ['projen'], 14 | peerDeps: ['projen'], 15 | devDeps: ['@types/fs-extra@^8'], // This will break if it's on 9 16 | bundledDeps: ['fs-extra'], 17 | 18 | eslint: false, 19 | mergify: false, 20 | }); 21 | 22 | project.synth(); -------------------------------------------------------------------------------- /.versionrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageFiles": [ 3 | { 4 | "filename": ".version.tmp.json", 5 | "type": "plain-text" 6 | } 7 | ], 8 | "bumpFiles": [ 9 | "package.json" 10 | ], 11 | "commitAll": false, 12 | "infile": ".changelog.tmp.md", 13 | "header": "", 14 | "skip": { 15 | "commit": true, 16 | "tag": true 17 | }, 18 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 19 | } 20 | -------------------------------------------------------------------------------- /API.md: -------------------------------------------------------------------------------- 1 | # API Reference 2 | 3 | **Classes** 4 | 5 | Name|Description 6 | ----|----------- 7 | [AwsCdkAppSyncApp](#cdk-appsync-project-awscdkappsyncapp)|AWS CDK AppSync Transformer App in TypeScript. 8 | 9 | 10 | **Structs** 11 | 12 | Name|Description 13 | ----|----------- 14 | [AwsCdkAppSyncAppOptions](#cdk-appsync-project-awscdkappsyncappoptions)|*No description* 15 | 16 | 17 | 18 | ## class AwsCdkAppSyncApp 🔹 19 | 20 | AWS CDK AppSync Transformer App in TypeScript. 21 | 22 | __Extends__: [AwsCdkTypeScriptApp](#projen-awscdktypescriptapp) 23 | 24 | ### Initializer 25 | 26 | 27 | 28 | 29 | ```ts 30 | new AwsCdkAppSyncApp(options: AwsCdkAppSyncAppOptions) 31 | ``` 32 | 33 | * **options** ([AwsCdkAppSyncAppOptions](#cdk-appsync-project-awscdkappsyncappoptions)) *No description* 34 | * **mergify** (boolean) Whether mergify should be enabled on this repository or not. __*Default*__: true 35 | * **name** (string) This is the name of your project. 36 | * **clobber** (boolean) Add a `clobber` task which resets the repo to origin. __*Default*__: true 37 | * **devContainer** (boolean) Add a VSCode development environment (used for GitHub Codespaces). __*Default*__: false 38 | * **gitpod** (boolean) Add a Gitpod development environment. __*Default*__: false 39 | * **logging** ([LoggerOptions](#projen-loggeroptions)) Configure logging options such as verbosity. __*Default*__: {} 40 | * **outdir** (string) The root directory of the project. __*Default*__: "." 41 | * **parent** ([Project](#projen-project)) The parent project, if this project is part of a bigger project. __*Optional*__ 42 | * **projectType** ([ProjectType](#projen-projecttype)) Which type of project this is (library/app). __*Default*__: ProjectType.UNKNOWN 43 | * **readme** ([SampleReadmeProps](#projen-samplereadmeprops)) The README setup. __*Default*__: { filename: 'README.md', contents: '# replace this' } 44 | * **allowLibraryDependencies** (boolean) Allow the project to include `peerDependencies` and `bundledDependencies`. __*Default*__: true 45 | * **authorEmail** (string) Author's e-mail. __*Optional*__ 46 | * **authorName** (string) Author's name. __*Optional*__ 47 | * **authorOrganization** (boolean) Author's Organization. __*Optional*__ 48 | * **authorUrl** (string) Author's URL / Website. __*Optional*__ 49 | * **autoDetectBin** (boolean) Automatically add all executables under the `bin` directory to your `package.json` file under the `bin` section. __*Default*__: true 50 | * **bin** (Map) Binary programs vended with your module. __*Optional*__ 51 | * **bundledDeps** (Array) List of dependencies to bundle into this module. __*Optional*__ 52 | * **deps** (Array) Runtime dependencies of this module. __*Default*__: [] 53 | * **description** (string) The description is just a string that helps people understand the purpose of the package. __*Optional*__ 54 | * **devDeps** (Array) Build dependencies for this module. __*Default*__: [] 55 | * **entrypoint** (string) Module entrypoint (`main` in `package.json`). __*Default*__: "lib/index.js" 56 | * **homepage** (string) Package's Homepage / Website. __*Optional*__ 57 | * **keywords** (Array) Keywords to include in `package.json`. __*Optional*__ 58 | * **license** (string) License's SPDX identifier. __*Default*__: "Apache-2.0" 59 | * **licensed** (boolean) Indicates if a license should be added. __*Default*__: true 60 | * **maxNodeVersion** (string) Minimum node.js version to require via `engines` (inclusive). __*Default*__: no max 61 | * **minNodeVersion** (string) Minimum Node.js version to require via package.json `engines` (inclusive). __*Default*__: no "engines" specified 62 | * **npmAccess** ([NpmAccess](#projen-npmaccess)) Access level of the npm package. __*Default*__: for scoped packages (e.g. `foo@bar`), the default is `NpmAccess.RESTRICTED`, for non-scoped packages, the default is `NpmAccess.PUBLIC`. 63 | * **npmDistTag** (string) Tags can be used to provide an alias instead of version numbers. __*Default*__: "latest" 64 | * **npmRegistry** (string) The host name of the npm registry to publish to. __*Optional*__ 65 | * **npmRegistryUrl** (string) The base URL of the npm package registry. __*Default*__: "https://registry.npmjs.org" 66 | * **npmTaskExecution** ([NpmTaskExecution](#projen-npmtaskexecution)) Determines how tasks are executed when invoked as npm scripts (yarn/npm run xyz). __*Default*__: NpmTaskExecution.PROJEN 67 | * **npmTokenSecret** (string) GitHub secret which contains the NPM token to use when publishing packages. __*Default*__: "NPM_TOKEN" 68 | * **packageManager** ([NodePackageManager](#projen-nodepackagemanager)) The Node Package Manager used to execute scripts. __*Default*__: NodePackageManager.YARN 69 | * **packageName** (string) The "name" in package.json. __*Default*__: defaults to project name 70 | * **peerDependencyOptions** ([PeerDependencyOptions](#projen-peerdependencyoptions)) Options for `peerDeps`. __*Optional*__ 71 | * **peerDeps** (Array) Peer dependencies for this module. __*Default*__: [] 72 | * **projenCommand** (string) The shell command to use in order to run the projen CLI. __*Default*__: "npx projen" 73 | * **repository** (string) The repository is the location where the actual code for your package lives. __*Optional*__ 74 | * **repositoryDirectory** (string) If the package.json for your package is not in the root directory (for example if it is part of a monorepo), you can specify the directory in which it lives. __*Optional*__ 75 | * **scripts** (Map) npm scripts to include. __*Default*__: {} 76 | * **stability** (string) Package's Stability. __*Optional*__ 77 | * **defaultReleaseBranch** (string) The name of the main release branch. 78 | * **antitamper** (boolean) Checks that after build there are no modified files on git. __*Default*__: true 79 | * **artifactsDirectory** (string) A directory which will contain artifacts to be published to npm. __*Default*__: "dist" 80 | * **buildWorkflow** (boolean) Define a GitHub workflow for building PRs. __*Default*__: true if not a subproject 81 | * **codeCov** (boolean) Define a GitHub workflow step for sending code coverage metrics to https://codecov.io/ Uses codecov/codecov-action@v1 A secret is required for private repos. Configured with @codeCovTokenSecret. __*Default*__: false 82 | * **codeCovTokenSecret** (string) Define the secret name for a specified https://codecov.io/ token A secret is required to send coverage for private repositories. __*Default*__: if this option is not specified, only public repositories are supported 83 | * **copyrightOwner** (string) License copyright owner. __*Default*__: defaults to the value of authorName or "" if `authorName` is undefined. 84 | * **copyrightPeriod** (string) The copyright years to put in the LICENSE file. __*Default*__: current year 85 | * **dependabot** (boolean) Include dependabot configuration. __*Default*__: true 86 | * **dependabotOptions** ([DependabotOptions](#projen-github-dependabotoptions)) Options for dependabot. __*Default*__: default options 87 | * **gitignore** (Array) Additional entries to .gitignore. __*Optional*__ 88 | * **jest** (boolean) Setup jest unit tests. __*Default*__: true 89 | * **jestOptions** ([JestOptions](#projen-jestoptions)) Jest options. __*Default*__: default options 90 | * **jsiiReleaseVersion** (string) Version requirement of `jsii-release` which is used to publish modules to npm. __*Default*__: "latest" 91 | * **mergifyAutoMergeLabel** (string) Automatically merge PRs that build successfully and have this label. __*Default*__: "auto-merge" 92 | * **mergifyOptions** ([MergifyOptions](#projen-github-mergifyoptions)) Options for mergify. __*Default*__: default options 93 | * **mutableBuild** (boolean) Automatically update files modified during builds to pull-request branches. __*Default*__: true 94 | * **npmignore** (Array) Additional entries to .npmignore. __*Optional*__ 95 | * **npmignoreEnabled** (boolean) Defines an .npmignore file. Normally this is only needed for libraries that are packaged as tarballs. __*Default*__: true 96 | * **projenDevDependency** (boolean) Indicates of "projen" should be installed as a devDependency. __*Default*__: true 97 | * **projenDuringBuild** (boolean) Execute `projen` as the first step of the `build` task to synthesize project files. __*Default*__: true 98 | * **projenrcJs** (boolean) Generate (once) .projenrc.js (in JavaScript). Set to `false` in order to disable .projenrc.js generation. __*Default*__: true 99 | * **projenrcJsOptions** ([ProjenrcOptions](#projen-javascript-projenrcoptions)) Options for .projenrc.js. __*Default*__: default options 100 | * **projenUpgradeAutoMerge** (boolean) Automatically merge projen upgrade PRs when build passes. __*Default*__: "true" if mergify auto-merge is enabled (default) 101 | * **projenUpgradeSchedule** (Array) Customize the projenUpgrade schedule in cron expression. __*Default*__: [ "0 6 * * *" ] 102 | * **projenUpgradeSecret** (string) Periodically submits a pull request for projen upgrades (executes `yarn projen:upgrade`). __*Default*__: no automatic projen upgrade pull requests 103 | * **projenVersion** (string) Version of projen to install. __*Default*__: Defaults to the latest version. 104 | * **pullRequestTemplate** (boolean) Include a GitHub pull request template. __*Default*__: true 105 | * **pullRequestTemplateContents** (string) The contents of the pull request template. __*Default*__: default content 106 | * **releaseBranches** (Array) Branches which trigger a release. __*Default*__: [ "main" ] 107 | * **releaseEveryCommit** (boolean) Automatically release new versions every commit to one of branches in `releaseBranches`. __*Default*__: true 108 | * **releaseSchedule** (string) CRON schedule to trigger new releases. __*Default*__: no scheduled releases 109 | * **releaseToNpm** (boolean) Automatically release to npm when new versions are introduced. __*Default*__: false 110 | * **releaseWorkflow** (boolean) Define a GitHub workflow for releasing from "main" when new versions are bumped. __*Default*__: true if not a subproject 111 | * **releaseWorkflowSetupSteps** (Array) A set of workflow steps to execute in order to setup the workflow container. __*Optional*__ 112 | * **workflowBootstrapSteps** (Array) Workflow steps to use in order to bootstrap this repo. __*Default*__: "yarn install --frozen-lockfile && yarn projen" 113 | * **workflowContainerImage** (string) Container image to use for GitHub workflows. __*Default*__: default image 114 | * **workflowNodeVersion** (string) The node version to use in GitHub workflows. __*Default*__: same as `minNodeVersion` 115 | * **compileBeforeTest** (boolean) Compile the code before running tests. __*Default*__: if `testdir` is under `src/**`, the default is `true`, otherwise the default is `false. 116 | * **disableTsconfig** (boolean) Do not generate a `tsconfig.json` file (used by jsii projects since tsconfig.json is generated by the jsii compiler). __*Default*__: false 117 | * **docgen** (boolean) Docgen by Typedoc. __*Default*__: false 118 | * **docsDirectory** (string) Docs directory. __*Default*__: "docs" 119 | * **entrypointTypes** (string) The .d.ts file that includes the type declarations for this module. __*Default*__: .d.ts file derived from the project's entrypoint (usually lib/index.d.ts) 120 | * **eslint** (boolean) Setup eslint. __*Default*__: true 121 | * **eslintOptions** ([EslintOptions](#projen-eslintoptions)) Eslint options. __*Default*__: opinionated default options 122 | * **libdir** (string) Typescript artifacts output directory. __*Default*__: "lib" 123 | * **package** (boolean) Defines a `yarn package` command that will produce a tarball and place it under `dist/js`. __*Default*__: true 124 | * **projenrcTs** (boolean) Use TypeScript for your projenrc file (`.projenrc.ts`). __*Default*__: false 125 | * **projenrcTsOptions** ([ProjenrcOptions](#projen-typescript-projenrcoptions)) Options for .projenrc.ts. __*Optional*__ 126 | * **sampleCode** (boolean) Generate one-time sample in `src/` and `test/` if there are no files there. __*Default*__: true 127 | * **srcdir** (string) Typescript sources directory. __*Default*__: "src" 128 | * **testdir** (string) Jest tests directory. Tests files should be named `xxx.test.ts`. __*Default*__: "test" 129 | * **tsconfig** ([TypescriptConfigOptions](#projen-typescriptconfigoptions)) Custom TSConfig. __*Optional*__ 130 | * **typescriptVersion** (string) TypeScript version to use. __*Default*__: "latest" 131 | * **cdkVersion** (string) AWS CDK version to use. 132 | * **appEntrypoint** (string) The CDK app's entrypoint (relative to the source directory, which is "src" by default). __*Default*__: "main.ts" 133 | * **cdkDependencies** (Array) Which AWS CDK modules (those that start with "@aws-cdk/") this app uses. __*Optional*__ 134 | * **cdkVersionPinning** (boolean) Use pinned version instead of caret version for CDK. __*Default*__: false 135 | * **context** (Map) Additional context to include in `cdk.json`. __*Optional*__ 136 | * **requireApproval** ([CdkApprovalLevel](#projen-cdkapprovallevel)) To protect you against unintended changes that affect your security posture, the AWS CDK Toolkit prompts you to approve security-related changes before deploying them. __*Default*__: CdkApprovalLevel.BROADENING 137 | * **transformerVersion** (string) cdk-appsync-transformer version to use. 138 | 139 | 140 | 141 | 142 | ## struct AwsCdkAppSyncAppOptions 🔹 143 | 144 | 145 | 146 | 147 | 148 | 149 | Name | Type | Description 150 | -----|------|------------- 151 | **cdkVersion**🔹 | string | AWS CDK version to use. 152 | **defaultReleaseBranch**🔹 | string | The name of the main release branch. 153 | **name**🔹 | string | This is the name of your project. 154 | **transformerVersion**🔹 | string | cdk-appsync-transformer version to use. 155 | **allowLibraryDependencies**?🔹 | boolean | Allow the project to include `peerDependencies` and `bundledDependencies`.
__*Default*__: true 156 | **antitamper**?🔹 | boolean | Checks that after build there are no modified files on git.
__*Default*__: true 157 | **appEntrypoint**?🔹 | string | The CDK app's entrypoint (relative to the source directory, which is "src" by default).
__*Default*__: "main.ts" 158 | **artifactsDirectory**?🔹 | string | A directory which will contain artifacts to be published to npm.
__*Default*__: "dist" 159 | **authorEmail**?🔹 | string | Author's e-mail.
__*Optional*__ 160 | **authorName**?🔹 | string | Author's name.
__*Optional*__ 161 | **authorOrganization**?🔹 | boolean | Author's Organization.
__*Optional*__ 162 | **authorUrl**?🔹 | string | Author's URL / Website.
__*Optional*__ 163 | **autoDetectBin**?🔹 | boolean | Automatically add all executables under the `bin` directory to your `package.json` file under the `bin` section.
__*Default*__: true 164 | **bin**?🔹 | Map | Binary programs vended with your module.
__*Optional*__ 165 | **buildWorkflow**?🔹 | boolean | Define a GitHub workflow for building PRs.
__*Default*__: true if not a subproject 166 | **bundledDeps**?🔹 | Array | List of dependencies to bundle into this module.
__*Optional*__ 167 | **cdkDependencies**?🔹 | Array | Which AWS CDK modules (those that start with "@aws-cdk/") this app uses.
__*Optional*__ 168 | **cdkVersionPinning**?🔹 | boolean | Use pinned version instead of caret version for CDK.
__*Default*__: false 169 | **clobber**?🔹 | boolean | Add a `clobber` task which resets the repo to origin.
__*Default*__: true 170 | **codeCov**?🔹 | boolean | Define a GitHub workflow step for sending code coverage metrics to https://codecov.io/ Uses codecov/codecov-action@v1 A secret is required for private repos. Configured with @codeCovTokenSecret.
__*Default*__: false 171 | **codeCovTokenSecret**?🔹 | string | Define the secret name for a specified https://codecov.io/ token A secret is required to send coverage for private repositories.
__*Default*__: if this option is not specified, only public repositories are supported 172 | **compileBeforeTest**?🔹 | boolean | Compile the code before running tests.
__*Default*__: if `testdir` is under `src/**`, the default is `true`, otherwise the default is `false. 173 | **context**?🔹 | Map | Additional context to include in `cdk.json`.
__*Optional*__ 174 | **copyrightOwner**?🔹 | string | License copyright owner.
__*Default*__: defaults to the value of authorName or "" if `authorName` is undefined. 175 | **copyrightPeriod**?🔹 | string | The copyright years to put in the LICENSE file.
__*Default*__: current year 176 | **dependabot**?🔹 | boolean | Include dependabot configuration.
__*Default*__: true 177 | **dependabotOptions**?🔹 | [DependabotOptions](#projen-github-dependabotoptions) | Options for dependabot.
__*Default*__: default options 178 | **deps**?🔹 | Array | Runtime dependencies of this module.
__*Default*__: [] 179 | **description**?🔹 | string | The description is just a string that helps people understand the purpose of the package.
__*Optional*__ 180 | **devContainer**?🔹 | boolean | Add a VSCode development environment (used for GitHub Codespaces).
__*Default*__: false 181 | **devDeps**?🔹 | Array | Build dependencies for this module.
__*Default*__: [] 182 | **disableTsconfig**?🔹 | boolean | Do not generate a `tsconfig.json` file (used by jsii projects since tsconfig.json is generated by the jsii compiler).
__*Default*__: false 183 | **docgen**?🔹 | boolean | Docgen by Typedoc.
__*Default*__: false 184 | **docsDirectory**?🔹 | string | Docs directory.
__*Default*__: "docs" 185 | **entrypoint**?🔹 | string | Module entrypoint (`main` in `package.json`).
__*Default*__: "lib/index.js" 186 | **entrypointTypes**?🔹 | string | The .d.ts file that includes the type declarations for this module.
__*Default*__: .d.ts file derived from the project's entrypoint (usually lib/index.d.ts) 187 | **eslint**?🔹 | boolean | Setup eslint.
__*Default*__: true 188 | **eslintOptions**?🔹 | [EslintOptions](#projen-eslintoptions) | Eslint options.
__*Default*__: opinionated default options 189 | **gitignore**?🔹 | Array | Additional entries to .gitignore.
__*Optional*__ 190 | **gitpod**?🔹 | boolean | Add a Gitpod development environment.
__*Default*__: false 191 | **homepage**?🔹 | string | Package's Homepage / Website.
__*Optional*__ 192 | **jest**?🔹 | boolean | Setup jest unit tests.
__*Default*__: true 193 | **jestOptions**?🔹 | [JestOptions](#projen-jestoptions) | Jest options.
__*Default*__: default options 194 | **jsiiReleaseVersion**?🔹 | string | Version requirement of `jsii-release` which is used to publish modules to npm.
__*Default*__: "latest" 195 | **keywords**?🔹 | Array | Keywords to include in `package.json`.
__*Optional*__ 196 | **libdir**?🔹 | string | Typescript artifacts output directory.
__*Default*__: "lib" 197 | **license**?🔹 | string | License's SPDX identifier.
__*Default*__: "Apache-2.0" 198 | **licensed**?🔹 | boolean | Indicates if a license should be added.
__*Default*__: true 199 | **logging**?🔹 | [LoggerOptions](#projen-loggeroptions) | Configure logging options such as verbosity.
__*Default*__: {} 200 | **maxNodeVersion**?🔹 | string | Minimum node.js version to require via `engines` (inclusive).
__*Default*__: no max 201 | **mergify**?🔹 | boolean | Whether mergify should be enabled on this repository or not.
__*Default*__: true 202 | **mergifyAutoMergeLabel**?🔹 | string | Automatically merge PRs that build successfully and have this label.
__*Default*__: "auto-merge" 203 | **mergifyOptions**?🔹 | [MergifyOptions](#projen-github-mergifyoptions) | Options for mergify.
__*Default*__: default options 204 | **minNodeVersion**?🔹 | string | Minimum Node.js version to require via package.json `engines` (inclusive).
__*Default*__: no "engines" specified 205 | **mutableBuild**?🔹 | boolean | Automatically update files modified during builds to pull-request branches.
__*Default*__: true 206 | **npmAccess**?🔹 | [NpmAccess](#projen-npmaccess) | Access level of the npm package.
__*Default*__: for scoped packages (e.g. `foo@bar`), the default is `NpmAccess.RESTRICTED`, for non-scoped packages, the default is `NpmAccess.PUBLIC`. 207 | **npmDistTag**?🔹 | string | Tags can be used to provide an alias instead of version numbers.
__*Default*__: "latest" 208 | **npmRegistry**?⚠️ | string | The host name of the npm registry to publish to.
__*Optional*__ 209 | **npmRegistryUrl**?🔹 | string | The base URL of the npm package registry.
__*Default*__: "https://registry.npmjs.org" 210 | **npmTaskExecution**?🔹 | [NpmTaskExecution](#projen-npmtaskexecution) | Determines how tasks are executed when invoked as npm scripts (yarn/npm run xyz).
__*Default*__: NpmTaskExecution.PROJEN 211 | **npmTokenSecret**?🔹 | string | GitHub secret which contains the NPM token to use when publishing packages.
__*Default*__: "NPM_TOKEN" 212 | **npmignore**?🔹 | Array | Additional entries to .npmignore.
__*Optional*__ 213 | **npmignoreEnabled**?🔹 | boolean | Defines an .npmignore file. Normally this is only needed for libraries that are packaged as tarballs.
__*Default*__: true 214 | **outdir**?🔹 | string | The root directory of the project.
__*Default*__: "." 215 | **package**?🔹 | boolean | Defines a `yarn package` command that will produce a tarball and place it under `dist/js`.
__*Default*__: true 216 | **packageManager**?🔹 | [NodePackageManager](#projen-nodepackagemanager) | The Node Package Manager used to execute scripts.
__*Default*__: NodePackageManager.YARN 217 | **packageName**?🔹 | string | The "name" in package.json.
__*Default*__: defaults to project name 218 | **parent**?🔹 | [Project](#projen-project) | The parent project, if this project is part of a bigger project.
__*Optional*__ 219 | **peerDependencyOptions**?🔹 | [PeerDependencyOptions](#projen-peerdependencyoptions) | Options for `peerDeps`.
__*Optional*__ 220 | **peerDeps**?🔹 | Array | Peer dependencies for this module.
__*Default*__: [] 221 | **projectType**?🔹 | [ProjectType](#projen-projecttype) | Which type of project this is (library/app).
__*Default*__: ProjectType.UNKNOWN 222 | **projenCommand**?🔹 | string | The shell command to use in order to run the projen CLI.
__*Default*__: "npx projen" 223 | **projenDevDependency**?🔹 | boolean | Indicates of "projen" should be installed as a devDependency.
__*Default*__: true 224 | **projenDuringBuild**?🔹 | boolean | Execute `projen` as the first step of the `build` task to synthesize project files.
__*Default*__: true 225 | **projenUpgradeAutoMerge**?🔹 | boolean | Automatically merge projen upgrade PRs when build passes.
__*Default*__: "true" if mergify auto-merge is enabled (default) 226 | **projenUpgradeSchedule**?🔹 | Array | Customize the projenUpgrade schedule in cron expression.
__*Default*__: [ "0 6 * * *" ] 227 | **projenUpgradeSecret**?🔹 | string | Periodically submits a pull request for projen upgrades (executes `yarn projen:upgrade`).
__*Default*__: no automatic projen upgrade pull requests 228 | **projenVersion**?🔹 | string | Version of projen to install.
__*Default*__: Defaults to the latest version. 229 | **projenrcJs**?🔹 | boolean | Generate (once) .projenrc.js (in JavaScript). Set to `false` in order to disable .projenrc.js generation.
__*Default*__: true 230 | **projenrcJsOptions**?🔹 | [ProjenrcOptions](#projen-javascript-projenrcoptions) | Options for .projenrc.js.
__*Default*__: default options 231 | **projenrcTs**?🔹 | boolean | Use TypeScript for your projenrc file (`.projenrc.ts`).
__*Default*__: false 232 | **projenrcTsOptions**?🔹 | [ProjenrcOptions](#projen-typescript-projenrcoptions) | Options for .projenrc.ts.
__*Optional*__ 233 | **pullRequestTemplate**?🔹 | boolean | Include a GitHub pull request template.
__*Default*__: true 234 | **pullRequestTemplateContents**?🔹 | string | The contents of the pull request template.
__*Default*__: default content 235 | **readme**?🔹 | [SampleReadmeProps](#projen-samplereadmeprops) | The README setup.
__*Default*__: { filename: 'README.md', contents: '# replace this' } 236 | **releaseBranches**?🔹 | Array | Branches which trigger a release.
__*Default*__: [ "main" ] 237 | **releaseEveryCommit**?🔹 | boolean | Automatically release new versions every commit to one of branches in `releaseBranches`.
__*Default*__: true 238 | **releaseSchedule**?🔹 | string | CRON schedule to trigger new releases.
__*Default*__: no scheduled releases 239 | **releaseToNpm**?🔹 | boolean | Automatically release to npm when new versions are introduced.
__*Default*__: false 240 | **releaseWorkflow**?🔹 | boolean | Define a GitHub workflow for releasing from "main" when new versions are bumped.
__*Default*__: true if not a subproject 241 | **releaseWorkflowSetupSteps**?🔹 | Array | A set of workflow steps to execute in order to setup the workflow container.
__*Optional*__ 242 | **repository**?🔹 | string | The repository is the location where the actual code for your package lives.
__*Optional*__ 243 | **repositoryDirectory**?🔹 | string | If the package.json for your package is not in the root directory (for example if it is part of a monorepo), you can specify the directory in which it lives.
__*Optional*__ 244 | **requireApproval**?🔹 | [CdkApprovalLevel](#projen-cdkapprovallevel) | To protect you against unintended changes that affect your security posture, the AWS CDK Toolkit prompts you to approve security-related changes before deploying them.
__*Default*__: CdkApprovalLevel.BROADENING 245 | **sampleCode**?🔹 | boolean | Generate one-time sample in `src/` and `test/` if there are no files there.
__*Default*__: true 246 | **scripts**?🔹 | Map | npm scripts to include.
__*Default*__: {} 247 | **srcdir**?🔹 | string | Typescript sources directory.
__*Default*__: "src" 248 | **stability**?🔹 | string | Package's Stability.
__*Optional*__ 249 | **testdir**?🔹 | string | Jest tests directory. Tests files should be named `xxx.test.ts`.
__*Default*__: "test" 250 | **tsconfig**?🔹 | [TypescriptConfigOptions](#projen-typescriptconfigoptions) | Custom TSConfig.
__*Optional*__ 251 | **typescriptVersion**?🔹 | string | TypeScript version to use.
__*Default*__: "latest" 252 | **workflowBootstrapSteps**?🔹 | Array | Workflow steps to use in order to bootstrap this repo.
__*Default*__: "yarn install --frozen-lockfile && yarn projen" 253 | **workflowContainerImage**?🔹 | string | Container image to use for GitHub workflows.
__*Default*__: default image 254 | **workflowNodeVersion**?🔹 | string | The node version to use in GitHub workflows.
__*Default*__: same as `minNodeVersion` 255 | 256 | 257 | 258 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### 1.0.4 (2020-11-09) 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021 Ken Winner 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CDK AppSync Project 2 | 3 | This project is meant to be used with [projen's external module](https://github.com/eladb/projen#projects-in-external-modules) feature. It will quickly create an AWS AppSync API that uses the [cdk-appsync-transformer](https://github.com/kcwinner/aws-cdk-appsync-transformer). 4 | 5 | Currently supports 6 | * [![GitHub package.json dependency version (prod)](https://img.shields.io/github/package-json/dependency-version/kcwinner/aws-cdk-appsync-transformer/@aws-cdk/core)](https://github.com/aws/aws-cdk) 7 | 8 | ## How To Use 9 | 10 | Since the AppSync transformer uses version `1.63.0` of the AWS CDK we want to pin our version here as there are breaking changes that have not yet been merged into the transformer construct. 11 | 12 | ```bash 13 | npx projen new --from cdk-appsync-project --cdk-version-pinning true --cdk-version "1.63.0" 14 | ``` 15 | 16 | ## Notice 17 | 18 | This project has the `.jsii` file and the `lib/` folder committed. This facilitates the following testing 19 | ```bash 20 | npx projen new --from https://github.com/kcwinner/cdk-appsync-project --cdk-version-pinning true --cdk-version "1.63.0" 21 | ``` -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cdk-appsync-project", 3 | "repository": { 4 | "type": "git", 5 | "url": "https://github.com/kcwinner/cdk-appsync-project.git" 6 | }, 7 | "scripts": { 8 | "clobber": "npx projen clobber", 9 | "bump": "npx projen bump", 10 | "unbump": "npx projen unbump", 11 | "compile": "npx projen compile", 12 | "test:compile": "npx projen test:compile", 13 | "test": "npx projen test", 14 | "build": "npx projen build", 15 | "test:watch": "npx projen test:watch", 16 | "test:update": "npx projen test:update", 17 | "projen:upgrade": "npx projen projen:upgrade", 18 | "default": "npx projen default", 19 | "watch": "npx projen watch", 20 | "package": "npx projen package", 21 | "compat": "npx projen compat", 22 | "docgen": "npx projen docgen", 23 | "projen": "npx projen", 24 | "start": "npx projen start" 25 | }, 26 | "author": { 27 | "name": "Ken Winner", 28 | "email": "kcswinner@gmail.com", 29 | "organization": false 30 | }, 31 | "devDependencies": { 32 | "@types/fs-extra": "^8", 33 | "@types/jest": "^26.0.15", 34 | "@types/node": "^10.17.0", 35 | "jest": "^26.6.3", 36 | "jest-junit": "^12", 37 | "jsii": "^1.11.0", 38 | "jsii-diff": "^1.11.0", 39 | "jsii-docgen": "^1.3.2", 40 | "jsii-pacmak": "^1.11.0", 41 | "projen": "^0.17.83", 42 | "standard-version": "^9", 43 | "ts-jest": "^26.4.4", 44 | "typescript": "^3.9.5" 45 | }, 46 | "peerDependencies": { 47 | "projen": "^0.17.83" 48 | }, 49 | "dependencies": { 50 | "fs-extra": "^9.1.0", 51 | "projen": "^0.17.83" 52 | }, 53 | "bundledDependencies": [ 54 | "fs-extra" 55 | ], 56 | "main": "lib/index.js", 57 | "license": "Apache-2.0", 58 | "version": "0.0.0", 59 | "jest": { 60 | "testMatch": [ 61 | "**/__tests__/**/*.ts?(x)", 62 | "**/?(*.)+(spec|test).ts?(x)" 63 | ], 64 | "clearMocks": true, 65 | "collectCoverage": true, 66 | "coverageReporters": [ 67 | "json", 68 | "lcov", 69 | "clover", 70 | "text" 71 | ], 72 | "coverageDirectory": "coverage", 73 | "coveragePathIgnorePatterns": [ 74 | "/node_modules/" 75 | ], 76 | "testPathIgnorePatterns": [ 77 | "/node_modules/" 78 | ], 79 | "watchPathIgnorePatterns": [ 80 | "/node_modules/" 81 | ], 82 | "reporters": [ 83 | "default", 84 | [ 85 | "jest-junit", 86 | { 87 | "outputDirectory": "test-reports" 88 | } 89 | ] 90 | ], 91 | "preset": "ts-jest", 92 | "globals": { 93 | "ts-jest": { 94 | "tsconfig": "tsconfig.jest.json" 95 | } 96 | } 97 | }, 98 | "types": "lib/index.d.ts", 99 | "stability": "experimental", 100 | "jsii": { 101 | "outdir": "dist", 102 | "targets": {}, 103 | "tsc": { 104 | "outDir": "lib", 105 | "rootDir": "src" 106 | } 107 | }, 108 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 109 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs-extra'; 2 | import * as path from 'path'; 3 | import { AwsCdkTypeScriptApp, AwsCdkTypeScriptAppOptions, Component, SampleDir } from 'projen'; 4 | import { pascalCase } from './pascalCase'; 5 | 6 | export interface AwsCdkAppSyncAppOptions extends AwsCdkTypeScriptAppOptions { 7 | /** 8 | * cdk-appsync-transformer version to use. 9 | * 10 | * @default "1.77.15" 11 | */ 12 | readonly transformerVersion: string; 13 | } 14 | 15 | /** 16 | * AWS CDK AppSync Transformer App in TypeScript 17 | * 18 | * @pjid awscdk-appsync-app-ts 19 | */ 20 | export class AwsCdkAppSyncApp extends AwsCdkTypeScriptApp { 21 | constructor(options: AwsCdkAppSyncAppOptions) { 22 | super({ 23 | ...options, 24 | sampleCode: false, 25 | }); 26 | 27 | const transformerVersion = options.cdkVersionPinning 28 | ? `^${options.transformerVersion}` 29 | : options.transformerVersion 30 | 31 | this.addDeps(`cdk-appsync-transformer@${transformerVersion}`) 32 | 33 | this.addCdkDependency(...[ 34 | '@aws-cdk/core', 35 | '@aws-cdk/aws-appsync', 36 | '@aws-cdk/aws-cognito', 37 | '@aws-cdk/aws-dynamodb', 38 | '@aws-cdk/aws-iam', 39 | ]); 40 | 41 | this.gitignore.exclude('appsync/'); 42 | this.npmignore?.exclude('appsync/'); 43 | 44 | if (options.sampleCode ?? true) { 45 | new SampleCode(this); 46 | } 47 | } 48 | } 49 | 50 | class SampleCode extends Component { 51 | private readonly appProject: AwsCdkAppSyncApp; 52 | private readonly projectName: string; 53 | 54 | constructor(project: AwsCdkAppSyncApp) { 55 | super(project); 56 | this.appProject = project; 57 | this.projectName = path.basename(process.cwd()); 58 | } 59 | 60 | public synthesize() { 61 | const srcdir = path.join(this.project.outdir, this.appProject.srcdir); 62 | if (fs.pathExistsSync(srcdir) && fs.readdirSync(srcdir).filter(x => x.endsWith('.ts'))) { 63 | return; 64 | } 65 | 66 | const projectType = pascalCase(this.projectName); 67 | 68 | new SampleDir(this.project, this.appProject.srcdir, { 69 | files: { 70 | 'main.ts': this.createMainTsContents(this.projectName, projectType), 71 | }, 72 | }); 73 | 74 | const libDir = path.join(this.appProject.srcdir, 'lib'); 75 | new SampleDir(this.appProject, libDir, { 76 | files: { 77 | [`${this.projectName}-stack.ts`]: this.createProjectStackContents(projectType), 78 | }, 79 | }); 80 | 81 | const testCode = `import '@aws-cdk/assert/jest'; 82 | import { MyStack } from '../src/main' 83 | import { App } from '@aws-cdk/core'; 84 | 85 | test('Snapshot', () => { 86 | const app = new App(); 87 | const stack = new MyStack(app, 'test'); 88 | 89 | expect(stack).toHaveResource('AWS::Cognito::UserPool'); 90 | expect(stack.api.nestedAppsyncStack).toHaveResource('AWS::AppSync::GraphQLApi'); 91 | });`; 92 | 93 | new SampleDir(this.project, this.appProject.testdir, { 94 | files: { 95 | 'main.test.ts': testCode 96 | } 97 | }) 98 | 99 | const sampleSchema = this.createSampleSchema(); 100 | fs.writeFileSync(path.join(this.project.outdir, 'schema.graphql'), sampleSchema); 101 | } 102 | 103 | private createMainTsContents(projectName: string, projectType: string): string { 104 | return `import { App } from '@aws-cdk/core'; 105 | import { ${projectType}Stack } from './lib/${projectName}-stack'; 106 | const STAGE = process.env.STAGE || 'dev'; // default to dev as the stage 107 | const ACCOUNT = process.env.ACCOUNT || process.env.CDK_DEFAULT_ACCOUNT; 108 | const REGION = process.env.REGION || 'us-east-2'; // default region we are using 109 | const app = new App( 110 | { 111 | context: { 112 | STAGE: STAGE, 113 | }, 114 | }, 115 | ); 116 | 117 | new ${projectType}Stack(app, \`${projectName}-\${STAGE}\`, { 118 | terminationProtection: true, 119 | description: 'Stack for ${projectName}', 120 | env: { 121 | account: ACCOUNT, 122 | region: REGION, 123 | }, 124 | }); 125 | app.synth();`; 126 | } 127 | 128 | private createProjectStackContents(projectType: string): string { 129 | return `import { Construct, Stack, StackProps } from '@aws-cdk/core'; 130 | import { AuthorizationType, UserPoolDefaultAction } from '@aws-cdk/aws-appsync'; 131 | import { CfnIdentityPool, UserPool, UserPoolClient, VerificationEmailStyle } from '@aws-cdk/aws-cognito'; 132 | import { Role, WebIdentityPrincipal } from '@aws-cdk/aws-iam'; 133 | 134 | import { AppSyncTransformer } from 'cdk-appsync-transformer'; 135 | 136 | export interface ${projectType}StackProps extends StackProps { } 137 | 138 | export class ${projectType}Stack extends Stack { 139 | public userPool: UserPool; 140 | public appsyncTransformer: AppSyncTransformer 141 | 142 | constructor(scope: Construct, id: string, props: ${projectType}StackProps = {}) { 143 | super(scope, id, props); 144 | 145 | this.userPool = new UserPool(this, 'user-pool', { 146 | autoVerify: { 147 | email: true, 148 | phone: false 149 | }, 150 | selfSignUpEnabled: true, 151 | signInAliases: { 152 | email: true 153 | }, 154 | standardAttributes: { 155 | email: { 156 | mutable: true, 157 | required: true 158 | }, 159 | }, 160 | userVerification: { 161 | emailSubject: 'Verify your email', 162 | emailBody: 'Hello {username}! Your verification code is {####}', 163 | emailStyle: VerificationEmailStyle.CODE, 164 | } 165 | }); 166 | 167 | const userpoolWebClient = new UserPoolClient(this, 'user-pool-client', { 168 | userPool: this.userPool, 169 | generateSecret: false, 170 | authFlows: { 171 | userPassword: true, 172 | } 173 | }); 174 | 175 | const identityPool = new CfnIdentityPool(this, 'identity-pool', { 176 | cognitoIdentityProviders: [ 177 | { 178 | clientId: userpoolWebClient.userPoolClientId, 179 | providerName: \`cognito-idp.\${this.region}.amazonaws.com/\${this.userPool.userPoolId}\`, 180 | }, 181 | ], 182 | allowUnauthenticatedIdentities: true, 183 | }); 184 | 185 | const unauthRole = new Role(this, 'unauth-role', { 186 | assumedBy: new WebIdentityPrincipal('cognito-identity.amazonaws.com') 187 | .withConditions({ 188 | 'StringEquals': { 'cognito-identity.amazonaws.com:aud': \`\${identityPool.ref}\` }, 189 | 'ForAnyValue:StringLike': { 'cognito-identity.amazonaws.com:amr': 'unauthenticated' }, 190 | }), 191 | }); 192 | 193 | const authRole = new Role(this, 'auth-role', { 194 | assumedBy: new WebIdentityPrincipal('cognito-identity.amazonaws.com') 195 | .withConditions({ 196 | 'StringEquals': { 'cognito-identity.amazonaws.com:aud': \`\${identityPool.ref}\` }, 197 | 'ForAnyValue:StringLike': { 'cognito-identity.amazonaws.com:amr': 'authenticated' }, 198 | }), 199 | }); 200 | 201 | this.appsyncTransformer = new AppSyncTransformer(this, 'appsync-api', { 202 | schemaPath: './schema.graphql', 203 | apiName: 'my-cool-api', 204 | authorizationConfig: { 205 | defaultAuthorization: { 206 | authorizationType: AuthorizationType.USER_POOL, 207 | userPoolConfig: { 208 | userPool: this.userPool, 209 | appIdClientRegex: userpoolWebClient.userPoolClientId, 210 | defaultAction: UserPoolDefaultAction.ALLOW 211 | } 212 | } 213 | } 214 | }); 215 | 216 | this.appsyncTransformer.grantPublic(unauthRole); 217 | } 218 | }` 219 | } 220 | 221 | private createSampleSchema(): string { 222 | return `# This is a sample generated schema 223 | type Customer @model 224 | @auth(rules: [ 225 | { allow: groups, groups: ["Admins"] }, 226 | { allow: private, provider: iam, operations: [read, update] } 227 | ]) { 228 | id: ID! 229 | firstName: String! 230 | lastName: String! 231 | active: Boolean! 232 | address: String! 233 | } 234 | 235 | type Product @model 236 | @auth(rules: [ 237 | { allow: groups, groups: ["Admins"] }, 238 | { allow: public, provider: iam, operations: [read] } 239 | ]) { 240 | id: ID! 241 | name: String! 242 | description: String! 243 | price: String! 244 | active: Boolean! 245 | added: AWSDateTime! 246 | orders: [Order] @connection 247 | } 248 | 249 | type Order @model 250 | @key(fields: ["id", "productID"]) { 251 | id: ID! 252 | productID: ID! 253 | total: String! 254 | ordered: AWSDateTime! 255 | } 256 | 257 | # Demonstrate the FUNCTION resolvers 258 | type User @model(queries: null, mutations: null, subscriptions: null) 259 | @auth(rules: [ 260 | { allow: groups, groups: ["Admins"] }, 261 | { allow: owner, ownerField: "sub" }, 262 | { allow: private, provider: iam, operations: [create, update] } 263 | ]) { 264 | id: ID! 265 | enabled: Boolean! 266 | status: String! 267 | email: String! 268 | name: String! 269 | email_verified: String 270 | phone_number: String 271 | phone_number_verified: String 272 | } 273 | 274 | type UserConnection { 275 | items: [User] 276 | } 277 | 278 | input CreateUserInput { 279 | email: String! 280 | name: String! 281 | } 282 | 283 | input UpdateUserInput { 284 | id: ID! 285 | email: String 286 | name: String 287 | number: String 288 | } 289 | 290 | # Demonstrate the FUNCTION resolvers 291 | type Query { 292 | listUsers: UserConnection @function(name: "router") 293 | getUser(id: ID!): User @function(name: "router") 294 | } 295 | 296 | type Mutation { 297 | createUser(input: CreateUserInput!): User @function(name: "router") 298 | updateUser(input: UpdateUserInput!): User @function(name: "router") 299 | }`; 300 | } 301 | } -------------------------------------------------------------------------------- /src/pascalCase.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Borrowed from https://github.com/blakeembrey/change-case 3 | * This way we do not have to bundle the package(s) 4 | */ 5 | 6 | export function pascalCase(input: string) { 7 | if (!(typeof input === 'string' || Array.isArray(input))) { 8 | throw new TypeError('Expected the input to be `string | string[]`'); 9 | } 10 | 11 | const options = { 12 | pascalCase: true, 13 | locale: 'en-US', 14 | }; 15 | 16 | if (Array.isArray(input)) { 17 | input = input.map(x => x.trim()) 18 | .filter(x => x.length) 19 | .join('-'); 20 | } else { 21 | input = input.trim(); 22 | } 23 | 24 | if (input.length === 0) { 25 | return ''; 26 | } 27 | 28 | if (input.length === 1) { 29 | return options.pascalCase ? input.toLocaleUpperCase(options.locale) : input.toLocaleLowerCase(options.locale); 30 | } 31 | 32 | input = input.replace(/^[_.\- ]+/, ''); 33 | input = input.toLocaleLowerCase(); 34 | 35 | if (options.pascalCase) { 36 | input = input.charAt(0).toLocaleUpperCase(options.locale) + input.slice(1); 37 | } 38 | 39 | return postProcess(input, options); 40 | }; 41 | 42 | function postProcess(input: string, options: any) { 43 | return input.replace(/[_.\- ]+([\p{Alpha}\p{N}_]|$)/gu, (_: any, p1: any) => p1.toLocaleUpperCase(options.locale)) 44 | .replace(/\d+([\p{Alpha}\p{N}_]|$)/gu, m => m.toLocaleUpperCase(options.locale)); 45 | }; -------------------------------------------------------------------------------- /test/project.test.ts: -------------------------------------------------------------------------------- 1 | import { AwsCdkAppSyncApp } from '../src'; 2 | 3 | test('Empty', () => { 4 | const project = new AwsCdkAppSyncApp({ 5 | name: 'test', 6 | cdkVersion: '1.80.0', 7 | transformerVersion: '1.77.9', 8 | defaultReleaseBranch: 'main' 9 | }); 10 | 11 | expect(project.cdkVersion).toEqual('^1.80.0'); 12 | expect(project.srcdir).toEqual('src'); 13 | expect(project.libdir).toEqual('lib'); 14 | 15 | // TODO: Fix this as it does not work 16 | // const cdkAppsyncTransformer = project.deps.getDependency('cdk-appsync-transformer'); 17 | 18 | // expect(dependencies['cdk-appsync-transformer']).toEqual('^1.77.9'); 19 | }); -------------------------------------------------------------------------------- /tsconfig.jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "alwaysStrict": true, 4 | "declaration": true, 5 | "experimentalDecorators": true, 6 | "inlineSourceMap": true, 7 | "inlineSources": true, 8 | "lib": [ 9 | "es2018" 10 | ], 11 | "module": "CommonJS", 12 | "noEmitOnError": false, 13 | "noFallthroughCasesInSwitch": true, 14 | "noImplicitAny": true, 15 | "noImplicitReturns": true, 16 | "noImplicitThis": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "resolveJsonModule": true, 20 | "strict": true, 21 | "strictNullChecks": true, 22 | "strictPropertyInitialization": true, 23 | "stripInternal": true, 24 | "target": "ES2018" 25 | }, 26 | "include": [ 27 | ".projenrc.js", 28 | "src/**/*.ts", 29 | "test/**/*.ts" 30 | ], 31 | "exclude": [ 32 | "node_modules" 33 | ], 34 | "//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"npx projen\"." 35 | } 36 | --------------------------------------------------------------------------------