From 2ed21f26d3ccd9b3c6b829c4af01ec6f5e93e68f Mon Sep 17 00:00:00 2001 From: "Sebastian \"Sebbie\" Silbermann" Date: Tue, 20 Jan 2026 11:33:55 +0100 Subject: [PATCH 1/3] [ci] Ensure Turbo Remote Cache can be written to (#88794) --- .github/workflows/build_reusable.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_reusable.yml b/.github/workflows/build_reusable.yml index e3e57f32df118..9a2f4c796f661 100644 --- a/.github/workflows/build_reusable.yml +++ b/.github/workflows/build_reusable.yml @@ -95,9 +95,9 @@ env: # disable backtrace for test snapshots RUST_BACKTRACE: 0 - TURBO_TEAM: 'vercel' + TURBO_TEAM: 'vtest314-next-e2e-tests' TURBO_CACHE: 'remote:rw' - TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} + TURBO_TOKEN: ${{ secrets.TURBO_REMOTE_CACHE_TOKEN }} NEXT_TELEMETRY_DISABLED: 1 # allow not skipping install-native postinstall script if we don't have a binary available already From 70d357a3ea87f9910248dc1bede8aacceb0fb940 Mon Sep 17 00:00:00 2001 From: Simeon Griggs Date: Tue, 20 Jan 2026 11:16:44 +0000 Subject: [PATCH 2/3] Update with-mysql example to Next.js 15, Tailwind 4, Prisma 7 (#88475) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Updates the `with-mysql` example to use latest versions of all dependencies. ### What - Migrate from Pages Router to App Router - Update to React 19 and Next.js latest - Update to Tailwind CSS v4 with `@import "tailwindcss"` syntax - Update to Prisma 7 with `@prisma/adapter-planetscale` driver adapter - Convert all files to TypeScript - Remove unused API route and `vercel.svg` - Update README to clarify this is for PlanetScale MySQL and link to [vercel/postgres-next-starter](https://github.com/vercel/postgres-next-starter) for Postgres users ### Why The example was significantly outdated: - Prisma 3.10.0 → Prisma 7 (latest) - Tailwind 3.0.23 → Tailwind 4 - React 18.2.0 → React 19 - Pages Router → App Router ### How Followed the official migration guides: - [Prisma 7 upgrade guide](https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-7) - [PlanetScale quickstart with Prisma](https://www.prisma.io/docs/getting-started/prisma-orm/quickstart/planetscale) - Aligned configuration files with a fresh `create-next-app` output ## Related N/A ## How to Test ```bash cd examples/with-mysql npm install # Set up .env with your PlanetScale DATABASE_URL npx prisma generate npx prisma db push npx prisma db seed npm run dev ``` ## Checklist - [x] Tests and samples are included - [x] Documentation is updated (README) --------- Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com> --- examples/with-mysql/.gitignore | 7 +- examples/with-mysql/README.md | 67 +++++++++---------- examples/with-mysql/app/globals.css | 1 + examples/with-mysql/app/layout.tsx | 19 ++++++ examples/with-mysql/app/page.tsx | 24 +++++++ examples/with-mysql/components/Product.js | 31 --------- examples/with-mysql/components/Product.tsx | 37 ++++++++++ examples/with-mysql/lib/prisma.js | 14 ---- examples/with-mysql/lib/prisma.ts | 21 ++++++ examples/with-mysql/next.config.js | 4 -- examples/with-mysql/next.config.ts | 7 ++ examples/with-mysql/package.json | 27 +++++--- examples/with-mysql/pages/_app.js | 5 -- examples/with-mysql/pages/api/products.js | 16 ----- examples/with-mysql/pages/index.js | 46 ------------- examples/with-mysql/postcss.config.js | 6 -- examples/with-mysql/postcss.config.mjs | 7 ++ examples/with-mysql/prisma.config.ts | 13 ++++ .../with-mysql/prisma/{data.js => data.ts} | 19 ++---- examples/with-mysql/prisma/schema.prisma | 33 +++++---- examples/with-mysql/prisma/seed.js | 36 ---------- examples/with-mysql/prisma/seed.ts | 49 ++++++++++++++ examples/with-mysql/public/vercel.svg | 4 -- examples/with-mysql/styles/globals.css | 3 - examples/with-mysql/tailwind.config.js | 11 --- examples/with-mysql/tsconfig.json | 27 ++++++++ 26 files changed, 283 insertions(+), 251 deletions(-) create mode 100644 examples/with-mysql/app/globals.css create mode 100644 examples/with-mysql/app/layout.tsx create mode 100644 examples/with-mysql/app/page.tsx delete mode 100644 examples/with-mysql/components/Product.js create mode 100644 examples/with-mysql/components/Product.tsx delete mode 100644 examples/with-mysql/lib/prisma.js create mode 100644 examples/with-mysql/lib/prisma.ts delete mode 100644 examples/with-mysql/next.config.js create mode 100644 examples/with-mysql/next.config.ts delete mode 100644 examples/with-mysql/pages/_app.js delete mode 100644 examples/with-mysql/pages/api/products.js delete mode 100644 examples/with-mysql/pages/index.js delete mode 100644 examples/with-mysql/postcss.config.js create mode 100644 examples/with-mysql/postcss.config.mjs create mode 100644 examples/with-mysql/prisma.config.ts rename examples/with-mysql/prisma/{data.js => data.ts} (81%) delete mode 100644 examples/with-mysql/prisma/seed.js create mode 100644 examples/with-mysql/prisma/seed.ts delete mode 100644 examples/with-mysql/public/vercel.svg delete mode 100644 examples/with-mysql/styles/globals.css delete mode 100644 examples/with-mysql/tailwind.config.js create mode 100644 examples/with-mysql/tsconfig.json diff --git a/examples/with-mysql/.gitignore b/examples/with-mysql/.gitignore index 8777267507c0e..24ecd608941c5 100644 --- a/examples/with-mysql/.gitignore +++ b/examples/with-mysql/.gitignore @@ -28,8 +28,10 @@ npm-debug.log* yarn-debug.log* yarn-error.log* +.pnpm-debug.log* -# local env files +# env files +.env .env*.local # vercel @@ -38,3 +40,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# prisma +/lib/generated/ diff --git a/examples/with-mysql/README.md b/examples/with-mysql/README.md index 93d7e1c857ba7..f1a41e22201a2 100644 --- a/examples/with-mysql/README.md +++ b/examples/with-mysql/README.md @@ -1,6 +1,8 @@ -# Next.js + MySQL +# Next.js + PlanetScale MySQL -This is a [Next.js](https://nextjs.org/) project that uses [Prisma](https://www.prisma.io/) to connect to a [PlanetScale](https://planetscale.com/) MySQL database and [Tailwind CSS](https://tailwindcss.com/) for styling. +This is a [Next.js](https://nextjs.org/) project that uses [Prisma](https://www.prisma.io/) to connect to a [PlanetScale MySQL database](https://planetscale.com/) and [Tailwind CSS](https://tailwindcss.com/) for styling. + +> **Using PlanetScale Postgres?** Check out the [Next.js and Postgres Starter Template](https://github.com/vercel/postgres-next-starter) for a PostgreSQL-based template. ## Demo @@ -16,24 +18,27 @@ https://next-mysql.vercel.app pscale auth login ``` -## Set up the database +## Set Up the Database Create a new database with the following command: ```sh -pscale database create +pscale database create --engine mysql ``` > A branch, `main`, was automatically created when you created your database, so you can use that for `BRANCH_NAME` in the steps below. -## Set up the starter Next.js app +## Set Up the Starter Next.js App -Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example: +Run [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with your preferred package manager to bootstrap the example: ```bash npx create-next-app --example with-mysql nextjs-mysql ``` +
+Or use yarn / pnpm / bun + ```bash yarn create next-app --example with-mysql nextjs-mysql ``` @@ -42,6 +47,12 @@ yarn create next-app --example with-mysql nextjs-mysql pnpm create next-app --example with-mysql nextjs-mysql ``` +```bash +bunx create-next-app --example with-mysql nextjs-mysql +``` + +
+ Next, you'll need to create a database username and password through the CLI to connect to your application. If you'd prefer to use the dashboard for this step, you can find those instructions in the [Connection Strings documentation](https://docs.planetscale.com/concepts/connection-strings#creating-a-password) and then come back here to finish setup. First, create your `.env` file by renaming the `.env.example` file to `.env`: @@ -61,12 +72,12 @@ pscale password create Take note of the values returned to you, as you won't be able to see this password again. ```text -Password production-password was successfully created. +Password was successfully created in . Please save the values below as they will not be shown again - NAME USERNAME ACCESS HOST URL ROLE PLAIN TEXT - --------------------- -------------- ----------------------------------- ------------------ ------------------------------------------------------- - production-password xxxxxxxxxxxxx xxxxxx.us-east-2.psdb.cloud Can Read & Write pscale_pw_xxxxxxx + NAME USERNAME ACCESS HOST URL ROLE PLAIN TEXT + ---------------- -------------- ----------------------------- ----------------- ----------------------------- + xxxxxxxxxxxxx xxxxxx.us-east-2.psdb.cloud Can Read & Write pscale_pw_xxxxxxx ``` You'll use these properties to construct your connection string, which will be the value for `DATABASE_URL` in your `.env` file. Update the `DATABASE_URL` property with your connection string in the following format: @@ -75,53 +86,35 @@ You'll use these properties to construct your connection string, which will be t mysql://:@/?sslaccept=strict ``` -Push the database schema to your PlanetScale database using Prisma. - -```bash -npx prisma db push -``` - -```bash -yarn prisma db push -``` +Generate the Prisma Client: ```bash -pnpm prisma +npx prisma generate ``` -Run the seed script to populate your database with `Product` and `Category` data. +Push the database schema to your PlanetScale database using Prisma: ```bash -npm run seed +npx prisma db push ``` -```bash -yarn seed -``` +Run the seed script to populate your database with `Product` and `Category` data: ```bash -pnpm seed +npx prisma db seed ``` ## Run the App -Run the app with following command: +Run the app with the following command: ```bash npm run dev ``` -```bash -yarn dev -``` - -```bash -pnpm dev -``` - -Open your browser at [localhost:3000](localhost:3000) to see the running application. +Open your browser at [localhost:3000](http://localhost:3000) to see the running application. -## Deploy your own +## Deploy Your Own After you've got your application running locally, it's time to deploy it. To do so, you'll need to promote your database branch (`main` by default) to be the production branch ([read the branching documentation for more information](https://docs.planetscale.com/concepts/branching)). diff --git a/examples/with-mysql/app/globals.css b/examples/with-mysql/app/globals.css new file mode 100644 index 0000000000000..f1d8c73cdcf9e --- /dev/null +++ b/examples/with-mysql/app/globals.css @@ -0,0 +1 @@ +@import "tailwindcss"; diff --git a/examples/with-mysql/app/layout.tsx b/examples/with-mysql/app/layout.tsx new file mode 100644 index 0000000000000..1c8a9a7815401 --- /dev/null +++ b/examples/with-mysql/app/layout.tsx @@ -0,0 +1,19 @@ +import type { Metadata } from "next"; +import "./globals.css"; + +export const metadata: Metadata = { + title: "PlanetScale MySQL + Next.js", + description: "A Next.js app using Prisma with PlanetScale MySQL", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/examples/with-mysql/app/page.tsx b/examples/with-mysql/app/page.tsx new file mode 100644 index 0000000000000..149f4600f4d29 --- /dev/null +++ b/examples/with-mysql/app/page.tsx @@ -0,0 +1,24 @@ +import prisma from "@/lib/prisma"; +import { Product } from "@/components/Product"; + +export default async function Home() { + const products = await prisma.product.findMany({ + include: { + category: true, + }, + }); + + return ( +
+

Next.js Starter

+

+ Shop from the hottest items in the world +

+
+ {products.map((product) => ( + + ))} +
+
+ ); +} diff --git a/examples/with-mysql/components/Product.js b/examples/with-mysql/components/Product.js deleted file mode 100644 index a2ec03a73d58f..0000000000000 --- a/examples/with-mysql/components/Product.js +++ /dev/null @@ -1,31 +0,0 @@ -import Image from "next/image"; - -export default function Product({ product }) { - const { name, description, price, image, category } = product; - - return ( -
- {name} -
-
{name}
-

{description}

-

${price}

-
-
- - {category.name} - -
-
- ); -} diff --git a/examples/with-mysql/components/Product.tsx b/examples/with-mysql/components/Product.tsx new file mode 100644 index 0000000000000..113490d8c8f09 --- /dev/null +++ b/examples/with-mysql/components/Product.tsx @@ -0,0 +1,37 @@ +import Image from "next/image"; +import type { + Product as ProductType, + Category, +} from "@/lib/generated/prisma/client"; + +type ProductWithCategory = ProductType & { + category: Category | null; +}; + +export function Product({ product }: { product: ProductWithCategory }) { + const { name, description, price, image, category } = product; + + return ( +
+ {name} +
+
{name}
+

{description}

+

${price.toString()}

+
+
+ {category && ( + + {category.name} + + )} +
+
+ ); +} diff --git a/examples/with-mysql/lib/prisma.js b/examples/with-mysql/lib/prisma.js deleted file mode 100644 index cc91a659083de..0000000000000 --- a/examples/with-mysql/lib/prisma.js +++ /dev/null @@ -1,14 +0,0 @@ -import { PrismaClient } from "@prisma/client"; - -let prisma; - -if (process.env.NODE_ENV === "production") { - prisma = new PrismaClient(); -} else { - if (!global.prisma) { - global.prisma = new PrismaClient(); - } - prisma = global.prisma; -} - -export default prisma; diff --git a/examples/with-mysql/lib/prisma.ts b/examples/with-mysql/lib/prisma.ts new file mode 100644 index 0000000000000..5045a11c0f57c --- /dev/null +++ b/examples/with-mysql/lib/prisma.ts @@ -0,0 +1,21 @@ +import { PrismaPlanetScale } from "@prisma/adapter-planetscale"; +import { PrismaClient } from "./generated/prisma/client"; +import { fetch as undiciFetch } from "undici"; + +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined; +}; + +function createPrismaClient() { + const adapter = new PrismaPlanetScale({ + url: process.env.DATABASE_URL, + fetch: undiciFetch, + }); + return new PrismaClient({ adapter }); +} + +const prisma = globalForPrisma.prisma ?? createPrismaClient(); + +if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; + +export default prisma; diff --git a/examples/with-mysql/next.config.js b/examples/with-mysql/next.config.js deleted file mode 100644 index 3dd7ef15191a9..0000000000000 --- a/examples/with-mysql/next.config.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @type {import('next').NextConfig} */ -module.exports = { - reactStrictMode: true, -}; diff --git a/examples/with-mysql/next.config.ts b/examples/with-mysql/next.config.ts new file mode 100644 index 0000000000000..e9ffa3083ad27 --- /dev/null +++ b/examples/with-mysql/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ +}; + +export default nextConfig; diff --git a/examples/with-mysql/package.json b/examples/with-mysql/package.json index 47080a1648ca0..dbea189d8d533 100644 --- a/examples/with-mysql/package.json +++ b/examples/with-mysql/package.json @@ -1,21 +1,32 @@ { + "type": "module", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", - "seed": "node prisma/seed.js" + "lint": "next lint" + }, + "prisma": { + "seed": "tsx prisma/seed.ts" }, "dependencies": { - "@prisma/client": "3.10.0", + "@prisma/adapter-planetscale": "latest", + "@prisma/client": "latest", "next": "latest", - "react": "18.2.0", - "react-dom": "18.2.0" + "react": "^19.0.0", + "react-dom": "^19.0.0", + "undici": "^7" }, "devDependencies": { - "autoprefixer": "10.4.2", - "postcss": "8.4.7", - "prisma": "3.10.0", - "tailwindcss": "3.0.23" + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "dotenv": "^16", + "prisma": "latest", + "tailwindcss": "^4", + "tsx": "^4", + "typescript": "^5" } } diff --git a/examples/with-mysql/pages/_app.js b/examples/with-mysql/pages/_app.js deleted file mode 100644 index 3844f96512117..0000000000000 --- a/examples/with-mysql/pages/_app.js +++ /dev/null @@ -1,5 +0,0 @@ -import "../styles/globals.css"; - -export default function MyApp({ Component, pageProps }) { - return ; -} diff --git a/examples/with-mysql/pages/api/products.js b/examples/with-mysql/pages/api/products.js deleted file mode 100644 index b68acdd5c1f8a..0000000000000 --- a/examples/with-mysql/pages/api/products.js +++ /dev/null @@ -1,16 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import prisma from "./../../lib/prisma.js"; - -export default async function handler(req, res) { - if (req.method === "GET") { - try { - const data = await prisma.product.findMany({}); - return res.status(200).json({ data }); - } catch (err) { - console.error(err); - return res.status(500).json({ msg: "Something went wrong" }); - } - } else { - return res.status(405).json({ msg: "Method not allowed" }); - } -} diff --git a/examples/with-mysql/pages/index.js b/examples/with-mysql/pages/index.js deleted file mode 100644 index b9bbc43316f53..0000000000000 --- a/examples/with-mysql/pages/index.js +++ /dev/null @@ -1,46 +0,0 @@ -import Head from "next/head"; -import Product from "../components/Product"; -import prisma from "../lib/prisma"; - -export default function Home({ products }) { - return ( -
- - PlanetScale Next.js Quickstart - - - - -
-

Next.js Starter

-

- 🔥 Shop from the hottest items in the world 🔥 -

-
- {products.map((product) => ( - - ))} -
-
- -
-
- ); -} - -export async function getStaticProps(context) { - const data = await prisma.product.findMany({ - include: { - category: true, - }, - }); - - //convert decimal value to string to pass through as json - const products = data.map((product) => ({ - ...product, - price: product.price.toString(), - })); - return { - props: { products }, - }; -} diff --git a/examples/with-mysql/postcss.config.js b/examples/with-mysql/postcss.config.js deleted file mode 100644 index 12a703d900da8..0000000000000 --- a/examples/with-mysql/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -module.exports = { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -}; diff --git a/examples/with-mysql/postcss.config.mjs b/examples/with-mysql/postcss.config.mjs new file mode 100644 index 0000000000000..61e36849cf7cf --- /dev/null +++ b/examples/with-mysql/postcss.config.mjs @@ -0,0 +1,7 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; + +export default config; diff --git a/examples/with-mysql/prisma.config.ts b/examples/with-mysql/prisma.config.ts new file mode 100644 index 0000000000000..be17ee0025baa --- /dev/null +++ b/examples/with-mysql/prisma.config.ts @@ -0,0 +1,13 @@ +import "dotenv/config"; +import { defineConfig, env } from "prisma/config"; + +export default defineConfig({ + schema: "prisma/schema.prisma", + migrations: { + path: "prisma/migrations", + seed: "tsx prisma/seed.ts", + }, + datasource: { + url: env("DATABASE_URL"), + }, +}); diff --git a/examples/with-mysql/prisma/data.js b/examples/with-mysql/prisma/data.ts similarity index 81% rename from examples/with-mysql/prisma/data.js rename to examples/with-mysql/prisma/data.ts index 85c040ec95070..ff2f694833138 100644 --- a/examples/with-mysql/prisma/data.js +++ b/examples/with-mysql/prisma/data.ts @@ -1,6 +1,6 @@ -const { Prisma } = require("@prisma/client"); +import { Prisma } from "../lib/generated/prisma/client"; -const categories = [ +export const categories = [ { name: "Hats", description: "Things you can wear on your head", @@ -15,38 +15,33 @@ const categories = [ }, ]; -const products = [ +export const products = [ { name: "Cool helmet.", description: "A nice helmet to wear on your head", price: new Prisma.Decimal(19.95), image: "/images/helmet.jpg", - category_id: 1, + categoryId: 1, }, { name: "Grey T-Shirt", description: "A nice shirt that you can wear on your body", price: new Prisma.Decimal(22.95), image: "/images/shirt.jpg", - category_id: 3, + categoryId: 3, }, { name: "Socks", description: "Cool socks that you can wear on your feet", price: new Prisma.Decimal(12.95), image: "/images/socks.jpg", - category_id: 2, + categoryId: 2, }, { name: "Sweatshirt", description: "Cool sweatshirt that you can wear on your body", price: new Prisma.Decimal(12.95), image: "/images/sweatshirt.jpg", - category_id: 3, + categoryId: 3, }, ]; - -module.exports = { - products, - categories, -}; diff --git a/examples/with-mysql/prisma/schema.prisma b/examples/with-mysql/prisma/schema.prisma index c74c68f987fd7..d8b293467c1f0 100644 --- a/examples/with-mysql/prisma/schema.prisma +++ b/examples/with-mysql/prisma/schema.prisma @@ -1,29 +1,28 @@ generator client { - provider = "prisma-client-js" - previewFeatures = ["referentialIntegrity"] + provider = "prisma-client" + output = "../lib/generated/prisma" } datasource db { - provider = "mysql" - url = env("DATABASE_URL") - referentialIntegrity = "prisma" + provider = "mysql" + relationMode = "prisma" } model Product { - id Int @id @default(autoincrement()) - name String - description String - price Decimal - image String - category Category? @relation(fields: [category_id], references: [id]) - category_id Int + id Int @id @default(autoincrement()) + name String + description String + price Decimal + image String + category Category @relation(fields: [categoryId], references: [id]) + categoryId Int - @@index([category_id]) + @@index([categoryId]) } model Category { - id Int @id @default(autoincrement()) - name String - description String - products Product[] + id Int @id @default(autoincrement()) + name String + description String + products Product[] } diff --git a/examples/with-mysql/prisma/seed.js b/examples/with-mysql/prisma/seed.js deleted file mode 100644 index b943d2d44c8b2..0000000000000 --- a/examples/with-mysql/prisma/seed.js +++ /dev/null @@ -1,36 +0,0 @@ -const { PrismaClient } = require("@prisma/client"); -const { categories, products } = require("./data.js"); -const prisma = new PrismaClient(); - -const load = async () => { - try { - await prisma.category.deleteMany(); - console.log("Deleted records in category table"); - - await prisma.product.deleteMany(); - console.log("Deleted records in product table"); - - await prisma.$queryRaw`ALTER TABLE Product AUTO_INCREMENT = 1`; - console.log("reset product auto increment to 1"); - - await prisma.$queryRaw`ALTER TABLE Category AUTO_INCREMENT = 1`; - console.log("reset category auto increment to 1"); - - await prisma.category.createMany({ - data: categories, - }); - console.log("Added category data"); - - await prisma.product.createMany({ - data: products, - }); - console.log("Added product data"); - } catch (e) { - console.error(e); - process.exit(1); - } finally { - await prisma.$disconnect(); - } -}; - -load(); diff --git a/examples/with-mysql/prisma/seed.ts b/examples/with-mysql/prisma/seed.ts new file mode 100644 index 0000000000000..1a31a5fa2995c --- /dev/null +++ b/examples/with-mysql/prisma/seed.ts @@ -0,0 +1,49 @@ +import "dotenv/config"; +import { PrismaPlanetScale } from "@prisma/adapter-planetscale"; +import { PrismaClient } from "../lib/generated/prisma/client"; +import { fetch as undiciFetch } from "undici"; +import { categories, products } from "./data"; + +const adapter = new PrismaPlanetScale({ + url: process.env.DATABASE_URL, + fetch: undiciFetch, +}); +const prisma = new PrismaClient({ adapter }); + +async function main() { + console.log("Seeding database..."); + + await prisma.product.deleteMany(); + console.log("Deleted records in product table"); + + await prisma.category.deleteMany(); + console.log("Deleted records in category table"); + + await prisma.$executeRaw`ALTER TABLE Product AUTO_INCREMENT = 1`; + console.log("Reset product auto increment to 1"); + + await prisma.$executeRaw`ALTER TABLE Category AUTO_INCREMENT = 1`; + console.log("Reset category auto increment to 1"); + + await prisma.category.createMany({ + data: categories, + }); + console.log("Added category data"); + + await prisma.product.createMany({ + data: products, + }); + console.log("Added product data"); + + console.log("Seeding complete!"); +} + +main() + .then(async () => { + await prisma.$disconnect(); + }) + .catch(async (e) => { + console.error(e); + await prisma.$disconnect(); + process.exit(1); + }); diff --git a/examples/with-mysql/public/vercel.svg b/examples/with-mysql/public/vercel.svg deleted file mode 100644 index fbf0e25a651c2..0000000000000 --- a/examples/with-mysql/public/vercel.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - \ No newline at end of file diff --git a/examples/with-mysql/styles/globals.css b/examples/with-mysql/styles/globals.css deleted file mode 100644 index b5c61c956711f..0000000000000 --- a/examples/with-mysql/styles/globals.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/examples/with-mysql/tailwind.config.js b/examples/with-mysql/tailwind.config.js deleted file mode 100644 index 48429970a27ad..0000000000000 --- a/examples/with-mysql/tailwind.config.js +++ /dev/null @@ -1,11 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - "./pages/**/*.{js,ts,jsx,tsx}", - "./components/**/*.{js,ts,jsx,tsx}", - ], - theme: { - extend: {}, - }, - plugins: [], -}; diff --git a/examples/with-mysql/tsconfig.json b/examples/with-mysql/tsconfig.json new file mode 100644 index 0000000000000..00978ef407fda --- /dev/null +++ b/examples/with-mysql/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} From 06421057b5d261388e23f31f1666de051ee0e2c6 Mon Sep 17 00:00:00 2001 From: Hendrik Liebau Date: Tue, 20 Jan 2026 12:47:08 +0100 Subject: [PATCH 3/3] Rename `rewroteURL` to `rewrittenPathname` in request metadata (#88751) The field stores a pathname, not a full URL. --- .../next/src/server/app-render/app-render.tsx | 5 ++--- packages/next/src/server/base-server.ts | 17 +++++++++++------ packages/next/src/server/request-meta.ts | 5 +++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 46586a2d8d4e8..607b1fa31da42 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -2023,9 +2023,8 @@ async function renderToHTMLOrFlightImpl( // fetch cache. Using the destination path ensures that // revalidatePath('/dest') invalidates cache entries for pages rewritten to // that destination. - // TODO: simplify getImplicitTags to accept pathname instead of url object, - // and rename 'rewroteURL' to 'rewrittenPathname' in request-meta.ts. - const rewrittenPathname = getRequestMeta(req, 'rewroteURL') + // TODO: simplify getImplicitTags to accept pathname instead of url object. + const rewrittenPathname = getRequestMeta(req, 'rewrittenPathname') const implicitTagsUrl = rewrittenPathname ? { ...url, pathname: rewrittenPathname } : url diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index a94d1f4401fb8..ea47bcf28289c 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -1207,7 +1207,11 @@ export default abstract class Server< pathnameBeforeRewrite !== rewrittenParsedUrl.pathname if (didRewrite && rewrittenParsedUrl.pathname) { - addRequestMeta(req, 'rewroteURL', rewrittenParsedUrl.pathname) + addRequestMeta( + req, + 'rewrittenPathname', + rewrittenParsedUrl.pathname + ) } const routeParamKeys = new Set() @@ -1502,7 +1506,7 @@ export default abstract class Server< if (parsedUrl.pathname !== parsedMatchedPath.pathname) { parsedUrl.pathname = parsedMatchedPath.pathname - addRequestMeta(req, 'rewroteURL', invokePathnameInfo.pathname) + addRequestMeta(req, 'rewrittenPathname', invokePathnameInfo.pathname) } const normalizeResult = normalizeLocalePath( removePathPrefix(parsedUrl.pathname, this.nextConfig.basePath || ''), @@ -2086,12 +2090,13 @@ export default abstract class Server< } } - // Compute the iSSG cache key. We use the rewroteUrl since + // Compute the iSSG cache key. We use the rewritten pathname since // pages with fallback: false are allowed to be rewritten to // and we need to look up the path by the rewritten path let urlPathname = parseUrl(req.url || '').pathname || '/' - let resolvedUrlPathname = getRequestMeta(req, 'rewroteURL') || urlPathname + let resolvedUrlPathname = + getRequestMeta(req, 'rewrittenPathname') || urlPathname this.setVaryHeader(req, res, isAppPath, resolvedUrlPathname) @@ -2616,8 +2621,8 @@ export default abstract class Server< url: ctx.req.url, matchedPath: ctx.req.headers[MATCHED_PATH_HEADER], initUrl: getRequestMeta(ctx.req, 'initURL'), - didRewrite: !!getRequestMeta(ctx.req, 'rewroteURL'), - rewroteUrl: getRequestMeta(ctx.req, 'rewroteURL'), + didRewrite: !!getRequestMeta(ctx.req, 'rewrittenPathname'), + rewrittenPathname: getRequestMeta(ctx.req, 'rewrittenPathname'), }, null, 2 diff --git a/packages/next/src/server/request-meta.ts b/packages/next/src/server/request-meta.ts index c60b09c1068f6..c72e4b67fef04 100644 --- a/packages/next/src/server/request-meta.ts +++ b/packages/next/src/server/request-meta.ts @@ -81,9 +81,10 @@ export interface RequestMeta { didStripLocale?: boolean /** - * If the request had it's URL rewritten, this is the URL it was rewritten to. + * If the request had its URL rewritten, this is the pathname it was rewritten + * to (not a full URL, just the pathname). */ - rewroteURL?: string + rewrittenPathname?: string /** * The cookies that were added by middleware and were added to the response.