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/") + ) + ); +};