@aws/nx-plugin 0.0.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 (142) hide show
  1. package/README.md +63 -0
  2. package/generators.json +52 -0
  3. package/package.json +27 -0
  4. package/src/cloudscape-website/app/README.md +253 -0
  5. package/src/cloudscape-website/app/__snapshots__/generator.spec.ts.snap +539 -0
  6. package/src/cloudscape-website/app/files/app/src/config.ts.template +4 -0
  7. package/src/cloudscape-website/app/files/app/src/layouts/App/index.tsx.template +132 -0
  8. package/src/cloudscape-website/app/files/app/src/layouts/App/navitems.ts.template +8 -0
  9. package/src/cloudscape-website/app/files/app/src/layouts/Routes/index.tsx.template +18 -0
  10. package/src/cloudscape-website/app/files/app/src/main.tsx.template +22 -0
  11. package/src/cloudscape-website/app/files/app/src/pages/Home/index.tsx.template +25 -0
  12. package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/cloudfront-web-acl.ts.template +317 -0
  13. package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/index.ts.template +4 -0
  14. package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/static-website.ts.template +237 -0
  15. package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/webacl_event_handler/index.ts.template +301 -0
  16. package/src/cloudscape-website/app/files/e2e/cypress/src/e2e/app.cy.ts.template +13 -0
  17. package/src/cloudscape-website/app/files/e2e/cypress/src/support/app.po.ts.template +1 -0
  18. package/src/cloudscape-website/app/files/e2e/playwright/src/example.spec.ts.template +6 -0
  19. package/src/cloudscape-website/app/generator.d.ts +4 -0
  20. package/src/cloudscape-website/app/generator.js +177 -0
  21. package/src/cloudscape-website/app/generator.js.map +1 -0
  22. package/src/cloudscape-website/app/schema.d.js +6 -0
  23. package/src/cloudscape-website/app/schema.d.js.map +1 -0
  24. package/src/cloudscape-website/app/schema.d.ts +35 -0
  25. package/src/cloudscape-website/app/schema.json +189 -0
  26. package/src/cloudscape-website/cognito-auth/README.md +172 -0
  27. package/src/cloudscape-website/cognito-auth/__snapshots__/generator.spec.ts.snap +238 -0
  28. package/src/cloudscape-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +50 -0
  29. package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/index.ts.template +4 -0
  30. package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/user-identity.ts.template +69 -0
  31. package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/userpool-with-mfa.ts.template +70 -0
  32. package/src/cloudscape-website/cognito-auth/generator.d.ts +4 -0
  33. package/src/cloudscape-website/cognito-auth/generator.js +100 -0
  34. package/src/cloudscape-website/cognito-auth/generator.js.map +1 -0
  35. package/src/cloudscape-website/cognito-auth/schema.d.js +6 -0
  36. package/src/cloudscape-website/cognito-auth/schema.d.js.map +1 -0
  37. package/src/cloudscape-website/cognito-auth/schema.d.ts +4 -0
  38. package/src/cloudscape-website/cognito-auth/schema.json +36 -0
  39. package/src/cloudscape-website/runtime-config/__snapshots__/generator.spec.ts.snap +112 -0
  40. package/src/cloudscape-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +46 -0
  41. package/src/cloudscape-website/runtime-config/generator.d.ts +4 -0
  42. package/src/cloudscape-website/runtime-config/generator.js +74 -0
  43. package/src/cloudscape-website/runtime-config/generator.js.map +1 -0
  44. package/src/cloudscape-website/runtime-config/schema.d.js +6 -0
  45. package/src/cloudscape-website/runtime-config/schema.d.js.map +1 -0
  46. package/src/cloudscape-website/runtime-config/schema.d.ts +3 -0
  47. package/src/cloudscape-website/runtime-config/schema.json +19 -0
  48. package/src/gitlab/files/.gitlab-ci.yml.template +26 -0
  49. package/src/gitlab/generator.d.ts +4 -0
  50. package/src/gitlab/generator.js +26 -0
  51. package/src/gitlab/generator.js.map +1 -0
  52. package/src/gitlab/schema.d.js +6 -0
  53. package/src/gitlab/schema.d.js.map +1 -0
  54. package/src/gitlab/schema.d.ts +5 -0
  55. package/src/gitlab/schema.json +52 -0
  56. package/src/index.d.ts +0 -0
  57. package/src/index.js +3 -0
  58. package/src/index.js.map +1 -0
  59. package/src/infra/app/README.md +175 -0
  60. package/src/infra/app/__snapshots__/generator.spec.ts.snap +864 -0
  61. package/src/infra/app/files/cdk.json +67 -0
  62. package/src/infra/app/files/src/main.ts.template +37 -0
  63. package/src/infra/app/files/src/stacks/application-stack.ts.template +10 -0
  64. package/src/infra/app/generator.d.ts +4 -0
  65. package/src/infra/app/generator.js +75 -0
  66. package/src/infra/app/generator.js.map +1 -0
  67. package/src/infra/app/schema.d.js +6 -0
  68. package/src/infra/app/schema.d.js.map +1 -0
  69. package/src/infra/app/schema.d.ts +6 -0
  70. package/src/infra/app/schema.json +35 -0
  71. package/src/trpc/backend/README.md +549 -0
  72. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +110 -0
  73. package/src/trpc/backend/files/backend/src/index.ts.template +1 -0
  74. package/src/trpc/backend/files/backend/src/lambdas/index.ts.template +1 -0
  75. package/src/trpc/backend/files/backend/src/lambdas/middleware.ts.template +146 -0
  76. package/src/trpc/backend/files/backend/src/lambdas/router.ts.template +36 -0
  77. package/src/trpc/backend/files/common/constructs/src/__apiNameKebabCase__/index.ts.template +64 -0
  78. package/src/trpc/backend/files/schema/src/index.ts.template +7 -0
  79. package/src/trpc/backend/generator.d.ts +4 -0
  80. package/src/trpc/backend/generator.js +128 -0
  81. package/src/trpc/backend/generator.js.map +1 -0
  82. package/src/trpc/backend/schema.d.js +6 -0
  83. package/src/trpc/backend/schema.d.js.map +1 -0
  84. package/src/trpc/backend/schema.d.ts +8 -0
  85. package/src/trpc/backend/schema.json +44 -0
  86. package/src/trpc/react/README.md +320 -0
  87. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +98 -0
  88. package/src/trpc/react/files/src/components/TRPCClientProvider/index.tsx.template +34 -0
  89. package/src/trpc/react/files/src/hooks/useTrpc.tsx.template +5 -0
  90. package/src/trpc/react/generator.d.ts +4 -0
  91. package/src/trpc/react/generator.js +81 -0
  92. package/src/trpc/react/generator.js.map +1 -0
  93. package/src/trpc/react/schema.d.js +6 -0
  94. package/src/trpc/react/schema.d.js.map +1 -0
  95. package/src/trpc/react/schema.d.ts +5 -0
  96. package/src/trpc/react/schema.json +32 -0
  97. package/src/ts/cjs-to-esm/generator.d.ts +8 -0
  98. package/src/ts/cjs-to-esm/generator.js +201 -0
  99. package/src/ts/cjs-to-esm/generator.js.map +1 -0
  100. package/src/ts/cjs-to-esm/schema.d.js +6 -0
  101. package/src/ts/cjs-to-esm/schema.d.js.map +1 -0
  102. package/src/ts/cjs-to-esm/schema.d.ts +5 -0
  103. package/src/ts/cjs-to-esm/schema.json +28 -0
  104. package/src/ts/lib/README.md +149 -0
  105. package/src/ts/lib/__snapshots__/generator.spec.ts.snap +260 -0
  106. package/src/ts/lib/eslint.d.ts +3 -0
  107. package/src/ts/lib/eslint.js +41 -0
  108. package/src/ts/lib/eslint.js.map +1 -0
  109. package/src/ts/lib/files/src/index.ts.template +3 -0
  110. package/src/ts/lib/generator.d.ts +21 -0
  111. package/src/ts/lib/generator.js +61 -0
  112. package/src/ts/lib/generator.js.map +1 -0
  113. package/src/ts/lib/schema.d.js +6 -0
  114. package/src/ts/lib/schema.d.js.map +1 -0
  115. package/src/ts/lib/schema.d.ts +13 -0
  116. package/src/ts/lib/schema.json +46 -0
  117. package/src/ts/lib/ts-project-utils.d.ts +6 -0
  118. package/src/ts/lib/ts-project-utils.js +107 -0
  119. package/src/ts/lib/ts-project-utils.js.map +1 -0
  120. package/src/ts/lib/types.d.ts +10 -0
  121. package/src/ts/lib/types.js +6 -0
  122. package/src/ts/lib/types.js.map +1 -0
  123. package/src/ts/lib/vitest.d.ts +3 -0
  124. package/src/ts/lib/vitest.js +67 -0
  125. package/src/ts/lib/vitest.js.map +1 -0
  126. package/src/utils/files/common/constructs/src/index.ts.template +1 -0
  127. package/src/utils/files/common/constructs/src/runtime-config/index.ts.template +1 -0
  128. package/src/utils/files/common/constructs/src/runtime-config/runtime-config.ts.template +33 -0
  129. package/src/utils/files/common/types/src/index.ts.template +1 -0
  130. package/src/utils/files/common/types/src/runtime-config.ts.template +13 -0
  131. package/src/utils/npm-scope.d.ts +7 -0
  132. package/src/utils/npm-scope.js +37 -0
  133. package/src/utils/npm-scope.js.map +1 -0
  134. package/src/utils/paths.d.ts +3 -0
  135. package/src/utils/paths.js +32 -0
  136. package/src/utils/paths.js.map +1 -0
  137. package/src/utils/shared-constructs.d.ts +7 -0
  138. package/src/utils/shared-constructs.js +72 -0
  139. package/src/utils/shared-constructs.js.map +1 -0
  140. package/src/utils/versions.d.ts +31 -0
  141. package/src/utils/versions.js +49 -0
  142. package/src/utils/versions.js.map +1 -0
