@rpcbase/client 0.288.0 → 0.289.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.
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const getServerApiClient = async (app) => {
|
|
2
|
+
const callRoute = async (app2, method, path, req, res) => {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
let isEnded = false;
|
|
5
|
+
const mockReq = {
|
|
6
|
+
...req,
|
|
7
|
+
method: method.toUpperCase(),
|
|
8
|
+
url: path
|
|
9
|
+
};
|
|
10
|
+
const mockRes = {
|
|
11
|
+
...res,
|
|
12
|
+
json: (data) => {
|
|
13
|
+
if (!isEnded) {
|
|
14
|
+
isEnded = true;
|
|
15
|
+
resolve(data);
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
status: (statusCode) => {
|
|
19
|
+
console.log("Status:", statusCode);
|
|
20
|
+
return mockRes;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const routerStack = app2.router.stack;
|
|
24
|
+
const firstApiMiddlewareIndex = routerStack.findIndex((layer) => layer.name === "__FIRST_API_MIDDLEWARE__");
|
|
25
|
+
if (!(firstApiMiddlewareIndex > -1)) {
|
|
26
|
+
throw new Error("middleware: __FIRST_API_MIDDLEWARE__ was not found in stack");
|
|
27
|
+
}
|
|
28
|
+
const apiStack = routerStack.slice(firstApiMiddlewareIndex + 1);
|
|
29
|
+
const processLayer = async (index) => {
|
|
30
|
+
if (index >= apiStack.length || isEnded) return;
|
|
31
|
+
const layer = apiStack[index];
|
|
32
|
+
const isNonMatchingLayer = !layer.match(path);
|
|
33
|
+
if (isNonMatchingLayer) {
|
|
34
|
+
await processLayer(index + 1);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const runHandler = async (handler) => new Promise((resolveMiddleware, rejectMiddleware) => {
|
|
38
|
+
handler(mockReq, mockRes, (err) => {
|
|
39
|
+
if (err) {
|
|
40
|
+
console.error("Middleware error:", err);
|
|
41
|
+
if (!isEnded) {
|
|
42
|
+
isEnded = true;
|
|
43
|
+
rejectMiddleware(err);
|
|
44
|
+
}
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
resolveMiddleware();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
if (layer.route) {
|
|
51
|
+
if (!layer.route.methods[method.toLowerCase()]) {
|
|
52
|
+
await processLayer(index + 1);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (layer.route.stack.length !== 1) {
|
|
56
|
+
throw new Error(`expected only one handler per route for route: ${layer.route.path}`);
|
|
57
|
+
}
|
|
58
|
+
await runHandler(layer.route.stack[0].handle);
|
|
59
|
+
} else {
|
|
60
|
+
await runHandler(layer.handle);
|
|
61
|
+
}
|
|
62
|
+
if (!isEnded) {
|
|
63
|
+
await processLayer(index + 1);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
processLayer(0);
|
|
67
|
+
setTimeout(() => {
|
|
68
|
+
if (!isEnded) {
|
|
69
|
+
reject("Route handler timed out");
|
|
70
|
+
}
|
|
71
|
+
}, 3e4);
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
const createMethod = (method) => {
|
|
75
|
+
return async (path, payload, ctx) => {
|
|
76
|
+
if (!ctx) {
|
|
77
|
+
throw new Error("Context must be provided in SSR mode");
|
|
78
|
+
}
|
|
79
|
+
ctx.req.body = payload;
|
|
80
|
+
return callRoute(app, method, path, ctx.req, ctx.res);
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
const apiClient = {
|
|
84
|
+
get: createMethod("get"),
|
|
85
|
+
post: createMethod("post"),
|
|
86
|
+
put: createMethod("put"),
|
|
87
|
+
delete: createMethod("delete")
|
|
88
|
+
};
|
|
89
|
+
return apiClient;
|
|
90
|
+
};
|
|
91
|
+
export {
|
|
92
|
+
getServerApiClient as default,
|
|
93
|
+
getServerApiClient
|
|
94
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const useThrottledMeasure: (throttleDuration?: number) => (import('react-use/
|
|
1
|
+
export declare const useThrottledMeasure: (throttleDuration?: number) => (import('react-use/esm/useMeasure.js').UseMeasureRef<Element> | {
|
|
2
2
|
x: number;
|
|
3
3
|
y: number;
|
|
4
4
|
width: number;
|
package/dist/index.js
CHANGED
|
@@ -4,10 +4,16 @@ import posthog from "posthog-js";
|
|
|
4
4
|
import { createRoutesFromElements, createBrowserRouter, RouterProvider, useLocation } from "@rpcbase/router";
|
|
5
5
|
import { hydrateRoot } from "react-dom/client";
|
|
6
6
|
import { PostHogProvider } from "posthog-js/react/dist/esm/index.js";
|
|
7
|
-
import useMeasure from "react-use/
|
|
7
|
+
import useMeasure from "react-use/esm/useMeasure.js";
|
|
8
8
|
let apiClient;
|
|
9
9
|
const initApiClient = async (args) => {
|
|
10
|
-
{
|
|
10
|
+
if (globalThis.__rb_env__.SSR) {
|
|
11
|
+
if (!args) {
|
|
12
|
+
throw new Error("Server args must be provided in SSR mode");
|
|
13
|
+
}
|
|
14
|
+
const { getServerApiClient } = await import("./getServerApiClient-CHA4nyjq.js");
|
|
15
|
+
apiClient = await getServerApiClient(args.app);
|
|
16
|
+
} else {
|
|
11
17
|
const axios = (await import("axios")).default;
|
|
12
18
|
const axiosClient = axios.create({
|
|
13
19
|
baseURL: "/",
|
|
@@ -48,6 +54,9 @@ const initApiClient = async (args) => {
|
|
|
48
54
|
};
|
|
49
55
|
const CLEANUP_WAIT_DELAY = 1e3;
|
|
50
56
|
const cleanupURL = () => {
|
|
57
|
+
if (globalThis.__rb_env__.SSR) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
51
60
|
const runCleanup = () => {
|
|
52
61
|
setTimeout(() => {
|
|
53
62
|
const url = new URL(window.location.href);
|
|
@@ -68,6 +77,7 @@ const cleanupURL = () => {
|
|
|
68
77
|
document.addEventListener("DOMContentLoaded", runCleanup, { once: true });
|
|
69
78
|
}
|
|
70
79
|
};
|
|
80
|
+
const isProduction = globalThis.__rb_env__.MODE === "production";
|
|
71
81
|
const showErrorOverlay = (err) => {
|
|
72
82
|
const ErrorOverlay = customElements.get("vite-error-overlay");
|
|
73
83
|
if (!ErrorOverlay) {
|
|
@@ -95,6 +105,20 @@ const initWithRoutes = async (routesElement, opts) => {
|
|
|
95
105
|
const routes = createRoutesFromElements(routesElement);
|
|
96
106
|
const router = createBrowserRouter(routes);
|
|
97
107
|
const toError = (error) => error instanceof Error ? error : new Error(String(error));
|
|
108
|
+
const mentionsHydration = (value, depth = 0) => {
|
|
109
|
+
if (depth > 5) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
if (typeof value === "string") {
|
|
113
|
+
return value.toLowerCase().includes("hydrat");
|
|
114
|
+
}
|
|
115
|
+
if (value instanceof Error) {
|
|
116
|
+
const digest = value.digest;
|
|
117
|
+
const cause = value.cause;
|
|
118
|
+
return mentionsHydration(value.message, depth + 1) || mentionsHydration(digest, depth + 1) || mentionsHydration(cause, depth + 1);
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
};
|
|
98
122
|
const phReactHandler = (react_context) => (error, errorInfo) => {
|
|
99
123
|
const err = toError(error);
|
|
100
124
|
posthog.captureException(err, {
|
|
@@ -105,11 +129,19 @@ const initWithRoutes = async (routesElement, opts) => {
|
|
|
105
129
|
console.warn("Uncaught error", err, errorInfo?.componentStack);
|
|
106
130
|
}
|
|
107
131
|
};
|
|
108
|
-
const hydrationOptions = {
|
|
132
|
+
const hydrationOptions = isProduction ? {
|
|
109
133
|
onUncaughtError: phReactHandler("uncaught"),
|
|
110
134
|
onCaughtError: phReactHandler("caught"),
|
|
111
135
|
onRecoverableError: phReactHandler("recoverable")
|
|
112
|
-
}
|
|
136
|
+
} : opts?.devThrowsOnHydrationErrors ? {
|
|
137
|
+
onRecoverableError(error, errorInfo) {
|
|
138
|
+
const err = toError(error);
|
|
139
|
+
if (mentionsHydration(err) || mentionsHydration(errorInfo?.componentStack)) {
|
|
140
|
+
throw err;
|
|
141
|
+
}
|
|
142
|
+
console.error(err, errorInfo?.componentStack);
|
|
143
|
+
}
|
|
144
|
+
} : void 0;
|
|
113
145
|
hydrateRoot(
|
|
114
146
|
document.getElementById("root"),
|
|
115
147
|
/* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsx(RouterProvider, { router }) }),
|
|
@@ -643,7 +675,23 @@ const _snakeCase = /* @__PURE__ */ getDefaultExportFromCjs(snakeCaseExports);
|
|
|
643
675
|
const __vite_import_meta_env__ = { "BASE_URL": "/", "DEV": false, "MODE": "production", "PROD": true, "SSR": false };
|
|
644
676
|
const getFeatureFlag = async (flag) => {
|
|
645
677
|
const envKey = `RB_PUBLIC_FLAG_${_snakeCase(flag).toUpperCase()}`;
|
|
646
|
-
{
|
|
678
|
+
if (globalThis.__rb_env__.SSR) {
|
|
679
|
+
if (process.env[envKey] !== void 0) {
|
|
680
|
+
return process.env[envKey];
|
|
681
|
+
}
|
|
682
|
+
const startTime = performance.now();
|
|
683
|
+
const { PostHog } = await import("./index.node-f83KBCsj.js");
|
|
684
|
+
const client = new PostHog(
|
|
685
|
+
process.env.RB_PUBLIC_POSTHOG_KEY,
|
|
686
|
+
{ host: "https://eu.i.posthog.com" }
|
|
687
|
+
);
|
|
688
|
+
const distinctId = "server";
|
|
689
|
+
console.log("TODO: NYI server side feature flags client distinctId");
|
|
690
|
+
const value = await client.getFeatureFlag(flag, distinctId);
|
|
691
|
+
const endTime = performance.now();
|
|
692
|
+
console.log(`SSR: Feature flag "${flag}" loaded in ${(endTime - startTime).toFixed(2)}ms`);
|
|
693
|
+
return value;
|
|
694
|
+
} else {
|
|
647
695
|
let waitForFeatureFlags = function() {
|
|
648
696
|
return new Promise((resolve) => {
|
|
649
697
|
if (hasLoadedFeatureFlags) {
|