@aws/nx-plugin 0.77.0 → 0.79.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.
Files changed (40) hide show
  1. package/LICENSE-THIRD-PARTY +36 -8
  2. package/package.json +2 -2
  3. package/src/open-api/ts-client/__snapshots__/generator.streaming.spec.ts.snap +401 -0
  4. package/src/open-api/ts-client/files/client.gen.ts.template +27 -4
  5. package/src/open-api/utils/codegen-data/types.d.ts +4 -0
  6. package/src/open-api/utils/codegen-data/types.js +8 -1
  7. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  8. package/src/open-api/utils/codegen-data.js +21 -1
  9. package/src/open-api/utils/codegen-data.js.map +1 -1
  10. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +42 -30
  11. package/src/py/fast-api/files/app/__name__/init.py.template +23 -17
  12. package/src/py/fast-api/files/app/__name__/main.py.template +2 -0
  13. package/src/py/fast-api/files/app/tests/test_main.py +1 -0
  14. package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +1 -1
  15. package/src/py/strands-agent/__snapshots__/generator.spec.ts.snap +16 -9
  16. package/src/py/strands-agent/files/app/agentcore_mcp_client.py.template +4 -12
  17. package/src/py/strands-agent/files/app/init.py.template +51 -1
  18. package/src/py/strands-agent/files/app/main.py.template +16 -9
  19. package/src/smithy/react-connection/__snapshots__/generator.spec.ts.snap +2 -2
  20. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +23 -17
  21. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +60 -34
  22. package/src/trpc/backend/files/src/handler.ts.template +48 -0
  23. package/src/trpc/backend/files/src/index.ts.template +1 -1
  24. package/src/trpc/backend/files/src/router.ts.template +0 -38
  25. package/src/trpc/backend/files/src/schema/z-async-iterable.ts.template +115 -0
  26. package/src/trpc/backend/generator.js +6 -2
  27. package/src/trpc/backend/generator.js.map +1 -1
  28. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +274 -27
  29. package/src/trpc/react/files/src/components/__apiNameClassName__ClientProvider.tsx.template +57 -1
  30. package/src/trpc/react/generator.js +11 -1
  31. package/src/trpc/react/generator.js.map +1 -1
  32. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +13 -1
  33. package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +3 -3
  34. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +8 -3
  35. package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +1 -1
  36. package/src/utils/connection/open-api/files/components/__apiNameClassName__Provider.tsx.template +1 -1
  37. package/src/utils/files/website/hooks/sigv4/useSigV4.tsx.template +81 -33
  38. package/src/utils/versions.d.ts +3 -1
  39. package/src/utils/versions.js +2 -0
  40. package/src/utils/versions.js.map +1 -1
@@ -1,10 +1,9 @@
1
1
  import uvicorn
2
2
  from bedrock_agentcore.runtime.models import PingStatus
3
- from fastapi.responses import PlainTextResponse, StreamingResponse
4
3
  from pydantic import BaseModel
5
4
 
6
5
  from .agent import get_agent
7
- from .init import app
6
+ from .init import JsonStreamingResponse, app
8
7
 
9
8
 
10
9
  class InvokeInput(BaseModel):
@@ -12,23 +11,31 @@ class InvokeInput(BaseModel):
12
11
  session_id: str
13
12
 
14
13
 
14
+ class StreamChunk(BaseModel):
15
+ content: str
16
+
17
+
15
18
  async def handle_invoke(input: InvokeInput):
16
19
  """Streaming handler for agent invocation"""
17
20
  with get_agent(session_id=input.session_id) as agent:
18
21
  stream = agent.stream_async(input.prompt)
19
22
  async for event in stream:
20
23
  print(event)
21
- content = event.get("event", {}).get("contentBlockDelta", {}).get("delta", {}).get("text")
22
- if content is not None:
23
- yield content
24
+ text = event.get("event", {}).get("contentBlockDelta", {}).get("delta", {}).get("text")
25
+ if text is not None:
26
+ yield StreamChunk(content=text)
24
27
  elif event.get("event", {}).get("messageStop") is not None:
25
- yield "\n"
28
+ yield StreamChunk(content="\n")
26
29
 
