Froxx
Froxx
TTCTheo's Typesafe Cult
Created by Froxx on 7/24/2024 in #questions
Handling ADHD while programming
This is kind of an off-topic question, but I thought some of you might have an interesting point of view / experience, or some resources to share. I have a friend who is very new to developing and who started working at my company. I'm basically giving him time to learn and teach him a lot about web dev myself. He is very motivated, but has days where he just can't function due to not being able to focus. On these days no progress is notable at all. He is very reflected about it, and we have a high amount of communication, but I am not sure on how to handle these situations. He is 29 btw, so not a "youngling" anymore. So motivation or other priorities like gaming, partying... is definitely not the problem. Do you have experience working with people having ADHD, and how do you handle it? Or do you even have ADHD yourself and can give some firsthand tips on how to handle these situations / how to pull yourself out of it / what other can do to help you / ...?
11 replies
TTCTheo's Typesafe Cult
Created by Froxx on 7/19/2023 in #questions
Single source of truth for models using Zod and Prisma
I feel I'm redundantly defining my models using Zod and Prisma. I do a rough db-fitting definition in my Prisma schema file, and another more detailed one in my Zod schemas. I tried using prisma-zod-generator to have my Prisma schema file as a SSoT, but since I need more detailed validations like min/max for numeric values, and also more complex refinements, this solution is not good enough. How do you guys do it? Do you have any recommendations?
6 replies
TTCTheo's Typesafe Cult
Created by Froxx on 6/13/2023 in #questions
Atomic Design for React components using Tailwind classes
I was thinking about basing my app's components on atomic design since I like the approach: "a component defines how it can look, the implementation just says where it goes". This basically means: - CSS Props like "margin", "position" and "z-index" may not be defined on a component's root level element within that component itself, but instead in the implementation - Other props like "color" are defined within the component and can be made changeable by custom props like e.g. "variant" This sounds nice but is hard to enforce since I usually style my components by simply passing "classNames" to it containing Tailwind classes, and I could potentially also pass classNames like "bg-red-500" which is something I don't want. Is there any common way to do this easily? Probably the way with the best DX would be a VS Code extension like "Tailwind CSS IntelliSense" which gives us auto-complete in the classNames prop of a component. Apart from that I thought about writing a custom type for my components, based on React.FC and extending it by margin, position, etc. instead of passing "classNames" as a prop in every component, but then I need a complex api that can handle everything from m-1 to mx-2 -ml-[calc(100px-2rem)] which sounds like a nightmare to me (also having in mind tailwind's tree-shaking) Did anyone of you ever waste a thought on this or has an opinion on the whole thing? Good idea? Bad idea? Good idea but too hard to make accessible?
6 replies
TTCTheo's Typesafe Cult
Created by Froxx on 4/19/2023 in #questions
Make NextAuth consider i18n
I am defining a custom sign-in page in my app setting
pages: {
signIn: "/auth/login",
}
pages: {
signIn: "/auth/login",
}
in [...nextauth].ts. I am also using react-intl for i18n, and I want NextAuth to localize this route as well. So when I have no valid session and route to a German route like /de/foo which needs auth, the signIn methods gets called, I get rerouted to my sign-in page, but my current locale gets lost. How can I make NextAuth remember my current locale, so I get redirected to /de/auth/login instead of plain /auth/login?
2 replies
TTCTheo's Typesafe Cult
Created by Froxx on 2/9/2023 in #questions
Clean definition of models using Zod schemas
My Current Situation My Zod schemas are my single source of truth regarding the structure of models used in my app because they are definable in a very detailed way and can even be used for runtime validation. Since there are usually multiple versions of each model (with id, when I fetch entities from my api; without id, when i create a new one; ...) I came up with a structure like this:
// base schema having the full scope of props (= result of GET requests)
const ModelSchema = z.object({
id: z.string().uuid(),
name: z.string(),
amount: z.number(),
active: z.boolean(),
});

// everything needed for creating a new entity of the model
const ModelCreateSchema = ModelSchema.omit({ id: true });

