From cc1ddca8d6482b7fe7a50a89533f36b8e54f684c Mon Sep 17 00:00:00 2001 From: Jack Stevenson Date: Thu, 2 Nov 2023 09:48:48 +1100 Subject: [PATCH] fix(infrastructure): fix java compilation issue without api, and skip unused constructs in java/py (#629) The Java website construct didn't compile when an api wasn't present due to some extra brackets being commented out. Additionally the website construct would always be rendered for typescript even if no website was configured. Likewise for Java and Python, the api and website constructs were always rendered. This PR also adds tests for the infrastructure projects. --- .../constructs/WebsiteConstruct.java.mustache | 6 +- .../java/infrastructure-java-project.ts | 13 +- .../python/infrastructure-py-project.ts | 11 +- .../typescript/infrastructure-ts-project.ts | 11 +- packages/infrastructure/test/.gitkeep | 1 - .../infrastructure-java-project.test.ts.snap | 3013 ++++++++++ .../java/infrastructure-java-project.test.ts | 58 + .../infrastructure-py-project.test.ts.snap | 2293 ++++++++ .../python/infrastructure-py-project.test.ts | 58 + .../infrastructure-ts-project.test.ts.snap | 5015 +++++++++++++++++ .../infrastructure-ts-project.test.ts | 58 + .../projects/utils/snapshot-infra-project.ts | 70 + 12 files changed, 10587 insertions(+), 20 deletions(-) delete mode 100644 packages/infrastructure/test/.gitkeep create mode 100644 packages/infrastructure/test/projects/java/__snapshots__/infrastructure-java-project.test.ts.snap create mode 100644 packages/infrastructure/test/projects/java/infrastructure-java-project.test.ts create mode 100644 packages/infrastructure/test/projects/python/__snapshots__/infrastructure-py-project.test.ts.snap create mode 100644 packages/infrastructure/test/projects/python/infrastructure-py-project.test.ts create mode 100644 packages/infrastructure/test/projects/typescript/__snapshots__/infrastructure-ts-project.test.ts.snap create mode 100644 packages/infrastructure/test/projects/typescript/infrastructure-ts-project.test.ts create mode 100644 packages/infrastructure/test/projects/utils/snapshot-infra-project.ts diff --git a/packages/infrastructure/samples/infrastructure/java/src/java/groupId/constructs/WebsiteConstruct.java.mustache b/packages/infrastructure/samples/infrastructure/java/src/java/groupId/constructs/WebsiteConstruct.java.mustache index 610fe8c7a..b2357708f 100644 --- a/packages/infrastructure/samples/infrastructure/java/src/java/groupId/constructs/WebsiteConstruct.java.mustache +++ b/packages/infrastructure/samples/infrastructure/java/src/java/groupId/constructs/WebsiteConstruct.java.mustache @@ -16,9 +16,6 @@ import software.constructs.Construct; * Construct to deploy a Static Website */ public class WebsiteConstruct extends Construct { - public WebsiteConstruct(Construct scope, String id, UserIdentity userIdentity) { - this(scope, id, userIdentity{{^hasApi}}/* {{/hasApi}}, null{{^hasApi}} */{{/hasApi}}); - } public WebsiteConstruct(Construct scope, String id, UserIdentity userIdentity{{^hasApi}}/* {{/hasApi}}, ApiConstruct apiConstruct{{^hasApi}} */{{/hasApi}}) { super(scope, id); @@ -31,7 +28,8 @@ public class WebsiteConstruct extends Construct { "identityPoolId", userIdentity.getIdentityPool().getIdentityPoolId(), "userPoolId", userIdentity.getUserPool().getUserPoolId(), "userPoolWebClientId", userIdentity.getUserPoolClient().getUserPoolClientId(){{#hasApi}},{{/hasApi}} - {{^hasApi}}// {{/hasApi}}"apiUrl", apiConstruct.api.getApi().urlForPath()))) + {{^hasApi}}// {{/hasApi}}"apiUrl", apiConstruct.api.getApi().urlForPath() + ))) .build()) .distributionProps(DistributionProps.builder() .geoRestriction(GeoRestriction.allowlist( diff --git a/packages/infrastructure/src/projects/java/infrastructure-java-project.ts b/packages/infrastructure/src/projects/java/infrastructure-java-project.ts index e1bd44e3f..9f4989af8 100644 --- a/packages/infrastructure/src/projects/java/infrastructure-java-project.ts +++ b/packages/infrastructure/src/projects/java/infrastructure-java-project.ts @@ -142,13 +142,16 @@ export class InfrastructureJavaProject extends AwsCdkJavaApp { ) { fs.readdirSync(dir, { withFileTypes: true }) .filter((f) => { + let shouldIncludeFile = true; if (!mustacheConfig.hasApi) { - return !f.name.endsWith("api.ts.mustache"); - } else if (!mustacheConfig.hasWebsite) { - return !f.name.endsWith("website.ts.mustache"); - } else { - return true; + shouldIncludeFile &&= !f.name.endsWith("ApiConstruct.java.mustache"); + } + if (!mustacheConfig.hasWebsite) { + shouldIncludeFile &&= !f.name.endsWith( + "WebsiteConstruct.java.mustache" + ); } + return shouldIncludeFile; }) .forEach((f) => { if (f.isDirectory()) { diff --git a/packages/infrastructure/src/projects/python/infrastructure-py-project.ts b/packages/infrastructure/src/projects/python/infrastructure-py-project.ts index fd59c9807..6b15e944c 100644 --- a/packages/infrastructure/src/projects/python/infrastructure-py-project.ts +++ b/packages/infrastructure/src/projects/python/infrastructure-py-project.ts @@ -130,13 +130,14 @@ export class InfrastructurePyProject extends AwsCdkPythonApp { ) { fs.readdirSync(dir, { withFileTypes: true }) .filter((f) => { + let shouldIncludeFile = true; if (!mustacheConfig.hasApi) { - return !f.name.endsWith("api.ts.mustache"); - } else if (!mustacheConfig.hasWebsite) { - return !f.name.endsWith("website.ts.mustache"); - } else { - return true; + shouldIncludeFile &&= !f.name.endsWith("api.py.mustache"); + } + if (!mustacheConfig.hasWebsite) { + shouldIncludeFile &&= !f.name.endsWith("website.py.mustache"); } + return shouldIncludeFile; }) .forEach((f) => { if (f.isDirectory()) { diff --git a/packages/infrastructure/src/projects/typescript/infrastructure-ts-project.ts b/packages/infrastructure/src/projects/typescript/infrastructure-ts-project.ts index 712426d46..97496ebcf 100644 --- a/packages/infrastructure/src/projects/typescript/infrastructure-ts-project.ts +++ b/packages/infrastructure/src/projects/typescript/infrastructure-ts-project.ts @@ -128,13 +128,14 @@ export class InfrastructureTsProject extends AwsCdkTypeScriptApp { ) { fs.readdirSync(dir, { withFileTypes: true }) .filter((f) => { + let shouldIncludeFile = true; if (!mustacheConfig.hasApi) { - return !f.name.endsWith("api.ts.mustache"); - } else if (!mustacheConfig.hasWebsite) { - return !f.name.endsWith("website.ts.mustache"); - } else { - return true; + shouldIncludeFile &&= !f.name.endsWith("api.ts.mustache"); } + if (!mustacheConfig.hasWebsite) { + shouldIncludeFile &&= !f.name.endsWith("website.ts.mustache"); + } + return shouldIncludeFile; }) .forEach((f) => f.isDirectory() diff --git a/packages/infrastructure/test/.gitkeep b/packages/infrastructure/test/.gitkeep deleted file mode 100644 index 4974098ca..000000000 --- a/packages/infrastructure/test/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -// Delete me once tests are added \ No newline at end of file diff --git a/packages/infrastructure/test/projects/java/__snapshots__/infrastructure-java-project.test.ts.snap b/packages/infrastructure/test/projects/java/__snapshots__/infrastructure-java-project.test.ts.snap new file mode 100644 index 000000000..c50914a3c --- /dev/null +++ b/packages/infrastructure/test/projects/java/__snapshots__/infrastructure-java-project.test.ts.snap @@ -0,0 +1,3013 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`InfrastructureJavaProject Defaults 1`] = ` +{ + ".gitattributes": "# ~~ Generated by projen. To modify, edit src/test/java/projenrc.java and run "npx projen". + +/.gitattributes linguist-generated +/.github/workflows/pull-request-lint.yml linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/pom.xml linguist-generated", + ".github/workflows/pull-request-lint.yml": "# ~~ Generated by projen. To modify, edit src/test/java/projenrc.java and run "npx projen". + +name: pull-request-lint +on: + pull_request_target: + types: + - labeled + - opened + - synchronize + - reopened + - ready_for_review + - edited +jobs: + validate: + name: Validate PR title + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: amannn/action-semantic-pull-request@v5.0.2 + env: + GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }} + with: + types: |- + feat + fix + chore + requireScope: false + githubBaseUrl: \${{ github.api_url }} +", + ".gitignore": "# ~~ Generated by projen. To modify, edit src/test/java/projenrc.java and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/.github/workflows/pull-request-lint.yml +!/pom.xml +.classpath +.project +.settings +target +dist/java +!/cdk.json +/cdk.out/ +.cdk.staging/ +", + ".projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit src/test/java/projenrc.java and run "npx projen".", + "dependencies": [ + { + "metadata": { + "configuration": { + "release": "11", + }, + }, + "name": "org.apache.maven.plugins/maven-compiler-plugin", + "type": "build", + "version": "3.8.1", + }, + { + "metadata": { + "configuration": { + "rules": [ + { + "requireMavenVersion": [ + { + "version": "3.6", + }, + ], + }, + ], + }, + "executions": [ + { + "goals": [ + "enforce", + ], + "id": "enforce-maven", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-enforcer-plugin", + "type": "build", + "version": "3.0.0-M3", + }, + { + "metadata": { + "configuration": { + "archive": { + "index": true, + "manifest": { + "addDefaultImplementationEntries": true, + "addDefaultSpecificationEntries": true, + }, + }, + }, + }, + "name": "org.apache.maven.plugins/maven-jar-plugin", + "type": "build", + "version": "3.2.0", + }, + { + "metadata": { + "configuration": { + "additionalJOptions": { + "additionalJOption": [ + "-J-XX:+TieredCompilation", + "-J-XX:TieredStopAtLevel=1", + ], + }, + "detectJavaApiLink": false, + "failOnError": false, + "show": "protected", + }, + "executions": [ + { + "goals": [ + "jar", + ], + "id": "attach-javadocs", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-javadoc-plugin", + "type": "build", + "version": "3.2.0", + }, + { + "metadata": { + "executions": [ + { + "goals": [ + "jar", + ], + "id": "attach-sources", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-source-plugin", + "type": "build", + "version": "3.2.1", + }, + { + "name": "org.apache.maven.plugins/maven-surefire-plugin", + "type": "build", + "version": "3.1.2", + }, + { + "name": "org.codehaus.mojo/exec-maven-plugin", + "type": "build", + "version": "3.0.0", + }, + { + "name": "software.amazon.awscdk/aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "software.aws/pdk", + "type": "runtime", + "version": "^0", + }, + { + "name": "software.constructs/constructs", + "type": "runtime", + "version": "^10.0.5", + }, + { + "name": "io.github.cdklabs/projen", + "type": "test", + "version": "99.99.99", + }, + { + "name": "io.github.origin-energy/java-snapshot-testing-junit5", + "type": "test", + "version": "^4.0.6", + }, + { + "name": "io.github.origin-energy/java-snapshot-testing-plugin-jackson", + "type": "test", + "version": "^4.0.6", + }, + { + "name": "org.junit.jupiter/junit-jupiter-api", + "type": "test", + "version": "^5", + }, + { + "name": "org.junit.jupiter/junit-jupiter-engine", + "type": "test", + "version": "^5", + }, + { + "name": "org.slf4j/slf4j-simple", + "type": "test", + "version": "2.0.0-alpha0", + }, + ], + }, + ".projen/files.json": { + "//": "~~ Generated by projen. To modify, edit src/test/java/projenrc.java and run "npx projen".", + "files": [ + ".gitattributes", + ".github/workflows/pull-request-lint.yml", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "pom.xml", + ], + }, + ".projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit src/test/java/projenrc.java and run "npx projen".", + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "default", + }, + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "clobber": { + "condition": "git diff --exit-code > /dev/null", + "description": "hard resets to HEAD of origin and cleans the local repo", + "env": { + "BRANCH": "$(git branch --show-current)", + }, + "name": "clobber", + "steps": [ + { + "exec": "git checkout -b scratch", + "name": "save current HEAD in "scratch" branch", + }, + { + "exec": "git checkout $BRANCH", + }, + { + "exec": "git fetch origin", + "name": "fetch latest changes from origin", + }, + { + "exec": "git reset --hard origin/$BRANCH", + "name": "hard reset to origin commit", + }, + { + "exec": "git clean -fdx", + "name": "clean all untracked files", + }, + { + "say": "ready to rock! (unpushed commits are under the "scratch" branch)", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + "steps": [ + { + "exec": "mvn compiler:compile", + }, + ], + }, + "default": { + "description": "Synthesize project files", + "name": "default", + "steps": [ + { + "exec": "mvn compiler:testCompile --quiet", + }, + { + "exec": "mvn exec:java --quiet -Dexec.mainClass=projenrc -Dexec.classpathScope="test"", + }, + ], + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "eject": { + "description": "Remove projen from the project", + "env": { + "PROJEN_EJECTING": "true", + }, + "name": "eject", + "steps": [ + { + "spawn": "default", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "env": { + "MAVEN_OPTS": "-XX:+TieredCompilation -XX:TieredStopAtLevel=1", + }, + "name": "package", + "steps": [ + { + "exec": "mkdir -p dist/java", + }, + { + "exec": "mvn deploy -D=altDeploymentRepository=local::default::file:///$PWD/dist/java", + }, + ], + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth", + }, + ], + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "mvn test", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "cdk.json": { + "//": "~~ Generated by projen. To modify, edit src/test/java/projenrc.java and run "npx projen".", + "app": "mvn exec:java --quiet -Dexec.mainClass=software.aws.infra.Main", + "output": "cdk.out", + }, + "pom.xml": " + + 4.0.0 + software.aws.infra + infra + 0.0.0 + jar + Defaults + + UTF-8 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + + 3.6 + + + + + + enforce-maven + + enforce + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + false + protected + false + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + + + + software.amazon.awscdk + aws-cdk-lib + [2.1.0,3.0.0) + + + software.aws + pdk + (,1.0.0) + + + software.constructs + constructs + [10.0.5,11.0.0) + + + io.github.cdklabs + projen + 99.99.99 + test + + + io.github.origin-energy + java-snapshot-testing-junit5 + [4.0.6,5.0.0) + test + + + io.github.origin-energy + java-snapshot-testing-plugin-jackson + [4.0.6,5.0.0) + test + + + org.junit.jupiter + junit-jupiter-api + [5.0.0,6.0.0) + test + + + org.junit.jupiter + junit-jupiter-engine + [5.0.0,6.0.0) + test + + + org.slf4j + slf4j-simple + 2.0.0-alpha0 + test + + + +", + "src/main/java/software/aws/infra/Main.java": "package software.aws.infra; + +import software.aws.pdk.cdk_graph.CdkGraph; +import software.aws.pdk.cdk_graph.FilterPreset; +import software.aws.pdk.cdk_graph.Filters; +import software.aws.pdk.cdk_graph.ICdkGraphProps; +import software.aws.pdk.cdk_graph.IFilter; +import software.aws.pdk.cdk_graph.IGraphFilterPlan; +import software.aws.pdk.cdk_graph_plugin_diagram.CdkGraphDiagramPlugin; +import software.aws.pdk.cdk_graph_plugin_diagram.IDiagramConfigBase; +import software.aws.pdk.cdk_graph_plugin_diagram.IPluginConfig; +import software.aws.pdk.pdk_nag.AwsPrototypingChecks; +import software.aws.pdk.pdk_nag.PDKNag; +import software.aws.pdk.pdk_nag.PDKNagAppProps; + +import software.aws.infra.stacks.ApplicationStack; + +import java.util.Arrays; + +import software.amazon.awscdk.App; +import software.amazon.awscdk.Environment; +import software.amazon.awscdk.StackProps; + +public class Main { + public static void main(final String[] args) { + App app = PDKNag.app(PDKNagAppProps.builder() + .nagPacks(Arrays.asList(new AwsPrototypingChecks())) + .build()); + + new ApplicationStack(app, "infra-dev", StackProps.builder() + .env(Environment.builder() + .account(System.getenv("CDK_DEFAULT_ACCOUNT")) + .region(System.getenv("CDK_DEFAULT_REGION")) + .build()) + .build()); + + CdkGraph graph = new CdkGraph(app, ICdkGraphProps.builder() + .plugins(Arrays.asList(new CdkGraphDiagramPlugin(IPluginConfig.builder() + .defaults(IDiagramConfigBase.builder() + .filterPlan(IGraphFilterPlan.builder() + .preset(FilterPreset.COMPACT) + .filters(Arrays.asList(IFilter.builder() + .store(Filters.pruneCustomResources()) + .build())) + .build()) + .build()) + .build()))) + .build()); + + app.synth(); + graph.report(); + } +}", + "src/main/java/software/aws/infra/stacks/ApplicationStack.java": "package software.aws.infra.stacks; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.aws.pdk.identity.UserIdentity; +import software.constructs.Construct; + +public class ApplicationStack extends Stack { + public ApplicationStack(Construct scope, String id, StackProps props) { + super(scope, id, props); + + UserIdentity userIdentity = new UserIdentity(this, String.format("%sUserIdentity", id)); + } +} +", + "src/test/java/software/aws/infra/stacks/ApplicationStackTest.java": "package software.aws.infra.stacks; + +import au.com.origin.snapshots.junit5.SnapshotExtension; +import software.amazon.awscdk.App; +import software.amazon.awscdk.assertions.Template; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import au.com.origin.snapshots.Expect; + +// Ensure you extend your test class with the SnapshotExtension +@ExtendWith(SnapshotExtension.class) +public class ApplicationStackTest { + Expect expect; + + @Test + public void myTest() { + App app = new App(); + ApplicationStack stack = new ApplicationStack(app, "test", null); + + Template template = Template.fromStack(stack); + expect.serializer("json").toMatchSnapshot(template.toJSON()); + } +}", + "src/test/resources/snapshot.properties": "serializer=au.com.origin.snapshots.serializers.v1.ToStringSnapshotSerializer +serializer.base64=au.com.origin.snapshots.serializers.v1.Base64SnapshotSerializer +serializer.json=au.com.origin.snapshots.jackson.serializers.v1.JacksonSnapshotSerializer +serializer.orderedJson=au.com.origin.snapshots.jackson.serializers.v1.DeterministicJacksonSnapshotSerializer +comparator=au.com.origin.snapshots.comparators.v1.PlainTextEqualsComparator +reporters=au.com.origin.snapshots.reporters.v1.PlainTextSnapshotReporter +snapshot-dir=__snapshots__ +output-dir=src/test/java +ci-env-var=CI +update-snapshot=none", +} +`; + +exports[`InfrastructureJavaProject With Api 1`] = ` +{ + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/pom.xml linguist-generated +/project.json linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/pom.xml +.classpath +.project +.settings +target +dist/java +!/cdk.json +/cdk.out/ +.cdk.staging/ +!/project.json +", + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "metadata": { + "configuration": { + "release": "11", + }, + }, + "name": "org.apache.maven.plugins/maven-compiler-plugin", + "type": "build", + "version": "3.8.1", + }, + { + "metadata": { + "configuration": { + "rules": [ + { + "requireMavenVersion": [ + { + "version": "3.6", + }, + ], + }, + ], + }, + "executions": [ + { + "goals": [ + "enforce", + ], + "id": "enforce-maven", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-enforcer-plugin", + "type": "build", + "version": "3.0.0-M3", + }, + { + "metadata": { + "configuration": { + "archive": { + "index": true, + "manifest": { + "addDefaultImplementationEntries": true, + "addDefaultSpecificationEntries": true, + }, + }, + }, + }, + "name": "org.apache.maven.plugins/maven-jar-plugin", + "type": "build", + "version": "3.2.0", + }, + { + "metadata": { + "configuration": { + "additionalJOptions": { + "additionalJOption": [ + "-J-XX:+TieredCompilation", + "-J-XX:TieredStopAtLevel=1", + ], + }, + "detectJavaApiLink": false, + "failOnError": false, + "show": "protected", + }, + "executions": [ + { + "goals": [ + "jar", + ], + "id": "attach-javadocs", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-javadoc-plugin", + "type": "build", + "version": "3.2.0", + }, + { + "metadata": { + "executions": [ + { + "goals": [ + "jar", + ], + "id": "attach-sources", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-source-plugin", + "type": "build", + "version": "3.2.1", + }, + { + "name": "org.apache.maven.plugins/maven-surefire-plugin", + "type": "build", + "version": "3.1.2", + }, + { + "name": "com.generated.api/Api-java-infra", + "type": "runtime", + "version": "0.0.0", + }, + { + "name": "software.amazon.awscdk/aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "software.aws/pdk", + "type": "runtime", + "version": "^0", + }, + { + "name": "software.constructs/constructs", + "type": "runtime", + "version": "^10.0.5", + }, + { + "name": "io.github.origin-energy/java-snapshot-testing-junit5", + "type": "test", + "version": "^4.0.6", + }, + { + "name": "io.github.origin-energy/java-snapshot-testing-plugin-jackson", + "type": "test", + "version": "^4.0.6", + }, + { + "name": "org.junit.jupiter/junit-jupiter-api", + "type": "test", + "version": "^5", + }, + { + "name": "org.junit.jupiter/junit-jupiter-engine", + "type": "test", + "version": "^5", + }, + { + "name": "org.slf4j/slf4j-simple", + "type": "test", + "version": "2.0.0-alpha0", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "pom.xml", + "project.json", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + "steps": [ + { + "exec": "mvn compiler:compile", + }, + ], + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "env": { + "MAVEN_OPTS": "-XX:+TieredCompilation -XX:TieredStopAtLevel=1", + }, + "name": "package", + "steps": [ + { + "exec": "mkdir -p dist/java", + }, + { + "exec": "mvn deploy -D=altDeploymentRepository=local::default::file:///$PWD/dist/java", + }, + ], + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth", + }, + ], + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "mvn test", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "mvn exec:java --quiet -Dexec.mainClass=software.aws.infra.Main", + "output": "cdk.out", + }, + "infra/pom.xml": " + + 4.0.0 + software.aws.infra + infra + 0.0.0 + jar + WithApi + + UTF-8 + + + + Apijavainfra + file://../api/generated/infrastructure/java/dist/java + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + + 3.6 + + + + + + enforce-maven + + enforce + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + false + protected + false + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + + + + com.generated.api + Api-java-infra + 0.0.0 + + + software.amazon.awscdk + aws-cdk-lib + [2.1.0,3.0.0) + + + software.aws + pdk + (,1.0.0) + + + software.constructs + constructs + [10.0.5,11.0.0) + + + io.github.origin-energy + java-snapshot-testing-junit5 + [4.0.6,5.0.0) + test + + + io.github.origin-energy + java-snapshot-testing-plugin-jackson + [4.0.6,5.0.0) + test + + + org.junit.jupiter + junit-jupiter-api + [5.0.0,6.0.0) + test + + + org.junit.jupiter + junit-jupiter-engine + [5.0.0,6.0.0) + test + + + org.slf4j + slf4j-simple + 2.0.0-alpha0 + test + + + +", + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "implicitDependencies": [ + "Apijavainfra", + ], + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen build", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen diff", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen post-compile", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen pre-compile", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen test", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/src/main/java/software/aws/infra/Main.java": "package software.aws.infra; + +import software.aws.pdk.cdk_graph.CdkGraph; +import software.aws.pdk.cdk_graph.FilterPreset; +import software.aws.pdk.cdk_graph.Filters; +import software.aws.pdk.cdk_graph.ICdkGraphProps; +import software.aws.pdk.cdk_graph.IFilter; +import software.aws.pdk.cdk_graph.IGraphFilterPlan; +import software.aws.pdk.cdk_graph_plugin_diagram.CdkGraphDiagramPlugin; +import software.aws.pdk.cdk_graph_plugin_diagram.IDiagramConfigBase; +import software.aws.pdk.cdk_graph_plugin_diagram.IPluginConfig; +import software.aws.pdk.pdk_nag.AwsPrototypingChecks; +import software.aws.pdk.pdk_nag.PDKNag; +import software.aws.pdk.pdk_nag.PDKNagAppProps; + +import software.aws.infra.stacks.ApplicationStack; + +import java.util.Arrays; + +import software.amazon.awscdk.App; +import software.amazon.awscdk.Environment; +import software.amazon.awscdk.StackProps; + +public class Main { + public static void main(final String[] args) { + App app = PDKNag.app(PDKNagAppProps.builder() + .nagPacks(Arrays.asList(new AwsPrototypingChecks())) + .build()); + + new ApplicationStack(app, "infra-dev", StackProps.builder() + .env(Environment.builder() + .account(System.getenv("CDK_DEFAULT_ACCOUNT")) + .region(System.getenv("CDK_DEFAULT_REGION")) + .build()) + .build()); + + CdkGraph graph = new CdkGraph(app, ICdkGraphProps.builder() + .plugins(Arrays.asList(new CdkGraphDiagramPlugin(IPluginConfig.builder() + .defaults(IDiagramConfigBase.builder() + .filterPlan(IGraphFilterPlan.builder() + .preset(FilterPreset.COMPACT) + .filters(Arrays.asList(IFilter.builder() + .store(Filters.pruneCustomResources()) + .build())) + .build()) + .build()) + .build()))) + .build()); + + app.synth(); + graph.report(); + } +}", + "infra/src/main/java/software/aws/infra/constructs/ApiConstruct.java": "package software.aws.infra.constructs; + +import com.generated.api.Apijavainfra.infra.Api; +import com.generated.api.Apijavainfra.infra.ApiProps; +import com.generated.api.Apijavainfra.infra.MockIntegrations; + +import java.util.Arrays; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.services.apigateway.Cors; +import software.amazon.awscdk.services.apigateway.CorsOptions; +import software.amazon.awscdk.services.iam.AccountPrincipal; +import software.amazon.awscdk.services.iam.AnyPrincipal; +import software.amazon.awscdk.services.iam.Effect; +import software.amazon.awscdk.services.iam.PolicyDocument; +import software.amazon.awscdk.services.iam.PolicyDocumentProps; +import software.amazon.awscdk.services.iam.PolicyStatement; +import software.amazon.awscdk.services.iam.PolicyStatementProps; +import software.aws.pdk.identity.UserIdentity; +import software.aws.pdk.type_safe_api.Authorizers; +import software.constructs.Construct; + +/** + * Infrastructure construct to deploy a Type Safe API. + */ +public class ApiConstruct extends Construct { + /** + * API instance + */ + public final Api api; + + public ApiConstruct(Construct scope, String id, UserIdentity userIdentity) { + super(scope, id); + + this.api = new Api(this, id, ApiProps.builder() + .defaultAuthorizer(Authorizers.iam()) + .corsOptions(CorsOptions.builder() + .allowOrigins(Cors.ALL_ORIGINS) + .allowMethods(Cors.ALL_METHODS) + .build()) + .integrations(MockIntegrations.mockAll().build()) + .policy(new PolicyDocument(PolicyDocumentProps.builder() + .statements(Arrays.asList( + // Here we grant any AWS credentials from the account that the prototype is deployed in to call the api. + // Machine to machine fine-grained access can be defined here using more specific principals (eg roles or + // users) and resources (ie which api paths may be invoked by which principal) if required. + // If doing so, the cognito identity pool authenticated role must still be granted access for cognito users to + // still be granted access to the API. + new PolicyStatement(PolicyStatementProps.builder() + .effect(Effect.ALLOW) + .principals(Arrays.asList(new AccountPrincipal(Stack.of(this).getAccount()))) + .actions(Arrays.asList("execute-api:Invoke")) + .resources(Arrays.asList("execute-api:/*")) + .build()), + // Open up OPTIONS to allow browsers to make unauthenticated preflight requests + new PolicyStatement(PolicyStatementProps.builder() + .effect(Effect.ALLOW) + .principals(Arrays.asList(new AnyPrincipal())) + .actions(Arrays.asList("execute-api:Invoke")) + .resources(Arrays.asList("execute-api:/*/OPTIONS/*")) + .build()) + )) + .build())) + .build()); + + userIdentity.getIdentityPool().getAuthenticatedRole() + .addToPrincipalPolicy(new PolicyStatement(PolicyStatementProps.builder() + .effect(Effect.ALLOW) + .actions(Arrays.asList("execute-api:Invoke")) + .resources(Arrays.asList(this.api.getApi().arnForExecuteApi("*", "/*", "*"))) + .build())); + } +} +", + "infra/src/main/java/software/aws/infra/stacks/ApplicationStack.java": "package software.aws.infra.stacks; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.aws.infra.constructs.ApiConstruct; +import software.aws.pdk.identity.UserIdentity; +import software.constructs.Construct; + +public class ApplicationStack extends Stack { + public ApplicationStack(Construct scope, String id, StackProps props) { + super(scope, id, props); + + UserIdentity userIdentity = new UserIdentity(this, String.format("%sUserIdentity", id)); + new ApiConstruct(this, "Api", userIdentity); + } +} +", + "infra/src/test/java/software/aws/infra/stacks/ApplicationStackTest.java": "package software.aws.infra.stacks; + +import au.com.origin.snapshots.junit5.SnapshotExtension; +import software.amazon.awscdk.App; +import software.amazon.awscdk.assertions.Template; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import au.com.origin.snapshots.Expect; + +// Ensure you extend your test class with the SnapshotExtension +@ExtendWith(SnapshotExtension.class) +public class ApplicationStackTest { + Expect expect; + + @Test + public void myTest() { + App app = new App(); + ApplicationStack stack = new ApplicationStack(app, "test", null); + + Template template = Template.fromStack(stack); + expect.serializer("json").toMatchSnapshot(template.toJSON()); + } +}", + "infra/src/test/resources/snapshot.properties": "serializer=au.com.origin.snapshots.serializers.v1.ToStringSnapshotSerializer +serializer.base64=au.com.origin.snapshots.serializers.v1.Base64SnapshotSerializer +serializer.json=au.com.origin.snapshots.jackson.serializers.v1.JacksonSnapshotSerializer +serializer.orderedJson=au.com.origin.snapshots.jackson.serializers.v1.DeterministicJacksonSnapshotSerializer +comparator=au.com.origin.snapshots.comparators.v1.PlainTextEqualsComparator +reporters=au.com.origin.snapshots.reporters.v1.PlainTextSnapshotReporter +snapshot-dir=__snapshots__ +output-dir=src/test/java +ci-env-var=CI +update-snapshot=none", +} +`; + +exports[`InfrastructureJavaProject With Api and Website 1`] = ` +{ + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/pom.xml linguist-generated +/project.json linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/pom.xml +.classpath +.project +.settings +target +dist/java +!/cdk.json +/cdk.out/ +.cdk.staging/ +!/project.json +", + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "metadata": { + "configuration": { + "release": "11", + }, + }, + "name": "org.apache.maven.plugins/maven-compiler-plugin", + "type": "build", + "version": "3.8.1", + }, + { + "metadata": { + "configuration": { + "rules": [ + { + "requireMavenVersion": [ + { + "version": "3.6", + }, + ], + }, + ], + }, + "executions": [ + { + "goals": [ + "enforce", + ], + "id": "enforce-maven", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-enforcer-plugin", + "type": "build", + "version": "3.0.0-M3", + }, + { + "metadata": { + "configuration": { + "archive": { + "index": true, + "manifest": { + "addDefaultImplementationEntries": true, + "addDefaultSpecificationEntries": true, + }, + }, + }, + }, + "name": "org.apache.maven.plugins/maven-jar-plugin", + "type": "build", + "version": "3.2.0", + }, + { + "metadata": { + "configuration": { + "additionalJOptions": { + "additionalJOption": [ + "-J-XX:+TieredCompilation", + "-J-XX:TieredStopAtLevel=1", + ], + }, + "detectJavaApiLink": false, + "failOnError": false, + "show": "protected", + }, + "executions": [ + { + "goals": [ + "jar", + ], + "id": "attach-javadocs", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-javadoc-plugin", + "type": "build", + "version": "3.2.0", + }, + { + "metadata": { + "executions": [ + { + "goals": [ + "jar", + ], + "id": "attach-sources", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-source-plugin", + "type": "build", + "version": "3.2.1", + }, + { + "name": "org.apache.maven.plugins/maven-surefire-plugin", + "type": "build", + "version": "3.1.2", + }, + { + "name": "com.generated.api/Api-java-infra", + "type": "runtime", + "version": "0.0.0", + }, + { + "name": "software.amazon.awscdk/aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "software.aws/pdk", + "type": "runtime", + "version": "^0", + }, + { + "name": "software.constructs/constructs", + "type": "runtime", + "version": "^10.0.5", + }, + { + "name": "io.github.origin-energy/java-snapshot-testing-junit5", + "type": "test", + "version": "^4.0.6", + }, + { + "name": "io.github.origin-energy/java-snapshot-testing-plugin-jackson", + "type": "test", + "version": "^4.0.6", + }, + { + "name": "org.junit.jupiter/junit-jupiter-api", + "type": "test", + "version": "^5", + }, + { + "name": "org.junit.jupiter/junit-jupiter-engine", + "type": "test", + "version": "^5", + }, + { + "name": "org.slf4j/slf4j-simple", + "type": "test", + "version": "2.0.0-alpha0", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "pom.xml", + "project.json", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + "steps": [ + { + "exec": "mvn compiler:compile", + }, + ], + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "env": { + "MAVEN_OPTS": "-XX:+TieredCompilation -XX:TieredStopAtLevel=1", + }, + "name": "package", + "steps": [ + { + "exec": "mkdir -p dist/java", + }, + { + "exec": "mvn deploy -D=altDeploymentRepository=local::default::file:///$PWD/dist/java", + }, + ], + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth", + }, + ], + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "mvn test", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "mvn exec:java --quiet -Dexec.mainClass=software.aws.infra.Main", + "output": "cdk.out", + }, + "infra/pom.xml": " + + 4.0.0 + software.aws.infra + infra + 0.0.0 + jar + WithApi + + UTF-8 + + + + Apijavainfra + file://../api/generated/infrastructure/java/dist/java + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + + 3.6 + + + + + + enforce-maven + + enforce + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + false + protected + false + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + + + + com.generated.api + Api-java-infra + 0.0.0 + + + software.amazon.awscdk + aws-cdk-lib + [2.1.0,3.0.0) + + + software.aws + pdk + (,1.0.0) + + + software.constructs + constructs + [10.0.5,11.0.0) + + + io.github.origin-energy + java-snapshot-testing-junit5 + [4.0.6,5.0.0) + test + + + io.github.origin-energy + java-snapshot-testing-plugin-jackson + [4.0.6,5.0.0) + test + + + org.junit.jupiter + junit-jupiter-api + [5.0.0,6.0.0) + test + + + org.junit.jupiter + junit-jupiter-engine + [5.0.0,6.0.0) + test + + + org.slf4j + slf4j-simple + 2.0.0-alpha0 + test + + + +", + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "implicitDependencies": [ + "Apijavainfra", + "Website", + ], + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen build", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen diff", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen post-compile", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen pre-compile", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen test", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/src/main/java/software/aws/infra/Main.java": "package software.aws.infra; + +import software.aws.pdk.cdk_graph.CdkGraph; +import software.aws.pdk.cdk_graph.FilterPreset; +import software.aws.pdk.cdk_graph.Filters; +import software.aws.pdk.cdk_graph.ICdkGraphProps; +import software.aws.pdk.cdk_graph.IFilter; +import software.aws.pdk.cdk_graph.IGraphFilterPlan; +import software.aws.pdk.cdk_graph_plugin_diagram.CdkGraphDiagramPlugin; +import software.aws.pdk.cdk_graph_plugin_diagram.IDiagramConfigBase; +import software.aws.pdk.cdk_graph_plugin_diagram.IPluginConfig; +import software.aws.pdk.pdk_nag.AwsPrototypingChecks; +import software.aws.pdk.pdk_nag.PDKNag; +import software.aws.pdk.pdk_nag.PDKNagAppProps; + +import software.aws.infra.stacks.ApplicationStack; + +import java.util.Arrays; + +import software.amazon.awscdk.App; +import software.amazon.awscdk.Environment; +import software.amazon.awscdk.StackProps; + +public class Main { + public static void main(final String[] args) { + App app = PDKNag.app(PDKNagAppProps.builder() + .nagPacks(Arrays.asList(new AwsPrototypingChecks())) + .build()); + + new ApplicationStack(app, "infra-dev", StackProps.builder() + .env(Environment.builder() + .account(System.getenv("CDK_DEFAULT_ACCOUNT")) + .region(System.getenv("CDK_DEFAULT_REGION")) + .build()) + .build()); + + CdkGraph graph = new CdkGraph(app, ICdkGraphProps.builder() + .plugins(Arrays.asList(new CdkGraphDiagramPlugin(IPluginConfig.builder() + .defaults(IDiagramConfigBase.builder() + .filterPlan(IGraphFilterPlan.builder() + .preset(FilterPreset.COMPACT) + .filters(Arrays.asList(IFilter.builder() + .store(Filters.pruneCustomResources()) + .build())) + .build()) + .build()) + .build()))) + .build()); + + app.synth(); + graph.report(); + } +}", + "infra/src/main/java/software/aws/infra/constructs/ApiConstruct.java": "package software.aws.infra.constructs; + +import com.generated.api.Apijavainfra.infra.Api; +import com.generated.api.Apijavainfra.infra.ApiProps; +import com.generated.api.Apijavainfra.infra.MockIntegrations; + +import java.util.Arrays; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.services.apigateway.Cors; +import software.amazon.awscdk.services.apigateway.CorsOptions; +import software.amazon.awscdk.services.iam.AccountPrincipal; +import software.amazon.awscdk.services.iam.AnyPrincipal; +import software.amazon.awscdk.services.iam.Effect; +import software.amazon.awscdk.services.iam.PolicyDocument; +import software.amazon.awscdk.services.iam.PolicyDocumentProps; +import software.amazon.awscdk.services.iam.PolicyStatement; +import software.amazon.awscdk.services.iam.PolicyStatementProps; +import software.aws.pdk.identity.UserIdentity; +import software.aws.pdk.type_safe_api.Authorizers; +import software.constructs.Construct; + +/** + * Infrastructure construct to deploy a Type Safe API. + */ +public class ApiConstruct extends Construct { + /** + * API instance + */ + public final Api api; + + public ApiConstruct(Construct scope, String id, UserIdentity userIdentity) { + super(scope, id); + + this.api = new Api(this, id, ApiProps.builder() + .defaultAuthorizer(Authorizers.iam()) + .corsOptions(CorsOptions.builder() + .allowOrigins(Cors.ALL_ORIGINS) + .allowMethods(Cors.ALL_METHODS) + .build()) + .integrations(MockIntegrations.mockAll().build()) + .policy(new PolicyDocument(PolicyDocumentProps.builder() + .statements(Arrays.asList( + // Here we grant any AWS credentials from the account that the prototype is deployed in to call the api. + // Machine to machine fine-grained access can be defined here using more specific principals (eg roles or + // users) and resources (ie which api paths may be invoked by which principal) if required. + // If doing so, the cognito identity pool authenticated role must still be granted access for cognito users to + // still be granted access to the API. + new PolicyStatement(PolicyStatementProps.builder() + .effect(Effect.ALLOW) + .principals(Arrays.asList(new AccountPrincipal(Stack.of(this).getAccount()))) + .actions(Arrays.asList("execute-api:Invoke")) + .resources(Arrays.asList("execute-api:/*")) + .build()), + // Open up OPTIONS to allow browsers to make unauthenticated preflight requests + new PolicyStatement(PolicyStatementProps.builder() + .effect(Effect.ALLOW) + .principals(Arrays.asList(new AnyPrincipal())) + .actions(Arrays.asList("execute-api:Invoke")) + .resources(Arrays.asList("execute-api:/*/OPTIONS/*")) + .build()) + )) + .build())) + .build()); + + userIdentity.getIdentityPool().getAuthenticatedRole() + .addToPrincipalPolicy(new PolicyStatement(PolicyStatementProps.builder() + .effect(Effect.ALLOW) + .actions(Arrays.asList("execute-api:Invoke")) + .resources(Arrays.asList(this.api.getApi().arnForExecuteApi("*", "/*", "*"))) + .build())); + } +} +", + "infra/src/main/java/software/aws/infra/constructs/WebsiteConstruct.java": "package software.aws.infra.constructs; + +import java.util.Map; +import java.util.TreeMap; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.services.cloudfront.GeoRestriction; +import software.aws.pdk.identity.UserIdentity; +import software.aws.pdk.static_website.DistributionProps; +import software.aws.pdk.static_website.RuntimeOptions; +import software.aws.pdk.static_website.StaticWebsite; +import software.aws.pdk.static_website.StaticWebsiteProps; +import software.constructs.Construct; + +/** + * Construct to deploy a Static Website + */ +public class WebsiteConstruct extends Construct { + + public WebsiteConstruct(Construct scope, String id, UserIdentity userIdentity, ApiConstruct apiConstruct) { + super(scope, id); + + new StaticWebsite(this, id, StaticWebsiteProps.builder() + .websiteContentPath("../website/build") + .runtimeOptions(RuntimeOptions.builder() + .jsonPayload(new TreeMap<>(Map.of( + "region", Stack.of(this).getRegion(), + "identityPoolId", userIdentity.getIdentityPool().getIdentityPoolId(), + "userPoolId", userIdentity.getUserPool().getUserPoolId(), + "userPoolWebClientId", userIdentity.getUserPoolClient().getUserPoolClientId(), + "apiUrl", apiConstruct.api.getApi().urlForPath() + ))) + .build()) + .distributionProps(DistributionProps.builder() + .geoRestriction(GeoRestriction.allowlist( + "AU", + "ID", + "IN", + "JP", + "KR", + "SG", + "US")) + .build()) + .build()); + } +} +", + "infra/src/main/java/software/aws/infra/stacks/ApplicationStack.java": "package software.aws.infra.stacks; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.aws.infra.constructs.ApiConstruct; +import software.aws.infra.constructs.WebsiteConstruct; +import software.aws.pdk.identity.UserIdentity; +import software.constructs.Construct; + +public class ApplicationStack extends Stack { + public ApplicationStack(Construct scope, String id, StackProps props) { + super(scope, id, props); + + UserIdentity userIdentity = new UserIdentity(this, String.format("%sUserIdentity", id)); + ApiConstruct apiConstruct = new ApiConstruct(this, "Api", userIdentity); + new WebsiteConstruct(this, "Website", userIdentity, apiConstruct); + } +} +", + "infra/src/test/java/software/aws/infra/stacks/ApplicationStackTest.java": "package software.aws.infra.stacks; + +import au.com.origin.snapshots.junit5.SnapshotExtension; +import software.amazon.awscdk.App; +import software.amazon.awscdk.assertions.Template; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import au.com.origin.snapshots.Expect; + +// Ensure you extend your test class with the SnapshotExtension +@ExtendWith(SnapshotExtension.class) +public class ApplicationStackTest { + Expect expect; + + @Test + public void myTest() { + App app = new App(); + ApplicationStack stack = new ApplicationStack(app, "test", null); + + Template template = Template.fromStack(stack); + expect.serializer("json").toMatchSnapshot(template.toJSON()); + } +}", + "infra/src/test/resources/snapshot.properties": "serializer=au.com.origin.snapshots.serializers.v1.ToStringSnapshotSerializer +serializer.base64=au.com.origin.snapshots.serializers.v1.Base64SnapshotSerializer +serializer.json=au.com.origin.snapshots.jackson.serializers.v1.JacksonSnapshotSerializer +serializer.orderedJson=au.com.origin.snapshots.jackson.serializers.v1.DeterministicJacksonSnapshotSerializer +comparator=au.com.origin.snapshots.comparators.v1.PlainTextEqualsComparator +reporters=au.com.origin.snapshots.reporters.v1.PlainTextSnapshotReporter +snapshot-dir=__snapshots__ +output-dir=src/test/java +ci-env-var=CI +update-snapshot=none", +} +`; + +exports[`InfrastructureJavaProject With Website 1`] = ` +{ + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/pom.xml linguist-generated +/project.json linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/pom.xml +.classpath +.project +.settings +target +dist/java +!/cdk.json +/cdk.out/ +.cdk.staging/ +!/project.json +", + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "metadata": { + "configuration": { + "release": "11", + }, + }, + "name": "org.apache.maven.plugins/maven-compiler-plugin", + "type": "build", + "version": "3.8.1", + }, + { + "metadata": { + "configuration": { + "rules": [ + { + "requireMavenVersion": [ + { + "version": "3.6", + }, + ], + }, + ], + }, + "executions": [ + { + "goals": [ + "enforce", + ], + "id": "enforce-maven", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-enforcer-plugin", + "type": "build", + "version": "3.0.0-M3", + }, + { + "metadata": { + "configuration": { + "archive": { + "index": true, + "manifest": { + "addDefaultImplementationEntries": true, + "addDefaultSpecificationEntries": true, + }, + }, + }, + }, + "name": "org.apache.maven.plugins/maven-jar-plugin", + "type": "build", + "version": "3.2.0", + }, + { + "metadata": { + "configuration": { + "additionalJOptions": { + "additionalJOption": [ + "-J-XX:+TieredCompilation", + "-J-XX:TieredStopAtLevel=1", + ], + }, + "detectJavaApiLink": false, + "failOnError": false, + "show": "protected", + }, + "executions": [ + { + "goals": [ + "jar", + ], + "id": "attach-javadocs", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-javadoc-plugin", + "type": "build", + "version": "3.2.0", + }, + { + "metadata": { + "executions": [ + { + "goals": [ + "jar", + ], + "id": "attach-sources", + }, + ], + }, + "name": "org.apache.maven.plugins/maven-source-plugin", + "type": "build", + "version": "3.2.1", + }, + { + "name": "org.apache.maven.plugins/maven-surefire-plugin", + "type": "build", + "version": "3.1.2", + }, + { + "name": "software.amazon.awscdk/aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "software.aws/pdk", + "type": "runtime", + "version": "^0", + }, + { + "name": "software.constructs/constructs", + "type": "runtime", + "version": "^10.0.5", + }, + { + "name": "io.github.origin-energy/java-snapshot-testing-junit5", + "type": "test", + "version": "^4.0.6", + }, + { + "name": "io.github.origin-energy/java-snapshot-testing-plugin-jackson", + "type": "test", + "version": "^4.0.6", + }, + { + "name": "org.junit.jupiter/junit-jupiter-api", + "type": "test", + "version": "^5", + }, + { + "name": "org.junit.jupiter/junit-jupiter-engine", + "type": "test", + "version": "^5", + }, + { + "name": "org.slf4j/slf4j-simple", + "type": "test", + "version": "2.0.0-alpha0", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "pom.xml", + "project.json", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + "steps": [ + { + "exec": "mvn compiler:compile", + }, + ], + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "env": { + "MAVEN_OPTS": "-XX:+TieredCompilation -XX:TieredStopAtLevel=1", + }, + "name": "package", + "steps": [ + { + "exec": "mkdir -p dist/java", + }, + { + "exec": "mvn deploy -D=altDeploymentRepository=local::default::file:///$PWD/dist/java", + }, + ], + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth", + }, + ], + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "mvn test", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "mvn exec:java --quiet -Dexec.mainClass=software.aws.infra.Main", + "output": "cdk.out", + }, + "infra/pom.xml": " + + 4.0.0 + software.aws.infra + infra + 0.0.0 + jar + WithApi + + UTF-8 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M3 + + + + 3.6 + + + + + + enforce-maven + + enforce + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + true + + true + true + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + false + protected + false + + -J-XX:+TieredCompilation + -J-XX:TieredStopAtLevel=1 + + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + + + + software.amazon.awscdk + aws-cdk-lib + [2.1.0,3.0.0) + + + software.aws + pdk + (,1.0.0) + + + software.constructs + constructs + [10.0.5,11.0.0) + + + io.github.origin-energy + java-snapshot-testing-junit5 + [4.0.6,5.0.0) + test + + + io.github.origin-energy + java-snapshot-testing-plugin-jackson + [4.0.6,5.0.0) + test + + + org.junit.jupiter + junit-jupiter-api + [5.0.0,6.0.0) + test + + + org.junit.jupiter + junit-jupiter-engine + [5.0.0,6.0.0) + test + + + org.slf4j + slf4j-simple + 2.0.0-alpha0 + test + + + +", + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "implicitDependencies": [ + "Website", + ], + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen build", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen diff", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen post-compile", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen pre-compile", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen test", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/src/main/java/software/aws/infra/Main.java": "package software.aws.infra; + +import software.aws.pdk.cdk_graph.CdkGraph; +import software.aws.pdk.cdk_graph.FilterPreset; +import software.aws.pdk.cdk_graph.Filters; +import software.aws.pdk.cdk_graph.ICdkGraphProps; +import software.aws.pdk.cdk_graph.IFilter; +import software.aws.pdk.cdk_graph.IGraphFilterPlan; +import software.aws.pdk.cdk_graph_plugin_diagram.CdkGraphDiagramPlugin; +import software.aws.pdk.cdk_graph_plugin_diagram.IDiagramConfigBase; +import software.aws.pdk.cdk_graph_plugin_diagram.IPluginConfig; +import software.aws.pdk.pdk_nag.AwsPrototypingChecks; +import software.aws.pdk.pdk_nag.PDKNag; +import software.aws.pdk.pdk_nag.PDKNagAppProps; + +import software.aws.infra.stacks.ApplicationStack; + +import java.util.Arrays; + +import software.amazon.awscdk.App; +import software.amazon.awscdk.Environment; +import software.amazon.awscdk.StackProps; + +public class Main { + public static void main(final String[] args) { + App app = PDKNag.app(PDKNagAppProps.builder() + .nagPacks(Arrays.asList(new AwsPrototypingChecks())) + .build()); + + new ApplicationStack(app, "infra-dev", StackProps.builder() + .env(Environment.builder() + .account(System.getenv("CDK_DEFAULT_ACCOUNT")) + .region(System.getenv("CDK_DEFAULT_REGION")) + .build()) + .build()); + + CdkGraph graph = new CdkGraph(app, ICdkGraphProps.builder() + .plugins(Arrays.asList(new CdkGraphDiagramPlugin(IPluginConfig.builder() + .defaults(IDiagramConfigBase.builder() + .filterPlan(IGraphFilterPlan.builder() + .preset(FilterPreset.COMPACT) + .filters(Arrays.asList(IFilter.builder() + .store(Filters.pruneCustomResources()) + .build())) + .build()) + .build()) + .build()))) + .build()); + + app.synth(); + graph.report(); + } +}", + "infra/src/main/java/software/aws/infra/constructs/WebsiteConstruct.java": "package software.aws.infra.constructs; + +import java.util.Map; +import java.util.TreeMap; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.services.cloudfront.GeoRestriction; +import software.aws.pdk.identity.UserIdentity; +import software.aws.pdk.static_website.DistributionProps; +import software.aws.pdk.static_website.RuntimeOptions; +import software.aws.pdk.static_website.StaticWebsite; +import software.aws.pdk.static_website.StaticWebsiteProps; +import software.constructs.Construct; + +/** + * Construct to deploy a Static Website + */ +public class WebsiteConstruct extends Construct { + + public WebsiteConstruct(Construct scope, String id, UserIdentity userIdentity/* , ApiConstruct apiConstruct */) { + super(scope, id); + + new StaticWebsite(this, id, StaticWebsiteProps.builder() + .websiteContentPath("../website/build") + .runtimeOptions(RuntimeOptions.builder() + .jsonPayload(new TreeMap<>(Map.of( + "region", Stack.of(this).getRegion(), + "identityPoolId", userIdentity.getIdentityPool().getIdentityPoolId(), + "userPoolId", userIdentity.getUserPool().getUserPoolId(), + "userPoolWebClientId", userIdentity.getUserPoolClient().getUserPoolClientId() + // "apiUrl", apiConstruct.api.getApi().urlForPath() + ))) + .build()) + .distributionProps(DistributionProps.builder() + .geoRestriction(GeoRestriction.allowlist( + "AU", + "ID", + "IN", + "JP", + "KR", + "SG", + "US")) + .build()) + .build()); + } +} +", + "infra/src/main/java/software/aws/infra/stacks/ApplicationStack.java": "package software.aws.infra.stacks; + +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.aws.infra.constructs.WebsiteConstruct; +import software.aws.pdk.identity.UserIdentity; +import software.constructs.Construct; + +public class ApplicationStack extends Stack { + public ApplicationStack(Construct scope, String id, StackProps props) { + super(scope, id, props); + + UserIdentity userIdentity = new UserIdentity(this, String.format("%sUserIdentity", id)); + new WebsiteConstruct(this, "Website", userIdentity); + } +} +", + "infra/src/test/java/software/aws/infra/stacks/ApplicationStackTest.java": "package software.aws.infra.stacks; + +import au.com.origin.snapshots.junit5.SnapshotExtension; +import software.amazon.awscdk.App; +import software.amazon.awscdk.assertions.Template; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import au.com.origin.snapshots.Expect; + +// Ensure you extend your test class with the SnapshotExtension +@ExtendWith(SnapshotExtension.class) +public class ApplicationStackTest { + Expect expect; + + @Test + public void myTest() { + App app = new App(); + ApplicationStack stack = new ApplicationStack(app, "test", null); + + Template template = Template.fromStack(stack); + expect.serializer("json").toMatchSnapshot(template.toJSON()); + } +}", + "infra/src/test/resources/snapshot.properties": "serializer=au.com.origin.snapshots.serializers.v1.ToStringSnapshotSerializer +serializer.base64=au.com.origin.snapshots.serializers.v1.Base64SnapshotSerializer +serializer.json=au.com.origin.snapshots.jackson.serializers.v1.JacksonSnapshotSerializer +serializer.orderedJson=au.com.origin.snapshots.jackson.serializers.v1.DeterministicJacksonSnapshotSerializer +comparator=au.com.origin.snapshots.comparators.v1.PlainTextEqualsComparator +reporters=au.com.origin.snapshots.reporters.v1.PlainTextSnapshotReporter +snapshot-dir=__snapshots__ +output-dir=src/test/java +ci-env-var=CI +update-snapshot=none", +} +`; diff --git a/packages/infrastructure/test/projects/java/infrastructure-java-project.test.ts b/packages/infrastructure/test/projects/java/infrastructure-java-project.test.ts new file mode 100644 index 000000000..eeecf08f2 --- /dev/null +++ b/packages/infrastructure/test/projects/java/infrastructure-java-project.test.ts @@ -0,0 +1,58 @@ +/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 */ +import { Language } from "@aws/type-safe-api"; +import { synthSnapshot } from "projen/lib/util/synth"; +import { + InfrastructureJavaProject, + InfrastructureJavaProjectOptions, +} from "../../../src"; +import { + BuildOptionsProps, + snapshotInfrastructureProject, +} from "../utils/snapshot-infra-project"; + +describe("InfrastructureJavaProject", () => { + const snapshot = ( + buildOptions: (props: BuildOptionsProps) => InfrastructureJavaProjectOptions + ) => + snapshotInfrastructureProject( + Language.JAVA, + InfrastructureJavaProject, + buildOptions + ); + + it("Defaults", () => { + const project = new InfrastructureJavaProject({ + name: "Defaults", + }); + expect(synthSnapshot(project)).toMatchSnapshot(); + }); + + it("With Api", () => { + expect( + snapshot(({ typeSafeApi }) => ({ + name: "WithApi", + typeSafeApi, + })) + ).toMatchSnapshot(); + }); + + it("With Website", () => { + expect( + snapshot(({ cloudscapeReactTsWebsite }) => ({ + name: "WithApi", + cloudscapeReactTsWebsite, + })) + ).toMatchSnapshot(); + }); + + it("With Api and Website", () => { + expect( + snapshot(({ cloudscapeReactTsWebsite, typeSafeApi }) => ({ + name: "WithApi", + typeSafeApi, + cloudscapeReactTsWebsite, + })) + ).toMatchSnapshot(); + }); +}); diff --git a/packages/infrastructure/test/projects/python/__snapshots__/infrastructure-py-project.test.ts.snap b/packages/infrastructure/test/projects/python/__snapshots__/infrastructure-py-project.test.ts.snap new file mode 100644 index 000000000..8df0b65fe --- /dev/null +++ b/packages/infrastructure/test/projects/python/__snapshots__/infrastructure-py-project.test.ts.snap @@ -0,0 +1,2293 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`InfrastructurePyProject Defaults 1`] = ` +{ + ".gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen". + +/.gitattributes linguist-generated +/.github/workflows/pull-request-lint.yml linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/pyproject.toml linguist-generated", + ".github/workflows/pull-request-lint.yml": "# ~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen". + +name: pull-request-lint +on: + pull_request_target: + types: + - labeled + - opened + - synchronize + - reopened + - ready_for_review + - edited +jobs: + validate: + name: Validate PR title + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: amannn/action-semantic-pull-request@v5.0.2 + env: + GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }} + with: + types: |- + feat + fix + chore + requireScope: false + githubBaseUrl: \${{ github.api_url }} +", + ".gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/.github/workflows/pull-request-lint.yml +!/pyproject.toml +/poetry.toml +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/cdk.json +/cdk.out/ +.cdk.staging/ +", + ".projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen".", + "dependencies": [ + { + "name": "projen", + "type": "devenv", + "version": "99.99.99", + }, + { + "name": "pytest", + "type": "devenv", + "version": "^7", + }, + { + "name": "syrupy", + "type": "devenv", + "version": "^4", + }, + { + "name": "aws_pdk", + "type": "runtime", + "version": "^0", + }, + { + "name": "aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "constructs", + "type": "runtime", + "version": "^10.0.5", + }, + { + "name": "python", + "type": "runtime", + "version": "^3.9", + }, + ], + }, + ".projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen".", + "files": [ + ".gitattributes", + ".github/workflows/pull-request-lint.yml", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "poetry.toml", + "pyproject.toml", + ], + }, + ".projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen".", + "env": { + "PATH": "$(echo $(poetry env info -p)/bin:$PATH)", + "VIRTUAL_ENV": "$(poetry env info -p)", + }, + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "default", + }, + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "clobber": { + "condition": "git diff --exit-code > /dev/null", + "description": "hard resets to HEAD of origin and cleans the local repo", + "env": { + "BRANCH": "$(git branch --show-current)", + }, + "name": "clobber", + "steps": [ + { + "exec": "git checkout -b scratch", + "name": "save current HEAD in "scratch" branch", + }, + { + "exec": "git checkout $BRANCH", + }, + { + "exec": "git fetch origin", + "name": "fetch latest changes from origin", + }, + { + "exec": "git reset --hard origin/$BRANCH", + "name": "hard reset to origin commit", + }, + { + "exec": "git clean -fdx", + "name": "clean all untracked files", + }, + { + "say": "ready to rock! (unpushed commits are under the "scratch" branch)", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + }, + "default": { + "description": "Synthesize project files", + "name": "default", + "steps": [ + { + "exec": "python .projenrc.py", + }, + ], + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "eject": { + "description": "Remove projen from the project", + "env": { + "PROJEN_EJECTING": "true", + }, + "name": "eject", + "steps": [ + { + "spawn": "default", + }, + ], + }, + "install": { + "description": "Install and upgrade dependencies", + "name": "install", + "steps": [ + { + "exec": "poetry update", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "name": "package", + "steps": [ + { + "exec": "poetry build", + }, + ], + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth:silent", + }, + ], + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "publish": { + "description": "Uploads the package to PyPI.", + "name": "publish", + "steps": [ + { + "exec": "poetry publish", + }, + ], + }, + "publish:test": { + "description": "Uploads the package against a test PyPI endpoint.", + "name": "publish:test", + "steps": [ + { + "exec": "poetry publish -r testpypi", + }, + ], + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "poetry run pytest \${CI:-'--snapshot-update'}", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen".", + "app": "python main.py", + "output": "cdk.out", + "watch": { + "exclude": [ + "README.md", + "cdk*.json", + "requirements*.txt", + "source.bat", + "**/__init__.py", + "python/__pycache__", + "tests", + ], + "include": [ + "**", + ], + }, + }, + "infra/stacks/application_stack.py": "from aws_cdk import Stack +from aws_pdk.identity import UserIdentity +from constructs import Construct + +class ApplicationStack(Stack): + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + user_identity = UserIdentity(self, '{}UserIdentity'.format(id)) + +", + "main.py": "import os +from aws_cdk import Environment +from aws_pdk.cdk_graph import CdkGraph, FilterPreset, Filters, IFilter, IGraphFilterPlan +from aws_pdk.cdk_graph_plugin_diagram import CdkGraphDiagramPlugin, IDiagramConfigBase +from aws_pdk.pdk_nag import PDKNag, AwsPrototypingChecks +from infra.stacks.application_stack import ApplicationStack + +# for development, use account/region from cdk cli +dev_env = Environment( + account=os.getenv('CDK_DEFAULT_ACCOUNT'), + region=os.getenv('CDK_DEFAULT_REGION') +) + +app = PDKNag.app(nag_packs=[AwsPrototypingChecks()]) +ApplicationStack(app, "infra-dev", env=dev_env) + +graph = CdkGraph(app, plugins=[CdkGraphDiagramPlugin( + defaults=IDiagramConfigBase( + filter_plan=IGraphFilterPlan( + preset=FilterPreset.COMPACT, + filters=[IFilter(store=Filters.prune_custom_resources())] + ) + ) +)]) +app.synth() +graph.report()", + "poetry.toml": "# ~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen". + +[repositories.testpypi] +url = "https://test.pypi.org/legacy/" +", + "pyproject.toml": "# ~~ Generated by projen. To modify, edit .projenrc.py and run "npx projen". + +[build-system] +requires = [ "poetry_core>=1.0.0" ] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "Defaults" +version = "0.0.0" +description = "" +authors = [ "pdkuser " ] +readme = "README.md" + + [tool.poetry.dependencies] + aws_pdk = "^0" + aws-cdk-lib = "^2.1.0" + constructs = "^10.0.5" + python = "^3.9" + + [tool.poetry.dev-dependencies] + projen = "99.99.99" + pytest = "^7" + syrupy = "^4" +", + "tests/__init__.py": "", + "tests/test_application_stack.py": "import pytest +from aws_cdk import App +from aws_cdk.assertions import Template +from infra.stacks.application_stack import ApplicationStack + +def test_template_with_snapshot(snapshot): + app = App() + stack = ApplicationStack(app, "my-stack-test") + template = Template.from_stack(stack) + assert template.to_json() == snapshot +", +} +`; + +exports[`InfrastructurePyProject With Api 1`] = ` +{ + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/project.json linguist-generated +/pyproject.toml linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/pyproject.toml +/poetry.toml +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/cdk.json +/cdk.out/ +.cdk.staging/ +!/project.json +", + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "name": "pytest", + "type": "devenv", + "version": "^7", + }, + { + "name": "syrupy", + "type": "devenv", + "version": "^4", + }, + { + "name": "Api-python-infra", + "type": "runtime", + "version": "{path="../api/generated/infrastructure/python", develop=true}", + }, + { + "name": "aws_pdk", + "type": "runtime", + "version": "^0", + }, + { + "name": "aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "constructs", + "type": "runtime", + "version": "^10.0.5", + }, + { + "name": "python", + "type": "runtime", + "version": "^3.9", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "poetry.toml", + "project.json", + "pyproject.toml", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "env": { + "PATH": "$(echo $(env -u VIRTUAL_ENV poetry env info -p || echo '')/bin:$PATH)", + "VIRTUAL_ENV": "$(env -u VIRTUAL_ENV poetry env info -p || echo '')", + }, + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "install": { + "description": "Install and upgrade dependencies", + "name": "install", + "steps": [ + { + "exec": "poetry update", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "name": "package", + "steps": [ + { + "exec": "poetry build", + }, + ], + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth:silent", + }, + ], + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "publish": { + "description": "Uploads the package to PyPI.", + "name": "publish", + "steps": [ + { + "exec": "poetry publish", + }, + ], + }, + "publish:test": { + "description": "Uploads the package against a test PyPI endpoint.", + "name": "publish:test", + "steps": [ + { + "exec": "poetry publish -r testpypi", + }, + ], + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "poetry run pytest \${CI:-'--snapshot-update'}", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "python main.py", + "output": "cdk.out", + "watch": { + "exclude": [ + "README.md", + "cdk*.json", + "requirements*.txt", + "source.bat", + "**/__init__.py", + "python/__pycache__", + "tests", + ], + "include": [ + "**", + ], + }, + }, + "infra/infra/constructs/api.py": "from constructs import Construct +from Api_python_infra.api import Api +from Api_python_infra.mock_integrations import MockIntegrations +from aws_cdk import Stack +from aws_pdk.identity import UserIdentity +from aws_pdk.type_safe_api import Authorizers +from aws_cdk.aws_apigateway import CorsOptions, Cors +from aws_cdk.aws_iam import AccountPrincipal, AnyPrincipal, Effect, PolicyDocument, PolicyStatement + +# Infrastructure construct to deploy a Type Safe API. +class ApiConstruct(Construct): + def __init__(self, scope: Construct, id: str, user_identity: UserIdentity, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + self.api = Api(self, id, + default_authorizer=Authorizers.iam(), + cors_options=CorsOptions( + allow_origins=Cors.ALL_ORIGINS, + allow_methods=Cors.ALL_METHODS + ), + integrations=MockIntegrations.mock_all(), + policy=PolicyDocument( + statements=[ + # Here we grant any AWS credentials from the account that the prototype is deployed in to call the api. + # Machine to machine fine-grained access can be defined here using more specific principals (eg roles or + # users) and resources (ie which api paths may be invoked by which principal) if required. + # If doing so, the cognito identity pool authenticated role must still be granted access for cognito users to + # still be granted access to the API. + PolicyStatement( + effect=Effect.ALLOW, + principals=[AccountPrincipal(Stack.of(self).account)], + actions=['execute-api:Invoke'], + resources=['execute-api:/*'] + ), + # Open up OPTIONS to allow browsers to make unauthenticated preflight requests + PolicyStatement( + effect=Effect.ALLOW, + principals=[AnyPrincipal()], + actions=['execute-api:Invoke'], + resources=['execute-api:/*/OPTIONS/*'] + ) + ] + )) + + user_identity.identity_pool.authenticated_role.add_to_principal_policy( + PolicyStatement( + effect=Effect.ALLOW, + actions=['execute-api:Invoke'], + resources=[self.api.api.arn_for_execute_api('*', '/*', '*')] + ) + ) +", + "infra/infra/stacks/application_stack.py": "from aws_cdk import Stack +from aws_pdk.identity import UserIdentity +from constructs import Construct +from infra.constructs.api import ApiConstruct + +class ApplicationStack(Stack): + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + user_identity = UserIdentity(self, '{}UserIdentity'.format(id)) + ApiConstruct(self, 'Api', user_identity) + +", + "infra/main.py": "import os +from aws_cdk import Environment +from aws_pdk.cdk_graph import CdkGraph, FilterPreset, Filters, IFilter, IGraphFilterPlan +from aws_pdk.cdk_graph_plugin_diagram import CdkGraphDiagramPlugin, IDiagramConfigBase +from aws_pdk.pdk_nag import PDKNag, AwsPrototypingChecks +from infra.stacks.application_stack import ApplicationStack + +# for development, use account/region from cdk cli +dev_env = Environment( + account=os.getenv('CDK_DEFAULT_ACCOUNT'), + region=os.getenv('CDK_DEFAULT_REGION') +) + +app = PDKNag.app(nag_packs=[AwsPrototypingChecks()]) +ApplicationStack(app, "infra-dev", env=dev_env) + +graph = CdkGraph(app, plugins=[CdkGraphDiagramPlugin( + defaults=IDiagramConfigBase( + filter_plan=IGraphFilterPlan( + preset=FilterPreset.COMPACT, + filters=[IFilter(store=Filters.prune_custom_resources())] + ) + ) +)]) +app.synth() +graph.report()", + "infra/poetry.toml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +[repositories.testpypi] +url = "https://test.pypi.org/legacy/" +", + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "implicitDependencies": [ + "Api-python-infra", + ], + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen build", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen diff", + "cwd": "infra", + }, + }, + "install": { + "dependsOn": [ + "^install", + ], + "executor": "nx:run-commands", + "options": { + "command": "npx projen install", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen post-compile", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen pre-compile", + "cwd": "infra", + }, + }, + "publish": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen publish", + "cwd": "infra", + }, + }, + "publish:test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen publish:test", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen test", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/pyproject.toml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +[build-system] +requires = [ "poetry_core>=1.0.0" ] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "WithApi" +version = "0.0.0" +description = "" +authors = [ "pdkuser " ] +readme = "README.md" + + [tool.poetry.dependencies] + aws_pdk = "^0" + aws-cdk-lib = "^2.1.0" + constructs = "^10.0.5" + python = "^3.9" + + [tool.poetry.dependencies.Api-python-infra] + path = "../api/generated/infrastructure/python" + develop = true + + [tool.poetry.dev-dependencies] + pytest = "^7" + syrupy = "^4" +", + "infra/tests/__init__.py": "", + "infra/tests/test_application_stack.py": "import pytest +from aws_cdk import App +from aws_cdk.assertions import Template +from infra.stacks.application_stack import ApplicationStack + +def test_template_with_snapshot(snapshot): + app = App() + stack = ApplicationStack(app, "my-stack-test") + template = Template.from_stack(stack) + assert template.to_json() == snapshot +", +} +`; + +exports[`InfrastructurePyProject With Api and Website 1`] = ` +{ + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/project.json linguist-generated +/pyproject.toml linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/pyproject.toml +/poetry.toml +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/cdk.json +/cdk.out/ +.cdk.staging/ +!/project.json +", + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "name": "pytest", + "type": "devenv", + "version": "^7", + }, + { + "name": "syrupy", + "type": "devenv", + "version": "^4", + }, + { + "name": "Api-python-infra", + "type": "runtime", + "version": "{path="../api/generated/infrastructure/python", develop=true}", + }, + { + "name": "aws_pdk", + "type": "runtime", + "version": "^0", + }, + { + "name": "aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "constructs", + "type": "runtime", + "version": "^10.0.5", + }, + { + "name": "python", + "type": "runtime", + "version": "^3.9", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "poetry.toml", + "project.json", + "pyproject.toml", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "env": { + "PATH": "$(echo $(env -u VIRTUAL_ENV poetry env info -p || echo '')/bin:$PATH)", + "VIRTUAL_ENV": "$(env -u VIRTUAL_ENV poetry env info -p || echo '')", + }, + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "install": { + "description": "Install and upgrade dependencies", + "name": "install", + "steps": [ + { + "exec": "poetry update", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "name": "package", + "steps": [ + { + "exec": "poetry build", + }, + ], + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth:silent", + }, + ], + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "publish": { + "description": "Uploads the package to PyPI.", + "name": "publish", + "steps": [ + { + "exec": "poetry publish", + }, + ], + }, + "publish:test": { + "description": "Uploads the package against a test PyPI endpoint.", + "name": "publish:test", + "steps": [ + { + "exec": "poetry publish -r testpypi", + }, + ], + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "poetry run pytest \${CI:-'--snapshot-update'}", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "python main.py", + "output": "cdk.out", + "watch": { + "exclude": [ + "README.md", + "cdk*.json", + "requirements*.txt", + "source.bat", + "**/__init__.py", + "python/__pycache__", + "tests", + ], + "include": [ + "**", + ], + }, + }, + "infra/infra/constructs/api.py": "from constructs import Construct +from Api_python_infra.api import Api +from Api_python_infra.mock_integrations import MockIntegrations +from aws_cdk import Stack +from aws_pdk.identity import UserIdentity +from aws_pdk.type_safe_api import Authorizers +from aws_cdk.aws_apigateway import CorsOptions, Cors +from aws_cdk.aws_iam import AccountPrincipal, AnyPrincipal, Effect, PolicyDocument, PolicyStatement + +# Infrastructure construct to deploy a Type Safe API. +class ApiConstruct(Construct): + def __init__(self, scope: Construct, id: str, user_identity: UserIdentity, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + self.api = Api(self, id, + default_authorizer=Authorizers.iam(), + cors_options=CorsOptions( + allow_origins=Cors.ALL_ORIGINS, + allow_methods=Cors.ALL_METHODS + ), + integrations=MockIntegrations.mock_all(), + policy=PolicyDocument( + statements=[ + # Here we grant any AWS credentials from the account that the prototype is deployed in to call the api. + # Machine to machine fine-grained access can be defined here using more specific principals (eg roles or + # users) and resources (ie which api paths may be invoked by which principal) if required. + # If doing so, the cognito identity pool authenticated role must still be granted access for cognito users to + # still be granted access to the API. + PolicyStatement( + effect=Effect.ALLOW, + principals=[AccountPrincipal(Stack.of(self).account)], + actions=['execute-api:Invoke'], + resources=['execute-api:/*'] + ), + # Open up OPTIONS to allow browsers to make unauthenticated preflight requests + PolicyStatement( + effect=Effect.ALLOW, + principals=[AnyPrincipal()], + actions=['execute-api:Invoke'], + resources=['execute-api:/*/OPTIONS/*'] + ) + ] + )) + + user_identity.identity_pool.authenticated_role.add_to_principal_policy( + PolicyStatement( + effect=Effect.ALLOW, + actions=['execute-api:Invoke'], + resources=[self.api.api.arn_for_execute_api('*', '/*', '*')] + ) + ) +", + "infra/infra/constructs/website.py": "from aws_cdk import Stack +from constructs import Construct +from aws_cdk.aws_cloudfront import GeoRestriction +from infra.constructs.api import ApiConstruct +from aws_pdk.identity import UserIdentity +from aws_pdk.static_website import StaticWebsite, RuntimeOptions, DistributionProps + +# Construct to deploy a Static Website +class WebsiteConstruct(Construct): + def __init__(self, scope: Construct, id: str, user_identity: UserIdentity, api_construct: ApiConstruct, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + StaticWebsite(self, id, + website_content_path='../website/build', + runtime_options=RuntimeOptions( + json_payload={ + 'region': Stack.of(self).region, + 'identityPoolId': user_identity.identity_pool.identity_pool_id, + 'userPoolId': user_identity.user_pool.user_pool_id, + 'userPoolWebClientId': user_identity.user_pool_client.user_pool_client_id, + 'apiUrl': api_construct.api.api.url_for_path(), + } + ), + distribution_props=DistributionProps( + geo_restriction=GeoRestriction.allowlist( + "AU", + "ID", + "IN", + "JP", + "KR", + "SG", + "US" + ) + )) +", + "infra/infra/stacks/application_stack.py": "from aws_cdk import Stack +from aws_pdk.identity import UserIdentity +from constructs import Construct +from infra.constructs.api import ApiConstruct +from infra.constructs.website import WebsiteConstruct + +class ApplicationStack(Stack): + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + user_identity = UserIdentity(self, '{}UserIdentity'.format(id)) + api = ApiConstruct(self, 'Api', user_identity) + WebsiteConstruct(self, 'Website', user_identity, api) + +", + "infra/main.py": "import os +from aws_cdk import Environment +from aws_pdk.cdk_graph import CdkGraph, FilterPreset, Filters, IFilter, IGraphFilterPlan +from aws_pdk.cdk_graph_plugin_diagram import CdkGraphDiagramPlugin, IDiagramConfigBase +from aws_pdk.pdk_nag import PDKNag, AwsPrototypingChecks +from infra.stacks.application_stack import ApplicationStack + +# for development, use account/region from cdk cli +dev_env = Environment( + account=os.getenv('CDK_DEFAULT_ACCOUNT'), + region=os.getenv('CDK_DEFAULT_REGION') +) + +app = PDKNag.app(nag_packs=[AwsPrototypingChecks()]) +ApplicationStack(app, "infra-dev", env=dev_env) + +graph = CdkGraph(app, plugins=[CdkGraphDiagramPlugin( + defaults=IDiagramConfigBase( + filter_plan=IGraphFilterPlan( + preset=FilterPreset.COMPACT, + filters=[IFilter(store=Filters.prune_custom_resources())] + ) + ) +)]) +app.synth() +graph.report()", + "infra/poetry.toml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +[repositories.testpypi] +url = "https://test.pypi.org/legacy/" +", + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "implicitDependencies": [ + "Api-python-infra", + "Website", + ], + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen build", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen diff", + "cwd": "infra", + }, + }, + "install": { + "dependsOn": [ + "^install", + ], + "executor": "nx:run-commands", + "options": { + "command": "npx projen install", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen post-compile", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen pre-compile", + "cwd": "infra", + }, + }, + "publish": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen publish", + "cwd": "infra", + }, + }, + "publish:test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen publish:test", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen test", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/pyproject.toml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +[build-system] +requires = [ "poetry_core>=1.0.0" ] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "WithApi" +version = "0.0.0" +description = "" +authors = [ "pdkuser " ] +readme = "README.md" + + [tool.poetry.dependencies] + aws_pdk = "^0" + aws-cdk-lib = "^2.1.0" + constructs = "^10.0.5" + python = "^3.9" + + [tool.poetry.dependencies.Api-python-infra] + path = "../api/generated/infrastructure/python" + develop = true + + [tool.poetry.dev-dependencies] + pytest = "^7" + syrupy = "^4" +", + "infra/tests/__init__.py": "", + "infra/tests/test_application_stack.py": "import pytest +from aws_cdk import App +from aws_cdk.assertions import Template +from infra.stacks.application_stack import ApplicationStack + +def test_template_with_snapshot(snapshot): + app = App() + stack = ApplicationStack(app, "my-stack-test") + template = Template.from_stack(stack) + assert template.to_json() == snapshot +", +} +`; + +exports[`InfrastructurePyProject With Website 1`] = ` +{ + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/project.json linguist-generated +/pyproject.toml linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +node_modules/ +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/pyproject.toml +/poetry.toml +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +*.manifest +*.spec +pip-log.txt +pip-delete-this-directory.txt +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ +*.mo +*.pot +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal +instance/ +.webassets-cache +.scrapy +docs/_build/ +.pybuilder/ +target/ +.ipynb_checkpoints +profile_default/ +ipython_config.py +__pypackages__/ +celerybeat-schedule +celerybeat.pid +*.sage.py +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.spyderproject +.spyproject +.ropeproject +/site +.mypy_cache/ +.dmypy.json +dmypy.json +.pyre/ +.pytype/ +cython_debug/ +!/cdk.json +/cdk.out/ +.cdk.staging/ +!/project.json +", + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "name": "pytest", + "type": "devenv", + "version": "^7", + }, + { + "name": "syrupy", + "type": "devenv", + "version": "^4", + }, + { + "name": "aws_pdk", + "type": "runtime", + "version": "^0", + }, + { + "name": "aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "constructs", + "type": "runtime", + "version": "^10.0.5", + }, + { + "name": "python", + "type": "runtime", + "version": "^3.9", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".gitattributes", + ".gitignore", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "poetry.toml", + "project.json", + "pyproject.toml", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "env": { + "PATH": "$(echo $(env -u VIRTUAL_ENV poetry env info -p || echo '')/bin:$PATH)", + "VIRTUAL_ENV": "$(env -u VIRTUAL_ENV poetry env info -p || echo '')", + }, + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "install": { + "description": "Install and upgrade dependencies", + "name": "install", + "steps": [ + { + "exec": "poetry update", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "name": "package", + "steps": [ + { + "exec": "poetry build", + }, + ], + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth:silent", + }, + ], + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "publish": { + "description": "Uploads the package to PyPI.", + "name": "publish", + "steps": [ + { + "exec": "poetry publish", + }, + ], + }, + "publish:test": { + "description": "Uploads the package against a test PyPI endpoint.", + "name": "publish:test", + "steps": [ + { + "exec": "poetry publish -r testpypi", + }, + ], + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "poetry run pytest \${CI:-'--snapshot-update'}", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "python main.py", + "output": "cdk.out", + "watch": { + "exclude": [ + "README.md", + "cdk*.json", + "requirements*.txt", + "source.bat", + "**/__init__.py", + "python/__pycache__", + "tests", + ], + "include": [ + "**", + ], + }, + }, + "infra/infra/constructs/website.py": "from aws_cdk import Stack +from constructs import Construct +from aws_cdk.aws_cloudfront import GeoRestriction +# from infra.constructs.api import ApiConstruct +from aws_pdk.identity import UserIdentity +from aws_pdk.static_website import StaticWebsite, RuntimeOptions, DistributionProps + +# Construct to deploy a Static Website +class WebsiteConstruct(Construct): + def __init__(self, scope: Construct, id: str, user_identity: UserIdentity''', api_construct: ApiConstruct''', **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + StaticWebsite(self, id, + website_content_path='../website/build', + runtime_options=RuntimeOptions( + json_payload={ + 'region': Stack.of(self).region, + 'identityPoolId': user_identity.identity_pool.identity_pool_id, + 'userPoolId': user_identity.user_pool.user_pool_id, + 'userPoolWebClientId': user_identity.user_pool_client.user_pool_client_id, + ''''apiUrl': api_construct.api.api.url_for_path(),''' + } + ), + distribution_props=DistributionProps( + geo_restriction=GeoRestriction.allowlist( + "AU", + "ID", + "IN", + "JP", + "KR", + "SG", + "US" + ) + )) +", + "infra/infra/stacks/application_stack.py": "from aws_cdk import Stack +from aws_pdk.identity import UserIdentity +from constructs import Construct +from infra.constructs.website import WebsiteConstruct + +class ApplicationStack(Stack): + def __init__(self, scope: Construct, id: str, **kwargs) -> None: + super().__init__(scope, id, **kwargs) + + user_identity = UserIdentity(self, '{}UserIdentity'.format(id)) + WebsiteConstruct(self, 'Website', user_identity) + +", + "infra/main.py": "import os +from aws_cdk import Environment +from aws_pdk.cdk_graph import CdkGraph, FilterPreset, Filters, IFilter, IGraphFilterPlan +from aws_pdk.cdk_graph_plugin_diagram import CdkGraphDiagramPlugin, IDiagramConfigBase +from aws_pdk.pdk_nag import PDKNag, AwsPrototypingChecks +from infra.stacks.application_stack import ApplicationStack + +# for development, use account/region from cdk cli +dev_env = Environment( + account=os.getenv('CDK_DEFAULT_ACCOUNT'), + region=os.getenv('CDK_DEFAULT_REGION') +) + +app = PDKNag.app(nag_packs=[AwsPrototypingChecks()]) +ApplicationStack(app, "infra-dev", env=dev_env) + +graph = CdkGraph(app, plugins=[CdkGraphDiagramPlugin( + defaults=IDiagramConfigBase( + filter_plan=IGraphFilterPlan( + preset=FilterPreset.COMPACT, + filters=[IFilter(store=Filters.prune_custom_resources())] + ) + ) +)]) +app.synth() +graph.report()", + "infra/poetry.toml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +[repositories.testpypi] +url = "https://test.pypi.org/legacy/" +", + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "implicitDependencies": [ + "Website", + ], + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen build", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen diff", + "cwd": "infra", + }, + }, + "install": { + "dependsOn": [ + "^install", + ], + "executor": "nx:run-commands", + "options": { + "command": "npx projen install", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen post-compile", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen pre-compile", + "cwd": "infra", + }, + }, + "publish": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen publish", + "cwd": "infra", + }, + }, + "publish:test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen publish:test", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen test", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "npx projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/pyproject.toml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +[build-system] +requires = [ "poetry_core>=1.0.0" ] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "WithApi" +version = "0.0.0" +description = "" +authors = [ "pdkuser " ] +readme = "README.md" + + [tool.poetry.dependencies] + aws_pdk = "^0" + aws-cdk-lib = "^2.1.0" + constructs = "^10.0.5" + python = "^3.9" + + [tool.poetry.dev-dependencies] + pytest = "^7" + syrupy = "^4" +", + "infra/tests/__init__.py": "", + "infra/tests/test_application_stack.py": "import pytest +from aws_cdk import App +from aws_cdk.assertions import Template +from infra.stacks.application_stack import ApplicationStack + +def test_template_with_snapshot(snapshot): + app = App() + stack = ApplicationStack(app, "my-stack-test") + template = Template.from_stack(stack) + assert template.to_json() == snapshot +", +} +`; diff --git a/packages/infrastructure/test/projects/python/infrastructure-py-project.test.ts b/packages/infrastructure/test/projects/python/infrastructure-py-project.test.ts new file mode 100644 index 000000000..3757597c8 --- /dev/null +++ b/packages/infrastructure/test/projects/python/infrastructure-py-project.test.ts @@ -0,0 +1,58 @@ +/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 */ +import { Language } from "@aws/type-safe-api"; +import { synthSnapshot } from "projen/lib/util/synth"; +import { + InfrastructurePyProject, + InfrastructurePyProjectOptions, +} from "../../../src"; +import { + BuildOptionsProps, + snapshotInfrastructureProject, +} from "../utils/snapshot-infra-project"; + +describe("InfrastructurePyProject", () => { + const snapshot = ( + buildOptions: (props: BuildOptionsProps) => InfrastructurePyProjectOptions + ) => + snapshotInfrastructureProject( + Language.PYTHON, + InfrastructurePyProject, + buildOptions + ); + + it("Defaults", () => { + const project = new InfrastructurePyProject({ + name: "Defaults", + }); + expect(synthSnapshot(project)).toMatchSnapshot(); + }); + + it("With Api", () => { + expect( + snapshot(({ typeSafeApi }) => ({ + name: "WithApi", + typeSafeApi, + })) + ).toMatchSnapshot(); + }); + + it("With Website", () => { + expect( + snapshot(({ cloudscapeReactTsWebsite }) => ({ + name: "WithApi", + cloudscapeReactTsWebsite, + })) + ).toMatchSnapshot(); + }); + + it("With Api and Website", () => { + expect( + snapshot(({ cloudscapeReactTsWebsite, typeSafeApi }) => ({ + name: "WithApi", + typeSafeApi, + cloudscapeReactTsWebsite, + })) + ).toMatchSnapshot(); + }); +}); diff --git a/packages/infrastructure/test/projects/typescript/__snapshots__/infrastructure-ts-project.test.ts.snap b/packages/infrastructure/test/projects/typescript/__snapshots__/infrastructure-ts-project.test.ts.snap new file mode 100644 index 000000000..ae54c5ea7 --- /dev/null +++ b/packages/infrastructure/test/projects/typescript/__snapshots__/infrastructure-ts-project.test.ts.snap @@ -0,0 +1,5015 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`InfrastructureTsProject Defaults 1`] = ` +{ + ".eslintrc.json": { + "env": { + "jest": true, + "node": true, + }, + "extends": [ + "plugin:import/typescript", + "prettier", + "plugin:prettier/recommended", + ], + "ignorePatterns": [ + "*.js", + "*.d.ts", + "node_modules/", + "*.generated.ts", + "coverage", + "!.projenrc.js", + ], + "overrides": [ + { + "files": [ + ".projenrc.js", + ], + "rules": { + "@typescript-eslint/no-require-imports": "off", + "import/no-extraneous-dependencies": "off", + }, + }, + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2018, + "project": "./tsconfig.dev.json", + "sourceType": "module", + }, + "plugins": [ + "@typescript-eslint", + "import", + "prettier", + ], + "root": true, + "rules": { + "@typescript-eslint/member-ordering": [ + "error", + { + "default": [ + "public-static-field", + "public-static-method", + "protected-static-field", + "protected-static-method", + "private-static-field", + "private-static-method", + "field", + "constructor", + "method", + ], + }, + ], + "@typescript-eslint/no-floating-promises": [ + "error", + ], + "@typescript-eslint/no-require-imports": [ + "error", + ], + "@typescript-eslint/no-shadow": [ + "error", + ], + "@typescript-eslint/return-await": [ + "error", + ], + "dot-notation": [ + "error", + ], + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": [ + "**/test/**", + "**/build-tools/**", + ], + "optionalDependencies": false, + "peerDependencies": true, + }, + ], + "import/no-unresolved": [ + "error", + ], + "import/order": [ + "warn", + { + "alphabetize": { + "caseInsensitive": true, + "order": "asc", + }, + "groups": [ + "builtin", + "external", + ], + }, + ], + "key-spacing": [ + "error", + ], + "no-bitwise": [ + "error", + ], + "no-duplicate-imports": [ + "error", + ], + "no-multiple-empty-lines": [ + "error", + ], + "no-return-await": [ + "off", + ], + "no-shadow": [ + "off", + ], + "no-trailing-spaces": [ + "error", + ], + "prettier/prettier": [ + "error", + ], + }, + "settings": { + "import/parsers": { + "@typescript-eslint/parser": [ + ".ts", + ".tsx", + ], + }, + "import/resolver": { + "node": {}, + "typescript": { + "alwaysTryTypes": true, + "project": "./tsconfig.dev.json", + }, + }, + }, + }, + ".gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +*.snap linguist-generated +/.eslintrc.json linguist-generated +/.gitattributes linguist-generated +/.github/pull_request_template.md linguist-generated +/.github/workflows/build.yml linguist-generated +/.github/workflows/pull-request-lint.yml linguist-generated +/.github/workflows/upgrade.yml linguist-generated +/.gitignore linguist-generated +/.mergify.yml linguist-generated +/.npmignore linguist-generated +/.prettierignore linguist-generated +/.prettierrc.json linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/LICENSE linguist-generated +/package.json linguist-generated +/tsconfig.dev.json linguist-generated +/tsconfig.json linguist-generated +/yarn.lock linguist-generated", + ".github/pull_request_template.md": "Fixes #", + ".github/workflows/build.yml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +name: build +on: + pull_request: {} + workflow_dispatch: {} +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + outputs: + self_mutation_happened: \${{ steps.self_mutation.outputs.self_mutation_happened }} + env: + CI: "true" + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + ref: \${{ github.event.pull_request.head.ref }} + repository: \${{ github.event.pull_request.head.repo.full_name }} + - name: Install dependencies + run: yarn install --check-files + - name: build + run: npx projen build + - name: Find mutations + id: self_mutation + run: |- + git add . + git diff --staged --patch --exit-code > .repo.patch || echo "self_mutation_happened=true" >> $GITHUB_OUTPUT + - name: Upload patch + if: steps.self_mutation.outputs.self_mutation_happened + uses: actions/upload-artifact@v3 + with: + name: .repo.patch + path: .repo.patch + - name: Fail build on mutation + if: steps.self_mutation.outputs.self_mutation_happened + run: |- + echo "::error::Files were changed during build (see build log). If this was triggered from a fork, you will need to update your branch." + cat .repo.patch + exit 1 + self-mutation: + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + if: always() && needs.build.outputs.self_mutation_happened && !(github.event.pull_request.head.repo.full_name != github.repository) + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + token: \${{ secrets.PROJEN_GITHUB_TOKEN }} + ref: \${{ github.event.pull_request.head.ref }} + repository: \${{ github.event.pull_request.head.repo.full_name }} + - name: Download patch + uses: actions/download-artifact@v3 + with: + name: .repo.patch + path: \${{ runner.temp }} + - name: Apply patch + run: '[ -s \${{ runner.temp }}/.repo.patch ] && git apply \${{ runner.temp }}/.repo.patch || echo "Empty patch. Skipping."' + - name: Set git identity + run: |- + git config user.name "github-actions" + git config user.email "github-actions@github.com" + - name: Push changes + env: + PULL_REQUEST_REF: \${{ github.event.pull_request.head.ref }} + run: |- + git add . + git commit -s -m "chore: self mutation" + git push origin HEAD:$PULL_REQUEST_REF +", + ".github/workflows/pull-request-lint.yml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +name: pull-request-lint +on: + pull_request_target: + types: + - labeled + - opened + - synchronize + - reopened + - ready_for_review + - edited +jobs: + validate: + name: Validate PR title + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: amannn/action-semantic-pull-request@v5.0.2 + env: + GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }} + with: + types: |- + feat + fix + chore + requireScope: false + githubBaseUrl: \${{ github.api_url }} +", + ".github/workflows/upgrade.yml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +name: upgrade +on: + workflow_dispatch: {} + schedule: + - cron: 0 0 * * * +jobs: + upgrade: + name: Upgrade + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + patch_created: \${{ steps.create_patch.outputs.patch_created }} + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install dependencies + run: yarn install --check-files --frozen-lockfile + - name: Upgrade dependencies + run: npx projen upgrade + - name: Find mutations + id: create_patch + run: |- + git add . + git diff --staged --patch --exit-code > .repo.patch || echo "patch_created=true" >> $GITHUB_OUTPUT + - name: Upload patch + if: steps.create_patch.outputs.patch_created + uses: actions/upload-artifact@v3 + with: + name: .repo.patch + path: .repo.patch + pr: + name: Create Pull Request + needs: upgrade + runs-on: ubuntu-latest + permissions: + contents: read + if: \${{ needs.upgrade.outputs.patch_created }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: {} + - name: Download patch + uses: actions/download-artifact@v3 + with: + name: .repo.patch + path: \${{ runner.temp }} + - name: Apply patch + run: '[ -s \${{ runner.temp }}/.repo.patch ] && git apply \${{ runner.temp }}/.repo.patch || echo "Empty patch. Skipping."' + - name: Set git identity + run: |- + git config user.name "github-actions" + git config user.email "github-actions@github.com" + - name: Create Pull Request + id: create-pr + uses: peter-evans/create-pull-request@v4 + with: + token: \${{ secrets.PROJEN_GITHUB_TOKEN }} + commit-message: |- + chore(deps): upgrade dependencies + + Upgrades project dependencies. See details in [workflow run]. + + [Workflow Run]: \${{ github.server_url }}/\${{ github.repository }}/actions/runs/\${{ github.run_id }} + + ------ + + *Automatically created by projen via the "upgrade" workflow* + branch: github-actions/upgrade + title: "chore(deps): upgrade dependencies" + body: |- + Upgrades project dependencies. See details in [workflow run]. + + [Workflow Run]: \${{ github.server_url }}/\${{ github.repository }}/actions/runs/\${{ github.run_id }} + + ------ + + *Automatically created by projen via the "upgrade" workflow* + author: github-actions + committer: github-actions + signoff: true +", + ".gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/.github/workflows/pull-request-lint.yml +!/package.json +!/LICENSE +!/.npmignore +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json +pids +*.pid +*.seed +*.pid.lock +lib-cov +coverage +*.lcov +.nyc_output +build/Release +node_modules/ +jspm_packages/ +*.tsbuildinfo +.eslintcache +*.tgz +.yarn-integrity +.cache +!/.projenrc.js +/test-reports/ +junit.xml +/coverage/ +!/.github/workflows/build.yml +!/.mergify.yml +!/.github/workflows/upgrade.yml +!/.github/pull_request_template.md +!/.prettierignore +!/.prettierrc.json +!/test/ +!/tsconfig.json +!/tsconfig.dev.json +!/src/ +/lib +/dist/ +!/.eslintrc.json +/assets/ +!/cdk.json +/cdk.out/ +.cdk.staging/ +.parcel-cache/ +", + ".mergify.yml": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +queue_rules: + - name: default + update_method: merge + conditions: + - "#approved-reviews-by>=1" + - -label~=(do-not-merge) + - status-success=build +pull_request_rules: + - name: Automatic merge on approval and successful build + actions: + delete_head_branch: {} + queue: + method: squash + name: default + commit_message_template: |- + {{ title }} (#{{ number }}) + + {{ body }} + conditions: + - "#approved-reviews-by>=1" + - -label~=(do-not-merge) + - status-success=build +", + ".npmignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +/.projen/ +/test-reports/ +junit.xml +/coverage/ +permissions-backup.acl +/.mergify.yml +/test/ +/tsconfig.dev.json +/src/ +!/lib/ +!/lib/**/*.js +!/lib/**/*.d.ts +dist +/tsconfig.json +/.github/ +/.vscode/ +/.idea/ +/.projenrc.js +tsconfig.tsbuildinfo +/.eslintrc.json +!/assets/ +cdk.out/ +.cdk.staging/ +", + ".prettierignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +", + ".prettierrc.json": { + "overrides": [], + }, + ".projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "name": "@types/jest", + "type": "build", + }, + { + "name": "@types/node", + "type": "build", + "version": "^16", + }, + { + "name": "@typescript-eslint/eslint-plugin", + "type": "build", + "version": "^6", + }, + { + "name": "@typescript-eslint/parser", + "type": "build", + "version": "^6", + }, + { + "name": "aws-cdk", + "type": "build", + "version": "^2.1.0", + }, + { + "name": "esbuild", + "type": "build", + }, + { + "name": "eslint-config-prettier", + "type": "build", + }, + { + "name": "eslint-import-resolver-node", + "type": "build", + }, + { + "name": "eslint-import-resolver-typescript", + "type": "build", + }, + { + "name": "eslint-plugin-import", + "type": "build", + }, + { + "name": "eslint-plugin-prettier", + "type": "build", + }, + { + "name": "eslint", + "type": "build", + "version": "^8", + }, + { + "name": "jest", + "type": "build", + }, + { + "name": "jest-junit", + "type": "build", + "version": "^15", + }, + { + "name": "npm-check-updates", + "type": "build", + "version": "^16", + }, + { + "name": "prettier", + "type": "build", + }, + { + "name": "projen", + "type": "build", + }, + { + "name": "ts-jest", + "type": "build", + }, + { + "name": "ts-node", + "type": "build", + }, + { + "name": "typescript", + "type": "build", + }, + { + "name": "@aws/pdk", + "type": "runtime", + }, + { + "name": "aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "constructs", + "type": "runtime", + "version": "^10.0.5", + }, + ], + }, + ".projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".eslintrc.json", + ".gitattributes", + ".github/pull_request_template.md", + ".github/workflows/build.yml", + ".github/workflows/pull-request-lint.yml", + ".github/workflows/upgrade.yml", + ".gitignore", + ".mergify.yml", + ".npmignore", + ".prettierignore", + ".prettierrc.json", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "LICENSE", + "tsconfig.dev.json", + "tsconfig.json", + ], + }, + ".projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "env": { + "PATH": "$(npx -c "node --print process.env.PATH")", + }, + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "default", + }, + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "bundle": { + "description": "Prepare assets", + "name": "bundle", + }, + "clobber": { + "condition": "git diff --exit-code > /dev/null", + "description": "hard resets to HEAD of origin and cleans the local repo", + "env": { + "BRANCH": "$(git branch --show-current)", + }, + "name": "clobber", + "steps": [ + { + "exec": "git checkout -b scratch", + "name": "save current HEAD in "scratch" branch", + }, + { + "exec": "git checkout $BRANCH", + }, + { + "exec": "git fetch origin", + "name": "fetch latest changes from origin", + }, + { + "exec": "git reset --hard origin/$BRANCH", + "name": "hard reset to origin commit", + }, + { + "exec": "git clean -fdx", + "name": "clean all untracked files", + }, + { + "say": "ready to rock! (unpushed commits are under the "scratch" branch)", + }, + ], + }, + "compile": { + "description": "Only compile", + "name": "compile", + }, + "default": { + "description": "Synthesize project files", + "name": "default", + "steps": [ + { + "exec": "node .projenrc.js", + }, + ], + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "eject": { + "description": "Remove projen from the project", + "env": { + "PROJEN_EJECTING": "true", + }, + "name": "eject", + "steps": [ + { + "spawn": "default", + }, + ], + }, + "eslint": { + "description": "Runs eslint against the codebase", + "name": "eslint", + "steps": [ + { + "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern src test build-tools .projenrc.js", + }, + ], + }, + "install": { + "description": "Install project dependencies and update lockfile (non-frozen)", + "name": "install", + "steps": [ + { + "exec": "yarn install --check-files", + }, + ], + }, + "install:ci": { + "description": "Install project dependencies using frozen lockfile", + "name": "install:ci", + "steps": [ + { + "exec": "yarn install --check-files --frozen-lockfile", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "name": "package", + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth:silent", + }, + ], + }, + "post-upgrade": { + "description": "Runs after upgrading dependencies", + "name": "post-upgrade", + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "jest --passWithNoTests \${CI:-'--updateSnapshot'}", + }, + { + "spawn": "eslint", + }, + ], + }, + "test:watch": { + "description": "Run jest in watch mode", + "name": "test:watch", + "steps": [ + { + "exec": "jest --watch", + }, + ], + }, + "upgrade": { + "description": "upgrade dependencies", + "env": { + "CI": "0", + }, + "name": "upgrade", + "steps": [ + { + "exec": "yarn upgrade npm-check-updates", + }, + { + "exec": "npm-check-updates --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@types/jest,@types/node,@typescript-eslint/eslint-plugin,@typescript-eslint/parser,aws-cdk,esbuild,eslint-config-prettier,eslint-import-resolver-node,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,eslint,jest,jest-junit,npm-check-updates,prettier,projen,ts-jest,ts-node,typescript,@aws/pdk,aws-cdk-lib,constructs", + }, + { + "exec": "yarn install --check-files", + }, + { + "exec": "yarn upgrade @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-cdk esbuild eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint jest jest-junit npm-check-updates prettier projen ts-jest ts-node typescript @aws/pdk aws-cdk-lib constructs", + }, + { + "exec": "npx projen", + }, + { + "spawn": "post-upgrade", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "LICENSE": " + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +", + "README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "npx ts-node -P tsconfig.json --prefer-ts-exts src/main.ts", + "build": "npx projen bundle", + "output": "cdk.out", + "watch": { + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + ], + "include": [ + "src/**/*.ts", + "test/**/*.ts", + ], + }, + }, + "package.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": { + "@aws/pdk": "*", + "aws-cdk-lib": "^2.1.0", + "constructs": "^10.0.5", + }, + "devDependencies": { + "@types/jest": "*", + "@types/node": "^16", + "@typescript-eslint/eslint-plugin": "^6", + "@typescript-eslint/parser": "^6", + "aws-cdk": "^2.1.0", + "esbuild": "*", + "eslint": "^8", + "eslint-config-prettier": "*", + "eslint-import-resolver-node": "*", + "eslint-import-resolver-typescript": "*", + "eslint-plugin-import": "*", + "eslint-plugin-prettier": "*", + "jest": "*", + "jest-junit": "^15", + "npm-check-updates": "^16", + "prettier": "*", + "projen": "*", + "ts-jest": "*", + "ts-node": "*", + "typescript": "*", + }, + "jest": { + "clearMocks": true, + "collectCoverage": true, + "coverageDirectory": "coverage", + "coveragePathIgnorePatterns": [ + "/node_modules/", + ], + "coverageReporters": [ + "json", + "lcov", + "clover", + "cobertura", + "text", + ], + "globals": { + "ts-jest": { + "tsconfig": "tsconfig.dev.json", + }, + }, + "preset": "ts-jest", + "reporters": [ + "default", + [ + "jest-junit", + { + "outputDirectory": "test-reports", + }, + ], + ], + "testMatch": [ + "/src/**/__tests__/**/*.ts?(x)", + "/(test|src)/**/*(*.)@(spec|test).ts?(x)", + ], + "testPathIgnorePatterns": [ + "/node_modules/", + ], + "watchPathIgnorePatterns": [ + "/node_modules/", + ], + }, + "license": "Apache-2.0", + "name": "Defaults", + "scripts": { + "build": "npx projen build", + "bundle": "npx projen bundle", + "clobber": "npx projen clobber", + "compile": "npx projen compile", + "default": "npx projen default", + "deploy": "npx projen deploy", + "destroy": "npx projen destroy", + "diff": "npx projen diff", + "eject": "npx projen eject", + "eslint": "npx projen eslint", + "package": "npx projen package", + "post-compile": "npx projen post-compile", + "post-upgrade": "npx projen post-upgrade", + "pre-compile": "npx projen pre-compile", + "projen": "npx projen", + "synth": "npx projen synth", + "synth:silent": "npx projen synth:silent", + "test": "npx projen test", + "test:watch": "npx projen test:watch", + "upgrade": "npx projen upgrade", + "watch": "npx projen watch", + }, + "version": "0.0.0", + }, + "src/main.ts": "import { CdkGraph, FilterPreset, Filters } from "@aws/pdk/cdk-graph"; +import { CdkGraphDiagramPlugin } from "@aws/pdk/cdk-graph-plugin-diagram"; +import { AwsPrototypingChecks, PDKNag } from "@aws/pdk/pdk-nag"; +import { ApplicationStack } from "./stacks/application-stack"; + +// for development, use account/region from cdk cli +const devEnv = { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, +}; + +/* eslint-disable @typescript-eslint/no-floating-promises */ +(async () => { + const app = PDKNag.app({ + nagPacks: [new AwsPrototypingChecks()], + }); + + new ApplicationStack(app, "infra-dev", { env: devEnv }); + + const graph = new CdkGraph(app, { + plugins: [ + new CdkGraphDiagramPlugin({ + defaults: { + filterPlan: { + preset: FilterPreset.COMPACT, + filters: [{ store: Filters.pruneCustomResources() }], + }, + }, + }), + ], + }); + + app.synth(); + await graph.report(); +})(); +", + "src/stacks/application-stack.ts": "import { UserIdentity } from "@aws/pdk/identity"; +import { Stack, StackProps } from "aws-cdk-lib"; +import { Construct } from "constructs"; + +export class ApplicationStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const userIdentity = new UserIdentity(this, \`\${id}UserIdentity\`); + } +} +", + "test/main.test.ts": "import { App } from "aws-cdk-lib"; +import { Template } from "aws-cdk-lib/assertions"; +import { ApplicationStack } from "../src/stacks/application-stack"; + +test("Snapshot", () => { + const app = new App(); + const stack = new ApplicationStack(app, "test"); + + const template = Template.fromStack(stack); + expect(template.toJSON()).toMatchSnapshot(); +}); +", + "tsconfig.dev.json": { + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019", + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + }, + "exclude": [ + "node_modules", + ], + "include": [ + ".projenrc.js", + "src/**/*.ts", + "test/**/*.ts", + ], + }, + "tsconfig.json": { + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019", + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "lib", + "resolveJsonModule": true, + "rootDir": "src", + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + }, + "exclude": [ + "cdk.out", + ], + "include": [ + "src/**/*.ts", + ], + }, +} +`; + +exports[`InfrastructureTsProject With Api 1`] = ` +{ + "infra/.eslintrc.json": { + "env": { + "jest": true, + "node": true, + }, + "extends": [ + "plugin:import/typescript", + "prettier", + "plugin:prettier/recommended", + ], + "ignorePatterns": [ + "*.js", + "*.d.ts", + "node_modules/", + "*.generated.ts", + "coverage", + ], + "overrides": [], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2018, + "project": "./tsconfig.dev.json", + "sourceType": "module", + }, + "plugins": [ + "@typescript-eslint", + "import", + "prettier", + ], + "root": true, + "rules": { + "@typescript-eslint/member-ordering": [ + "error", + { + "default": [ + "public-static-field", + "public-static-method", + "protected-static-field", + "protected-static-method", + "private-static-field", + "private-static-method", + "field", + "constructor", + "method", + ], + }, + ], + "@typescript-eslint/no-floating-promises": [ + "error", + ], + "@typescript-eslint/no-require-imports": [ + "error", + ], + "@typescript-eslint/no-shadow": [ + "error", + ], + "@typescript-eslint/return-await": [ + "error", + ], + "dot-notation": [ + "error", + ], + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": [ + "**/test/**", + "**/build-tools/**", + ], + "optionalDependencies": false, + "peerDependencies": true, + }, + ], + "import/no-unresolved": [ + "error", + ], + "import/order": [ + "warn", + { + "alphabetize": { + "caseInsensitive": true, + "order": "asc", + }, + "groups": [ + "builtin", + "external", + ], + }, + ], + "key-spacing": [ + "error", + ], + "no-bitwise": [ + "error", + ], + "no-duplicate-imports": [ + "error", + ], + "no-multiple-empty-lines": [ + "error", + ], + "no-return-await": [ + "off", + ], + "no-shadow": [ + "off", + ], + "no-trailing-spaces": [ + "error", + ], + "prettier/prettier": [ + "error", + ], + }, + "settings": { + "import/parsers": { + "@typescript-eslint/parser": [ + ".ts", + ".tsx", + ], + }, + "import/resolver": { + "node": {}, + "typescript": { + "alwaysTryTypes": true, + "project": "./tsconfig.dev.json", + }, + }, + }, + }, + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.eslintrc.json linguist-generated +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.npmignore linguist-generated +/.prettierignore linguist-generated +/.prettierrc.json linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/LICENSE linguist-generated +/package.json linguist-generated +/project.json linguist-generated +/tsconfig.dev.json linguist-generated +/tsconfig.json linguist-generated +/yarn.lock linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/package.json +!/LICENSE +!/.npmignore +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json +pids +*.pid +*.seed +*.pid.lock +lib-cov +coverage +*.lcov +.nyc_output +build/Release +node_modules/ +jspm_packages/ +*.tsbuildinfo +.eslintcache +*.tgz +.yarn-integrity +.cache +!/.projenrc.js +/test-reports/ +junit.xml +/coverage/ +!/.prettierignore +!/.prettierrc.json +!/test/ +!/tsconfig.json +!/tsconfig.dev.json +!/src/ +/lib +/dist/ +!/.eslintrc.json +/assets/ +!/cdk.json +/cdk.out/ +.cdk.staging/ +.parcel-cache/ +!/project.json +", + "infra/.npmignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +/.projen/ +/test-reports/ +junit.xml +/coverage/ +/test/ +/tsconfig.dev.json +/src/ +!/lib/ +!/lib/**/*.js +!/lib/**/*.d.ts +dist +/tsconfig.json +/.github/ +/.vscode/ +/.idea/ +/.projenrc.js +tsconfig.tsbuildinfo +/.eslintrc.json +!/assets/ +cdk.out/ +.cdk.staging/ +", + "infra/.prettierignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +", + "infra/.prettierrc.json": { + "overrides": [], + }, + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "name": "@types/jest", + "type": "build", + }, + { + "name": "@types/node", + "type": "build", + "version": "^16", + }, + { + "name": "@typescript-eslint/eslint-plugin", + "type": "build", + "version": "^6", + }, + { + "name": "@typescript-eslint/parser", + "type": "build", + "version": "^6", + }, + { + "name": "aws-cdk", + "type": "build", + "version": "^2.1.0", + }, + { + "name": "esbuild", + "type": "build", + }, + { + "name": "eslint-config-prettier", + "type": "build", + }, + { + "name": "eslint-import-resolver-node", + "type": "build", + }, + { + "name": "eslint-import-resolver-typescript", + "type": "build", + }, + { + "name": "eslint-plugin-import", + "type": "build", + }, + { + "name": "eslint-plugin-prettier", + "type": "build", + }, + { + "name": "eslint", + "type": "build", + "version": "^8", + }, + { + "name": "jest", + "type": "build", + }, + { + "name": "jest-junit", + "type": "build", + "version": "^15", + }, + { + "name": "npm-check-updates", + "type": "build", + "version": "^16", + }, + { + "name": "prettier", + "type": "build", + }, + { + "name": "projen", + "type": "build", + }, + { + "name": "ts-jest", + "type": "build", + }, + { + "name": "ts-node", + "type": "build", + }, + { + "name": "typescript", + "type": "build", + }, + { + "name": "@aws/pdk", + "type": "runtime", + }, + { + "name": "Api-typescript-infra", + "type": "runtime", + }, + { + "name": "aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "constructs", + "type": "runtime", + "version": "^10.0.5", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".eslintrc.json", + ".gitattributes", + ".gitignore", + ".npmignore", + ".prettierignore", + ".prettierrc.json", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "LICENSE", + "project.json", + "tsconfig.dev.json", + "tsconfig.json", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "env": { + "PATH": "$(npx -c "node --print process.env.PATH")", + }, + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "bundle": { + "description": "Prepare assets", + "name": "bundle", + }, + "compile": { + "description": "Only compile", + "name": "compile", + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "eslint": { + "description": "Runs eslint against the codebase", + "name": "eslint", + "steps": [ + { + "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern src test build-tools", + }, + ], + }, + "install": { + "description": "Install project dependencies and update lockfile (non-frozen)", + "name": "install", + "steps": [ + { + "exec": "yarn install --check-files", + }, + ], + }, + "install:ci": { + "description": "Install project dependencies using frozen lockfile", + "name": "install:ci", + "steps": [ + { + "exec": "yarn install --check-files --frozen-lockfile", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "name": "package", + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth:silent", + }, + ], + }, + "post-upgrade": { + "description": "Runs after upgrading dependencies", + "name": "post-upgrade", + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "jest --passWithNoTests \${CI:-'--updateSnapshot'}", + }, + { + "spawn": "eslint", + }, + ], + }, + "test:watch": { + "description": "Run jest in watch mode", + "name": "test:watch", + "steps": [ + { + "exec": "jest --watch", + }, + ], + }, + "upgrade": { + "description": "upgrade dependencies", + "env": { + "CI": "0", + }, + "name": "upgrade", + "steps": [ + { + "exec": "yarn upgrade npm-check-updates", + }, + { + "exec": "npm-check-updates --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@types/jest,@types/node,@typescript-eslint/eslint-plugin,@typescript-eslint/parser,aws-cdk,esbuild,eslint-config-prettier,eslint-import-resolver-node,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,eslint,jest,jest-junit,npm-check-updates,prettier,projen,ts-jest,ts-node,typescript,@aws/pdk,Api-typescript-infra,aws-cdk-lib,constructs", + }, + { + "exec": "yarn install --check-files", + }, + { + "exec": "yarn upgrade @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-cdk esbuild eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint jest jest-junit npm-check-updates prettier projen ts-jest ts-node typescript @aws/pdk Api-typescript-infra aws-cdk-lib constructs", + }, + { + "exec": "npx projen", + }, + { + "spawn": "post-upgrade", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/LICENSE": " + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +", + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "npx ts-node -P tsconfig.json --prefer-ts-exts src/main.ts", + "build": "npx projen bundle", + "output": "cdk.out", + "watch": { + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + ], + "include": [ + "src/**/*.ts", + "test/**/*.ts", + ], + }, + }, + "infra/package.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": { + "@aws/pdk": "*", + "Api-typescript-infra": "*", + "aws-cdk-lib": "^2.1.0", + "constructs": "^10.0.5", + }, + "devDependencies": { + "@types/jest": "*", + "@types/node": "^16", + "@typescript-eslint/eslint-plugin": "^6", + "@typescript-eslint/parser": "^6", + "aws-cdk": "^2.1.0", + "esbuild": "*", + "eslint": "^8", + "eslint-config-prettier": "*", + "eslint-import-resolver-node": "*", + "eslint-import-resolver-typescript": "*", + "eslint-plugin-import": "*", + "eslint-plugin-prettier": "*", + "jest": "*", + "jest-junit": "^15", + "npm-check-updates": "^16", + "prettier": "*", + "projen": "*", + "ts-jest": "*", + "ts-node": "*", + "typescript": "*", + }, + "jest": { + "clearMocks": true, + "collectCoverage": true, + "coverageDirectory": "coverage", + "coveragePathIgnorePatterns": [ + "/node_modules/", + ], + "coverageReporters": [ + "json", + "lcov", + "clover", + "cobertura", + "text", + ], + "globals": { + "ts-jest": { + "tsconfig": "tsconfig.dev.json", + }, + }, + "preset": "ts-jest", + "reporters": [ + "default", + [ + "jest-junit", + { + "outputDirectory": "test-reports", + }, + ], + ], + "testMatch": [ + "/src/**/__tests__/**/*.ts?(x)", + "/(test|src)/**/*(*.)@(spec|test).ts?(x)", + ], + "testPathIgnorePatterns": [ + "/node_modules/", + ], + "watchPathIgnorePatterns": [ + "/node_modules/", + ], + }, + "license": "Apache-2.0", + "name": "WithApi", + "scripts": { + "build": "npx projen build", + "bundle": "npx projen bundle", + "compile": "npx projen compile", + "default": "npx projen default", + "deploy": "npx projen deploy", + "destroy": "npx projen destroy", + "diff": "npx projen diff", + "eslint": "npx projen eslint", + "package": "npx projen package", + "post-compile": "npx projen post-compile", + "post-upgrade": "npx projen post-upgrade", + "pre-compile": "npx projen pre-compile", + "synth": "npx projen synth", + "synth:silent": "npx projen synth:silent", + "test": "npx projen test", + "test:watch": "npx projen test:watch", + "upgrade": "npx projen upgrade", + "watch": "npx projen watch", + }, + "version": "0.0.0", + }, + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen build", + "cwd": "infra", + }, + }, + "bundle": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen bundle", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen diff", + "cwd": "infra", + }, + }, + "eslint": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen eslint", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen post-compile", + "cwd": "infra", + }, + }, + "post-upgrade": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen post-upgrade", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen pre-compile", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen test", + "cwd": "infra", + }, + }, + "test:watch": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen test:watch", + "cwd": "infra", + }, + }, + "upgrade": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen upgrade", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/src/constructs/api.ts": "import { UserIdentity } from "@aws/pdk/identity"; +import { Authorizers } from "@aws/pdk/type-safe-api"; +import { Stack } from "aws-cdk-lib"; +import { Cors } from "aws-cdk-lib/aws-apigateway"; +import { + AccountPrincipal, + AnyPrincipal, + Effect, + PolicyDocument, + PolicyStatement, +} from "aws-cdk-lib/aws-iam"; +import { Construct } from "constructs"; +import { Api, MockIntegrations } from "Api-typescript-infra"; + +/** + * Api construct props. + */ +export interface ApiConstructProps { + /** + * Instance of the UserIdentity. + */ + readonly userIdentity: UserIdentity; +} + +/** + * Infrastructure construct to deploy a Type Safe API. + */ +export class ApiConstruct extends Construct { + /** + * API instance + */ + public readonly api: Api; + + constructor(scope: Construct, id: string, props?: ApiConstructProps) { + super(scope, id); + + this.api = new Api(this, id, { + defaultAuthorizer: Authorizers.iam(), + corsOptions: { + allowOrigins: Cors.ALL_ORIGINS, + allowMethods: Cors.ALL_METHODS, + }, + integrations: MockIntegrations.mockAll(), + policy: new PolicyDocument({ + statements: [ + // Here we grant any AWS credentials from the account that the prototype is deployed in to call the api. + // Machine to machine fine-grained access can be defined here using more specific principals (eg roles or + // users) and resources (ie which api paths may be invoked by which principal) if required. + // If doing so, the cognito identity pool authenticated role must still be granted access for cognito users to + // still be granted access to the API. + new PolicyStatement({ + effect: Effect.ALLOW, + principals: [new AccountPrincipal(Stack.of(this).account)], + actions: ["execute-api:Invoke"], + resources: ["execute-api:/*"], + }), + // Open up OPTIONS to allow browsers to make unauthenticated preflight requests + new PolicyStatement({ + effect: Effect.ALLOW, + principals: [new AnyPrincipal()], + actions: ["execute-api:Invoke"], + resources: ["execute-api:/*/OPTIONS/*"], + }), + ], + }), + }); + + // Grant authenticated users access to invoke the api + props?.userIdentity.identityPool.authenticatedRole.addToPrincipalPolicy( + new PolicyStatement({ + effect: Effect.ALLOW, + actions: ["execute-api:Invoke"], + resources: [this.api.api.arnForExecuteApi("*", "/*", "*")], + }), + ); + } +} +", + "infra/src/main.ts": "import { CdkGraph, FilterPreset, Filters } from "@aws/pdk/cdk-graph"; +import { CdkGraphDiagramPlugin } from "@aws/pdk/cdk-graph-plugin-diagram"; +import { AwsPrototypingChecks, PDKNag } from "@aws/pdk/pdk-nag"; +import { ApplicationStack } from "./stacks/application-stack"; + +// for development, use account/region from cdk cli +const devEnv = { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, +}; + +/* eslint-disable @typescript-eslint/no-floating-promises */ +(async () => { + const app = PDKNag.app({ + nagPacks: [new AwsPrototypingChecks()], + }); + + new ApplicationStack(app, "infra-dev", { env: devEnv }); + + const graph = new CdkGraph(app, { + plugins: [ + new CdkGraphDiagramPlugin({ + defaults: { + filterPlan: { + preset: FilterPreset.COMPACT, + filters: [{ store: Filters.pruneCustomResources() }], + }, + }, + }), + ], + }); + + app.synth(); + await graph.report(); +})(); +", + "infra/src/stacks/application-stack.ts": "import { UserIdentity } from "@aws/pdk/identity"; +import { Stack, StackProps } from "aws-cdk-lib"; +import { Construct } from "constructs"; +import { ApiConstruct } from "../constructs/api"; + +export class ApplicationStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const userIdentity = new UserIdentity(this, \`\${id}UserIdentity\`); + new ApiConstruct(this, "Api", { + userIdentity, + }); + } +} +", + "infra/test/main.test.ts": "import { App } from "aws-cdk-lib"; +import { Template } from "aws-cdk-lib/assertions"; +import { ApplicationStack } from "../src/stacks/application-stack"; + +test("Snapshot", () => { + const app = new App(); + const stack = new ApplicationStack(app, "test"); + + const template = Template.fromStack(stack); + expect(template.toJSON()).toMatchSnapshot(); +}); +", + "infra/tsconfig.dev.json": { + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019", + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + }, + "exclude": [ + "node_modules", + ], + "include": [ + ".projenrc.js", + "src/**/*.ts", + "test/**/*.ts", + ], + }, + "infra/tsconfig.json": { + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019", + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "lib", + "resolveJsonModule": true, + "rootDir": "src", + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + }, + "exclude": [ + "cdk.out", + ], + "include": [ + "src/**/*.ts", + ], + }, +} +`; + +exports[`InfrastructureTsProject With Api and Website 1`] = ` +{ + "infra/.eslintrc.json": { + "env": { + "jest": true, + "node": true, + }, + "extends": [ + "plugin:import/typescript", + "prettier", + "plugin:prettier/recommended", + ], + "ignorePatterns": [ + "*.js", + "*.d.ts", + "node_modules/", + "*.generated.ts", + "coverage", + ], + "overrides": [], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2018, + "project": "./tsconfig.dev.json", + "sourceType": "module", + }, + "plugins": [ + "@typescript-eslint", + "import", + "prettier", + ], + "root": true, + "rules": { + "@typescript-eslint/member-ordering": [ + "error", + { + "default": [ + "public-static-field", + "public-static-method", + "protected-static-field", + "protected-static-method", + "private-static-field", + "private-static-method", + "field", + "constructor", + "method", + ], + }, + ], + "@typescript-eslint/no-floating-promises": [ + "error", + ], + "@typescript-eslint/no-require-imports": [ + "error", + ], + "@typescript-eslint/no-shadow": [ + "error", + ], + "@typescript-eslint/return-await": [ + "error", + ], + "dot-notation": [ + "error", + ], + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": [ + "**/test/**", + "**/build-tools/**", + ], + "optionalDependencies": false, + "peerDependencies": true, + }, + ], + "import/no-unresolved": [ + "error", + ], + "import/order": [ + "warn", + { + "alphabetize": { + "caseInsensitive": true, + "order": "asc", + }, + "groups": [ + "builtin", + "external", + ], + }, + ], + "key-spacing": [ + "error", + ], + "no-bitwise": [ + "error", + ], + "no-duplicate-imports": [ + "error", + ], + "no-multiple-empty-lines": [ + "error", + ], + "no-return-await": [ + "off", + ], + "no-shadow": [ + "off", + ], + "no-trailing-spaces": [ + "error", + ], + "prettier/prettier": [ + "error", + ], + }, + "settings": { + "import/parsers": { + "@typescript-eslint/parser": [ + ".ts", + ".tsx", + ], + }, + "import/resolver": { + "node": {}, + "typescript": { + "alwaysTryTypes": true, + "project": "./tsconfig.dev.json", + }, + }, + }, + }, + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.eslintrc.json linguist-generated +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.npmignore linguist-generated +/.prettierignore linguist-generated +/.prettierrc.json linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/LICENSE linguist-generated +/package.json linguist-generated +/project.json linguist-generated +/tsconfig.dev.json linguist-generated +/tsconfig.json linguist-generated +/yarn.lock linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/package.json +!/LICENSE +!/.npmignore +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json +pids +*.pid +*.seed +*.pid.lock +lib-cov +coverage +*.lcov +.nyc_output +build/Release +node_modules/ +jspm_packages/ +*.tsbuildinfo +.eslintcache +*.tgz +.yarn-integrity +.cache +!/.projenrc.js +/test-reports/ +junit.xml +/coverage/ +!/.prettierignore +!/.prettierrc.json +!/test/ +!/tsconfig.json +!/tsconfig.dev.json +!/src/ +/lib +/dist/ +!/.eslintrc.json +/assets/ +!/cdk.json +/cdk.out/ +.cdk.staging/ +.parcel-cache/ +!/project.json +", + "infra/.npmignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +/.projen/ +/test-reports/ +junit.xml +/coverage/ +/test/ +/tsconfig.dev.json +/src/ +!/lib/ +!/lib/**/*.js +!/lib/**/*.d.ts +dist +/tsconfig.json +/.github/ +/.vscode/ +/.idea/ +/.projenrc.js +tsconfig.tsbuildinfo +/.eslintrc.json +!/assets/ +cdk.out/ +.cdk.staging/ +", + "infra/.prettierignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +", + "infra/.prettierrc.json": { + "overrides": [], + }, + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "name": "@types/jest", + "type": "build", + }, + { + "name": "@types/node", + "type": "build", + "version": "^16", + }, + { + "name": "@typescript-eslint/eslint-plugin", + "type": "build", + "version": "^6", + }, + { + "name": "@typescript-eslint/parser", + "type": "build", + "version": "^6", + }, + { + "name": "aws-cdk", + "type": "build", + "version": "^2.1.0", + }, + { + "name": "esbuild", + "type": "build", + }, + { + "name": "eslint-config-prettier", + "type": "build", + }, + { + "name": "eslint-import-resolver-node", + "type": "build", + }, + { + "name": "eslint-import-resolver-typescript", + "type": "build", + }, + { + "name": "eslint-plugin-import", + "type": "build", + }, + { + "name": "eslint-plugin-prettier", + "type": "build", + }, + { + "name": "eslint", + "type": "build", + "version": "^8", + }, + { + "name": "jest", + "type": "build", + }, + { + "name": "jest-junit", + "type": "build", + "version": "^15", + }, + { + "name": "npm-check-updates", + "type": "build", + "version": "^16", + }, + { + "name": "prettier", + "type": "build", + }, + { + "name": "projen", + "type": "build", + }, + { + "name": "ts-jest", + "type": "build", + }, + { + "name": "ts-node", + "type": "build", + }, + { + "name": "typescript", + "type": "build", + }, + { + "name": "Website", + "type": "build", + }, + { + "name": "@aws/pdk", + "type": "runtime", + }, + { + "name": "Api-typescript-infra", + "type": "runtime", + }, + { + "name": "aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "constructs", + "type": "runtime", + "version": "^10.0.5", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".eslintrc.json", + ".gitattributes", + ".gitignore", + ".npmignore", + ".prettierignore", + ".prettierrc.json", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "LICENSE", + "project.json", + "tsconfig.dev.json", + "tsconfig.json", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "env": { + "PATH": "$(npx -c "node --print process.env.PATH")", + }, + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "bundle": { + "description": "Prepare assets", + "name": "bundle", + }, + "compile": { + "description": "Only compile", + "name": "compile", + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "eslint": { + "description": "Runs eslint against the codebase", + "name": "eslint", + "steps": [ + { + "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern src test build-tools", + }, + ], + }, + "install": { + "description": "Install project dependencies and update lockfile (non-frozen)", + "name": "install", + "steps": [ + { + "exec": "yarn install --check-files", + }, + ], + }, + "install:ci": { + "description": "Install project dependencies using frozen lockfile", + "name": "install:ci", + "steps": [ + { + "exec": "yarn install --check-files --frozen-lockfile", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "name": "package", + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth:silent", + }, + ], + }, + "post-upgrade": { + "description": "Runs after upgrading dependencies", + "name": "post-upgrade", + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "jest --passWithNoTests \${CI:-'--updateSnapshot'}", + }, + { + "spawn": "eslint", + }, + ], + }, + "test:watch": { + "description": "Run jest in watch mode", + "name": "test:watch", + "steps": [ + { + "exec": "jest --watch", + }, + ], + }, + "upgrade": { + "description": "upgrade dependencies", + "env": { + "CI": "0", + }, + "name": "upgrade", + "steps": [ + { + "exec": "yarn upgrade npm-check-updates", + }, + { + "exec": "npm-check-updates --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@types/jest,@types/node,@typescript-eslint/eslint-plugin,@typescript-eslint/parser,aws-cdk,esbuild,eslint-config-prettier,eslint-import-resolver-node,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,eslint,jest,jest-junit,npm-check-updates,prettier,projen,ts-jest,ts-node,typescript,Website,@aws/pdk,Api-typescript-infra,aws-cdk-lib,constructs", + }, + { + "exec": "yarn install --check-files", + }, + { + "exec": "yarn upgrade @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-cdk esbuild eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint jest jest-junit npm-check-updates prettier projen ts-jest ts-node typescript Website @aws/pdk Api-typescript-infra aws-cdk-lib constructs", + }, + { + "exec": "npx projen", + }, + { + "spawn": "post-upgrade", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/LICENSE": " + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +", + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "npx ts-node -P tsconfig.json --prefer-ts-exts src/main.ts", + "build": "npx projen bundle", + "output": "cdk.out", + "watch": { + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + ], + "include": [ + "src/**/*.ts", + "test/**/*.ts", + ], + }, + }, + "infra/package.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": { + "@aws/pdk": "*", + "Api-typescript-infra": "*", + "aws-cdk-lib": "^2.1.0", + "constructs": "^10.0.5", + }, + "devDependencies": { + "@types/jest": "*", + "@types/node": "^16", + "@typescript-eslint/eslint-plugin": "^6", + "@typescript-eslint/parser": "^6", + "Website": "*", + "aws-cdk": "^2.1.0", + "esbuild": "*", + "eslint": "^8", + "eslint-config-prettier": "*", + "eslint-import-resolver-node": "*", + "eslint-import-resolver-typescript": "*", + "eslint-plugin-import": "*", + "eslint-plugin-prettier": "*", + "jest": "*", + "jest-junit": "^15", + "npm-check-updates": "^16", + "prettier": "*", + "projen": "*", + "ts-jest": "*", + "ts-node": "*", + "typescript": "*", + }, + "jest": { + "clearMocks": true, + "collectCoverage": true, + "coverageDirectory": "coverage", + "coveragePathIgnorePatterns": [ + "/node_modules/", + ], + "coverageReporters": [ + "json", + "lcov", + "clover", + "cobertura", + "text", + ], + "globals": { + "ts-jest": { + "tsconfig": "tsconfig.dev.json", + }, + }, + "preset": "ts-jest", + "reporters": [ + "default", + [ + "jest-junit", + { + "outputDirectory": "test-reports", + }, + ], + ], + "testMatch": [ + "/src/**/__tests__/**/*.ts?(x)", + "/(test|src)/**/*(*.)@(spec|test).ts?(x)", + ], + "testPathIgnorePatterns": [ + "/node_modules/", + ], + "watchPathIgnorePatterns": [ + "/node_modules/", + ], + }, + "license": "Apache-2.0", + "name": "WithApi", + "scripts": { + "build": "npx projen build", + "bundle": "npx projen bundle", + "compile": "npx projen compile", + "default": "npx projen default", + "deploy": "npx projen deploy", + "destroy": "npx projen destroy", + "diff": "npx projen diff", + "eslint": "npx projen eslint", + "package": "npx projen package", + "post-compile": "npx projen post-compile", + "post-upgrade": "npx projen post-upgrade", + "pre-compile": "npx projen pre-compile", + "synth": "npx projen synth", + "synth:silent": "npx projen synth:silent", + "test": "npx projen test", + "test:watch": "npx projen test:watch", + "upgrade": "npx projen upgrade", + "watch": "npx projen watch", + }, + "version": "0.0.0", + }, + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen build", + "cwd": "infra", + }, + }, + "bundle": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen bundle", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen diff", + "cwd": "infra", + }, + }, + "eslint": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen eslint", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen post-compile", + "cwd": "infra", + }, + }, + "post-upgrade": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen post-upgrade", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen pre-compile", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen test", + "cwd": "infra", + }, + }, + "test:watch": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen test:watch", + "cwd": "infra", + }, + }, + "upgrade": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen upgrade", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/src/constructs/api.ts": "import { UserIdentity } from "@aws/pdk/identity"; +import { Authorizers } from "@aws/pdk/type-safe-api"; +import { Stack } from "aws-cdk-lib"; +import { Cors } from "aws-cdk-lib/aws-apigateway"; +import { + AccountPrincipal, + AnyPrincipal, + Effect, + PolicyDocument, + PolicyStatement, +} from "aws-cdk-lib/aws-iam"; +import { Construct } from "constructs"; +import { Api, MockIntegrations } from "Api-typescript-infra"; + +/** + * Api construct props. + */ +export interface ApiConstructProps { + /** + * Instance of the UserIdentity. + */ + readonly userIdentity: UserIdentity; +} + +/** + * Infrastructure construct to deploy a Type Safe API. + */ +export class ApiConstruct extends Construct { + /** + * API instance + */ + public readonly api: Api; + + constructor(scope: Construct, id: string, props?: ApiConstructProps) { + super(scope, id); + + this.api = new Api(this, id, { + defaultAuthorizer: Authorizers.iam(), + corsOptions: { + allowOrigins: Cors.ALL_ORIGINS, + allowMethods: Cors.ALL_METHODS, + }, + integrations: MockIntegrations.mockAll(), + policy: new PolicyDocument({ + statements: [ + // Here we grant any AWS credentials from the account that the prototype is deployed in to call the api. + // Machine to machine fine-grained access can be defined here using more specific principals (eg roles or + // users) and resources (ie which api paths may be invoked by which principal) if required. + // If doing so, the cognito identity pool authenticated role must still be granted access for cognito users to + // still be granted access to the API. + new PolicyStatement({ + effect: Effect.ALLOW, + principals: [new AccountPrincipal(Stack.of(this).account)], + actions: ["execute-api:Invoke"], + resources: ["execute-api:/*"], + }), + // Open up OPTIONS to allow browsers to make unauthenticated preflight requests + new PolicyStatement({ + effect: Effect.ALLOW, + principals: [new AnyPrincipal()], + actions: ["execute-api:Invoke"], + resources: ["execute-api:/*/OPTIONS/*"], + }), + ], + }), + }); + + // Grant authenticated users access to invoke the api + props?.userIdentity.identityPool.authenticatedRole.addToPrincipalPolicy( + new PolicyStatement({ + effect: Effect.ALLOW, + actions: ["execute-api:Invoke"], + resources: [this.api.api.arnForExecuteApi("*", "/*", "*")], + }), + ); + } +} +", + "infra/src/constructs/website.ts": "import { UserIdentity } from "@aws/pdk/identity"; +import { StaticWebsite } from "@aws/pdk/static-website"; +import { Stack } from "aws-cdk-lib"; +import { GeoRestriction } from "aws-cdk-lib/aws-cloudfront"; +import { Construct } from "constructs"; +import { ApiConstruct } from "./api"; + +/** + * Website construct props + */ +export interface WebsiteConstructProps { + /** + * Instance of an API to configure the website to integrate with + */ + readonly apiConstruct: ApiConstruct; + + /** + * Instance of the UserIdentity. + */ + readonly userIdentity: UserIdentity; +} + +/** + * Construct to deploy a Static Website + */ +export class WebsiteConstruct extends Construct { + constructor(scope: Construct, id: string, props?: WebsiteConstructProps) { + super(scope, id); + + new StaticWebsite(this, id, { + websiteContentPath: "../website/build", + runtimeOptions: { + jsonPayload: { + region: Stack.of(this).region, + identityPoolId: props?.userIdentity.identityPool.identityPoolId, + userPoolId: props?.userIdentity.userPool?.userPoolId, + userPoolWebClientId: + props?.userIdentity.userPoolClient?.userPoolClientId, + apiUrl: props?.apiConstruct.api.api.urlForPath(), + }, + }, + distributionProps: { + geoRestriction: GeoRestriction.allowlist( + "AU", + "ID", + "IN", + "JP", + "KR", + "SG", + "US", + ), + }, + }); + } +} +", + "infra/src/main.ts": "import { CdkGraph, FilterPreset, Filters } from "@aws/pdk/cdk-graph"; +import { CdkGraphDiagramPlugin } from "@aws/pdk/cdk-graph-plugin-diagram"; +import { AwsPrototypingChecks, PDKNag } from "@aws/pdk/pdk-nag"; +import { ApplicationStack } from "./stacks/application-stack"; + +// for development, use account/region from cdk cli +const devEnv = { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, +}; + +/* eslint-disable @typescript-eslint/no-floating-promises */ +(async () => { + const app = PDKNag.app({ + nagPacks: [new AwsPrototypingChecks()], + }); + + new ApplicationStack(app, "infra-dev", { env: devEnv }); + + const graph = new CdkGraph(app, { + plugins: [ + new CdkGraphDiagramPlugin({ + defaults: { + filterPlan: { + preset: FilterPreset.COMPACT, + filters: [{ store: Filters.pruneCustomResources() }], + }, + }, + }), + ], + }); + + app.synth(); + await graph.report(); +})(); +", + "infra/src/stacks/application-stack.ts": "import { UserIdentity } from "@aws/pdk/identity"; +import { Stack, StackProps } from "aws-cdk-lib"; +import { Construct } from "constructs"; +import { ApiConstruct } from "../constructs/api"; +import { WebsiteConstruct } from "../constructs/website"; + +export class ApplicationStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const userIdentity = new UserIdentity(this, \`\${id}UserIdentity\`); + const apiConstruct = new ApiConstruct(this, "Api", { + userIdentity, + }); + new WebsiteConstruct(this, "Website", { userIdentity, apiConstruct }); + } +} +", + "infra/test/main.test.ts": "import { App } from "aws-cdk-lib"; +import { Template } from "aws-cdk-lib/assertions"; +import { ApplicationStack } from "../src/stacks/application-stack"; + +test("Snapshot", () => { + const app = new App(); + const stack = new ApplicationStack(app, "test"); + + const template = Template.fromStack(stack); + expect(template.toJSON()).toMatchSnapshot(); +}); +", + "infra/tsconfig.dev.json": { + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019", + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + }, + "exclude": [ + "node_modules", + ], + "include": [ + ".projenrc.js", + "src/**/*.ts", + "test/**/*.ts", + ], + }, + "infra/tsconfig.json": { + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019", + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "lib", + "resolveJsonModule": true, + "rootDir": "src", + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + }, + "exclude": [ + "cdk.out", + ], + "include": [ + "src/**/*.ts", + ], + }, +} +`; + +exports[`InfrastructureTsProject With Website 1`] = ` +{ + "infra/.eslintrc.json": { + "env": { + "jest": true, + "node": true, + }, + "extends": [ + "plugin:import/typescript", + "prettier", + "plugin:prettier/recommended", + ], + "ignorePatterns": [ + "*.js", + "*.d.ts", + "node_modules/", + "*.generated.ts", + "coverage", + ], + "overrides": [], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2018, + "project": "./tsconfig.dev.json", + "sourceType": "module", + }, + "plugins": [ + "@typescript-eslint", + "import", + "prettier", + ], + "root": true, + "rules": { + "@typescript-eslint/member-ordering": [ + "error", + { + "default": [ + "public-static-field", + "public-static-method", + "protected-static-field", + "protected-static-method", + "private-static-field", + "private-static-method", + "field", + "constructor", + "method", + ], + }, + ], + "@typescript-eslint/no-floating-promises": [ + "error", + ], + "@typescript-eslint/no-require-imports": [ + "error", + ], + "@typescript-eslint/no-shadow": [ + "error", + ], + "@typescript-eslint/return-await": [ + "error", + ], + "dot-notation": [ + "error", + ], + "import/no-extraneous-dependencies": [ + "error", + { + "devDependencies": [ + "**/test/**", + "**/build-tools/**", + ], + "optionalDependencies": false, + "peerDependencies": true, + }, + ], + "import/no-unresolved": [ + "error", + ], + "import/order": [ + "warn", + { + "alphabetize": { + "caseInsensitive": true, + "order": "asc", + }, + "groups": [ + "builtin", + "external", + ], + }, + ], + "key-spacing": [ + "error", + ], + "no-bitwise": [ + "error", + ], + "no-duplicate-imports": [ + "error", + ], + "no-multiple-empty-lines": [ + "error", + ], + "no-return-await": [ + "off", + ], + "no-shadow": [ + "off", + ], + "no-trailing-spaces": [ + "error", + ], + "prettier/prettier": [ + "error", + ], + }, + "settings": { + "import/parsers": { + "@typescript-eslint/parser": [ + ".ts", + ".tsx", + ], + }, + "import/resolver": { + "node": {}, + "typescript": { + "alwaysTryTypes": true, + "project": "./tsconfig.dev.json", + }, + }, + }, + }, + "infra/.gitattributes": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". + +/.eslintrc.json linguist-generated +/.gitattributes linguist-generated +/.gitignore linguist-generated +/.npmignore linguist-generated +/.prettierignore linguist-generated +/.prettierrc.json linguist-generated +/.projen/** linguist-generated +/.projen/deps.json linguist-generated +/.projen/files.json linguist-generated +/.projen/tasks.json linguist-generated +/cdk.json linguist-generated +/LICENSE linguist-generated +/package.json linguist-generated +/project.json linguist-generated +/tsconfig.dev.json linguist-generated +/tsconfig.json linguist-generated +/yarn.lock linguist-generated", + "infra/.gitignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +!/.gitattributes +!/.projen/tasks.json +!/.projen/deps.json +!/.projen/files.json +!/package.json +!/LICENSE +!/.npmignore +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json +pids +*.pid +*.seed +*.pid.lock +lib-cov +coverage +*.lcov +.nyc_output +build/Release +node_modules/ +jspm_packages/ +*.tsbuildinfo +.eslintcache +*.tgz +.yarn-integrity +.cache +!/.projenrc.js +/test-reports/ +junit.xml +/coverage/ +!/.prettierignore +!/.prettierrc.json +!/test/ +!/tsconfig.json +!/tsconfig.dev.json +!/src/ +/lib +/dist/ +!/.eslintrc.json +/assets/ +!/cdk.json +/cdk.out/ +.cdk.staging/ +.parcel-cache/ +!/project.json +", + "infra/.npmignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +/.projen/ +/test-reports/ +junit.xml +/coverage/ +/test/ +/tsconfig.dev.json +/src/ +!/lib/ +!/lib/**/*.js +!/lib/**/*.d.ts +dist +/tsconfig.json +/.github/ +/.vscode/ +/.idea/ +/.projenrc.js +tsconfig.tsbuildinfo +/.eslintrc.json +!/assets/ +cdk.out/ +.cdk.staging/ +", + "infra/.prettierignore": "# ~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen". +", + "infra/.prettierrc.json": { + "overrides": [], + }, + "infra/.projen/deps.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": [ + { + "name": "@types/jest", + "type": "build", + }, + { + "name": "@types/node", + "type": "build", + "version": "^16", + }, + { + "name": "@typescript-eslint/eslint-plugin", + "type": "build", + "version": "^6", + }, + { + "name": "@typescript-eslint/parser", + "type": "build", + "version": "^6", + }, + { + "name": "aws-cdk", + "type": "build", + "version": "^2.1.0", + }, + { + "name": "esbuild", + "type": "build", + }, + { + "name": "eslint-config-prettier", + "type": "build", + }, + { + "name": "eslint-import-resolver-node", + "type": "build", + }, + { + "name": "eslint-import-resolver-typescript", + "type": "build", + }, + { + "name": "eslint-plugin-import", + "type": "build", + }, + { + "name": "eslint-plugin-prettier", + "type": "build", + }, + { + "name": "eslint", + "type": "build", + "version": "^8", + }, + { + "name": "jest", + "type": "build", + }, + { + "name": "jest-junit", + "type": "build", + "version": "^15", + }, + { + "name": "npm-check-updates", + "type": "build", + "version": "^16", + }, + { + "name": "prettier", + "type": "build", + }, + { + "name": "projen", + "type": "build", + }, + { + "name": "ts-jest", + "type": "build", + }, + { + "name": "ts-node", + "type": "build", + }, + { + "name": "typescript", + "type": "build", + }, + { + "name": "Website", + "type": "build", + }, + { + "name": "@aws/pdk", + "type": "runtime", + }, + { + "name": "aws-cdk-lib", + "type": "runtime", + "version": "^2.1.0", + }, + { + "name": "constructs", + "type": "runtime", + "version": "^10.0.5", + }, + ], + }, + "infra/.projen/files.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "files": [ + ".eslintrc.json", + ".gitattributes", + ".gitignore", + ".npmignore", + ".prettierignore", + ".prettierrc.json", + ".projen/deps.json", + ".projen/files.json", + ".projen/tasks.json", + "cdk.json", + "LICENSE", + "project.json", + "tsconfig.dev.json", + "tsconfig.json", + ], + }, + "infra/.projen/tasks.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "env": { + "PATH": "$(npx -c "node --print process.env.PATH")", + }, + "tasks": { + "build": { + "description": "Full release build", + "name": "build", + "steps": [ + { + "spawn": "pre-compile", + }, + { + "spawn": "compile", + }, + { + "spawn": "post-compile", + }, + { + "spawn": "test", + }, + { + "spawn": "package", + }, + ], + }, + "bundle": { + "description": "Prepare assets", + "name": "bundle", + }, + "compile": { + "description": "Only compile", + "name": "compile", + }, + "default": { + "description": "Synthesize project files", + "name": "default", + }, + "deploy": { + "description": "Deploys your CDK app to the AWS cloud", + "name": "deploy", + "steps": [ + { + "exec": "cdk deploy", + "receiveArgs": true, + }, + ], + }, + "destroy": { + "description": "Destroys your cdk app in the AWS cloud", + "name": "destroy", + "steps": [ + { + "exec": "cdk destroy", + "receiveArgs": true, + }, + ], + }, + "diff": { + "description": "Diffs the currently deployed app against your code", + "name": "diff", + "steps": [ + { + "exec": "cdk diff", + }, + ], + }, + "eslint": { + "description": "Runs eslint against the codebase", + "name": "eslint", + "steps": [ + { + "exec": "eslint --ext .ts,.tsx --fix --no-error-on-unmatched-pattern src test build-tools", + }, + ], + }, + "install": { + "description": "Install project dependencies and update lockfile (non-frozen)", + "name": "install", + "steps": [ + { + "exec": "yarn install --check-files", + }, + ], + }, + "install:ci": { + "description": "Install project dependencies using frozen lockfile", + "name": "install:ci", + "steps": [ + { + "exec": "yarn install --check-files --frozen-lockfile", + }, + ], + }, + "package": { + "description": "Creates the distribution package", + "name": "package", + }, + "post-compile": { + "description": "Runs after successful compilation", + "name": "post-compile", + "steps": [ + { + "spawn": "synth:silent", + }, + ], + }, + "post-upgrade": { + "description": "Runs after upgrading dependencies", + "name": "post-upgrade", + }, + "pre-compile": { + "description": "Prepare the project for compilation", + "name": "pre-compile", + }, + "synth": { + "description": "Synthesizes your cdk app into cdk.out", + "name": "synth", + "steps": [ + { + "exec": "cdk synth", + }, + ], + }, + "synth:silent": { + "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of "yarn build")", + "name": "synth:silent", + "steps": [ + { + "exec": "cdk synth -q", + }, + ], + }, + "test": { + "description": "Run tests", + "name": "test", + "steps": [ + { + "exec": "jest --passWithNoTests \${CI:-'--updateSnapshot'}", + }, + { + "spawn": "eslint", + }, + ], + }, + "test:watch": { + "description": "Run jest in watch mode", + "name": "test:watch", + "steps": [ + { + "exec": "jest --watch", + }, + ], + }, + "upgrade": { + "description": "upgrade dependencies", + "env": { + "CI": "0", + }, + "name": "upgrade", + "steps": [ + { + "exec": "yarn upgrade npm-check-updates", + }, + { + "exec": "npm-check-updates --upgrade --target=minor --peer --dep=dev,peer,prod,optional --filter=@types/jest,@types/node,@typescript-eslint/eslint-plugin,@typescript-eslint/parser,aws-cdk,esbuild,eslint-config-prettier,eslint-import-resolver-node,eslint-import-resolver-typescript,eslint-plugin-import,eslint-plugin-prettier,eslint,jest,jest-junit,npm-check-updates,prettier,projen,ts-jest,ts-node,typescript,Website,@aws/pdk,aws-cdk-lib,constructs", + }, + { + "exec": "yarn install --check-files", + }, + { + "exec": "yarn upgrade @types/jest @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser aws-cdk esbuild eslint-config-prettier eslint-import-resolver-node eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-prettier eslint jest jest-junit npm-check-updates prettier projen ts-jest ts-node typescript Website @aws/pdk aws-cdk-lib constructs", + }, + { + "exec": "npx projen", + }, + { + "spawn": "post-upgrade", + }, + ], + }, + "watch": { + "description": "Watches changes in your source code and rebuilds and deploys to the current account", + "name": "watch", + "steps": [ + { + "exec": "cdk deploy --hotswap", + }, + { + "exec": "cdk watch", + }, + ], + }, + }, + }, + "infra/LICENSE": " + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +", + "infra/README.md": "## Getting started + +Refer to [Developer Guide](https://aws.github.io/aws-pdk/developer_guides/infrastructure/index.html)", + "infra/cdk.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "app": "npx ts-node -P tsconfig.json --prefer-ts-exts src/main.ts", + "build": "npx projen bundle", + "output": "cdk.out", + "watch": { + "exclude": [ + "README.md", + "cdk*.json", + "**/*.d.ts", + "**/*.js", + "tsconfig.json", + "package*.json", + "yarn.lock", + "node_modules", + ], + "include": [ + "src/**/*.ts", + "test/**/*.ts", + ], + }, + }, + "infra/package.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "dependencies": { + "@aws/pdk": "*", + "aws-cdk-lib": "^2.1.0", + "constructs": "^10.0.5", + }, + "devDependencies": { + "@types/jest": "*", + "@types/node": "^16", + "@typescript-eslint/eslint-plugin": "^6", + "@typescript-eslint/parser": "^6", + "Website": "*", + "aws-cdk": "^2.1.0", + "esbuild": "*", + "eslint": "^8", + "eslint-config-prettier": "*", + "eslint-import-resolver-node": "*", + "eslint-import-resolver-typescript": "*", + "eslint-plugin-import": "*", + "eslint-plugin-prettier": "*", + "jest": "*", + "jest-junit": "^15", + "npm-check-updates": "^16", + "prettier": "*", + "projen": "*", + "ts-jest": "*", + "ts-node": "*", + "typescript": "*", + }, + "jest": { + "clearMocks": true, + "collectCoverage": true, + "coverageDirectory": "coverage", + "coveragePathIgnorePatterns": [ + "/node_modules/", + ], + "coverageReporters": [ + "json", + "lcov", + "clover", + "cobertura", + "text", + ], + "globals": { + "ts-jest": { + "tsconfig": "tsconfig.dev.json", + }, + }, + "preset": "ts-jest", + "reporters": [ + "default", + [ + "jest-junit", + { + "outputDirectory": "test-reports", + }, + ], + ], + "testMatch": [ + "/src/**/__tests__/**/*.ts?(x)", + "/(test|src)/**/*(*.)@(spec|test).ts?(x)", + ], + "testPathIgnorePatterns": [ + "/node_modules/", + ], + "watchPathIgnorePatterns": [ + "/node_modules/", + ], + }, + "license": "Apache-2.0", + "name": "WithApi", + "scripts": { + "build": "npx projen build", + "bundle": "npx projen bundle", + "compile": "npx projen compile", + "default": "npx projen default", + "deploy": "npx projen deploy", + "destroy": "npx projen destroy", + "diff": "npx projen diff", + "eslint": "npx projen eslint", + "package": "npx projen package", + "post-compile": "npx projen post-compile", + "post-upgrade": "npx projen post-upgrade", + "pre-compile": "npx projen pre-compile", + "synth": "npx projen synth", + "synth:silent": "npx projen synth:silent", + "test": "npx projen test", + "test:watch": "npx projen test:watch", + "upgrade": "npx projen upgrade", + "watch": "npx projen watch", + }, + "version": "0.0.0", + }, + "infra/project.json": { + "//": "~~ Generated by projen. To modify, edit .projenrc.js and run "npx projen".", + "name": "WithApi", + "root": "infra", + "targets": { + "build": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen build", + "cwd": "infra", + }, + }, + "bundle": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen bundle", + "cwd": "infra", + }, + }, + "compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen compile", + "cwd": "infra", + }, + }, + "default": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen default", + "cwd": "infra", + }, + }, + "deploy": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen deploy", + "cwd": "infra", + }, + }, + "destroy": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen destroy", + "cwd": "infra", + }, + }, + "diff": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen diff", + "cwd": "infra", + }, + }, + "eslint": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen eslint", + "cwd": "infra", + }, + }, + "package": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen package", + "cwd": "infra", + }, + }, + "post-compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen post-compile", + "cwd": "infra", + }, + }, + "post-upgrade": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen post-upgrade", + "cwd": "infra", + }, + }, + "pre-compile": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen pre-compile", + "cwd": "infra", + }, + }, + "synth": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen synth", + "cwd": "infra", + }, + }, + "synth:silent": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen synth:silent", + "cwd": "infra", + }, + }, + "test": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen test", + "cwd": "infra", + }, + }, + "test:watch": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen test:watch", + "cwd": "infra", + }, + }, + "upgrade": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen upgrade", + "cwd": "infra", + }, + }, + "watch": { + "executor": "nx:run-commands", + "options": { + "command": "yarn projen watch", + "cwd": "infra", + }, + }, + }, + }, + "infra/src/constructs/website.ts": "import { UserIdentity } from "@aws/pdk/identity"; +import { StaticWebsite } from "@aws/pdk/static-website"; +import { Stack } from "aws-cdk-lib"; +import { GeoRestriction } from "aws-cdk-lib/aws-cloudfront"; +import { Construct } from "constructs"; +// import { ApiConstruct } from "./api"; + +/** + * Website construct props + */ +export interface WebsiteConstructProps { + /** + * Instance of an API to configure the website to integrate with + */ + // readonly apiConstruct: ApiConstruct; + + /** + * Instance of the UserIdentity. + */ + readonly userIdentity: UserIdentity; +} + +/** + * Construct to deploy a Static Website + */ +export class WebsiteConstruct extends Construct { + constructor(scope: Construct, id: string, props?: WebsiteConstructProps) { + super(scope, id); + + new StaticWebsite(this, id, { + websiteContentPath: "../website/build", + runtimeOptions: { + jsonPayload: { + region: Stack.of(this).region, + identityPoolId: props?.userIdentity.identityPool.identityPoolId, + userPoolId: props?.userIdentity.userPool?.userPoolId, + userPoolWebClientId: + props?.userIdentity.userPoolClient?.userPoolClientId, + // apiUrl: props?.apiConstruct.api.api.urlForPath(), + }, + }, + distributionProps: { + geoRestriction: GeoRestriction.allowlist( + "AU", + "ID", + "IN", + "JP", + "KR", + "SG", + "US", + ), + }, + }); + } +} +", + "infra/src/main.ts": "import { CdkGraph, FilterPreset, Filters } from "@aws/pdk/cdk-graph"; +import { CdkGraphDiagramPlugin } from "@aws/pdk/cdk-graph-plugin-diagram"; +import { AwsPrototypingChecks, PDKNag } from "@aws/pdk/pdk-nag"; +import { ApplicationStack } from "./stacks/application-stack"; + +// for development, use account/region from cdk cli +const devEnv = { + account: process.env.CDK_DEFAULT_ACCOUNT, + region: process.env.CDK_DEFAULT_REGION, +}; + +/* eslint-disable @typescript-eslint/no-floating-promises */ +(async () => { + const app = PDKNag.app({ + nagPacks: [new AwsPrototypingChecks()], + }); + + new ApplicationStack(app, "infra-dev", { env: devEnv }); + + const graph = new CdkGraph(app, { + plugins: [ + new CdkGraphDiagramPlugin({ + defaults: { + filterPlan: { + preset: FilterPreset.COMPACT, + filters: [{ store: Filters.pruneCustomResources() }], + }, + }, + }), + ], + }); + + app.synth(); + await graph.report(); +})(); +", + "infra/src/stacks/application-stack.ts": "import { UserIdentity } from "@aws/pdk/identity"; +import { Stack, StackProps } from "aws-cdk-lib"; +import { Construct } from "constructs"; +import { WebsiteConstruct } from "../constructs/website"; + +export class ApplicationStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const userIdentity = new UserIdentity(this, \`\${id}UserIdentity\`); + new WebsiteConstruct(this, "Website", { userIdentity }); + } +} +", + "infra/test/main.test.ts": "import { App } from "aws-cdk-lib"; +import { Template } from "aws-cdk-lib/assertions"; +import { ApplicationStack } from "../src/stacks/application-stack"; + +test("Snapshot", () => { + const app = new App(); + const stack = new ApplicationStack(app, "test"); + + const template = Template.fromStack(stack); + expect(template.toJSON()).toMatchSnapshot(); +}); +", + "infra/tsconfig.dev.json": { + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019", + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + }, + "exclude": [ + "node_modules", + ], + "include": [ + ".projenrc.js", + "src/**/*.ts", + "test/**/*.ts", + ], + }, + "infra/tsconfig.json": { + "compilerOptions": { + "alwaysStrict": true, + "declaration": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "inlineSourceMap": true, + "inlineSources": true, + "lib": [ + "es2019", + ], + "module": "CommonJS", + "noEmitOnError": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "lib", + "resolveJsonModule": true, + "rootDir": "src", + "strict": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "stripInternal": true, + "target": "ES2019", + }, + "exclude": [ + "cdk.out", + ], + "include": [ + "src/**/*.ts", + ], + }, +} +`; diff --git a/packages/infrastructure/test/projects/typescript/infrastructure-ts-project.test.ts b/packages/infrastructure/test/projects/typescript/infrastructure-ts-project.test.ts new file mode 100644 index 000000000..87013c9b6 --- /dev/null +++ b/packages/infrastructure/test/projects/typescript/infrastructure-ts-project.test.ts @@ -0,0 +1,58 @@ +/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 */ +import { Language } from "@aws/type-safe-api"; +import { synthSnapshot } from "projen/lib/util/synth"; +import { + InfrastructureTsProject, + InfrastructureTsProjectOptions, +} from "../../../src"; +import { + BuildOptionsProps, + snapshotInfrastructureProject, +} from "../utils/snapshot-infra-project"; + +describe("InfrastructureTsProject", () => { + const snapshot = ( + buildOptions: (props: BuildOptionsProps) => InfrastructureTsProjectOptions + ) => + snapshotInfrastructureProject( + Language.TYPESCRIPT, + InfrastructureTsProject, + buildOptions + ); + + it("Defaults", () => { + const project = new InfrastructureTsProject({ + name: "Defaults", + }); + expect(synthSnapshot(project)).toMatchSnapshot(); + }); + + it("With Api", () => { + expect( + snapshot(({ typeSafeApi }) => ({ + name: "WithApi", + typeSafeApi, + })) + ).toMatchSnapshot(); + }); + + it("With Website", () => { + expect( + snapshot(({ cloudscapeReactTsWebsite }) => ({ + name: "WithApi", + cloudscapeReactTsWebsite, + })) + ).toMatchSnapshot(); + }); + + it("With Api and Website", () => { + expect( + snapshot(({ cloudscapeReactTsWebsite, typeSafeApi }) => ({ + name: "WithApi", + typeSafeApi, + cloudscapeReactTsWebsite, + })) + ).toMatchSnapshot(); + }); +}); diff --git a/packages/infrastructure/test/projects/utils/snapshot-infra-project.ts b/packages/infrastructure/test/projects/utils/snapshot-infra-project.ts new file mode 100644 index 000000000..51e5f8d83 --- /dev/null +++ b/packages/infrastructure/test/projects/utils/snapshot-infra-project.ts @@ -0,0 +1,70 @@ +/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 */ +import { CloudscapeReactTsWebsiteProject } from "@aws/cloudscape-react-ts-website"; +import { MonorepoTsProject } from "@aws/monorepo"; +import { + Language, + ModelLanguage, + TypeSafeApiProject, +} from "@aws/type-safe-api"; +import { Project, ProjectOptions } from "projen"; +import { synthSnapshot } from "projen/lib/util/synth"; + +export interface BuildOptionsProps { + readonly typeSafeApi: TypeSafeApiProject; + readonly cloudscapeReactTsWebsite: CloudscapeReactTsWebsiteProject; +} + +export const snapshotInfrastructureProject = < + TProject extends Project, + TOptions extends ProjectOptions +>( + language: Language, + InfrastructureProject: new (opts: TOptions) => TProject, + buildOptions: (props: BuildOptionsProps) => TOptions +) => { + const monorepo = new MonorepoTsProject({ + name: "monorepo", + }); + + const typeSafeApi = new TypeSafeApiProject({ + parent: monorepo, + outdir: "api", + name: "Api", + model: { + language: ModelLanguage.SMITHY, + options: { + smithy: { + serviceName: { + namespace: "com.aws", + serviceName: "Api", + }, + }, + }, + }, + infrastructure: { + language, + }, + }); + + const cloudscapeReactTsWebsite = new CloudscapeReactTsWebsiteProject({ + parent: monorepo, + outdir: "website", + name: "Website", + }); + + new InfrastructureProject({ + ...buildOptions({ typeSafeApi, cloudscapeReactTsWebsite }), + parent: monorepo, + outdir: "infra", + }); + + const monorepoSnapshot = synthSnapshot(monorepo); + + // Filter to only the infrastructure project we're interested in + return Object.fromEntries( + Object.entries(monorepoSnapshot).filter(([filePath]) => + filePath.startsWith("infra/") + ) + ); +};