@aws/nx-plugin 0.79.1 → 0.80.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/LICENSE-THIRD-PARTY +69 -11
- package/package.json +1 -1
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +298 -57
- package/src/py/fast-api/files/app/__name__/init.py.template +61 -16
- package/src/py/fast-api/files/app/__name__/main.py.template +6 -3
- package/src/py/fast-api/files/app/run.sh.template +2 -0
- package/src/py/fast-api/generator.js +10 -2
- package/src/py/fast-api/generator.js.map +1 -1
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +12 -0
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +15 -0
- package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +28 -2
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +30 -4
- package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +44 -2
- package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +62 -2
- package/src/utils/versions.d.ts +0 -1
- package/src/utils/versions.js +0 -1
- package/src/utils/versions.js.map +1 -1
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import os
|
|
2
3
|
import uuid
|
|
3
|
-
from collections.abc import Callable
|
|
4
|
+
from collections.abc import AsyncIterator, Callable
|
|
5
|
+
from typing import Any
|
|
4
6
|
from urllib.parse import urlparse
|
|
5
7
|
|
|
6
8
|
from aws_lambda_powertools import Logger, Metrics, Tracer
|
|
7
9
|
from aws_lambda_powertools.metrics import MetricUnit
|
|
8
10
|
from fastapi import FastAPI, Request, Response
|
|
9
11
|
from fastapi.openapi.utils import get_openapi
|
|
10
|
-
from fastapi.responses import JSONResponse
|
|
12
|
+
from fastapi.responses import JSONResponse, StreamingResponse
|
|
11
13
|
from fastapi.routing import APIRoute
|
|
12
|
-
from mangum import Mangum
|
|
13
14
|
from pydantic import BaseModel
|
|
14
15
|
from starlette.middleware.exceptions import ExceptionMiddleware
|
|
15
16
|
|
|
@@ -25,16 +26,54 @@ class InternalServerErrorDetails(BaseModel):
|
|
|
25
26
|
detail: str
|
|
26
27
|
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
class JsonStreamingResponse(StreamingResponse):
|
|
30
|
+
"""A streaming response that serializes items to JSON Lines format."""
|
|
31
|
+
|
|
32
|
+
media_type = "application/jsonl"
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
content: AsyncIterator[BaseModel],
|
|
37
|
+
status_code: int = 200,
|
|
38
|
+
headers: dict[str, str] | None = None,
|
|
39
|
+
**kwargs: Any,
|
|
40
|
+
) -> None:
|
|
41
|
+
"""Stream json lines from an async iterator yielding Pydantic models"""
|
|
42
|
+
super().__init__(
|
|
43
|
+
content=self._serialize(content),
|
|
44
|
+
status_code=status_code,
|
|
45
|
+
headers=headers,
|
|
46
|
+
media_type=self.media_type,
|
|
47
|
+
**kwargs,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
async def _serialize(
|
|
52
|
+
content: AsyncIterator[BaseModel],
|
|
53
|
+
) -> AsyncIterator[bytes]:
|
|
54
|
+
"""Serialize Pydantic models to JSON Lines format."""
|
|
55
|
+
async for item in content:
|
|
56
|
+
yield (item.model_dump_json() + "\n").encode("utf-8")
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def openapi_response(
|
|
60
|
+
item_model: type[BaseModel],
|
|
61
|
+
description: str = "Streaming response",
|
|
62
|
+
) -> dict[str, Any]:
|
|
63
|
+
"""Generate an OpenAPI application/jsonl response for a stream of the given model"""
|
|
64
|
+
return {
|
|
65
|
+
"description": description,
|
|
66
|
+
"content": {
|
|
67
|
+
"application/jsonl": {
|
|
68
|
+
"itemSchema": {"$ref": f"#/components/schemas/{item_model.__name__}"},
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
# Include the model so FastAPI registers the schema in components/schemas
|
|
72
|
+
"model": item_model,
|
|
73
|
+
}
|
|
74
|
+
|
|
30
75
|
|
|
31
|
-
|
|
32
|
-
lambda_handler.__name__ = "handler" # tracer requires __name__ to be set
|
|
33
|
-
lambda_handler = tracer.capture_lambda_handler(lambda_handler)
|
|
34
|
-
# Add logging
|
|
35
|
-
lambda_handler = logger.inject_lambda_context(lambda_handler, clear_state=True)
|
|
36
|
-
# Add metrics last to properly flush metrics.
|
|
37
|
-
lambda_handler = metrics.log_metrics(lambda_handler, capture_cold_start_metric=True)
|
|
76
|
+
app = FastAPI(title="<%= apiNameClassName %>", responses={500: {"model": InternalServerErrorDetails}})
|
|
38
77
|
|
|
39
78
|
|
|
40
79
|
# Add cors middleware
|
|
@@ -92,10 +131,16 @@ async def metrics_handler(request: Request, call_next):
|
|
|
92
131
|
async def add_correlation_id(request: Request, call_next):
|
|
93
132
|
# Get correlation id from X-Correlation-Id header
|
|
94
133
|
corr_id = request.headers.get("x-correlation-id")
|
|
95
|
-
if not corr_id
|
|
96
|
-
#
|
|
97
|
-
|
|
98
|
-
|
|
134
|
+
if not corr_id:
|
|
135
|
+
# Try to get request id from Lambda context (forwarded by Lambda Web Adapter)
|
|
136
|
+
lambda_context_header = request.headers.get("x-amzn-lambda-context")
|
|
137
|
+
if lambda_context_header:
|
|
138
|
+
try:
|
|
139
|
+
lambda_context = json.loads(lambda_context_header)
|
|
140
|
+
corr_id = lambda_context.get("request_id")
|
|
141
|
+
except (json.JSONDecodeError, KeyError):
|
|
142
|
+
pass
|
|
143
|
+
if not corr_id:
|
|
99
144
|
# If still empty, use uuid
|
|
100
145
|
corr_id = uuid.uuid4().hex
|
|
101
146
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import uvicorn
|
|
1
2
|
from pydantic import BaseModel
|
|
2
3
|
|
|
3
|
-
from .init import app,
|
|
4
|
-
|
|
5
|
-
handler = lambda_handler
|
|
4
|
+
from .init import app, tracer
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
class EchoOutput(BaseModel):
|
|
@@ -13,3 +12,7 @@ class EchoOutput(BaseModel):
|
|
|
13
12
|
@tracer.capture_method
|
|
14
13
|
def echo(message: str) -> EchoOutput:
|
|
15
14
|
return EchoOutput(message=f"{message}")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
uvicorn.run("<%- name %>.main:app", port=8000)
|
|
@@ -16,6 +16,7 @@ const object_1 = require("../../utils/object");
|
|
|
16
16
|
const nx_1 = require("../../utils/nx");
|
|
17
17
|
const metrics_1 = require("../../utils/metrics");
|
|
18
18
|
const api_constructs_1 = require("../../utils/api-constructs/api-constructs");
|
|
19
|
+
const fs_1 = require("../../utils/fs");
|
|
19
20
|
const open_api_1 = require("./react/open-api");
|
|
20
21
|
const port_1 = require("../../utils/port");
|
|
21
22
|
const bundle_1 = require("../../utils/bundle/bundle");
|
|
@@ -46,7 +47,14 @@ const pyFastApiProjectGenerator = (tree, schema) => tslib_1.__awaiter(void 0, vo
|
|
|
46
47
|
});
|
|
47
48
|
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, fullyQualifiedName);
|
|
48
49
|
const port = (0, port_1.assignPort)(tree, projectConfig, 8000);
|
|
49
|
-
const { bundleOutputDir } = (0, bundle_1.addPythonBundleTarget)(projectConfig);
|
|
50
|
+
const { bundleOutputDir, bundleTargetName } = (0, bundle_1.addPythonBundleTarget)(projectConfig);
|
|
51
|
+
// Add a command to copy run.sh to the bundle output for Lambda Web Adapter
|
|
52
|
+
const fs = new fs_1.FsCommands(tree);
|
|
53
|
+
const bundleTarget = projectConfig.targets[bundleTargetName];
|
|
54
|
+
bundleTarget.options.commands = [
|
|
55
|
+
...bundleTarget.options.commands,
|
|
56
|
+
fs.cp(`{projectRoot}/run.sh`, `dist/{projectRoot}/${bundleTargetName}/run.sh`),
|
|
57
|
+
];
|
|
50
58
|
projectConfig.targets.serve = {
|
|
51
59
|
executor: '@nxlv/python:run-commands',
|
|
52
60
|
options: {
|
|
@@ -96,7 +104,7 @@ const pyFastApiProjectGenerator = (tree, schema) => tslib_1.__awaiter(void 0, vo
|
|
|
96
104
|
});
|
|
97
105
|
(0, py_1.addDependenciesToPyProjectToml)(tree, dir, [
|
|
98
106
|
'fastapi',
|
|
99
|
-
'
|
|
107
|
+
'uvicorn',
|
|
100
108
|
'aws-lambda-powertools',
|
|
101
109
|
'aws-lambda-powertools[tracer]',
|
|
102
110
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../packages/nx-plugin/src/py/fast-api/generator.ts"],"names":[],"mappings":";;;;AAAA;;;GAGG;AACH,uCAUoB;AAEpB,yDAA6D;AAC7D,0EAA+E;AAC/E,qEAA0E;AAC1E,6CAA6D;AAC7D,+CAA0D;AAC1D,+CAAoD;AACpD,uCAIwB;AACxB,iDAAsE;AACtE,8EAA+E;AAC/E,+CAAwD;AACxD,2CAA8C;AAC9C,sDAAkE;AAClE,uCAGwB;AACxB,yCAAqD;AACrD,oFAAgH;AAEnG,QAAA,uBAAuB,GAClC,IAAA,qBAAgB,EAAC,UAAU,CAAC,CAAC;AAE/B;;GAEG;AACI,MAAM,yBAAyB,GAAG,CACvC,IAAU,EACV,MAAuC,EACX,EAAE;IAC9B,MAAM,WAAW,GAAG,MAAM,IAAA,wBAAkB,EAAC,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvE,MAAM,IAAA,6CAAyB,EAAC,IAAI,EAAE;QACpC,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,EAAE,GAAG,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,GAAG,IAAA,+BAAmB,EAC3E,IAAI,EACJ;QACE,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CACF,CAAC;IACF,MAAM,gBAAgB,GAAG,IAAA,mBAAW,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,gBAAgB,GAAG,IAAA,mBAAW,EAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAElD,MAAM,IAAA,mBAAkB,EAAC,IAAI,EAAE;QAC7B,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,UAAU,EAAE,oBAAoB;QAChC,WAAW,EAAE,aAAa;KAC3B,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,IAAA,iCAAwB,EAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,IAAA,iBAAU,EAAC,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;IAEnD,MAAM,EAAE,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../../../../../../packages/nx-plugin/src/py/fast-api/generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -643,6 +643,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
643
643
|
mode = "Active"
|
|
644
644
|
}
|
|
645
645
|
|
|
646
|
+
|
|
646
647
|
environment {
|
|
647
648
|
variables = merge({
|
|
648
649
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -706,6 +707,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
706
707
|
}
|
|
707
708
|
|
|
708
709
|
|
|
710
|
+
|
|
709
711
|
# Create proxy resource (captures all paths)
|
|
710
712
|
resource "aws_api_gateway_resource" "proxy_resource" {
|
|
711
713
|
rest_api_id = module.rest_api.api_id
|
|
@@ -867,6 +869,7 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
|
|
|
867
869
|
depends_on = [module.rest_api, aws_lambda_function.api_lambda]
|
|
868
870
|
}
|
|
869
871
|
|
|
872
|
+
|
|
870
873
|
# Add API url to runtime config
|
|
871
874
|
module "add_url_to_runtime_config" {
|
|
872
875
|
source = "../../../core/runtime-config/entry"
|
|
@@ -1666,6 +1669,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
1666
1669
|
mode = "Active"
|
|
1667
1670
|
}
|
|
1668
1671
|
|
|
1672
|
+
|
|
1669
1673
|
environment {
|
|
1670
1674
|
variables = merge({
|
|
1671
1675
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -1728,6 +1732,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
1728
1732
|
tags = var.tags
|
|
1729
1733
|
}
|
|
1730
1734
|
|
|
1735
|
+
|
|
1731
1736
|
# Cognito User Pool Authorizer
|
|
1732
1737
|
resource "aws_api_gateway_authorizer" "cognito_authorizer" {
|
|
1733
1738
|
name = "TestApiAuthorizer"
|
|
@@ -1897,6 +1902,7 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
|
|
|
1897
1902
|
depends_on = [module.rest_api, aws_lambda_function.api_lambda]
|
|
1898
1903
|
}
|
|
1899
1904
|
|
|
1905
|
+
|
|
1900
1906
|
# Add API url to runtime config
|
|
1901
1907
|
module "add_url_to_runtime_config" {
|
|
1902
1908
|
source = "../../../core/runtime-config/entry"
|
|
@@ -2292,6 +2298,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
2292
2298
|
mode = "Active"
|
|
2293
2299
|
}
|
|
2294
2300
|
|
|
2301
|
+
|
|
2295
2302
|
environment {
|
|
2296
2303
|
variables = merge({
|
|
2297
2304
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -2355,6 +2362,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
2355
2362
|
}
|
|
2356
2363
|
|
|
2357
2364
|
|
|
2365
|
+
|
|
2358
2366
|
# Create proxy resource (captures all paths)
|
|
2359
2367
|
resource "aws_api_gateway_resource" "proxy_resource" {
|
|
2360
2368
|
rest_api_id = module.rest_api.api_id
|
|
@@ -2525,6 +2533,7 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
|
|
|
2525
2533
|
depends_on = [module.rest_api, aws_lambda_function.api_lambda]
|
|
2526
2534
|
}
|
|
2527
2535
|
|
|
2536
|
+
|
|
2528
2537
|
# Add API url to runtime config
|
|
2529
2538
|
module "add_url_to_runtime_config" {
|
|
2530
2539
|
source = "../../../core/runtime-config/entry"
|
|
@@ -2769,6 +2778,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
2769
2778
|
mode = "Active"
|
|
2770
2779
|
}
|
|
2771
2780
|
|
|
2781
|
+
|
|
2772
2782
|
environment {
|
|
2773
2783
|
variables = merge({
|
|
2774
2784
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -2832,6 +2842,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
2832
2842
|
}
|
|
2833
2843
|
|
|
2834
2844
|
|
|
2845
|
+
|
|
2835
2846
|
# Create proxy resource (captures all paths)
|
|
2836
2847
|
resource "aws_api_gateway_resource" "proxy_resource" {
|
|
2837
2848
|
rest_api_id = module.rest_api.api_id
|
|
@@ -2993,6 +3004,7 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
|
|
|
2993
3004
|
depends_on = [module.rest_api, aws_lambda_function.api_lambda]
|
|
2994
3005
|
}
|
|
2995
3006
|
|
|
3007
|
+
|
|
2996
3008
|
# Add API url to runtime config
|
|
2997
3009
|
module "add_url_to_runtime_config" {
|
|
2998
3010
|
source = "../../../core/runtime-config/entry"
|
|
@@ -2709,6 +2709,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
2709
2709
|
mode = "Active"
|
|
2710
2710
|
}
|
|
2711
2711
|
|
|
2712
|
+
|
|
2712
2713
|
environment {
|
|
2713
2714
|
variables = merge({
|
|
2714
2715
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -2771,6 +2772,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
2771
2772
|
tags = var.tags
|
|
2772
2773
|
}
|
|
2773
2774
|
|
|
2775
|
+
|
|
2774
2776
|
# Cognito User Pool Authorizer
|
|
2775
2777
|
resource "aws_apigatewayv2_authorizer" "cognito_authorizer" {
|
|
2776
2778
|
api_id = module.http_api.api_id
|
|
@@ -3329,6 +3331,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
3329
3331
|
mode = "Active"
|
|
3330
3332
|
}
|
|
3331
3333
|
|
|
3334
|
+
|
|
3332
3335
|
environment {
|
|
3333
3336
|
variables = merge({
|
|
3334
3337
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -3392,6 +3395,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
3392
3395
|
}
|
|
3393
3396
|
|
|
3394
3397
|
|
|
3398
|
+
|
|
3395
3399
|
# Lambda integration for HTTP API
|
|
3396
3400
|
resource "aws_apigatewayv2_integration" "lambda_integration" {
|
|
3397
3401
|
api_id = module.http_api.api_id
|
|
@@ -3936,6 +3940,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
3936
3940
|
mode = "Active"
|
|
3937
3941
|
}
|
|
3938
3942
|
|
|
3943
|
+
|
|
3939
3944
|
environment {
|
|
3940
3945
|
variables = merge({
|
|
3941
3946
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -3999,6 +4004,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
3999
4004
|
}
|
|
4000
4005
|
|
|
4001
4006
|
|
|
4007
|
+
|
|
4002
4008
|
# Lambda integration for HTTP API
|
|
4003
4009
|
resource "aws_apigatewayv2_integration" "lambda_integration" {
|
|
4004
4010
|
api_id = module.http_api.api_id
|
|
@@ -4433,6 +4439,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
4433
4439
|
mode = "Active"
|
|
4434
4440
|
}
|
|
4435
4441
|
|
|
4442
|
+
|
|
4436
4443
|
environment {
|
|
4437
4444
|
variables = merge({
|
|
4438
4445
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -4495,6 +4502,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
4495
4502
|
tags = var.tags
|
|
4496
4503
|
}
|
|
4497
4504
|
|
|
4505
|
+
|
|
4498
4506
|
# Cognito User Pool Authorizer
|
|
4499
4507
|
resource "aws_api_gateway_authorizer" "cognito_authorizer" {
|
|
4500
4508
|
name = "TestApiAuthorizer"
|
|
@@ -4665,6 +4673,7 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
|
|
|
4665
4673
|
depends_on = [module.rest_api, aws_lambda_function.api_lambda]
|
|
4666
4674
|
}
|
|
4667
4675
|
|
|
4676
|
+
|
|
4668
4677
|
# Add API url to runtime config
|
|
4669
4678
|
module "add_url_to_runtime_config" {
|
|
4670
4679
|
source = "../../../core/runtime-config/entry"
|
|
@@ -5060,6 +5069,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
5060
5069
|
mode = "Active"
|
|
5061
5070
|
}
|
|
5062
5071
|
|
|
5072
|
+
|
|
5063
5073
|
environment {
|
|
5064
5074
|
variables = merge({
|
|
5065
5075
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -5123,6 +5133,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
5123
5133
|
}
|
|
5124
5134
|
|
|
5125
5135
|
|
|
5136
|
+
|
|
5126
5137
|
# Create proxy resource (captures all paths)
|
|
5127
5138
|
resource "aws_api_gateway_resource" "proxy_resource" {
|
|
5128
5139
|
rest_api_id = module.rest_api.api_id
|
|
@@ -5294,6 +5305,7 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
|
|
|
5294
5305
|
depends_on = [module.rest_api, aws_lambda_function.api_lambda]
|
|
5295
5306
|
}
|
|
5296
5307
|
|
|
5308
|
+
|
|
5297
5309
|
# Add API url to runtime config
|
|
5298
5310
|
module "add_url_to_runtime_config" {
|
|
5299
5311
|
source = "../../../core/runtime-config/entry"
|
|
@@ -5689,6 +5701,7 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
5689
5701
|
mode = "Active"
|
|
5690
5702
|
}
|
|
5691
5703
|
|
|
5704
|
+
|
|
5692
5705
|
environment {
|
|
5693
5706
|
variables = merge({
|
|
5694
5707
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
@@ -5752,6 +5765,7 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
5752
5765
|
}
|
|
5753
5766
|
|
|
5754
5767
|
|
|
5768
|
+
|
|
5755
5769
|
# Create proxy resource (captures all paths)
|
|
5756
5770
|
resource "aws_api_gateway_resource" "proxy_resource" {
|
|
5757
5771
|
rest_api_id = module.rest_api.api_id
|
|
@@ -5914,6 +5928,7 @@ resource "aws_lambda_permission" "api_gateway_invoke" {
|
|
|
5914
5928
|
depends_on = [module.rest_api, aws_lambda_function.api_lambda]
|
|
5915
5929
|
}
|
|
5916
5930
|
|
|
5931
|
+
|
|
5917
5932
|
# Add API url to runtime config
|
|
5918
5933
|
module "add_url_to_runtime_config" {
|
|
5919
5934
|
source = "../../../core/runtime-config/entry"
|
|
@@ -7,8 +7,12 @@ import {
|
|
|
7
7
|
Function,
|
|
8
8
|
FunctionProps,
|
|
9
9
|
Tracing,
|
|
10
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
11
|
+
LayerVersion,
|
|
12
|
+
SnapStartConf,
|
|
13
|
+
<%_ } _%>
|
|
10
14
|
} from 'aws-cdk-lib/aws-lambda';
|
|
11
|
-
import { Duration } from 'aws-cdk-lib';
|
|
15
|
+
import { Duration<%_ if (backend.type === 'fastapi') { _%>, Stack<%_ } _%> } from 'aws-cdk-lib';
|
|
12
16
|
import {
|
|
13
17
|
CorsHttpMethod,
|
|
14
18
|
CfnApi,
|
|
@@ -109,7 +113,7 @@ export class <%= apiNameClassName %><
|
|
|
109
113
|
),
|
|
110
114
|
<%_ } else if (backend.type === 'fastapi') { _%>
|
|
111
115
|
runtime: Runtime.PYTHON_3_12,
|
|
112
|
-
handler: '
|
|
116
|
+
handler: 'run.sh',
|
|
113
117
|
code: Code.fromAsset(
|
|
114
118
|
url.fileURLToPath(
|
|
115
119
|
new URL(
|
|
@@ -121,15 +125,37 @@ export class <%= apiNameClassName %><
|
|
|
121
125
|
<%_ } _%>
|
|
122
126
|
timeout: Duration.seconds(30),
|
|
123
127
|
tracing: Tracing.ACTIVE,
|
|
128
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
129
|
+
snapStart: SnapStartConf.ON_PUBLISHED_VERSIONS,
|
|
130
|
+
<%_ } _%>
|
|
124
131
|
environment: {
|
|
125
132
|
AWS_CONNECTION_REUSE_ENABLED: '1',
|
|
133
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
134
|
+
PORT: '8000',
|
|
135
|
+
AWS_LWA_INVOKE_MODE: 'buffered',
|
|
136
|
+
AWS_LAMBDA_EXEC_WRAPPER: '/opt/bootstrap',
|
|
137
|
+
<%_ } _%>
|
|
126
138
|
},
|
|
127
139
|
} satisfies FunctionProps,
|
|
128
140
|
buildDefaultIntegration: (op, props: FunctionProps) => {
|
|
129
141
|
const handler = new Function(scope, `<%= apiNameClassName %>${op}Handler`, props);
|
|
142
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
143
|
+
const stack = Stack.of(scope);
|
|
144
|
+
handler.addLayers(
|
|
145
|
+
LayerVersion.fromLayerVersionArn(
|
|
146
|
+
scope,
|
|
147
|
+
`<%= apiNameClassName %>${op}LWALayer`,
|
|
148
|
+
`arn:aws:lambda:${stack.region}:753240598075:layer:LambdaAdapterLayerX86:24`,
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
<%_ } _%>
|
|
130
152
|
return {
|
|
131
153
|
handler,
|
|
154
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
155
|
+
integration: new HttpLambdaIntegration(`<%= apiNameClassName %>${op}Integration`, handler.currentVersion),
|
|
156
|
+
<%_ } else { _%>
|
|
132
157
|
integration: new HttpLambdaIntegration(`<%= apiNameClassName %>${op}Integration`, handler),
|
|
158
|
+
<%_ } _%>
|
|
133
159
|
};
|
|
134
160
|
},
|
|
135
161
|
});
|
|
@@ -7,19 +7,23 @@ import {
|
|
|
7
7
|
Function,
|
|
8
8
|
FunctionProps,
|
|
9
9
|
Tracing,
|
|
10
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
11
|
+
LayerVersion,
|
|
12
|
+
SnapStartConf,
|
|
13
|
+
<%_ } _%>
|
|
10
14
|
} from 'aws-cdk-lib/aws-lambda';
|
|
11
15
|
import {
|
|
12
16
|
AuthorizationType,
|
|
13
17
|
Cors,
|
|
14
18
|
LambdaIntegration,
|
|
15
|
-
<%_ if (backend.type
|
|
19
|
+
<%_ if (['trpc', 'fastapi'].includes(backend.type)) { _%>
|
|
16
20
|
ResponseTransferMode,
|
|
17
21
|
<%_ } _%>
|
|
18
22
|
<%_ if (auth === 'Cognito') { _%>
|
|
19
23
|
CognitoUserPoolsAuthorizer,
|
|
20
24
|
<%_ } _%>
|
|
21
25
|
} from 'aws-cdk-lib/aws-apigateway';
|
|
22
|
-
import { Duration } from 'aws-cdk-lib';
|
|
26
|
+
import { Duration<%_ if (backend.type === 'fastapi') { _%>, Stack<%_ } _%> } from 'aws-cdk-lib';
|
|
23
27
|
import {
|
|
24
28
|
PolicyDocument,
|
|
25
29
|
PolicyStatement,
|
|
@@ -109,7 +113,7 @@ export class <%= apiNameClassName %><
|
|
|
109
113
|
),
|
|
110
114
|
<%_ } else if (backend.type === 'fastapi') { _%>
|
|
111
115
|
runtime: Runtime.PYTHON_3_12,
|
|
112
|
-
handler: '
|
|
116
|
+
handler: 'run.sh',
|
|
113
117
|
code: Code.fromAsset(
|
|
114
118
|
url.fileURLToPath(
|
|
115
119
|
new URL(
|
|
@@ -121,15 +125,37 @@ export class <%= apiNameClassName %><
|
|
|
121
125
|
<%_ } _%>
|
|
122
126
|
timeout: Duration.seconds(30),
|
|
123
127
|
tracing: Tracing.ACTIVE,
|
|
128
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
129
|
+
snapStart: SnapStartConf.ON_PUBLISHED_VERSIONS,
|
|
130
|
+
<%_ } _%>
|
|
124
131
|
environment: {
|
|
125
132
|
AWS_CONNECTION_REUSE_ENABLED: '1',
|
|
133
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
134
|
+
PORT: '8000',
|
|
135
|
+
AWS_LWA_INVOKE_MODE: 'response_stream',
|
|
136
|
+
AWS_LAMBDA_EXEC_WRAPPER: '/opt/bootstrap',
|
|
137
|
+
<%_ } _%>
|
|
126
138
|
},
|
|
127
139
|
} satisfies FunctionProps,
|
|
128
140
|
buildDefaultIntegration: (op, props: FunctionProps) => {
|
|
129
141
|
const handler = new Function(scope, `<%= apiNameClassName %>${op}Handler`, props);
|
|
142
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
143
|
+
const stack = Stack.of(scope);
|
|
144
|
+
handler.addLayers(
|
|
145
|
+
LayerVersion.fromLayerVersionArn(
|
|
146
|
+
scope,
|
|
147
|
+
`<%= apiNameClassName %>${op}LWALayer`,
|
|
148
|
+
`arn:aws:lambda:${stack.region}:753240598075:layer:LambdaAdapterLayerX86:24`,
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
<%_ } _%>
|
|
130
152
|
return {
|
|
131
153
|
handler,
|
|
132
|
-
<%_ if (backend.type === '
|
|
154
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
155
|
+
integration: new LambdaIntegration(handler.currentVersion, {
|
|
156
|
+
responseTransferMode: ResponseTransferMode.STREAM,
|
|
157
|
+
}),
|
|
158
|
+
<%_ } else if (backend.type === 'trpc') { _%>
|
|
133
159
|
integration: new LambdaIntegration(handler, {
|
|
134
160
|
responseTransferMode: ResponseTransferMode.STREAM,
|
|
135
161
|
}),
|
|
@@ -132,11 +132,15 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
132
132
|
handler = "index.handler"
|
|
133
133
|
runtime = "nodejs22.x"
|
|
134
134
|
<%_ } else if (backend.type === 'fastapi') { _%>
|
|
135
|
-
handler = "
|
|
135
|
+
handler = "run.sh"
|
|
136
136
|
runtime = "python3.12"
|
|
137
|
+
layers = ["arn:aws:lambda:${data.aws_region.current.name}:753240598075:layer:LambdaAdapterLayerX86:24"]
|
|
137
138
|
<%_ } _%>
|
|
138
139
|
timeout = 30
|
|
139
140
|
memory_size = 128
|
|
141
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
142
|
+
publish = true
|
|
143
|
+
<%_ } _%>
|
|
140
144
|
|
|
141
145
|
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
|
|
142
146
|
|
|
@@ -145,9 +149,21 @@ resource "aws_lambda_function" "api_lambda" {
|
|
|
145
149
|
mode = "Active"
|
|
146
150
|
}
|
|
147
151
|
|
|
152
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
153
|
+
# Enable SnapStart for faster cold starts
|
|
154
|
+
snap_start {
|
|
155
|
+
apply_on = "PublishedVersions"
|
|
156
|
+
}
|
|
157
|
+
<%_ } _%>
|
|
158
|
+
|
|
148
159
|
environment {
|
|
149
160
|
variables = merge({
|
|
150
161
|
AWS_CONNECTION_REUSE_ENABLED = "1"
|
|
162
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
163
|
+
PORT = "8000"
|
|
164
|
+
AWS_LWA_INVOKE_MODE = "buffered"
|
|
165
|
+
AWS_LAMBDA_EXEC_WRAPPER = "/opt/bootstrap"
|
|
166
|
+
<%_ } _%>
|
|
151
167
|
}, var.env)
|
|
152
168
|
}
|
|
153
169
|
|
|
@@ -207,6 +223,17 @@ resource "aws_cloudwatch_log_group" "lambda_logs" {
|
|
|
207
223
|
tags = var.tags
|
|
208
224
|
}
|
|
209
225
|
|
|
226
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
227
|
+
# Lambda alias pointing to the latest published version for SnapStart
|
|
228
|
+
resource "aws_lambda_alias" "live" {
|
|
229
|
+
name = "live"
|
|
230
|
+
function_name = aws_lambda_function.api_lambda.function_name
|
|
231
|
+
function_version = aws_lambda_function.api_lambda.version
|
|
232
|
+
|
|
233
|
+
depends_on = [aws_lambda_function.api_lambda]
|
|
234
|
+
}
|
|
235
|
+
<%_ } _%>
|
|
236
|
+
|
|
210
237
|
<%_ if (auth === 'Cognito') { _%>
|
|
211
238
|
# Cognito User Pool Authorizer
|
|
212
239
|
resource "aws_apigatewayv2_authorizer" "cognito_authorizer" {
|
|
@@ -226,12 +253,20 @@ resource "aws_apigatewayv2_authorizer" "cognito_authorizer" {
|
|
|
226
253
|
resource "aws_apigatewayv2_integration" "lambda_integration" {
|
|
227
254
|
api_id = module.http_api.api_id
|
|
228
255
|
integration_type = "AWS_PROXY"
|
|
256
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
257
|
+
integration_uri = aws_lambda_alias.live.invoke_arn
|
|
258
|
+
<%_ } else { _%>
|
|
229
259
|
integration_uri = aws_lambda_function.api_lambda.invoke_arn
|
|
260
|
+
<%_ } _%>
|
|
230
261
|
|
|
231
262
|
payload_format_version = "2.0"
|
|
232
263
|
timeout_milliseconds = 30000
|
|
233
264
|
|
|
265
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
266
|
+
depends_on = [aws_lambda_alias.live]
|
|
267
|
+
<%_ } else { _%>
|
|
234
268
|
depends_on = [aws_lambda_function.api_lambda]
|
|
269
|
+
<%_ } _%>
|
|
235
270
|
}
|
|
236
271
|
|
|
237
272
|
# Route for proxy integration (catches all requests)
|
|
@@ -268,15 +303,22 @@ module "add_url_to_runtime_config" {
|
|
|
268
303
|
depends_on = [module.http_api]
|
|
269
304
|
}
|
|
270
305
|
|
|
271
|
-
# Lambda permission for API Gateway to invoke the function
|
|
306
|
+
# Lambda permission for API Gateway to invoke the function<% if (backend.type === 'fastapi') { %> via alias<% } %>
|
|
272
307
|
resource "aws_lambda_permission" "api_gateway_invoke" {
|
|
273
308
|
statement_id = "AllowExecutionFromAPIGateway"
|
|
274
309
|
action = "lambda:InvokeFunction"
|
|
275
310
|
function_name = aws_lambda_function.api_lambda.function_name
|
|
311
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
312
|
+
qualifier = aws_lambda_alias.live.name
|
|
313
|
+
<%_ } _%>
|
|
276
314
|
principal = "apigateway.amazonaws.com"
|
|
277
315
|
source_arn = "${module.http_api.api_execution_arn}/*/*"
|
|
278
316
|
|
|
317
|
+
<%_ if (backend.type === 'fastapi') { _%>
|
|
318
|
+
depends_on = [module.http_api, aws_lambda_alias.live]
|
|
319
|
+
<%_ } else { _%>
|
|
279
320
|
depends_on = [module.http_api, aws_lambda_function.api_lambda]
|
|
321
|
+
<%_ } _%>
|
|
280
322
|
}
|
|
281
323
|
|
|
282
324
|
# Outputs
|