@rpcbase/client 0.278.0 → 0.280.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/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/initWithRoutes.tsx +114 -0
- package/src/initClient.ts +0 -35
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { StrictMode } from "react"
|
|
2
|
+
import posthog from "posthog-js"
|
|
3
|
+
import {createBrowserRouter, createRoutesFromElements, RouterProvider} from "@rpcbase/router"
|
|
4
|
+
import { hydrateRoot } from "react-dom/client"
|
|
5
|
+
|
|
6
|
+
import { initApiClient } from "./apiClient"
|
|
7
|
+
import {cleanupURL} from "./cleanupURL"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const isProduction = import.meta.env.MODE === "production"
|
|
11
|
+
|
|
12
|
+
type ReactErrorInfo = { componentStack?: string }
|
|
13
|
+
|
|
14
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
15
|
+
const showErrorOverlay = (err: { title: string, message: string, reason: string, plugin: string }) => {
|
|
16
|
+
const ErrorOverlay = customElements.get("vite-error-overlay")
|
|
17
|
+
// don't open outside vite environment
|
|
18
|
+
if (!ErrorOverlay) {return}
|
|
19
|
+
console.log(err)
|
|
20
|
+
const overlay = new ErrorOverlay(err)
|
|
21
|
+
document.body.appendChild(overlay)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
const handleServerErrors = () => {
|
|
26
|
+
if ((window as any).__staticRouterHydrationData?.errors) {
|
|
27
|
+
|
|
28
|
+
const {errors} = (window as any).__staticRouterHydrationData
|
|
29
|
+
|
|
30
|
+
Object.values(errors).forEach((error: any) => {
|
|
31
|
+
showErrorOverlay({
|
|
32
|
+
plugin: "ssr-router",
|
|
33
|
+
...error.reason
|
|
34
|
+
})
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
// TODO: what type is this
|
|
41
|
+
export const initWithRoutes = async (routesElement, opts) => {
|
|
42
|
+
|
|
43
|
+
await initApiClient()
|
|
44
|
+
|
|
45
|
+
cleanupURL()
|
|
46
|
+
|
|
47
|
+
handleServerErrors()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
const routes = createRoutesFromElements(routesElement)
|
|
51
|
+
const router = createBrowserRouter(routes)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
const toError = (error: unknown): Error =>
|
|
55
|
+
error instanceof Error ? error : new Error(String(error))
|
|
56
|
+
|
|
57
|
+
const mentionsHydration = (value: unknown, depth = 0): boolean => {
|
|
58
|
+
if (depth > 5) {
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
if (typeof value === "string") {
|
|
62
|
+
return value.toLowerCase().includes("hydrat")
|
|
63
|
+
}
|
|
64
|
+
if (value instanceof Error) {
|
|
65
|
+
const digest = (value as { digest?: unknown }).digest
|
|
66
|
+
const cause = (value as { cause?: unknown }).cause
|
|
67
|
+
return (
|
|
68
|
+
mentionsHydration(value.message, depth + 1) ||
|
|
69
|
+
mentionsHydration(digest, depth + 1) ||
|
|
70
|
+
mentionsHydration(cause, depth + 1)
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
return false
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const phReactHandler =
|
|
77
|
+
(react_context: "uncaught" | "caught" | "recoverable") =>
|
|
78
|
+
(error: unknown, errorInfo?: ReactErrorInfo) => {
|
|
79
|
+
const err = toError(error)
|
|
80
|
+
// send as exception (counts toward error tracking)
|
|
81
|
+
posthog.captureException(err, {
|
|
82
|
+
react_context,
|
|
83
|
+
component_stack: errorInfo?.componentStack
|
|
84
|
+
})
|
|
85
|
+
if (react_context === "uncaught") {
|
|
86
|
+
console.warn("Uncaught error", err, errorInfo?.componentStack)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const hydrationOptions: Parameters<typeof hydrateRoot>[2] | undefined = isProduction ? {
|
|
91
|
+
onUncaughtError: phReactHandler("uncaught"),
|
|
92
|
+
onCaughtError: phReactHandler("caught"),
|
|
93
|
+
onRecoverableError: phReactHandler("recoverable")
|
|
94
|
+
} : (opts?.devThrowsOnHydrationErrors ? {
|
|
95
|
+
onRecoverableError(error, errorInfo) {
|
|
96
|
+
const err = toError(error)
|
|
97
|
+
if (mentionsHydration(err) || mentionsHydration(errorInfo?.componentStack)) {
|
|
98
|
+
throw err
|
|
99
|
+
}
|
|
100
|
+
// For non-hydration recoverable errors in dev, keep a visible signal.
|
|
101
|
+
console.error(err, errorInfo?.componentStack)
|
|
102
|
+
}
|
|
103
|
+
} : undefined)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
hydrateRoot(
|
|
107
|
+
document.getElementById("root") as HTMLElement,
|
|
108
|
+
<StrictMode>
|
|
109
|
+
<RouterProvider router={router} />
|
|
110
|
+
</StrictMode>,
|
|
111
|
+
hydrationOptions
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
}
|
package/src/initClient.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { initApiClient } from "./apiClient"
|
|
2
|
-
import {cleanupURL} from "./cleanupURL"
|
|
3
|
-
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
-
const showErrorOverlay = (err: { title: string, message: string, reason: string, plugin: string }) => {
|
|
6
|
-
const ErrorOverlay = customElements.get("vite-error-overlay")
|
|
7
|
-
// don't open outside vite environment
|
|
8
|
-
if (!ErrorOverlay) {return}
|
|
9
|
-
console.log(err)
|
|
10
|
-
const overlay = new ErrorOverlay(err)
|
|
11
|
-
document.body.appendChild(overlay)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const handleServerErrors = () => {
|
|
16
|
-
if ((window as any).__staticRouterHydrationData?.errors) {
|
|
17
|
-
|
|
18
|
-
const {errors} = (window as any).__staticRouterHydrationData
|
|
19
|
-
|
|
20
|
-
Object.values(errors).forEach((error: any) => {
|
|
21
|
-
showErrorOverlay({
|
|
22
|
-
plugin: "ssr-router",
|
|
23
|
-
...error.reason
|
|
24
|
-
})
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export const initClient = () => {
|
|
30
|
-
initApiClient()
|
|
31
|
-
|
|
32
|
-
cleanupURL()
|
|
33
|
-
|
|
34
|
-
handleServerErrors()
|
|
35
|
-
}
|