Files
webstudio/apps/builder/app/shared/trpc/trpc-client.ts
T
Ivan Starkov 8482ec4b77 fix: Wrong user is used when counting available custom domains on a free plan (#3792)
## 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
2024-07-30 19:22:45 +03:00

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;