Gabriel
Gabriel
Explore posts from servers
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
TTCTheo's Typesafe Cult
Created by Gabriel on 2/11/2023 in #questions
How could I create a multi-tenant application with the T3 stack?
Hi, I want to build a new startup, and I am feeling a little bit lost as to where to start. I know generally what I want to build, but honestly I feel like I get stuck on some problems I want to build a product that has two main areas: 1. A SaaS shop (many apps in the marketplace that you can pay monthly via stripe to access). For this part of the application, users will be able to create "Workspaces", or teams where you can share your data with your team. You will be able to work using the software you purchased and add people to it (maybe there could be multiple prices for each product, depending on number of active users) 2. A second "space" for the application, where I can only give access for it to certain people (say a company tenant). Basically, enable me to quickly spin up a new environment, and maybe even have its separate UI for this company. I would talk to a company and build a software for them on demand. I want to make sure that only people from the company have access to it etc. This part of the website will be strictly built for companies, or for tenants (multiple people) that want to have their own personal software that I would build on demand. I could make this software as resellable as possible, for other similar users that would want this software. I could then, whenever asked by another party, spin up a separate Tenant area, where only they will have access, and maybe change a few things depending on the client's needs. Basically, I want one area of the website (main url) to be accessed by anyone. There, you may log in, create a workspace and have multiple people join your workspace. There may be a few free apps, and then, apps where you subscribe to, in a monthly manner via stripe. This area, must have nothing to do with this second area of the app, where there will be multi environments for multiple tenants
12 replies