utdev
utdev
Explore posts from servers
TTCTheo's Typesafe Cult
Created by utdev on 3/24/2024 in #questions
Nextjs image config?
I get this error:
Unhandled Runtime Error
Error: Invalid src prop (https://images.unsplash.com/photo-1441974231531-c6227db76b6e?q=80&w=2560&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D) on `next/image`, hostname "images.unsplash.com" is not configured under images in your `next.config.js`
See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
Unhandled Runtime Error
Error: Invalid src prop (https://images.unsplash.com/photo-1441974231531-c6227db76b6e?q=80&w=2560&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D) on `next/image`, hostname "images.unsplash.com" is not configured under images in your `next.config.js`
See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
What am I missing on the next.config.mjs:
import rehypePrism from '@mapbox/rehype-prism'
import nextMDX from '@next/mdx'
import remarkGfm from 'remark-gfm'

/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'mdx'],
}

const withMDX = nextMDX({
extension: /\.mdx?$/,
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [rehypePrism],
},
images: {
domains: ['images.unsplash.com']
}
})

export default withMDX(nextConfig)
import rehypePrism from '@mapbox/rehype-prism'
import nextMDX from '@next/mdx'
import remarkGfm from 'remark-gfm'

/** @type {import('next').NextConfig} */
const nextConfig = {
pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'mdx'],
}

const withMDX = nextMDX({
extension: /\.mdx?$/,
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [rehypePrism],
},
images: {
domains: ['images.unsplash.com']
}
})

export default withMDX(nextConfig)
4 replies
TTCTheo's Typesafe Cult
Created by utdev on 1/22/2024 in #questions
Check for string to not be empty?
Not sure why I am struggling with this right now:
const { gender, firstname, lastname, email, mobile } = recipientData;

if (
gender === undefined ||
gender === null ||
firstname === undefined ||
firstname === null ||
lastname === undefined ||
lastname === null ||
((email === undefined || email === null) &&
(mobile === undefined || mobile === null))
) {
throw new ResponseError("missing_data");
}
const { gender, firstname, lastname, email, mobile } = recipientData;

if (
gender === undefined ||
gender === null ||
firstname === undefined ||
firstname === null ||
lastname === undefined ||
lastname === null ||
((email === undefined || email === null) &&
(mobile === undefined || mobile === null))
) {
throw new ResponseError("missing_data");
}
Is there a better way of checking if the data is not set, unfortunatly I get the ResponseError if I pass empty strings.
7 replies
TTCTheo's Typesafe Cult
Created by utdev on 1/9/2024 in #questions
Nextjs 14 build issue
I get this weird error running the build command on next 14:
pnpm build

> what_zip@0.1.0 build /Users/utdev/code/what_zip
> next build

▲ Next.js 14.0.3
- Environments: .env

Failed to compile.

