Gabriel
Gabriel
Explore posts from servers
TtRPC
Created by Gabriel on 11/9/2024 in #❓-help
How can I automatically use react's cache with tRPC on server side?
I have this in my repo:
import { cache } from "react";
import { headers } from "next/headers";

import { createCaller, createTRPCContext } from "@kdx/api";
import { auth } from "@kdx/auth";

/**
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(async () => {
const heads = new Headers(headers());
heads.set("x-trpc-source", "rsc");

return createTRPCContext({
auth: await auth(),
headers: heads,
});
});

export const api = createCaller(createContext);
import { cache } from "react";
import { headers } from "next/headers";

import { createCaller, createTRPCContext } from "@kdx/api";
import { auth } from "@kdx/auth";

/**
* This wraps the `createTRPCContext` helper and provides the required context for the tRPC API when
* handling a tRPC call from a React Server Component.
*/
const createContext = cache(async () => {
const heads = new Headers(headers());
heads.set("x-trpc-source", "rsc");

return createTRPCContext({
auth: await auth(),
headers: heads,
});
});

export const api = createCaller(createContext);
But, now I need to understand, how should I export the actual functions from the api caller so they are all cached with react's cache? I of course could do something like this
export const uglyGetNotifications = cache(api.user.getNotifications);
export const uglyGetNotifications = cache(api.user.getNotifications);
But I would prefer if I could get an instance of api where all of my endpoints will be using the cache automatically. something like
const notifs = await apiCached.user.getNotifications();
const notifs = await apiCached.user.getNotifications();
2 replies
TtRPC
Created by Gabriel on 7/10/2024 in #❓-help
How to improve typescript performance?
No description
57 replies
DTDrizzle Team
Created by Gabriel on 3/13/2024 in #help
disambiguate foreign key relations
No description
1 replies
TtRPC
Created by Gabriel on 3/6/2024 in #❓-help
Why deprecate experimental_standaloneMiddleware?
I am reading https://trpc.io/docs/server/middlewares#experimental-standalone-middlewares, but it's still not clear to me why experimental_standaloneMiddleware was deprecated. It says we can use .concat() to use "standalone" middlewares. However, I don't see how they are related exactly? The example shows we can use a plugin. This would take in a new procedure to do concating of procedures. But this is not exactly what I want. In my code I have this:
const todoAppInstalledMiddleware experimental_standaloneMiddleware<{
ctx: TProtectedProcedureContext;
}>().create(async ({ ctx, next }) => {
const foundPermission = await ctx.prisma.teamAppRole.findFirst({
where: {
AppPermissions: {
some: {
id: "234234324-my-todo-app-id-here-yay",
},
},
Team: {
id: ctx.session.user.activeTeamId,
},
Users: {
some: {
id: ctx.session.user.id,
},
},
},
select: { id: true },
});

if (!foundPermission)
throw new TRPCError({
code: "UNAUTHORIZED",
message: `You don't have permission to do this. Contact an administrator if you believe it is an error.`,
});

return next({ ctx });
});
const todoAppInstalledMiddleware experimental_standaloneMiddleware<{
ctx: TProtectedProcedureContext;
}>().create(async ({ ctx, next }) => {
const foundPermission = await ctx.prisma.teamAppRole.findFirst({
where: {
AppPermissions: {
some: {
id: "234234324-my-todo-app-id-here-yay",
},
},
Team: {
id: ctx.session.user.activeTeamId,
},
Users: {
some: {
id: ctx.session.user.id,
},
},
},
select: { id: true },
});

if (!foundPermission)
throw new TRPCError({
code: "UNAUTHORIZED",
message: `You don't have permission to do this. Contact an administrator if you believe it is an error.`,
});

return next({ ctx });
});
Doing this via concat() feels unnatural. I just want to define a middleware that I can use in multiple procedures where my session is not null (protected context). What is the recommended way of doing this?
5 replies
TtRPC
Created by Gabriel on 1/26/2024 in #❓-help
How do I pass a Generic to a trpc query procedure?
I want to to something like this:
type AppIdsWithConfig = typeof kodixCareAppId | typeof calendarAppId;

const fakeProcedure = <T extends AppIdsWithConfig>(kodixAppId: T) => {
const appIdToValue = {
[kodixCareAppId]: "my value 1",
[calendarAppId]: 1235,
} as const;

return appIdToValue[kodixAppId];
};

const value = fakeProcedure(kodixCareAppId);
// ^? --> const value: "my value 1"

const value2 = fakeProcedure(calendarAppId);
// ^? --> const value2: 1235
type AppIdsWithConfig = typeof kodixCareAppId | typeof calendarAppId;