// id + some props for updating an existing entity "the PATCH way"
const ModelUpdateSchema = ModelSchema.pick({id: true}).merge(ModelCreateSchema.partial());
// base schema having the full scope of props (= result of GET requests)
const ModelSchema = z.object({
id: z.string().uuid(),
name: z.string(),
amount: z.number(),
active: z.boolean(),
});

// everything needed for creating a new entity of the model
const ModelCreateSchema = ModelSchema.omit({ id: true });

// id + some props for updating an existing entity "the PATCH way"
const ModelUpdateSchema = ModelSchema.pick({id: true}).merge(ModelCreateSchema.partial());
Although this already seemed a bit more complicated than I think it might be possible, it worked for the time being. Since my models are of course a bit more complicated than this example, I want to add refines to them. But when adding one to my base schema, I can't omit or pick them anymore since the whole schema is no longer a ZodObject but a ZodEffect which doesn't support those methods. I mean I could keep my old, unrefined version of that model as the base, and add refines later on on top of each single version of my model (create, update, ...), but that seems way too complicated and brings a bad DX since I should only need to define those things once. The Question Now I want to know how do you guys define your models? Do you also use Zod schemas, and if so, how do you structure them to solve issues like mine? Or do you have a completely different approach?
6 replies
TTCTheo's Typesafe Cult
Created by Froxx on 2/1/2023 in #questions
react-hook-form with formatted numeric values
I have an "amount" field which is numeric in my react-hook-form. Since the amounts can grow up to the millions in my case, I want to format the displayed value having a thousand separator for better UX. I looked for libs for formatting these values, and the best (maintained, easy to use, high popularity) I could find was react-number-format, so I gave it a shot. I found some attempts, all telling I might need to make my input "uncontrolled". These are the 2 ways I tried: https://stackoverflow.com/a/69258165/3045531 https://stackoverflow.com/a/63091512/3045531 My problem is that the actual form value linked to the field in the form's context is not numeric but a string, since it's handling the formatted value there, not the numeric one. How can I make the form handle the numeric value instead of the formatted one, so my Zod validation won't fail there? I would prefer not to use coerce in the schema to keep it cleaner.
26 replies
TTCTheo's Typesafe Cult
Created by Froxx on 1/19/2023 in #questions
Using undefined for empty input field in react-hook-form
First off: I feel I'm thinking way too complicated here, but can't wrap my brain around it, so here we are: Let's say I have a schema:
const MySchema = z.object({
name: z.string(),
amount: z.number(),
});
const MySchema = z.object({
name: z.string(),
amount: z.number(),
});
I want to build a form with an input type "text" for name, and an input type "number" for amount. Do I need to create an extra "form type" of that schema to represent the data within the form before validation? So something like:
type FormData = {
name: string;
amount: number | "";
}
type FormData = {
name: string;
amount: number | "";
}
Imo this would make things really complicated since I would need to somewhere (where even?) map my form data to the actual schema data (e.g. amount: formData.amount === "" ? undefined : parseInt(formData.amount),. So yeah, I would like to prevent things like that. This is why I thought doing fancy things in my FormInput component like
<input
// ...
{...register("someProp")}
onChange={(e) => onChange(transformEventTargetStringValueToActualValueOfWhateverTypeMyPropInTheSchemaHas(e.target.value))}
/>
<input
// ...
{...register("someProp")}
onChange={(e) => onChange(transformEventTargetStringValueToActualValueOfWhateverTypeMyPropInTheSchemaHas(e.target.value))}
/>
once would be a good idea. But this also adds undefined as a possible value for the input which React doesn't like since changing a component's value between undefined and a defined value makes it switch between being controlled / uncontrolled. Like I said, I feel I'm thinking way too complicated here. Isn't there an easy solution to handle form input fields' data before validation? I really don't want to add an additional FormData type for all of my schemas since I'm building lots and lots of forms.
40 replies
TTCTheo's Typesafe Cult
Created by Froxx on 11/14/2022 in #questions
Solve migration conflicts
This is a complete noob question, but I'm new to db management and migration in general, and I can't find what I'm looking for in the prisma docs: https://www.prisma.io/docs/concepts/components/prisma-migrate Over time my prisma.schema changes. I want to migrate my existing data. If there is a new field being added to a table, it's no big deal as long as it's nullable or has a default value set in the schema. But if I want to make it required or do something else that requires manual explanation on how to do things, how do I tell prisma? What's the flow there? For now I usually fiddle a bit around locally using prisma db push and resetting my local db a few times until I get what I want, and finally use prisma migrate dev to create the migration file. But this of course has no logic for existing data included (which is needed for prod env later on). Do I just edit that migration file and manually add SQL statements to it to fill the new data fields, or what's the way to go there?
4 replies
TTCTheo's Typesafe Cult
Created by Froxx on 11/13/2022 in #questions
Make Zod.string() handle empty string as undefined
Having a schema like
z.string().min(4)
z.string().min(4)
I want "" to throw Field X is required and "abc" to throw Field X must contain at least 4 characters. But I don't want to add this specifically to every prop. Can I somehow make Zod handle "" as "not defined" by default?
9 replies
TTCTheo's Typesafe Cult
Created by Froxx on 11/9/2022 in #questions
Learning a new keyboard layout
Qwerty sucks. Even more does Qwertz (yes, I'm German). Learning an alternative keyboard layout sounds like a great idea to me, already knowing I will regret that of course poohheh I read about "programmer dvorak" which seems to be the general #1 choice for general programming. Still you guys might have own experiences, and maybe know about a more fitting one specifically for JS or even React. Things like the availability of useful keymaps for OS and VS Code are also interesting. What are your thoughts / stories?
10 replies
TTCTheo's Typesafe Cult
Created by Froxx on 11/6/2022 in #questions
Handle specific tRPC errors centrally
I would like to handle some errors of all of my queries centrally. e.g. I would like to have an 401 error always be handled the same way -> reroute the user to my login page. So I would like to prevent adding an onError func to every query I'm doing in my client. Is there a way to do that? I looked for a place to do it and found /server/trpc/trpc.ts where it sets up the protectedProcedure with the isAuthed function. Problem here is this isn't client side, so I can't call hooks including my router.
13 replies
TTCTheo's Typesafe Cult
Created by Froxx on 11/2/2022 in #questions
Getting no session from useSession() with NextAuth
I'm trying to implement a simple "username, password"-CredentialsProvider in my app. I'm using the standard prisma schema from create-t3-app, and just added a "password" prop to the User model. Im am using the authorize function in the authOptions of NextAuth ([...nextauth].ts) to check if a user with that username exists in my db, and also check if the password matches. If that's true, I create a new session like
// lifespan of session: 1 day
const expires = new Date();
expires.setDate(expires.getDate() + 1);

await prisma.session.create({
data: {
userId: user.id,
expires,
sessionToken: await hash(`${Math.random()}`),
},
});
// lifespan of session: 1 day
const expires = new Date();
expires.setDate(expires.getDate() + 1);

await prisma.session.create({
data: {
userId: user.id,
expires,
sessionToken: await hash(`${Math.random()}`),
},
});
and return the user object afterwards. In my custom login page I trigger NextAuth's signIn function like:
signIn("credentials", {
redirect: false,
username,
password,
});
signIn("credentials", {
redirect: false,
username,
password,
});
If given correct credentials, it's resolved without any errors, and a new session gets created in my db. Still when I check for session data using useSession() I always end up getting null. I am also missing the session cookie. I only have next-auth.csrf-token and next-auth.callback-url. Yes, I am providing the session using SessionProvider in my pages/_app.tsx. Why is the useSession hook not getting my data? What am I missing? My head is smoking...
25 replies
TTCTheo's Typesafe Cult
Created by Froxx on 10/30/2022 in #questions
env schema.mjs reading values as number
Most of the times env vars are strings, so my schema definition of a value looks like NEXTAUTH_URL: z.string() for those vars. But if I want to read numeric values like a port, it seems I can't just do EMAIL_SERVER_PORT: z.number(). Do I generally have to read env vars as string-ish values, and have to parse them to numeric values in my code later on, or am I doing something wrong?
1 replies
TTCTheo's Typesafe Cult
Created by Froxx on 10/28/2022 in #questions
Since next auth isn't working with node 18 yet, what's the recommended way to use it? Go down to 16?
Title says it all.
15 replies