static/media/thread.2465a67c.js from Terser
x 'import', and 'export' cannot be used outside of module code
,-[1:1]
1 | import { Buffer } from "node:buffer";
: ^^^^^^
2 | import crypto from "node:crypto";
3 | import { parentPort } from "node:worker_threads";
4 | parentPort.on("message", (message)=>{
`----

Caused by:
0: failed to parse input file
1: Syntax Error
Error:
x 'import', and 'export' cannot be used outside of module code
,-[1:1]
1 | import { Buffer } from "node:buffer";
: ^^^^^^
2 | import crypto from "node:crypto";
3 | import { parentPort } from "node:worker_threads";
4 | parentPort.on("message", (message)=>{
`----

Caused by:
0: failed to parse input file
1: Syntax Error


> Build failed because of webpack errors
Creating an optimized production build . ELIFECYCLE  Command failed with exit code 1.
pnpm build

> what_zip@0.1.0 build /Users/utdev/code/what_zip
> next build

▲ Next.js 14.0.3
- Environments: .env

Failed to compile.

static/media/thread.2465a67c.js from Terser
x 'import', and 'export' cannot be used outside of module code
,-[1:1]
1 | import { Buffer } from "node:buffer";
: ^^^^^^
2 | import crypto from "node:crypto";
3 | import { parentPort } from "node:worker_threads";
4 | parentPort.on("message", (message)=>{
`----

Caused by:
0: failed to parse input file
1: Syntax Error
Error:
x 'import', and 'export' cannot be used outside of module code
,-[1:1]
1 | import { Buffer } from "node:buffer";
: ^^^^^^
2 | import crypto from "node:crypto";
3 | import { parentPort } from "node:worker_threads";
4 | parentPort.on("message", (message)=>{
`----

Caused by:
0: failed to parse input file
1: Syntax Error


> Build failed because of webpack errors
Creating an optimized production build . ELIFECYCLE  Command failed with exit code 1.
6 replies
TTCTheo's Typesafe Cult
Created by utdev on 1/7/2024 in #questions
Trigger button click on useEffect
I am trying to trigger my button so my Sheet shows up, but it currently does not work on refresh, if I log the sheet in my useEffect it correctly contains the node and it also goes inside the if condition:
"use client"

import { useEffect, useRef } from "react"
import { usePathname, useRouter, useSearchParams } from "next/navigation"

import { Button } from "@/components/ui/button"
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
import { DashboardOverview } from "@/components/overview"

export function DashboardSheet() {
const sheetButtonRef = useRef<HTMLButtonElement>(null)
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()

const handleOverviewRoute = () => {
router.push(`${pathname}?tab=overview`)
}

useEffect(() => {
if (searchParams.get("tab") === "overview" && sheetButtonRef.current) {
sheetButtonRef.current.click()
}
}, [pathname, router, searchParams, sheetButtonRef])

return (
<Sheet>
<SheetTrigger>
<Button ref={sheetButtonRef} onClick={handleOverviewRoute}>
Open Overview
</Button>
</SheetTrigger>
<SheetContent side="rightHalfFull" className="z-[1200]">
<SheetHeader>
<SheetTitle className="py-2">Overview</SheetTitle>
<SheetDescription>
<DashboardOverview />
</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
)
}
"use client"

import { useEffect, useRef } from "react"
import { usePathname, useRouter, useSearchParams } from "next/navigation"

import { Button } from "@/components/ui/button"
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
import { DashboardOverview } from "@/components/overview"

export function DashboardSheet() {
const sheetButtonRef = useRef<HTMLButtonElement>(null)
const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()

const handleOverviewRoute = () => {
router.push(`${pathname}?tab=overview`)
}

useEffect(() => {
if (searchParams.get("tab") === "overview" && sheetButtonRef.current) {
sheetButtonRef.current.click()
}
}, [pathname, router, searchParams, sheetButtonRef])

return (
<Sheet>
<SheetTrigger>
<Button ref={sheetButtonRef} onClick={handleOverviewRoute}>
Open Overview
</Button>
</SheetTrigger>
<SheetContent side="rightHalfFull" className="z-[1200]">
<SheetHeader>
<SheetTitle className="py-2">Overview</SheetTitle>
<SheetDescription>
<DashboardOverview />
</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
)
}
4 replies
TTCTheo's Typesafe Cult
Created by utdev on 1/7/2024 in #questions
Update route info on click
I have a button which opens a slider (sheet component) from the right side. I also would like to update the route once clicked on it, since I am not opening a page. Currently I am doing this on button click
const handleOverviewRoute = () => {
router.replace("/dashboard/overview")
}
const handleOverviewRoute = () => {
router.replace("/dashboard/overview")
}
But that does not quiet work, it does not open the sheet anymore, seems like it tries to go to the page. How can I make this work? Also what do you think of this behavior is it fine to update the route even if I am not changing the path?
11 replies
TTCTheo's Typesafe Cult
Created by utdev on 12/11/2023 in #questions
VsCode use path defined in tsconfig paths?
Is there a way that Vscode automatically imports the files using the paths defined in my tsconfig?
"paths": {
"@/ui/*": [
"./src/components/ui/*"
],
"@/components/*": [
"./src/components/*"
],
"@/store/*": [
"./src/lib/store/*"
],
"@/*": [
"./src/*"
],
},
"paths": {
"@/ui/*": [
"./src/components/ui/*"
],
"@/components/*": [
"./src/components/*"
],
"@/store/*": [
"./src/lib/store/*"
],
"@/*": [
"./src/*"
],
},
It currently does not work and it imports paths like this:
import { UserNav } from "../user/user-nav";
import { UserNav } from "../user/user-nav";
I always have to update them manually in order to get this:
import { UserNav } from "@/components/user/user-nav";
import { UserNav } from "@/components/user/user-nav";
2 replies
TTCTheo's Typesafe Cult
Created by utdev on 12/10/2023 in #questions
Serial postgres issue
Anyone have this issue?
> tsx src/lib/db/migrate.ts

⏳ Running migrations...
❌ Migration failed
NeonDbError: db error: ERROR: type "serial" does not exist

Caused by:
ERROR: type "serial" does not exist
> tsx src/lib/db/migrate.ts

⏳ Running migrations...
❌ Migration failed
NeonDbError: db error: ERROR: type "serial" does not exist

Caused by:
ERROR: type "serial" does not exist
Shouldn't serial work? I am doing this
import { varchar, text, boolean, integer, serial, pgTable, uniqueIndex } from "drizzle-orm/pg-core";

export const spaces = pgTable('spaces', {
id: serial("id").primaryKey(),
title: varchar("title", { length: 256 }).notNull(),
description: text("description").notNull(),
active: boolean("active").notNull(),
numberOfMembers: integer("number_of_members").notNull(),
userId: varchar("user_id", { length: 15 }).references(() => users.id, { onDelete: "cascade" }).notNull(),
}, (spaces) => {
return {
titleIndex: uniqueIndex('title_idx').on(spaces.title),
}
});
import { varchar, text, boolean, integer, serial, pgTable, uniqueIndex } from "drizzle-orm/pg-core";

export const spaces = pgTable('spaces', {
id: serial("id").primaryKey(),
title: varchar("title", { length: 256 }).notNull(),
description: text("description").notNull(),
active: boolean("active").notNull(),
numberOfMembers: integer("number_of_members").notNull(),
userId: varchar("user_id", { length: 15 }).references(() => users.id, { onDelete: "cascade" }).notNull(),
}, (spaces) => {
return {
titleIndex: uniqueIndex('title_idx').on(spaces.title),
}
});
2 replies
TTCTheo's Typesafe Cult
Created by utdev on 10/9/2023 in #questions
Should I use Promise.all? When should I use it
Hi I am not sure if I should use a promise all in a case like this:
const userMessage = await Message.create()
const messages = await Session.get();
const userMessage = await Message.create()
const messages = await Session.get();
Does it make sense to use it here?
6 replies
TTCTheo's Typesafe Cult
Created by utdev on 7/29/2023 in #questions
turbo repo package not found
I added a new turborepo package in my turbo repo repository, but I get this error:
Failed to compile
../../packages/api/src/router/document.ts:1:0
Module not found: Can't resolve '@acme/validation'
> 1 | import { getDocumentByIdSchema, getDocumentByUserIdSchema } from '@acme/validation';
2 | import {
3 | GetObjectCommand,
4 | S3Client

Import trace for requested module:
../../packages/api/src/router/index.ts
../../packages/api/index.ts
./src/pages/api/trpc/[trpc].ts

https://nextjs.org/docs/messages/module-not-found
This error occurred during the build process and can only be dismissed by fixing the error.
Failed to compile
../../packages/api/src/router/document.ts:1:0
Module not found: Can't resolve '@acme/validation'
> 1 | import { getDocumentByIdSchema, getDocumentByUserIdSchema } from '@acme/validation';
2 | import {
3 | GetObjectCommand,
4 | S3Client

Import trace for requested module:
../../packages/api/src/router/index.ts
../../packages/api/index.ts
./src/pages/api/trpc/[trpc].ts

https://nextjs.org/docs/messages/module-not-found
This error occurred during the build process and can only be dismissed by fixing the error.
I added the @acme/validation package. It contains an index.ts file which exports all files inside /src.
export * from './'
export * from './'
Do I need to update anything else?
3 replies
TTCTheo's Typesafe Cult
Created by utdev on 7/16/2023 in #questions
Help adding trpc-openapi to t3 app
Hi, can anyone help adding https://github.com/jlalmes/trpc-openapi properly to my existing t3 app? So far I have this
import { generateOpenApiDocument } from 'trpc-openapi';
import { appRouter } from './root';

export const openApiDocument = generateOpenApiDocument(appRouter, {
title: 'tRPC OpenAPI - test',
version: '1.0.0',
baseUrl: 'http://localhost:3000/api',
});
import { generateOpenApiDocument } from 'trpc-openapi';
import { appRouter } from './root';

export const openApiDocument = generateOpenApiDocument(appRouter, {
title: 'tRPC OpenAPI - test',
version: '1.0.0',
baseUrl: 'http://localhost:3000/api',
});
Here: server/api/openapi.ts And I added this sayHello example route to my router:
import { documentRouter } from "@/server/api/routers/document";
import { favoriteRouter } from "@/server/api/routers/favorite";
import { messageRouter } from "@/server/api/routers/message";
import { realEstateRouter } from '@/server/api/routers/real-estate';
import { userActivityRouter } from '@/server/api/routers/user-activity';
import { z } from "zod";
import { router, t } from './trpc';


/**
* This is the primary router for your server.
*
* All routers added in /api/routers should be manually added here.
*/
export const appRouter = router({
realEstate: realEstateRouter,
document: documentRouter,
userActivity: userActivityRouter,
message: messageRouter,
favorite: favoriteRouter,
sayHello: t.procedure
.meta({ /* 👉 */ openapi: { method: 'GET', path: '/say-hello' } })
.input(z.object({ name: z.string() }))
.output(z.object({ greeting: z.string() }))
.query(({ input }) => {
return { greeting: `Hello ${input.name}!` };
}),
});

export type AppRouter = typeof appRouter;
import { documentRouter } from "@/server/api/routers/document";
import { favoriteRouter } from "@/server/api/routers/favorite";
import { messageRouter } from "@/server/api/routers/message";
import { realEstateRouter } from '@/server/api/routers/real-estate';
import { userActivityRouter } from '@/server/api/routers/user-activity';
import { z } from "zod";
import { router, t } from './trpc';


/**
* This is the primary router for your server.
*
* All routers added in /api/routers should be manually added here.
*/
export const appRouter = router({
realEstate: realEstateRouter,
document: documentRouter,
userActivity: userActivityRouter,
message: messageRouter,
favorite: favoriteRouter,
sayHello: t.procedure
.meta({ /* 👉 */ openapi: { method: 'GET', path: '/say-hello' } })
.input(z.object({ name: z.string() }))
.output(z.object({ greeting: z.string() }))
.query(({ input }) => {
return { greeting: `Hello ${input.name}!` };
}),
});

export type AppRouter = typeof appRouter;
But I am confused, how I should resume and actually start it
20 replies
TTCTheo's Typesafe Cult
Created by utdev on 6/16/2023 in #questions
Call route within route in server
How can I call a route in a different route. For example I have this route:
export const realEstateRouter = router({
create: protectedProcedure
.input(createRealEstateSchema)
.mutation(async ({ ctx, input }) => {
...
export const realEstateRouter = router({
create: protectedProcedure
.input(createRealEstateSchema)
.mutation(async ({ ctx, input }) => {
...
I want to call that create function in a different route like this:
import { createUserActivitySchema } from "@/validation/user-activity";
import { protectedProcedure, router } from './../trpc';

export const userActivityRouter = router({
create: protectedProcedure
.input(createUserActivitySchema)
.query(async ({ ctx, input }) => {

const userId = ctx.auth.userId;

if (!userId) throw new Error('User is not authenticated');

const result = await ctx.prisma.userActivity.create({
data: {
...input,
user: {
connect: {
userId: userId
}
}
}
})

return result;
}),
});
import { createUserActivitySchema } from "@/validation/user-activity";
import { protectedProcedure, router } from './../trpc';

export const userActivityRouter = router({
create: protectedProcedure
.input(createUserActivitySchema)
.query(async ({ ctx, input }) => {

const userId = ctx.auth.userId;

if (!userId) throw new Error('User is not authenticated');

const result = await ctx.prisma.userActivity.create({
data: {
...input,
user: {
connect: {
userId: userId
}
}
}
})

return result;
}),
});
But that does not work, any ideas?
6 replies
TTCTheo's Typesafe Cult
Created by utdev on 6/4/2023 in #questions
useMutation param syntax
Hi guys, I forgot how to add specific params / input to my useMutation, how can I do that for example here:
const { isLoading, mutate, error, isSuccess } =
api.realEstate.updateStatus.useMutation();
const { isLoading, mutate, error, isSuccess } =
api.realEstate.updateStatus.useMutation();
6 replies
TTCTheo's Typesafe Cult
Created by utdev on 5/27/2023 in #questions
Prisma zod enum validation
I have this prisma schema:
enum RealEstateType {
house
apartment
office
garage
land
store
industry
other
}
...
model RealEstate {
id Int @id @default(autoincrement())
status RealEstateStatus
title String
description String
availableFrom DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId String
user UserData @relation(fields: [userId], references: [userId])
type RealEstateType
contactId String?
contact UserData? @relation(name: "RealEstateContact", fields: [contactId], references: [userId])
favorites Favorite[]
Message Message[]
documents Document[]
energy EnergyEfficiency[]
location RealEstateLocation?
features RealEstateFeatures?
pricing RealEstatePricing?

@@index([userId])
@@index([contactId])
}
enum RealEstateType {
house
apartment
office
garage
land
store
industry
other
}
...
model RealEstate {
id Int @id @default(autoincrement())
status RealEstateStatus
title String
description String
availableFrom DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
userId String
user UserData @relation(fields: [userId], references: [userId])
type RealEstateType
contactId String?
contact UserData? @relation(name: "RealEstateContact", fields: [contactId], references: [userId])
favorites Favorite[]
Message Message[]
documents Document[]
energy EnergyEfficiency[]
location RealEstateLocation?
features RealEstateFeatures?
pricing RealEstatePricing?

@@index([userId])
@@index([contactId])
}
And this zod validation:
const apartmentTypes = [
'house',
'apartment',
'office',
'garage',
'land',
'store',
'industry',
'other'
] as const;

export const createRealEstateSchema = z.object({
type: z.enum(apartmentTypes),
title: z.string().min(3).max(30),
description: z.string().min(3).max(30),
availableFrom: z.date(),
contactId: z.string().optional(),
location: locationSchema.optional(),
features: featuresSchema.optional(),
pricing: pricingSchema.optional(),
documents: z.array(createDocumentSchema),
});
const apartmentTypes = [
'house',
'apartment',
'office',
'garage',
'land',
'store',
'industry',
'other'
] as const;

export const createRealEstateSchema = z.object({
type: z.enum(apartmentTypes),
title: z.string().min(3).max(30),
description: z.string().min(3).max(30),
availableFrom: z.date(),
contactId: z.string().optional(),
location: locationSchema.optional(),
features: featuresSchema.optional(),
pricing: pricingSchema.optional(),
documents: z.array(createDocumentSchema),
});
5 replies
TTCTheo's Typesafe Cult
Created by utdev on 5/14/2023 in #questions
S3 File Upload
Anyone got an idea what I am missing here: And this is my api route:
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { randomUUID } from 'crypto';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const accountid = process.env.CLOUDFLARE_ACCOUNT_ID

const s3 = new S3Client({
endpoint: `https://${accountid}.r2.cloudflarestorage.com`,
region: process.env.R2_REGION,
credentials: {
accessKeyId: process.env.WRITE_CLOUDFLARE_R2_ACCESS_KEY_ID!,
secretAccessKey: process.env.WRITE_CLOUDFLARE_R2_SECRET_ACCESS_KEY!,
}
})

// Check if the file is present in the request body
if (!req.body || !req.body.file) {
throw new Error('No file data found in the request');
}

console.log("api file upload", req.body.file)

// Get the file content and filename from the request
const file = req.body.file; // Assuming the uploaded file is in a 'file' field in the form-data
const fileContent = file.buffer;
const filename = file.name;

const uniqueName = `${randomUUID()}-${filename}`
const conditions = [['content-length-range', 0, 10485760]]


// Prepare the parameters for the S3 PutObjectCommand
const params = {
Bucket: 'test',
Key: uniqueName,
Body: fileContent,
};
const command = new PutObjectCommand(params);
await s3.send(command);
res.status(200).json({ message: 'File uploaded successfully' });
} catch (error) {
console.error('Error uploading file to S3:', error);
res.status(500).json({ message: 'Error uploading file to S3' });
}
}
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { randomUUID } from 'crypto';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
const accountid = process.env.CLOUDFLARE_ACCOUNT_ID

const s3 = new S3Client({
endpoint: `https://${accountid}.r2.cloudflarestorage.com`,
region: process.env.R2_REGION,
credentials: {
accessKeyId: process.env.WRITE_CLOUDFLARE_R2_ACCESS_KEY_ID!,
secretAccessKey: process.env.WRITE_CLOUDFLARE_R2_SECRET_ACCESS_KEY!,
}
})

// Check if the file is present in the request body
if (!req.body || !req.body.file) {
throw new Error('No file data found in the request');
}

console.log("api file upload", req.body.file)

// Get the file content and filename from the request
const file = req.body.file; // Assuming the uploaded file is in a 'file' field in the form-data
const fileContent = file.buffer;
const filename = file.name;

const uniqueName = `${randomUUID()}-${filename}`
const conditions = [['content-length-range', 0, 10485760]]


// Prepare the parameters for the S3 PutObjectCommand
const params = {
Bucket: 'test',
Key: uniqueName,
Body: fileContent,
};
const command = new PutObjectCommand(params);
await s3.send(command);
res.status(200).json({ message: 'File uploaded successfully' });
} catch (error) {
console.error('Error uploading file to S3:', error);
res.status(500).json({ message: 'Error uploading file to S3' });
}
}
But my req.body keeps returning undefined, any ideas? I am using the v3 package: aws-sdk/client-s3
4 replies
TTCTheo's Typesafe Cult
Created by utdev on 4/6/2023 in #questions
Deploying on Vercel, tailwind classes missing?
Does anyone have issues with deploying on vercel? Right now my app is deployed but my tailwind classes have no value, which is why my page looks wrong. Locally it looks fine with the dev and build command
46 replies
TTCTheo's Typesafe Cult
Created by utdev on 3/25/2023 in #questions
Invalid environment variables
I have following env var in my .env file: NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=xxx In my schema.mjs I have following:
export const clientSchema = z.object({
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string(),
})
export const clientSchema = z.object({
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string(),
})
and my client.mjs looks like this:
// @ts-check
import { clientSchema } from './schema.mjs'

/**
* You can't destruct `process.env` as a regular object, so we do
* a workaround. This is because Next.js evaluates this at build time,
* and only used environment variables are included in the build.
* @type {{ [key: string]: string | undefined; }}
*/
let clientEnv = {}
Object.keys(clientSchema.shape).forEach(
(key) => (clientEnv[key] = process.env[key]),
)

const _clientEnv = clientSchema.safeParse(clientEnv)

export const formatErrors = (
/** @type {import('zod').ZodFormattedError<Map<string,string>,string>} */
errors,
) =>
Object.entries(errors)
.map(([name, value]) => {
if (value && '_errors' in value)
return `${name}: ${value._errors.join(', ')}\n`
})
.filter(Boolean)

if (!_clientEnv.success) {
console.error(
'❌ Invalid environment variables:\n',
...formatErrors(_clientEnv.error.format()),
)
throw new Error('Invalid environment variables')
}

for (let key of Object.keys(_clientEnv.data)) {
if (!key.startsWith('NEXT_PUBLIC_')) {
console.warn(
`❌ Invalid public environment variable name: ${key}. It must begin with 'NEXT_PUBLIC_'`,
)

throw new Error('Invalid public environment variable name')
}
}

export const env = _clientEnv.data
// @ts-check
import { clientSchema } from './schema.mjs'

/**
* You can't destruct `process.env` as a regular object, so we do
* a workaround. This is because Next.js evaluates this at build time,
* and only used environment variables are included in the build.
* @type {{ [key: string]: string | undefined; }}
*/
let clientEnv = {}
Object.keys(clientSchema.shape).forEach(
(key) => (clientEnv[key] = process.env[key]),
)

const _clientEnv = clientSchema.safeParse(clientEnv)

export const formatErrors = (
/** @type {import('zod').ZodFormattedError<Map<string,string>,string>} */
errors,
) =>
Object.entries(errors)
.map(([name, value]) => {
if (value && '_errors' in value)
return `${name}: ${value._errors.join(', ')}\n`
})
.filter(Boolean)

if (!_clientEnv.success) {
console.error(
'❌ Invalid environment variables:\n',
...formatErrors(_clientEnv.error.format()),
)
throw new Error('Invalid environment variables')
}

for (let key of Object.keys(_clientEnv.data)) {
if (!key.startsWith('NEXT_PUBLIC_')) {
console.warn(
`❌ Invalid public environment variable name: ${key}. It must begin with 'NEXT_PUBLIC_'`,
)

throw new Error('Invalid public environment variable name')
}
}

export const env = _clientEnv.data
But I get this error:
Unhandled Runtime Error
Error: Invalid environment variables

Source
src/env/client.mjs (33:8) @ eval

31 | ...formatErrors(_clientEnv.error.format()),
32 | )
> 33 | throw new Error('Invalid environment variables')
| ^
34 | }
35 |
36 | for (let key of Object.keys(_clientEnv.data)) {
Unhandled Runtime Error
Error: Invalid environment variables

Source
src/env/client.mjs (33:8) @ eval

31 | ...formatErrors(_clientEnv.error.format()),
32 | )
> 33 | throw new Error('Invalid environment variables')
| ^
34 | }
35 |
36 | for (let key of Object.keys(_clientEnv.data)) {
2 replies
TTCTheo's Typesafe Cult
Created by utdev on 3/9/2023 in #questions
react-hydration-error using different browser?
I am trying a different browser right now called Sidekick, accessing my localhost returns this error:
Error: Hydration failed because the initial UI does not match what was rendered on the server.

See more info here: https://nextjs.org/docs/messages/react-hydration-error
Error: Hydration failed because the initial UI does not match what was rendered on the server.

See more info here: https://nextjs.org/docs/messages/react-hydration-error
I was kind of confused since it worked earlier so I tried it again on chrome. Seems like the app works fine on chrome but not on sidekick. Is this really related to the browser?
23 replies
TTCTheo's Typesafe Cult
Created by utdev on 3/4/2023 in #questions
Prisma schema delete many to many
Hi, I have some troubles deleting a many to many relationship / data. Currently it says:
prisma:error
Invalid `prisma.templateTag.deleteMany()` invocation:


Foreign key constraint failed on the field: `TagsOnTemplate_tagId_fkey (index)`
❌ tRPC failed on template.delete:
Invalid `prisma.templateTag.deleteMany()` invocation:


Foreign key constraint failed on the field: `TagsOnTemplate_tagId_fkey (index)`
prisma:error
Invalid `prisma.templateTag.deleteMany()` invocation:


Foreign key constraint failed on the field: `TagsOnTemplate_tagId_fkey (index)`
❌ tRPC failed on template.delete:
Invalid `prisma.templateTag.deleteMany()` invocation:


Foreign key constraint failed on the field: `TagsOnTemplate_tagId_fkey (index)`
This is the related schema:
model TemplateTag {
id String @id @default(cuid())
tag String @unique
templates TagsOnTemplate[]
}

model Template {
id String @id @default(cuid())
name String
description String?
visibility String @default("private")
filename String
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
tags TagsOnTemplate[]
}

model TagsOnTemplate {
id String @id @default(cuid())
template Template @relation(fields: [templateId], references: [id])
templateId String
tag TemplateTag @relation(fields: [tagId], references: [id])
tagId String
}
model TemplateTag {
id String @id @default(cuid())
tag String @unique
templates TagsOnTemplate[]
}

model Template {
id String @id @default(cuid())
name String
description String?
visibility String @default("private")
filename String
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
tags TagsOnTemplate[]
}

model TagsOnTemplate {
id String @id @default(cuid())
template Template @relation(fields: [templateId], references: [id])
templateId String
tag TemplateTag @relation(fields: [tagId], references: [id])
tagId String
}
4 replies
TTCTheo's Typesafe Cult
Created by utdev on 2/21/2023 in #questions
NextAuth credentials how to handle unauthorized user?
I have this parent component which distinguishes if the user is logged in or not and redirect the user in the specific case. I signed in to my app and deleted all my storage and cookie data which would result me being unauthorized. But the redirect / condition does not work properly in this component:
import { useSession } from 'next-auth/react'
import { AppType } from 'next/dist/shared/lib/utils'
import { MainLayout } from './main-layouts'

enum AuthStates {
AUTHENTICATED = 'authenticated',
UNAUTHENTICATED = 'unauthenticated',
}

const ChooseLayout: AppType = ({
Component,
pageProps: { ...pageProps },
...rest
}) => {
const { status, data } = useSession({
required: true,
onUnauthenticated() {
router.push('/sign-in')
},
})
const { router } = rest

console.log('status', status)

if (status === AuthStates.UNAUTHENTICATED) {
return <Component {...pageProps} {...rest} key={router.asPath} />
}

// Authenticated
return (
<MainLayout>
<Component {...pageProps} {...rest} key={router.asPath} />
</MainLayout>
)
}

export default ChooseLayout
import { useSession } from 'next-auth/react'
import { AppType } from 'next/dist/shared/lib/utils'
import { MainLayout } from './main-layouts'

enum AuthStates {
AUTHENTICATED = 'authenticated',
UNAUTHENTICATED = 'unauthenticated',
}

const ChooseLayout: AppType = ({
Component,
pageProps: { ...pageProps },
...rest
}) => {
const { status, data } = useSession({
required: true,
onUnauthenticated() {
router.push('/sign-in')
},
})
const { router } = rest

console.log('status', status)

if (status === AuthStates.UNAUTHENTICATED) {
return <Component {...pageProps} {...rest} key={router.asPath} />
}

// Authenticated
return (
<MainLayout>
<Component {...pageProps} {...rest} key={router.asPath} />
</MainLayout>
)
}

export default ChooseLayout
console.log('status', status) keeps returning loading why? How can I properly handle this?
16 replies