const fakeProcedure = <T extends AppIdsWithConfig>(kodixAppId: T) => {
const appIdToValue = {
[kodixCareAppId]: "my value 1",
[calendarAppId]: 1235,
} as const;

return appIdToValue[kodixAppId];
};

const value = fakeProcedure(kodixCareAppId);
// ^? --> const value: "my value 1"

const value2 = fakeProcedure(calendarAppId);
// ^? --> const value2: 1235
This is how you pass a generic to a function, as we know. I wanted to do it in a procedure. Right now I have a procedure:
type AppIdsWithConfig = typeof kodixCareAppId | typeof calendarAppId;

//How do I pass a Generic to this? I want to infer the result type based on the appId I pass in as an input
getConfig: protectedProcedure
.input(
z.object({
appId: z.custom<AppIdsWithConfig>(),
}),
)
.query(
async ({ ctx, input }) =>
await getAppConfig({
appId: input.appId,
prisma: ctx.prisma,
session: ctx.session,
}),
),
type AppIdsWithConfig = typeof kodixCareAppId | typeof calendarAppId;

//How do I pass a Generic to this? I want to infer the result type based on the appId I pass in as an input
getConfig: protectedProcedure
.input(
z.object({
appId: z.custom<AppIdsWithConfig>(),
}),
)
.query(
async ({ ctx, input }) =>
await getAppConfig({
appId: input.appId,
prisma: ctx.prisma,
session: ctx.session,
}),
),
6 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 10/8/2023 in #questions
How to add Prisma Client extensions to create-t3-app?
No description
3 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 10/2/2023 in #questions
What are these Typescript completion suggestions inside Prisma?
No description
2 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 9/23/2023 in #questions
Prisma deleting wrong table?? WHY
Ok, here's what I want to do: I want to delete a EventMaster that is linked to a certain EventException. Here's my query:
await ctx.prisma.eventMaster.deleteMany({
where: {
workspaceId: ctx.session.user.activeWorkspaceId,
EventExceptions: {
some: {
id: input.eventExceptionId,
},
},
},
});
await ctx.prisma.eventMaster.deleteMany({
where: {
workspaceId: ctx.session.user.activeWorkspaceId,
EventExceptions: {
some: {
id: input.eventExceptionId,
},
},
},
});
FOR SOME REASON, this is deleting my EventException and not my EventMaster. I don't know why... this is scaring me because the query looks solid to me. I do have setup cascade deletes on my EventException, because I do want prisma to delete my EventException after I delete the EventMaster. However, it is not deleting the master at all and only the EventException. WHy is this happening?
2 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 8/28/2023 in #questions
Help in Nextauth EmailProvider
I am getting this strange error in emailProvider for nextauth. Does anyone know what I am doing wrong?
Type 'EmailConfig' is not assignable to type 'Provider'.
Type 'EmailConfig' is not assignable to type 'EmailConfig & InternalProviderOptions'.
Type 'EmailConfig' is not assignable to type 'InternalProviderOptions'.
Types of property 'options' are incompatible.
Type 'EmailUserConfig' is not assignable to type 'Record<string, unknown>'.
Index signature for type 'string' is missing in type 'EmailUserConfig'.ts(2322)
Type 'EmailConfig' is not assignable to type 'Provider'.
Type 'EmailConfig' is not assignable to type 'EmailConfig & InternalProviderOptions'.
Type 'EmailConfig' is not assignable to type 'InternalProviderOptions'.
Types of property 'options' are incompatible.
Type 'EmailUserConfig' is not assignable to type 'Record<string, unknown>'.
Index signature for type 'string' is missing in type 'EmailUserConfig'.ts(2322)
13 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 8/15/2023 in #questions
How do I make Next App dir only run a function once? (Like getStaticProps)
Hi, I have a function called getLocalDevURL, but I can't seem to get it to properly run only once on the server, at build time. I am building an utility to generate a QR code, and for that I need to make getLocalDevURL run only once.
import { networkInterfaces } from "os";
import Image from "next/image";

import { Dialog, DialogContent, DialogTrigger } from "@kdx/ui";

function getLocalDevURL() {
const interfaces = networkInterfaces();
return (
interfaces.Ethernet?.find((x) => x.family === "IPv4")?.address +
":" +
"3001"
);
}

