@aws/nx-plugin 0.76.0 → 0.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE-THIRD-PARTY +96 -10
  2. package/package.json +9 -9
  3. package/src/infra/app/__snapshots__/generator.spec.ts.snap +378 -7
  4. package/src/infra/app/files/app/src/main.ts.template +17 -2
  5. package/src/infra/app/generator.js +34 -9
  6. package/src/infra/app/generator.js.map +1 -1
  7. package/src/infra/app/schema.d.ts +1 -0
  8. package/src/infra/app/schema.json +6 -0
  9. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +16 -13
  10. package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +1 -1
  11. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +2 -2
  12. package/src/py/strands-agent/__snapshots__/generator.spec.ts.snap +6 -6
  13. package/src/smithy/react-connection/__snapshots__/generator.spec.ts.snap +2 -2
  14. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +23 -17
  15. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +60 -34
  16. package/src/trpc/backend/files/src/handler.ts.template +48 -0
  17. package/src/trpc/backend/files/src/index.ts.template +1 -1
  18. package/src/trpc/backend/files/src/router.ts.template +0 -38
  19. package/src/trpc/backend/files/src/schema/z-async-iterable.ts.template +115 -0
  20. package/src/trpc/backend/generator.js +6 -2
  21. package/src/trpc/backend/generator.js.map +1 -1
  22. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +274 -27
  23. package/src/trpc/react/files/src/components/__apiNameClassName__ClientProvider.tsx.template +57 -1
  24. package/src/trpc/react/generator.js +11 -1
  25. package/src/trpc/react/generator.js.map +1 -1
  26. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +1 -1
  27. package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +1 -1
  28. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +13 -13
  29. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +13 -1
  30. package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +3 -3
  31. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +8 -3
  32. package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +1 -1
  33. package/src/utils/connection/open-api/files/components/__apiNameClassName__Provider.tsx.template +1 -1
  34. package/src/utils/files/common/infra-config/src/index.ts.template +3 -0
  35. package/src/utils/files/common/infra-config/src/resolve-stage.ts.template +23 -0
  36. package/src/utils/files/common/infra-config/src/stages.config.ts.template +48 -0
  37. package/src/utils/files/common/infra-config/src/stages.types.ts.template +66 -0
  38. package/src/utils/files/common/scripts/src/index.ts.template +1 -0
  39. package/src/utils/files/common/scripts/src/infra-deploy.ts.template +2 -0
  40. package/src/utils/files/common/scripts/src/infra-destroy.ts.template +2 -0
  41. package/src/utils/files/common/scripts/src/stage-credentials/cdk-command.ts.template +18 -0
  42. package/src/utils/files/common/scripts/src/stage-credentials/credentials.ts.template +100 -0
  43. package/src/utils/files/common/scripts/src/stage-credentials/run.ts.template +52 -0
  44. package/src/utils/files/common/scripts/src/stage-credentials/stage-parser.ts.template +15 -0
  45. package/src/utils/files/website/hooks/sigv4/useSigV4.tsx.template +81 -33
  46. package/src/utils/shared-constructs-constants.d.ts +4 -0
  47. package/src/utils/shared-constructs-constants.js +5 -1
  48. package/src/utils/shared-constructs-constants.js.map +1 -1
  49. package/src/utils/shared-infra-config.d.ts +11 -0
  50. package/src/utils/shared-infra-config.js +47 -0
  51. package/src/utils/shared-infra-config.js.map +1 -0
  52. package/src/utils/shared-scripts.d.ts +12 -0
  53. package/src/utils/shared-scripts.js +49 -0
  54. package/src/utils/shared-scripts.js.map +1 -0
  55. package/src/utils/versions.d.ts +31 -28
  56. package/src/utils/versions.js +30 -27
  57. package/src/utils/versions.js.map +1 -1
@@ -3352,12 +3352,12 @@ SOFTWARE.
3352
3352
 
3353
3353
  ---
3354
3354
 
3355
- The following software may be included in this product: @esbuild/linux-x64 (0.27.2)
3355
+ The following software may be included in this product: @esbuild/darwin-arm64 (0.27.2)
3356
3356
  This software contains the following license and notice below:
3357
3357
 
3358
3358
  MIT License
3359
3359
 
