## What does this PR do? Loom: https://www.loom.com/share/361ca6ca9b5748079cba59ed2f348d90 Not all items on edit from update the user. This is very temp page to help Milos How to test: Login as admin user settings > admin > users search - see filtered users scroll to bottom of list - notice we refetch before you hit the bottom so you dont notice items loading delete user -> user is deleted and removed from list (radix bug in main causes dialog to freeze refresh to make this go away) edit user -> Edit users email/username/identityprovider. Not all items on this update work just yet. These will be picked up when we come to implement the proper user table.
158 lines
5.1 KiB
TypeScript
158 lines
5.1 KiB
TypeScript
import type { NextPageContext } from "next/types";
|
||
import superjson from "superjson";
|
||
|
||
import { httpBatchLink } from "../client/links/httpBatchLink";
|
||
import { httpLink } from "../client/links/httpLink";
|
||
import { loggerLink } from "../client/links/loggerLink";
|
||
import { splitLink } from "../client/links/splitLink";
|
||
import { createTRPCNext } from "../next";
|
||
// ℹ️ Type-only import:
|
||
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export
|
||
import type { TRPCClientErrorLike } from "../react";
|
||
import type { inferRouterInputs, inferRouterOutputs, Maybe } from "../server";
|
||
import type { AppRouter } from "../server/routers/_app";
|
||
|
||
/**
|
||
* We deploy our tRPC router on multiple lambdas to keep number of imports as small as possible
|
||
* TODO: Make this dynamic based on folders in trpc server?
|
||
*/
|
||
const ENDPOINTS = [
|
||
"admin",
|
||
"apiKeys",
|
||
"appRoutingForms",
|
||
"apps",
|
||
"auth",
|
||
"availability",
|
||
"bookings",
|
||
"deploymentSetup",
|
||
"eventTypes",
|
||
"features",
|
||
"insights",
|
||
"payments",
|
||
"public",
|
||
"saml",
|
||
"slots",
|
||
"teams",
|
||
"organizations",
|
||
"users",
|
||
"viewer",
|
||
"webhook",
|
||
"workflows",
|
||
"appsRouter",
|
||
"googleWorkspace",
|
||
] as const;
|
||
export type Endpoint = (typeof ENDPOINTS)[number];
|
||
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
const resolveEndpoint = (links: any) => {
|
||
// TODO: Update our trpc routes so they are more clear.
|
||
// This function parses paths like the following and maps them
|
||
// to the correct API endpoints.
|
||
// - viewer.me - 2 segment paths like this are for logged in requests
|
||
// - viewer.public.i18n - 3 segments paths can be public or authed
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
return (ctx: any) => {
|
||
const parts = ctx.op.path.split(".");
|
||
let endpoint;
|
||
let path = "";
|
||
if (parts.length == 2) {
|
||
endpoint = parts[0] as keyof typeof links;
|
||
path = parts[1];
|
||
} else {
|
||
endpoint = parts[1] as keyof typeof links;
|
||
path = parts.splice(2, parts.length - 2).join(".");
|
||
}
|
||
return links[endpoint]({ ...ctx, op: { ...ctx.op, path } });
|
||
};
|
||
};
|
||
|
||
/**
|
||
* A set of strongly-typed React hooks from your `AppRouter` type signature with `createTRPCReact`.
|
||
* @link https://trpc.io/docs/v10/react#2-create-trpc-hooks
|
||
*/
|
||
export const trpc = createTRPCNext<AppRouter, NextPageContext, "ExperimentalSuspense">({
|
||
config() {
|
||
const url =
|
||
typeof window !== "undefined"
|
||
? "/api/trpc"
|
||
: process.env.VERCEL_URL
|
||
? `https://${process.env.VERCEL_URL}/api/trpc`
|
||
: `${process.env.NEXT_PUBLIC_WEBAPP_URL}/api/trpc`;
|
||
|
||
/**
|
||
* If you want to use SSR, you need to use the server's full URL
|
||
* @link https://trpc.io/docs/ssr
|
||
*/
|
||
return {
|
||
/**
|
||
* @link https://trpc.io/docs/links
|
||
*/
|
||
links: [
|
||
// adds pretty logs to your console in development and logs errors in production
|
||
loggerLink({
|
||
enabled: (opts) =>
|
||
!!process.env.NEXT_PUBLIC_DEBUG || (opts.direction === "down" && opts.result instanceof Error),
|
||
}),
|
||
splitLink({
|
||
// check for context property `skipBatch`
|
||
condition: (op) => !!op.context.skipBatch,
|
||
// when condition is true, use normal request
|
||
true: (runtime) => {
|
||
const links = Object.fromEntries(
|
||
ENDPOINTS.map((endpoint) => [endpoint, httpLink({ url: url + "/" + endpoint })(runtime)])
|
||
);
|
||
return resolveEndpoint(links);
|
||
},
|
||
// when condition is false, use batch request
|
||
false: (runtime) => {
|
||
const links = Object.fromEntries(
|
||
ENDPOINTS.map((endpoint) => [endpoint, httpBatchLink({ url: url + "/" + endpoint })(runtime)])
|
||
);
|
||
return resolveEndpoint(links);
|
||
},
|
||
}),
|
||
],
|
||
/**
|
||
* @link https://react-query.tanstack.com/reference/QueryClient
|
||
*/
|
||
queryClientConfig: {
|
||
defaultOptions: {
|
||
queries: {
|
||
/**
|
||
* 1s should be enough to just keep identical query waterfalls low
|
||
* @example if one page components uses a query that is also used further down the tree
|
||
*/
|
||
staleTime: 1000,
|
||
/**
|
||
* Retry `useQuery()` calls depending on this function
|
||
*/
|
||
retry(failureCount, _err) {
|
||
const err = _err as never as Maybe<TRPCClientErrorLike<AppRouter>>;
|
||
const code = err?.data?.code;
|
||
if (code === "BAD_REQUEST" || code === "FORBIDDEN" || code === "UNAUTHORIZED") {
|
||
// if input data is wrong or you're not authorized there's no point retrying a query
|
||
return false;
|
||
}
|
||
const MAX_QUERY_RETRIES = 3;
|
||
return failureCount < MAX_QUERY_RETRIES;
|
||
},
|
||
},
|
||
},
|
||
},
|
||
/**
|
||
* @link https://trpc.io/docs/data-transformers
|
||
*/
|
||
transformer: superjson,
|
||
};
|
||
},
|
||
/**
|
||
* @link https://trpc.io/docs/ssr
|
||
*/
|
||
ssr: false,
|
||
});
|
||
|
||
export const transformer = superjson;
|
||
|
||
export type RouterInputs = inferRouterInputs<AppRouter>;
|
||
export type RouterOutputs = inferRouterOutputs<AppRouter>;
|