Skip to content

Commit f45023c

Browse files
committed
Refactor Data Client to use a custom abstracton layer for better Connect RPC intercompatibility
1 parent 837c892 commit f45023c

30 files changed

Lines changed: 2250 additions & 2266 deletions

packages/client/src/assertions.tsx

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import { useTransport } from '@connectrpc/connect-query';
2-
import { useController, useSuspense } from '@data-client/react';
1+
import { useRouteContext } from '@tanstack/react-router';
32
import { Struct } from 'effect';
43
import { useEffect } from 'react';
54
import { useFieldArray, useForm } from 'react-hook-form';
@@ -14,6 +13,7 @@ import {
1413
} from '@the-dev-tools/spec/meta/collection/item/request/v1/request.endpoints.ts';
1514
import { Button } from '@the-dev-tools/ui/button';
1615
import { tw } from '@the-dev-tools/ui/tailwind-literal';
16+
import { useQuery } from '~data-client';
1717

1818
import { ConditionField } from './condition';
1919

@@ -23,19 +23,16 @@ interface AssertionViewProps {
2323
}
2424

2525
export const AssertionView = ({ exampleId, isReadOnly }: AssertionViewProps) => {
26-
const transport = useTransport();
27-
const controller = useController();
26+
const { dataClient } = useRouteContext({ from: '__root__' });
2827

29-
const { items } = useSuspense(AssertListEndpoint, transport, { exampleId });
28+
const { items } = useQuery(AssertListEndpoint, { exampleId });
3029

3130
const form = useForm({ values: { items } });
3231
const fieldArray = useFieldArray({ control: form.control, name: 'items' });
3332

3433
const assertUpdateCallback = useDebouncedCallback(
3534
form.handleSubmit(async ({ items }) => {
36-
const updates = items.map((_) =>
37-
controller.fetch(AssertUpdateEndpoint, transport, { ...Struct.omit(_, '$typeName') }),
38-
);
35+
const updates = items.map((_) => dataClient.fetch(AssertUpdateEndpoint, { ...Struct.omit(_, '$typeName') }));
3936
await Promise.allSettled(updates);
4037
}),
4138
500,
@@ -61,7 +58,7 @@ export const AssertionView = ({ exampleId, isReadOnly }: AssertionViewProps) =>
6158
/>
6259
<Button
6360
className={tw`h-8 text-red-700`}
64-
onPress={() => void controller.fetch(AssertDeleteEndpoint, transport, { assertId: item.assertId })}
61+
onPress={() => void dataClient.fetch(AssertDeleteEndpoint, { assertId: item.assertId })}
6562
variant='secondary'
6663
>
6764
<LuTrash2 />
@@ -70,9 +67,7 @@ export const AssertionView = ({ exampleId, isReadOnly }: AssertionViewProps) =>
7067
))}
7168

7269
{!isReadOnly && (
73-
<Button onPress={() => void controller.fetch(AssertCreateEndpoint, transport, { exampleId })}>
74-
New Assertion
75-
</Button>
70+
<Button onPress={() => void dataClient.fetch(AssertCreateEndpoint, { exampleId })}>New Assertion</Button>
7671
)}
7772
</div>
7873
);

packages/client/src/body.tsx

Lines changed: 36 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createClient } from '@connectrpc/connect';
22
import { useTransport } from '@connectrpc/connect-query';
3-
import { useController, useSuspense } from '@data-client/react';
3+
import { useRouteContext } from '@tanstack/react-router';
44
import CodeMirror from '@uiw/react-codemirror';
55
import { Match, pipe } from 'effect';
66
import { useContext, useState } from 'react';
@@ -51,6 +51,7 @@ import {
5151
CodeMirrorMarkupLanguages,
5252
useCodeMirrorLanguageExtensions,
5353
} from '~code-mirror/extensions';
54+
import { useQuery } from '~data-client';
5455
import { useReactRender } from '~react-render';
5556

