@aws/nx-plugin 0.3.0 → 0.5.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 (80) hide show
  1. package/LICENSE-THIRD-PARTY +76 -65
  2. package/package.json +2 -1
  3. package/src/cloudscape-website/app/README.md +1 -1
  4. package/src/cloudscape-website/app/__snapshots__/generator.spec.ts.snap +93 -29
  5. package/src/cloudscape-website/app/files/app/README.md.template +4 -2
  6. package/src/cloudscape-website/app/files/app/src/{layouts/App → components/AppLayout}/index.tsx.template +38 -19
  7. package/src/cloudscape-website/app/files/app/src/{layouts/App → components/AppLayout}/navitems.ts.template +1 -1
  8. package/src/cloudscape-website/app/files/app/src/hooks/useAppLayout.tsx.template +5 -0
  9. package/src/cloudscape-website/app/files/app/src/main.tsx.template +13 -6
  10. package/src/cloudscape-website/app/files/app/src/routeTree.gen.ts.template +111 -0
  11. package/src/cloudscape-website/app/files/app/src/routes/__root.tsx.template +6 -0
  12. package/src/cloudscape-website/app/files/app/src/routes/index.tsx.template +5 -0
  13. package/src/cloudscape-website/app/files/app/src/routes/welcome/index.tsx.template +21 -0
  14. package/src/cloudscape-website/app/files/app/src/styles.css.template +1 -0
  15. package/src/cloudscape-website/app/generator.js +24 -13
  16. package/src/cloudscape-website/app/generator.js.map +1 -1
  17. package/src/cloudscape-website/cognito-auth/__snapshots__/generator.spec.ts.snap +2 -2
  18. package/src/cloudscape-website/cognito-auth/generator.js +2 -2
  19. package/src/cloudscape-website/cognito-auth/generator.js.map +1 -1
  20. package/src/cloudscape-website/runtime-config/__snapshots__/generator.spec.ts.snap +2 -4
  21. package/src/cloudscape-website/runtime-config/generator.js +3 -3
  22. package/src/cloudscape-website/runtime-config/generator.js.map +1 -1
  23. package/src/infra/app/__snapshots__/generator.spec.ts.snap +5 -1
  24. package/src/infra/app/generator.js +1 -1
  25. package/src/infra/app/generator.js.map +1 -1
  26. package/src/license/README.md +50 -15
  27. package/src/license/__snapshots__/config.spec.ts.snap +10 -3
  28. package/src/license/config-types.d.ts +14 -0
  29. package/src/license/config.d.ts +1 -1
  30. package/src/license/config.js +15 -12
  31. package/src/license/config.js.map +1 -1
  32. package/src/license/generator.js +1 -4
  33. package/src/license/generator.js.map +1 -1
  34. package/src/license/sync/generator.js +40 -32
  35. package/src/license/sync/generator.js.map +1 -1
  36. package/src/license/sync/project-file-sync.d.ts +15 -0
  37. package/src/license/sync/project-file-sync.js +52 -0
  38. package/src/license/sync/project-file-sync.js.map +1 -0
  39. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +317 -6
  40. package/src/trpc/backend/files/backend/README.md.template +1 -1
  41. package/src/trpc/backend/files/backend/src/client/index.ts.template +33 -0
  42. package/src/trpc/backend/files/backend/src/client/sigv4.ts.template +9 -0
  43. package/src/trpc/backend/files/backend/src/index.ts.template +3 -1
  44. package/src/trpc/backend/files/backend/src/init.ts.template +18 -0
  45. package/src/trpc/backend/files/backend/src/local-server.ts.template +17 -0
  46. package/src/trpc/backend/files/backend/src/middleware/error.ts.template +26 -0
  47. package/src/trpc/backend/files/backend/src/middleware/index.ts.template +15 -0
  48. package/src/trpc/backend/files/backend/src/middleware/logger.ts.template +26 -0
  49. package/src/trpc/backend/files/backend/src/middleware/metrics.ts.template +36 -0
  50. package/src/trpc/backend/files/backend/src/middleware/tracer.ts.template +44 -0
  51. package/src/trpc/backend/files/backend/src/procedures/echo.ts.template +8 -0
  52. package/src/trpc/backend/files/backend/src/router.ts.template +20 -0
  53. package/src/trpc/backend/files/common/constructs/src/app/trpc-apis/__apiNameKebabCase__.ts.template +1 -1
  54. package/src/trpc/backend/files/schema/src/index.ts.template +1 -7
  55. package/src/trpc/backend/files/schema/src/procedures/echo.ts.template +13 -0
  56. package/src/trpc/backend/generator.js +10 -1
  57. package/src/trpc/backend/generator.js.map +1 -1
  58. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +4 -6
  59. package/src/trpc/react/files/src/hooks/useSigV4.tsx.template +20 -3
  60. package/src/trpc/react/generator.js +2 -2
  61. package/src/trpc/react/generator.js.map +1 -1
  62. package/src/ts/lib/eslint.js +1 -1
  63. package/src/ts/lib/eslint.js.map +1 -1
  64. package/src/utils/test.d.ts +4 -0
  65. package/src/utils/test.js +16 -1
  66. package/src/utils/test.js.map +1 -1
  67. package/src/utils/toml.d.ts +10 -0
  68. package/src/utils/toml.js +17 -0
  69. package/src/utils/toml.js.map +1 -0
  70. package/src/utils/versions.d.ts +6 -3
  71. package/src/utils/versions.js +5 -2
  72. package/src/utils/versions.js.map +1 -1
  73. package/src/cloudscape-website/app/files/app/src/layouts/Routes/index.tsx.template +0 -16
  74. package/src/cloudscape-website/app/files/app/src/pages/Home/index.tsx.template +0 -23
  75. package/src/trpc/backend/files/backend/src/lambdas/index.ts.template +0 -1
  76. package/src/trpc/backend/files/backend/src/lambdas/middleware.ts.template +0 -146
  77. package/src/trpc/backend/files/backend/src/lambdas/router.ts.template +0 -36
  78. /package/src/license/{files → sync/files}/licenses/ASL/LICENSE.template +0 -0
  79. /package/src/license/{files → sync/files}/licenses/Apache-2.0/LICENSE.template +0 -0
  80. /package/src/license/{files → sync/files}/licenses/MIT/LICENSE.template +0 -0