3360
- Copyright (c) The maintainers of @esbuild/linux-x64 <https://github.com/evanw/esbuild#readme>
3360
+ Copyright (c) The maintainers of @esbuild/darwin-arm64 <https://github.com/evanw/esbuild#readme>
3361
3361
 
3362
3362
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
3363
3363
  associated documentation files (the "Software"), to deal in the Software without restriction, including
@@ -3376,12 +3376,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
3376
3376
 
3377
3377
  ---
3378
3378
 
3379
- The following software may be included in this product: @esbuild/linux-x64 (0.27.3)
3379
+ The following software may be included in this product: @esbuild/darwin-arm64 (0.27.3)
3380
3380
  This software contains the following license and notice below:
3381
3381
 
3382
3382
  MIT License
3383
3383
 
3384
- Copyright (c) The maintainers of @esbuild/linux-x64 <https://github.com/evanw/esbuild#readme>
3384
+ Copyright (c) The maintainers of @esbuild/darwin-arm64 <https://github.com/evanw/esbuild#readme>
3385
3385
 
3386
3386
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
3387
3387
  associated documentation files (the "Software"), to deal in the Software without restriction, including
@@ -3903,7 +3903,7 @@ THE SOFTWARE.
3903
3903
 
3904
3904
  ---
3905
3905
 
3906
- The following software may be included in this product: @modelcontextprotocol/sdk (1.26.0)
3906
+ The following software may be included in this product: @modelcontextprotocol/sdk (1.27.0)
3907
3907
  This software contains the following license and notice below:
3908
3908
 
3909
3909
  MIT License
@@ -4631,7 +4631,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4631
4631
 
4632
4632
  ---
4633
4633
 
4634
- The following software may be included in this product: @nx/nx-linux-x64-gnu (22.5.1)
4634
+ The following software may be included in this product: @nx/nx-darwin-arm64 (22.5.1)
4635
4635
  This software contains the following license and notice below:
4636
4636
 
4637
4637
  (The MIT License)
@@ -5349,7 +5349,7 @@ THE SOFTWARE.
5349
5349
 
5350
5350
  ---
5351
5351
 
5352
- The following software may be included in this product: @rollup/rollup-linux-x64-gnu (4.50.1)
5352
+ The following software may be included in this product: @rollup/rollup-darwin-arm64 (4.50.1)
5353
5353
  This software contains the following license and notice below:
5354
5354
 
5355
5355
  MIT License
@@ -5401,7 +5401,7 @@ SOFTWARE.
5401
5401
 
5402
5402
  ---
5403
5403
 
5404
- The following software may be included in this product: @rspack/binding-linux-x64-gnu (1.6.8)
5404
+ The following software may be included in this product: @rspack/binding-darwin-arm64 (1.6.8)
5405
5405
  This software contains the following license and notice below:
5406
5406
 
5407
5407
  MIT License
@@ -8493,6 +8493,35 @@ SOFTWARE.
8493
8493
 
8494
8494
  ---
8495
8495
 
8496
+ The following software may be included in this product: balanced-match (4.0.4)
8497
+ This software contains the following license and notice below:
8498
+
8499
+ (MIT)
8500
+
8501
+ Original code Copyright Julian Gruber <julian@juliangruber.com>
8502
+
8503
+ Port to TypeScript Copyright Isaac Z. Schlueter <i@izs.me>
8504
+
8505
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
8506
+ this software and associated documentation files (the "Software"), to deal in
8507
+ the Software without restriction, including without limitation the rights to
8508
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8509
+ of the Software, and to permit persons to whom the Software is furnished to do
8510
+ so, subject to the following conditions:
8511
+
8512
+ The above copyright notice and this permission notice shall be included in all
8513
+ copies or substantial portions of the Software.
8514
+
8515
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8516
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8517
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8518
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8519
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8520
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
8521
+ SOFTWARE.
8522
+
8523
+ ---
8524
+
8496
8525
  The following software may be included in this product: base64-js (1.5.1)
8497
8526
  This software contains the following license and notice below:
8498
8527
 
@@ -8737,6 +8766,35 @@ SOFTWARE.
8737
8766
 
8738
8767
  ---
8739
8768
 
