diff --git a/.changeset/fresh-wombats-stick.md b/.changeset/fresh-wombats-stick.md new file mode 100644 index 000000000..e179e8af9 --- /dev/null +++ b/.changeset/fresh-wombats-stick.md @@ -0,0 +1,6 @@ +--- +'@vanilla-extract/turbopack-plugin': minor +'@vanilla-extract/next-plugin': minor +--- + +Add turbopack support for next.js >= 16.0.0 diff --git a/.changeset/green-years-yawn.md b/.changeset/green-years-yawn.md new file mode 100644 index 000000000..ef19fd664 --- /dev/null +++ b/.changeset/green-years-yawn.md @@ -0,0 +1,5 @@ +--- +'@vanilla-extract/compiler': minor +--- + +add `unstable_splitCssPerRule` option, generate one CSS import per rule instead of one per file. used by turbopack. \ No newline at end of file diff --git a/.changeset/heavy-boxes-protect.md b/.changeset/heavy-boxes-protect.md new file mode 100644 index 000000000..e36d24ad7 --- /dev/null +++ b/.changeset/heavy-boxes-protect.md @@ -0,0 +1,5 @@ +--- +'@vanilla-extract/compiler': minor +--- + +add `unstable_invalidateAllModules` to manually clear module cache diff --git a/.changeset/slimy-poems-wonder.md b/.changeset/slimy-poems-wonder.md new file mode 100644 index 000000000..d39bc5fef --- /dev/null +++ b/.changeset/slimy-poems-wonder.md @@ -0,0 +1,8 @@ +--- +'@vanilla-extract/compiler': patch +'@vanilla-extract/css': patch +'@vanilla-extract/turbopack-plugin': patch +'@vanilla-extract/next-plugin': patch +--- + +turbopack: improve CSS deduplication diff --git a/.changeset/tough-mails-jog.md b/.changeset/tough-mails-jog.md new file mode 100644 index 000000000..efdf6a373 --- /dev/null +++ b/.changeset/tough-mails-jog.md @@ -0,0 +1,5 @@ +--- +'@vanilla-extract/compiler': minor +--- + +the `cssImportSpecifier` option receives the css content in addition to the module id diff --git a/.gitignore b/.gitignore index 1eb2e7f77..f37eee6d0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ test-results .next .DS_Store .idea +next-env.d.ts \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 869b8973d..d57ff8a03 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,3 +12,4 @@ pnpm-lock.yaml *-snapshots test-results examples/remix/build +.pnpm-store diff --git a/fixtures/next-pages-router/CHANGELOG.md b/fixtures/next-12-pages-router/CHANGELOG.md similarity index 100% rename from fixtures/next-pages-router/CHANGELOG.md rename to fixtures/next-12-pages-router/CHANGELOG.md diff --git a/fixtures/next-pages-router/next.config.js b/fixtures/next-12-pages-router/next.config.js similarity index 100% rename from fixtures/next-pages-router/next.config.js rename to fixtures/next-12-pages-router/next.config.js diff --git a/fixtures/next-pages-router/package.json b/fixtures/next-12-pages-router/package.json similarity index 86% rename from fixtures/next-pages-router/package.json rename to fixtures/next-12-pages-router/package.json index 1d49ec676..fd1eb3af8 100644 --- a/fixtures/next-pages-router/package.json +++ b/fixtures/next-12-pages-router/package.json @@ -1,5 +1,5 @@ { - "name": "@fixtures/next-pages-router", + "name": "@fixtures/next-12-pages-router", "description": "Next pages router fixtures", "version": "0.0.7", "private": true, @@ -7,8 +7,6 @@ "dev": "next dev", "build": "next build", "start": "next start", - "clean-build": "pnpm clean && next build", - "clean": "pnpm clean:dev && pnpm clean:prod", "clean:dev": "rm -rf .next", "clean:prod": "rm -rf dist" }, diff --git a/fixtures/next-pages-router/src/pages/features/index.tsx b/fixtures/next-12-pages-router/src/pages/features/index.tsx similarity index 100% rename from fixtures/next-pages-router/src/pages/features/index.tsx rename to fixtures/next-12-pages-router/src/pages/features/index.tsx diff --git a/fixtures/next-pages-router/src/pages/index.tsx b/fixtures/next-12-pages-router/src/pages/index.tsx similarity index 100% rename from fixtures/next-pages-router/src/pages/index.tsx rename to fixtures/next-12-pages-router/src/pages/index.tsx diff --git a/fixtures/next-pages-router/src/pages/recipes/index.tsx b/fixtures/next-12-pages-router/src/pages/recipes/index.tsx similarity index 100% rename from fixtures/next-pages-router/src/pages/recipes/index.tsx rename to fixtures/next-12-pages-router/src/pages/recipes/index.tsx diff --git a/fixtures/next-pages-router/src/pages/sprinkles/index.tsx b/fixtures/next-12-pages-router/src/pages/sprinkles/index.tsx similarity index 100% rename from fixtures/next-pages-router/src/pages/sprinkles/index.tsx rename to fixtures/next-12-pages-router/src/pages/sprinkles/index.tsx diff --git a/fixtures/next-pages-router/tsconfig.json b/fixtures/next-12-pages-router/tsconfig.json similarity index 72% rename from fixtures/next-pages-router/tsconfig.json rename to fixtures/next-12-pages-router/tsconfig.json index f295fe6d3..c363dcf1f 100644 --- a/fixtures/next-pages-router/tsconfig.json +++ b/fixtures/next-12-pages-router/tsconfig.json @@ -3,7 +3,9 @@ "compilerOptions": { "forceConsistentCasingInFileNames": true, "jsx": "preserve", - "strictNullChecks": true + "strictNullChecks": true, + "module": "esnext", + "moduleResolution": "node" }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] diff --git a/fixtures/next-app-router/CHANGELOG.md b/fixtures/next-13-app-router/CHANGELOG.md similarity index 100% rename from fixtures/next-app-router/CHANGELOG.md rename to fixtures/next-13-app-router/CHANGELOG.md diff --git a/fixtures/next-app-router/next.config.js b/fixtures/next-13-app-router/next.config.js similarity index 84% rename from fixtures/next-app-router/next.config.js rename to fixtures/next-13-app-router/next.config.js index fb626cabf..ccf7e23ca 100644 --- a/fixtures/next-app-router/next.config.js +++ b/fixtures/next-13-app-router/next.config.js @@ -6,9 +6,6 @@ const withVanillaExtract = createVanillaExtractPlugin(); /** @type {import('next').NextConfig} */ const config = withVanillaExtract({ - // exporting a static build for next 13 - // due to issues with distDir on next custom server - output: 'export', // we need to differentiate build and dev folders // so they don't overwrite eachother when running tests distDir: process.env.NODE_ENV === 'production' ? 'dist' : '.next', diff --git a/fixtures/next-app-router/package.json b/fixtures/next-13-app-router/package.json similarity index 83% rename from fixtures/next-app-router/package.json rename to fixtures/next-13-app-router/package.json index 1938fb611..cb504aece 100644 --- a/fixtures/next-app-router/package.json +++ b/fixtures/next-13-app-router/package.json @@ -1,5 +1,5 @@ { - "name": "@fixtures/next-app-router", + "name": "@fixtures/next-13-app-router", "description": "Next app router fixtures", "version": "0.0.7", "private": true, @@ -7,8 +7,6 @@ "dev": "next dev", "build": "next build", "start": "next start", - "clean-build": "pnpm clean && pnpm build", - "clean": "pnpm clean:dev && pnpm clean:prod", "clean:dev": "rm -rf .next", "clean:prod": "rm -rf dist" }, @@ -19,7 +17,7 @@ "@vanilla-extract/css": "workspace:*", "@vanilla-extract/recipes": "workspace:*", "@vanilla-extract/sprinkles": "workspace:*", - "next": "npm:next@13.5.4", + "next": "npm:next@13.5.11", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/fixtures/next-app-router/src/app/features/page.tsx b/fixtures/next-13-app-router/src/app/features/page.tsx similarity index 100% rename from fixtures/next-app-router/src/app/features/page.tsx rename to fixtures/next-13-app-router/src/app/features/page.tsx diff --git a/fixtures/next-app-router/src/app/layout.tsx b/fixtures/next-13-app-router/src/app/layout.tsx similarity index 100% rename from fixtures/next-app-router/src/app/layout.tsx rename to fixtures/next-13-app-router/src/app/layout.tsx diff --git a/fixtures/next-app-router/src/app/page.tsx b/fixtures/next-13-app-router/src/app/page.tsx similarity index 100% rename from fixtures/next-app-router/src/app/page.tsx rename to fixtures/next-13-app-router/src/app/page.tsx diff --git a/fixtures/next-app-router/src/app/recipes/page.tsx b/fixtures/next-13-app-router/src/app/recipes/page.tsx similarity index 100% rename from fixtures/next-app-router/src/app/recipes/page.tsx rename to fixtures/next-13-app-router/src/app/recipes/page.tsx diff --git a/fixtures/next-app-router/src/app/sprinkles/page.tsx b/fixtures/next-13-app-router/src/app/sprinkles/page.tsx similarity index 100% rename from fixtures/next-app-router/src/app/sprinkles/page.tsx rename to fixtures/next-13-app-router/src/app/sprinkles/page.tsx diff --git a/fixtures/next-app-router/tsconfig.json b/fixtures/next-13-app-router/tsconfig.json similarity index 86% rename from fixtures/next-app-router/tsconfig.json rename to fixtures/next-13-app-router/tsconfig.json index d751428c7..8c8ab9649 100644 --- a/fixtures/next-app-router/tsconfig.json +++ b/fixtures/next-13-app-router/tsconfig.json @@ -8,7 +8,8 @@ "name": "next" } ], - "strictNullChecks": true + "strictNullChecks": true, + "module": "esnext" }, "include": [ "next-env.d.ts", diff --git a/fixtures/next-16-app-pages-router/next.config.ts b/fixtures/next-16-app-pages-router/next.config.ts new file mode 100644 index 000000000..0b03fdfd8 --- /dev/null +++ b/fixtures/next-16-app-pages-router/next.config.ts @@ -0,0 +1,13 @@ +import { NextConfig } from 'next'; +import { createVanillaExtractPlugin } from './next-plugin/dist/vanilla-extract-next-plugin.cjs.js'; +const withVanillaExtract = createVanillaExtractPlugin(); + +export const config: NextConfig = { + distDir: process.env.NEXT_DIST_DIR || '.next', + experimental: { externalDir: true }, + onDemandEntries: { maxInactiveAge: 1000 * 60 * 60 }, + transpilePackages: ['@fixtures/sprinkles/src/html'], + devIndicators: false, +}; + +export default withVanillaExtract(config); diff --git a/fixtures/next-16-app-pages-router/package.json b/fixtures/next-16-app-pages-router/package.json new file mode 100644 index 000000000..80eb7ac59 --- /dev/null +++ b/fixtures/next-16-app-pages-router/package.json @@ -0,0 +1,32 @@ +{ + "name": "@fixtures/next-16-app-pages-router", + "version": "0.0.1", + "private": true, + "description": "Next 16 fixture with app + pages routers; supports webpack and turbopack builds", + "scripts": { + "dev-webpack": "NEXT_DIST_DIR=.next/webpack next dev --webpack", + "dev-turbo": "NEXT_DIST_DIR=.next/turbo next dev --turbo", + "build-webpack": "NEXT_DIST_DIR=dist/webpack next build --webpack", + "start-webpack": "NEXT_DIST_DIR=dist/webpack next start", + "build-turbo": "NEXT_DIST_DIR=dist/turbo next build --turbo", + "start-turbo": "NEXT_DIST_DIR=dist/turbo next start", + "clean:dev": "rm -rf .next", + "clean:prod": "rm -rf dist" + }, + "dependencies": { + "@fixtures/features": "workspace:*", + "@fixtures/recipes": "workspace:*", + "@fixtures/sprinkles": "workspace:*", + "@vanilla-extract/css": "workspace:*", + "@vanilla-extract/recipes": "workspace:*", + "@vanilla-extract/sprinkles": "workspace:*", + "next": "npm:next@^16.0.0", + "react": "npm:react@^19.2.0", + "react-dom": "npm:react-dom@^19.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.55", + "@vanilla-extract/next-plugin": "workspace:*", + "@vanilla-extract/webpack-plugin": "workspace:*" + } +} diff --git a/fixtures/next-16-app-pages-router/src/app/creepster/page.tsx b/fixtures/next-16-app-pages-router/src/app/creepster/page.tsx new file mode 100644 index 000000000..67ca334b4 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/creepster/page.tsx @@ -0,0 +1,9 @@ +import { creepsterText } from '../../styles/creepster.css'; + +export default function CreepsterPage() { + return ( +
+ This text should look scary (Creepster Font) +
+ ); +} diff --git a/fixtures/next-16-app-pages-router/src/app/duplication-test/a-plain.css.ts b/fixtures/next-16-app-pages-router/src/app/duplication-test/a-plain.css.ts new file mode 100644 index 000000000..b835f2f2c --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/duplication-test/a-plain.css.ts @@ -0,0 +1,5 @@ +import { globalStyle } from '@vanilla-extract/css'; + +globalStyle('body', { + backgroundColor: '#0cdbcd', +}); diff --git a/fixtures/next-16-app-pages-router/src/app/duplication-test/a.css.ts b/fixtures/next-16-app-pages-router/src/app/duplication-test/a.css.ts new file mode 100644 index 000000000..721b2632a --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/duplication-test/a.css.ts @@ -0,0 +1,9 @@ +import { globalStyle, style } from '@vanilla-extract/css'; + +globalStyle('body', { + backgroundColor: '#0cdbcd', +}); + +export const a = style({ + border: '1px solid black', +}); diff --git a/fixtures/next-16-app-pages-router/src/app/duplication-test/b-plain.css.ts b/fixtures/next-16-app-pages-router/src/app/duplication-test/b-plain.css.ts new file mode 100644 index 000000000..b835f2f2c --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/duplication-test/b-plain.css.ts @@ -0,0 +1,5 @@ +import { globalStyle } from '@vanilla-extract/css'; + +globalStyle('body', { + backgroundColor: '#0cdbcd', +}); diff --git a/fixtures/next-16-app-pages-router/src/app/duplication-test/b.css.ts b/fixtures/next-16-app-pages-router/src/app/duplication-test/b.css.ts new file mode 100644 index 000000000..b25a94197 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/duplication-test/b.css.ts @@ -0,0 +1,9 @@ +import { globalStyle, style } from '@vanilla-extract/css'; + +globalStyle('body', { + backgroundColor: '#0cdbcd', +}); + +export const b = style({ + border: '1px solid red', +}); diff --git a/fixtures/next-16-app-pages-router/src/app/duplication-test/extra/c-plain.css.ts b/fixtures/next-16-app-pages-router/src/app/duplication-test/extra/c-plain.css.ts new file mode 100644 index 000000000..b835f2f2c --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/duplication-test/extra/c-plain.css.ts @@ -0,0 +1,5 @@ +import { globalStyle } from '@vanilla-extract/css'; + +globalStyle('body', { + backgroundColor: '#0cdbcd', +}); diff --git a/fixtures/next-16-app-pages-router/src/app/duplication-test/extra/c.css.ts b/fixtures/next-16-app-pages-router/src/app/duplication-test/extra/c.css.ts new file mode 100644 index 000000000..388ec5cc0 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/duplication-test/extra/c.css.ts @@ -0,0 +1,9 @@ +import { globalStyle, style } from '@vanilla-extract/css'; + +globalStyle('body', { + backgroundColor: '#0cdbcd', +}); + +export const c = style({ + border: '1px solid black', +}); diff --git a/fixtures/next-16-app-pages-router/src/app/duplication-test/page.tsx b/fixtures/next-16-app-pages-router/src/app/duplication-test/page.tsx new file mode 100644 index 000000000..7ebf1396a --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/duplication-test/page.tsx @@ -0,0 +1,18 @@ +import './a-plain.css'; +import { a } from './a.css'; +import './b-plain.css'; +import { b } from './b.css'; +import './extra/c-plain.css'; +import { c } from './extra/c.css'; + +export default function DuplicationTestPage() { + return ( +
+
+
+
duplication test
+
+
+
+ ); +} diff --git a/fixtures/next-16-app-pages-router/src/app/features/page.tsx b/fixtures/next-16-app-pages-router/src/app/features/page.tsx new file mode 100644 index 000000000..ffffe61a8 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/features/page.tsx @@ -0,0 +1,10 @@ +import html from '@fixtures/features/src/html'; + +export default function Features() { + return ( + <> + +
+ + ); +} diff --git a/fixtures/next-16-app-pages-router/src/app/function-serializer/page.tsx b/fixtures/next-16-app-pages-router/src/app/function-serializer/page.tsx new file mode 100644 index 000000000..426255cca --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/function-serializer/page.tsx @@ -0,0 +1,12 @@ +import { RedBox, BlueText } from './source.css'; + +export default function Page() { + return ( +
+

Function Serializer Test

+ + This should be a red box with blue text inside + +
+ ); +} diff --git a/fixtures/next-16-app-pages-router/src/app/function-serializer/runtime.tsx b/fixtures/next-16-app-pages-router/src/app/function-serializer/runtime.tsx new file mode 100644 index 000000000..6ead362c9 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/function-serializer/runtime.tsx @@ -0,0 +1,14 @@ +export function runtimeStyled( + tag: Tag, + className: string, +) { + return function Component(props: React.ComponentProps) { + const Element = tag as any; + return ( + + ); + }; +} diff --git a/fixtures/next-16-app-pages-router/src/app/function-serializer/source.css.ts b/fixtures/next-16-app-pages-router/src/app/function-serializer/source.css.ts new file mode 100644 index 000000000..85d8aa56d --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/function-serializer/source.css.ts @@ -0,0 +1,12 @@ +import { styled } from './styled'; + +export const RedBox = styled('div', { + backgroundColor: 'red', + color: 'white', + padding: '20px', +}); + +export const BlueText = styled('span', { + color: 'blue', + fontWeight: 'bold', +}); diff --git a/fixtures/next-16-app-pages-router/src/app/function-serializer/styled.ts b/fixtures/next-16-app-pages-router/src/app/function-serializer/styled.ts new file mode 100644 index 000000000..d4b8e684b --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/function-serializer/styled.ts @@ -0,0 +1,28 @@ +import { addFunctionSerializer } from '@vanilla-extract/css/functionSerializer'; +import { style, type StyleRule } from '@vanilla-extract/css'; +import { runtimeStyled } from './runtime'; +import React from 'react'; + +if (React.version.includes('canary')) { + throw new Error( + 'detected vendored React in styles, this will cause errors in some projects', + ); +} + +export function styled( + tag: Tag, + styles: StyleRule, +) { + const className = style(styles); + const args = [tag, className] as const; + + const Component = runtimeStyled(...args); + + addFunctionSerializer(Component, { + importPath: './runtime', + importName: 'runtimeStyled', + args, + }); + + return Component; +} diff --git a/fixtures/next-16-app-pages-router/src/app/layout.tsx b/fixtures/next-16-app-pages-router/src/app/layout.tsx new file mode 100644 index 000000000..225b6038d --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/fixtures/next-16-app-pages-router/src/app/next-font/page.tsx b/fixtures/next-16-app-pages-router/src/app/next-font/page.tsx new file mode 100644 index 000000000..5573693b8 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/next-font/page.tsx @@ -0,0 +1,41 @@ +import * as directFonts from '../../styles/fonts'; +import { pickedValues } from '../../styles/nextFont.css'; + +export default function NextFontChecks() { + const pairs: Array< + [string, string | number | undefined, string | number | undefined] + > = []; + + for (const [name, vePicked] of Object.entries(pickedValues)) { + const direct = directFonts[name as keyof typeof directFonts]; + const style = direct?.style || {}; + pairs.push([`${name} family`, vePicked.fontFamily, style.fontFamily]); + pairs.push([`${name} weight`, vePicked.fontWeight, style.fontWeight]); + pairs.push([`${name} style`, vePicked.fontStyle, style.fontStyle]); + } + + pairs.sort((a, b) => a[0].localeCompare(b[0])); + + for (const [name, fromVe, direct] of pairs) { + if (String(fromVe) !== String(direct)) { + throw new Error( + `[next-font] mismatch for ${name}:\n${String(fromVe)} !==\n${String( + direct, + )}`, + ); + } + } + + return ( +
+

next 16 next/font comparisons

+
    + {pairs.map(([name, fromVe, direct]) => ( +
  • + {name}: {fromVe} +
  • + ))} +
+
+ ); +} diff --git a/fixtures/next-16-app-pages-router/src/app/next-image/image.css.ts b/fixtures/next-16-app-pages-router/src/app/next-image/image.css.ts new file mode 100644 index 000000000..41074e056 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/next-image/image.css.ts @@ -0,0 +1,13 @@ +import logo from './logo.png'; +import { style } from '@vanilla-extract/css'; +import type { StaticImageData } from 'next/image'; + +// types are funky because of our monorepo setup +const withCast = logo as unknown as StaticImageData; + +export const imageStyle = style({ + backgroundImage: `url(${withCast.src})`, + width: `${withCast.width}px`, + height: `${withCast.height}px`, + border: '1px solid red', +}); diff --git a/fixtures/next-16-app-pages-router/src/app/next-image/logo.png b/fixtures/next-16-app-pages-router/src/app/next-image/logo.png new file mode 100644 index 000000000..40506eac8 Binary files /dev/null and b/fixtures/next-16-app-pages-router/src/app/next-image/logo.png differ diff --git a/fixtures/next-16-app-pages-router/src/app/next-image/page.tsx b/fixtures/next-16-app-pages-router/src/app/next-image/page.tsx new file mode 100644 index 000000000..d7eac9525 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/next-image/page.tsx @@ -0,0 +1,5 @@ +import { imageStyle } from './image.css'; + +export default function NextImagePage() { + return
Next Image Page
; +} diff --git a/fixtures/next-16-app-pages-router/src/app/page.tsx b/fixtures/next-16-app-pages-router/src/app/page.tsx new file mode 100644 index 000000000..0a72cb5a5 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/page.tsx @@ -0,0 +1,23 @@ +import Link from 'next/link'; + +export default function Home() { + return ( + <> + sprinkles +
+ recipes +
+ features +
+ function serializer +
+ creepster test +
+ next font +
+ duplication test +
+ next image + + ); +} diff --git a/fixtures/next-16-app-pages-router/src/app/recipes/page.tsx b/fixtures/next-16-app-pages-router/src/app/recipes/page.tsx new file mode 100644 index 000000000..fcde26b0d --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/recipes/page.tsx @@ -0,0 +1,10 @@ +import html from '@fixtures/recipes/src/html'; + +export default function Recipes() { + return ( + <> + +
+ + ); +} diff --git a/fixtures/next-16-app-pages-router/src/app/sprinkles/page.tsx b/fixtures/next-16-app-pages-router/src/app/sprinkles/page.tsx new file mode 100644 index 000000000..f70bcf5d4 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/app/sprinkles/page.tsx @@ -0,0 +1,10 @@ +import html from '@fixtures/sprinkles/src/html'; + +export default function Sprinkles() { + return ( + <> + +
+ + ); +} diff --git a/fixtures/next-16-app-pages-router/src/pages/pages-router/features/index.tsx b/fixtures/next-16-app-pages-router/src/pages/pages-router/features/index.tsx new file mode 100644 index 000000000..ffffe61a8 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/pages/pages-router/features/index.tsx @@ -0,0 +1,10 @@ +import html from '@fixtures/features/src/html'; + +export default function Features() { + return ( + <> + +
+ + ); +} diff --git a/fixtures/next-16-app-pages-router/src/pages/pages-router/index.tsx b/fixtures/next-16-app-pages-router/src/pages/pages-router/index.tsx new file mode 100644 index 000000000..3a09b6975 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/pages/pages-router/index.tsx @@ -0,0 +1,13 @@ +import Link from 'next/link'; + +export default function Home() { + return ( + <> + sprinkles +
+ recipes +
+ features + + ); +} diff --git a/fixtures/next-16-app-pages-router/src/pages/pages-router/recipes/index.tsx b/fixtures/next-16-app-pages-router/src/pages/pages-router/recipes/index.tsx new file mode 100644 index 000000000..fcde26b0d --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/pages/pages-router/recipes/index.tsx @@ -0,0 +1,10 @@ +import html from '@fixtures/recipes/src/html'; + +export default function Recipes() { + return ( + <> + +
+ + ); +} diff --git a/fixtures/next-16-app-pages-router/src/pages/pages-router/sprinkles/index.tsx b/fixtures/next-16-app-pages-router/src/pages/pages-router/sprinkles/index.tsx new file mode 100644 index 000000000..f70bcf5d4 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/pages/pages-router/sprinkles/index.tsx @@ -0,0 +1,10 @@ +import html from '@fixtures/sprinkles/src/html'; + +export default function Sprinkles() { + return ( + <> + +
+ + ); +} diff --git a/fixtures/next-16-app-pages-router/src/styles/creepster-font.ts b/fixtures/next-16-app-pages-router/src/styles/creepster-font.ts new file mode 100644 index 000000000..dc9cdc5e5 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/styles/creepster-font.ts @@ -0,0 +1,8 @@ +import { Creepster } from 'next/font/google'; + +export const creepster = Creepster({ + weight: '400', + subsets: ['latin'], + display: 'block', + preload: true, +}); diff --git a/fixtures/next-16-app-pages-router/src/styles/creepster.css.ts b/fixtures/next-16-app-pages-router/src/styles/creepster.css.ts new file mode 100644 index 000000000..bb19251b1 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/styles/creepster.css.ts @@ -0,0 +1,8 @@ +import { style } from '@vanilla-extract/css'; +import { creepster } from './creepster-font'; + +export const creepsterText = style({ + fontFamily: creepster.style.fontFamily, + fontSize: '40px', + color: 'red', +}); diff --git a/fixtures/next-16-app-pages-router/src/styles/fonts.ts b/fixtures/next-16-app-pages-router/src/styles/fonts.ts new file mode 100644 index 000000000..9024f1e66 --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/styles/fonts.ts @@ -0,0 +1,251 @@ +// --- 1. Imports --- +// Test weirdly named imports for both local and google fonts. + +import { + Noto_Serif as NotoSerif, + Roboto as R, + Roboto_Flex as RF, + Inter as Weird_Renamed_Font$8a_, +} from 'next/font/google'; +import weird_renamed_local$3_ from 'next/font/local'; + +// ================================================================= +// next/font/local (using weird_renamed_local$3_) +// ================================================================= + +// --- 2. Local: Variable Name Edge Cases (Export) --- +// The import name is already tested. This tests weird export names. + +export const localSimple = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + preload: false, +}); + +export const $local_weird_EXPORT_name_ = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + fallback: ['system-ui'], + preload: false, +}); + +// --- 3. Local: Fallback Prop --- + +export const localFallbackOmitted = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + // fallback is omitted + preload: false, +}); + +export const localFallbackSingleArray = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + fallback: ['system-ui'], + preload: false, +}); + +export const localFallbackMultiArray = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + fallback: ['Times New Roman', 'Gill Sans', 'emoji'], + preload: false, +}); + +// --- 4. Local: Style Prop --- + +export const localStyleOmitted = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + // style is omitted + preload: false, +}); + +export const localStyleSingle = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + style: 'italic', + preload: false, +}); + +// --- 5. Local: Weight Prop --- + +export const localWeightOmitted = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + // weight is omitted + preload: false, +}); + +export const localWeightSingle = weird_renamed_local$3_({ + src: './fonts/Inter-Regular.woff2', + weight: '400', + preload: false, +}); + +// ================================================================= +// next/font/google (using Weird_Renamed_Font$8a_) +// ================================================================= + +// --- 6. Google: Variable Name Edge Cases (Export) --- +// The import name is already tested. This tests weird export names. + +export const googleSimple = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + preload: false, +}); + +export const $google_weird_EXPORT_name_ = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + fallback: ['system-ui'], + preload: false, +}); + +// --- 7. Google: Fallback Prop --- + +export const googleFallbackOmitted = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + // fallback is omitted + preload: false, +}); + +export const googleFallbackSingleArray = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + fallback: ['system-ui'], + preload: false, +}); + +export const googleFallbackMultiArray = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + fallback: ['Times New Roman', 'Gill Sans', 'emoji'], + preload: false, +}); + +// --- 8. Google: Style Prop --- + +export const googleStyleOmitted = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + // style is omitted + preload: false, +}); + +export const googleStyleSingle = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + style: 'italic', + preload: false, +}); + +export const googleStyleArray = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + style: ['italic', 'normal'], + preload: false, +}); + +// --- 9. Google: Weight Prop --- + +export const googleWeightOmitted = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + // weight is omitted + preload: false, +}); + +export const googleWeightSingle = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + weight: '400', + preload: false, +}); + +export const googleWeightVariable = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + weight: 'variable', + preload: false, +}); + +export const googleWeightArray = Weird_Renamed_Font$8a_({ + subsets: ['latin'], + weight: ['400', '700', '900'], + preload: false, +}); + +// intentionally odd local variable name to exercise transform edge-cases +export const __Local_Font = weird_renamed_local$3_({ + src: [{ path: './fonts/Inter-Regular.woff2', weight: '400' }], + fallback: ['system-ui'], + preload: false, +}); + +// renamed imports +export const _Roboto = R({ + weight: '400', + subsets: ['latin'], + fallback: ['system-ui', 'skibidi', 'third font'], + style: ['italic', 'normal'], + preload: false, +}); + +export const _Flex = RF({ + subsets: ['latin', 'greek'], + weight: ['200', '300'], + adjustFontFallback: false, + style: 'normal', + fallback: ['system-ui'], + preload: false, +}); + +// style properties are consumed dynamically in nextFont.css.ts via pickedValues + +// mirror additional cases from next-16 +export const _localMultiFallback = weird_renamed_local$3_({ + src: [{ path: './fonts/Inter-Regular.woff2' }], + fallback: ['system-ui', 'ui-monospace', 'third font'], + preload: false, +}); + +export const _localExplicit = weird_renamed_local$3_({ + src: [{ path: './fonts/Inter-Regular.woff2' }], + weight: '400', + style: 'italic', + fallback: ['Times New Roman', 'Gill Sans'], + preload: false, +}); + +export const _localDupFallback = weird_renamed_local$3_({ + src: [{ path: './fonts/Inter-Regular.woff2' }], + fallback: ['system-ui', 'system-ui', 'ui-serif', 'weird_font'], + preload: false, +}); + +export const _robotoDefaultStyle = R({ + subsets: ['latin'], + fallback: ['serif'], + preload: false, +}); + +export const _robotoItalic = R({ + subsets: ['latin'], + fallback: ['sans-serif'], + style: 'italic', + weight: '400', + preload: false, +}); + +export const _robotoMultiStyle = R({ + subsets: ['latin'], + fallback: ['monospace'], + style: ['italic', 'normal'], + preload: false, +}); + +export const _robotoWeightStr = R({ weight: '400', preload: false }); + +export const _robotoWeightVar = R({ weight: 'variable', preload: false }); + +export const _notoSerif = NotoSerif({ + subsets: ['latin'], + fallback: ['system-ui'], + preload: false, +}); + +export const _robotoFallbackSpaces = R({ + subsets: ['latin'], + fallback: ['Times New Roman', 'Gill Sans', 'Avenir Next'], + preload: false, +}); + +export const _robotoDupFallback = R({ + subsets: ['latin'], + fallback: ['system-ui', 'system-ui', 'ui-serif', 'weird_font'], + preload: false, +}); diff --git a/fixtures/next-16-app-pages-router/src/styles/fonts/Inter-Regular.woff2 b/fixtures/next-16-app-pages-router/src/styles/fonts/Inter-Regular.woff2 new file mode 100644 index 000000000..2bcd222ec Binary files /dev/null and b/fixtures/next-16-app-pages-router/src/styles/fonts/Inter-Regular.woff2 differ diff --git a/fixtures/next-16-app-pages-router/src/styles/nextFont.css.ts b/fixtures/next-16-app-pages-router/src/styles/nextFont.css.ts new file mode 100644 index 000000000..6b3175e6e --- /dev/null +++ b/fixtures/next-16-app-pages-router/src/styles/nextFont.css.ts @@ -0,0 +1,22 @@ +import * as fonts from './fonts'; + +export const pickedValues = Object.fromEntries( + Object.entries(fonts).map( + ([importName, { style }]) => + [ + importName, + { + fontFamily: style.fontFamily, + fontWeight: style.fontWeight, + fontStyle: style.fontStyle, + }, + ] as const, + ), +) as Record< + keyof typeof fonts, + { + fontFamily: string; + fontWeight: number; + fontStyle: string; + } +>; diff --git a/fixtures/next-16-app-pages-router/tsconfig.json b/fixtures/next-16-app-pages-router/tsconfig.json new file mode 100644 index 000000000..70056b1fa --- /dev/null +++ b/fixtures/next-16-app-pages-router/tsconfig.json @@ -0,0 +1,42 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": [ + "next-env.d.ts", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts", + "**/*.ts", + "**/*.tsx", + "dist/turbo/types/**/*.ts", + "dist/turbo/dev/types/**/*.ts", + "dist/webpack/types/**/*.ts", + "dist/webpack/dev/types/**/*.ts", + ".next/turbo/types/**/*.ts", + ".next/turbo/dev/types/**/*.ts", + ".next/webpack/types/**/*.ts", + ".next/webpack/dev/types/**/*.ts" + ], + "exclude": ["node_modules"] +} diff --git a/fixtures/next-app-router/next-env.d.ts b/fixtures/next-app-router/next-env.d.ts deleted file mode 100644 index 4f11a03dc..000000000 --- a/fixtures/next-app-router/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/fixtures/next-pages-router/next-env.d.ts b/fixtures/next-pages-router/next-env.d.ts deleted file mode 100644 index 4f11a03dc..000000000 --- a/fixtures/next-pages-router/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/package.json b/package.json index 794f7a2ab..dc20c6e27 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,9 @@ "test:unit": "pnpm test:jest && pnpm test:vitest", "test:jest": "cross-env NODE_OPTIONS=--experimental-vm-modules jest", "test:vitest": "vitest --watch=false", - "test:playwright": "pnpm test:build-next && playwright test", - "test:build-next": "node scripts/copy-next-plugin.ts && pnpm --filter=@fixtures/next-* clean-build", + "test:playwright": "pnpm test:clean-next && pnpm test:build-next && playwright test", + "test:clean-next": "pnpm --filter=@fixtures/next-* run '/^clean.*/'", + "test:build-next": "node scripts/copy-next-plugin.ts && pnpm --filter=@fixtures/next-* run '/^build.*/'", "format": "prettier --write .", "lint": "pnpm run '/^lint:.*/'", "lint:manypkg": "manypkg check", @@ -28,15 +29,15 @@ "prepare-release": "pnpm copy-readme-to-packages && pnpm build", "release": "pnpm prepare-release && changeset publish" }, - "dependencies": { + "devDependencies": { "@babel/core": "^7.23.9", "@babel/preset-env": "^7.23.9", "@babel/preset-react": "^7.23.3", "@babel/preset-typescript": "^7.23.3", "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "^2.27.8", - "@manypkg/cli": "^0.21.4", - "@playwright/test": "^1.43.1", + "@manypkg/cli": "^0.25.1", + "@playwright/test": "^1.57.0", "@preconstruct/cli": "^2.8.2", "@testing-library/jest-dom": "^6.4.2", "@types/jest": "^29.5.12", diff --git a/packages/compiler/src/compiler.ts b/packages/compiler/src/compiler.ts index 31f2a0fef..0b1450890 100644 --- a/packages/compiler/src/compiler.ts +++ b/packages/compiler/src/compiler.ts @@ -239,6 +239,7 @@ export interface Compiler { outputCss?: boolean; }, ): Promise<{ source: string; watchFiles: Set }>; + unstable_invalidateAllModules(): Promise; getCssForFile(virtualCssFilePath: string): { filePath: string; css: string }; close(): Promise; getAllCss(): string; @@ -258,7 +259,17 @@ export interface CreateCompilerOptions { * @default true */ enableFileWatcher?: boolean; - cssImportSpecifier?: (filePath: string) => string; + cssImportSpecifier?: ( + filePath: string, + css: string, + ) => string | Promise; + /** + * When true, generates one CSS import per rule instead of one per file. + * This can help bundlers like Turbopack deduplicate shared CSS more effectively. + * + * @default false + */ + unstable_splitCssPerRule?: boolean; identifiers?: IdentifierOption; viteConfig?: ViteUserConfig; /** @deprecated */ @@ -270,6 +281,7 @@ export const createCompiler = ({ root, identifiers = 'debug', cssImportSpecifier = (filePath) => filePath + '.vanilla.css', + unstable_splitCssPerRule: splitCssPerRule = false, viteConfig, enableFileWatcher, viteResolve, @@ -298,7 +310,7 @@ export const createCompiler = ({ } >(); - const cssCache = new NormalizedMap<{ css: string }>(root); + const cssCache = new NormalizedMap<{ css: string; cssRules: string[] }>(root); const classRegistrationsByModuleId = new NormalizedMap<{ localClassNames: Set; composedClassLists: Array; @@ -428,17 +440,20 @@ export const createCompiler = ({ } if (cssObjs) { - let css = ''; + let cssRules: string[] = []; if (cssObjs.length > 0) { - css = transformCss({ + cssRules = transformCss({ localClassNames: Array.from(localClassNames), composedClassLists: orderedComposedClassLists, cssObjs, - }).join('\n'); + }); } - cssCache.set(cssDepModuleId, { css }); + cssCache.set(cssDepModuleId, { + css: cssRules.join('\n'), + cssRules, + }); } else if (cachedClassRegistrations) { cachedClassRegistrations.localClassNames.forEach( (localClassName) => { @@ -450,10 +465,23 @@ export const createCompiler = ({ ); } - if (cssObjs || cachedCss?.css) { - cssImports.push( - `import '${cssImportSpecifier(cssDepModuleId)}';`, - ); + const { css = '', cssRules = [] } = + cssCache.get(cssDepModuleId) ?? {}; + + if (cssObjs || css) { + if (splitCssPerRule) { + const importSpecifiers = await Promise.all( + cssRules.map((rule, i) => + cssImportSpecifier(cssDepModuleId + `#${i}`, rule), + ), + ); + for (const specifier of importSpecifiers) { + cssImports.push(`import '${specifier}';`); + } + } else { + const specifier = await cssImportSpecifier(cssDepModuleId, css); + cssImports.push(`import '${specifier}';`); + } } } @@ -481,6 +509,21 @@ export const createCompiler = ({ return result; }, + async unstable_invalidateAllModules() { + const { server, runner } = await vitePromise; + + for (const [key] of runner.moduleCache.entries()) { + if (!key.includes('node_modules')) { + runner.moduleCache.delete(key); + } + } + + for (const [id, moduleNode] of server.moduleGraph.idToModuleMap) { + if (!id.includes('node_modules')) { + server.moduleGraph.invalidateModule(moduleNode); + } + } + }, getCssForFile(filePath: string) { filePath = isAbsolute(filePath) ? filePath : join(root, filePath); const moduleId = normalizePath(filePath); diff --git a/packages/css/package.json b/packages/css/package.json index 8a0c6fca9..5a89f7e4b 100644 --- a/packages/css/package.json +++ b/packages/css/package.json @@ -12,6 +12,7 @@ }, "exports": { "./package.json": "./package.json", + "./vanilla.virtual.css?*": "./vanilla.virtual.css?*", ".": { "types": "./dist/vanilla-extract-css.cjs.d.ts", "browser": { @@ -106,7 +107,8 @@ "/transformCss", "/fileScope", "/injectStyles", - "/disableRuntimeStyles" + "/disableRuntimeStyles", + "vanilla.virtual.css" ], "repository": { "type": "git", diff --git a/packages/css/vanilla.virtual.css b/packages/css/vanilla.virtual.css new file mode 100644 index 000000000..fdb526ecf --- /dev/null +++ b/packages/css/vanilla.virtual.css @@ -0,0 +1,10 @@ +/* + +This is a noop file for extracted CSS source to point to. + +Some loaders, like Webpack and Turbopack, require a file to exist on disk for virtual source files. + +For turbopack specifically, this reference file must be resolvable from any context where css is imported +even if the next plugin itself isn't available (for example, in a monorepo). + +*/ diff --git a/packages/next-plugin/package.json b/packages/next-plugin/package.json index 75eebccf3..f4aaba5c1 100644 --- a/packages/next-plugin/package.json +++ b/packages/next-plugin/package.json @@ -21,12 +21,15 @@ "author": "SEEK", "license": "MIT", "dependencies": { - "@vanilla-extract/webpack-plugin": "workspace:^" + "@vanilla-extract/turbopack-plugin": "workspace:^", + "@vanilla-extract/webpack-plugin": "workspace:^", + "semver": "^7.6.3" }, "peerDependencies": { "next": ">=12.1.7" }, "devDependencies": { + "@types/semver": "^7.7.1", "next": "12.3.4", "webpack": "^5.90.0" } diff --git a/packages/next-plugin/src/index.ts b/packages/next-plugin/src/index.ts index 56f0ff677..2cb94c939 100644 --- a/packages/next-plugin/src/index.ts +++ b/packages/next-plugin/src/index.ts @@ -12,10 +12,24 @@ import type { WebpackConfigContext, } from 'next/dist/server/config-shared'; import { createRequire } from 'node:module'; +import * as path from 'node:path'; +import type { TurboLoaderOptions } from '@vanilla-extract/turbopack-plugin'; +import semver from 'semver'; const require = createRequire(import.meta.url); -type PluginOptions = ConstructorParameters[0]; +type PluginOptions = ConstructorParameters[0] & { + unstable_turbopack?: { + glob?: string[]; + /** + * controls whether we attempt to configure turbopack + * auto: enable only when Next >= 16.0.0 + * on: force enable regardless of detected Next version + * off: never configure turbopack, webpack only + */ + mode?: 'auto' | 'on' | 'off'; + }; +}; const NextMiniCssExtractPlugin = NextMiniCssExtractPluginDefault as any; @@ -135,94 +149,174 @@ const getVanillaExtractCssLoaders = ( export const createVanillaExtractPlugin = ( pluginOptions: PluginOptions = {}, ) => { - return (nextConfig: NextConfig = {}): NextConfig => ({ - ...nextConfig, - webpack(config: any, options: WebpackConfigContext) { - const { dir, dev, config: resolvedNextConfig } = options; - - // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/index.ts#L336 - // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/webpack-config.ts#L626 - // https://github.com/vercel/next.js/pull/43916 - // on Next.js 12, findPagesDirResult is a string. on Next.js 13, findPagesDirResult is an object - const findPagesDirResult = findPagesDir( - dir, - resolvedNextConfig.experimental?.appDir ?? false, + return (nextConfig: NextConfig = {}): NextConfig => { + const { + unstable_turbopack: turbopackOptions = {}, + ...webpackPluginOptions + } = pluginOptions; + const { + mode: turbopackMode = 'auto', + glob: turbopackGlob = ['**/*.css.{js,cjs,mjs,jsx,ts,tsx}'], + } = turbopackOptions; + // detect Next version and decide whether to configure turbopack + const nextVersion = (() => { + try { + // resolve from the consumer app's cwd, not this package + const requireFromCwd = createRequire( + path.join(process.cwd(), 'package.json'), + ); + const pkg = requireFromCwd('next/package.json') as { version?: string }; + return pkg?.version ?? null; + } catch { + return null; + } + })(); + const coerced = nextVersion ? semver.coerce(nextVersion) : null; + const supportsTurbopackRules = !!coerced && semver.gte(coerced, '16.0.0'); + const enableTurbopack = + turbopackMode === 'on' || + (turbopackMode === 'auto' && supportsTurbopackRules); + + if (turbopackMode === 'on' && !supportsTurbopackRules) { + console.warn( + `[@vanilla-extract/next-plugin] Turbopack is configured but does not seem supported. Expected Next.js >= 16.0.0, got ${nextVersion}`, ); - // Skip nextConfig check since appDir is stable feature after Next.js 13.4 - const hasAppDir = !!(findPagesDirResult && findPagesDirResult.appDir); - - const outputCss = true; - - // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/helpers.ts#L12-L21 - const cssRules = config.module.rules.find( - (rule: any) => - Array.isArray(rule.oneOf) && - rule.oneOf.some( - ({ test }: any) => - typeof test === 'object' && - typeof test.test === 'function' && - test.test('filename.css'), - ), - ).oneOf; - - // https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L187-L190 - cssRules.unshift({ - test: /vanilla\.virtual\.css/i, - sideEffects: true, - use: getVanillaExtractCssLoaders( - options, - resolvedNextConfig.assetPrefix, - hasAppDir, + } + + let turbopack: typeof nextConfig.turbopack; + if (enableTurbopack) { + turbopack = { ...(nextConfig.turbopack || {}) }; + + if (turbopackGlob.some((glob) => turbopack.rules?.[glob])) { + throw new Error( + 'Vanilla extract could not be applied automatically due to conflicting turbopack rules', + ); + } + + const vanillaExtractRule = { + as: '*.js', + loaders: [ + { + loader: require.resolve('@vanilla-extract/turbopack-plugin'), + options: { + nextEnv: nextConfig.env ?? null, + outputCss: pluginOptions.outputCss ?? null, + identifiers: pluginOptions.identifiers ?? null, + } satisfies TurboLoaderOptions, + }, + ], + } as const; + + const vanillaExtractCssRule = { + as: '*.css', + loaders: [require.resolve('@vanilla-extract/turbopack-plugin')], + } as const; + + turbopack.rules = { + ...(turbopack.rules || {}), + ...Object.fromEntries( + turbopackGlob.map((glob) => [glob, vanillaExtractRule]), ), - }); + 'vanilla.virtual.css': vanillaExtractCssRule, + }; + } + + const baseConfig: NextConfig = { + ...nextConfig, + webpack(config: any, options: WebpackConfigContext) { + const { dir, dev, config: resolvedNextConfig } = options; + + // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/index.ts#L336 + // https://github.com/vercel/next.js/blob/1fb4cad2a8329811b5ccde47217b4a6ae739124e/packages/next/build/webpack-config.ts#L626 + // https://github.com/vercel/next.js/pull/43916 + // on Next.js 12, findPagesDirResult is a string. on Next.js 13, findPagesDirResult is an object + const findPagesDirResult = findPagesDir( + dir, + resolvedNextConfig.experimental?.appDir ?? false, + ); + // Skip nextConfig check since appDir is stable feature after Next.js 13.4 + const hasAppDir = !!(findPagesDirResult && findPagesDirResult.appDir); + + const outputCss = true; + + // https://github.com/vercel/next.js/blob/6e5b935fd7a61497f6854a81aec7df3a5dbf61ac/packages/next/src/build/webpack/config/helpers.ts#L12-L21 + const cssRules = config.module.rules.find( + (rule: any) => + Array.isArray(rule.oneOf) && + rule.oneOf.some( + ({ test }: any) => + typeof test === 'object' && + typeof test.test === 'function' && + test.test('filename.css'), + ), + ).oneOf; + + // https://github.com/SukkaW/style9-webpack/blob/f51c46bbcd95ea3b988d3559c3b35cc056874366/src/next-appdir/index.ts#L187-L190 + cssRules.unshift({ + test: /vanilla\.virtual\.css/i, + sideEffects: true, + use: getVanillaExtractCssLoaders( + options, + resolvedNextConfig.assetPrefix, + hasAppDir, + ), + }); - // vanilla-extract need to emit the css file on both server and client, both during the - // development and production. - // However, Next.js only add MiniCssExtractPlugin on pages dir + client build + production mode. - // - // To simplify the logic at our side, we will add MiniCssExtractPlugin based on - // the "instanceof" check (We will only add our required MiniCssExtractPlugin if - // Next.js hasn't added it yet). - // This also prevent multiple MiniCssExtractPlugin being added (which will cause - // RealContentHashPlugin to panic) - if ( - !config.plugins.some((p: any) => p instanceof NextMiniCssExtractPlugin) - ) { - // HMR reloads the CSS file when the content changes but does not use - // the new file name, which means it can't contain a hash. - const filename = dev - ? 'static/css/[name].css' - : 'static/css/[contenthash].css'; + // vanilla-extract need to emit the css file on both server and client, both during the + // development and production. + // However, Next.js only add MiniCssExtractPlugin on pages dir + client build + production mode. + // + // To simplify the logic at our side, we will add MiniCssExtractPlugin based on + // the "instanceof" check (We will only add our required MiniCssExtractPlugin if + // Next.js hasn't added it yet). + // This also prevent multiple MiniCssExtractPlugin being added (which will cause + // RealContentHashPlugin to panic) + if ( + !config.plugins.some( + (p: any) => p instanceof NextMiniCssExtractPlugin, + ) + ) { + // HMR reloads the CSS file when the content changes but does not use + // the new file name, which means it can't contain a hash. + const filename = dev + ? 'static/css/[name].css' + : 'static/css/[contenthash].css'; + + config.plugins.push( + new NextMiniCssExtractPlugin({ + filename, + chunkFilename: filename, + // Next.js guarantees that CSS order "doesn't matter", due to imposed + // restrictions: + // 1. Global CSS can only be defined in a single entrypoint (_app) + // 2. CSS Modules generate scoped class names by default and cannot + // include Global CSS (:global() selector). + // + // While not a perfect guarantee (e.g. liberal use of `:global()` + // selector), this assumption is required to code-split CSS. + // + // If this warning were to trigger, it'd be unactionable by the user, + // but likely not valid -- so just disable it. + ignoreOrder: true, + }), + ); + } config.plugins.push( - new NextMiniCssExtractPlugin({ - filename, - chunkFilename: filename, - // Next.js guarantees that CSS order "doesn't matter", due to imposed - // restrictions: - // 1. Global CSS can only be defined in a single entrypoint (_app) - // 2. CSS Modules generate scoped class names by default and cannot - // include Global CSS (:global() selector). - // - // While not a perfect guarantee (e.g. liberal use of `:global()` - // selector), this assumption is required to code-split CSS. - // - // If this warning were to trigger, it'd be unactionable by the user, - // but likely not valid -- so just disable it. - ignoreOrder: true, - }), + new VanillaExtractPlugin({ outputCss, ...webpackPluginOptions }), ); - } - config.plugins.push( - new VanillaExtractPlugin({ outputCss, ...pluginOptions }), - ); + if (typeof nextConfig.webpack === 'function') { + return nextConfig.webpack(config, options); + } - if (typeof nextConfig.webpack === 'function') { - return nextConfig.webpack(config, options); - } + return config; + }, + }; - return config; - }, - }); + if (enableTurbopack && turbopack) { + return { ...baseConfig, turbopack } as NextConfig; + } + return baseConfig; + }; }; diff --git a/packages/turbopack-plugin/package.json b/packages/turbopack-plugin/package.json new file mode 100644 index 000000000..148691646 --- /dev/null +++ b/packages/turbopack-plugin/package.json @@ -0,0 +1,35 @@ +{ + "name": "@vanilla-extract/turbopack-plugin", + "version": "0.0.0", + "description": "Turbopack loader for vanilla-extract", + "main": "dist/vanilla-extract-turbopack-plugin.cjs.js", + "module": "dist/vanilla-extract-turbopack-plugin.esm.js", + "types": "dist/vanilla-extract-turbopack-plugin.cjs.d.ts", + "preconstruct": { + "entrypoints": [ + "index.ts" + ] + }, + "files": [ + "/dist" + ], + "repository": { + "type": "git", + "url": "https://github.com/vanilla-extract-css/vanilla-extract.git", + "directory": "packages/turbopack-plugin" + }, + "author": "SEEK", + "license": "MIT", + "dependencies": { + "@swc/core": "^1.13.5", + "@vanilla-extract/compiler": "workspace:^", + "@vanilla-extract/integration": "workspace:^" + }, + "devDependencies": { + "next": "12.3.4", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependencies": { + "next": ">=12.1.7" + } +} diff --git a/packages/turbopack-plugin/src/index.test.ts b/packages/turbopack-plugin/src/index.test.ts new file mode 100644 index 000000000..40fe4590b --- /dev/null +++ b/packages/turbopack-plugin/src/index.test.ts @@ -0,0 +1,145 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { deserializeCss } from '@vanilla-extract/integration'; +import turbopackVanillaExtractLoader, { + type TurboLoaderContext, + type TurboLoaderOptions, + cleanupSharedCompiler, +} from './index'; + +const testDir = path.join(process.cwd(), 'fixtures/next-16-app-pages-router'); + +// for CI testing, 10 iterations is fine +// for local testing, issues can be *very* rare since this is a race condition +// for most of my testing I used 1000 iterations +const iterations = 10; +const timeout = iterations * 250; + +describe('turbopack-plugin stress test', () => { + afterEach(() => { + cleanupSharedCompiler(); + }); + + it( + 'should handle rapid entry updates correctly', + async () => { + const mockContext: TurboLoaderContext = { + rootContext: testDir, + resourcePath: path.join(testDir, 'style.css.ts'), + getOptions: () => ({ + identifiers: 'short', + outputCss: true, + nextEnv: {}, + }), + getResolve: () => async (context: string, request: string) => { + // Simplified resolver that just returns the request if it's relative, + // or null if we can't handle it. For this test, we don't need much. + if (request.startsWith('.')) { + return path.resolve(context, request); + } + return request; + }, + fs: { + readFile: fs.readFile, + }, + }; + + for (let i = 0; i < iterations; i++) { + const uniqueId = crypto.randomUUID(); + const fileContent = ` + import { style } from '@vanilla-extract/css'; + + export const myStyle = style({ + content: "${uniqueId}" + }); + `; + + fs.writeFileSync(mockContext.resourcePath, fileContent); + + const result = await turbopackVanillaExtractLoader.call(mockContext); + + expect(result).toContain( + '@vanilla-extract/css/vanilla.virtual.css?ve-css=', + ); + const match = result.match( + /import '@vanilla-extract\/css\/vanilla\.virtual\.css\?ve-css=([^']+)';/, + ); + expect(match).toBeTruthy(); + + if (match) { + const encodedCss = decodeURIComponent(match[1]); + const decodedCss = await deserializeCss(encodedCss); + expect(decodedCss).toContain(`content: "${uniqueId}"`); + } + } + + fs.rmSync(mockContext.resourcePath); + }, + timeout, + ); + + it( + 'should handle rapid dependency updates correctly', + async () => { + const mockContext: TurboLoaderContext = { + rootContext: testDir, + resourcePath: path.join(testDir, 'style.css.ts'), + getOptions: () => ({ + identifiers: 'short', + outputCss: true, + nextEnv: {}, + }), + getResolve: () => async (context: string, request: string) => { + // Simplified resolver that just returns the request if it's relative, + // or null if we can't handle it. For this test, we don't need much. + if (request.startsWith('.')) { + return path.resolve(context, request); + } + return request; + }, + fs: { + readFile: fs.readFile, + }, + }; + + for (let i = 0; i < iterations; i++) { + const uniqueId = crypto.randomUUID(); + const fileDependency = ` + export const randomId = "${uniqueId}"; + `; + const fileContent = ` + import { style } from '@vanilla-extract/css'; + import { randomId } from './dependency.ts'; + + export const myStyle = style({ + content: randomId + }); + `; + + fs.writeFileSync(path.join(testDir, 'dependency.ts'), fileDependency); + if (i === 0) + fs.writeFileSync(path.join(testDir, 'style.css.ts'), fileContent); + + const result = await turbopackVanillaExtractLoader.call(mockContext); + + expect(result).toContain( + '@vanilla-extract/css/vanilla.virtual.css?ve-css=', + ); + const match = result.match( + /import '@vanilla-extract\/css\/vanilla\.virtual\.css\?ve-css=([^']+)';/, + ); + expect(match).toBeTruthy(); + + if (match) { + const encodedCss = decodeURIComponent(match[1]); + const decodedCss = await deserializeCss(encodedCss); + expect(decodedCss).toContain(`content: "${uniqueId}"`); + } + } + + fs.rmSync(path.join(testDir, 'dependency.ts')); + fs.rmSync(mockContext.resourcePath); + }, + timeout, + ); +}); diff --git a/packages/turbopack-plugin/src/index.ts b/packages/turbopack-plugin/src/index.ts new file mode 100644 index 000000000..17091002d --- /dev/null +++ b/packages/turbopack-plugin/src/index.ts @@ -0,0 +1,219 @@ +import { + createCompiler, + type Compiler as VeCompiler, +} from '@vanilla-extract/compiler'; +import { + deserializeCss, + serializeCss, + type IdentifierOption, +} from '@vanilla-extract/integration'; +import * as path from 'node:path'; +import { createNextFontVePlugin } from './next-font/plugin'; +import type fs from 'node:fs'; +import { injectFontImports } from './next-font/inject'; + +export type TurboLoaderContext = { + getOptions: { + (): OptionsType; + }; + getResolve: (options: unknown) => { + (context: string, request: string): Promise; + }; + + fs: { + readFile: typeof fs.readFile; + }; + + rootContext: string; + resourcePath: string; + resourceQuery?: string; +}; + +export type TurboLoaderOptions = { + identifiers: IdentifierOption | null; + outputCss: boolean | null; + nextEnv: Record | null; +}; + +let sharedCompiler: VeCompiler | null = null; + +/** + * reset the global state, used in tests to cleanup the compiler + */ +export const cleanupSharedCompiler = () => { + if (sharedCompiler) { + sharedCompiler.close(); + sharedCompiler = null; + } +}; + +const getOrMakeCompiler = async ({ + identifiers, + nextEnv, + loaderContext, +}: { + identifiers: IdentifierOption; + nextEnv: Record | null; + loaderContext: TurboLoaderContext; +}): Promise => { + if (sharedCompiler) return sharedCompiler; + + const defineEnv: Record = {}; + for (const [key, value] of Object.entries(nextEnv ?? {})) { + defineEnv[`process.env.${key}`] = JSON.stringify(value); + } + + sharedCompiler = createCompiler({ + root: loaderContext.rootContext, + identifiers, + enableFileWatcher: false, + unstable_splitCssPerRule: true, + cssImportSpecifier: async (_filePath, css) => { + return `@vanilla-extract/css/vanilla.virtual.css?ve-css=${encodeURIComponent( + await serializeCss(css), + )}`; + }, + viteConfig: { + define: defineEnv, + plugins: [ + createNextFontVePlugin(), + { + // route vite file reads through turbopack's fs to handle dependency tracking automatically + name: 'vanilla-extract-turbo-fs', + enforce: 'pre', + async load(id: string) { + return new Promise((resolve, reject) => { + // we can reuse this fs instance across all loader calls + // turbopack will associate dependencies to the file currently being loaded + loaderContext.fs.readFile(id, (error, data) => { + if (error) { + reject(error); + } else if (typeof data === 'string') { + resolve({ code: data }); + } else resolve(null); + }); + }); + }, + }, + { + name: 'vanilla-extract-next-image', + enforce: 'pre', + async resolveId(source: string, importer: string | undefined) { + if (!importer) return null; + + if ( + source.endsWith('.png') || + source.endsWith('.svg') || + source.endsWith('.jpg') || + source.endsWith('.jpeg') || + source.endsWith('.gif') || + source.endsWith('.webp') || + source.endsWith('.avif') || + source.endsWith('.ico') || + source.endsWith('.bmp') + ) { + const sourceImage = path.isAbsolute(source) + ? path.join(loaderContext.rootContext, source) + : path.join(path.dirname(importer), source); + + // since we'll be using the image in our final css file, we must craft an import path that will resolve to the image file from the css file + const referenceFile = require.resolve( + '@vanilla-extract/css/vanilla.virtual.css?ve-css=unknown', + { paths: [importer] }, + ); + const relativeImport = path.relative( + path.dirname(referenceFile), + sourceImage, + ); + + // determine the dimensions of the image + const imageAsBuffer = new Promise((resolve, reject) => { + loaderContext.fs.readFile(sourceImage, (error, data) => { + if (error) reject(error); + resolve(data); + }); + }); + const { getImageSize } = await import( + 'next/dist/server/image-optimizer.js' + ); + const imageSize: { width?: number; height?: number } = + // @ts-expect-error - next.js version mismatch loads next 12 types but uses next 16 code + await getImageSize(await imageAsBuffer).catch((error) => { + const message = `Process image "${sourceImage}" failed: ${error}`; + throw new Error(message); + }); + + const moduleContent = `export default { + src: '${relativeImport}', + height: ${imageSize.height}, + width: ${imageSize.width}, + blurDataURL: undefined, + blurWidth: undefined, + blurHeight: undefined, + }`; + + return ( + 'data:text/javascript;base64,' + + Buffer.from(moduleContent).toString('base64') + ); + } + + return null; + }, + }, + { + // avoid module resolution errors by letting turbopack resolve our modules for us + name: 'vanilla-extract-turbo-resolve', + // do NOT enforce pre as it breaks builds on some projects (not sure why) + async resolveId(source: string, importer: string | undefined) { + if (source.startsWith('/')) return null; // turbopack doesn't support server relative imports + if (!importer) return null; + + // react is vendored by next, so we need to use the upstream version to avoid errors + if (source === 'react' || source === 'react-dom') { + return null; + } + + const resolver = loaderContext.getResolve({}); + return resolver(path.dirname(importer), source); + }, + }, + ], + }, + }); + + return sharedCompiler; +}; + +export default async function turbopackVanillaExtractLoader( + this: TurboLoaderContext, +) { + // Check if this is a CSS request via query param + if (this.resourceQuery?.startsWith('?ve-css=')) { + const encodedCss = this.resourceQuery.slice(8); + return await deserializeCss(decodeURIComponent(encodedCss)); + } + + const options = this.getOptions() as TurboLoaderOptions; + const identifiers = + options.identifiers ?? + (process.env.NODE_ENV === 'production' ? 'short' : 'debug'); + const outputCss = options.outputCss ?? true; + + const compiler = await getOrMakeCompiler({ + identifiers, + nextEnv: options.nextEnv, + loaderContext: this, + }); + + // if turbopack invokes the loader quickly, vite can't invalidate the module fast enough + // so we disable the internal file watcher and manually invalidate the module instead + await compiler.unstable_invalidateAllModules(); + + const { source, watchFiles } = await compiler.processVanillaFile( + this.resourcePath, + { outputCss }, + ); + + return await injectFontImports(source, watchFiles, this); +} diff --git a/packages/turbopack-plugin/src/next-font/inject.ts b/packages/turbopack-plugin/src/next-font/inject.ts new file mode 100644 index 000000000..cc85b210e --- /dev/null +++ b/packages/turbopack-plugin/src/next-font/inject.ts @@ -0,0 +1,47 @@ +import path from 'node:path'; +import { promisify } from 'node:util'; +import type { TurboLoaderContext, TurboLoaderOptions } from '../index'; + +/** + * we need to ensure that any next/font/google or next/font/local imports + * are preserved in the output code, even if they are only used in CSS + * + * this is because next needs to see these imports to generate the font files + */ +export async function injectFontImports( + source: string, + watchFiles: Set, + loaderContext: TurboLoaderContext, +): Promise { + const readFile = promisify(loaderContext.fs.readFile); + const importsToInject: string[] = []; + + await Promise.all( + Array.from(watchFiles).map(async (file) => { + if (file.includes('node_modules')) return; + if (file === loaderContext.resourcePath) return; + if (!/\.(m|c)?(js|ts)x?$/.test(file)) return; + + const content = String(await readFile(file).catch(() => null)); + if (/from\s+['"]next\/font\/(google|local)['"]/.test(content)) { + let relativeImport = path.relative( + path.dirname(loaderContext.resourcePath), + file, + ); + + if (!relativeImport.startsWith('.')) + relativeImport = `./${relativeImport}`; + + importsToInject.push(relativeImport); + } + }), + ); + + if (importsToInject.length > 0) { + return `${importsToInject + .map((importPath) => `import '${importPath}';`) + .join('\n')}\n${source}`; + } + + return source; +} diff --git a/packages/turbopack-plugin/src/next-font/plugin.ts b/packages/turbopack-plugin/src/next-font/plugin.ts new file mode 100644 index 000000000..93dedeb4c --- /dev/null +++ b/packages/turbopack-plugin/src/next-font/plugin.ts @@ -0,0 +1,16 @@ +import { transformNextFont } from './transform'; +import type { Plugin } from 'vite'; + +export function createNextFontVePlugin(): Plugin { + return { + name: 've-next-font-stub', + enforce: 'pre', + async transform(code: string, id: string) { + if (!/\.(m|c)?(js|ts)x?$/.test(id) || !code.includes('next/font')) { + return null; + } + + return await transformNextFont(code, id); + }, + }; +} diff --git a/packages/turbopack-plugin/src/next-font/transform.ts b/packages/turbopack-plugin/src/next-font/transform.ts new file mode 100644 index 000000000..9074269eb --- /dev/null +++ b/packages/turbopack-plugin/src/next-font/transform.ts @@ -0,0 +1,299 @@ +import * as swc from '@swc/core'; +import type { Argument, Expression, VariableDeclarator } from '@swc/core'; + +export type NextFontTransformResult = { + code: string; + map: string | null; +}; + +const THROW_MSG = + "next/font class names are generated by Turbopack and aren't available during vanilla-extract evaluation. Use style.* in VE files, and apply the real font's className/variable in runtime code."; + +const GENERIC_FAMILIES = new Set([ + 'serif', + 'sans-serif', + 'monospace', + 'cursive', + 'fantasy', + 'system-ui', + 'ui-serif', + 'ui-sans-serif', + 'ui-monospace', + 'ui-rounded', + 'emoji', + 'math', + 'fangsong', +]); + +// --- Helpers --- + +function formatFontFamily(name: string): string { + const clean = name.replace(/['\"]/g, ''); + return GENERIC_FAMILIES.has(clean.toLowerCase()) ? clean : `'${clean}'`; +} + +function getFontFamily( + baseName: string, + fallbacks: string[] | undefined, + isLocal: boolean, +): string { + const parts = [formatFontFamily(baseName)]; + + // Local fonts always get a generated fallback. Google fonts get it if no user fallbacks. + // Original logic: + // Local: [Name, Name Fallback, ...UserFallbacks] + // Google: [Name, ...UserFallbacks] OR [Name, Name Fallback] + const hasUserFallbacks = fallbacks && fallbacks.length > 0; + + if (isLocal || !hasUserFallbacks) { + parts.push(formatFontFamily(`${baseName} Fallback`)); + } + + if (hasUserFallbacks) { + parts.push(...fallbacks); + } + + return parts.join(', '); +} + +function parseWeight(weight: unknown): number | undefined { + if (typeof weight === 'number') return weight; + if (typeof weight === 'string' && weight && !weight.includes(' ')) { + const n = Number(weight); + if (!Number.isNaN(n)) return n; + } + return undefined; +} + +function parseStyle(style: unknown, isGoogle: boolean): string | undefined { + if (Array.isArray(style)) return undefined; + if (typeof style === 'string' && style && !style.includes(' ')) return style; + return isGoogle ? 'normal' : undefined; +} + +// --- AST Utilities --- + +type FontOptions = { + src?: unknown; + weight?: unknown; + style?: unknown; + fallback?: string[]; +}; + +/** + * Extract simple values from AST nodes (literals, arrays of literals). + * Returns `undefined` if too complex. + */ +function unwrapValue(node: Expression | undefined): unknown { + if (!node) return undefined; + + // Handle basic literals + if (node.type === 'StringLiteral' || node.type === 'NumericLiteral') { + return node.value; + } + + // Handle arrays + if (node.type === 'ArrayExpression') { + return node.elements + .map((el) => unwrapValue(el?.expression)) + .filter((v) => v !== undefined); + } + + return undefined; +} + +/** + * Extracts the configuration object from the first argument of a call. + */ +function extractFontOptions(args: Argument[]): FontOptions { + const options: FontOptions = {}; + const configNode = args[0]?.expression; + + if (configNode?.type !== 'ObjectExpression') { + return options; + } + + for (const prop of configNode.properties) { + if (prop.type !== 'KeyValueProperty') continue; + + const keyNode = prop.key; + if (keyNode.type !== 'Identifier' && keyNode.type !== 'StringLiteral') + continue; + const key = keyNode.value; + const value = unwrapValue(prop.value); + + if (key === 'src') options.src = value; + if (key === 'weight') options.weight = value; + if (key === 'style') options.style = value; + if (key === 'fallback') { + if ( + !Array.isArray(value) || + !value.every((v): v is string => typeof v === 'string') + ) { + throw new Error( + `[vanilla-extract/turbopack-plugin] next/font: 'fallback' must be an array of strings, got: ${JSON.stringify( + value, + )}`, + ); + } + options.fallback = value; + } + } + + return options; +} + +async function createStubNode( + family: string, + weight: number | undefined, + style: string | undefined, +): Promise { + const styleObj = [ + `fontFamily: ${JSON.stringify(family)}`, + weight !== undefined ? `fontWeight: ${weight}` : null, + style !== undefined ? `fontStyle: ${JSON.stringify(style)}` : null, + ] + .filter(Boolean) + .join(', '); + + const stubSource = `({ + get className() { throw new Error(${JSON.stringify(THROW_MSG)}); }, + get variable() { throw new Error(${JSON.stringify(THROW_MSG)}); }, + style: { ${styleObj} } + })`; + + // Parse this tiny snippet to get an Expression node + const m = await swc.parse(stubSource, { syntax: 'ecmascript' }); + const stmt = m.body[0]; + if (stmt?.type !== 'ExpressionStatement') { + throw new Error( + '[vanilla-extract/turbopack-plugin] Internal error: stub source did not produce an ExpressionStatement', + ); + } + return stmt.expression; +} + +async function processDeclarator( + decl: VariableDeclarator, + imports: Map, +): Promise { + if (!decl.init || decl.init.type !== 'CallExpression') return; + + const callee = decl.init.callee; + if (callee.type !== 'Identifier') return; + + const fontDef = imports.get(callee.value); + if (!fontDef) return; + + const args = decl.init.arguments || []; + const opts = extractFontOptions(args); + const varName = decl.id.type === 'Identifier' ? decl.id.value : 'font'; + + const isGoogle = fontDef.type === 'google'; + const familyName = isGoogle ? fontDef.name : varName; + + const family = getFontFamily(familyName, opts.fallback, !isGoogle); + let weight = parseWeight(opts.weight); + let style = parseStyle(opts.style, isGoogle); + + // Local fonts only stub weight/style if src is a simple string + if (!isGoogle && typeof opts.src !== 'string') { + weight = undefined; + style = undefined; + } + + return createStubNode(family, weight, style); +} + +// --- Main Transform --- + +export async function transformNextFont( + code: string, + filename: string, +): Promise { + // 1. Parse + const isTs = /\.(?:[cm]?ts|tsx)$/.test(filename); + const isTsx = /\.tsx$/.test(filename); + const isJsx = /\.jsx$/.test(filename); + + const module = await swc.parse(code, { + syntax: isTs ? 'typescript' : 'ecmascript', + tsx: isTsx, + jsx: isJsx, + dynamicImport: true, + decorators: false, + target: 'esnext', + comments: false, + script: false, + }); + + const imports = new Map(); + let changed = false; + + // 2. Scan imports & filter body + const newBody = []; + + for (const item of module.body) { + if (item.type === 'ImportDeclaration') { + const source = item.source.value; + if (source === 'next/font/local') { + item.specifiers.forEach((s) => { + if (s.type === 'ImportDefaultSpecifier') { + imports.set(s.local.value, { type: 'local', name: 'local' }); + } + }); + changed = true; + continue; // Remove import + } + if (source === 'next/font/google') { + item.specifiers.forEach((s) => { + if (s.type === 'ImportSpecifier') { + const local = s.local.value; + const imported = s.imported?.value || local; + imports.set(local, { + type: 'google', + name: imported.replace(/_/g, ' '), + }); + } + }); + changed = true; + continue; // Remove import + } + } + newBody.push(item); + } + + const usedNextFont = changed; + if (!usedNextFont) { + return { code, map: null }; + } + + // 3. Transform Declarations + for (const item of newBody) { + if (item.type === 'VariableDeclaration') { + for (const decl of item.declarations) { + const stubNode = await processDeclarator(decl, imports); + if (stubNode) decl.init = stubNode; + } + } else if ( + item.type === 'ExportDeclaration' && + item.declaration.type === 'VariableDeclaration' + ) { + for (const decl of item.declaration.declarations) { + const stubNode = await processDeclarator(decl, imports); + if (stubNode) decl.init = stubNode; + } + } + } + + // 4. Generate Code + const { code: outputCode, map } = await swc.print( + { ...module, body: newBody }, + { minify: false, sourceMaps: true }, + ); + + return { + code: outputCode, + map: map || null, + }; +} diff --git a/playwright.config.ts b/playwright.config.ts index 7b00ff93d..ceb1a6cfa 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,10 +1,12 @@ -import { PlaywrightTestConfig, defineConfig } from '@playwright/test'; +import { type PlaywrightTestConfig, defineConfig } from '@playwright/test'; import { cpus } from 'os'; +import { NEXT_SERVERS } from './tests/servers'; // Prevent Vite from attempting to clear the screen process.stdout.isTTY = false; const config: PlaywrightTestConfig = defineConfig({ + fullyParallel: true, testMatch: '**/*.playwright.ts', updateSnapshots: 'none', expect: { @@ -13,8 +15,16 @@ const config: PlaywrightTestConfig = defineConfig({ maxDiffPixelRatio: 0.02, }, }, + webServer: NEXT_SERVERS.map((server) => ({ + command: server.script + ` --port ${server.port}`, + env: { NODE_ENV: server.isProduction ? 'production' : 'development' }, + url: `http://localhost:${server.port}`, + reuseExistingServer: !process.env.CI, + name: server.name, + })), workers: process.env.CI ? cpus().length : undefined, retries: process.env.CI ? 2 : 0, + timeout: 120_000, forbidOnly: !!process.env.CI, snapshotDir: 'tests/e2e/snapshots', // put all snapshots in one directory diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6167dcd75..dfa98996c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,7 +7,7 @@ settings: importers: .: - dependencies: + devDependencies: '@babel/core': specifier: ^7.23.9 version: 7.23.9 @@ -27,17 +27,17 @@ importers: specifier: ^2.27.8 version: 2.27.8 '@manypkg/cli': - specifier: ^0.21.4 - version: 0.21.4 + specifier: ^0.25.1 + version: 0.25.1 '@playwright/test': - specifier: ^1.43.1 - version: 1.43.1 + specifier: ^1.57.0 + version: 1.57.0 '@preconstruct/cli': specifier: ^2.8.2 version: 2.8.2 '@testing-library/jest-dom': specifier: ^6.4.2 - version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)))(vitest@4.0.15(@types/node@22.15.3)(jiti@1.21.7)(jsdom@20.0.3)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0)) + version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)))(vitest@4.0.15(@types/node@22.15.3)(jiti@1.21.7)(jsdom@20.0.3)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0)) '@types/jest': specifier: ^29.5.12 version: 29.5.12 @@ -55,7 +55,7 @@ importers: version: 7.0.3 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + version: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) jest-environment-jsdom: specifier: ^29.7.0 version: 29.7.0 @@ -132,7 +132,7 @@ importers: devDependencies: '@remix-run/dev': specifier: ^2.17.2 - version: 2.17.2(@remix-run/react@2.17.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.8.3))(@remix-run/serve@2.17.2(typescript@5.8.3))(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3))(tsx@4.21.0)(typescript@5.8.3)(vite@6.0.10(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0)) + version: 2.17.2(@remix-run/react@2.17.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.8.3))(@remix-run/serve@2.17.2(typescript@5.8.3))(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3))(tsx@4.21.0)(typescript@5.8.3)(vite@6.0.10(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0)) '@types/react': specifier: ^18.2.55 version: 18.2.55 @@ -189,7 +189,7 @@ importers: version: 4.1.18 webpack: specifier: ^5.90.0 - version: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + version: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) webpack-cli: specifier: ^6.0.1 version: 6.0.1(webpack-bundle-analyzer@5.1.0)(webpack-dev-server@5.2.2)(webpack@5.104.0) @@ -225,7 +225,7 @@ importers: specifier: workspace:^ version: link:../../packages/css - fixtures/next-app-router: + fixtures/next-12-pages-router: dependencies: '@fixtures/features': specifier: workspace:* @@ -246,8 +246,8 @@ importers: specifier: workspace:* version: link:../../packages/sprinkles next: - specifier: npm:next@13.5.4 - version: 13.5.4(@babel/core@7.23.9)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: 12.3.4 + version: 12.3.4(@babel/core@7.23.9)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -265,7 +265,7 @@ importers: specifier: workspace:* version: link:../../packages/webpack-plugin - fixtures/next-pages-router: + fixtures/next-13-app-router: dependencies: '@fixtures/features': specifier: workspace:* @@ -286,8 +286,8 @@ importers: specifier: workspace:* version: link:../../packages/sprinkles next: - specifier: 12.3.4 - version: 12.3.4(@babel/core@7.23.9)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + specifier: npm:next@13.5.11 + version: 13.5.11(@babel/core@7.23.9)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -305,6 +305,46 @@ importers: specifier: workspace:* version: link:../../packages/webpack-plugin + fixtures/next-16-app-pages-router: + dependencies: + '@fixtures/features': + specifier: workspace:* + version: link:../features + '@fixtures/recipes': + specifier: workspace:* + version: link:../recipes + '@fixtures/sprinkles': + specifier: workspace:* + version: link:../sprinkles + '@vanilla-extract/css': + specifier: workspace:* + version: link:../../packages/css + '@vanilla-extract/recipes': + specifier: workspace:* + version: link:../../packages/recipes + '@vanilla-extract/sprinkles': + specifier: workspace:* + version: link:../../packages/sprinkles + next: + specifier: npm:next@^16.0.0 + version: 16.1.1(@babel/core@7.23.9)(@playwright/test@1.57.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: + specifier: npm:react@^19.2.0 + version: 19.2.3 + react-dom: + specifier: npm:react-dom@^19.2.0 + version: 19.2.3(react@19.2.3) + devDependencies: + '@types/react': + specifier: ^18.2.55 + version: 18.2.55 + '@vanilla-extract/next-plugin': + specifier: workspace:* + version: link:../../packages/next-plugin + '@vanilla-extract/webpack-plugin': + specifier: workspace:* + version: link:../../packages/webpack-plugin + fixtures/react-library-example: dependencies: '@vanilla-extract/css': @@ -543,16 +583,25 @@ importers: packages/next-plugin: dependencies: + '@vanilla-extract/turbopack-plugin': + specifier: workspace:^ + version: link:../turbopack-plugin '@vanilla-extract/webpack-plugin': specifier: workspace:^ version: link:../webpack-plugin + semver: + specifier: ^7.6.3 + version: 7.7.1 devDependencies: + '@types/semver': + specifier: ^7.7.1 + version: 7.7.1 next: specifier: 12.3.4 - version: 12.3.4(@babel/core@7.23.9)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 12.3.4(@babel/core@7.23.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) webpack: specifier: ^5.90.0 - version: 5.104.0(@swc/core@1.11.24) + version: 5.104.0(@swc/core@1.15.8) packages/parcel-transformer: dependencies: @@ -608,6 +657,25 @@ importers: specifier: workspace:^ version: link:../css + packages/turbopack-plugin: + dependencies: + '@swc/core': + specifier: ^1.13.5 + version: 1.15.8 + '@vanilla-extract/compiler': + specifier: workspace:^ + version: link:../compiler + '@vanilla-extract/integration': + specifier: workspace:^ + version: link:../integration + devDependencies: + next: + specifier: 12.3.4 + version: 12.3.4(@babel/core@7.23.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + vite: + specifier: ^5.0.0 || ^6.0.0 || ^7.0.0 + version: 6.0.10(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0) + packages/utils: {} packages/vite-plugin: @@ -643,7 +711,7 @@ importers: version: 4.1.7 webpack: specifier: ^5.90.0 - version: 5.104.0(@swc/core@1.11.24) + version: 5.104.0(@swc/core@1.15.8) scripts: devDependencies: @@ -731,7 +799,7 @@ importers: version: 2.4.9 '@types/webpack-bundle-analyzer': specifier: ^4.7.0 - version: 4.7.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + version: 4.7.0(@swc/core@1.15.8)(webpack-cli@6.0.1) '@vanilla-extract/css': specifier: workspace:* version: link:../packages/css @@ -785,7 +853,7 @@ importers: version: 2.9.4(webpack@5.104.0) netlify-cli: specifier: ^11.8.3 - version: 11.8.3(@swc/core@1.11.24)(@types/express@4.17.21) + version: 11.8.3(@swc/core@1.15.8)(@types/express@4.17.21) null-loader: specifier: ^4.0.1 version: 4.0.1(webpack@5.104.0) @@ -794,7 +862,7 @@ importers: version: 4.1.18 webpack: specifier: ^5.90.0 - version: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + version: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) webpack-bundle-analyzer: specifier: ^5.1.0 version: 5.1.0 @@ -822,12 +890,15 @@ importers: '@fixtures/low-level': specifier: workspace:* version: link:../fixtures/low-level - '@fixtures/next-app-router': + '@fixtures/next-12-pages-router': + specifier: workspace:* + version: link:../fixtures/next-12-pages-router + '@fixtures/next-13-app-router': specifier: workspace:* - version: link:../fixtures/next-app-router - '@fixtures/next-pages-router': + version: link:../fixtures/next-13-app-router + '@fixtures/next-16-app-pages-router': specifier: workspace:* - version: link:../fixtures/next-pages-router + version: link:../fixtures/next-16-app-pages-router '@fixtures/recipes': specifier: workspace:* version: link:../fixtures/recipes @@ -854,7 +925,7 @@ importers: version: 2.15.0 '@types/mini-css-extract-plugin': specifier: ^1.2.2 - version: 1.4.3(@swc/core@1.11.24)(esbuild@0.27.1) + version: 1.4.3(@swc/core@1.15.8)(esbuild@0.27.1) '@types/webpack-dev-server': specifier: ^3.11.1 version: 3.11.6 @@ -875,10 +946,10 @@ importers: version: link:../packages/webpack-plugin babel-loader: specifier: ^10.0.0 - version: 10.0.0(@babel/core@7.23.9)(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)) + version: 10.0.0(@babel/core@7.23.9)(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)) css-loader: specifier: ^7.1.2 - version: 7.1.2(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)) + version: 7.1.2(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)) cssnano: specifier: ^5.1.15 version: 5.1.15(postcss@8.5.1) @@ -890,10 +961,10 @@ importers: version: 0.27.1 html-webpack-plugin: specifier: ^5.3.1 - version: 5.5.0(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)) + version: 5.5.0(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)) mini-css-extract-plugin: specifier: ^2.9.4 - version: 2.9.4(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)) + version: 2.9.4(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)) minimist: specifier: ^1.2.5 version: 1.2.8 @@ -911,7 +982,7 @@ importers: version: 6.1.3 style-loader: specifier: ^2.0.0 - version: 2.0.0(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)) + version: 2.0.0(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)) vite: specifier: ^5.0.0 || ^6.0.0 || ^7.0.0 version: 6.0.10(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0) @@ -920,10 +991,10 @@ importers: version: 11.3.3(vite@6.0.10(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0)) webpack: specifier: ^5.90.0 - version: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + version: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) webpack-dev-server: specifier: ^5.2.2 - version: 5.2.2(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)) + version: 5.2.2(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)) webpack-merge: specifier: ^6.0.1 version: 6.0.1 @@ -940,15 +1011,12 @@ importers: tests: dependencies: - '@playwright/test': - specifier: ^1.43.1 - version: 1.43.1 '@testing-library/dom': specifier: ^10.0.0 version: 10.0.0 '@testing-library/jest-dom': specifier: ^6.4.2 - version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)))(vitest@4.0.15(@types/node@22.15.3)(jiti@1.21.7)(jsdom@20.0.3)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0)) + version: 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)))(vitest@4.0.15(@types/node@22.15.3)(jiti@1.21.7)(jsdom@20.0.3)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0)) '@vanilla-extract-private/test-helpers': specifier: workspace:* version: link:../test-helpers @@ -2583,6 +2651,143 @@ packages: cpu: [x64] os: [win32] + '@img/colour@1.0.0': + resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@import-maps/resolve@1.0.1': resolution: {integrity: sha512-tWZNBIS1CoekcwlMuyG2mr0a1Wo5lb5lEHwwWvZo+5GLgr3e9LLDTtmgtCWEwBpXMkxn9D+2W9j2FY6eZQq0tA==} @@ -2778,28 +2983,28 @@ packages: cpu: [x64] os: [win32] - '@manypkg/cli@0.21.4': - resolution: {integrity: sha512-EACxxb+c/t6G0l1FrlyewZeBnyR5V1cLkXjnBfsay5TN1UgbilFpG6POglzn+lVJet9NqnEKe3RLHABzkIDZ0Q==} - engines: {node: '>=14.18.0'} + '@manypkg/cli@0.25.1': + resolution: {integrity: sha512-lag906FyiNxzZjsRErkUD5/to174I2JzPk5bZubuJp6loMKKJn73zrtqeU7nHlVkHBg3tgXDTJj22HxUDxLRXw==} + engines: {node: '>=20.0.0'} hasBin: true '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} - '@manypkg/find-root@2.2.1': - resolution: {integrity: sha512-34NlypD5mmTY65cFAK7QPgY5Tzt0qXR4ZRXdg97xAlkiLuwXUPBEXy5Hsqzd+7S2acsLxUz6Cs50rlDZQr4xUA==} - engines: {node: '>=14.18.0'} + '@manypkg/find-root@3.1.0': + resolution: {integrity: sha512-BcSqCyKhBVZ5YkSzOiheMCV41kqAFptW6xGqYSTjkVTl9XQpr+pqHhwgGCOHQtjDCv7Is6EFyA14Sm5GVbVABA==} + engines: {node: '>=20.0.0'} '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} - '@manypkg/get-packages@2.2.1': - resolution: {integrity: sha512-TrJd86paBkKEx6InhObcUhuoJNcATlbO6+s1dQdLd4+Y1SLDKJUAMhU46kTZ1SOFbegTuhDbIF3j+Jy564BERA==} - engines: {node: '>=14.18.0'} + '@manypkg/get-packages@3.1.0': + resolution: {integrity: sha512-0TbBVyvPrP7xGYBI/cP8UP+yl/z+HtbTttAD7FMAJgn/kXOTwh5/60TsqP9ZYY710forNfyV0N8P/IE/ujGZJg==} + engines: {node: '>=20.0.0'} - '@manypkg/tools@1.1.0': - resolution: {integrity: sha512-SkAyKAByB9l93Slyg8AUHGuM2kjvWioUTCckT/03J09jYnfEzMO/wSXmEhnKGYs6qx9De8TH4yJCl0Y9lRgnyQ==} - engines: {node: '>=14.18.0'} + '@manypkg/tools@2.1.0': + resolution: {integrity: sha512-0FOIepYR4ugPYaHwK7hDeHDkfPOBVvayt9QpvRbi2LT/h2b0GaE/gM9Gag7fsnyYyNaTZ2IGyOuVg07IYepvYQ==} + engines: {node: '>=20.0.0'} '@mapbox/node-pre-gyp@1.0.10': resolution: {integrity: sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==} @@ -3115,8 +3320,11 @@ packages: '@next/env@12.3.4': resolution: {integrity: sha512-H/69Lc5Q02dq3o+dxxy5O/oNxFsZpdL6WREtOOtOM1B/weonIwDXkekr1KV5DPVPr12IHFPrMrcJQ6bgPMfn7A==} - '@next/env@13.5.4': - resolution: {integrity: sha512-LGegJkMvRNw90WWphGJ3RMHMVplYcOfRWf2Be3td3sUa+1AaxmsYyANsA+znrGCBjXJNi4XAQlSoEfUxs/4kIQ==} + '@next/env@13.5.11': + resolution: {integrity: sha512-fbb2C7HChgM7CemdCY+y3N1n8pcTKdqtQLbC7/EQtPdLvlMUT9JX/dBYl8MMZAtYG4uVMyPFHXckb68q/NRwqg==} + + '@next/env@16.1.1': + resolution: {integrity: sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA==} '@next/swc-android-arm-eabi@12.3.4': resolution: {integrity: sha512-cM42Cw6V4Bz/2+j/xIzO8nK/Q3Ly+VSlZJTa1vHzsocJRYz8KT6MrreXaci2++SIZCF1rVRCDgAg5PpqRibdIA==} @@ -3136,8 +3344,14 @@ packages: cpu: [arm64] os: [darwin] - '@next/swc-darwin-arm64@13.5.4': - resolution: {integrity: sha512-Df8SHuXgF1p+aonBMcDPEsaahNo2TCwuie7VXED4FVyECvdXfRT9unapm54NssV9tF3OQFKBFOdlje4T43VO0w==} + '@next/swc-darwin-arm64@13.5.9': + resolution: {integrity: sha512-pVyd8/1y1l5atQRvOaLOvfbmRwefxLhqQOzYo/M7FQ5eaRwA1+wuCn7t39VwEgDd7Aw1+AIWwd+MURXUeXhwDw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-arm64@16.1.1': + resolution: {integrity: sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] @@ -3148,8 +3362,14 @@ packages: cpu: [x64] os: [darwin] - '@next/swc-darwin-x64@13.5.4': - resolution: {integrity: sha512-siPuUwO45PnNRMeZnSa8n/Lye5ZX93IJom9wQRB5DEOdFrw0JjOMu1GINB8jAEdwa7Vdyn1oJ2xGNaQpdQQ9Pw==} + '@next/swc-darwin-x64@13.5.9': + resolution: {integrity: sha512-DwdeJqP7v8wmoyTWPbPVodTwCybBZa02xjSJ6YQFIFZFZ7dFgrieKW4Eo0GoIcOJq5+JxkQyejmI+8zwDp3pwA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-darwin-x64@16.1.1': + resolution: {integrity: sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] @@ -3172,8 +3392,14 @@ packages: cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-gnu@13.5.4': - resolution: {integrity: sha512-l/k/fvRP/zmB2jkFMfefmFkyZbDkYW0mRM/LB+tH5u9pB98WsHXC0WvDHlGCYp3CH/jlkJPL7gN8nkTQVrQ/2w==} + '@next/swc-linux-arm64-gnu@13.5.9': + resolution: {integrity: sha512-wdQsKsIsGSNdFojvjW3Ozrh8Q00+GqL3wTaMjDkQxVtRbAqfFBtrLPO0IuWChVUP2UeuQcHpVeUvu0YgOP00+g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-gnu@16.1.1': + resolution: {integrity: sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -3184,8 +3410,14 @@ packages: cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@13.5.4': - resolution: {integrity: sha512-YYGb7SlLkI+XqfQa8VPErljb7k9nUnhhRrVaOdfJNCaQnHBcvbT7cx/UjDQLdleJcfyg1Hkn5YSSIeVfjgmkTg==} + '@next/swc-linux-arm64-musl@13.5.9': + resolution: {integrity: sha512-6VpS+bodQqzOeCwGxoimlRoosiWlSc0C224I7SQWJZoyJuT1ChNCo+45QQH+/GtbR/s7nhaUqmiHdzZC9TXnXA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@16.1.1': + resolution: {integrity: sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] @@ -3196,8 +3428,14 @@ packages: cpu: [x64] os: [linux] - '@next/swc-linux-x64-gnu@13.5.4': - resolution: {integrity: sha512-uE61vyUSClnCH18YHjA8tE1prr/PBFlBFhxBZis4XBRJoR+txAky5d7gGNUIbQ8sZZ7LVkSVgm/5Fc7mwXmRAg==} + '@next/swc-linux-x64-gnu@13.5.9': + resolution: {integrity: sha512-XxG3yj61WDd28NA8gFASIR+2viQaYZEFQagEodhI/R49gXWnYhiflTeeEmCn7Vgnxa/OfK81h1gvhUZ66lozpw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-gnu@16.1.1': + resolution: {integrity: sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -3208,8 +3446,14 @@ packages: cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@13.5.4': - resolution: {integrity: sha512-qVEKFYML/GvJSy9CfYqAdUexA6M5AklYcQCW+8JECmkQHGoPxCf04iMh7CPR7wkHyWWK+XLt4Ja7hhsPJtSnhg==} + '@next/swc-linux-x64-musl@13.5.9': + resolution: {integrity: sha512-/dnscWqfO3+U8asd+Fc6dwL2l9AZDl7eKtPNKW8mKLh4Y4wOpjJiamhe8Dx+D+Oq0GYVjuW0WwjIxYWVozt2bA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@16.1.1': + resolution: {integrity: sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] @@ -3220,8 +3464,14 @@ packages: cpu: [arm64] os: [win32] - '@next/swc-win32-arm64-msvc@13.5.4': - resolution: {integrity: sha512-mDSQfqxAlfpeZOLPxLymZkX0hYF3juN57W6vFHTvwKlnHfmh12Pt7hPIRLYIShk8uYRsKPtMTth/EzpwRI+u8w==} + '@next/swc-win32-arm64-msvc@13.5.9': + resolution: {integrity: sha512-T/iPnyurOK5a4HRUcxAlss8uzoEf5h9tkd+W2dSWAfzxv8WLKlUgbfk+DH43JY3Gc2xK5URLuXrxDZ2mGfk/jw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-arm64-msvc@16.1.1': + resolution: {integrity: sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] @@ -3232,8 +3482,8 @@ packages: cpu: [ia32] os: [win32] - '@next/swc-win32-ia32-msvc@13.5.4': - resolution: {integrity: sha512-aoqAT2XIekIWoriwzOmGFAvTtVY5O7JjV21giozBTP5c6uZhpvTWRbmHXbmsjZqY4HnEZQRXWkSAppsIBweKqw==} + '@next/swc-win32-ia32-msvc@13.5.9': + resolution: {integrity: sha512-BLiPKJomaPrTAb7ykjA0LPcuuNMLDVK177Z1xe0nAem33+9FIayU4k/OWrtSn9SAJW/U60+1hoey5z+KCHdRLQ==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] @@ -3244,8 +3494,14 @@ packages: cpu: [x64] os: [win32] - '@next/swc-win32-x64-msvc@13.5.4': - resolution: {integrity: sha512-cyRvlAxwlddlqeB9xtPSfNSCRy8BOa4wtMo0IuI9P7Y0XT2qpDrpFKRyZ7kUngZis59mPVla5k8X1oOJ8RxDYg==} + '@next/swc-win32-x64-msvc@13.5.9': + resolution: {integrity: sha512-/72/dZfjXXNY/u+n8gqZDjI6rxKMpYsgBBYNZKWOQw0BpBF7WCnPflRy3ZtvQ2+IYI3ZH2bPyj7K+6a6wNk90Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@next/swc-win32-x64-msvc@16.1.1': + resolution: {integrity: sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -3693,10 +3949,9 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/test@1.43.1': - resolution: {integrity: sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==} - engines: {node: '>=16'} - deprecated: Please update to the latest version of Playwright to test up-to-date browsers. + '@playwright/test@1.57.0': + resolution: {integrity: sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA==} + engines: {node: '>=18'} hasBin: true '@pnpm/config.env-replace@1.1.0': @@ -4057,10 +4312,6 @@ packages: resolution: {integrity: sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==} engines: {node: '>=10'} - '@sindresorhus/is@5.6.0': - resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} - engines: {node: '>=14.16'} - '@sindresorhus/slugify@1.1.2': resolution: {integrity: sha512-V9nR/W0Xd9TSGXpZ4iFUcFGhuOJtZX82Fzxj1YISlbSgKvIiNa7eLEZrT0vAraPOt++KHauIVNYgGRgjc13dXA==} engines: {node: '>=10'} @@ -4086,68 +4337,68 @@ packages: '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} - '@swc/core-darwin-arm64@1.11.24': - resolution: {integrity: sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==} + '@swc/core-darwin-arm64@1.15.8': + resolution: {integrity: sha512-M9cK5GwyWWRkRGwwCbREuj6r8jKdES/haCZ3Xckgkl8MUQJZA3XB7IXXK1IXRNeLjg6m7cnoMICpXv1v1hlJOg==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.11.24': - resolution: {integrity: sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==} + '@swc/core-darwin-x64@1.15.8': + resolution: {integrity: sha512-j47DasuOvXl80sKJHSi2X25l44CMc3VDhlJwA7oewC1nV1VsSzwX+KOwE5tLnfORvVJJyeiXgJORNYg4jeIjYQ==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.11.24': - resolution: {integrity: sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==} + '@swc/core-linux-arm-gnueabihf@1.15.8': + resolution: {integrity: sha512-siAzDENu2rUbwr9+fayWa26r5A9fol1iORG53HWxQL1J8ym4k7xt9eME0dMPXlYZDytK5r9sW8zEA10F2U3Xwg==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.11.24': - resolution: {integrity: sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==} + '@swc/core-linux-arm64-gnu@1.15.8': + resolution: {integrity: sha512-o+1y5u6k2FfPYbTRUPvurwzNt5qd0NTumCTFscCNuBksycloXY16J8L+SMW5QRX59n4Hp9EmFa3vpvNHRVv1+Q==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.11.24': - resolution: {integrity: sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==} + '@swc/core-linux-arm64-musl@1.15.8': + resolution: {integrity: sha512-koiCqL09EwOP1S2RShCI7NbsQuG6r2brTqUYE7pV7kZm9O17wZ0LSz22m6gVibpwEnw8jI3IE1yYsQTVpluALw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.11.24': - resolution: {integrity: sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==} + '@swc/core-linux-x64-gnu@1.15.8': + resolution: {integrity: sha512-4p6lOMU3bC+Vd5ARtKJ/FxpIC5G8v3XLoPEZ5s7mLR8h7411HWC/LmTXDHcrSXRC55zvAVia1eldy6zDLz8iFQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.11.24': - resolution: {integrity: sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==} + '@swc/core-linux-x64-musl@1.15.8': + resolution: {integrity: sha512-z3XBnbrZAL+6xDGAhJoN4lOueIxC/8rGrJ9tg+fEaeqLEuAtHSW2QHDHxDwkxZMjuF/pZ6MUTjHjbp8wLbuRLA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.11.24': - resolution: {integrity: sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==} + '@swc/core-win32-arm64-msvc@1.15.8': + resolution: {integrity: sha512-djQPJ9Rh9vP8GTS/Df3hcc6XP6xnG5c8qsngWId/BLA9oX6C7UzCPAn74BG/wGb9a6j4w3RINuoaieJB3t+7iQ==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.11.24': - resolution: {integrity: sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==} + '@swc/core-win32-ia32-msvc@1.15.8': + resolution: {integrity: sha512-/wfAgxORg2VBaUoFdytcVBVCgf1isWZIEXB9MZEUty4wwK93M/PxAkjifOho9RN3WrM3inPLabICRCEgdHpKKQ==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.11.24': - resolution: {integrity: sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==} + '@swc/core-win32-x64-msvc@1.15.8': + resolution: {integrity: sha512-GpMePrh9Sl4d61o4KAHOOv5is5+zt6BEXCOCgs/H0FLGeii7j9bWDE8ExvKFy2GRRZVNR1ugsnzaGWHKM6kuzA==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.11.24': - resolution: {integrity: sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==} + '@swc/core@1.15.8': + resolution: {integrity: sha512-T8keoJjXaSUoVBCIjgL6wAnhADIb09GOELzKg10CjNg+vLX48P93SME6jTfte9MZIm5m+Il57H3rTSk/0kzDUw==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -4161,11 +4412,14 @@ packages: '@swc/helpers@0.4.11': resolution: {integrity: sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==} + '@swc/helpers@0.5.15': + resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} + '@swc/helpers@0.5.2': resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} - '@swc/types@0.1.21': - resolution: {integrity: sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==} + '@swc/types@0.1.25': + resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==} '@szmarczak/http-timer@1.1.2': resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==} @@ -4175,10 +4429,6 @@ packages: resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} engines: {node: '>=10'} - '@szmarczak/http-timer@5.0.1': - resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} - engines: {node: '>=14.16'} - '@testing-library/dom@10.0.0': resolution: {integrity: sha512-PmJPnogldqoVFf+EwbHvbBJ98MmqASV8kLrBYgsDNxQcFMeIS7JFL48sfyXvuMtgmWO/wMhh25odr+8VhDmn4g==} engines: {node: '>=18'} @@ -4452,11 +4702,8 @@ packages: '@types/scheduler@0.16.2': resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==} - '@types/semver@6.2.3': - resolution: {integrity: sha512-KQf+QAMWKMrtBMsB8/24w53tEsxllMj6TuA80TT/5igJalLI/zm0L3oXRbIAl4Ohfc85gyHX/jhMwsVkmhLU4A==} - - '@types/semver@7.5.5': - resolution: {integrity: sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==} + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} @@ -5164,9 +5411,6 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - builtins@1.0.3: - resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} - builtins@5.0.1: resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} @@ -5206,14 +5450,6 @@ packages: resolution: {integrity: sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==} engines: {node: '>=10'} - cacheable-lookup@7.0.0: - resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} - engines: {node: '>=14.16'} - - cacheable-request@10.2.14: - resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} - engines: {node: '>=14.16'} - cacheable-request@2.1.4: resolution: {integrity: sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==} @@ -5848,10 +6084,6 @@ packages: resolution: {integrity: sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==} engines: {node: '>=10'} - decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - decompress-tar@4.1.1: resolution: {integrity: sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==} engines: {node: '>=4'} @@ -5973,6 +6205,10 @@ packages: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} + detect-indent@7.0.2: + resolution: {integrity: sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==} + engines: {node: '>=12.20'} + detect-libc@1.0.3: resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} engines: {node: '>=0.10'} @@ -5982,6 +6218,10 @@ packages: resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==} engines: {node: '>=8'} + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -6633,10 +6873,6 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} - form-data-encoder@2.1.4: - resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} - engines: {node: '>= 14.17'} - form-data@3.0.1: resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} engines: {node: '>= 6'} @@ -6890,10 +7126,6 @@ packages: resolution: {integrity: sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==} engines: {node: '>=10'} - got@12.6.1: - resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} - engines: {node: '>=14.16'} - got@8.3.2: resolution: {integrity: sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==} engines: {node: '>=4'} @@ -7138,10 +7370,6 @@ packages: resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} engines: {node: '>=8.0.0'} - http2-wrapper@2.2.1: - resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} - engines: {node: '>=10.19.0'} - https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -7950,6 +8178,10 @@ packages: kuler@2.0.0: resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + ky@1.14.2: + resolution: {integrity: sha512-q3RBbsO5A5zrPhB6CaCS8ZUv+NWCXv6JJT4Em0i264G9W0fdPB8YRfnnEi7Dm7X7omAkBIPojzYJ2D1oHTHqug==} + engines: {node: '>=18'} + lambda-local@2.0.3: resolution: {integrity: sha512-Vs55gujwdjhPL2VpXEXAWWwxiOYdnVPDsMgwOr9BqC0O1EoSXs1S8TKBmD/ySEnPVRiQfFlABcQgcykF1mkE8Q==} engines: {node: '>=6'} @@ -8215,10 +8447,6 @@ packages: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} - lowercase-keys@3.0.0: - resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - lowlight@1.20.0: resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==} @@ -8573,14 +8801,6 @@ packages: resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} engines: {node: '>=8'} - mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - mimic-response@4.0.0: - resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -8778,8 +8998,8 @@ packages: sass: optional: true - next@13.5.4: - resolution: {integrity: sha512-+93un5S779gho8y9ASQhb/bTkQF17FNQOtXLKAj3lsNgltEcF0C5PMLLncDmH+8X1EnJH1kbqAERa29nRXqhjA==} + next@13.5.11: + resolution: {integrity: sha512-WUPJ6WbAX9tdC86kGTu92qkrRdgRqVrY++nwM+shmWQwmyxt4zhZfR59moXSI4N8GDYCBY3lIAqhzjDd4rTC8Q==} engines: {node: '>=16.14.0'} hasBin: true peerDependencies: @@ -8793,6 +9013,27 @@ packages: sass: optional: true + next@16.1.1: + resolution: {integrity: sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w==} + engines: {node: '>=20.9.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.51.1 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + no-case@2.3.2: resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} @@ -8908,10 +9149,6 @@ packages: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} - normalize-url@8.0.1: - resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} - engines: {node: '>=14.16'} - npm-bundled@1.1.2: resolution: {integrity: sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==} @@ -9089,10 +9326,6 @@ packages: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} - p-cancelable@3.0.0: - resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} - engines: {node: '>=12.20'} - p-event@2.3.1: resolution: {integrity: sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==} engines: {node: '>=6'} @@ -9137,6 +9370,10 @@ packages: resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-limit@6.2.0: + resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} + engines: {node: '>=18'} + p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -9201,14 +9438,14 @@ packages: resolution: {integrity: sha512-i8nE5q++9h8oaQHWltS1Tnnv4IoMDOlqN7C0KFG2OdbK0iFJIt6CROZ8wfBM+K4Pxqfnq4C4lkkpXqTEpB5DZw==} engines: {node: '>=12'} + package-json@10.0.1: + resolution: {integrity: sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==} + engines: {node: '>=18'} + package-json@6.5.0: resolution: {integrity: sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==} engines: {node: '>=8'} - package-json@8.1.1: - resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} - engines: {node: '>=14.16'} - package-manager-detector@0.2.0: resolution: {integrity: sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==} @@ -9238,6 +9475,11 @@ packages: engines: {node: '>=0.10.0'} hasBin: true + parse-github-url@1.0.3: + resolution: {integrity: sha512-tfalY5/4SqGaV/GIGzWyHnFjlpTPTNpENR9Ea2lLldSJ8EWXMsvacWucqY3m3I4YPtas15IxTLQVQ5NSYXPrww==} + engines: {node: '>= 0.10'} + hasBin: true + parse-gitignore@1.0.1: resolution: {integrity: sha512-UGyowyjtx26n65kdAMWhm6/3uy5uSrpcuH7tt+QEVudiBoVS+eqHxD5kbi9oWVRwj7sCzXqwuM+rUGw7earl6A==} engines: {node: '>=6'} @@ -9400,14 +9642,14 @@ packages: pkg-types@1.0.3: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} - playwright-core@1.43.1: - resolution: {integrity: sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==} - engines: {node: '>=16'} + playwright-core@1.57.0: + resolution: {integrity: sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==} + engines: {node: '>=18'} hasBin: true - playwright@1.43.1: - resolution: {integrity: sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==} - engines: {node: '>=16'} + playwright@1.57.0: + resolution: {integrity: sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==} + engines: {node: '>=18'} hasBin: true polished@4.1.3: @@ -9834,6 +10076,11 @@ packages: peerDependencies: react: ^18.2.0 + react-dom@19.2.3: + resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} + peerDependencies: + react: ^19.2.3 + react-head@3.4.2: resolution: {integrity: sha512-mnl6u7E0SSzY9w+mExKGVz8vW/oObUTnj+vpRaZF6jcdjFcCGs0vl8MRwlRws56dye3f1CpzU7C/hz3b3S2BBA==} peerDependencies: @@ -9886,6 +10133,10 @@ packages: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} + react@19.2.3: + resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} + engines: {node: '>=0.10.0'} + read-package-json-fast@2.0.3: resolution: {integrity: sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==} engines: {node: '>=10'} @@ -10068,9 +10319,6 @@ packages: requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - resolve-alpn@1.2.1: - resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -10104,10 +10352,6 @@ packages: responselike@2.0.0: resolution: {integrity: sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==} - responselike@3.0.0: - resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} - engines: {node: '>=14.16'} - restore-cursor@2.0.0: resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} engines: {node: '>=4'} @@ -10229,6 +10473,9 @@ packages: scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} @@ -10252,8 +10499,8 @@ packages: resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} engines: {node: '>=10'} - sembear@0.5.2: - resolution: {integrity: sha512-Ij1vCAdFgWABd7zTg50Xw1/p0JgESNxuLlneEAsmBrKishA06ulTTL/SHGmNy2Zud7+rKrHTKNI6moJsn1ppAQ==} + sembear@0.7.0: + resolution: {integrity: sha512-XyLTEich2D02FODCkfdto3mB9DetWPLuTzr4tvoofe9SvyM27h4nQSbV3+iVcYQz94AFyKtqBv5pcZbj3k2hdA==} semver-diff@3.1.1: resolution: {integrity: sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==} @@ -10272,6 +10519,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + send@0.19.0: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} @@ -10321,6 +10573,10 @@ packages: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -10715,6 +10971,19 @@ packages: babel-plugin-macros: optional: true + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + stylehacks@5.1.1: resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} engines: {node: ^10 || ^12 || >=14.0} @@ -11038,6 +11307,9 @@ packages: tslib@2.5.0: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsutils@3.21.0: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -11396,9 +11668,6 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - validate-npm-package-name@3.0.0: - resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==} - validate-npm-package-name@4.0.0: resolution: {integrity: sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -11407,6 +11676,10 @@ packages: resolution: {integrity: sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + validate-npm-package-name@6.0.2: + resolution: {integrity: sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==} + engines: {node: ^18.17.0 || >=20.5.0} + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -11887,6 +12160,10 @@ packages: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + zip-stream@4.1.0: resolution: {integrity: sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==} engines: {node: '>= 10'} @@ -12953,7 +13230,7 @@ snapshots: '@changesets/types': 6.0.0 '@changesets/write': 0.3.2 '@manypkg/get-packages': 1.1.3 - '@types/semver': 7.5.5 + '@types/semver': 7.7.1 ansi-colors: 4.1.3 ci-info: 3.9.0 enquirer: 2.3.6 @@ -13464,6 +13741,103 @@ snapshots: '@esbuild/win32-x64@0.27.1': optional: true + '@img/colour@1.0.0': + optional: true + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.7.1 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + '@import-maps/resolve@1.0.1': {} '@isaacs/cliui@8.0.2': @@ -13494,7 +13868,7 @@ snapshots: jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3))': + '@jest/core@29.7.0(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -13508,7 +13882,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + jest-config: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -13758,21 +14132,19 @@ snapshots: '@lmdb/lmdb-win32-x64@2.8.5': optional: true - '@manypkg/cli@0.21.4': + '@manypkg/cli@0.25.1': dependencies: - '@manypkg/get-packages': 2.2.1 - chalk: 2.4.2 - detect-indent: 6.1.0 - find-up: 4.1.0 - fs-extra: 8.1.0 + '@manypkg/get-packages': 3.1.0 + detect-indent: 7.0.2 normalize-path: 3.0.0 - p-limit: 2.3.0 - package-json: 8.1.1 - parse-github-url: 1.0.2 - sembear: 0.5.2 - semver: 6.3.1 - spawndamnit: 2.0.0 - validate-npm-package-name: 3.0.0 + p-limit: 6.2.0 + package-json: 10.0.1 + parse-github-url: 1.0.3 + picocolors: 1.1.1 + sembear: 0.7.0 + semver: 7.7.1 + tinyexec: 1.0.2 + validate-npm-package-name: 6.0.2 '@manypkg/find-root@1.1.0': dependencies: @@ -13781,11 +14153,9 @@ snapshots: find-up: 4.1.0 fs-extra: 8.1.0 - '@manypkg/find-root@2.2.1': + '@manypkg/find-root@3.1.0': dependencies: - '@manypkg/tools': 1.1.0 - find-up: 4.1.0 - fs-extra: 8.1.0 + '@manypkg/tools': 2.1.0 '@manypkg/get-packages@1.1.3': dependencies: @@ -13796,17 +14166,16 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 - '@manypkg/get-packages@2.2.1': + '@manypkg/get-packages@3.1.0': dependencies: - '@manypkg/find-root': 2.2.1 - '@manypkg/tools': 1.1.0 + '@manypkg/find-root': 3.1.0 + '@manypkg/tools': 2.1.0 - '@manypkg/tools@1.1.0': + '@manypkg/tools@2.1.0': dependencies: - fs-extra: 8.1.0 - globby: 11.1.0 jju: 1.4.0 - read-yaml-file: 1.1.0 + js-yaml: 4.1.0 + tinyglobby: 0.2.15 '@mapbox/node-pre-gyp@1.0.10(supports-color@9.2.3)': dependencies: @@ -13924,7 +14293,7 @@ snapshots: '@netlify/binary-info@1.0.0': {} - '@netlify/build@27.18.5(@swc/core@1.11.24)': + '@netlify/build@27.18.5(@swc/core@1.15.8)': dependencies: '@bugsnag/js': 7.18.0 '@netlify/cache-utils': 4.1.4(supports-color@9.2.3) @@ -13976,7 +14345,7 @@ snapshots: strip-ansi: 7.0.1 supports-color: 9.2.3 tmp-promise: 3.0.3 - ts-node: 10.9.1(@swc/core@1.11.24)(@types/node@16.11.10)(typescript@4.9.4) + ts-node: 10.9.1(@swc/core@1.15.8)(@types/node@16.11.10)(typescript@4.9.4) typescript: 4.9.4 update-notifier: 5.1.0 uuid: 8.3.2 @@ -14256,7 +14625,9 @@ snapshots: '@next/env@12.3.4': {} - '@next/env@13.5.4': {} + '@next/env@13.5.11': {} + + '@next/env@16.1.1': {} '@next/swc-android-arm-eabi@12.3.4': optional: true @@ -14267,13 +14638,19 @@ snapshots: '@next/swc-darwin-arm64@12.3.4': optional: true - '@next/swc-darwin-arm64@13.5.4': + '@next/swc-darwin-arm64@13.5.9': + optional: true + + '@next/swc-darwin-arm64@16.1.1': optional: true '@next/swc-darwin-x64@12.3.4': optional: true - '@next/swc-darwin-x64@13.5.4': + '@next/swc-darwin-x64@13.5.9': + optional: true + + '@next/swc-darwin-x64@16.1.1': optional: true '@next/swc-freebsd-x64@12.3.4': @@ -14285,43 +14662,61 @@ snapshots: '@next/swc-linux-arm64-gnu@12.3.4': optional: true - '@next/swc-linux-arm64-gnu@13.5.4': + '@next/swc-linux-arm64-gnu@13.5.9': + optional: true + + '@next/swc-linux-arm64-gnu@16.1.1': optional: true '@next/swc-linux-arm64-musl@12.3.4': optional: true - '@next/swc-linux-arm64-musl@13.5.4': + '@next/swc-linux-arm64-musl@13.5.9': + optional: true + + '@next/swc-linux-arm64-musl@16.1.1': optional: true '@next/swc-linux-x64-gnu@12.3.4': optional: true - '@next/swc-linux-x64-gnu@13.5.4': + '@next/swc-linux-x64-gnu@13.5.9': + optional: true + + '@next/swc-linux-x64-gnu@16.1.1': optional: true '@next/swc-linux-x64-musl@12.3.4': optional: true - '@next/swc-linux-x64-musl@13.5.4': + '@next/swc-linux-x64-musl@13.5.9': + optional: true + + '@next/swc-linux-x64-musl@16.1.1': optional: true '@next/swc-win32-arm64-msvc@12.3.4': optional: true - '@next/swc-win32-arm64-msvc@13.5.4': + '@next/swc-win32-arm64-msvc@13.5.9': + optional: true + + '@next/swc-win32-arm64-msvc@16.1.1': optional: true '@next/swc-win32-ia32-msvc@12.3.4': optional: true - '@next/swc-win32-ia32-msvc@13.5.4': + '@next/swc-win32-ia32-msvc@13.5.9': optional: true '@next/swc-win32-x64-msvc@12.3.4': optional: true - '@next/swc-win32-x64-msvc@13.5.4': + '@next/swc-win32-x64-msvc@13.5.9': + optional: true + + '@next/swc-win32-x64-msvc@16.1.1': optional: true '@nodelib/fs.scandir@2.1.5': @@ -14662,7 +15057,7 @@ snapshots: '@parcel/plugin': 2.15.0(@parcel/core@2.15.0) '@parcel/source-map': 2.1.1 '@parcel/utils': 2.15.0 - '@swc/core': 1.11.24 + '@swc/core': 1.15.8 nullthrows: 1.1.1 transitivePeerDependencies: - '@parcel/core' @@ -14679,7 +15074,7 @@ snapshots: '@parcel/types': 2.15.0(@parcel/core@2.15.0) '@parcel/utils': 2.15.0 '@parcel/workers': 2.15.0(@parcel/core@2.15.0) - '@swc/core': 1.11.24 + '@swc/core': 1.15.8 semver: 7.7.1 transitivePeerDependencies: - '@swc/helpers' @@ -15078,9 +15473,9 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/test@1.43.1': + '@playwright/test@1.57.0': dependencies: - playwright: 1.43.1 + playwright: 1.57.0 '@pnpm/config.env-replace@1.1.0': {} @@ -15153,7 +15548,7 @@ snapshots: make-synchronized: 0.2.9 prettier: 3.4.2 - '@remix-run/dev@2.17.2(@remix-run/react@2.17.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.8.3))(@remix-run/serve@2.17.2(typescript@5.8.3))(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3))(tsx@4.21.0)(typescript@5.8.3)(vite@6.0.10(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0))': + '@remix-run/dev@2.17.2(@remix-run/react@2.17.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.8.3))(@remix-run/serve@2.17.2(typescript@5.8.3))(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3))(tsx@4.21.0)(typescript@5.8.3)(vite@6.0.10(@types/node@22.15.3)(jiti@1.21.7)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0))': dependencies: '@babel/core': 7.23.9 '@babel/generator': 7.23.6 @@ -15198,7 +15593,7 @@ snapshots: pidtree: 0.6.0 postcss: 8.5.1 postcss-discard-duplicates: 5.1.0(postcss@8.5.1) - postcss-load-config: 4.0.2(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + postcss-load-config: 4.0.2(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) postcss-modules: 6.0.0(postcss@8.5.1) prettier: 2.8.8 pretty-ms: 7.0.1 @@ -15499,8 +15894,6 @@ snapshots: '@sindresorhus/is@2.1.1': {} - '@sindresorhus/is@5.6.0': {} - '@sindresorhus/slugify@1.1.2': dependencies: '@sindresorhus/transliterate': 0.1.2 @@ -15531,51 +15924,51 @@ snapshots: '@standard-schema/spec@1.0.0': {} - '@swc/core-darwin-arm64@1.11.24': + '@swc/core-darwin-arm64@1.15.8': optional: true - '@swc/core-darwin-x64@1.11.24': + '@swc/core-darwin-x64@1.15.8': optional: true - '@swc/core-linux-arm-gnueabihf@1.11.24': + '@swc/core-linux-arm-gnueabihf@1.15.8': optional: true - '@swc/core-linux-arm64-gnu@1.11.24': + '@swc/core-linux-arm64-gnu@1.15.8': optional: true - '@swc/core-linux-arm64-musl@1.11.24': + '@swc/core-linux-arm64-musl@1.15.8': optional: true - '@swc/core-linux-x64-gnu@1.11.24': + '@swc/core-linux-x64-gnu@1.15.8': optional: true - '@swc/core-linux-x64-musl@1.11.24': + '@swc/core-linux-x64-musl@1.15.8': optional: true - '@swc/core-win32-arm64-msvc@1.11.24': + '@swc/core-win32-arm64-msvc@1.15.8': optional: true - '@swc/core-win32-ia32-msvc@1.11.24': + '@swc/core-win32-ia32-msvc@1.15.8': optional: true - '@swc/core-win32-x64-msvc@1.11.24': + '@swc/core-win32-x64-msvc@1.15.8': optional: true - '@swc/core@1.11.24': + '@swc/core@1.15.8': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.21 + '@swc/types': 0.1.25 optionalDependencies: - '@swc/core-darwin-arm64': 1.11.24 - '@swc/core-darwin-x64': 1.11.24 - '@swc/core-linux-arm-gnueabihf': 1.11.24 - '@swc/core-linux-arm64-gnu': 1.11.24 - '@swc/core-linux-arm64-musl': 1.11.24 - '@swc/core-linux-x64-gnu': 1.11.24 - '@swc/core-linux-x64-musl': 1.11.24 - '@swc/core-win32-arm64-msvc': 1.11.24 - '@swc/core-win32-ia32-msvc': 1.11.24 - '@swc/core-win32-x64-msvc': 1.11.24 + '@swc/core-darwin-arm64': 1.15.8 + '@swc/core-darwin-x64': 1.15.8 + '@swc/core-linux-arm-gnueabihf': 1.15.8 + '@swc/core-linux-arm64-gnu': 1.15.8 + '@swc/core-linux-arm64-musl': 1.15.8 + '@swc/core-linux-x64-gnu': 1.15.8 + '@swc/core-linux-x64-musl': 1.15.8 + '@swc/core-win32-arm64-msvc': 1.15.8 + '@swc/core-win32-ia32-msvc': 1.15.8 + '@swc/core-win32-x64-msvc': 1.15.8 '@swc/counter@0.1.3': {} @@ -15583,11 +15976,15 @@ snapshots: dependencies: tslib: 2.5.0 + '@swc/helpers@0.5.15': + dependencies: + tslib: 2.8.1 + '@swc/helpers@0.5.2': dependencies: tslib: 2.5.0 - '@swc/types@0.1.21': + '@swc/types@0.1.25': dependencies: '@swc/counter': 0.1.3 @@ -15599,10 +15996,6 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@szmarczak/http-timer@5.0.1': - dependencies: - defer-to-connect: 2.0.1 - '@testing-library/dom@10.0.0': dependencies: '@babel/code-frame': 7.24.7 @@ -15614,7 +16007,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)))(vitest@4.0.15(@types/node@22.15.3)(jiti@1.21.7)(jsdom@20.0.3)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0))': + '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)))(vitest@4.0.15(@types/node@22.15.3)(jiti@1.21.7)(jsdom@20.0.3)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0))': dependencies: '@adobe/css-tools': 4.3.3 '@babel/runtime': 7.28.4 @@ -15627,7 +16020,7 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.12 - jest: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + jest: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) vitest: 4.0.15(@types/node@22.15.3)(jiti@1.21.7)(jsdom@20.0.3)(lightningcss@1.30.0)(terser@5.44.1)(tsx@4.21.0) '@tootallnate/once@2.0.0': {} @@ -15837,11 +16230,11 @@ snapshots: '@types/mime@1.3.2': {} - '@types/mini-css-extract-plugin@1.4.3(@swc/core@1.11.24)(esbuild@0.27.1)': + '@types/mini-css-extract-plugin@1.4.3(@swc/core@1.15.8)(esbuild@0.27.1)': dependencies: '@types/node': 22.15.3 tapable: 2.3.0 - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -15926,9 +16319,7 @@ snapshots: '@types/scheduler@0.16.2': {} - '@types/semver@6.2.3': {} - - '@types/semver@7.5.5': {} + '@types/semver@7.7.1': {} '@types/send@0.17.4': dependencies: @@ -15967,11 +16358,11 @@ snapshots: '@types/unist@2.0.6': {} - '@types/webpack-bundle-analyzer@4.7.0(@swc/core@1.11.24)(webpack-cli@6.0.1)': + '@types/webpack-bundle-analyzer@4.7.0(@swc/core@1.15.8)(webpack-cli@6.0.1)': dependencies: '@types/node': 22.15.3 tapable: 2.3.0 - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) transitivePeerDependencies: - '@swc/core' - esbuild @@ -16247,17 +16638,17 @@ snapshots: '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.104.0)': dependencies: - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) webpack-cli: 6.0.1(webpack-bundle-analyzer@5.1.0)(webpack-dev-server@5.2.2)(webpack@5.104.0) '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.104.0)': dependencies: - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) webpack-cli: 6.0.1(webpack-bundle-analyzer@5.1.0)(webpack-dev-server@5.2.2)(webpack@5.104.0) '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack-dev-server@5.2.2)(webpack@5.104.0)': dependencies: - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) webpack-cli: 6.0.1(webpack-bundle-analyzer@5.1.0)(webpack-dev-server@5.2.2)(webpack@5.104.0) optionalDependencies: webpack-dev-server: 5.2.2(webpack-cli@6.0.1)(webpack@5.104.0) @@ -16551,17 +16942,17 @@ snapshots: transitivePeerDependencies: - supports-color - babel-loader@10.0.0(@babel/core@7.23.9)(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)): + babel-loader@10.0.0(@babel/core@7.23.9)(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)): dependencies: '@babel/core': 7.23.9 find-up: 5.0.0 - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) babel-loader@10.0.0(@babel/core@7.23.9)(webpack@5.104.0): dependencies: '@babel/core': 7.23.9 find-up: 5.0.0 - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) babel-plugin-apply-mdx-type-prop@1.6.22(@babel/core@7.12.9): dependencies: @@ -16804,8 +17195,6 @@ snapshots: builtin-modules@3.3.0: {} - builtins@1.0.3: {} - builtins@5.0.1: dependencies: semver: 7.7.1 @@ -16858,18 +17247,6 @@ snapshots: '@types/keyv': 3.1.3 keyv: 4.5.4 - cacheable-lookup@7.0.0: {} - - cacheable-request@10.2.14: - dependencies: - '@types/http-cache-semantics': 4.0.4 - get-stream: 6.0.1 - http-cache-semantics: 4.1.1 - keyv: 4.5.4 - mimic-response: 4.0.0 - normalize-url: 8.0.1 - responselike: 3.0.0 - cacheable-request@2.1.4: dependencies: clone-response: 1.0.2 @@ -17321,7 +17698,7 @@ snapshots: schema-utils: 4.3.3 serialize-javascript: 6.0.2 tinyglobby: 0.2.15 - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) core-js-compat@3.36.0: dependencies: @@ -17364,13 +17741,13 @@ snapshots: crc-32: 1.2.2 readable-stream: 3.6.0 - create-jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)): + create-jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + jest-config: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -17407,7 +17784,7 @@ snapshots: dependencies: postcss: 8.5.1 - css-loader@7.1.2(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)): + css-loader@7.1.2(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)): dependencies: icss-utils: 5.1.0(postcss@8.5.1) postcss: 8.5.1 @@ -17418,7 +17795,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.7.1 optionalDependencies: - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) css-loader@7.1.2(webpack@5.104.0): dependencies: @@ -17431,7 +17808,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.7.1 optionalDependencies: - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) css-select@4.1.3: dependencies: @@ -17587,10 +17964,6 @@ snapshots: dependencies: mimic-response: 2.1.0 - decompress-response@6.0.0: - dependencies: - mimic-response: 3.1.0 - decompress-tar@4.1.1: dependencies: file-type: 5.2.0 @@ -17708,10 +18081,15 @@ snapshots: detect-indent@6.1.0: {} + detect-indent@7.0.2: {} + detect-libc@1.0.3: {} detect-libc@2.0.4: {} + detect-libc@2.1.2: + optional: true + detect-newline@3.1.0: {} detect-node@2.1.0: {} @@ -18513,8 +18891,6 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - form-data-encoder@2.1.4: {} - form-data@3.0.1: dependencies: asynckit: 0.4.0 @@ -18673,7 +19049,7 @@ snapshots: dependencies: '@types/download': 8.0.1 '@types/node-fetch': 2.6.2 - '@types/semver': 7.5.5 + '@types/semver': 7.7.1 download: 8.0.0 node-fetch: 2.6.7 semver: 7.7.1 @@ -18818,20 +19194,6 @@ snapshots: to-readable-stream: 2.1.0 type-fest: 0.10.0 - got@12.6.1: - dependencies: - '@sindresorhus/is': 5.6.0 - '@szmarczak/http-timer': 5.0.1 - cacheable-lookup: 7.0.0 - cacheable-request: 10.2.14 - decompress-response: 6.0.0 - form-data-encoder: 2.1.4 - get-stream: 6.0.1 - http2-wrapper: 2.2.1 - lowercase-keys: 3.0.0 - p-cancelable: 3.0.0 - responselike: 3.0.0 - got@8.3.2: dependencies: '@sindresorhus/is': 0.7.0 @@ -19104,14 +19466,14 @@ snapshots: html-void-elements@1.0.5: {} - html-webpack-plugin@5.5.0(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)): + html-webpack-plugin@5.5.0(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 lodash: 4.17.21 pretty-error: 4.0.0 tapable: 2.3.0 - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) html-webpack-plugin@5.5.0(webpack@5.104.0): dependencies: @@ -19120,7 +19482,7 @@ snapshots: lodash: 4.17.21 pretty-error: 4.0.0 tapable: 2.3.0 - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) htmlparser2@6.1.0: dependencies: @@ -19206,11 +19568,6 @@ snapshots: transitivePeerDependencies: - debug - http2-wrapper@2.2.1: - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - https-proxy-agent@5.0.1(supports-color@9.2.3): dependencies: agent-base: 6.0.2(supports-color@9.2.3) @@ -19656,16 +20013,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)): + jest-cli@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + '@jest/core': 29.7.0(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + create-jest: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) exit: 0.1.2 import-local: 3.0.3 - jest-config: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + jest-config: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -19675,7 +20032,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)): + jest-config@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)): dependencies: '@babel/core': 7.23.9 '@jest/test-sequencer': 29.7.0 @@ -19701,7 +20058,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 22.15.3 - ts-node: 10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3) + ts-node: 10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -19970,12 +20327,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)): + jest@29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + '@jest/core': 29.7.0(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) '@jest/types': 29.6.3 import-local: 3.0.3 - jest-cli: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)) + jest-cli: 29.7.0(@types/node@22.15.3)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -20140,6 +20497,8 @@ snapshots: kuler@2.0.0: {} + ky@1.14.2: {} + lambda-local@2.0.3: dependencies: commander: 9.4.0 @@ -20404,8 +20763,6 @@ snapshots: lowercase-keys@2.0.0: {} - lowercase-keys@3.0.0: {} - lowlight@1.20.0: dependencies: fault: 1.0.4 @@ -20996,23 +21353,19 @@ snapshots: mimic-response@2.1.0: {} - mimic-response@3.1.0: {} - - mimic-response@4.0.0: {} - min-indent@1.0.1: {} - mini-css-extract-plugin@2.9.4(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)): + mini-css-extract-plugin@2.9.4(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)): dependencies: schema-utils: 4.3.3 tapable: 2.3.0 - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) mini-css-extract-plugin@2.9.4(webpack@5.104.0): dependencies: schema-utils: 4.3.3 tapable: 2.3.0 - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) minimalistic-assert@1.0.1: {} @@ -21172,9 +21525,9 @@ snapshots: nested-error-stacks@2.1.1: {} - netlify-cli@11.8.3(@swc/core@1.11.24)(@types/express@4.17.21): + netlify-cli@11.8.3(@swc/core@1.15.8)(@types/express@4.17.21): dependencies: - '@netlify/build': 27.18.5(@swc/core@1.11.24) + '@netlify/build': 27.18.5(@swc/core@1.15.8) '@netlify/config': 18.2.3 '@netlify/edge-bundler': 2.2.0 '@netlify/framework-info': 9.2.0 @@ -21355,9 +21708,37 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@13.5.4(@babel/core@7.23.9)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + next@12.3.4(@babel/core@7.23.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: - '@next/env': 13.5.4 + '@next/env': 12.3.4 + '@swc/helpers': 0.4.11 + caniuse-lite: 1.0.30001760 + postcss: 8.4.14 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + styled-jsx: 5.0.7(@babel/core@7.23.9)(react@19.2.3) + use-sync-external-store: 1.2.0(react@19.2.3) + optionalDependencies: + '@next/swc-android-arm-eabi': 12.3.4 + '@next/swc-android-arm64': 12.3.4 + '@next/swc-darwin-arm64': 12.3.4 + '@next/swc-darwin-x64': 12.3.4 + '@next/swc-freebsd-x64': 12.3.4 + '@next/swc-linux-arm-gnueabihf': 12.3.4 + '@next/swc-linux-arm64-gnu': 12.3.4 + '@next/swc-linux-arm64-musl': 12.3.4 + '@next/swc-linux-x64-gnu': 12.3.4 + '@next/swc-linux-x64-musl': 12.3.4 + '@next/swc-win32-arm64-msvc': 12.3.4 + '@next/swc-win32-ia32-msvc': 12.3.4 + '@next/swc-win32-x64-msvc': 12.3.4 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + next@13.5.11(@babel/core@7.23.9)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@next/env': 13.5.11 '@swc/helpers': 0.5.2 busboy: 1.6.0 caniuse-lite: 1.0.30001760 @@ -21367,15 +21748,40 @@ snapshots: styled-jsx: 5.1.1(@babel/core@7.23.9)(react@18.2.0) watchpack: 2.4.0 optionalDependencies: - '@next/swc-darwin-arm64': 13.5.4 - '@next/swc-darwin-x64': 13.5.4 - '@next/swc-linux-arm64-gnu': 13.5.4 - '@next/swc-linux-arm64-musl': 13.5.4 - '@next/swc-linux-x64-gnu': 13.5.4 - '@next/swc-linux-x64-musl': 13.5.4 - '@next/swc-win32-arm64-msvc': 13.5.4 - '@next/swc-win32-ia32-msvc': 13.5.4 - '@next/swc-win32-x64-msvc': 13.5.4 + '@next/swc-darwin-arm64': 13.5.9 + '@next/swc-darwin-x64': 13.5.9 + '@next/swc-linux-arm64-gnu': 13.5.9 + '@next/swc-linux-arm64-musl': 13.5.9 + '@next/swc-linux-x64-gnu': 13.5.9 + '@next/swc-linux-x64-musl': 13.5.9 + '@next/swc-win32-arm64-msvc': 13.5.9 + '@next/swc-win32-ia32-msvc': 13.5.9 + '@next/swc-win32-x64-msvc': 13.5.9 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + next@16.1.1(@babel/core@7.23.9)(@playwright/test@1.57.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + '@next/env': 16.1.1 + '@swc/helpers': 0.5.15 + baseline-browser-mapping: 2.9.8 + caniuse-lite: 1.0.30001760 + postcss: 8.4.31 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + styled-jsx: 5.1.6(@babel/core@7.23.9)(react@19.2.3) + optionalDependencies: + '@next/swc-darwin-arm64': 16.1.1 + '@next/swc-darwin-x64': 16.1.1 + '@next/swc-linux-arm64-gnu': 16.1.1 + '@next/swc-linux-arm64-musl': 16.1.1 + '@next/swc-linux-x64-gnu': 16.1.1 + '@next/swc-linux-x64-musl': 16.1.1 + '@next/swc-win32-arm64-msvc': 16.1.1 + '@next/swc-win32-x64-msvc': 16.1.1 + '@playwright/test': 1.57.0 + sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -21493,8 +21899,6 @@ snapshots: normalize-url@6.1.0: {} - normalize-url@8.0.1: {} - npm-bundled@1.1.2: dependencies: npm-normalize-package-bin: 1.0.1 @@ -21551,7 +21955,7 @@ snapshots: dependencies: loader-utils: 2.0.2 schema-utils: 3.3.0 - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) nullthrows@1.1.1: {} @@ -21678,8 +22082,6 @@ snapshots: p-cancelable@2.1.1: {} - p-cancelable@3.0.0: {} - p-event@2.3.1: dependencies: p-timeout: 2.0.1 @@ -21720,6 +22122,10 @@ snapshots: dependencies: yocto-queue: 1.0.0 + p-limit@6.2.0: + dependencies: + yocto-queue: 1.2.2 + p-locate@4.1.0: dependencies: p-limit: 2.3.0 @@ -21779,6 +22185,13 @@ snapshots: dependencies: p-timeout: 5.1.0 + package-json@10.0.1: + dependencies: + ky: 1.14.2 + registry-auth-token: 5.0.2 + registry-url: 6.0.1 + semver: 7.7.1 + package-json@6.5.0: dependencies: got: 9.6.0 @@ -21786,13 +22199,6 @@ snapshots: registry-url: 5.1.0 semver: 6.3.1 - package-json@8.1.1: - dependencies: - got: 12.6.1 - registry-auth-token: 5.0.2 - registry-url: 6.0.1 - semver: 7.7.1 - package-manager-detector@0.2.0: {} pako@0.2.9: {} @@ -21843,6 +22249,8 @@ snapshots: parse-github-url@1.0.2: {} + parse-github-url@1.0.3: {} + parse-gitignore@1.0.1: {} parse-glob@3.0.4: @@ -21976,11 +22384,11 @@ snapshots: mlly: 1.4.2 pathe: 1.1.2 - playwright-core@1.43.1: {} + playwright-core@1.57.0: {} - playwright@1.43.1: + playwright@1.57.0: dependencies: - playwright-core: 1.43.1 + playwright-core: 1.57.0 optionalDependencies: fsevents: 2.3.2 @@ -22034,13 +22442,13 @@ snapshots: dependencies: postcss: 8.5.1 - postcss-load-config@4.0.2(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3)): + postcss-load-config@4.0.2(postcss@8.5.1)(ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3)): dependencies: lilconfig: 3.1.0 yaml: 2.3.4 optionalDependencies: postcss: 8.5.1 - ts-node: 10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3) + ts-node: 10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3) postcss-merge-longhand@5.1.7(postcss@8.5.1): dependencies: @@ -22405,6 +22813,11 @@ snapshots: react: 18.2.0 scheduler: 0.23.0 + react-dom@19.2.3(react@19.2.3): + dependencies: + react: 19.2.3 + scheduler: 0.27.0 + react-head@3.4.2(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@babel/runtime': 7.28.4 @@ -22453,6 +22866,8 @@ snapshots: dependencies: loose-envify: 1.4.0 + react@19.2.3: {} + read-package-json-fast@2.0.3: dependencies: json-parse-even-better-errors: 2.3.1 @@ -22733,8 +23148,6 @@ snapshots: requires-port@1.0.0: {} - resolve-alpn@1.2.1: {} - resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -22767,10 +23180,6 @@ snapshots: dependencies: lowercase-keys: 2.0.0 - responselike@3.0.0: - dependencies: - lowercase-keys: 3.0.0 - restore-cursor@2.0.0: dependencies: onetime: 2.0.1 @@ -22918,6 +23327,8 @@ snapshots: dependencies: loose-envify: 1.4.0 + scheduler@0.27.0: {} + schema-utils@3.3.0: dependencies: '@types/json-schema': 7.0.15 @@ -22947,10 +23358,9 @@ snapshots: '@types/node-forge': 1.3.11 node-forge: 1.3.1 - sembear@0.5.2: + sembear@0.7.0: dependencies: - '@types/semver': 6.2.3 - semver: 6.3.1 + semver: 7.7.1 semver-diff@3.1.1: dependencies: @@ -22962,6 +23372,9 @@ snapshots: semver@7.7.1: {} + semver@7.7.3: + optional: true + send@0.19.0: dependencies: debug: 2.6.9(supports-color@9.2.3) @@ -23065,6 +23478,38 @@ snapshots: dependencies: kind-of: 6.0.3 + sharp@0.34.5: + dependencies: + '@img/colour': 1.0.0 + detect-libc: 2.1.2 + semver: 7.7.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + optional: true + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -23427,11 +23872,11 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 - style-loader@2.0.0(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)): + style-loader@2.0.0(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)): dependencies: loader-utils: 2.0.2 schema-utils: 3.3.0 - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) style-to-object@0.3.0: dependencies: @@ -23447,6 +23892,12 @@ snapshots: optionalDependencies: '@babel/core': 7.23.9 + styled-jsx@5.0.7(@babel/core@7.23.9)(react@19.2.3): + dependencies: + react: 19.2.3 + optionalDependencies: + '@babel/core': 7.23.9 + styled-jsx@5.1.1(@babel/core@7.23.9)(react@18.2.0): dependencies: client-only: 0.0.1 @@ -23454,6 +23905,13 @@ snapshots: optionalDependencies: '@babel/core': 7.23.9 + styled-jsx@5.1.6(@babel/core@7.23.9)(react@19.2.3): + dependencies: + client-only: 0.0.1 + react: 19.2.3 + optionalDependencies: + '@babel/core': 7.23.9 + stylehacks@5.1.1(postcss@8.5.1): dependencies: browserslist: 4.28.1 @@ -23570,39 +24028,39 @@ snapshots: ansi-escapes: 4.3.2 supports-hyperlinks: 2.2.0 - terser-webpack-plugin@5.3.16(@swc/core@1.11.24)(esbuild@0.27.1)(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)): + terser-webpack-plugin@5.3.16(@swc/core@1.15.8)(esbuild@0.27.1)(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.44.1 - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) optionalDependencies: - '@swc/core': 1.11.24 + '@swc/core': 1.15.8 esbuild: 0.27.1 - terser-webpack-plugin@5.3.16(@swc/core@1.11.24)(webpack@5.104.0(@swc/core@1.11.24)): + terser-webpack-plugin@5.3.16(@swc/core@1.15.8)(webpack@5.104.0(@swc/core@1.15.8)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.44.1 - webpack: 5.104.0(@swc/core@1.11.24) + webpack: 5.104.0(@swc/core@1.15.8) optionalDependencies: - '@swc/core': 1.11.24 + '@swc/core': 1.15.8 - terser-webpack-plugin@5.3.16(@swc/core@1.11.24)(webpack@5.104.0): + terser-webpack-plugin@5.3.16(@swc/core@1.15.8)(webpack@5.104.0): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.44.1 - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) optionalDependencies: - '@swc/core': 1.11.24 + '@swc/core': 1.15.8 terser@5.44.1: dependencies: @@ -23759,7 +24217,7 @@ snapshots: trough@2.2.0: {} - ts-node@10.9.1(@swc/core@1.11.24)(@types/node@16.11.10)(typescript@4.9.4): + ts-node@10.9.1(@swc/core@1.15.8)(@types/node@16.11.10)(typescript@4.9.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.8 @@ -23777,9 +24235,9 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.11.24 + '@swc/core': 1.15.8 - ts-node@10.9.1(@swc/core@1.11.24)(@types/node@22.15.3)(typescript@5.8.3): + ts-node@10.9.1(@swc/core@1.15.8)(@types/node@22.15.3)(typescript@5.8.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.8 @@ -23797,7 +24255,7 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 optionalDependencies: - '@swc/core': 1.11.24 + '@swc/core': 1.15.8 optional: true tsconfck@3.1.4(typescript@5.8.3): @@ -23814,6 +24272,8 @@ snapshots: tslib@2.5.0: {} + tslib@2.8.1: {} + tsutils@3.21.0(typescript@4.9.4): dependencies: tslib: 1.14.1 @@ -24126,6 +24586,10 @@ snapshots: dependencies: react: 18.2.0 + use-sync-external-store@1.2.0(react@19.2.3): + dependencies: + react: 19.2.3 + use@3.1.1: {} util-deprecate@1.0.2: {} @@ -24174,10 +24638,6 @@ snapshots: spdx-correct: 3.1.1 spdx-expression-parse: 3.0.1 - validate-npm-package-name@3.0.0: - dependencies: - builtins: 1.0.3 - validate-npm-package-name@4.0.0: dependencies: builtins: 5.0.1 @@ -24186,6 +24646,8 @@ snapshots: dependencies: builtins: 5.0.1 + validate-npm-package-name@6.0.2: {} + vary@1.1.2: {} vfile-location@2.0.6: {} @@ -24445,13 +24907,13 @@ snapshots: import-local: 3.0.3 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) webpack-merge: 6.0.1 optionalDependencies: webpack-bundle-analyzer: 5.1.0 webpack-dev-server: 5.2.2(webpack-cli@6.0.1)(webpack@5.104.0) - webpack-dev-middleware@7.4.5(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)): + webpack-dev-middleware@7.4.5(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)): dependencies: colorette: 2.0.16 memfs: 4.51.1 @@ -24460,7 +24922,7 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.3.3 optionalDependencies: - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) webpack-dev-middleware@7.4.5(webpack@5.104.0): dependencies: @@ -24471,7 +24933,7 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.3.3 optionalDependencies: - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) webpack-dev-server@5.2.2(webpack-cli@6.0.1)(webpack@5.104.0): dependencies: @@ -24504,7 +24966,7 @@ snapshots: webpack-dev-middleware: 7.4.5(webpack@5.104.0) ws: 8.18.3 optionalDependencies: - webpack: 5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1) + webpack: 5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1) webpack-cli: 6.0.1(webpack-bundle-analyzer@5.1.0)(webpack-dev-server@5.2.2)(webpack@5.104.0) transitivePeerDependencies: - bufferutil @@ -24512,7 +24974,7 @@ snapshots: - supports-color - utf-8-validate - webpack-dev-server@5.2.2(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)): + webpack-dev-server@5.2.2(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -24540,10 +25002,10 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.5(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)) + webpack-dev-middleware: 7.4.5(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)) ws: 8.18.3 optionalDependencies: - webpack: 5.104.0(@swc/core@1.11.24)(esbuild@0.27.1) + webpack: 5.104.0(@swc/core@1.15.8)(esbuild@0.27.1) transitivePeerDependencies: - bufferutil - debug @@ -24560,7 +25022,7 @@ snapshots: webpack-sources@3.3.3: {} - webpack@5.104.0(@swc/core@1.11.24): + webpack@5.104.0(@swc/core@1.15.8): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -24584,7 +25046,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(@swc/core@1.11.24)(webpack@5.104.0(@swc/core@1.11.24)) + terser-webpack-plugin: 5.3.16(@swc/core@1.15.8)(webpack@5.104.0(@swc/core@1.15.8)) watchpack: 2.4.4 webpack-sources: 3.3.3 transitivePeerDependencies: @@ -24592,7 +25054,7 @@ snapshots: - esbuild - uglify-js - webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1): + webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -24616,7 +25078,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(@swc/core@1.11.24)(esbuild@0.27.1)(webpack@5.104.0(@swc/core@1.11.24)(esbuild@0.27.1)) + terser-webpack-plugin: 5.3.16(@swc/core@1.15.8)(esbuild@0.27.1)(webpack@5.104.0(@swc/core@1.15.8)(esbuild@0.27.1)) watchpack: 2.4.4 webpack-sources: 3.3.3 transitivePeerDependencies: @@ -24624,7 +25086,7 @@ snapshots: - esbuild - uglify-js - webpack@5.104.0(@swc/core@1.11.24)(webpack-cli@6.0.1): + webpack@5.104.0(@swc/core@1.15.8)(webpack-cli@6.0.1): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -24648,7 +25110,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(@swc/core@1.11.24)(webpack@5.104.0) + terser-webpack-plugin: 5.3.16(@swc/core@1.15.8)(webpack@5.104.0) watchpack: 2.4.4 webpack-sources: 3.3.3 optionalDependencies: @@ -24846,6 +25308,8 @@ snapshots: yocto-queue@1.0.0: {} + yocto-queue@1.2.2: {} + zip-stream@4.1.0: dependencies: archiver-utils: 2.1.0 diff --git a/site/docs/integrations/next.md b/site/docs/integrations/next.md index 1a805696c..a0122299a 100644 --- a/site/docs/integrations/next.md +++ b/site/docs/integrations/next.md @@ -15,41 +15,46 @@ npm install --save-dev @vanilla-extract/next-plugin ## Setup -If you don't have a `next.config.js` file in the root of your project, create one. Add the plugin to your `next.config.js` file. +If you don't have a `next.config.js` or `next.config.ts` file in the root of your project, create one. Add the plugin to your Next.js config file. -```js -const { - createVanillaExtractPlugin -} = require('@vanilla-extract/next-plugin'); +```ts +// next.config.ts +import type { NextConfig } from 'next'; +import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin'; const withVanillaExtract = createVanillaExtractPlugin(); -/** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig: NextConfig = {}; -module.exports = withVanillaExtract(nextConfig); +export default withVanillaExtract(nextConfig); ``` If required, this plugin can be composed with other plugins. -```js -const { - createVanillaExtractPlugin -} = require('@vanilla-extract/next-plugin'); +```ts +// next.config.ts +import type { NextConfig } from 'next'; +import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin'; +import createMDX from '@next/mdx'; + const withVanillaExtract = createVanillaExtractPlugin(); -const withMDX = require('@next/mdx')({ +const withMDX = createMDX({ extension: /\.mdx$/ }); -/** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig: NextConfig = {}; -module.exports = withVanillaExtract(withMDX(nextConfig)); +export default withVanillaExtract(withMDX(nextConfig)); ``` +## Version Support + +- **Next.js >= 16.x**: Both Turbopack and Webpack are supported +- **Next.js <= 15.x**: Webpack-only support + ## Configuration -The plugin accepts the following as optional configuration: +The plugin accepts the following as optional configuration, passed to `createVanillaExtractPlugin`. ### identifiers @@ -60,6 +65,9 @@ Different formatting of identifiers (e.g. class names, keyframes, CSS Vars, etc) - A custom identifier function takes an object parameter with properties `hash`, `filePath`, `debugId`, and `packageName`, and returns a customized identifier. e.g. ```ts +// next.config.ts +import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin'; + const withVanillaExtract = createVanillaExtractPlugin({ identifiers: ({ hash }) => `prefix_${hash}` }); @@ -67,6 +75,52 @@ const withVanillaExtract = createVanillaExtractPlugin({ Each integration will set a default value based on the configuration options passed to the bundler. +### unstable_turbopack + +> ⚠️  Turbopack support is experimental. Its API is unstable and may undergo breaking changes in non-major versions. Additionally, it may not handle all features supported by Next.js. + +Turbopack-related options are grouped under the `unstable_turbopack` key. + +#### unstable_turbopack.mode + +You can control Turbopack autoconfiguration using `mode`: + +- `auto` (default): enable Turbopack config only when Next >= 16.0.0 +- `on`: force-enable Turbopack config +- `off`: never configure Turbopack (Webpack-only) + +For example, to disable Turbopack integration explicitly: + +```ts +// next.config.ts +import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin'; + +const withVanillaExtract = createVanillaExtractPlugin({ + unstable_turbopack: { mode: 'off' } +}); + +export default withVanillaExtract({}); +``` + +If you already manage `turbopack.rules` yourself for the same file globs, the plugin may throw to avoid rule conflicts. In that case, set `mode: 'off'` and apply your Turbopack config manually. + +#### unstable_turbopack.glob + +By default Turbopack integration processes `**/*.css.{js,cjs,mjs,jsx,ts,tsx}`. You can override this via `glob`: + +```ts +// next.config.ts +import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin'; + +const withVanillaExtract = createVanillaExtractPlugin({ + unstable_turbopack: { + glob: ['**/*.css.ts', '**/*.css.tsx'] + } +}); + +export default withVanillaExtract({}); +``` + ## Transpiling Vanilla Extract-dependent Libraries By default, Next.js does not allow importing of TypeScript files outside of the app root. @@ -83,20 +137,18 @@ export default function App() { } ``` -```js -// next.config.js -const { - createVanillaExtractPlugin -} = require('@vanilla-extract/next-plugin'); +```ts +// next.config.ts +import type { NextConfig } from 'next'; +import { createVanillaExtractPlugin } from '@vanilla-extract/next-plugin'; const withVanillaExtract = createVanillaExtractPlugin(); -/** @type {import('next').NextConfig} */ -const nextConfig = { +const nextConfig: NextConfig = { transpilePackages: ['@company/design-system'] }; // Next.js Vanilla Extract integration will now compile @company/design-system styles -module.exports = withVanillaExtract(nextConfig); +export default withVanillaExtract(nextConfig); ``` [`transpilepackages`]: https://nextjs.org/docs/app/api-reference/next-config-js/transpilePackages diff --git a/test-helpers/package.json b/test-helpers/package.json index bc7a716fa..9d9ece74b 100644 --- a/test-helpers/package.json +++ b/test-helpers/package.json @@ -10,8 +10,9 @@ "@fixtures/features": "workspace:*", "@fixtures/layers": "workspace:*", "@fixtures/low-level": "workspace:*", - "@fixtures/next-app-router": "workspace:*", - "@fixtures/next-pages-router": "workspace:*", + "@fixtures/next-12-pages-router": "workspace:*", + "@fixtures/next-13-app-router": "workspace:*", + "@fixtures/next-16-app-pages-router": "workspace:*", "@fixtures/recipes": "workspace:*", "@fixtures/sprinkles": "workspace:*", "@fixtures/template-string-paths": "workspace:*", diff --git a/test-helpers/src/startFixture/index.ts b/test-helpers/src/startFixture/index.ts index 99a9a0f3e..a352b03f2 100644 --- a/test-helpers/src/startFixture/index.ts +++ b/test-helpers/src/startFixture/index.ts @@ -69,7 +69,11 @@ export async function startFixture( }); } - if (type === 'next-pages-router' || type === 'next-app-router') { + if ( + type === 'next-12-pages-router' || + type === 'next-13-app-router' || + type === 'next-16-app-pages-router' + ) { return startNextFixture({ type, port, diff --git a/test-helpers/src/startFixture/next.ts b/test-helpers/src/startFixture/next.ts index b4bb25326..00ea3a32a 100644 --- a/test-helpers/src/startFixture/next.ts +++ b/test-helpers/src/startFixture/next.ts @@ -1,7 +1,7 @@ import type { NextServer, NextServerOptions, -} from '@fixtures/next-pages-router/node_modules/next/dist/server/next'; +} from '@fixtures/next-12-pages-router/node_modules/next/dist/server/next'; import { existsSync } from 'fs'; import { Server as _Server, createServer } from 'http'; import path from 'path'; @@ -20,7 +20,10 @@ const DIST_DIR = 'dist'; export const nextFixtures = ['sprinkles', 'recipes', 'features'] as const; export interface NextFixtureOptions { - type: 'next-app-router' | 'next-pages-router'; + type: + | 'next-13-app-router' + | 'next-12-pages-router' + | 'next-16-app-pages-router'; mode?: 'development' | 'production'; port: number; } @@ -92,7 +95,7 @@ export const startNextFixture = async ({ // using export mode for production build in next 13 // due to issues with the distDir config not being set // properly. - if (!dev && type === 'next-app-router') { + if (!dev && type === 'next-13-app-router') { // Use vite to server the static build. const closeServer = await serveAssets({ port, diff --git a/tests/e2e/css-deduplication.playwright.ts b/tests/e2e/css-deduplication.playwright.ts new file mode 100644 index 000000000..309902141 --- /dev/null +++ b/tests/e2e/css-deduplication.playwright.ts @@ -0,0 +1,40 @@ +import { expect } from '@playwright/test'; +import { readFileSync } from 'fs'; +import { globSync } from 'node:fs'; +import path from 'path'; + +import test from './fixture'; + +const fixtureDir = path.resolve( + __dirname, + '../../fixtures/next-16-app-pages-router', +); + +test.describe('CSS deduplication @agnostic', () => { + const buildTypes = [ + { name: 'webpack', distDir: 'dist/webpack' }, + { name: 'turbopack', distDir: 'dist/turbo' }, + ]; + + buildTypes.forEach(({ name, distDir: distDirName }) => { + test(`shared globalStyle should only appear once in ${name} production build`, async () => { + const distDir = path.join(fixtureDir, distDirName); + + const cssFiles = globSync('**/*.css', { cwd: distDir }); + expect(cssFiles.length).toBeGreaterThan(0); + + let totalOccurrences = 0; + const cssPattern = /body\s*\{\s*background-color:\s*#0cdbcd;?\s*\}/g; + + for (const cssFile of cssFiles) { + const content = readFileSync(path.join(distDir, cssFile), 'utf-8'); + const matches = content.match(cssPattern); + if (matches) { + totalOccurrences += matches.length; + } + } + + expect(totalOccurrences).toBe(1); + }); + }); +}); diff --git a/tests/e2e/fixtures-next-development.playwright.ts b/tests/e2e/fixtures-next-development.playwright.ts deleted file mode 100644 index 5362fe29d..000000000 --- a/tests/e2e/fixtures-next-development.playwright.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { - nextFixtures, - startFixture, - type TestServer, -} from '@vanilla-extract-private/test-helpers'; -import { expect } from '@playwright/test'; - -import test from './fixture'; - -const testCases = [ - { - type: 'next-pages-router', - mode: 'development', - clientSideRouting: true, - }, - { - type: 'next-app-router', - mode: 'development', - clientSideRouting: false, - }, -] as const; - -testCases.forEach(({ type, mode, clientSideRouting }) => { - test.describe.serial(`${type} (${mode})`, async () => { - let server: TestServer; - - test.beforeAll(async ({ port }) => { - server = await startFixture(type, { - type, - basePort: port, - mode, - }); - }); - - test(`screenshot`, async ({ page }) => { - for await (const fixture of nextFixtures) { - const fixtureUrl = `${server.url}/${fixture}`; - - await page.goto(fixtureUrl); - await page.waitForSelector(`#${fixture}`, { state: 'attached' }); - expect(await page.screenshot()).toMatchSnapshot(`${fixture}.png`); - } - }); - - if (clientSideRouting) { - test(`screenshot (csr)`, async ({ page }) => { - for await (const fixture of nextFixtures) { - await page.goto(server.url); - await page.waitForLoadState('networkidle'); - - const fixtureUrl = `${server.url}/${fixture}`; - // navigate to fixture page via link - const loc = page.locator('a', { hasText: fixture }); - await loc.click(); - // prevent triggering a css hover on the new page - await page.mouse.move(0, 0); - await page.waitForURL(fixtureUrl); - await page.waitForLoadState('networkidle'); - - await page.waitForSelector(`#${fixture}`, { - state: 'attached', - }); - expect(await page.screenshot()).toMatchSnapshot(`${fixture}.png`); - } - }); - } - - test.afterAll(async () => { - await server.close(); - }); - }); -}); diff --git a/tests/e2e/fixtures-next-production.playwright.ts b/tests/e2e/fixtures-next-production.playwright.ts deleted file mode 100644 index d78b5ba65..000000000 --- a/tests/e2e/fixtures-next-production.playwright.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { - nextFixtures, - startFixture, - type TestServer, -} from '@vanilla-extract-private/test-helpers'; -import { expect } from '@playwright/test'; - -import test from './fixture'; - -const testCases = [ - { - type: 'next-pages-router', - mode: 'production', - }, - { - type: 'next-app-router', - mode: 'production', - }, -] as const; - -testCases.forEach(({ type, mode }) => { - test.describe.serial(`${type} (${mode})`, async () => { - let server: TestServer; - - test.beforeAll(async ({ port }) => { - server = await startFixture('', { - type, - basePort: port, - mode, - }); - }); - - test(`screenshot`, async ({ page }) => { - for await (const fixture of nextFixtures) { - await page.goto(`${server.url}/${fixture}`); - // make sure the fixture is visible - await page.waitForSelector(`#${fixture}`, { state: 'attached' }); - expect(await page.screenshot()).toMatchSnapshot(`${fixture}.png`); - } - }); - - test.afterAll(async () => { - await server.close(); - }); - }); -}); diff --git a/tests/e2e/fixtures-next-unified.playwright.ts b/tests/e2e/fixtures-next-unified.playwright.ts new file mode 100644 index 000000000..14171bd25 --- /dev/null +++ b/tests/e2e/fixtures-next-unified.playwright.ts @@ -0,0 +1,91 @@ +import { expect, test } from '@playwright/test'; +import { NEXT_SERVERS } from '../servers'; + +const limited = [ + { route: '/features', index: '/' }, + { route: '/recipes', index: '/' }, + { route: '/sprinkles', index: '/' }, +]; + +const full = [ + { route: '/features', index: '/' }, + { route: '/recipes', index: '/' }, + { route: '/sprinkles', index: '/' }, + { route: '/pages-router/features', index: '/pages-router' }, + { route: '/pages-router/recipes', index: '/pages-router' }, + { route: '/pages-router/sprinkles', index: '/pages-router' }, + { route: '/creepster', index: '/' }, + { route: '/duplication-test', index: '/' }, + { route: '/function-serializer', index: '/' }, + { route: '/next-font', index: '/' }, + { route: '/next-image', index: '/' }, +]; + +const getTasks = (type: 'full' | 'limited') => { + if (type === 'full') return full; + return limited; +}; + +NEXT_SERVERS.map((server) => { + test.describe(server.name, () => { + const tasks = getTasks(server.suite); + + for (const { route, index: indexUrl } of tasks) { + const snapshotPrefix = + // font names are different between webpack and turbopack + route.includes('next-font') && server.name.includes('Webpack') + ? 'next-font-webpack' + : route.split('/').at(-1); + + // FIXME: webpack fails the creepster test! + if (server.name.includes('Webpack') && route.includes('creepster')) { + continue; + } + + // Test SSR + test(`${route} - SSR`, async ({ page }) => { + const targetUrl = `http://localhost:${server.port}${route}`; + await page.goto(targetUrl, { waitUntil: 'networkidle' }); + + expect(await page.screenshot()).toMatchSnapshot( + `${snapshotPrefix}.png`, + ); + }); + + // FIXME: webpack dev in next 16 fails CSR tests! + if ( + server.name.includes('Webpack') && + server.name.includes('Next 16') && + route.includes('pages-router') + ) { + continue; + } + // FIXME: turbopack build in next 16 fails CSR tests! + if ( + server.name.includes('Turbopack') && + server.name.includes('Next 16') && + route.includes('pages-router') + ) { + continue; + } + + // Test CSR + test(`${route} - CSR`, async ({ page }) => { + await page.goto(`http://localhost:${server.port}${indexUrl}`); + + const linkLocator = page.locator(`a[href="${route}"]`).first(); + await linkLocator.click(); + + // Prevent triggering a css hover on the new page + await page.mouse.move(0, 0); + + await page.waitForURL(`http://localhost:${server.port}${route}`); + await page.waitForLoadState('networkidle'); + + expect(await page.screenshot()).toMatchSnapshot( + `${snapshotPrefix}.png`, + ); + }); + } + }); +}); diff --git a/tests/e2e/snapshots/creepster-Desktop---Chromium-darwin.png b/tests/e2e/snapshots/creepster-Desktop---Chromium-darwin.png new file mode 100644 index 000000000..3724e6909 Binary files /dev/null and b/tests/e2e/snapshots/creepster-Desktop---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/creepster-Mobile---Chromium-darwin.png b/tests/e2e/snapshots/creepster-Mobile---Chromium-darwin.png new file mode 100644 index 000000000..c2c2e3df0 Binary files /dev/null and b/tests/e2e/snapshots/creepster-Mobile---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/duplication-test-Desktop---Chromium-darwin.png b/tests/e2e/snapshots/duplication-test-Desktop---Chromium-darwin.png new file mode 100644 index 000000000..496aee551 Binary files /dev/null and b/tests/e2e/snapshots/duplication-test-Desktop---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/duplication-test-Mobile---Chromium-darwin.png b/tests/e2e/snapshots/duplication-test-Mobile---Chromium-darwin.png new file mode 100644 index 000000000..ea5bc9de8 Binary files /dev/null and b/tests/e2e/snapshots/duplication-test-Mobile---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/function-serializer-Desktop---Chromium-darwin.png b/tests/e2e/snapshots/function-serializer-Desktop---Chromium-darwin.png new file mode 100644 index 000000000..840343192 Binary files /dev/null and b/tests/e2e/snapshots/function-serializer-Desktop---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/function-serializer-Mobile---Chromium-darwin.png b/tests/e2e/snapshots/function-serializer-Mobile---Chromium-darwin.png new file mode 100644 index 000000000..97b194305 Binary files /dev/null and b/tests/e2e/snapshots/function-serializer-Mobile---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/next-font-Desktop---Chromium-darwin.png b/tests/e2e/snapshots/next-font-Desktop---Chromium-darwin.png new file mode 100644 index 000000000..8068416be Binary files /dev/null and b/tests/e2e/snapshots/next-font-Desktop---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/next-font-Mobile---Chromium-darwin.png b/tests/e2e/snapshots/next-font-Mobile---Chromium-darwin.png new file mode 100644 index 000000000..1c0b3a06d Binary files /dev/null and b/tests/e2e/snapshots/next-font-Mobile---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/next-font-webpack-Desktop---Chromium-darwin.png b/tests/e2e/snapshots/next-font-webpack-Desktop---Chromium-darwin.png new file mode 100644 index 000000000..776378626 Binary files /dev/null and b/tests/e2e/snapshots/next-font-webpack-Desktop---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/next-font-webpack-Mobile---Chromium-darwin.png b/tests/e2e/snapshots/next-font-webpack-Mobile---Chromium-darwin.png new file mode 100644 index 000000000..bb43dcace Binary files /dev/null and b/tests/e2e/snapshots/next-font-webpack-Mobile---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/next-image-Desktop---Chromium-darwin.png b/tests/e2e/snapshots/next-image-Desktop---Chromium-darwin.png new file mode 100644 index 000000000..a1aa003e9 Binary files /dev/null and b/tests/e2e/snapshots/next-image-Desktop---Chromium-darwin.png differ diff --git a/tests/e2e/snapshots/next-image-Mobile---Chromium-darwin.png b/tests/e2e/snapshots/next-image-Mobile---Chromium-darwin.png new file mode 100644 index 000000000..c165ff6ed Binary files /dev/null and b/tests/e2e/snapshots/next-image-Mobile---Chromium-darwin.png differ diff --git a/tests/package.json b/tests/package.json index b244b4e20..4575a70c5 100644 --- a/tests/package.json +++ b/tests/package.json @@ -5,7 +5,6 @@ "author": "SEEK", "license": "MIT", "dependencies": { - "@playwright/test": "^1.43.1", "@testing-library/dom": "^10.0.0", "@testing-library/jest-dom": "^6.4.2", "@vanilla-extract-private/test-helpers": "workspace:*", diff --git a/tests/servers.ts b/tests/servers.ts new file mode 100644 index 000000000..8c56d01be --- /dev/null +++ b/tests/servers.ts @@ -0,0 +1,66 @@ +interface ServerDefinition { + name: string; + isProduction: boolean; + script: string; + port: number; + suite: 'full' | 'limited'; +} + +export const NEXT_SERVERS: ServerDefinition[] = [ + { + name: 'Next 12 Dev Server', + isProduction: false, + script: 'pnpm --filter=next-12-pages-router dev', + port: 3001, + suite: 'limited', + }, + { + name: 'Next 12 Build', + isProduction: true, + script: 'pnpm --filter=next-12-pages-router start', + port: 3002, + suite: 'limited', + }, + { + name: 'Next 13 Dev Server', + isProduction: false, + script: 'pnpm --filter=next-13-app-router dev', + port: 3003, + suite: 'limited', + }, + { + name: 'Next 13 Build', + isProduction: true, + script: 'pnpm --filter=next-13-app-router start', + port: 3004, + suite: 'limited', + }, + { + name: 'Next 16 Dev Server (Webpack)', + isProduction: false, + script: 'pnpm --filter=next-16-app-pages-router dev-webpack', + port: 3005, + suite: 'full', + }, + { + name: 'Next 16 Build (Webpack)', + isProduction: true, + script: 'pnpm --filter=next-16-app-pages-router start-webpack', + port: 3006, + suite: 'full', + }, + { + name: 'Next 16 Dev Server (Turbopack)', + isProduction: false, + script: 'pnpm --filter=next-16-app-pages-router dev-turbo', + port: 3007, + suite: 'full', + }, + { + name: 'Next 16 Build (Turbopack)', + isProduction: true, + script: 'pnpm --filter=next-16-app-pages-router start-turbo', + port: 3008, + suite: 'full', + }, +];