@@ -1,18 +1,329 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`trpc backend generator > should generate backend and schema projects > backend-index.ts 1`] = `
4
- "export * from './lambdas/index.js';
3
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/client/index.ts 1`] = `
4
+ "import {
5
+ createTRPCClient,
6
+ httpBatchLink,
7
+ httpLink,
8
+ HTTPBatchLinkOptions,
9
+ HTTPLinkOptions,
10
+ splitLink,
11
+ } from '@trpc/client';
12
+
13
+ import { AppRouter } from '../router.js';
14
+ import { sigv4Fetch } from './sigv4.js';
15
+
16
+ export interface TestApiClientConfig {
17
+ readonly url: string;
18
+ }
19
+
20
+ export const createTestApiClient = (config: TestApiClientConfig) => {
21
+ const linkOptions: HTTPLinkOptions<any> & HTTPBatchLinkOptions<any> = {
22
+ url: config.url,
23
+ fetch: sigv4Fetch,
24
+ };
25
+ return createTRPCClient<AppRouter>({
26
+ links: [
27
+ splitLink({
28
+ condition(op) {
29
+ return op.context.skipBatch === true;
30
+ },
31
+ true: httpLink(linkOptions),
32
+ false: httpBatchLink(linkOptions),
33
+ }),
34
+ ],
35
+ });
36
+ };
37
+ "
38
+ `;
39
+
40
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/client/sigv4.ts 1`] = `
41
+ "import { AwsClient } from 'aws4fetch';
42
+ import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
43
+
44
+ const credentialProvider = fromNodeProviderChain();
45
+
46
+ export const sigv4Fetch = (async (...args) => {
47
+ const client = new AwsClient(await credentialProvider());
48
+ return client.fetch(...args);
49
+ }) satisfies AwsClient['fetch'];
50
+ "
51
+ `;
52
+
53
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/index.ts 1`] = `
54
+ "export type { AppRouter } from './router.js';
55
+ export type { Context } from './init.js';
56
+ export * from './client/index.js';
57
+ "
58
+ `;
59
+
60
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/init.ts 1`] = `
61
+ "import { initTRPC } from '@trpc/server';
62
+ import {
63
+ createErrorPlugin,
64
+ createLoggerPlugin,
65
+ createMetricsPlugin,
66
+ createTracerPlugin,
67
+ IMiddlewareContext,
68
+ } from './middleware/index.js';
69
+
70
+ export type Context = IMiddlewareContext;
71
+
72
+ export const t = initTRPC.context<Context>().create();
73
+
74
+ export const publicProcedure = t.procedure
75
+ .unstable_concat(createLoggerPlugin())
76
+ .unstable_concat(createTracerPlugin())
77
+ .unstable_concat(createMetricsPlugin())
78
+ .unstable_concat(createErrorPlugin());
5
79
  "
