@aws/nx-plugin-mcp 1.0.0-rc.9 → 1.0.0-rc.90

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 (200) hide show
  1. package/bin/aws-nx-mcp.js +14263 -13571
  2. package/docs/get_started/building-with-ai.mdx +116 -0
  3. package/docs/get_started/concepts.mdx +67 -0
  4. package/docs/get_started/existing-project.mdx +180 -0
  5. package/docs/get_started/graph-builder.mdx +39 -0
  6. package/docs/get_started/quick-start.mdx +277 -0
  7. package/docs/get_started/tutorials/contribute-generator.mdx +408 -0
  8. package/docs/get_started/tutorials/dungeon-game/1.mdx +1578 -0
  9. package/docs/get_started/tutorials/dungeon-game/2.mdx +245 -0
  10. package/docs/get_started/tutorials/dungeon-game/3.mdx +66 -0
  11. package/docs/get_started/tutorials/dungeon-game/4.mdx +164 -0
  12. package/docs/get_started/tutorials/dungeon-game/overview.mdx +145 -0
  13. package/docs/get_started/tutorials/dungeon-game/wrap-up.mdx +41 -0
  14. package/docs/get_started/upgrading.mdx +157 -0
  15. package/docs/guides/agentcore-gateway.mdx +490 -0
  16. package/docs/guides/agentcore-harness.mdx +312 -0
  17. package/docs/guides/astro-docs.mdx +8 -0
  18. package/docs/guides/connection/agentcore-gateway-agent.mdx +222 -0
  19. package/docs/guides/connection/agentcore-gateway-gateway.mdx +154 -0
  20. package/docs/guides/connection/agentcore-gateway-mcp.mdx +134 -0
  21. package/docs/guides/connection/py-agent-a2a.mdx +48 -16
  22. package/docs/guides/connection/py-agent-dynamodb.mdx +115 -0
  23. package/docs/guides/connection/py-agent-gateway.mdx +182 -0
  24. package/docs/guides/connection/py-agent-mcp.mdx +43 -14
  25. package/docs/guides/connection/py-agent-rdb.mdx +169 -0
  26. package/docs/guides/connection/py-fast-api-dynamodb.mdx +56 -0
  27. package/docs/guides/connection/py-fast-api-rdb.mdx +175 -0
  28. package/docs/guides/connection/py-mcp-server-dynamodb.mdx +115 -0
  29. package/docs/guides/connection/py-mcp-server-rdb.mdx +178 -0
  30. package/docs/guides/connection/react-agentcore-gateway.mdx +112 -0
  31. package/docs/guides/connection/react-agui.mdx +33 -14
  32. package/docs/guides/connection/react-fastapi.mdx +39 -3
  33. package/docs/guides/connection/react-py-agent.mdx +10 -16
  34. package/docs/guides/connection/react-smithy.mdx +4 -4
  35. package/docs/guides/connection/react-trpc.mdx +1 -1
  36. package/docs/guides/connection/react-ts-agent.mdx +9 -9
  37. package/docs/guides/connection/smithy-dynamodb.mdx +5 -5
  38. package/docs/guides/connection/smithy-rdb.mdx +9 -9
  39. package/docs/guides/connection/trpc-dynamodb.mdx +4 -4
  40. package/docs/guides/connection/trpc-rdb.mdx +5 -5
  41. package/docs/guides/connection/ts-agent-a2a.mdx +14 -11
  42. package/docs/guides/connection/ts-agent-dynamodb.mdx +35 -36
  43. package/docs/guides/connection/ts-agent-gateway.mdx +147 -0
  44. package/docs/guides/connection/ts-agent-mcp.mdx +12 -9
  45. package/docs/guides/connection/ts-agent-rdb.mdx +61 -25
  46. package/docs/guides/connection/ts-mcp-server-dynamodb.mdx +35 -36
  47. package/docs/guides/connection/ts-mcp-server-rdb.mdx +59 -18
  48. package/docs/guides/connection.mdx +122 -5
  49. package/docs/guides/docker-bundling.mdx +82 -14
  50. package/docs/guides/fastapi.mdx +253 -12
  51. package/docs/guides/local-development.mdx +87 -0
  52. package/docs/guides/nx-generator.mdx +4 -3
  53. package/docs/guides/nx-migration.mdx +165 -0
  54. package/docs/guides/py-agent.mdx +332 -55
  55. package/docs/guides/py-dynamodb.mdx +476 -0
  56. package/docs/guides/py-mcp-server.mdx +57 -2
  57. package/docs/guides/py-rdb.mdx +269 -0
  58. package/docs/guides/python-lambda-function.mdx +1 -1
  59. package/docs/guides/python-project.mdx +31 -0
  60. package/docs/guides/react-website-auth.mdx +104 -5
  61. package/docs/guides/react-website.mdx +409 -95
  62. package/docs/guides/runtime-config.mdx +17 -4
  63. package/docs/guides/security.mdx +75 -0
  64. package/docs/guides/smithy-project.mdx +167 -0
  65. package/docs/guides/terraform-project.mdx +119 -8
  66. package/docs/guides/trpc.mdx +55 -14
  67. package/docs/guides/ts-agent.mdx +207 -23
  68. package/docs/guides/ts-dcr-proxy.mdx +569 -0
  69. package/docs/guides/ts-dynamodb.mdx +66 -242
  70. package/docs/guides/ts-lambda-function.mdx +1 -1
  71. package/docs/guides/ts-mcp-server.mdx +111 -29
  72. package/docs/guides/ts-nx-plugin.mdx +4 -4
  73. package/docs/guides/ts-rdb.mdx +116 -466
  74. package/docs/guides/ts-smithy-api.mdx +260 -16
  75. package/docs/guides/typescript-infrastructure.mdx +79 -25
  76. package/docs/guides/typescript-project.mdx +157 -24
  77. package/docs/guides/workspace.mdx +31 -2
  78. package/docs/snippets/agent/architecture.mdx +1 -1
  79. package/docs/snippets/agent/bedrock-deployment.mdx +9 -5
  80. package/docs/snippets/agent/runtime-arn.mdx +23 -2
  81. package/docs/snippets/agent/securing-your-agent.mdx +39 -0
  82. package/docs/snippets/api/access-logging.mdx +38 -0
  83. package/docs/snippets/api/cors-configuration-cdk-note.mdx +1 -1
  84. package/docs/snippets/api/cors-configuration-terraform-note.mdx +1 -1
  85. package/docs/snippets/api/type-safe-api-integrations.mdx +218 -373
  86. package/docs/snippets/api/waf-configuration.mdx +3 -3
  87. package/docs/snippets/connection/a2a-infrastructure.mdx +1 -1
  88. package/docs/snippets/connection/dynamodb-local-development.mdx +2 -2
  89. package/docs/snippets/connection/lambda-dynamodb-access.mdx +2 -2
  90. package/docs/snippets/connection/py-dynamodb-local-development.mdx +7 -0
  91. package/docs/snippets/connection/py-lambda-rdb-ssl-requirements.mdx +7 -0
  92. package/docs/snippets/connection/rdb-api-infrastructure.mdx +42 -19
  93. package/docs/snippets/dynamodb/deploying-table.mdx +176 -0
  94. package/docs/snippets/dynamodb/encryption-options.mdx +168 -0
  95. package/docs/snippets/dynamodb/gsi-config.mdx +38 -0
  96. package/docs/snippets/dynamodb/infrastructure.mdx +33 -0
  97. package/docs/snippets/dynamodb/local-dev-start.mdx +13 -0
  98. package/docs/snippets/dynamodb/local-dev-windows.mdx +15 -0
  99. package/docs/snippets/experimental-generator.mdx +8 -0
  100. package/docs/snippets/lambda-function/deploying-your-function.mdx +3 -3
  101. package/docs/snippets/mcp/architecture.mdx +1 -1
  102. package/docs/snippets/mcp/bedrock-deployment.mdx +9 -5
  103. package/docs/snippets/mcp/config.mdx +3 -2
  104. package/docs/snippets/mcp/shared-constructs.mdx +4 -5
  105. package/docs/snippets/pdk-migration/example/01-migrate-api.mdx +7 -5
  106. package/docs/snippets/pdk-migration/example/02-migrate-website.mdx +29 -10
  107. package/docs/snippets/pdk-migration/example/03-migrate-infra.mdx +4 -4
  108. package/docs/snippets/pdk-migration/faq/type-safe-api.mdx +5 -111
  109. package/docs/snippets/prerequisites.mdx +1 -4
  110. package/docs/snippets/rdb/admin-credentials.mdx +42 -0
  111. package/docs/snippets/rdb/architecture.mdx +39 -0
  112. package/docs/snippets/rdb/cluster-instances.mdx +31 -0
  113. package/docs/snippets/rdb/deletion-protection.mdx +64 -0
  114. package/docs/snippets/rdb/deploying.mdx +178 -0
  115. package/docs/snippets/rdb/encryption-key-rotation.mdx +30 -0
  116. package/docs/snippets/rdb/engine-version.mdx +63 -0
  117. package/docs/snippets/rdb/infrastructure.mdx +35 -0
  118. package/docs/snippets/rdb/logging-mysql.mdx +5 -0
  119. package/docs/snippets/rdb/logging-postgres.mdx +5 -0
  120. package/docs/snippets/rdb/performance-insights.mdx +36 -0
  121. package/docs/snippets/rdb/rds-proxy.mdx +50 -0
  122. package/docs/snippets/rdb/removal-policy.mdx +57 -0
  123. package/docs/snippets/rdb/serverless-capacity.mdx +32 -0
  124. package/docs/snippets/recommended-prerequisites.mdx +10 -0
  125. package/docs/snippets/required-prerequisites.mdx +1 -4
  126. package/docs/snippets/runtime-config-app-id-note.mdx +8 -0
  127. package/docs/snippets/shared-constructs.mdx +1 -1
  128. package/docs/snippets/trivy-image-scan.mdx +37 -0
  129. package/generators.json +170 -10
  130. package/package.json +1 -1
  131. package/src/agentcore-gateway/agent-connection/schema.json +31 -0
  132. package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
  133. package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
  134. package/src/agentcore-gateway/react-connection/schema.json +31 -0
  135. package/src/agentcore-gateway/schema.json +72 -0
  136. package/src/agentcore-harness/schema.json +53 -0
  137. package/src/connection/schema.json +5 -0
  138. package/src/infra/app/schema.json +5 -0
  139. package/src/init/schema.json +35 -0
  140. package/src/internal/test-matrix/schema.json +21 -0
  141. package/src/license/schema.json +5 -0
  142. package/src/open-api/json-metadata/schema.json +20 -0
  143. package/src/preset/schema.json +16 -5
  144. package/src/py/agent/a2a-connection/schema.json +5 -0
  145. package/src/py/agent/gateway-connection/schema.json +31 -0
  146. package/src/py/agent/mcp-connection/schema.json +5 -0
  147. package/src/py/agent/react-connection/schema.json +5 -0
  148. package/src/py/agent/schema.json +15 -1
  149. package/src/py/api/schema.json +5 -0
  150. package/src/py/dynamodb/agent-connection/schema.json +27 -0
  151. package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
  152. package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
  153. package/src/py/dynamodb/schema.json +76 -0
  154. package/src/py/fast-api/react/schema.json +5 -0
  155. package/src/py/fast-api/schema.json +6 -0
  156. package/src/py/lambda-function/schema.json +6 -1
  157. package/src/py/mcp-server/schema.json +6 -0
  158. package/src/py/project/schema.json +6 -0
  159. package/src/py/rdb/agent-connection/schema.json +27 -0
  160. package/src/py/rdb/fast-api-connection/schema.json +23 -0
  161. package/src/py/rdb/mcp-server-connection/schema.json +27 -0
  162. package/src/py/rdb/schema.json +78 -0
  163. package/src/smithy/project/schema.json +28 -1
  164. package/src/smithy/react-connection/schema.json +5 -0
  165. package/src/smithy/ts/api/schema.json +6 -0
  166. package/src/terraform/project/schema.json +5 -0
  167. package/src/trpc/backend/schema.json +6 -0
  168. package/src/trpc/react/schema.json +5 -0
  169. package/src/ts/agent/a2a-connection/schema.json +5 -0
  170. package/src/ts/agent/gateway-connection/schema.json +31 -0
  171. package/src/ts/agent/mcp-connection/schema.json +5 -0
  172. package/src/ts/agent/react-connection/schema.json +5 -0
  173. package/src/ts/agent/schema.json +14 -0
  174. package/src/ts/api/schema.json +5 -0
  175. package/src/ts/astro-docs/schema.json +3 -3
  176. package/src/ts/dcr-proxy/schema.json +44 -0
  177. package/src/ts/docs/schema.json +3 -3
  178. package/src/ts/dynamodb/agent-connection/schema.json +5 -0
  179. package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
  180. package/src/ts/dynamodb/schema.json +26 -2
  181. package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
  182. package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
  183. package/src/ts/lambda-function/schema.json +5 -0
  184. package/src/ts/lib/schema.json +5 -0
  185. package/src/ts/mcp-server/schema.json +6 -0
  186. package/src/ts/nx-generator/schema.json +5 -0
  187. package/src/ts/nx-migration/schema.json +63 -0
  188. package/src/ts/nx-plugin/schema.json +5 -0
  189. package/src/ts/rdb/agent-connection/schema.json +5 -0
  190. package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
  191. package/src/ts/rdb/schema.json +7 -1
  192. package/src/ts/rdb/smithy-connection/schema.json +5 -0
  193. package/src/ts/rdb/trpc-connection/schema.json +5 -0
  194. package/src/ts/react-website/app/schema.json +12 -6
  195. package/src/ts/react-website/cognito-auth/schema.json +5 -0
  196. package/src/ts/react-website/runtime-config/schema.json +5 -0
  197. package/src/ts/website/app/schema.json +11 -6
  198. package/src/ts/website/auth/schema.json +5 -0
  199. /package/docs/snippets/connection/{lambda-rdb-ssl-requirements.mdx → ts-lambda-rdb-ssl-requirements.mdx} +0 -0
  200. /package/docs/snippets/connection/{mcp-server-rdb-ssl-requirements.mdx → ts-mcp-server-rdb-ssl-requirements.mdx} +0 -0