8769
+ The following software may be included in this product: brace-expansion (5.0.3)
8770
+ This software contains the following license and notice below:
8771
+
8772
+ MIT License
8773
+
8774
+ Copyright Julian Gruber <julian@juliangruber.com>
8775
+
8776
+ TypeScript port Copyright Isaac Z. Schlueter <i@izs.me>
8777
+
8778
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8779
+ of this software and associated documentation files (the "Software"), to deal
8780
+ in the Software without restriction, including without limitation the rights
8781
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8782
+ copies of the Software, and to permit persons to whom the Software is
8783
+ furnished to do so, subject to the following conditions:
8784
+
8785
+ The above copyright notice and this permission notice shall be included in all
8786
+ copies or substantial portions of the Software.
8787
+
8788
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8789
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8790
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8791
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8792
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8793
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
8794
+ SOFTWARE.
8795
+
8796
+ ---
8797
+
8740
8798
  The following software may be included in this product: braces (3.0.3)
8741
8799
  This software contains the following license and notice below:
8742
8800
 
@@ -13107,6 +13165,34 @@ OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHE
13107
13165
 
13108
13166
  ---
13109
13167
 
13168
+ The following software may be included in this product: fsevents (2.3.3)
13169
+ This software contains the following license and notice below:
13170
+
13171
+ MIT License
13172
+ -----------
13173
+
13174
+ Copyright (C) 2010-2020 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller
13175
+
13176
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13177
+ of this software and associated documentation files (the "Software"), to deal
13178
+ in the Software without restriction, including without limitation the rights
13179
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13180
+ copies of the Software, and to permit persons to whom the Software is
13181
+ furnished to do so, subject to the following conditions:
13182
+
13183
+ The above copyright notice and this permission notice shall be included in
13184
+ all copies or substantial portions of the Software.
13185
+
13186
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13187
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13188
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13189
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
13190
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
13191
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
13192
+ THE SOFTWARE.
13193
+
13194
+ ---
13195
+
13110
13196
  The following software may be included in this product: function-bind (1.1.2)
13111
13197
  This software contains the following license and notice below:
13112
13198
 
@@ -39041,7 +39127,7 @@ software or this license, under any kind of legal claim._**
39041
39127
 
39042
39128
  ---
39043
39129
 
39044
- The following software may be included in this product: minimatch (10.1.2)
39130
+ The following software may be included in this product: minimatch (10.2.2)
39045
39131
  This software contains the following license and notice below:
39046
39132
 
39047
39133
  # Blue Oak Model License
@@ -39873,7 +39959,7 @@ defined by the Mozilla Public License, v. 2.0.
39873
39959
 
39874
39960
  ---
39875
39961
 
39876
- The following software may be included in this product: lightningcss-linux-x64-gnu (1.30.2)
39962
+ The following software may be included in this product: lightningcss-darwin-arm64 (1.30.2)
39877
39963
  This software contains the following license and notice below:
39878
39964
 
39879
39965
  Mozilla Public License Version 2.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin",
3
- "version": "0.76.0",
3
+ "version": "0.78.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -19,19 +19,19 @@
19
19
  },
20
20
  "generators": "./generators.json",
21
21
  "peerDependencies": {
22
- "nx": "~22.5.0",
22
+ "nx": "~22.5.1",
23
23
  "prettier": "^3.8.1"
24
24
  },