27
30
 
28
- @app.post("/invocations", openapi_extra={"x-streaming": True}, response_class=PlainTextResponse)
29
- async def invoke(input: InvokeInput) -> str:
31
+ @app.post(
32
+ "/invocations",
33
+ response_class=JsonStreamingResponse,
34
+ responses={200: JsonStreamingResponse.openapi_response(StreamChunk, "Stream of agent response chunks")},
35
+ )
36
+ async def invoke(input: InvokeInput) -> JsonStreamingResponse:
30
37
  """Entry point for agent invocation"""
31
- return StreamingResponse(handle_invoke(input), media_type="text/event-stream")
38
+ return JsonStreamingResponse(handle_invoke(input))
32
39
 
33
40
 
34
41
  @app.get("/ping")
@@ -57,7 +57,7 @@ const useCreateTestApiClient = (): TestApi => {
57
57
  () =>
58
58
  new TestApi({
59
59
  url: apiUrl,
60
- fetch: sigv4Client,
60
+ fetch: sigv4Client.fetch,
61
61
  }),
62
62
  [apiUrl, sigv4Client],
63
63
  );
@@ -175,7 +175,7 @@ const useCreateTestApiClient = (): TestApi => {
175
175
  () =>
176
176
  new TestApi({
177
177
  url: apiUrl,
178
- fetch: sigv4Client,
178
+ fetch: sigv4Client.fetch,
179
179
  }),
180
180
  [apiUrl, sigv4Client],
181
181
  );
@@ -123,7 +123,10 @@ export class TestApi<
123
123
  } satisfies FunctionProps,
124
124
  buildDefaultIntegration: (op, props: FunctionProps) => {
125
125
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
126
- return { handler, integration: new LambdaIntegration(handler) };
126
+ return {
127
+ handler,
128
+ integration: new LambdaIntegration(handler),
129
+ };
127
130
  },
128
131
  });
129
132
  };
@@ -281,7 +284,10 @@ export class TestApi<
281
284
  } satisfies FunctionProps,
282
285
  buildDefaultIntegration: (op, props: FunctionProps) => {
283
286
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
284
- return { handler, integration: new LambdaIntegration(handler) };
287
+ return {
288
+ handler,
289
+ integration: new LambdaIntegration(handler),
290
+ };
285
291
  },
286
292
  });
287
293
  };
@@ -385,7 +391,7 @@ terraform {
385
391
  required_providers {
386
392
  aws = {
387
393
  source = "hashicorp/aws"
388
- version = "~> 6.0"
394
+ version = "~> 6.33"
389
395
  }
390
396
  }
391
397
  }
