From f6403aaa6b0dae95c8e753cbed8205ec957df85e Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Mon, 10 Feb 2025 13:25:27 +0100 Subject: [PATCH 01/18] move playwright tests into separate folder --- integration-test/nextjs/package.json | 1 - integration-test/nextjs/tsconfig.json | 25 +++++++++++++---- .../{nextjs => playwright}/empty.har | 0 .../{nextjs => playwright}/fixture.ts | 0 integration-test/playwright/package.json | 12 ++++++++ .../playwright.config.ts | 0 .../src/cc-dynamic.test.ts} | 2 +- .../src/cc-static.test.ts} | 2 +- .../src/rsc-dynamic-PreloadQuery.test.ts} | 2 +- .../src/rsc-dynamic.test.ts} | 2 +- .../src/rsc-static.test.ts} | 2 +- integration-test/playwright/tsconfig.json | 28 +++++++++++++++++++ yarn.lock | 10 ++++++- 13 files changed, 74 insertions(+), 12 deletions(-) rename integration-test/{nextjs => playwright}/empty.har (100%) rename integration-test/{nextjs => playwright}/fixture.ts (100%) create mode 100644 integration-test/playwright/package.json rename integration-test/{nextjs => playwright}/playwright.config.ts (100%) rename integration-test/{nextjs/src/app/cc/dynamic/dynamic.test.ts => playwright/src/cc-dynamic.test.ts} (99%) rename integration-test/{nextjs/src/app/cc/static/static.test.ts => playwright/src/cc-static.test.ts} (96%) rename integration-test/{nextjs/src/app/rsc/dynamic/PreloadQuery/PreloadQuery.test.ts => playwright/src/rsc-dynamic-PreloadQuery.test.ts} (99%) rename integration-test/{nextjs/src/app/rsc/dynamic/apollo-client.test.ts => playwright/src/rsc-dynamic.test.ts} (87%) rename integration-test/{nextjs/src/app/rsc/static/apollo-client.test.ts => playwright/src/rsc-static.test.ts} (87%) create mode 100644 integration-test/playwright/tsconfig.json diff --git a/integration-test/nextjs/package.json b/integration-test/nextjs/package.json index 08efaf05..fe6b4235 100644 --- a/integration-test/nextjs/package.json +++ b/integration-test/nextjs/package.json @@ -30,7 +30,6 @@ "typescript": "5.1.3" }, "devDependencies": { - "@playwright/test": "^1.49.1", "webpack-stats-plugin": "^1.1.3" } } diff --git a/integration-test/nextjs/tsconfig.json b/integration-test/nextjs/tsconfig.json index a98b748c..c471aef8 100644 --- a/integration-test/nextjs/tsconfig.json +++ b/integration-test/nextjs/tsconfig.json @@ -1,7 +1,11 @@ { "compilerOptions": { "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -20,9 +24,20 @@ } ], "paths": { - "@/*": ["./src/*"] + "@/*": [ + "./src/*" + ] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "../shared/*.ts"], - "exclude": ["node_modules"] -} + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "../shared/*.ts", + "../playwright/fixture.ts" + ], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/integration-test/nextjs/empty.har b/integration-test/playwright/empty.har similarity index 100% rename from integration-test/nextjs/empty.har rename to integration-test/playwright/empty.har diff --git a/integration-test/nextjs/fixture.ts b/integration-test/playwright/fixture.ts similarity index 100% rename from integration-test/nextjs/fixture.ts rename to integration-test/playwright/fixture.ts diff --git a/integration-test/playwright/package.json b/integration-test/playwright/package.json new file mode 100644 index 00000000..78971b79 --- /dev/null +++ b/integration-test/playwright/package.json @@ -0,0 +1,12 @@ +{ + "name": "@integration-test/playwright", + "version": "0.0.0", + "private": true, + "scripts": { + "test": "yarn playwright test" + }, + "devDependencies": { + "@playwright/test": "^1.49.1", + "typescript": "5.1.3" + } +} diff --git a/integration-test/nextjs/playwright.config.ts b/integration-test/playwright/playwright.config.ts similarity index 100% rename from integration-test/nextjs/playwright.config.ts rename to integration-test/playwright/playwright.config.ts diff --git a/integration-test/nextjs/src/app/cc/dynamic/dynamic.test.ts b/integration-test/playwright/src/cc-dynamic.test.ts similarity index 99% rename from integration-test/nextjs/src/app/cc/dynamic/dynamic.test.ts rename to integration-test/playwright/src/cc-dynamic.test.ts index 23b79bcf..c2c5d2be 100644 --- a/integration-test/nextjs/src/app/cc/dynamic/dynamic.test.ts +++ b/integration-test/playwright/src/cc-dynamic.test.ts @@ -1,5 +1,5 @@ import { expect } from "@playwright/test"; -import { test } from "../../../../fixture"; +import { test } from "../fixture"; const regex_connection_closed_early = /streaming connection closed before server query could be fully transported, rerunning/i; diff --git a/integration-test/nextjs/src/app/cc/static/static.test.ts b/integration-test/playwright/src/cc-static.test.ts similarity index 96% rename from integration-test/nextjs/src/app/cc/static/static.test.ts rename to integration-test/playwright/src/cc-static.test.ts index 18f4c13a..9b7a193c 100644 --- a/integration-test/nextjs/src/app/cc/static/static.test.ts +++ b/integration-test/playwright/src/cc-static.test.ts @@ -1,5 +1,5 @@ import { expect } from "@playwright/test"; -import { test } from "../../../../fixture"; +import { test } from "../fixture"; test.describe("CC static", () => { test.describe("useSuspenseQuery", () => { diff --git a/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/PreloadQuery.test.ts b/integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts similarity index 99% rename from integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/PreloadQuery.test.ts rename to integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts index 82f1bf2b..37c38052 100644 --- a/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/PreloadQuery.test.ts +++ b/integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts @@ -1,5 +1,5 @@ import { expect } from "@playwright/test"; -import { test } from "../../../../../fixture"; +import { test } from "../fixture"; const reactErr419 = /(Minified React error #419|Switched to client rendering)/; diff --git a/integration-test/nextjs/src/app/rsc/dynamic/apollo-client.test.ts b/integration-test/playwright/src/rsc-dynamic.test.ts similarity index 87% rename from integration-test/nextjs/src/app/rsc/dynamic/apollo-client.test.ts rename to integration-test/playwright/src/rsc-dynamic.test.ts index 31804886..d6670606 100644 --- a/integration-test/nextjs/src/app/rsc/dynamic/apollo-client.test.ts +++ b/integration-test/playwright/src/rsc-dynamic.test.ts @@ -1,5 +1,5 @@ import { expect } from "@playwright/test"; -import { test } from "../../../../fixture"; +import { test } from "../fixture"; test.describe("RSC dynamic", () => { test("query (one query)", async ({ page, blockRequest }) => { diff --git a/integration-test/nextjs/src/app/rsc/static/apollo-client.test.ts b/integration-test/playwright/src/rsc-static.test.ts similarity index 87% rename from integration-test/nextjs/src/app/rsc/static/apollo-client.test.ts rename to integration-test/playwright/src/rsc-static.test.ts index 283eb216..b8d347c3 100644 --- a/integration-test/nextjs/src/app/rsc/static/apollo-client.test.ts +++ b/integration-test/playwright/src/rsc-static.test.ts @@ -1,5 +1,5 @@ import { expect } from "@playwright/test"; -import { test } from "../../../../fixture"; +import { test } from "../fixture"; test.describe("RSC static", () => { test("query (one query)", async ({ page, blockRequest }) => { diff --git a/integration-test/playwright/tsconfig.json b/integration-test/playwright/tsconfig.json new file mode 100644 index 00000000..a98b748c --- /dev/null +++ b/integration-test/playwright/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "../shared/*.ts"], + "exclude": ["node_modules"] +} diff --git a/yarn.lock b/yarn.lock index 7960398f..05c77d5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6534,7 +6534,6 @@ __metadata: "@as-integrations/next": "npm:^3.2.0" "@graphql-tools/schema": "npm:^10.0.0" "@integration-test/shared": "workspace:^" - "@playwright/test": "npm:^1.49.1" "@types/node": "npm:20.3.1" "@types/react": "npm:^19.0.0" "@types/react-dom": "npm:^19.0.0" @@ -6551,6 +6550,15 @@ __metadata: languageName: unknown linkType: soft +"@integration-test/playwright@workspace:integration-test/playwright": + version: 0.0.0-use.local + resolution: "@integration-test/playwright@workspace:integration-test/playwright" + dependencies: + "@playwright/test": "npm:^1.49.1" + typescript: "npm:5.1.3" + languageName: unknown + linkType: soft + "@integration-test/react-router@workspace:integration-test/react-router": version: 0.0.0-use.local resolution: "@integration-test/react-router@workspace:integration-test/react-router" From 7041cede38f44b43ac7279c397b3647d2de695cf Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Mon, 10 Feb 2025 13:44:24 +0100 Subject: [PATCH 02/18] tag tests, hook script up --- integration-test/nextjs/package.json | 2 +- integration-test/playwright/package.json | 3 +- .../playwright/playwright.config.ts | 4 +- .../playwright/src/cc-dynamic.test.ts | 198 ++++++++-------- .../playwright/src/cc-static.test.ts | 52 +++-- .../src/rsc-dynamic-PreloadQuery.test.ts | 220 +++++++++--------- .../playwright/src/rsc-dynamic.test.ts | 22 +- .../playwright/src/rsc-static.test.ts | 22 +- 8 files changed, 280 insertions(+), 243 deletions(-) diff --git a/integration-test/nextjs/package.json b/integration-test/nextjs/package.json index fe6b4235..87cb9033 100644 --- a/integration-test/nextjs/package.json +++ b/integration-test/nextjs/package.json @@ -7,7 +7,7 @@ "build": "next build", "start": "next start", "build-and-test": "yarn build && yarn test", - "test": "yarn playwright test" + "test": "yarn test:nextjs" }, "dependencies": { "@apollo/client": "^3.11.10", diff --git a/integration-test/playwright/package.json b/integration-test/playwright/package.json index 78971b79..9ba22ed2 100644 --- a/integration-test/playwright/package.json +++ b/integration-test/playwright/package.json @@ -3,7 +3,8 @@ "version": "0.0.0", "private": true, "scripts": { - "test": "yarn playwright test" + "test": "yarn playwright test", + "test:nextjs": "TEST_PROJECT_DIR=../nextjs yarn playwright test --grep nextjs" }, "devDependencies": { "@playwright/test": "^1.49.1", diff --git a/integration-test/playwright/playwright.config.ts b/integration-test/playwright/playwright.config.ts index 85301760..e155bf0e 100644 --- a/integration-test/playwright/playwright.config.ts +++ b/integration-test/playwright/playwright.config.ts @@ -1,10 +1,12 @@ import { defineConfig } from "@playwright/test"; +import { resolve } from "node:path"; export default defineConfig({ webServer: process.env.BASE_URL ? undefined : { - command: "yarn next start", + command: "yarn start", + cwd: resolve(__dirname, process.env.TEST_PROJECT_DIR), port: 3000, timeout: 15 * 1000, reuseExistingServer: !process.env.CI, diff --git a/integration-test/playwright/src/cc-dynamic.test.ts b/integration-test/playwright/src/cc-dynamic.test.ts index c2c5d2be..546e9750 100644 --- a/integration-test/playwright/src/cc-dynamic.test.ts +++ b/integration-test/playwright/src/cc-dynamic.test.ts @@ -7,126 +7,132 @@ const regex_query_error_restart = /query failed on server, rerunning in browser/i; const reactErr419 = /(Minified React error #419|Switched to client rendering)/; -test.describe("CC dynamic", () => { - test.describe("useSuspenseQuery", () => { - test("one query", async ({ page, blockRequest, hydrationFinished }) => { - await page.goto("/cc/dynamic/useSuspenseQuery", { - waitUntil: "commit", - }); - - await expect(page).toBeInitiallyLoading(false); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); +test.describe( + "CC dynamic", + { + tag: ["@nextjs"], + }, + () => { + test.describe("useSuspenseQuery", () => { + test("one query", async ({ page, blockRequest, hydrationFinished }) => { + await page.goto("/cc/dynamic/useSuspenseQuery", { + waitUntil: "commit", + }); - await hydrationFinished; - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); + await expect(page).toBeInitiallyLoading(false); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - test("error during SSR restarts query in browser", async ({ - page, - hydrationFinished, - }) => { - page.allowErrors?.(); - let allLogs: string[] = []; - page.on("console", (message) => { - allLogs.push(message.text()); + await hydrationFinished; + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); }); - await page.goto("/cc/dynamic/useSuspenseQueryWithError", { - waitUntil: "commit", - }); + test("error during SSR restarts query in browser", async ({ + page, + hydrationFinished, + }) => { + page.allowErrors?.(); + let allLogs: string[] = []; + page.on("console", (message) => { + allLogs.push(message.text()); + }); + + await page.goto("/cc/dynamic/useSuspenseQueryWithError", { + waitUntil: "commit", + }); - await expect(page).toBeInitiallyLoading(true); + await expect(page).toBeInitiallyLoading(true); - await page.waitForEvent("console", (message) => { - return regex_query_error_restart.test(message.text()); - }); - await page.waitForEvent("pageerror", (error) => { - return reactErr419.test(error.message); - }); + await page.waitForEvent("console", (message) => { + return regex_query_error_restart.test(message.text()); + }); + await page.waitForEvent("pageerror", (error) => { + return reactErr419.test(error.message); + }); - await hydrationFinished; - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + await hydrationFinished; + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - for (const log of allLogs) { - expect(log).not.toMatch(regex_connection_closed_early); - } - }); - }); - - test.describe("useBackgroundQuery + useReadQuery", () => { - test("one query", async ({ page, blockRequest, hydrationFinished }) => { - await page.goto("/cc/dynamic/useBackgroundQuery", { - waitUntil: "commit", + for (const log of allLogs) { + expect(log).not.toMatch(regex_connection_closed_early); + } }); + }); - await expect(page).toBeInitiallyLoading(true); - await expect(page.getByText("loading")).not.toBeVisible(); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + test.describe("useBackgroundQuery + useReadQuery", () => { + test("one query", async ({ page, blockRequest, hydrationFinished }) => { + await page.goto("/cc/dynamic/useBackgroundQuery", { + waitUntil: "commit", + }); - await hydrationFinished; - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); + await expect(page).toBeInitiallyLoading(true); + await expect(page.getByText("loading")).not.toBeVisible(); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - // this will close the connection before the final result is received, so it can never be forwarded - test("no `useReadQuery` on the server", async ({ page }) => { - await page.goto("/cc/dynamic/useBackgroundQueryWithoutSsrReadQuery", { - waitUntil: "commit", + await hydrationFinished; + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); }); - await expect(page.getByText("rendered on server")).toBeVisible(); + // this will close the connection before the final result is received, so it can never be forwarded + test("no `useReadQuery` on the server", async ({ page }) => { + await page.goto("/cc/dynamic/useBackgroundQueryWithoutSsrReadQuery", { + waitUntil: "commit", + }); - await page.waitForEvent("console", (message) => { - return regex_connection_closed_early.test(message.text()); - }); + await expect(page.getByText("rendered on server")).toBeVisible(); - await expect(page.getByText("rendered on client")).toBeVisible(); - await expect(page.getByText("loading")).toBeVisible(); - await expect(page.getByText("loading")).not.toBeVisible(); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); - }); - test.describe("useQuery", () => { - test("without cache value", async ({ page }) => { - await page.goto("/cc/dynamic/useQuery", { - waitUntil: "commit", - }); + await page.waitForEvent("console", (message) => { + return regex_connection_closed_early.test(message.text()); + }); - await expect(page).toBeInitiallyLoading(true); - await expect(page.getByText("loading")).not.toBeVisible(); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + await expect(page.getByText("rendered on client")).toBeVisible(); + await expect(page.getByText("loading")).toBeVisible(); + await expect(page.getByText("loading")).not.toBeVisible(); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + }); }); + test.describe("useQuery", () => { + test("without cache value", async ({ page }) => { + await page.goto("/cc/dynamic/useQuery", { + waitUntil: "commit", + }); - test("with cache value", async ({ page }) => { - await page.goto("/cc/dynamic/useQueryWithCache", { - waitUntil: "commit", + await expect(page).toBeInitiallyLoading(true); + await expect(page.getByText("loading")).not.toBeVisible(); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); }); - await expect(page).toBeInitiallyLoading(false); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); - }); - test.describe("useSuspenseQuery with a nonce", () => { - test("invalid: logs an error", async ({ page, blockRequest }) => { - await page.goto("/cc/dynamic/useSuspenseQuery?nonce=invalid", { - waitUntil: "commit", - }); + test("with cache value", async ({ page }) => { + await page.goto("/cc/dynamic/useQueryWithCache", { + waitUntil: "commit", + }); - await page.waitForEvent("console", (message) => { - return /^Refused to execute inline script because it violates the following Content Security Policy/.test( - message.text() - ); + await expect(page).toBeInitiallyLoading(false); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); }); }); - test("valid: does not log an error", async ({ page, blockRequest }) => { - await page.goto( - "/cc/dynamic/useSuspenseQuery?nonce=8IBTHwOdqNKAWeKl7plt8g==", - { + test.describe("useSuspenseQuery with a nonce", () => { + test("invalid: logs an error", async ({ page, blockRequest }) => { + await page.goto("/cc/dynamic/useSuspenseQuery?nonce=invalid", { waitUntil: "commit", - } - ); + }); - const messagePromise = page.waitForEvent("console"); - expect(messagePromise).rejects.toThrow(/waiting for event \"console\"/); + await page.waitForEvent("console", (message) => { + return /^Refused to execute inline script because it violates the following Content Security Policy/.test( + message.text() + ); + }); + }); + test("valid: does not log an error", async ({ page, blockRequest }) => { + await page.goto( + "/cc/dynamic/useSuspenseQuery?nonce=8IBTHwOdqNKAWeKl7plt8g==", + { + waitUntil: "commit", + } + ); + + const messagePromise = page.waitForEvent("console"); + expect(messagePromise).rejects.toThrow(/waiting for event \"console\"/); + }); }); - }); -}); + } +); diff --git a/integration-test/playwright/src/cc-static.test.ts b/integration-test/playwright/src/cc-static.test.ts index 9b7a193c..bd8f5272 100644 --- a/integration-test/playwright/src/cc-static.test.ts +++ b/integration-test/playwright/src/cc-static.test.ts @@ -1,31 +1,37 @@ import { expect } from "@playwright/test"; import { test } from "../fixture"; -test.describe("CC static", () => { - test.describe("useSuspenseQuery", () => { - test("one query", async ({ page, blockRequest, hydrationFinished }) => { - await page.goto("/cc/static/useSuspenseQuery", { - waitUntil: "commit", - }); +test.describe( + "CC static", + { + tag: ["@nextjs"], + }, + () => { + test.describe("useSuspenseQuery", () => { + test("one query", async ({ page, blockRequest, hydrationFinished }) => { + await page.goto("/cc/static/useSuspenseQuery", { + waitUntil: "commit", + }); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - await hydrationFinished; - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + await hydrationFinished; + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + }); }); - }); - test.describe("useBackgroundQuery", () => { - // this will close the connection before the final result is received, so it can never be forwarded - test("no `useReadQuery` on the server", async ({ page }) => { - await page.goto("/cc/static/useBackgroundQueryWithoutSsrReadQuery", { - waitUntil: "commit", - }); + test.describe("useBackgroundQuery", () => { + // this will close the connection before the final result is received, so it can never be forwarded + test("no `useReadQuery` on the server", async ({ page }) => { + await page.goto("/cc/static/useBackgroundQueryWithoutSsrReadQuery", { + waitUntil: "commit", + }); - await expect(page.getByText("rendered on server")).toBeVisible(); - await expect(page.getByText("rendered on client")).toBeVisible(); - await expect(page.getByText("loading")).toBeVisible(); - await expect(page.getByText("loading")).not.toBeVisible(); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + await expect(page.getByText("rendered on server")).toBeVisible(); + await expect(page.getByText("rendered on client")).toBeVisible(); + await expect(page.getByText("loading")).toBeVisible(); + await expect(page.getByText("loading")).not.toBeVisible(); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + }); }); - }); -}); + } +); diff --git a/integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts b/integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts index 37c38052..2cfeb99b 100644 --- a/integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts +++ b/integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts @@ -3,92 +3,43 @@ import { test } from "../fixture"; const reactErr419 = /(Minified React error #419|Switched to client rendering)/; -test.describe("PreloadQuery", () => { - for (const [description, path] of [ - ["with useSuspenseQuery", "useSuspenseQuery"], - ["with queryRef and useReadQuery", "queryRef-useReadQuery"], - ] as const) { - test.describe(description, () => { - test("query resolves on the server", async ({ page, blockRequest }) => { - await page.goto( - `/rsc/dynamic/PreloadQuery/${path}?errorIn=ssr,browser`, - { - waitUntil: "commit", - } - ); - - await expect(page).toBeInitiallyLoading(true); - await expect(page.getByText("loading")).not.toBeVisible(); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - await expect( - page.getByText("Queried in RSC environment") - ).toBeVisible(); - }); - - test("link chain errors on the server, restarts in the browser", async ({ - page, - }) => { - page.allowErrors?.(); - await page.goto( - `/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc,network_error`, - { - waitUntil: "commit", - } - ); - - await expect(page).toBeInitiallyLoading(true); - - await page.waitForEvent("pageerror", (error) => { - return reactErr419.test(error.message); - }); - - await expect(page.getByText("loading")).not.toBeVisible(); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - await expect( - page.getByText("Queried in Browser environment") - ).toBeVisible(); - }); - - if (path === "queryRef-useReadQuery") { - // this only works for `useReadQuery`, because `useSuspenseQuery` won't attach - // to the exact same suspenseCache entry and as a result, it won't get the - // error message from the ReadableStream. - test("graphqlError on the server, transported to the browser, can be restarted", async ({ - page, - }) => { - page.allowErrors?.(); - await page.goto(`/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc`, { - waitUntil: "commit", - }); +test.describe( + "PreloadQuery", + { + tag: ["@nextjs"], + }, + () => { + for (const [description, path] of [ + ["with useSuspenseQuery", "useSuspenseQuery"], + ["with queryRef and useReadQuery", "queryRef-useReadQuery"], + ] as const) { + test.describe(description, () => { + test("query resolves on the server", async ({ page, blockRequest }) => { + await page.goto( + `/rsc/dynamic/PreloadQuery/${path}?errorIn=ssr,browser`, + { + waitUntil: "commit", + } + ); await expect(page).toBeInitiallyLoading(true); - await expect(page.getByText("loading")).not.toBeVisible(); - - await expect(page.getByText("Encountered an error:")).toBeVisible(); - await expect(page.getByText("Simulated error")).toBeVisible(); - - page.getByRole("button", { name: "Try again" }).click(); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); await expect( - page.getByText("Queried in Browser environment") + page.getByText("Queried in RSC environment") ).toBeVisible(); }); - } else { - // instead, `useSuspenseQuery` will behave as if nothing had been transported - // and rerun the query in the browser. - // there is a chance it will also rerun the query during SSR, that's a timing - // question that might need further investigation - // the bottom line: `PreloadQuery` with `useSuspenseQuery` works in the happy - // path, but it's not as robust as `queryRef` with `useReadQuery`. - test("graphqlError on the server, restarts in the browser", async ({ + + test("link chain errors on the server, restarts in the browser", async ({ page, }) => { page.allowErrors?.(); - await page.goto(`/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc`, { - waitUntil: "commit", - }); + await page.goto( + `/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc,network_error`, + { + waitUntil: "commit", + } + ); await expect(page).toBeInitiallyLoading(true); @@ -102,37 +53,96 @@ test.describe("PreloadQuery", () => { page.getByText("Queried in Browser environment") ).toBeVisible(); }); - } - }); - } - test("queryRef works with useQueryRefHandlers", async ({ page }) => { - await page.goto(`/rsc/dynamic/PreloadQuery/queryRef-useReadQuery`, { - waitUntil: "commit", - }); + if (path === "queryRef-useReadQuery") { + // this only works for `useReadQuery`, because `useSuspenseQuery` won't attach + // to the exact same suspenseCache entry and as a result, it won't get the + // error message from the ReadableStream. + test("graphqlError on the server, transported to the browser, can be restarted", async ({ + page, + }) => { + page.allowErrors?.(); + await page.goto(`/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc`, { + waitUntil: "commit", + }); + + await expect(page).toBeInitiallyLoading(true); + + await expect(page.getByText("loading")).not.toBeVisible(); + + await expect(page.getByText("Encountered an error:")).toBeVisible(); + await expect(page.getByText("Simulated error")).toBeVisible(); + + page.getByRole("button", { name: "Try again" }).click(); + + await expect( + page.getByText("Soft Warm Apollo Beanie") + ).toBeVisible(); + await expect( + page.getByText("Queried in Browser environment") + ).toBeVisible(); + }); + } else { + // instead, `useSuspenseQuery` will behave as if nothing had been transported + // and rerun the query in the browser. + // there is a chance it will also rerun the query during SSR, that's a timing + // question that might need further investigation + // the bottom line: `PreloadQuery` with `useSuspenseQuery` works in the happy + // path, but it's not as robust as `queryRef` with `useReadQuery`. + test("graphqlError on the server, restarts in the browser", async ({ + page, + }) => { + page.allowErrors?.(); + await page.goto(`/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc`, { + waitUntil: "commit", + }); + + await expect(page).toBeInitiallyLoading(true); + + await page.waitForEvent("pageerror", (error) => { + return reactErr419.test(error.message); + }); + + await expect(page.getByText("loading")).not.toBeVisible(); + await expect( + page.getByText("Soft Warm Apollo Beanie") + ).toBeVisible(); + await expect( + page.getByText("Queried in Browser environment") + ).toBeVisible(); + }); + } + }); + } - await expect(page).toBeInitiallyLoading(true); - await expect(page.getByText("loading")).not.toBeVisible(); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - await expect(page.getByText("Queried in RSC environment")).toBeVisible(); - - await page.getByRole("button", { name: "refetch" }).click(); - await expect( - page.getByText("Queried in Browser environment") - ).toBeVisible(); - }); - - test.skip("queryRef: assumptions about referential equality", async ({ - page, - }) => { - await page.goto(`/rsc/dynamic/PreloadQuery/queryRef-refTest`, { - waitUntil: "commit", + test("queryRef works with useQueryRefHandlers", async ({ page }) => { + await page.goto(`/rsc/dynamic/PreloadQuery/queryRef-useReadQuery`, { + waitUntil: "commit", + }); + + await expect(page).toBeInitiallyLoading(true); + await expect(page.getByText("loading")).not.toBeVisible(); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + await expect(page.getByText("Queried in RSC environment")).toBeVisible(); + + await page.getByRole("button", { name: "refetch" }).click(); + await expect( + page.getByText("Queried in Browser environment") + ).toBeVisible(); }); - await page.getByRole("spinbutton").nth(11).waitFor(); + test.skip("queryRef: assumptions about referential equality", async ({ + page, + }) => { + await page.goto(`/rsc/dynamic/PreloadQuery/queryRef-refTest`, { + waitUntil: "commit", + }); - for (let i = 0; i < 12; i++) { - await expect(page.getByRole("spinbutton").nth(i)).toHaveClass("valid"); - } - }); -}); + await page.getByRole("spinbutton").nth(11).waitFor(); + + for (let i = 0; i < 12; i++) { + await expect(page.getByRole("spinbutton").nth(i)).toHaveClass("valid"); + } + }); + } +); diff --git a/integration-test/playwright/src/rsc-dynamic.test.ts b/integration-test/playwright/src/rsc-dynamic.test.ts index d6670606..d3b76abf 100644 --- a/integration-test/playwright/src/rsc-dynamic.test.ts +++ b/integration-test/playwright/src/rsc-dynamic.test.ts @@ -1,12 +1,18 @@ import { expect } from "@playwright/test"; import { test } from "../fixture"; -test.describe("RSC dynamic", () => { - test("query (one query)", async ({ page, blockRequest }) => { - await page.goto("/rsc/dynamic/query", { - waitUntil: "commit", - }); +test.describe( + "RSC dynamic", + { + tag: ["@nextjs"], + }, + () => { + test("query (one query)", async ({ page, blockRequest }) => { + await page.goto("/rsc/dynamic/query", { + waitUntil: "commit", + }); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); -}); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + }); + } +); diff --git a/integration-test/playwright/src/rsc-static.test.ts b/integration-test/playwright/src/rsc-static.test.ts index b8d347c3..7fcf1122 100644 --- a/integration-test/playwright/src/rsc-static.test.ts +++ b/integration-test/playwright/src/rsc-static.test.ts @@ -1,12 +1,18 @@ import { expect } from "@playwright/test"; import { test } from "../fixture"; -test.describe("RSC static", () => { - test("query (one query)", async ({ page, blockRequest }) => { - await page.goto("/rsc/static/query", { - waitUntil: "commit", - }); +test.describe( + "RSC static", + { + tag: ["@nextjs"], + }, + () => { + test("query (one query)", async ({ page, blockRequest }) => { + await page.goto("/rsc/static/query", { + waitUntil: "commit", + }); - await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); -}); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + }); + } +); From 57ebe0d8dd4f8cb29b300f115ccf0ec7f17f1ce7 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Mon, 10 Feb 2025 13:59:14 +0100 Subject: [PATCH 03/18] fix config for knip --- integration-test/playwright/playwright.config.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/integration-test/playwright/playwright.config.ts b/integration-test/playwright/playwright.config.ts index e155bf0e..cc8ebf5e 100644 --- a/integration-test/playwright/playwright.config.ts +++ b/integration-test/playwright/playwright.config.ts @@ -6,7 +6,9 @@ export default defineConfig({ ? undefined : { command: "yarn start", - cwd: resolve(__dirname, process.env.TEST_PROJECT_DIR), + cwd: process.env.TEST_PROJECT_DIR + ? resolve(__dirname, process.env.TEST_PROJECT_DIR) + : undefined, port: 3000, timeout: 15 * 1000, reuseExistingServer: !process.env.CI, From 0a3c8a868e9d2a556676b9ea6dad1828cd550f23 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Mon, 10 Feb 2025 14:45:39 +0100 Subject: [PATCH 04/18] rename route --- ...seQuery.tsx => useSuspenseQuery-defer.tsx} | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) rename integration-test/tanstack-start/app/routes/{useSuspenseQuery.tsx => useSuspenseQuery-defer.tsx} (58%) diff --git a/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx b/integration-test/tanstack-start/app/routes/useSuspenseQuery-defer.tsx similarity index 58% rename from integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx rename to integration-test/tanstack-start/app/routes/useSuspenseQuery-defer.tsx index adbc20a5..1204f8ea 100644 --- a/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx +++ b/integration-test/tanstack-start/app/routes/useSuspenseQuery-defer.tsx @@ -1,18 +1,18 @@ -import { createFileRoute } from "@tanstack/react-router"; -import { DEFERRED_QUERY } from "@integration-test/shared/queries"; -import { useApolloClient, useSuspenseQuery } from "@apollo/client/index.js"; -import { useTransition } from "react"; +import { createFileRoute } from '@tanstack/react-router' +import { DEFERRED_QUERY } from '@integration-test/shared/queries' +import { useApolloClient, useSuspenseQuery } from '@apollo/client/index.js' +import { useTransition } from 'react' -export const Route = createFileRoute("/useSuspenseQuery")({ +export const Route = createFileRoute('/useSuspenseQuery-defer')({ component: RouteComponent, -}); +}) function RouteComponent() { - const [refetching, startTransition] = useTransition(); - const client = useApolloClient(); + const [refetching, startTransition] = useTransition() + const client = useApolloClient() const { data, refetch } = useSuspenseQuery(DEFERRED_QUERY, { variables: { delayDeferred: 1000 }, - }); + }) return ( <> @@ -21,11 +21,11 @@ function RouteComponent() {
  • {title}
    - Rating:{" "} -
    - {rating?.value || ""} + Rating:{' '} +
    + {rating?.value || ''}
    - {rating ? `Queried in ${rating.env} environment` : "loading..."} + {rating ? `Queried in ${rating.env} environment` : 'loading...'}
  • ))} @@ -42,17 +42,17 @@ function RouteComponent() { fields: { rating: () => null, }, - }); + }) } }, - }); + }) startTransition(() => { - refetch(); - }); + refetch() + }) }} > - {refetching ? "refetching..." : "refetch"} + {refetching ? 'refetching...' : 'refetch'} - ); + ) } From 04540f1248d464a172053c0e74719653693c5a7e Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Mon, 10 Feb 2025 16:25:22 +0100 Subject: [PATCH 05/18] first tests --- .../nextjs/src/app/cc/ApolloWrapper.tsx | 4 +- .../cc/dynamic/useBackgroundQuery/page.tsx | 4 +- .../page.tsx | 4 +- .../app/cc/dynamic/useSuspenseQuery/page.tsx | 25 ++- .../useSuspenseQueryWithError/page.tsx | 55 ------- .../page.tsx | 8 +- integration-test/nextjs/src/app/rsc/client.ts | 4 +- integration-test/nextjs/tsconfig.json | 1 - integration-test/playwright/package.json | 3 +- .../playwright/playwright.config.ts | 26 ++- .../playwright/src/cc-dynamic.test.ts | 146 +++++++++++------ integration-test/playwright/src/helpers.ts | 4 + ...loadQuery.test.ts => preloadQuery.test.ts} | 30 ++-- .../{nextjs/src => }/shared/delayLink.ts | 2 +- .../{nextjs/src => }/shared/errorLink.tsx | 2 +- .../tanstack-start/app/routeTree.gen.ts | 150 +++++++++++++++++- .../tanstack-start/app/router.tsx | 15 +- .../tanstack-start/app/routes/__root.tsx | 8 +- .../app/routes/useBackgroundQuery.tsx | 39 +++++ .../useBackgroundQueryWithoutSsrReadQuery.tsx | 47 ++++++ .../tanstack-start/app/routes/useQuery.tsx | 24 +++ .../app/routes/useQueryWithCache.tsx | 25 +++ .../app/routes/useSuspenseQuery.tsx | 53 +++++++ integration-test/tanstack-start/package.json | 1 + yarn.lock | 1 + 25 files changed, 528 insertions(+), 153 deletions(-) delete mode 100644 integration-test/nextjs/src/app/cc/dynamic/useSuspenseQueryWithError/page.tsx create mode 100644 integration-test/playwright/src/helpers.ts rename integration-test/playwright/src/{rsc-dynamic-PreloadQuery.test.ts => preloadQuery.test.ts} (87%) rename integration-test/{nextjs/src => }/shared/delayLink.ts (90%) rename integration-test/{nextjs/src => }/shared/errorLink.tsx (95%) create mode 100644 integration-test/tanstack-start/app/routes/useBackgroundQuery.tsx create mode 100644 integration-test/tanstack-start/app/routes/useBackgroundQueryWithoutSsrReadQuery.tsx create mode 100644 integration-test/tanstack-start/app/routes/useQuery.tsx create mode 100644 integration-test/tanstack-start/app/routes/useQueryWithCache.tsx create mode 100644 integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx diff --git a/integration-test/nextjs/src/app/cc/ApolloWrapper.tsx b/integration-test/nextjs/src/app/cc/ApolloWrapper.tsx index c39ee232..b236a759 100644 --- a/integration-test/nextjs/src/app/cc/ApolloWrapper.tsx +++ b/integration-test/nextjs/src/app/cc/ApolloWrapper.tsx @@ -9,11 +9,11 @@ import { import { loadErrorMessages, loadDevMessages } from "@apollo/client/dev"; import { setVerbosity } from "ts-invariant"; -import { delayLink } from "@/shared/delayLink"; +import { delayLink } from "@integration-test/shared/delayLink"; import { schema } from "@integration-test/shared/schema"; import { useSSROnlySecret } from "ssr-only-secrets"; -import { errorLink } from "../../shared/errorLink"; +import { errorLink } from "@integration-test/shared/errorLink"; import { IncrementalSchemaLink } from "@integration-test/shared/IncrementalSchemaLink"; setVerbosity("debug"); diff --git a/integration-test/nextjs/src/app/cc/dynamic/useBackgroundQuery/page.tsx b/integration-test/nextjs/src/app/cc/dynamic/useBackgroundQuery/page.tsx index 74f8ed5d..62f5f2c4 100644 --- a/integration-test/nextjs/src/app/cc/dynamic/useBackgroundQuery/page.tsx +++ b/integration-test/nextjs/src/app/cc/dynamic/useBackgroundQuery/page.tsx @@ -5,7 +5,7 @@ import { useBackgroundQuery, useReadQuery, gql, - QueryReference, + QueryRef, } from "@apollo/client"; import { Suspense } from "react"; @@ -38,7 +38,7 @@ export default function Page() { ); } -function DisplayData({ queryRef }: { queryRef: QueryReference }) { +function DisplayData({ queryRef }: { queryRef: QueryRef }) { const { data } = useReadQuery(queryRef); globalThis.hydrationFinished?.(); return ( diff --git a/integration-test/nextjs/src/app/cc/dynamic/useBackgroundQueryWithoutSsrReadQuery/page.tsx b/integration-test/nextjs/src/app/cc/dynamic/useBackgroundQueryWithoutSsrReadQuery/page.tsx index a2cbb020..ba3838ef 100644 --- a/integration-test/nextjs/src/app/cc/dynamic/useBackgroundQueryWithoutSsrReadQuery/page.tsx +++ b/integration-test/nextjs/src/app/cc/dynamic/useBackgroundQueryWithoutSsrReadQuery/page.tsx @@ -2,7 +2,7 @@ import { useBackgroundQuery, useReadQuery } from "@apollo/client"; import type { TypedDocumentNode } from "@apollo/client"; -import { gql, QueryReference } from "@apollo/client"; +import { gql, QueryRef } from "@apollo/client"; import { Suspense, useState, useEffect } from "react"; interface Data { @@ -37,7 +37,7 @@ export default function Page() { ); } -function DisplayData({ queryRef }: { queryRef: QueryReference }) { +function DisplayData({ queryRef }: { queryRef: QueryRef }) { const { data } = useReadQuery(queryRef); globalThis.hydrationFinished?.(); diff --git a/integration-test/nextjs/src/app/cc/dynamic/useSuspenseQuery/page.tsx b/integration-test/nextjs/src/app/cc/dynamic/useSuspenseQuery/page.tsx index b154708f..18852646 100644 --- a/integration-test/nextjs/src/app/cc/dynamic/useSuspenseQuery/page.tsx +++ b/integration-test/nextjs/src/app/cc/dynamic/useSuspenseQuery/page.tsx @@ -2,6 +2,9 @@ import type { TypedDocumentNode } from "@apollo/client"; import { useSuspenseQuery, gql } from "@apollo/client"; +import { ErrorBoundary, FallbackProps } from "react-error-boundary"; +import { Suspense } from "react"; +import { useSearchParams } from "next/navigation"; const QUERY: TypedDocumentNode<{ products: { @@ -20,8 +23,28 @@ const QUERY: TypedDocumentNode<{ export const dynamic = "force-dynamic"; export default function Page() { + const searchParams = useSearchParams(); + const errorLevel = searchParams.get("errorLevel") as "ssr" | "always" | null; + return ( + + + + + + ); +} + +function FallbackComponent({ error, resetErrorBoundary }: FallbackProps) { + return ( + <> +

    {error.message}

    + + ); +} + +function Component({ errorLevel }: { errorLevel: "ssr" | "always" | null }) { const { data } = useSuspenseQuery(QUERY, { - context: { delay: 1000 }, + context: { delay: 1000, ...(errorLevel ? { error: errorLevel } : {}) }, }); globalThis.hydrationFinished?.(); diff --git a/integration-test/nextjs/src/app/cc/dynamic/useSuspenseQueryWithError/page.tsx b/integration-test/nextjs/src/app/cc/dynamic/useSuspenseQueryWithError/page.tsx deleted file mode 100644 index 0862ddad..00000000 --- a/integration-test/nextjs/src/app/cc/dynamic/useSuspenseQueryWithError/page.tsx +++ /dev/null @@ -1,55 +0,0 @@ -"use client"; - -import type { TypedDocumentNode } from "@apollo/client"; -import { useSuspenseQuery, gql } from "@apollo/client"; -import { ErrorBoundary, FallbackProps } from "react-error-boundary"; -import { Suspense } from "react"; - -const QUERY: TypedDocumentNode<{ - products: { - id: string; - title: string; - }[]; -}> = gql` - query dynamicProducts { - products { - id - title - } - } -`; - -export const dynamic = "force-dynamic"; - -export default function Page() { - return ( - - - - - - ); -} - -function FallbackComponent({ error, resetErrorBoundary }: FallbackProps) { - return ( - <> -

    {error.message}

    - - ); -} - -function Component({ errorLevel }: { errorLevel: "ssr" | "always" }) { - const { data } = useSuspenseQuery(QUERY, { - context: { error: errorLevel }, - }); - globalThis.hydrationFinished?.(); - - return ( -
      - {data.products.map(({ id, title }) => ( -
    • {title}
    • - ))} -
    - ); -} diff --git a/integration-test/nextjs/src/app/cc/static/useBackgroundQueryWithoutSsrReadQuery/page.tsx b/integration-test/nextjs/src/app/cc/static/useBackgroundQueryWithoutSsrReadQuery/page.tsx index 18a46960..f2268bd5 100644 --- a/integration-test/nextjs/src/app/cc/static/useBackgroundQueryWithoutSsrReadQuery/page.tsx +++ b/integration-test/nextjs/src/app/cc/static/useBackgroundQueryWithoutSsrReadQuery/page.tsx @@ -5,7 +5,7 @@ import { useBackgroundQuery, useReadQuery, gql, - QueryReference, + QueryRef, } from "@apollo/client"; import { Suspense, useState, useEffect } from "react"; @@ -26,7 +26,9 @@ const QUERY: TypedDocumentNode = gql` `; export default function Page() { - const [queryRef] = useBackgroundQuery(QUERY, { context: { delay: 2000 } }); + const [queryRef] = useBackgroundQuery(QUERY, { + context: { delay: 2000 }, + }); const [isClient, setIsClient] = useState(false); useEffect(() => setIsClient(true), []); return ( @@ -39,7 +41,7 @@ export default function Page() { ); } -function DisplayData({ queryRef }: { queryRef: QueryReference }) { +function DisplayData({ queryRef }: { queryRef: QueryRef }) { const { data } = useReadQuery(queryRef); globalThis.hydrationFinished?.(); diff --git a/integration-test/nextjs/src/app/rsc/client.ts b/integration-test/nextjs/src/app/rsc/client.ts index 1e90da7d..15b48b38 100644 --- a/integration-test/nextjs/src/app/rsc/client.ts +++ b/integration-test/nextjs/src/app/rsc/client.ts @@ -6,8 +6,8 @@ import { import { loadErrorMessages, loadDevMessages } from "@apollo/client/dev"; import { setVerbosity } from "ts-invariant"; -import { delayLink } from "@/shared/delayLink"; -import { errorLink } from "@/shared/errorLink"; +import { delayLink } from "@integration-test/shared/delayLink"; +import { errorLink } from "@integration-test/shared/errorLink"; import { schema } from "@integration-test/shared/schema"; import { IncrementalSchemaLink } from "@integration-test/shared/IncrementalSchemaLink"; diff --git a/integration-test/nextjs/tsconfig.json b/integration-test/nextjs/tsconfig.json index c471aef8..a9746dac 100644 --- a/integration-test/nextjs/tsconfig.json +++ b/integration-test/nextjs/tsconfig.json @@ -35,7 +35,6 @@ "**/*.tsx", ".next/types/**/*.ts", "../shared/*.ts", - "../playwright/fixture.ts" ], "exclude": [ "node_modules" diff --git a/integration-test/playwright/package.json b/integration-test/playwright/package.json index 9ba22ed2..b9da5d89 100644 --- a/integration-test/playwright/package.json +++ b/integration-test/playwright/package.json @@ -4,7 +4,8 @@ "private": true, "scripts": { "test": "yarn playwright test", - "test:nextjs": "TEST_PROJECT_DIR=../nextjs yarn playwright test --grep nextjs" + "test:nextjs": "TEST_PROJECT_DIR=../nextjs yarn playwright test --grep=@nextjs", + "test:tanstack": "TEST_PROJECT_DIR=../tanstack-start yarn playwright test --grep=@tanstack" }, "devDependencies": { "@playwright/test": "^1.49.1", diff --git a/integration-test/playwright/playwright.config.ts b/integration-test/playwright/playwright.config.ts index cc8ebf5e..039a07c1 100644 --- a/integration-test/playwright/playwright.config.ts +++ b/integration-test/playwright/playwright.config.ts @@ -1,5 +1,22 @@ -import { defineConfig } from "@playwright/test"; +import { defineConfig, devices } from "@playwright/test"; import { resolve } from "node:path"; +import { parseArgs } from "node:util"; + +if (!process.env.GREP) { + const { + values: { grep }, + } = parseArgs({ + options: { + grep: { + type: "string", + default: "", + }, + }, + allowPositionals: true, + strict: false, + }); + process.env.GREP = JSON.stringify(grep); +} export default defineConfig({ webServer: process.env.BASE_URL @@ -14,7 +31,14 @@ export default defineConfig({ reuseExistingServer: !process.env.CI, }, timeout: 15 * 1000, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], use: { + // "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" headless: true, viewport: { width: 1280, height: 720 }, ignoreHTTPSErrors: true, diff --git a/integration-test/playwright/src/cc-dynamic.test.ts b/integration-test/playwright/src/cc-dynamic.test.ts index 546e9750..95573206 100644 --- a/integration-test/playwright/src/cc-dynamic.test.ts +++ b/integration-test/playwright/src/cc-dynamic.test.ts @@ -1,5 +1,6 @@ import { expect } from "@playwright/test"; import { test } from "../fixture"; +import { matchesTag } from "./helpers"; const regex_connection_closed_early = /streaming connection closed before server query could be fully transported, rerunning/i; @@ -7,36 +8,40 @@ const regex_query_error_restart = /query failed on server, rerunning in browser/i; const reactErr419 = /(Minified React error #419|Switched to client rendering)/; -test.describe( - "CC dynamic", - { - tag: ["@nextjs"], - }, - () => { - test.describe("useSuspenseQuery", () => { - test("one query", async ({ page, blockRequest, hydrationFinished }) => { - await page.goto("/cc/dynamic/useSuspenseQuery", { +const base = matchesTag("@nextjs") ? "/cc/dynamic" : ""; +test.describe("CC dynamic", () => { + test.describe("useSuspenseQuery", () => { + test( + "one query", + { + tag: ["@nextjs", "@tanstack"], + }, + async ({ page, blockRequest, hydrationFinished }) => { + await page.goto(`${base}/useSuspenseQuery`, { waitUntil: "commit", }); - await expect(page).toBeInitiallyLoading(false); + await expect(page).toBeInitiallyLoading(true); await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); await hydrationFinished; await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); - - test("error during SSR restarts query in browser", async ({ - page, - hydrationFinished, - }) => { + } + ); + + test( + "error during SSR restarts query in browser", + { + tag: ["@nextjs", "@tanstack"], + }, + async ({ page, hydrationFinished }) => { page.allowErrors?.(); let allLogs: string[] = []; page.on("console", (message) => { allLogs.push(message.text()); }); - await page.goto("/cc/dynamic/useSuspenseQueryWithError", { + await page.goto(`${base}/useSuspenseQuery?errorLevel=ssr`, { waitUntil: "commit", }); @@ -55,12 +60,18 @@ test.describe( for (const log of allLogs) { expect(log).not.toMatch(regex_connection_closed_early); } - }); - }); - - test.describe("useBackgroundQuery + useReadQuery", () => { - test("one query", async ({ page, blockRequest, hydrationFinished }) => { - await page.goto("/cc/dynamic/useBackgroundQuery", { + } + ); + }); + + test.describe("useBackgroundQuery + useReadQuery", () => { + test( + "one query", + { + tag: ["@nextjs", "@tanstack"], + }, + async ({ page, blockRequest, hydrationFinished }) => { + await page.goto(`${base}/useBackgroundQuery`, { waitUntil: "commit", }); @@ -70,11 +81,16 @@ test.describe( await hydrationFinished; await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); - - // this will close the connection before the final result is received, so it can never be forwarded - test("no `useReadQuery` on the server", async ({ page }) => { - await page.goto("/cc/dynamic/useBackgroundQueryWithoutSsrReadQuery", { + } + ); + + // Next.js will close the connection prematurely if `useReadQuery` is not used + // we want to ensure it logs a message that it restarts the query in the browser + test( + "no `useReadQuery` on the server - restarts in the browser", + { tag: ["@nextjs"] }, + async ({ page }) => { + await page.goto(`${base}/useBackgroundQueryWithoutSsrReadQuery`, { waitUntil: "commit", }); @@ -88,31 +104,59 @@ test.describe( await expect(page.getByText("loading")).toBeVisible(); await expect(page.getByText("loading")).not.toBeVisible(); await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); - }); - test.describe("useQuery", () => { - test("without cache value", async ({ page }) => { - await page.goto("/cc/dynamic/useQuery", { + } + ); + test( + "no `useReadQuery` on the server - streams over without a browser network request", + { tag: ["@tanstack"] }, + async ({ page, blockRequest }) => { + await page.goto(`${base}/useBackgroundQueryWithoutSsrReadQuery`, { waitUntil: "commit", }); - await expect(page).toBeInitiallyLoading(true); + await expect(page.getByText("rendered on server")).toBeVisible(); + + await expect(page.getByText("rendered on client")).toBeVisible(); + await expect(page.getByText("loading")).toBeVisible(); await expect(page.getByText("loading")).not.toBeVisible(); await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); + } + ); + }); + test.describe("useQuery", () => { + test( + "without cache value", + { tag: ["@nextjs", "@tanstack"] }, + async ({ page }) => { + await page.goto(`${base}/useQuery`, { + waitUntil: "commit", + }); - test("with cache value", async ({ page }) => { - await page.goto("/cc/dynamic/useQueryWithCache", { + await expect(page).toBeInitiallyLoading(true); + await expect(page.getByText("loading")).not.toBeVisible(); + await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); + } + ); + + test( + "with cache value", + { tag: ["@nextjs", "@tanstack"] }, + async ({ page }) => { + await page.goto(`${base}/useQueryWithCache`, { waitUntil: "commit", }); await expect(page).toBeInitiallyLoading(false); await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - }); - }); - test.describe("useSuspenseQuery with a nonce", () => { - test("invalid: logs an error", async ({ page, blockRequest }) => { - await page.goto("/cc/dynamic/useSuspenseQuery?nonce=invalid", { + } + ); + }); + test.describe("useSuspenseQuery with a nonce", () => { + test( + "invalid: logs an error", + { tag: ["@nextjs"] }, + async ({ page, blockRequest }) => { + await page.goto(`${base}/useSuspenseQuery?nonce=invalid`, { waitUntil: "commit", }); @@ -121,10 +165,14 @@ test.describe( message.text() ); }); - }); - test("valid: does not log an error", async ({ page, blockRequest }) => { + } + ); + test( + "valid: does not log an error", + { tag: ["@nextjs"] }, + async ({ page, blockRequest }) => { await page.goto( - "/cc/dynamic/useSuspenseQuery?nonce=8IBTHwOdqNKAWeKl7plt8g==", + `${base}/useSuspenseQuery?nonce=8IBTHwOdqNKAWeKl7plt8g==`, { waitUntil: "commit", } @@ -132,7 +180,7 @@ test.describe( const messagePromise = page.waitForEvent("console"); expect(messagePromise).rejects.toThrow(/waiting for event \"console\"/); - }); - }); - } -); + } + ); + }); +}); diff --git a/integration-test/playwright/src/helpers.ts b/integration-test/playwright/src/helpers.ts new file mode 100644 index 00000000..da621624 --- /dev/null +++ b/integration-test/playwright/src/helpers.ts @@ -0,0 +1,4 @@ +export function matchesTag(tag: string) { + const grep = JSON.parse(process.env.GREP || "null"); + return grep && new RegExp(grep).test(tag); +} diff --git a/integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts b/integration-test/playwright/src/preloadQuery.test.ts similarity index 87% rename from integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts rename to integration-test/playwright/src/preloadQuery.test.ts index 2cfeb99b..ebed4ff0 100644 --- a/integration-test/playwright/src/rsc-dynamic-PreloadQuery.test.ts +++ b/integration-test/playwright/src/preloadQuery.test.ts @@ -1,8 +1,12 @@ import { expect } from "@playwright/test"; import { test } from "../fixture"; +import { matchesTag } from "./helpers"; const reactErr419 = /(Minified React error #419|Switched to client rendering)/; +const base = matchesTag("@nextjs") + ? "/rsc/dynamic/PreloadQuery" + : "/preloadQuery"; test.describe( "PreloadQuery", { @@ -15,12 +19,9 @@ test.describe( ] as const) { test.describe(description, () => { test("query resolves on the server", async ({ page, blockRequest }) => { - await page.goto( - `/rsc/dynamic/PreloadQuery/${path}?errorIn=ssr,browser`, - { - waitUntil: "commit", - } - ); + await page.goto(`${base}/${path}?errorIn=ssr,browser`, { + waitUntil: "commit", + }); await expect(page).toBeInitiallyLoading(true); await expect(page.getByText("loading")).not.toBeVisible(); @@ -34,12 +35,9 @@ test.describe( page, }) => { page.allowErrors?.(); - await page.goto( - `/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc,network_error`, - { - waitUntil: "commit", - } - ); + await page.goto(`${base}/${path}?errorIn=rsc,network_error`, { + waitUntil: "commit", + }); await expect(page).toBeInitiallyLoading(true); @@ -62,7 +60,7 @@ test.describe( page, }) => { page.allowErrors?.(); - await page.goto(`/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc`, { + await page.goto(`${base}/${path}?errorIn=rsc`, { waitUntil: "commit", }); @@ -93,7 +91,7 @@ test.describe( page, }) => { page.allowErrors?.(); - await page.goto(`/rsc/dynamic/PreloadQuery/${path}?errorIn=rsc`, { + await page.goto(`${base}/${path}?errorIn=rsc`, { waitUntil: "commit", }); @@ -116,7 +114,7 @@ test.describe( } test("queryRef works with useQueryRefHandlers", async ({ page }) => { - await page.goto(`/rsc/dynamic/PreloadQuery/queryRef-useReadQuery`, { + await page.goto(`${base}/queryRef-useReadQuery`, { waitUntil: "commit", }); @@ -134,7 +132,7 @@ test.describe( test.skip("queryRef: assumptions about referential equality", async ({ page, }) => { - await page.goto(`/rsc/dynamic/PreloadQuery/queryRef-refTest`, { + await page.goto(`${base}/queryRef-refTest`, { waitUntil: "commit", }); diff --git a/integration-test/nextjs/src/shared/delayLink.ts b/integration-test/shared/delayLink.ts similarity index 90% rename from integration-test/nextjs/src/shared/delayLink.ts rename to integration-test/shared/delayLink.ts index e4f81b1d..8510c237 100644 --- a/integration-test/nextjs/src/shared/delayLink.ts +++ b/integration-test/shared/delayLink.ts @@ -1,4 +1,4 @@ -import { ApolloLink, Observable } from "@apollo/client"; +import { ApolloLink, Observable } from "@apollo/client/index.js"; declare module "@apollo/client" { export interface DefaultContext { diff --git a/integration-test/nextjs/src/shared/errorLink.tsx b/integration-test/shared/errorLink.tsx similarity index 95% rename from integration-test/nextjs/src/shared/errorLink.tsx rename to integration-test/shared/errorLink.tsx index bb503b15..cd9a5e60 100644 --- a/integration-test/nextjs/src/shared/errorLink.tsx +++ b/integration-test/shared/errorLink.tsx @@ -1,4 +1,4 @@ -import { ApolloLink, Observable } from "@apollo/client"; +import { ApolloLink, Observable } from "@apollo/client/index.js"; import { GraphQLError, GraphQLFormattedError } from "graphql"; import * as entryPoint from "@apollo/client-react-streaming"; diff --git a/integration-test/tanstack-start/app/routeTree.gen.ts b/integration-test/tanstack-start/app/routeTree.gen.ts index d71a5696..739cfbad 100644 --- a/integration-test/tanstack-start/app/routeTree.gen.ts +++ b/integration-test/tanstack-start/app/routeTree.gen.ts @@ -11,18 +11,54 @@ // Import Routes import { Route as rootRoute } from './routes/__root' +import { Route as UseSuspenseQueryDeferImport } from './routes/useSuspenseQuery-defer' import { Route as UseSuspenseQueryImport } from './routes/useSuspenseQuery' +import { Route as UseQueryWithCacheImport } from './routes/useQueryWithCache' +import { Route as UseQueryImport } from './routes/useQuery' +import { Route as UseBackgroundQueryWithoutSsrReadQueryImport } from './routes/useBackgroundQueryWithoutSsrReadQuery' +import { Route as UseBackgroundQueryImport } from './routes/useBackgroundQuery' import { Route as LoaderDeferImport } from './routes/loader-defer' import { Route as IndexImport } from './routes/index' // Create/Update Routes +const UseSuspenseQueryDeferRoute = UseSuspenseQueryDeferImport.update({ + id: '/useSuspenseQuery-defer', + path: '/useSuspenseQuery-defer', + getParentRoute: () => rootRoute, +} as any) + const UseSuspenseQueryRoute = UseSuspenseQueryImport.update({ id: '/useSuspenseQuery', path: '/useSuspenseQuery', getParentRoute: () => rootRoute, } as any) +const UseQueryWithCacheRoute = UseQueryWithCacheImport.update({ + id: '/useQueryWithCache', + path: '/useQueryWithCache', + getParentRoute: () => rootRoute, +} as any) + +const UseQueryRoute = UseQueryImport.update({ + id: '/useQuery', + path: '/useQuery', + getParentRoute: () => rootRoute, +} as any) + +const UseBackgroundQueryWithoutSsrReadQueryRoute = + UseBackgroundQueryWithoutSsrReadQueryImport.update({ + id: '/useBackgroundQueryWithoutSsrReadQuery', + path: '/useBackgroundQueryWithoutSsrReadQuery', + getParentRoute: () => rootRoute, + } as any) + +const UseBackgroundQueryRoute = UseBackgroundQueryImport.update({ + id: '/useBackgroundQuery', + path: '/useBackgroundQuery', + getParentRoute: () => rootRoute, +} as any) + const LoaderDeferRoute = LoaderDeferImport.update({ id: '/loader-defer', path: '/loader-defer', @@ -53,6 +89,34 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LoaderDeferImport parentRoute: typeof rootRoute } + '/useBackgroundQuery': { + id: '/useBackgroundQuery' + path: '/useBackgroundQuery' + fullPath: '/useBackgroundQuery' + preLoaderRoute: typeof UseBackgroundQueryImport + parentRoute: typeof rootRoute + } + '/useBackgroundQueryWithoutSsrReadQuery': { + id: '/useBackgroundQueryWithoutSsrReadQuery' + path: '/useBackgroundQueryWithoutSsrReadQuery' + fullPath: '/useBackgroundQueryWithoutSsrReadQuery' + preLoaderRoute: typeof UseBackgroundQueryWithoutSsrReadQueryImport + parentRoute: typeof rootRoute + } + '/useQuery': { + id: '/useQuery' + path: '/useQuery' + fullPath: '/useQuery' + preLoaderRoute: typeof UseQueryImport + parentRoute: typeof rootRoute + } + '/useQueryWithCache': { + id: '/useQueryWithCache' + path: '/useQueryWithCache' + fullPath: '/useQueryWithCache' + preLoaderRoute: typeof UseQueryWithCacheImport + parentRoute: typeof rootRoute + } '/useSuspenseQuery': { id: '/useSuspenseQuery' path: '/useSuspenseQuery' @@ -60,6 +124,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof UseSuspenseQueryImport parentRoute: typeof rootRoute } + '/useSuspenseQuery-defer': { + id: '/useSuspenseQuery-defer' + path: '/useSuspenseQuery-defer' + fullPath: '/useSuspenseQuery-defer' + preLoaderRoute: typeof UseSuspenseQueryDeferImport + parentRoute: typeof rootRoute + } } } @@ -68,41 +139,92 @@ declare module '@tanstack/react-router' { export interface FileRoutesByFullPath { '/': typeof IndexRoute '/loader-defer': typeof LoaderDeferRoute + '/useBackgroundQuery': typeof UseBackgroundQueryRoute + '/useBackgroundQueryWithoutSsrReadQuery': typeof UseBackgroundQueryWithoutSsrReadQueryRoute + '/useQuery': typeof UseQueryRoute + '/useQueryWithCache': typeof UseQueryWithCacheRoute '/useSuspenseQuery': typeof UseSuspenseQueryRoute + '/useSuspenseQuery-defer': typeof UseSuspenseQueryDeferRoute } export interface FileRoutesByTo { '/': typeof IndexRoute '/loader-defer': typeof LoaderDeferRoute + '/useBackgroundQuery': typeof UseBackgroundQueryRoute + '/useBackgroundQueryWithoutSsrReadQuery': typeof UseBackgroundQueryWithoutSsrReadQueryRoute + '/useQuery': typeof UseQueryRoute + '/useQueryWithCache': typeof UseQueryWithCacheRoute '/useSuspenseQuery': typeof UseSuspenseQueryRoute + '/useSuspenseQuery-defer': typeof UseSuspenseQueryDeferRoute } export interface FileRoutesById { __root__: typeof rootRoute '/': typeof IndexRoute '/loader-defer': typeof LoaderDeferRoute + '/useBackgroundQuery': typeof UseBackgroundQueryRoute + '/useBackgroundQueryWithoutSsrReadQuery': typeof UseBackgroundQueryWithoutSsrReadQueryRoute + '/useQuery': typeof UseQueryRoute + '/useQueryWithCache': typeof UseQueryWithCacheRoute '/useSuspenseQuery': typeof UseSuspenseQueryRoute + '/useSuspenseQuery-defer': typeof UseSuspenseQueryDeferRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/loader-defer' | '/useSuspenseQuery' + fullPaths: + | '/' + | '/loader-defer' + | '/useBackgroundQuery' + | '/useBackgroundQueryWithoutSsrReadQuery' + | '/useQuery' + | '/useQueryWithCache' + | '/useSuspenseQuery' + | '/useSuspenseQuery-defer' fileRoutesByTo: FileRoutesByTo - to: '/' | '/loader-defer' | '/useSuspenseQuery' - id: '__root__' | '/' | '/loader-defer' | '/useSuspenseQuery' + to: + | '/' + | '/loader-defer' + | '/useBackgroundQuery' + | '/useBackgroundQueryWithoutSsrReadQuery' + | '/useQuery' + | '/useQueryWithCache' + | '/useSuspenseQuery' + | '/useSuspenseQuery-defer' + id: + | '__root__' + | '/' + | '/loader-defer' + | '/useBackgroundQuery' + | '/useBackgroundQueryWithoutSsrReadQuery' + | '/useQuery' + | '/useQueryWithCache' + | '/useSuspenseQuery' + | '/useSuspenseQuery-defer' fileRoutesById: FileRoutesById } export interface RootRouteChildren { IndexRoute: typeof IndexRoute LoaderDeferRoute: typeof LoaderDeferRoute + UseBackgroundQueryRoute: typeof UseBackgroundQueryRoute + UseBackgroundQueryWithoutSsrReadQueryRoute: typeof UseBackgroundQueryWithoutSsrReadQueryRoute + UseQueryRoute: typeof UseQueryRoute + UseQueryWithCacheRoute: typeof UseQueryWithCacheRoute UseSuspenseQueryRoute: typeof UseSuspenseQueryRoute + UseSuspenseQueryDeferRoute: typeof UseSuspenseQueryDeferRoute } const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, LoaderDeferRoute: LoaderDeferRoute, + UseBackgroundQueryRoute: UseBackgroundQueryRoute, + UseBackgroundQueryWithoutSsrReadQueryRoute: + UseBackgroundQueryWithoutSsrReadQueryRoute, + UseQueryRoute: UseQueryRoute, + UseQueryWithCacheRoute: UseQueryWithCacheRoute, UseSuspenseQueryRoute: UseSuspenseQueryRoute, + UseSuspenseQueryDeferRoute: UseSuspenseQueryDeferRoute, } export const routeTree = rootRoute @@ -117,7 +239,12 @@ export const routeTree = rootRoute "children": [ "/", "/loader-defer", - "/useSuspenseQuery" + "/useBackgroundQuery", + "/useBackgroundQueryWithoutSsrReadQuery", + "/useQuery", + "/useQueryWithCache", + "/useSuspenseQuery", + "/useSuspenseQuery-defer" ] }, "/": { @@ -126,8 +253,23 @@ export const routeTree = rootRoute "/loader-defer": { "filePath": "loader-defer.tsx" }, + "/useBackgroundQuery": { + "filePath": "useBackgroundQuery.tsx" + }, + "/useBackgroundQueryWithoutSsrReadQuery": { + "filePath": "useBackgroundQueryWithoutSsrReadQuery.tsx" + }, + "/useQuery": { + "filePath": "useQuery.tsx" + }, + "/useQueryWithCache": { + "filePath": "useQueryWithCache.tsx" + }, "/useSuspenseQuery": { "filePath": "useSuspenseQuery.tsx" + }, + "/useSuspenseQuery-defer": { + "filePath": "useSuspenseQuery-defer.tsx" } } } diff --git a/integration-test/tanstack-start/app/router.tsx b/integration-test/tanstack-start/app/router.tsx index f1218906..68b2b4ea 100644 --- a/integration-test/tanstack-start/app/router.tsx +++ b/integration-test/tanstack-start/app/router.tsx @@ -13,22 +13,17 @@ import { import { IncrementalSchemaLink } from "@integration-test/shared/IncrementalSchemaLink"; import { schema } from "@integration-test/shared/schema"; -import { HttpLink, ApolloLink, Observable } from "@apollo/client/index.js"; +import { errorLink } from "@integration-test/shared/errorLink"; +import { delayLink } from "@integration-test/shared/delayLink"; +import { HttpLink, ApolloLink, setLogVerbosity } from "@apollo/client/index.js"; +setLogVerbosity("debug"); loadDevMessages(); loadErrorMessages(); -export const delayLink = new ApolloLink((operation, forward) => { - return new Observable((observer) => { - const timeout = setTimeout(() => { - forward(operation).subscribe(observer); - }, operation.getContext().delay ?? 500); - return () => clearTimeout(timeout); - }); -}); - const link = ApolloLink.from([ delayLink, + errorLink, typeof window === "undefined" ? new IncrementalSchemaLink({ schema }) : new HttpLink({ uri: "/api/graphql" }), diff --git a/integration-test/tanstack-start/app/routes/__root.tsx b/integration-test/tanstack-start/app/routes/__root.tsx index fa25cb3a..77c3841e 100644 --- a/integration-test/tanstack-start/app/routes/__root.tsx +++ b/integration-test/tanstack-start/app/routes/__root.tsx @@ -1,7 +1,7 @@ import { TanStackRouterDevtools } from "@tanstack/router-devtools"; import { Link, Outlet } from "@tanstack/react-router"; import { Meta, Scripts } from "@tanstack/start"; -import type { ReactNode } from "react"; +import { useState, type ReactNode } from "react"; import { type ApolloClientRouterContext } from "@apollo/client-integration-tanstack-start"; import { createRootRouteWithContext } from "@tanstack/react-router"; @@ -33,6 +33,7 @@ function RootComponent() { } function RootDocument({ children }: Readonly<{ children: ReactNode }>) { + const [devToolsOpen, setDevToolsOpen] = useState(false); return ( @@ -65,10 +66,13 @@ function RootDocument({ children }: Readonly<{ children: ReactNode }>) { > useSuspenseQuery {" "} +
    {children} - + {devToolsOpen && } diff --git a/integration-test/tanstack-start/app/routes/useBackgroundQuery.tsx b/integration-test/tanstack-start/app/routes/useBackgroundQuery.tsx new file mode 100644 index 00000000..61876dae --- /dev/null +++ b/integration-test/tanstack-start/app/routes/useBackgroundQuery.tsx @@ -0,0 +1,39 @@ +import { + QueryRef, + useBackgroundQuery, + useReadQuery, +} from "@apollo/client/index.js"; +import { DynamicProductResult, QUERY } from "@integration-test/shared/queries"; +import { createFileRoute } from "@tanstack/react-router"; +import { Suspense } from "react"; + +export const Route = createFileRoute("/useBackgroundQuery")({ + component: RouteComponent, +}); + +function RouteComponent() { + const [queryRef] = useBackgroundQuery(QUERY, { + context: { delay: 1000, error: "browser" }, + }); + return ( + loading

    }> + +
    + ); +} + +function DisplayData({ + queryRef, +}: { + queryRef: QueryRef; +}) { + const { data } = useReadQuery(queryRef); + globalThis.hydrationFinished?.(); + return ( +
      + {data.products.map(({ id, title }) => ( +
    • {title}
    • + ))} +
    + ); +} diff --git a/integration-test/tanstack-start/app/routes/useBackgroundQueryWithoutSsrReadQuery.tsx b/integration-test/tanstack-start/app/routes/useBackgroundQueryWithoutSsrReadQuery.tsx new file mode 100644 index 00000000..0eb68870 --- /dev/null +++ b/integration-test/tanstack-start/app/routes/useBackgroundQueryWithoutSsrReadQuery.tsx @@ -0,0 +1,47 @@ +import { + QueryRef, + useBackgroundQuery, + useReadQuery, +} from "@apollo/client/index.js"; +import { DynamicProductResult, QUERY } from "@integration-test/shared/queries"; +import { createFileRoute } from "@tanstack/react-router"; +import { Suspense, useSyncExternalStore } from "react"; + +export const Route = createFileRoute("/useBackgroundQueryWithoutSsrReadQuery")({ + component: RouteComponent, +}); + +function RouteComponent() { + const [queryRef] = useBackgroundQuery(QUERY, { + context: { delay: 1000, error: "browser" }, + }); + const isClient = useSyncExternalStore( + () => () => {}, + () => true, + () => false + ); + return ( + <> + {isClient ? "rendered on client" : "rendered on server"} + loading

    }> + {isClient && } +
    + + ); +} + +function DisplayData({ + queryRef, +}: { + queryRef: QueryRef; +}) { + const { data } = useReadQuery(queryRef); + globalThis.hydrationFinished?.(); + return ( +
      + {data.products.map(({ id, title }) => ( +
    • {title}
    • + ))} +
    + ); +} diff --git a/integration-test/tanstack-start/app/routes/useQuery.tsx b/integration-test/tanstack-start/app/routes/useQuery.tsx new file mode 100644 index 00000000..e363a15a --- /dev/null +++ b/integration-test/tanstack-start/app/routes/useQuery.tsx @@ -0,0 +1,24 @@ +import { useQuery } from "@apollo/client/index.js"; +import { QUERY } from "@integration-test/shared/queries"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/useQuery")({ + component: RouteComponent, +}); + +function RouteComponent() { + const result = useQuery(QUERY); + globalThis.hydrationFinished?.(); + + if (!result.data) { + return
    Loading...
    ; + } + + return ( +
      + {result.data.products.map(({ id, title }) => ( +
    • {title}
    • + ))} +
    + ); +} diff --git a/integration-test/tanstack-start/app/routes/useQueryWithCache.tsx b/integration-test/tanstack-start/app/routes/useQueryWithCache.tsx new file mode 100644 index 00000000..d3962de1 --- /dev/null +++ b/integration-test/tanstack-start/app/routes/useQueryWithCache.tsx @@ -0,0 +1,25 @@ +import { useQuery, useSuspenseQuery } from "@apollo/client/index.js"; +import { QUERY } from "@integration-test/shared/queries"; +import { createFileRoute } from "@tanstack/react-router"; + +export const Route = createFileRoute("/useQueryWithCache")({ + component: RouteComponent, +}); + +function RouteComponent() { + useSuspenseQuery(QUERY); // fill cache with `useSuspenseQuery` + const result = useQuery(QUERY); + globalThis.hydrationFinished?.(); + + if (!result.data) { + return
    Loading...
    ; + } + + return ( +
      + {result.data.products.map(({ id, title }) => ( +
    • {title}
    • + ))} +
    + ); +} diff --git a/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx b/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx new file mode 100644 index 00000000..f224cb46 --- /dev/null +++ b/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx @@ -0,0 +1,53 @@ +import { createFileRoute } from "@tanstack/react-router"; +import { ErrorBoundary, FallbackProps } from "react-error-boundary"; + +import { QUERY } from "@integration-test/shared/queries"; +import { useSuspenseQuery } from "@apollo/client/index.js"; +import { Suspense } from "react"; + +export const Route = createFileRoute("/useSuspenseQuery")({ + component: RouteComponent, + validateSearch: (search: Record) => { + return { + errorLevel: search.errorLevel as "ssr" | "always" | undefined, + }; + }, +}); + +function RouteComponent() { + const { errorLevel } = Route.useSearch(); + return ( + + + + + + ); +} + +function FallbackComponent({ error, resetErrorBoundary }: FallbackProps) { + return ( + <> +

    {error.message}

    + + ); +} + +function Component({ + errorLevel, +}: { + errorLevel: "ssr" | "always" | undefined; +}) { + const { data } = useSuspenseQuery(QUERY, { + context: { delay: 1000, ...(errorLevel ? { error: errorLevel } : {}) }, + }); + globalThis.hydrationFinished?.(); + + return ( +
      + {data.products.map(({ id, title }) => ( +
    • {title}
    • + ))} +
    + ); +} diff --git a/integration-test/tanstack-start/package.json b/integration-test/tanstack-start/package.json index 9fb315e8..35e794f8 100644 --- a/integration-test/tanstack-start/package.json +++ b/integration-test/tanstack-start/package.json @@ -17,6 +17,7 @@ "graphql": "^16.10.0", "react": "^19.0.0", "react-dom": "^19.0.0", + "react-error-boundary": "^5.0.0", "vinxi": "^0.5.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 05c77d5e..7732582c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6615,6 +6615,7 @@ __metadata: graphql: "npm:^16.10.0" react: "npm:^19.0.0" react-dom: "npm:^19.0.0" + react-error-boundary: "npm:^5.0.0" typescript: "npm:^5.7.2" vinxi: "npm:^0.5.1" languageName: unknown From 6ac9152a52067ea082f96817aabe3e39fa9ae1dc Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Mon, 10 Feb 2025 16:36:08 +0100 Subject: [PATCH 06/18] run tanstack tests in CI --- .github/workflows/tests.yml | 6 ++++++ integration-test/tanstack-start/package.json | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 66f115be..564c3f2d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -116,6 +116,12 @@ jobs: - name: "Next.js: Test" run: yarn workspace @integration-test/nextjs run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} + - name: "TanStack Start: Build" + run: yarn workspace @integration-test/tanstack-start run build + + - name: "Next.js: Test" + run: yarn workspace @integration-test/tanstack-start run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} + - name: "Vite Streaming: Build" run: yarn workspace @integration-test/vite-streaming run build - name: "Vite Streaming: Test" diff --git a/integration-test/tanstack-start/package.json b/integration-test/tanstack-start/package.json index 35e794f8..64427754 100644 --- a/integration-test/tanstack-start/package.json +++ b/integration-test/tanstack-start/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "rm -rvf node_modules/.vinxi node_modules/.cache node_modules/.tanstack-start .output .vinxi && vinxi dev", "build": "rm -rvf node_modules/.vinxi node_modules/.cache node_modules/.tanstack-start .output .vinxi && vinxi build", - "start": "vinxi start" + "start": "vinxi start", + "test": "yarn test:tanstack" }, "dependencies": { "@apollo/client": "^3.12.4", From 7fbcdec42333a2b757f005d666fd852fb1220cfc Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Tue, 11 Feb 2025 10:41:13 +0100 Subject: [PATCH 07/18] QueryRef tests wih `preloadQuery` --- .../queryRef-refTest/RefTestChild.tsx | 103 ------------ .../PreloadQuery/queryRef-refTest/page.tsx | 50 ------ .../PreloadQuery/queryRef-refTest/styles.css | 8 - .../playwright/src/cc-dynamic.test.ts | 3 + .../playwright/src/preloadQuery.test.ts | 157 ++++++++++-------- integration-test/shared/errorLink.tsx | 1 + .../tanstack-start/app/routeTree.gen.ts | 56 ++++++- .../tanstack-start/app/routes/__root.tsx | 1 + .../preloadQuery/queryRef-useReadQuery.tsx | 9 + .../routes/preloadQuery/useSuspenseQuery.tsx | 48 ++++++ .../app/routes/useSuspenseQuery.tsx | 10 +- integration-test/tanstack-start/tsconfig.json | 4 +- 12 files changed, 209 insertions(+), 241 deletions(-) delete mode 100644 integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/RefTestChild.tsx delete mode 100644 integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/page.tsx delete mode 100644 integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/styles.css create mode 100644 integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx create mode 100644 integration-test/tanstack-start/app/routes/preloadQuery/useSuspenseQuery.tsx diff --git a/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/RefTestChild.tsx b/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/RefTestChild.tsx deleted file mode 100644 index 37365db0..00000000 --- a/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/RefTestChild.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client"; - -import { QueryRef, useQueryRefHandlers } from "@apollo/client"; -import { DynamicProductResult } from "@integration-test/shared/queries"; -import { useEffect, useState } from "react"; -import { - InternalQueryReference, - unwrapQueryRef, -} from "@apollo/client/react/internal"; - -import { TransportedQueryRef } from "@apollo/experimental-nextjs-app-support"; - -declare global { - interface Window { - testRefs?: { - distinctObjectReferences: Set; - uniqueQueryRefs1: Set>; - uniqueQueryRefs2: Set>; - distinctQueryRefs: Set>; - }; - } -} -export function RefTestChild({ - queryRef, - set, -}: { - queryRef: TransportedQueryRef; - set: "1" | "2"; -}) { - const [isClient, setIsClient] = useState(false); - - useQueryRefHandlers(queryRef); - - useEffect(() => { - const realQueryRef = queryRef as any as { - __transportedQueryRef: QueryRef; - }; - if (!window.testRefs) { - window.testRefs = { - distinctObjectReferences: new Set(), // expected: [transportedQueryRef1_1, transportedQueryRef1_2, transportedQueryRef2_1, transportedQueryRef2_2] - distinctQueryRefs: new Set(), // expected: [innerQueryRef1, innerQueryRef2] - uniqueQueryRefs1: new Set(), // expected: [innerQueryRef1] - uniqueQueryRefs2: new Set(), // expected: [innerQueryRef2] - }; - } - window.testRefs[`uniqueQueryRefs${set}`].add( - unwrapQueryRef(realQueryRef.__transportedQueryRef)! - ); - window.testRefs.distinctQueryRefs.add( - unwrapQueryRef(realQueryRef.__transportedQueryRef)! - ); - window.testRefs.distinctObjectReferences.add(queryRef); - setIsClient(true); - }, []); - - return isClient && window.testRefs ? ( - <> -
    - -
    -
    - -
    -
    - -
    - - ) : null; -} diff --git a/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/page.tsx b/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/page.tsx deleted file mode 100644 index 0d933a78..00000000 --- a/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/page.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { QUERY } from "@integration-test/shared/queries"; -import { Suspense } from "react"; -import { PreloadQuery } from "@/app/rsc/client"; -import { RefTestChild } from "./RefTestChild"; -import { ApolloWrapper } from "@/app/cc/ApolloWrapper"; - -import "./styles.css"; - -export const dynamic = "force-dynamic"; - -export default function Page() { - return ( - -
    - - {(queryRef1) => ( - <> - - - - )} - - - {(queryRef2) => ( - loading}> - - - - )} - -
    -
    - ); -} diff --git a/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/styles.css b/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/styles.css deleted file mode 100644 index 1aaf8dc2..00000000 --- a/integration-test/nextjs/src/app/rsc/dynamic/PreloadQuery/queryRef-refTest/styles.css +++ /dev/null @@ -1,8 +0,0 @@ -.invalid { - border: 1px solid red; -} - -form { - display: flex; - flex-direction: column; -} diff --git a/integration-test/playwright/src/cc-dynamic.test.ts b/integration-test/playwright/src/cc-dynamic.test.ts index 95573206..3d460444 100644 --- a/integration-test/playwright/src/cc-dynamic.test.ts +++ b/integration-test/playwright/src/cc-dynamic.test.ts @@ -151,6 +151,9 @@ test.describe("CC dynamic", () => { } ); }); + + test.fixme("useSuspenseQuery with @defer", { tag: ["@tanstack"] }, () => {}); + test.describe("useSuspenseQuery with a nonce", () => { test( "invalid: logs an error", diff --git a/integration-test/playwright/src/preloadQuery.test.ts b/integration-test/playwright/src/preloadQuery.test.ts index ebed4ff0..67ec6224 100644 --- a/integration-test/playwright/src/preloadQuery.test.ts +++ b/integration-test/playwright/src/preloadQuery.test.ts @@ -7,19 +7,23 @@ const reactErr419 = /(Minified React error #419|Switched to client rendering)/; const base = matchesTag("@nextjs") ? "/rsc/dynamic/PreloadQuery" : "/preloadQuery"; -test.describe( - "PreloadQuery", - { - tag: ["@nextjs"], - }, - () => { - for (const [description, path] of [ - ["with useSuspenseQuery", "useSuspenseQuery"], - ["with queryRef and useReadQuery", "queryRef-useReadQuery"], - ] as const) { - test.describe(description, () => { - test("query resolves on the server", async ({ page, blockRequest }) => { - await page.goto(`${base}/${path}?errorIn=ssr,browser`, { + +const originatesIn = matchesTag("@nextjs") ? "RSC" : "SSR"; +const otherEnvs = matchesTag("@nextjs") ? "ssr,browser" : "browser"; + +test.describe("PreloadQuery", () => { + for (const [description, path] of [ + ["with useSuspenseQuery", "useSuspenseQuery"], + // ["with queryRef and useReadQuery", "queryRef-useReadQuery"], + ] as const) { + test.describe(description, () => { + test( + "query resolves on the server", + { + tag: ["@nextjs", "@tanstack"], + }, + async ({ page, blockRequest }) => { + await page.goto(`${base}/${path}?errorIn=${otherEnvs}`, { waitUntil: "commit", }); @@ -27,17 +31,24 @@ test.describe( await expect(page.getByText("loading")).not.toBeVisible(); await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); await expect( - page.getByText("Queried in RSC environment") + page.getByText(`Queried in ${originatesIn} environment`) ).toBeVisible(); - }); - - test("link chain errors on the server, restarts in the browser", async ({ - page, - }) => { + } + ); + + test( + "link chain errors on the server, restarts in the browser", + { + tag: ["@nextjs", "@tanstack"], + }, + async ({ page }) => { page.allowErrors?.(); - await page.goto(`${base}/${path}?errorIn=rsc,network_error`, { - waitUntil: "commit", - }); + await page.goto( + `${base}/${path}?errorIn=${originatesIn.toLowerCase()},network_error`, + { + waitUntil: "commit", + } + ); await expect(page).toBeInitiallyLoading(true); @@ -50,19 +61,26 @@ test.describe( await expect( page.getByText("Queried in Browser environment") ).toBeVisible(); - }); - - if (path === "queryRef-useReadQuery") { - // this only works for `useReadQuery`, because `useSuspenseQuery` won't attach - // to the exact same suspenseCache entry and as a result, it won't get the - // error message from the ReadableStream. - test("graphqlError on the server, transported to the browser, can be restarted", async ({ - page, - }) => { + } + ); + + if (path === "queryRef-useReadQuery") { + // this only works for `useReadQuery`, because `useSuspenseQuery` won't attach + // to the exact same suspenseCache entry and as a result, it won't get the + // error message from the ReadableStream. + test( + "graphqlError on the server, transported to the browser, can be restarted", + { + tag: ["@nextjs"], + }, + async ({ page }) => { page.allowErrors?.(); - await page.goto(`${base}/${path}?errorIn=rsc`, { - waitUntil: "commit", - }); + await page.goto( + `${base}/${path}?errorIn=${originatesIn.toLowerCase()}`, + { + waitUntil: "commit", + } + ); await expect(page).toBeInitiallyLoading(true); @@ -79,21 +97,28 @@ test.describe( await expect( page.getByText("Queried in Browser environment") ).toBeVisible(); - }); - } else { - // instead, `useSuspenseQuery` will behave as if nothing had been transported - // and rerun the query in the browser. - // there is a chance it will also rerun the query during SSR, that's a timing - // question that might need further investigation - // the bottom line: `PreloadQuery` with `useSuspenseQuery` works in the happy - // path, but it's not as robust as `queryRef` with `useReadQuery`. - test("graphqlError on the server, restarts in the browser", async ({ - page, - }) => { + } + ); + } else { + // instead, `useSuspenseQuery` will behave as if nothing had been transported + // and rerun the query in the browser. + // there is a chance it will also rerun the query during SSR, that's a timing + // question that might need further investigation + // the bottom line: `PreloadQuery` with `useSuspenseQuery` works in the happy + // path, but it's not as robust as `queryRef` with `useReadQuery`. + test( + "graphqlError on the server, restarts in the browser", + { + tag: ["@nextjs", "@tanstack"], + }, + async ({ page }) => { page.allowErrors?.(); - await page.goto(`${base}/${path}?errorIn=rsc`, { - waitUntil: "commit", - }); + await page.goto( + `${base}/${path}?errorIn=${originatesIn.toLowerCase()}`, + { + waitUntil: "commit", + } + ); await expect(page).toBeInitiallyLoading(true); @@ -108,12 +133,18 @@ test.describe( await expect( page.getByText("Queried in Browser environment") ).toBeVisible(); - }); - } - }); - } + } + ); + } + }); + } - test("queryRef works with useQueryRefHandlers", async ({ page }) => { + test( + "queryRef works with useQueryRefHandlers", + { + tag: ["@nextjs"], + }, + async ({ page }) => { await page.goto(`${base}/queryRef-useReadQuery`, { waitUntil: "commit", }); @@ -127,20 +158,6 @@ test.describe( await expect( page.getByText("Queried in Browser environment") ).toBeVisible(); - }); - - test.skip("queryRef: assumptions about referential equality", async ({ - page, - }) => { - await page.goto(`${base}/queryRef-refTest`, { - waitUntil: "commit", - }); - - await page.getByRole("spinbutton").nth(11).waitFor(); - - for (let i = 0; i < 12; i++) { - await expect(page.getByRole("spinbutton").nth(i)).toHaveClass("valid"); - } - }); - } -); + } + ); +}); diff --git a/integration-test/shared/errorLink.tsx b/integration-test/shared/errorLink.tsx index cd9a5e60..21afb259 100644 --- a/integration-test/shared/errorLink.tsx +++ b/integration-test/shared/errorLink.tsx @@ -40,6 +40,7 @@ export const errorLink = new ApolloLink((operation, forward) => { } satisfies GraphQLFormattedError as GraphQLError, ], }); + subscriber.complete(); } }); } diff --git a/integration-test/tanstack-start/app/routeTree.gen.ts b/integration-test/tanstack-start/app/routeTree.gen.ts index 739cfbad..9b899e83 100644 --- a/integration-test/tanstack-start/app/routeTree.gen.ts +++ b/integration-test/tanstack-start/app/routeTree.gen.ts @@ -19,6 +19,8 @@ import { Route as UseBackgroundQueryWithoutSsrReadQueryImport } from './routes/u import { Route as UseBackgroundQueryImport } from './routes/useBackgroundQuery' import { Route as LoaderDeferImport } from './routes/loader-defer' import { Route as IndexImport } from './routes/index' +import { Route as PreloadQueryUseSuspenseQueryImport } from './routes/preloadQuery/useSuspenseQuery' +import { Route as PreloadQueryQueryRefUseReadQueryImport } from './routes/preloadQuery/queryRef-useReadQuery' // Create/Update Routes @@ -71,6 +73,20 @@ const IndexRoute = IndexImport.update({ getParentRoute: () => rootRoute, } as any) +const PreloadQueryUseSuspenseQueryRoute = + PreloadQueryUseSuspenseQueryImport.update({ + id: '/preloadQuery/useSuspenseQuery', + path: '/preloadQuery/useSuspenseQuery', + getParentRoute: () => rootRoute, + } as any) + +const PreloadQueryQueryRefUseReadQueryRoute = + PreloadQueryQueryRefUseReadQueryImport.update({ + id: '/preloadQuery/queryRef-useReadQuery', + path: '/preloadQuery/queryRef-useReadQuery', + getParentRoute: () => rootRoute, + } as any) + // Populate the FileRoutesByPath interface declare module '@tanstack/react-router' { @@ -131,6 +147,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof UseSuspenseQueryDeferImport parentRoute: typeof rootRoute } + '/preloadQuery/queryRef-useReadQuery': { + id: '/preloadQuery/queryRef-useReadQuery' + path: '/preloadQuery/queryRef-useReadQuery' + fullPath: '/preloadQuery/queryRef-useReadQuery' + preLoaderRoute: typeof PreloadQueryQueryRefUseReadQueryImport + parentRoute: typeof rootRoute + } + '/preloadQuery/useSuspenseQuery': { + id: '/preloadQuery/useSuspenseQuery' + path: '/preloadQuery/useSuspenseQuery' + fullPath: '/preloadQuery/useSuspenseQuery' + preLoaderRoute: typeof PreloadQueryUseSuspenseQueryImport + parentRoute: typeof rootRoute + } } } @@ -145,6 +175,8 @@ export interface FileRoutesByFullPath { '/useQueryWithCache': typeof UseQueryWithCacheRoute '/useSuspenseQuery': typeof UseSuspenseQueryRoute '/useSuspenseQuery-defer': typeof UseSuspenseQueryDeferRoute + '/preloadQuery/queryRef-useReadQuery': typeof PreloadQueryQueryRefUseReadQueryRoute + '/preloadQuery/useSuspenseQuery': typeof PreloadQueryUseSuspenseQueryRoute } export interface FileRoutesByTo { @@ -156,6 +188,8 @@ export interface FileRoutesByTo { '/useQueryWithCache': typeof UseQueryWithCacheRoute '/useSuspenseQuery': typeof UseSuspenseQueryRoute '/useSuspenseQuery-defer': typeof UseSuspenseQueryDeferRoute + '/preloadQuery/queryRef-useReadQuery': typeof PreloadQueryQueryRefUseReadQueryRoute + '/preloadQuery/useSuspenseQuery': typeof PreloadQueryUseSuspenseQueryRoute } export interface FileRoutesById { @@ -168,6 +202,8 @@ export interface FileRoutesById { '/useQueryWithCache': typeof UseQueryWithCacheRoute '/useSuspenseQuery': typeof UseSuspenseQueryRoute '/useSuspenseQuery-defer': typeof UseSuspenseQueryDeferRoute + '/preloadQuery/queryRef-useReadQuery': typeof PreloadQueryQueryRefUseReadQueryRoute + '/preloadQuery/useSuspenseQuery': typeof PreloadQueryUseSuspenseQueryRoute } export interface FileRouteTypes { @@ -181,6 +217,8 @@ export interface FileRouteTypes { | '/useQueryWithCache' | '/useSuspenseQuery' | '/useSuspenseQuery-defer' + | '/preloadQuery/queryRef-useReadQuery' + | '/preloadQuery/useSuspenseQuery' fileRoutesByTo: FileRoutesByTo to: | '/' @@ -191,6 +229,8 @@ export interface FileRouteTypes { | '/useQueryWithCache' | '/useSuspenseQuery' | '/useSuspenseQuery-defer' + | '/preloadQuery/queryRef-useReadQuery' + | '/preloadQuery/useSuspenseQuery' id: | '__root__' | '/' @@ -201,6 +241,8 @@ export interface FileRouteTypes { | '/useQueryWithCache' | '/useSuspenseQuery' | '/useSuspenseQuery-defer' + | '/preloadQuery/queryRef-useReadQuery' + | '/preloadQuery/useSuspenseQuery' fileRoutesById: FileRoutesById } @@ -213,6 +255,8 @@ export interface RootRouteChildren { UseQueryWithCacheRoute: typeof UseQueryWithCacheRoute UseSuspenseQueryRoute: typeof UseSuspenseQueryRoute UseSuspenseQueryDeferRoute: typeof UseSuspenseQueryDeferRoute + PreloadQueryQueryRefUseReadQueryRoute: typeof PreloadQueryQueryRefUseReadQueryRoute + PreloadQueryUseSuspenseQueryRoute: typeof PreloadQueryUseSuspenseQueryRoute } const rootRouteChildren: RootRouteChildren = { @@ -225,6 +269,8 @@ const rootRouteChildren: RootRouteChildren = { UseQueryWithCacheRoute: UseQueryWithCacheRoute, UseSuspenseQueryRoute: UseSuspenseQueryRoute, UseSuspenseQueryDeferRoute: UseSuspenseQueryDeferRoute, + PreloadQueryQueryRefUseReadQueryRoute: PreloadQueryQueryRefUseReadQueryRoute, + PreloadQueryUseSuspenseQueryRoute: PreloadQueryUseSuspenseQueryRoute, } export const routeTree = rootRoute @@ -244,7 +290,9 @@ export const routeTree = rootRoute "/useQuery", "/useQueryWithCache", "/useSuspenseQuery", - "/useSuspenseQuery-defer" + "/useSuspenseQuery-defer", + "/preloadQuery/queryRef-useReadQuery", + "/preloadQuery/useSuspenseQuery" ] }, "/": { @@ -270,6 +318,12 @@ export const routeTree = rootRoute }, "/useSuspenseQuery-defer": { "filePath": "useSuspenseQuery-defer.tsx" + }, + "/preloadQuery/queryRef-useReadQuery": { + "filePath": "preloadQuery/queryRef-useReadQuery.tsx" + }, + "/preloadQuery/useSuspenseQuery": { + "filePath": "preloadQuery/useSuspenseQuery.tsx" } } } diff --git a/integration-test/tanstack-start/app/routes/__root.tsx b/integration-test/tanstack-start/app/routes/__root.tsx index 77c3841e..88c08451 100644 --- a/integration-test/tanstack-start/app/routes/__root.tsx +++ b/integration-test/tanstack-start/app/routes/__root.tsx @@ -63,6 +63,7 @@ function RootDocument({ children }: Readonly<{ children: ReactNode }>) { activeProps={{ className: "font-bold", }} + search={{ errorLevel: undefined }} > useSuspenseQuery {" "} diff --git a/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx b/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx new file mode 100644 index 00000000..dd8a19fc --- /dev/null +++ b/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx @@ -0,0 +1,9 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/preloadQuery/queryRef-useReadQuery')({ + component: RouteComponent, +}) + +function RouteComponent() { + return
    Hello "/preloadQuery/queryRef-useReadQuery"!
    +} diff --git a/integration-test/tanstack-start/app/routes/preloadQuery/useSuspenseQuery.tsx b/integration-test/tanstack-start/app/routes/preloadQuery/useSuspenseQuery.tsx new file mode 100644 index 00000000..d5da6f3c --- /dev/null +++ b/integration-test/tanstack-start/app/routes/preloadQuery/useSuspenseQuery.tsx @@ -0,0 +1,48 @@ +import { QUERY } from "@integration-test/shared/queries"; +import { useSuspenseQuery, type DefaultContext } from "@apollo/client/index.js"; +import "@integration-test/shared/errorLink"; +import { createFileRoute } from "@tanstack/react-router"; +import { Suspense } from "react"; + +export const Route = createFileRoute("/preloadQuery/useSuspenseQuery")({ + component: RouteComponent, + validateSearch: (search: Record) => { + return { + errorIn: search.errorIn as DefaultContext["error"], + }; + }, + loaderDeps: ({ search: { errorIn } }) => ({ errorIn }), + loader: async ({ context: { preloadQuery }, deps: { errorIn } }) => { + const queryRef = preloadQuery(QUERY, { + context: { delay: 1000, ...(errorIn ? { error: errorIn } : {}) }, + }); + return { + queryRef, + }; + }, +}); + +function RouteComponent() { + return ( + loading}> + + + ); +} + +export function Child() { + const { errorIn } = Route.useSearch(); + const { data } = useSuspenseQuery(QUERY, { + context: { delay: 1000, ...(errorIn ? { error: errorIn } : {}) }, + }); + return ( + <> +
      + {data.products.map(({ id, title }: any) => ( +
    • {title}
    • + ))} +
    +

    Queried in {data.env} environment

    + + ); +} diff --git a/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx b/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx index f224cb46..6a035023 100644 --- a/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx +++ b/integration-test/tanstack-start/app/routes/useSuspenseQuery.tsx @@ -2,14 +2,14 @@ import { createFileRoute } from "@tanstack/react-router"; import { ErrorBoundary, FallbackProps } from "react-error-boundary"; import { QUERY } from "@integration-test/shared/queries"; -import { useSuspenseQuery } from "@apollo/client/index.js"; +import { DefaultContext, useSuspenseQuery } from "@apollo/client/index.js"; import { Suspense } from "react"; export const Route = createFileRoute("/useSuspenseQuery")({ component: RouteComponent, validateSearch: (search: Record) => { return { - errorLevel: search.errorLevel as "ssr" | "always" | undefined, + errorLevel: search.errorLevel as DefaultContext["error"], }; }, }); @@ -33,11 +33,7 @@ function FallbackComponent({ error, resetErrorBoundary }: FallbackProps) { ); } -function Component({ - errorLevel, -}: { - errorLevel: "ssr" | "always" | undefined; -}) { +function Component({ errorLevel }: { errorLevel: DefaultContext["error"] }) { const { data } = useSuspenseQuery(QUERY, { context: { delay: 1000, ...(errorLevel ? { error: errorLevel } : {}) }, }); diff --git a/integration-test/tanstack-start/tsconfig.json b/integration-test/tanstack-start/tsconfig.json index 28632ab5..49579526 100644 --- a/integration-test/tanstack-start/tsconfig.json +++ b/integration-test/tanstack-start/tsconfig.json @@ -1,9 +1,9 @@ { "compilerOptions": { "jsx": "react-jsx", - "moduleResolution": "Bundler", - "module": "ESNext", "target": "ES2022", + "module": "ES2022", + "moduleResolution": "bundler", "skipLibCheck": true, "strictNullChecks": true, }, From 00c0d703b19624efadb46adf17835af5ae1610a1 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Tue, 11 Feb 2025 11:22:59 +0100 Subject: [PATCH 08/18] add `preloadQuery` `useReadQuery` tests --- .../playwright/src/preloadQuery.test.ts | 7 ++- .../preloadQuery/queryRef-useReadQuery.tsx | 53 +++++++++++++++++-- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/integration-test/playwright/src/preloadQuery.test.ts b/integration-test/playwright/src/preloadQuery.test.ts index 67ec6224..bf92cb80 100644 --- a/integration-test/playwright/src/preloadQuery.test.ts +++ b/integration-test/playwright/src/preloadQuery.test.ts @@ -14,7 +14,7 @@ const otherEnvs = matchesTag("@nextjs") ? "ssr,browser" : "browser"; test.describe("PreloadQuery", () => { for (const [description, path] of [ ["with useSuspenseQuery", "useSuspenseQuery"], - // ["with queryRef and useReadQuery", "queryRef-useReadQuery"], + ["with queryRef and useReadQuery", "queryRef-useReadQuery"], ] as const) { test.describe(description, () => { test( @@ -71,7 +71,10 @@ test.describe("PreloadQuery", () => { test( "graphqlError on the server, transported to the browser, can be restarted", { - tag: ["@nextjs"], + tag: [ + "@nextjs", + // TODO: "@tanstack" causes a non-recoverable hydration mismatch + ], }, async ({ page }) => { page.allowErrors?.(); diff --git a/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx b/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx index dd8a19fc..8575f5de 100644 --- a/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx +++ b/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx @@ -1,9 +1,54 @@ -import { createFileRoute } from '@tanstack/react-router' +import { DynamicProductResult, QUERY } from "@integration-test/shared/queries"; +import { + QueryRef, + useQueryRefHandlers, + useReadQuery, + useSuspenseQuery, + type DefaultContext, +} from "@apollo/client/index.js"; +import "@integration-test/shared/errorLink"; +import { createFileRoute } from "@tanstack/react-router"; +import { Suspense } from "react"; -export const Route = createFileRoute('/preloadQuery/queryRef-useReadQuery')({ +export const Route = createFileRoute("/preloadQuery/queryRef-useReadQuery")({ component: RouteComponent, -}) + validateSearch: (search: Record) => { + return { + errorIn: search.errorIn as DefaultContext["error"], + }; + }, + loaderDeps: ({ search: { errorIn } }) => ({ errorIn }), + loader: async ({ context: { preloadQuery }, deps: { errorIn } }) => { + const queryRef = preloadQuery(QUERY, { + context: { delay: 1000, ...(errorIn ? { error: errorIn } : {}) }, + }); + return { + queryRef, + }; + }, +}); function RouteComponent() { - return
    Hello "/preloadQuery/queryRef-useReadQuery"!
    + const { queryRef } = Route.useLoaderData(); + return ( + loading}> + + + ); +} + +function Child({ queryRef }: { queryRef: QueryRef }) { + const { refetch } = useQueryRefHandlers(queryRef); + const { data } = useReadQuery(queryRef); + return ( + <> +
      + {data.products.map(({ id, title }: any) => ( +
    • {title}
    • + ))} +
    +

    Queried in {data.env} environment

    + + + ); } From 34437a7f28abfacd812e504ab0aa4abc1b7d02d1 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Tue, 11 Feb 2025 11:29:15 +0100 Subject: [PATCH 09/18] run integration tests against TanStack deployment on Vercel --- .github/workflows/vercel-integration.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/vercel-integration.yml b/.github/workflows/vercel-integration.yml index 5f622560..63dd0cba 100644 --- a/.github/workflows/vercel-integration.yml +++ b/.github/workflows/vercel-integration.yml @@ -10,9 +10,13 @@ jobs: run: echo 'Deployment status is ${{ toJSON(github.event.deployment_status) }}' run-next-e2e: - if: github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success' && github.event.deployment_status.environment == 'Preview – apollo__experimental-nextjs-app-support' + if: | + github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success' && ( + github.event.deployment_status.environment == 'Preview – apollo__experimental-nextjs-app-support' || + github.event.deployment_status.environment == 'Preview – apollo__client-integration-tanstack-start' + ) runs-on: ubuntu-latest - name: Run Playwright tests against Vercel deployment + name: Run Playwright tests against Vercel deployment ${{ github.event.deployment_status.environment }} steps: - uses: actions/checkout@v2 - uses: actions/checkout@v4 @@ -39,7 +43,14 @@ jobs: - run: npx playwright install-deps if: steps.playwright-cache.outputs.cache-hit == 'true' - - name: "Run Playwright tests against Vercel deployment" + - name: "Run Playwright tests against Vercel deployment - Next.js" + if: github.event.deployment_status.environment == 'Preview – apollo__experimental-nextjs-app-support' run: yarn workspace @integration-test/nextjs run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} env: BASE_URL: ${{ github.event.deployment_status.environment_url }} + + - name: "Run Playwright tests against Vercel deployment - TanStack Start" + if: github.event.deployment_status.environment == 'Preview – apollo__client-integration-tanstack-start' + run: yarn workspace @integration-test/tanstack-start run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} + env: + BASE_URL: ${{ github.event.deployment_status.environment_url }} From e9b4698922d756bd2b334652230c6aaa19c9e7bd Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Feb 2025 10:36:16 +0100 Subject: [PATCH 10/18] annotate a test --- .../playwright/src/preloadQuery.test.ts | 8 +++++++- .../preloadQuery/queryRef-useReadQuery.tsx | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/integration-test/playwright/src/preloadQuery.test.ts b/integration-test/playwright/src/preloadQuery.test.ts index bf92cb80..cd27509d 100644 --- a/integration-test/playwright/src/preloadQuery.test.ts +++ b/integration-test/playwright/src/preloadQuery.test.ts @@ -73,7 +73,13 @@ test.describe("PreloadQuery", () => { { tag: [ "@nextjs", - // TODO: "@tanstack" causes a non-recoverable hydration mismatch + // This actually doesn't work in TanStack Query because of the `autoDisposeTimeout` + // that keeps the errored `queryRef` around. + // (if you wait long enough, it will work). + // We might need to revisit this conceptually as right now we have no very good way + // of restarting a query in this situation. + // I'm honestly a bit irritated this works as it does in Next.js + // "@tanstack" ], }, async ({ page }) => { diff --git a/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx b/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx index 8575f5de..b15647bc 100644 --- a/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx +++ b/integration-test/tanstack-start/app/routes/preloadQuery/queryRef-useReadQuery.tsx @@ -3,11 +3,10 @@ import { QueryRef, useQueryRefHandlers, useReadQuery, - useSuspenseQuery, type DefaultContext, } from "@apollo/client/index.js"; import "@integration-test/shared/errorLink"; -import { createFileRoute } from "@tanstack/react-router"; +import { createFileRoute, ErrorComponentProps } from "@tanstack/react-router"; import { Suspense } from "react"; export const Route = createFileRoute("/preloadQuery/queryRef-useReadQuery")({ @@ -26,6 +25,7 @@ export const Route = createFileRoute("/preloadQuery/queryRef-useReadQuery")({ queryRef, }; }, + errorComponent: ErrorComponent, }); function RouteComponent() { @@ -48,7 +48,19 @@ function Child({ queryRef }: { queryRef: QueryRef }) { ))}

    Queried in {data.env} environment

    - + + + ); +} + +export function ErrorComponent({ error, reset }: ErrorComponentProps) { + return ( + <> +

    Encountered an error:

    +
    {error.message}
    + ); } From 10b6ac370267c31c85382a89d23fa963244b81c4 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Feb 2025 10:40:19 +0100 Subject: [PATCH 11/18] another test --- integration-test/playwright/src/preloadQuery.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/integration-test/playwright/src/preloadQuery.test.ts b/integration-test/playwright/src/preloadQuery.test.ts index cd27509d..c47b9d80 100644 --- a/integration-test/playwright/src/preloadQuery.test.ts +++ b/integration-test/playwright/src/preloadQuery.test.ts @@ -151,7 +151,7 @@ test.describe("PreloadQuery", () => { test( "queryRef works with useQueryRefHandlers", { - tag: ["@nextjs"], + tag: ["@nextjs", "@tanstack"], }, async ({ page }) => { await page.goto(`${base}/queryRef-useReadQuery`, { @@ -161,7 +161,9 @@ test.describe("PreloadQuery", () => { await expect(page).toBeInitiallyLoading(true); await expect(page.getByText("loading")).not.toBeVisible(); await expect(page.getByText("Soft Warm Apollo Beanie")).toBeVisible(); - await expect(page.getByText("Queried in RSC environment")).toBeVisible(); + await expect( + page.getByText(`Queried in ${originatesIn} environment`) + ).toBeVisible(); await page.getByRole("button", { name: "refetch" }).click(); await expect( From b92e01d18255d1af0fda14f8cdf9b62ab5ef4bfb Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Feb 2025 12:52:52 +0100 Subject: [PATCH 12/18] bump react-router to newest template, add vercel preset --- .../react-router-npm-7.0.2-b96f2bd13c.patch | 94 - .../react-router-npm-7.1.5-9668fa2213.patch | 112 + integration-test/react-router/.gitignore | 11 +- .../react-router/app/entry.server.tsx | 12 +- integration-test/react-router/package.json | 36 +- .../react-router/react-router.config.ts | 8 +- integration-test/react-router/server/app.ts | 25 - .../react-router/tailwind.config.ts | 22 - integration-test/react-router/tsconfig.json | 25 +- .../react-router/vercel/output/config.json | 17 - .../functions/index.func/.vc-config.json | 6 - .../output/functions/index.func/package.json | 3 - .../react-router/vercel/prepare.js | 10 - integration-test/react-router/vite.config.ts | 24 +- package.json | 2 +- packages/react-router/package.json | 2 +- yarn.config.cjs | 4 +- yarn.lock | 1908 +++++++++++++++-- 18 files changed, 1905 insertions(+), 416 deletions(-) delete mode 100644 .yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch create mode 100644 .yarn/patches/react-router-npm-7.1.5-9668fa2213.patch delete mode 100644 integration-test/react-router/server/app.ts delete mode 100644 integration-test/react-router/tailwind.config.ts delete mode 100644 integration-test/react-router/vercel/output/config.json delete mode 100644 integration-test/react-router/vercel/output/functions/index.func/.vc-config.json delete mode 100644 integration-test/react-router/vercel/output/functions/index.func/package.json delete mode 100644 integration-test/react-router/vercel/prepare.js diff --git a/.yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch b/.yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch deleted file mode 100644 index 9c3a7fc8..00000000 --- a/.yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch +++ /dev/null @@ -1,94 +0,0 @@ -diff --git a/dist/development/lib/types/route-module.d.mts b/dist/development/lib/types/route-module.d.mts -index c4553062633a6a1352378bfedb2c9dc7eaef94fb..762fd83a1ad06f940ba39c6552bd61cc5c4d1cf1 100644 ---- a/dist/development/lib/types/route-module.d.mts -+++ b/dist/development/lib/types/route-module.d.mts -@@ -1,7 +1,9 @@ - import { av as LinkDescriptor, as as MetaDescriptor, aJ as ServerDataFrom, aK as ClientDataFrom, aL as Func, aM as Equal, aN as Pretty } from '../../route-data-DuV3tXo2.mjs'; - import { A as AppLoadContext } from '../../data-CQbyyGzl.mjs'; - import 'react'; -- -+export type SerializesTo = { -+ $__RR_SerializesTo?: [T]; -+ }; - type IsDefined = Equal extends true ? false : true; - type RouteModule = { - meta?: Func; -diff --git a/dist/development/lib/types/route-module.d.ts b/dist/development/lib/types/route-module.d.ts -index a7b3449b84f7be4e7da9ce82ba6ac3ae3e30d64f..776fdbc13033eb82ce4de2b9026476e87e65c7f7 100644 ---- a/dist/development/lib/types/route-module.d.ts -+++ b/dist/development/lib/types/route-module.d.ts -@@ -1,7 +1,9 @@ - import { av as LinkDescriptor, as as MetaDescriptor, aJ as ServerDataFrom, aK as ClientDataFrom, aL as Func, aM as Equal, aN as Pretty } from '../../route-data-DuV3tXo2.js'; - import { A as AppLoadContext } from '../../data-CQbyyGzl.js'; - import 'react'; -- -+export type SerializesTo = { -+ $__RR_SerializesTo?: [T]; -+ }; - type IsDefined = Equal extends true ? false : true; - type RouteModule = { - meta?: Func; -diff --git a/dist/development/route-data-DuV3tXo2.d.mts b/dist/development/route-data-DuV3tXo2.d.mts -index 53dbfb38b8c2cd09bb944aeb17dd3951f2a157ad..d33adfc7147222f4e283487df804faeb95f2a4c8 100644 ---- a/dist/development/route-data-DuV3tXo2.d.mts -+++ b/dist/development/route-data-DuV3tXo2.d.mts -@@ -1531,8 +1531,10 @@ type Func = (...args: any[]) => unknown; - type Pretty = { - [K in keyof T]: T[K]; - } & {}; -- --type Serialize = T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { -+export type SerializesTo = { -+ $__RR_SerializesTo?: [T]; -+ }; -+type Serialize = T extends SerializesTo ? To : T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { - [K in keyof T]: Serialize; - } : undefined; - type VoidToUndefined = Equal extends true ? undefined : T; -diff --git a/dist/development/route-data-DuV3tXo2.d.ts b/dist/development/route-data-DuV3tXo2.d.ts -index 53dbfb38b8c2cd09bb944aeb17dd3951f2a157ad..d33adfc7147222f4e283487df804faeb95f2a4c8 100644 ---- a/dist/development/route-data-DuV3tXo2.d.ts -+++ b/dist/development/route-data-DuV3tXo2.d.ts -@@ -1531,8 +1531,10 @@ type Func = (...args: any[]) => unknown; - type Pretty = { - [K in keyof T]: T[K]; - } & {}; -- --type Serialize = T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { -+export type SerializesTo = { -+ $__RR_SerializesTo?: [T]; -+ }; -+type Serialize = T extends SerializesTo ? To : T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { - [K in keyof T]: Serialize; - } : undefined; - type VoidToUndefined = Equal extends true ? undefined : T; -diff --git a/dist/production/lib/types/route-module.d.mts b/dist/production/lib/types/route-module.d.mts -index c4553062633a6a1352378bfedb2c9dc7eaef94fb..762fd83a1ad06f940ba39c6552bd61cc5c4d1cf1 100644 ---- a/dist/production/lib/types/route-module.d.mts -+++ b/dist/production/lib/types/route-module.d.mts -@@ -1,7 +1,9 @@ - import { av as LinkDescriptor, as as MetaDescriptor, aJ as ServerDataFrom, aK as ClientDataFrom, aL as Func, aM as Equal, aN as Pretty } from '../../route-data-DuV3tXo2.mjs'; - import { A as AppLoadContext } from '../../data-CQbyyGzl.mjs'; - import 'react'; -- -+export type SerializesTo = { -+ $__RR_SerializesTo?: [T]; -+ }; - type IsDefined = Equal extends true ? false : true; - type RouteModule = { - meta?: Func; -diff --git a/dist/production/lib/types/route-module.d.ts b/dist/production/lib/types/route-module.d.ts -index a7b3449b84f7be4e7da9ce82ba6ac3ae3e30d64f..776fdbc13033eb82ce4de2b9026476e87e65c7f7 100644 ---- a/dist/production/lib/types/route-module.d.ts -+++ b/dist/production/lib/types/route-module.d.ts -@@ -1,7 +1,9 @@ - import { av as LinkDescriptor, as as MetaDescriptor, aJ as ServerDataFrom, aK as ClientDataFrom, aL as Func, aM as Equal, aN as Pretty } from '../../route-data-DuV3tXo2.js'; - import { A as AppLoadContext } from '../../data-CQbyyGzl.js'; - import 'react'; -- -+export type SerializesTo = { -+ $__RR_SerializesTo?: [T]; -+ }; - type IsDefined = Equal extends true ? false : true; - type RouteModule = { - meta?: Func; diff --git a/.yarn/patches/react-router-npm-7.1.5-9668fa2213.patch b/.yarn/patches/react-router-npm-7.1.5-9668fa2213.patch new file mode 100644 index 00000000..e1597def --- /dev/null +++ b/.yarn/patches/react-router-npm-7.1.5-9668fa2213.patch @@ -0,0 +1,112 @@ +diff --git a/dist/development/lib/types/route-module.d.mts b/dist/development/lib/types/route-module.d.mts +index 65548f5090c95d9a8a34f916306d3b9d6bff4250..bf88cb4f4f1fa1c9576913efc3c9d230a5315de0 100644 +--- a/dist/development/lib/types/route-module.d.mts ++++ b/dist/development/lib/types/route-module.d.mts +@@ -1,7 +1,9 @@ + import { ay as LinkDescriptor, av as MetaDescriptor, aM as ServerDataFrom, aN as ClientDataFrom, aO as Func, aP as Equal, aQ as Pretty } from '../../route-data-Cq_b5feC.mjs'; + import { A as AppLoadContext } from '../../data-CQbyyGzl.mjs'; + import 'react'; +- ++export type SerializesTo = { ++ $__RR_SerializesTo?: [T]; ++}; + type IsDefined = Equal extends true ? false : true; + type RouteModule = { + meta?: Func; +diff --git a/dist/development/lib/types/route-module.d.ts b/dist/development/lib/types/route-module.d.ts +index a8b932c982cbf7935cdf5402cb844c118a2b9e79..5f9d3fbb1f79c680b3f3ba5f06caee2268ee34fd 100644 +--- a/dist/development/lib/types/route-module.d.ts ++++ b/dist/development/lib/types/route-module.d.ts +@@ -1,7 +1,9 @@ + import { ay as LinkDescriptor, av as MetaDescriptor, aM as ServerDataFrom, aN as ClientDataFrom, aO as Func, aP as Equal, aQ as Pretty } from '../../route-data-Cq_b5feC.js'; + import { A as AppLoadContext } from '../../data-CQbyyGzl.js'; + import 'react'; +- ++export type SerializesTo = { ++ $__RR_SerializesTo?: [T]; ++}; + type IsDefined = Equal extends true ? false : true; + type RouteModule = { + meta?: Func; +diff --git a/dist/development/route-data-Cq_b5feC.d.mts b/dist/development/route-data-Cq_b5feC.d.mts +index a44077c379d51d720dc5539ef006d105657d673c..e5a646b097b82714a739fec8510d13bf09207699 100644 +--- a/dist/development/route-data-Cq_b5feC.d.mts ++++ b/dist/development/route-data-Cq_b5feC.d.mts +@@ -1564,7 +1564,7 @@ type Pretty = { + [K in keyof T]: T[K]; + } & {}; + +-type Serialize = T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { ++type Serialize = T extends import('./lib/types/route-module.mjs').SerializesTo ? To : T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { + [K in keyof T]: Serialize; + } : undefined; + type VoidToUndefined = Equal extends true ? undefined : T; +diff --git a/dist/development/route-data-Cq_b5feC.d.ts b/dist/development/route-data-Cq_b5feC.d.ts +index a44077c379d51d720dc5539ef006d105657d673c..ac555685ba76cc74c6052517fa03ca632e03ba75 100644 +--- a/dist/development/route-data-Cq_b5feC.d.ts ++++ b/dist/development/route-data-Cq_b5feC.d.ts +@@ -1564,7 +1564,7 @@ type Pretty = { + [K in keyof T]: T[K]; + } & {}; + +-type Serialize = T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { ++type Serialize = T extends import('./lib/types/route-module.js').SerializesTo ? To : T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { + [K in keyof T]: Serialize; + } : undefined; + type VoidToUndefined = Equal extends true ? undefined : T; +diff --git a/dist/production/lib/types/route-module.d.mts b/dist/production/lib/types/route-module.d.mts +index 65548f5090c95d9a8a34f916306d3b9d6bff4250..bf88cb4f4f1fa1c9576913efc3c9d230a5315de0 100644 +--- a/dist/production/lib/types/route-module.d.mts ++++ b/dist/production/lib/types/route-module.d.mts +@@ -1,7 +1,9 @@ + import { ay as LinkDescriptor, av as MetaDescriptor, aM as ServerDataFrom, aN as ClientDataFrom, aO as Func, aP as Equal, aQ as Pretty } from '../../route-data-Cq_b5feC.mjs'; + import { A as AppLoadContext } from '../../data-CQbyyGzl.mjs'; + import 'react'; +- ++export type SerializesTo = { ++ $__RR_SerializesTo?: [T]; ++}; + type IsDefined = Equal extends true ? false : true; + type RouteModule = { + meta?: Func; +diff --git a/dist/production/lib/types/route-module.d.ts b/dist/production/lib/types/route-module.d.ts +index a8b932c982cbf7935cdf5402cb844c118a2b9e79..5f9d3fbb1f79c680b3f3ba5f06caee2268ee34fd 100644 +--- a/dist/production/lib/types/route-module.d.ts ++++ b/dist/production/lib/types/route-module.d.ts +@@ -1,7 +1,9 @@ + import { ay as LinkDescriptor, av as MetaDescriptor, aM as ServerDataFrom, aN as ClientDataFrom, aO as Func, aP as Equal, aQ as Pretty } from '../../route-data-Cq_b5feC.js'; + import { A as AppLoadContext } from '../../data-CQbyyGzl.js'; + import 'react'; +- ++export type SerializesTo = { ++ $__RR_SerializesTo?: [T]; ++}; + type IsDefined = Equal extends true ? false : true; + type RouteModule = { + meta?: Func; +diff --git a/dist/production/route-data-Cq_b5feC.d.mts b/dist/production/route-data-Cq_b5feC.d.mts +index a44077c379d51d720dc5539ef006d105657d673c..e5a646b097b82714a739fec8510d13bf09207699 100644 +--- a/dist/production/route-data-Cq_b5feC.d.mts ++++ b/dist/production/route-data-Cq_b5feC.d.mts +@@ -1564,7 +1564,7 @@ type Pretty = { + [K in keyof T]: T[K]; + } & {}; + +-type Serialize = T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { ++type Serialize = T extends import('./lib/types/route-module.mjs').SerializesTo ? To : T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { + [K in keyof T]: Serialize; + } : undefined; + type VoidToUndefined = Equal extends true ? undefined : T; +diff --git a/dist/production/route-data-Cq_b5feC.d.ts b/dist/production/route-data-Cq_b5feC.d.ts +index a44077c379d51d720dc5539ef006d105657d673c..ac555685ba76cc74c6052517fa03ca632e03ba75 100644 +--- a/dist/production/route-data-Cq_b5feC.d.ts ++++ b/dist/production/route-data-Cq_b5feC.d.ts +@@ -1564,7 +1564,7 @@ type Pretty = { + [K in keyof T]: T[K]; + } & {}; + +-type Serialize = T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { ++type Serialize = T extends import('./lib/types/route-module.js').SerializesTo ? To : T extends Serializable ? T : T extends (...args: any[]) => unknown ? undefined : T extends Promise ? Promise> : T extends Map ? Map, Serialize> : T extends Set ? Set> : T extends [] ? [] : T extends readonly [infer F, ...infer R] ? [Serialize, ...Serialize] : T extends Array ? Array> : T extends readonly unknown[] ? readonly Serialize[] : T extends Record ? { + [K in keyof T]: Serialize; + } : undefined; + type VoidToUndefined = Equal extends true ? undefined : T; diff --git a/integration-test/react-router/.gitignore b/integration-test/react-router/.gitignore index ce9b6d65..9b7c041f 100644 --- a/integration-test/react-router/.gitignore +++ b/integration-test/react-router/.gitignore @@ -1,7 +1,6 @@ -.env -!.env.example .DS_Store -.react-router -build -node_modules -*.tsbuildinfo +/node_modules/ + +# React Router +/.react-router/ +/build/ diff --git a/integration-test/react-router/app/entry.server.tsx b/integration-test/react-router/app/entry.server.tsx index 194eadd2..6f791a6f 100644 --- a/integration-test/react-router/app/entry.server.tsx +++ b/integration-test/react-router/app/entry.server.tsx @@ -9,7 +9,7 @@ import { renderToPipeableStream } from "react-dom/server"; import { makeClient } from "./apollo"; import { ApolloProvider } from "@apollo/client/index.js"; -const ABORT_DELAY = 5_000; +export const streamTimeout = 5_000; export default function handleRequest( request: Request, @@ -32,11 +32,7 @@ export default function handleRequest( const client = makeClient(request); const { pipe, abort } = renderToPipeableStream( - + , { [readyOption]() { @@ -70,6 +66,8 @@ export default function handleRequest( } ); - setTimeout(abort, ABORT_DELAY); + // Abort the rendering stream after the `streamTimeout` so it has time to + // flush down the rejected boundaries + setTimeout(abort, streamTimeout + 1000); }); } diff --git a/integration-test/react-router/package.json b/integration-test/react-router/package.json index 25f12ba0..ea3ea30d 100644 --- a/integration-test/react-router/package.json +++ b/integration-test/react-router/package.json @@ -1,36 +1,36 @@ { - "name": "@integration-test/react-router", - "version": "0.0.0", + "name": "react-router", "private": true, "type": "module", "scripts": { - "build": "react-router build && node vercel/prepare.js", + "build": "react-router build", "dev": "react-router dev", "start": "react-router-serve ./build/server/index.js", - "typecheck": "react-router typegen && tsc --build --noEmit" + "typecheck": "react-router typegen && tsc" }, "dependencies": { "@apollo/client": "^3.11.10", "@apollo/client-integration-react-router": "workspace:^", "@integration-test/shared": "workspace:^", - "@react-router/node": "^7.0.1", - "@react-router/serve": "^7.0.1", + "@react-router/node": "^7.1.5", + "@react-router/serve": "^7.1.5", + "@vercel/react-router": "^1.0.2", + "graphql": "*", "isbot": "^5.1.17", - "react": "^19", - "react-dom": "^19", - "react-router": "7.0.2" + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-router": "^7.1.5" }, "devDependencies": { - "@react-router/dev": "^7.0.1", + "@react-router/dev": "^7.1.5", + "@tailwindcss/vite": "^4.0.0", "@types/node": "^20", - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", - "autoprefixer": "^10.4.20", - "graphql": "*", - "postcss": "^8.4.49", - "tailwindcss": "^3.4.15", - "typescript": "^5.6.3", + "@types/react": "^19.0.1", + "@types/react-dom": "^19.0.1", + "react-router-devtools": "^1.1.0", + "tailwindcss": "^4.0.0", + "typescript": "^5.7.2", "vite": "^5.4.11", - "vite-tsconfig-paths": "^5.1.2" + "vite-tsconfig-paths": "^5.1.4" } } diff --git a/integration-test/react-router/react-router.config.ts b/integration-test/react-router/react-router.config.ts index 8fcafa64..c3718b54 100644 --- a/integration-test/react-router/react-router.config.ts +++ b/integration-test/react-router/react-router.config.ts @@ -1,3 +1,9 @@ +import { vercelPreset } from "@vercel/react-router/vite"; import type { Config } from "@react-router/dev/config"; -export default {} satisfies Config; +export default { + // Config options... + // Server-side render by default, to enable SPA mode set this to `false` + ssr: true, + presets: process.env.VERCEL ? [vercelPreset()] : [], +} satisfies Config; diff --git a/integration-test/react-router/server/app.ts b/integration-test/react-router/server/app.ts deleted file mode 100644 index dfadc4fa..00000000 --- a/integration-test/react-router/server/app.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createRequestHandler } from "@react-router/express"; -import express from "express"; -import "react-router"; - -declare module "react-router" { - export interface AppLoadContext { - VALUE_FROM_VERCEL: string; - } -} - -const app = express(); - -app.use( - createRequestHandler({ - // @ts-expect-error - virtual module provided by React Router at build time - build: () => import("virtual:react-router/server-build"), - getLoadContext() { - return { - VALUE_FROM_VERCEL: "Hello from Vercel", - }; - }, - }) -); - -export default app; diff --git a/integration-test/react-router/tailwind.config.ts b/integration-test/react-router/tailwind.config.ts deleted file mode 100644 index 14d0f00c..00000000 --- a/integration-test/react-router/tailwind.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { Config } from "tailwindcss"; - -export default { - content: ["./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}"], - theme: { - extend: { - fontFamily: { - sans: [ - '"Inter"', - "ui-sans-serif", - "system-ui", - "sans-serif", - '"Apple Color Emoji"', - '"Segoe UI Emoji"', - '"Segoe UI Symbol"', - '"Noto Color Emoji"', - ], - }, - }, - }, - plugins: [], -} satisfies Config; diff --git a/integration-test/react-router/tsconfig.json b/integration-test/react-router/tsconfig.json index f73dcfac..41199847 100644 --- a/integration-test/react-router/tsconfig.json +++ b/integration-test/react-router/tsconfig.json @@ -7,23 +7,34 @@ "../shared/**/*" ], "compilerOptions": { - "lib": ["DOM", "DOM.Iterable", "ES2022"], - "types": ["node", "vite/client"], + "lib": [ + "DOM", + "DOM.Iterable", + "ES2022" + ], + "types": [ + "node", + "vite/client" + ], "target": "ES2022", "module": "ES2022", "moduleResolution": "bundler", "jsx": "react-jsx", - "rootDirs": [".", "./.react-router/types"], + "rootDirs": [ + ".", + "./.react-router/types" + ], "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": [ + "./app/*" + ] }, "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "isolatedModules": true, + "verbatimModuleSyntax": true, "noEmit": true, "resolveJsonModule": true, "skipLibCheck": true, "strict": true } -} +} \ No newline at end of file diff --git a/integration-test/react-router/vercel/output/config.json b/integration-test/react-router/vercel/output/config.json deleted file mode 100644 index afa42c77..00000000 --- a/integration-test/react-router/vercel/output/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "version": 3, - "routes": [ - { - "src": "/favicon.ico", - "dest": "/favicon.ico" - }, - { - "src": "/assets/(.*)", - "dest": "/assets/$1" - }, - { - "src": "/(.*)", - "dest": "/" - } - ] -} diff --git a/integration-test/react-router/vercel/output/functions/index.func/.vc-config.json b/integration-test/react-router/vercel/output/functions/index.func/.vc-config.json deleted file mode 100644 index 033eb405..00000000 --- a/integration-test/react-router/vercel/output/functions/index.func/.vc-config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "runtime": "nodejs20.x", - "handler": "index.js", - "launcherType": "Nodejs", - "shouldAddHelpers": true -} diff --git a/integration-test/react-router/vercel/output/functions/index.func/package.json b/integration-test/react-router/vercel/output/functions/index.func/package.json deleted file mode 100644 index 3dbc1ca5..00000000 --- a/integration-test/react-router/vercel/output/functions/index.func/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "module" -} diff --git a/integration-test/react-router/vercel/prepare.js b/integration-test/react-router/vercel/prepare.js deleted file mode 100644 index 1feee5bb..00000000 --- a/integration-test/react-router/vercel/prepare.js +++ /dev/null @@ -1,10 +0,0 @@ -import * as fsp from "node:fs/promises"; - -await fsp.rm(".vercel", { recursive: true }).catch(() => {}); -await fsp.mkdir(".vercel/output/static", { recursive: true }); - -await fsp.cp("vercel/output/", ".vercel/output", { recursive: true }); -await fsp.cp("build/client/", ".vercel/output/static", { recursive: true }); -await fsp.cp("build/server/", ".vercel/output/functions/index.func", { - recursive: true, -}); diff --git a/integration-test/react-router/vite.config.ts b/integration-test/react-router/vite.config.ts index 0b1fd393..4a88d587 100644 --- a/integration-test/react-router/vite.config.ts +++ b/integration-test/react-router/vite.config.ts @@ -1,24 +1,8 @@ import { reactRouter } from "@react-router/dev/vite"; -import autoprefixer from "autoprefixer"; -import tailwindcss from "tailwindcss"; +import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; -export default defineConfig(({ isSsrBuild, command }) => ({ - build: { - rollupOptions: isSsrBuild - ? { - input: "./server/app.ts", - } - : undefined, - }, - css: { - postcss: { - plugins: [tailwindcss, autoprefixer], - }, - }, - ssr: { - noExternal: command === "build" ? true : undefined, - }, - plugins: [reactRouter(), tsconfigPaths()], -})); +export default defineConfig({ + plugins: [tailwindcss(), reactRouter(), tsconfigPaths()], +}); diff --git a/package.json b/package.json index c143d9f0..25dfffba 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@microsoft/api-documenter": "7.24.1", "@apollo/client": "3.13.0-rc.0", "graphql": "17.0.0-alpha.2", - "react-router": "patch:react-router@npm%3A7.0.2#~/.yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch", + "react-router": "patch:react-router@npm%3A7.1.5#~/.yarn/patches/react-router-npm-7.1.5-9668fa2213.patch", "@tanstack/start": "1.99.6", "@tanstack/react-router": "1.99.6", "@tanstack/start-router-manifest": "1.99.0", diff --git a/packages/react-router/package.json b/packages/react-router/package.json index fc1fcbac..55cf8b39 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -79,7 +79,7 @@ "publint": "0.2.7", "react": "^19.0.0", "react-dom": "*", - "react-router": "patch:react-router@npm%3A7.0.2#~/.yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch", + "react-router": "^7.1.5", "rimraf": "5.0.5", "tsup": "8.0.2", "typescript": "5.4.5", diff --git a/yarn.config.cjs b/yarn.config.cjs index 25fe680d..bce02bf0 100644 --- a/yarn.config.cjs +++ b/yarn.config.cjs @@ -51,6 +51,8 @@ module.exports = defineConfig({ "@types/react-dom", "@tanstack/start", "@tanstack/react-router", + "@react-router/*", + "react-router", ]); for (const [ident, peers] of Object.entries(packagesWithFixedPeers)) { @@ -70,7 +72,7 @@ module.exports = defineConfig({ } for (const ident of Array.from(shouldBeUnique.values())) { if (Object.keys(getCandidates(ident)).length > 1) { - Yarn.workspace()?.error(` + Yarn.workspace()?.error(` The package ${ident} has multiple versions installed, which will cause problems. This could not be autofixed, so you need to manually fix it. Run this command to see how these installations differ from each other and fix them: diff --git a/yarn.lock b/yarn.lock index 7732582c..a6611dd8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -223,7 +223,7 @@ __metadata: publint: "npm:0.2.7" react: "npm:^19.0.0" react-dom: "npm:*" - react-router: "patch:react-router@npm%3A7.0.2#~/.yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch" + react-router: "npm:^7.1.5" rimraf: "npm:5.0.5" tsup: "npm:8.0.2" typescript: "npm:5.4.5" @@ -2449,6 +2449,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.1.2": + version: 7.26.7 + resolution: "@babel/runtime@npm:7.26.7" + dependencies: + regenerator-runtime: "npm:^0.14.0" + checksum: 10/c7a661a6836b332d9d2e047cba77ba1862c1e4f78cec7146db45808182ef7636d8a7170be9797e5d8fd513180bffb9fa16f6ca1c69341891efec56113cf22bfc + languageName: node + linkType: hard + "@babel/standalone@npm:^7.26.4": version: 7.26.4 resolution: "@babel/standalone@npm:7.26.4" @@ -2589,6 +2598,30 @@ __metadata: languageName: node linkType: hard +"@biomejs/cli-darwin-arm64@npm:^1.9.4": + version: 1.9.4 + resolution: "@biomejs/cli-darwin-arm64@npm:1.9.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@bkrem/react-transition-group@npm:^1.3.5": + version: 1.3.5 + resolution: "@bkrem/react-transition-group@npm:1.3.5" + dependencies: + chain-function: "npm:^1.0.0" + dom-helpers: "npm:^3.3.1" + loose-envify: "npm:^1.3.1" + prop-types: "npm:^15.5.6" + react-lifecycles-compat: "npm:^3.0.4" + warning: "npm:^3.0.0" + peerDependencies: + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10/90829b3da7dd0fa8f351e8d69afa73842adc448df7378499b7479509c772a608f5eb55f3b15f1ee94ed2bf359b3e48c8cc8832bab165bc8f4a8ed8711cfa4b16 + languageName: node + linkType: hard + "@chakra-ui/accordion@npm:2.1.11": version: 2.1.11 resolution: "@chakra-ui/accordion@npm:2.1.11" @@ -4123,6 +4156,25 @@ __metadata: languageName: node linkType: hard +"@emotion/babel-plugin@npm:^11.13.5": + version: 11.13.5 + resolution: "@emotion/babel-plugin@npm:11.13.5" + dependencies: + "@babel/helper-module-imports": "npm:^7.16.7" + "@babel/runtime": "npm:^7.18.3" + "@emotion/hash": "npm:^0.9.2" + "@emotion/memoize": "npm:^0.9.0" + "@emotion/serialize": "npm:^1.3.3" + babel-plugin-macros: "npm:^3.1.0" + convert-source-map: "npm:^1.5.0" + escape-string-regexp: "npm:^4.0.0" + find-root: "npm:^1.1.0" + source-map: "npm:^0.5.7" + stylis: "npm:4.2.0" + checksum: 10/cd310568314d886ca328e504f84c4f7f9c7f092ea34a2b43fdb61f84665bf301ba2ef49e0fd1e7ded3d81363d9bbefbb32674ce88b317cfb64db2b65e5ff423f + languageName: node + linkType: hard + "@emotion/cache@npm:^11.10.5, @emotion/cache@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/cache@npm:11.11.0" @@ -4136,6 +4188,19 @@ __metadata: languageName: node linkType: hard +"@emotion/cache@npm:^11.13.5, @emotion/cache@npm:^11.14.0": + version: 11.14.0 + resolution: "@emotion/cache@npm:11.14.0" + dependencies: + "@emotion/memoize": "npm:^0.9.0" + "@emotion/sheet": "npm:^1.4.0" + "@emotion/utils": "npm:^1.4.2" + "@emotion/weak-memoize": "npm:^0.4.0" + stylis: "npm:4.2.0" + checksum: 10/52336b28a27b07dde8fcdfd80851cbd1487672bbd4db1e24cca1440c95d8a6a968c57b0453c2b7c88d9b432b717f99554dbecc05b5cdef27933299827e69fd8e + languageName: node + linkType: hard + "@emotion/core@npm:^11.0.0": version: 11.0.0 resolution: "@emotion/core@npm:11.0.0" @@ -4143,6 +4208,19 @@ __metadata: languageName: node linkType: hard +"@emotion/css@npm:^11.13.5": + version: 11.13.5 + resolution: "@emotion/css@npm:11.13.5" + dependencies: + "@emotion/babel-plugin": "npm:^11.13.5" + "@emotion/cache": "npm:^11.13.5" + "@emotion/serialize": "npm:^1.3.3" + "@emotion/sheet": "npm:^1.4.0" + "@emotion/utils": "npm:^1.4.2" + checksum: 10/267acf535e6c82e5835563f38a2c49ddc320ba005aeee1b8d1b04a2a217ce6d45639601e95617a78f3746a424d92bbbc837f785dbc29c401e4b614c0c50766d9 + languageName: node + linkType: hard + "@emotion/hash@npm:^0.9.0": version: 0.9.0 resolution: "@emotion/hash@npm:0.9.0" @@ -4150,6 +4228,13 @@ __metadata: languageName: node linkType: hard +"@emotion/hash@npm:^0.9.2": + version: 0.9.2 + resolution: "@emotion/hash@npm:0.9.2" + checksum: 10/379bde2830ccb0328c2617ec009642321c0e009a46aa383dfbe75b679c6aea977ca698c832d225a893901f29d7b3eef0e38cf341f560f6b2b56f1ff23c172387 + languageName: node + linkType: hard + "@emotion/is-prop-valid@npm:^0.8.2": version: 0.8.8 resolution: "@emotion/is-prop-valid@npm:0.8.8" @@ -4182,6 +4267,13 @@ __metadata: languageName: node linkType: hard +"@emotion/memoize@npm:^0.9.0": + version: 0.9.0 + resolution: "@emotion/memoize@npm:0.9.0" + checksum: 10/038132359397348e378c593a773b1148cd0cf0a2285ffd067a0f63447b945f5278860d9de718f906a74c7c940ba1783ac2ca18f1c06a307b01cc0e3944e783b1 + languageName: node + linkType: hard + "@emotion/react@npm:^11.10.6": version: 11.10.6 resolution: "@emotion/react@npm:11.10.6" @@ -4203,6 +4295,27 @@ __metadata: languageName: node linkType: hard +"@emotion/react@npm:^11.14.0": + version: 11.14.0 + resolution: "@emotion/react@npm:11.14.0" + dependencies: + "@babel/runtime": "npm:^7.18.3" + "@emotion/babel-plugin": "npm:^11.13.5" + "@emotion/cache": "npm:^11.14.0" + "@emotion/serialize": "npm:^1.3.3" + "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.2.0" + "@emotion/utils": "npm:^1.4.2" + "@emotion/weak-memoize": "npm:^0.4.0" + hoist-non-react-statics: "npm:^3.3.1" + peerDependencies: + react: ">=16.8.0" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/3356c1d66f37f4e7abf88a2be843f6023b794b286c9c99a0aaf1cd1b2b7c50f8d80a2ef77183da737de70150f638e698ff4a2a38ab2d922f868615f1d5761c37 + languageName: node + linkType: hard + "@emotion/serialize@npm:^1.1.1": version: 1.1.1 resolution: "@emotion/serialize@npm:1.1.1" @@ -4216,6 +4329,19 @@ __metadata: languageName: node linkType: hard +"@emotion/serialize@npm:^1.3.3": + version: 1.3.3 + resolution: "@emotion/serialize@npm:1.3.3" + dependencies: + "@emotion/hash": "npm:^0.9.2" + "@emotion/memoize": "npm:^0.9.0" + "@emotion/unitless": "npm:^0.10.0" + "@emotion/utils": "npm:^1.4.2" + csstype: "npm:^3.0.2" + checksum: 10/44a2e06fc52dba177d9cf720f7b2c5d45ee4c0d9c09b78302d9a625e758d728ef3ae26f849237fec6f70e9eeb7d87e45a65028e944dc1f877df97c599f1cdaee + languageName: node + linkType: hard + "@emotion/sheet@npm:^1.2.2": version: 1.2.2 resolution: "@emotion/sheet@npm:1.2.2" @@ -4223,6 +4349,13 @@ __metadata: languageName: node linkType: hard +"@emotion/sheet@npm:^1.4.0": + version: 1.4.0 + resolution: "@emotion/sheet@npm:1.4.0" + checksum: 10/8ac6e9bf6b373a648f26ae7f1c24041038524f4c72f436f4f8c4761c665e58880c3229d8d89b1f7a4815dd8e5b49634d03e60187cb6f93097d7f7c1859e869d5 + languageName: node + linkType: hard + "@emotion/styled@npm:^11.10.6": version: 11.10.6 resolution: "@emotion/styled@npm:11.10.6" @@ -4243,6 +4376,13 @@ __metadata: languageName: node linkType: hard +"@emotion/unitless@npm:^0.10.0": + version: 0.10.0 + resolution: "@emotion/unitless@npm:0.10.0" + checksum: 10/6851c16edce01c494305f43b2cad7a26b939a821131b7c354e49b8e3b012c8810024755b0f4a03ef51117750309e55339825a97bd10411fb3687e68904769106 + languageName: node + linkType: hard + "@emotion/unitless@npm:^0.8.0": version: 0.8.0 resolution: "@emotion/unitless@npm:0.8.0" @@ -4259,6 +4399,15 @@ __metadata: languageName: node linkType: hard +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.2.0" + peerDependencies: + react: ">=16.8.0" + checksum: 10/2374999db8d53ef661d61ed1026c42a849632e4f03826f7eba0314c1d92ae342161d737f5045453aa46dd4008e13ccefeba68d3165b667dfad8e5784fcb0c643 + languageName: node + linkType: hard + "@emotion/utils@npm:^1.2.0, @emotion/utils@npm:^1.2.1": version: 1.2.1 resolution: "@emotion/utils@npm:1.2.1" @@ -4266,6 +4415,13 @@ __metadata: languageName: node linkType: hard +"@emotion/utils@npm:^1.4.2": + version: 1.4.2 + resolution: "@emotion/utils@npm:1.4.2" + checksum: 10/e5f3b8bca066b3361a7ad9064baeb9d01ed1bf51d98416a67359b62cb3affec6bb0249802c4ed11f4f8030f93cc4b67506909420bdb110adec6983d712897208 + languageName: node + linkType: hard + "@emotion/weak-memoize@npm:^0.3.0, @emotion/weak-memoize@npm:^0.3.1": version: 0.3.1 resolution: "@emotion/weak-memoize@npm:0.3.1" @@ -4273,6 +4429,13 @@ __metadata: languageName: node linkType: hard +"@emotion/weak-memoize@npm:^0.4.0": + version: 0.4.0 + resolution: "@emotion/weak-memoize@npm:0.4.0" + checksum: 10/db5da0e89bd752c78b6bd65a1e56231f0abebe2f71c0bd8fc47dff96408f7065b02e214080f99924f6a3bfe7ee15afc48dad999d76df86b39b16e513f7a94f52 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.19.12": version: 0.19.12 resolution: "@esbuild/aix-ppc64@npm:0.19.12" @@ -5522,6 +5685,44 @@ __metadata: languageName: node linkType: hard +"@floating-ui/core@npm:^1.6.0": + version: 1.6.9 + resolution: "@floating-ui/core@npm:1.6.9" + dependencies: + "@floating-ui/utils": "npm:^0.2.9" + checksum: 10/656fcd383da17fffca2efa0635cbe3c0b835c3312949e30bd19d05bf42479f2ac22aaf336a6a31cb160621fc6f35cfc9e115e76c5cf48ba96e33474d123ced22 + languageName: node + linkType: hard + +"@floating-ui/dom@npm:^1.0.0, @floating-ui/dom@npm:^1.6.1": + version: 1.6.13 + resolution: "@floating-ui/dom@npm:1.6.13" + dependencies: + "@floating-ui/core": "npm:^1.6.0" + "@floating-ui/utils": "npm:^0.2.9" + checksum: 10/4bb732baf3270007741bcdc91be1de767b2bb5d8b891eb838e5f1e7c4cccad998643dbdd4e8b8cec4c5d12c9898f80febc68e9793dd6e26a445283c4fb1b6a78 + languageName: node + linkType: hard + +"@floating-ui/react-dom@npm:^2.0.0": + version: 2.1.2 + resolution: "@floating-ui/react-dom@npm:2.1.2" + dependencies: + "@floating-ui/dom": "npm:^1.0.0" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 10/2a67dc8499674e42ff32c7246bded185bb0fdd492150067caf9568569557ac4756a67787421d8604b0f241e5337de10762aee270d9aeef106d078a0ff13596c4 + languageName: node + linkType: hard + +"@floating-ui/utils@npm:^0.2.9": + version: 0.2.9 + resolution: "@floating-ui/utils@npm:0.2.9" + checksum: 10/0ca786347db3dd8d9034b86d1449fabb96642788e5900cc5f2aee433cd7b243efbcd7a165bead50b004ee3f20a90ddebb6a35296fc41d43cfd361b6f01b69ffb + languageName: node + linkType: hard + "@gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -6559,33 +6760,6 @@ __metadata: languageName: unknown linkType: soft -"@integration-test/react-router@workspace:integration-test/react-router": - version: 0.0.0-use.local - resolution: "@integration-test/react-router@workspace:integration-test/react-router" - dependencies: - "@apollo/client": "npm:^3.11.10" - "@apollo/client-integration-react-router": "workspace:^" - "@integration-test/shared": "workspace:^" - "@react-router/dev": "npm:^7.0.1" - "@react-router/node": "npm:^7.0.1" - "@react-router/serve": "npm:^7.0.1" - "@types/node": "npm:^20" - "@types/react": "npm:^19.0.8" - "@types/react-dom": "npm:^19.0.3" - autoprefixer: "npm:^10.4.20" - graphql: "npm:*" - isbot: "npm:^5.1.17" - postcss: "npm:^8.4.49" - react: "npm:^19" - react-dom: "npm:^19" - react-router: "npm:7.0.2" - tailwindcss: "npm:^3.4.15" - typescript: "npm:^5.6.3" - vite: "npm:^5.4.11" - vite-tsconfig-paths: "npm:^5.1.2" - languageName: unknown - linkType: soft - "@integration-test/shared@workspace:^, @integration-test/shared@workspace:integration-test/shared": version: 0.0.0-use.local resolution: "@integration-test/shared@workspace:integration-test/shared" @@ -7403,6 +7577,13 @@ __metadata: languageName: node linkType: hard +"@one-ini/wasm@npm:0.1.1": + version: 0.1.1 + resolution: "@one-ini/wasm@npm:0.1.1" + checksum: 10/673c11518dba2e582e42415cbefe928513616f3af25e12f6e4e6b1b98b52b3e6c14bc251a361654af63cd64f208f22a1f7556fa49da2bf7efcf28cb14f16f807 + languageName: node + linkType: hard + "@parcel/watcher-android-arm64@npm:2.5.0": version: 2.5.0 resolution: "@parcel/watcher-android-arm64@npm:2.5.0" @@ -7721,6 +7902,491 @@ __metadata: languageName: node linkType: hard +"@radix-ui/number@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/number@npm:1.1.0" + checksum: 10/e4fc7483c19141c25dbaf3d140b75e2b7fed0bfa3ad969f4441f0266ed34b35413f57a35df7b025e2a977152bbe6131849d3444fc6f15a73345dfc2bfdc105fa + languageName: node + linkType: hard + +"@radix-ui/primitive@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/primitive@npm:1.1.1" + checksum: 10/d7e819177590108b74139809d52ec043c0962ae3513e947998be575fb13639c5c1c091896ddcf1d6a22a777d44ade59d22c2019ce9099607fc62a5de09c59707 + languageName: node + linkType: hard + +"@radix-ui/react-accordion@npm:^1.2.2": + version: 1.2.3 + resolution: "@radix-ui/react-accordion@npm:1.2.3" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-collapsible": "npm:1.1.3" + "@radix-ui/react-collection": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-direction": "npm:1.1.0" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/c44094b4817a39ec9db3446e46a68a26f92d68aa74eb1660869b4bdf2f1b15b59b23abf33c12c48f47f56d7fd93e46e4d4175c7565a40a76f55748a92fb32f69 + languageName: node + linkType: hard + +"@radix-ui/react-arrow@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-arrow@npm:1.1.2" + dependencies: + "@radix-ui/react-primitive": "npm:2.0.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/75dcb4430c1d3d4eb1635bbdd61f9eb079a9a9ad0281f4db4107f3dd6965164aba594c466b24ed5f29e498ad8bc3c8ec1ed78d9ccce9f7a7b3c380a36437fdb4 + languageName: node + linkType: hard + +"@radix-ui/react-collapsible@npm:1.1.3": + version: 1.1.3 + resolution: "@radix-ui/react-collapsible@npm:1.1.3" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-presence": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/4d8fcd68e3b3b9ad87728d0acc6b9afb61d6eb742187536a1eb335fe54855e0039632d5c36e86e61359b45ad1f5768688216c7732cd27add5b87c054e60ae9e6 + languageName: node + linkType: hard + +"@radix-ui/react-collection@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-collection@npm:1.1.2" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-slot": "npm:1.1.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/f9ecb91327262f8d373b820cd72645b5de40ce8fa99070db537092629d1e0ba67c3f9b50e360a6532a029544e93a92f2e508ffff0c371791b4239e12f61bc697 + languageName: node + linkType: hard + +"@radix-ui/react-compose-refs@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-compose-refs@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/1be82f9f7fab96cc10f167a2e4f976e0135a63d473334f664c06f02af13bc5ea1994cb0505f89ed190d756cb65d57506721c030908af07e49b9e3cfd36044f33 + languageName: node + linkType: hard + +"@radix-ui/react-context@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-context@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/f6469583bf11cc7bff3ea5c95c56b0774a959512adead00dc64b0527cca01b90b476ca39a64edfd7e18e428e17940aa0339116b1ce5b6e8eab513cfd1065d391 + languageName: node + linkType: hard + +"@radix-ui/react-direction@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-direction@npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/25ad0d1d65ad08c93cebfbefdff9ef2602e53f4573a66b37d2c366ede9485e75ec6fc8e7dd7d2939b34ea5504ca0fe6ac4a3acc2f6ee9b62d131d65486eafd49 + languageName: node + linkType: hard + +"@radix-ui/react-dismissable-layer@npm:1.1.5": + version: 1.1.5 + resolution: "@radix-ui/react-dismissable-layer@npm:1.1.5" + dependencies: + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + "@radix-ui/react-use-escape-keydown": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/1f9e57f4e52712897b2a61541f54dd4a53172685345e885b11a47c1e6227b0927c399324e8b39c027148f8d7fd661212de7740589c15b2a7e61328b33fad473e + languageName: node + linkType: hard + +"@radix-ui/react-focus-guards@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-focus-guards@npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/ac8dd31f48fa0500bafd9368f2f06c5a06918dccefa89fa5dc77ca218dc931a094a81ca57f6b181138029822f7acdd5280dceccf5ba4d9263c754fb8f7961879 + languageName: node + linkType: hard + +"@radix-ui/react-focus-scope@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-focus-scope@npm:1.1.2" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/dfb2d098d5af01260dd67a268fe99aa634cbef677b660fdce7079d4e1869de2243062807441a4ee4f65c7e0db6974691996efe1d5161a4da70482541c4fe5c70 + languageName: node + linkType: hard + +"@radix-ui/react-id@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-id@npm:1.1.0" + dependencies: + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/6fbc9d1739b3b082412da10359e63967b4f3a60383ebda4c9e56b07a722d29bee53b203b3b1418f88854a29315a7715867133bb149e6e22a027a048cdd20d970 + languageName: node + linkType: hard + +"@radix-ui/react-popper@npm:1.2.2": + version: 1.2.2 + resolution: "@radix-ui/react-popper@npm:1.2.2" + dependencies: + "@floating-ui/react-dom": "npm:^2.0.0" + "@radix-ui/react-arrow": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + "@radix-ui/react-use-rect": "npm:1.1.0" + "@radix-ui/react-use-size": "npm:1.1.0" + "@radix-ui/rect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/c76d65f86360e3971ce42356874c9729588fed03369d49e8b84afb26313ce65e1e5bd043ff1d33e0cd6dc198b76fc65532ab9dace4f34dbdb36c07fefd06065a + languageName: node + linkType: hard + +"@radix-ui/react-portal@npm:1.1.4": + version: 1.1.4 + resolution: "@radix-ui/react-portal@npm:1.1.4" + dependencies: + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/7797c53d071c762e234c92b5ca721f97ba300969fa9d630e808d436a896082b7c31553cdc0ed1cbfd46b76fe2ddbe5e3a0790f9ff2f6542923b896301a634bbd + languageName: node + linkType: hard + +"@radix-ui/react-presence@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-presence@npm:1.1.2" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/b7c7a1eed6e2a4b8778f37d925bca12fccb2a3fdd48fa854cb3d6308592aec7253b0a193cba65b8c323e14a14119935434e8f6d9bdc0fbf97450c0da1b4eb0f9 + languageName: node + linkType: hard + +"@radix-ui/react-primitive@npm:2.0.2": + version: 2.0.2 + resolution: "@radix-ui/react-primitive@npm:2.0.2" + dependencies: + "@radix-ui/react-slot": "npm:1.1.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/877b20d63487d0dec3f152f59a11d5826507d0839603b48b6aaa3f3eededea11f040ed36d6b868c02a7364570e5fbbbdb102c624fd930d4ed308b36c57154638 + languageName: node + linkType: hard + +"@radix-ui/react-select@npm:^2.1.5": + version: 2.1.6 + resolution: "@radix-ui/react-select@npm:2.1.6" + dependencies: + "@radix-ui/number": "npm:1.1.0" + "@radix-ui/primitive": "npm:1.1.1" + "@radix-ui/react-collection": "npm:1.1.2" + "@radix-ui/react-compose-refs": "npm:1.1.1" + "@radix-ui/react-context": "npm:1.1.1" + "@radix-ui/react-direction": "npm:1.1.0" + "@radix-ui/react-dismissable-layer": "npm:1.1.5" + "@radix-ui/react-focus-guards": "npm:1.1.1" + "@radix-ui/react-focus-scope": "npm:1.1.2" + "@radix-ui/react-id": "npm:1.1.0" + "@radix-ui/react-popper": "npm:1.2.2" + "@radix-ui/react-portal": "npm:1.1.4" + "@radix-ui/react-primitive": "npm:2.0.2" + "@radix-ui/react-slot": "npm:1.1.2" + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + "@radix-ui/react-use-controllable-state": "npm:1.1.0" + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + "@radix-ui/react-use-previous": "npm:1.1.0" + "@radix-ui/react-visually-hidden": "npm:1.1.2" + aria-hidden: "npm:^1.2.4" + react-remove-scroll: "npm:^2.6.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/0ec6e7615fb397d78ddad16cdea1fc6d4821d2c29a947199f2842d70224308017e2ef9dc9db4e7fcd33b07576ac7ca30a12f402a39b4ba2bc9b88c436ffb4885 + languageName: node + linkType: hard + +"@radix-ui/react-slot@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-slot@npm:1.1.2" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/6d5e1fac17b3eb79019a697581133dff23a3f6406f8ecfca476ab4a6a73baa53d66a7c9caeeebcc677363aa3b4132aa9d2168641ba9642658a2e4a297c05e4d3 + languageName: node + linkType: hard + +"@radix-ui/react-use-callback-ref@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-callback-ref@npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/2ec7903c67e3034b646005556f44fd975dc5204db6885fc58403e3584f27d95f0b573bc161de3d14fab9fda25150bf3b91f718d299fdfc701c736bd0bd2281fa + languageName: node + linkType: hard + +"@radix-ui/react-use-controllable-state@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-controllable-state@npm:1.1.0" + dependencies: + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/9583679150dc521c9de20ee22cb858697dd4f5cefc46ab8ebfc5e7511415a053994e87d4ca3f49de84d27eebc13535b0a6c9892c91ab43e3e553e5d7270f378f + languageName: node + linkType: hard + +"@radix-ui/react-use-escape-keydown@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-escape-keydown@npm:1.1.0" + dependencies: + "@radix-ui/react-use-callback-ref": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/9bf88ea272b32ea0f292afd336780a59c5646f795036b7e6105df2d224d73c54399ee5265f61d571eb545d28382491a8b02dc436e3088de8dae415d58b959b71 + languageName: node + linkType: hard + +"@radix-ui/react-use-layout-effect@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-layout-effect@npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/271ea0bf1cd74718895a68414a6e95537737f36e02ad08eeb61a82b229d6abda9cff3135a479e134e1f0ce2c3ff97bb85babbdce751985fb755a39b231d7ccf2 + languageName: node + linkType: hard + +"@radix-ui/react-use-previous@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-previous@npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/8a2407e3db6248ab52bf425f5f4161355d09f1a228038094959250ae53552e73543532b3bb80e452f6ad624621e2e1c6aebb8c702f2dfaa5e89f07ec629d9304 + languageName: node + linkType: hard + +"@radix-ui/react-use-rect@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-rect@npm:1.1.0" + dependencies: + "@radix-ui/rect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/facc9528af43df3b01952dbb915ff751b5924db2c31d41f053ddea19a7cc5cac5b096c4d7a2059e8f564a3f0d4a95bcd909df8faed52fa01709af27337628e2c + languageName: node + linkType: hard + +"@radix-ui/react-use-size@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/react-use-size@npm:1.1.0" + dependencies: + "@radix-ui/react-use-layout-effect": "npm:1.1.0" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/01a11d4c07fc620b8a081e53d7ec8495b19a11e02688f3d9f47cf41a5fe0428d1e52ed60b2bf88dfd447dc2502797b9dad2841097389126dd108530913c4d90d + languageName: node + linkType: hard + +"@radix-ui/react-visually-hidden@npm:1.1.2": + version: 1.1.2 + resolution: "@radix-ui/react-visually-hidden@npm:1.1.2" + dependencies: + "@radix-ui/react-primitive": "npm:2.0.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10/87dc45ffb32b652bde629bb5c3b216adb82fd1ec68c484fec260980b31508cbc515a73327798d0f47d558dd22245b25f51bb06296b1762693af9f27e23c1cb1f + languageName: node + linkType: hard + +"@radix-ui/rect@npm:1.1.0": + version: 1.1.0 + resolution: "@radix-ui/rect@npm:1.1.0" + checksum: 10/3ffdc5e3f7bcd91de4d5983513bd11c3a82b89b966e5c1bd8c17690a8f5da2d83fa156474c7b68fc6b9465df2281f81983b146e1d9dc57d332abda05751a9cbc + languageName: node + linkType: hard + "@react-aria/focus@npm:^3.1.0, @react-aria/focus@npm:^3.12.0": version: 3.12.0 resolution: "@react-aria/focus@npm:3.12.0" @@ -7823,9 +8489,9 @@ __metadata: languageName: node linkType: hard -"@react-router/dev@npm:^7.0.1": - version: 7.1.3 - resolution: "@react-router/dev@npm:7.1.3" +"@react-router/dev@npm:^7.1.5": + version: 7.1.5 + resolution: "@react-router/dev@npm:7.1.5" dependencies: "@babel/core": "npm:^7.21.8" "@babel/generator": "npm:^7.21.5" @@ -7836,7 +8502,7 @@ __metadata: "@babel/traverse": "npm:^7.23.2" "@babel/types": "npm:^7.22.5" "@npmcli/package-json": "npm:^4.0.1" - "@react-router/node": "npm:7.1.3" + "@react-router/node": "npm:7.1.5" arg: "npm:^5.0.1" babel-dead-code-elimination: "npm:^1.0.6" chokidar: "npm:^4.0.0" @@ -7857,8 +8523,8 @@ __metadata: valibot: "npm:^0.41.0" vite-node: "npm:3.0.0-beta.2" peerDependencies: - "@react-router/serve": ^7.1.3 - react-router: ^7.1.3 + "@react-router/serve": ^7.1.5 + react-router: ^7.1.5 typescript: ^5.1.0 vite: ^5.1.0 || ^6.0.0 wrangler: ^3.28.2 @@ -7871,60 +8537,60 @@ __metadata: optional: true bin: react-router: bin.js - checksum: 10/25ca20cd96f20127b46cd758a729b5ff708c6d5eeba1de4117dbf38e7e5be168783b36ddab7335f34d6fda8d49d17364ead29e3f02a47007f2f28f0c4688712a + checksum: 10/651bb041c7ff2f5268601b65e7ceffe48cac89bdb1fb07d4c5340e3cfb46ac18fa5a02c0a20615de3c4d0239c90091e51b00c9f73632da64d5c9bb2a73b196c8 languageName: node linkType: hard -"@react-router/express@npm:7.1.3": - version: 7.1.3 - resolution: "@react-router/express@npm:7.1.3" +"@react-router/express@npm:7.1.5": + version: 7.1.5 + resolution: "@react-router/express@npm:7.1.5" dependencies: - "@react-router/node": "npm:7.1.3" + "@react-router/node": "npm:7.1.5" peerDependencies: express: ^4.17.1 - react-router: 7.1.3 + react-router: 7.1.5 typescript: ^5.1.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/ff5591426718d5e4f3b5b0500ede85db020fc01d8690ee529e26dd06b2709e8f1952242b80b116c8610cebf58fe40d657956b8d5d6baf4725b7caaca400cc9e7 + checksum: 10/861cbf520177347bfa4036c4dfc8fe69d780a8715e82b0892a9db98d22c809a15295792fddba660f614af247cffcb5554ce57be2953c4e125467440c82651a59 languageName: node linkType: hard -"@react-router/node@npm:7.1.3, @react-router/node@npm:^7.0.1": - version: 7.1.3 - resolution: "@react-router/node@npm:7.1.3" +"@react-router/node@npm:7.1.5, @react-router/node@npm:^7.1.5": + version: 7.1.5 + resolution: "@react-router/node@npm:7.1.5" dependencies: "@mjackson/node-fetch-server": "npm:^0.2.0" source-map-support: "npm:^0.5.21" stream-slice: "npm:^0.1.2" undici: "npm:^6.19.2" peerDependencies: - react-router: 7.1.3 + react-router: 7.1.5 typescript: ^5.1.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/562db94545ff8bff351e530a92eee2b9a6ae66cedf5565cbc5ecbcdad5803a1523feab8678faee3914d2ecd496621ed163ab8e0a927d99d84b911f12c4856262 + checksum: 10/0593b0bcd2ceb3d50a1e63d1cdbf6f12f0a42a1c976a7abdc6e20fc714058712aac552cc8356b8f62a74151c75d813839f7521abe514a005efb7840e1a612df0 languageName: node linkType: hard -"@react-router/serve@npm:^7.0.1": - version: 7.1.3 - resolution: "@react-router/serve@npm:7.1.3" +"@react-router/serve@npm:^7.1.5": + version: 7.1.5 + resolution: "@react-router/serve@npm:7.1.5" dependencies: - "@react-router/express": "npm:7.1.3" - "@react-router/node": "npm:7.1.3" + "@react-router/express": "npm:7.1.5" + "@react-router/node": "npm:7.1.5" compression: "npm:^1.7.4" express: "npm:^4.19.2" get-port: "npm:5.1.1" morgan: "npm:^1.10.0" source-map-support: "npm:^0.5.21" peerDependencies: - react-router: 7.1.3 + react-router: 7.1.5 bin: react-router-serve: bin.js - checksum: 10/8f3c0734e26f0e6e66030fcad4f74cb84aa170d0424157accdedd17e6efaacdf3819d5083277f0acc44348e717d8bfb7b0dd043eb6108e136ff414a427e28ccc + checksum: 10/a9b67b7f7185fdbab1bc92823595ca03e0171ab750c36a157f78c677c305a0e90e38a66923525ee00abd8e2ad4c5c6bb658d583ad301617487557dc7117782af languageName: node linkType: hard @@ -8198,6 +8864,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:^4.32.1": + version: 4.34.6 + resolution: "@rollup/rollup-darwin-arm64@npm:4.34.6" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.28.1": version: 4.28.1 resolution: "@rollup/rollup-darwin-x64@npm:4.28.1" @@ -8366,6 +9039,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:^4.32.1": + version: 4.34.6 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.34.6" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.28.1": version: 4.28.1 resolution: "@rollup/rollup-linux-x64-musl@npm:4.28.1" @@ -8790,61 +9470,205 @@ __metadata: languageName: node linkType: hard -"@statoscope/webpack-stats-extension-package-info@npm:5.28.2": - version: 5.28.2 - resolution: "@statoscope/webpack-stats-extension-package-info@npm:5.28.2" - dependencies: - "@statoscope/stats": "npm:5.28.1" - "@statoscope/stats-extension-package-info": "npm:5.28.1" - "@statoscope/webpack-model": "npm:5.28.2" - "@types/webpack": "npm:^5.0.0" - peerDependencies: - webpack: ^4.0.0 || ^5.0.0 - checksum: 10/922d9693a0694b4af9a4a565793cd717e67c65b361aa0aeaef0f6d186d8f5d378d393addc3eabc8f6c4130db16d2e5614d97da492f153fee33eb5600320f1392 +"@statoscope/webpack-stats-extension-package-info@npm:5.28.2": + version: 5.28.2 + resolution: "@statoscope/webpack-stats-extension-package-info@npm:5.28.2" + dependencies: + "@statoscope/stats": "npm:5.28.1" + "@statoscope/stats-extension-package-info": "npm:5.28.1" + "@statoscope/webpack-model": "npm:5.28.2" + "@types/webpack": "npm:^5.0.0" + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + checksum: 10/922d9693a0694b4af9a4a565793cd717e67c65b361aa0aeaef0f6d186d8f5d378d393addc3eabc8f6c4130db16d2e5614d97da492f153fee33eb5600320f1392 + languageName: node + linkType: hard + +"@statoscope/webpack-ui@npm:5.28.2": + version: 5.28.2 + resolution: "@statoscope/webpack-ui@npm:5.28.2" + dependencies: + "@statoscope/types": "npm:5.28.1" + "@types/md5": "npm:^2.3.2" + checksum: 10/8b60312403758f118b924f069e75bbe78582d54d43e5f419a89e4756ec5aedb3265b901823dc936b80e8e7a7c9f91b4f4d282b4d1ef09b17efb856465c7ac1f0 + languageName: node + linkType: hard + +"@swc/counter@npm:0.1.3": + version: 0.1.3 + resolution: "@swc/counter@npm:0.1.3" + checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 + languageName: node + linkType: hard + +"@swc/helpers@npm:0.5.15": + version: 0.5.15 + resolution: "@swc/helpers@npm:0.5.15" + dependencies: + tslib: "npm:^2.8.0" + checksum: 10/e3f32c6deeecfb0fa3f22edff03a7b358e7ce16d27b0f1c8b5cdc3042c5c4ce4da6eac0b781ab7cc4f54696ece657467d56734fb26883439fb00017385364c4c + languageName: node + linkType: hard + +"@swc/helpers@npm:^0.4.14": + version: 0.4.14 + resolution: "@swc/helpers@npm:0.4.14" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/236afd445fb22e3df7aa84336d5c45d29e021ad01917aa7c24267330df8b39ed89c3d8d9836ac2ac7569b46923591d0e49174f72df7fb997aea841d08f374dbd + languageName: node + linkType: hard + +"@szmarczak/http-timer@npm:^4.0.5": + version: 4.0.6 + resolution: "@szmarczak/http-timer@npm:4.0.6" + dependencies: + defer-to-connect: "npm:^2.0.0" + checksum: 10/c29df3bcec6fc3bdec2b17981d89d9c9fc9bd7d0c9bcfe92821dc533f4440bc890ccde79971838b4ceed1921d456973c4180d7175ee1d0023ad0562240a58d95 + languageName: node + linkType: hard + +"@tailwindcss/node@npm:^4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/node@npm:4.0.6" + dependencies: + enhanced-resolve: "npm:^5.18.0" + jiti: "npm:^2.4.2" + tailwindcss: "npm:4.0.6" + checksum: 10/9be034f28d12f68d001e64bb10297b5018efe2e29ad5b43b7cb0921146e14dcf0a1f8389f13f143c71374c4513fde348993d6cbaa8116d6c02d9d5b5de8a0337 + languageName: node + linkType: hard + +"@tailwindcss/oxide-android-arm64@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-android-arm64@npm:4.0.6" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@tailwindcss/oxide-darwin-arm64@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-darwin-arm64@npm:4.0.6" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@tailwindcss/oxide-darwin-x64@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-darwin-x64@npm:4.0.6" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@tailwindcss/oxide-freebsd-x64@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-freebsd-x64@npm:4.0.6" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@tailwindcss/oxide-linux-arm-gnueabihf@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-linux-arm-gnueabihf@npm:4.0.6" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@tailwindcss/oxide-linux-arm64-gnu@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-linux-arm64-gnu@npm:4.0.6" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@tailwindcss/oxide-linux-arm64-musl@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-linux-arm64-musl@npm:4.0.6" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@tailwindcss/oxide-linux-x64-gnu@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-linux-x64-gnu@npm:4.0.6" + conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@statoscope/webpack-ui@npm:5.28.2": - version: 5.28.2 - resolution: "@statoscope/webpack-ui@npm:5.28.2" - dependencies: - "@statoscope/types": "npm:5.28.1" - "@types/md5": "npm:^2.3.2" - checksum: 10/8b60312403758f118b924f069e75bbe78582d54d43e5f419a89e4756ec5aedb3265b901823dc936b80e8e7a7c9f91b4f4d282b4d1ef09b17efb856465c7ac1f0 +"@tailwindcss/oxide-linux-x64-musl@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-linux-x64-musl@npm:4.0.6" + conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@swc/counter@npm:0.1.3": - version: 0.1.3 - resolution: "@swc/counter@npm:0.1.3" - checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 +"@tailwindcss/oxide-win32-arm64-msvc@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-win32-arm64-msvc@npm:4.0.6" + conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@swc/helpers@npm:0.5.15": - version: 0.5.15 - resolution: "@swc/helpers@npm:0.5.15" - dependencies: - tslib: "npm:^2.8.0" - checksum: 10/e3f32c6deeecfb0fa3f22edff03a7b358e7ce16d27b0f1c8b5cdc3042c5c4ce4da6eac0b781ab7cc4f54696ece657467d56734fb26883439fb00017385364c4c +"@tailwindcss/oxide-win32-x64-msvc@npm:4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide-win32-x64-msvc@npm:4.0.6" + conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@swc/helpers@npm:^0.4.14": - version: 0.4.14 - resolution: "@swc/helpers@npm:0.4.14" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10/236afd445fb22e3df7aa84336d5c45d29e021ad01917aa7c24267330df8b39ed89c3d8d9836ac2ac7569b46923591d0e49174f72df7fb997aea841d08f374dbd +"@tailwindcss/oxide@npm:^4.0.6": + version: 4.0.6 + resolution: "@tailwindcss/oxide@npm:4.0.6" + dependencies: + "@tailwindcss/oxide-android-arm64": "npm:4.0.6" + "@tailwindcss/oxide-darwin-arm64": "npm:4.0.6" + "@tailwindcss/oxide-darwin-x64": "npm:4.0.6" + "@tailwindcss/oxide-freebsd-x64": "npm:4.0.6" + "@tailwindcss/oxide-linux-arm-gnueabihf": "npm:4.0.6" + "@tailwindcss/oxide-linux-arm64-gnu": "npm:4.0.6" + "@tailwindcss/oxide-linux-arm64-musl": "npm:4.0.6" + "@tailwindcss/oxide-linux-x64-gnu": "npm:4.0.6" + "@tailwindcss/oxide-linux-x64-musl": "npm:4.0.6" + "@tailwindcss/oxide-win32-arm64-msvc": "npm:4.0.6" + "@tailwindcss/oxide-win32-x64-msvc": "npm:4.0.6" + dependenciesMeta: + "@tailwindcss/oxide-android-arm64": + optional: true + "@tailwindcss/oxide-darwin-arm64": + optional: true + "@tailwindcss/oxide-darwin-x64": + optional: true + "@tailwindcss/oxide-freebsd-x64": + optional: true + "@tailwindcss/oxide-linux-arm-gnueabihf": + optional: true + "@tailwindcss/oxide-linux-arm64-gnu": + optional: true + "@tailwindcss/oxide-linux-arm64-musl": + optional: true + "@tailwindcss/oxide-linux-x64-gnu": + optional: true + "@tailwindcss/oxide-linux-x64-musl": + optional: true + "@tailwindcss/oxide-win32-arm64-msvc": + optional: true + "@tailwindcss/oxide-win32-x64-msvc": + optional: true + checksum: 10/31c5f5bfc79a9c23831e14301fbcc437fa2e61b25712b64786977eb21fee6082862e8010273eed91592a2c5ba41499b2f67a53ee1e44ad9d733158f622060c34 languageName: node linkType: hard -"@szmarczak/http-timer@npm:^4.0.5": +"@tailwindcss/vite@npm:^4.0.0": version: 4.0.6 - resolution: "@szmarczak/http-timer@npm:4.0.6" + resolution: "@tailwindcss/vite@npm:4.0.6" dependencies: - defer-to-connect: "npm:^2.0.0" - checksum: 10/c29df3bcec6fc3bdec2b17981d89d9c9fc9bd7d0c9bcfe92821dc533f4440bc890ccde79971838b4ceed1921d456973c4180d7175ee1d0023ad0562240a58d95 + "@tailwindcss/node": "npm:^4.0.6" + "@tailwindcss/oxide": "npm:^4.0.6" + lightningcss: "npm:^1.29.1" + tailwindcss: "npm:4.0.6" + peerDependencies: + vite: ^5.2.0 || ^6 + checksum: 10/b01050554d1b8b0234ad71fdca4272a6f6f084541b298114a3e14f91ca081083f656f67acc779ecb5dc573317b736c06fab9358905395f587ff51dad5eb8ccff languageName: node linkType: hard @@ -9360,6 +10184,18 @@ __metadata: languageName: node linkType: hard +"@ts-morph/common@npm:~0.11.0": + version: 0.11.1 + resolution: "@ts-morph/common@npm:0.11.1" + dependencies: + fast-glob: "npm:^3.2.7" + minimatch: "npm:^3.0.4" + mkdirp: "npm:^1.0.4" + path-browserify: "npm:^1.0.1" + checksum: 10/6a66c50ef2f3b2edd2ea87c2ee2eaf916a41fdd6c94da58dcffe3923c9ceae36eb6a34b22dba4200cc50427b982ada9b4df048dc21509bb99b2725e4dfcf0063 + languageName: node + linkType: hard + "@tsconfig/recommended@npm:1.0.6": version: 1.0.6 resolution: "@tsconfig/recommended@npm:1.0.6" @@ -9646,7 +10482,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.8": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.8": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 10/1a3c3e06236e4c4aab89499c428d585527ce50c24fe8259e8b3926d3df4cfbbbcf306cfc73ddfb66cbafc973116efd15967020b0f738f63e09e64c7d260519e7 @@ -9837,6 +10673,15 @@ __metadata: languageName: node linkType: hard +"@types/react-reconciler@npm:^0.28.9": + version: 0.28.9 + resolution: "@types/react-reconciler@npm:0.28.9" + peerDependencies: + "@types/react": "*" + checksum: 10/2450e3df6169fb887591f2a949ca8f08439ac76c756124feeee7370f1a79b5060ba8e5f612302dc70169433e043da7f617dd7ea3b14a3c2bb39559d66b7a0986 + languageName: node + linkType: hard + "@types/react@npm:19.0.2": version: 19.0.2 resolution: "@types/react@npm:19.0.2" @@ -10189,6 +11034,33 @@ __metadata: languageName: node linkType: hard +"@vercel/react-router@npm:^1.0.2": + version: 1.0.2 + resolution: "@vercel/react-router@npm:1.0.2" + dependencies: + "@vercel/static-config": "npm:3.0.0" + ts-morph: "npm:12.0.0" + peerDependencies: + "@react-router/dev": 7 + "@react-router/node": 7 + isbot: 5 + react: ">=18" + react-dom: ">=18" + checksum: 10/5f7e60adb6f84473603d37e61572f24395490bce19ff0fe2fb240fa97a8be77c9e4da27ad9f45bc053d9c87f63d2068ca93027fc2014f0ac6ee0659c2e111628 + languageName: node + linkType: hard + +"@vercel/static-config@npm:3.0.0": + version: 3.0.0 + resolution: "@vercel/static-config@npm:3.0.0" + dependencies: + ajv: "npm:8.6.3" + json-schema-to-ts: "npm:1.6.4" + ts-morph: "npm:12.0.0" + checksum: 10/69d9b0a4b1edd4dec767c512963a2000563c3923ce4343bf6f12bcfb30c8689338eb6216ab16d52f5ff16d4839fcc53ae6d4898a02582db8359d1ead5abd4cf1 + languageName: node + linkType: hard + "@vinxi/listhen@npm:^1.5.6": version: 1.5.6 resolution: "@vinxi/listhen@npm:1.5.6" @@ -11269,6 +12141,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:8.6.3": + version: 8.6.3 + resolution: "ajv@npm:8.6.3" + dependencies: + fast-deep-equal: "npm:^3.1.1" + json-schema-traverse: "npm:^1.0.0" + require-from-string: "npm:^2.0.2" + uri-js: "npm:^4.2.2" + checksum: 10/344796bb989c57788b0bffb6872b4a0d20b8cf44c70891a7f8484d614978342a8d5f3ac77a5dc4299d93b2c8225bf7bb224e1c78a1359c0489e6be537fdda184 + languageName: node + linkType: hard + "ajv@npm:^6.10.0, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:~6.12.6": version: 6.12.6 resolution: "ajv@npm:6.12.6" @@ -11573,6 +12457,15 @@ __metadata: languageName: node linkType: hard +"aria-hidden@npm:^1.2.4": + version: 1.2.4 + resolution: "aria-hidden@npm:1.2.4" + dependencies: + tslib: "npm:^2.0.0" + checksum: 10/df4bc15423aaaba3729a7d40abcbf6d3fffa5b8fd5eb33d3ac8b7da0110c47552fca60d97f2e1edfbb68a27cae1da499f1c3896966efb3e26aac4e3b57e3cc8b + languageName: node + linkType: hard + "aria-query@npm:5.3.0": version: 5.3.0 resolution: "aria-query@npm:5.3.0" @@ -11822,24 +12715,6 @@ __metadata: languageName: node linkType: hard -"autoprefixer@npm:^10.4.20": - version: 10.4.20 - resolution: "autoprefixer@npm:10.4.20" - dependencies: - browserslist: "npm:^4.23.3" - caniuse-lite: "npm:^1.0.30001646" - fraction.js: "npm:^4.3.7" - normalize-range: "npm:^0.1.2" - picocolors: "npm:^1.0.1" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.1.0 - bin: - autoprefixer: bin/autoprefixer - checksum: 10/d3c4b562fc4af2393623a0207cc336f5b9f94c4264ae1c316376904c279702ce2b12dc3f27205f491195d1e29bb52ffc269970ceb0f271f035fadee128a273f7 - languageName: node - linkType: hard - "available-typed-arrays@npm:^1.0.5": version: 1.0.5 resolution: "available-typed-arrays@npm:1.0.5" @@ -12102,6 +12977,19 @@ __metadata: languageName: node linkType: hard +"beautify@npm:^0.0.8": + version: 0.0.8 + resolution: "beautify@npm:0.0.8" + dependencies: + cssbeautify: "npm:^0.3.1" + html: "npm:^1.0.0" + js-beautify: "npm:^1.6.4" + bin: + beautify: ./bin/beautify.js + checksum: 10/29945230bb72e9e236a485d29d0adb8085ea3001fc1ecbb408540f349efb1cf79c532ac38a9a3410900bc99e502df5b564f433f3c2783922e9c6f85bddc17e8e + languageName: node + linkType: hard + "better-path-resolve@npm:1.0.0": version: 1.0.0 resolution: "better-path-resolve@npm:1.0.0" @@ -12127,6 +13015,17 @@ __metadata: languageName: node linkType: hard +"bippy@npm:^0.2.24": + version: 0.2.24 + resolution: "bippy@npm:0.2.24" + dependencies: + "@types/react-reconciler": "npm:^0.28.9" + peerDependencies: + react: ">=17.0.1" + checksum: 10/091ccf947f5608b483f537363c3f14edd354b57cdd45609f65e81e8fa2de80cfa7f5d015f8962293d45d081607766a9b3186ad80957aa214ec5c44d937575eab + languageName: node + linkType: hard + "bl@npm:^4.0.3, bl@npm:^4.1.0": version: 4.1.0 resolution: "bl@npm:4.1.0" @@ -12251,7 +13150,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.21.10, browserslist@npm:^4.23.3, browserslist@npm:^4.24.3": +"browserslist@npm:^4.21.10, browserslist@npm:^4.24.3": version: 4.24.4 resolution: "browserslist@npm:4.24.4" dependencies: @@ -12531,13 +13430,6 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001646": - version: 1.0.30001695 - resolution: "caniuse-lite@npm:1.0.30001695" - checksum: 10/8107c5e89b86c7a2fd506b93c658ff945c98c6518260c3b28af9f02bd83bf83939696241f0b413545c5b9895c86bcae64c9370388576440e74e9b848f04170d3 - languageName: node - linkType: hard - "caniuse-lite@npm:^1.0.30001688": version: 1.0.30001690 resolution: "caniuse-lite@npm:1.0.30001690" @@ -12583,6 +13475,13 @@ __metadata: languageName: node linkType: hard +"chain-function@npm:^1.0.0": + version: 1.0.1 + resolution: "chain-function@npm:1.0.1" + checksum: 10/11b2c4aaea5b37a74717181197312bc95ddfe61a6de7c2b275b34ebb8c2d1e72ce3f20b828dc84982c0b2defc5fc0814bbd3e50f294420f252392ec04de5c806 + languageName: node + linkType: hard + "chalk@npm:1.0.0": version: 1.0.0 resolution: "chalk@npm:1.0.0" @@ -12641,6 +13540,13 @@ __metadata: languageName: node linkType: hard +"chalk@npm:^5.4.1": + version: 5.4.1 + resolution: "chalk@npm:5.4.1" + checksum: 10/29df3ffcdf25656fed6e95962e2ef86d14dfe03cd50e7074b06bad9ffbbf6089adbb40f75c00744d843685c8d008adaf3aed31476780312553caf07fa86e5bc7 + languageName: node + linkType: hard + "change-case-all@npm:1.0.14": version: 1.0.14 resolution: "change-case-all@npm:1.0.14" @@ -12827,6 +13733,13 @@ __metadata: languageName: node linkType: hard +"classnames@npm:^2.3.0, classnames@npm:^2.5.1": + version: 2.5.1 + resolution: "classnames@npm:2.5.1" + checksum: 10/58eb394e8817021b153bb6e7d782cfb667e4ab390cb2e9dac2fc7c6b979d1cc2b2a733093955fc5c94aa79ef5c8c89f11ab77780894509be6afbb91dddd79d15 + languageName: node + linkType: hard + "clean-stack@npm:^2.0.0": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -12961,6 +13874,13 @@ __metadata: languageName: node linkType: hard +"clone@npm:^2.1.1": + version: 2.1.2 + resolution: "clone@npm:2.1.2" + checksum: 10/d9c79efba655f0bf601ab299c57eb54cbaa9860fb011aee9d89ed5ac0d12df1660ab7642fddaabb9a26b7eff0e117d4520512cb70798319ff5d30a111b5310c2 + languageName: node + linkType: hard + "clsx@npm:^1.1.1, clsx@npm:^1.2.1": version: 1.2.1 resolution: "clsx@npm:1.2.1" @@ -13005,6 +13925,13 @@ __metadata: languageName: node linkType: hard +"code-block-writer@npm:^10.1.1": + version: 10.1.1 + resolution: "code-block-writer@npm:10.1.1" + checksum: 10/06c720f3216e59654868a63a9db5d89c8cafaf760ad57d8facff2463a2605a196fe0f1ab2fa8a4face5c3afa2cc1513363a712f8f3843fb9c7228a6fa781f62b + languageName: node + linkType: hard + "code-excerpt@npm:^3.0.0": version: 3.0.0 resolution: "code-excerpt@npm:3.0.0" @@ -13119,7 +14046,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^10.0.1": +"commander@npm:^10.0.0, commander@npm:^10.0.1": version: 10.0.1 resolution: "commander@npm:10.0.1" checksum: 10/8799faa84a30da985802e661cc9856adfaee324d4b138413013ef7f087e8d7924b144c30a1f1405475f0909f467665cd9e1ce13270a2f41b141dab0b7a58f3fb @@ -13219,6 +14146,18 @@ __metadata: languageName: node linkType: hard +"concat-stream@npm:^1.4.7": + version: 1.6.2 + resolution: "concat-stream@npm:1.6.2" + dependencies: + buffer-from: "npm:^1.0.0" + inherits: "npm:^2.0.3" + readable-stream: "npm:^2.2.2" + typedarray: "npm:^0.0.6" + checksum: 10/71db903c84fc073ca35a274074e8d26c4330713d299f8623e993c448c1f6bf8b967806dd1d1a7b0f8add6f15ab1af7435df21fe79b4fe7efd78420c89e054e28 + languageName: node + linkType: hard + "concurrently@npm:8.2.2": version: 8.2.2 resolution: "concurrently@npm:8.2.2" @@ -13246,6 +14185,16 @@ __metadata: languageName: node linkType: hard +"config-chain@npm:^1.1.13": + version: 1.1.13 + resolution: "config-chain@npm:1.1.13" + dependencies: + ini: "npm:^1.3.4" + proto-list: "npm:~1.2.1" + checksum: 10/83d22cabf709e7669f6870021c4d552e4fc02e9682702b726be94295f42ce76cfed00f70b2910ce3d6c9465d9758e191e28ad2e72ff4e3331768a90da6c1ef03 + languageName: node + linkType: hard + "consola@npm:^3.2.3": version: 3.3.0 resolution: "consola@npm:3.3.0" @@ -13530,6 +14479,15 @@ __metadata: languageName: node linkType: hard +"cssbeautify@npm:^0.3.1": + version: 0.3.1 + resolution: "cssbeautify@npm:0.3.1" + bin: + cssbeautify: bin/cssbeautify + checksum: 10/93e77e94e333394f0cf9434ea3bc5c1b816c8b018c3734080d996d0b42b99baf674e58ea503dd2b0220180699cf1577c27321c15419c3d8fb7db3cd8cb25de69 + languageName: node + linkType: hard + "cssesc@npm:^3.0.0": version: 3.0.0 resolution: "cssesc@npm:3.0.0" @@ -13586,6 +14544,111 @@ __metadata: languageName: node linkType: hard +"d3-color@npm:1 - 3": + version: 3.1.0 + resolution: "d3-color@npm:3.1.0" + checksum: 10/536ba05bfd9f4fcd6fa289b5974f5c846b21d186875684637e22bf6855e6aba93e24a2eb3712985c6af3f502fbbfa03708edb72f58142f626241a8a17258e545 + languageName: node + linkType: hard + +"d3-dispatch@npm:1 - 3": + version: 3.0.1 + resolution: "d3-dispatch@npm:3.0.1" + checksum: 10/2b82f41bf4ef88c2f9033dfe32815b67e2ef1c5754a74137a74c7d44d6f0d6ecfa934ac56ed8afe358f6c1f06462e8aa42ca0a388397b5b77a42721570e80487 + languageName: node + linkType: hard + +"d3-drag@npm:2 - 3": + version: 3.0.0 + resolution: "d3-drag@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-selection: "npm:3" + checksum: 10/80bc689935e5a46ee92b2d7f71e1c792279382affed9fbcf46034bff3ff7d3f50cf61a874da4bdf331037292b9e7dca5c6401a605d4bb699fdcb4e0c87e176ec + languageName: node + linkType: hard + +"d3-ease@npm:1 - 3": + version: 3.0.1 + resolution: "d3-ease@npm:3.0.1" + checksum: 10/985d46e868494e9e6806fedd20bad712a50dcf98f357bf604a843a9f6bc17714a657c83dd762f183173dcde983a3570fa679b2bc40017d40b24163cdc4167796 + languageName: node + linkType: hard + +"d3-hierarchy@npm:^1.1.9": + version: 1.1.9 + resolution: "d3-hierarchy@npm:1.1.9" + checksum: 10/d2a4e518c3e35de15e0ac7f0a420300a658435850fc32eaf15b7811697e34565b89012e07e60a53babb723dc43df8981102079b4097b790b42ac21c8d23c0424 + languageName: node + linkType: hard + +"d3-interpolate@npm:1 - 3": + version: 3.0.1 + resolution: "d3-interpolate@npm:3.0.1" + dependencies: + d3-color: "npm:1 - 3" + checksum: 10/988d66497ef5c190cf64f8c80cd66e1e9a58c4d1f8932d776a8e3ae59330291795d5a342f5a97602782ccbef21a5df73bc7faf1f0dc46a5145ba6243a82a0f0e + languageName: node + linkType: hard + +"d3-path@npm:1": + version: 1.0.9 + resolution: "d3-path@npm:1.0.9" + checksum: 10/6ce1747837ea2a449d9ea32e169a382978ab09a4805eb408feb6bbc12cb5f5f6ce29aefc252dd9a815d420f4813d672f75578b78b3bbaf7811f54d8c7f93fd11 + languageName: node + linkType: hard + +"d3-selection@npm:2 - 3, d3-selection@npm:3, d3-selection@npm:^3.0.0": + version: 3.0.0 + resolution: "d3-selection@npm:3.0.0" + checksum: 10/0e5acfd305b31628b7be5009ba7303d84bb34817a88ed4dde9c8bd9c23528573fc5272f89fc04e5be03d2cbf5441a248d7274aaf55a8ef3dad46e16333d72298 + languageName: node + linkType: hard + +"d3-shape@npm:^1.3.7": + version: 1.3.7 + resolution: "d3-shape@npm:1.3.7" + dependencies: + d3-path: "npm:1" + checksum: 10/1e40fdcfdc8edc9c53a77a6aaea2dbf31bf06df12ebd66cc8d91f76bbde753049ad21dfee0577f7dc5d0a4468554ede4783f6df7d809e291745334dba977c09e + languageName: node + linkType: hard + +"d3-timer@npm:1 - 3": + version: 3.0.1 + resolution: "d3-timer@npm:3.0.1" + checksum: 10/004128602bb187948d72c7dc153f0f063f38ac7a584171de0b45e3a841ad2e17f1e40ad396a4af9cce5551b6ab4a838d5246d23492553843d9da4a4050a911e2 + languageName: node + linkType: hard + +"d3-transition@npm:2 - 3": + version: 3.0.1 + resolution: "d3-transition@npm:3.0.1" + dependencies: + d3-color: "npm:1 - 3" + d3-dispatch: "npm:1 - 3" + d3-ease: "npm:1 - 3" + d3-interpolate: "npm:1 - 3" + d3-timer: "npm:1 - 3" + peerDependencies: + d3-selection: 2 - 3 + checksum: 10/02571636acb82f5532117928a87fe25de68f088c38ab4a8b16e495f0f2d08a3fd2937eaebdefdfcf7f1461545524927d2632d795839b88d2e4c71e387aaaffac + languageName: node + linkType: hard + +"d3-zoom@npm:^3.0.0": + version: 3.0.0 + resolution: "d3-zoom@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-drag: "npm:2 - 3" + d3-interpolate: "npm:1 - 3" + d3-selection: "npm:2 - 3" + d3-transition: "npm:2 - 3" + checksum: 10/0e6e5c14e33c4ecdff311a900dd037dea407734f2dd2818988ed6eae342c1799e8605824523678bd404f81e37824cc588f62dbde46912444c89acc7888036c6b + languageName: node + linkType: hard + "damerau-levenshtein@npm:^1.0.8": version: 1.0.8 resolution: "damerau-levenshtein@npm:1.0.8" @@ -13663,6 +14726,13 @@ __metadata: languageName: node linkType: hard +"date-fns@npm:^4.1.0": + version: 4.1.0 + resolution: "date-fns@npm:4.1.0" + checksum: 10/d5f6e9de5bbc52310f786099e18609289ed5e30af60a71e0646784c8185ddd1d0eebcf7c96b7faaaefc4a8366f3a3a4244d099b6d0866ee2bec80d1361e64342 + languageName: node + linkType: hard + "dax-sh@npm:^0.39.1": version: 0.39.2 resolution: "dax-sh@npm:0.39.2" @@ -13983,7 +15053,7 @@ __metadata: languageName: node linkType: hard -"diff@npm:^5.1.0": +"diff@npm:^5.1.0, diff@npm:^5.2.0": version: 5.2.0 resolution: "diff@npm:5.2.0" checksum: 10/01b7b440f83a997350a988e9d2f558366c0f90f15be19f4aa7f1bb3109a4e153dfc3b9fbf78e14ea725717017407eeaa2271e3896374a0181e8f52445740846d @@ -14045,6 +15115,15 @@ __metadata: languageName: node linkType: hard +"dom-helpers@npm:^3.3.1": + version: 3.4.0 + resolution: "dom-helpers@npm:3.4.0" + dependencies: + "@babel/runtime": "npm:^7.1.2" + checksum: 10/63ce62469be8cb481c41811f6b463a1b071dce8a7cd73a39cd4fdaa1e570201af6e7a895a502f4db414e2cc0533e44096ad95c13f303e5a3c3a036f0a43798e4 + languageName: node + linkType: hard + "domexception@npm:^4.0.0": version: 4.0.0 resolution: "domexception@npm:4.0.0" @@ -14141,6 +15220,20 @@ __metadata: languageName: node linkType: hard +"editorconfig@npm:^1.0.4": + version: 1.0.4 + resolution: "editorconfig@npm:1.0.4" + dependencies: + "@one-ini/wasm": "npm:0.1.1" + commander: "npm:^10.0.0" + minimatch: "npm:9.0.1" + semver: "npm:^7.5.3" + bin: + editorconfig: bin/editorconfig + checksum: 10/bd0a7236f31a7f54801cb6f3222508d4f872a24e440bef30ee29f4ba667c0741724e52e0ad521abe3409b12cdafd8384bb751de9b2a2ee5f845c740edd2e742f + languageName: node + linkType: hard + "ee-first@npm:1.1.1": version: 1.1.1 resolution: "ee-first@npm:1.1.1" @@ -15848,7 +16941,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.2, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.3": +"fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.2, fast-glob@npm:^3.2.7, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.3": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" dependencies: @@ -16156,7 +17249,7 @@ __metadata: languageName: node linkType: hard -"fraction.js@npm:^4.2.0, fraction.js@npm:^4.3.7": +"fraction.js@npm:^4.2.0": version: 4.3.7 resolution: "fraction.js@npm:4.3.7" checksum: 10/bb5ebcdeeffcdc37b68ead3bdfc244e68de188e0c64e9702197333c72963b95cc798883ad16adc21588088b942bca5b6a6ff4aeb1362d19f6f3b629035dc15f5 @@ -16184,6 +17277,28 @@ __metadata: languageName: node linkType: hard +"framer-motion@npm:^12.0.6": + version: 12.4.2 + resolution: "framer-motion@npm:12.4.2" + dependencies: + motion-dom: "npm:^12.0.0" + motion-utils: "npm:^12.0.0" + tslib: "npm:^2.4.0" + peerDependencies: + "@emotion/is-prop-valid": "*" + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@emotion/is-prop-valid": + optional: true + react: + optional: true + react-dom: + optional: true + checksum: 10/629b76b5db022bb3fbc2c03ef681704672697ee922051857f0004b2b7268546fa138ff7c06df9689e22d518264df1b42cd7c363aec1fb40c422e1c1abcb7c376 + languageName: node + linkType: hard + "framesync@npm:6.1.2": version: 6.1.2 resolution: "framesync@npm:6.1.2" @@ -16570,7 +17685,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.0.0, glob@npm:^10.2.2": +"glob@npm:^10.0.0, glob@npm:^10.2.2, glob@npm:^10.4.2": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -17116,6 +18231,17 @@ __metadata: languageName: node linkType: hard +"html@npm:^1.0.0": + version: 1.0.0 + resolution: "html@npm:1.0.0" + dependencies: + concat-stream: "npm:^1.4.7" + bin: + html: ./bin/html.js + checksum: 10/a741e0e18cb4969097faed6879ef90e35e0632c6a94f0dc4679f4a11f20ac5595227bc4680a36295a20316b572c987aed26b1a8ac2569013d0e060b2c514bac4 + languageName: node + linkType: hard + "http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -17385,6 +18511,13 @@ __metadata: languageName: node linkType: hard +"ini@npm:^1.3.4": + version: 1.3.8 + resolution: "ini@npm:1.3.8" + checksum: 10/314ae176e8d4deb3def56106da8002b462221c174ddb7ce0c49ee72c8cd1f9044f7b10cc555a7d8850982c3b9ca96fc212122749f5234bc2b6fb05fb942ed566 + languageName: node + linkType: hard + "ink-text-input@npm:^4.0.3": version: 4.0.3 resolution: "ink-text-input@npm:4.0.3" @@ -18709,7 +19842,7 @@ __metadata: languageName: node linkType: hard -"jiti@npm:^1.17.1, jiti@npm:^1.18.2, jiti@npm:^1.21.6": +"jiti@npm:^1.17.1, jiti@npm:^1.18.2": version: 1.21.7 resolution: "jiti@npm:1.21.7" bin: @@ -18779,6 +19912,23 @@ __metadata: languageName: node linkType: hard +"js-beautify@npm:^1.6.4": + version: 1.15.3 + resolution: "js-beautify@npm:1.15.3" + dependencies: + config-chain: "npm:^1.1.13" + editorconfig: "npm:^1.0.4" + glob: "npm:^10.4.2" + js-cookie: "npm:^3.0.5" + nopt: "npm:^8.0.0" + bin: + css-beautify: js/bin/css-beautify.js + html-beautify: js/bin/html-beautify.js + js-beautify: js/bin/js-beautify.js + checksum: 10/5d2b4f494883d1ce5b3aa71f0cee4b7311c4d6abdf1c94d4add1dd3b8a259c6e6d229c9d785fc5589d04615c80cd2787a94b9aa7b5c1c8b61e15f027d6364bf4 + languageName: node + linkType: hard + "js-cookie@npm:^3.0.1": version: 3.0.1 resolution: "js-cookie@npm:3.0.1" @@ -18786,6 +19936,13 @@ __metadata: languageName: node linkType: hard +"js-cookie@npm:^3.0.5": + version: 3.0.5 + resolution: "js-cookie@npm:3.0.5" + checksum: 10/366494b1630b9fb8abaef3659748db5dfd52c58c6fc3459b9f0a03b492593bc1b01c6dfcc066b46f6413c28edb3a00cc68fb61ea8cdf6991bedf1f100f8a389d + languageName: node + linkType: hard + "js-levenshtein@npm:^1.1.6": version: 1.1.6 resolution: "js-levenshtein@npm:1.1.6" @@ -19004,6 +20161,16 @@ __metadata: languageName: node linkType: hard +"json-schema-to-ts@npm:1.6.4": + version: 1.6.4 + resolution: "json-schema-to-ts@npm:1.6.4" + dependencies: + "@types/json-schema": "npm:^7.0.6" + ts-toolbelt: "npm:^6.15.5" + checksum: 10/25aac2f56f1f4e614e965b6d5f20fb1f98a6cf6b3d0a1b93b9a004bac21a11ec3d972a85b37be969c81109d22096f8bca804a942edf6e49d8edb0b8fe6cded77 + languageName: node + linkType: hard + "json-schema-traverse@npm:^0.4.1": version: 0.4.1 resolution: "json-schema-traverse@npm:0.4.1" @@ -19208,6 +20375,116 @@ __metadata: languageName: node linkType: hard +"lightningcss-darwin-arm64@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-darwin-arm64@npm:1.29.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-x64@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-darwin-x64@npm:1.29.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-freebsd-x64@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-freebsd-x64@npm:1.29.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-linux-arm-gnueabihf@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.29.1" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"lightningcss-linux-arm64-gnu@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-linux-arm64-gnu@npm:1.29.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-arm64-musl@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-linux-arm64-musl@npm:1.29.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-linux-x64-gnu@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-linux-x64-gnu@npm:1.29.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-x64-musl@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-linux-x64-musl@npm:1.29.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-win32-arm64-msvc@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-win32-arm64-msvc@npm:1.29.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-win32-x64-msvc@npm:1.29.1": + version: 1.29.1 + resolution: "lightningcss-win32-x64-msvc@npm:1.29.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"lightningcss@npm:^1.29.1": + version: 1.29.1 + resolution: "lightningcss@npm:1.29.1" + dependencies: + detect-libc: "npm:^1.0.3" + lightningcss-darwin-arm64: "npm:1.29.1" + lightningcss-darwin-x64: "npm:1.29.1" + lightningcss-freebsd-x64: "npm:1.29.1" + lightningcss-linux-arm-gnueabihf: "npm:1.29.1" + lightningcss-linux-arm64-gnu: "npm:1.29.1" + lightningcss-linux-arm64-musl: "npm:1.29.1" + lightningcss-linux-x64-gnu: "npm:1.29.1" + lightningcss-linux-x64-musl: "npm:1.29.1" + lightningcss-win32-arm64-msvc: "npm:1.29.1" + lightningcss-win32-x64-msvc: "npm:1.29.1" + dependenciesMeta: + lightningcss-darwin-arm64: + optional: true + lightningcss-darwin-x64: + optional: true + lightningcss-freebsd-x64: + optional: true + lightningcss-linux-arm-gnueabihf: + optional: true + lightningcss-linux-arm64-gnu: + optional: true + lightningcss-linux-arm64-musl: + optional: true + lightningcss-linux-x64-gnu: + optional: true + lightningcss-linux-x64-musl: + optional: true + lightningcss-win32-arm64-msvc: + optional: true + lightningcss-win32-x64-msvc: + optional: true + checksum: 10/c6428a695ca985fa28ea899eb72471e0c6a71715291cb62f938b038596a971b6b22d83415d882dec27841169b1b773989b16df173f5ce9075c3fdc22ff764cff + languageName: node + linkType: hard + "lilconfig@npm:^2.1.0": version: 2.1.0 resolution: "lilconfig@npm:2.1.0" @@ -19215,7 +20492,7 @@ __metadata: languageName: node linkType: hard -"lilconfig@npm:^3.0.0, lilconfig@npm:^3.1.3": +"lilconfig@npm:^3.0.0": version: 3.1.3 resolution: "lilconfig@npm:3.1.3" checksum: 10/b932ce1af94985f0efbe8896e57b1f814a48c8dbd7fc0ef8469785c6303ed29d0090af3ccad7e36b626bfca3a4dc56cc262697e9a8dd867623cf09a39d54e4c3 @@ -19434,7 +20711,7 @@ __metadata: languageName: node linkType: hard -"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0": +"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" dependencies: @@ -19639,6 +20916,13 @@ __metadata: languageName: node linkType: hard +"memoize-one@npm:^6.0.0": + version: 6.0.0 + resolution: "memoize-one@npm:6.0.0" + checksum: 10/28feaf7e9a870efef1187df110b876ce42deaf86c955f4111d72d23b96e44eed573469316e6ad0d2cc7fa3b1526978215617b126158015f957242c7493babca9 + languageName: node + linkType: hard + "merge-descriptors@npm:1.0.1": version: 1.0.1 resolution: "merge-descriptors@npm:1.0.1" @@ -19790,6 +21074,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:9.0.1": + version: 9.0.1 + resolution: "minimatch@npm:9.0.1" + dependencies: + brace-expansion: "npm:^2.0.1" + checksum: 10/b4e98f4dc740dcf33999a99af23ae6e5e1c47632f296dc95cb649a282150f92378d41434bf64af4ea2e5975255a757d031c3bf014bad9214544ac57d97f3ba63 + languageName: node + linkType: hard + "minimatch@npm:9.0.3, minimatch@npm:^9.0.1": version: 9.0.3 resolution: "minimatch@npm:9.0.3" @@ -20001,6 +21294,22 @@ __metadata: languageName: node linkType: hard +"motion-dom@npm:^12.0.0": + version: 12.0.0 + resolution: "motion-dom@npm:12.0.0" + dependencies: + motion-utils: "npm:^12.0.0" + checksum: 10/ddb50b0dc0ca08bbcbba78850d0530840821944158849776af11110a7c32f6b53d02afc16880f70b4bd33d105dce3c1c69a37df57675f2882bf7f7cb2a814438 + languageName: node + linkType: hard + +"motion-utils@npm:^12.0.0": + version: 12.0.0 + resolution: "motion-utils@npm:12.0.0" + checksum: 10/e73b82cf36746f6d498bc48450d34bf8d51128279d8f542cab8a02edf13368d0b99e4208c6d60c670fac5481c60e09d590db7345e390070ed0499dd4367d1695 + languageName: node + linkType: hard + "mri@npm:^1.1.0, mri@npm:^1.2.0": version: 1.2.0 resolution: "mri@npm:1.2.0" @@ -21127,6 +22436,13 @@ __metadata: languageName: node linkType: hard +"path-browserify@npm:^1.0.1": + version: 1.0.1 + resolution: "path-browserify@npm:1.0.1" + checksum: 10/7e7368a5207e7c6b9051ef045711d0dc3c2b6203e96057e408e6e74d09f383061010d2be95cb8593fe6258a767c3e9fc6b2bfc7ce8d48ae8c3d9f6994cca9ad8 + languageName: node + linkType: hard + "path-case@npm:^3.0.4": version: 3.0.4 resolution: "path-case@npm:3.0.4" @@ -21275,7 +22591,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": +"picocolors@npm:^1.0.0, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10/e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 @@ -21399,7 +22715,7 @@ __metadata: languageName: node linkType: hard -"postcss-load-config@npm:^4.0.1, postcss-load-config@npm:^4.0.2": +"postcss-load-config@npm:^4.0.1": version: 4.0.2 resolution: "postcss-load-config@npm:4.0.2" dependencies: @@ -21417,7 +22733,7 @@ __metadata: languageName: node linkType: hard -"postcss-nested@npm:^6.0.1, postcss-nested@npm:^6.2.0": +"postcss-nested@npm:^6.0.1": version: 6.2.0 resolution: "postcss-nested@npm:6.2.0" dependencies: @@ -21428,7 +22744,7 @@ __metadata: languageName: node linkType: hard -"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2": +"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.1.1": version: 6.1.2 resolution: "postcss-selector-parser@npm:6.1.2" dependencies: @@ -21467,7 +22783,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.23, postcss@npm:^8.4.43, postcss@npm:^8.4.47": +"postcss@npm:^8.4.23, postcss@npm:^8.4.43": version: 8.5.1 resolution: "postcss@npm:8.5.1" dependencies: @@ -21616,7 +22932,7 @@ __metadata: languageName: node linkType: hard -"prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": +"prop-types@npm:^15.5.6, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" dependencies: @@ -21627,6 +22943,13 @@ __metadata: languageName: node linkType: hard +"proto-list@npm:~1.2.1": + version: 1.2.4 + resolution: "proto-list@npm:1.2.4" + checksum: 10/9cc3b46d613fa0d637033b225db1bc98e914c3c05864f7adc9bee728192e353125ef2e49f71129a413f6333951756000b0e54f299d921f02d3e9e370cc994100 + languageName: node + linkType: hard + "protocols@npm:^2.0.0, protocols@npm:^2.0.1": version: 2.0.1 resolution: "protocols@npm:2.0.1" @@ -21873,6 +23196,25 @@ __metadata: languageName: node linkType: hard +"react-d3-tree@npm:^3.6.4": + version: 3.6.5 + resolution: "react-d3-tree@npm:3.6.5" + dependencies: + "@bkrem/react-transition-group": "npm:^1.3.5" + clone: "npm:^2.1.1" + d3-hierarchy: "npm:^1.1.9" + d3-selection: "npm:^3.0.0" + d3-shape: "npm:^1.3.7" + d3-zoom: "npm:^3.0.0" + dequal: "npm:^2.0.2" + uuid: "npm:^8.3.1" + peerDependencies: + react: 16.x || 17.x || 18.x || 19.x + react-dom: 16.x || 17.x || 18.x || 19.x + checksum: 10/d52a7f63a53bda689b90aa25366bc6edfa2a152a58725b383bbef898e3205f949ed24a9ae7fb8d02dbf8234f075168baba53a9a8b2043b0f9d8b0619c84a2072 + languageName: node + linkType: hard + "react-devtools-core@npm:^4.19.1": version: 4.28.5 resolution: "react-devtools-core@npm:4.28.5" @@ -21883,6 +23225,22 @@ __metadata: languageName: node linkType: hard +"react-diff-viewer-continued@npm:^4.0.5": + version: 4.0.5 + resolution: "react-diff-viewer-continued@npm:4.0.5" + dependencies: + "@emotion/css": "npm:^11.13.5" + "@emotion/react": "npm:^11.14.0" + classnames: "npm:^2.5.1" + diff: "npm:^5.2.0" + memoize-one: "npm:^6.0.0" + peerDependencies: + react: ^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: 10/92f69d7978a6d9f1c2c96eefe06ad835442970df5a12127a2277f097c9b8103e3206bff110e096a231824fe6033a236a1dd7b7ca8f90f11b31fa87bdd59c57f9 + languageName: node + linkType: hard + "react-dom@npm:19.0.0": version: 19.0.0 resolution: "react-dom@npm:19.0.0" @@ -21954,6 +23312,16 @@ __metadata: languageName: node linkType: hard +"react-hotkeys-hook@npm:^4.6.1": + version: 4.6.1 + resolution: "react-hotkeys-hook@npm:4.6.1" + peerDependencies: + react: ">=16.8.1" + react-dom: ">=16.8.1" + checksum: 10/fc7449c72899c1adcb67d4d3d5130411a6ea26a9dc862f1599d2542201b57612b0add169ad0037a2de9e5a5db588c308a32f421ad47221f44eb88ab01018e750 + languageName: node + linkType: hard + "react-icons@npm:^4.8.0": version: 4.8.0 resolution: "react-icons@npm:4.8.0" @@ -21984,6 +23352,13 @@ __metadata: languageName: node linkType: hard +"react-lifecycles-compat@npm:^3.0.4": + version: 3.0.4 + resolution: "react-lifecycles-compat@npm:3.0.4" + checksum: 10/c66b9c98c15cd6b0d0a4402df5f665e8cc7562fb7033c34508865bea51fd7b623f7139b5b7e708515d3cd665f264a6a9403e1fa7e6d61a05759066f5e9f07783 + languageName: node + linkType: hard + "react-rating-stars-component@npm:^2.2.0": version: 2.2.3 resolution: "react-rating-stars-component@npm:2.2.3" @@ -22027,6 +23402,22 @@ __metadata: languageName: node linkType: hard +"react-remove-scroll-bar@npm:^2.3.7": + version: 2.3.8 + resolution: "react-remove-scroll-bar@npm:2.3.8" + dependencies: + react-style-singleton: "npm:^2.2.2" + tslib: "npm:^2.0.0" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/6c0f8cff98b9f49a4ee2263f1eedf12926dced5ce220fbe83bd93544460e2a7ec8ec39b35d1b2a75d2fced0b2d64afeb8e66f830431ca896e05a20585f9fc350 + languageName: node + linkType: hard + "react-remove-scroll@npm:^2.5.5": version: 2.5.5 resolution: "react-remove-scroll@npm:2.5.5" @@ -22046,9 +23437,68 @@ __metadata: languageName: node linkType: hard -"react-router@npm:7.0.2": - version: 7.0.2 - resolution: "react-router@npm:7.0.2" +"react-remove-scroll@npm:^2.6.3": + version: 2.6.3 + resolution: "react-remove-scroll@npm:2.6.3" + dependencies: + react-remove-scroll-bar: "npm:^2.3.7" + react-style-singleton: "npm:^2.2.3" + tslib: "npm:^2.1.0" + use-callback-ref: "npm:^1.3.3" + use-sidecar: "npm:^1.1.3" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/d4dfd38e4381fa6059c8b810568b2d3a31fe21168bb3e2f57d1b1885ee08736fbd5a3fd83936faef0d17031c9c4175a1af83885bfc6c4280611f025447b19a4c + languageName: node + linkType: hard + +"react-router-devtools@npm:^1.1.0": + version: 1.1.4 + resolution: "react-router-devtools@npm:1.1.4" + dependencies: + "@babel/core": "npm:^7.26.7" + "@babel/generator": "npm:^7.26.5" + "@babel/parser": "npm:^7.26.7" + "@babel/traverse": "npm:^7.26.7" + "@babel/types": "npm:^7.26.7" + "@biomejs/cli-darwin-arm64": "npm:^1.9.4" + "@radix-ui/react-accordion": "npm:^1.2.2" + "@radix-ui/react-select": "npm:^2.1.5" + "@rollup/rollup-darwin-arm64": "npm:^4.32.1" + "@rollup/rollup-linux-x64-gnu": "npm:^4.32.1" + beautify: "npm:^0.0.8" + bippy: "npm:^0.2.24" + chalk: "npm:^5.4.1" + clsx: "npm:^2.1.1" + date-fns: "npm:^4.1.0" + framer-motion: "npm:^12.0.6" + react-d3-tree: "npm:^3.6.4" + react-diff-viewer-continued: "npm:^4.0.5" + react-hotkeys-hook: "npm:^4.6.1" + react-tooltip: "npm:^5.28.0" + peerDependencies: + react: ">=17" + react-dom: ">=17" + react-router: ">=7.0.0" + vite: ">=5.0.0 || >=6.0.0" + dependenciesMeta: + "@biomejs/cli-darwin-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + checksum: 10/2e104a5d5dae856acb5ce322a1cb8efefca2b8e4d0432678ef12cd6a0e14946145e888d752c6e66d62d1b9b04f49211cfecb7419ad92b0468ebc315719b0c9f1 + languageName: node + linkType: hard + +"react-router@npm:7.1.5": + version: 7.1.5 + resolution: "react-router@npm:7.1.5" dependencies: "@types/cookie": "npm:^0.6.0" cookie: "npm:^1.0.1" @@ -22060,13 +23510,13 @@ __metadata: peerDependenciesMeta: react-dom: optional: true - checksum: 10/f8bf5f7810388d4da81444d5e816135306aadd0340a26d645eb171e2b4c4a6d7f5a810f1d27e25ae0f006b949f7cf66fcf399f2af79f48341752a6651b2b30cb + checksum: 10/3802ff0e0419aa53c1824b1ad2ebac6facb918306c67ff64ed86b5cbc49197c15f077b84e425f57beb24dd01cd5818a100da5269b8e160deee62b06fda008b56 languageName: node linkType: hard -"react-router@patch:react-router@npm%3A7.0.2#~/.yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch": - version: 7.0.2 - resolution: "react-router@patch:react-router@npm%3A7.0.2#~/.yarn/patches/react-router-npm-7.0.2-b96f2bd13c.patch::version=7.0.2&hash=c518b8" +"react-router@patch:react-router@npm%3A7.1.5#~/.yarn/patches/react-router-npm-7.1.5-9668fa2213.patch": + version: 7.1.5 + resolution: "react-router@patch:react-router@npm%3A7.1.5#~/.yarn/patches/react-router-npm-7.1.5-9668fa2213.patch::version=7.1.5&hash=dcc110" dependencies: "@types/cookie": "npm:^0.6.0" cookie: "npm:^1.0.1" @@ -22078,10 +23528,38 @@ __metadata: peerDependenciesMeta: react-dom: optional: true - checksum: 10/80a72cad438b52ac86793e381e37285a8b8212cce65fbe9d8e465b55c228b3907688973582bfa19b0fb4f2e0ea76de55b79538b76976980408cd19b3541d8873 + checksum: 10/31fee5bef4b9615693a689c3be8a09c6de7adc80b14f823c5dbb27f77839d505bcfefe1ab2f03c07093f934c4cd0806272afd138f5f3569ebc01de2941274651 languageName: node linkType: hard +"react-router@workspace:integration-test/react-router": + version: 0.0.0-use.local + resolution: "react-router@workspace:integration-test/react-router" + dependencies: + "@apollo/client": "npm:^3.11.10" + "@apollo/client-integration-react-router": "workspace:^" + "@integration-test/shared": "workspace:^" + "@react-router/dev": "npm:^7.1.5" + "@react-router/node": "npm:^7.1.5" + "@react-router/serve": "npm:^7.1.5" + "@tailwindcss/vite": "npm:^4.0.0" + "@types/node": "npm:^20" + "@types/react": "npm:^19.0.1" + "@types/react-dom": "npm:^19.0.1" + "@vercel/react-router": "npm:^1.0.2" + graphql: "npm:*" + isbot: "npm:^5.1.17" + react: "npm:^19.0.0" + react-dom: "npm:^19.0.0" + react-router: "npm:^7.1.5" + react-router-devtools: "npm:^1.1.0" + tailwindcss: "npm:^4.0.0" + typescript: "npm:^5.7.2" + vite: "npm:^5.4.11" + vite-tsconfig-paths: "npm:^5.1.4" + languageName: unknown + linkType: soft + "react-server-dom-webpack@npm:^19.0.0": version: 19.0.0 resolution: "react-server-dom-webpack@npm:19.0.0" @@ -22114,6 +23592,35 @@ __metadata: languageName: node linkType: hard +"react-style-singleton@npm:^2.2.2, react-style-singleton@npm:^2.2.3": + version: 2.2.3 + resolution: "react-style-singleton@npm:2.2.3" + dependencies: + get-nonce: "npm:^1.0.0" + tslib: "npm:^2.0.0" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/62498094ff3877a37f351b29e6cad9e38b2eb1ac3c0cb27ebf80aee96554f80b35e17bdb552bcd7ac8b7cb9904fea93ea5668f2057c73d38f90b5d46bb9b27ab + languageName: node + linkType: hard + +"react-tooltip@npm:^5.28.0": + version: 5.28.0 + resolution: "react-tooltip@npm:5.28.0" + dependencies: + "@floating-ui/dom": "npm:^1.6.1" + classnames: "npm:^2.3.0" + peerDependencies: + react: ">=16.14.0" + react-dom: ">=16.14.0" + checksum: 10/ec13ad0fafcae51c9c1193c6f0bccba4e7047e9d02eaf77231474cefd1a3d05254e76f27229808e79dad4c0a8c47b8e5cafdad47920e34a11d7a2703adf5f998 + languageName: node + linkType: hard + "react@npm:19.0.0": version: 19.0.0 resolution: "react@npm:19.0.0" @@ -22142,7 +23649,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.5, readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.0.0, readable-stream@npm:^2.0.5, readable-stream@npm:^2.2.2, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -22470,7 +23977,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.14.2, resolve@npm:^1.20.0, resolve@npm:^1.22.6, resolve@npm:^1.22.8": +"resolve@npm:^1.14.2, resolve@npm:^1.20.0, resolve@npm:^1.22.6": version: 1.22.10 resolution: "resolve@npm:1.22.10" dependencies: @@ -22558,7 +24065,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.6#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin": +"resolve@patch:resolve@npm%3A^1.14.2#optional!builtin, resolve@patch:resolve@npm%3A^1.20.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.6#optional!builtin": version: 1.22.10 resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" dependencies: @@ -24029,7 +25536,7 @@ __metadata: languageName: node linkType: hard -"sucrase@npm:^3.20.3, sucrase@npm:^3.35.0": +"sucrase@npm:^3.20.3": version: 3.35.0 resolution: "sucrase@npm:3.35.0" dependencies: @@ -24206,36 +25713,10 @@ __metadata: languageName: node linkType: hard -"tailwindcss@npm:^3.4.15": - version: 3.4.17 - resolution: "tailwindcss@npm:3.4.17" - dependencies: - "@alloc/quick-lru": "npm:^5.2.0" - arg: "npm:^5.0.2" - chokidar: "npm:^3.6.0" - didyoumean: "npm:^1.2.2" - dlv: "npm:^1.1.3" - fast-glob: "npm:^3.3.2" - glob-parent: "npm:^6.0.2" - is-glob: "npm:^4.0.3" - jiti: "npm:^1.21.6" - lilconfig: "npm:^3.1.3" - micromatch: "npm:^4.0.8" - normalize-path: "npm:^3.0.0" - object-hash: "npm:^3.0.0" - picocolors: "npm:^1.1.1" - postcss: "npm:^8.4.47" - postcss-import: "npm:^15.1.0" - postcss-js: "npm:^4.0.1" - postcss-load-config: "npm:^4.0.2" - postcss-nested: "npm:^6.2.0" - postcss-selector-parser: "npm:^6.1.2" - resolve: "npm:^1.22.8" - sucrase: "npm:^3.35.0" - bin: - tailwind: lib/cli.js - tailwindcss: lib/cli.js - checksum: 10/b0e00533ae3800223b5b71af9cb1dd9bfea5ef5ffa01300f1ced99de9511487aa41e03106173e4168c56c8f6600ee21c98c1d75a5def23cddf9b39b4ad71210d +"tailwindcss@npm:4.0.6, tailwindcss@npm:^4.0.0": + version: 4.0.6 + resolution: "tailwindcss@npm:4.0.6" + checksum: 10/b1141d98730b89164a38dab2c6fe0150a0910ab4ab45865d345b1fbf9eb9c0893f8cbe1392b7bcf59e52eb9f2e9750970b1d912f2ac4458e4b9e4cabe4518798 languageName: node linkType: hard @@ -24697,6 +26178,23 @@ __metadata: languageName: node linkType: hard +"ts-morph@npm:12.0.0": + version: 12.0.0 + resolution: "ts-morph@npm:12.0.0" + dependencies: + "@ts-morph/common": "npm:~0.11.0" + code-block-writer: "npm:^10.1.1" + checksum: 10/6b08cc4a301f09e0cce92fae7949fadcd4b1e03555a315ae3ec7a65f72abd4ee38f4f80c91f89eeb0eb0fd254f0022851304e7727e55bbf733dce319fffdfbdc + languageName: node + linkType: hard + +"ts-toolbelt@npm:^6.15.5": + version: 6.15.5 + resolution: "ts-toolbelt@npm:6.15.5" + checksum: 10/1816b11f6a4ca7b11da1e81613dda217535718862c9c7c1d9e5dbeb12abc765b6803dbc0c90ee8a5c1b782bc369e2851913005042921028d16e6ae8bf054b2da + languageName: node + linkType: hard + "tsconfck@npm:^3.0.3": version: 3.1.4 resolution: "tsconfck@npm:3.1.4" @@ -24995,6 +26493,13 @@ __metadata: languageName: node linkType: hard +"typedarray@npm:^0.0.6": + version: 0.0.6 + resolution: "typedarray@npm:0.0.6" + checksum: 10/2cc1bcf7d8c1237f6a16c04efc06637b2c5f2d74e58e84665445cf87668b85a21ab18dd751fa49eee6ae024b70326635d7b79ad37b1c370ed2fec6aeeeb52714 + languageName: node + linkType: hard + "typescript@npm:5.1.3": version: 5.1.3 resolution: "typescript@npm:5.1.3" @@ -25035,7 +26540,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.6.3, typescript@npm:^5.7.2, typescript@npm:^5.7.3": +"typescript@npm:^5.7.2, typescript@npm:^5.7.3": version: 5.7.3 resolution: "typescript@npm:5.7.3" bin: @@ -25085,7 +26590,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.6.3#optional!builtin, typescript@patch:typescript@npm%3A^5.7.2#optional!builtin, typescript@patch:typescript@npm%3A^5.7.3#optional!builtin": +"typescript@patch:typescript@npm%3A^5.7.2#optional!builtin, typescript@patch:typescript@npm%3A^5.7.3#optional!builtin": version: 5.7.3 resolution: "typescript@patch:typescript@npm%3A5.7.3#optional!builtin::version=5.7.3&hash=b45daf" bin: @@ -25557,6 +27062,21 @@ __metadata: languageName: node linkType: hard +"use-callback-ref@npm:^1.3.3": + version: 1.3.3 + resolution: "use-callback-ref@npm:1.3.3" + dependencies: + tslib: "npm:^2.0.0" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/adf06a7b6a27d3651c325ac9b66d2b82ccacaed7450b85b211d123e91d9a23cb5a587fcc6db5b4fd07ac7233e5abf024d30cf02ddc2ec46bca712151c0836151 + languageName: node + linkType: hard + "use-deep-compare-effect@npm:^1.4.0": version: 1.8.1 resolution: "use-deep-compare-effect@npm:1.8.1" @@ -25585,6 +27105,22 @@ __metadata: languageName: node linkType: hard +"use-sidecar@npm:^1.1.3": + version: 1.1.3 + resolution: "use-sidecar@npm:1.1.3" + dependencies: + detect-node-es: "npm:^1.1.0" + tslib: "npm:^2.0.0" + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/2fec05eb851cdfc4a4657b1dfb434e686f346c3265ffc9db8a974bb58f8128bd4a708a3cc00e8f51655fccf81822ed4419ebed42f41610589e3aab0cf2492edb + languageName: node + linkType: hard + "use-sync-external-store@npm:^1.4.0": version: 1.4.0 resolution: "use-sync-external-store@npm:1.4.0" @@ -25615,6 +27151,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^8.3.1": + version: 8.3.2 + resolution: "uuid@npm:8.3.2" + bin: + uuid: dist/bin/uuid + checksum: 10/9a5f7aa1d6f56dd1e8d5f2478f855f25c645e64e26e347a98e98d95781d5ed20062d6cca2eecb58ba7c84bc3910be95c0451ef4161906abaab44f9cb68ffbdd1 + languageName: node + linkType: hard + "uuid@npm:^9.0.0": version: 9.0.0 resolution: "uuid@npm:9.0.0" @@ -25761,7 +27306,7 @@ __metadata: languageName: node linkType: hard -"vite-tsconfig-paths@npm:^5.1.2": +"vite-tsconfig-paths@npm:^5.1.4": version: 5.1.4 resolution: "vite-tsconfig-paths@npm:5.1.4" dependencies: @@ -26051,6 +27596,15 @@ __metadata: languageName: node linkType: hard +"warning@npm:^3.0.0": + version: 3.0.0 + resolution: "warning@npm:3.0.0" + dependencies: + loose-envify: "npm:^1.0.0" + checksum: 10/c9f99a12803aab81b29858e7dc3415bf98b41baee3a4c3acdeb680d98c47b6e17490f1087dccc54432deed5711a5ce0ebcda2b27e9b5eb054c32ae50acb4419c + languageName: node + linkType: hard + "watchpack@npm:^2.4.1": version: 2.4.1 resolution: "watchpack@npm:2.4.1" From b0a79333d1a8a29ee04c4cfcb64893ed2b51635f Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Feb 2025 13:03:48 +0100 Subject: [PATCH 13/18] update config, add log message --- integration-test/react-router/react-router.config.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/integration-test/react-router/react-router.config.ts b/integration-test/react-router/react-router.config.ts index c3718b54..fc433a55 100644 --- a/integration-test/react-router/react-router.config.ts +++ b/integration-test/react-router/react-router.config.ts @@ -1,9 +1,15 @@ import { vercelPreset } from "@vercel/react-router/vite"; -import type { Config } from "@react-router/dev/config"; +import type { Config, Preset } from "@react-router/dev/config"; + +let presets: Array = []; +if (process.env.VERCEL) { + console.log("Adding Vercel preset"); + presets.push(vercelPreset()); +} export default { // Config options... // Server-side render by default, to enable SPA mode set this to `false` ssr: true, - presets: process.env.VERCEL ? [vercelPreset()] : [], + presets, } satisfies Config; From f32716dd16f0cbe55d064100f2611f1152f6bb94 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Feb 2025 13:15:38 +0100 Subject: [PATCH 14/18] apply vercel-specific options --- .../react-router/app/entry.server.tsx | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/integration-test/react-router/app/entry.server.tsx b/integration-test/react-router/app/entry.server.tsx index 6f791a6f..7eb35026 100644 --- a/integration-test/react-router/app/entry.server.tsx +++ b/integration-test/react-router/app/entry.server.tsx @@ -4,19 +4,28 @@ import type { AppLoadContext, EntryContext } from "react-router"; import { createReadableStreamFromReadable } from "@react-router/node"; import { ServerRouter } from "react-router"; import { isbot } from "isbot"; -import type { RenderToPipeableStreamOptions } from "react-dom/server"; +import type { + RenderToPipeableStreamOptions, + RenderToReadableStreamOptions, +} from "react-dom/server"; import { renderToPipeableStream } from "react-dom/server"; import { makeClient } from "./apollo"; import { ApolloProvider } from "@apollo/client/index.js"; export const streamTimeout = 5_000; +export type RenderOptions = { + [K in keyof RenderToReadableStreamOptions & + keyof RenderToPipeableStreamOptions]?: RenderToReadableStreamOptions[K]; +}; export default function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, routerContext: EntryContext, - loadContext: AppLoadContext + loadContext: AppLoadContext, + // vercel-specific options, originating from `@vercel/react-router/entry.server.js` + options?: RenderOptions ) { return new Promise((resolve, reject) => { let shellRendered = false; @@ -32,9 +41,14 @@ export default function handleRequest( const client = makeClient(request); const { pipe, abort } = renderToPipeableStream( - + , { + ...options, [readyOption]() { shellRendered = true; const body = new PassThrough(); From b26b8ef918fdc59c58561de7055d68e7b7872710 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Feb 2025 13:57:02 +0100 Subject: [PATCH 15/18] first react-router tests --- integration-test/playwright/package.json | 3 +- .../playwright/src/preloadQuery.test.ts | 4 +- integration-test/react-router/app/apollo.ts | 9 ++- integration-test/react-router/app/routes.ts | 7 +-- .../app/routes/{home.tsx => _index.tsx} | 0 .../app/routes/{api.ts => graphql.ts} | 0 .../preloadQuery.queryRef-useReadQuery.tsx | 59 +++++++++++++++++++ .../routes/preloadQuery.useSuspenseQuery.tsx | 59 +++++++++++++++++++ integration-test/react-router/package.json | 6 +- .../routes/preloadQuery/useSuspenseQuery.tsx | 2 +- yarn.lock | 18 +++++- 11 files changed, 153 insertions(+), 14 deletions(-) rename integration-test/react-router/app/routes/{home.tsx => _index.tsx} (100%) rename integration-test/react-router/app/routes/{api.ts => graphql.ts} (100%) create mode 100644 integration-test/react-router/app/routes/preloadQuery.queryRef-useReadQuery.tsx create mode 100644 integration-test/react-router/app/routes/preloadQuery.useSuspenseQuery.tsx diff --git a/integration-test/playwright/package.json b/integration-test/playwright/package.json index b9da5d89..91b625de 100644 --- a/integration-test/playwright/package.json +++ b/integration-test/playwright/package.json @@ -5,7 +5,8 @@ "scripts": { "test": "yarn playwright test", "test:nextjs": "TEST_PROJECT_DIR=../nextjs yarn playwright test --grep=@nextjs", - "test:tanstack": "TEST_PROJECT_DIR=../tanstack-start yarn playwright test --grep=@tanstack" + "test:tanstack": "TEST_PROJECT_DIR=../tanstack-start yarn playwright test --grep=@tanstack", + "test:react-router": "TEST_PROJECT_DIR=../react-router yarn playwright test --grep=@react-router" }, "devDependencies": { "@playwright/test": "^1.49.1", diff --git a/integration-test/playwright/src/preloadQuery.test.ts b/integration-test/playwright/src/preloadQuery.test.ts index c47b9d80..5732b0f3 100644 --- a/integration-test/playwright/src/preloadQuery.test.ts +++ b/integration-test/playwright/src/preloadQuery.test.ts @@ -20,7 +20,7 @@ test.describe("PreloadQuery", () => { test( "query resolves on the server", { - tag: ["@nextjs", "@tanstack"], + tag: ["@nextjs", "@tanstack", "@react-router"], }, async ({ page, blockRequest }) => { await page.goto(`${base}/${path}?errorIn=${otherEnvs}`, { @@ -39,7 +39,7 @@ test.describe("PreloadQuery", () => { test( "link chain errors on the server, restarts in the browser", { - tag: ["@nextjs", "@tanstack"], + tag: ["@nextjs", "@tanstack", "@react-router"], }, async ({ page }) => { page.allowErrors?.(); diff --git a/integration-test/react-router/app/apollo.ts b/integration-test/react-router/app/apollo.ts index c8dc444d..eea30ada 100644 --- a/integration-test/react-router/app/apollo.ts +++ b/integration-test/react-router/app/apollo.ts @@ -5,11 +5,16 @@ import { } from "@apollo/client-integration-react-router"; import { IncrementalSchemaLink } from "@integration-test/shared/IncrementalSchemaLink"; import { schema } from "@integration-test/shared/schema"; +import { delayLink } from "@integration-test/shared/delayLink"; +import { errorLink } from "@integration-test/shared/errorLink"; -const link = +const link = ApolloLink.from([ + delayLink, + errorLink, typeof window === "undefined" ? (new IncrementalSchemaLink({ schema }) as any as ApolloLink) - : new HttpLink({ uri: "/graphql" }); + : new HttpLink({ uri: "/graphql" }), +]); export const makeClient = (request?: Request) => { return new ApolloClient({ diff --git a/integration-test/react-router/app/routes.ts b/integration-test/react-router/app/routes.ts index 6b5c36af..dc7d046f 100644 --- a/integration-test/react-router/app/routes.ts +++ b/integration-test/react-router/app/routes.ts @@ -1,6 +1,3 @@ -import { type RouteConfig, index, route } from "@react-router/dev/routes"; +import { flatRoutes } from "@react-router/fs-routes"; -export default [ - index("routes/home.tsx"), - route("graphql", "routes/api.ts"), -] satisfies RouteConfig; +export default flatRoutes(); diff --git a/integration-test/react-router/app/routes/home.tsx b/integration-test/react-router/app/routes/_index.tsx similarity index 100% rename from integration-test/react-router/app/routes/home.tsx rename to integration-test/react-router/app/routes/_index.tsx diff --git a/integration-test/react-router/app/routes/api.ts b/integration-test/react-router/app/routes/graphql.ts similarity index 100% rename from integration-test/react-router/app/routes/api.ts rename to integration-test/react-router/app/routes/graphql.ts diff --git a/integration-test/react-router/app/routes/preloadQuery.queryRef-useReadQuery.tsx b/integration-test/react-router/app/routes/preloadQuery.queryRef-useReadQuery.tsx new file mode 100644 index 00000000..b13f57c6 --- /dev/null +++ b/integration-test/react-router/app/routes/preloadQuery.queryRef-useReadQuery.tsx @@ -0,0 +1,59 @@ +import { useLoaderData } from "react-router"; +import type { Route } from "./+types/preloadQuery.queryRef-useReadQuery"; +import { + useQueryRefHandlers, + useReadQuery, + type QueryRef, + type DefaultContext, +} from "@apollo/client/index.js"; +import { apolloLoader } from "~/apollo"; +import { + QUERY, + type DynamicProductResult, +} from "@integration-test/shared/queries"; +import { Suspense } from "react"; + +export const loader = apolloLoader()(({ + preloadQuery, + request, +}) => { + const errorIn = new URL(request.url).searchParams.get( + "errorIn" + ) as DefaultContext["error"]; + const queryRef = preloadQuery(QUERY, { + context: { + delay: 1000, + ...(errorIn ? { error: errorIn } : {}), + }, + }); + return { + queryRef, + }; +}); + +export default function RouteComponent() { + const { queryRef } = useLoaderData(); + return ( + loading}> + + + ); +} + +function Child({ queryRef }: { queryRef: QueryRef }) { + const { refetch } = useQueryRefHandlers(queryRef); + const { data } = useReadQuery(queryRef); + return ( + <> +
      + {data.products.map(({ id, title }: any) => ( +
    • {title}
    • + ))} +
    +

    Queried in {data.env} environment

    + + + ); +} diff --git a/integration-test/react-router/app/routes/preloadQuery.useSuspenseQuery.tsx b/integration-test/react-router/app/routes/preloadQuery.useSuspenseQuery.tsx new file mode 100644 index 00000000..d550eb7a --- /dev/null +++ b/integration-test/react-router/app/routes/preloadQuery.useSuspenseQuery.tsx @@ -0,0 +1,59 @@ +import { useLoaderData, useSearchParams } from "react-router"; +import type { Route } from "./+types/preloadQuery.useSuspenseQuery"; +import { + useQueryRefHandlers, + useReadQuery, + type QueryRef, + type DefaultContext, + useSuspenseQuery, +} from "@apollo/client/index.js"; +import { apolloLoader } from "~/apollo"; +import { + QUERY, + type DynamicProductResult, +} from "@integration-test/shared/queries"; +import { Suspense } from "react"; + +export const loader = apolloLoader()(({ + preloadQuery, + request, +}) => { + const errorIn = new URL(request.url).searchParams.get( + "errorIn" + ) as DefaultContext["error"]; + const queryRef = preloadQuery(QUERY, { + context: { + delay: 1000, + ...(errorIn ? { error: errorIn } : {}), + }, + }); + return { + queryRef, + }; +}); + +export default function RouteComponent() { + return ( + loading}> + + + ); +} + +function Child() { + const [search] = useSearchParams(); + const errorIn = search.get("errorIn") as DefaultContext["error"]; + const { data } = useSuspenseQuery(QUERY, { + context: { delay: 1000, ...(errorIn ? { error: errorIn } : {}) }, + }); + return ( + <> +
      + {data.products.map(({ id, title }: any) => ( +
    • {title}
    • + ))} +
    +

    Queried in {data.env} environment

    + + ); +} diff --git a/integration-test/react-router/package.json b/integration-test/react-router/package.json index ea3ea30d..7a56c838 100644 --- a/integration-test/react-router/package.json +++ b/integration-test/react-router/package.json @@ -4,14 +4,16 @@ "type": "module", "scripts": { "build": "react-router build", - "dev": "react-router dev", + "dev": "react-router dev --port 3000", "start": "react-router-serve ./build/server/index.js", - "typecheck": "react-router typegen && tsc" + "typecheck": "react-router typegen && tsc", + "test": "yarn test:react-router" }, "dependencies": { "@apollo/client": "^3.11.10", "@apollo/client-integration-react-router": "workspace:^", "@integration-test/shared": "workspace:^", + "@react-router/fs-routes": "^7.1.5", "@react-router/node": "^7.1.5", "@react-router/serve": "^7.1.5", "@vercel/react-router": "^1.0.2", diff --git a/integration-test/tanstack-start/app/routes/preloadQuery/useSuspenseQuery.tsx b/integration-test/tanstack-start/app/routes/preloadQuery/useSuspenseQuery.tsx index d5da6f3c..4fc3c2c6 100644 --- a/integration-test/tanstack-start/app/routes/preloadQuery/useSuspenseQuery.tsx +++ b/integration-test/tanstack-start/app/routes/preloadQuery/useSuspenseQuery.tsx @@ -30,7 +30,7 @@ function RouteComponent() { ); } -export function Child() { +function Child() { const { errorIn } = Route.useSearch(); const { data } = useSuspenseQuery(QUERY, { context: { delay: 1000, ...(errorIn ? { error: errorIn } : {}) }, diff --git a/yarn.lock b/yarn.lock index a6611dd8..ec1af3d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8557,6 +8557,21 @@ __metadata: languageName: node linkType: hard +"@react-router/fs-routes@npm:^7.1.5": + version: 7.1.5 + resolution: "@react-router/fs-routes@npm:7.1.5" + dependencies: + minimatch: "npm:^9.0.0" + peerDependencies: + "@react-router/dev": ^7.1.5 + typescript: ^5.1.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/35f4b42741346941ae32e4a1de9f2304d5a35b685db864e49a8b8f000d54f6b2b20fb4bfb34b5ce7c385b3fc6d6aa709b0baca40b6852ae4d44e89668fd661a9 + languageName: node + linkType: hard + "@react-router/node@npm:7.1.5, @react-router/node@npm:^7.1.5": version: 7.1.5 resolution: "@react-router/node@npm:7.1.5" @@ -21110,7 +21125,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.4": +"minimatch@npm:^9.0.0, minimatch@npm:^9.0.4": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -23540,6 +23555,7 @@ __metadata: "@apollo/client-integration-react-router": "workspace:^" "@integration-test/shared": "workspace:^" "@react-router/dev": "npm:^7.1.5" + "@react-router/fs-routes": "npm:^7.1.5" "@react-router/node": "npm:^7.1.5" "@react-router/serve": "npm:^7.1.5" "@tailwindcss/vite": "npm:^4.0.0" From f1e627ca84e1ce908227ad3f93e27332248ecfd5 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Feb 2025 14:21:13 +0100 Subject: [PATCH 16/18] run tests in CI --- .github/workflows/tests.yml | 8 +++++++- .github/workflows/vercel-integration.yml | 6 ++++++ integration-test/playwright/src/preloadQuery.test.ts | 7 ++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 564c3f2d..6ef926a1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -119,9 +119,15 @@ jobs: - name: "TanStack Start: Build" run: yarn workspace @integration-test/tanstack-start run build - - name: "Next.js: Test" + - name: "TanStack Start: Test" run: yarn workspace @integration-test/tanstack-start run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} + - name: "React Router: Build" + run: yarn workspace @integration-test/react-router run build + + - name: "React Router: Test" + run: yarn workspace @integration-test/react-router run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} + - name: "Vite Streaming: Build" run: yarn workspace @integration-test/vite-streaming run build - name: "Vite Streaming: Test" diff --git a/.github/workflows/vercel-integration.yml b/.github/workflows/vercel-integration.yml index 63dd0cba..f4e0de33 100644 --- a/.github/workflows/vercel-integration.yml +++ b/.github/workflows/vercel-integration.yml @@ -54,3 +54,9 @@ jobs: run: yarn workspace @integration-test/tanstack-start run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} env: BASE_URL: ${{ github.event.deployment_status.environment_url }} + + - name: "Run Playwright tests against Vercel deployment - React Router" + if: github.event.deployment_status.environment == 'Preview – apoll__client-integration-react-router' + run: yarn workspace @integration-test/react-router run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} + env: + BASE_URL: ${{ github.event.deployment_status.environment_url }} diff --git a/integration-test/playwright/src/preloadQuery.test.ts b/integration-test/playwright/src/preloadQuery.test.ts index 5732b0f3..90cb4272 100644 --- a/integration-test/playwright/src/preloadQuery.test.ts +++ b/integration-test/playwright/src/preloadQuery.test.ts @@ -79,7 +79,8 @@ test.describe("PreloadQuery", () => { // We might need to revisit this conceptually as right now we have no very good way // of restarting a query in this situation. // I'm honestly a bit irritated this works as it does in Next.js - // "@tanstack" + // "@tanstack", + // "@react-router", ], }, async ({ page }) => { @@ -118,7 +119,7 @@ test.describe("PreloadQuery", () => { test( "graphqlError on the server, restarts in the browser", { - tag: ["@nextjs", "@tanstack"], + tag: ["@nextjs", "@tanstack", "@react-router"], }, async ({ page }) => { page.allowErrors?.(); @@ -151,7 +152,7 @@ test.describe("PreloadQuery", () => { test( "queryRef works with useQueryRefHandlers", { - tag: ["@nextjs", "@tanstack"], + tag: ["@nextjs", "@tanstack", "@react-router"], }, async ({ page }) => { await page.goto(`${base}/queryRef-useReadQuery`, { From e532b5bd39b57139113def28b7edfd3e656a7ce7 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Wed, 12 Feb 2025 18:32:44 +0100 Subject: [PATCH 17/18] update package json name --- integration-test/react-router/package.json | 2 +- yarn.lock | 58 +++++++++++----------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/integration-test/react-router/package.json b/integration-test/react-router/package.json index 7a56c838..7fb6cde6 100644 --- a/integration-test/react-router/package.json +++ b/integration-test/react-router/package.json @@ -1,5 +1,5 @@ { - "name": "react-router", + "name": "@integration-test/react-router", "private": true, "type": "module", "scripts": { diff --git a/yarn.lock b/yarn.lock index ec1af3d8..bfce477f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6760,6 +6760,35 @@ __metadata: languageName: unknown linkType: soft +"@integration-test/react-router@workspace:integration-test/react-router": + version: 0.0.0-use.local + resolution: "@integration-test/react-router@workspace:integration-test/react-router" + dependencies: + "@apollo/client": "npm:^3.11.10" + "@apollo/client-integration-react-router": "workspace:^" + "@integration-test/shared": "workspace:^" + "@react-router/dev": "npm:^7.1.5" + "@react-router/fs-routes": "npm:^7.1.5" + "@react-router/node": "npm:^7.1.5" + "@react-router/serve": "npm:^7.1.5" + "@tailwindcss/vite": "npm:^4.0.0" + "@types/node": "npm:^20" + "@types/react": "npm:^19.0.1" + "@types/react-dom": "npm:^19.0.1" + "@vercel/react-router": "npm:^1.0.2" + graphql: "npm:*" + isbot: "npm:^5.1.17" + react: "npm:^19.0.0" + react-dom: "npm:^19.0.0" + react-router: "npm:^7.1.5" + react-router-devtools: "npm:^1.1.0" + tailwindcss: "npm:^4.0.0" + typescript: "npm:^5.7.2" + vite: "npm:^5.4.11" + vite-tsconfig-paths: "npm:^5.1.4" + languageName: unknown + linkType: soft + "@integration-test/shared@workspace:^, @integration-test/shared@workspace:integration-test/shared": version: 0.0.0-use.local resolution: "@integration-test/shared@workspace:integration-test/shared" @@ -23547,35 +23576,6 @@ __metadata: languageName: node linkType: hard -"react-router@workspace:integration-test/react-router": - version: 0.0.0-use.local - resolution: "react-router@workspace:integration-test/react-router" - dependencies: - "@apollo/client": "npm:^3.11.10" - "@apollo/client-integration-react-router": "workspace:^" - "@integration-test/shared": "workspace:^" - "@react-router/dev": "npm:^7.1.5" - "@react-router/fs-routes": "npm:^7.1.5" - "@react-router/node": "npm:^7.1.5" - "@react-router/serve": "npm:^7.1.5" - "@tailwindcss/vite": "npm:^4.0.0" - "@types/node": "npm:^20" - "@types/react": "npm:^19.0.1" - "@types/react-dom": "npm:^19.0.1" - "@vercel/react-router": "npm:^1.0.2" - graphql: "npm:*" - isbot: "npm:^5.1.17" - react: "npm:^19.0.0" - react-dom: "npm:^19.0.0" - react-router: "npm:^7.1.5" - react-router-devtools: "npm:^1.1.0" - tailwindcss: "npm:^4.0.0" - typescript: "npm:^5.7.2" - vite: "npm:^5.4.11" - vite-tsconfig-paths: "npm:^5.1.4" - languageName: unknown - linkType: soft - "react-server-dom-webpack@npm:^19.0.0": version: 19.0.0 resolution: "react-server-dom-webpack@npm:19.0.0" From c7cddb1480431b45e01267a358cad4bd6a27dfd3 Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Fri, 14 Feb 2025 10:50:44 +0100 Subject: [PATCH 18/18] fix review comment --- .github/workflows/vercel-integration.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/vercel-integration.yml b/.github/workflows/vercel-integration.yml index f4e0de33..04345c14 100644 --- a/.github/workflows/vercel-integration.yml +++ b/.github/workflows/vercel-integration.yml @@ -13,6 +13,7 @@ jobs: if: | github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success' && ( github.event.deployment_status.environment == 'Preview – apollo__experimental-nextjs-app-support' || + github.event.deployment_status.environment == 'Preview – apollo__client-integration-react-router' || github.event.deployment_status.environment == 'Preview – apollo__client-integration-tanstack-start' ) runs-on: ubuntu-latest @@ -56,7 +57,7 @@ jobs: BASE_URL: ${{ github.event.deployment_status.environment_url }} - name: "Run Playwright tests against Vercel deployment - React Router" - if: github.event.deployment_status.environment == 'Preview – apoll__client-integration-react-router' + if: github.event.deployment_status.environment == 'Preview – apollo__client-integration-react-router' run: yarn workspace @integration-test/react-router run test | tee $GITHUB_STEP_SUMMARY; exit ${PIPESTATUS[0]} env: BASE_URL: ${{ github.event.deployment_status.environment_url }}