6
80
  `;
7
81
 
8
- exports[`trpc backend generator > should generate backend and schema projects > schema-index.ts 1`] = `
82
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/local-server.ts 1`] = `
83
+ "import { createHTTPServer } from '@trpc/server/adapters/standalone';
84
+ import { appRouter } from './router.js';
85
+
86
+ const PORT = 2022;
87
+
88
+ createHTTPServer({
89
+ router: appRouter,
90
+ createContext() {
91
+ return {
92
+ event: {} as any,
93
+ context: {} as any,
94
+ info: {} as any,
95
+ };
96
+ },
97
+ }).listen(PORT);
98
+
99
+ console.log(\`Local TRPC server listening on port \${PORT}\`);
100
+ "
101
+ `;
102
+
103
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/middleware/error.ts 1`] = `
104
+ "import { initTRPC, TRPCError } from '@trpc/server';
105
+
106
+ export const createErrorPlugin = () => {
107
+ const t = initTRPC.context().create();
108
+ return t.procedure.use(async (opts) => {
109
+ const response = await opts.next({
110
+ ctx: {
111
+ ...opts.ctx,
112
+ },
113
+ });
114
+
115
+ if (!response.ok) {
116
+ if (response.error instanceof TRPCError) {
117
+ throw response.error;
118
+ }
119
+
120
+ throw new TRPCError({
121
+ code: 'INTERNAL_SERVER_ERROR',
122
+ message: 'An unexpected error occurred, please try again later.',
123
+ cause: response.error,
124
+ });
125
+ }
126
+
127
+ return response;
128
+ });
129
+ };
130
+ "
131
+ `;
132
+
133
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/middleware/index.ts 1`] = `
134
+ "import { CreateAWSLambdaContextOptions } from '@trpc/server/adapters/aws-lambda';
135
+ import type { APIGatewayProxyEventV2WithIAMAuthorizer } from 'aws-lambda';
136
+ import { ILoggerContext } from './logger.js';
137
+ import { IMetricsContext } from './metrics.js';
138
+ import { ITracerContext } from './tracer.js';
139
+
140
+ export * from './logger.js';
141
+ export * from './metrics.js';
142
+ export * from './tracer.js';
143
+ export * from './error.js';
144
+
145
+ export type IMiddlewareContext =
146
+ CreateAWSLambdaContextOptions<APIGatewayProxyEventV2WithIAMAuthorizer> &
147
+ ILoggerContext &
148
+ IMetricsContext &
149
+ ITracerContext;
150
+ "
151
+ `;
152
+
153
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/middleware/logger.ts 1`] = `
154
+ "import { initTRPC } from '@trpc/server';
155
+ import { Logger } from '@aws-lambda-powertools/logger';
156
+
157
+ export interface ILoggerContext {
158
+ logger?: Logger;
159
+ }
160
+
161
+ export const createLoggerPlugin = () => {
162
+ const t = initTRPC.context<ILoggerContext>().create();
163
+ return t.procedure.use(async (opts) => {
164
+ const logger = new Logger();
165
+
166
+ const response = await opts.next({
167
+ ctx: {
168
+ ...opts.ctx,
169
+ logger,
170
+ },
171
+ });
172
+
173
+ if (!response.ok) {
174
+ logger.error('Unexpected error occured', response.error.cause ?? '');
175
+ }
176
+
177
+ return response;
178
+ });
179
+ };
180
+ "
181
+ `;
182
+
183
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/middleware/metrics.ts 1`] = `
184
+ "import { initTRPC } from '@trpc/server';
185
+ import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics';
186
+
187
+ export interface IMetricsContext {
188
+ metrics?: Metrics;
189
+ }
190
+
191
+ export const createMetricsPlugin = () => {
192
+ const t = initTRPC.context<IMetricsContext>().create();
193
+
194
+ return t.procedure.use(async (opts) => {
195
+ const metrics = new Metrics();
196
+ metrics.captureColdStartMetric();
197
+
198
+ metrics.addMetric('requestCount', MetricUnit.Count, 1);
199
+
200
+ try {
201
+ const response = await opts.next({
202
+ ctx: {
203
+ ...opts.ctx,
204
+ metrics,
205
+ },
206
+ });
207
+
208
+ if (!response.ok) {
209
+ metrics.addMetric('errorCount', MetricUnit.Count, 1);
210
+ } else {
211
+ metrics.addMetric('successCount', MetricUnit.Count, 1);
212
+ }
213
+
214
+ return response;
215
+ } finally {
216
+ metrics.publishStoredMetrics();
217
+ }
218
+ });
219
+ };
220
+ "
221
+ `;
222
+
223
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/middleware/tracer.ts 1`] = `
224
+ "import { initTRPC } from '@trpc/server';
225
+ import { Tracer } from '@aws-lambda-powertools/tracer';
226
+ import { Subsegment } from 'aws-xray-sdk-core';
227
+
228
+ export interface ITracerContext {
229
+ tracer?: Tracer;
230
+ }
231
+
232
+ export const createTracerPlugin = () => {
233
+ const t = initTRPC.context<ITracerContext>().create();
234
+
235
+ return t.procedure.use(async (opts) => {
236
+ const tracer = new Tracer();
237
+ const segment = tracer.getSegment();
238
+ let handlerSegment: Subsegment | undefined;
239
+
240
+ if (segment) {
241
+ handlerSegment = segment.addNewSubsegment(\`## \${opts.path}\`);
242
+ tracer.setSegment(handlerSegment);
243
+ }
244
+
245
+ tracer.annotateColdStart();
246
+ tracer.addServiceNameAnnotation();
247
+
248
+ try {
249
+ const response = await opts.next({
250
+ ctx: {
251
+ ...opts.ctx,
252
+ tracer,
253
+ },
254
+ });
255
+
256
+ if (!response.ok && response.error.cause instanceof Error) {
257
+ tracer.addErrorAsMetadata(response.error.cause);
258
+ }
259
+ return response;
260
+ } finally {
261
+ if (segment && handlerSegment) {
262
+ handlerSegment.close();
263
+ tracer.setSegment(segment);
264
+ }
265
+ }
266
+ });
267
+ };
268
+ "
269
+ `;
270
+
271
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/procedures/echo.ts 1`] = `
272
+ "import { publicProcedure } from '../init.js';
273
+ import { EchoInputSchema, EchoOutputSchema } from ':proj/test-api-schema';
274
+
275
+ export const echo = publicProcedure
276
+ .input(EchoInputSchema)
277
+ .output(EchoOutputSchema)
278
+ .query((opts) => ({ result: opts.input.message }));
279
+ "
280
+ `;
281
+
282
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/backend/src/router.ts 1`] = `
283
+ "import {
284
+ awsLambdaRequestHandler,
285
+ CreateAWSLambdaContextOptions,
286
+ } from '@trpc/server/adapters/aws-lambda';
287
+ import { echo } from './procedures/echo.js';
288
+ import { t } from './init.js';
289
+ import { APIGatewayProxyEventV2WithIAMAuthorizer } from 'aws-lambda';
290
+
291
+ export const router = t.router;
292
+
293
+ export const appRouter = router({
294
+ echo,
295
+ });
296
+
297
+ export const handler = awsLambdaRequestHandler({
298
+ router: appRouter,
299
+ createContext: (
300
+ ctx: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2WithIAMAuthorizer>,
301
+ ) => ctx,
302
+ });
303
+
304
+ export type AppRouter = typeof appRouter;
305
+ "
306
+ `;
307
+
308
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/schema/src/index.ts 1`] = `
309
+ "export * from './procedures/echo.js';
310
+ "
311
+ `;
312
+
313
+ exports[`trpc backend generator > should generate backend and schema projects > apps/test-api/schema/src/procedures/echo.ts 1`] = `
9
314
  "import { z } from 'zod';
10
315
 
11
- export const EchoSchema = z.object({
316
+ export const EchoInputSchema = z.object({
317
+ message: z.string(),
318
+ });
319
+
320
+ export type IEchoInput = z.TypeOf<typeof EchoInputSchema>;
321
+
322
+ export const EchoOutputSchema = z.object({
12
323
  result: z.string(),
13
324
  });
14
325
 
15
- export type IEcho = z.TypeOf<typeof EchoSchema>;
326
+ export type IEchoOutput = z.TypeOf<typeof EchoOutputSchema>;
16
327
  "
17
328
  `;
18
329
 
@@ -33,7 +344,7 @@ export class TestApi extends TrpcApi {
33
344
  defaultAuthorizer: new HttpIamAuthorizer(),
34
345
  handlerFilePath: url.fileURLToPath(
35
346
  new URL(
36
- '../../../../../../apps/test-api/backend/src/lambdas/router.ts',
347
+ '../../../../../../apps/test-api/backend/src/router.ts',
37
348
  import.meta.url,
38
349
  ),
39
350
  ),
@@ -28,6 +28,6 @@ You can also automatiaclly fix some lint errors by running the following command
28
28
 
29
29
  ## Useful links
30
30
 
31
- - [Trpc reference docs](TODO)
31
+ - [tRPC reference docs](https://trpc.io/docs/)
32
32
  - [Learn more about NX](https://nx.dev/getting-started/intro)
33
33
 
@@ -0,0 +1,33 @@
1
+ import {
2
+ createTRPCClient,
3
+ httpBatchLink,
4
+ httpLink,
5
+ HTTPBatchLinkOptions,
6
+ HTTPLinkOptions,
7
+ splitLink,
8
+ } from '@trpc/client';
9
+
10
+ import { AppRouter } from "../router.js";
11
+ import { sigv4Fetch } from './sigv4.js';
12
+
13
+ export interface <%= apiNameClassName %>ClientConfig {
14
+ readonly url: string;
15
+ }
16
+
17
+ export const create<%= apiNameClassName %>Client = (config: <%= apiNameClassName %>ClientConfig) => {
18
+ const linkOptions: HTTPLinkOptions<any> & HTTPBatchLinkOptions<any> = {
19
+ url: config.url,
20
+ fetch: sigv4Fetch,
21
+ };
22
+ return createTRPCClient<AppRouter>({
23
+ links: [
24
+ splitLink({
25
+ condition(op) {
26
+ return op.context.skipBatch === true;
27
+ },
28
+ true: httpLink(linkOptions),
29
+ false: httpBatchLink(linkOptions),
30
+ }),
31
+ ],
32
+ });
33
+ };
@@ -0,0 +1,9 @@
1
+ import { AwsClient } from 'aws4fetch';
2
+ import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
3
+
4
+ const credentialProvider = fromNodeProviderChain();
5
+
6
+ export const sigv4Fetch = (async (...args) => {
7
+ const client = new AwsClient(await credentialProvider());
8
+ return client.fetch(...args);
9
+ }) satisfies AwsClient['fetch'];
@@ -1 +1,3 @@
1
- export * from './lambdas/index.js';
1
+ export type { AppRouter } from './router.js';
2
+ export type { Context } from './init.js';
3
+ export * from './client/index.js';
@@ -0,0 +1,18 @@
1
+ import { initTRPC } from '@trpc/server';
2
+ import {
3
+ createErrorPlugin,
4
+ createLoggerPlugin,
5
+ createMetricsPlugin,
6
+ createTracerPlugin,
7
+ IMiddlewareContext,
8
+ } from './middleware/index.js';
9
+
10
+ export type Context = IMiddlewareContext;
11
+
12
+ export const t = initTRPC.context<Context>().create();
13
+
14
+ export const publicProcedure = t.procedure
15
+ .unstable_concat(createLoggerPlugin())
16
+ .unstable_concat(createTracerPlugin())
17
+ .unstable_concat(createMetricsPlugin())
18
+ .unstable_concat(createErrorPlugin());
@@ -0,0 +1,17 @@
1
+ import { createHTTPServer } from '@trpc/server/adapters/standalone';
2
+ import { appRouter } from './router.js';
3
+
4
+ const PORT = 2022;
5
+
6
+ createHTTPServer({
7
+ router: appRouter,
8
+ createContext() {
9
+ return {
10
+ event: {} as any,
11
+ context: {} as any,
12
+ info: {} as any,
13
+ };
14
+ },
15
+ }).listen(PORT);
16
+
17
+ console.log(`Local TRPC server listening on port ${PORT}`);
@@ -0,0 +1,26 @@
1
+ import { initTRPC, TRPCError } from '@trpc/server';
2
+
3
+ export const createErrorPlugin = () => {
4
+ const t = initTRPC.context().create();
5
+ return t.procedure.use(async (opts) => {
6
+ const response = await opts.next({
7
+ ctx: {
8
+ ...opts.ctx,
9
+ },
10
+ });
11
+
12
+ if (!response.ok) {
13
+ if (response.error instanceof TRPCError) {
14
+ throw response.error;
15
+ }
16
+
17
+ throw new TRPCError({
18
+ code: 'INTERNAL_SERVER_ERROR',
19
+ message: 'An unexpected error occurred, please try again later.',
20
+ cause: response.error,
21
+ });
22
+ }
23
+
24
+ return response;
25
+ });
26
+ };
@@ -0,0 +1,15 @@
1
+ import { CreateAWSLambdaContextOptions } from '@trpc/server/adapters/aws-lambda';
2
+ import type { APIGatewayProxyEventV2WithIAMAuthorizer } from 'aws-lambda';
3
+ import { ILoggerContext } from './logger.js';
4
+ import { IMetricsContext } from './metrics.js';
5
+ import { ITracerContext } from './tracer.js';
6
+
7
+ export * from './logger.js';
8
+ export * from './metrics.js';
9
+ export * from './tracer.js';
10
+ export * from './error.js';
11
+
12
+ export type IMiddlewareContext = CreateAWSLambdaContextOptions<APIGatewayProxyEventV2WithIAMAuthorizer>
13
+ & ILoggerContext
14
+ & IMetricsContext
15
+ & ITracerContext;
@@ -0,0 +1,26 @@
1
+ import { initTRPC } from '@trpc/server';
2
+ import { Logger } from '@aws-lambda-powertools/logger';
3
+
4
+ export interface ILoggerContext {
5
+ logger?: Logger;
6
+ }
7
+
8
+ export const createLoggerPlugin = () => {
9
+ const t = initTRPC.context<ILoggerContext>().create();
10
+ return t.procedure.use(async (opts) => {
11
+ const logger = new Logger();
12
+
13
+ const response = await opts.next({
14
+ ctx: {
15
+ ...opts.ctx,
16
+ logger,
17
+ },
18
+ });
19
+
20
+ if (!response.ok) {
21
+ logger.error('Unexpected error occured', response.error.cause ?? '');
22
+ }
23
+
24
+ return response;
25
+ });
26
+ };
@@ -0,0 +1,36 @@
1
+ import { initTRPC } from '@trpc/server';
2
+ import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics';
3
+
4
+ export interface IMetricsContext {
5
+ metrics?: Metrics;
6
+ }
7
+
8
+ export const createMetricsPlugin = () => {
9
+ const t = initTRPC.context<IMetricsContext>().create();
10
+
11
+ return t.procedure.use(async (opts) => {
12
+ const metrics = new Metrics();
13
+ metrics.captureColdStartMetric();
14
+
15
+ metrics.addMetric('requestCount', MetricUnit.Count, 1);
16
+
17
+ try {
18
+ const response = await opts.next({
19
+ ctx: {
20
+ ...opts.ctx,
21
+ metrics,
22
+ },
23
+ });
24
+
25
+ if (!response.ok) {
26
+ metrics.addMetric('errorCount', MetricUnit.Count, 1);
27
+ } else {
28
+ metrics.addMetric('successCount', MetricUnit.Count, 1);
29
+ }
30
+
31
+ return response;
32
+ } finally {
33
+ metrics.publishStoredMetrics();
34
+ }
35
+ });
36
+ };
@@ -0,0 +1,44 @@
1
+ import { initTRPC } from '@trpc/server';
2
+ import { Tracer } from '@aws-lambda-powertools/tracer';
3
+ import { Subsegment } from 'aws-xray-sdk-core';
4
+
5
+ export interface ITracerContext {
6
+ tracer?: Tracer;
7
+ }
8
+
9
+ export const createTracerPlugin = () => {
10
+ const t = initTRPC.context<ITracerContext>().create();
11
+
12
+ return t.procedure.use(async (opts) => {
13
+ const tracer = new Tracer();
14
+ const segment = tracer.getSegment();
15
+ let handlerSegment: Subsegment | undefined;
16
+
17
+ if (segment) {
18
+ handlerSegment = segment.addNewSubsegment(`## ${opts.path}`);
19
+ tracer.setSegment(handlerSegment);
20
+ }
21
+
22
+ tracer.annotateColdStart();
23
+ tracer.addServiceNameAnnotation();
24
+
25
+ try {
26
+ const response = await opts.next({
27
+ ctx: {
28
+ ...opts.ctx,
29
+ tracer,
30
+ },
31
+ });
32
+
33
+ if (!response.ok && response.error.cause instanceof Error) {
34
+ tracer.addErrorAsMetadata(response.error.cause);
35
+ }
36
+ return response;
37
+ } finally {
38
+ if (segment && handlerSegment) {
39
+ handlerSegment.close();
40
+ tracer.setSegment(segment);
41
+ }
42
+ }
43
+ });
44
+ };
@@ -0,0 +1,8 @@
1
+ import { publicProcedure } from '../init.js';
2
+ import { EchoInputSchema, EchoOutputSchema } from '<%= schemaProjectAlias %>';
3
+
4
+
5
+ export const echo = publicProcedure
6
+ .input(EchoInputSchema)
7
+ .output(EchoOutputSchema)
8
+ .query((opts) => ({ result: opts.input.message }));
@@ -0,0 +1,20 @@
1
+ import {
2
+ awsLambdaRequestHandler,
3
+ CreateAWSLambdaContextOptions,
4
+ } from '@trpc/server/adapters/aws-lambda';
5
+ import { echo } from './procedures/echo.js';
6
+ import { t } from './init.js';
7
+ import { APIGatewayProxyEventV2WithIAMAuthorizer } from 'aws-lambda';
8
+
9
+ export const router = t.router;
10
+
11
+ export const appRouter = router({
12
+ echo,
13
+ });
14
+
15
+ export const handler = awsLambdaRequestHandler({
16
+ router: appRouter,
17
+ createContext: (ctx: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2WithIAMAuthorizer>) => ctx,
18
+ });
19
+
20
+ export type AppRouter = typeof appRouter;
@@ -9,7 +9,7 @@ export class <%= apiNameClassName %> extends TrpcApi {
9
9
  defaultAuthorizer: new HttpIamAuthorizer(),
10
10
  handlerFilePath: url.fileURLToPath(
11
11
  new URL(
12
- '../../../<%= relativePathToProjectRoot %>/backend/src/lambdas/router.ts',
12
+ '../../../<%= relativePathToProjectRoot %>/backend/src/router.ts',
13
13
  import.meta.url
14
14
  )
15
15
  )
@@ -1,7 +1 @@
1
- import { z } from 'zod';
2
-
3
- export const EchoSchema = z.object({
4
- result: z.string(),
5
- });
6
-
7
- export type IEcho = z.TypeOf<typeof EchoSchema>;
1
+ export * from './procedures/echo.js';
@@ -0,0 +1,13 @@
1
+ import { z } from 'zod';
2
+
3
+ export const EchoInputSchema = z.object({
4
+ message: z.string(),
5
+ });
6
+
7
+ export type IEchoInput = z.TypeOf<typeof EchoInputSchema>;
8
+
9
+ export const EchoOutputSchema = z.object({
10
+ result: z.string(),
11
+ });
12
+
13
+ export type IEchoOutput = z.TypeOf<typeof EchoOutputSchema>;
@@ -64,6 +64,13 @@ function trpcBackendGenerator(tree, options) {
64
64
  config.metadata = {
65
65
  apiName: options.apiName,
66
66
  };
67
+ config.targets = Object.assign(Object.assign({}, config.targets), { serve: {
68
+ executor: 'nx:run-commands',
69
+ options: {
70
+ commands: ['tsx src/local-server.ts'],
71
+ cwd: backendRoot,
72
+ },
73
+ } });
67
74
  return config;
68
75
  });
69
76
  (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, 'files', 'backend'), backendRoot, enhancedOptions, {
@@ -81,7 +88,9 @@ function trpcBackendGenerator(tree, options) {
81
88
  '@aws-lambda-powertools/metrics',
82
89
  '@aws-lambda-powertools/tracer',
83
90
  '@trpc/server',
84
- ]), (0, versions_1.withVersions)(['@types/aws-lambda']));
91
+ 'aws4fetch',
92
+ '@aws-sdk/credential-providers',
93
+ ]), (0, versions_1.withVersions)(['@types/aws-lambda', 'tsx']));
85
94
  tree.delete((0, devkit_1.joinPathFragments)(backendRoot, 'package.json'));
86
95
  tree.delete((0, devkit_1.joinPathFragments)(schemaRoot, 'package.json'));
87
96
  yield (0, format_1.formatFilesInSubtree)(tree);