diff --git a/.changeset/lovely-files-move.md b/.changeset/lovely-files-move.md new file mode 100644 index 00000000000..d092bc1a9b3 --- /dev/null +++ b/.changeset/lovely-files-move.md @@ -0,0 +1,5 @@ +--- +"@remix-run/dev": minor +--- + +Add Vite v6 support diff --git a/.gitignore b/.gitignore index 19829b12fcb..6f3911b5c21 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ tsconfig.tsbuildinfo /fixtures/my-remix-app /fixtures/deno-app /integration/playwright-report -/test-results +test-results /uploads .eslintcache diff --git a/docs/guides/typescript.md b/docs/guides/typescript.md index e57e15e74e9..d09978e8ea9 100644 --- a/docs/guides/typescript.md +++ b/docs/guides/typescript.md @@ -35,7 +35,7 @@ The Remix CLI will not perform any type checking. Instead, you'll want to use Ty "@types/react-dom": "^18.2.7", "eslint": "^8.23.1", "typescript": "^5.1.6", - "vite": "^5.1.4" + "vite": "^6.0.0" }, "engines": { "node": ">=18.0.0" diff --git a/integration/helpers/vite-template/.gitignore b/integration/helpers/vite-5-template/.gitignore similarity index 100% rename from integration/helpers/vite-template/.gitignore rename to integration/helpers/vite-5-template/.gitignore diff --git a/integration/helpers/vite-template/app/root.tsx b/integration/helpers/vite-5-template/app/root.tsx similarity index 100% rename from integration/helpers/vite-template/app/root.tsx rename to integration/helpers/vite-5-template/app/root.tsx diff --git a/integration/helpers/vite-template/app/routes/_index.tsx b/integration/helpers/vite-5-template/app/routes/_index.tsx similarity index 100% rename from integration/helpers/vite-template/app/routes/_index.tsx rename to integration/helpers/vite-5-template/app/routes/_index.tsx diff --git a/integration/helpers/vite-template/env.d.ts b/integration/helpers/vite-5-template/env.d.ts similarity index 100% rename from integration/helpers/vite-template/env.d.ts rename to integration/helpers/vite-5-template/env.d.ts diff --git a/integration/helpers/vite-5-template/package.json b/integration/helpers/vite-5-template/package.json new file mode 100644 index 00000000000..e436e3ec831 --- /dev/null +++ b/integration/helpers/vite-5-template/package.json @@ -0,0 +1,43 @@ +{ + "name": "integration-vite-5-template", + "version": "0.0.0", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "dev": "remix vite:dev", + "build": "remix vite:build", + "start": "remix-serve ./build/server/index.js", + "typecheck": "tsc" + }, + "dependencies": { + "@remix-run/express": "workspace:*", + "@remix-run/node": "workspace:*", + "@remix-run/react": "workspace:*", + "@remix-run/serve": "workspace:*", + "@remix-run/server-runtime": "workspace:*", + "@vanilla-extract/css": "^1.10.0", + "@vanilla-extract/vite-plugin": "^3.9.2", + "express": "^4.20.0", + "isbot": "^4.1.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "serialize-javascript": "^6.0.1" + }, + "devDependencies": { + "@remix-run/dev": "workspace:*", + "@remix-run/eslint-config": "workspace:*", + "@remix-run/route-config": "workspace:*", + "@types/react": "^18.2.20", + "@types/react-dom": "^18.2.7", + "eslint": "^8.38.0", + "typescript": "^5.1.6", + "vite": "5.1.8", + "vite-env-only": "^2.0.0", + "vite-tsconfig-paths": "^4.2.1", + "wrangler": "^3.24.0" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/integration/helpers/vite-template/public/favicon.ico b/integration/helpers/vite-5-template/public/favicon.ico similarity index 100% rename from integration/helpers/vite-template/public/favicon.ico rename to integration/helpers/vite-5-template/public/favicon.ico diff --git a/integration/helpers/vite-template/tsconfig.json b/integration/helpers/vite-5-template/tsconfig.json similarity index 100% rename from integration/helpers/vite-template/tsconfig.json rename to integration/helpers/vite-5-template/tsconfig.json diff --git a/integration/helpers/vite-template/vite.config.ts b/integration/helpers/vite-5-template/vite.config.ts similarity index 100% rename from integration/helpers/vite-template/vite.config.ts rename to integration/helpers/vite-5-template/vite.config.ts diff --git a/integration/helpers/vite-6-template/.gitignore b/integration/helpers/vite-6-template/.gitignore new file mode 100644 index 00000000000..80ec311f4ff --- /dev/null +++ b/integration/helpers/vite-6-template/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/.cache +/build +.env diff --git a/integration/helpers/vite-6-template/app/root.tsx b/integration/helpers/vite-6-template/app/root.tsx new file mode 100644 index 00000000000..e31409ca31d --- /dev/null +++ b/integration/helpers/vite-6-template/app/root.tsx @@ -0,0 +1,25 @@ +import { + Links, + Meta, + Outlet, + Scripts, + ScrollRestoration, +} from "@remix-run/react"; + +export default function App() { + return ( + + + + + + + + + + + + + + ); +} diff --git a/integration/helpers/vite-6-template/app/routes/_index.tsx b/integration/helpers/vite-6-template/app/routes/_index.tsx new file mode 100644 index 00000000000..5347369230e --- /dev/null +++ b/integration/helpers/vite-6-template/app/routes/_index.tsx @@ -0,0 +1,41 @@ +import type { MetaFunction } from "@remix-run/node"; + +export const meta: MetaFunction = () => { + return [ + { title: "New Remix App" }, + { name: "description", content: "Welcome to Remix!" }, + ]; +}; + +export default function Index() { + return ( +
+

Welcome to Remix

