@aws/nx-plugin-mcp 0.119.0 → 0.121.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.
- package/bin/aws-nx-mcp.js +23 -35
- package/docs/guides/astro-docs.mdx +142 -0
- package/docs/guides/connection/py-agent-a2a.mdx +105 -0
- package/docs/guides/connection/py-agent-mcp.mdx +147 -0
- package/docs/guides/connection/react-agui.mdx +240 -0
- package/docs/guides/connection/react-fastapi.mdx +1476 -0
- package/docs/guides/connection/react-py-agent.mdx +198 -0
- package/docs/guides/connection/react-smithy.mdx +1355 -0
- package/docs/guides/connection/react-trpc.mdx +447 -0
- package/docs/guides/connection/react-ts-agent.mdx +198 -0
- package/docs/guides/connection/smithy-rdb.mdx +161 -0
- package/docs/guides/connection/trpc-rdb.mdx +127 -0
- package/docs/guides/connection/ts-agent-a2a.mdx +106 -0
- package/docs/guides/connection/ts-agent-mcp.mdx +144 -0
- package/docs/guides/connection/ts-agent-rdb.mdx +141 -0
- package/docs/guides/connection/ts-mcp-server-rdb.mdx +135 -0
- package/docs/guides/connection.mdx +126 -0
- package/docs/guides/docker-bundling.mdx +403 -0
- package/docs/guides/fastapi.mdx +509 -0
- package/docs/guides/license.mdx +293 -0
- package/docs/guides/nx-generator.mdx +588 -0
- package/docs/guides/py-agent.mdx +483 -0
- package/docs/guides/py-mcp-server.mdx +161 -0
- package/docs/guides/python-lambda-function.mdx +207 -0
- package/docs/guides/python-project.mdx +228 -0
- package/docs/guides/react-website-auth.mdx +216 -0
- package/docs/guides/react-website.mdx +421 -0
- package/docs/guides/runtime-config.mdx +312 -0
- package/docs/guides/terraform-project.mdx +317 -0
- package/docs/guides/trpc.mdx +816 -0
- package/docs/guides/ts-agent.mdx +436 -0
- package/docs/guides/ts-lambda-function.mdx +218 -0
- package/docs/guides/ts-mcp-server.mdx +169 -0
- package/docs/guides/ts-nx-plugin.mdx +159 -0
- package/docs/guides/ts-rdb.mdx +759 -0
- package/docs/guides/ts-smithy-api.mdx +661 -0
- package/docs/guides/typescript-infrastructure.mdx +408 -0
- package/docs/guides/typescript-project.mdx +312 -0
- package/docs/guides/workspace.mdx +181 -0
- package/docs/snippets/agent/architecture.mdx +72 -0
- package/docs/snippets/agent/bedrock-deployment.mdx +172 -0
- package/docs/snippets/agent/runtime-arn.mdx +64 -0
- package/docs/snippets/api/api-architecture.mdx +93 -0
- package/docs/snippets/api/api-choice-note.mdx +6 -0
- package/docs/snippets/api/cors-configuration-cdk-note.mdx +25 -0
- package/docs/snippets/api/cors-configuration-terraform-note.mdx +28 -0
- package/docs/snippets/api/shared-constructs.mdx +38 -0
- package/docs/snippets/api/type-safe-api-integrations.mdx +643 -0
- package/docs/snippets/api/waf-configuration.mdx +37 -0
- package/docs/snippets/connection/a2a-infrastructure.mdx +63 -0
- package/docs/snippets/connection/lambda-rdb-ssl-requirements.mdx +40 -0
- package/docs/snippets/connection/mcp-server-rdb-ssl-requirements.mdx +35 -0
- package/docs/snippets/connection/rdb-api-infrastructure.mdx +72 -0
- package/docs/snippets/connection/react-agent-infrastructure.mdx +61 -0
- package/docs/snippets/connection/strands-agent-rdb-ssl-requirements.mdx +35 -0
- package/docs/snippets/lambda-function/architecture.mdx +36 -0
- package/docs/snippets/lambda-function/deploying-your-function.mdx +118 -0
- package/docs/snippets/mcp/architecture.mdx +58 -0
- package/docs/snippets/mcp/assistant-docs.mdx +10 -0
- package/docs/snippets/mcp/bedrock-deployment.mdx +167 -0
- package/docs/snippets/mcp/config.mdx +13 -0
- package/docs/snippets/mcp/configuration-py.mdx +42 -0
- package/docs/snippets/mcp/configuration-ts.mdx +53 -0
- package/docs/snippets/mcp/observability.mdx +8 -0
- package/docs/snippets/mcp/shared-constructs.mdx +32 -0
- package/docs/snippets/pdk-migration/example/01-migrate-api.mdx +602 -0
- package/docs/snippets/pdk-migration/example/02-migrate-website.mdx +915 -0
- package/docs/snippets/pdk-migration/example/03-migrate-infra.mdx +161 -0
- package/docs/snippets/pdk-migration/example/04-deploy.mdx +229 -0
- package/docs/snippets/pdk-migration/faq/aws-arch.mdx +17 -0
- package/docs/snippets/pdk-migration/faq/cdk-graph.mdx +29 -0
- package/docs/snippets/pdk-migration/faq/infrastructure-python-java.mdx +19 -0
- package/docs/snippets/pdk-migration/faq/pdk-nag.mdx +15 -0
- package/docs/snippets/pdk-migration/faq/pipeline.mdx +15 -0
- package/docs/snippets/pdk-migration/faq/type-safe-api.mdx +310 -0
- package/docs/snippets/pdk-migration/faq/use-of-projen.mdx +15 -0
- package/docs/snippets/prerequisites.mdx +20 -0
- package/docs/snippets/required-prerequisites.mdx +12 -0
- package/docs/snippets/shared-constructs.mdx +40 -0
- package/docs/snippets/tools/acurl.mdx +73 -0
- package/docs/snippets/ts-bundle.mdx +14 -0
- package/package.json +1 -1
- package/src/py/agent/schema.json +1 -1
- package/src/py/fast-api/schema.json +2 -2
- package/src/py/mcp-server/schema.json +1 -1
- package/src/smithy/ts/api/schema.json +2 -2
- package/src/trpc/backend/schema.json +2 -2
- package/src/ts/agent/schema.json +1 -1
- package/src/ts/mcp-server/schema.json +1 -1
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Smithy TypeScript API
|
|
3
|
+
description: Reference documentation for Smithy TypeScript API
|
|
4
|
+
generator: ts#smithy-api
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { FileTree } from '@astrojs/starlight/components';
|
|
8
|
+
import Link from '@components/link.astro';
|
|
9
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
10
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
11
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
12
|
+
import PackageManagerShortCommand from '@components/package-manager-short-command.astro';
|
|
13
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
14
|
+
import Snippet from '@components/snippet.astro';
|
|
15
|
+
import OptionFilter from '@components/option-filter.astro';
|
|
16
|
+
|
|
17
|
+
[Smithy](https://smithy.io/) is a protocol-agnostic interface definition language for authoring APIs in a model driven fashion.
|
|
18
|
+
|
|
19
|
+
The Smithy TypeScript API generator creates a new API using Smithy for service definition, and the [Smithy TypeScript Server SDK](https://github.com/awslabs/smithy-typescript) for implementation. The generator vends CDK or Terraform infrastructure as code to deploy your service to AWS Lambda, exposed via an AWS API Gateway REST API. It provides type-safe API development with automatic code generation from Smithy models. The generated handler uses [AWS Lambda Powertools for TypeScript](https://docs.powertools.aws.dev/lambda/typescript/latest/) for observability, including logging, AWS X-Ray tracing and CloudWatch Metrics
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### Generate a Smithy TypeScript API
|
|
24
|
+
|
|
25
|
+
You can generate a new Smithy TypeScript API in two ways:
|
|
26
|
+
|
|
27
|
+
<RunGenerator generator="ts#smithy-api" />
|
|
28
|
+
|
|
29
|
+
### Options
|
|
30
|
+
|
|
31
|
+
<GeneratorParameters generator="ts#smithy-api" />
|
|
32
|
+
|
|
33
|
+
:::tip[Integration Pattern]
|
|
34
|
+
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.
|
|
35
|
+
:::
|
|
36
|
+
|
|
37
|
+
## Generator Output
|
|
38
|
+
|
|
39
|
+
The generator creates two related projects in the `<directory>/<api-name>` directory:
|
|
40
|
+
|
|
41
|
+
<FileTree>
|
|
42
|
+
|
|
43
|
+
- **model/** Smithy model project
|
|
44
|
+
- project.json Project configuration and build targets
|
|
45
|
+
- smithy-build.json Smithy build configuration
|
|
46
|
+
- build.Dockerfile Docker configuration for building Smithy artifacts
|
|
47
|
+
- src/
|
|
48
|
+
- main.smithy Main service definition
|
|
49
|
+
- operations/
|
|
50
|
+
- echo.smithy Example operation definition
|
|
51
|
+
- **backend/** TypeScript backend implementation
|
|
52
|
+
- project.json Project configuration and build targets
|
|
53
|
+
- rolldown.config.ts Bundle configuration
|
|
54
|
+
- src/
|
|
55
|
+
- handler.ts AWS Lambda handler
|
|
56
|
+
- local-server.ts Local development server
|
|
57
|
+
- service.ts Service implementation
|
|
58
|
+
- context.ts Service context definition
|
|
59
|
+
- operations/
|
|
60
|
+
- echo.ts Example operation implementation
|
|
61
|
+
- generated/ Generated TypeScript SDK (created during build)
|
|
62
|
+
|
|
63
|
+
</FileTree>
|
|
64
|
+
|
|
65
|
+
### Infrastructure
|
|
66
|
+
|
|
67
|
+
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.
|
|
68
|
+
|
|
69
|
+
The common infrastructure as code project is structured as follows:
|
|
70
|
+
|
|
71
|
+
<Infrastructure>
|
|
72
|
+
<Fragment slot="cdk">
|
|
73
|
+
<FileTree>
|
|
74
|
+
- packages/common/constructs
|
|
75
|
+
- src
|
|
76
|
+
- app/ Constructs for infrastructure specific to a project/generator
|
|
77
|
+
- apis/
|
|
78
|
+
- \<project-name>.ts CDK construct for deploying your API
|
|
79
|
+
- core/ Generic constructs which are reused by constructs in `app`
|
|
80
|
+
- api/
|
|
81
|
+
- rest-api.ts CDK construct for deploying a REST API
|
|
82
|
+
- utils.ts Utilities for the API constructs
|
|
83
|
+
- index.ts Entry point exporting constructs from `app`
|
|
84
|
+
- project.json Project build targets and configuration
|
|
85
|
+
</FileTree>
|
|
86
|
+
|
|
87
|
+
:::note[Generated Project]
|
|
88
|
+
This project is generated using the [`ts#project`](guides/typescript-project) generator and therefore configures the same build targets.
|
|
89
|
+
:::
|
|
90
|
+
</Fragment>
|
|
91
|
+
<Fragment slot="terraform">
|
|
92
|
+
<FileTree>
|
|
93
|
+
- packages/common/terraform
|
|
94
|
+
- src
|
|
95
|
+
- app/ Terraform modules for infrastructure specific to a project/generator
|
|
96
|
+
- apis/
|
|
97
|
+
- \<project-name>/
|
|
98
|
+
- \<project-name>.tf Module for deploying your API
|
|
99
|
+
- core/ Generic modules which are reused by modules in `app`
|
|
100
|
+
- api/
|
|
101
|
+
- rest-api/
|
|
102
|
+
- rest-api.tf Module for deploying a REST API
|
|
103
|
+
- project.json Project build targets and configuration
|
|
104
|
+
</FileTree>
|
|
105
|
+
|
|
106
|
+
:::note[Generated Project]
|
|
107
|
+
This project is generated using the [`terraform#project`](guides/terraform-project) generator and therefore configures the same build targets.
|
|
108
|
+
:::
|
|
109
|
+
</Fragment>
|
|
110
|
+
</Infrastructure>
|
|
111
|
+
|
|
112
|
+
#### Architecture
|
|
113
|
+
|
|
114
|
+
The deployed Smithy API has the following architecture, with an [AWS WAFv2](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) Web ACL in front of the API Gateway stage:
|
|
115
|
+
|
|
116
|
+
```d2 inline=true
|
|
117
|
+
direction: right
|
|
118
|
+
|
|
119
|
+
client: Client {
|
|
120
|
+
shape: image
|
|
121
|
+
icon: /nx-plugin-for-aws/icons/aws/client.svg
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
waf: WAF {
|
|
125
|
+
shape: image
|
|
126
|
+
icon: /nx-plugin-for-aws/icons/aws/waf.svg
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
apigw: API Gateway\n(REST API) {
|
|
130
|
+
shape: image
|
|
131
|
+
icon: /nx-plugin-for-aws/icons/aws/api-gateway.svg
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
lambda: Lambda\n(Smithy Server SDK) {
|
|
135
|
+
shape: image
|
|
136
|
+
icon: /nx-plugin-for-aws/icons/aws/lambda.svg
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
cw: CloudWatch\n(Logs, Metrics) {
|
|
140
|
+
shape: image
|
|
141
|
+
icon: /nx-plugin-for-aws/icons/aws/cloudwatch.svg
|
|
142
|
+
near: top-right
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
xray: X-Ray\n(Traces) {
|
|
146
|
+
shape: image
|
|
147
|
+
icon: /nx-plugin-for-aws/icons/aws/xray.svg
|
|
148
|
+
near: bottom-right
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
client -> waf
|
|
152
|
+
waf -> apigw
|
|
153
|
+
apigw -> lambda
|
|
154
|
+
lambda -> cw
|
|
155
|
+
lambda -> xray
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Implementing your Smithy API
|
|
159
|
+
|
|
160
|
+
### Defining Operations in Smithy
|
|
161
|
+
|
|
162
|
+
Operations are defined in Smithy files within the model project. The main service definition is in `main.smithy`:
|
|
163
|
+
|
|
164
|
+
```smithy
|
|
165
|
+
$version: "2.0"
|
|
166
|
+
|
|
167
|
+
namespace your.namespace
|
|
168
|
+
|
|
169
|
+
use aws.protocols#restJson1
|
|
170
|
+
use smithy.framework#ValidationException
|
|
171
|
+
|
|
172
|
+
@title("YourService")
|
|
173
|
+
@restJson1
|
|
174
|
+
service YourService {
|
|
175
|
+
version: "1.0.0"
|
|
176
|
+
operations: [
|
|
177
|
+
Echo,
|
|
178
|
+
// Add your operations here
|
|
179
|
+
]
|
|
180
|
+
errors: [
|
|
181
|
+
ValidationException
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Individual operations are defined in separate files in the `operations/` directory:
|
|
187
|
+
|
|
188
|
+
```smithy
|
|
189
|
+
$version: "2.0"
|
|
190
|
+
|
|
191
|
+
namespace your.namespace
|
|
192
|
+
|
|
193
|
+
@http(method: "POST", uri: "/echo")
|
|
194
|
+
operation Echo {
|
|
195
|
+
input: EchoInput
|
|
196
|
+
output: EchoOutput
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
structure EchoInput {
|
|
200
|
+
@required
|
|
201
|
+
message: String
|
|
202
|
+
|
|
203
|
+
foo: Integer
|
|
204
|
+
bar: String
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
structure EchoOutput {
|
|
208
|
+
@required
|
|
209
|
+
message: String
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
:::note[Custom Folder Structure]
|
|
214
|
+
You can change the folder structure however you like - all `.smithy` files in the `src` folder will be included in the Smithy build.
|
|
215
|
+
:::
|
|
216
|
+
|
|
217
|
+
:::tip[Smithy Documentation]
|
|
218
|
+
For more details on Smithy and its syntax, refer to the [Smithy specification](https://smithy.io/2.0/spec/index.html).
|
|
219
|
+
:::
|
|
220
|
+
|
|
221
|
+
### Implementing Operations in TypeScript
|
|
222
|
+
|
|
223
|
+
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).
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import { ServiceContext } from '../context.js';
|
|
227
|
+
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
|
|
228
|
+
|
|
229
|
+
export const Echo: EchoOperation<ServiceContext> = async (input) => {
|
|
230
|
+
// Your business logic here
|
|
231
|
+
return {
|
|
232
|
+
message: `Echo: ${input.message}` // type-safe based on your Smithy model
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Operations must be registered to the service definition in `src/service.ts`:
|
|
238
|
+
|
|
239
|
+
```typescript
|
|
240
|
+
import { ServiceContext } from './context.js';
|
|
241
|
+
import { YourServiceService } from './generated/ssdk/index.js';
|
|
242
|
+
import { Echo } from './operations/echo.js';
|
|
243
|
+
// Import other operations here
|
|
244
|
+
|
|
245
|
+
// Register operations to the service here
|
|
246
|
+
export const Service: YourServiceService<ServiceContext> = {
|
|
247
|
+
Echo,
|
|
248
|
+
// Add other operations here
|
|
249
|
+
};
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Service Context
|
|
253
|
+
|
|
254
|
+
You can define shared context for your operations in `context.ts`:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
export interface ServiceContext {
|
|
258
|
+
// Powertools tracer, logger and metrics are provided by default
|
|
259
|
+
tracer: Tracer;
|
|
260
|
+
logger: Logger;
|
|
261
|
+
metrics: Metrics;
|
|
262
|
+
// Add shared dependencies, database connections, etc.
|
|
263
|
+
dbClient: any;
|
|
264
|
+
userIdentity: string;
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
This context is passed to all operation implementations and can be used to share resources like database connections, configuration, or logging utilities.
|
|
269
|
+
|
|
270
|
+
:::caution[Manual Context Required]
|
|
271
|
+
You must construct the context yourself in both `handler.ts` (the Lambda function entry point) and `local-server.ts` (the entry point for running locally via the `serve` target).
|
|
272
|
+
:::
|
|
273
|
+
|
|
274
|
+
### Observability with AWS Lambda Powertools
|
|
275
|
+
|
|
276
|
+
#### Logging
|
|
277
|
+
|
|
278
|
+
The generator configures structured logging using AWS Lambda Powertools with automatic context injection via Middy middleware.
|
|
279
|
+
|
|
280
|
+
```typescript {4}
|
|
281
|
+
// handler.ts
|
|
282
|
+
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
|
|
283
|
+
.use(captureLambdaHandler(tracer))
|
|
284
|
+
.use(injectLambdaContext(logger))
|
|
285
|
+
.use(logMetrics(metrics))
|
|
286
|
+
.handler(lambdaHandler);
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
You can reference the logger from your operation implementations via the context:
|
|
290
|
+
|
|
291
|
+
```typescript {6}
|
|
292
|
+
// operations/echo.ts
|
|
293
|
+
import { ServiceContext } from '../context.js';
|
|
294
|
+
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
|
|
295
|
+
|
|
296
|
+
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
|
|
297
|
+
ctx.logger.info('Your log message');
|
|
298
|
+
// ...
|
|
299
|
+
};
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
#### Tracing
|
|
303
|
+
|
|
304
|
+
AWS X-Ray tracing is configured automatically via the `captureLambdaHandler` middleware.
|
|
305
|
+
|
|
306
|
+
```typescript {3}
|
|
307
|
+
// handler.ts
|
|
308
|
+
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
|
|
309
|
+
.use(captureLambdaHandler(tracer))
|
|
310
|
+
.use(injectLambdaContext(logger))
|
|
311
|
+
.use(logMetrics(metrics))
|
|
312
|
+
.handler(lambdaHandler);
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
You can add custom subsegments to your traces in your operations:
|
|
316
|
+
|
|
317
|
+
```typescript {7, 11, 14}
|
|
318
|
+
// operations/echo.ts
|
|
319
|
+
import { ServiceContext } from '../context.js';
|
|
320
|
+
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
|
|
321
|
+
|
|
322
|
+
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
|
|
323
|
+
// Creates a new subsegment
|
|
324
|
+
const subsegment = ctx.tracer.getSegment()?.addNewSubsegment('custom-operation');
|
|
325
|
+
try {
|
|
326
|
+
// Your logic here
|
|
327
|
+
} catch (error) {
|
|
328
|
+
subsegment?.addError(error as Error);
|
|
329
|
+
throw error;
|
|
330
|
+
} finally {
|
|
331
|
+
subsegment?.close();
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
#### Metrics
|
|
337
|
+
|
|
338
|
+
CloudWatch metrics are collected automatically for each request via the `logMetrics` middleware.
|
|
339
|
+
|
|
340
|
+
```typescript {5}
|
|
341
|
+
// handler.ts
|
|
342
|
+
export const handler = middy<APIGatewayProxyEvent, APIGatewayProxyResult>()
|
|
343
|
+
.use(captureLambdaHandler(tracer))
|
|
344
|
+
.use(injectLambdaContext(logger))
|
|
345
|
+
.use(logMetrics(metrics))
|
|
346
|
+
.handler(lambdaHandler);
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
You can add custom metrics in your operations:
|
|
350
|
+
|
|
351
|
+
```typescript {7}
|
|
352
|
+
// operations/echo.ts
|
|
353
|
+
import { MetricUnit } from '@aws-lambda-powertools/metrics';
|
|
354
|
+
import { ServiceContext } from '../context.js';
|
|
355
|
+
import { Echo as EchoOperation } from '../generated/ssdk/index.js';
|
|
356
|
+
|
|
357
|
+
export const Echo: EchoOperation<ServiceContext> = async (input, ctx) => {
|
|
358
|
+
ctx.metrics.addMetric("CustomMetric", MetricUnit.Count, 1);
|
|
359
|
+
// ...
|
|
360
|
+
};
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Error Handling
|
|
364
|
+
|
|
365
|
+
Smithy provides built-in error handling. You can define custom errors in your Smithy model:
|
|
366
|
+
|
|
367
|
+
```smithy
|
|
368
|
+
@error("client")
|
|
369
|
+
@httpError(400)
|
|
370
|
+
structure InvalidRequestError {
|
|
371
|
+
@required
|
|
372
|
+
message: String
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
And register them to your operation/service:
|
|
377
|
+
|
|
378
|
+
```smithy
|
|
379
|
+
operation MyOperation {
|
|
380
|
+
...
|
|
381
|
+
errors: [InvalidRequestError]
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Then throw them in your TypeScript implementation:
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
import { InvalidRequestError } from '../generated/ssdk/index.js';
|
|
389
|
+
|
|
390
|
+
export const MyOperation: MyOperationHandler<ServiceContext> = async (input) => {
|
|
391
|
+
if (!input.requiredField) {
|
|
392
|
+
throw new InvalidRequestError({
|
|
393
|
+
message: "Required field is missing"
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return { /* success response */ };
|
|
398
|
+
};
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## Building and Code Generation
|
|
402
|
+
|
|
403
|
+
The Smithy model project uses [Docker](https://www.docker.com/) to build the Smithy artifacts and generate the TypeScript Server SDK:
|
|
404
|
+
|
|
405
|
+
<NxCommands commands={['build <model-project>']} />
|
|
406
|
+
|
|
407
|
+
This process:
|
|
408
|
+
|
|
409
|
+
1. **Compiles the Smithy model** and validates it
|
|
410
|
+
2. **Generates OpenAPI specification** from the Smithy model
|
|
411
|
+
3. **Creates TypeScript Server SDK** with type-safe operation interfaces
|
|
412
|
+
4. **Outputs build artifacts** to `dist/<model-project>/build/`
|
|
413
|
+
|
|
414
|
+
The backend project automatically copies the generated SDK during compilation:
|
|
415
|
+
|
|
416
|
+
<NxCommands commands={['copy-ssdk <backend-project>']} />
|
|
417
|
+
|
|
418
|
+
### Bundle Target
|
|
419
|
+
|
|
420
|
+
<Snippet name="ts-bundle" />
|
|
421
|
+
|
|
422
|
+
## Local Development
|
|
423
|
+
|
|
424
|
+
The generator configures a local development server with hot reloading:
|
|
425
|
+
|
|
426
|
+
<NxCommands commands={['serve <backend-project>']} />
|
|
427
|
+
|
|
428
|
+
:::tip[Hot Reloading]
|
|
429
|
+
The local server will not only hot-reload when you make TypeScript changes to your backend code, but will reload when you make changes to your Smithy model project, allowing you to continuously iterate on your Smithy model and server together.
|
|
430
|
+
:::
|
|
431
|
+
|
|
432
|
+
## Deploying your Smithy API
|
|
433
|
+
|
|
434
|
+
The generator creates CDK or Terraform infrastructure based on your selected `iacProvider`.
|
|
435
|
+
|
|
436
|
+
<Infrastructure>
|
|
437
|
+
<Fragment slot="cdk">
|
|
438
|
+
The CDK construct for deploying your API is in the `common/constructs` folder:
|
|
439
|
+
|
|
440
|
+
```ts {6-8}
|
|
441
|
+
import { MyApi } from ':my-scope/common-constructs';
|
|
442
|
+
|
|
443
|
+
export class ExampleStack extends Stack {
|
|
444
|
+
constructor(scope: Construct, id: string) {
|
|
445
|
+
// Add the API to your stack
|
|
446
|
+
const api = new MyApi(this, 'MyApi', {
|
|
447
|
+
integrations: MyApi.defaultIntegrations(this).build(),
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
This sets up:
|
|
454
|
+
|
|
455
|
+
1. An AWS Lambda function for the Smithy service
|
|
456
|
+
2. API Gateway REST API as the function trigger
|
|
457
|
+
3. IAM roles and permissions
|
|
458
|
+
4. CloudWatch log group
|
|
459
|
+
5. X-Ray tracing configuration
|
|
460
|
+
|
|
461
|
+
<Snippet name="api/cors-configuration-cdk-note" />
|
|
462
|
+
|
|
463
|
+
<OptionFilter when={{ auth: 'Cognito' }} description="Cognito identity construct wiring">
|
|
464
|
+
:::note[Cognito Authentication]
|
|
465
|
+
If you selected `Cognito` authentication, you will need to supply the `identity` property to the API construct:
|
|
466
|
+
|
|
467
|
+
```ts {9}
|
|
468
|
+
import { MyApi, UserIdentity } from ':my-scope/common-constructs';
|
|
469
|
+
|
|
470
|
+
export class ExampleStack extends Stack {
|
|
471
|
+
constructor(scope: Construct, id: string) {
|
|
472
|
+
const identity = new UserIdentity(this, 'Identity');
|
|
473
|
+
|
|
474
|
+
const api = new MyApi(this, 'MyApi', {
|
|
475
|
+
integrations: MyApi.defaultIntegrations(this).build(),
|
|
476
|
+
identity,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
The `UserIdentity` construct can be generated using the <Link path="/guides/react-website-auth">`ts#react-website-auth` generator</Link>
|
|
483
|
+
:::
|
|
484
|
+
</OptionFilter>
|
|
485
|
+
|
|
486
|
+
<OptionFilter when={{ auth: 'Custom' }} description="Custom Lambda Authorizer CDK usage">
|
|
487
|
+
:::caution[Custom Lambda Authorizer]
|
|
488
|
+
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.
|
|
489
|
+
:::
|
|
490
|
+
</OptionFilter>
|
|
491
|
+
</Fragment>
|
|
492
|
+
<Fragment slot="terraform">
|
|
493
|
+
The Terraform modules for deploying your API are in the `common/terraform` folder.
|
|
494
|
+
|
|
495
|
+
The API module stages its Lambda deployment zip in a shared S3 asset bucket — see the <Link path="/guides/terraform-project">Terraform infrastructure guide</Link> for details. Instantiate the `core/asset-bucket` module once per deployment and pass its `bucket_name` output into every API / Lambda module via the `asset_bucket_name` input:
|
|
496
|
+
|
|
497
|
+
```hcl {1-3, 8}
|
|
498
|
+
module "asset_bucket" {
|
|
499
|
+
source = "../../common/terraform/src/core/asset-bucket"
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
module "my_api" {
|
|
503
|
+
source = "../../common/terraform/src/app/apis/my-api"
|
|
504
|
+
|
|
505
|
+
asset_bucket_name = module.asset_bucket.bucket_name
|
|
506
|
+
|
|
507
|
+
# Environment variables for the Lambda function
|
|
508
|
+
env = {
|
|
509
|
+
ENVIRONMENT = var.environment
|
|
510
|
+
LOG_LEVEL = "INFO"
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
# Additional IAM policies if needed
|
|
514
|
+
additional_iam_policy_statements = [
|
|
515
|
+
# Add any additional permissions your API needs
|
|
516
|
+
]
|
|
517
|
+
|
|
518
|
+
tags = local.common_tags
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
This sets up:
|
|
523
|
+
|
|
524
|
+
1. An AWS Lambda function that serves the Smithy API
|
|
525
|
+
2. API Gateway REST API as the function trigger
|
|
526
|
+
3. IAM roles and permissions
|
|
527
|
+
4. CloudWatch log group
|
|
528
|
+
5. X-Ray tracing configuration
|
|
529
|
+
6. CORS configuration
|
|
530
|
+
|
|
531
|
+
<Snippet name="api/cors-configuration-terraform-note" />
|
|
532
|
+
|
|
533
|
+
<OptionFilter when={{ auth: 'Cognito' }} description="Cognito module wiring">
|
|
534
|
+
:::note[Cognito Authentication]
|
|
535
|
+
If you selected `Cognito` authentication, you will need to supply the Cognito configuration:
|
|
536
|
+
|
|
537
|
+
```hcl {3, 5-6}
|
|
538
|
+
module "my_api" {
|
|
539
|
+
source = "../../common/terraform/src/app/apis/my-api"
|
|
540
|
+
|
|
541
|
+
asset_bucket_name = module.asset_bucket.bucket_name
|
|
542
|
+
|
|
543
|
+
user_pool_id = local.user_pool_id
|
|
544
|
+
user_pool_client_ids = [local.client_id]
|
|
545
|
+
|
|
546
|
+
env = {
|
|
547
|
+
ENVIRONMENT = var.environment
|
|
548
|
+
LOG_LEVEL = "INFO"
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
tags = local.common_tags
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
:::
|
|
555
|
+
</OptionFilter>
|
|
556
|
+
|
|
557
|
+
<OptionFilter when={{ auth: 'Custom' }} description="Custom Lambda Authorizer usage with Terraform">
|
|
558
|
+
:::caution[Custom Lambda Authorizer]
|
|
559
|
+
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.
|
|
560
|
+
:::
|
|
561
|
+
</OptionFilter>
|
|
562
|
+
|
|
563
|
+
The Terraform module provides several outputs:
|
|
564
|
+
|
|
565
|
+
```hcl
|
|
566
|
+
# Access the API endpoint
|
|
567
|
+
output "api_url" {
|
|
568
|
+
value = module.my_api.stage_invoke_url
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
# Access Lambda function details
|
|
572
|
+
output "lambda_function_name" {
|
|
573
|
+
value = module.my_api.lambda_function_name
|
|
574
|
+
}
|
|
575
|
+
```
|
|
576
|
+
</Fragment>
|
|
577
|
+
</Infrastructure>
|
|
578
|
+
|
|
579
|
+
### WAF
|
|
580
|
+
|
|
581
|
+
<Snippet name="api/waf-configuration" parentHeading="WAF" />
|
|
582
|
+
|
|
583
|
+
### Integrations
|
|
584
|
+
|
|
585
|
+
<Snippet name="api/type-safe-api-integrations" parentHeading="Integrations" />
|
|
586
|
+
|
|
587
|
+
#### Code Generation
|
|
588
|
+
|
|
589
|
+
<Infrastructure>
|
|
590
|
+
<Fragment slot="cdk">
|
|
591
|
+
Since operations are defined in Smithy, we use code generation to supply metadata to the CDK construct for type-safe integrations.
|
|
592
|
+
|
|
593
|
+
A `generate:<ApiName>-metadata` target is added to the common constructs `project.json` to facilitate this code generation, which emits a file such as `packages/common/constructs/src/generated/my-api/metadata.gen.ts`. Since this is generated at build time, it is ignored in version control.
|
|
594
|
+
|
|
595
|
+
:::note[Build Before Deploy]
|
|
596
|
+
You will need to run a build whenever you change your Smithy model to ensure the types consumed by the CDK construct are up to date.
|
|
597
|
+
|
|
598
|
+
<PackageManagerShortCommand commands={["build"]} />
|
|
599
|
+
:::
|
|
600
|
+
|
|
601
|
+
:::tip[Hot Reloading]
|
|
602
|
+
If you are actively working on both your CDK infrastructure and Smithy API together, you can use [`nx watch`](https://nx.dev/nx-api/nx/documents/watch) to regenerate these types every time you make model changes:
|
|
603
|
+
|
|
604
|
+
<NxCommands
|
|
605
|
+
commands={[
|
|
606
|
+
'watch --projects=<ModelProject> -- \\ ',
|
|
607
|
+
'run <InfraProject>:"generate:<ApiName>-metadata"',
|
|
608
|
+
]}
|
|
609
|
+
/>
|
|
610
|
+
:::
|
|
611
|
+
</Fragment>
|
|
612
|
+
<Fragment slot="terraform">
|
|
613
|
+
:::note[Terraform Limitations]
|
|
614
|
+
We do not support type-safe integrations for Terraform, and therefore no code generation targets are configured if you selected Terraform for your `iacProvider`.
|
|
615
|
+
:::
|
|
616
|
+
</Fragment>
|
|
617
|
+
</Infrastructure>
|
|
618
|
+
|
|
619
|
+
<OptionFilter when={{ auth: 'IAM' }} description="IAM-authenticated APIs only">
|
|
620
|
+
### Granting Access (IAM Only)
|
|
621
|
+
|
|
622
|
+
If you selected `IAM` authentication, you can use the `grantInvokeAccess` method to grant access to your API:
|
|
623
|
+
|
|
624
|
+
<Infrastructure>
|
|
625
|
+
<Fragment slot="cdk">
|
|
626
|
+
```ts
|
|
627
|
+
api.grantInvokeAccess(myIdentityPool.authenticatedRole);
|
|
628
|
+
```
|
|
629
|
+
</Fragment>
|
|
630
|
+
<Fragment slot="terraform">
|
|
631
|
+
```hcl
|
|
632
|
+
# Create an IAM policy to allow invoking the API
|
|
633
|
+
resource "aws_iam_policy" "api_invoke_policy" {
|
|
634
|
+
name = "MyApiInvokePolicy"
|
|
635
|
+
description = "Policy to allow invoking the Smithy API"
|
|
636
|
+
|
|
637
|
+
policy = jsonencode({
|
|
638
|
+
Version = "2012-10-17"
|
|
639
|
+
Statement = [
|
|
640
|
+
{
|
|
641
|
+
Effect = "Allow"
|
|
642
|
+
Action = "execute-api:Invoke"
|
|
643
|
+
Resource = "${module.my_api.api_execution_arn}/*/*"
|
|
644
|
+
}
|
|
645
|
+
]
|
|
646
|
+
})
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
# Attach the policy to an IAM role
|
|
650
|
+
resource "aws_iam_role_policy_attachment" "api_invoke_access" {
|
|
651
|
+
role = aws_iam_role.authenticated_user_role.name
|
|
652
|
+
policy_arn = aws_iam_policy.api_invoke_policy.arn
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
</Fragment>
|
|
656
|
+
</Infrastructure>
|
|
657
|
+
</OptionFilter>
|
|
658
|
+
|
|
659
|
+
## Invoking your Smithy API
|
|
660
|
+
|
|
661
|
+
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.
|