@aws/nx-plugin 0.1.6 → 0.2.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 +114 -244
- package/generators.json +1 -7
- package/package.json +1 -1
- package/src/cloudscape-website/app/README.md +84 -48
- package/src/cloudscape-website/app/__snapshots__/generator.spec.ts.snap +157 -218
- package/src/cloudscape-website/app/files/app/README.md.template +44 -0
- package/src/cloudscape-website/app/files/app/src/layouts/App/index.tsx.template +40 -43
- package/src/cloudscape-website/app/files/app/src/layouts/App/navitems.ts.template +3 -3
- package/src/cloudscape-website/app/files/app/src/layouts/Routes/index.tsx.template +4 -6
- package/src/cloudscape-website/app/files/app/src/main.tsx.template +7 -10
- package/src/cloudscape-website/app/files/app/src/pages/Home/index.tsx.template +0 -2
- package/src/cloudscape-website/app/files/common/constructs/src/app/static-websites/__websiteNameKebabCase__.ts.template +13 -0
- package/src/cloudscape-website/app/files/common/constructs/src/{__websiteNameKebabCase__ → core}/static-website.ts.template +74 -144
- package/src/cloudscape-website/app/generator.js +74 -64
- package/src/cloudscape-website/app/generator.js.map +1 -1
- package/src/cloudscape-website/app/schema.d.ts +3 -4
- package/src/cloudscape-website/app/schema.json +1 -24
- package/src/cloudscape-website/cognito-auth/README.md +53 -32
- package/src/cloudscape-website/cognito-auth/__snapshots__/generator.spec.ts.snap +161 -125
- package/src/cloudscape-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +53 -39
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/core/user-identity.ts.template +168 -0
- package/src/cloudscape-website/cognito-auth/generator.js +129 -46
- package/src/cloudscape-website/cognito-auth/generator.js.map +1 -1
- package/src/cloudscape-website/cognito-auth/schema.d.ts +1 -0
- package/src/cloudscape-website/cognito-auth/schema.json +7 -1
- package/src/cloudscape-website/runtime-config/__snapshots__/generator.spec.ts.snap +15 -17
- package/src/cloudscape-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +7 -10
- package/src/cloudscape-website/runtime-config/files/app/hooks/useRuntimeConfig.tsx.template +13 -0
- package/src/cloudscape-website/runtime-config/generator.js +3 -1
- package/src/cloudscape-website/runtime-config/generator.js.map +1 -1
- package/src/infra/app/README.md +71 -46
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +114 -252
- package/src/infra/app/files/app/README.md.template +76 -0
- package/src/infra/app/files/app/src/main.ts.template +18 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/aws-prototyping.guard +1282 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/cfn-nag.guard +6839 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/hipaa-security.guard +2807 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/nist-csf.guard +2585 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/pci-dss-3-2-1.guard +2236 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/wa-reliability-pillar.guard +885 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard-rules/wa-security-pillar.guard +2205 -0
- package/src/infra/app/files/common/constructs/src/core/cfn-guard.ts.template +63 -0
- package/src/infra/app/generator.js +17 -3
- package/src/infra/app/generator.js.map +1 -1
- package/src/infra/app/schema.d.ts +10 -1
- package/src/infra/app/schema.json +16 -8
- package/src/trpc/backend/README.md +102 -80
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +37 -17
- package/src/trpc/backend/files/backend/README.md.template +33 -0
- package/src/trpc/backend/files/common/constructs/src/app/trpc-apis/__apiNameKebabCase__.ts.template +18 -0
- package/src/trpc/backend/files/common/constructs/src/{__apiNameKebabCase__/index.ts.template → core/trpc-api.ts.template} +12 -16
- package/src/trpc/backend/files/schema/README.md.template +33 -0
- package/src/trpc/backend/generator.js +29 -43
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/backend/schema.d.ts +3 -1
- package/src/trpc/backend/schema.json +8 -13
- package/src/trpc/react/README.md +46 -66
- package/src/trpc/react/__snapshots__/generator.spec.ts.snap +104 -65
- package/src/trpc/react/files/src/components/TrpcClients/IsolatedTrpcProvider.tsx.template +75 -0
- package/src/trpc/react/files/src/components/TrpcClients/TrpcApis.tsx.template +1 -0
- package/src/trpc/react/files/src/components/TrpcClients/TrpcClientProviders.tsx.template +10 -0
- package/src/trpc/react/files/src/components/TrpcClients/index.tsx.template +5 -0
- package/src/trpc/react/files/src/hooks/useSigV4.tsx.template +38 -0
- package/src/trpc/react/files/src/hooks/use__apiNameClassName__.tsx.template +3 -0
- package/src/trpc/react/generator.js +123 -24
- package/src/trpc/react/generator.js.map +1 -1
- package/src/trpc/react/schema.json +2 -2
- package/src/ts/cjs-to-esm/generator.js.map +1 -1
- package/src/ts/lib/eslint.d.ts +1 -1
- package/src/ts/lib/eslint.js +59 -11
- package/src/ts/lib/eslint.js.map +1 -1
- package/src/ts/lib/files/README.md.template +33 -0
- package/src/ts/lib/generator.js +11 -4
- package/src/ts/lib/generator.js.map +1 -1
- package/src/ts/lib/schema.d.ts +1 -3
- package/src/ts/lib/schema.json +2 -15
- package/src/ts/lib/ts-project-utils.js.map +1 -1
- package/src/ts/lib/vitest.js +14 -0
- package/src/ts/lib/vitest.js.map +1 -1
- package/src/utils/ast.d.ts +13 -0
- package/src/utils/ast.js +102 -0
- package/src/utils/ast.js.map +1 -0
- package/src/utils/files/common/constructs/src/app/index.ts.template +0 -0
- package/src/utils/files/common/constructs/src/{runtime-config → core}/runtime-config.ts.template +3 -5
- package/src/utils/files/common/constructs/src/index.ts.template +2 -1
- package/src/utils/files/common/readme/README.md.template +33 -0
- package/src/utils/files/common/types/src/runtime-config.ts.template +1 -13
- package/src/utils/format.js.map +1 -1
- package/src/utils/names.d.ts +2 -0
- package/src/utils/names.js +27 -0
- package/src/utils/names.js.map +1 -0
- package/src/utils/npm-scope.js.map +1 -1
- package/src/utils/paths.js.map +1 -1
- package/src/utils/shared-constructs.js +37 -4
- package/src/utils/shared-constructs.js.map +1 -1
- package/src/utils/versions.d.ts +15 -9
- package/src/utils/versions.js +14 -8
- package/src/utils/versions.js.map +1 -1
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/cloudfront-web-acl.ts.template +0 -317
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/index.ts.template +0 -4
- package/src/cloudscape-website/app/files/common/constructs/src/__websiteNameKebabCase__/webacl_event_handler/index.ts.template +0 -301
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/index.ts.template +0 -4
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/user-identity.ts.template +0 -66
- package/src/cloudscape-website/cognito-auth/files/common/constructs/src/identity/userpool-with-mfa.ts.template +0 -70
- package/src/gitlab/generator.d.ts +0 -8
- package/src/gitlab/generator.js +0 -16
- package/src/gitlab/generator.js.map +0 -1
- package/src/gitlab/schema.d.ts +0 -9
- package/src/gitlab/schema.json +0 -52
- package/src/infra/app/files/src/main.ts.template +0 -37
- package/src/trpc/react/files/src/components/TRPCClientProvider/index.tsx.template +0 -34
- package/src/trpc/react/files/src/hooks/useTrpc.tsx.template +0 -5
- /package/src/infra/app/files/{cdk.json → app/cdk.json} +0 -0
- /package/src/infra/app/files/{src → app/src}/stacks/application-stack.ts.template +0 -0
- /package/src/utils/files/common/constructs/src/{runtime-config → core}/index.ts.template +0 -0
package/src/trpc/react/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# tRPC React Generator
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
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 backends, including AWS IAM authentication support and proper error handling. The integration provides full end-to-end type safety between your frontend and tRPC backend(s).
|
|
5
6
|
|
|
6
7
|
## Prerequisites
|
|
7
8
|
|
|
@@ -12,14 +13,13 @@ Before using this generator, ensure your React application has:
|
|
|
12
13
|
3. A working tRPC backend (generated using the tRPC backend generator)
|
|
13
14
|
|
|
14
15
|
Example of required `main.tsx` structure:
|
|
16
|
+
|
|
15
17
|
```tsx
|
|
16
18
|
import { StrictMode } from 'react';
|
|
17
19
|
import * as ReactDOM from 'react-dom/client';
|
|
18
20
|
import App from './app/app';
|
|
19
21
|
|
|
20
|
-
const root = ReactDOM.createRoot(
|
|
21
|
-
document.getElementById('root') as HTMLElement
|
|
22
|
-
);
|
|
22
|
+
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
|
23
23
|
root.render(
|
|
24
24
|
<StrictMode>
|
|
25
25
|
<App />
|
|
@@ -34,12 +34,14 @@ You can generate the tRPC React integration in two ways:
|
|
|
34
34
|
### 1. Using VSCode IDE
|
|
35
35
|
|
|
36
36
|
First, install the NX Console extension for VSCode:
|
|
37
|
+
|
|
37
38
|
1. Open VSCode
|
|
38
39
|
2. Go to Extensions (Ctrl+Shift+X / Cmd+Shift+X)
|
|
39
40
|
3. Search for "Nx Console"
|
|
40
41
|
4. Install [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console)
|
|
41
42
|
|
|
42
43
|
Then add tRPC to your React application:
|
|
44
|
+
|
|
43
45
|
1. Open the NX Console in VSCode
|
|
44
46
|
2. Click on "Generate"
|
|
45
47
|
3. Search for "trpc#react"
|
|
@@ -49,11 +51,13 @@ Then add tRPC to your React application:
|
|
|
49
51
|
### 2. Using CLI
|
|
50
52
|
|
|
51
53
|
Add tRPC to your React application:
|
|
54
|
+
|
|
52
55
|
```bash
|
|
53
56
|
nx g @aws/nx-plugin:trpc#react --frontendProjectName=my-app --backendProjectName=my-api --auth=IAM
|
|
54
57
|
```
|
|
55
58
|
|
|
56
59
|
You can also perform a dry-run to see what files would be generated without actually creating them:
|
|
60
|
+
|
|
57
61
|
```bash
|
|
58
62
|
nx g @aws/nx-plugin:trpc#react --frontendProjectName=my-app --backendProjectName=my-api --auth=IAM --dry-run
|
|
59
63
|
```
|
|
@@ -62,13 +66,13 @@ Both methods will add tRPC client integration to your React application with all
|
|
|
62
66
|
|
|
63
67
|
## Input Parameters
|
|
64
68
|
|
|
65
|
-
| Parameter
|
|
66
|
-
|
|
67
|
-
| frontendProjectName
|
|
68
|
-
| backendProjectName
|
|
69
|
-
| auth
|
|
69
|
+
| Parameter | Type | Default | Description |
|
|
70
|
+
| --------------------- | ------ | ------- | ------------------------------------------------------ |
|
|
71
|
+
| frontendProjectName\* | string | - | The name of your React application project (required). |
|
|
72
|
+
| backendProjectName\* | string | - | The name of your tRPC backend project (required). |
|
|
73
|
+
| auth\* | string | "IAM" | Authentication strategy. Options: "IAM", "None" |
|
|
70
74
|
|
|
71
|
-
|
|
75
|
+
\*Required parameter
|
|
72
76
|
|
|
73
77
|
## Expected Output
|
|
74
78
|
|
|
@@ -77,13 +81,18 @@ The generator creates the following structure in your React application:
|
|
|
77
81
|
```
|
|
78
82
|
src/
|
|
79
83
|
├── components/
|
|
80
|
-
│ └──
|
|
81
|
-
│ └── index.tsx
|
|
84
|
+
│ └── TrpcClients/
|
|
85
|
+
│ └── index.tsx
|
|
86
|
+
│ └── IsolatedTrpcProvider.tsx # Supports add connections to multiple tRPC APIs
|
|
87
|
+
│ └── TrpcApis.tsx # Object containing all of your trpc API connections
|
|
88
|
+
│ └── TrpcClientProviders.tsx # Sets up the trpc clients and bindings to your backend schema(s)
|
|
82
89
|
└── hooks/
|
|
83
|
-
└──
|
|
90
|
+
└── useSigV4.tsx # Custom hook for signing HTTP(s) requests with SigV4 (IAM only)
|
|
91
|
+
└── use<ApiName>.tsx # Adds a hook for the given backend API. ApiName will resolve to the name of the api.
|
|
84
92
|
```
|
|
85
93
|
|
|
86
94
|
Additionally, it:
|
|
95
|
+
|
|
87
96
|
1. Installs required dependencies:
|
|
88
97
|
- @trpc/client
|
|
89
98
|
- @trpc/react-query
|
|
@@ -94,13 +103,13 @@ Additionally, it:
|
|
|
94
103
|
|
|
95
104
|
### Using the tRPC Hook
|
|
96
105
|
|
|
97
|
-
The generator provides a `
|
|
106
|
+
The generator provides a `use<ApiName>` hook that gives you access to the type-safe tRPC client:
|
|
98
107
|
|
|
99
108
|
```tsx
|
|
100
|
-
import {
|
|
109
|
+
import { useMyApi } from './hooks/useMyApi';
|
|
101
110
|
|
|
102
111
|
function MyComponent() {
|
|
103
|
-
const trpc =
|
|
112
|
+
const trpc = useMyApi();
|
|
104
113
|
|
|
105
114
|
// Example query
|
|
106
115
|
const { data, isLoading } = trpc.users.list.useQuery();
|
|
@@ -111,17 +120,13 @@ function MyComponent() {
|
|
|
111
120
|
const handleCreate = () => {
|
|
112
121
|
mutation.mutate({
|
|
113
122
|
name: 'John Doe',
|
|
114
|
-
email: 'john@example.com'
|
|
123
|
+
email: 'john@example.com',
|
|
115
124
|
});
|
|
116
125
|
};
|
|
117
126
|
|
|
118
127
|
if (isLoading) return <div>Loading...</div>;
|
|
119
128
|
|
|
120
|
-
return
|
|
121
|
-
<div>
|
|
122
|
-
{/* Your component JSX */}
|
|
123
|
-
</div>
|
|
124
|
-
);
|
|
129
|
+
return <div>{/* Your component JSX */}</div>;
|
|
125
130
|
}
|
|
126
131
|
```
|
|
127
132
|
|
|
@@ -145,11 +150,7 @@ function MyComponent() {
|
|
|
145
150
|
);
|
|
146
151
|
}
|
|
147
152
|
|
|
148
|
-
return
|
|
149
|
-
<div>
|
|
150
|
-
{/* Your component JSX */}
|
|
151
|
-
</div>
|
|
152
|
-
);
|
|
153
|
+
return <div>{/* Your component JSX */}</div>;
|
|
153
154
|
}
|
|
154
155
|
```
|
|
155
156
|
|
|
@@ -173,7 +174,7 @@ function UserList() {
|
|
|
173
174
|
|
|
174
175
|
return (
|
|
175
176
|
<ul>
|
|
176
|
-
{users.data.map(user => (
|
|
177
|
+
{users.data.map((user) => (
|
|
177
178
|
<li key={user.id}>{user.name}</li>
|
|
178
179
|
))}
|
|
179
180
|
</ul>
|
|
@@ -187,7 +188,7 @@ Use optimistic updates for better user experience:
|
|
|
187
188
|
|
|
188
189
|
```tsx
|
|
189
190
|
function UserList() {
|
|
190
|
-
const trpc =
|
|
191
|
+
const trpc = useUsers();
|
|
191
192
|
const utils = trpc.useUtils();
|
|
192
193
|
|
|
193
194
|
const deleteMutation = trpc.users.delete.useMutation({
|
|
@@ -199,26 +200,22 @@ function UserList() {
|
|
|
199
200
|
const previousUsers = utils.users.list.getData();
|
|
200
201
|
|
|
201
202
|
// Optimistically remove the user
|
|
202
|
-
utils.users.list.setData(undefined, (old) =>
|
|
203
|
-
old?.filter(user => user.id !== userId)
|
|
204
|
-
);
|
|
203
|
+
utils.users.list.setData(undefined, (old) => old?.filter((user) => user.id !== userId));
|
|
205
204
|
|
|
206
205
|
return { previousUsers };
|
|
207
206
|
},
|
|
208
207
|
onError: (err, userId, context) => {
|
|
209
208
|
// Restore previous data on error
|
|
210
209
|
utils.users.list.setData(undefined, context?.previousUsers);
|
|
211
|
-
}
|
|
210
|
+
},
|
|
212
211
|
});
|
|
213
212
|
|
|
214
213
|
return (
|
|
215
214
|
<ul>
|
|
216
|
-
{users.map(user => (
|
|
215
|
+
{users.map((user) => (
|
|
217
216
|
<li key={user.id}>
|
|
218
217
|
{user.name}
|
|
219
|
-
<button onClick={() => deleteMutation.mutate(user.id)}>
|
|
220
|
-
Delete
|
|
221
|
-
</button>
|
|
218
|
+
<button onClick={() => deleteMutation.mutate(user.id)}>Delete</button>
|
|
222
219
|
</li>
|
|
223
220
|
))}
|
|
224
221
|
</ul>
|
|
@@ -232,7 +229,7 @@ Prefetch data for better performance:
|
|
|
232
229
|
|
|
233
230
|
```tsx
|
|
234
231
|
function UserList() {
|
|
235
|
-
const trpc =
|
|
232
|
+
const trpc = useUsers();
|
|
236
233
|
|
|
237
234
|
// Prefetch user details on hover
|
|
238
235
|
const prefetchUser = async (userId: string) => {
|
|
@@ -241,14 +238,9 @@ function UserList() {
|
|
|
241
238
|
|
|
242
239
|
return (
|
|
243
240
|
<ul>
|
|
244
|
-
{users.map(user => (
|
|
245
|
-
<li
|
|
246
|
-
|
|
247
|
-
onMouseEnter={() => prefetchUser(user.id)}
|
|
248
|
-
>
|
|
249
|
-
<Link to={`/users/${user.id}`}>
|
|
250
|
-
{user.name}
|
|
251
|
-
</Link>
|
|
241
|
+
{users.map((user) => (
|
|
242
|
+
<li key={user.id} onMouseEnter={() => prefetchUser(user.id)}>
|
|
243
|
+
<Link to={`/users/${user.id}`}>{user.name}</Link>
|
|
252
244
|
</li>
|
|
253
245
|
))}
|
|
254
246
|
</ul>
|
|
@@ -262,14 +254,9 @@ Handle pagination with infinite queries:
|
|
|
262
254
|
|
|
263
255
|
```tsx
|
|
264
256
|
function UserList() {
|
|
265
|
-
const trpc =
|
|
257
|
+
const trpc = useUsers();
|
|
266
258
|
|
|
267
|
-
const {
|
|
268
|
-
data,
|
|
269
|
-
fetchNextPage,
|
|
270
|
-
hasNextPage,
|
|
271
|
-
isFetchingNextPage
|
|
272
|
-
} = trpc.users.list.useInfiniteQuery(
|
|
259
|
+
const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = trpc.users.list.useInfiniteQuery(
|
|
273
260
|
{ limit: 10 },
|
|
274
261
|
{
|
|
275
262
|
getNextPageParam: (lastPage) => lastPage.nextCursor,
|
|
@@ -278,17 +265,10 @@ function UserList() {
|
|
|
278
265
|
|
|
279
266
|
return (
|
|
280
267
|
<div>
|
|
281
|
-
{data?.pages.map((page) => (
|
|
282
|
-
page.users.map(user => (
|
|
283
|
-
<UserCard key={user.id} user={user} />
|
|
284
|
-
))
|
|
285
|
-
))}
|
|
268
|
+
{data?.pages.map((page) => page.users.map((user) => <UserCard key={user.id} user={user} />))}
|
|
286
269
|
|
|
287
270
|
{hasNextPage && (
|
|
288
|
-
<button
|
|
289
|
-
onClick={() => fetchNextPage()}
|
|
290
|
-
disabled={isFetchingNextPage}
|
|
291
|
-
>
|
|
271
|
+
<button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
|
|
292
272
|
{isFetchingNextPage ? 'Loading...' : 'Load More'}
|
|
293
273
|
</button>
|
|
294
274
|
)}
|
|
@@ -303,16 +283,16 @@ The integration provides complete end-to-end type safety. Your IDE will provide
|
|
|
303
283
|
|
|
304
284
|
```tsx
|
|
305
285
|
function UserForm() {
|
|
306
|
-
const trpc =
|
|
307
|
-
|
|
286
|
+
const trpc = useUsers();
|
|
287
|
+
|
|
308
288
|
// ✅ Input is fully typed
|
|
309
289
|
const createUser = trpc.users.create.useMutation();
|
|
310
|
-
|
|
290
|
+
|
|
311
291
|
const handleSubmit = (data: CreateUserInput) => {
|
|
312
292
|
// ✅ Type error if input doesn't match schema
|
|
313
293
|
createUser.mutate(data);
|
|
314
294
|
};
|
|
315
|
-
|
|
295
|
+
|
|
316
296
|
return <form onSubmit={handleSubmit}>{/* ... */}</form>;
|
|
317
297
|
}
|
|
318
298
|
```
|
|
@@ -1,85 +1,124 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`trpc react generator > should generate trpc react files >
|
|
3
|
+
exports[`trpc react generator > should generate trpc react files > TrpcClients-IsolatedTrpcProvider.tsx 1`] = `
|
|
4
4
|
"import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const [trpcClient] = useState(() =>
|
|
16
|
-
trpc.createClient({
|
|
17
|
-
links: [
|
|
18
|
-
httpBatchLink({
|
|
19
|
-
url: runtimeContext?.trpcApis?.['TestApi']!,
|
|
20
|
-
}),
|
|
21
|
-
],
|
|
22
|
-
})
|
|
23
|
-
);
|
|
5
|
+
import { createTRPCReact } from '@trpc/react-query';
|
|
6
|
+
import {
|
|
7
|
+
httpBatchLink,
|
|
8
|
+
httpLink,
|
|
9
|
+
HTTPBatchLinkOptions,
|
|
10
|
+
HTTPLinkOptions,
|
|
11
|
+
splitLink,
|
|
12
|
+
} from '@trpc/client';
|
|
13
|
+
import { useState, FC, createContext, useMemo, PropsWithChildren } from 'react';
|
|
24
14
|
|
|
25
|
-
|
|
26
|
-
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
27
|
-
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
28
|
-
</trpc.Provider>
|
|
29
|
-
);
|
|
30
|
-
};
|
|
15
|
+
import { AnyTRPCRouter } from '@trpc/server';
|
|
31
16
|
|
|
32
|
-
export
|
|
33
|
-
|
|
34
|
-
|
|
17
|
+
export interface IsolatedTrpcClientProviderProps extends PropsWithChildren {
|
|
18
|
+
readonly apiUrl: string;
|
|
19
|
+
}
|
|
35
20
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
21
|
+
export const createIsolatedTrpcClientProvider = <
|
|
22
|
+
TAppRouter extends AnyTRPCRouter,
|
|
23
|
+
TContext
|
|
24
|
+
>() => {
|
|
25
|
+
const isolatedTrpcContext = createContext(null as any);
|
|
26
|
+
const trpc = createTRPCReact<TAppRouter, TContext>({
|
|
27
|
+
context: isolatedTrpcContext,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const IsolatedTrpcClientProvider: FC<IsolatedTrpcClientProviderProps> = ({
|
|
31
|
+
apiUrl,
|
|
32
|
+
children,
|
|
33
|
+
}) => {
|
|
34
|
+
const [queryClient] = useState(() => new QueryClient());
|
|
35
|
+
|
|
36
|
+
const trpcClient = useMemo(() => {
|
|
37
|
+
const linkOptions: HTTPLinkOptions<any> & HTTPBatchLinkOptions<any> = {
|
|
38
|
+
url: apiUrl,
|
|
39
|
+
};
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
// @ts-expect-error type errors due to unknown concrete AppRouter
|
|
42
|
+
return trpc.createClient({
|
|
43
|
+
links: [
|
|
44
|
+
splitLink({
|
|
45
|
+
condition(op) {
|
|
46
|
+
return op.context.skipBatch === true;
|
|
47
|
+
},
|
|
48
|
+
true: httpLink(linkOptions),
|
|
49
|
+
false: httpBatchLink(linkOptions),
|
|
50
|
+
}),
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
}, [apiUrl, sigv4Client]);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
// @ts-expect-error type errors due to unknown concrete AppRouter
|
|
57
|
+
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
58
|
+
<QueryClientProvider client={queryClient}>
|
|
59
|
+
{children}
|
|
60
|
+
</QueryClientProvider>
|
|
61
|
+
{/* @ts-expect-error type errors due to unknown concrete AppRouter */}
|
|
62
|
+
</trpc.Provider>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
trpc,
|
|
68
|
+
Provider: IsolatedTrpcClientProvider,
|
|
69
|
+
};
|
|
70
|
+
};
|
|
42
71
|
"
|
|
43
72
|
`;
|
|
44
73
|
|
|
45
|
-
exports[`trpc react generator > should
|
|
46
|
-
"import {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
import {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
);
|
|
74
|
+
exports[`trpc react generator > should generate trpc react files > TrpcClients-TrpcApis.tsx 1`] = `
|
|
75
|
+
"import {
|
|
76
|
+
AppRouter as TestApiAppRouter,
|
|
77
|
+
Context as TestApiContext,
|
|
78
|
+
} from 'backend';
|
|
79
|
+
import { createIsolatedTrpcClientProvider } from './IsolatedTrpcProvider';
|
|
80
|
+
export default {
|
|
81
|
+
TestApi: createIsolatedTrpcClientProvider<TestApiAppRouter, TestApiContext>(),
|
|
82
|
+
};
|
|
83
|
+
"
|
|
84
|
+
`;
|
|
69
85
|
|
|
86
|
+
exports[`trpc react generator > should generate trpc react files > TrpcClients-TrpcClientProviders.tsx 1`] = `
|
|
87
|
+
"import TrpcApis from './TrpcApis';
|
|
88
|
+
import { useRuntimeConfig } from '../../hooks/useRuntimeConfig';
|
|
89
|
+
import { FC, PropsWithChildren } from 'react';
|
|
90
|
+
const TrpcClientProviders: FC<PropsWithChildren> = ({ children }) => {
|
|
91
|
+
const runtimeConfig = useRuntimeConfig();
|
|
70
92
|
return (
|
|
71
|
-
<
|
|
72
|
-
|
|
73
|
-
</
|
|
93
|
+
<TrpcApis.TestApi.Provider apiUrl={runtimeConfig.trpcApis.TestApi}>
|
|
94
|
+
{children}
|
|
95
|
+
</TrpcApis.TestApi.Provider>
|
|
74
96
|
);
|
|
75
97
|
};
|
|
98
|
+
export default TrpcClientProviders;
|
|
99
|
+
"
|
|
100
|
+
`;
|
|
76
101
|
|
|
77
|
-
|
|
102
|
+
exports[`trpc react generator > should generate trpc react files > TrpcClients-index.tsx 1`] = `
|
|
103
|
+
"import TrpcClientProviders from './TrpcClientProviders';
|
|
104
|
+
import _TrpcApis from './TrpcApis';
|
|
105
|
+
|
|
106
|
+
export const TrpcApis = _TrpcApis;
|
|
107
|
+
export default TrpcClientProviders;
|
|
108
|
+
"
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
exports[`trpc react generator > should generate trpc react files > useTestApi.tsx 1`] = `
|
|
112
|
+
"import { TrpcApis } from '../components/TrpcClients';
|
|
113
|
+
|
|
114
|
+
export const useTestApi = () => TrpcApis.TestApi.trpc;
|
|
78
115
|
"
|
|
79
116
|
`;
|
|
80
117
|
|
|
118
|
+
exports[`trpc react generator > should handle IAM auth option > TRPCClientProvider-IAM.tsx 1`] = `null`;
|
|
119
|
+
|
|
81
120
|
exports[`trpc react generator > should modify main.tsx correctly > main.tsx 1`] = `
|
|
82
|
-
"import
|
|
121
|
+
"import TrpcClientProviders from './components/TrpcClients';
|
|
83
122
|
import RuntimeConfigProvider from './components/RuntimeConfig';
|
|
84
123
|
import { App } from './app';
|
|
85
124
|
import { BrowserRouter } from 'react-router-dom';
|
|
@@ -87,9 +126,9 @@ export function Main() {
|
|
|
87
126
|
return (
|
|
88
127
|
<RuntimeConfigProvider>
|
|
89
128
|
<BrowserRouter>
|
|
90
|
-
<
|
|
129
|
+
<TrpcClientProviders>
|
|
91
130
|
<App />
|
|
92
|
-
</
|
|
131
|
+
</TrpcClientProviders>
|
|
93
132
|
</BrowserRouter>
|
|
94
133
|
</RuntimeConfigProvider>
|
|
95
134
|
);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
2
|
+
import { createTRPCReact } from '@trpc/react-query';
|
|
3
|
+
import {
|
|
4
|
+
httpBatchLink,
|
|
5
|
+
httpLink,
|
|
6
|
+
HTTPBatchLinkOptions,
|
|
7
|
+
HTTPLinkOptions,
|
|
8
|
+
splitLink,
|
|
9
|
+
} from '@trpc/client';
|
|
10
|
+
import {
|
|
11
|
+
useState,
|
|
12
|
+
FC,
|
|
13
|
+
createContext,
|
|
14
|
+
useMemo,
|
|
15
|
+
PropsWithChildren,
|
|
16
|
+
} from 'react';
|
|
17
|
+
<% if(auth === 'IAM') { %> import { useSigV4 } from '../../hooks/useSigV4'; <% } %>
|
|
18
|
+
import { AnyTRPCRouter } from '@trpc/server';
|
|
19
|
+
|
|
20
|
+
export interface IsolatedTrpcClientProviderProps extends PropsWithChildren {
|
|
21
|
+
readonly apiUrl: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const createIsolatedTrpcClientProvider = <
|
|
25
|
+
TAppRouter extends AnyTRPCRouter,
|
|
26
|
+
TContext
|
|
27
|
+
>() => {
|
|
28
|
+
const isolatedTrpcContext = createContext(null as any);
|
|
29
|
+
const trpc = createTRPCReact<TAppRouter, TContext>({
|
|
30
|
+
context: isolatedTrpcContext,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const IsolatedTrpcClientProvider: FC<IsolatedTrpcClientProviderProps> = ({
|
|
34
|
+
apiUrl,
|
|
35
|
+
children,
|
|
36
|
+
}) => {
|
|
37
|
+
const [queryClient] = useState(() => new QueryClient());
|
|
38
|
+
<% if(auth === 'IAM') { %> const sigv4Client = useSigV4(); <% } %>
|
|
39
|
+
|
|
40
|
+
const trpcClient = useMemo(() => {
|
|
41
|
+
const linkOptions: HTTPLinkOptions<any> & HTTPBatchLinkOptions<any> = {
|
|
42
|
+
url: apiUrl,
|
|
43
|
+
<% if(auth === 'IAM') { %> fetch: sigv4Client <% } %>
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// @ts-expect-error type errors due to unknown concrete AppRouter
|
|
47
|
+
return trpc.createClient({
|
|
48
|
+
links: [
|
|
49
|
+
splitLink({
|
|
50
|
+
condition(op) {
|
|
51
|
+
return op.context.skipBatch === true;
|
|
52
|
+
},
|
|
53
|
+
true: httpLink(linkOptions),
|
|
54
|
+
false: httpBatchLink(linkOptions),
|
|
55
|
+
}),
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
}, [apiUrl, sigv4Client]);
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
// @ts-expect-error type errors due to unknown concrete AppRouter
|
|
62
|
+
<trpc.Provider client={trpcClient} queryClient={queryClient}>
|
|
63
|
+
<QueryClientProvider client={queryClient}>
|
|
64
|
+
{children}
|
|
65
|
+
</QueryClientProvider>
|
|
66
|
+
{/* @ts-expect-error type errors due to unknown concrete AppRouter */}
|
|
67
|
+
</trpc.Provider>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
trpc,
|
|
73
|
+
Provider: IsolatedTrpcClientProvider,
|
|
74
|
+
};
|
|
75
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default {}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { AwsClient } from 'aws4fetch';
|
|
2
|
+
import { CognitoIdentityClient } from '@aws-sdk/client-cognito-identity';
|
|
3
|
+
import { fromCognitoIdentityPool } from '@aws-sdk/credential-provider-cognito-identity';
|
|
4
|
+
import { useCallback } from 'react';
|
|
5
|
+
import { useAuth } from 'react-oidc-context';
|
|
6
|
+
import { useRuntimeConfig } from './useRuntimeConfig';
|
|
7
|
+
|
|
8
|
+
export const useSigV4 = () => {
|
|
9
|
+
const { cognitoProps } = useRuntimeConfig();
|
|
10
|
+
const { user } = useAuth();
|
|
11
|
+
|
|
12
|
+
return useCallback(
|
|
13
|
+
async (input: RequestInfo | URL, init?: RequestInit | undefined) => {
|
|
14
|
+
if (!cognitoProps) {
|
|
15
|
+
throw new Error('cognitoProps is undefined!');
|
|
16
|
+
}
|
|
17
|
+
if (!user?.id_token) {
|
|
18
|
+
throw new Error('user.id_token is undefined!');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const credentialsFromCognitoIdentityPool = fromCognitoIdentityPool({
|
|
22
|
+
client: new CognitoIdentityClient({ region: cognitoProps.region }),
|
|
23
|
+
identityPoolId: cognitoProps.identityPoolId,
|
|
24
|
+
logins: {
|
|
25
|
+
[`cognito-idp.${cognitoProps.region}.amazonaws.com/${cognitoProps.userPoolId}`]:
|
|
26
|
+
user.id_token,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
const cognitoidentity = new CognitoIdentityClient({
|
|
30
|
+
credentials: credentialsFromCognitoIdentityPool,
|
|
31
|
+
});
|
|
32
|
+
const credential = await cognitoidentity.config.credentials();
|
|
33
|
+
const awsClient = new AwsClient(credential);
|
|
34
|
+
return awsClient.fetch(input, init);
|
|
35
|
+
},
|
|
36
|
+
[cognitoProps, user?.id_token]
|
|
37
|
+
);
|
|
38
|
+
};
|