export default function TailwindIndicator() {
if (process.env.NODE_ENV === "production") return null;

const url = getLocalDevURL();

return (
<Dialog>
<DialogTrigger asChild>
<div className="fixed bottom-1 right-1 z-50 flex flex-row items-center space-x-1">
<div className="bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-full p-3 font-mono text-xs font-bold">
<div className="block sm:hidden">xs</div>
<div className="hidden sm:block md:hidden lg:hidden xl:hidden 2xl:hidden">
sm
</div>
<div className="hidden md:block lg:hidden xl:hidden 2xl:hidden">
md
</div>
<div className="hidden lg:block xl:hidden 2xl:hidden">lg</div>
<div className="hidden xl:block 2xl:hidden">xl</div>
<div className="hidden 2xl:block">2xl</div>
</div>
</div>
</DialogTrigger>
<DialogContent className="w-fit">
<Image
alt="QR Code"
width={150}
height={150}
src={`https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=http://${url}`}
></Image>
</DialogContent>
</Dialog>
);
}
import { networkInterfaces } from "os";
import Image from "next/image";

import { Dialog, DialogContent, DialogTrigger } from "@kdx/ui";

function getLocalDevURL() {
const interfaces = networkInterfaces();
return (
interfaces.Ethernet?.find((x) => x.family === "IPv4")?.address +
":" +
"3001"
);
}

export default function TailwindIndicator() {
if (process.env.NODE_ENV === "production") return null;

const url = getLocalDevURL();

return (
<Dialog>
<DialogTrigger asChild>
<div className="fixed bottom-1 right-1 z-50 flex flex-row items-center space-x-1">
<div className="bg-foreground text-background flex h-6 w-6 items-center justify-center rounded-full p-3 font-mono text-xs font-bold">
<div className="block sm:hidden">xs</div>
<div className="hidden sm:block md:hidden lg:hidden xl:hidden 2xl:hidden">
sm
</div>
<div className="hidden md:block lg:hidden xl:hidden 2xl:hidden">
md
</div>
<div className="hidden lg:block xl:hidden 2xl:hidden">lg</div>
<div className="hidden xl:block 2xl:hidden">xl</div>
<div className="hidden 2xl:block">2xl</div>
</div>
</div>
</DialogTrigger>
<DialogContent className="w-fit">
<Image
alt="QR Code"
width={150}
height={150}
src={`https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=http://${url}`}
></Image>
</DialogContent>
</Dialog>
);
}
7 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 7/22/2023 in #questions
What is prefetching in TRPC server side?
I was able to create a TRPC server helper with "createServerSideHelpers". I am using it in my server function like this:
import { helpers } from "~/utils/proxy";
import Client from "./Client";

export default async function HomePage() {
await helpers.test.test.prefetch({ source: "client" });
return (
<main className="flex h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
<Client />
</main>
);
}
import { helpers } from "~/utils/proxy";
import Client from "./Client";

export default async function HomePage() {
await helpers.test.test.prefetch({ source: "client" });
return (
<main className="flex h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white">
<Client />
</main>
);
}
But I don't understand what it is doing. The docs say it does not return anything and never throws. I tried importing "Client" that is actually a Client component to see how it behaves:
"use client";

import React from "react";

import { api } from "~/utils/api";

export default function Client() {
const apps = api.test.test.useQuery({ source: "client" });

return <div className="">{JSON.stringify(apps.data)}</div>;
}
"use client";

import React from "react";

import { api } from "~/utils/api";

export default function Client() {
const apps = api.test.test.useQuery({ source: "client" });

return <div className="">{JSON.stringify(apps.data)}</div>;
}
I thought it would somehow have sent the data into the ReactQuery as initialData or something, but it always fetches right when the Client component is mounted. I don't understand what prefetching does. Can someone explain
10 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 7/22/2023 in #questions
Correct way to fetch data in a server component and pass it to a client component? ReactQuery TRPC
Hi, I want to understand what are the best practices to deal with TRPC and react server components. Say that I want to have a server component that fetches data in the backend using trpc. I understand that if I am in the server I should use createCaller method from trpc. I tried to do it like so, and pass the data I fetch from the caller to my client component:
3 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 7/18/2023 in #questions
Can I still get features like SSR/ISR with this infrastructure?
21 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 7/17/2023 in #questions
Feedback for my infrastructure needed!
11 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 7/13/2023 in #questions
How can I use a TurboRepo to have multiple Apps? Do I use multiple Next.JS projects? Help with infra
13 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 5/9/2023 in #questions
Is there a onRegister handler for NextAuth?
Hi folks, how would you go about creating a onRegister function on NextAuth for new users? Their documentation does not have this, I don't know why. I want to generate some data on DB whenever a new user is logged in for the very first time
5 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 5/3/2023 in #questions
Help with Vercel deployment
3 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 5/2/2023 in #questions
How do I set the default useState value of a trpc call?
12 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 2/28/2023 in #questions
Help, how do I do this?
5 replies
TTCTheo's Typesafe Cult
Created by Gabriel on 2/23/2023 in #questions
Debugging TRPC issues?
9 replies