@helloleo/plugins 0.2.1 → 0.2.2
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/templates/tanstack-start-2026-06-18/src/components/error-component.tsx +47 -0
- package/dist/templates/tanstack-start-2026-06-18/src/router.tsx +4 -0
- package/package.json +1 -1
- package/src/templates/tanstack-start-2026-06-18/src/components/error-component.tsx +47 -0
- package/src/templates/tanstack-start-2026-06-18/src/router.tsx +4 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { useRouterState } from '@tanstack/react-router'
|
|
3
|
+
import { Button } from '@/components/ui/button'
|
|
4
|
+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
5
|
+
|
|
6
|
+
// Rendered by the router's defaultErrorComponent for any uncaught render or
|
|
7
|
+
// loader error. Per-route `errorComponent` options override it. Keep this
|
|
8
|
+
// component free of app dependencies (toasts, auth, etc.) -- it must still
|
|
9
|
+
// render when the rest of the app is broken.
|
|
10
|
+
export function DefaultErrorComponent({ error }: { error: Error }) {
|
|
11
|
+
const pathname = useRouterState({ select: (s) => s.location.pathname })
|
|
12
|
+
const [copied, setCopied] = useState(false)
|
|
13
|
+
|
|
14
|
+
async function copyForLeo() {
|
|
15
|
+
// Blank lines + fenced stack so the report keeps its structure when
|
|
16
|
+
// pasted into a markdown-rendering chat.
|
|
17
|
+
const report = [
|
|
18
|
+
'My app threw an error, please fix it:',
|
|
19
|
+
`Page: ${pathname}`,
|
|
20
|
+
`Error: ${error.message}`,
|
|
21
|
+
['Stack:', '```', error.stack ?? '(no stack trace)', '```'].join('\n'),
|
|
22
|
+
].join('\n\n')
|
|
23
|
+
|
|
24
|
+
await navigator.clipboard.writeText(report)
|
|
25
|
+
setCopied(true)
|
|
26
|
+
setTimeout(() => setCopied(false), 2000)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div className="min-h-screen flex items-center justify-center bg-background p-4">
|
|
31
|
+
<Card className="w-full max-w-lg">
|
|
32
|
+
<CardHeader>
|
|
33
|
+
<CardTitle>Something went wrong</CardTitle>
|
|
34
|
+
</CardHeader>
|
|
35
|
+
<CardContent className="space-y-4">
|
|
36
|
+
<pre className="text-sm text-destructive whitespace-pre-wrap break-words rounded-md bg-muted p-3">
|
|
37
|
+
{error.message}
|
|
38
|
+
</pre>
|
|
39
|
+
<Button onClick={copyForLeo}>{copied ? 'Copied!' : 'Copy error'}</Button>
|
|
40
|
+
<p className="text-sm text-muted-foreground">
|
|
41
|
+
Paste the copied error to Leo and it will help you fix it.
|
|
42
|
+
</p>
|
|
43
|
+
</CardContent>
|
|
44
|
+
</Card>
|
|
45
|
+
</div>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -2,6 +2,7 @@ import { QueryClient } from '@tanstack/react-query'
|
|
|
2
2
|
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
|
|
3
3
|
import { routerWithQueryClient } from '@tanstack/react-router-with-query'
|
|
4
4
|
import { routeTree } from './routeTree.gen'
|
|
5
|
+
import { DefaultErrorComponent } from '@/components/error-component'
|
|
5
6
|
|
|
6
7
|
// TanStack Start calls getRouter() on both server and client. routerWithQueryClient
|
|
7
8
|
// wires the QueryClient into the router context and handles SSR dehydration /
|
|
@@ -15,6 +16,9 @@ export function getRouter() {
|
|
|
15
16
|
routeTree,
|
|
16
17
|
context: { queryClient },
|
|
17
18
|
scrollRestoration: true,
|
|
19
|
+
// Catches uncaught render/loader errors on any route. Routes can still
|
|
20
|
+
// set their own `errorComponent` to override this.
|
|
21
|
+
defaultErrorComponent: DefaultErrorComponent,
|
|
18
22
|
defaultPreload: 'intent',
|
|
19
23
|
// With React Query we never want loader data to be stale -- the loader runs
|
|
20
24
|
// on every preload/visit and React Query owns caching from there.
|
package/package.json
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
import { useRouterState } from '@tanstack/react-router'
|
|
3
|
+
import { Button } from '@/components/ui/button'
|
|
4
|
+
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
5
|
+
|
|
6
|
+
// Rendered by the router's defaultErrorComponent for any uncaught render or
|
|
7
|
+
// loader error. Per-route `errorComponent` options override it. Keep this
|
|
8
|
+
// component free of app dependencies (toasts, auth, etc.) -- it must still
|
|
9
|
+
// render when the rest of the app is broken.
|
|
10
|
+
export function DefaultErrorComponent({ error }: { error: Error }) {
|
|
11
|
+
const pathname = useRouterState({ select: (s) => s.location.pathname })
|
|
12
|
+
const [copied, setCopied] = useState(false)
|
|
13
|
+
|
|
14
|
+
async function copyForLeo() {
|
|
15
|
+
// Blank lines + fenced stack so the report keeps its structure when
|
|
16
|
+
// pasted into a markdown-rendering chat.
|
|
17
|
+
const report = [
|
|
18
|
+
'My app threw an error, please fix it:',
|
|
19
|
+
`Page: ${pathname}`,
|
|
20
|
+
`Error: ${error.message}`,
|
|
21
|
+
['Stack:', '```', error.stack ?? '(no stack trace)', '```'].join('\n'),
|
|
22
|
+
].join('\n\n')
|
|
23
|
+
|
|
24
|
+
await navigator.clipboard.writeText(report)
|
|
25
|
+
setCopied(true)
|
|
26
|
+
setTimeout(() => setCopied(false), 2000)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div className="min-h-screen flex items-center justify-center bg-background p-4">
|
|
31
|
+
<Card className="w-full max-w-lg">
|
|
32
|
+
<CardHeader>
|
|
33
|
+
<CardTitle>Something went wrong</CardTitle>
|
|
34
|
+
</CardHeader>
|
|
35
|
+
<CardContent className="space-y-4">
|
|
36
|
+
<pre className="text-sm text-destructive whitespace-pre-wrap break-words rounded-md bg-muted p-3">
|
|
37
|
+
{error.message}
|
|
38
|
+
</pre>
|
|
39
|
+
<Button onClick={copyForLeo}>{copied ? 'Copied!' : 'Copy error'}</Button>
|
|
40
|
+
<p className="text-sm text-muted-foreground">
|
|
41
|
+
Paste the copied error to Leo and it will help you fix it.
|
|
42
|
+
</p>
|
|
43
|
+
</CardContent>
|
|
44
|
+
</Card>
|
|
45
|
+
</div>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -2,6 +2,7 @@ import { QueryClient } from '@tanstack/react-query'
|
|
|
2
2
|
import { createRouter as createTanStackRouter } from '@tanstack/react-router'
|
|
3
3
|
import { routerWithQueryClient } from '@tanstack/react-router-with-query'
|
|
4
4
|
import { routeTree } from './routeTree.gen'
|
|
5
|
+
import { DefaultErrorComponent } from '@/components/error-component'
|
|
5
6
|
|
|
6
7
|
// TanStack Start calls getRouter() on both server and client. routerWithQueryClient
|
|
7
8
|
// wires the QueryClient into the router context and handles SSR dehydration /
|
|
@@ -15,6 +16,9 @@ export function getRouter() {
|
|
|
15
16
|
routeTree,
|
|
16
17
|
context: { queryClient },
|
|
17
18
|
scrollRestoration: true,
|
|
19
|
+
// Catches uncaught render/loader errors on any route. Routes can still
|
|
20
|
+
// set their own `errorComponent` to override this.
|
|
21
|
+
defaultErrorComponent: DefaultErrorComponent,
|
|
18
22
|
defaultPreload: 'intent',
|
|
19
23
|
// With React Query we never want loader data to be stale -- the loader runs
|
|
20
24
|
// on every preload/visit and React Query owns caching from there.
|