caleb
caleb
TTCTheo's Typesafe Cult
Created by Bored Student on 2/10/2025 in #questions
Nest.js CLI not working
pnpm vs pnpx is actually frustrating sometimes. i also have better luck using pnpm dlx instead of pnpx
7 replies
TTCTheo's Typesafe Cult
Created by greypixel on 2/4/2025 in #questions
Images w/ next & vercel
I assume you're just using this image in one place in your site?
11 replies
TTCTheo's Typesafe Cult
Created by greypixel on 2/4/2025 in #questions
Images w/ next & vercel
Hey man! I have a couple points Next highly recommends not using the vanilla <img> element but the built-in <Image> component they provide. This handles size optimization for different screen sizes and device speeds. It is also a good practice to use a CDN for images, however particularly for larger and more images. And yes, when you import and set an image the way you're doing it it grabs the image's data and puts it into the <img> element.
11 replies
TTCTheo's Typesafe Cult
Created by caleb on 1/6/2025 in #questions
Jose DataError: HMAC key data must not be empty
I made sure jwt and secret are both set. I even logged it to make sure
7 replies
TTCTheo's Typesafe Cult
Created by caleb on 1/6/2025 in #questions
Jose DataError: HMAC key data must not be empty
I verified that jwt and secret in the providers code are not null or blank, which is what it looks like the error I'm getting would be caused by. I also confirmed they're the exact same from when the JWT is being signed.
7 replies
TTCTheo's Typesafe Cult
Created by caleb on 1/6/2025 in #questions
Jose DataError: HMAC key data must not be empty
I was using middleware to parse and validate the auth cookie but needed to use Prisma. I had issues adding Prisma to edge runtime so I instead moved it over to my providers.tsx file. Discord isn't letting me post the code for some reason so here's a Hastebin link with the providers code: https://hastebin.com/share/enomewaken.javascript
7 replies
TTCTheo's Typesafe Cult
Created by caleb on 1/6/2025 in #questions
Jose DataError: HMAC key data must not be empty
Here's the /src/app/api/sign/route.ts file:
import { NextResponse } from 'next/server'
import { api } from '~/trpc/server'
import * as jose from 'jose'
import { env } from '~/env'

export async function GET(req: Request, { params }: { params: { token: string } }) {
const token = params.token

const { message } = await api.authentication.verifyUserAuthenticationTokenCode({ token })

if (message === 'not_found') {
return NextResponse.redirect(new URL('/signin?message=code_not_found', req.url))
} else if (message === 'expired') {
return NextResponse.redirect(new URL('/signin?message=code_expired', req.url))
} else if (message === 'verified') {
const secret = new TextEncoder().encode(env.JWT_SECRET)

const user = await api.user.getUserByAuthToken({ token })

if (!user) {
return NextResponse.redirect(new URL('/signin?message=user_not_found', req.url))
}

const jwt = await new jose.SignJWT().setProtectedHeader({ alg: 'HS256' }).setIssuedAt().setIssuer('urn:caaampus:issuer').setAudience('urn:caaampus:audience').setSubject(JSON.stringify(user.id)).setExpirationTime('72h').sign(secret)

const response = NextResponse.redirect(new URL('/profile', req.url))
response.cookies.set('Authorization', jwt, {
httpOnly: true,
secure: true,
sameSite: 'strict',
path: '/',
expires: new Date(Date.now() + 72 * 60 * 60 * 1000)
})

return response
}
}
import { NextResponse } from 'next/server'
import { api } from '~/trpc/server'
import * as jose from 'jose'
import { env } from '~/env'

export async function GET(req: Request, { params }: { params: { token: string } }) {
const token = params.token

const { message } = await api.authentication.verifyUserAuthenticationTokenCode({ token })

if (message === 'not_found') {
return NextResponse.redirect(new URL('/signin?message=code_not_found', req.url))
} else if (message === 'expired') {
return NextResponse.redirect(new URL('/signin?message=code_expired', req.url))
} else if (message === 'verified') {
const secret = new TextEncoder().encode(env.JWT_SECRET)

const user = await api.user.getUserByAuthToken({ token })

if (!user) {
return NextResponse.redirect(new URL('/signin?message=user_not_found', req.url))
}

const jwt = await new jose.SignJWT().setProtectedHeader({ alg: 'HS256' }).setIssuedAt().setIssuer('urn:caaampus:issuer').setAudience('urn:caaampus:audience').setSubject(JSON.stringify(user.id)).setExpirationTime('72h').sign(secret)

const response = NextResponse.redirect(new URL('/profile', req.url))
response.cookies.set('Authorization', jwt, {
httpOnly: true,
secure: true,
sameSite: 'strict',
path: '/',
expires: new Date(Date.now() + 72 * 60 * 60 * 1000)
})

return response
}
}
7 replies