fotoflo
fotoflo
Explore posts from servers
PPrisma
Created by fotoflo on 6/4/2024 in #help-and-questions
db push and migrate dev
i used prisma db push, and now i want to create the migration and push to prod. I used migrate dev on local and it wants me to delete all data. i assume later when i migrate prod i will also lose all data?
9 replies
PPrisma
Created by fotoflo on 5/14/2024 in #help-and-questions
Database Design for Sitemaps
No description
2 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 5/9/2024 in #questions
TRPC not returning immediately on error
Simple:
export const sitemapRouter = router({
getSitemap: protectedProcedure
.query(async ({ ctx, input }) => {
throw new Error("testing throwing errors");
})
export const sitemapRouter = router({
getSitemap: protectedProcedure
.query(async ({ ctx, input }) => {
throw new Error("testing throwing errors");
})
Component:
const {
sitemapUri,
setSitemapUri,
sitemapUrls,
sitemapIsLoading,
sitemapIsError,
sitemapError,
sitemapStatus,
sitemapUrlForm,
submitHandler,
} = useSitemaps();

return (
{sitemapError && <div>error: {sitemapError.message}</div>}
{sitemapIsError && <div>Iserror: {sitemapError.message}</div>}
{sitemapStatus && <div>Status: {sitemapStatus}</div>}
)

useSitemaps:
const {
sitemapUri,
setSitemapUri,
sitemapUrls,
sitemapIsLoading,
sitemapIsError,
sitemapError,
sitemapStatus,
sitemapUrlForm,
submitHandler,
} = useSitemaps();

return (
{sitemapError && <div>error: {sitemapError.message}</div>}
{sitemapIsError && <div>Iserror: {sitemapError.message}</div>}
{sitemapStatus && <div>Status: {sitemapStatus}</div>}
)

useSitemaps:
ts export function useSitemaps() { const { data: sitemapUrls, isLoading: sitemapIsLoading, isError: sitemapIsError, error: sitemapError, status: sitemapStatus, } = trpc.sitemaps.getSitemap.useQuery( { url: sitemapUri, } );
return { sitemapUri, setSitemapUri, sitemapUrls, sitemapIsLoading, sitemapIsError, sitemapUrlForm, submitHandler, sitemapError, sitemapStatus, }; } ```
5 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 5/8/2024 in #questions
NextJs not picking up my ENV vars - no changes made
Very strange - haven't touched this part of the code, or done any new npm installs or anything... but after restarting my workstation, im getting the Invalid Env Vars error... I've just added an var called ENV_FILENAME (with the file name of the ENV File it's in) to all the env's on my system and added
if (_serverEnv.success) {
console.log(
`✅ Valid environment variables on server - ${_serverEnv.ENV_FILENAME}`
);
}
if (_serverEnv.success) {
console.log(
`✅ Valid environment variables on server - ${_serverEnv.ENV_FILENAME}`
);
}
the ENV_FILENAME (which i've defined at the top of each env file) is coming back undefined also I've also added this custom thing to my next.config.mjs
console.log(`
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!
!! WELCOME TO T3
!!
!! Node Version: ${process.version} (use 18!)
!! Database: ${db}
!! ENV: ${env.ENV_FILENAME}
!! Your Developer Handle: ${env.DEVELOPER_HANDLE}
!! HOST: ${env.NEXT_PUBLIC_HOST}
!! NGROK: https://${env.NGROK_DOMAIN}
!!
!! Happy Coding!
!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
`);
console.log(`
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!
!! WELCOME TO T3
!!
!! Node Version: ${process.version} (use 18!)
!! Database: ${db}
!! ENV: ${env.ENV_FILENAME}
!! Your Developer Handle: ${env.DEVELOPER_HANDLE}
!! HOST: ${env.NEXT_PUBLIC_HOST}
!! NGROK: https://${env.NGROK_DOMAIN}
!!
!! Happy Coding!
!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
`);
and oddly that renders correctly, with .env.local
7 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 4/29/2024 in #questions
Optimistic Updates with TRPC Hook
I've made a hook with TRPC and am trying to create optimistic updates.. simplified below
export function useComments(urlId: string) {
const [comments, setComments] = useState([] as urlComments[]);
const [error, setError] = useState(null);
const trpcContext = trpc.useContext();


// works
const { data, isLoading, isError } = trpc.comments.getComments.useQuery(
urlId,
{
onSuccess: (data) => {
setComments(data);
},
}
);

// this is where the optimistic update happens
const commentMutation = trpc.comments.createComment.useMutation({
onMutate: async (newComment) => {
const previousComments = [...comments];
const optimisticComment = {
...newComment,
id: `temp-${Date.now()}`,
type: "TEMP",
};

setComments((oldComments) => [optimisticComment, ...previousComments]);

/// above line didnt work, below also no workie

trpcContext.timelines.getTimeline.setData("undefined", (data) => {
return [optimisticComment, ...previousComments];
});

return { previousComments }; // Return the snapshot for potential rollback
},
....
});

const addComment = (commentData) => {
commentMutation.mutate({ urlId, ...commentData });
};

return {
comments,
addComment,
error,
isLoading,
isError,
};
}
export function useComments(urlId: string) {
const [comments, setComments] = useState([] as urlComments[]);
const [error, setError] = useState(null);
const trpcContext = trpc.useContext();


// works
const { data, isLoading, isError } = trpc.comments.getComments.useQuery(
urlId,
{
onSuccess: (data) => {
setComments(data);
},
}
);

// this is where the optimistic update happens
const commentMutation = trpc.comments.createComment.useMutation({
onMutate: async (newComment) => {
const previousComments = [...comments];
const optimisticComment = {
...newComment,
id: `temp-${Date.now()}`,
type: "TEMP",
};

setComments((oldComments) => [optimisticComment, ...previousComments]);

/// above line didnt work, below also no workie

trpcContext.timelines.getTimeline.setData("undefined", (data) => {
return [optimisticComment, ...previousComments];
});

return { previousComments }; // Return the snapshot for potential rollback
},
....
});

const addComment = (commentData) => {
commentMutation.mutate({ urlId, ...commentData });
};

return {
comments,
addComment,
error,
isLoading,
isError,
};
}
and then i consume it here:
export default function Comments({
}: Props): JSX.Element {
const { comments } = useComments(id);

// RERENDER NOT HAPPENING!!
console.log({comments});

return (
<>
{comments &&
comments.map((item) => (
<Item item={item} />
))}
<>
);
}
export default function Comments({
}: Props): JSX.Element {
const { comments } = useComments(id);

// RERENDER NOT HAPPENING!!
console.log({comments});

return (
<>
{comments &&
comments.map((item) => (
<Item item={item} />
))}
<>
);
}
7 replies
PPrisma
Created by fotoflo on 4/19/2024 in #help-and-questions
How to get the type of a compound query?
how would i get the type of this?
ts
const commentsPromise = prisma.urlComments.findMany({
where: {
urlId,
},
include: {
User: {
select: {
name: true,
email: true,
image: true,
},
},
},
orderBy: {
createdAt: "desc",
},
});

const statusCheckPromise = prisma.statusChecks.findMany({
where: {
urlId,
httpCode: {
notIn: [200, 301, 302, 303, 307, 308],
},
},
orderBy: {
createdAt: "desc",
},
});

const [comments, statusChecks] = await prisma.$transaction([
commentsPromise,
statusCheckPromise,
]);
ts
const commentsPromise = prisma.urlComments.findMany({
where: {
urlId,
},
include: {
User: {
select: {
name: true,
email: true,
image: true,
},
},
},
orderBy: {
createdAt: "desc",
},
});

const statusCheckPromise = prisma.statusChecks.findMany({
where: {
urlId,
httpCode: {
notIn: [200, 301, 302, 303, 307, 308],
},
},
orderBy: {
createdAt: "desc",
},
});

const [comments, statusChecks] = await prisma.$transaction([
commentsPromise,
statusCheckPromise,
]);
6 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 3/26/2024 in #questions
Firing a client-side event when the user signs in
Hi guys, I want to fire an event when a user signs in on the client side. Currently i can do it for new users cause they land on a welcome page. When a user signs in normally I increment user.logins on the server side and take them to their dashboard. Is there a good way to know if it's a new sign so i can fire a client side event?
2 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 3/9/2024 in #questions
slow trpc query seems to be delaying render of non-dependant components
I have a simple Page component:
const Page: NextPage = () => {
const { data: urlRecord } = trpc.urls.getByUrn.useQuery("string");
return (
<div record={urlRecord}>
<ComponentOne record={urlRecord} />
<ComponentTwo record={urlRecord} />
<ComponentThree record={urlRecord} />
</div>
);
};
const Page: NextPage = () => {
const { data: urlRecord } = trpc.urls.getByUrn.useQuery("string");
return (
<div record={urlRecord}>
<ComponentOne record={urlRecord} />
<ComponentTwo record={urlRecord} />
<ComponentThree record={urlRecord} />
</div>
);
};
All three sub Components have tRPC queries in them, they return a loader if isLoading. The urlRecord returns quickly (10ms), <ComponentOne> and <ComponentTwo>'s queries return in under 100ms, but <ComponentThree>'s query make take a few seconds ore more. the page loads quickly and the loaders are seen until the slowest query (CompnentThree) returns its data. Then all of the components render with data at once. Why is this? is it possible to get the components to all render when they';re ready?
8 replies
PPrisma
Created by fotoflo on 3/9/2024 in #help-and-questions
Fixing slow query
Hey guys, any idea why this query might suddenly take 9 seconds?
export async function getStatusChecks(urlId: string) {
console.time("getStatusChecks");

const millisInDay = 1000 * 60 * 60 * 24;
const result = await prisma.statusChecks.findMany({
where: {
urlId: { equals: urlId },
createdAt: { gte: new Date(Date.now() - 4 * millisInDay) },
},
orderBy: {
createdAt: "asc",
},
take: 50,
});

console.timeEnd("getStatusChecks");
return result;
}
export async function getStatusChecks(urlId: string) {
console.time("getStatusChecks");

const millisInDay = 1000 * 60 * 60 * 24;
const result = await prisma.statusChecks.findMany({
where: {
urlId: { equals: urlId },
createdAt: { gte: new Date(Date.now() - 4 * millisInDay) },
},
orderBy: {
createdAt: "asc",
},
take: 50,
});

console.timeEnd("getStatusChecks");
return result;
}
schema:
model statusChecks {
id String @id @default(cuid())
createdAt DateTime @default(now()) @db.Timestamp(0)
bodySize Int?
effectiveUrl String @db.VarChar(4096)
errorCode String?
httpCode Int?
httpCodeLang String?
redirectCount Int?
totalTime Decimal
status Boolean
urlId String @db.VarChar(25)
urls urls @relation(fields: [urlId], references: [id], onDelete: Cascade)
}
model statusChecks {
id String @id @default(cuid())
createdAt DateTime @default(now()) @db.Timestamp(0)
bodySize Int?
effectiveUrl String @db.VarChar(4096)
errorCode String?
httpCode Int?
httpCodeLang String?
redirectCount Int?
totalTime Decimal
status Boolean
urlId String @db.VarChar(25)
urls urls @relation(fields: [urlId], references: [id], onDelete: Cascade)
}
Maybe i need to add some indices?
11 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 10/29/2023 in #questions
Where to put / how to cache frequently used user info?
hi guys, i think i made a big mistake - i put a lot of logic in my session callback to build a nice session.user object that has a lot of the things i need to reference all the time on it. It all worked fine until i pushed to Vercel - now it's crazy slow.... So where does this kind of information typically go? My current session: https://pastebin.pl/view/d2329da1
13 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 9/12/2023 in #questions
trouble with Vercel deploy (no errors)
No description
4 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 4/1/2023 in #questions
Simple long polling with tRPC
I'm sending an email with a useMutation with MailJet. MailJet's API returns success, even when the email is queued, sending may still fail. They have another API to get the status of the email. I've created a backend function with Quirrel to keep hitting that API until i have a status that's not pending, and then put that status in my DB. Now I want to long-poll my db in the useMutation's onSuccess to check the email status. In order to do that, i create a function in the onSuccess that invalidate's the whole collection's data every second until i get the status. I'd much rather just check the ID of the item with like a Get API repeated and then invalidate everything when it changes... is there a way to do that with tRPC? Also, This sounds overly complex.
5 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 3/26/2023 in #questions
zod-prisma-types and prisma-zod-generator BOTH fail to generate
Just installed both zod-prisma-types and prisma-zod-generator
$ prisma db push

Running generate... (Use --skip-generate to skip the generators)
Error: Generator at zod-prisma-types could not start:

/bin/sh: zod-prisma-types: command not found
$ prisma db push

Running generate... (Use --skip-generate to skip the generators)
Error: Generator at zod-prisma-types could not start:

/bin/sh: zod-prisma-types: command not found
and removing that one and subbing in prisma-zod-generator i get:
Running generate... (Use --skip-generate to skip the generators)
Error: Generator at prisma-zod-generator could not start:

/bin/sh: prisma-zod-generator: command not found
Running generate... (Use --skip-generate to skip the generators)
Error: Generator at prisma-zod-generator could not start:

/bin/sh: prisma-zod-generator: command not found
have a feeling this has to do with my t3 install anyone have any idea how to debug?
13 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 3/21/2023 in #questions
chrome-launcher wont launch
It's kind of outside t3 scope but im hoping i can get some help here - the error is happening in my t3 app I'm using node to run lighthouse and chrome launcher wont launch in my dev env (mac monterey), with a t3 app It seems like there's something wrong with the dependency - (but typescript compiles) I think maybe it cant find chrome? But google chrome at /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome which google-chrome returns not found
import ChromeLauncher from "chrome-launcher";

const chromeOptions = {
chromeFlags: ["--headless", "--disable-gpu"],
};

async function launchChrome() {
try {
const chrome = await ChromeLauncher.launch(chromeOptions);
console.log("chrome running!");
return chrome;
} catch (e) {
console.log("**** Chrome failed to launch", e);
debugger; // always land here.
throw e;
}
}
import ChromeLauncher from "chrome-launcher";

const chromeOptions = {
chromeFlags: ["--headless", "--disable-gpu"],
};

async function launchChrome() {
try {
const chrome = await ChromeLauncher.launch(chromeOptions);
console.log("chrome running!");
return chrome;
} catch (e) {
console.log("**** Chrome failed to launch", e);
debugger; // always land here.
throw e;
}
}
error:
**** Chrome failed to launch TypeError: Cannot read properties of undefined (reading 'launch')
at launchChrome (webpack-internal:///(api)/./src/server/reporting/lighthouseRunner.ts:35:84)
**** Chrome failed to launch TypeError: Cannot read properties of undefined (reading 'launch')
at launchChrome (webpack-internal:///(api)/./src/server/reporting/lighthouseRunner.ts:35:84)
I tried: - Adding this to my env CHROME_PATH="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
- Adding and removing chrome-launcher from package.json dependancies, deleting node_modules and reinstalling all "chrome-launcher": "^0.15.1",
- Making a symlink from Google\ Chrome to google-chrome (it wouldn't run from the terminal) - Copying Google\ Chrome to google-chrome, now it's in the path and launches with a warning (below) but chrome-launcher still doesnt launch ``` $ google-chrome [41560:259:0321/104228.826676:ERROR:keychain_password_mac.mm(103)] Keychain lookup failed: Error Domain=NSOSStatusErrorDomain Code=-25293 "errKCAuthFailed / errSecAuthFailed: / Authorization/Authentication failed." (-25293) Opening in existing browser session.
2 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 3/17/2023 in #questions
Help with (new) monorepo tsconfig
Ive just started merging two codebases into a monorepo basically i have FM and reporting we have a /tsconfig.json (in FM) and a /reporting/tsconfig.json after merging all the /reporting tests passed, but then after updating the prisma.schema in /prisma/prisma.schema the reporting tests started to fail both of these tsconfigs had
"paths": {
"src/*": ["./src/*"],
}
"paths": {
"src/*": ["./src/*"],
}
and a prisma client importing "src/prisma" i've now moved /reporting/src to reporting/code and done a replace all on "src/" to "code/" and then changed all the "code/prisma" references to "src/prisma" so that we should be referencing FM's prisma client but the paths in tsconifg are not resolving the way i expect...
47 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 3/14/2023 in #questions
Two repos one Prisma. Lets Merge.
Good morning guys. I just started merging two repos into a Monorepo and have no idea what im doing :-). Would love some help. I have two repos, FM and LH. FM is t3-app and LH is basically pure ts-node. They share a prisma instance. I just copied the whole LH into FM as a subdirectory. Nothing changed in the FM git status. Should i delete the .git from the LH repo to see updates into the FM repo? And delete the /FM/LH/prisma directory? Since i want /FM/prisma to be canonical?
Also now i have two jest configs, two ts configs, two package.json's, two node_modules and two sets of env...
6 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 2/20/2023 in #questions
should i just make a REST api for that?
9 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 2/14/2023 in #questions
Inviting a teammate with nextAuth
Hi guys, in [...nextAuth], the email provider is working nicely:
EmailProvider({
sendVerificationRequest(params: SendVerificationRequestParams) {
const { identifier: email, url, expires } = params;
const newParams = { ...mailjetParams, email, url };
newParams.email = params.identifier;
sendEmailWithMailjet(newParams as SendWithMailjetProps);
},
}),
EmailProvider({
sendVerificationRequest(params: SendVerificationRequestParams) {
const { identifier: email, url, expires } = params;
const newParams = { ...mailjetParams, email, url };
newParams.email = params.identifier;
sendEmailWithMailjet(newParams as SendWithMailjetProps);
},
}),
Now i want to add invite team members functionality. How can I trigger this from the server side?
50 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 2/7/2023 in #questions
nextAuth - Add to the user model
https://next-auth.js.org/adapters/models Hello, I'd like to add modify the user before it comes into the session callback in [..nextauth]
callbacks: {
async session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
callbacks: {
async session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
I found this but the authorize method never gets called: https://stackoverflow.com/questions/71185287/pass-more-data-to-session-in-next-auth is it a bad idea to overoptimze this and i should just make an extra prisma call here?
24 replies
TTCTheo's Typesafe Cult
Created by fotoflo on 2/7/2023 in #questions
Noob Question Many-to-Many in prisma after nextAuth
Hello all! I'm trying to create my first many-to-many relationship in Prisma. schema:
model User {
id String @id @default(cuid())
teams usersInTeams[]
}

model Team {
id String @id @default(cuid())
name String @unique
slug String @unique
users usersInTeams[]
}

model usersInTeams {
userId String @db.VarChar(64)
teamId String @db.VarChar(64)
user User @relation(fields: [userId], references: [id])
team Team @relation(fields: [teamId], references: [id])
role String @default("USER")

@@id([userId, teamId])
}
model User {
id String @id @default(cuid())
teams usersInTeams[]
}

model Team {
id String @id @default(cuid())
name String @unique
slug String @unique
users usersInTeams[]
}

model usersInTeams {
userId String @db.VarChar(64)
teamId String @db.VarChar(64)
user User @relation(fields: [userId], references: [id])
team Team @relation(fields: [teamId], references: [id])
role String @default("USER")

@@id([userId, teamId])
}
export async function createTeam({ teamName, ownerId }: CreateTeamProps) {
try {
const team = await prisma.team.create({
data: {
name: teamName,
users: {
connect: [
{
userId_teamId: // the only type in intellesense, but it depends on a created team?
},
],
},
},
});

return team;
} catch (error) {
console.error(error);
return null;
}
}
export async function createTeam({ teamName, ownerId }: CreateTeamProps) {
try {
const team = await prisma.team.create({
data: {
name: teamName,
users: {
connect: [
{
userId_teamId: // the only type in intellesense, but it depends on a created team?
},
],
},
},
});

return team;
} catch (error) {
console.error(error);
return null;
}
}
but i cant for the life of me figure out how to write the createTeam() function - this is as close as i've gotten...
39 replies