@@ -535,7 +541,7 @@ exports[`tsSmithyApiGenerator > should generate smithy ts api with Terraform pro
535
541
  required_providers {
536
542
  aws = {
537
543
  source = "hashicorp/aws"
538
- version = "~> 6.0"
544
+ version = "~> 6.33"
539
545
  }
540
546
  }
541
547
  }
@@ -714,8 +720,8 @@ resource "aws_api_gateway_integration" "lambda_integration" {
714
720
  http_method = aws_api_gateway_method.proxy_method.http_method
715
721
 
716
722
  integration_http_method = "POST"
717
- type = "AWS_PROXY"
718
- uri = aws_lambda_function.api_lambda.invoke_arn
723
+ type = "AWS_PROXY"
724
+ uri = aws_lambda_function.api_lambda.invoke_arn
719
725
 
720
726
  depends_on = [aws_lambda_function.api_lambda]
721
727
  }
@@ -1391,7 +1397,7 @@ terraform {
1391
1397
  required_providers {
1392
1398
  aws = {
1393
1399
  source = "hashicorp/aws"
1394
- version = "~> 6.0"
1400
+ version = "~> 6.33"
1395
1401
  }
1396
1402
  }
1397
1403
  }
@@ -1538,7 +1544,7 @@ output "api_root_resource_id" {
1538
1544
  required_providers {
1539
1545
  aws = {
1540
1546
  source = "hashicorp/aws"
1541
- version = "~> 6.0"
1547
+ version = "~> 6.33"
1542
1548
  }
1543
1549
  }
1544
1550
  }
@@ -1735,8 +1741,8 @@ resource "aws_api_gateway_integration" "lambda_integration" {
1735
1741
  http_method = aws_api_gateway_method.proxy_method.http_method
1736
1742
 
1737
1743
  integration_http_method = "POST"
1738
- type = "AWS_PROXY"
1739
- uri = aws_lambda_function.api_lambda.invoke_arn
1744
+ type = "AWS_PROXY"
1745
+ uri = aws_lambda_function.api_lambda.invoke_arn
1740
1746
 
1741
1747
  depends_on = [aws_lambda_function.api_lambda]
1742
1748
  }
@@ -2027,7 +2033,7 @@ terraform {
2027
2033
  required_providers {
2028
2034
  aws = {
2029
2035
  source = "hashicorp/aws"
2030
- version = "~> 6.0"
2036
+ version = "~> 6.33"
2031
2037
  }
2032
2038
  }
2033
2039
  }
@@ -2174,7 +2180,7 @@ output "api_root_resource_id" {
2174
2180
  required_providers {
2175
2181
  aws = {
2176
2182
  source = "hashicorp/aws"
2177
- version = "~> 6.0"
2183
+ version = "~> 6.33"
2178
2184
  }
2179
2185
  }
2180
2186
  }
@@ -2353,8 +2359,8 @@ resource "aws_api_gateway_integration" "lambda_integration" {
2353
2359
  http_method = aws_api_gateway_method.proxy_method.http_method
2354
2360
 
2355
2361
  integration_http_method = "POST"
2356
- type = "AWS_PROXY"
2357
- uri = aws_lambda_function.api_lambda.invoke_arn
2362
+ type = "AWS_PROXY"
2363
+ uri = aws_lambda_function.api_lambda.invoke_arn
2358
2364
 
2359
2365
  depends_on = [aws_lambda_function.api_lambda]
2360
2366
  }
@@ -2651,7 +2657,7 @@ exports[`tsSmithyApiGenerator > terraform iacProvider > should generate terrafor
2651
2657
  required_providers {
2652
2658
  aws = {
2653
2659
  source = "hashicorp/aws"
2654
- version = "~> 6.0"
2660
+ version = "~> 6.33"
2655
2661
  }
2656
2662
  }
2657
2663
  }
@@ -2830,8 +2836,8 @@ resource "aws_api_gateway_integration" "lambda_integration" {
2830
2836
  http_method = aws_api_gateway_method.proxy_method.http_method
2831
2837
 
2832
2838
  integration_http_method = "POST"
2833
- type = "AWS_PROXY"
2834
- uri = aws_lambda_function.api_lambda.invoke_arn
2839
+ type = "AWS_PROXY"
2840
+ uri = aws_lambda_function.api_lambda.invoke_arn
2835
2841
 
2836
2842
  depends_on = [aws_lambda_function.api_lambda]
2837
2843
  }
@@ -29,6 +29,23 @@ export const createTestApiClient = (config: TestApiClientConfig) => {
29
29
  "
30
30
  `;
31
31
 
32
+ exports[`trpc backend generator > should generate the project > apps/test-api/src/handler.ts 1`] = `
33
+ "import {
34
+ CreateAWSLambdaContextOptions,
35
+ awsLambdaRequestHandler,
36
+ } from '@trpc/server/adapters/aws-lambda';
37
+ import type { APIGatewayProxyEventV2WithIAMAuthorizer } from 'aws-lambda';
38
+ import { appRouter } from './router.js';
39
+
40
+ export const handler = awsLambdaRequestHandler({
41
+ router: appRouter,
42
+ createContext: (
43
+ ctx: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2WithIAMAuthorizer>,
44
+ ) => ctx,
45
+ });
46
+ "
47
+ `;
48
+
32
49
  exports[`trpc backend generator > should generate the project > apps/test-api/src/index.ts 1`] = `
33
50
  "export type { AppRouter } from './router.js';
34
51
  export { appRouter } from './router.js';
@@ -269,13 +286,8 @@ export const echo = publicProcedure
269
286
  `;
270
287
 
271
288
  exports[`trpc backend generator > should generate the project > apps/test-api/src/router.ts 1`] = `
