mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-05 19:49:57 +09:00
## Description AuthorisationToken didn't used in case of trpc call for context creation Closes #3786 ## Steps for reproduction Open in incognito https://fix-plan.development.webstudio.is/builder/d68d6dd1-bc0a-4b21-b5e5-08b7f99336f7?authToken=9d196f63-4256-4e74-98d4-ea678f9f94f1&mode=edit Add domain, owner plan settings will be used ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [ ] made a self-review - [ ] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 5de6) - [ ] updated [test cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md) document - [ ] added tests - [ ] if any new env variables are added, added them to `.env` file
145 lines
3.9 KiB
TypeScript
145 lines
3.9 KiB
TypeScript
import type { AppRouter } from "~/services/trcp-router.server";
|
|
import { createTRPCProxyClient, httpBatchLink } from "@trpc/client";
|
|
|
|
import type {
|
|
AnyMutationProcedure,
|
|
AnyRouter,
|
|
inferRouterInputs,
|
|
inferRouterOutputs,
|
|
} from "@trpc/server";
|
|
import { createRecursiveProxy } from "@trpc/server/shared";
|
|
import { useMemo, useState } from "react";
|
|
import { $authToken } from "../nano-states";
|
|
|
|
export const nativeClient = createTRPCProxyClient<AppRouter>({
|
|
links: [
|
|
httpBatchLink({
|
|
url: "/trpc",
|
|
// You can pass any HTTP headers you wish here
|
|
async headers(_opts) {
|
|
const authToken = $authToken.get();
|
|
|
|
if (authToken == null) {
|
|
return {};
|
|
}
|
|
// Pass token to api call
|
|
return {
|
|
"x-auth-token": authToken,
|
|
};
|
|
},
|
|
}),
|
|
],
|
|
});
|
|
|
|
type Procedures<T> = T extends AnyRouter
|
|
? {
|
|
[Procedure in keyof T["_def"]["record"]]: T["_def"]["record"][Procedure] extends AnyMutationProcedure
|
|
? {
|
|
useMutation: () => {
|
|
send: (
|
|
input: inferRouterInputs<T>[Procedure],
|
|
onSuccess?: (data: inferRouterOutputs<T>[Procedure]) => void
|
|
) => void;
|
|
data?: inferRouterOutputs<T>[Procedure];
|
|
state: "idle" | "submitting";
|
|
error?: string | undefined;
|
|
};
|
|
}
|
|
: {
|
|
useQuery: () => {
|
|
load: (
|
|
input: inferRouterInputs<T>[Procedure],
|
|
onSuccess?: (data: inferRouterOutputs<T>[Procedure]) => void
|
|
) => void;
|
|
data?: inferRouterOutputs<T>[Procedure];
|
|
state: "idle" | "submitting";
|
|
error?: string | undefined;
|
|
};
|
|
};
|
|
}
|
|
: never;
|
|
|
|
type Client = Record<
|
|
string,
|
|
Record<
|
|
string,
|
|
{ query: (args: unknown) => unknown; mutate: (args: unknown) => unknown }
|
|
>
|
|
>;
|
|
|
|
export const trpcClient: {
|
|
[SubRoute in keyof AppRouter["_def"]["record"]]: Procedures<
|
|
AppRouter["_def"]["record"][SubRoute]
|
|
>;
|
|
} = createRecursiveProxy((options) => {
|
|
const path = [...options.path];
|
|
const hook = path.pop();
|
|
const [data, setData] = useState<unknown>(undefined);
|
|
const [state, setState] = useState<"idle" | "submitting">("idle");
|
|
const [error, setError] = useState<string | undefined>(undefined);
|
|
|
|
if (hook !== "useMutation" && hook !== "useQuery") {
|
|
throw new Error(`Invalid hook ${hook}`);
|
|
}
|
|
|
|
// const method = path.join(".");
|
|
if (path.length !== 2) {
|
|
throw new Error(`Invalid path ${path}`);
|
|
}
|
|
|
|
const [namespace, method] = path;
|
|
|
|
const submit = useMemo(() => {
|
|
let requestId = 0;
|
|
|
|
return async (input: never, onSuccess?: (data: unknown) => void) => {
|
|
requestId += 1;
|
|
const currentRequestId = requestId;
|
|
try {
|
|
setState("submitting");
|
|
|
|
// if (process.env.NODE_ENV !== "production") {
|
|
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
// }
|
|
|
|
const result = await (nativeClient as unknown as Client)[namespace][
|
|
method
|
|
][hook === "useMutation" ? "mutate" : "query"](input);
|
|
|
|
// Newer request has been made, ignore this one
|
|
// In the future to support optimistic updates we can call onComplete with the requestId order
|
|
if (currentRequestId !== requestId) {
|
|
return;
|
|
}
|
|
|
|
setData(result);
|
|
setError(undefined);
|
|
onSuccess?.(result);
|
|
} catch (error) {
|
|
if (currentRequestId !== requestId) {
|
|
return;
|
|
}
|
|
|
|
console.error("TRPC ERROR", error);
|
|
|
|
if (error instanceof Error) {
|
|
setError(error.message);
|
|
return;
|
|
}
|
|
setError("Unknown error");
|
|
} finally {
|
|
if (currentRequestId === requestId) {
|
|
setState("idle");
|
|
}
|
|
}
|
|
};
|
|
}, [hook, namespace, method]);
|
|
|
|
return {
|
|
[hook === "useMutation" ? "send" : "load"]: submit,
|
|
data: data,
|
|
state,
|
|
error,
|
|
};
|
|
}) as never;
|