@aws/nx-plugin-mcp 1.0.0-rc.6 → 1.0.0-rc.62
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.
- package/bin/aws-nx-mcp.js +11732 -10472
- package/docs/get_started/building-with-ai.mdx +116 -0
- package/docs/get_started/concepts.mdx +67 -0
- package/docs/get_started/existing-project.mdx +180 -0
- package/docs/get_started/graph-builder.mdx +39 -0
- package/docs/get_started/quick-start.mdx +277 -0
- package/docs/get_started/tutorials/contribute-generator.mdx +408 -0
- package/docs/get_started/tutorials/dungeon-game/1.mdx +1301 -0
- package/docs/get_started/tutorials/dungeon-game/2.mdx +237 -0
- package/docs/get_started/tutorials/dungeon-game/3.mdx +76 -0
- package/docs/get_started/tutorials/dungeon-game/4.mdx +162 -0
- package/docs/get_started/tutorials/dungeon-game/overview.mdx +145 -0
- package/docs/get_started/tutorials/dungeon-game/wrap-up.mdx +41 -0
- package/docs/get_started/tutorials/existing-project.mdx +4 -0
- package/docs/get_started/upgrading.mdx +147 -0
- package/docs/guides/agentcore-gateway.mdx +490 -0
- package/docs/guides/connection/agentcore-gateway-agent.mdx +222 -0
- package/docs/guides/connection/agentcore-gateway-gateway.mdx +154 -0
- package/docs/guides/connection/agentcore-gateway-mcp.mdx +134 -0
- package/docs/guides/connection/py-agent-a2a.mdx +48 -16
- package/docs/guides/connection/py-agent-dynamodb.mdx +116 -0
- package/docs/guides/connection/py-agent-gateway.mdx +178 -0
- package/docs/guides/connection/py-agent-mcp.mdx +43 -14
- package/docs/guides/connection/py-agent-rdb.mdx +178 -0
- package/docs/guides/connection/py-fast-api-dynamodb.mdx +56 -0
- package/docs/guides/connection/py-fast-api-rdb.mdx +184 -0
- package/docs/guides/connection/py-mcp-server-dynamodb.mdx +116 -0
- package/docs/guides/connection/py-mcp-server-rdb.mdx +187 -0
- package/docs/guides/connection/react-agentcore-gateway.mdx +112 -0
- package/docs/guides/connection/react-agui.mdx +13 -13
- package/docs/guides/connection/react-fastapi.mdx +38 -2
- package/docs/guides/connection/react-py-agent.mdx +9 -15
- package/docs/guides/connection/react-smithy.mdx +3 -3
- package/docs/guides/connection/react-trpc.mdx +1 -1
- package/docs/guides/connection/react-ts-agent.mdx +8 -8
- package/docs/guides/connection/smithy-dynamodb.mdx +5 -5
- package/docs/guides/connection/smithy-rdb.mdx +9 -9
- package/docs/guides/connection/trpc-dynamodb.mdx +5 -5
- package/docs/guides/connection/trpc-rdb.mdx +6 -6
- package/docs/guides/connection/ts-agent-a2a.mdx +14 -11
- package/docs/guides/connection/ts-agent-dynamodb.mdx +5 -5
- package/docs/guides/connection/ts-agent-gateway.mdx +143 -0
- package/docs/guides/connection/ts-agent-mcp.mdx +12 -9
- package/docs/guides/connection/ts-agent-rdb.mdx +70 -25
- package/docs/guides/connection/ts-mcp-server-dynamodb.mdx +5 -5
- package/docs/guides/connection/ts-mcp-server-rdb.mdx +68 -18
- package/docs/guides/connection.mdx +122 -5
- package/docs/guides/docker-bundling.mdx +68 -11
- package/docs/guides/fastapi.mdx +249 -9
- package/docs/guides/local-development.mdx +87 -0
- package/docs/guides/nx-generator.mdx +7 -2
- package/docs/guides/nx-migration.mdx +165 -0
- package/docs/guides/py-agent.mdx +264 -49
- package/docs/guides/py-dynamodb.mdx +476 -0
- package/docs/guides/py-mcp-server.mdx +61 -2
- package/docs/guides/py-rdb.mdx +265 -0
- package/docs/guides/python-lambda-function.mdx +1 -1
- package/docs/guides/react-website-auth.mdx +65 -4
- package/docs/guides/react-website.mdx +149 -30
- package/docs/guides/runtime-config.mdx +1 -1
- package/docs/guides/security.mdx +75 -0
- package/docs/guides/smithy-project.mdx +175 -0
- package/docs/guides/terraform-project.mdx +2 -2
- package/docs/guides/trpc.mdx +53 -16
- package/docs/guides/ts-agent.mdx +183 -10
- package/docs/guides/ts-dcr-proxy.mdx +569 -0
- package/docs/guides/ts-dynamodb.mdx +66 -242
- package/docs/guides/ts-lambda-function.mdx +1 -1
- package/docs/guides/ts-mcp-server.mdx +109 -29
- package/docs/guides/ts-nx-plugin.mdx +3 -3
- package/docs/guides/ts-rdb.mdx +113 -467
- package/docs/guides/ts-smithy-api.mdx +221 -16
- package/docs/guides/typescript-infrastructure.mdx +25 -15
- package/docs/guides/typescript-project.mdx +133 -26
- package/docs/guides/workspace.mdx +10 -3
- package/docs/snippets/agent/architecture.mdx +1 -1
- package/docs/snippets/agent/bedrock-deployment.mdx +9 -5
- package/docs/snippets/agent/runtime-arn.mdx +23 -2
- package/docs/snippets/agent/securing-your-agent.mdx +39 -0
- package/docs/snippets/api/access-logging.mdx +33 -0
- package/docs/snippets/api/cors-configuration-cdk-note.mdx +1 -1
- package/docs/snippets/api/cors-configuration-terraform-note.mdx +1 -1
- package/docs/snippets/api/type-safe-api-integrations.mdx +33 -2
- package/docs/snippets/api/waf-configuration.mdx +3 -3
- package/docs/snippets/connection/a2a-infrastructure.mdx +1 -1
- package/docs/snippets/connection/dynamodb-local-development.mdx +2 -2
- package/docs/snippets/connection/lambda-dynamodb-access.mdx +1 -1
- package/docs/snippets/connection/py-dynamodb-local-development.mdx +7 -0
- package/docs/snippets/connection/py-lambda-rdb-ssl-requirements.mdx +7 -0
- package/docs/snippets/connection/rdb-api-infrastructure.mdx +51 -19
- package/docs/snippets/dynamodb/deploying-table.mdx +166 -0
- package/docs/snippets/dynamodb/gsi-config.mdx +38 -0
- package/docs/snippets/dynamodb/infrastructure.mdx +33 -0
- package/docs/snippets/dynamodb/local-dev-start.mdx +13 -0
- package/docs/snippets/dynamodb/local-dev-windows.mdx +15 -0
- package/docs/snippets/lambda-function/deploying-your-function.mdx +3 -3
- package/docs/snippets/mcp/architecture.mdx +1 -1
- package/docs/snippets/mcp/bedrock-deployment.mdx +9 -5
- package/docs/snippets/mcp/config.mdx +3 -2
- package/docs/snippets/pdk-migration/example/01-migrate-api.mdx +7 -5
- package/docs/snippets/pdk-migration/example/02-migrate-website.mdx +29 -10
- package/docs/snippets/pdk-migration/example/03-migrate-infra.mdx +4 -4
- package/docs/snippets/pdk-migration/faq/type-safe-api.mdx +5 -111
- package/docs/snippets/prerequisites.mdx +4 -1
- package/docs/snippets/rdb/architecture.mdx +38 -0
- package/docs/snippets/rdb/cluster-instances.mdx +31 -0
- package/docs/snippets/rdb/deletion-protection.mdx +34 -0
- package/docs/snippets/rdb/deploying.mdx +187 -0
- package/docs/snippets/rdb/encryption-key-rotation.mdx +30 -0
- package/docs/snippets/rdb/engine-version.mdx +63 -0
- package/docs/snippets/rdb/infrastructure.mdx +35 -0
- package/docs/snippets/rdb/logging-mysql.mdx +5 -0
- package/docs/snippets/rdb/logging-postgres.mdx +5 -0
- package/docs/snippets/rdb/performance-insights.mdx +34 -0
- package/docs/snippets/rdb/rds-proxy.mdx +50 -0
- package/docs/snippets/rdb/removal-policy.mdx +57 -0
- package/docs/snippets/rdb/serverless-capacity.mdx +32 -0
- package/docs/snippets/required-prerequisites.mdx +1 -4
- package/docs/snippets/runtime-config-app-id-note.mdx +8 -0
- package/docs/snippets/shared-constructs.mdx +1 -1
- package/docs/snippets/trivy-image-scan.mdx +37 -0
- package/generators.json +145 -10
- package/package.json +1 -1
- package/src/agentcore-gateway/agent-connection/schema.json +31 -0
- package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
- package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
- package/src/agentcore-gateway/react-connection/schema.json +31 -0
- package/src/agentcore-gateway/schema.json +72 -0
- package/src/connection/schema.json +5 -0
- package/src/infra/app/schema.json +5 -0
- package/src/init/schema.json +35 -0
- package/src/internal/test-matrix/schema.json +21 -0
- package/src/license/schema.json +5 -0
- package/src/preset/schema.json +16 -5
- package/src/py/agent/a2a-connection/schema.json +5 -0
- package/src/py/agent/gateway-connection/schema.json +31 -0
- package/src/py/agent/mcp-connection/schema.json +5 -0
- package/src/py/agent/react-connection/schema.json +5 -0
- package/src/py/agent/schema.json +15 -1
- package/src/py/api/schema.json +5 -0
- package/src/py/dynamodb/agent-connection/schema.json +27 -0
- package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
- package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
- package/src/py/dynamodb/schema.json +76 -0
- package/src/py/fast-api/react/schema.json +5 -0
- package/src/py/fast-api/schema.json +6 -0
- package/src/py/lambda-function/schema.json +5 -0
- package/src/py/mcp-server/schema.json +6 -0
- package/src/py/project/schema.json +5 -0
- package/src/py/rdb/agent-connection/schema.json +27 -0
- package/src/py/rdb/fast-api-connection/schema.json +23 -0
- package/src/py/rdb/mcp-server-connection/schema.json +27 -0
- package/src/py/rdb/schema.json +78 -0
- package/src/smithy/project/schema.json +28 -1
- package/src/smithy/react-connection/schema.json +5 -0
- package/src/smithy/ts/api/schema.json +6 -0
- package/src/terraform/project/schema.json +5 -0
- package/src/trpc/backend/schema.json +6 -0
- package/src/trpc/react/schema.json +5 -0
- package/src/ts/agent/a2a-connection/schema.json +5 -0
- package/src/ts/agent/gateway-connection/schema.json +31 -0
- package/src/ts/agent/mcp-connection/schema.json +5 -0
- package/src/ts/agent/react-connection/schema.json +5 -0
- package/src/ts/agent/schema.json +14 -0
- package/src/ts/api/schema.json +5 -0
- package/src/ts/astro-docs/schema.json +3 -3
- package/src/ts/dcr-proxy/schema.json +44 -0
- package/src/ts/docs/schema.json +3 -3
- package/src/ts/dynamodb/agent-connection/schema.json +5 -0
- package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
- package/src/ts/dynamodb/schema.json +26 -2
- package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
- package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
- package/src/ts/lambda-function/schema.json +5 -0
- package/src/ts/lib/schema.json +5 -0
- package/src/ts/mcp-server/schema.json +6 -0
- package/src/ts/nx-generator/schema.json +5 -0
- package/src/ts/nx-migration/schema.json +63 -0
- package/src/ts/nx-plugin/schema.json +5 -0
- package/src/ts/rdb/agent-connection/schema.json +5 -0
- package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
- package/src/ts/rdb/schema.json +7 -1
- package/src/ts/rdb/smithy-connection/schema.json +5 -0
- package/src/ts/rdb/trpc-connection/schema.json +5 -0
- package/src/ts/react-website/app/schema.json +12 -6
- package/src/ts/react-website/cognito-auth/schema.json +5 -0
- package/src/ts/react-website/runtime-config/schema.json +5 -0
- package/src/ts/website/app/schema.json +11 -6
- package/src/ts/website/auth/schema.json +5 -0
- /package/docs/snippets/connection/{lambda-rdb-ssl-requirements.mdx → ts-lambda-rdb-ssl-requirements.mdx} +0 -0
- /package/docs/snippets/connection/{mcp-server-rdb-ssl-requirements.mdx → ts-mcp-server-rdb-ssl-requirements.mdx} +0 -0
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Smithy TypeScript API
|
|
3
3
|
description: Reference documentation for Smithy TypeScript API
|
|
4
|
-
generator: ts#
|
|
4
|
+
generator: ts#api
|
|
5
5
|
when:
|
|
6
6
|
framework: [smithy]
|
|
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';
|
|
@@ -27,11 +29,11 @@ The Smithy TypeScript API generator creates a new API using Smithy for service d
|
|
|
27
29
|
|
|
28
30
|
You can generate a new Smithy TypeScript API in two ways:
|
|
29
31
|
|
|
30
|
-
<RunGenerator generator="ts#
|
|
32
|
+
<RunGenerator generator="ts#api" requiredParameters={{ framework: 'smithy' }} />
|
|
31
33
|
|
|
32
34
|
### Options
|
|
33
35
|
|
|
34
|
-
<GeneratorParameters generator="ts#
|
|
36
|
+
<GeneratorParameters generator="ts#api" />
|
|
35
37
|
|
|
36
38
|
:::tip[Integration Pattern]
|
|
37
39
|
The `integrationPattern` option defaults to `isolated`, which creates one Lambda per Smithy operation. Select `shared` if you would prefer a single shared Lambda handler for the whole API, with optional per-operation overrides.
|
|
@@ -44,6 +46,7 @@ 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
52
|
- build.Dockerfile Docker configuration for building Smithy artifacts
|
|
@@ -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 `
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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,6 +429,151 @@ 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
579
|
The Smithy model project uses [Docker](https://www.docker.com/) to build the Smithy artifacts and generate the TypeScript Server SDK:
|
|
@@ -434,14 +607,14 @@ The local server will not only hot-reload when you make TypeScript changes to yo
|
|
|
434
607
|
|
|
435
608
|
## Deploying your Smithy API
|
|
436
609
|
|
|
437
|
-
The generator creates CDK or Terraform infrastructure based on your selected `
|
|
610
|
+
The generator creates CDK or Terraform infrastructure based on your selected `iac`.
|
|
438
611
|
|
|
439
612
|
<Infrastructure>
|
|
440
613
|
<Fragment slot="cdk">
|
|
441
614
|
The CDK construct for deploying your API is in the `common/constructs` folder:
|
|
442
615
|
|
|
443
616
|
```ts {6-8}
|
|
444
|
-
import { MyApi } from '
|
|
617
|
+
import { MyApi } from '@my-scope/common-constructs';
|
|
445
618
|
|
|
446
619
|
export class ExampleStack extends Stack {
|
|
447
620
|
constructor(scope: Construct, id: string) {
|
|
@@ -468,7 +641,7 @@ This sets up:
|
|
|
468
641
|
If you selected `Cognito` authentication, you will need to supply the `identity` property to the API construct:
|
|
469
642
|
|
|
470
643
|
```ts {9}
|
|
471
|
-
import { MyApi, UserIdentity } from '
|
|
644
|
+
import { MyApi, UserIdentity } from '@my-scope/common-constructs';
|
|
472
645
|
|
|
473
646
|
export class ExampleStack extends Stack {
|
|
474
647
|
constructor(scope: Construct, id: string) {
|
|
@@ -537,7 +710,7 @@ This sets up:
|
|
|
537
710
|
:::note[Cognito Authentication]
|
|
538
711
|
If you selected `Cognito` authentication, you will need to supply the Cognito configuration:
|
|
539
712
|
|
|
540
|
-
```hcl {
|
|
713
|
+
```hcl {6-7}
|
|
541
714
|
module "my_api" {
|
|
542
715
|
source = "../../common/terraform/src/app/apis/my-api"
|
|
543
716
|
|
|
@@ -583,6 +756,10 @@ output "lambda_function_name" {
|
|
|
583
756
|
|
|
584
757
|
<Snippet name="api/waf-configuration" parentHeading="WAF" />
|
|
585
758
|
|
|
759
|
+
### Access logging
|
|
760
|
+
|
|
761
|
+
<Snippet name="api/access-logging" parentHeading="Access logging" />
|
|
762
|
+
|
|
586
763
|
### Integrations
|
|
587
764
|
|
|
588
765
|
<Snippet name="api/type-safe-api-integrations" parentHeading="Integrations" />
|
|
@@ -614,7 +791,7 @@ If you are actively working on both your CDK infrastructure and Smithy API toget
|
|
|
614
791
|
</Fragment>
|
|
615
792
|
<Fragment slot="terraform">
|
|
616
793
|
:::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 `
|
|
794
|
+
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
795
|
:::
|
|
619
796
|
</Fragment>
|
|
620
797
|
</Infrastructure>
|
|
@@ -662,3 +839,31 @@ resource "aws_iam_role_policy_attachment" "api_invoke_access" {
|
|
|
662
839
|
## Invoking your Smithy API
|
|
663
840
|
|
|
664
841
|
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.
|
|
842
|
+
|
|
843
|
+
## Connections
|
|
844
|
+
|
|
845
|
+
Use the <Link path="guides/connection">`connection`</Link> generator to integrate this project with others in your workspace. The following connections involve this project:
|
|
846
|
+
|
|
847
|
+
<CardGrid>
|
|
848
|
+
<ConnectionCard
|
|
849
|
+
title="React to Smithy API"
|
|
850
|
+
description="Call a Smithy API from a React website"
|
|
851
|
+
href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/react-smithy`}
|
|
852
|
+
source="react"
|
|
853
|
+
target="smithy"
|
|
854
|
+
/>
|
|
855
|
+
<ConnectionCard
|
|
856
|
+
title="Smithy API to Relational Database"
|
|
857
|
+
description="Connect a Smithy API to an Aurora relational database"
|
|
858
|
+
href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/smithy-rdb`}
|
|
859
|
+
source="smithy"
|
|
860
|
+
target="aurora"
|
|
861
|
+
/>
|
|
862
|
+
<ConnectionCard
|
|
863
|
+
title="Smithy API to TypeScript DynamoDB"
|
|
864
|
+
description="Connect a Smithy API to a DynamoDB table"
|
|
865
|
+
href={`/nx-plugin-for-aws/${Astro.currentLocale || 'en'}/guides/connection/smithy-dynamodb`}
|
|
866
|
+
source="smithy"
|
|
867
|
+
target="dynamodb"
|
|
868
|
+
/>
|
|
869
|
+
</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 `
|
|
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
|
|
|
@@ -99,13 +100,14 @@ new ApplicationStage(app, 'my-app-sandbox', {
|
|
|
99
100
|
|
|
100
101
|
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
102
|
|
|
102
|
-
If you generated with `
|
|
103
|
+
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
104
|
|
|
104
|
-
```ts title="src/main.ts (with
|
|
105
|
-
import
|
|
105
|
+
```ts title="src/main.ts (with stageConfig)"
|
|
106
|
+
import { resolveStage } from '@my-scope/common-infra-config';
|
|
106
107
|
|
|
107
|
-
|
|
108
|
-
|
|
108
|
+
// Looks up the stage under this project (packages/infra), falling back to
|
|
109
|
+
// shared stages. Returns undefined when no config exists for the stage.
|
|
110
|
+
const sandboxConfig = resolveStage('packages/infra', 'my-app-sandbox');
|
|
109
111
|
|
|
110
112
|
new ApplicationStage(app, 'my-app-sandbox', {
|
|
111
113
|
env: {
|
|
@@ -158,12 +160,12 @@ export class ApplicationStage extends Stage {
|
|
|
158
160
|
### Stage Credential Configuration
|
|
159
161
|
|
|
160
162
|
:::note[Staged Configuration]
|
|
161
|
-
This section applies when you generate with `
|
|
163
|
+
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
164
|
:::
|
|
163
165
|
|
|
164
166
|
When you have multiple stages targeting different AWS accounts, managing credentials manually can be error-prone, especially as the number of stages grows.
|
|
165
167
|
|
|
166
|
-
The `
|
|
168
|
+
The `stageConfig` option solves this by generating two shared packages:
|
|
167
169
|
|
|
168
170
|
- **`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
171
|
- **`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 +244,7 @@ Each stage config includes a required `region` and an optional `account`:
|
|
|
242
244
|
The generated `main.ts` reads these values from the config so that CDK synthesis and deployment use the same environment settings:
|
|
243
245
|
|
|
244
246
|
```ts title="src/main.ts"
|
|
245
|
-
const sandboxConfig =
|
|
247
|
+
const sandboxConfig = resolveStage('packages/infra', 'my-app-sandbox');
|
|
246
248
|
new ApplicationStage(app, 'my-app-sandbox', {
|
|
247
249
|
env: {
|
|
248
250
|
account: sandboxConfig?.account ?? process.env.CDK_DEFAULT_ACCOUNT,
|
|
@@ -270,7 +272,7 @@ If, for example, you created a tRPC API called `my-api`, you can simply import a
|
|
|
270
272
|
```ts title="src/stacks/application-stack.ts" {3, 9-12}
|
|
271
273
|
import { Stack, StackProps } from 'aws-cdk-lib';
|
|
272
274
|
import { Construct } from 'constructs';
|
|
273
|
-
import { MyApi } from '
|
|
275
|
+
import { MyApi } from '@my-scope/common-constructs';
|
|
274
276
|
|
|
275
277
|
export class ApplicationStack extends Stack {
|
|
276
278
|
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
@@ -286,12 +288,12 @@ export class ApplicationStack extends Stack {
|
|
|
286
288
|
|
|
287
289
|
### Website Infrastructure
|
|
288
290
|
|
|
289
|
-
If you have used the <Link path="guides/react-website">
|
|
291
|
+
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
292
|
|
|
291
293
|
```ts title="src/stacks/application-stack.ts" {3, 9-10}
|
|
292
294
|
import { Stack, StackProps } from 'aws-cdk-lib';
|
|
293
295
|
import { Construct } from 'constructs';
|
|
294
|
-
import { MyWebsite } from '
|
|
296
|
+
import { MyWebsite } from '@my-scope/common-constructs';
|
|
295
297
|
|
|
296
298
|
export class ApplicationStack extends Stack {
|
|
297
299
|
constructor(scope: Construct, id: string, props?: StackProps) {
|
|
@@ -338,7 +340,7 @@ There may be instances where you want to suppress certain rules on resources. Yo
|
|
|
338
340
|
#### Supress a rule on a given construct
|
|
339
341
|
|
|
340
342
|
```typescript
|
|
341
|
-
import { suppressRules } from '
|
|
343
|
+
import { suppressRules } from '@my-scope/common-constructs';
|
|
342
344
|
|
|
343
345
|
// suppresses the CKV_AWS_XXX for the given construct.
|
|
344
346
|
suppressRules(construct, ['CKV_AWS_XXX'], 'Reason');
|
|
@@ -347,7 +349,7 @@ suppressRules(construct, ['CKV_AWS_XXX'], 'Reason');
|
|
|
347
349
|
#### Supress a rule on a descendant construct
|
|
348
350
|
|
|
349
351
|
```typescript
|
|
350
|
-
import { suppressRules } from '
|
|
352
|
+
import { suppressRules } from '@my-scope/common-constructs';
|
|
351
353
|
|
|
352
354
|
// Supresses the CKV_AWS_XXX for the construct or any of its descendants if it is an instance of Bucket
|
|
353
355
|
suppressRules(construct, ['CKV_AWS_XXX'], 'Reason', (construct) => construct instanceof Bucket);
|
|
@@ -375,12 +377,20 @@ After a build, you can deploy your infrastructure to AWS using the `deploy` targ
|
|
|
375
377
|
Use the `deploy-ci` target if deploying in a CI/CD pipeline. See below for more details.
|
|
376
378
|
:::
|
|
377
379
|
|
|
378
|
-
First, make sure you have AWS credentials configured. If you generated with `
|
|
380
|
+
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
381
|
|
|
380
382
|
Then run the deploy target:
|
|
381
383
|
|
|
382
384
|
<NxCommands commands={['deploy <my-infra> <my-infra>-sandbox/*']} />
|
|
383
385
|
|
|
386
|
+
:::tip[Express Mode for Faster Deployments]
|
|
387
|
+
The `deploy` target waits 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:
|
|
388
|
+
|
|
389
|
+
<NxCommands commands={['deploy <my-infra> <my-infra>-sandbox/* --express']} />
|
|
390
|
+
|
|
391
|
+
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.
|
|
392
|
+
:::
|
|
393
|
+
|
|
384
394
|
:::tip[Selective Stack Deployment]
|
|
385
395
|
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`.
|
|
386
396
|
|