272
- "import {
273
- awsLambdaRequestHandler,
274
- CreateAWSLambdaContextOptions,
275
- } from '@trpc/server/adapters/aws-lambda';
276
- import { echo } from './procedures/echo.js';
289
+ "import { echo } from './procedures/echo.js';
277
290
  import { t } from './init.js';
278
- import type { APIGatewayProxyEventV2WithIAMAuthorizer } from 'aws-lambda';
279
291
 
280
292
  export const router = t.router;
281
293
 
@@ -283,13 +295,6 @@ export const appRouter = router({
283
295
  echo,
284
296
  });
285
297
 
286
- export const handler = awsLambdaRequestHandler({
287
- router: appRouter,
288
- createContext: (
289
- ctx: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2WithIAMAuthorizer>,
290
- ) => ctx,
291
- });
292
-
293
298
  export type AppRouter = typeof appRouter;
294
299
  "
295
300
  `;
@@ -359,6 +364,7 @@ import {
359
364
  AuthorizationType,
360
365
  Cors,
361
366
  LambdaIntegration,
367
+ ResponseTransferMode,
362
368
  CognitoUserPoolsAuthorizer,
363
369
  } from 'aws-cdk-lib/aws-apigateway';
364
370
  import { Duration } from 'aws-cdk-lib';
@@ -437,7 +443,12 @@ export class TestApi<
437
443
  } satisfies FunctionProps,
438
444
  buildDefaultIntegration: (op, props: FunctionProps) => {
439
445
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
440
- return { handler, integration: new LambdaIntegration(handler) };
446
+ return {
447
+ handler,
448
+ integration: new LambdaIntegration(handler, {
449
+ responseTransferMode: ResponseTransferMode.STREAM,
450
+ }),
451
+ };
441
452
  },
442
453
  });
443
454
  };
@@ -747,6 +758,7 @@ import {
747
758
  AuthorizationType,
748
759
  Cors,
749
760
  LambdaIntegration,
761
+ ResponseTransferMode,
750
762
  } from 'aws-cdk-lib/aws-apigateway';
751
763
  import { Duration } from 'aws-cdk-lib';
752
764
  import {
@@ -817,7 +829,12 @@ export class TestApi<
817
829
  } satisfies FunctionProps,
818
830
  buildDefaultIntegration: (op, props: FunctionProps) => {
819
831
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
820
- return { handler, integration: new LambdaIntegration(handler) };
832
+ return {
833
+ handler,
834
+ integration: new LambdaIntegration(handler, {
835
+ responseTransferMode: ResponseTransferMode.STREAM,
836
+ }),
837
+ };
821
838
  },
822
839
  });
823
840
  };
@@ -1436,9 +1453,9 @@ export const routerToOperations = <TRouter extends AnyTRPCRouter>(
1436
1453
  {
1437
1454
  path: fullPath,
1438
1455
  method:
1439
- procedureOrRouter._def.type === 'query'
1440
- ? HttpMethod.GET
1441
- : HttpMethod.POST,
1456
+ procedureOrRouter._def.type === 'mutation'
1457
+ ? HttpMethod.POST
1458
+ : HttpMethod.GET,
1442
1459
  },
1443
1460
  ],
1444
1461
  ];
@@ -1827,6 +1844,7 @@ import {
1827
1844
  AuthorizationType,
1828
1845
  Cors,
1829
1846
  LambdaIntegration,
1847
+ ResponseTransferMode,
1830
1848
  } from 'aws-cdk-lib/aws-apigateway';
1831
1849
  import { Duration } from 'aws-cdk-lib';
1832
1850
  import {
@@ -1899,7 +1917,12 @@ export class TestApi<
1899
1917
  } satisfies FunctionProps,
1900
1918
  buildDefaultIntegration: (op, props: FunctionProps) => {
1901
1919
  const handler = new Function(scope, \`TestApi\${op}Handler\`, props);
1902
- return { handler, integration: new LambdaIntegration(handler) };
1920
+ return {
1921
+ handler,
1922
+ integration: new LambdaIntegration(handler, {
1923
+ responseTransferMode: ResponseTransferMode.STREAM,
1924
+ }),
1925
+ };
1903
1926
  },
1904
1927
  });
1905
1928
  };
@@ -2051,9 +2074,9 @@ export const routerToOperations = <TRouter extends AnyTRPCRouter>(
2051
2074
  {
2052
2075
  path: fullPath,
2053
2076
  method:
2054
- procedureOrRouter._def.type === 'query'
2055
- ? HttpMethod.GET
2056
- : HttpMethod.POST,
2077
+ procedureOrRouter._def.type === 'mutation'
2078
+ ? HttpMethod.POST
2079
+ : HttpMethod.GET,
2057
2080
  },
2058
2081
  ],
2059
2082
  ];
@@ -4151,7 +4174,7 @@ terraform {
4151
4174
  required_providers {
4152
4175
  aws = {
4153
4176
  source = "hashicorp/aws"
4154
- version = "~> 6.0"
4177
+ version = "~> 6.33"
4155
4178
  }
4156
4179
  }
4157
4180
  }
@@ -4298,7 +4321,7 @@ output "api_root_resource_id" {
4298
4321
  required_providers {
4299
4322
  aws = {
4300
4323
  source = "hashicorp/aws"
4301
- version = "~> 6.0"
4324
+ version = "~> 6.33"
4302
4325
  }
4303
4326
  }
4304
4327
  }
@@ -4495,8 +4518,9 @@ resource "aws_api_gateway_integration" "lambda_integration" {
4495
4518
  http_method = aws_api_gateway_method.proxy_method.http_method
4496
4519
 
4497
4520
  integration_http_method = "POST"
4498
- type = "AWS_PROXY"
4499
- uri = aws_lambda_function.api_lambda.invoke_arn
4521
+ type = "AWS_PROXY"
4522
+ uri = aws_lambda_function.api_lambda.response_streaming_invoke_arn
4523
+ response_transfer_mode = "STREAM"
4500
4524
 
4501
4525
  depends_on = [aws_lambda_function.api_lambda]
4502
4526
  }
@@ -4787,7 +4811,7 @@ terraform {
4787
4811
  required_providers {
4788
4812
  aws = {
4789
4813
  source = "hashicorp/aws"
4790
- version = "~> 6.0"
4814
+ version = "~> 6.33"
4791
4815
  }
4792
4816
  }
4793
4817
  }
@@ -4934,7 +4958,7 @@ output "api_root_resource_id" {
4934
4958
  required_providers {
4935
4959
  aws = {
4936
4960
  source = "hashicorp/aws"
4937
- version = "~> 6.0"
4961
+ version = "~> 6.33"
4938
4962
  }
4939
4963
  }
4940
4964
  }
@@ -5113,8 +5137,9 @@ resource "aws_api_gateway_integration" "lambda_integration" {
5113
5137
  http_method = aws_api_gateway_method.proxy_method.http_method
5114
5138
 
5115
5139
  integration_http_method = "POST"
5116
- type = "AWS_PROXY"
5117
- uri = aws_lambda_function.api_lambda.invoke_arn
5140
+ type = "AWS_PROXY"
5141
+ uri = aws_lambda_function.api_lambda.response_streaming_invoke_arn
5142
+ response_transfer_mode = "STREAM"
5118
5143
 
5119
5144
  depends_on = [aws_lambda_function.api_lambda]
5120
5145
  }
@@ -5415,7 +5440,7 @@ terraform {
5415
5440
  required_providers {
5416
5441
  aws = {
5417
5442
  source = "hashicorp/aws"
5418
- version = "~> 6.0"
5443
+ version = "~> 6.33"
5419
5444
  }
5420
5445
  }
5421
5446
  }
@@ -5562,7 +5587,7 @@ output "api_root_resource_id" {
5562
5587
  required_providers {
5563
5588
  aws = {
5564
5589
  source = "hashicorp/aws"
5565
- version = "~> 6.0"
5590
+ version = "~> 6.33"
5566
5591
  }
5567
5592
  }
5568
5593
  }
@@ -5741,8 +5766,9 @@ resource "aws_api_gateway_integration" "lambda_integration" {
5741
5766
  http_method = aws_api_gateway_method.proxy_method.http_method
5742
5767
 
5743
5768
  integration_http_method = "POST"
5744
- type = "AWS_PROXY"
5745
- uri = aws_lambda_function.api_lambda.invoke_arn
5769
+ type = "AWS_PROXY"
5770
+ uri = aws_lambda_function.api_lambda.response_streaming_invoke_arn
5771
+ response_transfer_mode = "STREAM"
5746
5772
 
5747
5773
  depends_on = [aws_lambda_function.api_lambda]
5748
5774
  }
@@ -0,0 +1,48 @@
1
+ import {
2
+ CreateAWSLambdaContextOptions,
3
+ <%_ if (computeType === 'ServerlessApiGatewayRestApi') { _%>
4
+ awsLambdaStreamingRequestHandler,
5
+ <%_ } else { _%>
6
+ awsLambdaRequestHandler,
7
+ <%_ } _%>
8
+ } from '@trpc/server/adapters/aws-lambda';
9
+ import type { <%- apiGatewayEventType %> } from 'aws-lambda';
10
+ import { appRouter } from './router.js';
11
+
12
+ <%_ if (computeType === 'ServerlessApiGatewayRestApi') { _%>
13
+ export const handler = awslambda.streamifyResponse(
14
+ awsLambdaStreamingRequestHandler({
15
+ router: appRouter,
16
+ createContext: (ctx: CreateAWSLambdaContextOptions<<%- apiGatewayEventType %>>) => ctx,
17
+ responseMeta: ({ ctx }) => ({
18
+ headers: {
19
+ 'Access-Control-Allow-Origin': getAllowedOrigin(ctx?.event),
20
+ 'Access-Control-Allow-Methods': '*',
21
+ },
22
+ }),
23
+ }),
24
+ );
25
+
26
+ /**
27
+ * Restricts CORS origins to localhost and the domains specified in
28
+ * the ALLOWED_ORIGINS environment variable if set, or * otherwise.
29
+ * Customise using `restrictCorsTo` in your API CDK construct
30
+ */
31
+ const getAllowedOrigin = (event: <%- apiGatewayEventType %> | undefined) => {
32
+ const origin = event?.headers?.origin ?? event?.headers?.Origin;
33
+ const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') ?? [];
34
+ const isLocalHost =
35
+ origin && new Set(['localhost', '127.0.0.1']).has(new URL(origin).hostname);
36
+ const isAllowedOrigin = origin && allowedOrigins.includes(origin);
37
+ let corsOrigin = '*';
38
+ if (allowedOrigins.length > 0 && !isLocalHost) {
39
+ corsOrigin = isAllowedOrigin ? origin : allowedOrigins[0];
40
+ }
41
+ return corsOrigin;
42
+ };
43
+ <%_ } else { _%>
44
+ export const handler = awsLambdaRequestHandler({
45
+ router: appRouter,
46
+ createContext: (ctx: CreateAWSLambdaContextOptions<<%- apiGatewayEventType %>>) => ctx,
47
+ });
48
+ <%_ } _%>
@@ -2,4 +2,4 @@ export type { AppRouter } from './router.js';
2
2
  export { appRouter } from './router.js';
3
3
  export type { Context } from './init.js';
4
4
  export * from './client/index.js';
5
- export * from './schema/index.js';
5
+ export * from './schema/index.js';
@@ -1,10 +1,5 @@
1
- import {
2
- awsLambdaRequestHandler,
3
- CreateAWSLambdaContextOptions,
4
- } from '@trpc/server/adapters/aws-lambda';
5
1
  import { echo } from './procedures/echo.js';
6
2
  import { t } from './init.js';
7
- import type { <%- apiGatewayEventType %> } from 'aws-lambda';
8
3
 
9
4
  export const router = t.router;
10
5
 
@@ -12,37 +7,4 @@ export const appRouter = router({
12
7
  echo,
13
8
  });
14
9
 
15
- export const handler = awsLambdaRequestHandler({
16
- router: appRouter,
17
- createContext: (ctx: CreateAWSLambdaContextOptions<<%- apiGatewayEventType %>>) => ctx,
18
- <%_ if (computeType === 'ServerlessApiGatewayRestApi') { _%>
19
- responseMeta: ({ ctx }) => ({
20
- headers: {
21
- 'Access-Control-Allow-Origin': getAllowedOrigin(ctx?.event),
22
- 'Access-Control-Allow-Methods': '*',
23
- },
24
- }),
25
- <%_ } _%>
26
- });
27
-
28
- <%_ if (computeType === 'ServerlessApiGatewayRestApi') { _%>
29
- /**
30
- * Restricts CORS origins to localhost and the domains specified in
31
- * the ALLOWED_ORIGINS environment variable if set, or * otherwise.
32
- * Customise using `restrictCorsTo` in your API CDK construct
33
- */
34
- const getAllowedOrigin = (event: <%- apiGatewayEventType %> | undefined) => {
35
- const origin = event?.headers?.origin ?? event?.headers?.Origin;
36
- const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') ?? [];
37
- const isLocalHost =
38
- origin && new Set(['localhost', '127.0.0.1']).has(new URL(origin).hostname);
39
- const isAllowedOrigin = origin && allowedOrigins.includes(origin);
40
- let corsOrigin = '*';
41
- if (allowedOrigins.length > 0 && !isLocalHost) {
42
- corsOrigin = isAllowedOrigin ? origin : allowedOrigins[0];
43
- }
44
- return corsOrigin;
45
- };
46
- <%_ } _%>
47
-
48
10
  export type AppRouter = typeof appRouter;
@@ -0,0 +1,115 @@
1
+ import { isTrackedEnvelope, tracked, type TrackedEnvelope } from '@trpc/server';
2
+ import { z } from 'zod';
3
+
4
+ function isAsyncIterable<TValue, TReturn = unknown>(
5
+ value: unknown,
6
+ ): value is AsyncIterable<TValue, TReturn> {
7
+ return !!value && typeof value === 'object' && Symbol.asyncIterator in value;
8
+ }
9
+
10
+ /**
11
+ * A Zod schema helper designed specifically for validating async iterables. This schema ensures that:
12
+ * 1. The value being validated is an async iterable.
13
+ * 2. Each item yielded by the async iterable conforms to a specified type.
14
+ * 3. The return value of the async iterable, if any, also conforms to a specified type.
15
+ */
16
+
17
+ // Non-tracked overload
18
+ export function ZodAsyncIterable<
19
+ TYieldIn,
20
+ TYieldOut,
21
+ TReturnIn = void,
22
+ TReturnOut = void,
23
+ >(opts: {
24
+ yield: z.ZodType<TYieldOut, TYieldIn>;
25
+ return?: z.ZodType<TReturnOut, TReturnIn>;
26
+ tracked?: false;
27
+ }): z.ZodPipe<
28
+ z.ZodCustom<
29
+ AsyncIterable<TYieldIn, TReturnIn>,
30
+ AsyncIterable<TYieldIn, TReturnIn>
31
+ >,
32
+ z.ZodTransform<
33
+ AsyncGenerator<
34
+ Awaited<TYieldOut>,
35
+ Awaited<TReturnOut> | undefined,
36
+ unknown
37
+ >,
38
+ AsyncIterable<TYieldIn, TReturnIn>
39
+ >
40
+ >;
41
+
42
+ // Tracked overload
43
+ export function ZodAsyncIterable<
44
+ TYieldIn,
45
+ TYieldOut,
46
+ TReturnIn = void,
47
+ TReturnOut = void,
48
+ >(opts: {
49
+ yield: z.ZodType<TYieldOut, TYieldIn>;
50
+ return?: z.ZodType<TReturnOut, TReturnIn>;
51
+ tracked: true;
52
+ }): z.ZodPipe<
53
+ z.ZodCustom<
54
+ AsyncIterable<TrackedEnvelope<TYieldIn>, TReturnIn>,
55
+ AsyncIterable<TrackedEnvelope<TYieldIn>, TReturnIn>
56
+ >,
57
+ z.ZodTransform<
58
+ AsyncGenerator<
59
+ TrackedEnvelope<Awaited<TYieldOut>>,
60
+ Awaited<TReturnOut> | undefined,
61
+ unknown
62
+ >,
63
+ AsyncIterable<TrackedEnvelope<TYieldIn>, TReturnIn>
64
+ >
65
+ >;
66
+
67
+ // Implementation
68
+ export function ZodAsyncIterable<
69
+ TYieldIn,
70
+ TYieldOut,
71
+ TReturnIn = void,
72
+ TReturnOut = void,
73
+ >(opts: {
74
+ /**
75
+ * Validate the value yielded by the async generator
76
+ */
77
+ yield: z.ZodType<TYieldOut, TYieldIn>;
78
+ /**
79
+ * Validate the return value of the async generator
80
+ * @remark not applicable for subscriptions
81
+ */
82
+ return?: z.ZodType<TReturnOut, TReturnIn>;
83
+ /**
84
+ * Whether if the yielded values are tracked
85
+ * @remark only applicable for subscriptions
86
+ */
87
+ tracked?: boolean;
88
+ }) {
89
+ return z
90
+ .custom<AsyncIterable<TYieldIn | TrackedEnvelope<TYieldIn>, TReturnIn>>(
91
+ (val) => isAsyncIterable(val),
92
+ )
93
+ .transform(async function* (iter) {
94
+ const iterator = iter[Symbol.asyncIterator]();
95
+ try {
96
+ let next;
97
+ while ((next = await iterator.next()) && !next.done) {
98
+ if (opts.tracked) {
99
+ const [id, data] = z
100
+ .custom<TrackedEnvelope<unknown>>(isTrackedEnvelope)
101
+ .parse(next.value);
102
+ yield tracked(id, await opts.yield.parseAsync(data));
103
+ continue;
104
+ }
105
+ yield opts.yield.parseAsync(next.value);
106
+ }
107
+ if (opts.return) {
108
+ return await opts.return.parseAsync(next.value);
109
+ }
110
+ return;
111
+ } finally {
112
+ await iterator.return?.();
113
+ }
114
+ });
115
+ }
@@ -56,7 +56,7 @@ function tsTrpcApiGenerator(tree, options) {
56
56
  auth: options.auth,
57
57
  iacProvider,
58
58
  });
59
- projectConfig.metadata = Object.assign(Object.assign({}, projectConfig.metadata), { apiName: options.name, apiType: 'trpc', auth: options.auth });
59
+ projectConfig.metadata = Object.assign(Object.assign({}, projectConfig.metadata), { apiName: options.name, apiType: 'trpc', auth: options.auth, computeType: options.computeType });
60
60
  projectConfig.targets.serve = {
61
61
  executor: 'nx:run-commands',
62
62
  options: {
@@ -66,7 +66,7 @@ function tsTrpcApiGenerator(tree, options) {
66
66
  continuous: true,
67
67
  };
68
68
  (0, bundle_1.addTypeScriptBundleTarget)(tree, projectConfig, {
69
- targetFilePath: 'src/router.ts',
69
+ targetFilePath: 'src/handler.ts',
70
70
  external: [/@aws-sdk\/.*/], // lambda runtime provides aws sdk
71
71
  });
72
72
  (0, nx_1.addDependencyToTargetIfNotPresent)(projectConfig, 'build', 'bundle');
@@ -76,6 +76,10 @@ function tsTrpcApiGenerator(tree, options) {
76
76
  overwriteStrategy: devkit_1.OverwriteStrategy.Overwrite,
77
77
  });
78
78
  tree.delete((0, devkit_1.joinPathFragments)(backendRoot, 'src', 'lib'));
79
+ // Remove streaming schema helper for HTTP APIs (API Gateway HTTP API doesn't support streaming)
80
+ if (options.computeType !== 'ServerlessApiGatewayRestApi') {
81
+ tree.delete((0, devkit_1.joinPathFragments)(backendRoot, 'src', 'schema', 'z-async-iterable.ts'));
82
+ }
79
83
  (0, devkit_1.addDependenciesToPackageJson)(tree, (0, versions_1.withVersions)([
80
84
  'aws-xray-sdk-core',
81
85
  'zod',