@@ -7,7 +7,9 @@ when:
7
7
  infra: [rest-lambda]
8
8
  ---
9
9
 
10
- import { FileTree } from '@astrojs/starlight/components';
10
+ import { FileTree, CardGrid } from '@astrojs/starlight/components';
11
+ import Astro from '@astrojs/react';
12
+ import ConnectionCard from '@components/connection-card.astro';
11
13
  import Link from '@components/link.astro';
12
14
  import RunGenerator from '@components/run-generator.astro';
13
15
  import GeneratorParameters from '@components/generator-parameters.astro';
@@ -44,9 +46,10 @@ The generator creates two related projects in the `<directory>/<api-name>` direc
44
46
  <FileTree>
45
47
 
46
48
  - **model/** Smithy model project
49
+ - package.json Project manifest defining the project's package name and dependencies
47
50
  - project.json Project configuration and build targets
48
51
  - smithy-build.json Smithy build configuration
49
- - build.Dockerfile Docker configuration for building Smithy artifacts
52
+ - ssdk.rolldown.config.mjs Bundles the generated TypeScript Server SDK
50
53
  - src/
51
54
  - main.smithy Main service definition
52
55
  - operations/
@@ -67,7 +70,7 @@ The generator creates two related projects in the `<directory>/<api-name>` direc
67
70
 
68
71
  ### Infrastructure
69
72
 
70
- Since this generator creates infrastructure as code based on your chosen `iacProvider`, it will create a project in `packages/common` which includes the relevant CDK constructs or Terraform modules.
73
+ Since this generator creates infrastructure as code based on your chosen `iac`, it will create a project in `packages/common` which includes the relevant CDK constructs or Terraform modules.
71
74
 
72
75
  The common infrastructure as code project is structured as follows:
73
76
 
@@ -221,6 +224,31 @@ You can change the folder structure however you like - all `.smithy` files in th
221
224
  For more details on Smithy and its syntax, refer to the [Smithy specification](https://smithy.io/2.0/spec/index.html).
222
225
  :::
223
226
 
227
+ ### Adding a Shape Library
228
+
229
+ If you have several Smithy APIs which share the same data types, you can define those types once in a shape library rather than duplicating them in each model. A shape library is a Smithy project with no service — just reusable shapes — which any number of Smithy projects can depend on.
230
+
231
+ Generate one with the <Link path="guides/smithy-project">`smithy#project`</Link> generator:
232
+
233
+ <RunGenerator generator="smithy#project" requiredParameters={{ name: 'my-shapes', type: 'shapes' }} />
234
+
235
+ Your API's model can then reference its shapes with `use`:
236
+
237
+ ```smithy
238
+ $version: "2.0"
239
+
240
+ namespace com.example.api
241
+
242
+ use com.example.shared#Customer
243
+
244
+ structure GetCustomerOutput {
245
+ @required
246
+ customer: Customer
247
+ }
248
+ ```
249
+
250
+ See the <Link path="guides/smithy-project">Smithy project guide</Link> for how to create a shape library and wire it up as a dependency of your API's model.
251
+
224
252
  ### Implementing Operations in TypeScript
225
253
 
226
254
  Operation implementations are located in the backend project's `src/operations/` directory. Each operation is implemented using the generated types from the TypeScript Server SDK (generated at build time from your Smithy model).
@@ -280,7 +308,7 @@ You must construct the context yourself in both `handler.ts` (the Lambda functio
280
308
 
281
309
  The generator configures structured logging using AWS Lambda Powertools with automatic context injection via Middy middleware.
282
310
 
283
- ```typescript {4}
311
+ ```typescript {3}
284
312
  // handler.ts
285
313
  export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
286
314
  .use(captureLambdaHandler(tracer))
@@ -291,7 +319,7 @@ export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
291
319
 
292
320
  You can reference the logger from your operation implementations via the context:
293
321
 
294
- ```typescript {6}
322
+ ```typescript {5}
295
323
  // operations/echo.ts
296
324
  import { ServiceContext } from '../context.js';
297
325
  import { Echo as EchoOperation } from '../generated/ssdk/index.js';
@@ -306,7 +334,7 @@ export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
306
334
 
307
335
  AWS X-Ray tracing is configured automatically via the `captureLambdaHandler` middleware.
308
336
 
309
- ```typescript {3}
337
+ ```typescript {2}
310
338
  // handler.ts
311
339
  export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
312
340
  .use(captureLambdaHandler(tracer))
@@ -317,7 +345,7 @@ export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
317
345
 
318
346
  You can add custom subsegments to your traces in your operations:
319
347
 
320
- ```typescript {7, 11, 14}
348
+ ```typescript {6, 10, 13}
321
349
  // operations/echo.ts
322
350
  import { ServiceContext } from '../context.js';
323
351
  import { Echo as EchoOperation } from '../generated/ssdk/index.js';
@@ -340,7 +368,7 @@ export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
340
368
 
341
369
  CloudWatch metrics are collected automatically for each request via the `logMetrics` middleware.
342
370
 
343
- ```typescript {5}
371
+ ```typescript {4}
344
372
  // handler.ts
345
373
  export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
346
374
  .use(captureLambdaHandler(tracer))
@@ -351,7 +379,7 @@ export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
351
379
 
352
380
  You can add custom metrics in your operations:
353
381
 
354
- ```typescript {7}
382
+ ```typescript {6}
355
383
  // operations/echo.ts
356
384
  import { MetricUnit } from '@aws-lambda-powertools/metrics';
357
385
  import { ServiceContext } from '../context.js';
@@ -401,12 +429,159 @@ export const MyOperation: MyOperationHandler<ServiceContext> = async (input) =>
401
429
  };
402
430
  ```
403
431
 
432
+ ### Accessing the Calling User
433
+
434
+ When your API is protected by authentication, your operations often need to know who is calling. The recommended approach is to resolve the caller's identity once in the handler and pass it through the [service context](#service-context) for consumption by specific operations.
435
+
436
+ We'll model the unauthorized case as a Smithy error so it serializes to a proper `403` response. Add it to your model, for example in `model/src/operations/errors.smithy`, and reference it on any operation that requires identity:
437
+
438
+ ```smithy
439
+ $version: "2.0"
440
+
441
+ namespace your.namespace
442
+
443
+ /// Thrown when the calling user cannot be determined
444
+ @error("client")
445
+ @httpError(403)
446
+ structure UnauthorizedError {
447
+ @required
448
+ message: String
449
+ }
450
+ ```
451
+
452
+ First, expose the resolved identity on the service context in `src/context.ts`. We provide it as a function so that the `UnauthorizedError` is thrown from within an operation (where the Server SDK serializes it to a `403`), rather than from the handler:
453
+
454
+ ```ts {5-8,17} ins={5-8,17}
455
+ import { Logger } from '@aws-lambda-powertools/logger';
456
+ import { Metrics } from '@aws-lambda-powertools/metrics';
457
+ import { Tracer } from '@aws-lambda-powertools/tracer';
458
+
459
+ export interface Identity {
460
+ sub: string;
461
+ username: string;
462
+ }
463
+
464
+ /**
465
+ * Context provided to all operations.
466
+ */
467
+ export interface ServiceContext {
468
+ tracer: Tracer;
469
+ logger: Logger;
470
+ metrics: Metrics;
471
+ getIdentity: () => Promise<Identity>;
472
+ }
473
+ ```
474
+
475
+ Next, write the resolver in `src/identity.ts`. It throws `UnauthorizedError` when the caller cannot be determined. The implementation depends on your selected `auth` method:
476
+
477
+ <OptionFilter when={{ auth: 'iam' }} description="Identity resolution for IAM-authenticated APIs">
478
+ For `IAM` authentication, we look up the caller in Cognito using the sub extracted from the API Gateway event:
479
+
480
+ ```ts
481
+ import { CognitoIdentityProvider } from '@aws-sdk/client-cognito-identity-provider';
482
+ import type { APIGatewayProxyEvent } from 'aws-lambda';
483
+ import { Identity } from './context.js';
484
+ import { UnauthorizedError } from './generated/ssdk/index.js';
485
+
486
+ const cognito = new CognitoIdentityProvider();
487
+
488
+ export const getIdentity = async (
489
+ event: APIGatewayProxyEvent,
490
+ ): Promise<Identity> => {
491
+ const cognitoAuthenticationProvider =
492
+ event.requestContext?.identity?.cognitoAuthenticationProvider;
493
+
494
+ let sub: string | undefined = undefined;
495
+ if (cognitoAuthenticationProvider) {
496
+ const providerParts = cognitoAuthenticationProvider.split(':');
497
+ sub = providerParts[providerParts.length - 1];
498
+ }
499
+
500
+ if (!sub) {
501
+ throw new UnauthorizedError({ message: 'Unable to determine calling user' });
502
+ }
503
+
504
+ const { Users } = await cognito.listUsers({
505
+ // Assumes user pool id is configured in lambda environment
506
+ UserPoolId: process.env.USER_POOL_ID!,
507
+ Limit: 1,
508
+ Filter: `sub="${sub}"`,
509
+ });
510
+
511
+ if (!Users || Users.length !== 1) {
512
+ throw new UnauthorizedError({ message: `No user found with subjectId ${sub}` });
513
+ }
514
+
515
+ return { sub, username: Users[0].Username! };
516
+ };
517
+ ```
518
+ </OptionFilter>
519
+
520
+ <OptionFilter when={{ auth: 'cognito' }} description="Identity resolution for Cognito-authenticated APIs">
521
+ With `auth: 'cognito'`, the API Gateway Cognito User Pools authorizer verifies the JWT that the caller supplies in the `Authorization` header and places the verified claims on the event at `event.requestContext.authorizer.claims`:
522
+
523
+ ```ts
524
+ import type { APIGatewayProxyEvent } from 'aws-lambda';
525
+ import { Identity } from './context.js';
526
+ import { UnauthorizedError } from './generated/ssdk/index.js';
527
+
528
+ export const getIdentity = async (
529
+ event: APIGatewayProxyEvent,
530
+ ): Promise<Identity> => {
531
+ const claims = event.requestContext?.authorizer?.claims as
532
+ | Record<string, string>
533
+ | undefined;
534
+
535
+ const sub = claims?.sub;
536
+ const username = claims?.username;
537
+
538
+ if (!sub || !username) {
539
+ throw new UnauthorizedError({ message: 'Unable to determine calling user' });
540
+ }
541
+
542
+ return { sub, username };
543
+ };
544
+ ```
545
+
546
+ :::tip[No token verification required]
547
+ You don't need `aws-jwt-verify` or any other JWT-verification library here — the API Gateway Cognito User Pools authorizer has already verified the signature, issuer, scopes, and expiry by the time your Lambda runs. If any of those checks fail, API Gateway returns `401 Unauthorized` and your handler is never invoked.
548
+ :::
549
+ </OptionFilter>
550
+
551
+ Then wire the resolver into the context in `src/handler.ts`:
552
+
553
+ ```ts {2,8} ins={2,8}
554
+ import { Service } from './service.js';
555
+ import { getIdentity } from './identity.js';
556
+ // ...
557
+ const httpResponse = await serviceHandler.handle(httpRequest, {
558
+ tracer,
559
+ logger,
560
+ metrics,
561
+ getIdentity: () => getIdentity(event),
562
+ });
563
+ ```
564
+
565
+ We can now use the resolved identity in an operation, for example in `src/operations/echo.ts`:
566
+
567
+ ```ts
568
+ import { ServiceContext } from '../context.js';
569
+ import { Echo as EchoOperation } from '../generated/ssdk/index.js';
570
+
571
+ export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
572
+ const identity = await ctx.getIdentity();
573
+ return { message: `${identity.username} says ${input.message}` };
574
+ };
575
+ ```
576
+
404
577
  ## Building and Code Generation
405
578
 
406
- The Smithy model project uses [Docker](https://www.docker.com/) to build the Smithy artifacts and generate the TypeScript Server SDK:
579
+ The Smithy model project uses the [Smithy CLI](https://smithy.io/2.0/guides/smithy-cli/index.html) to build the Smithy artifacts and generate the TypeScript Server SDK:
407
580
 
408
581
  <NxCommands commands={['build <model-project>']} />
409
582
 
583
+ On macOS and Linux the CLI is resolved by [mise](https://mise.jdx.dev/), which the build fetches on demand, so there is nothing to install — it downloads and caches the pinned version the first time you build.
584
+
410
585
  This process:
411
586
 
412
587
  1. **Compiles the Smithy model** and validates it
@@ -418,6 +593,39 @@ The backend project automatically copies the generated SDK during compilation:
418
593
 
419
594
  <NxCommands commands={['copy-ssdk <backend-project>']} />
420
595
 
596
+ ### Building on Windows
597
+
598
+ `mise` publishes no Windows package to npm, so on Windows the Smithy CLI is a prerequisite you install yourself. Install it once following the [Smithy CLI installation guide](https://smithy.io/2.0/guides/smithy-cli/cli_installation.html) (for example `winget install smithy` or `scoop install smithy`), and make sure `smithy` is on your `PATH`. A Smithy project generated on Windows runs `smithy` directly rather than through `mise`.
599
+
600
+ :::caution[Upgrading the CLI]
601
+ Because the CLI is installed globally rather than pinned in your workspace, upgrading the workspace with `nx migrate` does **not** upgrade it. When a migration moves the Smithy dependencies forward, upgrade your global Smithy CLI to a matching version yourself.
602
+ :::
603
+
604
+ Alternatively, develop inside [WSL](https://learn.microsoft.com/en-us/windows/wsl/install), where the build runs the Linux path and `mise` resolves the CLI for you — nothing to install.
605
+
606
+ A project generated on Windows commits a `compile` target that invokes `smithy` directly, so anyone else working on it — including on macOS or Linux — needs the Smithy CLI on their `PATH` too. To have those machines resolve the CLI through `mise` instead, switch the target to the `mise` command as [described below](#choosing-how-the-cli-is-resolved).
607
+
608
+ ### Choosing how the CLI is resolved
609
+
610
+ macOS and Linux resolve the CLI through `mise` and Windows uses a globally installed CLI, but you can pick either on any platform by editing the `compile` target's command in the model project's `project.json`.
611
+
612
+ To use a globally installed Smithy CLI instead of `mise`, replace the `mise` prefix with a bare `smithy`:
613
+
614
+ ```json title="project.json" del={5} ins={6}
615
+ {
616
+ "targets": {
617
+ "compile": {
618
+ "options": {
619
+ "commands": ["... npx -y mise@<version> exec smithy@<version> -- smithy build ..."]
620
+ "commands": ["... smithy build ..."]
621
+ }
622
+ }
623
+ }
624
+ }
625
+ ```
626
+
627
+ To go back to `mise` resolving the CLI, restore the `npx -y mise@<version> exec smithy@<version> --` prefix.
628
+
421
629
  ### Bundle Target
422
630
 
423
631
  <Snippet name="ts-bundle" />
@@ -434,14 +642,14 @@ The local server will not only hot-reload when you make TypeScript changes to yo
434
642
 
435
643
  ## Deploying your Smithy API
436
644
 
437
- The generator creates CDK or Terraform infrastructure based on your selected `iacProvider`.
645
+ The generator creates CDK or Terraform infrastructure based on your selected `iac`.
438
646
 
439
647
  <Infrastructure>
440
648
  <Fragment slot="cdk">
441
649
  The CDK construct for deploying your API is in the `common/constructs` folder:
442
650
 
443
651
  ```ts {6-8}