25
25
  "dependencies": {
26
26
  "@apidevtools/swagger-parser": "^10.1.1",
27
27
  "@hey-api/openapi-ts": "0.64.13",
28
28
  "@iarna/toml": "^2.2.5",
29
- "@modelcontextprotocol/sdk": "~1.26.0",
30
- "@nx/devkit": "~22.5.0",
31
- "@nx/eslint": "~22.5.0",
32
- "@nx/js": "~22.5.0",
33
- "@nx/react": "~22.5.0",
34
- "@nx/vite": "~22.5.0",
29
+ "@modelcontextprotocol/sdk": "~1.27.0",
30
+ "@nx/devkit": "~22.5.1",
31
+ "@nx/eslint": "~22.5.1",
32
+ "@nx/js": "~22.5.1",
33
+ "@nx/react": "~22.5.1",
34
+ "@nx/vite": "~22.5.1",
35
35
  "@nxlv/python": "~22.1.0",
36
36
  "@phenomnomnominal/tsquery": "6.1.4",
37
37
  "enquirer": "^2.4.1",
@@ -42,7 +42,7 @@
42
42
  "lodash.orderby": "^4.6.0",
43
43
  "lodash.trim": "^4.5.1",
44
44
  "lodash.uniqby": "^4.7.0",
45
- "minimatch": "^10.1.2",
45
+ "minimatch": "^10.2.1",
46
46
  "openapi-types": "^12.1.3",
47
47
  "pip-requirements-js": "^0.2.1",
48
48
  "typescript": "~5.9.3",
@@ -2,9 +2,9 @@
2
2
 
3
3
  exports[`infra generator > should add required dependencies to package.json > dependencies 1`] = `
4
4
  {
5
- "aws-cdk": "2.1105.0",
5
+ "aws-cdk": "2.1106.0",
6
6
  "aws-cdk-lib": "2.238.0",
7
- "constructs": "10.4.5",
7
+ "constructs": "10.5.0",
8
8
  "esbuild": "0.27.3",
9
9
  "source-map-support": "0.5.21",
10
10
  }
@@ -39,9 +39,9 @@ exports[`infra generator > should add required dependencies to package.json > de
39
39
  exports[`infra generator > should add required dependencies to package.json > package-json 1`] = `
40
40
  {
41
41
  "dependencies": {
42
- "aws-cdk": "2.1105.0",
42
+ "aws-cdk": "2.1106.0",
43
43
  "aws-cdk-lib": "2.238.0",
44
- "constructs": "10.4.5",
44
+ "constructs": "10.5.0",
45
45
  "esbuild": "0.27.3",
46
46
  "source-map-support": "0.5.21",
47
47
  },
@@ -84,7 +84,7 @@ exports[`infra generator > should configure Checkov target correctly > checkov-t
84
84
  "{workspaceRoot}/dist/{projectRoot}/cdk.out",
85
85
  ],
86
86
  "options": {
87
- "command": "uvx checkov==3.2.501 --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
87
+ "command": "uvx checkov==3.2.505 --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
88
88
  },
