@idealyst/cli 1.0.91 → 1.0.93
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/dist/generators/init.js +8 -13
- package/dist/generators/init.js.map +1 -1
- package/dist/generators/utils.js +3 -7
- package/dist/generators/utils.js.map +1 -1
- package/dist/template/.devcontainer/gitignore.template +2 -0
- package/dist/template/gitignore.template +56 -0
- package/dist/template/mcp.json.template +8 -0
- package/dist/template/packages/api/README.md +400 -164
- package/dist/template/packages/api/gitignore.template +35 -0
- package/dist/template/packages/api/package.json +11 -1
- package/dist/template/packages/api/src/context.ts +35 -2
- package/dist/template/packages/api/src/graphql/builder.ts +75 -0
- package/dist/template/packages/api/src/graphql/generated.ts +64 -0
- package/dist/template/packages/api/src/graphql/index.ts +75 -0
- package/dist/template/packages/api/src/graphql/types/index.ts +44 -0
- package/dist/template/packages/api/src/graphql/types/test.ts +245 -0
- package/dist/template/packages/api/src/index.ts +20 -3
- package/dist/template/packages/api/src/lib/database.ts +1 -1
- package/dist/template/packages/api/src/routers/test.ts +140 -38
- package/dist/template/packages/api/src/server.ts +23 -5
- package/dist/template/packages/api/tsconfig.json +1 -0
- package/dist/template/packages/database/gitignore.template +41 -0
- package/dist/template/packages/mobile/babel.config.js +1 -2
- package/dist/template/packages/mobile/gitignore.template +73 -0
- package/dist/template/packages/mobile/package.json +10 -2
- package/dist/template/packages/shared/gitignore.template +35 -0
- package/dist/template/packages/shared/package.json +6 -0
- package/dist/template/packages/shared/src/components/App.tsx +13 -2
- package/dist/template/packages/shared/src/components/HelloWorld.tsx +333 -106
- package/dist/template/packages/shared/src/graphql/client.ts +34 -0
- package/dist/template/packages/shared/src/index.ts +8 -0
- package/dist/template/packages/web/gitignore.template +35 -0
- package/dist/template/packages/web/vite.config.ts +2 -2
- package/dist/template/yarnrc.yml.template +4 -0
- package/package.json +1 -1
- package/template/packages/api/README.md +400 -164
- package/template/packages/api/package.json +11 -1
- package/template/packages/api/src/context.ts +35 -2
- package/template/packages/api/src/graphql/builder.ts +75 -0
- package/template/packages/api/src/graphql/generated.ts +64 -0
- package/template/packages/api/src/graphql/index.ts +75 -0
- package/template/packages/api/src/graphql/types/index.ts +44 -0
- package/template/packages/api/src/graphql/types/test.ts +245 -0
- package/template/packages/api/src/index.ts +20 -3
- package/template/packages/api/src/lib/database.ts +1 -1
- package/template/packages/api/src/routers/test.ts +140 -38
- package/template/packages/api/src/server.ts +23 -5
- package/template/packages/api/tsconfig.json +1 -0
- package/template/packages/mobile/babel.config.js +1 -2
- package/template/packages/mobile/package.json +10 -2
- package/template/packages/shared/package.json +6 -0
- package/template/packages/shared/src/components/App.tsx +13 -2
- package/template/packages/shared/src/components/HelloWorld.tsx +333 -106
- package/template/packages/shared/src/graphql/client.ts +34 -0
- package/template/packages/shared/src/index.ts +8 -0
- package/template/packages/web/vite.config.ts +2 -2
- package/dist/template/packages/api/src/lib/crud.ts +0 -150
- package/dist/template/packages/api/src/routers/user.example.ts +0 -83
- package/dist/template/packages/mobile/src/App-with-trpc-and-shared.tsx +0 -8
- package/dist/template/packages/mobile/src/App-with-trpc.tsx +0 -30
- package/dist/template/packages/web/src/App-with-trpc-and-shared.tsx +0 -14
- package/dist/template/packages/web/src/App-with-trpc.tsx +0 -32
- package/template/packages/api/src/lib/crud.ts +0 -150
- package/template/packages/api/src/routers/user.example.ts +0 -83
- package/template/packages/mobile/src/App-with-trpc-and-shared.tsx +0 -8
- package/template/packages/mobile/src/App-with-trpc.tsx +0 -30
- package/template/packages/web/src/App-with-trpc-and-shared.tsx +0 -14
- package/template/packages/web/src/App-with-trpc.tsx +0 -32
- /package/dist/template/{.dockerignore → dockerignore.template} +0 -0
- /package/dist/template/{.env.example → env.example.template} +0 -0
- /package/dist/template/packages/api/{.env.example → env.example.template} +0 -0
|
@@ -1,48 +1,144 @@
|
|
|
1
1
|
import { Button, Card, Input, Screen, Text, View } from "@idealyst/components";
|
|
2
|
+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
2
3
|
import { useState } from "react";
|
|
4
|
+
import { getGraphQLClient, gql } from "../graphql/client";
|
|
3
5
|
import { trpc } from "../trpc/client";
|
|
4
6
|
|
|
7
|
+
// GraphQL queries and mutations
|
|
8
|
+
const TESTS_QUERY = gql`
|
|
9
|
+
query GetTests($take: Int, $skip: Int) {
|
|
10
|
+
tests(take: $take, skip: $skip) {
|
|
11
|
+
id
|
|
12
|
+
name
|
|
13
|
+
message
|
|
14
|
+
status
|
|
15
|
+
createdAt
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
const CREATE_TEST_MUTATION = gql`
|
|
21
|
+
mutation CreateTest($input: CreateTestInput!) {
|
|
22
|
+
createTest(input: $input) {
|
|
23
|
+
id
|
|
24
|
+
name
|
|
25
|
+
message
|
|
26
|
+
status
|
|
27
|
+
createdAt
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
const DELETE_TEST_MUTATION = gql`
|
|
33
|
+
mutation DeleteTest($id: String!) {
|
|
34
|
+
deleteTest(id: $id) {
|
|
35
|
+
id
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
|
|
5
40
|
interface HelloWorldProps {
|
|
6
41
|
name?: string;
|
|
7
42
|
platform?: "web" | "mobile";
|
|
8
43
|
projectName?: string;
|
|
9
44
|
}
|
|
10
45
|
|
|
46
|
+
// Type for test records
|
|
47
|
+
interface TestRecord {
|
|
48
|
+
id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
message: string;
|
|
51
|
+
status: string;
|
|
52
|
+
createdAt: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
11
55
|
export const HelloWorld = ({
|
|
12
56
|
name = "World",
|
|
13
57
|
platform = "web",
|
|
14
58
|
projectName = "Your Project",
|
|
15
59
|
}: HelloWorldProps) => {
|
|
16
|
-
const
|
|
17
|
-
const [
|
|
60
|
+
const queryClient = useQueryClient();
|
|
61
|
+
const [activeTab, setActiveTab] = useState<"trpc" | "graphql">("trpc");
|
|
62
|
+
|
|
63
|
+
// tRPC state
|
|
64
|
+
const [trpcTestName, setTrpcTestName] = useState("");
|
|
65
|
+
const [trpcTestMessage, setTrpcTestMessage] = useState("");
|
|
66
|
+
|
|
67
|
+
// GraphQL state
|
|
68
|
+
const [gqlTestName, setGqlTestName] = useState("");
|
|
69
|
+
const [gqlTestMessage, setGqlTestMessage] = useState("");
|
|
18
70
|
|
|
19
|
-
//
|
|
20
|
-
const
|
|
21
|
-
const
|
|
71
|
+
// ========== tRPC Hooks ==========
|
|
72
|
+
const trpcTests = trpc.test.getAll.useQuery({});
|
|
73
|
+
const trpcCreateMutation = trpc.test.create.useMutation({
|
|
22
74
|
onSuccess: () => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
75
|
+
trpcTests.refetch();
|
|
76
|
+
setTrpcTestName("");
|
|
77
|
+
setTrpcTestMessage("");
|
|
26
78
|
},
|
|
27
79
|
});
|
|
28
|
-
const
|
|
80
|
+
const trpcDeleteMutation = trpc.test.delete.useMutation({
|
|
29
81
|
onSuccess: () => {
|
|
30
|
-
|
|
82
|
+
trpcTests.refetch();
|
|
31
83
|
},
|
|
32
84
|
});
|
|
33
85
|
|
|
34
|
-
|
|
35
|
-
|
|
86
|
+
// ========== GraphQL Hooks (with React Query) ==========
|
|
87
|
+
const gqlTests = useQuery<{ tests: TestRecord[] }>({
|
|
88
|
+
queryKey: ["graphql", "tests"],
|
|
89
|
+
queryFn: async () => {
|
|
90
|
+
const client = getGraphQLClient();
|
|
91
|
+
return client.request(TESTS_QUERY, { take: 10 });
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const gqlCreateMutation = useMutation({
|
|
96
|
+
mutationFn: async (data: { name: string; message: string; status: string }) => {
|
|
97
|
+
const client = getGraphQLClient();
|
|
98
|
+
return client.request(CREATE_TEST_MUTATION, { input: data });
|
|
99
|
+
},
|
|
100
|
+
onSuccess: () => {
|
|
101
|
+
queryClient.invalidateQueries({ queryKey: ["graphql", "tests"] });
|
|
102
|
+
setGqlTestName("");
|
|
103
|
+
setGqlTestMessage("");
|
|
104
|
+
},
|
|
105
|
+
});
|
|
36
106
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
107
|
+
const gqlDeleteMutation = useMutation({
|
|
108
|
+
mutationFn: async (id: string) => {
|
|
109
|
+
const client = getGraphQLClient();
|
|
110
|
+
return client.request(DELETE_TEST_MUTATION, { id });
|
|
111
|
+
},
|
|
112
|
+
onSuccess: () => {
|
|
113
|
+
queryClient.invalidateQueries({ queryKey: ["graphql", "tests"] });
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ========== Handlers ==========
|
|
118
|
+
const handleTrpcCreate = async () => {
|
|
119
|
+
if (!trpcTestName || !trpcTestMessage) return;
|
|
120
|
+
await trpcCreateMutation.mutateAsync({
|
|
121
|
+
name: trpcTestName,
|
|
122
|
+
message: trpcTestMessage,
|
|
40
123
|
status: "active",
|
|
41
124
|
});
|
|
42
125
|
};
|
|
43
126
|
|
|
44
|
-
const
|
|
45
|
-
await
|
|
127
|
+
const handleTrpcDelete = async (id: string) => {
|
|
128
|
+
await trpcDeleteMutation.mutateAsync({ id });
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const handleGqlCreate = async () => {
|
|
132
|
+
if (!gqlTestName || !gqlTestMessage) return;
|
|
133
|
+
await gqlCreateMutation.mutateAsync({
|
|
134
|
+
name: gqlTestName,
|
|
135
|
+
message: gqlTestMessage,
|
|
136
|
+
status: "active",
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const handleGqlDelete = async (id: string) => {
|
|
141
|
+
await gqlDeleteMutation.mutateAsync(id);
|
|
46
142
|
};
|
|
47
143
|
|
|
48
144
|
const platformEmoji = platform === "mobile" ? "📱" : "🌐";
|
|
@@ -196,107 +292,238 @@ export const HelloWorld = ({
|
|
|
196
292
|
🚀 API Demo - Database Integration
|
|
197
293
|
</Text>
|
|
198
294
|
<Text size="md" style={{ marginBottom: 16, color: "#64748b" }}>
|
|
199
|
-
Test your full-stack integration!
|
|
200
|
-
|
|
295
|
+
Test your full-stack integration! Toggle between tRPC and GraphQL to
|
|
296
|
+
see both APIs in action.
|
|
201
297
|
</Text>
|
|
202
298
|
|
|
203
|
-
{/*
|
|
204
|
-
<
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
299
|
+
{/* API Toggle */}
|
|
300
|
+
<View
|
|
301
|
+
style={{
|
|
302
|
+
flexDirection: "row",
|
|
303
|
+
gap: 8,
|
|
304
|
+
marginBottom: 16,
|
|
305
|
+
}}
|
|
208
306
|
>
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
307
|
+
<Button
|
|
308
|
+
type={activeTab === "trpc" ? "contained" : "outlined"}
|
|
309
|
+
intent={activeTab === "trpc" ? "primary" : "neutral"}
|
|
310
|
+
onPress={() => setActiveTab("trpc")}
|
|
311
|
+
size="sm"
|
|
312
|
+
>
|
|
313
|
+
tRPC
|
|
314
|
+
</Button>
|
|
315
|
+
<Button
|
|
316
|
+
type={activeTab === "graphql" ? "contained" : "outlined"}
|
|
317
|
+
intent={activeTab === "graphql" ? "primary" : "neutral"}
|
|
318
|
+
onPress={() => setActiveTab("graphql")}
|
|
319
|
+
size="sm"
|
|
320
|
+
>
|
|
321
|
+
GraphQL
|
|
322
|
+
</Button>
|
|
323
|
+
</View>
|
|
212
324
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
placeholder="Test message"
|
|
221
|
-
value={newTestMessage}
|
|
222
|
-
onChangeText={setNewTestMessage}
|
|
223
|
-
/>
|
|
224
|
-
<Button
|
|
225
|
-
onPress={handleCreateTest}
|
|
226
|
-
disabled={
|
|
227
|
-
!newTestName ||
|
|
228
|
-
!newTestMessage ||
|
|
229
|
-
createTestMutation.isPending
|
|
230
|
-
}
|
|
231
|
-
style={{ alignSelf: "flex-start" }}
|
|
325
|
+
{/* tRPC Tab */}
|
|
326
|
+
{activeTab === "trpc" && (
|
|
327
|
+
<>
|
|
328
|
+
<Card
|
|
329
|
+
type="filled"
|
|
330
|
+
padding="md"
|
|
331
|
+
style={{ marginBottom: 16, backgroundColor: "#f0f9ff" }}
|
|
232
332
|
>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
333
|
+
<Text size="md" weight="semibold" style={{ marginBottom: 12 }}>
|
|
334
|
+
Create via tRPC
|
|
335
|
+
</Text>
|
|
336
|
+
<View style={{ gap: 12 }}>
|
|
337
|
+
<Input
|
|
338
|
+
placeholder="Test name"
|
|
339
|
+
value={trpcTestName}
|
|
340
|
+
onChangeText={setTrpcTestName}
|
|
341
|
+
/>
|
|
342
|
+
<Input
|
|
343
|
+
placeholder="Test message"
|
|
344
|
+
value={trpcTestMessage}
|
|
345
|
+
onChangeText={setTrpcTestMessage}
|
|
346
|
+
/>
|
|
347
|
+
<Button
|
|
348
|
+
onPress={handleTrpcCreate}
|
|
349
|
+
disabled={
|
|
350
|
+
!trpcTestName ||
|
|
351
|
+
!trpcTestMessage ||
|
|
352
|
+
trpcCreateMutation.isPending
|
|
353
|
+
}
|
|
354
|
+
style={{ alignSelf: "flex-start" }}
|
|
355
|
+
>
|
|
356
|
+
{trpcCreateMutation.isPending ? "Creating..." : "Create (tRPC)"}
|
|
357
|
+
</Button>
|
|
358
|
+
</View>
|
|
359
|
+
</Card>
|
|
237
360
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
361
|
+
<View>
|
|
362
|
+
<Text size="md" weight="semibold" style={{ marginBottom: 12 }}>
|
|
363
|
+
Records via tRPC ({trpcTests.data?.length || 0})
|
|
364
|
+
</Text>
|
|
365
|
+
|
|
366
|
+
{trpcTests.isPending ? (
|
|
367
|
+
<Card type="outlined" padding="md">
|
|
368
|
+
<Text size="sm" style={{ color: "#64748b" }}>
|
|
369
|
+
Loading via tRPC...
|
|
370
|
+
</Text>
|
|
371
|
+
</Card>
|
|
372
|
+
) : trpcTests.data?.length === 0 ? (
|
|
373
|
+
<Card type="outlined" padding="md">
|
|
374
|
+
<Text size="sm" style={{ color: "#64748b" }}>
|
|
375
|
+
No tests found. Create one above!
|
|
376
|
+
</Text>
|
|
377
|
+
</Card>
|
|
378
|
+
) : (
|
|
379
|
+
<View style={{ gap: 8 }}>
|
|
380
|
+
{trpcTests.data?.map((test: TestRecord) => (
|
|
381
|
+
<Card key={test.id} type="outlined" padding="md">
|
|
382
|
+
<View
|
|
383
|
+
style={{
|
|
384
|
+
flexDirection: "row",
|
|
385
|
+
justifyContent: "space-between",
|
|
386
|
+
alignItems: "center",
|
|
387
|
+
}}
|
|
388
|
+
>
|
|
389
|
+
<View style={{ flex: 1 }}>
|
|
390
|
+
<Text
|
|
391
|
+
size="sm"
|
|
392
|
+
weight="semibold"
|
|
393
|
+
style={{ marginBottom: 4 }}
|
|
394
|
+
>
|
|
395
|
+
{test.name}
|
|
396
|
+
</Text>
|
|
397
|
+
<Text
|
|
398
|
+
size="sm"
|
|
399
|
+
style={{ color: "#64748b", marginBottom: 4 }}
|
|
400
|
+
>
|
|
401
|
+
{test.message}
|
|
402
|
+
</Text>
|
|
403
|
+
<Text size="sm" style={{ color: "#0ea5e9" }}>
|
|
404
|
+
tRPC • {test.status} •{" "}
|
|
405
|
+
{new Date(test.createdAt).toLocaleDateString()}
|
|
406
|
+
</Text>
|
|
407
|
+
</View>
|
|
408
|
+
<Button
|
|
409
|
+
intent="error"
|
|
410
|
+
size="sm"
|
|
411
|
+
onPress={() => handleTrpcDelete(test.id)}
|
|
412
|
+
disabled={trpcDeleteMutation.isPending}
|
|
413
|
+
>
|
|
414
|
+
Delete
|
|
415
|
+
</Button>
|
|
416
|
+
</View>
|
|
417
|
+
</Card>
|
|
418
|
+
))}
|
|
419
|
+
</View>
|
|
420
|
+
)}
|
|
421
|
+
</View>
|
|
422
|
+
</>
|
|
423
|
+
)}
|
|
243
424
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
425
|
+
{/* GraphQL Tab */}
|
|
426
|
+
{activeTab === "graphql" && (
|
|
427
|
+
<>
|
|
428
|
+
<Card
|
|
429
|
+
type="filled"
|
|
430
|
+
padding="md"
|
|
431
|
+
style={{ marginBottom: 16, backgroundColor: "#fdf4ff" }}
|
|
432
|
+
>
|
|
433
|
+
<Text size="md" weight="semibold" style={{ marginBottom: 12 }}>
|
|
434
|
+
Create via GraphQL
|
|
248
435
|
</Text>
|
|
436
|
+
<View style={{ gap: 12 }}>
|
|
437
|
+
<Input
|
|
438
|
+
placeholder="Test name"
|
|
439
|
+
value={gqlTestName}
|
|
440
|
+
onChangeText={setGqlTestName}
|
|
441
|
+
/>
|
|
442
|
+
<Input
|
|
443
|
+
placeholder="Test message"
|
|
444
|
+
value={gqlTestMessage}
|
|
445
|
+
onChangeText={setGqlTestMessage}
|
|
446
|
+
/>
|
|
447
|
+
<Button
|
|
448
|
+
intent="primary"
|
|
449
|
+
onPress={handleGqlCreate}
|
|
450
|
+
disabled={
|
|
451
|
+
!gqlTestName ||
|
|
452
|
+
!gqlTestMessage ||
|
|
453
|
+
gqlCreateMutation.isPending
|
|
454
|
+
}
|
|
455
|
+
style={{ alignSelf: "flex-start" }}
|
|
456
|
+
>
|
|
457
|
+
{gqlCreateMutation.isPending
|
|
458
|
+
? "Creating..."
|
|
459
|
+
: "Create (GraphQL)"}
|
|
460
|
+
</Button>
|
|
461
|
+
</View>
|
|
249
462
|
</Card>
|
|
250
|
-
|
|
251
|
-
<
|
|
252
|
-
<Text size="
|
|
253
|
-
|
|
463
|
+
|
|
464
|
+
<View>
|
|
465
|
+
<Text size="md" weight="semibold" style={{ marginBottom: 12 }}>
|
|
466
|
+
Records via GraphQL ({gqlTests.data?.tests?.length || 0})
|
|
254
467
|
</Text>
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
style={{
|
|
262
|
-
flexDirection: "row",
|
|
263
|
-
justifyContent: "space-between",
|
|
264
|
-
alignItems: "center",
|
|
265
|
-
}}
|
|
266
|
-
>
|
|
267
|
-
<View style={{ flex: 1 }}>
|
|
268
|
-
<Text
|
|
269
|
-
size="sm"
|
|
270
|
-
weight="semibold"
|
|
271
|
-
style={{ marginBottom: 4 }}
|
|
272
|
-
>
|
|
273
|
-
{test.name}
|
|
274
|
-
</Text>
|
|
275
|
-
<Text
|
|
276
|
-
size="sm"
|
|
277
|
-
style={{ color: "#64748b", marginBottom: 4 }}
|
|
278
|
-
>
|
|
279
|
-
{test.message}
|
|
280
|
-
</Text>
|
|
281
|
-
<Text size="sm" style={{ color: "#10b981" }}>
|
|
282
|
-
Status: {test.status} •{" "}
|
|
283
|
-
{new Date(test.createdAt).toLocaleDateString()}
|
|
284
|
-
</Text>
|
|
285
|
-
</View>
|
|
286
|
-
<Button
|
|
287
|
-
intent="error"
|
|
288
|
-
size="sm"
|
|
289
|
-
onPress={() => handleDeleteTest(test.id)}
|
|
290
|
-
disabled={deleteTestMutation.isPending}
|
|
291
|
-
>
|
|
292
|
-
Delete
|
|
293
|
-
</Button>
|
|
294
|
-
</View>
|
|
468
|
+
|
|
469
|
+
{gqlTests.isPending ? (
|
|
470
|
+
<Card type="outlined" padding="md">
|
|
471
|
+
<Text size="sm" style={{ color: "#64748b" }}>
|
|
472
|
+
Loading via GraphQL...
|
|
473
|
+
</Text>
|
|
295
474
|
</Card>
|
|
296
|
-
)
|
|
475
|
+
) : gqlTests.data?.tests?.length === 0 ? (
|
|
476
|
+
<Card type="outlined" padding="md">
|
|
477
|
+
<Text size="sm" style={{ color: "#64748b" }}>
|
|
478
|
+
No tests found. Create one above!
|
|
479
|
+
</Text>
|
|
480
|
+
</Card>
|
|
481
|
+
) : (
|
|
482
|
+
<View style={{ gap: 8 }}>
|
|
483
|
+
{gqlTests.data?.tests?.map((test: TestRecord) => (
|
|
484
|
+
<Card key={test.id} type="outlined" padding="md">
|
|
485
|
+
<View
|
|
486
|
+
style={{
|
|
487
|
+
flexDirection: "row",
|
|
488
|
+
justifyContent: "space-between",
|
|
489
|
+
alignItems: "center",
|
|
490
|
+
}}
|
|
491
|
+
>
|
|
492
|
+
<View style={{ flex: 1 }}>
|
|
493
|
+
<Text
|
|
494
|
+
size="sm"
|
|
495
|
+
weight="semibold"
|
|
496
|
+
style={{ marginBottom: 4 }}
|
|
497
|
+
>
|
|
498
|
+
{test.name}
|
|
499
|
+
</Text>
|
|
500
|
+
<Text
|
|
501
|
+
size="sm"
|
|
502
|
+
style={{ color: "#64748b", marginBottom: 4 }}
|
|
503
|
+
>
|
|
504
|
+
{test.message}
|
|
505
|
+
</Text>
|
|
506
|
+
<Text size="sm" style={{ color: "#d946ef" }}>
|
|
507
|
+
GraphQL • {test.status} •{" "}
|
|
508
|
+
{new Date(test.createdAt).toLocaleDateString()}
|
|
509
|
+
</Text>
|
|
510
|
+
</View>
|
|
511
|
+
<Button
|
|
512
|
+
intent="error"
|
|
513
|
+
size="sm"
|
|
514
|
+
onPress={() => handleGqlDelete(test.id)}
|
|
515
|
+
disabled={gqlDeleteMutation.isPending}
|
|
516
|
+
>
|
|
517
|
+
Delete
|
|
518
|
+
</Button>
|
|
519
|
+
</View>
|
|
520
|
+
</Card>
|
|
521
|
+
))}
|
|
522
|
+
</View>
|
|
523
|
+
)}
|
|
297
524
|
</View>
|
|
298
|
-
|
|
299
|
-
|
|
525
|
+
</>
|
|
526
|
+
)}
|
|
300
527
|
</Card>
|
|
301
528
|
</View>
|
|
302
529
|
</Screen>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { GraphQLClient } from "graphql-request";
|
|
2
|
+
|
|
3
|
+
// Configuration for GraphQL client
|
|
4
|
+
export interface GraphQLClientConfig {
|
|
5
|
+
apiUrl: string;
|
|
6
|
+
headers?: () => Record<string, string>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Singleton instance for the GraphQL client
|
|
10
|
+
let graphqlClient: GraphQLClient | null = null;
|
|
11
|
+
|
|
12
|
+
// Create GraphQL client factory
|
|
13
|
+
export function createGraphQLClient(config: GraphQLClientConfig): GraphQLClient {
|
|
14
|
+
graphqlClient = new GraphQLClient(config.apiUrl, {
|
|
15
|
+
headers: config.headers?.() ?? {},
|
|
16
|
+
});
|
|
17
|
+
return graphqlClient;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Get the current GraphQL client instance
|
|
21
|
+
export function getGraphQLClient(): GraphQLClient {
|
|
22
|
+
if (!graphqlClient) {
|
|
23
|
+
throw new Error(
|
|
24
|
+
"GraphQL client not initialized. Call createGraphQLClient first."
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return graphqlClient;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Re-export gql for convenience
|
|
31
|
+
export { gql } from "graphql-request";
|
|
32
|
+
|
|
33
|
+
// Re-export GraphQLClient type
|
|
34
|
+
export type { GraphQLClient };
|
|
@@ -8,6 +8,14 @@ export { default as AppRouter } from './navigation/AppRouter';
|
|
|
8
8
|
export { trpc, createTRPCClient, createVanillaTRPCClient } from './trpc/client';
|
|
9
9
|
export type { TRPCClientConfig, AppRouter } from './trpc/client';
|
|
10
10
|
|
|
11
|
+
// Export GraphQL client utilities
|
|
12
|
+
export {
|
|
13
|
+
createGraphQLClient,
|
|
14
|
+
getGraphQLClient,
|
|
15
|
+
gql,
|
|
16
|
+
} from './graphql/client';
|
|
17
|
+
export type { GraphQLClientConfig, GraphQLClient } from './graphql/client';
|
|
18
|
+
|
|
11
19
|
// Simple type for the HelloWorld component props
|
|
12
20
|
export interface HelloWorldProps {
|
|
13
21
|
name?: string;
|
|
@@ -48,7 +48,7 @@ export default defineConfig({
|
|
|
48
48
|
"react-native": path.resolve(__dirname, "node_modules/react-native-web"),
|
|
49
49
|
"@react-native/normalize-colors": path.resolve(
|
|
50
50
|
__dirname,
|
|
51
|
-
"
|
|
51
|
+
"node_modules/@react-native/normalize-colors"
|
|
52
52
|
),
|
|
53
53
|
},
|
|
54
54
|
// Platform-specific file resolution
|
|
@@ -87,7 +87,7 @@ export default defineConfig({
|
|
|
87
87
|
},
|
|
88
88
|
alias: {
|
|
89
89
|
"react-native": path.resolve(__dirname, "node_modules/react-native-web"),
|
|
90
|
-
"@react-native/normalize-colors": path.resolve(__dirname, "
|
|
90
|
+
"@react-native/normalize-colors": path.resolve(__dirname, "node_modules/@react-native/normalize-colors"),
|
|
91
91
|
},
|
|
92
92
|
},
|
|
93
93
|
},
|