444
- import { MyApi } from ':my-scope/common-constructs';
652
+ import { MyApi } from '@my-scope/common-constructs';
445
653
 
446
654
  export class ExampleStack extends Stack {
447
655
  constructor(scope: Construct, id: string) {
@@ -468,7 +676,7 @@ This sets up:
468
676
  If you selected `Cognito` authentication, you will need to supply the `identity` property to the API construct:
469
677
 
470
678
  ```ts {9}
471
- import { MyApi, UserIdentity } from ':my-scope/common-constructs';
679
+ import { MyApi, UserIdentity } from '@my-scope/common-constructs';
472
680
 
473
681
  export class ExampleStack extends Stack {
474
682
  constructor(scope: Construct, id: string) {
@@ -489,6 +697,8 @@ The `UserIdentity` construct can be generated using the <Link path="/guides/reac
489
697
  <OptionFilter when={{ auth: 'custom' }} description="Custom Lambda Authorizer CDK usage">
490
698
  :::caution[Custom Lambda Authorizer]
491
699
  When using `Custom` auth, the construct creates a Lambda Authorizer internally from the generated `src/authorizer.ts` file, which **denies all requests by default**. You must implement your authorization logic in that file before your API will accept any traffic.
700
+
701
+ Authorizer results are cached for 5 minutes, keyed on the `Authorization` header, so a revoked token may be accepted until its cached result expires. Reduce the cache duration in the generated infrastructure if you need faster revocation.
492
702
  :::
493
703
  </OptionFilter>
494
704
  </Fragment>
@@ -537,7 +747,7 @@ This sets up:
537
747
  :::note[Cognito Authentication]
538
748
  If you selected `Cognito` authentication, you will need to supply the Cognito configuration:
539
749
 
540
- ```hcl {3, 5-6}
750
+ ```hcl {6-7}
541
751
  module "my_api" {
542
752
  source = "../../common/terraform/src/app/apis/my-api"
543
753
 
@@ -560,6 +770,8 @@ module "my_api" {
560
770
  <OptionFilter when={{ auth: 'custom' }} description="Custom Lambda Authorizer usage with Terraform">
561
771
  :::caution[Custom Lambda Authorizer]
562
772
  When using `Custom` auth, your API is protected by a Lambda Authorizer that **denies all requests by default**. You must implement your authorization logic in the generated `src/authorizer.ts` file before your API will accept any traffic.
773
+
774
+ Authorizer results are cached for 5 minutes, keyed on the `Authorization` header, so a revoked token may be accepted until its cached result expires. Reduce the cache duration in the generated infrastructure if you need faster revocation.
563
775
  :::
564
776
  </OptionFilter>
565
777
 
@@ -583,6 +795,10 @@ output "lambda_function_name" {
583
795
 
584
796
  <Snippet name="api/waf-configuration" parentHeading="WAF" />
585
797
 
798
+ ### Access logging
799
+
800
+ <Snippet name="api/access-logging" parentHeading="Access logging" />
801
+
586
802
  ### Integrations
587
803
 
588
804
  <Snippet name="api/type-safe-api-integrations" parentHeading="Integrations" />
@@ -607,14 +823,14 @@ If you are actively working on both your CDK infrastructure and Smithy API toget
607
823
  <NxCommands
608
824
  commands={[
609
825
  'watch --projects=<ModelProject> -- \\ ',
610
- 'run <InfraProject>:"generate:<ApiName>-metadata"',
826
+ 'run @<scope>/common-constructs:"generate:<ApiName>-metadata"',
611
827
  ]}
612
828
  />
613
829
  :::
614
830
  </Fragment>
615
831
  <Fragment slot="terraform">
616
832
  :::note[Terraform Limitations]
617
- We do not support type-safe integrations for Terraform, and therefore no code generation targets are configured if you selected Terraform for your `iacProvider`.
833
+ We do not support type-safe integrations for Terraform, and therefore no code generation targets are configured if you selected Terraform for your `iac`.
618
834
  :::
619
835
  </Fragment>
620
836
  </Infrastructure>
@@ -662,3 +878,31 @@ resource "aws_iam_role_policy_attachment" "api_invoke_access" {
662
878
  ## Invoking your Smithy API
663
879
 
664
880
  To invoke your API from a React website, you can use the <Link path="guides/connection/react-smithy">`connection`</Link> generator, which provides type-safe client generation from your Smithy model.
881
+
882
+ ## Connections
883
+
884
+ Use the <Link path="guides/connection">`connection`</Link> generator to integrate this project with others in your workspace. The following connections involve this project:
885
+
886
+ <CardGrid>
887
+ <ConnectionCard
888
+ title="React to Smithy API"
889
+ description="Call a Smithy API from a React website"
890
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/react-smithy`}
891
+ source="react"
892
+ target="smithy"
893
+ />
894
+ <ConnectionCard
895
+ title="Smithy API to Relational Database"
896
+ description="Connect a Smithy API to an Aurora relational database"
897
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/smithy-rdb`}
898
+ source="smithy"
899
+ target="aurora"
900
+ />
901
+ <ConnectionCard
902
+ title="Smithy API to TypeScript DynamoDB"
903
+ description="Connect a Smithy API to a DynamoDB table"
904
+ href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/smithy-dynamodb`}
905
+ source="smithy"
906
+ target="dynamodb"
907
+ />
908
+ </CardGrid>
@@ -38,12 +38,13 @@ The generator will create the following project structure in the `<directory>/<n
38
38
  - stacks CDK Stack definitions
39
39
  - application-stack.ts Main application stack
40
40
  - cdk.json CDK configuration
41
+ - package.json Project manifest defining the project's package name and dependencies
41
42
  - project.json Project configuration and build targets
42
43
  - checkov.yml Checkov configuration file
43
44
 
44
45
  </FileTree>
45
46
 
46
- If you set the `enableStageConfig` option, the generator also creates two shared packages for centralized credential management (if they don't already exist):
47
+ If you set the `stageConfig` option, the generator also creates two shared packages for centralized credential management (if they don't already exist):
47
48
 
48
49
  <FileTree>
49
50
 
@@ -95,17 +96,22 @@ new ApplicationStage(app, 'my-app-sandbox', {
95
96
  region: process.env.CDK_DEFAULT_REGION,
96
97
  },
97
98
  });
99
+
100
+ // Define other instances of stages, such as beta and prod, below
98
101
  ```