89
89
  "outputs": [
90
90
  "{workspaceRoot}/dist/{projectRoot}/checkov",
@@ -177,7 +177,7 @@ exports[`infra generator > should configure project.json with correct targets >
177
177
  "{workspaceRoot}/dist/{projectRoot}/cdk.out",
178
178
  ],
179
179
  "options": {
180
- "command": "uvx checkov==3.2.501 --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
180
+ "command": "uvx checkov==3.2.505 --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
181
181
  },
182
182
  "outputs": [
183
183
  "{workspaceRoot}/dist/{projectRoot}/checkov",
@@ -727,7 +727,7 @@ exports[`infra generator > should handle custom project names correctly > custom
727
727
  "{workspaceRoot}/dist/{projectRoot}/cdk.out",
728
728
  ],
729
729
  "options": {
730
- "command": "uvx checkov==3.2.501 --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
730
+ "command": "uvx checkov==3.2.505 --config-file {projectRoot}/checkov.yml --directory dist/{projectRoot}/cdk.out --framework cloudformation",
731
731
  },
732
732
  "outputs": [
733
733
  "{workspaceRoot}/dist/{projectRoot}/checkov",
@@ -812,3 +812,374 @@ exports[`infra generator > should handle custom project names correctly > custom
812
812
  },
813
813
  }
814
814
  `;
815
+
816
+ exports[`infra generator > with enableStageConfig > should snapshot generated infra-config src directory > packages/common/infra-config/src/index.ts 1`] = `
817
+ "export * from './stages.types.js';
818
+ export { default } from './stages.config.js';
819
+ export { resolveStage } from './resolve-stage.js';
820
+ "
821
+ `;
822
+
823
+ exports[`infra generator > with enableStageConfig > should snapshot generated infra-config src directory > packages/common/infra-config/src/resolve-stage.ts 1`] = `
824
+ "import type { StageConfig, StagesConfig } from './stages.types.js';
825
+ import stagesConfig from './stages.config.js';
826
+
827
+ // Widen the narrow \`as const\` type to StagesConfig for dynamic key access
828
+ const config: StagesConfig = stagesConfig;
829
+
830
+ /**
831
+ * Resolves stage config for a given project and stage name.
832
+ * Project-specific fields take priority over shared ones.
833
+ *
834
+ * @param projectPath - Project path relative to workspace root (e.g., 'packages/infra')
835
+ * @param stageName - CDK stage name (e.g., 'my-app-dev')
836
+ * @returns Merged StageConfig or undefined if no config exists for this stage
837
+ */
838
+ export function resolveStage(
839
+ projectPath: string,
840
+ stageName: string,
841
+ ): StageConfig | undefined {
842
+ const shared = config.shared?.stages?.[stageName];
843
+ const project = config.projects?.[projectPath]?.stages?.[stageName];
844
+ if (!shared && !project) return undefined;
845
+ return { ...shared, ...project } as StageConfig;
846
+ }
847
+ "
848
+ `;
849
+
850
+ exports[`infra generator > with enableStageConfig > should snapshot generated infra-config src directory > packages/common/infra-config/src/stages.config.ts 1`] = `
851
+ "/**
852
+ * Stage configuration for CDK deployments.
853
+ *
854
+ * This file maps CDK stage names to their deployment settings. When you run
855
+ * \`npx nx run <project>:deploy <stage-name>/*\`, the infra-deploy script
856
+ * automatically resolves and applies the correct credentials.
857
+ *
858
+ * Project keys are the project path relative to the workspace root
859
+ * (e.g., 'packages/infra').
860
+ *
861
+ * Stage names must match the CDK stage identifiers defined in your main.ts —
862
+ * the first argument to \`new ApplicationStage(app, '<stage-name>', ...)\`.
863
+ * For example, if main.ts has \`new ApplicationStage(app, 'my-app-dev', ...)\`
864
+ * then the stage name here is 'my-app-dev'.
865
+ *
866
+ * We recommend committing this file so the team shares a single source of truth.
867
+ * If it contains personal profile names, you can add it to .gitignore instead.
868
+ */
869
+ import type { StagesConfig } from './stages.types.js';
870
+
871
+ export default {
872
+ projects: {
873
+ // Example: map stages for a specific infra project
874
+ // 'packages/infra': {
875
+ // stages: {
876
+ // 'my-app-dev': {
877
+ // credentials: { type: 'profile', profile: 'dev-account' },
878
+ // region: 'us-east-1',
879
+ // // account is optional — if omitted, CDK infers from the profile
880
+ // },
881
+ // 'my-app-prod': {
882
+ // credentials: { type: 'assumeRole', assumeRole: 'arn:aws:iam::123456789012:role/DeployRole' },
883
+ // region: 'us-west-2',
884
+ // account: '123456789012',
885
+ // },
886
+ // },
887
+ // },
888
+ },
889
+ shared: {
890
+ stages: {
891
+ // Example: shared sandbox stage available to all projects
892
+ // 'sandbox': {
893
+ // credentials: { type: 'profile', profile: 'sandbox-profile' },
894
+ // region: 'us-east-1',
895
+ // },
896
+ },
897
+ },
898
+ } as const satisfies StagesConfig;
899
+ "
900
+ `;
901
+
902
+ exports[`infra generator > with enableStageConfig > should snapshot generated infra-config src directory > packages/common/infra-config/src/stages.types.ts 1`] = `
903
+ "/**
904
+ * Type definitions for stage and project configuration.
905
+ *
906
+ * These types are used by both stages.config.ts and the infra-deploy/
907
+ * infra-destroy scripts. They live in a shared package so any
908
+ * project in the workspace can import them.
909
+ */
910
+
911
+ /** Use an AWS CLI profile from ~/.aws/config */
912
+ export type ProfileCredentials = {
913
+ type: 'profile';
914
+ /** AWS CLI profile name */
915
+ profile: string;
916
+ };
917
+
918
+ /** Assume an IAM role via STS, optionally using a profile as the source credentials */
919
+ export type AssumeRoleCredentials = {
920
+ type: 'assumeRole';
921
+ /** IAM Role ARN to assume */
922
+ assumeRole: string;
923
+ /** Optional: AWS CLI profile to use as source credentials for the AssumeRole call */
924
+ profile?: string;
925
+ /** Optional: External ID required by the role's trust policy */
926
+ externalId?: string;
927
+ /** Optional: Session duration in seconds (default: 3600). Increase for long deployments. */
928
+ sessionDuration?: number;
929
+ };
930
+
931
+ /**
932
+ * Credentials for deploying to a specific CDK stage.
933
+ * The \`type\` field determines which credential strategy is used.
934
+ */
935
+ export type StageCredentials = ProfileCredentials | AssumeRoleCredentials;
936
+
937
+ /**
938
+ * Configuration for a single CDK stage.
939
+ * Includes credentials, region, and optionally account.
940
+ */
941
+ export type StageConfig = {
942
+ /** How to authenticate when deploying this stage */
943
+ credentials: StageCredentials;
944
+ /** AWS region for this stage (e.g., 'us-east-1') */
945
+ region: string;
946
+ /** AWS account ID. If omitted, CDK infers it from the active credentials. */
947
+ account?: string;
948
+ };
949
+
950
+ /**
951
+ * Configuration for a single infrastructure project.
952
+ * The key in the parent map is the project path relative to workspace root
953
+ * (e.g., 'packages/infra').
954
+ */
955
+ export type ProjectConfig = {
956
+ /** Map of CDK stage names to their configuration */
957
+ stages: { [stageName: string]: StageConfig };
958
+ };
959
+
960
+ /** Top-level configuration mapping projects and stages to their settings. */
961
+ export type StagesConfig = {
962
+ /** Project-specific config. Key is the project path relative to workspace root. */
963
+ projects?: { [projectPath: string]: ProjectConfig };
964
+ /** Shared stage config available to all projects. */
965
+ shared?: {
966
+ stages: { [stageName: string]: StageConfig };
967
+ };
968
+ };
969
+ "
970
+ `;
971
+
972
+ exports[`infra generator > with enableStageConfig > should snapshot generated scripts src directory > packages/common/scripts/src/index.ts 1`] = `
973
+ "// Scripts (infra-deploy, infra-destroy) are the public interface of this package.
974
+ "
975
+ `;
976
+
977
+ exports[`infra generator > with enableStageConfig > should snapshot generated scripts src directory > packages/common/scripts/src/infra-deploy.ts 1`] = `
978
+ "import { run } from './stage-credentials/run.js';
979
+ run('deploy');
980
+ "
981
+ `;
982
+
983
+ exports[`infra generator > with enableStageConfig > should snapshot generated scripts src directory > packages/common/scripts/src/infra-destroy.ts 1`] = `
984
+ "import { run } from './stage-credentials/run.js';
985
+ run('destroy');
986
+ "
987
+ `;
988
+
989
+ exports[`infra generator > with enableStageConfig > should snapshot generated scripts src directory > packages/common/scripts/src/stage-credentials/cdk-command.ts 1`] = `
990
+ "/**
991
+ * Builds the CDK command as an array of arguments for spawnSync.
992
+ *
993
+ * Defaults to --require-approval=never (standard for local dev deploys).
994
+ * If the user explicitly passes --require-approval with any value, we
995
+ * respect their choice and don't add the default.
996
+ */
997
+ export function buildCdkCommand(
998
+ action: string,
999
+ remainingArgs: string[],
1000
+ ): string[] {
1001
+ const hasRequireApproval = remainingArgs.some(
1002
+ (a) => a === '--require-approval' || a.startsWith('--require-approval='),
1003
+ );
1004
+ return hasRequireApproval
1005
+ ? ['cdk', action, ...remainingArgs]
1006
+ : ['cdk', action, '--require-approval=never', ...remainingArgs];
1007
+ }
1008
+ "
1009
+ `;
1010
+
1011
+ exports[`infra generator > with enableStageConfig > should snapshot generated scripts src directory > packages/common/scripts/src/stage-credentials/credentials.ts 1`] = `
1012
+ "import type { StageCredentials, StagesConfig } from ':proj/common-infra-config';
1013
+
1014
+ /**
1015
+ * Looks up credentials for a given project + stage combination.
1016
+ *
1017
+ * Lookup order:
1018
+ * 1. Project-specific: config.projects[projectPath].stages[stageName].credentials
1019
+ * 2. Shared: config.shared.stages[stageName].credentials
1020
+ * 3. No match: returns undefined — caller falls back to env vars
1021
+ */
1022
+ export function lookupCredentials(
1023
+ config: StagesConfig | undefined,
1024
+ projectPath: string,
1025
+ stageName: string,
1026
+ ): { credentials: StageCredentials | undefined; source: string } {
1027
+ const projectCreds =
1028
+ config?.projects?.[projectPath]?.stages?.[stageName]?.credentials;
1029
+ if (projectCreds) {
1030
+ return { credentials: projectCreds, source: 'project-specific' };
1031
+ }
1032
+
1033
+ const sharedCreds = config?.shared?.stages?.[stageName]?.credentials;
1034
+ if (sharedCreds) {
1035
+ return { credentials: sharedCreds, source: 'shared' };
1036
+ }
1037
+
1038
+ return { credentials: undefined, source: 'environment fallback' };
1039
+ }
1040
+
1041
+ /**
1042
+ * Builds a child process environment with the resolved credentials overlaid.
1043
+ * Never modifies process.env — returns a new object.
1044
+ */
1045
+ export async function buildChildEnv(
1046
+ credentials: StageCredentials,
1047
+ projectPath: string,
1048
+ ): Promise<Record<string, string | undefined>> {
1049
+ const env = { ...process.env };
1050
+
1051
+ switch (credentials.type) {
1052
+ case 'profile': {
1053
+ env.AWS_PROFILE = credentials.profile;
1054
+ break;
1055
+ }
1056
+ case 'assumeRole': {
1057
+ let STSClient: typeof import('@aws-sdk/client-sts').STSClient;
1058
+ let AssumeRoleCommand: typeof import('@aws-sdk/client-sts').AssumeRoleCommand;
1059
+ try {
1060
+ ({ STSClient, AssumeRoleCommand } =
1061
+ await import('@aws-sdk/client-sts'));
1062
+ } catch {
1063
+ console.error(
1064
+ '[infra-deploy] Error: @aws-sdk/client-sts is required for assumeRole credentials but is not installed.',
1065
+ );
1066
+ console.error('[infra-deploy] Please install @aws-sdk/client-sts');
1067
+ process.exit(1);
1068
+ }
1069
+
1070
+ // If a source profile is specified, configure the STS client to use it
1071
+ const stsClientOptions: Record<string, unknown> = {};
1072
+ if (credentials.profile) {
1073
+ const { fromIni } = await import('@aws-sdk/credential-providers');
1074
+ stsClientOptions.credentials = fromIni({
1075
+ profile: credentials.profile,
1076
+ });
1077
+ }
1078
+
1079
+ const response = await new STSClient(stsClientOptions).send(
1080
+ new AssumeRoleCommand({
1081
+ RoleArn: credentials.assumeRole,
1082
+ RoleSessionName: \`infra-deploy-\${projectPath.replace(/\\//g, '-')}\`,
1083
+ ...(credentials.externalId
1084
+ ? { ExternalId: credentials.externalId }
1085
+ : {}),
1086
+ ...(credentials.sessionDuration
1087
+ ? { DurationSeconds: credentials.sessionDuration }
1088
+ : {}),
1089
+ }),
1090
+ );
1091
+
1092
+ env.AWS_ACCESS_KEY_ID = response.Credentials?.AccessKeyId;
1093
+ env.AWS_SECRET_ACCESS_KEY = response.Credentials?.SecretAccessKey;
1094
+ env.AWS_SESSION_TOKEN = response.Credentials?.SessionToken;
1095
+ delete env.AWS_PROFILE;
1096
+ break;
1097
+ }
1098
+ }
1099
+
1100
+ return env;
1101
+ }
1102
+
1103
+ /** Human-readable description of credentials for logging */
1104
+ export function describeCredentials(creds: StageCredentials): string {
1105
+ return creds.type === 'profile'
1106
+ ? \`profile '\${creds.profile}'\`
1107
+ : \`role '\${creds.assumeRole}'\`;
1108
+ }
1109
+ "
1110
+ `;
1111
+
1112
+ exports[`infra generator > with enableStageConfig > should snapshot generated scripts src directory > packages/common/scripts/src/stage-credentials/run.ts 1`] = `
1113
+ "import { spawnSync } from 'child_process';
1114
+ import stagesConfig from ':proj/common-infra-config';
1115
+ import { parseStageName } from './stage-parser.js';
1116
+ import {
1117
+ lookupCredentials,
1118
+ buildChildEnv,
1119
+ describeCredentials,
1120
+ } from './credentials.js';
1121
+ import { buildCdkCommand } from './cdk-command.js';
1122
+
1123
+ const log = (msg: string) => console.error(\`[infra-deploy] \${msg}\`);
1124
+
1125
+ export async function run(action: 'deploy' | 'destroy'): Promise<void> {
1126
+ const [projectPath, ...remainingArgs] = process.argv.slice(2);
1127
+
1128
+ if (!projectPath) {
1129
+ log(\`Usage: infra-\${action} <project-path> [stage/*] [cdk-args...]\`);
1130
+ process.exit(1);
1131
+ }
1132
+
1133
+ const stageName = parseStageName(remainingArgs[0]);
1134
+ let childEnv: Record<string, string | undefined> = { ...process.env };
1135
+
1136
+ if (stageName) {
1137
+ const { credentials, source } = lookupCredentials(
1138
+ stagesConfig,
1139
+ projectPath,
1140
+ stageName,
1141
+ );
1142
+
1143
+ if (credentials) {
1144
+ log(
1145
+ \`Using \${describeCredentials(credentials)} for '\${stageName}' (\${source})\`,
1146
+ );
1147
+ childEnv = await buildChildEnv(credentials, projectPath);
1148
+ } else {
1149
+ log(\`No credentials for '\${stageName}' — using environment\`);
1150
+ }
1151
+ } else {
1152
+ log('No stage specified — using environment credentials');
1153
+ }
1154
+
1155
+ // Run CDK from the project directory so it finds cdk.json
1156
+ const cmd = buildCdkCommand(action, remainingArgs);
1157
+ const { status } = spawnSync(cmd[0], cmd.slice(1), {
1158
+ stdio: 'inherit',
1159
+ env: childEnv,
1160
+ cwd: projectPath,
1161
+ });
1162
+
1163
+ process.exit(status ?? 1);
1164
+ }
1165
+ "
1166
+ `;
1167
+
1168
+ exports[`infra generator > with enableStageConfig > should snapshot generated scripts src directory > packages/common/scripts/src/stage-credentials/stage-parser.ts 1`] = `
1169
+ "/**
1170
+ * Extracts the CDK stage name from the first positional argument.
1171
+ *
1172
+ * Examples:
1173
+ * parseStageName('my-app-dev/*') → 'my-app-dev'
1174
+ * parseStageName('my-app-dev') → 'my-app-dev'
1175
+ * parseStageName('--verbose') → undefined (flag, not a stage)
1176
+ * parseStageName(undefined) → undefined
1177
+ */
1178
+ export function parseStageName(
1179
+ firstArg: string | undefined,
1180
+ ): string | undefined {
1181
+ if (!firstArg || firstArg.startsWith('-')) return undefined;
1182
+ return firstArg.includes('/') ? firstArg.split('/')[0] : firstArg;
1183
+ }
1184
+ "
1185
+ `;
@@ -1,8 +1,23 @@
1
1
  import { ApplicationStage } from './stages/application-stage.js';
2
2
  import { App } from '<%= scopeAlias %>common-constructs';
3
-
3
+ <% if (enableStageConfig) { %>import { resolveStage } from '<%= scopeAlias %>common-infra-config';
4
+ <% } %>
4
5
  const app = new App();
6
+ <% if (enableStageConfig) { %>
7
+ // Stage configuration is defined in packages/common/infra-config/src/stages.config.ts
8
+ // The project path '<%= dir %>' is used as the key in the config.
9
+ // Project-specific settings override shared settings for the same stage name.
5
10
 
11
+ // Sandbox stage — uses your CLI credentials by default.
12
+ // Add an entry in stages.config.ts to configure specific credentials.
13
+ const sandboxConfig = resolveStage('<%= dir %>', '<%= namespace %>-sandbox');
14
+ new ApplicationStage(app, '<%= namespace %>-sandbox', {
15
+ env: {
16
+ account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
17
+ region: sandboxConfig?.region ?? process.env.CDK_DEFAULT_REGION,
18
+ },
19
+ });
20
+ <% } else { %>
6
21
  // Use this to deploy your own sandbox environment (assumes your CLI credentials)
7
22
  new ApplicationStage(app, '<%= namespace %>-sandbox', {
8
23
  env: {
@@ -10,5 +25,5 @@ new ApplicationStage(app, '<%= namespace %>-sandbox', {
10
25
  region: process.env.CDK_DEFAULT_REGION,
11
26
  },
12
27
  });
13
-
28
+ <% } %>
14
29
  app.synth();