@tscircuit/fake-snippets 0.0.106 → 0.0.108

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 (43) hide show
  1. package/CLAUDE.md +92 -0
  2. package/api/generated-index.js +84 -25
  3. package/biome.json +7 -1
  4. package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +0 -15
  5. package/bun-tests/fake-snippets-api/routes/package_builds/list.test.ts +0 -12
  6. package/dist/bundle.js +360 -434
  7. package/dist/index.d.ts +26 -15
  8. package/dist/index.js +40 -21
  9. package/dist/schema.d.ts +32 -24
  10. package/dist/schema.js +7 -5
  11. package/fake-snippets-api/lib/db/db-client.ts +19 -1
  12. package/fake-snippets-api/lib/db/schema.ts +6 -3
  13. package/fake-snippets-api/lib/db/seed.ts +23 -12
  14. package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +0 -3
  15. package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +3 -0
  16. package/fake-snippets-api/routes/api/package_builds/list.ts +0 -1
  17. package/package.json +3 -2
  18. package/src/App.tsx +27 -9
  19. package/src/components/FileSidebar.tsx +14 -159
  20. package/src/components/PackageBreadcrumb.tsx +111 -0
  21. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +1 -1
  22. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +18 -2
  23. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +18 -8
  24. package/src/components/preview/BuildsList.tsx +84 -167
  25. package/src/components/preview/ConnectedPackagesList.tsx +92 -62
  26. package/src/components/preview/ConnectedRepoOverview.tsx +171 -155
  27. package/src/components/preview/{ConnectedRepoDashboard.tsx → PackageReleasesDashboard.tsx} +31 -69
  28. package/src/components/preview/index.tsx +20 -154
  29. package/src/hooks/use-package-builds.ts +0 -48
  30. package/src/hooks/use-package-release-by-id-or-version.ts +36 -0
  31. package/src/hooks/use-package-release.ts +32 -0
  32. package/src/index.css +24 -0
  33. package/src/lib/utils/isUuid.ts +5 -0
  34. package/src/lib/utils/transformFilesToTreeData.tsx +195 -0
  35. package/src/pages/404.tsx +3 -5
  36. package/src/pages/preview-release.tsx +269 -0
  37. package/src/pages/release-builds.tsx +99 -0
  38. package/src/pages/release-detail.tsx +120 -0
  39. package/src/pages/releases.tsx +55 -0
  40. package/fake-snippets-api/routes/api/package_builds/latest.ts +0 -109
  41. package/src/hooks/use-snippets-base-api-url.ts +0 -3
  42. package/src/pages/preview-build.tsx +0 -380
  43. package/src/pages/view-connected-repo.tsx +0 -49
@@ -27,34 +27,109 @@ import {
27
27
  } from "fake-snippets-api/lib/db/schema"
28
28
 