99
102
 
100
103
  The `env` property tells CDK which AWS account and region to deploy to. `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION` are resolved automatically by the CDK CLI from your active AWS credentials. See the [CDK environments documentation](https://docs.aws.amazon.com/cdk/v2/guide/environments.html) for more details.
101
104
 
102
- If you generated with `enableStageConfig`, the `main.ts` reads account and region from a centralized config file instead, falling back to environment variables when no config is set:
105
+ The sandbox stage is the one the <Link path="guides/typescript-infrastructure#deploying-your-sandbox-stage">`deploy-sandbox`</Link> and <Link path="guides/typescript-infrastructure#tearing-down-your-sandbox-stage">`destroy-sandbox`</Link> targets act on.
106
+
107
+ If you generated with `stageConfig`, the `main.ts` reads account and region from a centralized config file instead, falling back to environment variables when no config is set:
103
108
 
104
- ```ts title="src/main.ts (with enableStageConfig)"
105
- import stagesConfig from ':my-scope/common-infra-config';
109
+ ```ts title="src/main.ts (with stageConfig)"
110
+ import { resolveStage } from '@my-scope/common-infra-config';
106
111
 
107
- const projectStages = stagesConfig.projects?.['packages/infra']?.stages ?? {};
108
- const sandboxConfig = projectStages['my-app-sandbox'];
112
+ // Looks up the stage under this project (packages/infra), falling back to
113
+ // shared stages. Returns undefined when no config exists for the stage.
114
+ const sandboxConfig = resolveStage('packages/infra', 'my-app-sandbox');
109
115
 
110
116
  new ApplicationStage(app, 'my-app-sandbox', {
111
117
  env: {
@@ -158,12 +164,12 @@ export class ApplicationStage extends Stage {
158
164
  ### Stage Credential Configuration
159
165
 
160
166
  :::note[Staged Configuration]
161
- This section applies when you generate with `enableStageConfig`. Without it, the generator produces a simpler setup where you manage AWS credentials yourself (e.g., by exporting `AWS_PROFILE` before deploying).
167
+ This section applies when you generate with `stageConfig`. Without it, the generator produces a simpler setup where you manage AWS credentials yourself (e.g., by exporting `AWS_PROFILE` before deploying).
162
168
  :::
163
169
 
164
170
  When you have multiple stages targeting different AWS accounts, managing credentials manually can be error-prone, especially as the number of stages grows.
165
171
 
166
- The `enableStageConfig` option solves this by generating two shared packages:
172
+ The `stageConfig` option solves this by generating two shared packages:
167
173
 
168
174
  - **`packages/common/infra-config`** — A single config file where you map each stage to its AWS credentials, account, and region. This is importable from any package in your workspace, so your CDK `main.ts` can read account and region from the same source of truth.
169
175
  - **`packages/common/scripts`** — `infra-deploy` and `infra-destroy` commands that wrap CDK with automatic credential resolution. When you run `deploy`, the script reads the config, sets the right AWS environment variables for the CDK child process, and runs `cdk deploy`. Your shell environment is never modified.
@@ -242,7 +248,7 @@ Each stage config includes a required `region` and an optional `account`:
242
248
  The generated `main.ts` reads these values from the config so that CDK synthesis and deployment use the same environment settings:
243
249
 
244
250
  ```ts title="src/main.ts"
245
- const sandboxConfig = projectStages['my-app-sandbox'];
251
+ const sandboxConfig = resolveStage('packages/infra', 'my-app-sandbox');
246
252
  new ApplicationStage(app, 'my-app-sandbox', {
247
253
  env: {
248
254
  account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
@@ -270,7 +276,7 @@ If, for example, you created a tRPC API called `my-api`, you can simply import a
270
276
  ```ts title="src/stacks/application-stack.ts" {3, 9-12}
271
277
  import { Stack, StackProps } from 'aws-cdk-lib';
272
278
  import { Construct } from 'constructs';
273
- import { MyApi } from ':my-scope/common-constructs';
279
+ import { MyApi } from '@my-scope/common-constructs';
274
280
 
275
281
  export class ApplicationStack extends Stack {
276
282
  constructor(scope: Construct, id: string, props?: StackProps) {
@@ -286,12 +292,12 @@ export class ApplicationStack extends Stack {
286
292
 
287
293
  ### Website Infrastructure
288
294
 
289
- If you have used the <Link path="guides/react-website">CloudScape website</Link> generator, you will notice you already have a construct in `packages/common/constructs` to deploy it. For example:
295
+ If you have used the <Link path="guides/react-website">React Website</Link> generator, you will notice you already have a construct in `packages/common/constructs` to deploy it. For example:
290
296
 
291
297
  ```ts title="src/stacks/application-stack.ts" {3, 9-10}
292
298
  import { Stack, StackProps } from 'aws-cdk-lib';
293
299
  import { Construct } from 'constructs';
294
- import { MyWebsite } from ':my-scope/common-constructs';
300
+ import { MyWebsite } from '@my-scope/common-constructs';
295
301
 
296
302
  export class ApplicationStack extends Stack {
297
303
  constructor(scope: Construct, id: string, props?: StackProps) {
@@ -315,6 +321,8 @@ As part of your `build` target, as well as running the <Link path="guides/typesc
315
321
 
316
322
  You will find your synthesized cloud assembly in the root `dist` folder, under `dist/packages/<my-infra-project>/cdk.out`.
317
323
 
324
+ `synth` depends on `^assemble`, so synthesizing builds the artifacts your stacks deploy, such as the Lambda bundles, container images and generated specifications, without running every upstream project's lint, test and type-check gates. See <Link path="guides/typescript-project#assembling">Assembling</Link> for more detail on `assemble`.
325
+
318
326
  ## Security Testing
319
327
 
320
328
  A `checkov` target is added to your project which runs security checks on your infrastructure using [Checkov](https://www.checkov.io/).
@@ -338,7 +346,7 @@ There may be instances where you want to suppress certain rules on resources. Yo
338
346
  #### Supress a rule on a given construct
339
347
 
340
348
  ```typescript
341
- import { suppressRules } from ':my-scope/common-constructs';
349
+ import { suppressRules } from '@my-scope/common-constructs';
342
350
 
343
351
  // suppresses the CKV_AWS_XXX for the given construct.
344
352
  suppressRules(construct, ['CKV_AWS_XXX'], 'Reason');
@@ -347,7 +355,7 @@ suppressRules(construct, ['CKV_AWS_XXX'], 'Reason');
347
355
  #### Supress a rule on a descendant construct
348
356
 
349
357
  ```typescript
350
- import { suppressRules } from ':my-scope/common-constructs';
358
+ import { suppressRules } from '@my-scope/common-constructs';
351
359
 
352
360
  // Supresses the CKV_AWS_XXX for the construct or any of its descendants if it is an instance of Bucket
353
361
  suppressRules(construct, ['CKV_AWS_XXX'], 'Reason', (construct) => construct instanceof Bucket);
@@ -369,26 +377,48 @@ For more details, please refer to the [CDK bootstrapping documentation](https://
369
377
 
370
378
  ## Deploying to AWS
371
379
 
372
- After a build, you can deploy your infrastructure to AWS using the `deploy` target.
380
+ Your project has three deploy targets, each suited to a different situation:
381
+
382
+ | Target | Use it for |
383
+ | ---------------- | -------------------------------------------------------------------------------- |
384
+ | `deploy-sandbox` | Deploying your own sandbox stage during development. No stage argument needed. |
385
+ | `deploy` | Deploying any stage, by naming the stage or stacks you want. |
386
+ | `deploy-ci` | Deploying from a CI/CD pipeline, using a pre-synthesized cloud assembly. |
373
387
 
374
- :::caution[CI Deployment]
375
- Use the `deploy-ci` target if deploying in a CI/CD pipeline. See below for more details.
388
+ `deploy-sandbox` and `deploy` depend on `^assemble`, so they build the artifacts they are about to deploy and nothing else. `deploy-ci` deploys an assembly your pipeline already built, so it has no build dependencies at all.
389
+
390
+ :::caution[Use `build` in your pipeline]
391
+ `assemble` is used for faster iteration during development. Run `build` in your CI pipeline to ensure your project passes quality gates prior to a production deployment.
376
392
  :::
377
393
 
378
- First, make sure you have AWS credentials configured. If you generated with `enableStageConfig` and have configured stage credentials in `packages/common/infra-config/src/stages.config.ts`, the deploy command will automatically resolve and apply the correct credentials for the target stage. Otherwise, ensure your AWS credentials are set in your environment (e.g., via `AWS_PROFILE` or environment variables). See the [AWS credentials documentation](https://docs.aws.amazon.com/sdkref/latest/guide/access.html) for the available options.
394
+ First, make sure you have AWS credentials configured. If you generated with `stageConfig` and have configured stage credentials in `packages/common/infra-config/src/stages.config.ts`, the deploy command will automatically resolve and apply the correct credentials for the target stage. Otherwise, ensure your AWS credentials are set in your environment (e.g., via `AWS_PROFILE` or environment variables). See the [AWS credentials documentation](https://docs.aws.amazon.com/sdkref/latest/guide/access.html) for the available options.
379
395
 
380
- Then run the deploy target:
396
+ ### Deploying your Sandbox Stage
381
397
 
382
- <NxCommands commands={['deploy <my-infra> <my-infra>-sandbox/*']} />
398
+ The `deploy-sandbox` target deploys the sandbox stage that `main.ts` declares, so you don't need to remember its stage name:
383
399
 
384
- :::tip[Selective Stack Deployment]
385
- The above command deploys _all_ stacks for the `<my-infra>-sandbox` stage. You can specify other stages so long as they are defined in `main.ts`.
400
+ <NxCommands commands={['deploy-sandbox <my-infra>']} />
386
401
 
387
- You can also deploy individual stacks by specifying the full stack name, for example:
402
+ This is the quickest way to get your own copy of the application running in AWS while you develop.
388
403
 
389
- <NxCommands commands={['deploy <my-infra> <my-infra>-sandbox/Application']} />
404
+ :::tip[Express Mode for Faster Deployments]
405
+ The deploy targets wait for full resource stabilization by default, favouring consistency over speed. To speed up iteration during development, opt into [CloudFormation express mode](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-express-mode.html) by passing CDK's `--express` flag:
406
+
407
+ <NxCommands commands={['deploy-sandbox <my-infra> --express']} />
408
+
409
+ Express mode finishes once resource configuration is confirmed applied rather than waiting for full stabilization, with propagation continuing in the background, for significantly faster iteration cycles. It is intended for development and iteration.
390
410
  :::
391
411
 
412
+ ### Deploying a Specific Stage
413
+
414
+ The `deploy` target deploys whichever stage or stacks you name. Use it for stages other than your sandbox, or to deploy a single stack:
415
+
416
+ <NxCommands commands={['deploy <my-infra> <my-infra>-sandbox/*']} />
417
+
418
+ You can specify any stage so long as it is defined in `main.ts`. To deploy an individual stack, give the full stack name:
419
+
420
+ <NxCommands commands={['deploy <my-infra> <my-infra>-sandbox/Application']} />
421
+
392
422
  ## Deploying to AWS in a CI/CD Pipeline
393
423
 
394
424
  Use the `deploy-ci` target if you are deploying to AWS as part of a CI/CD pipeline.
@@ -399,10 +429,34 @@ This target differs slightly from the regular `deploy` target in that it deploys
399
429
 
400
430
  ## Tearing Down AWS Infrastructure
401
431
 
402
- Use the `destroy` target to tear down your resources:
432
+ Your project has three destroy targets, mirroring the deploy ones:
433
+
434
+ | Target | Use it for |
435
+ | ----------------- | ------------------------------------------------------------------------- |
436
+ | `destroy-sandbox` | Tearing down your own sandbox stage. No stage argument needed. |
437
+ | `destroy` | Tearing down any stage, by naming the stage or stacks you want. |
438
+ | `destroy-ci` | Tearing down from a CI/CD pipeline, using a pre-synthesized cloud assembly. |
439
+
440
+ ### Tearing Down your Sandbox Stage
441
+
442
+ The `destroy-sandbox` target tears down the sandbox stage that `main.ts` declares, so you don't need to remember its stage name:
443
+
444
+ <NxCommands commands={['destroy-sandbox <my-infra>']} />
445
+
446
+ Destroying is irreversible, so CDK asks you to confirm the stacks it is about to delete. Pass `--force` to skip that confirmation, which is what you want when there is no terminal attached (in a script, say):
447
+
448
+ <NxCommands commands={['destroy-sandbox <my-infra> --force']} />
449
+
450
+ ### Tearing Down a Specific Stage
451
+
452
+ The `destroy` target tears down whichever stage or stacks you name:
403
453
 
404
454
  <NxCommands commands={['destroy <my-infra> <my-infra>-sandbox/*']} />
405
455
 
456
+ To tear down an individual stack, give the full stack name:
457
+
458
+ <NxCommands commands={['destroy <my-infra> <my-infra>-sandbox/Application']} />
459
+
406
460
  ## More Information
407
461
 
408
462
  For more information about CDK, please refer to the [CDK Developer Guide](https://docs.aws.amazon.com/cdk/v2/guide/core_concepts.html) and [API Reference](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html).