@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,207 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Python Lambda Functions
|
|
3
|
+
description: Reference documentation for Python Lambda Functions
|
|
4
|
+
generator: py#lambda-function
|
|
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 Infrastructure from '@components/infrastructure.astro';
|
|
12
|
+
import Snippet from '@components/snippet.astro';
|
|
13
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
14
|
+
import OptionFilter from '@components/option-filter.astro';
|
|
15
|
+
|
|
16
|
+
The Python Lambda Function generator provides the ability to add a lambda function to an existing python project.
|
|
17
|
+
|
|
18
|
+
This generator creates a new python lambda handler with AWS CDK or Terraform infrastructure setup. The generated backend uses AWS Lambda for serverless deployment, with optional type-safety using the [Parser from AWS Lambda Powertools](https://docs.powertools.aws.dev/lambda/python/latest/utilities/parser/). It sets up [AWS Lambda Powertools](https://docs.powertools.aws.dev/lambda/python/latest/) for observability, including logging, AWS X-Ray tracing and Cloudwatch Metrics.
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Generate a Lambda Function
|
|
23
|
+
|
|
24
|
+
You can generate a new Lambda Function in two ways:
|
|
25
|
+
|
|
26
|
+
<RunGenerator generator="py#lambda-function" />
|
|
27
|
+
|
|
28
|
+
### Options
|
|
29
|
+
|
|
30
|
+
<GeneratorParameters generator="py#lambda-function" />
|
|
31
|
+
|
|
32
|
+
## Generator Output
|
|
33
|
+
|
|
34
|
+
The generator will add the following files to your project:
|
|
35
|
+
|
|
36
|
+
<FileTree>
|
|
37
|
+
|
|
38
|
+
- \<module-name>
|
|
39
|
+
- \<lambda-function>.py Function implementation
|
|
40
|
+
|
|
41
|
+
</FileTree>
|
|
42
|
+
|
|
43
|
+
If the `functionPath` option is provided, the generater will add the necessary files to the specified path:
|
|
44
|
+
|
|
45
|
+
<FileTree>
|
|
46
|
+
|
|
47
|
+
- \<module-name>
|
|
48
|
+
- \<custom-path>
|
|
49
|
+
- \<function-name>.py Function implementation
|
|
50
|
+
|
|
51
|
+
</FileTree>
|
|
52
|
+
|
|
53
|
+
### Infrastructure
|
|
54
|
+
|
|
55
|
+
<Snippet name="shared-constructs" />
|
|
56
|
+
|
|
57
|
+
The generator creates infrastructure as code for deploying your function based on your selected `iacProvider`:
|
|
58
|
+
|
|
59
|
+
<Infrastructure>
|
|
60
|
+
<Fragment slot="cdk">
|
|
61
|
+
The generator creates CDK constructs which can be used to deploy your function, which reside in the `packages/common/constructs` directory.
|
|
62
|
+
</Fragment>
|
|
63
|
+
<Fragment slot="terraform">
|
|
64
|
+
The generator creates a Terraform module which can be used to deploy your function, which resides in the `packages/common/terraform/src/app/lambda-functions/<function-name>` directory.
|
|
65
|
+
</Fragment>
|
|
66
|
+
</Infrastructure>
|
|
67
|
+
|
|
68
|
+
#### Architecture
|
|
69
|
+
|
|
70
|
+
<Snippet name="lambda-function/architecture" />
|
|
71
|
+
|
|
72
|
+
## Implementing your Function
|
|
73
|
+
|
|
74
|
+
The main function implementation is in `<function-name>.py`. Here's an example:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
import os
|
|
78
|
+
|
|
79
|
+
from aws_lambda_powertools import Logger, Metrics, Tracer
|
|
80
|
+
from aws_lambda_powertools.metrics import MetricUnit
|
|
81
|
+
from aws_lambda_powertools.utilities.parser import event_parser
|
|
82
|
+
from aws_lambda_powertools.utilities.parser.models import EventBridgeModel
|
|
83
|
+
from aws_lambda_powertools.utilities.typing import LambdaContext
|
|
84
|
+
|
|
85
|
+
os.environ["POWERTOOLS_METRICS_NAMESPACE"] = "Foo"
|
|
86
|
+
os.environ["POWERTOOLS_SERVICE_NAME"] = "Foo"
|
|
87
|
+
|
|
88
|
+
logger: Logger = Logger()
|
|
89
|
+
metrics: Metrics = Metrics()
|
|
90
|
+
tracer: Tracer = Tracer()
|
|
91
|
+
|
|
92
|
+
@tracer.capture_lambda_handler
|
|
93
|
+
@metrics.log_metrics
|
|
94
|
+
@event_parser(model=EventBridgeModel)
|
|
95
|
+
def lambda_handler(event: EventBridgeModel, context: LambdaContext):
|
|
96
|
+
logger.info("Received event", extra={"event": event.model_dump() })
|
|
97
|
+
metrics.add_metric(name="InvocationCount", unit=MetricUnit.Count, value=1)
|
|
98
|
+
|
|
99
|
+
try:
|
|
100
|
+
# TODO: Implement
|
|
101
|
+
metrics.add_metric(name="SuccessCount", unit=MetricUnit.Count, value=1)
|
|
102
|
+
# TODO: Implement success response if required
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.exception(e)
|
|
105
|
+
metrics.add_metric(name="ErrorCount", unit=MetricUnit.Count, value=1)
|
|
106
|
+
# TODO: Implement error response if required
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The generator sets up several features automatically:
|
|
110
|
+
|
|
111
|
+
1. AWS Lambda Powertools integration for observability
|
|
112
|
+
2. Metrics collection
|
|
113
|
+
3. Type-safety using `@event_parser`
|
|
114
|
+
|
|
115
|
+
### Observability with AWS Lambda Powertools
|
|
116
|
+
|
|
117
|
+
#### Logging
|
|
118
|
+
|
|
119
|
+
The generator configures structured logging using AWS Lambda Powertools.
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
def lambda_handler(event: EventBridgeModel, context: LambdaContext):
|
|
123
|
+
logger.info("Received event", extra={"event": event.model_dump()})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
:::tip[Correlation ID]
|
|
127
|
+
It is recommended to set the correlation id for all unique requests for easier debugging and monitoring. Please refer to the [aws powertools logger](https://docs.powertools.aws.dev/lambda/python/2.22.0/core/logger/#setting-a-correlation-id) documentation for correlation id best practices.
|
|
128
|
+
:::
|
|
129
|
+
|
|
130
|
+
The logger automatically includes:
|
|
131
|
+
|
|
132
|
+
- Event requests
|
|
133
|
+
- Lambda context information
|
|
134
|
+
- Cold start indicators
|
|
135
|
+
|
|
136
|
+
#### Tracing
|
|
137
|
+
|
|
138
|
+
AWS X-Ray tracing is configured automatically. You can add custom subsegments to your traces:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
def lambda_handler(event: EventBridgeModel, context: LambdaContext):
|
|
142
|
+
# Creates a new subsegment
|
|
143
|
+
with tracer.provider.in_subsegment("function-subsegment"):
|
|
144
|
+
# Your logic here
|
|
145
|
+
return ....
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### Metrics
|
|
149
|
+
|
|
150
|
+
CloudWatch metrics are collected automatically for each request. You can add custom metrics:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
def lambda_handler(event: EventBridgeModel, context: LambdaContext):
|
|
154
|
+
metrics.add_metric(name="NewMetric", unit=MetricUnit.Count, value=1)
|
|
155
|
+
return ...
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Default metrics include:
|
|
159
|
+
|
|
160
|
+
- Invocation counts
|
|
161
|
+
- Success/failure counts
|
|
162
|
+
- Cold start metrics
|
|
163
|
+
|
|
164
|
+
### Type Safety
|
|
165
|
+
|
|
166
|
+
<OptionFilter not when={{ eventSource: 'Any' }} description="Typed eventSource wires @event_parser with a Pydantic model">
|
|
167
|
+
If you chose an `eventSource` when generating your lambda function, your function is instrumented with [`@event_parser` from AWS Lambda Powertools](https://docs.powertools.aws.dev/lambda/python/latest/utilities/parser/). For example:
|
|
168
|
+
|
|
169
|
+
```python {3}
|
|
170
|
+
@event_parser(model=EventBridgeModel)
|
|
171
|
+
def lambda_handler(event: EventBridgeModel, context: LambdaContext):
|
|
172
|
+
event.detail_type # <- type-safe with IDE autocompletion
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
This allows you to define data models using [Pydantic](https://docs.pydantic.dev/latest/), in a similar manner to working with <Link path="guides/fastapi">Fast API</Link>.
|
|
176
|
+
|
|
177
|
+
:::tip[Custom Event Data]
|
|
178
|
+
If you have custom data nested within an event, for example a DynamoDB stream or EventBridge event, you may benefit from using [Envelopes](https://docs.powertools.aws.dev/lambda/python/latest/utilities/parser/#envelopes) to provide type-safety for that custom data.
|
|
179
|
+
:::
|
|
180
|
+
</OptionFilter>
|
|
181
|
+
|
|
182
|
+
<OptionFilter when={{ eventSource: 'Any' }} description="eventSource=Any — no parser decorator, event is untyped">
|
|
183
|
+
If you selected `Any` for your `eventSource`, the `@event_parser` decorator is not applied and the handler receives an untyped event dict. Regenerate with a specific `eventSource` if you want Pydantic validation and typed field access.
|
|
184
|
+
</OptionFilter>
|
|
185
|
+
|
|
186
|
+
## Bundling
|
|
187
|
+
|
|
188
|
+
The generator automatically configures Python bundling for Lambda deployment packages using [uv](https://docs.astral.sh/uv/):
|
|
189
|
+
|
|
190
|
+
<NxCommands commands={['bundle <project-name>']} />
|
|
191
|
+
|
|
192
|
+
:::note[Bundle Behavior]
|
|
193
|
+
This bundles the whole project as the deployment package. To minimise deployment size, you may wish to split multiple lambda functions over multiple Python projects generated with the <Link path="guides/python-project">`py#project`</Link> generator.
|
|
194
|
+
:::
|
|
195
|
+
|
|
196
|
+
This process uses:
|
|
197
|
+
|
|
198
|
+
1. [`uv export`](https://docs.astral.sh/uv/reference/cli/#uv-export) to export your Python dependencies to a `requirements.txt` file
|
|
199
|
+
2. [`uv pip install`](https://docs.astral.sh/uv/reference/cli/#uv-pip-install) to install dependencies for the target platform (`x86_64-manylinux_2_28`) for Lambda deployment
|
|
200
|
+
|
|
201
|
+
:::note[Architecture Changes]
|
|
202
|
+
If you change your [lambda architecture to ARM](https://docs.aws.amazon.com/lambda/latest/dg/foundation-arch.html), you will need to edit your bundle target to use the `aarch64-manylinux_2_28` target.
|
|
203
|
+
:::
|
|
204
|
+
|
|
205
|
+
## Deploying your Function
|
|
206
|
+
|
|
207
|
+
<Snippet name="lambda-function/deploying-your-function" parentHeading="Deploying your Function" />
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Python Projects
|
|
3
|
+
description: Reference documentation for Python Projects
|
|
4
|
+
generator: py#project
|
|
5
|
+
---
|
|
6
|
+
import { FileTree } from '@astrojs/starlight/components';
|
|
7
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
8
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
9
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
10
|
+
import PackageManagerShortCommand from '@components/package-manager-short-command.astro';
|
|
11
|
+
|
|
12
|
+
The Python project generator can be used to create a modern [Python](https://www.python.org/) library or application configured with best practices, managed with [UV](https://docs.astral.sh/uv/), a single lockfile and virtual environment in an [UV workspace](https://docs.astral.sh/uv/concepts/projects/workspaces/), [pytest](https://docs.pytest.org/en/stable/) for running tests, [Ruff](https://docs.astral.sh/ruff/) for static analysis, and [ty](https://docs.astral.sh/ty/) for type checking.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
### Generate a Python Project
|
|
17
|
+
|
|
18
|
+
You can generate a new Python project in two ways:
|
|
19
|
+
|
|
20
|
+
<RunGenerator generator="py#project" />
|
|
21
|
+
|
|
22
|
+
### Options
|
|
23
|
+
|
|
24
|
+
<GeneratorParameters generator="py#project" />
|
|
25
|
+
|
|
26
|
+
## Generator Output
|
|
27
|
+
|
|
28
|
+
The generator will create the following project structure in the `<directory>/<name>` directory:
|
|
29
|
+
|
|
30
|
+
<FileTree>
|
|
31
|
+
|
|
32
|
+
- \<module-name>
|
|
33
|
+
- \_\_init\_\_.py Module initialisation
|
|
34
|
+
- tests
|
|
35
|
+
- \_\_init\_\_.py Module initialisation
|
|
36
|
+
- conftest.py Test configuration
|
|
37
|
+
- test_noop.py Placeholder test
|
|
38
|
+
- project.json Project configuration and build targets
|
|
39
|
+
- pyproject.toml Packaging configuration file used by UV
|
|
40
|
+
- .python-version Contains the project's Python version
|
|
41
|
+
|
|
42
|
+
</FileTree>
|
|
43
|
+
|
|
44
|
+
You may also notice the following files created/updated in the root of your workspace:
|
|
45
|
+
|
|
46
|
+
<FileTree>
|
|
47
|
+
|
|
48
|
+
- pyproject.toml Workspace level packaging configuration for UV
|
|
49
|
+
- .python-version Contains the workspace Python version
|
|
50
|
+
- uv.lock Lockfile for Python dependencies
|
|
51
|
+
|
|
52
|
+
</FileTree>
|
|
53
|
+
|
|
54
|
+
## Writing Python Source Code
|
|
55
|
+
|
|
56
|
+
Add your Python source code in the `<module-name>` directory.
|
|
57
|
+
|
|
58
|
+
### Importing your Library Code in Other Projects
|
|
59
|
+
|
|
60
|
+
Use the `add` target to add a dependency to a Python project.
|
|
61
|
+
|
|
62
|
+
Suppose we have created two python projects, `my_app` and `my_lib`. These will have fully qualified project names of `my_scope.my_app` and `my_scope.my_lib`, and by default will each have module names of `my_scope_my_app` and `my_scope_my_lib`.
|
|
63
|
+
|
|
64
|
+
For `my_app` to depend on `my_lib`, we can run the following command:
|
|
65
|
+
|
|
66
|
+
<NxCommands commands={['run my_scope.my_app:add my_scope.my_lib']} />
|
|
67
|
+
|
|
68
|
+
:::note[Fully Qualified Names]
|
|
69
|
+
We use the fully qualified project name for both the dependant and dependee. We can use the shorthand syntax for the project we want to add the dependency to, but must fully qualify the name of the project to depend on.
|
|
70
|
+
:::
|
|
71
|
+
|
|
72
|
+
You can then import your library code:
|
|
73
|
+
|
|
74
|
+
```python title="packages/my_app/my_scope_my_app/main.py"
|
|
75
|
+
from my_scope_my_lib.my_module import my_function
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Above, `my_scope_my_lib` is the module name for the lib, `my_module` corresponds to a Python source file `my_module.py`, and `my_function` is a method defined in that file.
|
|
79
|
+
|
|
80
|
+
### Dependencies
|
|
81
|
+
|
|
82
|
+
To add dependencies to your project, you can run the `add` target in your Python project, for example:
|
|
83
|
+
|
|
84
|
+
<NxCommands commands={['run my_scope.my_library:add some-pip-package']} />
|
|
85
|
+
|
|
86
|
+
This will add the dependency to your project's `pyproject.toml` file, and update the root `uv.lock`.
|
|
87
|
+
|
|
88
|
+
#### Runtime Code
|
|
89
|
+
|
|
90
|
+
When you use your Python project as runtime code (for example as the handler for an AWS lambda function), you will need to create a bundle of the source code and all its dependencies. You can achieve this by adding a target such as the following to your `project.json` file:
|
|
91
|
+
|
|
92
|
+
```json title="project.json"
|
|
93
|
+
{
|
|
94
|
+
...
|
|
95
|
+
"targets": {
|
|
96
|
+
...
|
|
97
|
+
"bundle": {
|
|
98
|
+
"cache": true,
|
|
99
|
+
"executor": "nx:run-commands",
|
|
100
|
+
"outputs": ["{workspaceRoot}/dist/packages/my_library/bundle"],
|
|
101
|
+
"options": {
|
|
102
|
+
"commands": [
|
|
103
|
+
"uv export --frozen --no-dev --no-editable --project packages/my_library --package my_scope.my_library -o dist/packages/my_library/bundle/requirements.txt",
|
|
104
|
+
"uv pip install -n --no-deps --no-installer-metadata --no-compile-bytecode --python-platform x86_64-manylinux_2_28 --python `uv python pin` --target dist/packages/my_library/bundle -r dist/packages/my_library/bundle/requirements.txt"
|
|
105
|
+
],
|
|
106
|
+
"parallel": false
|
|
107
|
+
},
|
|
108
|
+
"dependsOn": ["compile"]
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Building
|
|
115
|
+
|
|
116
|
+
Your Python project is configured with a `build` target (defined in `project.json`), which you can run via:
|
|
117
|
+
|
|
118
|
+
<NxCommands commands={['build <project-name>']} />
|
|
119
|
+
|
|
120
|
+
Where `<project-name>` is the fully qualified name of your project.
|
|
121
|
+
|
|
122
|
+
The `build` target will compile, lint, test and type check your project.
|
|
123
|
+
|
|
124
|
+
Build output can be found in the root `dist` folder in your workspace, inside a directory for your package and target, for example `dist/packages/<my-library>/build`
|
|
125
|
+
|
|
126
|
+
To build all of the projects in your workspace, run:
|
|
127
|
+
|
|
128
|
+
<NxCommands commands={['run-many --target build']} />
|
|
129
|
+
|
|
130
|
+
Or use the shorthand command:
|
|
131
|
+
|
|
132
|
+
<PackageManagerShortCommand commands={["build"]} />
|
|
133
|
+
|
|
134
|
+
## Testing
|
|
135
|
+
|
|
136
|
+
[pytest](https://docs.pytest.org/en/stable/) is configured for testing your project.
|
|
137
|
+
|
|
138
|
+
### Writing Tests
|
|
139
|
+
|
|
140
|
+
Tests should be written in the `test` directory within your project, in python files prefixed with `test_`, for example:
|
|
141
|
+
|
|
142
|
+
<FileTree>
|
|
143
|
+
- my_library
|
|
144
|
+
- my_module.py
|
|
145
|
+
- tests
|
|
146
|
+
- test_my_module.py Tests for my_module.py
|
|
147
|
+
</FileTree>
|
|
148
|
+
|
|
149
|
+
Tests are methods which begin with `test_` and make assertions to verify expectations, for example:
|
|
150
|
+
|
|
151
|
+
```python title="tests/test_my_module.py"
|
|
152
|
+
from my_library.my_module import say_hello
|
|
153
|
+
|
|
154
|
+
def test_say_hello():
|
|
155
|
+
assert say_hello("Darth Vader") == "Hello, Darth Vader!"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
For more details about how to write tests, please refer to the [pytest documentation](https://docs.pytest.org/en/stable/how-to/assert.html#).
|
|
159
|
+
|
|
160
|
+
### Running Tests
|
|
161
|
+
|
|
162
|
+
Tests will run as part of the `build` target for your project, but you can also run them separately by running the `test` target:
|
|
163
|
+
|
|
164
|
+
<NxCommands commands={['test <project-name>']} />
|
|
165
|
+
|
|
166
|
+
You can run an individual test or suite of tests using the `-k` flag, specifying either the name of the test file or method:
|
|
167
|
+
|
|
168
|
+
<NxCommands commands={["test <project-name> -k 'test_say_hello'"]} />
|
|
169
|
+
|
|
170
|
+
## Type Checking
|
|
171
|
+
|
|
172
|
+
Python projects use [ty](https://docs.astral.sh/ty/) for type checking.
|
|
173
|
+
|
|
174
|
+
### Running the Type Checker
|
|
175
|
+
|
|
176
|
+
Type checking runs as part of the `build` target for your project, but you can also run it separately via the `typecheck` target:
|
|
177
|
+
|
|
178
|
+
<NxCommands commands={['run <project-name>:typecheck']} />
|
|
179
|
+
|
|
180
|
+
### Suppressing Type Errors
|
|
181
|
+
|
|
182
|
+
To suppress a specific diagnostic for a single line, add a `# ty: ignore[<rule>]` comment at the end of the line, for example:
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
value: int = "not an int" # ty: ignore[invalid-assignment]
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
To configure type checking behaviour across your project, add a `[tool.ty]` section to your project's `pyproject.toml`. Refer to the [ty configuration reference](https://docs.astral.sh/ty/reference/configuration/) for available options.
|
|
189
|
+
|
|
190
|
+
## Linting
|
|
191
|
+
|
|
192
|
+
Python projects use [Ruff](https://docs.astral.sh/ruff/) for linting.
|
|
193
|
+
|
|
194
|
+
### Running the Linter
|
|
195
|
+
|
|
196
|
+
To invoke the linter to check your project, you can run the `lint` target.
|
|
197
|
+
|
|
198
|
+
<NxCommands commands={["lint <project-name>"]} />
|
|
199
|
+
|
|
200
|
+
### Fixing Lint Issues
|
|
201
|
+
|
|
202
|
+
The majority of linting or formatting issues can be fixed automatically. You can tell Ruff to fix lint issues by running with the `--configuration=fix` argument.
|
|
203
|
+
|
|
204
|
+
<NxCommands commands={["lint <project-name> --configuration=fix"]} />
|
|
205
|
+
|
|
206
|
+
Similarly if you would like to fix all lint issues in all packages in your workspace, you can run:
|
|
207
|
+
|
|
208
|
+
<NxCommands commands={["run-many --target lint --all --configuration=fix"]} />
|
|
209
|
+
|
|
210
|
+
:::tip[Shorthand Command]
|
|
211
|
+
This has a shorthand command from the root of your workspace:
|
|
212
|
+
|
|
213
|
+
<PackageManagerShortCommand commands={["lint"]} />
|
|
214
|
+
:::
|
|
215
|
+
|
|
216
|
+
### Skipping Lint Issues
|
|
217
|
+
|
|
218
|
+
To avoid linting issues slowing you down during development (particularly if you have non auto-fixable issues in your project), you can run a build with the `skip-lint` configuration:
|
|
219
|
+
|
|
220
|
+
<NxCommands commands={["run-many --target build --configuration=skip-lint"]} />
|
|
221
|
+
|
|
222
|
+
This will still run Ruff as part of the build, but the lint target will always be considered successful.
|
|
223
|
+
|
|
224
|
+
:::tip[Shorthand Command]
|
|
225
|
+
This has a shorthand command from the root of your workspace:
|
|
226
|
+
|
|
227
|
+
<PackageManagerShortCommand commands={["build:skip-lint"]} />
|
|
228
|
+
:::
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: React Website Authentication
|
|
3
|
+
description: Reference documentation for React Website Authentication
|
|
4
|
+
generator: ts#react-website#auth
|
|
5
|
+
---
|
|
6
|
+
import { FileTree } from '@astrojs/starlight/components';
|
|
7
|
+
import Link from '@components/link.astro';
|
|
8
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
9
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
10
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
11
|
+
import Infrastructure from '@components/infrastructure.astro';
|
|
12
|
+
import Snippet from '@components/snippet.astro';
|
|
13
|
+
|
|
14
|
+
The React Website Authentication generator adds authentication to your React website using [Amazon Cognito](https://aws.amazon.com/cognito/).
|
|
15
|
+
|
|
16
|
+
This generator configures the CDK or Terraform infrastructure to create a Cognito User Pool and associated Identity Pool, as well as a hosted UI for handling user login flows, and its integration with your React website.
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Add Authentication to your React Website
|
|
21
|
+
|
|
22
|
+
You can add authentication to your React website in two ways:
|
|
23
|
+
|
|
24
|
+
<RunGenerator generator="ts#react-website#auth" />
|
|
25
|
+
|
|
26
|
+
### Options
|
|
27
|
+
|
|
28
|
+
<GeneratorParameters generator="ts#react-website#auth" />
|
|
29
|
+
|
|
30
|
+
## Generator Output
|
|
31
|
+
|
|
32
|
+
You will find the following changes in your React website:
|
|
33
|
+
|
|
34
|
+
<FileTree>
|
|
35
|
+
- src
|
|
36
|
+
- components
|
|
37
|
+
- CognitoAuth
|
|
38
|
+
- index.tsx Main authentication component
|
|
39
|
+
- main.tsx Updated to instrument the CognitoAuth component
|
|
40
|
+
</FileTree>
|
|
41
|
+
|
|
42
|
+
### Infrastructure
|
|
43
|
+
|
|
44
|
+
<Snippet name="shared-constructs" />
|
|
45
|
+
|
|
46
|
+
You will also find the following infrastructure code generated based on your selected `iacProvider`:
|
|
47
|
+
|
|
48
|
+
<Infrastructure>
|
|
49
|
+
<Fragment slot="cdk">
|
|
50
|
+
<FileTree>
|
|
51
|
+
- packages/common/constructs/src
|
|
52
|
+
- core
|
|
53
|
+
- user-identity.ts Construct which defines the user pool and identity pool
|
|
54
|
+
</FileTree>
|
|
55
|
+
</Fragment>
|
|
56
|
+
<Fragment slot="terraform">
|
|
57
|
+
<FileTree>
|
|
58
|
+
- packages/common/terraform/src
|
|
59
|
+
- core
|
|
60
|
+
- user-identity
|
|
61
|
+
- main.tf Module wrapper for the identity configuration
|
|
62
|
+
- identity
|
|
63
|
+
- identity.tf Core identity infrastructure including Cognito User Pool and Identity Pool
|
|
64
|
+
- add-callback-url
|
|
65
|
+
- add-callback-url.tf Module for adding callback URLs to existing user pool clients
|
|
66
|
+
</FileTree>
|
|
67
|
+
</Fragment>
|
|
68
|
+
</Infrastructure>
|
|
69
|
+
|
|
70
|
+
#### Architecture
|
|
71
|
+
|
|
72
|
+
This generator adds an Amazon Cognito user pool (for sign-in) and an identity pool (for federating signed-in users to scoped IAM credentials) to the existing static-website architecture:
|
|
73
|
+
|
|
74
|
+
```d2 inline=true
|
|
75
|
+
direction: right
|
|
76
|
+
|
|
77
|
+
browser: Web Browser {
|
|
78
|
+
shape: image
|
|
79
|
+
icon: /nx-plugin-for-aws/icons/aws/client.svg
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
cognito: Cognito\n(User + Identity Pool) {
|
|
83
|
+
shape: image
|
|
84
|
+
icon: /nx-plugin-for-aws/icons/aws/cognito.svg
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
iam: Scoped IAM\nCredentials {
|
|
88
|
+
shape: image
|
|
89
|
+
icon: /nx-plugin-for-aws/icons/aws/iam.svg
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
backend: Authenticated\nAWS Resources {
|
|
93
|
+
shape: rectangle
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
browser -> cognito: Sign in
|
|
97
|
+
cognito -> iam
|
|
98
|
+
browser -> backend: IAM/Cognito
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Infrastructure Usage
|
|
102
|
+
|
|
103
|
+
<Infrastructure>
|
|
104
|
+
<Fragment slot="cdk">
|
|
105
|
+
You will need to add the user identity infrastructure to your stack, declaring it _before_ the website:
|
|
106
|
+
|
|
107
|
+
```ts title="packages/infra/src/stacks/application-stack.ts" {3,9}
|
|
108
|
+
import { Stack } from 'aws-cdk-lib';
|
|
109
|
+
import { Construct } from 'constructs';
|
|
110
|
+
import { MyWebsite, UserIdentity } from ':my-scope/common-constructs';
|
|
111
|
+
|
|
112
|
+
export class ApplicationStack extends Stack {
|
|
113
|
+
constructor(scope: Construct, id: string) {
|
|
114
|
+
super(scope, id);
|
|
115
|
+
|
|
116
|
+
new UserIdentity(this, 'Identity');
|
|
117
|
+
|
|
118
|
+
new MyWebsite(this, 'MyWebsite');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The `UserIdentity` construct automatically adds the necessary <Link path="guides/react-website#runtime-configuration">Runtime Configuration</Link> to ensure that your website can point to the correct Cognito User Pool for authentication.
|
|
124
|
+
|
|
125
|
+
:::note[SMS role retention]
|
|
126
|
+
The User Pool is backed by an IAM role that Cognito assumes to send SMS messages. The role's removal policy mirrors the User Pool's — by default CDK's `UserPool` uses `RemovalPolicy.RETAIN`, so on `cdk destroy` both the User Pool and its SMS role are retained and will need to be cleaned up manually if no longer needed.
|
|
127
|
+
:::
|
|
128
|
+
</Fragment>
|
|
129
|
+
<Fragment slot="terraform">
|
|
130
|
+
You will need to add the user identity module, and ensure your website depends on it:
|
|
131
|
+
|
|
132
|
+
```hcl title="packages/infra/src/main.tf" {2-4,14-15}
|
|
133
|
+
# Deploy user identity first to add to runtime config
|
|
134
|
+
module "user_identity" {
|
|
135
|
+
source = "../../common/terraform/src/core/user-identity"
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
# Deploy website after identity to include runtime config
|
|
139
|
+
module "my_website" {
|
|
140
|
+
source = "../../common/terraform/src/app/static-websites/my-website"
|
|
141
|
+
|
|
142
|
+
providers = {
|
|
143
|
+
aws.us_east_1 = aws.us_east_1
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Ensure identity is deployed first to add to runtime config
|
|
147
|
+
depends_on = [module.user_identity]
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The user identity module automatically adds the necessary <Link path="guides/react-website#runtime-configuration">Runtime Configuration</Link> to ensure that your website can point to the correct Cognito User Pool for authentication.
|
|
152
|
+
</Fragment>
|
|
153
|
+
</Infrastructure>
|
|
154
|
+
|
|
155
|
+
### Granting Access to Authenticated Users
|
|
156
|
+
|
|
157
|
+
In order to grant authenticated users access to perform certain actions, such as granting permissions to invoke an API, you can add IAM policy statements to the identity pool authenticated role:
|
|
158
|
+
|
|
159
|
+
<Infrastructure>
|
|
160
|
+
<Fragment slot="cdk">
|
|
161
|
+
```ts title="packages/infra/src/stacks/application-stack.ts" {12}
|
|
162
|
+
import { Stack } from 'aws-cdk-lib';
|
|
163
|
+
import { Construct } from 'constructs';
|
|
164
|
+
import { MyWebsite, UserIdentity, MyApi } from ':my-scope/common-constructs';
|
|
165
|
+
|
|
166
|
+
export class ApplicationStack extends Stack {
|
|
167
|
+
constructor(scope: Construct, id: string) {
|
|
168
|
+
super(scope, id);
|
|
169
|
+
|
|
170
|
+
const identity = new UserIdentity(this, 'Identity');
|
|
171
|
+
const api = new MyApi(this, 'MyApi');
|
|
172
|
+
|
|
173
|
+
api.grantInvokeAccess(identity.identityPool.authenticatedRole);
|
|
174
|
+
|
|
175
|
+
new MyWebsite(this, 'MyWebsite');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
</Fragment>
|
|
180
|
+
<Fragment slot="terraform">
|
|
181
|
+
```hcl title="packages/infra/src/main.tf" {16,26}
|
|
182
|
+
module "user_identity" {
|
|
183
|
+
source = "../../common/terraform/src/core/user-identity"
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
module "asset_bucket" {
|
|
187
|
+
source = "../../common/terraform/src/core/asset-bucket"
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module "my_api" {
|
|
191
|
+
source = "../../common/terraform/src/app/apis/my-api"
|
|
192
|
+
|
|
193
|
+
asset_bucket_name = module.asset_bucket.bucket_name
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
# Add permissions for authenticated users to invoke Fast API
|
|
197
|
+
resource "aws_iam_role_policy" "authenticated_fast_api_invoke" {
|
|
198
|
+
name = "authenticated-user-invoke-my-api"
|
|
199
|
+
role = module.user_identity.authenticated_role_name
|
|
200
|
+
|
|
201
|
+
policy = jsonencode({
|
|
202
|
+
Version = "2012-10-17"
|
|
203
|
+
Statement = [
|
|
204
|
+
{
|
|
205
|
+
Effect = "Allow"
|
|
206
|
+
Action = [
|
|
207
|
+
"execute-api:Invoke"
|
|
208
|
+
]
|
|
209
|
+
Resource = "${module.my_api.api_execution_arn}/*"
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
})
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
</Fragment>
|
|
216
|
+
</Infrastructure>
|