@@ -0,0 +1,320 @@
1
+ # tRPC React Generator
2
+
3
+ ## Overview
4
+ This generator adds tRPC client integration to your React application, enabling type-safe API calls to your tRPC backend. It sets up all necessary configuration for connecting to your tRPC backend, including AWS IAM authentication support and proper error handling. The integration provides full end-to-end type safety between your frontend and backend.
5
+
6
+ ## Prerequisites
7
+
8
+ Before using this generator, ensure your React application has:
9
+
10
+ 1. A `main.tsx` file that renders your application
11
+ 2. An `<App/>` JSX element where the tRPC provider will be automatically injected
12
+ 3. A working tRPC backend (generated using the tRPC backend generator)
13
+
14
+ Example of required `main.tsx` structure:
15
+ ```tsx
16
+ import { StrictMode } from 'react';
17
+ import * as ReactDOM from 'react-dom/client';
18
+ import App from './app/app';
19
+
20
+ const root = ReactDOM.createRoot(
21
+ document.getElementById('root') as HTMLElement
22
+ );
23
+ root.render(
24
+ <StrictMode>
25
+ <App />
26
+ </StrictMode>
27
+ );
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ You can generate the tRPC React integration in two ways:
33
+
34
+ ### 1. Using VSCode IDE
35
+
36
+ First, install the NX Console extension for VSCode:
37
+ 1. Open VSCode
38
+ 2. Go to Extensions (Ctrl+Shift+X / Cmd+Shift+X)
39
+ 3. Search for "Nx Console"
40
+ 4. Install [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console)
41
+
42
+ Then add tRPC to your React application:
43
+ 1. Open the NX Console in VSCode
44
+ 2. Click on "Generate"
45
+ 3. Search for "trpc#react"
46
+ 4. Fill in the required parameters in the form
47
+ 5. Click "Run"
48
+
49
+ ### 2. Using CLI
50
+
51
+ Add tRPC to your React application:
52
+ ```bash
53
+ nx g @aws/nx-plugin:trpc#react --frontendProjectName=my-app --backendProjectName=my-api --auth=IAM
54
+ ```
55
+
56
+ You can also perform a dry-run to see what files would be generated without actually creating them:
57
+ ```bash
58
+ nx g @aws/nx-plugin:trpc#react --frontendProjectName=my-app --backendProjectName=my-api --auth=IAM --dry-run
59
+ ```
60
+
61
+ Both methods will add tRPC client integration to your React application with all the necessary configuration.
62
+
63
+ ## Input Parameters
64
+
65
+ | Parameter | Type | Default | Description |
66
+ |-----------|------|---------|-------------|
67
+ | frontendProjectName* | string | - | The name of your React application project (required). |
68
+ | backendProjectName* | string | - | The name of your tRPC backend project (required). |
69
+ | auth* | string | "IAM" | Authentication strategy. Options: "IAM", "None" |
70
+
71
+ *Required parameter
72
+
73
+ ## Expected Output
74
+
75
+ The generator creates the following structure in your React application:
76
+
77
+ ```
78
+ src/
79
+ ├── components/
80
+ │ └── TRPCClientProvider/
81
+ │ └── index.tsx # tRPC client configuration and provider
82
+ └── hooks/
83
+ └── useTrpc.tsx # Custom hook for using tRPC client
84
+ ```
85
+
86
+ Additionally, it:
87
+ 1. Installs required dependencies:
88
+ - @trpc/client
89
+ - @trpc/react-query
90
+ - @tanstack/react-query
91
+ - aws4fetch (if using IAM auth)
92
+
93
+ ## Using the Generated Code
94
+
95
+ ### Using the tRPC Hook
96
+
97
+ The generator provides a `useTrpc` hook that gives you access to the type-safe tRPC client:
98
+
99
+ ```tsx
100
+ import { useTrpc } from './hooks/useTrpc';
101
+
102
+ function MyComponent() {
103
+ const trpc = useTrpc();
104
+
105
+ // Example query
106
+ const { data, isLoading } = trpc.users.list.useQuery();
107
+
108
+ // Example mutation
109
+ const mutation = trpc.users.create.useMutation();
110
+
111
+ const handleCreate = () => {
112
+ mutation.mutate({
113
+ name: 'John Doe',
114
+ email: 'john@example.com'
115
+ });
116
+ };
117
+
118
+ if (isLoading) return <div>Loading...</div>;
119
+
120
+ return (
121
+ <div>
122
+ {/* Your component JSX */}
123
+ </div>
124
+ );
125
+ }
126
+ ```
127
+
128
+ ### Error Handling
129
+
130
+ The integration includes built-in error handling that properly processes tRPC errors:
131
+
132
+ ```tsx
133
+ function MyComponent() {
134
+ const trpc = useTrpc();
135
+
136
+ const { data, error } = trpc.users.list.useQuery();
137
+
138
+ if (error) {
139
+ return (
140
+ <div>
141
+ <h2>Error occurred:</h2>
142
+ <p>{error.message}</p>
143
+ {error.data?.code && <p>Code: {error.data.code}</p>}
144
+ </div>
145
+ );
146
+ }
147
+
148
+ return (
149
+ <div>
150
+ {/* Your component JSX */}
151
+ </div>
152
+ );
153
+ }
154
+ ```
155
+
156
+ ## Best Practices
157
+
158
+ ### 1. Handle Loading States
159
+
160
+ Always handle loading states for better user experience:
161
+
162
+ ```tsx
163
+ function UserList() {
164
+ const { users } = useUsers();
165
+
166
+ if (users.isLoading) {
167
+ return <LoadingSpinner />;
168
+ }
169
+
170
+ if (users.error) {
171
+ return <ErrorMessage error={users.error} />;
172
+ }
173
+
174
+ return (
175
+ <ul>
176
+ {users.data.map(user => (
177
+ <li key={user.id}>{user.name}</li>
178
+ ))}
179
+ </ul>
180
+ );
181
+ }
182
+ ```
183
+
184
+ ### 2. Optimistic Updates
185
+
186
+ Use optimistic updates for better user experience:
187
+
188
+ ```tsx
189
+ function UserList() {
190
+ const trpc = useTrpc();
191
+ const utils = trpc.useUtils();
192
+
193
+ const deleteMutation = trpc.users.delete.useMutation({
194
+ onMutate: async (userId) => {
195
+ // Cancel outgoing fetches
196
+ await utils.users.list.cancel();
197
+
198
+ // Get snapshot of current data
199
+ const previousUsers = utils.users.list.getData();
200
+
201
+ // Optimistically remove the user
202
+ utils.users.list.setData(undefined, (old) =>
203
+ old?.filter(user => user.id !== userId)
204
+ );
205
+
206
+ return { previousUsers };
207
+ },
208
+ onError: (err, userId, context) => {
209
+ // Restore previous data on error
210
+ utils.users.list.setData(undefined, context?.previousUsers);
211
+ }
212
+ });
213
+
214
+ return (
215
+ <ul>
216
+ {users.map(user => (
217
+ <li key={user.id}>
218
+ {user.name}
219
+ <button onClick={() => deleteMutation.mutate(user.id)}>
220
+ Delete
221
+ </button>
222
+ </li>
223
+ ))}
224
+ </ul>
225
+ );
226
+ }
227
+ ```
228
+
229
+ ### 3. Prefetching Data
230
+
231
+ Prefetch data for better performance:
232
+
233
+ ```tsx
234
+ function UserList() {
235
+ const trpc = useTrpc();
236
+
237
+ // Prefetch user details on hover
238
+ const prefetchUser = async (userId: string) => {
239
+ await trpc.users.getById.usePrefetchQuery(userId);
240
+ };
241
+
242
+ return (
243
+ <ul>
244
+ {users.map(user => (
245
+ <li
246
+ key={user.id}
247
+ onMouseEnter={() => prefetchUser(user.id)}
248
+ >
249
+ <Link to={`/users/${user.id}`}>
250
+ {user.name}
251
+ </Link>
252
+ </li>
253
+ ))}
254
+ </ul>
255
+ );
256
+ }
257
+ ```
258
+
259
+ ### 4. Infinite Queries
260
+
261
+ Handle pagination with infinite queries:
262
+
263
+ ```tsx
264
+ function UserList() {
265
+ const trpc = useTrpc();
266
+
267
+ const {
268
+ data,
269
+ fetchNextPage,
270
+ hasNextPage,
271
+ isFetchingNextPage
272
+ } = trpc.users.list.useInfiniteQuery(
273
+ { limit: 10 },
274
+ {
275
+ getNextPageParam: (lastPage) => lastPage.nextCursor,
276
+ }
277
+ );
278
+
279
+ return (
280
+ <div>
281
+ {data?.pages.map((page) => (
282
+ page.users.map(user => (
283
+ <UserCard key={user.id} user={user} />
284
+ ))
285
+ ))}
286
+
287
+ {hasNextPage && (
288
+ <button
289
+ onClick={() => fetchNextPage()}
290
+ disabled={isFetchingNextPage}
291
+ >
292
+ {isFetchingNextPage ? 'Loading...' : 'Load More'}
293
+ </button>
294
+ )}
295
+ </div>
296
+ );
297
+ }
298
+ ```
299
+
300
+ ## Type Safety
301
+
302
+ The integration provides complete end-to-end type safety. Your IDE will provide full autocompletion and type checking for all your API calls:
303
+
304
+ ```tsx
305
+ function UserForm() {
306
+ const trpc = useTrpc();
307
+
308
+ // ✅ Input is fully typed
309
+ const createUser = trpc.users.create.useMutation();
310
+
311
+ const handleSubmit = (data: CreateUserInput) => {
312
+ // ✅ Type error if input doesn't match schema
313
+ createUser.mutate(data);
314
+ };
315
+
316
+ return <form onSubmit={handleSubmit}>{/* ... */}</form>;
317
+ }
318
+ ```
319
+
320
+ The types are automatically inferred from your backend's router and schema definitions, ensuring that any changes to your API are immediately reflected in your frontend code without the need to build.
@@ -0,0 +1,98 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`trpc react generator > should generate trpc react files > TRPCClientProvider.tsx 1`] = `
4
+ "import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5
+ import { httpBatchLink } from '@trpc/react-query';
6
+ import { useContext, useState, FC } from 'react';
7
+ import { useTrpc } from '../../hooks/useTrpc';
8
+ import { RuntimeConfigContext } from '../RuntimeConfig';
9
+
10
+ const TRPCClientProvider: FC<any> = ({ children }) => {
11
+ const trpc = useTrpc();
12
+ const runtimeContext = useContext(RuntimeConfigContext);
13
+ const [queryClient] = useState(() => new QueryClient());
14
+
15
+ const [trpcClient] = useState(() =>
16
+ trpc.createClient({
17
+ links: [
18
+ httpBatchLink({
19
+ url: runtimeContext?.trpcApis?.['TestApi']!,
20
+ }),
21
+ ],
22
+ })
23
+ );
24
+
25
+ return (
26
+ <trpc.Provider client={trpcClient} queryClient={queryClient}>
27
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
28
+ </trpc.Provider>
29
+ );
30
+ };
31
+
32
+ export default TRPCClientProvider;
33
+ "
34
+ `;
35
+
36
+ exports[`trpc react generator > should generate trpc react files > useTrpc.tsx 1`] = `
37
+ "import type { AppRouter } from 'backend';
38
+ import { createTRPCReact } from '@trpc/react-query';
39
+
40
+ const trpc = createTRPCReact<AppRouter>();
41
+ export const useTrpc = () => trpc;
42
+ "
43
+ `;
44
+
45
+ exports[`trpc react generator > should handle IAM auth option > TRPCClientProvider-IAM.tsx 1`] = `
46
+ "import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
47
+ import { httpBatchLink } from '@trpc/react-query';
48
+ import { useContext, useState, FC } from 'react';
49
+ import { useTrpc } from '../../hooks/useTrpc';
50
+ import { RuntimeConfigContext } from '../RuntimeConfig';
51
+ import useSigV4Client from '@aws-northstar/ui/components/CognitoAuth/hooks/useSigv4Client';
52
+
53
+ const TRPCClientProvider: FC<any> = ({ children }) => {
54
+ const trpc = useTrpc();
55
+ const runtimeContext = useContext(RuntimeConfigContext);
56
+ const [queryClient] = useState(() => new QueryClient());
57
+ const sigv4Client = useSigV4Client();
58
+
59
+ const [trpcClient] = useState(() =>
60
+ trpc.createClient({
61
+ links: [
62
+ httpBatchLink({
63
+ url: runtimeContext?.trpcApis?.['TestApi']!,
64
+ fetch: sigv4Client,
65
+ }),
66
+ ],
67
+ })
68
+ );
69
+
70
+ return (
71
+ <trpc.Provider client={trpcClient} queryClient={queryClient}>
72
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
73
+ </trpc.Provider>
74
+ );
75
+ };
76
+
77
+ export default TRPCClientProvider;
78
+ "
79
+ `;
80
+
81
+ exports[`trpc react generator > should modify main.tsx correctly > main.tsx 1`] = `
82
+ "import TRPCClientProvider from './components/TRPCClientProvider';
83
+ import RuntimeConfigProvider from './components/RuntimeConfig';
84
+ import { App } from './app';
85
+ import { BrowserRouter } from 'react-router-dom';
86
+ export function Main() {
87
+ return (
88
+ <RuntimeConfigProvider>
89
+ <BrowserRouter>
90
+ <TRPCClientProvider>
91
+ <App />
92
+ </TRPCClientProvider>
93
+ </BrowserRouter>
94
+ </RuntimeConfigProvider>
95
+ );
96
+ }
97
+ "
98
+ `;
@@ -0,0 +1,34 @@
1
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
2
+ import { httpBatchLink } from '@trpc/react-query';
3
+ import { useContext, useState, FC } from 'react';
4
+ import { useTrpc } from '../../hooks/useTrpc';
5
+ import { RuntimeConfigContext } from '../RuntimeConfig';
6
+ <% if(auth === 'IAM') { %> import useSigV4Client from "@aws-northstar/ui/components/CognitoAuth/hooks/useSigv4Client"; <% } %>
7
+
8
+ const TRPCClientProvider: FC<any> = ({ children }) => {
9
+ const trpc = useTrpc();
10
+ const runtimeContext = useContext(RuntimeConfigContext);
11
+ const [queryClient] = useState(() => new QueryClient());
12
+ <% if(auth === 'IAM') { %> const sigv4Client = useSigV4Client(); <% } %>
13
+
14
+ const [trpcClient] = useState(() =>
15
+ trpc.createClient({
16
+ links: [
17
+ httpBatchLink({
18
+ url: runtimeContext?.trpcApis?.['<%= apiName %>']!,
19
+ <% if(auth === 'IAM') { %> fetch: sigv4Client <% } %>
20
+ })
21
+ ],
22
+ }),
23
+ );
24
+
25
+ return (
26
+ <trpc.Provider client={trpcClient} queryClient={queryClient}>
27
+ <QueryClientProvider client={queryClient}>
28
+ {children}
29
+ </QueryClientProvider>
30
+ </trpc.Provider>
31
+ );
32
+ };
33
+
34
+ export default TRPCClientProvider;
@@ -0,0 +1,5 @@
1
+ import type { AppRouter } from '<%= backendProjectAlias %>';
2
+ import { createTRPCReact } from '@trpc/react-query';
3
+
4
+ const trpc = createTRPCReact<AppRouter>();
5
+ export const useTrpc = () => trpc;
@@ -0,0 +1,4 @@
1
+ import { Tree } from '@nx/devkit';
2
+ import { ReactGeneratorSchema } from './schema';
3
+ export declare function reactGenerator(tree: Tree, options: ReactGeneratorSchema): Promise<() => void>;
4
+ export default reactGenerator;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ default: function() {
13
+ return _default;
14
+ },
15
+ reactGenerator: function() {
16
+ return reactGenerator;
17
+ }
18
+ });
19
+ const _extends = require("@swc/helpers/_/_extends");
20
+ const _devkit = require("@nx/devkit");
21
+ const _typescript = require("typescript");
22
+ const _tsquery = require("@phenomnomnominal/tsquery");
23
+ const _generator = require("../../cloudscape-website/runtime-config/generator");
24
+ const _npmscope = require("../../utils/npm-scope");
25
+ const _versions = require("../../utils/versions");
26
+ async function reactGenerator(tree, options) {
27
+ var _backendProjectConfig_metadata;
28
+ const frontendProjectConfig = (0, _devkit.readProjectConfiguration)(tree, options.frontendProjectName);
29
+ const backendProjectConfig = (0, _devkit.readProjectConfiguration)(tree, options.backendProjectName);
30
+ const apiName = (_backendProjectConfig_metadata = backendProjectConfig.metadata) == null ? void 0 : _backendProjectConfig_metadata.apiName;
31
+ (0, _devkit.generateFiles)(tree, (0, _devkit.joinPathFragments)(__dirname, 'files'), frontendProjectConfig.root, _extends._({
32
+ apiName
33
+ }, options, {
34
+ backendProjectAlias: (0, _npmscope.toScopeAlias)(options.backendProjectName)
35
+ }));
36
+ await (0, _generator.runtimeConfigGenerator)(tree, {
37
+ project: options.frontendProjectName
38
+ });
39
+ const mainTsxPath = (0, _devkit.joinPathFragments)(frontendProjectConfig.sourceRoot, 'main.tsx');
40
+ if (!tree.exists(mainTsxPath)) {
41
+ throw new Error(`Could not find main.tsx in ${frontendProjectConfig.sourceRoot}`);
42
+ }
43
+ const mainTsxContents = tree.read(mainTsxPath).toString();
44
+ const trpcProviderImport = _typescript.factory.createImportDeclaration(undefined, _typescript.factory.createImportClause(false, _typescript.factory.createIdentifier('TRPCClientProvider'), undefined), _typescript.factory.createStringLiteral('./components/TRPCClientProvider'));
45
+ const updatedImports = _tsquery.tsquery.map((0, _tsquery.ast)(mainTsxContents), 'SourceFile', (node)=>{
46
+ return _extends._({}, node, {
47
+ statements: [
48
+ trpcProviderImport,
49
+ ...node.statements
50
+ ]
51
+ });
52
+ }).getFullText();
53
+ let locatedNode = false;
54
+ const mainTsxUpdatedContents = _tsquery.tsquery.map((0, _tsquery.ast)(updatedImports), 'JsxSelfClosingElement', (node)=>{
55
+ if (node.tagName.getText() !== 'App') {
56
+ return node;
57
+ } else {
58
+ locatedNode = true;
59
+ }
60
+ return _typescript.factory.createJsxElement(_typescript.factory.createJsxOpeningElement(_typescript.factory.createIdentifier('TRPCClientProvider'), undefined, _typescript.factory.createJsxAttributes([])), [
61
+ node
62
+ ], _typescript.factory.createJsxClosingElement(_typescript.factory.createIdentifier('TRPCClientProvider')));
63
+ }).getFullText();
64
+ if (!locatedNode) {
65
+ throw new Error('Could not locate App component in main.tsx');
66
+ }
67
+ if (mainTsxContents !== mainTsxUpdatedContents) {
68
+ tree.write(mainTsxPath, mainTsxUpdatedContents);
69
+ }
70
+ (0, _devkit.addDependenciesToPackageJson)(tree, (0, _versions.withVersions)([
71
+ "@trpc/react-query",
72
+ "@tanstack/react-query"
73
+ ]), {});
74
+ await (0, _devkit.formatFiles)(tree);
75
+ return ()=>{
76
+ (0, _devkit.installPackagesTask)(tree);
77
+ };
78
+ }
79
+ const _default = reactGenerator;
80
+
81
+ //# sourceMappingURL=generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/trpc/react/generator.ts"],"sourcesContent":["import {\n addDependenciesToPackageJson,\n formatFiles,\n generateFiles,\n installPackagesTask,\n joinPathFragments,\n readProjectConfiguration,\n Tree,\n} from '@nx/devkit';\nimport { ReactGeneratorSchema } from './schema';\nimport {\n factory,\n ImportClause,\n JsxSelfClosingElement,\n SourceFile,\n} from 'typescript';\nimport { ast, tsquery } from '@phenomnomnominal/tsquery';\nimport { runtimeConfigGenerator } from '../../cloudscape-website/runtime-config/generator';\nimport { toScopeAlias } from '../../utils/npm-scope';\nimport { withVersions } from '../../utils/versions';\n\nexport async function reactGenerator(\n tree: Tree,\n options: ReactGeneratorSchema\n) {\n const frontendProjectConfig = readProjectConfiguration(\n tree,\n options.frontendProjectName\n );\n const backendProjectConfig = readProjectConfiguration(\n tree,\n options.backendProjectName\n );\n const apiName = (backendProjectConfig.metadata as any)?.apiName;\n generateFiles(\n tree,\n joinPathFragments(__dirname, 'files'),\n frontendProjectConfig.root,\n {\n apiName,\n ...options,\n backendProjectAlias: toScopeAlias(options.backendProjectName),\n }\n );\n\n await runtimeConfigGenerator(tree, {\n project: options.frontendProjectName,\n });\n\n const mainTsxPath = joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'main.tsx'\n );\n\n if (!tree.exists(mainTsxPath)) {\n throw new Error(\n `Could not find main.tsx in ${frontendProjectConfig.sourceRoot}`\n );\n }\n\n const mainTsxContents = tree.read(mainTsxPath).toString();\n\n const trpcProviderImport = factory.createImportDeclaration(\n undefined,\n factory.createImportClause(\n false,\n factory.createIdentifier('TRPCClientProvider'),\n undefined\n ) as ImportClause,\n factory.createStringLiteral('./components/TRPCClientProvider')\n );\n\n const updatedImports = tsquery\n .map(ast(mainTsxContents), 'SourceFile', (node: SourceFile) => {\n return {\n ...node,\n statements: [trpcProviderImport, ...node.statements],\n };\n })\n .getFullText();\n\n let locatedNode = false;\n const mainTsxUpdatedContents = tsquery\n .map(\n ast(updatedImports),\n 'JsxSelfClosingElement',\n (node: JsxSelfClosingElement) => {\n if (node.tagName.getText() !== 'App') {\n return node;\n } else {\n locatedNode = true;\n }\n\n return factory.createJsxElement(\n factory.createJsxOpeningElement(\n factory.createIdentifier('TRPCClientProvider'),\n undefined,\n factory.createJsxAttributes([])\n ),\n [node],\n factory.createJsxClosingElement(\n factory.createIdentifier('TRPCClientProvider')\n )\n );\n }\n )\n .getFullText();\n\n if (!locatedNode) {\n throw new Error('Could not locate App component in main.tsx');\n }\n\n if (mainTsxContents !== mainTsxUpdatedContents) {\n tree.write(mainTsxPath, mainTsxUpdatedContents);\n }\n\n addDependenciesToPackageJson(\n tree,\n withVersions([\n \"@trpc/react-query\",\n \"@tanstack/react-query\",\n ]),\n {}\n );\n await formatFiles(tree);\n\n return () => {\n installPackagesTask(tree);\n };\n}\n\nexport default reactGenerator;\n"],"names":["reactGenerator","tree","options","backendProjectConfig","frontendProjectConfig","readProjectConfiguration","frontendProjectName","backendProjectName","apiName","metadata","generateFiles","joinPathFragments","__dirname","root","backendProjectAlias","toScopeAlias","runtimeConfigGenerator","project","mainTsxPath","sourceRoot","exists","Error","mainTsxContents","read","toString","trpcProviderImport","factory","createImportDeclaration","undefined","createImportClause","createIdentifier","createStringLiteral","updatedImports","tsquery","map","ast","node","statements","getFullText","locatedNode","mainTsxUpdatedContents","tagName","getText","createJsxElement","createJsxOpeningElement","createJsxAttributes","createJsxClosingElement","write","addDependenciesToPackageJson","withVersions","formatFiles","installPackagesTask"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;;;;;;;;IAmIA,OAA8B;eAA9B;;IA9GsBA,cAAc;eAAdA;;;;wBAbf;4BAOA;yBACsB;2BACU;0BACV;0BACA;AAEtB,eAAeA,eACpBC,IAAU,EACVC,OAA6B;QAUZC;IARjB,MAAMC,wBAAwBC,IAAAA,gCAAwB,EACpDJ,MACAC,QAAQI,mBAAmB;IAE7B,MAAMH,uBAAuBE,IAAAA,gCAAwB,EACnDJ,MACAC,QAAQK,kBAAkB;IAE5B,MAAMC,WAAWL,iCAAAA,qBAAqBM,QAAQ,qBAA9B,AAACN,+BAAuCK,OAAO;IAC/DE,IAAAA,qBAAa,EACXT,MACAU,IAAAA,yBAAiB,EAACC,WAAW,UAC7BR,sBAAsBS,IAAI,EAC1B;QACEL;OACGN;QACHY,qBAAqBC,IAAAA,sBAAY,EAACb,QAAQK,kBAAkB;;IAIhE,MAAMS,IAAAA,iCAAsB,EAACf,MAAM;QACjCgB,SAASf,QAAQI,mBAAmB;IACtC;IAEA,MAAMY,cAAcP,IAAAA,yBAAiB,EACnCP,sBAAsBe,UAAU,EAChC;IAGF,IAAI,CAAClB,KAAKmB,MAAM,CAACF,cAAc;QAC7B,MAAM,IAAIG,MACR,CAAC,2BAA2B,EAAEjB,sBAAsBe,UAAU,CAAC,CAAC;IAEpE;IAEA,MAAMG,kBAAkBrB,KAAKsB,IAAI,CAACL,aAAaM,QAAQ;IAEvD,MAAMC,qBAAqBC,mBAAO,CAACC,uBAAuB,CACxDC,WACAF,mBAAO,CAACG,kBAAkB,CACxB,OACAH,mBAAO,CAACI,gBAAgB,CAAC,uBACzBF,YAEFF,mBAAO,CAACK,mBAAmB,CAAC;IAG9B,MAAMC,iBAAiBC,gBAAO,CAC3BC,GAAG,CAACC,IAAAA,YAAG,EAACb,kBAAkB,cAAc,CAACc;QACxC,OAAO,eACFA;YACHC,YAAY;gBAACZ;mBAAuBW,KAAKC,UAAU;aAAC;;IAExD,GACCC,WAAW;IAEd,IAAIC,cAAc;IAClB,MAAMC,yBAAyBP,gBAAO,CACnCC,GAAG,CACFC,IAAAA,YAAG,EAACH,iBACJ,yBACA,CAACI;QACC,IAAIA,KAAKK,OAAO,CAACC,OAAO,OAAO,OAAO;YACpC,OAAON;QACT,OAAO;YACHG,cAAc;QAClB;QAEA,OAAOb,mBAAO,CAACiB,gBAAgB,CAC7BjB,mBAAO,CAACkB,uBAAuB,CAC7BlB,mBAAO,CAACI,gBAAgB,CAAC,uBACzBF,WACAF,mBAAO,CAACmB,mBAAmB,CAAC,EAAE,IAEhC;YAACT;SAAK,EACNV,mBAAO,CAACoB,uBAAuB,CAC7BpB,mBAAO,CAACI,gBAAgB,CAAC;IAG/B,GAEDQ,WAAW;IAEd,IAAI,CAACC,aAAa;QAChB,MAAM,IAAIlB,MAAM;IAClB;IAEA,IAAIC,oBAAoBkB,wBAAwB;QAC9CvC,KAAK8C,KAAK,CAAC7B,aAAasB;IAC1B;IAEAQ,IAAAA,oCAA4B,EAC1B/C,MACAgD,IAAAA,sBAAY,EAAC;QACX;QACA;KACD,GACD,CAAC;IAEH,MAAMC,IAAAA,mBAAW,EAACjD;IAElB,OAAO;QACLkD,IAAAA,2BAAmB,EAAClD;IACtB;AACF;MAEA,WAAeD"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+
6
+ //# sourceMappingURL=schema.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/trpc/react/schema.d.ts"],"names":[],"rangeMappings":"","mappings":""}
@@ -0,0 +1,5 @@
1
+ export interface ReactGeneratorSchema {
2
+ frontendProjectName: string;
3
+ backendProjectName: string;
4
+ auth: 'IAM' | 'None';
5
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "$schema": "https://json-schema.org/schema",
3
+ "$id": "React",
4
+ "title": "",
5
+ "type": "object",
6
+ "properties": {
7
+ "frontendProjectName": {
8
+ "type": "string",
9
+ "description": "",
10
+ "$default": {
11
+ "$source": "argv",
12
+ "index": 0
13
+ },
14
+ "x-prompt": "React application's project name.",
15
+ "x-dropdown": "projects"
16
+ },
17
+ "backendProjectName": {
18
+ "type": "string",
19
+ "description": "",
20
+ "x-prompt": "Package containing your Api Backend.",
21
+ "x-dropdown": "projects"
22
+ },
23
+ "auth": {
24
+ "type": "string",
25
+ "description": "",
26
+ "x-prompt": "Select your API authentication strategy",
27
+ "x-dropdown": ["IAM", "None"],
28
+ "default": "IAM"
29
+ }
30
+ },
31
+ "required": ["frontendProjectName", "backendProjectName", "auth"]
32
+ }
@@ -0,0 +1,8 @@
1
+ import { Tree } from '@nx/devkit';
2
+ import { CjsToEsmGeneratorSchema } from './schema';
3
+ export declare function cjsToEsm(tree: Tree, relativePathInTree: string, options?: {
4
+ include?: string[];
5
+ exclude?: string[];
6
+ }): void;
7
+ export declare function cjsToEsmGenerator(tree: Tree, options: CjsToEsmGeneratorSchema): Promise<void>;
8
+ export default cjsToEsmGenerator;