@rpcbase/client 0.279.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpcbase/client",
3
- "version": "0.279.0",
3
+ "version": "0.280.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "scripts": {
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from "./apiClient"
2
- export * from "./initClient"
2
+ export * from "./initWithRoutes"
3
3
  export * from "./types"
4
4
  export * from "./getFeatureFlag"
@@ -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
- }