29
29
  export const ConnectedRepoOverview = ({
30
- build,
30
+ packageBuild,
31
31
  pkg,
32
+ isLoadingBuild,
32
33
  packageRelease,
33
34
  }: {
34
- build: PackageBuild
35
+ packageBuild?: PackageBuild | null
36
+ isLoadingBuild: boolean
35
37
  pkg: Package
36
38
  packageRelease: PackageRelease
37
39
  }) => {
38
- const { status, label } = getBuildStatus(build)
40
+ const { status, label } = getBuildStatus(packageBuild ?? null)
39
41
  const [openSections, setOpenSections] = useState({
40
42
  transpilation: false,
41
43
  circuitJson: false,
42
- finalBuild: false,
43
44
  })
44
45
 
46
+ // Gracefully handle when there is no build yet
47
+ if (isLoadingBuild) {
48
+ return (
49
+ <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-6 space-y-6 focus:outline-none">
50
+ <div className="bg-white border border-gray-200 rounded-lg">
51
+ <div className="px-6 py-6 border-b border-gray-200">
52
+ <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
53
+ <div className="flex items-center gap-4">
54
+ <div className="w-6 h-6 rounded-full bg-gray-200 animate-pulse" />
55
+ <div className="flex-1 space-y-2">
56
+ <div className="h-7 w-32 bg-gray-200 rounded animate-pulse" />
57
+ <div className="h-4 w-24 bg-gray-200 rounded animate-pulse" />
58
+ </div>
59
+ </div>
60
+ <div className="w-24 h-9 bg-gray-200 rounded animate-pulse" />
61
+ </div>
62
+ </div>
63
+ <div className="px-6 py-4">
64
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
65
+ {Array(4)
66
+ .fill(0)
67
+ .map((_, i) => (
68
+ <div key={i} className="flex items-center gap-3">
69
+ <div className="w-4 h-4 rounded bg-gray-200 animate-pulse" />
70
+ <div className="space-y-2">
71
+ <div className="h-4 w-20 bg-gray-200 rounded animate-pulse" />
72
+ <div className="h-5 w-24 bg-gray-200 rounded animate-pulse" />
73
+ </div>
74
+ </div>
75
+ ))}
76
+ </div>
77
+ <div className="mt-6 p-4 bg-gray-50 rounded-lg">
78
+ <div className="h-4 w-32 bg-gray-200 rounded animate-pulse mb-2" />
79
+ <div className="h-5 w-full bg-gray-200 rounded animate-pulse" />
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </div>
84
+ )
85
+ }
86
+
87
+ if (!packageBuild) {
88
+ return (
89
+ <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
90
+ <div className="bg-white border border-gray-200 rounded-lg p-6 text-center">
91
+ <p className="text-sm text-gray-600">
92
+ No build information available.
93
+ </p>
94
+ </div>
95
+ </div>
96
+ )
97
+ }
98
+
45
99
  const copyToClipboard = (text: string) => {
46
100
  navigator.clipboard.writeText(text)
47
101
  }
48
102
 
49
- const buildDuration =
50
- build.build_started_at && build.build_completed_at
103
+ const buildDuration = (() => {
104
+ const transpilationDuration = packageBuild?.transpilation_started_at
51
105
  ? Math.floor(
52
- (new Date(build.build_completed_at).getTime() -
53
- new Date(build.build_started_at).getTime()) /
106
+ (new Date(
107
+ packageBuild.transpilation_completed_at || new Date(),
108
+ ).getTime() -
109
+ new Date(packageBuild.transpilation_started_at).getTime()) /
54
110
  1000,
55
111
  )
56
- : null
112
+ : 0
57
113
 
114
+ const circuitJsonDuration = packageBuild?.circuit_json_build_started_at
115
+ ? Math.floor(
116
+ (new Date(
117
+ packageBuild.circuit_json_build_completed_at || new Date(),
118
+ ).getTime() -
119
+ new Date(packageBuild.circuit_json_build_started_at).getTime()) /
120
+ 1000,
121
+ )
122
+ : 0
123
+
124
+ if (
125
+ !packageBuild?.transpilation_started_at &&
126
+ !packageBuild?.circuit_json_build_started_at
127
+ ) {
128
+ return null
129
+ }
130
+
131
+ return transpilationDuration + circuitJsonDuration
132
+ })()
58
133
  const toggleSection = (section: keyof typeof openSections) => {
59
134
  setOpenSections((prev) => ({ ...prev, [section]: !prev[section] }))
60
135
  }
@@ -97,28 +172,33 @@ export const ConnectedRepoOverview = ({
97
172
  </h1>
98
173
  </div>
99
174
  <p className="text-sm text-gray-600 mt-1">
100
- <time dateTime={build.created_at}>
101
- Built {formatTimeAgo(build.created_at)}
175
+ <time dateTime={packageBuild.created_at}>
176
+ Built {formatTimeAgo(packageBuild.created_at)}
102
177
  </time>
103
178
  </p>
104
179
  </div>
105
180
  </div>
106
181
  <div className="flex items-center gap-3 flex-shrink-0">
107
- {build.preview_url && (
182
+ {status !== "error" && (
108
183
  <Button
109
184
  size="sm"
110
185
  className="flex items-center gap-2 min-w-[80px] h-9"
111
- onClick={() => window.open(build.preview_url!, "_blank")}
186
+ onClick={() =>
187
+ window.open(
188
+ `/${pkg.name}/releases/${packageBuild.package_release_id}/preview`,
189
+ "_blank",
190
+ )
191
+ }
112
192
  >
113
193
  <ExternalLink className="w-3 h-3" />
114
- Preview Build
194
+ Preview
115
195
  </Button>
116
196
  )}
117
197
  </div>
118
198
  </div>
119
199
  </div>
120
200
 
121
- <div className="px-6 py-4">
201
+ <div className="px-6 py-4 select-none">
122
202
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
123
203
  <div className="flex items-center gap-3 group">
124
204
  <Hash className="w-4 h-4 text-gray-500 group-hover:text-blue-500 transition-colors" />
@@ -128,10 +208,12 @@ export const ConnectedRepoOverview = ({
128
208
  </p>
129
209
  <div className="flex items-center gap-2">
130
210
  <button
131
- onClick={() => copyToClipboard(build.package_build_id)}
132
- className="group-hover:text-blue-500 rounded text-left transition-colors"
211
+ onClick={() =>
212
+ copyToClipboard(packageBuild.package_build_id)
213
+ }
214
+ className="group-hover:text-blue-500 text-xs rounded text-left transition-colors"
133
215
  >
134
- {build.package_build_id}
216
+ {packageBuild.package_build_id}
135
217
  </button>
136
218
  </div>
137
219
  </div>
@@ -150,8 +232,8 @@ export const ConnectedRepoOverview = ({
150
232
  <a
151
233
  href={
152
234
  packageRelease?.is_pr_preview
153
- ? `https://github.com/${pkg.github_repo_full_name}/pull/${packageRelease.github_pr_number}`
154
- : `https://github.com/${pkg.github_repo_full_name}/tree/${build.branch_name || "main"}`
235
+ ? `https://github.com/${pkg.github_repo_full_name}/pull/${packageRelease?.github_pr_number}`
236
+ : `https://github.com/${pkg.github_repo_full_name}/tree/${packageRelease?.branch_name || "main"}`
155
237
  }
156
238
  target="_blank"
157
239
  rel="noopener noreferrer"
@@ -163,7 +245,7 @@ export const ConnectedRepoOverview = ({
163
245
  >
164
246
  {packageRelease?.is_pr_preview
165
247
  ? `#${packageRelease.github_pr_number}`
166
- : build?.branch_name || "main"}
248
+ : packageRelease?.branch_name || "main"}
167
249
  </Badge>
168
250
  </a>
169
251
  </div>
@@ -176,12 +258,12 @@ export const ConnectedRepoOverview = ({
176
258
  Author
177
259
  </p>
178
260
  <a
179
- href={`https://github.com/${build.commit_author}`}
261
+ href={`https://github.com/${pkg.owner_github_username}`}
180
262
  target="_blank"
181
263
  rel="noopener noreferrer"
182
264
  className="text-sm font-medium hover:text-blue-500 transition-colors"
183
265
  >
184
- {build.commit_author || "Unknown"}
266
+ {pkg.owner_github_username || "Unknown"}
185
267
  </a>
186
268
  </div>
187
269
  </div>
@@ -194,21 +276,21 @@ export const ConnectedRepoOverview = ({
194
276
  </p>
195
277
  <p
196
278
  className="text-sm font-medium hover:text-blue-500 transition-colors cursor-help"
197
- title={`Build started at ${build.build_started_at}`}
279
+ title={`Build started at ${packageBuild.build_started_at}`}
198
280
  >
199
- {buildDuration}s
281
+ {buildDuration || 0}s
200
282
  </p>
201
283
  </div>
202
284
  </div>
203
285
  </div>
204
286
 
205
- {build.commit_message && (
287
+ {packageRelease?.commit_message && (
206
288
  <div className="mt-6 p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors group">
207
289
  <p className="text-xs text-gray-500 uppercase tracking-wide mb-2">
208
290
  Commit Message
209
291
  </p>
210
292
  <p className="text-sm text-gray-900 group-hover:text-gray-700 transition-colors">
211
- {build.commit_message}
293
+ {packageRelease?.commit_message}
212
294
  </p>
213
295
  </div>
214
296
  )}
@@ -216,7 +298,17 @@ export const ConnectedRepoOverview = ({
216
298
  </div>
217
299
 
218
300
  <div className="space-y-3">
219
- <h2 className="text-lg font-semibold text-gray-900">Logs</h2>
301
+ <div className="flex items-center justify-between">
302
+ <h2 className="text-lg font-semibold text-gray-900">
303
+ Latest Build Logs
304
+ </h2>
305
+ <a
306
+ href={`/${pkg.name.split("/")[0]}/${pkg.name.split("/")[1]}/releases/${packageRelease.package_release_id}/builds`}
307
+ className="text-sm text-blue-600 hover:text-blue-800 transition-colors"
308
+ >
309
+ (previous builds)
310
+ </a>
311
+ </div>
220
312
 
221
313
  <Collapsible
222
314
  open={openSections.transpilation}
@@ -228,11 +320,11 @@ export const ConnectedRepoOverview = ({
228
320
  <ChevronRight
229
321
  className={`w-4 h-4 transition-transform ${openSections.transpilation ? "rotate-90" : ""}`}
230
322
  />
231
- {build.transpilation_error ? (
323
+ {packageBuild.transpilation_error ? (
232
324
  <AlertCircle className="w-5 h-5 text-red-500" />
233
- ) : build.transpilation_completed_at ? (
325
+ ) : packageBuild.transpilation_completed_at ? (
234
326
  <CheckCircle className="w-5 h-5 text-green-500" />
235
- ) : build.transpilation_in_progress ? (
327
+ ) : packageBuild.transpilation_in_progress ? (
236
328
  <Loader2 className="w-5 h-5 text-blue-500 animate-spin" />
237
329
  ) : (
238
330
  <Clock className="w-5 h-5 text-gray-400" />
@@ -241,39 +333,39 @@ export const ConnectedRepoOverview = ({
241
333
  </div>
242
334
  <div className="flex items-center gap-2">
243
335
  {getStepDuration(
244
- build.transpilation_started_at,
245
- build.transpilation_completed_at,
336
+ packageBuild.transpilation_started_at,
337
+ packageBuild.transpilation_completed_at,
246
338
  ) && (
247
339
  <span className="text-sm text-gray-600">
248
340
  {getStepDuration(
249
- build.transpilation_started_at,
250
- build.transpilation_completed_at,
341
+ packageBuild.transpilation_started_at,
342
+ packageBuild.transpilation_completed_at,
251
343
  )}
252
344
  </span>
253
345
  )}
254
346
  <Badge
255
347
  variant={
256
348
  getStepStatus(
257
- build.transpilation_error,
258
- build.transpilation_completed_at,
259
- build.transpilation_in_progress,
349
+ packageBuild.transpilation_error,
350
+ packageBuild.transpilation_completed_at,
351
+ packageBuild.transpilation_in_progress,
260
352
  ) === "success"
261
353
  ? "default"
262
354
  : getStepStatus(
263
- build.transpilation_error,
264
- build.transpilation_completed_at,
265
- build.transpilation_in_progress,
355
+ packageBuild.transpilation_error,
356
+ packageBuild.transpilation_completed_at,
357
+ packageBuild.transpilation_in_progress,
266
358
  ) === "error"
267
359
  ? "destructive"
268
360
  : "secondary"
269
361
  }
270
362
  className="text-xs"
271
363
  >
272
- {build.transpilation_error
364
+ {packageBuild.transpilation_error
273
365
  ? "Failed"
274
- : build.transpilation_completed_at
366
+ : packageBuild.transpilation_completed_at
275
367
  ? "Completed"
276
- : build.transpilation_in_progress
368
+ : packageBuild.transpilation_in_progress
277
369
  ? "Running"
278
370
  : "Queued"}
279
371
  </Badge>
@@ -283,13 +375,13 @@ export const ConnectedRepoOverview = ({
283
375
  <CollapsibleContent>
284
376
  <div className="bg-white border-x border-b border-gray-200 rounded-b-lg p-4">
285
377
  <div className="font-mono text-xs space-y-1">
286
- {build.transpilation_error ? (
378
+ {packageBuild.transpilation_error ? (
287
379
  <div className="text-red-600 whitespace-pre-wrap">
288
- {build.transpilation_error}
380
+ {packageBuild.transpilation_error}
289
381
  </div>
290
- ) : build.transpilation_logs &&
291
- build.transpilation_logs.length > 0 ? (
292
- build.transpilation_logs.map((log: any, i: number) => (
382
+ ) : packageBuild.transpilation_logs &&
383
+ packageBuild.transpilation_logs.length > 0 ? (
384
+ packageBuild.transpilation_logs.map((log: any, i: number) => (
293
385
  <div key={i} className="text-gray-600 whitespace-pre-wrap">
294
386
  {log.msg || log.message || JSON.stringify(log)}
295
387
  </div>
@@ -312,11 +404,11 @@ export const ConnectedRepoOverview = ({
312
404
  <ChevronRight
313
405
  className={`w-4 h-4 transition-transform ${openSections.circuitJson ? "rotate-90" : ""}`}
314
406
  />
315
- {build.circuit_json_build_error ? (
407
+ {packageBuild.circuit_json_build_error ? (
316
408
  <AlertCircle className="w-5 h-5 text-red-500" />
317
- ) : build.circuit_json_build_completed_at ? (
409
+ ) : packageBuild.circuit_json_build_completed_at ? (
318
410
  <CheckCircle className="w-5 h-5 text-green-500" />
319
- ) : build.circuit_json_build_in_progress ? (
411
+ ) : packageBuild.circuit_json_build_in_progress ? (
320
412
  <Loader2 className="w-5 h-5 text-blue-500 animate-spin" />
321
413
  ) : (
322
414
  <Clock className="w-5 h-5 text-gray-400" />
@@ -325,39 +417,39 @@ export const ConnectedRepoOverview = ({
325
417
  </div>
326
418
  <div className="flex items-center gap-2">
327
419
  {getStepDuration(
328
- build.circuit_json_build_started_at,
329
- build.circuit_json_build_completed_at,
420
+ packageBuild.circuit_json_build_started_at,
421
+ packageBuild.circuit_json_build_completed_at,
330
422
  ) && (
331
423
  <span className="text-sm text-gray-600">
332
424
  {getStepDuration(
333
- build.circuit_json_build_started_at,
334
- build.circuit_json_build_completed_at,
425
+ packageBuild.circuit_json_build_started_at,
426
+ packageBuild.circuit_json_build_completed_at,
335
427
  )}
336
428
  </span>
337
429
  )}
338
430
  <Badge
339
431
  variant={
340
432
  getStepStatus(
341
- build.circuit_json_build_error,
342
- build.circuit_json_build_completed_at,
343
- build.circuit_json_build_in_progress,
433
+ packageBuild.circuit_json_build_error,
434
+ packageBuild.circuit_json_build_completed_at,
435
+ packageBuild.circuit_json_build_in_progress,
344
436
  ) === "success"
345
437
  ? "default"
346
438
  : getStepStatus(
347
- build.circuit_json_build_error,
348
- build.circuit_json_build_completed_at,
349
- build.circuit_json_build_in_progress,
439
+ packageBuild.circuit_json_build_error,
440
+ packageBuild.circuit_json_build_completed_at,
441
+ packageBuild.circuit_json_build_in_progress,
350
442
  ) === "error"
351
443
  ? "destructive"
352
444
  : "secondary"
353
445
  }
354
446
  className="text-xs"
355
447
  >
356
- {build.circuit_json_build_error
448
+ {packageBuild.circuit_json_build_error
357
449
  ? "Failed"
358
- : build.circuit_json_build_completed_at
450
+ : packageBuild.circuit_json_build_completed_at
359
451
  ? "Completed"
360
- : build.circuit_json_build_in_progress
452
+ : packageBuild.circuit_json_build_in_progress
361
453
  ? "Running"
362
454
  : "Queued"}
363
455
  </Badge>
@@ -367,98 +459,22 @@ export const ConnectedRepoOverview = ({
367
459
  <CollapsibleContent>
368
460
  <div className="bg-white border-x border-b border-gray-200 rounded-b-lg p-4">
369
461
  <div className="font-mono text-xs space-y-1">
370
- {build.circuit_json_build_error ? (
462
+ {packageBuild.circuit_json_build_error ? (
371
463
  <div className="text-red-600 whitespace-pre-wrap">
372
- {build.circuit_json_build_error}
373
- </div>
374
- ) : build.circuit_json_build_logs &&
375
- build.circuit_json_build_logs.length > 0 ? (
376
- build.circuit_json_build_logs.map((log: any, i: number) => (
377
- <div key={i} className="text-gray-600 whitespace-pre-wrap">
378
- {log.msg || log.message || JSON.stringify(log)}
379
- </div>
380
- ))
381
- ) : (
382
- <div className="text-gray-500">No logs available</div>
383
- )}
384
- </div>
385
- </div>
386
- </CollapsibleContent>
387
- </Collapsible>
388
-
389
- <Collapsible
390
- open={openSections.finalBuild}
391
- onOpenChange={() => toggleSection("finalBuild")}
392
- >
393
- <CollapsibleTrigger asChild>
394
- <div className="flex items-center justify-between p-4 bg-white border border-gray-200 rounded-lg cursor-pointer hover:bg-gray-50">
395
- <div className="flex items-center gap-3">
396
- <ChevronRight
397
- className={`w-4 h-4 transition-transform ${openSections.finalBuild ? "rotate-90" : ""}`}
398
- />
399
- {build.build_error ? (
400
- <AlertCircle className="w-5 h-5 text-red-500" />
401
- ) : build.build_completed_at ? (
402
- <CheckCircle className="w-5 h-5 text-green-500" />
403
- ) : build.build_in_progress ? (
404
- <Loader2 className="w-5 h-5 text-blue-500 animate-spin" />
405
- ) : (
406
- <Clock className="w-5 h-5 text-gray-400" />
407
- )}
408
- <span className="font-medium">Build</span>
409
- </div>
410
- <div className="flex items-center gap-2">
411
- {getStepDuration(
412
- build.build_started_at,
413
- build.build_completed_at,
414
- ) && (
415
- <span className="text-sm text-gray-600">
416
- {getStepDuration(
417
- build.build_started_at,
418
- build.build_completed_at,
419
- )}
420
- </span>
421
- )}
422
- <Badge
423
- variant={
424
- getStepStatus(
425
- build.build_error,
426
- build.build_completed_at,
427
- build.build_in_progress,
428
- ) === "success"
429
- ? "default"
430
- : getStepStatus(
431
- build.build_error,
432
- build.build_completed_at,
433
- build.build_in_progress,
434
- ) === "error"
435
- ? "destructive"
436
- : "secondary"
437
- }
438
- className="text-xs"
439
- >
440
- {build.build_error
441
- ? "Failed"
442
- : build.build_completed_at
443
- ? "Completed"
444
- : build.build_in_progress
445
- ? "Running"
446
- : "Queued"}
447
- </Badge>
448
- </div>
449
- </div>
450
- </CollapsibleTrigger>
451
- <CollapsibleContent>
452
- <div className="bg-white border-x border-b border-gray-200 rounded-b-lg p-4">
453
- <div className="font-mono text-xs space-y-1">
454
- {build.build_error ? (
455
- <div className="text-red-600 whitespace-pre-wrap">
456
- {build.build_error}
457
- </div>
458
- ) : build.build_logs ? (
459
- <div className="text-gray-600 whitespace-pre-wrap">
460
- {build.build_logs}
464
+ {packageBuild.circuit_json_build_error}
461
465
  </div>
466
+ ) : packageBuild.circuit_json_build_logs &&
467
+ packageBuild.circuit_json_build_logs.length > 0 ? (
468
+ packageBuild.circuit_json_build_logs.map(
469
+ (log: any, i: number) => (
470
+ <div
471
+ key={i}
472
+ className="text-gray-600 whitespace-pre-wrap"
473
+ >
474
+ {log.msg || log.message || JSON.stringify(log)}
475
+ </div>
476
+ ),
477
+ )
462
478
  ) : (
463
479
  <div className="text-gray-500">No logs available</div>
464
480
  )}