+ +
+ ); +} diff --git a/integration/helpers/vite-6-template/env.d.ts b/integration/helpers/vite-6-template/env.d.ts new file mode 100644 index 00000000000..78ed2345c6e --- /dev/null +++ b/integration/helpers/vite-6-template/env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/integration/helpers/vite-template/package.json b/integration/helpers/vite-6-template/package.json similarity index 91% rename from integration/helpers/vite-template/package.json rename to integration/helpers/vite-6-template/package.json index b2b9b38c7cd..a4b1372b930 100644 --- a/integration/helpers/vite-template/package.json +++ b/integration/helpers/vite-6-template/package.json @@ -1,5 +1,5 @@ { - "name": "integration-vite-template", + "name": "integration-vite-6-template", "version": "0.0.0", "private": true, "sideEffects": false, @@ -15,6 +15,7 @@ "@remix-run/node": "workspace:*", "@remix-run/react": "workspace:*", "@remix-run/serve": "workspace:*", + "@remix-run/server-runtime": "workspace:*", "@vanilla-extract/css": "^1.10.0", "@vanilla-extract/vite-plugin": "^3.9.2", "express": "^4.20.0", @@ -31,7 +32,7 @@ "@types/react-dom": "^18.2.7", "eslint": "^8.38.0", "typescript": "^5.1.6", - "vite": "5.1.8", + "vite": "^6.0.0", "vite-env-only": "^2.0.0", "vite-tsconfig-paths": "^4.2.1", "wrangler": "^3.24.0" diff --git a/integration/helpers/vite-6-template/public/favicon.ico b/integration/helpers/vite-6-template/public/favicon.ico new file mode 100644 index 00000000000..8830cf6821b Binary files /dev/null and b/integration/helpers/vite-6-template/public/favicon.ico differ diff --git a/integration/helpers/vite-6-template/tsconfig.json b/integration/helpers/vite-6-template/tsconfig.json new file mode 100644 index 00000000000..ad5ae05598e --- /dev/null +++ b/integration/helpers/vite-6-template/tsconfig.json @@ -0,0 +1,21 @@ +{ + "include": ["env.d.ts", "**/*.ts", "**/*.tsx"], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "target": "ES2022", + "strict": true, + "allowJs": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./app/*"] + }, + "noEmit": true + } +} diff --git a/integration/helpers/vite-6-template/vite.config.ts b/integration/helpers/vite-6-template/vite.config.ts new file mode 100644 index 00000000000..a1fcb5a7b79 --- /dev/null +++ b/integration/helpers/vite-6-template/vite.config.ts @@ -0,0 +1,7 @@ +import { vitePlugin as remix } from "@remix-run/dev"; +import { defineConfig } from "vite"; +import tsconfigPaths from "vite-tsconfig-paths"; + +export default defineConfig({ + plugins: [remix(), tsconfigPaths()], +}); diff --git a/integration/helpers/vite-cloudflare-template/package.json b/integration/helpers/vite-cloudflare-template/package.json index 7ea4574904b..d220b231c31 100644 --- a/integration/helpers/vite-cloudflare-template/package.json +++ b/integration/helpers/vite-cloudflare-template/package.json @@ -11,9 +11,10 @@ "typecheck": "tsc" }, "dependencies": { - "@remix-run/cloudflare": "2.15.1", - "@remix-run/cloudflare-pages": "2.15.1", - "@remix-run/react": "2.15.1", + "@remix-run/cloudflare": "workspace:*", + "@remix-run/cloudflare-pages": "workspace:*", + "@remix-run/react": "workspace:*", + "@remix-run/server-runtime": "workspace:*", "isbot": "^4.1.0", "miniflare": "^3.20231030.4", "react": "^18.2.0", @@ -26,7 +27,7 @@ "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "typescript": "^5.1.6", - "vite": "5.1.8", + "vite": "^6.0.0", "vite-tsconfig-paths": "^4.2.1", "wrangler": "^3.24.0" }, diff --git a/integration/helpers/vite.ts b/integration/helpers/vite.ts index cf6cc609dbf..784413bc3f0 100644 --- a/integration/helpers/vite.ts +++ b/integration/helpers/vite.ts @@ -96,11 +96,45 @@ export const EXPRESS_SERVER = (args: { app.listen(port, () => console.log('http://localhost:' + port)); `; -type TemplateName = "vite-template" | "vite-cloudflare-template"; +type TemplateName = + | "vite-5-template" + | "vite-6-template" + | "vite-cloudflare-template"; + +export const viteMajorTemplates = [ + { templateName: "vite-5-template", templateDisplayName: "Vite 5" }, + { templateName: "vite-6-template", templateDisplayName: "Vite 6" }, +] as const satisfies ReadonlyArray<{ + templateName: TemplateName; + templateDisplayName: string; +}>; + +function resolveDevPackageDir(root: string) { + return path.join(root, "node_modules", "@remix-run", "dev"); +} + +function resolveDevPackageNodeModulesDir(root: string) { + return path.join(resolveDevPackageDir(root), "node_modules"); +} + +async function copyDirContents( + srcDir: string, + destDir: string, + filter?: (file: string) => boolean +) { + for (let file of await fse.readdir(srcDir)) { + if (filter && !filter(path.normalize(file))) { + continue; + } + let srcFile = path.join(srcDir, file); + let destFile = path.join(destDir, file); + await fse.copy(srcFile, destFile, { errorOnExist: true }); + } +} export async function createProject( files: Record = {}, - templateName: TemplateName = "vite-template" + templateName: TemplateName = "vite-5-template" ) { let projectName = `remix-${Math.random().toString(32).slice(2)}`; let projectDir = path.join(TMP_DIR, projectName); @@ -108,7 +142,27 @@ export async function createProject( // base template let templateDir = path.resolve(__dirname, templateName); - await fse.copy(templateDir, projectDir, { errorOnExist: true }); + + // When we copy the template, we need to filter out the version of Vite + // installed locally within @remix-run/dev. If we don't do this, the dev + // package doesn't use the version of Vite defined within the test template + // which means we can't run integration tests across different versions of + // Vite. Since pnpm uses symlinks for dependencies, we need to perform the + // copy in multiple steps so that we can filter at each level. + await fse.copy(templateDir, projectDir, { + errorOnExist: true, + filter: (src) => !path.normalize(src).endsWith("/@remix-run/dev"), + }); + await copyDirContents( + resolveDevPackageDir(templateDir), + resolveDevPackageDir(projectDir), + (file) => file !== "node_modules" + ); + await copyDirContents( + resolveDevPackageNodeModulesDir(templateDir), + resolveDevPackageNodeModulesDir(projectDir), + (file) => file !== "vite" + ); // user-defined files await Promise.all( @@ -246,7 +300,10 @@ type Fixtures = { port: number; cwd: string; }>; - customDev: (files: Files) => Promise<{ + customDev: ( + files: Files, + templateName?: TemplateName + ) => Promise<{ port: number; cwd: string; }>; @@ -280,7 +337,7 @@ export const test = base.extend({ // eslint-disable-next-line no-empty-pattern customDev: async ({}, use) => { let stop: (() => unknown) | undefined; - await use(async (files) => { + await use(async (files, template) => { let port = await getPort(); let cwd = await createProject(await files({ port })); stop = await customDev({ cwd, port }); diff --git a/integration/package.json b/integration/package.json index 4ced519bc75..3a63a551fe3 100644 --- a/integration/package.json +++ b/integration/package.json @@ -10,7 +10,7 @@ "dependencies": { "@cloudflare/kv-asset-handler": "^0.3.0", "@cloudflare/workers-types": "^4.20230518.0", - "@playwright/test": "^1.33.0", + "@playwright/test": "^1.49.1", "@remix-run/dev": "workspace:*", "@remix-run/express": "workspace:*", "@remix-run/node": "workspace:*", @@ -30,6 +30,7 @@ "globby": "^11.1.0", "isbot": "^4.1.0", "npm-run-all": "^4.1.5", + "pathe": "^1.1.2", "pidtree": "^0.6.0", "postcss": "^8.4.19", "postcss-import": "^15.1.0", diff --git a/integration/vite-css-test.ts b/integration/vite-css-test.ts index 77bc5ccc2f6..cd58b00c3b5 100644 --- a/integration/vite-css-test.ts +++ b/integration/vite-css-test.ts @@ -12,6 +12,7 @@ import { customDev, EXPRESS_SERVER, viteConfig, + viteMajorTemplates, } from "./helpers/vite.js"; const js = String.raw; @@ -171,114 +172,132 @@ const VITE_CONFIG = async (port: number) => dedent` } `; -test.describe(() => { - test.describe(async () => { - let port: number; - let cwd: string; - let stop: () => void; - - test.beforeAll(async () => { - port = await getPort(); - cwd = await createProject({ - "vite.config.ts": await VITE_CONFIG(port), - ...files, - }); - stop = await viteDev({ cwd, port }); - }); - test.afterAll(() => stop()); - - test.describe(() => { - test.use({ javaScriptEnabled: false }); - test("Vite / CSS / vite dev / without JS", async ({ page }) => { - await pageLoadWorkflow({ page, port }); - }); - }); - - test.describe(() => { - test.use({ javaScriptEnabled: true }); - test("Vite / CSS / vite dev / with JS", async ({ page }) => { - await pageLoadWorkflow({ page, port }); - await hmrWorkflow({ page, port, cwd }); - }); - }); - }); - - test.describe(async () => { - let port: number; - let cwd: string; - let stop: () => void; - - test.beforeAll(async () => { - port = await getPort(); - cwd = await createProject({ - "vite.config.ts": await VITE_CONFIG(port), - "server.mjs": EXPRESS_SERVER({ port }), - ...files, - }); - stop = await customDev({ cwd, port }); - }); - test.afterAll(() => stop()); - - test.describe(() => { - test.use({ javaScriptEnabled: false }); - test("Vite / CSS / express / without JS", async ({ page }) => { - await pageLoadWorkflow({ page, port }); - }); - }); - - test.describe(() => { - test.use({ javaScriptEnabled: true }); - test("Vite / CSS / express / with JS", async ({ page }) => { - await pageLoadWorkflow({ page, port }); - await hmrWorkflow({ page, port, cwd }); - }); - }); - }); - - test.describe(async () => { - let port: number; - let cwd: string; - let stop: () => void; - - test.beforeAll(async () => { - port = await getPort(); - cwd = await createProject({ - "vite.config.ts": await VITE_CONFIG(port), - ...files, - }); - - let edit = createEditor(cwd); - await edit("package.json", (contents) => - contents.replace('"sideEffects": false', '"sideEffects": ["*.css.ts"]') - ); - - let { stderr, status } = viteBuild({ - cwd, - env: { - // Vanilla Extract uses Vite's CJS build which emits a warning to stderr - VITE_CJS_IGNORE_WARNING: "true", - }, - }); - expect(stderr.toString()).toBeFalsy(); - expect(status).toBe(0); - stop = await viteRemixServe({ cwd, port }); - }); - test.afterAll(() => stop()); - - test.describe(() => { - test.use({ javaScriptEnabled: false }); - test("Vite / CSS / vite build / without JS", async ({ page }) => { - await pageLoadWorkflow({ page, port }); - }); - }); - - test.describe(() => { - test.use({ javaScriptEnabled: true }); - test("Vite / CSS / vite build / with JS", async ({ page }) => { - await pageLoadWorkflow({ page, port }); +test.describe("Vite CSS", () => { + viteMajorTemplates + // .filter(({ templateName }) => templateName === "vite-5-template") + .forEach(({ templateName, templateDisplayName }) => { + test.describe(templateDisplayName, () => { + test.describe("vite dev", async () => { + let port: number; + let cwd: string; + let stop: () => void; + + test.beforeAll(async () => { + port = await getPort(); + cwd = await createProject( + { + "vite.config.ts": await VITE_CONFIG(port), + ...files, + }, + templateName + ); + stop = await viteDev({ cwd, port }); + }); + test.afterAll(() => stop()); + + test.describe(() => { + test.use({ javaScriptEnabled: false }); + test("without JS", async ({ page }) => { + await pageLoadWorkflow({ page, port }); + }); + }); + + test.describe(() => { + test.use({ javaScriptEnabled: true }); + test("with JS", async ({ page }) => { + await pageLoadWorkflow({ page, port }); + await hmrWorkflow({ page, port, cwd }); + }); + }); + }); + + test.describe("express", async () => { + let port: number; + let cwd: string; + let stop: () => void; + + test.beforeAll(async () => { + port = await getPort(); + cwd = await createProject( + { + "vite.config.ts": await VITE_CONFIG(port), + "server.mjs": EXPRESS_SERVER({ port }), + ...files, + }, + templateName + ); + stop = await customDev({ cwd, port }); + }); + test.afterAll(() => stop()); + + test.describe(() => { + test.use({ javaScriptEnabled: false }); + test("without JS", async ({ page }) => { + await pageLoadWorkflow({ page, port }); + }); + }); + + test.describe(() => { + test.use({ javaScriptEnabled: true }); + test("with JS", async ({ page }) => { + await pageLoadWorkflow({ page, port }); + await hmrWorkflow({ page, port, cwd }); + }); + }); + }); + + test.describe("vite build", async () => { + let port: number; + let cwd: string; + let stop: () => void; + + test.beforeAll(async () => { + port = await getPort(); + cwd = await createProject( + { + "vite.config.ts": await VITE_CONFIG(port), + ...files, + }, + templateName + ); + + let edit = createEditor(cwd); + await edit("package.json", (contents) => + contents.replace( + '"sideEffects": false', + '"sideEffects": ["*.css.ts"]' + ) + ); + + let { stderr, status } = viteBuild({ + cwd, + env: { + // Vanilla Extract uses Vite's CJS build which emits a warning to stderr + VITE_CJS_IGNORE_WARNING: "true", + }, + }); + expect(stderr.toString()).toBeFalsy(); + expect(status).toBe(0); + stop = await viteRemixServe({ cwd, port }); + }); + test.afterAll(() => stop()); + + test.describe(() => { + test.use({ javaScriptEnabled: false }); + test("without JS", async ({ page }) => { + await pageLoadWorkflow({ page, port }); + }); + }); + + test.describe(() => { + test.use({ javaScriptEnabled: true }); + test("with JS", async ({ page }) => { + await pageLoadWorkflow({ page, port }); + }); + }); + }); }); }); - }); }); async function pageLoadWorkflow({ page, port }: { page: Page; port: number }) { diff --git a/integration/vite-hmr-hdr-test.ts b/integration/vite-hmr-hdr-test.ts index aca542c36d7..19ef3622567 100644 --- a/integration/vite-hmr-hdr-test.ts +++ b/integration/vite-hmr-hdr-test.ts @@ -9,6 +9,7 @@ import { createEditor, EXPRESS_SERVER, viteConfig, + viteMajorTemplates, } from "./helpers/vite.js"; import { js } from "./helpers/create-fixture.js"; @@ -39,132 +40,130 @@ const indexRoute = ` } `; -test("Vite / HMR & HDR / vite dev", async ({ page, browserName, viteDev }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": await viteConfig.basic({ port }), - "app/routes/_index.tsx": indexRoute, - }); - let { cwd, port } = await viteDev(files); - await workflow({ page, browserName, cwd, port }); -}); - -test("Vite / HMR & HDR / express", async ({ page, browserName, customDev }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": await viteConfig.basic({ port }), - "server.mjs": EXPRESS_SERVER({ port }), - "app/routes/_index.tsx": indexRoute, - }); - let { cwd, port } = await customDev(files); - await workflow({ page, browserName, cwd, port }); -}); - -test("Vite / HMR & HDR / mdx", async ({ page, viteDev }) => { - let files: Files = async ({ port }) => ({ - "vite.config.ts": ` - import { defineConfig } from "vite"; - import { vitePlugin as remix } from "@remix-run/dev"; - import mdx from "@mdx-js/rollup"; - - export default defineConfig({ - ${await viteConfig.server({ port })} - plugins: [ - mdx(), - remix(), - ], +test.describe("Vite HMR & HDR", () => { + viteMajorTemplates.forEach(({ templateName, templateDisplayName }) => { + test.describe(templateDisplayName, () => { + test("vite dev", async ({ page, browserName, viteDev }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": await viteConfig.basic({ port }), + "app/routes/_index.tsx": indexRoute, + }); + let { cwd, port } = await viteDev(files, templateName); + await workflow({ page, browserName, cwd, port }); }); - `, - "app/component.tsx": ` - import {useState} from "react"; - export const Counter = () => { - const [count, setCount] = useState(0); - return - } - `, - "app/routes/mdx.mdx": ` - import { Counter } from "../component"; - - # MDX Title (HMR: 0) - - - `, - }); - - let { port, cwd } = await viteDev(files); - let edit = createEditor(cwd); - await page.goto(`http://localhost:${port}/mdx`, { - waitUntil: "networkidle", - }); - - await expect(page.locator("h1")).toHaveText("MDX Title (HMR: 0)"); - let button = page.locator("button"); - await expect(button).toHaveText("Count: 0"); - await button.click(); - await expect(button).toHaveText("Count: 1"); - - await edit("app/routes/mdx.mdx", (contents) => - contents.replace("(HMR: 0)", "(HMR: 1)") - ); - await page.waitForLoadState("networkidle"); - - await expect(page.locator("h1")).toHaveText("MDX Title (HMR: 1)"); - await expect(page.locator("button")).toHaveText("Count: 1"); - - expect(page.errors).toEqual([]); -}); + test("express", async ({ page, browserName, customDev }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": await viteConfig.basic({ port }), + "server.mjs": EXPRESS_SERVER({ port }), + "app/routes/_index.tsx": indexRoute, + }); + let { cwd, port } = await customDev(files, templateName); + await workflow({ page, browserName, cwd, port }); + }); -test.describe("single fetch", () => { - test("Vite / HMR & HDR / vite dev", async ({ - page, - browserName, - viteDev, - }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": js` - import { vitePlugin as remix } from "@remix-run/dev"; - - export default { - ${await viteConfig.server({ port })} - plugins: [ - remix({ - future: { - v3_singleFetch: true - }, - }) - ] - } - `, - "app/routes/_index.tsx": indexRoute, - }); - let { cwd, port } = await viteDev(files); - await workflow({ page, browserName, cwd, port }); - }); + test("mdx", async ({ page, viteDev }) => { + let files: Files = async ({ port }) => ({ + "vite.config.ts": ` + import { defineConfig } from "vite"; + import { vitePlugin as remix } from "@remix-run/dev"; + import mdx from "@mdx-js/rollup"; + + export default defineConfig({ + ${await viteConfig.server({ port })} + plugins: [ + mdx(), + remix(), + ], + }); + `, + "app/component.tsx": ` + import {useState} from "react"; + + export const Counter = () => { + const [count, setCount] = useState(0); + return + } + `, + "app/routes/mdx.mdx": ` + import { Counter } from "../component"; + + # MDX Title (HMR: 0) + + + `, + }); + + let { port, cwd } = await viteDev(files, templateName); + let edit = createEditor(cwd); + await page.goto(`http://localhost:${port}/mdx`, { + waitUntil: "networkidle", + }); + + await expect(page.locator("h1")).toHaveText("MDX Title (HMR: 0)"); + let button = page.locator("button"); + await expect(button).toHaveText("Count: 0"); + await button.click(); + await expect(button).toHaveText("Count: 1"); + + await edit("app/routes/mdx.mdx", (contents) => + contents.replace("(HMR: 0)", "(HMR: 1)") + ); + await page.waitForLoadState("networkidle"); + + await expect(page.locator("h1")).toHaveText("MDX Title (HMR: 1)"); + await expect(page.locator("button")).toHaveText("Count: 1"); + + expect(page.errors).toEqual([]); + }); - test("Vite / HMR & HDR / express", async ({ - page, - browserName, - customDev, - }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": js` - import { vitePlugin as remix } from "@remix-run/dev"; - - export default { - ${await viteConfig.server({ port })} - plugins: [ - remix({ - future: { - v3_singleFetch: true - }, - }) - ] - } - `, - "server.mjs": EXPRESS_SERVER({ port }), - "app/routes/_index.tsx": indexRoute, + test.describe("single fetch", () => { + test("vite dev", async ({ page, browserName, viteDev }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": js` + import { vitePlugin as remix } from "@remix-run/dev"; + + export default { + ${await viteConfig.server({ port })} + plugins: [ + remix({ + future: { + v3_singleFetch: true + }, + }) + ] + } + `, + "app/routes/_index.tsx": indexRoute, + }); + let { cwd, port } = await viteDev(files, templateName); + await workflow({ page, browserName, cwd, port }); + }); + + test("express", async ({ page, browserName, customDev }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": js` + import { vitePlugin as remix } from "@remix-run/dev"; + + export default { + ${await viteConfig.server({ port })} + plugins: [ + remix({ + future: { + v3_singleFetch: true + }, + }) + ] + } + `, + "server.mjs": EXPRESS_SERVER({ port }), + "app/routes/_index.tsx": indexRoute, + }); + let { cwd, port } = await customDev(files, templateName); + await workflow({ page, browserName, cwd, port }); + }); + }); }); - let { cwd, port } = await customDev(files); - await workflow({ page, browserName, cwd, port }); }); }); diff --git a/integration/vite-route-config-test.ts b/integration/vite-route-config-test.ts index daf2e1a25be..258ef08bc67 100644 --- a/integration/vite-route-config-test.ts +++ b/integration/vite-route-config-test.ts @@ -9,6 +9,7 @@ import { test, viteConfig, createEditor, + viteMajorTemplates, } from "./helpers/vite.js"; const js = String.raw; @@ -36,53 +37,61 @@ async function reloadPage({ } test.describe("route config", () => { - test("fails the build if route config is missing", async () => { - let cwd = await createProject({ - "vite.config.js": ` - import { vitePlugin as remix } from "@remix-run/dev"; - - export default { - plugins: [remix({ - future: { v3_routeConfig: true }, - })] - } - `, - }); - // Ensure file is missing in case it's ever added to test fixture - await fs.rm(path.join(cwd, "app/routes.ts"), { force: true }); - let buildResult = viteBuild({ cwd }); - expect(buildResult.status).toBe(1); - expect(buildResult.stderr.toString()).toContain( - 'Route config file not found at "app/routes.ts"' - ); - }); - - test("fails the build if routes option is used", async () => { - let cwd = await createProject({ - "vite.config.js": ` - import { vitePlugin as remix } from "@remix-run/dev"; - - export default { - plugins: [remix({ - future: { v3_routeConfig: true }, - routes: () => {}, - })] - } - `, - "app/routes.ts": `export default [];`, - }); - let buildResult = viteBuild({ cwd }); - expect(buildResult.status).toBe(1); - expect(buildResult.stderr.toString()).toContain( - 'The "routes" config option is not supported when a "routes.ts" file is present. You should migrate these routes into "routes.ts".' - ); - }); - - test("fails the dev process if routes option is used", async ({ - viteDev, - }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": ` + viteMajorTemplates.forEach(({ templateName, templateDisplayName }) => { + test.describe(templateDisplayName, () => { + test("fails the build if route config is missing", async () => { + let cwd = await createProject( + { + "vite.config.js": ` + import { vitePlugin as remix } from "@remix-run/dev"; + + export default { + plugins: [remix({ + future: { v3_routeConfig: true }, + })] + } + `, + }, + templateName + ); + // Ensure file is missing in case it's ever added to test fixture + await fs.rm(path.join(cwd, "app/routes.ts"), { force: true }); + let buildResult = viteBuild({ cwd }); + expect(buildResult.status).toBe(1); + expect(buildResult.stderr.toString()).toContain( + 'Route config file not found at "app/routes.ts"' + ); + }); + + test("fails the build if routes option is used", async () => { + let cwd = await createProject( + { + "vite.config.js": ` + import { vitePlugin as remix } from "@remix-run/dev"; + + export default { + plugins: [remix({ + future: { v3_routeConfig: true }, + routes: () => {}, + })] + } + `, + "app/routes.ts": `export default [];`, + }, + templateName + ); + let buildResult = viteBuild({ cwd }); + expect(buildResult.status).toBe(1); + expect(buildResult.stderr.toString()).toContain( + 'The "routes" config option is not supported when a "routes.ts" file is present. You should migrate these routes into "routes.ts".' + ); + }); + + test("fails the dev process if routes option is used", async ({ + viteDev, + }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": ` import { vitePlugin as remix } from "@remix-run/dev"; export default { @@ -93,280 +102,305 @@ test.describe("route config", () => { })] } `, - "app/routes.ts": `export default [];`, - }); - let devError: Error | undefined; - try { - await viteDev(files); - } catch (error: any) { - devError = error; - } - expect(devError?.toString()).toContain( - 'The "routes" config option is not supported when a "routes.ts" file is present. You should migrate these routes into "routes.ts".' - ); - }); - - test("fails the build if route config is invalid", async () => { - let cwd = await createProject({ - "vite.config.js": ` - import { vitePlugin as remix } from "@remix-run/dev"; - - export default { - plugins: [remix({ - future: { v3_routeConfig: true }, - })] - } - `, - "app/routes.ts": `export default INVALID(`, - }); - let buildResult = viteBuild({ cwd }); - expect(buildResult.status).toBe(1); - expect(buildResult.stderr.toString()).toContain( - 'Route config in "routes.ts" is invalid.' - ); - }); - - test("fails the dev process if route config is initially invalid", async ({ - viteDev, - }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": await viteConfig.basic({ - routeConfig: true, - port, - }), - "app/routes.ts": `export default INVALID(`, - }); - let devError: Error | undefined; - try { - await viteDev(files); - } catch (error: any) { - devError = error; - } - expect(devError?.toString()).toContain( - 'Route config in "routes.ts" is invalid.' - ); - }); - - test("supports correcting an invalid route config", async ({ - browserName, - page, - context, - viteDev, - }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": await viteConfig.basic({ - routeConfig: true, - port, - }), - "app/routes.ts": js` - import { type RouteConfig, index } from "@remix-run/route-config"; - - export default [ - index("test-route-1.tsx"), - ] satisfies RouteConfig; - `, - "app/test-route-1.tsx": ` - export default function TestRoute1() { - return
Test route 1
- } - `, - "app/test-route-2.tsx": ` - export default function TestRoute2() { - return
Test route 2
- } - `, - }); - let { cwd, port } = await viteDev(files); - - await page.goto(`http://localhost:${port}/`, { waitUntil: "networkidle" }); - await expect(page.locator("[data-test-route]")).toHaveText("Test route 1"); - - let edit = createEditor(cwd); - - // Make config invalid - await edit("app/routes.ts", (contents) => contents + "INVALID"); - - // Ensure dev server is still running with old config + HMR - await edit("app/test-route-1.tsx", (contents) => - contents.replace("Test route 1", "Test route 1 updated") - ); - await expect(page.locator("[data-test-route]")).toHaveText( - "Test route 1 updated" - ); - - // Fix config with new route - await edit("app/routes.ts", (contents) => - contents.replace("INVALID", "").replace("test-route-1", "test-route-2") - ); - - await expect(async () => { - // Reload to pick up new route for current path - page = await reloadPage({ browserName, page, context }); - await expect(page.locator("[data-test-route]")).toHaveText( - "Test route 2" - ); - }).toPass(); - }); - - test("supports correcting an invalid route config module graph", async ({ - page, - context, - browserName, - viteDev, - }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": await viteConfig.basic({ - routeConfig: true, - port, - }), - "app/routes.ts": js` - export { default } from "./actual-routes"; - `, - "app/actual-routes.ts": js` - import { type RouteConfig, index } from "@remix-run/route-config"; - - export default [ - index("test-route-1.tsx"), - ] satisfies RouteConfig; - `, - "app/test-route-1.tsx": ` - export default function TestRoute1() { - return
Test route 1
+ "app/routes.ts": `export default [];`, + }); + let devError: Error | undefined; + try { + await viteDev(files, templateName); + } catch (error: any) { + devError = error; } - `, - "app/test-route-2.tsx": ` - export default function TestRoute2() { - return
Test route 2
+ expect(devError?.toString()).toContain( + 'The "routes" config option is not supported when a "routes.ts" file is present. You should migrate these routes into "routes.ts".' + ); + }); + + test("fails the build if route config is invalid", async () => { + let cwd = await createProject( + { + "vite.config.js": ` + import { vitePlugin as remix } from "@remix-run/dev"; + + export default { + plugins: [remix({ + future: { v3_routeConfig: true }, + })] + } + `, + "app/routes.ts": `export default INVALID(`, + }, + templateName + ); + let buildResult = viteBuild({ cwd }); + expect(buildResult.status).toBe(1); + expect(buildResult.stderr.toString()).toContain( + 'Route config in "routes.ts" is invalid.' + ); + }); + + test("fails the dev process if route config is initially invalid", async ({ + viteDev, + }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": await viteConfig.basic({ + routeConfig: true, + port, + }), + "app/routes.ts": `export default INVALID(`, + }); + let devError: Error | undefined; + try { + await viteDev(files, templateName); + } catch (error: any) { + devError = error; } - `, - }); - let { cwd, port } = await viteDev(files); - - await page.goto(`http://localhost:${port}/`, { waitUntil: "networkidle" }); - await expect(page.locator("[data-test-route]")).toHaveText("Test route 1"); - - let edit = createEditor(cwd); - - // Make config invalid - await edit("app/actual-routes.ts", (contents) => contents + "INVALID"); - - // Ensure dev server is still running with old config + HMR - await edit("app/test-route-1.tsx", (contents) => - contents.replace("Test route 1", "Test route 1 updated") - ); - await expect(page.locator("[data-test-route]")).toHaveText( - "Test route 1 updated" - ); - - // Fix config with new route - await edit("app/actual-routes.ts", (contents) => - contents.replace("INVALID", "").replace("test-route-1", "test-route-2") - ); - - await expect(async () => { - // Reload to pick up new route for current path - page = await reloadPage({ browserName, page, context }); - await expect(page.locator("[data-test-route]")).toHaveText( - "Test route 2" - ); - }).toPass(); - }); - - test("supports correcting a missing route config", async ({ - browserName, - page, - context, - viteDev, - }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": await viteConfig.basic({ - routeConfig: true, - port, - }), - "app/routes.ts": js` + expect(devError?.toString()).toContain( + 'Route config in "routes.ts" is invalid.' + ); + }); + + test("supports correcting an invalid route config", async ({ + browserName, + page, + context, + viteDev, + }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": await viteConfig.basic({ + routeConfig: true, + port, + }), + "app/routes.ts": js` import { type RouteConfig, index } from "@remix-run/route-config"; export default [ index("test-route-1.tsx"), ] satisfies RouteConfig; `, - "app/test-route-1.tsx": ` - export default function TestRoute1() { - return
Test route 1
- } - `, - "app/test-route-2.tsx": ` - export default function TestRoute2() { - return
Test route 2
- } - `, - }); - let { cwd, port } = await viteDev(files); - - await page.goto(`http://localhost:${port}/`, { waitUntil: "networkidle" }); - await expect(page.locator("[data-test-route]")).toHaveText("Test route 1"); - - let edit = createEditor(cwd); - - let INVALID_FILENAME = "app/routes.ts.oops"; - - // Rename config to make it missing - await fs.rename( - path.join(cwd, "app/routes.ts"), - path.join(cwd, INVALID_FILENAME) - ); - - // Ensure dev server is still running with old config + HMR - await edit("app/test-route-1.tsx", (contents) => - contents.replace("Test route 1", "Test route 1 updated") - ); - await expect(page.locator("[data-test-route]")).toHaveText( - "Test route 1 updated" - ); - - // Add new route - await edit(INVALID_FILENAME, (contents) => - contents.replace("test-route-1", "test-route-2") - ); - - // Rename config to bring it back - await fs.rename( - path.join(cwd, INVALID_FILENAME), - path.join(cwd, "app/routes.ts") - ); - - await expect(async () => { - // Reload to pick up new route for current path - page = await reloadPage({ browserName, page, context }); - await expect(page.locator("[data-test-route]")).toHaveText( - "Test route 2" - ); - }).toPass(); - }); - - test("supports absolute route file paths", async ({ page, viteDev }) => { - let files: Files = async ({ port }) => ({ - "vite.config.js": await viteConfig.basic({ - routeConfig: true, - port, - }), - "app/routes.ts": js` - import path from "node:path"; - import { type RouteConfig, index } from "@remix-run/route-config"; - - export default [ - index(path.resolve(import.meta.dirname, "test-route.tsx")), - ] satisfies RouteConfig; - `, - "app/test-route.tsx": ` - export default function TestRoute() { - return
Test route
- } - `, + "app/test-route-1.tsx": ` + export default function TestRoute1() { + return
Test route 1
+ } + `, + "app/test-route-2.tsx": ` + export default function TestRoute2() { + return
Test route 2
+ } + `, + }); + let { cwd, port } = await viteDev(files, templateName); + + await page.goto(`http://localhost:${port}/`, { + waitUntil: "networkidle", + }); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 1" + ); + + let edit = createEditor(cwd); + + // Make config invalid + await edit("app/routes.ts", (contents) => contents + "INVALID"); + + // Ensure dev server is still running with old config + HMR + await edit("app/test-route-1.tsx", (contents) => + contents.replace("Test route 1", "Test route 1 updated") + ); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 1 updated" + ); + + // Fix config with new route + await edit("app/routes.ts", (contents) => + contents + .replace("INVALID", "") + .replace("test-route-1", "test-route-2") + ); + + await expect(async () => { + // Reload to pick up new route for current path + page = await reloadPage({ browserName, page, context }); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 2" + ); + }).toPass(); + }); + + test("supports correcting an invalid route config module graph", async ({ + page, + context, + browserName, + viteDev, + }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": await viteConfig.basic({ + routeConfig: true, + port, + }), + "app/routes.ts": js` + export { default } from "./actual-routes"; + `, + "app/actual-routes.ts": js` + import { type RouteConfig, index } from "@remix-run/route-config"; + + export default [ + index("test-route-1.tsx"), + ] satisfies RouteConfig; + `, + "app/test-route-1.tsx": ` + export default function TestRoute1() { + return
Test route 1
+ } + `, + "app/test-route-2.tsx": ` + export default function TestRoute2() { + return
Test route 2
+ } + `, + }); + let { cwd, port } = await viteDev(files, templateName); + + await page.goto(`http://localhost:${port}/`, { + waitUntil: "networkidle", + }); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 1" + ); + + let edit = createEditor(cwd); + + // Make config invalid + await edit("app/actual-routes.ts", (contents) => contents + "INVALID"); + + // Ensure dev server is still running with old config + HMR + await edit("app/test-route-1.tsx", (contents) => + contents.replace("Test route 1", "Test route 1 updated") + ); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 1 updated" + ); + + // Fix config with new route + await edit("app/actual-routes.ts", (contents) => + contents + .replace("INVALID", "") + .replace("test-route-1", "test-route-2") + ); + + await expect(async () => { + // Reload to pick up new route for current path + page = await reloadPage({ browserName, page, context }); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 2" + ); + }).toPass(); + }); + + test("supports correcting a missing route config", async ({ + browserName, + page, + context, + viteDev, + }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": await viteConfig.basic({ + routeConfig: true, + port, + }), + "app/routes.ts": js` + import { type RouteConfig, index } from "@remix-run/route-config"; + + export default [ + index("test-route-1.tsx"), + ] satisfies RouteConfig; + `, + "app/test-route-1.tsx": ` + export default function TestRoute1() { + return
Test route 1
+ } + `, + "app/test-route-2.tsx": ` + export default function TestRoute2() { + return
Test route 2
+ } + `, + }); + let { cwd, port } = await viteDev(files, templateName); + + await page.goto(`http://localhost:${port}/`, { + waitUntil: "networkidle", + }); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 1" + ); + + let edit = createEditor(cwd); + + let INVALID_FILENAME = "app/routes.ts.oops"; + + // Rename config to make it missing + await fs.rename( + path.join(cwd, "app/routes.ts"), + path.join(cwd, INVALID_FILENAME) + ); + + // Ensure dev server is still running with old config + HMR + await edit("app/test-route-1.tsx", (contents) => + contents.replace("Test route 1", "Test route 1 updated") + ); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 1 updated" + ); + + // Add new route + await edit(INVALID_FILENAME, (contents) => + contents.replace("test-route-1", "test-route-2") + ); + + // Rename config to bring it back + await fs.rename( + path.join(cwd, INVALID_FILENAME), + path.join(cwd, "app/routes.ts") + ); + + await expect(async () => { + // Reload to pick up new route for current path + page = await reloadPage({ browserName, page, context }); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route 2" + ); + }).toPass(); + }); + + test("supports absolute route file paths", async ({ page, viteDev }) => { + let files: Files = async ({ port }) => ({ + "vite.config.js": await viteConfig.basic({ + routeConfig: true, + port, + }), + "app/routes.ts": js` + import path from "node:path"; + import { type RouteConfig, index } from "@remix-run/route-config"; + + export default [ + index(path.resolve(import.meta.dirname, "test-route.tsx")), + ] satisfies RouteConfig; + `, + "app/test-route.tsx": ` + export default function TestRoute() { + return
Test route
+ } + `, + }); + let { port } = await viteDev(files, templateName); + + await page.goto(`http://localhost:${port}/`, { + waitUntil: "networkidle", + }); + await expect(page.locator("[data-test-route]")).toHaveText( + "Test route" + ); + }); }); - let { port } = await viteDev(files); - - await page.goto(`http://localhost:${port}/`, { waitUntil: "networkidle" }); - await expect(page.locator("[data-test-route]")).toHaveText("Test route"); }); }); diff --git a/package.json b/package.json index 511e6694e4c..2a0afe76882 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@octokit/graphql": "^4.8.0", "@octokit/plugin-paginate-rest": "^2.17.0", "@octokit/rest": "^18.12.0", - "@playwright/test": "^1.33.0", + "@playwright/test": "^1.49.1", "@remix-run/architect": "workspace:*", "@remix-run/changelog-github": "^0.0.5", "@remix-run/cloudflare": "workspace:*", @@ -129,7 +129,7 @@ "unified": "^10.1.2", "unist-util-remove": "^3.1.0", "unist-util-visit": "^4.1.1", - "vite": "5.1.8", + "vite": "^6.0.0", "vite-tsconfig-paths": "^4.2.2", "wait-on": "^7.0.1", "wrangler": "^3.72.3" diff --git a/packages/remix-dev/package.json b/packages/remix-dev/package.json index e7fd64e8795..5d4bc2be4a1 100644 --- a/packages/remix-dev/package.json +++ b/packages/remix-dev/package.json @@ -74,7 +74,7 @@ "tar-fs": "^2.1.1", "tsconfig-paths": "^4.0.0", "valibot": "^0.41.0", - "vite-node": "^1.6.0", + "vite-node": "3.0.0-beta.2", "ws": "^7.5.10" }, "devDependencies": { @@ -104,14 +104,13 @@ "msw": "^1.2.3", "strip-ansi": "^6.0.1", "tiny-invariant": "^1.2.0", - "vite": "5.1.8", "wrangler": "^3.28.2" }, "peerDependencies": { "@remix-run/react": "^2.15.1", "@remix-run/serve": "^2.15.1", "typescript": "^5.1.0", - "vite": "^5.1.0", + "vite": "^5.1.0 || ^6.0.0", "wrangler": "^3.28.2" }, "peerDependenciesMeta": { diff --git a/packages/remix-dev/vite/plugin.ts b/packages/remix-dev/vite/plugin.ts index e18bf788568..882d3b5d61d 100644 --- a/packages/remix-dev/vite/plugin.ts +++ b/packages/remix-dev/vite/plugin.ts @@ -1815,13 +1815,74 @@ export const remixVitePlugin: RemixVitePlugin = (remixUserConfig = {}) => { return modules; }, }, + { + name: "react-router-server-change-trigger-client-hmr", + // This hook is only available in Vite v6+ so this is a no-op in v5. + // Previously the server and client modules were shared in a single module + // graph. This meant that changes to server code automatically resulted in + // client HMR updates. In Vite v6+ these module graphs are separate from + // each other so we need to manually trigger client HMR updates if server + // code has changed. + hotUpdate(this, { server, modules }) { + if (this.environment.name !== "ssr" && modules.length <= 0) { + return; + } + + let clientModules = uniqueNodes( + modules.flatMap((mod) => + getParentClientNodes(server.environments.client.moduleGraph, mod) + ) + ); + + for (let clientModule of clientModules) { + server.environments.client.reloadModule(clientModule); + } + }, + }, ]; }; +function getParentClientNodes( + clientModuleGraph: Vite.EnvironmentModuleGraph, + module: Vite.EnvironmentModuleNode +): Vite.EnvironmentModuleNode[] { + if (!module.id) { + return []; + } + + let clientModule = clientModuleGraph.getModuleById(module.id); + if (clientModule) { + return [clientModule]; + } + + return [...module.importers].flatMap((importer) => + getParentClientNodes(clientModuleGraph, importer) + ); +} + +function uniqueNodes( + nodes: Vite.EnvironmentModuleNode[] +): Vite.EnvironmentModuleNode[] { + let nodeUrls = new Set(); + let unique: Vite.EnvironmentModuleNode[] = []; + for (let node of nodes) { + if (nodeUrls.has(node.url)) { + continue; + } + nodeUrls.add(node.url); + unique.push(node); + } + return unique; +} + function isInRemixMonorepo() { - let devPath = path.dirname(require.resolve("@remix-run/dev/package.json")); - let devParentDir = path.basename(path.resolve(devPath, "..")); - return devParentDir === "packages"; + try { + let devPath = path.dirname(require.resolve("@remix-run/node/package.json")); + let devParentDir = path.basename(path.resolve(devPath, "..")); + return devParentDir === "packages"; + } catch { + return false; + } } function isEqualJson(v1: unknown, v2: unknown) { diff --git a/packages/remix-dev/vite/styles.ts b/packages/remix-dev/vite/styles.ts index f2910da5f89..7c9e85d309c 100644 --- a/packages/remix-dev/vite/styles.ts +++ b/packages/remix-dev/vite/styles.ts @@ -5,6 +5,7 @@ import { type ModuleNode, type ViteDevServer } from "vite"; import { type RemixConfig as ResolvedRemixConfig } from "../config"; import { resolveFileUrl } from "./resolve-file-url"; +import { importViteEsmSync } from "./import-vite-esm-sync"; type ServerRouteManifest = ServerBuild["routes"]; type ServerRoute = ServerRouteManifest[string]; @@ -48,6 +49,9 @@ export const isCssUrlWithoutSideEffects = (url: string) => { return false; }; +const injectQuery = (url: string, query: string) => + url.includes("?") ? url.replace("?", `?${query}&`) : `${url}?${query}`; + const getStylesForFiles = async ({ viteDevServer, rootDirectory, @@ -59,6 +63,9 @@ const getStylesForFiles = async ({ cssModulesManifest: Record; files: string[]; }): Promise => { + let vite = importViteEsmSync(); + let viteMajor = parseInt(vite.version.split(".")[0], 10); + let styles: Record = {}; let deps = new Set(); @@ -103,15 +110,26 @@ const getStylesForFiles = async ({ try { let css = isCssModulesFile(dep.file) ? cssModulesManifest[dep.file] - : (await viteDevServer.ssrLoadModule(dep.url)).default; + : ( + await viteDevServer.ssrLoadModule( + // We need the ?inline query in Vite v6 when loading CSS in SSR + // since it does not expose the default export for CSS in a + // server environment. This is to align with non-SSR + // environments. For backwards compatibility with v5 we keep + // using the URL without ?inline query because the HMR code was + // relying on the implicit SSR-client module graph relationship. + viteMajor >= 6 ? injectQuery(dep.url, "inline") : dep.url + ) + ).default; if (css === undefined) { throw new Error(); } styles[dep.url] = css; - } catch { + } catch (err) { console.warn(`Could not load ${dep.file}`); + console.error(err); // this can happen with dynamically imported modules, I think // because the Vite module graph doesn't distinguish between // static and dynamic imports? TODO investigate, submit fix diff --git a/packages/remix-route-config/package.json b/packages/remix-route-config/package.json index 175af0bcbfe..b7f4a47d663 100644 --- a/packages/remix-route-config/package.json +++ b/packages/remix-route-config/package.json @@ -23,7 +23,7 @@ "@remix-run/dev": "workspace:*", "@types/lodash": "^4.14.182", "typescript": "^5.1.6", - "vite": "5.1.8" + "vite": "^6.0.0" }, "peerDependencies": { "@remix-run/dev": "^2.15.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e0dd0f6f2c..e7658f510b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,8 +62,8 @@ importers: specifier: ^18.12.0 version: 18.12.0 '@playwright/test': - specifier: ^1.33.0 - version: 1.41.2 + specifier: ^1.49.1 + version: 1.49.1 '@remix-run/architect': specifier: workspace:* version: link:packages/remix-architect @@ -290,11 +290,11 @@ importers: specifier: ^4.1.1 version: 4.1.1 vite: - specifier: 5.1.8 - version: 5.1.8(@types/node@18.17.1) + specifier: ^6.0.0 + version: 6.0.3(@types/node@18.17.1) vite-tsconfig-paths: specifier: ^4.2.2 - version: 4.3.1(typescript@5.1.6)(vite@5.1.8) + version: 4.3.1(typescript@5.1.6)(vite@6.0.3) wait-on: specifier: ^7.0.1 version: 7.0.1 @@ -311,8 +311,8 @@ importers: specifier: ^4.20230518.0 version: 4.20240208.0 '@playwright/test': - specifier: ^1.33.0 - version: 1.41.2 + specifier: ^1.49.1 + version: 1.49.1 '@remix-run/dev': specifier: workspace:* version: link:../packages/remix-dev @@ -370,6 +370,9 @@ importers: npm-run-all: specifier: ^4.1.5 version: 4.1.5 + pathe: + specifier: ^1.1.2 + version: 1.1.2 pidtree: specifier: ^0.6.0 version: 0.6.0 @@ -546,7 +549,7 @@ importers: version: 3.2.1 postcss-import: specifier: ^15.1.0 - version: 15.1.0(postcss@8.4.35) + version: 15.1.0(postcss@8.4.49) tailwindcss: specifier: ^3.3.0 version: 3.4.1 @@ -554,51 +557,72 @@ importers: specifier: ^5.1.0 version: 5.1.6 - integration/helpers/vite-cloudflare-template: + integration/helpers/vite-5-template: dependencies: - '@remix-run/cloudflare': - specifier: 2.15.1 - version: link:../../../packages/remix-cloudflare - '@remix-run/cloudflare-pages': - specifier: 2.15.1 - version: link:../../../packages/remix-cloudflare-pages + '@remix-run/express': + specifier: workspace:* + version: link:../../../packages/remix-express + '@remix-run/node': + specifier: workspace:* + version: link:../../../packages/remix-node '@remix-run/react': - specifier: 2.15.1 + specifier: workspace:* version: link:../../../packages/remix-react + '@remix-run/serve': + specifier: workspace:* + version: link:../../../packages/remix-serve + '@remix-run/server-runtime': + specifier: workspace:* + version: link:../../../packages/remix-server-runtime + '@vanilla-extract/css': + specifier: ^1.10.0 + version: 1.14.1 + '@vanilla-extract/vite-plugin': + specifier: ^3.9.2 + version: 3.9.5(vite@5.1.8) + express: + specifier: ^4.20.0 + version: 4.21.1 isbot: specifier: ^4.1.0 version: 4.4.0 - miniflare: - specifier: ^3.20231030.4 - version: 3.20240821.1 react: specifier: ^18.2.0 version: 18.2.0 react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + serialize-javascript: + specifier: ^6.0.1 + version: 6.0.2 devDependencies: - '@cloudflare/workers-types': - specifier: ^4.20230518.0 - version: 4.20240208.0 '@remix-run/dev': specifier: workspace:* version: link:../../../packages/remix-dev '@remix-run/eslint-config': specifier: workspace:* version: link:../../../packages/remix-eslint-config + '@remix-run/route-config': + specifier: workspace:* + version: link:../../../packages/remix-route-config '@types/react': specifier: ^18.2.20 version: 18.2.20 '@types/react-dom': specifier: ^18.2.7 version: 18.2.7 + eslint: + specifier: ^8.38.0 + version: 8.56.0 typescript: specifier: ^5.1.6 version: 5.1.6 vite: specifier: 5.1.8 version: 5.1.8(@types/node@18.17.1) + vite-env-only: + specifier: ^2.0.0 + version: 2.2.0 vite-tsconfig-paths: specifier: ^4.2.1 version: 4.3.1(typescript@5.1.6)(vite@5.1.8) @@ -606,7 +630,7 @@ importers: specifier: ^3.24.0 version: 3.74.0(@cloudflare/workers-types@4.20240208.0) - integration/helpers/vite-template: + integration/helpers/vite-6-template: dependencies: '@remix-run/express': specifier: workspace:* @@ -620,12 +644,15 @@ importers: '@remix-run/serve': specifier: workspace:* version: link:../../../packages/remix-serve + '@remix-run/server-runtime': + specifier: workspace:* + version: link:../../../packages/remix-server-runtime '@vanilla-extract/css': specifier: ^1.10.0 version: 1.14.1 '@vanilla-extract/vite-plugin': specifier: ^3.9.2 - version: 3.9.5(vite@5.1.8) + version: 3.9.5(vite@6.0.3) express: specifier: ^4.20.0 version: 4.21.1 @@ -664,14 +691,69 @@ importers: specifier: ^5.1.6 version: 5.1.6 vite: - specifier: 5.1.8 - version: 5.1.8(@types/node@18.17.1) + specifier: ^6.0.0 + version: 6.0.3(@types/node@18.17.1) vite-env-only: specifier: ^2.0.0 version: 2.2.0 vite-tsconfig-paths: specifier: ^4.2.1 - version: 4.3.1(typescript@5.1.6)(vite@5.1.8) + version: 4.3.1(typescript@5.1.6)(vite@6.0.3) + wrangler: + specifier: ^3.24.0 + version: 3.74.0(@cloudflare/workers-types@4.20240208.0) + + integration/helpers/vite-cloudflare-template: + dependencies: + '@remix-run/cloudflare': + specifier: workspace:* + version: link:../../../packages/remix-cloudflare + '@remix-run/cloudflare-pages': + specifier: workspace:* + version: link:../../../packages/remix-cloudflare-pages + '@remix-run/react': + specifier: workspace:* + version: link:../../../packages/remix-react + '@remix-run/server-runtime': + specifier: workspace:* + version: link:../../../packages/remix-server-runtime + isbot: + specifier: ^4.1.0 + version: 4.4.0 + miniflare: + specifier: ^3.20231030.4 + version: 3.20240821.1 + react: + specifier: ^18.2.0 + version: 18.2.0 + react-dom: + specifier: ^18.2.0 + version: 18.2.0(react@18.2.0) + devDependencies: + '@cloudflare/workers-types': + specifier: ^4.20230518.0 + version: 4.20240208.0 + '@remix-run/dev': + specifier: workspace:* + version: link:../../../packages/remix-dev + '@remix-run/eslint-config': + specifier: workspace:* + version: link:../../../packages/remix-eslint-config + '@types/react': + specifier: ^18.2.20 + version: 18.2.20 + '@types/react-dom': + specifier: ^18.2.7 + version: 18.2.7 + typescript: + specifier: ^5.1.6 + version: 5.1.6 + vite: + specifier: ^6.0.0 + version: 6.0.3(@types/node@18.17.1) + vite-tsconfig-paths: + specifier: ^4.2.1 + version: 4.3.1(typescript@5.1.6)(vite@6.0.3) wrangler: specifier: ^3.24.0 version: 3.74.0(@cloudflare/workers-types@4.20240208.0) @@ -1011,9 +1093,12 @@ importers: valibot: specifier: ^0.41.0 version: 0.41.0(typescript@5.1.6) + vite: + specifier: ^5.1.0 || ^6.0.0 + version: 6.0.3(@types/node@18.17.1) vite-node: - specifier: ^1.6.0 - version: 1.6.0(@types/node@18.17.1) + specifier: 3.0.0-beta.2 + version: 3.0.0-beta.2(@types/node@18.17.1) ws: specifier: ^7.5.10 version: 7.5.10 @@ -1096,9 +1181,6 @@ importers: tiny-invariant: specifier: ^1.2.0 version: 1.3.1 - vite: - specifier: 5.1.8 - version: 5.1.8(@types/node@18.17.1) wrangler: specifier: ^3.28.2 version: 3.74.0(@cloudflare/workers-types@4.20240208.0) @@ -1306,8 +1388,8 @@ importers: specifier: ^5.1.6 version: 5.1.6 vite: - specifier: 5.1.8 - version: 5.1.8(@types/node@18.17.1) + specifier: ^6.0.0 + version: 6.0.3(@types/node@18.17.1) packages/remix-routes-option-adapter: devDependencies: @@ -3064,6 +3146,14 @@ packages: requiresBuild: true optional: true + /@esbuild/aix-ppc64@0.24.0: + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + optional: true + /@esbuild/android-arm64@0.17.19: resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} @@ -3088,6 +3178,14 @@ packages: requiresBuild: true optional: true + /@esbuild/android-arm64@0.24.0: + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + /@esbuild/android-arm@0.17.19: resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} engines: {node: '>=12'} @@ -3112,6 +3210,14 @@ packages: requiresBuild: true optional: true + /@esbuild/android-arm@0.24.0: + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + /@esbuild/android-x64@0.17.19: resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} engines: {node: '>=12'} @@ -3136,6 +3242,14 @@ packages: requiresBuild: true optional: true + /@esbuild/android-x64@0.24.0: + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + requiresBuild: true + optional: true + /@esbuild/darwin-arm64@0.17.19: resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} engines: {node: '>=12'} @@ -3160,6 +3274,14 @@ packages: requiresBuild: true optional: true + /@esbuild/darwin-arm64@0.24.0: + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + /@esbuild/darwin-x64@0.17.19: resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} engines: {node: '>=12'} @@ -3184,6 +3306,14 @@ packages: requiresBuild: true optional: true + /@esbuild/darwin-x64@0.24.0: + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + /@esbuild/freebsd-arm64@0.17.19: resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} engines: {node: '>=12'} @@ -3208,6 +3338,14 @@ packages: requiresBuild: true optional: true + /@esbuild/freebsd-arm64@0.24.0: + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + /@esbuild/freebsd-x64@0.17.19: resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} engines: {node: '>=12'} @@ -3232,6 +3370,14 @@ packages: requiresBuild: true optional: true + /@esbuild/freebsd-x64@0.24.0: + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + /@esbuild/linux-arm64@0.17.19: resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} engines: {node: '>=12'} @@ -3256,6 +3402,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-arm64@0.24.0: + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/linux-arm@0.17.19: resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} engines: {node: '>=12'} @@ -3280,6 +3434,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-arm@0.24.0: + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/linux-ia32@0.17.19: resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} engines: {node: '>=12'} @@ -3304,6 +3466,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-ia32@0.24.0: + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/linux-loong64@0.17.19: resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} engines: {node: '>=12'} @@ -3328,6 +3498,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-loong64@0.24.0: + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/linux-mips64el@0.17.19: resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} engines: {node: '>=12'} @@ -3352,6 +3530,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-mips64el@0.24.0: + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/linux-ppc64@0.17.19: resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} engines: {node: '>=12'} @@ -3376,6 +3562,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-ppc64@0.24.0: + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/linux-riscv64@0.17.19: resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} engines: {node: '>=12'} @@ -3400,6 +3594,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-riscv64@0.24.0: + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/linux-s390x@0.17.19: resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} engines: {node: '>=12'} @@ -3424,6 +3626,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-s390x@0.24.0: + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/linux-x64@0.17.19: resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} engines: {node: '>=12'} @@ -3448,6 +3658,14 @@ packages: requiresBuild: true optional: true + /@esbuild/linux-x64@0.24.0: + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + /@esbuild/netbsd-x64@0.17.19: resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} engines: {node: '>=12'} @@ -3472,6 +3690,22 @@ packages: requiresBuild: true optional: true + /@esbuild/netbsd-x64@0.24.0: + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + optional: true + + /@esbuild/openbsd-arm64@0.24.0: + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + requiresBuild: true + optional: true + /@esbuild/openbsd-x64@0.17.19: resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} engines: {node: '>=12'} @@ -3496,6 +3730,14 @@ packages: requiresBuild: true optional: true + /@esbuild/openbsd-x64@0.24.0: + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + optional: true + /@esbuild/sunos-x64@0.17.19: resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} engines: {node: '>=12'} @@ -3520,6 +3762,14 @@ packages: requiresBuild: true optional: true + /@esbuild/sunos-x64@0.24.0: + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + requiresBuild: true + optional: true + /@esbuild/win32-arm64@0.17.19: resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} engines: {node: '>=12'} @@ -3544,6 +3794,14 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-arm64@0.24.0: + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + /@esbuild/win32-ia32@0.17.19: resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} engines: {node: '>=12'} @@ -3568,6 +3826,14 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-ia32@0.24.0: + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + /@esbuild/win32-x64@0.17.19: resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} engines: {node: '>=12'} @@ -3592,6 +3858,14 @@ packages: requiresBuild: true optional: true + /@esbuild/win32-x64@0.24.0: + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4248,12 +4522,12 @@ packages: requiresBuild: true optional: true - /@playwright/test@1.41.2: - resolution: {integrity: sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg==} - engines: {node: '>=16'} + /@playwright/test@1.49.1: + resolution: {integrity: sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==} + engines: {node: '>=18'} hasBin: true dependencies: - playwright: 1.41.2 + playwright: 1.49.1 dev: false /@remix-run/changelog-github@0.0.5: @@ -4413,6 +4687,13 @@ packages: rollup: 2.79.2 dev: false + /@rollup/rollup-android-arm-eabi@4.28.1: + resolution: {integrity: sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==} + cpu: [arm] + os: [android] + requiresBuild: true + optional: true + /@rollup/rollup-android-arm-eabi@4.4.1: resolution: {integrity: sha512-Ss4suS/sd+6xLRu+MLCkED2mUrAyqHmmvZB+zpzZ9Znn9S8wCkTQCJaQ8P8aHofnvG5L16u9MVnJjCqioPErwQ==} cpu: [arm] @@ -4420,6 +4701,13 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-android-arm64@4.28.1: + resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==} + cpu: [arm64] + os: [android] + requiresBuild: true + optional: true + /@rollup/rollup-android-arm64@4.4.1: resolution: {integrity: sha512-sRSkGTvGsARwWd7TzC8LKRf8FiPn7257vd/edzmvG4RIr9x68KBN0/Ek48CkuUJ5Pj/Dp9vKWv6PEupjKWjTYA==} cpu: [arm64] @@ -4427,6 +4715,13 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-darwin-arm64@4.28.1: + resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optional: true + /@rollup/rollup-darwin-arm64@4.4.1: resolution: {integrity: sha512-nz0AiGrrXyaWpsmBXUGOBiRDU0wyfSXbFuF98pPvIO8O6auQsPG6riWsfQqmCCC5FNd8zKQ4JhgugRNAkBJ8mQ==} cpu: [arm64] @@ -4434,6 +4729,13 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-darwin-x64@4.28.1: + resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==} + cpu: [x64] + os: [darwin] + requiresBuild: true + optional: true + /@rollup/rollup-darwin-x64@4.4.1: resolution: {integrity: sha512-Ogqvf4/Ve/faMaiPRvzsJEqajbqs00LO+8vtrPBVvLgdw4wBg6ZDXdkDAZO+4MLnrc8mhGV6VJAzYScZdPLtJg==} cpu: [x64] @@ -4441,6 +4743,27 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-freebsd-arm64@4.28.1: + resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + optional: true + + /@rollup/rollup-freebsd-x64@4.28.1: + resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==} + cpu: [x64] + os: [freebsd] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.28.1: + resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + /@rollup/rollup-linux-arm-gnueabihf@4.4.1: resolution: {integrity: sha512-9zc2tqlr6HfO+hx9+wktUlWTRdje7Ub15iJqKcqg5uJZ+iKqmd2CMxlgPpXi7+bU7bjfDIuvCvnGk7wewFEhCg==} cpu: [arm] @@ -4448,6 +4771,20 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-linux-arm-musleabihf@4.28.1: + resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==} + cpu: [arm] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.28.1: + resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + /@rollup/rollup-linux-arm64-gnu@4.4.1: resolution: {integrity: sha512-phLb1fN3rq2o1j1v+nKxXUTSJnAhzhU0hLrl7Qzb0fLpwkGMHDem+o6d+ZI8+/BlTXfMU4kVWGvy6g9k/B8L6Q==} cpu: [arm64] @@ -4455,6 +4792,13 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-linux-arm64-musl@4.28.1: + resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==} + cpu: [arm64] + os: [linux] + requiresBuild: true + optional: true + /@rollup/rollup-linux-arm64-musl@4.4.1: resolution: {integrity: sha512-M2sDtw4tf57VPSjbTAN/lz1doWUqO2CbQuX3L9K6GWIR5uw9j+ROKCvvUNBY8WUbMxwaoc8mH9HmmBKsLht7+w==} cpu: [arm64] @@ -4462,6 +4806,41 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-linux-loongarch64-gnu@4.28.1: + resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==} + cpu: [loong64] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-powerpc64le-gnu@4.28.1: + resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==} + cpu: [ppc64] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.28.1: + resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-s390x-gnu@4.28.1: + resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==} + cpu: [s390x] + os: [linux] + requiresBuild: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.28.1: + resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + /@rollup/rollup-linux-x64-gnu@4.4.1: resolution: {integrity: sha512-mHIlRLX+hx+30cD6c4BaBOsSqdnCE4ok7/KDvjHYAHoSuveoMMxIisZFvcLhUnyZcPBXDGZTuBoalcuh43UfQQ==} cpu: [x64] @@ -4469,6 +4848,13 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-linux-x64-musl@4.28.1: + resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==} + cpu: [x64] + os: [linux] + requiresBuild: true + optional: true + /@rollup/rollup-linux-x64-musl@4.4.1: resolution: {integrity: sha512-tB+RZuDi3zxFx7vDrjTNGVLu2KNyzYv+UY8jz7e4TMEoAj7iEt8Qk6xVu6mo3pgjnsHj6jnq3uuRsHp97DLwOA==} cpu: [x64] @@ -4476,6 +4862,13 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-win32-arm64-msvc@4.28.1: + resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==} + cpu: [arm64] + os: [win32] + requiresBuild: true + optional: true + /@rollup/rollup-win32-arm64-msvc@4.4.1: resolution: {integrity: sha512-Hdn39PzOQowK/HZzYpCuZdJC91PE6EaGbTe2VCA9oq2u18evkisQfws0Smh9QQGNNRa/T7MOuGNQoLeXhhE3PQ==} cpu: [arm64] @@ -4483,6 +4876,13 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-win32-ia32-msvc@4.28.1: + resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==} + cpu: [ia32] + os: [win32] + requiresBuild: true + optional: true + /@rollup/rollup-win32-ia32-msvc@4.4.1: resolution: {integrity: sha512-tLpKb1Elm9fM8c5w3nl4N1eLTP4bCqTYw9tqUBxX8/hsxqHO3dxc2qPbZ9PNkdK4tg4iLEYn0pOUnVByRd2CbA==} cpu: [ia32] @@ -4490,6 +4890,13 @@ packages: requiresBuild: true optional: true + /@rollup/rollup-win32-x64-msvc@4.28.1: + resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==} + cpu: [x64] + os: [win32] + requiresBuild: true + optional: true + /@rollup/rollup-win32-x64-msvc@4.4.1: resolution: {integrity: sha512-eAhItDX9yQtZVM3yvXS/VR3qPqcnXvnLyx1pLXl4JzyNMBNO3KC986t/iAg2zcMzpAp9JSvxB5VZGnBiNoA98w==} cpu: [x64] @@ -4756,6 +5163,9 @@ packages: /@types/estree@1.0.0: resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} + /@types/estree@1.0.6: + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + /@types/express-serve-static-core@4.17.43: resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} dependencies: @@ -5342,6 +5752,28 @@ packages: - terser - ts-node + /@vanilla-extract/vite-plugin@3.9.5(vite@6.0.3): + resolution: {integrity: sha512-CWI/CtrVW6i3HKccI6T7uGQkTJ8bd8Xl2UMBg3Pkr7dwWMmavXTeucV0I9KSbmXaYXSbEj+Q8c9y0xAZwtmTig==} + peerDependencies: + vite: ^2.2.3 || ^3.0.0 || ^4.0.3 || ^5.0.0 + dependencies: + '@vanilla-extract/integration': 6.5.0(@types/node@18.17.1) + outdent: 0.8.0 + postcss: 8.4.35 + postcss-load-config: 4.0.2(postcss@8.4.35) + vite: 6.0.3(@types/node@18.17.1) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + - ts-node + dev: false + /@web3-storage/multipart-parser@1.0.0: resolution: {integrity: sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw==} dev: false @@ -6915,6 +7347,18 @@ packages: ms: 2.1.2 supports-color: 8.1.1 + /debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: false + /decamelize-keys@1.1.0: resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==} engines: {node: '>=0.10.0'} @@ -7353,6 +7797,10 @@ packages: resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} dev: false + /es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + dev: false + /es-set-tostringtag@2.0.2: resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} engines: {node: '>= 0.4'} @@ -7488,6 +7936,37 @@ packages: '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 + /esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -12325,6 +12804,9 @@ packages: /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + /picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -12372,18 +12854,18 @@ packages: mlly: 1.5.0 pathe: 1.1.2 - /playwright-core@1.41.2: - resolution: {integrity: sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA==} - engines: {node: '>=16'} + /playwright-core@1.49.1: + resolution: {integrity: sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==} + engines: {node: '>=18'} hasBin: true dev: false - /playwright@1.41.2: - resolution: {integrity: sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A==} - engines: {node: '>=16'} + /playwright@1.49.1: + resolution: {integrity: sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==} + engines: {node: '>=18'} hasBin: true dependencies: - playwright-core: 1.41.2 + playwright-core: 1.49.1 optionalDependencies: fsevents: 2.3.2 dev: false @@ -12413,6 +12895,18 @@ packages: read-cache: 1.0.0 resolve: 1.22.8 + /postcss-import@15.1.0(postcss@8.4.49): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + dev: true + /postcss-js@4.0.1(postcss@8.4.35): resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} engines: {node: ^12 || ^14 || >= 16} @@ -12522,6 +13016,14 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + /preferred-pm@3.0.3: resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==} engines: {node: '>=10'} @@ -13309,6 +13811,34 @@ packages: fsevents: 2.3.3 dev: false + /rollup@4.28.1: + resolution: {integrity: sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.28.1 + '@rollup/rollup-android-arm64': 4.28.1 + '@rollup/rollup-darwin-arm64': 4.28.1 + '@rollup/rollup-darwin-x64': 4.28.1 + '@rollup/rollup-freebsd-arm64': 4.28.1 + '@rollup/rollup-freebsd-x64': 4.28.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.28.1 + '@rollup/rollup-linux-arm-musleabihf': 4.28.1 + '@rollup/rollup-linux-arm64-gnu': 4.28.1 + '@rollup/rollup-linux-arm64-musl': 4.28.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.28.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.28.1 + '@rollup/rollup-linux-riscv64-gnu': 4.28.1 + '@rollup/rollup-linux-s390x-gnu': 4.28.1 + '@rollup/rollup-linux-x64-gnu': 4.28.1 + '@rollup/rollup-linux-x64-musl': 4.28.1 + '@rollup/rollup-win32-arm64-msvc': 4.28.1 + '@rollup/rollup-win32-ia32-msvc': 4.28.1 + '@rollup/rollup-win32-x64-msvc': 4.28.1 + fsevents: 2.3.3 + /rollup@4.4.1: resolution: {integrity: sha512-idZzrUpWSblPJX66i+GzrpjKE3vbYrlWirUHteoAbjKReZwa0cohAErOYA5efoMmNCdvG9yrJS+w9Kl6csaH4w==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -13682,6 +14212,10 @@ packages: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + /source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + /source-map-support@0.5.13: resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} dependencies: @@ -14902,6 +15436,31 @@ packages: - supports-color - terser + /vite-node@3.0.0-beta.2(@types/node@18.17.1): + resolution: {integrity: sha512-ofTf6cfRdL30Wbl9n/BX81EyIR5s4PReLmSurrxQ+koLaWUNOEo8E0lCM53OJkb8vpa2URM2nSrxZsIFyvY1rg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.5.4 + pathe: 1.1.2 + vite: 6.0.3(@types/node@18.17.1) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + dev: false + /vite-tsconfig-paths@4.3.1(typescript@5.1.6)(vite@5.1.8): resolution: {integrity: sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==} peerDependencies: @@ -14918,6 +15477,22 @@ packages: - supports-color - typescript + /vite-tsconfig-paths@4.3.1(typescript@5.1.6)(vite@6.0.3): + resolution: {integrity: sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw==} + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + debug: 4.3.4(supports-color@8.1.1) + globrex: 0.1.2 + tsconfck: 3.0.2(typescript@5.1.6) + vite: 6.0.3(@types/node@18.17.1) + transitivePeerDependencies: + - supports-color + - typescript + /vite@5.1.8(@types/node@18.17.1): resolution: {integrity: sha512-mB8ToUuSmzODSpENgvpFk2fTiU/YQ1tmcVJJ4WZbq4fPdGJkFNVcmVL5k7iDug6xzWjjuGDKAuSievIsD6H7Xw==} engines: {node: ^18.0.0 || >=20.0.0} @@ -14953,6 +15528,53 @@ packages: optionalDependencies: fsevents: 2.3.3 + /vite@6.0.3(@types/node@18.17.1): + resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + dependencies: + '@types/node': 18.17.1 + esbuild: 0.24.0 + postcss: 8.4.49 + rollup: 4.28.1 + optionalDependencies: + fsevents: 2.3.3 + /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e8c91c3e82c..cae0a89b7ea 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,26 +1,4 @@ packages: - "integration" - - "integration/helpers/node-template" - - "integration/helpers/cf-template" - - "integration/helpers/deno-template" - - "integration/helpers/vite-cloudflare-template" - - "integration/helpers/vite-template" - - "packages/create-remix" - - "packages/remix" - - "packages/remix-architect" - - "packages/remix-cloudflare" - - "packages/remix-cloudflare-pages" - - "packages/remix-cloudflare-workers" - - "packages/remix-css-bundle" - - "packages/remix-deno" - - "packages/remix-dev" - - "packages/remix-eslint-config" - - "packages/remix-express" - - "packages/remix-fs-routes" - - "packages/remix-node" - - "packages/remix-react" - - "packages/remix-route-config" - - "packages/remix-routes-option-adapter" - - "packages/remix-serve" - - "packages/remix-server-runtime" - - "packages/remix-testing" + - "integration/helpers/*" + - "packages/*" diff --git a/templates/cloudflare-workers/package.json b/templates/cloudflare-workers/package.json index 05f8a969ee8..d84d92f8ba5 100644 --- a/templates/cloudflare-workers/package.json +++ b/templates/cloudflare-workers/package.json @@ -36,7 +36,7 @@ "postcss": "^8.4.38", "tailwindcss": "^3.4.4", "typescript": "^5.1.6", - "vite": "^5.1.0", + "vite": "^6.0.0", "vite-tsconfig-paths": "^4.2.1", "wrangler": "3.84.0" }, diff --git a/templates/cloudflare/package.json b/templates/cloudflare/package.json index a5e4ad758f9..143b49d5704 100644 --- a/templates/cloudflare/package.json +++ b/templates/cloudflare/package.json @@ -36,7 +36,7 @@ "postcss": "^8.4.38", "tailwindcss": "^3.4.4", "typescript": "^5.1.6", - "vite": "^5.1.0", + "vite": "^6.0.0", "vite-tsconfig-paths": "^4.2.1", "wrangler": "3.57.1" }, diff --git a/templates/express/package.json b/templates/express/package.json index 76cfea70840..46cfef75153 100644 --- a/templates/express/package.json +++ b/templates/express/package.json @@ -40,7 +40,7 @@ "postcss": "^8.4.38", "tailwindcss": "^3.4.4", "typescript": "^5.1.6", - "vite": "^5.1.0", + "vite": "^6.0.0", "vite-tsconfig-paths": "^4.2.1" }, "engines": { diff --git a/templates/remix-javascript/package.json b/templates/remix-javascript/package.json index 37ef4a0149f..da45a9f8994 100644 --- a/templates/remix-javascript/package.json +++ b/templates/remix-javascript/package.json @@ -26,7 +26,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "postcss": "^8.4.38", "tailwindcss": "^3.4.4", - "vite": "^5.1.0" + "vite": "^6.0.0" }, "engines": { "node": ">=20.0.0" diff --git a/templates/remix-tutorial/package.json b/templates/remix-tutorial/package.json index 33f36e251e7..b097107debd 100644 --- a/templates/remix-tutorial/package.json +++ b/templates/remix-tutorial/package.json @@ -33,7 +33,7 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.6", - "vite": "^5.1.4", + "vite": "^6.0.0", "vite-tsconfig-paths": "^4.3.1" }, "engines": { diff --git a/templates/remix/package.json b/templates/remix/package.json index 439b4d75a6a..a67dfacc2ce 100644 --- a/templates/remix/package.json +++ b/templates/remix/package.json @@ -33,7 +33,7 @@ "postcss": "^8.4.38", "tailwindcss": "^3.4.4", "typescript": "^5.1.6", - "vite": "^5.1.0", + "vite": "^6.0.0", "vite-tsconfig-paths": "^4.2.1" }, "engines": { diff --git a/templates/spa/package.json b/templates/spa/package.json index 29f994629d9..3c9ca2040d4 100644 --- a/templates/spa/package.json +++ b/templates/spa/package.json @@ -31,7 +31,7 @@ "postcss": "^8.4.38", "tailwindcss": "^3.4.4", "typescript": "^5.1.6", - "vite": "^5.1.0", + "vite": "^6.0.0", "vite-tsconfig-paths": "^4.2.1" }, "engines": {