5657
import {
@@ -73,18 +74,17 @@ interface BodyViewProps {
7374
}
7475

7576
export const BodyView = ({ deltaExampleId, exampleId, isReadOnly }: BodyViewProps) => {
76-
const transport = useTransport();
77-
const controller = useController();
77+
const { dataClient } = useRouteContext({ from: '__root__' });
7878

79-
const { bodyKind } = useSuspense(ExampleGetEndpoint, transport, { exampleId });
79+
const { bodyKind } = useQuery(ExampleGetEndpoint, { exampleId });
8080

8181
return (
8282
<div className='grid flex-1 grid-cols-[auto_1fr] grid-rows-[auto_1fr] items-start gap-4'>
8383
<RadioGroup
8484
aria-label='Body type'
8585
className='h-7 justify-center'
8686
isReadOnly={isReadOnly ?? false}
87-
onChange={(key) => controller.fetch(ExampleUpdateEndpoint, transport, { bodyKind: parseInt(key), exampleId })}
87+
onChange={(key) => dataClient.fetch(ExampleUpdateEndpoint, { bodyKind: parseInt(key), exampleId })}
8888
orientation='horizontal'
8989
value={bodyKind.toString()}
9090
>
@@ -127,9 +127,7 @@ interface FormDisplayTableProps {
127127
}
128128

129129
const FormDisplayTable = ({ exampleId }: FormDisplayTableProps) => {
130-
const transport = useTransport();
131-
132-
const { items } = useSuspense(BodyFormListEndpoint, transport, { exampleId });
130+
const { items } = useQuery(BodyFormListEndpoint, { exampleId });
133131

134132
const table = useReactTable({
135133
columns: formDataColumns,
@@ -144,18 +142,17 @@ interface FormDataTableProps {
144142
}
145143

146144
const FormDataTable = ({ exampleId }: FormDataTableProps) => {
147-
const transport = useTransport();
148-
const controller = useController();
145+
const { dataClient } = useRouteContext({ from: '__root__' });
149146

150-
const items: GenericMessage<BodyFormListItem>[] = useSuspense(BodyFormListEndpoint, transport, {
147+
const items: GenericMessage<BodyFormListItem>[] = useQuery(BodyFormListEndpoint, {
151148
exampleId,
152149
}).items;
153150

154151
const table = useReactTable({
155152
columns: [
156153
...formDataColumns,
157154
columnActionsCommon<GenericMessage<BodyFormListItem>>({
158-
onDelete: (_) => controller.fetch(BodyFormDeleteEndpoint, transport, { bodyId: _.bodyId }),
155+
onDelete: (_) => dataClient.fetch(BodyFormDeleteEndpoint, { bodyId: _.bodyId }),
159156
}),
160157
],
161158
data: items,
@@ -165,10 +162,10 @@ const FormDataTable = ({ exampleId }: FormDataTableProps) => {
165162
createLabel: 'New form data item',
166163
items,
167164
onCreate: async () => {
168-
await controller.fetch(BodyFormCreateEndpoint, transport, { enabled: true, exampleId });
169-
await controller.invalidateAll({ testKey: (_) => _.startsWith(BodyFormDeltaListEndpoint.name) });
165+
await dataClient.fetch(BodyFormCreateEndpoint, { enabled: true, exampleId });
166+
await dataClient.controller.invalidateAll({ testKey: (_) => _.startsWith(BodyFormDeltaListEndpoint.name) });
170167
},
171-
onUpdate: ({ $typeName: _, ...item }) => controller.fetch(BodyFormUpdateEndpoint, transport, item),
168+
onUpdate: ({ $typeName: _, ...item }) => dataClient.fetch(BodyFormUpdateEndpoint, item),
172169
primaryColumn: 'key',
173170
});
174171

@@ -181,19 +178,17 @@ interface FormDeltaDataTableProps {
181178
}
182179

183180
const FormDeltaDataTable = ({ deltaExampleId: exampleId, exampleId: originId }: FormDeltaDataTableProps) => {
184-
const transport = useTransport();
185-
const controller = useController();
181+
const { dataClient } = useRouteContext({ from: '__root__' });
186182

187-
const items = pipe(
188-
useSuspense(BodyFormDeltaListEndpoint, transport, { exampleId, originId }).items,
189-
(_: BodyFormDeltaListItem[]) => makeDeltaItems(_, 'bodyId'),
183+
const items = pipe(useQuery(BodyFormDeltaListEndpoint, { exampleId, originId }).items, (_: BodyFormDeltaListItem[]) =>
184+
makeDeltaItems(_, 'bodyId'),
190185
);
191186

192187
const formTable = useFormTable({
193188
createLabel: 'New form data item',
194189
items,
195-
onCreate: () => controller.fetch(BodyFormDeltaCreateEndpoint, transport, { enabled: true, exampleId, originId }),
196-
onUpdate: ({ $typeName: _, ...item }) => controller.fetch(BodyFormDeltaUpdateEndpoint, transport, item),
190+
onCreate: () => dataClient.fetch(BodyFormDeltaCreateEndpoint, { enabled: true, exampleId, originId }),
191+
onUpdate: ({ $typeName: _, ...item }) => dataClient.fetch(BodyFormDeltaUpdateEndpoint, item),
197192
primaryColumn: 'key',
198193
});
199194

@@ -202,8 +197,8 @@ const FormDeltaDataTable = ({ deltaExampleId: exampleId, exampleId: originId }:
202197
columns={[
203198
...formDataColumns,
204199
columnActionsDeltaCommon<GenericMessage<BodyFormDeltaListItem>>({
205-
onDelete: (_) => controller.fetch(BodyFormDeltaDeleteEndpoint, transport, { bodyId: _.bodyId }),
206-
onReset: (_) => controller.fetch(BodyFormDeltaResetEndpoint, transport, { bodyId: _.bodyId }),
200+
onDelete: (_) => dataClient.fetch(BodyFormDeltaDeleteEndpoint, { bodyId: _.bodyId }),
201+
onReset: (_) => dataClient.fetch(BodyFormDeltaResetEndpoint, { bodyId: _.bodyId }),
207202
source: (_) => _.source,
208203
}),
209204
]}
@@ -227,9 +222,7 @@ interface UrlEncodedDisplayTableProps {
227222
}
228223

229224
const UrlEncodedDisplayTable = ({ exampleId }: UrlEncodedDisplayTableProps) => {
230-
const transport = useTransport();
231-
232-
const { items } = useSuspense(BodyUrlEncodedListEndpoint, transport, { exampleId });
225+
const { items } = useQuery(BodyUrlEncodedListEndpoint, { exampleId });
233226

234227
const table = useReactTable({
235228
columns: urlEncodedDataColumns,
@@ -244,18 +237,17 @@ interface UrlEncodedFormTableProps {
244237
}
245238

246239
const UrlEncodedFormTable = ({ exampleId }: UrlEncodedFormTableProps) => {
247-
const transport = useTransport();
248-
const controller = useController();
240+
const { dataClient } = useRouteContext({ from: '__root__' });
249241

250-
const items: GenericMessage<BodyUrlEncodedListItem>[] = useSuspense(BodyUrlEncodedListEndpoint, transport, {
242+
const items: GenericMessage<BodyUrlEncodedListItem>[] = useQuery(BodyUrlEncodedListEndpoint, {
251243
exampleId,
252244
}).items;
253245

254246
const table = useReactTable({
255247
columns: [
256248
...urlEncodedDataColumns,
257249
columnActionsCommon<GenericMessage<BodyUrlEncodedListItem>>({
258-
onDelete: (_) => controller.fetch(BodyUrlEncodedDeleteEndpoint, transport, { bodyId: _.bodyId }),
250+
onDelete: (_) => dataClient.fetch(BodyUrlEncodedDeleteEndpoint, { bodyId: _.bodyId }),
259251
}),
260252
],
261253
data: items,
@@ -265,10 +257,10 @@ const UrlEncodedFormTable = ({ exampleId }: UrlEncodedFormTableProps) => {
265257
createLabel: 'New URL encoded item',
266258
items,
267259
onCreate: async () => {
268-
await controller.fetch(BodyUrlEncodedCreateEndpoint, transport, { enabled: true, exampleId });
269-
await controller.invalidateAll({ testKey: (_) => _.startsWith(BodyUrlEncodedDeltaListEndpoint.name) });
260+
await dataClient.fetch(BodyUrlEncodedCreateEndpoint, { enabled: true, exampleId });
261+
await dataClient.controller.invalidateAll({ testKey: (_) => _.startsWith(BodyUrlEncodedDeltaListEndpoint.name) });
270262
},
271-
onUpdate: ({ $typeName: _, ...item }) => controller.fetch(BodyUrlEncodedUpdateEndpoint, transport, item),
263+
onUpdate: ({ $typeName: _, ...item }) => dataClient.fetch(BodyUrlEncodedUpdateEndpoint, item),
272264
primaryColumn: 'key',
273265
});
274266

@@ -284,20 +276,18 @@ const UrlEncodedDeltaFormTable = ({
284276
deltaExampleId: exampleId,
285277
exampleId: originId,
286278
}: UrlEncodedDeltaFormTableProps) => {
287-
const transport = useTransport();
288-
const controller = useController();
279+
const { dataClient } = useRouteContext({ from: '__root__' });
289280

290281
const items = pipe(
291-
useSuspense(BodyUrlEncodedDeltaListEndpoint, transport, { exampleId, originId }).items,
282+
useQuery(BodyUrlEncodedDeltaListEndpoint, { exampleId, originId }).items,
292283
(_: BodyUrlEncodedDeltaListItem[]) => makeDeltaItems(_, 'bodyId'),
293284
);
294285

295286
const formTable = useFormTable({
296287
createLabel: 'New URL encoded item',
297288
items,
298-
onCreate: () =>
299-
controller.fetch(BodyUrlEncodedDeltaCreateEndpoint, transport, { enabled: true, exampleId, originId }),
300-
onUpdate: ({ $typeName: _, ...item }) => controller.fetch(BodyUrlEncodedDeltaUpdateEndpoint, transport, item),
289+
onCreate: () => dataClient.fetch(BodyUrlEncodedDeltaCreateEndpoint, { enabled: true, exampleId, originId }),
290+
onUpdate: ({ $typeName: _, ...item }) => dataClient.fetch(BodyUrlEncodedDeltaUpdateEndpoint, item),
301291
primaryColumn: 'key',
302292
});
303293

@@ -306,8 +296,8 @@ const UrlEncodedDeltaFormTable = ({
306296
columns={[
307297
...urlEncodedDataColumns,
308298
columnActionsDeltaCommon<GenericMessage<BodyUrlEncodedDeltaListItem>>({
309-
onDelete: (_) => controller.fetch(BodyUrlEncodedDeltaDeleteEndpoint, transport, { bodyId: _.bodyId }),
310-
onReset: (_) => controller.fetch(BodyUrlEncodedDeltaResetEndpoint, transport, { bodyId: _.bodyId }),
299+
onDelete: (_) => dataClient.fetch(BodyUrlEncodedDeltaDeleteEndpoint, { bodyId: _.bodyId }),
300+
onReset: (_) => dataClient.fetch(BodyUrlEncodedDeltaResetEndpoint, { bodyId: _.bodyId }),
311301
source: (_) => _.source,
312302
}),
313303
]}
@@ -326,15 +316,11 @@ interface RawFormProps {
326316
}
327317

328318
const RawForm = ({ deltaExampleId, exampleId, isReadOnly }: RawFormProps) => {
329-
const controller = useController();
319+
const { dataClient } = useRouteContext({ from: '__root__' });
330320
const transport = useTransport();
331321

332-
// TODO: switch to Data Client Endpoints
333-
const bodyRaw = useSuspense(BodyRawGetEndpoint, transport, { exampleId });
334-
const deltaBodyRaw = useSuspense(
335-
BodyRawGetEndpoint,
336-
...(deltaExampleId ? [transport, { exampleId: deltaExampleId }] : [null]),
337-
);
322+
const bodyRaw = useQuery(BodyRawGetEndpoint, { exampleId });
323+
const deltaBodyRaw = useQuery(BodyRawGetEndpoint, deltaExampleId ? { exampleId: deltaExampleId } : null);
338324

339325
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
340326
const body = new TextDecoder().decode(deltaBodyRaw?.data || bodyRaw.data);
@@ -375,7 +361,7 @@ const RawForm = ({ deltaExampleId, exampleId, isReadOnly }: RawFormProps) => {
375361
extensions={combinedExtensions}
376362
height='100%'
377363
onBlur={() =>
378-
void controller.fetch(BodyRawUpdateEndpoint, transport, {
364+
void dataClient.fetch(BodyRawUpdateEndpoint, {
379365
data: new TextEncoder().encode(value),
380366
exampleId: deltaExampleId ?? exampleId,
381367
})

0 commit comments

Comments
 (0)